Merge branch 'rings' into 'master'

Rings

See merge request KartKrew/Kart!128
This commit is contained in:
Sal 2019-05-30 01:58:34 -04:00
commit 2ce77fdce9
23 changed files with 2641 additions and 1815 deletions

View file

@ -328,6 +328,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};*/ consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/
// SRB2kart // 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_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_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}; consvar_t cv_invincibility = {"invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -365,7 +366,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}; 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}}; 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}; 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 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}}; 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}; consvar_t cv_kartvoices = {"kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};

View file

@ -101,7 +101,7 @@ extern consvar_t cv_1up, cv_eggmanbox;
extern consvar_t cv_recycler;*/ extern consvar_t cv_recycler;*/
// SRB2kart items // 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_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine;
extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink; extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink; extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink;

View file

@ -216,6 +216,7 @@ typedef enum
KITEM_THUNDERSHIELD, KITEM_THUNDERSHIELD,
KITEM_HYUDORO, KITEM_HYUDORO,
KITEM_POGOSPRING, KITEM_POGOSPRING,
KITEM_SUPERRING,
KITEM_KITCHENSINK, KITEM_KITCHENSINK,
NUMKARTITEMS, NUMKARTITEMS,
@ -234,6 +235,7 @@ typedef enum
//{ SRB2kart - kartstuff //{ SRB2kart - kartstuff
typedef enum 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 // Basic gameplay things
k_position, // Used for Kart positions, mostly for deterministic stuff k_position, // Used for Kart positions, mostly for deterministic stuff
k_oldposition, // Used for taunting when you pass someone k_oldposition, // Used for taunting when you pass someone
@ -247,16 +249,10 @@ typedef enum
k_dropdash, // Charge up for respawn Drop Dash k_dropdash, // Charge up for respawn Drop Dash
k_throwdir, // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir") 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_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_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_drift, // Drifting Left or Right, plus a bigger counter = sharper turn
k_driftend, // Drift has ended, used to adjust character angle after drift 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_driftboost, // Boost you get from drifting
k_boostcharge, // Charge-up for boosting at the start of the race 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_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_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_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_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_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_waterskip, // Water skipping counter
k_dashpadcooldown, // Separate the vanilla SA-style dash pads from using pw_flashing 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_boostpower, // Base boost value, for offroad
k_speedboost, // Boost value smoothing for max speed k_speedboost, // Boost value smoothing for max speed
k_accelboost, // Boost value smoothing for acceleration 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_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_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 k_brakedrift, // Helper for brake-drift spark spawning
@ -294,7 +298,9 @@ typedef enum
k_hyudorotimer, // Duration of the Hyudoro offroad effect itself k_hyudorotimer, // Duration of the Hyudoro offroad effect itself
k_stealingtimer, // You are stealing an item, this is your timer k_stealingtimer, // You are stealing an item, this is your timer
k_stolentimer, // You are being stolen from, 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_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_growshrinktimer, // > 0 = Big, < 0 = small
k_squishedtimer, // Squished frame timer k_squishedtimer, // Squished frame timer
k_rocketsneakertimer, // Rocket Sneaker duration 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_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_comebackmode, // 0 = bomb, 1 = item
k_wanted, // Timer for determining WANTED status, lowers when hitting people, prevents the game turning into Camp Lazlo 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 // 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_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_jawztargetdelay, // Delay for Jawz target switching, to make it less twitchy
k_spectatewait, // How long have you been waiting as a spectator k_spectatewait, // How long have you been waiting as a spectator
@ -327,6 +330,44 @@ typedef enum
NUMKARTSTUFF NUMKARTSTUFF
} kartstufftype_t; } 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 #define WEP_AUTO 1
@ -387,6 +428,7 @@ typedef struct player_s
// SRB2kart stuff // SRB2kart stuff
INT32 kartstuff[NUMKARTSTUFF]; INT32 kartstuff[NUMKARTSTUFF];
INT32 karthud[NUMKARTHUD];
angle_t frameangle; // for the player add the ability to have the sprite only face other angles 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 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 INT16 rturn_max[MAXPREDICTTICS]; // Ditto but for full-right

View file

