Merge branch 'master' into versus-record

This commit is contained in:
TehRealSalt 2019-09-23 07:03:56 -04:00
commit 77aeb4663b
34 changed files with 3104 additions and 2086 deletions

View file

@ -107,7 +107,7 @@ matrix:
- p7zip-full
- gcc-8
compiler: gcc-8
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow" GCC81=1
env: WFLAGS="-Wno-tautological-compare -Wno-error=implicit-fallthrough -Wno-implicit-fallthrough -Wno-error=format-overflow -Wno-error=format-truncation" GCC81=1
if: env(DPL_ENABLED) != "1" OR env(DPL_TERMINATE_TESTS) != "1" OR NOT branch =~ /^.*deployer.*$/
#gcc-8 (Ubuntu 7.2.0-1ubuntu1~14.04) 8.1.0
- os: linux

View file

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
# DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string.
# Version change is fine.
project(SRB2
VERSION 1.1.0
VERSION 2.0.0
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View file

@ -1,4 +1,4 @@
version: 1.1.0.{branch}-{build}
version: 2.0.0.{branch}-{build}
os: MinGW
environment:
@ -29,7 +29,7 @@ environment:
##############################
DPL_ENABLED: 0
DPL_TAG_ENABLED: 0
DPL_INSTALLER_NAME: srb2kart-v110
DPL_INSTALLER_NAME: srb2kart-v200
# Asset handling is barebones vs. Travis Deployer. We operate on 7z only.
# Include the README files and the OpenGL batch in the main and patch archives.
# The x86/x64 archives contain the DLL binaries.

View file

@ -902,7 +902,10 @@ static void COM_Add_f(void)
return;
}
CV_AddValue(cvar, atoi(COM_Argv(2)));
if (( cvar->flags & CV_FLOAT ))
CV_Set(cvar, va("%f", FIXED_TO_FLOAT (cvar->value) + atof(COM_Argv(2))));
else
CV_AddValue(cvar, atoi(COM_Argv(2)));
}
// =========================================================================

View file