@ -4796,6 +4796,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Ring // Ring
"S_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 // Blue Sphere for special stages
"S_BLUEBALL", "S_BLUEBALL",
@ -7164,6 +7176,29 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_OPAQUESMOKE4", "S_OPAQUESMOKE4",
"S_OPAQUESMOKE5", "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 #ifdef SEENAMES
"S_NAMECHECK", "S_NAMECHECK",
#endif #endif
@ -7950,6 +7985,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_LIONMAN", "MT_LIONMAN",
"MT_KARMAFIREWORK", "MT_KARMAFIREWORK",
"MT_RINGSPARKS",
"MT_DRAFTDUST",
#ifdef SEENAMES #ifdef SEENAMES
"MT_NAMECHECK", "MT_NAMECHECK",
@ -8364,13 +8401,7 @@ static const char *const KARTSTUFF_LIST[] = {
"DROPDASH", "DROPDASH",
"THROWDIR", "THROWDIR",
"LAPANIMATION",
"LAPHAND",
"CARDANIMATION",
"VOICES",
"TAUNTVOICES",
"INSTASHIELD", "INSTASHIELD",
"ENGINESND",
"FLOORBOOST", "FLOORBOOST",
"SPINOUTTYPE", "SPINOUTTYPE",
@ -8381,19 +8412,27 @@ static const char *const KARTSTUFF_LIST[] = {
"DRIFTBOOST", "DRIFTBOOST",
"BOOSTCHARGE", "BOOSTCHARGE",
"STARTBOOST", "STARTBOOST",
"RINGS",
"PICKUPRINGS",
"USERINGS",
"RINGDELAY",
"RINGBOOST",
"RINGLOCK",
"SPARKLEANIM",
"JMP", "JMP",
"OFFROAD", "OFFROAD",
"POGOSPRING", "POGOSPRING",
"BRAKESTOP", "BRAKESTOP",
"WATERSKIP", "WATERSKIP",
"DASHPADCOOLDOWN", "DASHPADCOOLDOWN",
"NUMBOOSTS",
"BOOSTPOWER", "BOOSTPOWER",
"SPEEDBOOST", "SPEEDBOOST",
"ACCELBOOST", "ACCELBOOST",
"DRAFTPOWER",
"DRAFTLEEWAY",
"LASTDRAFT",
"BOOSTANGLE", "BOOSTANGLE",
"BOOSTCAM",
"DESTBOOSTCAM",
"TIMEOVERCAM",
"AIZDRIFTSTRAT", "AIZDRIFTSTRAT",
"BRAKEDRIFT", "BRAKEDRIFT",
@ -8408,7 +8447,9 @@ static const char *const KARTSTUFF_LIST[] = {
"HYUDOROTIMER", "HYUDOROTIMER",
"STEALINGTIMER", "STEALINGTIMER",
"STOLENTIMER", "STOLENTIMER",
"SUPERRING",
"SNEAKERTIMER", "SNEAKERTIMER",
"LEVELBOOSTER",
"GROWSHRINKTIMER", "GROWSHRINKTIMER",
"SQUISHEDTIMER", "SQUISHEDTIMER",
"ROCKETSNEAKERTIMER", "ROCKETSNEAKERTIMER",
@ -8428,10 +8469,7 @@ static const char *const KARTSTUFF_LIST[] = {
"COMEBACKPOINTS", "COMEBACKPOINTS",
"COMEBACKMODE", "COMEBACKMODE",
"WANTED", "WANTED",
"YOUGOTEM",
"ITEMBLINK",
"ITEMBLINKMODE",
"GETSPARKS", "GETSPARKS",
"JAWZTARGETDELAY", "JAWZTARGETDELAY",
"SPECTATEWAIT", "SPECTATEWAIT",
@ -8529,9 +8567,13 @@ struct {
// Frame settings // Frame settings
{"FF_FRAMEMASK",FF_FRAMEMASK}, {"FF_FRAMEMASK",FF_FRAMEMASK},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_ANIMATE",FF_ANIMATE}, {"FF_ANIMATE",FF_ANIMATE},
{"FF_RANDOMANIM",FF_RANDOMANIM},
{"FF_GLOBALANIM",FF_GLOBALANIM},
{"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_SEMIBRIGHT",FF_SEMIBRIGHT},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_VERTICALFLIP",FF_VERTICALFLIP},
{"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSMASK",FF_TRANSMASK},
{"FF_TRANSSHIFT",FF_TRANSSHIFT}, {"FF_TRANSSHIFT",FF_TRANSSHIFT},
// new preshifted translucency (used in source) // new preshifted translucency (used in source)
@ -8956,6 +8998,7 @@ struct {
{"KITEM_THUNDERSHIELD",KITEM_THUNDERSHIELD}, {"KITEM_THUNDERSHIELD",KITEM_THUNDERSHIELD},
{"KITEM_HYUDORO",KITEM_HYUDORO}, {"KITEM_HYUDORO",KITEM_HYUDORO},
{"KITEM_POGOSPRING",KITEM_POGOSPRING}, {"KITEM_POGOSPRING",KITEM_POGOSPRING},
{"KITEM_SUPERRING",KITEM_SUPERRING},
{"KITEM_KITCHENSINK",KITEM_KITCHENSINK}, {"KITEM_KITCHENSINK",KITEM_KITCHENSINK},
{"NUMKARTITEMS",NUMKARTITEMS}, {"NUMKARTITEMS",NUMKARTITEMS},
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch) {"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
@ -9349,7 +9392,7 @@ fixed_t get_number(const char *word)
void DEH_Check(void) 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 dehstates = sizeof(STATE_LIST)/sizeof(const char*);
const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*); const size_t dehmobjs = sizeof(MOBJTYPE_LIST)/sizeof(const char*);
const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*); const size_t dehpowers = sizeof(POWERS_LIST)/sizeof(const char*);
@ -9370,7 +9413,7 @@ void DEH_Check(void)
if (dehcolors != MAXTRANSLATIONS) 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)); 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 #ifdef HAVE_BLUA

View file

@ -163,7 +163,7 @@ extern FILE *logstream;
// Does this version require an added patch file? // Does this version require an added patch file?
// Comment or uncomment this as necessary. // Comment or uncomment this as necessary.
//#define USE_PATCH_FILE #define USE_PATCH_FILE
// Use .kart extension addons // Use .kart extension addons
#define USE_KART #define USE_KART

View file

@ -1406,7 +1406,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. // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward.
axis = JoyAxis(AXISMOVE, ssplayer); 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; cmd->buttons |= BT_ACCELERATE;
forward = forwardmove[1]; // 50 forward = forwardmove[1]; // 50
@ -1555,10 +1555,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
cmd->angleturn *= realtics; cmd->angleturn *= realtics;
// SRB2kart - no additional angle if not moving // 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 || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning || (player->kartstuff[k_respawn]) // Respawning
|| (player->spectator || objectplacing))) // Not a physical player || (player->spectator || objectplacing)) // Not a physical player
lang += (cmd->angleturn<<16); lang += (cmd->angleturn<<16);
cmd->angleturn = (INT16)(lang >> 16); cmd->angleturn = (INT16)(lang >> 16);
@ -2580,6 +2580,7 @@ void G_PlayerReborn(INT32 player)
INT32 bumper; INT32 bumper;
INT32 comebackpoints; INT32 comebackpoints;
INT32 wanted; INT32 wanted;
INT32 rings;
INT32 respawnflip; INT32 respawnflip;
boolean songcredit = false; boolean songcredit = false;
@ -2631,6 +2632,7 @@ void G_PlayerReborn(INT32 player)
itemamount = 0; itemamount = 0;
growshrinktimer = 0; growshrinktimer = 0;
bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0); bumper = (G_BattleGametype() ? cv_kartbumpers.value : 0);
rings = (G_BattleGametype() ? 0 : 5);
comebackpoints = 0; comebackpoints = 0;
wanted = 0; wanted = 0;
starpostwp = 0; starpostwp = 0;
@ -2660,6 +2662,7 @@ void G_PlayerReborn(INT32 player)
growshrinktimer = 0; growshrinktimer = 0;
bumper = players[player].kartstuff[k_bumper]; bumper = players[player].kartstuff[k_bumper];
rings = players[player].kartstuff[k_rings];
comebackpoints = players[player].kartstuff[k_comebackpoints]; comebackpoints = players[player].kartstuff[k_comebackpoints];
wanted = players[player].kartstuff[k_wanted]; wanted = players[player].kartstuff[k_wanted];
} }
@ -2704,17 +2707,19 @@ void G_PlayerReborn(INT32 player)
p->pity = pity; p->pity = pity;
// SRB2kart // 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_itemroulette] = itemroulette;
p->kartstuff[k_roulettetype] = roulettetype; p->kartstuff[k_roulettetype] = roulettetype;
p->kartstuff[k_itemtype] = itemtype; p->kartstuff[k_itemtype] = itemtype;
p->kartstuff[k_itemamount] = itemamount; p->kartstuff[k_itemamount] = itemamount;
p->kartstuff[k_growshrinktimer] = growshrinktimer; p->kartstuff[k_growshrinktimer] = growshrinktimer;
p->kartstuff[k_bumper] = bumper; p->kartstuff[k_bumper] = bumper;
p->kartstuff[k_rings] = rings;
p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebackpoints] = comebackpoints;
p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_comebacktimer] = comebacktime;
p->kartstuff[k_wanted] = wanted; p->kartstuff[k_wanted] = wanted;
p->kartstuff[k_eggmanblame] = -1; p->kartstuff[k_eggmanblame] = -1;
p->kartstuff[k_lastdraft] = -1;
p->kartstuff[k_starpostflip] = respawnflip; p->kartstuff[k_starpostflip] = respawnflip;
// Don't do anything immediately // Don't do anything immediately
@ -5103,7 +5108,8 @@ void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
|| (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning || (players[displayplayers[0]].kartstuff[k_respawn]) // Respawning
|| (players[displayplayers[0]].spectator || objectplacing)) // Not a physical player || (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); localangle[0] += (cmd->angleturn<<16);
if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
@ -5351,7 +5357,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
} }
// Store the sprite frame. // Store the sprite frame.
frame = ghost->frame & 0xFF; frame = ghost->frame & FF_FRAMEMASK;
if (frame != oldghost[playernum].frame) if (frame != oldghost[playernum].frame)
{ {
oldghost[playernum].frame = frame; oldghost[playernum].frame = frame;

View file

@ -4220,7 +4220,11 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false); INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *sector->lightlist[light].lightlevel; lightlevel = *sector->lightlist[light].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
if (sector->lightlist[light].extra_colormap) if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap; colormap = sector->lightlist[light].extra_colormap;
@ -4441,16 +4445,20 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
alpha = Surf.FlatColor.s.alpha; 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); temp = FLOAT_TO_FIXED(realtop);
if (spr->mobj->frame & FF_FULLBRIGHT)
lightlevel = 255;
#ifdef ESLOPE #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++) 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) fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y)
@ -4458,7 +4466,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (h <= temp) if (h <= temp)
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i-1].lightlevel; lightlevel = *list[i-1].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i-1].extra_colormap; colormap = list[i-1].extra_colormap;
break; break;
} }
@ -4466,7 +4478,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
#else #else
i = R_GetPlaneLight(sector, temp, false); i = R_GetPlaneLight(sector, temp, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i].lightlevel; lightlevel = *list[i].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i].extra_colormap; colormap = list[i].extra_colormap;
#endif #endif
@ -4482,7 +4498,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES)) if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
{ {
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = *list[i].lightlevel; lightlevel = *list[i].lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
colormap = list[i].extra_colormap; colormap = list[i].extra_colormap;
} }
@ -4775,7 +4795,11 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
extracolormap_t *colormap = sector->extra_colormap; extracolormap_t *colormap = sector->extra_colormap;
if (!(spr->mobj->frame & FF_FULLBRIGHT)) if (!(spr->mobj->frame & FF_FULLBRIGHT))
{
lightlevel = sector->lightlevel; lightlevel = sector->lightlevel;
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
}
if (colormap) if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
@ -4886,6 +4910,9 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
colormap = sector->extra_colormap; colormap = sector->extra_colormap;
} }
if (spr->mobj->frame & FF_SEMIBRIGHT)
lightlevel = 128 + (lightlevel>>1);
if (colormap) if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false); Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
else else
@ -5515,6 +5542,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
size_t lumpoff; size_t lumpoff;
unsigned rot; unsigned rot;
UINT8 flip; UINT8 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
angle_t ang; angle_t ang;
INT32 heightsec, phs; INT32 heightsec, phs;
const boolean papersprite = (thing->frame & FF_PAPERSPRITE); const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
@ -5646,7 +5674,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
x1 = tr_x + x1 * rightcos; x1 = tr_x + x1 * rightcos;
x2 = tr_x - x2 * 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; 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; gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale;
@ -5733,10 +5761,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", //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]); // thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
if (thing->eflags & MFE_VERTICALFLIP) vis->vflip = vflip;
vis->vflip = true;
else
vis->vflip = false;
vis->precip = false; vis->precip = false;
} }