@ -1433,8 +1433,14 @@ static void SV_SendPlayerInfo(INT32 node)
UINT8 i;
netbuffer->packettype = PT_PLAYERINFO;
for (i = 0; i < MAXPLAYERS; i++)
for (i = 0; i < MSCOMPAT_MAXPLAYERS; i++)
{
if (i >= MAXPLAYERS)
{
netbuffer->u.playerinfo[i].node = 255;
continue;
}
if (!playeringame[i])
{
netbuffer->u.playerinfo[i].node = 255; // This slot is empty.
@ -1482,7 +1488,7 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].data |= 0x80;
}
HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS);
HSendPacket(node, false, 0, sizeof(plrinfo) * MSCOMPAT_MAXPLAYERS);
}
/** Sends a PT_SERVERCFG packet

View file

@ -470,7 +470,7 @@ typedef struct
serverrefuse_pak serverrefuse; // 65025 bytes (somehow I feel like those values are garbage...)
askinfo_pak askinfo; // 61 bytes
msaskinfo_pak msaskinfo; // 22 bytes
plrinfo playerinfo[MAXPLAYERS]; // 576 bytes(?)
plrinfo playerinfo[MSCOMPAT_MAXPLAYERS];// 576 bytes(?)
plrconfig playerconfig[MAXPLAYERS]; // (up to) 528 bytes(?)
INT32 filesneedednum; // 4 bytes
filesneededconfig_pak filesneededcfg; // ??? bytes

View file

@ -329,6 +329,7 @@ consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chanc
consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/
// SRB2kart
consvar_t cv_superring = {"superring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sneaker = {"sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rocketsneaker = {"rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invincibility = {"invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -366,7 +367,7 @@ consvar_t cv_kartcomeback = {"kartcomeback", "On", CV_NETVAR|CV_CHEAT|CV_CALL|CV
consvar_t cv_kartencore = {"kartencore", "Off", CV_NETVAR|CV_CALL|CV_NOINIT, CV_OnOff, KartEncore_OnChange, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
consvar_t cv_kartvoterulechanges = {"kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Kilometers"}, {2, "Miles"}, {3, "Fracunits"}, {0, NULL}};
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Percentage"}, {2, "Kilometers"}, {3, "Miles"}, {4, "Fracunits"}, {0, NULL}};
consvar_t cv_kartspeedometer = {"kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -2083,7 +2084,7 @@ static void Command_View_f(void)
return;
}
displayplayerp = &displayplayers[viewnum];
displayplayerp = &displayplayers[viewnum-1];
if (COM_Argc() > 1)/* switch to player */
{

View file

@ -101,7 +101,7 @@ extern consvar_t cv_1up, cv_eggmanbox;
extern consvar_t cv_recycler;*/
// SRB2kart items
extern consvar_t cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana;
extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana;
extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine;
extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink;

View file

@ -130,7 +130,8 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
nameonly(strcpy(wadfilename, wadfiles[i]->filename));
if (p + 1 + 4 + strlen(wadfilename) + 16 > p_start + MAXFILENEEDED)
// Look below at the WRITE macros to understand what these numbers mean.
if (p + 1 + 4 + min(strlen(wadfilename) + 1, MAX_WADPATH) + 16 > p_start + MAXFILENEEDED)
{
// Too many files to send all at once
if (netbuffer->packettype == PT_MOREFILESNEEDED)

View file

@ -216,6 +216,7 @@ typedef enum
KITEM_THUNDERSHIELD,
KITEM_HYUDORO,
KITEM_POGOSPRING,
KITEM_SUPERRING,
KITEM_KITCHENSINK,
NUMKARTITEMS,
@ -234,6 +235,7 @@ typedef enum
//{ SRB2kart - kartstuff
typedef enum
{
// TODO: Kill this giant array. Add them as actual player_t variables, or condense related timers into their own, smaller arrays.
// Basic gameplay things
k_position, // Used for Kart positions, mostly for deterministic stuff
k_oldposition, // Used for taunting when you pass someone
@ -247,16 +249,10 @@ typedef enum
k_dropdash, // Charge up for respawn Drop Dash
k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir")
k_lapanimation, // Used to show the lap start wing logo animation
k_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down:
k_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
k_voices, // Used to stop the player saying more voices than it should
k_tauntvoices, // Used to specifically stop taunt voice spam
k_instashield, // Instashield no-damage animation timer
k_enginesnd, // Engine sound number you're on.
k_floorboost, // Prevents Sneaker sounds for a breif duration when triggered by a floor panel
k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still
k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still, 2 = stay still & no flashing tics
k_drift, // Drifting Left or Right, plus a bigger counter = sharper turn
k_driftend, // Drift has ended, used to adjust character angle after drift
@ -264,19 +260,27 @@ typedef enum
k_driftboost, // Boost you get from drifting
k_boostcharge, // Charge-up for boosting at the start of the race
k_startboost, // Boost you get from start of race or respawn drop dash
k_rings, // Number of held rings
k_pickuprings, // Number of rings being picked up before added to the counter (prevents rings from being deleted forever over 20)
k_userings, // Have to be not holding the item button to change from using rings to using items (or vice versa), to prevent some weirdness with the button
k_ringdelay, // 3 tic delay between every ring usage
k_ringboost, // Ring boost timer
k_ringlock, // Prevent picking up rings while SPB is locked on
k_sparkleanim, // Angle offset for ring sparkle animation
k_jmp, // In Mario Kart, letting go of the jump button stops the drift
k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed
k_pogospring, // Pogo spring bounce effect
k_brakestop, // Wait until you've made a complete stop for a few tics before letting brake go in reverse.
k_waterskip, // Water skipping counter
k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing
k_numboosts, // Count of how many boosts are being stacked, for after image spawning
k_boostpower, // Base boost value, for offroad
k_speedboost, // Boost value smoothing for max speed
k_accelboost, // Boost value smoothing for acceleration
k_draftpower, // Drafting power (from 0 to FRACUNIT), doubles your top speed & acceleration at max
k_draftleeway, // Leniency timer before removing draft power
k_lastdraft, // Last player being drafted
k_boostangle, // angle set when not spun out OR boosted to determine what direction you should keep going at if you're spun out and boosted.
k_boostcam, // Camera push forward on boost
k_destboostcam, // Ditto
k_timeovercam, // Camera timer for leaving behind or not
k_aizdriftstrat, // Let go of your drift while boosting? Helper for the SICK STRATZ you have just unlocked
k_brakedrift, // Helper for brake-drift spark spawning
@ -294,7 +298,9 @@ typedef enum
k_hyudorotimer, // Duration of the Hyudoro offroad effect itself
k_stealingtimer, // You are stealing an item, this is your timer
k_stolentimer, // You are being stolen from, this is your timer
k_superring, // Spawn rings on top of you every tic!
k_sneakertimer, // Duration of the Sneaker Boost itself
k_levelbooster, // Duration of a level booster's boost (same as sneaker, but separated for )
k_growshrinktimer, // > 0 = Big, < 0 = small
k_squishedtimer, // Squished frame timer
k_rocketsneakertimer, // Rocket Sneaker duration timer
@ -315,11 +321,8 @@ typedef enum
k_comebackpoints, // Number of times you've bombed or gave an item to someone; once it's 3 it gets set back to 0 and you're given a bumper
k_comebackmode, // 0 = bomb, 1 = item
k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo
k_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
// v1.0.2+ vars
k_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator
k_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items)
k_getsparks, // Disable drift sparks at low speed, JUST enough to give acceleration the actual headstart above speed
k_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy
k_spectatewait, // How long have you been waiting as a spectator
@ -327,6 +330,44 @@ typedef enum
NUMKARTSTUFF
} kartstufftype_t;
typedef enum
{
// Unsynced, HUD or clientsided effects
// Item box
khud_itemblink, // Item flashing after roulette, prevents Hyudoro stealing AND serves as a mashing indicator
khud_itemblinkmode, // Type of flashing: 0 = white (normal), 1 = red (mashing), 2 = rainbow (enhanced items)
// Rings
khud_ringframe, // Ring spin frame
khud_ringtics, // Tics left until next ring frame
khud_ringdelay, // Next frame's tics
khud_ringspblock, // Which frame of the SPB ring lock animation to use
// Lap finish
khud_lapanimation, // Used to show the lap start wing logo animation
khud_laphand, // Lap hand gfx to use; 0 = none, 1 = :ok_hand:, 2 = :thumbs_up:, 3 = :thumps_down:
// Camera
khud_boostcam, // Camera push forward on boost
khud_destboostcam, // Ditto
khud_timeovercam, // Camera timer for leaving behind or not
// Sounds
khud_enginesnd, // Engine sound offset this player is using.
khud_voices, // Used to stop the player saying more voices than it should
khud_tauntvoices, // Used to specifically stop taunt voice spam
// Battle
khud_cardanimation, // Used to determine the position of some full-screen Battle Mode graphics
khud_yougotem, // "You Got Em" gfx when hitting someone as a karma player via a method that gets you back in the game instantly
NUMKARTHUD
} karthudtype_t;
// QUICKLY GET EITHER SNEAKER OR LEVEL BOOSTER SINCE THEY ARE FUNCTIONALLY IDENTICAL
#define EITHERSNEAKER(p) (p->kartstuff[k_sneakertimer] || p->kartstuff[k_levelbooster])
//}
#define WEP_AUTO 1
@ -387,6 +428,7 @@ typedef struct player_s
// SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF];
INT32 karthud[NUMKARTHUD];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles
INT16 lturn_max[MAXPREDICTTICS]; // What's the expected turn value for full-left for a number of frames back (to account for netgame latency)?
INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right

View file

@ -4809,6 +4809,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Ring
"S_RING",
"S_FASTRING1",
"S_FASTRING2",
"S_FASTRING3",
"S_FASTRING4",
"S_FASTRING5",
"S_FASTRING6",
"S_FASTRING7",
"S_FASTRING8",
"S_FASTRING9",
"S_FASTRING10",
"S_FASTRING11",
"S_FASTRING12",
// Blue Sphere for special stages
"S_BLUEBALL",
@ -7177,6 +7189,29 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_OPAQUESMOKE4",
"S_OPAQUESMOKE5",
"S_RINGDEBT",
"S_RINGSPARKS1",
"S_RINGSPARKS2",
"S_RINGSPARKS3",
"S_RINGSPARKS4",
"S_RINGSPARKS5",
"S_RINGSPARKS6",
"S_RINGSPARKS7",
"S_RINGSPARKS8",
"S_RINGSPARKS9",
"S_RINGSPARKS10",
"S_RINGSPARKS11",
"S_RINGSPARKS12",
"S_RINGSPARKS13",
"S_RINGSPARKS14",
"S_RINGSPARKS15",
"S_DRAFTDUST1",
"S_DRAFTDUST2",
"S_DRAFTDUST3",
"S_DRAFTDUST4",
"S_DRAFTDUST5",
#ifdef SEENAMES
"S_NAMECHECK",
#endif
@ -7963,6 +7998,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_LIONMAN",
"MT_KARMAFIREWORK",
"MT_RINGSPARKS",
"MT_DRAFTDUST",
#ifdef SEENAMES
"MT_NAMECHECK",
@ -8377,13 +8414,7 @@ static const char *const KARTSTUFF_LIST[] = {
"DROPDASH",
"THROWDIR",
"LAPANIMATION",
"LAPHAND",
"CARDANIMATION",
"VOICES",
"TAUNTVOICES",
"INSTASHIELD",
"ENGINESND",
"FLOORBOOST",
"SPINOUTTYPE",
@ -8394,19 +8425,27 @@ static const char *const KARTSTUFF_LIST[] = {
"DRIFTBOOST",
"BOOSTCHARGE",
"STARTBOOST",
"RINGS",
"PICKUPRINGS",
"USERINGS",
"RINGDELAY",
"RINGBOOST",
"RINGLOCK",
"SPARKLEANIM",
"JMP",
"OFFROAD",
"POGOSPRING",
"BRAKESTOP",
"WATERSKIP",
"DASHPADCOOLDOWN",
"NUMBOOSTS",
"BOOSTPOWER",
"SPEEDBOOST",
"ACCELBOOST",
"DRAFTPOWER",
"DRAFTLEEWAY",
"LASTDRAFT",
"BOOSTANGLE",
"BOOSTCAM",
"DESTBOOSTCAM",
"TIMEOVERCAM",
"AIZDRIFTSTRAT",
"BRAKEDRIFT",
@ -8421,7 +8460,9 @@ static const char *const KARTSTUFF_LIST[] = {
"HYUDOROTIMER",
"STEALINGTIMER",
"STOLENTIMER",
"SUPERRING",
"SNEAKERTIMER",
"LEVELBOOSTER",
"GROWSHRINKTIMER",
"SQUISHEDTIMER",
"ROCKETSNEAKERTIMER",
@ -8441,10 +8482,7 @@ static const char *const KARTSTUFF_LIST[] = {
"COMEBACKPOINTS",
"COMEBACKMODE",
"WANTED",
"YOUGOTEM",
"ITEMBLINK",
"ITEMBLINKMODE",
"GETSPARKS",
"JAWZTARGETDELAY",
"SPECTATEWAIT",
@ -8542,9 +8580,13 @@ struct {
// Frame settings
{"FF_FRAMEMASK",FF_FRAMEMASK},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_ANIMATE",FF_ANIMATE},
{"FF_RANDOMANIM",FF_RANDOMANIM},
{"FF_GLOBALANIM",FF_GLOBALANIM},
{"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_SEMIBRIGHT",FF_SEMIBRIGHT},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_VERTICALFLIP",FF_VERTICALFLIP},
{"FF_TRANSMASK",FF_TRANSMASK},
{"FF_TRANSSHIFT",FF_TRANSSHIFT},
// new preshifted translucency (used in source)
@ -8969,6 +9011,7 @@ struct {
{"KITEM_THUNDERSHIELD",KITEM_THUNDERSHIELD},
{"KITEM_HYUDORO",KITEM_HYUDORO},
{"KITEM_POGOSPRING",KITEM_POGOSPRING},
{"KITEM_SUPERRING",KITEM_SUPERRING},
{"KITEM_KITCHENSINK",KITEM_KITCHENSINK},
{"NUMKARTITEMS",NUMKARTITEMS},
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
@ -9362,7 +9405,7 @@ fixed_t get_number(const char *word)
void DEH_Check(void)
{
#if defined(_DEBUG) || defined(PARANOIA)
//#if defined(_DEBUG) || defined(PARANOIA)
const size_t dehstates = sizeof(STATE_LIST)/sizeof(const char*);
const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*);
const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*);
@ -9383,7 +9426,7 @@ void DEH_Check(void)
if (dehcolors != MAXTRANSLATIONS)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors));
#endif
//#endif
}
#ifdef HAVE_BLUA

View file

@ -149,10 +149,10 @@ extern FILE *logstream;
// most interface strings are ignored in development mode.
// we use comprevision and compbranch instead.
#else
#define VERSION 110 // Game version
#define VERSION 200 // Game version
#define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "v1.1"
#define VERSIONSTRINGW L"v1.1"
#define VERSIONSTRING "v2.0"
#define VERSIONSTRINGW L"v2.0"
// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates!
// And change CMakeLists.txt, for CMake users!
// AND appveyor.yml, for the build bots!
@ -160,7 +160,7 @@ extern FILE *logstream;
// Does this version require an added patch file?
// Comment or uncomment this as necessary.
//#define USE_PATCH_FILE
#define USE_PATCH_FILE
// Use .kart extension addons
#define USE_KART
@ -219,7 +219,7 @@ extern FILE *logstream;
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 5
#define MODVERSION 6
// Filter consvars by version
// To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically.
@ -246,6 +246,9 @@ extern FILE *logstream;
#define PLAYERSMASK (MAXPLAYERS-1)
#define MAXPLAYERNAME 21
// Master Server compatibility ONLY
#define MSCOMPAT_MAXPLAYERS (32)
typedef enum
{
SKINCOLOR_NONE = 0,

View file

@ -1411,7 +1411,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
{
// forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
axis = JoyAxis(AXISMOVE, ssplayer);
if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer])
if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || EITHERSNEAKER(player))
{
cmd->buttons |= BT_ACCELERATE;
forward = forwardmove[1]; // 50
@ -1560,10 +1560,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
cmd->angleturn *= realtics;
// SRB2kart - no additional angle if not moving
if (((player->mo && player->speed > 0) // Moving
if ((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning
|| (player->spectator || objectplacing))) // Not a physical player
|| (player->spectator || objectplacing)) // Not a physical player
lang += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(lang >> 16);
@ -2585,6 +2585,7 @@ void G_PlayerReborn(INT32 player)
INT32 bumper;
INT32 comebackpoints;
INT32 wanted;
INT32 rings;
INT32 respawnflip;
boolean songcredit = false;
@ -2636,6 +2637,7 @@ void G_PlayerReborn(INT32 player)
itemamount = 0;
growshrinktimer = 0;
bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0);
rings = (G_BattleGametype() ? 0 : 5);
comebackpoints = 0;
wanted = 0;
starpostwp = 0;
@ -2665,6 +2667,7 @@ void G_PlayerReborn(INT32 player)
growshrinktimer = 0;
bumper = players[player].kartstuff[k_bumper];
rings = players[player].kartstuff[k_rings];
comebackpoints = players[player].kartstuff[k_comebackpoints];
wanted = players[player].kartstuff[k_wanted];
}
@ -2709,17 +2712,19 @@ void G_PlayerReborn(INT32 player)
p->pity = pity;
// SRB2kart
p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync
p->kartstuff[k_starpostwp] = starpostwp; // TODO: get these out of kartstuff, it causes desync (Does it...?)
p->kartstuff[k_itemroulette] = itemroulette;
p->kartstuff[k_roulettetype] = roulettetype;
p->kartstuff[k_itemtype] = itemtype;
p->kartstuff[k_itemamount] = itemamount;
p->kartstuff[k_growshrinktimer] = growshrinktimer;
p->kartstuff[k_bumper] = bumper;
p->kartstuff[k_rings] = rings;
p->kartstuff[k_comebackpoints] = comebackpoints;
p->kartstuff[k_comebacktimer] = comebacktime;
p->kartstuff[k_wanted] = wanted;
p->kartstuff[k_eggmanblame] = -1;
p->kartstuff[k_lastdraft] = -1;
p->kartstuff[k_starpostflip] = respawnflip;
// Don't do anything immediately
@ -5143,7 +5148,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning
|| (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player
&& !(players[displayplayers[0]].kartstuff[k_spinouttimer] && players[displayplayers[0]].kartstuff[k_sneakertimer])) // Spinning and boosting cancels out spinout
&& !(players[displayplayers[0]].kartstuff[k_spinouttimer]
&& (players[displayplayers[0]].kartstuff[k_sneakertimer] || players[displayplayers[0]].kartstuff[k_levelbooster]))) // Spinning and boosting cancels out spinout
localangle[0] += (cmd->angleturn<<16);
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
@ -5391,7 +5397,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
}
// Store the sprite frame.
frame = ghost->frame & 0xFF;
frame = ghost->frame & FF_FRAMEMASK;
if (frame != oldghost[playernum].frame)
{
oldghost[playernum].frame = frame;
@ -6045,7 +6051,7 @@ void G_ConfirmRewind(tic_t rewindtime)
G_DoPlayDemo(NULL); // Restart the current demo
for (j = 0; j < rewindtime && leveltime < rewindtime; i++)
for (j = 0; j < rewindtime && leveltime < rewindtime; j++)
{
//TryRunTics(1);
G_Ticker((j % NEWTICRATERATIO) == 0);
@ -6488,10 +6494,10 @@ void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT
{
char temp[16];
if (demoinfo_p && (UINT32)(*demoinfo_p) == 0)
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
{
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
WRITEUINT32(demoinfo_p, demo_p - demobuffer);
*(UINT32 *)demoinfo_p = demo_p - demobuffer;
}
WRITEUINT8(demo_p, DW_STANDING);
@ -7946,16 +7952,17 @@ boolean G_CheckDemoStatus(void)
void G_SaveDemo(void)
{
UINT8 *p = demobuffer+16; // checksum position
UINT8 *p = demobuffer+16; // after version
UINT32 length;
#ifdef NOMD5
UINT8 i;
#endif
// Ensure extrainfo pointer is always available, even if no info is present.
if (demoinfo_p && (UINT32)(*demoinfo_p) == 0)
if (demoinfo_p && *(UINT32 *)demoinfo_p == 0)
{
WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
WRITEUINT32(demoinfo_p, (UINT32)(demo_p - demobuffer));
*(UINT32 *)demoinfo_p = demo_p - demobuffer;
}
WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data.
@ -8001,12 +8008,14 @@ void G_SaveDemo(void)
sprintf(writepoint, "%s.lmp", demo_slug);
}
length = *(UINT32 *)demoinfo_p;
WRITEUINT32(demoinfo_p, length);
#ifdef NOMD5
for (i = 0; i < 16; i++, p++)
*p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
#else
// Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable.
md5_buffer((char *)p+16, (demobuffer + (UINT32)*demoinfo_p) - (p+16), p);
md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p);
#endif

View file

@ -1319,7 +1319,7 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
// HWR_DrawSkyWalls
// Draw walls into the depth buffer so that anything behind is culled properly
static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t bottom, fixed_t top)
static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf)
{
HWD.pfnSetTexture(NULL);
// no texture
@ -1327,9 +1327,6 @@ static void HWR_DrawSkyWall(wallVert3D *wallVerts, FSurfaceInfo *Surf, fixed_t b
wallVerts[0].t = wallVerts[1].t = 0;
wallVerts[0].s = wallVerts[3].s = 0;
wallVerts[2].s = wallVerts[1].s = 0;
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(top); // No real way to find the correct height of this
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(bottom); // worldlow/bottom because it needs to cover up the lower thok barrier wall
HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_Clip|PF_NoTexture, 255, NULL);
// PF_Invisible so it's not drawn into the colour buffer
// PF_NoTexture for no texture
@ -1462,6 +1459,111 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
worldlow = gr_backsector->floorheight;
#endif
// Sky culling
if (!gr_curline->polyseg) // Don't do it for polyobjects
{
// Sky Ceilings
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX);
if (gr_frontsector->ceilingpic == skyflatnum)
{
if (gr_backsector->ceilingpic == skyflatnum)
{
// Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the
// backsector is lower
if ((worldhigh <= worldtop)
#ifdef ESLOPE
&& (worldhighslope <= worldtopslope)
#endif
)
{
#ifdef ESLOPE
wallVerts[0].y = FIXED_TO_FLOAT(worldhigh);
wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope);
#else
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else
{
// Only the frontsector is sky, just draw a skywall from the front ceiling
#ifdef ESLOPE
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
#else
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else if (gr_backsector->ceilingpic == skyflatnum)
{
// Only the backsector is sky, just draw a skywall from the front ceiling
#ifdef ESLOPE
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
#else
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
// Sky Floors
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN);
if (gr_frontsector->floorpic == skyflatnum)
{
if (gr_backsector->floorpic == skyflatnum)
{
// Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the
// it's higher, also needs to check for bottomtexture as the floors don't usually move down
// when both sides are sky floors
if ((worldlow >= worldbottom)
#ifdef ESLOPE
&& (worldlowslope >= worldbottomslope)
#endif
&& !(gr_sidedef->bottomtexture))
{
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
#else
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else
{
// Only the backsector has sky, just draw a skywall from the back floor
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
#else
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
else if ((gr_backsector->floorpic == skyflatnum) && !(gr_sidedef->bottomtexture))
{
// Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
#else
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
// hack to allow height changes in outdoor areas
// This is what gets rid of the upper textures if there should be sky
if (gr_frontsector->ceilingpic == skyflatnum &&
@ -1914,85 +2016,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
Surf.FlatColor.rgba = 0xffffffff;
}*/
}
// Isn't this just the most lovely mess
if (!gr_curline->polyseg) // Don't do it for polyobjects
{
if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum)
{
fixed_t depthwallheight;
if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn
depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
else
depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
{
if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
{
if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture
HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX);
else
HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX);
}
// behind sector is not a thok barrier
else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector
HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
// gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on
}
else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
{
if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height
|| gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height
|| gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky
HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
}
else // neither sectors are thok barriers
{
if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower
|| gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky
HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
}
}
// And now for sky floors!
if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum)
{
fixed_t depthwallheight;
if (!gr_sidedef->bottomtexture)
depthwallheight = worldbottom > worldlow ? worldbottom : worldlow;
else
depthwallheight = worldbottom < worldlow ? worldbottom : worldlow;
if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
{
if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
{
if (!gr_sidedef->toptexture) // Only extend up if there's no texture
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh);
else
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh);
}
// behind sector is not a thok barrier
else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
}
else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
{
if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height
|| gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height
|| gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
}
else // neither sectors are thok barriers
{
if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher
|| gr_backsector->floorpic != skyflatnum) // behind sector is not a sky
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
}
}
}
}
else
{
@ -2060,13 +2083,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
}
}
else
{
#ifdef ESLOPE
//Set textures properly on single sided walls that are sloped
wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
#else
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom);
#endif
// When there's no midtexture, draw a skywall to prevent rendering behind it
HWR_DrawSkyWall(wallVerts, &Surf);
}
// Single sided lines are simple for skywalls, just need to draw from the top or bottom of the sector if there's
// a sky flat
if (!gr_curline->polyseg)
{
if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX);
{
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX);
#ifdef ESLOPE
wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
#else
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop);
#endif
HWR_DrawSkyWall(wallVerts, &Surf);
}
if (gr_frontsector->floorpic == skyflatnum)
HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom);
{
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
#else
wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom);
#endif
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN);
HWR_DrawSkyWall(wallVerts, &Surf);
}
}
}
@ -2381,7 +2443,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// e6y: Check whether the player can look beyond this line
//
#ifdef NEWCLIP
boolean checkforemptylines = true;
static boolean checkforemptylines = true;
// Don't modify anything here, just check
// Kalaron: Modified for sloped linedefs
static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector)
@ -2421,62 +2483,47 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
backc1 = backc2 = abacksector->ceilingheight;
}
// now check for closed sectors!
if (backc1 <= frontf1 && backc2 <= frontf2)
if (viewsector != abacksector && viewsector != afrontsector)
{
checkforemptylines = false;
if (!seg->sidedef->toptexture)
return false;
boolean mydoorclosed = false; // My door? Closed!? (doorclosed is actually otherwise unused in openGL)
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
return false;
return true;
}
if (backf1 >= frontc1 && backf2 >= frontc2)
{
checkforemptylines = false;
if (!seg->sidedef->bottomtexture)
return false;
// properly render skies (consider door "open" if both floors are sky):
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
return false;
return true;
}
if (backc1 <= backf1 && backc2 <= backf2)
{
checkforemptylines = false;
// preserve a kind of transparent door/lift special effect:
if (backc1 < frontc1 || backc2 < frontc2)
{
if (!seg->sidedef->toptexture)
return false;
}
if (backf1 > frontf1 || backf2 > frontf2)
{
if (!seg->sidedef->bottomtexture)
return false;
}
if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum)
return false;
if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum)
return false;
return true;
}
if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2)
// If the sector behind the line blocks all kinds of view past it
// (back ceiling is lower than close floor, or back floor is higher than close ceiling)
if ((backc1 <= frontf1 && backc2 <= frontf2)
|| (backf1 >= frontc1 && backf2 >= frontc2))
{
checkforemptylines = false;
return false;
return true;
}
// The door is closed if:
// backsector is 0 height or less and
// back ceiling is higher than close ceiling or we need to render a top texture and
// back floor is lower than close floor or we need to render a bottom texture and
// neither front or back sectors are using the sky ceiling
mydoorclosed = (backc1 <= backf1 && backc2 <= backf2
&& ((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture)
&& ((backf1 <= frontf1 && backf2 >= frontf2) || seg->sidedef->bottomtexture)
&& (abacksector->ceilingpic != skyflatnum || afrontsector->ceilingpic != skyflatnum));
if (mydoorclosed)
{
checkforemptylines = false;
return true;
}
}
// Window.
// We know it's a window when the above isn't true and the back and front sectors don't match
if (backc1 != frontc1 || backc2 != frontc2
|| backf1 != frontf1 || backf2 != frontf2)
{
checkforemptylines = false;
return false;
}
// In this case we just need to check whether there is actually a need to render any lines, so checkforempty lines
// stays true
return false;
}
#else
@ -4220,7 +4267,11 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *sector->lightlist[light].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap;
@ -4441,16 +4492,20 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
alpha = Surf.FlatColor.s.alpha;
// Start with the lightlevel and colormap from the top of the sprite
lightlevel = *list[sector->numlights - 1].lightlevel;
colormap = list[sector->numlights - 1].extra_colormap;
i = 0;
temp = FLOAT_TO_FIXED(realtop);
if (spr->mobj->frame & FF_FULLBRIGHT)
lightlevel = 255;
#ifdef ESLOPE
// Start with the lightlevel and colormap from the top of the sprite
lightlevel = 255;
colormap = list[sector->numlights - 1].extra_colormap;
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[sector->numlights - 1].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
for (i = 1; i < sector->numlights; i++)
{
fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y)
@ -4458,7 +4513,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (h <= temp)
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i-1].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i-1].extra_colormap;
break;
}
@ -4466,7 +4525,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
#else
i = R_GetPlaneLight(sector, temp, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i].extra_colormap;
#endif
@ -4482,7 +4545,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i].extra_colormap;
}
@ -4775,7 +4842,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
extracolormap_t *colormap = sector->extra_colormap;
if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = sector->lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
@ -4886,6 +4957,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
colormap = sector->extra_colormap;
}
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
else
@ -5470,7 +5544,7 @@ static void HWR_AddSprites(sector_t *sec)
}
#ifdef HWPRECIP
// Someone seriously wants infinite draw distance for precipitation?
// No to infinite precipitation draw distance.
if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS))
{
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
@ -5486,13 +5560,6 @@ static void HWR_AddSprites(sector_t *sec)
HWR_ProjectPrecipitationSprite(precipthing);
}
}
else
{
// Draw everything in sector, no checks
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
if (!(precipthing->precipflags & PCF_INVISIBLE))
HWR_ProjectPrecipitationSprite(precipthing);
}
#endif
}
@ -5515,6 +5582,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
size_t lumpoff;
unsigned rot;
UINT8 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
angle_t ang;
INT32 heightsec, phs;
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
@ -5646,7 +5714,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
x1 = tr_x + x1 * rightcos;
x2 = tr_x - x2 * rightcos;
if (thing->eflags & MFE_VERTICALFLIP)
if (vflip)
{
gz = FIXED_TO_FLOAT(thing->z+thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale;
gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
@ -5733,10 +5801,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
//CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n",
// thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
if (thing->eflags & MFE_VERTICALFLIP)
vis->vflip = true;
else
vis->vflip = false;
vis->vflip = vflip;
vis->precip = false;
}

View file

@ -2386,7 +2386,7 @@ void HU_Drawer(void)
}*/
// draw song credits
if (cv_songcredits.value)
if (cv_songcredits.value && !( hu_showscores && (netgame || multiplayer) ))
HU_DrawSongCredits();
// draw desynch text

View file

@ -1311,7 +1311,7 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
int gaie;
if (!port || !port[0])
port = port_name;
port = DEFAULTPORT;
DEBFILE(va("Creating new node: %s@%s\n", address, port));

View file

@ -69,7 +69,7 @@ char sprnames[NUMSPRITES + 1][5] =
"CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH",
"MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT",
"OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK",
"XMS4","XMS5","VIEW"
"MXCL","RGSP","DRAF","XMS4","XMS5","VIEW"
};
// Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@ -969,7 +969,19 @@ state_t states[NUMSTATES] =
{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12
// Ring
{SPR_RING, FF_ANIMATE, -1, {NULL}, 23, 1, S_RING}, // S_RING
{SPR_RING, FF_SEMIBRIGHT|FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING
{SPR_RING, 0, 1, {NULL}, 0, 0, S_FASTRING2}, // S_FASTRING1
{SPR_RING, 2, 1, {NULL}, 0, 0, S_FASTRING3}, // S_FASTRING2
{SPR_RING, 4, 1, {NULL}, 0, 0, S_FASTRING4}, // S_FASTRING3
{SPR_RING, 6, 1, {NULL}, 0, 0, S_FASTRING5}, // S_FASTRING4
{SPR_RING, 8, 1, {NULL}, 0, 0, S_FASTRING6}, // S_FASTRING5
{SPR_RING, 10, 1, {NULL}, 0, 0, S_FASTRING7}, // S_FASTRING6
{SPR_RING, 12, 1, {NULL}, 0, 0, S_FASTRING8}, // S_FASTRING7
{SPR_RING, 14, 1, {NULL}, 0, 0, S_FASTRING9}, // S_FASTRING8
{SPR_RING, 16, 1, {NULL}, 0, 0, S_FASTRING10}, // S_FASTRING9
{SPR_RING, 18, 1, {NULL}, 0, 0, S_FASTRING11}, // S_FASTRING10
{SPR_RING, 20, 1, {NULL}, 0, 0, S_FASTRING12}, // S_FASTRING11
{SPR_RING, 22, 1, {NULL}, 0, 0, S_FASTRING1}, // S_FASTRING12
// Blue Sphere Replacement for special stages
{SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL
@ -3401,6 +3413,30 @@ state_t states[NUMSTATES] =
{SPR_SMOK, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4
{SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5
{SPR_MXCL, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_RINGDEBT
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_RINGSPARKS2}, // S_RINGSPARKS1
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_RINGSPARKS3}, // S_RINGSPARKS2
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_RINGSPARKS4}, // S_RINGSPARKS3
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|3, 1, {NULL}, 0, 0, S_RINGSPARKS5}, // S_RINGSPARKS4
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|4, 1, {NULL}, 0, 0, S_RINGSPARKS6}, // S_RINGSPARKS5
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_RINGSPARKS7}, // S_RINGSPARKS6
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|6, 1, {NULL}, 0, 0, S_RINGSPARKS8}, // S_RINGSPARKS7
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|7, 1, {NULL}, 0, 0, S_RINGSPARKS9}, // S_RINGSPARKS8
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|8, 1, {NULL}, 0, 0, S_RINGSPARKS10}, // S_RINGSPARKS9
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|9, 1, {NULL}, 0, 0, S_RINGSPARKS11}, // S_RINGSPARKS10
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|10, 1, {NULL}, 0, 0, S_RINGSPARKS12}, // S_RINGSPARKS11
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|11, 1, {NULL}, 0, 0, S_RINGSPARKS13}, // S_RINGSPARKS12
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|12, 1, {NULL}, 0, 0, S_RINGSPARKS14}, // S_RINGSPARKS13
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|13, 1, {NULL}, 0, 0, S_RINGSPARKS15}, // S_RINGSPARKS14
{SPR_RGSP, FF_PAPERSPRITE|FF_FULLBRIGHT|14, 1, {NULL}, 0, 0, S_NULL}, // S_RINGSPARKS15
{SPR_DRAF, 0, 2, {NULL}, 0, 0, S_DRAFTDUST2}, // S_DRAFTDUST1
{SPR_DRAF, 1, 1, {NULL}, 0, 0, S_DRAFTDUST3}, // S_DRAFTDUST2
{SPR_DRAF, 2, 1, {NULL}, 0, 0, S_DRAFTDUST4}, // S_DRAFTDUST3
{SPR_DRAF, 3, 1, {NULL}, 0, 0, S_DRAFTDUST5}, // S_DRAFTDUST4
{SPR_DRAF, 4, 1, {NULL}, 0, 0, S_NULL}, // S_DRAFTDUST5
#ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif
@ -5447,12 +5483,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_SPRK1, // deathstate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_itemup, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
48*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
@ -5478,13 +5514,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
38*FRACUNIT, // speed
15*FRACUNIT, // radius
24*FRACUNIT, // height
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
MF_SLIDEME|MF_BOUNCE|MF_SPECIAL|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
@ -20059,6 +20095,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_RINGSPARKS
-1, // doomednum
S_RINGSPARKS1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8<<FRACBITS, // radius
16<<FRACBITS, // height
1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_DRAFTDUST
-1, // doomednum
S_DRAFTDUST1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8<<FRACBITS, // radius
16<<FRACBITS, // height
1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
// ============================================================================================================================//
#ifdef SEENAMES

View file

@ -775,6 +775,9 @@ typedef enum sprite
SPR_WBLN,
SPR_FWRK,
SPR_MXCL,
SPR_RGSP,
SPR_DRAF,
// Xmas-specific sprites that don't fit aboxe
SPR_XMS4,
@ -1675,6 +1678,18 @@ typedef enum state
// Ring
S_RING,
S_FASTRING1,
S_FASTRING2,
S_FASTRING3,
S_FASTRING4,
S_FASTRING5,
S_FASTRING6,
S_FASTRING7,
S_FASTRING8,
S_FASTRING9,
S_FASTRING10,
S_FASTRING11,
S_FASTRING12,
// Blue Sphere for special stages
S_BLUEBALL,
@ -4058,6 +4073,29 @@ typedef enum state
S_OPAQUESMOKE4,
S_OPAQUESMOKE5,
S_RINGDEBT,
S_RINGSPARKS1,
S_RINGSPARKS2,
S_RINGSPARKS3,
S_RINGSPARKS4,
S_RINGSPARKS5,
S_RINGSPARKS6,
S_RINGSPARKS7,
S_RINGSPARKS8,
S_RINGSPARKS9,
S_RINGSPARKS10,
S_RINGSPARKS11,
S_RINGSPARKS12,
S_RINGSPARKS13,
S_RINGSPARKS14,
S_RINGSPARKS15,
S_DRAFTDUST1,
S_DRAFTDUST2,
S_DRAFTDUST3,
S_DRAFTDUST4,
S_DRAFTDUST5,
#ifdef SEENAMES
S_NAMECHECK,
#endif
@ -4861,6 +4899,8 @@ typedef enum mobj_type
MT_LIONMAN,
MT_KARMAFIREWORK,
MT_RINGSPARKS,
MT_DRAFTDUST,
#ifdef SEENAMES
MT_NAMECHECK,

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,9 @@ void K_RegisterKartStuff(void);
boolean K_IsPlayerLosing(player_t *player);
boolean K_IsPlayerWanted(player_t *player);
fixed_t K_GetKartGameSpeedScalar(SINT8 value);
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_KartPainEnergyFling(player_t *player);
void K_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_RespawnChecker(player_t *player);
@ -41,6 +43,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
void K_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_SpawnDraftDust(mobj_t *mo);
void K_DriftDustHandling(mobj_t *spawner);
void K_PuntMine(mobj_t *mine, mobj_t *punter);
void K_DoSneaker(player_t *player, INT32 type);
@ -74,6 +77,7 @@ void K_CheckSpectateStatus(void);
void K_PlayAttackTaunt(mobj_t *source);
void K_PlayBoostTaunt(mobj_t *source);
void K_PlayOvertakeSound(mobj_t *source);
void K_PlayPainSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source);
void K_PlayPowerGloatSound(mobj_t *source);

View file