View file

@ -69,7 +69,7 @@ char sprnames[NUMSPRITES + 1][5] =
"CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH", "CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS","ZTCH",
"MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT", "MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH","BFRT",
"OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN","FWRK", "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) // 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 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1}, // S_MSSHIELD_F12
// Ring // 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 // Blue Sphere Replacement for special stages
{SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL {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, 3, 7, {NULL}, 0, 0, S_OPAQUESMOKE5}, // S_OPAQUESMOKE4
{SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL}, // S_OPAQUESMOKE5 {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 #ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
#endif #endif
@ -5447,12 +5483,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_SPRK1, // deathstate S_NULL, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
38*FRACUNIT, // speed 38*FRACUNIT, // speed
16*FRACUNIT, // radius 48*FRACUNIT, // radius
24*FRACUNIT, // height 48*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
@ -5478,13 +5514,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_itemup, // deathsound sfx_itemup, // deathsound
38*FRACUNIT, // speed 38*FRACUNIT, // speed
15*FRACUNIT, // radius 24*FRACUNIT, // radius
24*FRACUNIT, // height 48*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags MF_SLIDEME|MF_BOUNCE|MF_SPECIAL|MF_DONTENCOREMAP, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -20059,6 +20095,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate 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 #ifdef SEENAMES

View file

@ -775,6 +775,9 @@ typedef enum sprite
SPR_WBLN, SPR_WBLN,
SPR_FWRK, SPR_FWRK,
SPR_MXCL,
SPR_RGSP,
SPR_DRAF,
// Xmas-specific sprites that don't fit aboxe // Xmas-specific sprites that don't fit aboxe
SPR_XMS4, SPR_XMS4,
@ -1675,6 +1678,18 @@ typedef enum state
// Ring // Ring
S_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 // Blue Sphere for special stages
S_BLUEBALL, S_BLUEBALL,
@ -4058,6 +4073,29 @@ typedef enum state
S_OPAQUESMOKE4, S_OPAQUESMOKE4,
S_OPAQUESMOKE5, 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 #ifdef SEENAMES
S_NAMECHECK, S_NAMECHECK,
#endif #endif
@ -4861,6 +4899,8 @@ typedef enum mobj_type
MT_LIONMAN, MT_LIONMAN,
MT_KARMAFIREWORK, MT_KARMAFIREWORK,
MT_RINGSPARKS,
MT_DRAFTDUST,
#ifdef SEENAMES #ifdef SEENAMES
MT_NAMECHECK, 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_IsPlayerLosing(player_t *player);
boolean K_IsPlayerWanted(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_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_FlipFromObject(mobj_t *mo, mobj_t *master);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master); void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_RespawnChecker(player_t *player); 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_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent);
void K_SpawnDraftDust(mobj_t *mo);
void K_DriftDustHandling(mobj_t *spawner); void K_DriftDustHandling(mobj_t *spawner);
void K_PuntMine(mobj_t *mine, mobj_t *punter); void K_PuntMine(mobj_t *mine, mobj_t *punter);
void K_DoSneaker(player_t *player, INT32 type); void K_DoSneaker(player_t *player, INT32 type);
@ -71,6 +74,7 @@ void K_CheckSpectateStatus(void);
void K_PlayAttackTaunt(mobj_t *source); void K_PlayAttackTaunt(mobj_t *source);
void K_PlayBoostTaunt(mobj_t *source); void K_PlayBoostTaunt(mobj_t *source);
void K_PlayOvertakeSound(mobj_t *source); void K_PlayOvertakeSound(mobj_t *source);
void K_PlayPainSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source); void K_PlayHitEmSound(mobj_t *source);
void K_PlayPowerGloatSound(mobj_t *source); void K_PlayPowerGloatSound(mobj_t *source);