@ -1166,37 +1166,6 @@ static int lib_pPlayerRingBurst(lua_State *L)
return 0;
}
static int lib_pPlayerWeaponPanelBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelBurst(player);
return 0;
}
static int lib_pPlayerWeaponAmmoBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponAmmoBurst(player);
return 0;
}
static int lib_pPlayerEmeraldBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerEmeraldBurst(player, toss);
return 0;
}
static int lib_pPlayerFlagBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2229,6 +2198,16 @@ static int lib_kOvertakeSound(lua_State *L)
return 0;
}
static int lib_kPainSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayPainSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayPainSound(mobj);
return 0;
}
static int lib_kHitEmSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2744,9 +2723,6 @@ static luaL_Reg lib[] = {
{"P_DamageMobj",lib_pDamageMobj},
{"P_KillMobj",lib_pKillMobj},
{"P_PlayerRingBurst",lib_pPlayerRingBurst},
{"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst},
{"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst},
{"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst},
{"P_PlayerFlagBurst",lib_pPlayerFlagBurst},
{"P_PlayRinglossSound",lib_pPlayRinglossSound},
{"P_PlayDeathSound",lib_pPlayDeathSound},
@ -2835,6 +2811,7 @@ static luaL_Reg lib[] = {
{"K_PlayPowerGloatSound", lib_kGloatSound},
{"K_PlayOvertakeSound", lib_kOvertakeSound},
{"K_PlayLossSound", lib_kLossSound},
{"K_PlayPainSound", lib_kPainSound},
{"K_PlayHitEmSound", lib_kHitEmSound},
{"K_GetKartColorByName",lib_kGetKartColorByName},
{"K_IsPlayerLosing",lib_kIsPlayerLosing},

View file

@ -522,7 +522,7 @@ static menuitem_t PlaybackMenu[] =
{IT_CALL | IT_STRING, "M_PREW", "Rewind", M_PlaybackRewind, 20},
{IT_CALL | IT_STRING, "M_PPAUSE", "Pause", M_PlaybackPause, 36},
{IT_CALL | IT_STRING, "M_PFFWD", "Fast-Foward", M_PlaybackFastForward, 52},
{IT_CALL | IT_STRING, "M_PFFWD", "Fast-Forward", M_PlaybackFastForward, 52},
{IT_CALL | IT_STRING, "M_PSTEPB", "Backup Frame", M_PlaybackRewind, 20},
{IT_CALL | IT_STRING, "M_PRESUM", "Resume", M_PlaybackPause, 36},
{IT_CALL | IT_STRING, "M_PFADV", "Advance Frame", M_PlaybackAdvance, 52},
@ -1561,7 +1561,7 @@ static menuitem_t OP_AdvServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66},
};*/
#define ITEMTOGGLEBOTTOMRIGHT
//#define ITEMTOGGLEBOTTOMRIGHT
static menuitem_t OP_MonitorToggleMenu[] =
{
@ -1589,6 +1589,7 @@ static menuitem_t OP_MonitorToggleMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", M_HandleMonitorToggles, KITEM_SUPERRING},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK},
#ifdef ITEMTOGGLEBOTTOMRIGHT
{IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255},
@ -8444,7 +8445,11 @@ static void M_ConnectMenu(INT32 choice)
// first page of servers
serverlistpage = 0;
if (ms_RoomId < 0)
{
M_RoomMenu(0); // Select a room instead of staring at an empty list
// This prevents us from returning to the modified game alert.
currentMenu->prevMenu = &MP_MainDef;
}
else
M_SetupNextMenu(&MP_ConnectDef);
itemOn = 0;
@ -10643,6 +10648,7 @@ static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = {
&cv_thundershield,
&cv_hyudoro,
&cv_pogospring,
&cv_superring,
&cv_kitchensink,
&cv_triplesneaker,
&cv_triplebanana,

View file

@ -661,19 +661,11 @@ FUNCMATH static const char *int2str(INT32 n)
#ifndef NONET
static INT32 ConnectionFailed(void)
{
time(&MSLastPing);
con_state = MSCS_FAILED;
CONS_Alert(CONS_ERROR, M_GetText("Connection to Master Server failed\n"));
CloseConnection();
return MS_CONNECT_ERROR;
}
static INT32 ConnectionFailedwerrno(int no)
{
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error: %s\n"),
strerror(no));
return ConnectionFailed();
}
#endif
/** Tries to register the local game server on the master server.
@ -690,43 +682,57 @@ static INT32 AddToMasterServer(boolean firstadd)
msg_server_t *info = (msg_server_t *)msg.buffer;
INT32 room = -1;
fd_set tset;
time_t timestamp = time(NULL);
UINT32 signature, tmp;
const char *insname;
if (socket_fd == (SOCKET_TYPE)ERRSOCKET)/* Woah, our socket was closed! */
{
if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
return ConnectionFailedwerrno(errno);
}
M_Memcpy(&tset, &wset, sizeof (tset));
res = select(255, NULL, &tset, NULL, &select_timeout);
if (res == ERRSOCKET)
return ConnectionFailedwerrno(errno);
if (res == 0)/* nothing selected */
if (res != ERRSOCKET && !res)
{
/*
Timeout next call because SendPingToMasterServer
(our calling function) already calls this once
every two minutes.
*/
if (retry++ == 1)
if (retry++ > 30) // an about 30 second timeout
{
retry = 0;
CONS_Alert(CONS_ERROR, M_GetText("Master Server timed out\n"));
MSLastPing = timestamp;
return ConnectionFailed();
}
return MS_CONNECT_ERROR;
}
retry = 0;
/*
Somehow we can still select our old socket despite it being closed(?).
Atleast, that's what I THINK is happening. Anyway, we have to check that we
haven't open a socket, and actually open it!
*/
/*if (res == ERRSOCKET)*//* wtf? no! */
if (socket_fd == (SOCKET_TYPE)ERRSOCKET)
{
if (MS_Connect(GetMasterServerIP(), GetMasterServerPort(), 0))
{
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
MSLastPing = timestamp;
return ConnectionFailed();
}
}
// so, the socket is writable, but what does that mean, that the connection is
// ok, or bad... let see that!
j = (socklen_t)sizeof (i);
if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j) == ERRSOCKET)
return ConnectionFailedwerrno(errno);
getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, (char *)&i, &j);
/*
This is also wrong. If getsockopt fails, i doesn't have to be set. Plus, if
it is set (which it appearantly is on linux), we check errno anyway. And in
the case that i is returned as normal, we don't even report the correct
value! So we accomplish NOTHING, except returning due to dumb luck.
If you care, fix this--I don't. -James (R.)
*/
if (i) // it was bad
return ConnectionFailedwerrno(i);
{
CONS_Alert(CONS_ERROR, M_GetText("Master Server socket error #%u: %s\n"), errno, strerror(errno));
MSLastPing = timestamp;
return ConnectionFailed();
}
#ifdef PARANOIA
if (ms_RoomId <= 0)
@ -759,12 +765,15 @@ static INT32 AddToMasterServer(boolean firstadd)
msg.length = (UINT32)sizeof (msg_server_t);
msg.room = 0;
if (MS_Write(&msg) < 0)
{
MSLastPing = timestamp;
return ConnectionFailed();
}
if(con_state != MSCS_REGISTERED)
CONS_Printf(M_GetText("Master Server update successful.\n"));
time(&MSLastPing);
MSLastPing = timestamp;
con_state = MSCS_REGISTERED;
CloseConnection();
#endif

View file

@ -710,59 +710,6 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
//return false;
}
/** Looks for a player with a ring shield.
* Used by rings.
*
* \param actor Ring looking for a shield to be attracted to.
* \return True if a player with ring shield is found, otherwise false.
* \sa A_AttractChase
*/
static boolean P_LookForShield(mobj_t *actor)
{
INT32 c = 0, stop;
player_t *player;
// BP: first time init, this allow minimum lastlook changes
if (actor->lastlook < 0)
actor->lastlook = P_RandomByte();
actor->lastlook %= MAXPLAYERS;
stop = (actor->lastlook - 1) & PLAYERSMASK;
for (; ; actor->lastlook = ((actor->lastlook + 1) & PLAYERSMASK))
{
// done looking
if (actor->lastlook == stop)
return false;
if (!playeringame[actor->lastlook])
continue;
if (c++ == 2)
return false;
player = &players[actor->lastlook];
if (player->health <= 0 || !player->mo)
continue; // dead
//When in CTF, don't pull rings that you cannot pick up.
if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) ||
(actor->type == MT_BLUETEAMRING && player->ctfteam != 2))
continue;
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
&& (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST/4, player->mo->scale)))
{
P_SetTarget(&actor->tracer, player->mo);
return true;
}
}
//return false;
}
#ifdef WEIGHTEDRECYCLER
// Compares players to see who currently has the "best" items, etc.
static int P_RecycleCompare(const void *p1, const void *p2)
@ -3611,61 +3558,179 @@ void A_BubbleCheck(mobj_t *actor)
//
void A_AttractChase(mobj_t *actor)
{
fixed_t z;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_AttractChase", actor))
return;
#endif
if (actor->flags2 & MF2_NIGHTSPULL || !actor->health)
return;
// spilled rings flicker before disappearing
if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE)
actor->flags2 |= MF2_DONTDRAW;
if (actor->extravalue1) // SRB2Kart
{
#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2)
if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player)
{
P_RemoveMobj(actor);
return;
}
if (actor->extravalue2) // Using for ring boost
{
// Always fullbright
actor->frame |= FF_FULLBRIGHT;
if (actor->extravalue1 >= 21)
{
mobj_t *sparkle;
angle_t offset = FixedAngle(18<<FRACBITS);
// Base add is 3 tics for 9,9, adds 1 tic for each point closer to the 1,1 end
actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3;
S_StartSound(actor->target, sfx_s1b5);
sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS);
P_SetTarget(&sparkle->target, actor->target);
sparkle->angle = (actor->target->angle + (offset>>1)) + (offset * actor->target->player->kartstuff[k_sparkleanim]);
actor->target->player->kartstuff[k_sparkleanim] = (actor->target->player->kartstuff[k_sparkleanim]+1) % 20;
P_KillMobj(actor, actor->target, actor->target);
return;
}
else
{
fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT));
//P_SetScale(actor, (actor->destscale = actor->target->scale));
z = actor->target->z;
if (( actor->eflags & MFE_VERTICALFLIP ))
z -= actor->height + offz;
else
z += actor->target->height + offz;
P_TeleportMove(actor, actor->target->x, actor->target->y, z);
actor->extravalue1++;
}
}
else // Collecting
{
if (actor->extravalue1 >= 16)
{
if (actor->target->player->kartstuff[k_rings] >= 20)
actor->target->player->kartstuff[k_ringboost] += RINGBOOSTPWR+3;
else
P_GivePlayerRings(actor->target->player, 1);
if (actor->cvmem) // caching
S_StartSound(actor->target, sfx_s1c5);
else
S_StartSound(actor->target, sfx_s227);
actor->target->player->kartstuff[k_pickuprings]--;
P_RemoveMobj(actor);
return;
}
else
{
fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1);
P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1)));
z = actor->target->z;
if (( actor->eflags & MFE_VERTICALFLIP ))
z += actor->target->height - actor->height - 24 * actor->target->scale;
else
z += 24 * actor->target->scale;
P_TeleportMove(actor,
actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)),
actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)),
z);
actor->angle += ANG30;
actor->extravalue1++;
}
}
#undef RINGBOOSTPWR
}
else
actor->flags2 &= ~MF2_DONTDRAW;
// Turn flingrings back into regular rings if attracted.
if (actor->tracer && actor->tracer->player
&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT
&& actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
{
mobj_t *newring;
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime);
newring->momx = actor->momx;
newring->momy = actor->momy;
newring->momz = actor->momz;
P_RemoveMobj(actor);
return;
// Don't immediately pick up spilled rings
if (actor->threshold > 0)
actor->threshold--;
// Rings flicker before disappearing
if (actor->fuse && actor->fuse < 5*TICRATE && (leveltime & 1))
actor->flags2 |= MF2_DONTDRAW;
else
actor->flags2 &= ~MF2_DONTDRAW;
// spilled rings have ghost trails and get capped to a certain speed
if (actor->type == (mobjtype_t)actor->info->reactiontime)
{
const fixed_t maxspeed = 4<<FRACBITS;
fixed_t oldspeed = R_PointToDist2(0, 0, actor->momx, actor->momy);
if (oldspeed > maxspeed)
{
fixed_t newspeed = max(maxspeed, oldspeed-FRACUNIT);
actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed);
actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed);
}
if (!P_IsObjectOnGround(actor))
P_SpawnGhostMobj(actor)->tics = 3;
}
if (actor->tracer && actor->tracer->player && actor->tracer->health
//&& P_CheckSight(actor, actor->tracer)
&& actor->tracer->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD
&& (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20
&& !actor->tracer->player->kartstuff[k_ringlock])
{
fixed_t dist;
angle_t hang, vang;
// If a flung ring gets attracted by a shield, change it into a normal ring.
if (actor->type == (mobjtype_t)actor->info->reactiontime)
{
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance);
P_RemoveMobj(actor);
return;
}
// Keep stuff from going down inside floors and junk
actor->flags &= ~MF_NOCLIPHEIGHT;
// Let attracted rings move through walls and such.
actor->flags |= MF_NOCLIP;
// P_Attract is too "smart" for Kart; keep it simple, stupid!
dist = P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z);
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
vang = R_PointToAngle2(actor->z , 0, actor->tracer->z, dist);
actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4;
actor->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), 4*actor->scale));
actor->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), 4*actor->scale));
actor->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), 4*actor->scale);
}
else
{
// Turn rings back into flung rings if lost
if (actor->cusval && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
{
mobj_t *newring;
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime);
P_InstaThrust(newring, P_RandomRange(0,7) * ANGLE_45, 2<<FRACBITS);
newring->momz = 8<<FRACBITS;
newring->fuse = 120*TICRATE;
P_RemoveMobj(actor);
return;
}
/*else
P_LookForShield(actor);*/
// SRB2Kart: now it's the PLAYER'S job to use the blockmap to find rings, not the ring's.
}
}
P_LookForShield(actor); // Go find 'em, boy!
if (!actor->tracer
|| !actor->tracer->player
|| !actor->tracer->health
|| !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta
{
// Lost attracted rings don't through walls anymore.
actor->flags &= ~MF_NOCLIP;
P_SetTarget(&actor->tracer, NULL);
return;
}
// If a FlingRing gets attracted by a shield, change it into a normal ring.
if (actor->type == (mobjtype_t)actor->info->reactiontime)
{
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance);
P_RemoveMobj(actor);
return;
}
// Keep stuff from going down inside floors and junk
actor->flags &= ~MF_NOCLIPHEIGHT;
// Let attracted rings move through walls and such.
actor->flags |= MF_NOCLIP;
P_Attract(actor, actor->tracer, false);
}
// Function: A_DropMine
@ -8256,7 +8321,11 @@ void A_ItemPop(mobj_t *actor)
void A_JawzChase(mobj_t *actor)
{
const fixed_t currentspeed = R_PointToDist2(0, 0, actor->momx, actor->momy);
player_t *player;
fixed_t thrustamount = 0;
fixed_t frictionsafety = (actor->friction == 0) ? 1 : actor->friction;
fixed_t topspeed = actor->movefactor;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_JawzChase", actor))
return;
@ -8269,20 +8338,100 @@ void A_JawzChase(mobj_t *actor)
if (actor->tracer->health)
{
const angle_t targetangle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
mobj_t *ret;
angle_t angledelta = actor->angle - targetangle;
boolean turnclockwise = true;
if (G_RaceGametype())
{
const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4)));
const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
if (distaway < distbarrier)
{
if (actor->tracer->player)
{
fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false)));
topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier));
}
}
}
if (angledelta != 0)
{
angle_t MAX_JAWZ_TURN = ANGLE_90/15; // We can turn a maximum of 6 degrees per frame at regular max speed
// MAX_JAWZ_TURN gets stronger the slower the top speed of jawz
if (topspeed < actor->movefactor)
{
if (topspeed == 0)
{
MAX_JAWZ_TURN = ANGLE_180;
}
else
{
fixed_t anglemultiplier = FixedDiv(actor->movefactor, topspeed);
MAX_JAWZ_TURN += FixedAngle(FixedMul(AngleFixed(MAX_JAWZ_TURN), anglemultiplier));
}
}
if (angledelta > ANGLE_180)
{
angledelta = InvAngle(angledelta);
turnclockwise = false;
}
if (angledelta > MAX_JAWZ_TURN)
{
angledelta = MAX_JAWZ_TURN;
}
if (turnclockwise)
{
actor->angle -= angledelta;
}
else
{
actor->angle += angledelta;
}
}
ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE);
P_SetTarget(&ret->target, actor->tracer);
ret->frame |= ((leveltime % 10) / 2) + 5;
ret->color = actor->cvmem;
P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), (7*actor->movefactor)/64);
return;
}
else
P_SetTarget(&actor->tracer, NULL);
}
if (!P_IsObjectOnGround(actor))
{
// No friction in the air
frictionsafety = FRACUNIT;
}
if (currentspeed >= topspeed)
{
// Thrust as if you were at top speed, slow down naturally
thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed;
}
else
{
const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed;
// Thrust to immediately get to top speed
thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety);
}
if (!actor->tracer)
{
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
}
P_Thrust(actor, actor->angle, thrustamount);
if ((actor->tracer != NULL) && (actor->tracer->health > 0))
return;
if (actor->extravalue1) // Disable looking by setting this
return;
@ -8405,6 +8554,7 @@ void A_SPBChase(mobj_t *actor)
fixed_t easiness = ((actor->tracer->player->kartspeed + (10-spark)) << FRACBITS) / 2;
actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming...
actor->tracer->player->kartstuff[k_ringlock] = 1; // set ring lock
if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/)
{
@ -8488,6 +8638,15 @@ void A_SPBChase(mobj_t *actor)
actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
// Spawn a trail of rings behind the SPB!
if (leveltime % 6 == 0)
{
mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx,
actor->z - actor->momz + (24*mapobjectscale), MT_RING);
ring->threshold = 10;
ring->fuse = 120*TICRATE;
}
// Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed!
if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15
: (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
@ -8529,6 +8688,7 @@ void A_SPBChase(mobj_t *actor)
&& !players[actor->lastlook].exiting)
{
spbplace = players[actor->lastlook].kartstuff[k_position];
players[actor->lastlook].kartstuff[k_ringlock] = 1;
if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo)
{
P_SetTarget(&actor->tracer, players[actor->lastlook].mo);

View file

@ -116,7 +116,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
{
// Invulnerable
if (player->powers[pw_flashing] > 0
|| player->kartstuff[k_spinouttimer] > 0
|| (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)
|| player->kartstuff[k_squishedtimer] > 0
|| player->kartstuff[k_invincibilitytimer] > 0
|| player->kartstuff[k_growshrinktimer] > 0
@ -494,7 +494,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1)
special->target->player->kartstuff[k_yougotem] = 2*TICRATE;
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true);
@ -557,7 +557,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1)
special->target->player->kartstuff[k_yougotem] = 2*TICRATE;
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true);
@ -687,15 +687,34 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
/* FALLTHRU */
case MT_RING:
case MT_FLINGRING:
if (special->extravalue1)
return;
// No picking up rings while SPB is targetting you
if (player->kartstuff[k_ringlock])
return;
// Don't immediately pick up spilled rings
if (special->threshold > 0
|| player->kartstuff[k_squishedtimer]
|| player->kartstuff[k_spinouttimer])
return;
if (!(P_CanPickupItem(player, 0)))
return;
special->momx = special->momy = special->momz = 0;
P_GivePlayerRings(player, 1);
// Reached the cap, don't waste 'em!
if ((player->kartstuff[k_rings] + player->kartstuff[k_pickuprings]) >= 20)
return;
if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING)
P_DoNightsScore(player);
break;
special->momx = special->momy = special->momz = 0;
special->extravalue1 = 1; // Ring collect animation timer
special->angle = R_PointToAngle2(toucher->x, toucher->y, special->x, special->y); // animation angle
P_SetTarget(&special->target, toucher); // toucher for thinker
player->kartstuff[k_pickuprings]++;
return;
case MT_COIN:
case MT_FLINGCOIN:
@ -2816,16 +2835,8 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return true;
}
if (target->health <= 1) // Death
{
P_PlayDeathSound(target);
P_PlayVictorySound(source); // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!!
}
else if (target->health > 1) // Ring loss
{
P_PlayRinglossSound(target);
P_PlayerRingBurst(player, player->mo->health - 1);
}
P_PlayRinglossSound(target);
P_PlayerRingBurst(player, 5);
if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
@ -2881,14 +2892,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
{
player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE);
(void)source;
// Burst weapons and emeralds in Match/CTF only
if (source && (G_BattleGametype()))
{
P_PlayerRingBurst(player, player->health - 1);
P_PlayerEmeraldBurst(player, false);
}
player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE);
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
@ -2904,32 +2910,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
/*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
// If the player was super, tell them he/she ain't so super nomore.
if (gametype != GT_COOP && player->powers[pw_super])
{
S_StartSound(NULL, sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}*/
if (player->pflags & PF_TIMEOVER)
{
mobj_t *boom;
@ -2990,75 +2970,6 @@ void P_RemoveShield(player_t *player)
player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK;
}
/*
static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
// Must do pain first to set flashing -- P_RemoveShield can cause damage
P_DoPlayerPain(player, source, inflictor);
P_RemoveShield(player);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes
S_StartSound(player->mo, sfx_spkdth);
else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, cv_match_scoring.value == 1 ? 25 : 50);
}
}
*/
static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
//const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1);
if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoPlayerPain(player, source, inflictor);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes
S_StartSound(player->mo, sfx_spkdth);
}
/*if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
}*/
// Ring loss sound plays despite hitting spikes
P_PlayRinglossSound(player->mo); // Ringledingle!
}
/** Damages an object, which may or may not be a player.
* For melee attacks, source and inflictor are the same.
@ -3276,121 +3187,21 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|| inflictor->type == MT_SMK_THWOMP || inflictor->player))
{
player->kartstuff[k_sneakertimer] = 0;
K_SpinPlayer(player, source, 1, inflictor, false);
damage = player->mo->health - 1;
P_RingDamage(player, inflictor, source, damage);
P_PlayerRingBurst(player, 5);
if (P_IsLocalPlayer(player))
K_KartPainEnergyFling(player);
if (P_IsDisplayPlayer(player))
{
quake.intensity = 32*FRACUNIT;
quake.time = 5;
}
}
else
{
K_SpinPlayer(player, source, 0, inflictor, false);
}
return true;
}
/* // SRB2kart - don't need these
else if (metalrecording)
{
if (!inflictor)
inflictor = source;
if (inflictor && inflictor->flags & MF_ENEMY)
{ // Metal Sonic destroy enemy !!
P_KillMobj(inflictor, NULL, target);
return false;
}
else if (inflictor && inflictor->flags & MF_MISSILE)
return false; // Metal Sonic walk through flame !!
else
{ // Oh no! Metal Sonic is hit !!
P_ShieldDamage(player, inflictor, source, damage);
return true;
}
}
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] // ignore bouncing & such in invulnerability
|| (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player))))
{
if (force || (inflictor && (inflictor->flags & MF_MISSILE)
&& (inflictor->flags2 & MF2_SUPERFIRE)
&& player->powers[pw_super]))
{
#ifdef HAVE_BLUA
if (!LUAh_MobjDamage(target, inflictor, source, damage))
#endif
P_SuperDamage(player, inflictor, source, damage);
return true;
}
else
return false;
}
#ifdef HAVE_BLUA
else if (LUAh_MobjDamage(target, inflictor, source, damage))
return true;
#endif
else if (!player->powers[pw_super] && (player->powers[pw_shield] || player->bot)) //If One-Hit Shield
{
P_ShieldDamage(player, inflictor, source, damage);
damage = 0;
}
else if (player->mo->health > 1) // No shield but have rings.
{
damage = player->mo->health - 1;
P_RingDamage(player, inflictor, source, damage);
}
else // No shield, no rings, no invincibility.
{
// To reduce griefing potential, don't allow players to be killed
// by friendly fire. Spilling their rings and other items is enough.
if (force || !(G_GametypeHasTeams()
&& source && source->player && (source->player->ctfteam == player->ctfteam)
&& cv_friendlyfire.value))
{
damage = 1;
P_KillPlayer(player, source, damage);
}
else
{
damage = 0;
P_ShieldDamage(player, inflictor, source, damage);
}
}
*/
if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
if (player->powers[pw_shield])
{
P_RemoveShield(player);
return true;
}
else
{
player->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500)));
if (player->health < 2)
player->health = 2;
}
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
P_PlayerFlagBurst(player, false);
}
else
{
player->health -= damage; // mirror mobj health here
if (damage < 10000)
{
target->player->powers[pw_flashing] = K_GetKartFlashing(target->player);
if (damage > 0) // don't spill emeralds/ammo/panels for shield damage
P_PlayerRingBurst(player, damage);
}
}
if (player->health < 0)
player->health = 0;
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
}
// Killing dead. Just for kicks.
@ -3465,7 +3276,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
/** Spills an injured player's rings.
*
* \param player The player who is losing rings.
* \param num_rings Number of rings lost. A maximum of 32 rings will be
* \param num_rings Number of rings lost. A maximum of 20 rings will be
* spawned.
* \sa P_PlayerFlagBurst
*/
@ -3476,32 +3287,38 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
angle_t fa;
fixed_t ns;
fixed_t z;
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
// Rings shouldn't be in Battle!
if (G_BattleGametype())
return;
// Better safe than sorry.
if (!player)
return;
// Never have health in kart I think
if (player->mo->health <= 1)
num_rings = 5;
// Has a shield? Don't lose your rings!
if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
return;
if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL))
num_rings = 32;
// 20 is the ring cap in kart
if (num_rings > 20)
num_rings = 20;
else if (num_rings <= 0)
return;
if (player->powers[pw_emeralds])
P_PlayerEmeraldBurst(player, false);
// Cap the maximum loss automatically to 2 in ring debt
if (player->kartstuff[k_rings] <= 0 && num_rings > 2)
num_rings = 2;
// Spill weapons first
if (player->ringweapons)
P_PlayerWeaponPanelBurst(player);
P_GivePlayerRings(player, -num_rings);
// Spill the ammo
P_PlayerWeaponAmmoBurst(player);
// determine first angle
fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90);
// There's no ring spilling in kart, so I'm hijacking this for the same thing as TD
for (i = 0; i < num_rings; i++)
{
INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime;
INT32 objType = mobjinfo[MT_RING].reactiontime;
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -3509,379 +3326,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
mo->fuse = 8*TICRATE;
mo->threshold = 10;
mo->fuse = 120*TICRATE;
P_SetTarget(&mo->target, player->mo);
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle, then slightly offset by amount of rings
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
if (player->pflags & PF_NIGHTSFALL)
// Angle / height offset changes every other ring
if (i != 0)
{
ns = FixedMul(((i*FRACUNIT)/16)+2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 8*FRACUNIT, false);
mo->fuse = 20*TICRATE; // Adjust fuse for NiGHTS
}
else
{
fixed_t momxy, momz; // base horizonal/vertical thrusts
if (i > 15)
{
momxy = 3*FRACUNIT;
momz = 4*FRACUNIT;
}
else
{
momxy = 28*FRACUNIT;
momz = 3*FRACUNIT;
}
ns = FixedMul(momxy, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
ns = momz;
P_SetObjectMomZ(mo, ns, false);
if (i & 1)
P_SetObjectMomZ(mo, ns, true);
{
momxy -= FRACUNIT;
momz += 2<<FRACBITS;
}
fa += ANGLE_180;
}
ns = FixedMul(momxy, mo->scale);
mo->momx = (mo->target->momx/2) + FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns);
mo->momy = (mo->target->momy/2) + FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns);
ns = FixedMul(momz, mo->scale);
P_SetObjectMomZ(mo, (mo->target->momz/2) + ns, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1;
}
player->losstime += 10*TICRATE;
if (P_IsObjectOnGround(player->mo))
player->pflags &= ~PF_NIGHTSFALL;
return;
}
void P_PlayerWeaponPanelBurst(player_t *player)
{
mobj_t *mo;
angle_t fa;
fixed_t ns;
INT32 i;
fixed_t z;
INT32 num_weapons = M_CountBits((UINT32)player->ringweapons, NUM_WEAPONS-1);
UINT16 ammoamt = 0;
for (i = 0; i < num_weapons; i++)
{
mobjtype_t weptype = 0;
powertype_t power = 0;
if (player->ringweapons & RW_BOUNCE) // Bounce
{
weptype = MT_BOUNCEPICKUP;
player->ringweapons &= ~RW_BOUNCE;
power = pw_bouncering;
}
else if (player->ringweapons & RW_RAIL) // Rail
{
weptype = MT_RAILPICKUP;
player->ringweapons &= ~RW_RAIL;
power = pw_railring;
}
else if (player->ringweapons & RW_AUTO) // Auto
{
weptype = MT_AUTOPICKUP;
player->ringweapons &= ~RW_AUTO;
power = pw_automaticring;
}
else if (player->ringweapons & RW_EXPLODE) // Explode
{
weptype = MT_EXPLODEPICKUP;
player->ringweapons &= ~RW_EXPLODE;
power = pw_explosionring;
}
else if (player->ringweapons & RW_SCATTER) // Scatter
{
weptype = MT_SCATTERPICKUP;
player->ringweapons &= ~RW_SCATTER;
power = pw_scatterring;
}
else if (player->ringweapons & RW_GRENADE) // Grenade
{
weptype = MT_GRENADEPICKUP;
player->ringweapons &= ~RW_GRENADE;
power = pw_grenadering;
}
if (!weptype) // ???
continue;
if (player->powers[power] >= mobjinfo[weptype].reactiontime)
ammoamt = (UINT16)mobjinfo[weptype].reactiontime;
else
ammoamt = player->powers[power];
player->powers[power] -= ammoamt;
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
mo->reactiontime = ammoamt;
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
// >16 ring type spillout
ns = FixedMul(3*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 4*FRACUNIT, false);
if (i & 1)
P_SetObjectMomZ(mo, 4*FRACUNIT, true);
}
}
void P_PlayerWeaponAmmoBurst(player_t *player)
{
mobj_t *mo;
angle_t fa;
fixed_t ns;
INT32 i = 0;
fixed_t z;
mobjtype_t weptype = 0;
powertype_t power = 0;
while (true)
{
if (player->powers[pw_bouncering])
{
weptype = MT_BOUNCERING;
power = pw_bouncering;
}
else if (player->powers[pw_railring])
{
weptype = MT_RAILRING;
power = pw_railring;
}
else if (player->powers[pw_infinityring])
{
weptype = MT_INFINITYRING;
power = pw_infinityring;
}
else if (player->powers[pw_automaticring])
{
weptype = MT_AUTOMATICRING;
power = pw_automaticring;
}
else if (player->powers[pw_explosionring])
{
weptype = MT_EXPLOSIONRING;
power = pw_explosionring;
}
else if (player->powers[pw_scatterring])
{
weptype = MT_SCATTERRING;
power = pw_scatterring;
}
else if (player->powers[pw_grenadering])
{
weptype = MT_GRENADERING;
power = pw_grenadering;
}
else
break; // All done!
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
mo->health = player->powers[power];
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
player->powers[power] = 0;
mo->fuse = 12*TICRATE;
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK;
// Spill them!
ns = FixedMul(2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa), ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (i & 1)
P_SetObjectMomZ(mo, 3*FRACUNIT, true);
i++;
}
}
//
// P_PlayerEmeraldBurst
//
// Spills ONLY emeralds.
//
void P_PlayerEmeraldBurst(player_t *player, boolean toss)
{
INT32 i;
angle_t fa;
fixed_t ns;
fixed_t z = 0, momx = 0, momy = 0;
// Better safe than sorry.
if (!player)
return;
// Spill power stones
if (player->powers[pw_emeralds])
{
INT32 num_stones = 0;
if (player->powers[pw_emeralds] & EMERALD1)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD2)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD3)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD4)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD5)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD6)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD7)
num_stones++;
for (i = 0; i < num_stones; i++)
{
INT32 stoneflag = 0;
statenum_t statenum = S_CEMG1;
mobj_t *mo;
if (player->powers[pw_emeralds] & EMERALD1)
{
stoneflag = EMERALD1;
statenum = S_CEMG1;
}
else if (player->powers[pw_emeralds] & EMERALD2)
{
stoneflag = EMERALD2;
statenum = S_CEMG2;
}
else if (player->powers[pw_emeralds] & EMERALD3)
{
stoneflag = EMERALD3;
statenum = S_CEMG3;
}
else if (player->powers[pw_emeralds] & EMERALD4)
{
stoneflag = EMERALD4;
statenum = S_CEMG4;
}
else if (player->powers[pw_emeralds] & EMERALD5)
{
stoneflag = EMERALD5;
statenum = S_CEMG5;
}
else if (player->powers[pw_emeralds] & EMERALD6)
{
stoneflag = EMERALD6;
statenum = S_CEMG6;
}
else if (player->powers[pw_emeralds] & EMERALD7)
{
stoneflag = EMERALD7;
statenum = S_CEMG7;
}
if (!stoneflag) // ???
continue;
player->powers[pw_emeralds] &= ~stoneflag;
if (toss)
{
fa = player->mo->angle>>ANGLETOFINESHIFT;
z = player->mo->z + player->mo->height;
if (player->mo->eflags & MFE_VERTICALFLIP)
z -= mobjinfo[MT_FLINGEMERALD].height + player->mo->height;
ns = FixedMul(8*FRACUNIT, player->mo->scale);
}
else
{
fa = ((255 / num_stones) * i) * FINEANGLES/256;
z = player->mo->z + (player->mo->height / 2);
if (player->mo->eflags & MFE_VERTICALFLIP)
z -= mobjinfo[MT_FLINGEMERALD].height;
ns = FixedMul(4*FRACUNIT, player->mo->scale);
}
momx = FixedMul(FINECOSINE(fa), ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
momy = FixedMul(FINESINE(fa),ns);
else
momy = 0;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, MT_FLINGEMERALD);
mo->health = 1;
mo->threshold = stoneflag;
mo->flags2 |= (MF2_DONTRESPAWN|MF2_SLIDEPUSH);
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
P_SetMobjState(mo, statenum);
mo->momx = momx;
mo->momy = momy;
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz = -mo->momz;
if (toss)
player->tossdelay = 2*TICRATE;
}
}
}
/** Makes an injured or dead player lose possession of the flag.

View file

@ -390,9 +390,6 @@ void P_RemoveShield(player_t *player);
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage);
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source);
void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c
void P_PlayerWeaponPanelBurst(player_t *player);
void P_PlayerWeaponAmmoBurst(player_t *player);
void P_PlayerEmeraldBurst(player_t *player, boolean toss);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
void P_PlayerFlagBurst(player_t *player, boolean toss);

View file

@ -1557,39 +1557,50 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
if (P_IsObjectOnGround(thing) && tmthing->momz < 0)
{
K_KartBouncing(tmthing, thing, true, false);
if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring])
{
K_StealBumper(tmthing->player, thing->player, false);
K_SpinPlayer(thing->player, tmthing, 0, tmthing, false);
}
}
else if (P_IsObjectOnGround(tmthing) && thing->momz < 0)
{
K_KartBouncing(thing, tmthing, true, false);
if (G_BattleGametype() && thing->player->kartstuff[k_pogospring])
{
K_StealBumper(thing->player, tmthing->player, false);
K_SpinPlayer(tmthing->player, thing, 0, thing, false);
}
}
else
K_KartBouncing(tmthing, thing, false, false);
// The bump has to happen last
mobj_t *mo1 = tmthing;
mobj_t *mo2 = thing;
boolean zbounce = false;
if (G_BattleGametype())
{
if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible
if (P_IsObjectOnGround(thing) && tmthing->momz < 0)
{
K_StealBumper(thing->player, tmthing->player, false);
K_SpinPlayer(tmthing->player, thing, 0, tmthing, false);
zbounce = true;
mo1 = thing;
mo2 = tmthing;
if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring])
{
K_StealBumper(tmthing->player, thing->player, false);
K_SpinPlayer(thing->player, tmthing, 0, tmthing, false);
}
}
else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing]))
else if (P_IsObjectOnGround(tmthing) && thing->momz < 0)
{
K_StealBumper(tmthing->player, thing->player, false);
K_SpinPlayer(thing->player, tmthing, 0, thing, false);
zbounce = true;
if (G_BattleGametype() && thing->player->kartstuff[k_pogospring])
{
K_StealBumper(thing->player, tmthing->player, false);
K_SpinPlayer(tmthing->player, thing, 0, thing, false);
}
}
if (G_BattleGametype())
{
if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible
{
K_StealBumper(thing->player, tmthing->player, false);
K_SpinPlayer(tmthing->player, thing, 0, tmthing, false);
}
else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing]))
{
K_StealBumper(tmthing->player, thing->player, false);
K_SpinPlayer(thing->player, tmthing, 0, thing, false);
}
}
K_KartBouncing(mo1, mo2, zbounce, false);
}
return true;

View file

@ -85,6 +85,37 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
actioncachehead.prev = newaction;
}
//
// P_SetupStateAnimation
//
FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
{
if (!(st->frame & FF_ANIMATE))
return;
if (st->var1 <= 0 || st->var2 == 0)
{
mobj->frame &= ~FF_ANIMATE;
return; // Crash/stupidity prevention
}
mobj->anim_duration = (UINT16)st->var2;
if (st->frame & FF_GLOBALANIM)
{
// Attempt to account for the pre-ticker for objects spawned on load
if (!leveltime) return;
mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer
mobj->frame += ((leveltime + 2) / st->var2) % (st->var1 + 1); // Frame synced to timer (duration taken into account)
}
else if (st->frame & FF_RANDOMANIM)
{
mobj->frame += P_RandomKey(st->var1 + 1); // Random starting frame
mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame
}
}
//
// P_CycleStateAnimation
//
@ -93,6 +124,7 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
// var2 determines delay between animation frames
if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0)
return;
mobj->anim_duration = (UINT16)mobj->state->var2;
// compare the current sprite frame to the one we started from
@ -212,7 +244,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation(mobj, st);
// Modified handling.
// Call action functions when the state is set
@ -280,7 +312,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation(mobj, st);
// Modified handling.
// Call action functions when the state is set
@ -334,7 +366,7 @@ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation(mobj, st);
return true;
}
@ -353,7 +385,7 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation((mobj_t*)mobj, st);
return true;
}
@ -1905,7 +1937,7 @@ void P_XYMovement(mobj_t *mo)
#endif
//{ SRB2kart stuff
if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG) //(mo->type == MT_JAWZ && !mo->tracer))
if (mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer))
return;
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2)
@ -2456,11 +2488,11 @@ static boolean P_ZMovement(mobj_t *mo)
mom.z = -mom.z;
else
// Flingrings bounce
if (mo->type == MT_FLINGRING
if (/*mo->type == MT_FLINGRING
|| mo->type == MT_FLINGCOIN
|| P_WeaponOrPanel(mo->type)
|| mo->type == MT_FLINGEMERALD
|| mo->type == MT_BIGTUMBLEWEED
||*/ mo->type == MT_BIGTUMBLEWEED
|| mo->type == MT_LITTLETUMBLEWEED
|| mo->type == MT_CANNONBALLDECOR
|| mo->type == MT_FALLINGROCK)
@ -3592,7 +3624,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
dummy.z = thiscam->z;
dummy.height = thiscam->height;
if (player->pflags & PF_TIMEOVER)
player->kartstuff[k_timeovercam] = (2*TICRATE)+1;
player->karthud[khud_timeovercam] = (2*TICRATE)+1;
if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead.
P_ResetCamera(player, thiscam);
else
@ -6670,7 +6702,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0)
#if 1 // Set to 0 to test without needing to host
|| ((mobj->target->player == &players[displayplayers[0]]) || P_IsLocalPlayer(mobj->target->player))
|| (P_IsDisplayPlayer(mobj->target->player))
#endif
)
mobj->flags2 |= MF2_DONTDRAW;
@ -7903,8 +7935,17 @@ void P_MobjThinker(mobj_t *mobj)
else
{
fixed_t finalspeed = mobj->movefactor;
const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy);
fixed_t thrustamount = 0;
fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction;
mobj_t *ghost = P_SpawnGhostMobj(mobj);
ghost->colorized = true; // already has color!
P_SpawnGhostMobj(mobj);
if (!grounded)
{
// No friction in the air
frictionsafety = FRACUNIT;
}
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
if (mobj->health <= 5)
@ -7914,7 +7955,19 @@ void P_MobjThinker(mobj_t *mobj)
finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4);
}
P_InstaThrust(mobj, mobj->angle, finalspeed);
if (currentspeed >= finalspeed)
{
// Thrust as if you were at top speed, slow down naturally
thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed;
}
else
{
const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed;
// Thrust to immediately get to top speed
thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety);
}
P_Thrust(mobj, mobj->angle, thrustamount);
if (grounded)
{
@ -7936,51 +7989,20 @@ void P_MobjThinker(mobj_t *mobj)
case MT_JAWZ:
{
sector_t *sec2;
fixed_t topspeed = mobj->movefactor;
fixed_t distbarrier = 512*mapobjectscale;
fixed_t distaway;
mobj_t *ghost = P_SpawnGhostMobj(mobj);
P_SpawnGhostMobj(mobj);
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
if (mobj->threshold > 0)
mobj->threshold--;
if (leveltime % TICRATE == 0)
S_StartSound(mobj, mobj->info->activesound);
if (gamespeed == 0)
distbarrier = FixedMul(distbarrier, FRACUNIT-FRACUNIT/4);
else if (gamespeed == 2)
distbarrier = FixedMul(distbarrier, FRACUNIT+FRACUNIT/4);
if (G_RaceGametype() && mobj->tracer)
{
distaway = P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y);
if (distaway < distbarrier)
{
if (mobj->tracer->player)
{
fixed_t speeddifference = abs(topspeed - min(mobj->tracer->player->speed, K_GetKartSpeed(mobj->tracer->player, false)));
topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier));
}
}
}
if (G_BattleGametype())
{
mobj->friction -= 1228;
if (mobj->friction > FRACUNIT)
mobj->friction = FRACUNIT;
if (mobj->friction < 0)
mobj->friction = 0;
}
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
P_InstaThrust(mobj, mobj->angle, topspeed);
if (mobj->tracer)
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y);
else
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
// Movement handling has ALL been moved to A_JawzChase
K_DriftDustHandling(mobj);
@ -8007,9 +8029,37 @@ void P_MobjThinker(mobj_t *mobj)
}
else
{
P_SpawnGhostMobj(mobj);
mobj_t *ghost = P_SpawnGhostMobj(mobj);
const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy);
fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction;
fixed_t thrustamount = 0;
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
if (!grounded)
{
// No friction in the air
frictionsafety = FRACUNIT;
}
if (currentspeed >= mobj->movefactor)
{
// Thrust as if you were at top speed, slow down naturally
thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor;
}
else
{
const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed;
// Thrust to immediately get to top speed
thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety);
}
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
P_InstaThrust(mobj, mobj->angle, mobj->movefactor);
P_Thrust(mobj, mobj->angle, thrustamount);
if (grounded)
{
@ -8032,14 +8082,25 @@ void P_MobjThinker(mobj_t *mobj)
case MT_BANANA:
case MT_EGGMANITEM:
mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj);
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
}
if (P_IsObjectOnGround(mobj) && mobj->health > 1)
{
S_StartSound(mobj, mobj->info->activesound);
mobj->momx = mobj->momy = 0;
mobj->health = 1;
}
if (mobj->threshold > 0)
mobj->threshold--;
break;
@ -8047,18 +8108,38 @@ void P_MobjThinker(mobj_t *mobj)
indirectitemcooldown = 20*TICRATE;
/* FALLTHRU */
case MT_BALLHOG:
P_SpawnGhostMobj(mobj)->fuse = 3;
if (mobj->threshold > 0)
mobj->threshold--;
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
ghost->fuse = 3;
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
if (mobj->threshold > 0)
mobj->threshold--;
}
break;
case MT_SINK:
if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj);
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player)
{
ghost->color = mobj->target->player->skincolor;
ghost->colorized = true;
}
}
if (P_IsObjectOnGround(mobj))
{
S_StartSound(mobj, mobj->info->deathsound);
P_SetMobjState(mobj, S_NULL);
}
if (mobj->threshold > 0)
mobj->threshold--;
break;
@ -8069,7 +8150,10 @@ void P_MobjThinker(mobj_t *mobj)
mobj->color = SKINCOLOR_KETCHUP;
if (mobj->momx || mobj->momy)
P_SpawnGhostMobj(mobj);
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
ghost->colorized = true; // already has color!
}
if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]))
{
@ -8142,9 +8226,10 @@ void P_MobjThinker(mobj_t *mobj)
if (p)
{
if (p->kartstuff[k_sneakertimer] > mobj->movecount)
if (p->kartstuff[k_sneakertimer] > mobj->movecount
|| p->kartstuff[k_levelbooster] > mobj->movecount)
P_SetMobjState(mobj, S_BOOSTFLAME);
mobj->movecount = p->kartstuff[k_sneakertimer];
mobj->movecount = max(p->kartstuff[k_sneakertimer], p->kartstuff[k_levelbooster]);
}
}
@ -8263,6 +8348,26 @@ void P_MobjThinker(mobj_t *mobj)
K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
break;
case MT_RINGSPARKS:
if (!mobj->target || P_MobjWasRemoved(mobj->target))
{
P_RemoveMobj(mobj);
return;
}
K_MatchGenericExtraFlags(mobj, mobj->target);
{
fixed_t z;
z = mobj->target->z;
if (( mobj->eflags & MFE_VERTICALFLIP ))
z -= mobj->height;
else
z += mobj->target->height;
P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT),
mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT),
z);
}
break;
case MT_THUNDERSHIELD:
{
fixed_t destx, desty;
@ -9351,7 +9456,9 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
|| mobj->type == MT_BIGTUMBLEWEED
|| mobj->type == MT_LITTLETUMBLEWEED
|| mobj->type == MT_CANNONBALLDECOR
|| mobj->type == MT_FALLINGROCK) {
|| mobj->type == MT_FALLINGROCK
|| mobj->type == MT_ORBINAUT
|| mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD) {
P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly
//if (mobj->standingslope) CONS_Printf("slope physics on mobj\n");
P_ButteredSlope(mobj);
@ -9528,6 +9635,21 @@ void P_SceneryThinker(mobj_t *mobj)
}
}
// Sonic Advance 2 flashing afterimages
if (mobj->type == MT_GHOST && mobj->fuse > 0
&& mobj->extravalue1 > 0 && mobj->extravalue2 >= 2)
{
if (mobj->extravalue2 == 2) // I don't know why the normal logic doesn't work for this.
mobj->flags2 ^= MF2_DONTDRAW;
else
{
if (mobj->fuse == mobj->extravalue2)
mobj->flags2 &= ~MF2_DONTDRAW;
else
mobj->flags2 |= MF2_DONTDRAW;
}
}
// momentum movement
if (mobj->momx || mobj->momy)
{
@ -9635,7 +9757,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation(mobj, st);
mobj->friction = ORIG_FRICTION;
@ -10086,6 +10208,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
P_SetupStateAnimation(mobj, st);
mobj->friction = ORIG_FRICTION;
@ -10178,7 +10301,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
P_SetupStateAnimation((mobj_t*)mobj, st);
// set subsector and/or block links
P_SetPrecipitationThingPosition(mobj);
@ -10608,6 +10731,8 @@ void P_PrecipitationEffects(void)
//
void P_RespawnSpecials(void)
{
UINT8 p, pcount = 0;
tic_t time = 30*TICRATE; // Respawn things in empty dedicated servers
fixed_t x, y, z;
subsector_t *ss;
mobj_t *mo = NULL;
@ -10654,21 +10779,28 @@ void P_RespawnSpecials(void)
numgotboxes = 0;
}
// only respawn items when cv_itemrespawn is on
if (!cv_itemrespawn.value)
return;
// wait time depends on player count
for (p = 0; p < MAXPLAYERS; p++)
{
if (playeringame[p] && !players[p].spectator)
pcount++;
}
// Don't respawn in special stages!
if (G_IsSpecialStage(gamemap))
if (pcount == 1) // No respawn when alone
return;
else if (pcount > 1)
time = (180 - (pcount * 10))*TICRATE;
// only respawn items when cv_itemrespawn is on
//if (!cv_itemrespawn.value) // TODO: remove this cvar
//return;
// nothing left to respawn?
if (iquehead == iquetail)
return;
// the first item in the queue is the first to respawn
// wait at least 30 seconds
if (leveltime - itemrespawntime[iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE)
if (leveltime - itemrespawntime[iquetail] < time)
return;
mthing = itemrespawnque[iquetail];
@ -11953,7 +12085,7 @@ ML_NOCLIMB : Direction not controllable
void P_SpawnHoopsAndRings(mapthing_t *mthing)
{
mobj_t *mobj = NULL;
INT32 /*r,*/ i;
INT32 r, i;
fixed_t x, y, z, finalx, finaly, finalz;
sector_t *sec;
TVector v, *res;
@ -12240,8 +12372,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
return;
}
else return; // srb2kart - no rings or ring-like objects in R1
/*
// Wing logo item.
else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
{
@ -12535,7 +12665,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
}
}
return;
}*/
}
else return;
}
//