View file

@ -1166,37 +1166,6 @@ static int lib_pPlayerRingBurst(lua_State *L)
return 0; 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) static int lib_pPlayerFlagBurst(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2229,6 +2198,16 @@ static int lib_kOvertakeSound(lua_State *L)
return 0; 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) static int lib_kHitEmSound(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2744,9 +2723,6 @@ static luaL_Reg lib[] = {
{"P_DamageMobj",lib_pDamageMobj}, {"P_DamageMobj",lib_pDamageMobj},
{"P_KillMobj",lib_pKillMobj}, {"P_KillMobj",lib_pKillMobj},
{"P_PlayerRingBurst",lib_pPlayerRingBurst}, {"P_PlayerRingBurst",lib_pPlayerRingBurst},
{"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst},
{"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst},
{"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst},
{"P_PlayerFlagBurst",lib_pPlayerFlagBurst}, {"P_PlayerFlagBurst",lib_pPlayerFlagBurst},
{"P_PlayRinglossSound",lib_pPlayRinglossSound}, {"P_PlayRinglossSound",lib_pPlayRinglossSound},
{"P_PlayDeathSound",lib_pPlayDeathSound}, {"P_PlayDeathSound",lib_pPlayDeathSound},
@ -2835,6 +2811,7 @@ static luaL_Reg lib[] = {
{"K_PlayPowerGloatSound", lib_kGloatSound}, {"K_PlayPowerGloatSound", lib_kGloatSound},
{"K_PlayOvertakeSound", lib_kOvertakeSound}, {"K_PlayOvertakeSound", lib_kOvertakeSound},
{"K_PlayLossSound", lib_kLossSound}, {"K_PlayLossSound", lib_kLossSound},
{"K_PlayPainSound", lib_kPainSound},
{"K_PlayHitEmSound", lib_kHitEmSound}, {"K_PlayHitEmSound", lib_kHitEmSound},
{"K_GetKartColorByName",lib_kGetKartColorByName}, {"K_GetKartColorByName",lib_kGetKartColorByName},
{"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerLosing",lib_kIsPlayerLosing},

View file

@ -1562,7 +1562,7 @@ static menuitem_t OP_AdvServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66}, {IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66},
};*/ };*/
#define ITEMTOGGLEBOTTOMRIGHT //#define ITEMTOGGLEBOTTOMRIGHT
static menuitem_t OP_MonitorToggleMenu[] = static menuitem_t OP_MonitorToggleMenu[] =
{ {
@ -1590,6 +1590,7 @@ static menuitem_t OP_MonitorToggleMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD}, {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, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING}, {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}, {IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK},
#ifdef ITEMTOGGLEBOTTOMRIGHT #ifdef ITEMTOGGLEBOTTOMRIGHT
{IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255}, {IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255},
@ -10627,6 +10628,7 @@ static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = {
&cv_thundershield, &cv_thundershield,
&cv_hyudoro, &cv_hyudoro,
&cv_pogospring, &cv_pogospring,
&cv_superring,
&cv_kitchensink, &cv_kitchensink,
&cv_triplesneaker, &cv_triplesneaker,
&cv_triplebanana, &cv_triplebanana,

View file

@ -710,59 +710,6 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
//return false; //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 #ifdef WEIGHTEDRECYCLER
// Compares players to see who currently has the "best" items, etc. // Compares players to see who currently has the "best" items, etc.
static int P_RecycleCompare(const void *p1, const void *p2) static int P_RecycleCompare(const void *p1, const void *p2)
@ -3615,57 +3562,163 @@ void A_AttractChase(mobj_t *actor)
if (LUA_CallAction("A_AttractChase", actor)) if (LUA_CallAction("A_AttractChase", actor))
return; return;
#endif #endif
if (actor->flags2 & MF2_NIGHTSPULL || !actor->health) if (actor->flags2 & MF2_NIGHTSPULL || !actor->health)
return; return;
// spilled rings flicker before disappearing if (actor->extravalue1) // SRB2Kart
if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE) {
actor->flags2 |= MF2_DONTDRAW; #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));
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + actor->target->height + offz);
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)));
P_TeleportMove(actor,
actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)),
actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)),
actor->target->z + (24 * actor->target->scale));
actor->angle += ANG30;
actor->extravalue1++;
}
}
#undef RINGBOOSTPWR
}
else 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; // Don't immediately pick up spilled rings
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime); if (actor->threshold > 0)
newring->momx = actor->momx; actor->threshold--;
newring->momy = actor->momy;
newring->momz = actor->momz; // Rings flicker before disappearing
P_RemoveMobj(actor); if (actor->fuse && actor->fuse < 5*TICRATE && (leveltime & 1))
return; 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 // Function: A_DropMine
@ -8405,6 +8458,7 @@ void A_SPBChase(mobj_t *actor)
fixed_t easiness = ((actor->tracer->player->kartspeed + (10-spark)) << FRACBITS) / 2; 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->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]*/) if (!P_IsObjectOnGround(actor->tracer) /*&& !actor->tracer->player->kartstuff[k_pogospring]*/)
{ {
@ -8488,6 +8542,15 @@ void A_SPBChase(mobj_t *actor)
actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
actor->momz = FixedMul(zspeed, FINESINE(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! // 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 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 : (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
@ -8529,6 +8592,7 @@ void A_SPBChase(mobj_t *actor)
&& !players[actor->lastlook].exiting) && !players[actor->lastlook].exiting)
{ {
spbplace = players[actor->lastlook].kartstuff[k_position]; spbplace = players[actor->lastlook].kartstuff[k_position];
players[actor->lastlook].kartstuff[k_ringlock] = 1;
if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo)
{ {
P_SetTarget(&actor->tracer, 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 // Invulnerable
if (player->powers[pw_flashing] > 0 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_squishedtimer] > 0
|| player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_invincibilitytimer] > 0
|| player->kartstuff[k_growshrinktimer] > 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; special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1) 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) if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true); 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; special->target->player->kartstuff[k_comebackpoints] += ptadd;
if (ptadd > 1) 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) if (special->target->player->kartstuff[k_comebackpoints] >= 2)
K_StealBumper(special->target->player, player, true); K_StealBumper(special->target->player, player, true);
@ -687,15 +687,34 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
/* FALLTHRU */ /* FALLTHRU */
case MT_RING: case MT_RING:
case MT_FLINGRING: 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))) if (!(P_CanPickupItem(player, 0)))
return; return;
special->momx = special->momy = special->momz = 0; // Reached the cap, don't waste 'em!
P_GivePlayerRings(player, 1); if ((player->kartstuff[k_rings] + player->kartstuff[k_pickuprings]) >= 20)
return;
if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING) special->momx = special->momy = special->momz = 0;
P_DoNightsScore(player);
break; 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_COIN:
case MT_FLINGCOIN: case MT_FLINGCOIN:
@ -2819,16 +2838,8 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return true; return true;
} }
if (target->health <= 1) // Death P_PlayRinglossSound(target);
{ P_PlayerRingBurst(player, 5);
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);
}
if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{ {
@ -2884,14 +2895,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) 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 player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE);
if (source && (G_BattleGametype()))
{
P_PlayerRingBurst(player, player->health - 1);
P_PlayerEmeraldBurst(player, false);
}
// Get rid of shield // Get rid of shield
player->powers[pw_shield] = SH_NONE; player->powers[pw_shield] = SH_NONE;
@ -2907,32 +2913,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); 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) if (player->pflags & PF_TIMEOVER)
{ {
mobj_t *boom; mobj_t *boom;
@ -2993,75 +2973,6 @@ void P_RemoveShield(player_t *player)
player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; 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. /** Damages an object, which may or may not be a player.
* For melee attacks, source and inflictor are the same. * For melee attacks, source and inflictor are the same.
@ -3279,121 +3190,21 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|| inflictor->type == MT_SMK_THWOMP || inflictor->player)) || inflictor->type == MT_SMK_THWOMP || inflictor->player))
{ {
player->kartstuff[k_sneakertimer] = 0; player->kartstuff[k_sneakertimer] = 0;
K_SpinPlayer(player, source, 1, inflictor, false); K_SpinPlayer(player, source, 1, inflictor, false);
damage = player->mo->health - 1; K_KartPainEnergyFling(player);
P_RingDamage(player, inflictor, source, damage);
P_PlayerRingBurst(player, 5); if (P_IsDisplayPlayer(player))
if (P_IsLocalPlayer(player))
{ {
quake.intensity = 32*FRACUNIT; quake.intensity = 32*FRACUNIT;
quake.time = 5; quake.time = 5;
} }
} }
else else
{
K_SpinPlayer(player, source, 0, inflictor, false); K_SpinPlayer(player, source, 0, inflictor, false);
}
return true; 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. // Killing dead. Just for kicks.
@ -3468,7 +3279,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
/** Spills an injured player's rings. /** Spills an injured player's rings.
* *
* \param player The player who is losing 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. * spawned.
* \sa P_PlayerFlagBurst * \sa P_PlayerFlagBurst
*/ */
@ -3479,32 +3290,38 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
angle_t fa; angle_t fa;
fixed_t ns; fixed_t ns;
fixed_t z; 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. // Better safe than sorry.
if (!player) if (!player)
return; return;
// Never have health in kart I think // Has a shield? Don't lose your rings!
if (player->mo->health <= 1) if (player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
num_rings = 5; return;
if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL)) // 20 is the ring cap in kart
num_rings = 32; if (num_rings > 20)
num_rings = 20;
else if (num_rings <= 0)
return;
if (player->powers[pw_emeralds]) // Cap the maximum loss automatically to 2 in ring debt
P_PlayerEmeraldBurst(player, false); if (player->kartstuff[k_rings] <= 0 && num_rings > 2)
num_rings = 2;
// Spill weapons first P_GivePlayerRings(player, -num_rings);
if (player->ringweapons)
P_PlayerWeaponPanelBurst(player);
// Spill the ammo // determine first angle
P_PlayerWeaponAmmoBurst(player); 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++) for (i = 0; i < num_rings; i++)
{ {
INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime; INT32 objType = mobjinfo[MT_RING].reactiontime;
z = player->mo->z; z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP) if (player->mo->eflags & MFE_VERTICALFLIP)
@ -3512,379 +3329,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); 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); P_SetTarget(&mo->target, player->mo);
mo->destscale = player->mo->scale; mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale); P_SetScale(mo, player->mo->scale);
// Angle offset by player angle, then slightly offset by amount of rings // Angle / height offset changes every other ring
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; if (i != 0)
// 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)
{ {
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) 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) if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1; 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. /** 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); 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_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_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_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
void P_PlayerFlagBurst(player_t *player, boolean toss); void P_PlayerFlagBurst(player_t *player, boolean toss);

View file

@ -1557,39 +1557,50 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; return true;
} }
if (P_IsObjectOnGround(thing) && tmthing->momz < 0)
{ {
K_KartBouncing(tmthing, thing, true, false); // The bump has to happen last
if (G_BattleGametype() && tmthing->player->kartstuff[k_pogospring]) mobj_t *mo1 = tmthing;
{ mobj_t *mo2 = thing;
K_StealBumper(tmthing->player, thing->player, false); boolean zbounce = 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);
if (G_BattleGametype()) if (P_IsObjectOnGround(thing) && tmthing->momz < 0)
{
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); zbounce = true;
K_SpinPlayer(tmthing->player, thing, 0, tmthing, false); 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); zbounce = true;
K_SpinPlayer(thing->player, tmthing, 0, thing, false);
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; return true;

View file

@ -85,6 +85,37 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
actioncachehead.prev = newaction; 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 // P_CycleStateAnimation
// //
@ -93,6 +124,7 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
// var2 determines delay between animation frames // var2 determines delay between animation frames
if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0) if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0)
return; return;
mobj->anim_duration = (UINT16)mobj->state->var2; mobj->anim_duration = (UINT16)mobj->state->var2;
// compare the current sprite frame to the one we started from // 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->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set P_SetupStateAnimation(mobj, st);
// Modified handling. // Modified handling.
// Call action functions when the state is set // 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->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set P_SetupStateAnimation(mobj, st);
// Modified handling. // Modified handling.
// Call action functions when the state is set // 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->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; mobj->frame = st->frame;
mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set P_SetupStateAnimation(mobj, st);
return true; return true;
} }
@ -353,7 +385,7 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state)
mobj->tics = st->tics; mobj->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; 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; return true;
} }
@ -1905,7 +1937,7 @@ void P_XYMovement(mobj_t *mo)
#endif #endif
//{ SRB2kart stuff //{ 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_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer))
return; return;
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= K_GetKartSpeed(mo->player, false)/2) 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; mom.z = -mom.z;
else else
// Flingrings bounce // Flingrings bounce
if (mo->type == MT_FLINGRING if (/*mo->type == MT_FLINGRING
|| mo->type == MT_FLINGCOIN || mo->type == MT_FLINGCOIN
|| P_WeaponOrPanel(mo->type) || P_WeaponOrPanel(mo->type)
|| mo->type == MT_FLINGEMERALD || mo->type == MT_FLINGEMERALD
|| mo->type == MT_BIGTUMBLEWEED ||*/ mo->type == MT_BIGTUMBLEWEED
|| mo->type == MT_LITTLETUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED
|| mo->type == MT_CANNONBALLDECOR || mo->type == MT_CANNONBALLDECOR
|| mo->type == MT_FALLINGROCK) || mo->type == MT_FALLINGROCK)
@ -3592,7 +3624,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
dummy.z = thiscam->z; dummy.z = thiscam->z;
dummy.height = thiscam->height; dummy.height = thiscam->height;
if (player->pflags & PF_TIMEOVER) 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. if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead.
P_ResetCamera(player, thiscam); P_ResetCamera(player, thiscam);
else else
@ -6670,7 +6702,7 @@ void P_MobjThinker(mobj_t *mobj)
if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0) if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0)
#if 1 // Set to 0 to test without needing to host #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 #endif
) )
mobj->flags2 |= MF2_DONTDRAW; mobj->flags2 |= MF2_DONTDRAW;
@ -7903,8 +7935,8 @@ void P_MobjThinker(mobj_t *mobj)
else else
{ {
fixed_t finalspeed = mobj->movefactor; fixed_t finalspeed = mobj->movefactor;
mobj_t *ghost = P_SpawnGhostMobj(mobj);
P_SpawnGhostMobj(mobj); ghost->colorized = true; // already has color!
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
if (mobj->health <= 5) if (mobj->health <= 5)
@ -7939,18 +7971,20 @@ void P_MobjThinker(mobj_t *mobj)
fixed_t topspeed = mobj->movefactor; fixed_t topspeed = mobj->movefactor;
fixed_t distbarrier = 512*mapobjectscale; fixed_t distbarrier = 512*mapobjectscale;
fixed_t distaway; 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) if (mobj->threshold > 0)
mobj->threshold--; mobj->threshold--;
if (leveltime % TICRATE == 0) if (leveltime % TICRATE == 0)
S_StartSound(mobj, mobj->info->activesound); S_StartSound(mobj, mobj->info->activesound);
if (gamespeed == 0) distbarrier = FixedMul(distbarrier, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4)));
distbarrier = FixedMul(distbarrier, FRACUNIT-FRACUNIT/4);
else if (gamespeed == 2)
distbarrier = FixedMul(distbarrier, FRACUNIT+FRACUNIT/4);
if (G_RaceGametype() && mobj->tracer) if (G_RaceGametype() && mobj->tracer)
{ {
@ -8007,7 +8041,14 @@ void P_MobjThinker(mobj_t *mobj)
} }
else else
{ {
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;
}
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
P_InstaThrust(mobj, mobj->angle, mobj->movefactor); P_InstaThrust(mobj, mobj->angle, mobj->movefactor);
@ -8032,14 +8073,25 @@ void P_MobjThinker(mobj_t *mobj)
case MT_BANANA: case MT_BANANA:
case MT_EGGMANITEM: case MT_EGGMANITEM:
mobj->friction = ORIG_FRICTION/4; mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy) 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) if (P_IsObjectOnGround(mobj) && mobj->health > 1)
{ {
S_StartSound(mobj, mobj->info->activesound); S_StartSound(mobj, mobj->info->activesound);
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
mobj->health = 1; mobj->health = 1;
} }
if (mobj->threshold > 0) if (mobj->threshold > 0)
mobj->threshold--; mobj->threshold--;
break; break;
@ -8047,18 +8099,38 @@ void P_MobjThinker(mobj_t *mobj)
indirectitemcooldown = 20*TICRATE; indirectitemcooldown = 20*TICRATE;
/* FALLTHRU */ /* FALLTHRU */
case MT_BALLHOG: case MT_BALLHOG:
P_SpawnGhostMobj(mobj)->fuse = 3; {
if (mobj->threshold > 0) mobj_t *ghost = P_SpawnGhostMobj(mobj);
mobj->threshold--; 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; break;
case MT_SINK: case MT_SINK:
if (mobj->momx || mobj->momy) 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)) if (P_IsObjectOnGround(mobj))
{ {
S_StartSound(mobj, mobj->info->deathsound); S_StartSound(mobj, mobj->info->deathsound);
P_SetMobjState(mobj, S_NULL); P_SetMobjState(mobj, S_NULL);
} }
if (mobj->threshold > 0) if (mobj->threshold > 0)
mobj->threshold--; mobj->threshold--;
break; break;
@ -8069,7 +8141,10 @@ void P_MobjThinker(mobj_t *mobj)
mobj->color = SKINCOLOR_KETCHUP; mobj->color = SKINCOLOR_KETCHUP;
if (mobj->momx || mobj->momy) 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])) if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2]))
{ {
@ -8142,9 +8217,10 @@ void P_MobjThinker(mobj_t *mobj)
if (p) 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); P_SetMobjState(mobj, S_BOOSTFLAME);
mobj->movecount = p->kartstuff[k_sneakertimer]; mobj->movecount = max(p->kartstuff[k_sneakertimer], p->kartstuff[k_levelbooster]);
} }
} }
@ -8263,6 +8339,18 @@ void P_MobjThinker(mobj_t *mobj)
K_MatchGenericExtraFlags(mobj, mobj->target); K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor);
break; break;
case MT_RINGSPARKS:
if (!mobj->target || P_MobjWasRemoved(mobj->target))
{
P_RemoveMobj(mobj);
return;
}
K_MatchGenericExtraFlags(mobj, mobj->target);
P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT),
mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT),
mobj->target->z + mobj->target->height);
break;
case MT_THUNDERSHIELD: case MT_THUNDERSHIELD:
{ {
fixed_t destx, desty; fixed_t destx, desty;
@ -9528,6 +9616,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 // momentum movement
if (mobj->momx || mobj->momy) if (mobj->momx || mobj->momy)
{ {
@ -9635,7 +9738,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->tics = st->tics; mobj->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. 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; mobj->friction = ORIG_FRICTION;
@ -10086,6 +10189,7 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster)
mobj->tics = st->tics; mobj->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
P_SetupStateAnimation(mobj, st);
mobj->friction = ORIG_FRICTION; mobj->friction = ORIG_FRICTION;
@ -10178,7 +10282,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
mobj->tics = st->tics; mobj->tics = st->tics;
mobj->sprite = st->sprite; mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits.. 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 // set subsector and/or block links
P_SetPrecipitationThingPosition(mobj); P_SetPrecipitationThingPosition(mobj);
@ -10608,6 +10712,8 @@ void P_PrecipitationEffects(void)
// //
void P_RespawnSpecials(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; fixed_t x, y, z;
subsector_t *ss; subsector_t *ss;
mobj_t *mo = NULL; mobj_t *mo = NULL;
@ -10654,21 +10760,28 @@ void P_RespawnSpecials(void)
numgotboxes = 0; numgotboxes = 0;
} }
// only respawn items when cv_itemrespawn is on // wait time depends on player count
if (!cv_itemrespawn.value) for (p = 0; p < MAXPLAYERS; p++)
return; {
if (playeringame[p] && !players[p].spectator)
pcount++;
}
// Don't respawn in special stages! if (pcount == 1) // No respawn when alone
if (G_IsSpecialStage(gamemap))
return; 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? // nothing left to respawn?
if (iquehead == iquetail) if (iquehead == iquetail)
return; return;
// the first item in the queue is the first to respawn // the first item in the queue is the first to respawn
// wait at least 30 seconds if (leveltime - itemrespawntime[iquetail] < time)
if (leveltime - itemrespawntime[iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE)
return; return;
mthing = itemrespawnque[iquetail]; mthing = itemrespawnque[iquetail];
@ -11953,7 +12066,7 @@ ML_NOCLIMB : Direction not controllable
void P_SpawnHoopsAndRings(mapthing_t *mthing) void P_SpawnHoopsAndRings(mapthing_t *mthing)
{ {
mobj_t *mobj = NULL; mobj_t *mobj = NULL;
INT32 /*r,*/ i; INT32 r, i;
fixed_t x, y, z, finalx, finaly, finalz; fixed_t x, y, z, finalx, finaly, finalz;
sector_t *sec; sector_t *sec;
TVector v, *res; TVector v, *res;
@ -12240,8 +12353,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
return; return;
} }
else return; // srb2kart - no rings or ring-like objects in R1
/*
// Wing logo item. // Wing logo item.
else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum) else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
{ {
@ -12535,7 +12646,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
} }
} }
return; return;
}*/ }
else return;
} }
// //

View file

@ -35,14 +35,9 @@
#pragma interface #pragma interface
#endif #endif
/// \brief Frame flags: only the frame number /// \brief Frame flags: only the frame number (frames from 0 to 63, but a bit of headroom for 2.2 compat)
#define FF_FRAMEMASK 0x1ff #define FF_FRAMEMASK 0xff
/// \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: 0 = no trans(opaque), 1-15 = transl. table /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table
#define FF_TRANSMASK 0xf0000 #define FF_TRANSMASK 0xf0000
/// \brief shift for FF_TRANSMASK /// \brief shift for FF_TRANSMASK
@ -58,6 +53,23 @@
#define FF_TRANS80 (tr_trans80<<FF_TRANSSHIFT) #define FF_TRANS80 (tr_trans80<<FF_TRANSSHIFT)
#define FF_TRANS90 (tr_trans90<<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 /** \brief translucency tables
\todo add another asm routine which use the fg and bg indexes in the \todo add another asm routine which use the fg and bg indexes in the

View file

@ -4247,19 +4247,19 @@ DoneSection2:
if (nump > 1) if (nump > 1)
{ {
if (K_IsPlayerLosing(player)) if (K_IsPlayerLosing(player))
player->kartstuff[k_laphand] = 3; player->karthud[khud_laphand] = 3;
else else
{ {
if (nump > 2 && player->kartstuff[k_position] == 1) // 1st place in 1v1 uses thumbs up 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 else
player->kartstuff[k_laphand] = 2; player->karthud[khud_laphand] = 2;
} }
} }
else 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) if (player->pflags & PF_NIGHTSMODE)
player->drillmeter += 48*20; player->drillmeter += 48*20;
@ -4295,7 +4295,7 @@ DoneSection2:
player->starpostangle = player->starpostx = player->starposty = player->starpostz = player->kartstuff[k_starpostflip] = 0; 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)) if (player->laps == (UINT8)(cv_numlaps.value - 1))
S_StartSound(NULL, sfx_s3k68); S_StartSound(NULL, sfx_s3k68);
@ -4325,7 +4325,7 @@ DoneSection2:
if (player->laps >= (unsigned)cv_numlaps.value) if (player->laps >= (unsigned)cv_numlaps.value)
{ {
if (P_IsLocalPlayer(player)) if (P_IsDisplayPlayer(player))
S_StartSound(NULL, sfx_s3k6a); S_StartSound(NULL, sfx_s3k6a);
else if (player->kartstuff[k_position] == 1) else if (player->kartstuff[k_position] == 1)
S_StartSound(NULL, sfx_s253); S_StartSound(NULL, sfx_s253);
@ -7356,9 +7356,7 @@ void T_Friction(friction_t *f)
// apparently, all I had to do was comment out part of the next line and // apparently, all I had to do was comment out part of the next line and
// friction works for all mobj's // friction works for all mobj's
// (or at least MF_PUSHABLEs, which is all I care about anyway) // (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 if (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && thing->z == thing->floorz)
&& (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 (f->roverfriction) if (f->roverfriction)
{ {

View file

@ -946,50 +946,19 @@ void P_ResetPlayer(player_t *player)
// //
void P_GivePlayerRings(player_t *player, INT32 num_rings) void P_GivePlayerRings(player_t *player, INT32 num_rings)
{ {
if (player->bot)
player = &players[consoleplayer];
if (!player->mo) if (!player->mo)
return; return;
player->mo->health += num_rings; if (G_BattleGametype()) // No rings in Battle Mode
player->health += num_rings; return;
if (!G_IsSpecialStage(gamemap) || !useNightsSS) player->kartstuff[k_rings] += num_rings;
player->totalring += 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. if (player->kartstuff[k_rings] > 20)
/* player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry!
// Can only get up to 9999 rings, sorry! else if (player->kartstuff[k_rings] < -20)
if (player->mo->health > 10000) player->kartstuff[k_rings] = -20; // Chaotix ring debt!
{
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);
}
}
} }
// //
@ -1114,11 +1083,12 @@ void P_PlayLivesJingle(player_t *player)
void P_PlayRinglossSound(mobj_t *source) void P_PlayRinglossSound(mobj_t *source)
{ {
sfxenum_t key = P_RandomKey(2); if (source->player && source->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD)
if (cv_kartvoices.value) S_StartSound(source, sfx_s1a3); // Shield hit (no ring loss)
S_StartSound(source, (mariomode) ? sfx_mario8 : sfx_khurt1 + key); else if (source->player && source->player->kartstuff[k_rings] <= 0)
S_StartSound(source, sfx_s1a6); // Ring debt (lessened ring loss)
else else
S_StartSound(source, sfx_slip); S_StartSound(source, sfx_s1c6); // Normal ring loss sound
} }
void P_PlayDeathSound(mobj_t *source) void P_PlayDeathSound(mobj_t *source)
@ -1704,7 +1674,7 @@ void P_DoPlayerExit(player_t *player)
if (cv_kartvoices.value) if (cv_kartvoices.value)
{ {
if (P_IsLocalPlayer(player)) if (P_IsDisplayPlayer(player))
{ {
sfxenum_t sfx_id; sfxenum_t sfx_id;
if (K_IsPlayerLosing(player)) if (K_IsPlayerLosing(player))
@ -1751,7 +1721,7 @@ void P_DoPlayerExit(player_t *player)
*/ */
player->powers[pw_underwater] = 0; player->powers[pw_underwater] = 0;
player->powers[pw_spacetime] = 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]) if (player == &players[consoleplayer])
demo.savebutton = leveltime; 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? if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam?
{ {
cmd->forwardmove = cmd->sidemove = 0; cmd->forwardmove = cmd->sidemove = 0;
if (player->kartstuff[k_sneakertimer]) if (EITHERSNEAKER(player))
cmd->forwardmove = 50; cmd->forwardmove = 50;
} }
@ -4129,13 +4099,6 @@ static void P_3dMovement(player_t *player)
//movepushforward = cmd->forwardmove * (thrustfactor * acceleration); //movepushforward = cmd->forwardmove * (thrustfactor * acceleration);
movepushforward = K_3dKartMovement(player, onground, cmd->forwardmove); 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... if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
movepushforward = FixedMul(movepushforward, player->mo->movefactor); movepushforward = FixedMul(movepushforward, player->mo->movefactor);
@ -4199,6 +4162,18 @@ static void P_3dMovement(player_t *player)
player->mo->momx += totalthrust.x; player->mo->momx += totalthrust.x;
player->mo->momy += totalthrust.y; 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 #endif
// Time to ask three questions: // Time to ask three questions:
@ -4215,7 +4190,7 @@ static void P_3dMovement(player_t *player)
if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed) if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed)
{ {
fixed_t tempmomx, tempmomy; fixed_t tempmomx, tempmomy;
if (oldMagnitude > K_GetKartSpeed(player, true) && onground) // SRB2Kart: onground check for air speed cap if (oldMagnitude > K_GetKartSpeed(player, true))
{ {
if (newMagnitude > oldMagnitude) if (newMagnitude > oldMagnitude)
{ {
@ -5778,11 +5753,10 @@ static void P_MovePlayer(player_t *player)
boolean add_delta = true; boolean add_delta = true;
// Kart: store the current turn range for later use // 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 || (leveltime > starttime && (cmd->buttons & BT_ACCELERATE && cmd->buttons & BT_BRAKE)) // Rubber-burn turn
|| (player->kartstuff[k_respawn]) // Respawning || (player->kartstuff[k_respawn]) // Respawning
|| (player->spectator || objectplacing)) // Not a physical player || (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->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1;
player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1; player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1;
@ -6172,7 +6146,7 @@ static void P_MovePlayer(player_t *player)
//////////////////////////// ////////////////////////////
// SRB2kart - Drifting smoke and fire // SRB2kart - Drifting smoke and fire
if (player->kartstuff[k_sneakertimer] > 0 && onground && (leveltime & 1)) if (EITHERSNEAKER(player) && onground && (leveltime & 1))
K_SpawnBoostTrail(player); K_SpawnBoostTrail(player);
if (player->kartstuff[k_invincibilitytimer] > 0) if (player->kartstuff[k_invincibilitytimer] > 0)
@ -7064,7 +7038,7 @@ static void P_DeathThink(player_t *player)
if (player->pflags & PF_TIMEOVER) if (player->pflags & PF_TIMEOVER)
{ {
player->kartstuff[k_timeovercam]++; player->karthud[khud_timeovercam]++;
if (player->mo) if (player->mo)
{ {
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
@ -7072,7 +7046,7 @@ static void P_DeathThink(player_t *player)
} }
} }
else else
player->kartstuff[k_timeovercam] = 0; player->karthud[khud_timeovercam] = 0;
K_KartPlayerHUDUpdate(player); K_KartPlayerHUDUpdate(player);
@ -7280,7 +7254,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
#endif #endif
if (player->pflags & PF_TIMEOVER) // 1 for momentum keep, 2 for turnaround 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 else
timeover = 0; timeover = 0;
@ -7423,7 +7397,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (timeover) 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; camrotate += timeovercam;
} }
else if (leveltime < introtime) // Whoooshy camera! else if (leveltime < introtime) // Whoooshy camera!
@ -7497,10 +7471,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
dist += 4*(player->speed - K_GetKartSpeed(player, false)); dist += 4*(player->speed - K_GetKartSpeed(player, false));
dist += abs(thiscam->momz)/4; dist += abs(thiscam->momz)/4;
if (player->kartstuff[k_boostcam]) if (player->karthud[khud_boostcam])
{ {
dist -= FixedMul(11*dist/16, player->kartstuff[k_boostcam]); dist -= FixedMul(11*dist/16, player->karthud[khud_boostcam]);
height -= FixedMul(height, player->kartstuff[k_boostcam]); height -= FixedMul(height, player->karthud[khud_boostcam]);
} }
x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist); x = mo->x - FixedMul(FINECOSINE((angle>>ANGLETOFINESHIFT) & FINEMASK), dist);
@ -8437,8 +8411,7 @@ void P_PlayerThink(player_t *player)
#if 1 #if 1
// "Blur" a bit when you have speed shoes and are going fast enough // "Blur" a bit when you have speed shoes and are going fast enough
if ((player->powers[pw_super] || player->powers[pw_sneakers] 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
&& (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale)) && (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{ {
UINT8 i; UINT8 i;

View file

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

View file

@ -104,9 +104,20 @@ extern CV_PossibleValue_t Forceskin_cons_t[];
// ----------- // -----------
typedef enum typedef enum
{ {
// actual cuts
SC_NONE = 0, SC_NONE = 0,
SC_TOP = 1, 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; } spritecut_e;
// A vissprite_t is a thing that will be drawn during a refresh, // 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]; INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
boolean precip;
boolean vflip; // Flip vertically
boolean isScaled;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
} vissprite_t; } vissprite_t;