View file

@ -35,14 +35,9 @@
#pragma interface
#endif
/// \brief Frame flags: only the frame number
#define FF_FRAMEMASK 0x1ff
/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION)
#define FF_PAPERSPRITE 0x800
/// \brief Frame flags: Simple stateless animation
#define FF_ANIMATE 0x4000
/// \brief Frame flags: frame always appears full bright
#define FF_FULLBRIGHT 0x8000
/// \brief Frame flags: only the frame number (frames from 0 to 63, but a bit of headroom for 2.2 compat)
#define FF_FRAMEMASK 0xff
/// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table
#define FF_TRANSMASK 0xf0000
/// \brief shift for FF_TRANSMASK
@ -58,6 +53,23 @@
#define FF_TRANS80 (tr_trans80<<FF_TRANSSHIFT)
#define FF_TRANS90 (tr_trans90<<FF_TRANSSHIFT)
/// \brief Frame flags: frame always appears full bright (mutually exclusive with below, currently takes priority)
#define FF_FULLBRIGHT 0x00100000
/// \brief Frame flags: frame appears with moderate brightness (mutually exclusive with above)
#define FF_SEMIBRIGHT 0x00200000
/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION)
#define FF_PAPERSPRITE 0x00400000
/// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity)
#define FF_VERTICALFLIP 0x00800000
/// \brief Frame flags - Animate: Simple stateless animation
#define FF_ANIMATE 0x01000000
/// \brief Frame flags - Animate: Sync animation to global timer (mutually exclusive with below, currently takes priority)
#define FF_GLOBALANIM 0x02000000
/// \brief Frame flags - Animate: Start at a random place in the animation (mutually exclusive with above)
#define FF_RANDOMANIM 0x04000000
/** \brief translucency tables
\todo add another asm routine which use the fg and bg indexes in the

View file

@ -625,8 +625,7 @@ void P_ResetDynamicSlopes(void) {
slopelist = NULL;
slopecount = 0;
// We'll handle copy slopes later, after all the tag lists have been made.
// Yes, this means copied slopes won't affect things' spawning heights. Too bad for you.
/// Generates line special-defined slopes.
for (i = 0; i < numlines; i++)
{
switch (lines[i].special)
@ -725,11 +724,21 @@ void P_ResetDynamicSlopes(void) {
break;
}
}
/// Copies slopes from tagged sectors via line specials.
/// \note Doesn't actually copy, but instead they share the same pointers.
for (i = 0; i < numlines; i++)
switch (lines[i].special)
{
case 720:
case 721:
case 722:
P_CopySectorSlope(&lines[i]);
default:
break;
}
}
// ============================================================================
//
// Various utilities related to slopes
@ -862,33 +871,31 @@ void P_ButteredSlope(mobj_t *mo)
return; // don't slide down slopes if you can't touch them or you're not affected by gravity
if (mo->player) {
if (abs(mo->standingslope->zdelta) < FRACUNIT/4 && !(mo->player->pflags & PF_SPINNING))
// Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles)
if (abs(mo->standingslope->zdelta) < FRACUNIT/21 && !(mo->player->pflags & PF_SPINNING))
return; // Don't slide on non-steep slopes unless spinning
// This only means you can be stopped on slopes that aren't steeper than 45 degrees
if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy))
return; // Allow the player to stand still on slopes below a certain steepness
}
thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 15 / 16 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 4 / 5 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
if (mo->player && (mo->player->pflags & PF_SPINNING)) {
fixed_t mult = 0;
if (mo->player) {
fixed_t mult = FRACUNIT;
if (mo->momx || mo->momy) {
angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection;
if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0)
angle ^= ANGLE_180;
mult = FINECOSINE(angle >> ANGLETOFINESHIFT);
mult = FRACUNIT + (FRACUNIT + FINECOSINE(angle>>ANGLETOFINESHIFT))*3/2;
}
thrust = FixedMul(thrust, FRACUNIT*2/3 + mult/8);
thrust = FixedMul(thrust, mult);
}
if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed
thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/16);
// This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down
// Let's get the gravity strength for the object...
thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo)));

View file

@ -4247,19 +4247,19 @@ DoneSection2:
if (nump > 1)
{
if (K_IsPlayerLosing(player))
player->kartstuff[k_laphand] = 3;
player->karthud[khud_laphand] = 3;
else
{
if (nump > 2 && player->kartstuff[k_position] == 1) // 1st place in 1v1 uses thumbs up
player->kartstuff[k_laphand] = 1;
player->karthud[khud_laphand] = 1;
else
player->kartstuff[k_laphand] = 2;
player->karthud[khud_laphand] = 2;
}
}
else
player->kartstuff[k_laphand] = 0; // No hands in FREE PLAY
player->karthud[khud_laphand] = 0; // No hands in FREE PLAY
player->kartstuff[k_lapanimation] = 80;
player->karthud[khud_lapanimation] = 80;
if (player->pflags & PF_NIGHTSMODE)
player->drillmeter += 48*20;
@ -4295,7 +4295,7 @@ DoneSection2:
player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->kartstuff[k_starpostflip] = 0;
}
if (P_IsLocalPlayer(player))
if (P_IsDisplayPlayer(player))
{
if (player->laps == (UINT8)(cv_numlaps.value - 1))
S_StartSound(NULL, sfx_s3k68);
@ -4321,7 +4321,7 @@ DoneSection2:
if (player->laps >= (unsigned)cv_numlaps.value)
{
if (P_IsLocalPlayer(player))
if (P_IsDisplayPlayer(player))
S_StartSound(NULL, sfx_s3k6a);
else if (player->kartstuff[k_position] == 1)
S_StartSound(NULL, sfx_s253);
@ -6689,14 +6689,6 @@ void P_SpawnSpecials(INT32 fromnetsave)
sectors[s].midmap = lines[i].frontsector->midmap;
break;
#ifdef ESLOPE // Slope copy specials. Handled here for sanity.
case 720:
case 721:
case 722:
P_CopySectorSlope(&lines[i]);
break;
#endif
default:
break;
}
@ -7352,9 +7344,7 @@ void T_Friction(friction_t *f)
// apparently, all I had to do was comment out part of the next line and
// friction works for all mobj's
// (or at least MF_PUSHABLEs, which is all I care about anyway)
if ((!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz) && (thing->player
&& (thing->player->kartstuff[k_invincibilitytimer] == 0 && thing->player->kartstuff[k_hyudorotimer] == 0
&& thing->player->kartstuff[k_sneakertimer] == 0 && thing->player->kartstuff[k_growshrinktimer] <= 0)))
if (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz)
{
if (f->roverfriction)
{

View file

@ -946,50 +946,19 @@ void P_ResetPlayer(player_t *player)
//
void P_GivePlayerRings(player_t *player, INT32 num_rings)
{
if (player->bot)
player = &players[consoleplayer];
if (!player->mo)
return;
player->mo->health += num_rings;
player->health += num_rings;
if (G_BattleGametype()) // No rings in Battle Mode
return;
if (!G_IsSpecialStage(gamemap) || !useNightsSS)
player->totalring += num_rings;
player->kartstuff[k_rings] += num_rings;
//player->totalring += num_rings; // Used for GP lives later
//{ SRB2kart - rings don't really do anything, but we don't want the player spilling them later.
/*
// Can only get up to 9999 rings, sorry!
if (player->mo->health > 10000)
{
player->mo->health = 10000;
player->health = 10000;
}
else if (player->mo->health < 1)*/
{
player->mo->health = 1;
player->health = 1;
}
//}
// Now extra life bonuses are handled here instead of in P_MovePlayer, since why not?
if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives())
{
INT32 gainlives = 0;
while (player->xtralife < maxXtraLife && player->health > 100 * (player->xtralife+1))
{
++gainlives;
++player->xtralife;
}
if (gainlives)
{
P_GivePlayerLives(player, gainlives);
P_PlayLivesJingle(player);
}
}
if (player->kartstuff[k_rings] > 20)
player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry!
else if (player->kartstuff[k_rings] < -20)
player->kartstuff[k_rings] = -20; // Chaotix ring debt!
}
//
@ -1114,11 +1083,12 @@ void P_PlayLivesJingle(player_t *player)
void P_PlayRinglossSound(mobj_t *source)
{
sfxenum_t key = P_RandomKey(2);
if (cv_kartvoices.value)
S_StartSound(source, (mariomode) ? sfx_mario8 : sfx_khurt1 + key);
if (source->player && source->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
S_StartSound(source, sfx_s1a3); // Shield hit (no ring loss)
else if (source->player && source->player->kartstuff[k_rings] <= 0)
S_StartSound(source, sfx_s1a6); // Ring debt (lessened ring loss)
else
S_StartSound(source, sfx_slip);
S_StartSound(source, sfx_s1c6); // Normal ring loss sound
}
void P_PlayDeathSound(mobj_t *source)
@ -1704,7 +1674,7 @@ void P_DoPlayerExit(player_t *player)
if (cv_kartvoices.value)
{
if (P_IsLocalPlayer(player))
if (P_IsDisplayPlayer(player))
{
sfxenum_t sfx_id;
if (K_IsPlayerLosing(player))
@ -1751,7 +1721,7 @@ void P_DoPlayerExit(player_t *player)
*/
player->powers[pw_underwater] = 0;
player->powers[pw_spacetime] = 0;
player->kartstuff[k_cardanimation] = 0; // srb2kart: reset battle animation
player->karthud[khud_cardanimation] = 0; // srb2kart: reset battle animation
if (player == &players[consoleplayer])
demo.savebutton = leveltime;
@ -4039,7 +4009,7 @@ static void P_3dMovement(player_t *player)
if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam?
{
cmd->forwardmove = cmd->sidemove = 0;
if (player->kartstuff[k_sneakertimer])
if (EITHERSNEAKER(player))
cmd->forwardmove = 50;
}
@ -4129,13 +4099,6 @@ static void P_3dMovement(player_t *player)
//movepushforward = cmd->forwardmove * (thrustfactor * acceleration);
movepushforward = K_3dKartMovement(player, onground, cmd->forwardmove);
// allow very small movement while in air for gameplay
if (!onground)
movepushforward >>= 2; // proper air movement
// don't need to account for scale here with kart accel code
//movepushforward = FixedMul(movepushforward, player->mo->scale);
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
movepushforward = FixedMul(movepushforward, player->mo->movefactor);
@ -4199,6 +4162,18 @@ static void P_3dMovement(player_t *player)
player->mo->momx += totalthrust.x;
player->mo->momy += totalthrust.y;
if (!onground)
{
fixed_t airspeedcap = (50*mapobjectscale);
fixed_t speed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy);
if (speed > airspeedcap)
{
fixed_t newspeed = speed - ((speed - airspeedcap) / 32);
player->mo->momx = FixedMul(FixedDiv(player->mo->momx, speed), newspeed);
player->mo->momy = FixedMul(FixedDiv(player->mo->momy, speed), newspeed);
}
}
#endif
// Time to ask three questions:
@ -4211,27 +4186,33 @@ static void P_3dMovement(player_t *player)
// If "no" to 2, normalize to topspeed, so we can't suddenly run faster than it of our own accord.
// If "no" to 1, we're not reaching any limits yet, so ignore this entirely!
// -Shadow Hog
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed)
// Only do this forced cap of speed when in midair, the kart acceleration code takes into account friction, and
// doesn't let you accelerate past top speed, so this is unnecessary on the ground, but in the air is needed to
// allow for being able to change direction on spring jumps without being accelerated into the void - Sryder
if (!P_IsObjectOnGround(player->mo))
{
fixed_t tempmomx, tempmomy;
if (oldMagnitude > K_GetKartSpeed(player, true) && onground) // SRB2Kart: onground check for air speed cap
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed)
{
if (newMagnitude > oldMagnitude)
fixed_t tempmomx, tempmomy;
if (oldMagnitude > K_GetKartSpeed(player, true))
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude);
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude);
if (newMagnitude > oldMagnitude)
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude);
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude);
player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy;
}
// else do nothing
}
else
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy;
}
// else do nothing
}
else
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy;
}
}
}
@ -5778,11 +5759,10 @@ static void P_MovePlayer(player_t *player)
boolean add_delta = true;
// Kart: store the current turn range for later use
if (((player->mo && player->speed > 0) // Moving
if ((player->mo && player->speed > 0) // Moving
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning
|| (player->spectator || objectplacing)) // Not a physical player
) // ~~Spinning and boosting cancels out turning~~ Not anymore given spinout is more slippery and more prone to get you killed because of boosters.
{
player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1;
player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1;
@ -6172,7 +6152,7 @@ static void P_MovePlayer(player_t *player)
////////////////////////////
// SRB2kart - Drifting smoke and fire
if (player->kartstuff[k_sneakertimer] > 0 && onground && (leveltime & 1))
if (EITHERSNEAKER(player) && onground && (leveltime & 1))
K_SpawnBoostTrail(player);
if (player->kartstuff[k_invincibilitytimer] > 0)
@ -7064,7 +7044,7 @@ static void P_DeathThink(player_t *player)
if (player->pflags & PF_TIMEOVER)
{
player->kartstuff[k_timeovercam]++;
player->karthud[khud_timeovercam]++;
if (player->mo)
{
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
@ -7072,7 +7052,7 @@ static void P_DeathThink(player_t *player)
}
}
else
player->kartstuff[k_timeovercam] = 0;
player->karthud[khud_timeovercam] = 0;
K_KartPlayerHUDUpdate(player);
@ -7280,7 +7260,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
#endif
if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround
timeover = (player->kartstuff[k_timeovercam] > 2*TICRATE ? 2 : 1);
timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1);
else
timeover = 0;
@ -7423,7 +7403,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (timeover)
{
const INT32 timeovercam = max(0, min(180, (player->kartstuff[k_timeovercam] - 2*TICRATE)*15));
const INT32 timeovercam = max(0, min(180, (player->karthud[khud_timeovercam] - 2*TICRATE)*15));
camrotate += timeovercam;
}
else if (leveltime < introtime) // Whoooshy camera!
@ -7497,10 +7477,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
dist += 4*(player->speed - K_GetKartSpeed(player, false));
dist += abs(thiscam->momz)/4;
if (player->kartstuff[k_boostcam])
if (player->karthud[khud_boostcam])
{
dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]);
height -= FixedMul(height, player->kartstuff[k_boostcam]);
dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
height -= FixedMul(height, player->karthud[khud_boostcam]);
}
x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist);
@ -7913,7 +7893,7 @@ boolean P_SpectatorJoinGame(player_t *player)
static void P_CalcPostImg(player_t *player)
{
sector_t *sector = player->mo->subsector->sector;
postimg_t *type = postimg_none;
postimg_t *type = NULL;
INT32 *param;
fixed_t pviewheight;
UINT8 i;
@ -8437,8 +8417,7 @@ void P_PlayerThink(player_t *player)
#if 1
// "Blur" a bit when you have speed shoes and are going fast enough
if ((player->powers[pw_super] || player->powers[pw_sneakers]
|| player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart
if ((player->powers[pw_super] || player->powers[pw_sneakers])
&& (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{
UINT8 i;

View file

@ -828,7 +828,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap;
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{
// translate certain pixels to white
colfunc = transcolfunc;
@ -899,18 +899,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
frac = vis->startfrac;
windowtop = windowbottom = sprbotscreen = INT32_MAX;
if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
this_scale = FixedMul(this_scale, ((skin_t *)vis->mobj->skin)->highresscale);
if (this_scale <= 0)
this_scale = 1;
if (this_scale != FRACUNIT)
{
if (!vis->isScaled)
if (!(vis->cut & SC_ISSCALED))
{
vis->scale = FixedMul(vis->scale, this_scale);
vis->scalestep = FixedMul(vis->scalestep, this_scale);
vis->xiscale = FixedDiv(vis->xiscale,this_scale);
vis->isScaled = true;
vis->cut |= SC_ISSCALED;
}
dc_texturemid = FixedDiv(dc_texturemid,this_scale);
}
@ -963,7 +963,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->vflip)
if (vis->cut & SC_VFLIP)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
@ -1043,7 +1043,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
//
// R_SplitSprite
// runs through a sector's lightlist and
static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
static void R_SplitSprite(vissprite_t *sprite)
{
INT32 i, lightnum, lindex;
INT16 cutfrac;
@ -1079,6 +1079,8 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
// adjust the heights.
newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t));
newsprite->cut |= (sprite->cut & SC_FLAGMASK);
sprite->cut |= SC_BOTTOM;
sprite->gz = testheight;
@ -1118,13 +1120,17 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
;
else
*/
if (!((thing->frame & (FF_FULLBRIGHT|FF_TRANSMASK) || thing->flags2 & MF2_SHADOW)
if (!((newsprite->cut & SC_FULLBRIGHT)
&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
{
lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
if (lindex >= MAXLIGHTSCALE)
lindex = MAXLIGHTSCALE-1;
if (newsprite->cut & SC_SEMIBRIGHT)
lindex = (MAXLIGHTSCALE/2) + (lindex >> 1);
newsprite->colormap = spritelights[lindex];
}
}
@ -1152,6 +1158,7 @@ static void R_ProjectSprite(mobj_t *thing)
size_t rot;
UINT8 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
INT32 lindex;
@ -1357,7 +1364,7 @@ static void R_ProjectSprite(mobj_t *thing)
}
//SoM: 3/17/2000: Disregard sprites that are out of view..
if (thing->eflags & MFE_VERTICALFLIP)
if (vflip)
{
// When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned.
// sprite height - sprite topoffset is the proper inverse of the vertical offset, of course.
@ -1499,7 +1506,12 @@ static void R_ProjectSprite(mobj_t *thing)
else if (thing->frame & FF_TRANSMASK)
vis->transmap = transtables + (thing->frame & FF_TRANSMASK) - 0x10000;
if (((thing->frame & FF_FULLBRIGHT) || (thing->flags2 & MF2_SHADOW))
if (thing->frame & FF_FULLBRIGHT || thing->flags2 & MF2_SHADOW)
vis->cut |= SC_FULLBRIGHT;
else if (thing->frame & FF_SEMIBRIGHT)
vis->cut |= SC_SEMIBRIGHT;
if (vis->cut & SC_FULLBRIGHT
&& (!vis->extra_colormap || !(vis->extra_colormap->fog & 1)))
{
// full bright: goggles
@ -1513,20 +1525,17 @@ static void R_ProjectSprite(mobj_t *thing)
if (lindex >= MAXLIGHTSCALE)
lindex = MAXLIGHTSCALE-1;
if (vis->cut & SC_SEMIBRIGHT)
lindex = (MAXLIGHTSCALE/2) + (lindex >> 1);
vis->colormap = spritelights[lindex];
}
vis->precip = false;
if (thing->eflags & MFE_VERTICALFLIP)
vis->vflip = true;
else
vis->vflip = false;
vis->isScaled = false;
if (vflip)
vis->cut |= SC_VFLIP;
if (thing->subsector->sector->numlights)
R_SplitSprite(vis, thing);
R_SplitSprite(vis);
// Debug
++objectsdrawn;
@ -1698,15 +1707,12 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->transmap = NULL;
vis->mobjflags = 0;
vis->cut = SC_NONE;
vis->cut = SC_PRECIP;
vis->extra_colormap = thing->subsector->sector->extra_colormap;
vis->heightsec = thing->subsector->sector->heightsec;
// Fullbright
vis->colormap = colormaps;
vis->precip = true;
vis->vflip = false;
vis->isScaled = false;
}
// R_AddSprites
@ -2492,7 +2498,7 @@ void R_DrawMasked(void)
next = r2->prev;
// Tails 08-18-2002
if (r2->sprite->precip == true)
if (r2->sprite->cut & SC_PRECIP)
R_DrawPrecipitationSprite(r2->sprite);
else
R_DrawSprite(r2->sprite);

View file

@ -104,9 +104,20 @@ extern CV_PossibleValue_t Forceskin_cons_t[];
// -----------
typedef enum
{
// actual cuts
SC_NONE = 0,
SC_TOP = 1,
SC_BOTTOM = 2
SC_BOTTOM = 1<<1,
// other flags
SC_PRECIP = 1<<2,
//SC_LINKDRAW = 1<<3, -- 2.2 compat
SC_FULLBRIGHT = 1<<4,
SC_SEMIBRIGHT = 1<<5,
SC_VFLIP = 1<<6,
SC_ISSCALED = 1>>7,
// masks
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e;
// A vissprite_t is a thing that will be drawn during a refresh,
@ -155,9 +166,6 @@ typedef struct vissprite_s
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
boolean precip;
boolean vflip; // Flip vertically
boolean isScaled;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} vissprite_t;