Merge branch 'just-tumble' into 'master'

Tumble

See merge request KartKrew/Kart!345
This commit is contained in:
Sal 2021-01-07 00:36:38 -05:00
commit 061ad6587b
24 changed files with 509 additions and 192 deletions

View file

@ -626,6 +626,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->karmadelay = SHORT(players[i].karmadelay);
rsp->eliminated = players[i].eliminated;
rsp->tumbleBounces = players[i].tumbleBounces;
rsp->tumbleHeight = SHORT(players[i].tumbleHeight);
rsp->tumbleLastBounce = players[i].tumbleLastBounce;
// respawnvars_t
rsp->respawn_state = players[i].respawn.state;
rsp->respawn_pointx = (fixed_t)LONG(players[i].respawn.pointx);
@ -779,6 +783,10 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].karmadelay = SHORT(rsp->karmadelay);
players[i].eliminated = rsp->eliminated;
players[i].tumbleBounces = rsp->tumbleBounces;
players[i].tumbleHeight = SHORT(rsp->tumbleHeight);
players[i].tumbleLastBounce = (boolean)rsp->tumbleLastBounce;
// respawnvars_t
players[i].respawn.state = rsp->respawn_state;
players[i].respawn.pointx = (fixed_t)LONG(rsp->respawn_pointx);

View file

@ -291,6 +291,10 @@ typedef struct
INT16 karmadelay;
boolean eliminated;
UINT8 tumbleBounces;
UINT16 tumbleHeight;
boolean tumbleLastBounce;
// respawnvars_t
UINT8 respawn_state;
fixed_t respawn_pointx;

View file

@ -351,6 +351,7 @@ consvar_t cv_eggmanmonitor = CVAR_INIT ("eggmanmonitor", "On", CV_NETVAR|CV_C
consvar_t cv_orbinaut = CVAR_INIT ("orbinaut", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_jawz = CVAR_INIT ("jawz", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_mine = CVAR_INIT ("mine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_landmine = CVAR_INIT ("landmine", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_ballhog = CVAR_INIT ("ballhog", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_selfpropelledbomb = CVAR_INIT ("selfpropelledbomb", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);
consvar_t cv_grow = CVAR_INIT ("grow", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL);

View file

@ -66,7 +66,7 @@ extern consvar_t cv_restrictskinchange, cv_allowteamchange, cv_ingamecap, cv_res
// SRB2kart items
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, cv_landmine;
extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
extern consvar_t cv_thundershield, cv_bubbleshield, cv_flameshield;
extern consvar_t cv_hyudoro, cv_pogospring, cv_kitchensink;

View file

@ -245,17 +245,18 @@ Run this macro, then #undef FOREACH afterward
FOREACH (ORBINAUT, 6),\
FOREACH (JAWZ, 7),\
FOREACH (MINE, 8),\
FOREACH (BALLHOG, 9),\
FOREACH (SPB, 10),\
FOREACH (GROW, 11),\
FOREACH (SHRINK, 12),\
FOREACH (THUNDERSHIELD, 13),\
FOREACH (BUBBLESHIELD, 14),\
FOREACH (FLAMESHIELD, 15),\
FOREACH (HYUDORO, 16),\
FOREACH (POGOSPRING, 17),\
FOREACH (SUPERRING, 18),\
FOREACH (KITCHENSINK, 19)
FOREACH (LANDMINE, 9),\
FOREACH (BALLHOG, 10),\
FOREACH (SPB, 11),\
FOREACH (GROW, 12),\
FOREACH (SHRINK, 13),\
FOREACH (THUNDERSHIELD, 14),\
FOREACH (BUBBLESHIELD, 15),\
FOREACH (FLAMESHIELD, 16),\
FOREACH (HYUDORO, 17),\
FOREACH (POGOSPRING, 18),\
FOREACH (SUPERRING, 19),\
FOREACH (KITCHENSINK, 20)
typedef enum
{
@ -569,6 +570,10 @@ typedef struct player_s
UINT16 followercolor; // Kart: Used to store the follower colour the player wishes to use
mobj_t *follower; // Kart: This is the follower object we have. (If any)
UINT8 tumbleBounces;
UINT16 tumbleHeight;
boolean tumbleLastBounce;
//
UINT32 charflags; // Extra abilities/settings for skins (combinable stuff)

View file

@ -8555,6 +8555,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SLOWBOOM9",
"S_SLOWBOOM10",
// Land Mine
"S_LANDMINE",
"S_LANDMINE_EXPLODE",
// Ballhog
"S_BALLHOG1",
"S_BALLHOG2",
@ -10222,6 +10226,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BOOMEXPLODE",
"MT_BOOMPARTICLE",
"MT_LANDMINE", // Land Mine
"MT_BALLHOG", // Ballhog
"MT_BALLHOGBOOM",
@ -11354,7 +11360,7 @@ struct {
{"DMG_NORMAL",DMG_NORMAL},
{"DMG_WIPEOUT",DMG_WIPEOUT},
{"DMG_EXPLODE",DMG_EXPLODE},
{"DMG_SQUISH",DMG_SQUISH},
{"DMG_TUMBLE",DMG_TUMBLE},
{"DMG_STING",DMG_STING},
{"DMG_KARMA",DMG_KARMA},
//// Death types

View file

@ -544,6 +544,7 @@ char sprnames[NUMSPRITES + 1][5] =
"JAWZ", // Jawz
"SSMN", // SS Mine
"KRBM", // SS Mine BOOM
"LNDM", // Land Mine
"BHOG", // Ballhog
"BHBM", // Ballhog BOOM
"SPBM", // Self-Propelled Bomb
@ -4249,6 +4250,9 @@ state_t states[NUMSTATES] =
{SPR_KRBM, FF_FULLBRIGHT|8, 5, {NULL}, 0, 0, S_SLOWBOOM10}, // S_SLOWBOOM9
{SPR_KRBM, FF_FULLBRIGHT|9, 5, {NULL}, 0, 0, S_NULL}, // S_SLOWBOOM10
{SPR_LNDM, 0, -1, {NULL}, 0, 0, S_LANDMINE}, // S_LANDMINE
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_LANDMINE_EXPLODE
{SPR_BHOG, 0, 3, {A_PlaySound}, sfx_s1bd, 1, S_BALLHOG2}, // S_BALLHOG1
{SPR_BHOG, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_BALLHOG3}, // S_BALLHOG2
{SPR_BHOG, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_BALLHOG4}, // S_BALLHOG3
@ -23765,6 +23769,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_LANDMINE
-1, // doomednum
S_LANDMINE, // spawnstate
2, // spawnhealth
S_NULL, // seestate
sfx_tossed, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_LANDMINE_EXPLODE, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
24*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_s3k5c, // activesound
MF_SHOOTABLE|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_BALLHOG
-1, // doomednum
S_BALLHOG1, // spawnstate

View file

@ -815,6 +815,7 @@ typedef enum sprite
SPR_JAWZ, // Jawz
SPR_SSMN, // SS Mine
SPR_KRBM, // SS Mine BOOM
SPR_LNDM, // Land Mine
SPR_BHOG, // Ballhog
SPR_BHBM, // Ballhog BOOM
SPR_SPBM, // Self-Propelled Bomb
@ -4407,6 +4408,10 @@ typedef enum state
S_SLOWBOOM9,
S_SLOWBOOM10,
// Land mine
S_LANDMINE,
S_LANDMINE_EXPLODE,
// Ballhog
S_BALLHOG1,
S_BALLHOG2,
@ -6114,6 +6119,8 @@ typedef enum mobj_type
MT_BOOMEXPLODE,
MT_BOOMPARTICLE,
MT_LANDMINE, // Land Mine
MT_BALLHOG, // Ballhog
MT_BALLHOGBOOM,

View file

@ -1036,6 +1036,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
K_BotItemSneaker(player, cmd);
break;
case KITEM_BANANA:
case KITEM_LANDMINE:
if (!player->kartstuff[k_itemheld])
{
K_BotItemGenericTrapShield(player, cmd, turnamt, false);

View file

@ -589,6 +589,7 @@ static boolean K_BotSteerObjects(mobj_t *thing)
case MT_JAWZ_SHIELD:
case MT_SSMINE:
case MT_SSMINE_SHIELD:
case MT_LANDMINE:
case MT_BALLHOG:
case MT_SPB:
case MT_BUBBLESHIELDTRAP:

View file

@ -68,7 +68,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
damageitem = true;
}
else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE)
else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE)
{
damageitem = true;
// Bomb death
@ -158,6 +158,12 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
damageitem = true;
}
else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE)
{
damageitem = true;
// Bomb death
P_KillMobj(t2, t1, t1, DMG_NORMAL);
}
else if (t2->flags & MF_SHOOTABLE)
{
// Shootable damage
@ -329,6 +335,73 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2)
return true;
}
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
{
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
if (t1->health <= 0 || t2->health <= 0)
return true;
if (t2->player)
{
if (t2->player->powers[pw_flashing])
return true;
// Banana snipe!
if (t1->health > 1)
S_StartSound(t2, sfx_bsnipe);
if (t2->player->kartstuff[k_flamedash] && t2->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
{
// Melt item
S_StartSound(t2, sfx_s3k43);
}
else
{
// Player Damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_TUMBLE);
}
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD
|| t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD
|| t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD
|| t2->type == MT_BALLHOG)
{
// Other Item Damage
if (t2->eflags & MFE_VERTICALFLIP)
t2->z -= t2->height;
else
t2->z += t2->height;
S_StartSound(t2, t2->info->deathsound);
P_KillMobj(t2, t1, t1, DMG_NORMAL);
P_SetObjectMomZ(t2, 8*FRACUNIT, false);
P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT);
P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH);
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}
else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE)
{
P_KillMobj(t1, t2, t2, DMG_NORMAL);
// Bomb death
P_KillMobj(t2, t1, t1, DMG_NORMAL);
}
else if (t2->flags & MF_SHOOTABLE)
{
// Shootable damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}
return true;
}
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
{
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
@ -384,10 +457,112 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2)
if (t1->health)
P_KillMobj(t1, t2, t2, DMG_NORMAL);
/*if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0
/*
if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0
|| t2->player->kartstuff[k_growshrinktimer] > 0))
return true;*/
return true;
*/
K_KartBouncing(t2, t1, false, true);
return false;
}
boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
{
boolean t1Condition = false;
boolean t2Condition = false;
boolean stung = false;
// Grow damage
t1Condition = (t1->scale > t2->scale + (mapobjectscale/8));
t2Condition = (t2->scale > t1->scale + (mapobjectscale/8));
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
return true;
}
// Invincibility damage
t1Condition = (t1->player->kartstuff[k_invincibilitytimer] > 0);
t2Condition = (t2->player->kartstuff[k_invincibilitytimer] > 0);
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
return true;
}
// Flame Shield dash damage
t1Condition = (t1->player->kartstuff[k_flamedash] > 0 && t1->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD);
t2Condition = (t2->player->kartstuff[k_flamedash] > 0 && t2->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD);
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT);
return true;
}
// Battle Mode Sneaker damage
// (Pogo Spring damage is handled in head-stomping code)
if (gametyperules & GTR_BUMPERS)
{
t1Condition = (t1->player->kartstuff[k_sneakertimer] > 0 && t1->player->powers[pw_flashing] != 0);
t2Condition = (t2->player->kartstuff[k_sneakertimer] > 0 && t2->player->powers[pw_flashing] != 0);
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT|DMG_STEAL);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT|DMG_STEAL);
return true;
}
}
// Ring sting, this is a bit more unique
t1Condition = (K_GetShieldFromItem(t2->player->kartstuff[k_itemtype]) == KSHIELD_NONE);
t2Condition = (K_GetShieldFromItem(t1->player->kartstuff[k_itemtype]) == KSHIELD_NONE);
if (t1Condition == true)
{
if (t2->player->rings <= 0)
{
P_DamageMobj(t2, t1, t1, 1, DMG_STING);
stung = true;
}
P_PlayerRingBurst(t2->player, 1);
stung = true;
}
if (t2Condition == true)
{
if (t1->player->rings <= 0)
{
P_DamageMobj(t1, t2, t2, 1, DMG_STING);
stung = true;
}
P_PlayerRingBurst(t2->player, 1);
}
return stung;
}

View file

@ -9,8 +9,10 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2);
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2);
boolean K_MineCollide(mobj_t *t1, mobj_t *t2);
boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2);
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2);
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2);
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2);
boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2);
boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2);
#endif

View file

@ -115,6 +115,7 @@ static patch_t *kp_eggman[2];
static patch_t *kp_orbinaut[5];
static patch_t *kp_jawz[2];
static patch_t *kp_mine[2];
static patch_t *kp_landmine[2];
static patch_t *kp_ballhog[2];
static patch_t *kp_selfpropelledbomb[2];
static patch_t *kp_grow[2];
@ -394,6 +395,7 @@ void K_LoadKartHUDGraphics(void)
}
kp_jawz[0] = W_CachePatchName("K_ITJAWZ", PU_HUDGFX);
kp_mine[0] = W_CachePatchName("K_ITMINE", PU_HUDGFX);
kp_landmine[0] = W_CachePatchName("K_ITLNDM", PU_HUDGFX);
kp_ballhog[0] = W_CachePatchName("K_ITBHOG", PU_HUDGFX);
kp_selfpropelledbomb[0] = W_CachePatchName("K_ITSPB", PU_HUDGFX);
kp_grow[0] = W_CachePatchName("K_ITGROW", PU_HUDGFX);
@ -443,6 +445,7 @@ void K_LoadKartHUDGraphics(void)
kp_orbinaut[4] = W_CachePatchName("K_ISORBN", PU_HUDGFX);
kp_jawz[1] = W_CachePatchName("K_ISJAWZ", PU_HUDGFX);
kp_mine[1] = W_CachePatchName("K_ISMINE", PU_HUDGFX);
kp_landmine[1] = W_CachePatchName("K_ISLNDM", PU_HUDGFX);
kp_ballhog[1] = W_CachePatchName("K_ISBHOG", PU_HUDGFX);
kp_selfpropelledbomb[1] = W_CachePatchName("K_ISSPB", PU_HUDGFX);
kp_grow[1] = W_CachePatchName("K_ISGROW", PU_HUDGFX);
@ -619,6 +622,8 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny)
return (tiny ? "K_ISJAWZ" : "K_ITJAWZ");
case KITEM_MINE:
return (tiny ? "K_ISMINE" : "K_ITMINE");
case KITEM_LANDMINE:
return (tiny ? "K_ISLNDM" : "K_ITLNDM");
case KITEM_BALLHOG:
return (tiny ? "K_ISBHOG" : "K_ITBHOG");
case KITEM_SPB:
@ -970,6 +975,10 @@ static void K_drawKartItem(void)
localpatch = kp_superring[offset];
//localcolor = SKINCOLOR_GOLD;
break;
case 15: // Land Mine
localpatch = kp_landmine[offset];
//localcolor = SKINCOLOR_JET;
break;
/*case 15: // Pogo Spring
localpatch = kp_pogospring[offset];
localcolor = SKINCOLOR_TANGERINE;
@ -1055,6 +1064,9 @@ static void K_drawKartItem(void)
case KITEM_MINE:
localpatch = kp_mine[offset];
break;
case KITEM_LANDMINE:
localpatch = kp_landmine[offset];
break;
case KITEM_BALLHOG:
localpatch = kp_ballhog[offset];
break;
@ -3822,6 +3834,7 @@ static void K_drawDistributionDebugger(void)
kp_orbinaut[4],
kp_jawz[1],
kp_mine[1],
kp_landmine[1],
kp_ballhog[1],
kp_selfpropelledbomb[1],
kp_grow[1],

View file

@ -151,6 +151,7 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_orbinaut);
CV_RegisterVar(&cv_jawz);
CV_RegisterVar(&cv_mine);
CV_RegisterVar(&cv_landmine);
CV_RegisterVar(&cv_ballhog);
CV_RegisterVar(&cv_selfpropelledbomb);
CV_RegisterVar(&cv_grow);
@ -252,6 +253,7 @@ consvar_t *KartItemCVars[NUMKARTRESULTS-1] =
&cv_orbinaut,
&cv_jawz,
&cv_mine,
&cv_landmine,
&cv_ballhog,
&cv_selfpropelledbomb,
&cv_grow,
@ -281,11 +283,12 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
/*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker
/*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility
/*Banana*/ { 7, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 3, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Banana*/ { 5, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Orbinaut*/ { 7, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut
/*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine
/*Land Mine*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
/*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 1, 2, 3, 4, 2, 2, 0 }, // Self-Propelled Bomb
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
@ -317,6 +320,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
/*Orbinaut*/ { 8, 0 }, // Orbinaut
/*Jawz*/ { 8, 1 }, // Jawz
/*Mine*/ { 6, 1 }, // Mine
/*Land Mine*/ { 0, 0 }, // Land Mine
/*Ballhog*/ { 2, 1 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 0 }, // Self-Propelled Bomb
/*Grow*/ { 2, 1 }, // Grow
@ -525,6 +529,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush,
case KITEM_ORBINAUT:
case KITEM_JAWZ:
case KITEM_MINE:
case KITEM_LANDMINE:
case KITEM_BALLHOG:
case KITEM_SPB:
case KITEM_GROW:
@ -553,6 +558,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush,
{
case KITEM_ROCKETSNEAKER:
case KITEM_JAWZ:
case KITEM_LANDMINE:
case KITEM_BALLHOG:
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEBANANA:
@ -976,7 +982,7 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against)
return weight;
if (against && !P_MobjWasRemoved(against) && against->player
&& ((!against->player->kartstuff[k_spinouttimer] && mobj->player->kartstuff[k_spinouttimer]) // You're in spinout
&& ((!P_PlayerInPain(against->player) && P_PlayerInPain(mobj->player)) // You're hurt
|| (against->player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD && mobj->player->kartstuff[k_itemtype] != KITEM_BUBBLESHIELD))) // They have a Bubble Shield
{
weight = 0; // This player does not cause any bump action
@ -1201,15 +1207,6 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol
mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]);
//mobj1->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type
}
else if (mobj2->player // Player VS player bumping only
&& (K_GetShieldFromItem(mobj1->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields
{
if (mobj1->player->rings <= 0)
{
P_DamageMobj(mobj1, mobj2, mobj2, 1, DMG_STING);
}
P_PlayerRingBurst(mobj1->player, 1);
}
}
if (mobj2->player)
@ -1225,15 +1222,6 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean sol
mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]);
//mobj2->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type
}
else if (mobj1->player // Player VS player bumping only
&& (K_GetShieldFromItem(mobj2->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields
{
if (mobj2->player->rings <= 0)
{
P_DamageMobj(mobj2, mobj1, mobj1, 1, DMG_STING);
}
P_PlayerRingBurst(mobj2->player, 1);
}
}
return true;
@ -2370,7 +2358,7 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics)
if (mo1valid == true && mo2valid == true)
{
const INT32 mintics = 1;
const INT32 mintics = tics;
const fixed_t ticaddfactor = mapobjectscale * 8;
const fixed_t mo1speed = FixedHypot(FixedHypot(mo1->momx, mo1->momy), mo1->momz);
@ -2532,25 +2520,64 @@ static void K_RemoveGrowShrink(player_t *player)
P_RestoreMusic(player);
}
void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
{
(void)inflictor;
(void)source;
player->kartstuff[k_squishedtimer] = TICRATE;
player->tumbleBounces = 1;
// Reduce Shrink timer
if (player->kartstuff[k_growshrinktimer] < 0)
player->mo->momx = 2 * player->mo->momx / 3;
player->mo->momy = 2 * player->mo->momy / 3;
player->tumbleHeight = 30;
if (inflictor && !P_MobjWasRemoved(inflictor))
{
player->kartstuff[k_growshrinktimer] += TICRATE;
if (player->kartstuff[k_growshrinktimer] >= 0)
K_RemoveGrowShrink(player);
const fixed_t addHeight = FixedHypot(FixedHypot(inflictor->momx, inflictor->momy) / 2, FixedHypot(player->mo->momx, player->mo->momy) / 2);
player->tumbleHeight += (addHeight / player->mo->scale);
}
player->mo->flags |= MF_NOCLIP;
player->mo->momz = player->tumbleHeight * player->mo->scale * P_MobjFlip(player->mo);
if (player->mo->state != &states[S_KART_SQUISH]) // Squash
P_SetPlayerMobjState(player->mo, S_KART_SQUISH);
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 5);
}
static void K_HandleTumbleBounce(player_t *player)
{
player->tumbleBounces++;
player->tumbleHeight = (player->tumbleHeight * 4) / 5;
if (player->tumbleHeight < 10)
{
// 10 minimum bounce height
player->tumbleHeight = 10;
}
if (player->tumbleBounces > 4 && player->tumbleHeight < 30)
{
// Leave tumble state when below 30 height, and have bounced off the ground enough
if (player->tumbleLastBounce == true)
{
// End tumble state
player->tumbleBounces = 0;
return;
}
else
{
// One last bounce at the minimum height, to reset the animation
player->tumbleHeight = 10;
player->tumbleLastBounce = true;
}
}
player->mo->momx = player->mo->momx / 2;
player->mo->momy = player->mo->momy / 2;
player->mo->momz = player->tumbleHeight * player->mo->scale * P_MobjFlip(player->mo);
}
void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer
@ -2579,8 +2606,6 @@ void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A b
if (P_IsDisplayPlayer(player))
P_StartQuake(64<<FRACBITS, 5);
K_DropItems(player);
}
// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter.
@ -4227,6 +4252,40 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
}
}
static void K_ThrowLandMine(player_t *player)
{
mobj_t *landMine;
mobj_t *throwmo;
landMine = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_LANDMINE);
K_FlipFromObject(landMine, player->mo);
landMine->threshold = 10;
if (landMine->info->seesound)
S_StartSound(player->mo, landMine->info->seesound);
P_SetTarget(&landMine->target, player->mo);
P_SetScale(landMine, player->mo->scale);
landMine->destscale = player->mo->destscale;
landMine->angle = player->mo->angle;
landMine->momz = (30 * mapobjectscale * P_MobjFlip(player->mo)) + player->mo->momz;
landMine->color = player->skincolor;
throwmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_FIREDITEM);
P_SetTarget(&throwmo->target, player->mo);
// Ditto:
if (player->mo->eflags & MFE_VERTICALFLIP)
{
throwmo->z -= player->mo->height;
throwmo->eflags |= MFE_VERTICALFLIP;
}
throwmo->movecount = 0; // above player
}
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source)
{
mobj_t *cachenext;
@ -5790,9 +5849,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->powers[pw_flashing] = 0;
}
// Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations.
else if (player->kartstuff[k_spinouttimer] != 0
|| player->kartstuff[k_wipeoutslow] != 0
|| player->kartstuff[k_squishedtimer] != 0)
else if (player->kartstuff[k_spinouttimer] != 0 || player->kartstuff[k_wipeoutslow] != 0)
{
player->powers[pw_flashing] = K_GetKartFlashing(player);
}
@ -5937,22 +5994,18 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_stolentimer])
player->kartstuff[k_stolentimer]--;
if (player->kartstuff[k_squishedtimer])
{
player->kartstuff[k_squishedtimer]--;
if ((player->kartstuff[k_squishedtimer] == 0) && !(player->pflags & PF_NOCLIP))
{
player->mo->flags &= ~MF_NOCLIP;
}
}
if (player->kartstuff[k_justbumped] > 0)
player->kartstuff[k_justbumped]--;
if (player->kartstuff[k_tiregrease])
player->kartstuff[k_tiregrease]--;
if (player->tumbleBounces > 0)
{
if (P_IsObjectOnGround(player->mo) && player->mo->momz * P_MobjFlip(player->mo) <= 0)
K_HandleTumbleBounce(player);
}
// This doesn't go in HUD update because it has potential gameplay ramifications
if (player->karthud[khud_itemblink] && player->karthud[khud_itemblink]-- <= 0)
{
@ -7636,6 +7689,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_UpdateHnextList(player, true);
}
break;
case KITEM_LANDMINE:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->kartstuff[k_itemamount]--;
K_ThrowLandMine(player);
K_PlayAttackTaunt(player->mo);
}
break;
case KITEM_BALLHOG:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
@ -8057,16 +8118,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads
K_KartSpindash(player);
// Squishing
// If a Grow player or a sector crushes you, get flattened instead of being killed.
if (player->kartstuff[k_squishedtimer] > 0)
{
//player->mo->flags |= MF_NOCLIP;
player->mo->momx = 0;
player->mo->momy = 0;
}
// Play the starting countdown sounds
if (player == &players[g_localplayers[0]]) // Don't play louder in splitscreen
{

View file

@ -44,7 +44,7 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics);
void K_DoInstashield(player_t *player);
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_DebtStingPlayer(player_t *player, mobj_t *source);
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);

View file

@ -3412,7 +3412,7 @@ static int lib_kSpinPlayer(lua_State *L)
return 0;
}
static int lib_kSquishPlayer(lua_State *L)
static int lib_kTumblePlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *inflictor = NULL;
@ -3424,7 +3424,7 @@ static int lib_kSquishPlayer(lua_State *L)
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
K_SquishPlayer(player, inflictor, source);
K_TumblePlayer(player, inflictor, source);
return 0;
}
@ -3930,7 +3930,7 @@ static luaL_Reg lib[] = {
{"K_DoInstashield",lib_kDoInstashield},
{"K_SpawnBattlePoints",lib_kSpawnBattlePoints},
{"K_SpinPlayer",lib_kSpinPlayer},
{"K_SquishPlayer",lib_kSquishPlayer},
{"K_TumblePlayer",lib_kTumblePlayer},
{"K_ExplodePlayer",lib_kExplodePlayer},
{"K_TakeBumpersFromPlayer",lib_kTakeBumpersFromPlayer},
{"K_SpawnKartExplosion",lib_kSpawnKartExplosion},

View file

@ -214,6 +214,12 @@ static int player_get(lua_State *L)
LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF);
else if (fastcmp(field,"airtime"))
lua_pushinteger(L, plr->airtime);
else if (fastcmp(field,"tumbleBounces"))
lua_pushinteger(L, plr->tumbleBounces);
else if (fastcmp(field,"tumbleHeight"))
lua_pushinteger(L, plr->tumbleHeight);
else if (fastcmp(field,"tumbleLastBounce"))
lua_pushboolean(L, plr->tumbleLastBounce);
else if (fastcmp(field,"trickpanel"))
lua_pushinteger(L, plr->trickpanel);
else if (fastcmp(field,"trickdelay"))
@ -513,6 +519,12 @@ static int player_set(lua_State *L)
return NOSET;
else if (fastcmp(field,"airtime"))
plr->airtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"tumbleBounces"))
plr->tumbleBounces = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"tumbleHeight"))
plr->tumbleHeight = (UINT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"tumbleLastBounce"))
plr->tumbleLastBounce = luaL_checkboolean(L, 3);
else if (fastcmp(field,"trickpanel"))
plr->trickpanel = luaL_checkinteger(L, 3);
else if (fastcmp(field,"trickdelay"))

View file

@ -481,8 +481,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
// no interaction
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0
|| player->kartstuff[k_squishedtimer] > 0 || P_PlayerInPain(player))
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0 || P_PlayerInPain(player))
return;
// attach to player!
@ -1878,7 +1877,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player) // Player is the target
{
const UINT8 type = (damagetype & DMG_TYPEMASK);
const boolean combo = (type == DMG_EXPLODE); // This damage type can be comboed from other damage
const boolean combo = (type == DMG_EXPLODE || type == DMG_KARMA || type == DMG_TUMBLE); // This damage type can be comboed from other damage
INT16 ringburst = 5;
if (player->pflags & PF_GODMODE)
@ -2014,6 +2013,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
K_KartPainEnergyFling(player);
ringburst = 0;
break;
case DMG_TUMBLE:
K_TumblePlayer(player, inflictor, source);
break;
case DMG_EXPLODE:
case DMG_KARMA:
K_ExplodePlayer(player, inflictor, source);
@ -2021,7 +2023,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
case DMG_WIPEOUT:
if (P_IsDisplayPlayer(player))
P_StartQuake(32<<FRACBITS, 5);
K_SpinPlayer(player, inflictor, source, KSPIN_WIPEOUT);
K_KartPainEnergyFling(player);
break;
@ -2045,7 +2046,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
K_PlayPainSound(player->mo);
if ((type == DMG_EXPLODE || type == DMG_KARMA) || (cv_kartdebughuddrop.value && !modeattacking))
if ((combo == true) || (cv_kartdebughuddrop.value && !modeattacking))
{
K_DropItems(player);
}

View file

@ -467,7 +467,7 @@ typedef struct BasicFF_s
#define DMG_NORMAL 0x00
#define DMG_WIPEOUT 0x01 // Normal, but with extra flashy effects
#define DMG_EXPLODE 0x02
#define DMG_SQUISH 0x03
#define DMG_TUMBLE 0x03
#define DMG_STING 0x04
#define DMG_KARMA 0x05 // Karma Bomb explosion -- works like DMG_EXPLODE, but steals half of their bumpers & deletes the rest
//// Death types - cannot be combined with damage types

View file

@ -730,7 +730,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|| (thing->player && thing->player->kartstuff[k_bubbleblowup]))
&& (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD
|| tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG
|| tmthing->type == MT_SSMINE || tmthing->type == MT_SINK
|| tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK
|| (tmthing->type == MT_PLAYER && thing->target != tmthing)))
{
// see if it went over / under
@ -788,7 +788,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
|| (tmthing->player && tmthing->player->kartstuff[k_bubbleblowup]))
&& (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD
|| thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG
|| thing->type == MT_SSMINE || thing->type == MT_SINK
|| thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK
|| (thing->type == MT_PLAYER && tmthing->target != thing)))
{
// see if it went over / under
@ -933,6 +933,27 @@ static boolean PIT_CheckThing(mobj_t *thing)
return K_MineExplosionCollide(thing, tmthing);
}
if (tmthing->type == MT_LANDMINE)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
return K_LandMineCollide(tmthing, thing);
}
else if (thing->type == MT_LANDMINE)
{
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
return K_LandMineCollide(thing, tmthing);
}
if (tmthing->type == MT_SINK)
{
// see if it went over / under
@ -1214,69 +1235,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false;
}
// Damage other players when invincible
if (tmthing->player && thing->player
// Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person.
&& !(thing->z + thing->height < tmthing->z || thing->z > tmthing->z + tmthing->height))
{
if (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam)
{
if (tmthing->scale > thing->scale + (mapobjectscale/8)) // SRB2kart - Handle squishes first!
{
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SQUISH);
}
else if (thing->scale > tmthing->scale + (mapobjectscale/8))
{
P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH);
}
else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility!
{
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT);
}
else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer])
{
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT);
}
else if ((tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
&& !(thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield!
{
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT);
}
else if ((thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
&& !(tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD))
{
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT);
}
}
}
if (thing->player)
{
// Doesn't matter what gravity player's following! Just do your stuff in YOUR direction only
if (tmthing->eflags & MFE_VERTICALFLIP
&& (tmthing->z + tmthing->height + tmthing->momz < thing->z
|| tmthing->z + tmthing->height + tmthing->momz >= thing->z + thing->height))
;
else if (!(tmthing->eflags & MFE_VERTICALFLIP)
&& (tmthing->z + tmthing->momz > thing->z + thing->height
|| tmthing->z + tmthing->momz <= thing->z))
;
else if (P_IsObjectOnGround(thing)
&& !P_IsObjectOnGround(tmthing) // Don't crush if the monitor is on the ground...
&& (tmthing->flags & MF_SOLID))
{
if (tmthing->flags & (MF_MONITOR|MF_PUSHABLE))
{
// Objects kill you if it falls from above.
if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_CRUSHED);
tmthing->momz = -tmthing->momz/2; // Bounce, just for fun!
// The tmthing->target allows the pusher of the object
// to get the point if he topples it on an opponent.
}
}
if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM)
P_DoFanAndGasJet(tmthing, thing);
}
@ -1304,10 +1264,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->player->kartstuff[k_squishedtimer] || thing->player->kartstuff[k_hyudorotimer]
|| thing->player->kartstuff[k_justbumped] || thing->scale > tmthing->scale + (mapobjectscale/8)
|| tmthing->player->kartstuff[k_squishedtimer] || tmthing->player->kartstuff[k_hyudorotimer]
|| tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (mapobjectscale/8))
if (thing->player->kartstuff[k_hyudorotimer] || tmthing->player->kartstuff[k_hyudorotimer])
{
return true;
}
@ -1341,16 +1298,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->player->trickpanel)
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL);
}
else if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible
{
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL);
}
else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing]))
{
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL);
}
K_KartBouncing(mo1, mo2, zbounce, false);
if (K_KartBouncing(mo1, mo2, zbounce, false))
{
K_PvPTouchDamage(mo1, mo2);
}
}
return true;
@ -1430,22 +1382,13 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
// continue to squish
if (tmthing->player->kartstuff[k_squishedtimer])
{
tmthing->player->kartstuff[k_squishedtimer] = 2*TICRATE;
tmthing->player->powers[pw_flashing] = K_GetKartFlashing(tmthing->player);
return true;
}
// no interaction
if (tmthing->player->powers[pw_flashing] > 0 || tmthing->player->kartstuff[k_hyudorotimer] > 0
|| tmthing->player->kartstuff[k_spinouttimer] > 0) //|| tmthing->player->kartstuff[k_squishedtimer] > 0
if (tmthing->player->powers[pw_flashing] > 0 || tmthing->player->kartstuff[k_hyudorotimer] > 0 || tmthing->player->kartstuff[k_spinouttimer] > 0)
return true;
// collide
if (tmthing->z < thing->z && thing->momz < 0)
K_SquishPlayer(tmthing->player, thing, thing);
P_DamageMobj(tmthing, thing, thing, 1, DMG_TUMBLE);
else
{
if (thing->flags2 & MF2_AMBUSH)

View file

@ -1105,6 +1105,11 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
{
gravityadd = (5*gravityadd)/2;
}
if (mo->player->tumbleBounces > 0)
{
gravityadd = (5*gravityadd)/2;
}
}
else
{
@ -1163,6 +1168,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_BANANA:
case MT_EGGMANITEM:
case MT_SSMINE:
case MT_LANDMINE:
case MT_SINK:
case MT_EMERALD:
if (mo->extravalue2 > 0)
@ -2105,6 +2111,7 @@ boolean P_ZMovement(mobj_t *mo)
case MT_JAWZ_DUD:
case MT_BALLHOG:
case MT_SSMINE:
case MT_LANDMINE:
case MT_BUBBLESHIELDTRAP:
// Remove stuff from death pits.
if (P_CheckDeathPitCollide(mo))
@ -2626,7 +2633,7 @@ void P_PlayerZMovement(mobj_t *mo)
mo->z = mo->floorz;
// Get up if you fell.
if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->kartstuff[k_squishedtimer] == 0)
if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->tumbleBounces == 0)
P_SetPlayerMobjState(mo, S_KART_STILL);
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
@ -4494,7 +4501,8 @@ boolean P_IsKartItem(INT32 type)
type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD ||
type == MT_SSMINE || type == MT_SSMINE_SHIELD ||
type == MT_SINK || type == MT_SINK_SHIELD ||
type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP)
type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP ||
type == MT_LANDMINE)
return true;
else
return false;
@ -5900,6 +5908,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
case MT_ORBINAUT:
case MT_BANANA:
case MT_EGGMANITEM:
case MT_LANDMINE:
case MT_SPB:
if (P_IsObjectOnGround(mobj))
{
@ -6514,6 +6523,25 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|| (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13]))
A_GrenadeRing(mobj);
if (mobj->threshold > 0)
mobj->threshold--;
break;
case MT_LANDMINE:
mobj->friction = ORIG_FRICTION/4;
if (mobj->momx || mobj->momy || mobj->momz)
{
mobj_t *ghost = P_SpawnGhostMobj(mobj);
ghost->colorized = true; // already has color!
}
if (P_IsObjectOnGround(mobj) && mobj->health > 1)
{
S_StartSound(mobj, mobj->info->activesound);
mobj->momx = mobj->momy = 0;
mobj->health = 1;
}
if (mobj->threshold > 0)
mobj->threshold--;
break;
@ -8685,7 +8713,8 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->type == MT_BANANA || mobj->type == MT_EGGMANITEM
|| mobj->type == MT_ORBINAUT || mobj->type == MT_BALLHOG
|| mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD
|| mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP)
|| mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP
|| mobj->type == MT_LANDMINE)
{
if (mobj->health > 0 && P_MobjTouchingSectorSpecial(mobj, 4, 7, true))
{
@ -9066,6 +9095,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
case MT_JAWZ_SHIELD:
case MT_SSMINE:
case MT_SSMINE_SHIELD:
case MT_LANDMINE:
case MT_BALLHOG:
case MT_SINK:
case MT_ROCKETSNEAKER:

View file

@ -266,6 +266,10 @@ static void P_NetArchivePlayers(void)
WRITEINT16(save_p, players[i].karmadelay);
WRITEUINT8(save_p, players[i].eliminated);
WRITEUINT8(save_p, players[i].tumbleBounces);
WRITEUINT16(save_p, players[i].tumbleHeight);
WRITEUINT8(save_p, players[i].tumbleLastBounce);
// respawnvars_t
WRITEUINT8(save_p, players[i].respawn.state);
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].respawn.wp));
@ -461,6 +465,10 @@ static void P_NetUnArchivePlayers(void)
players[i].karmadelay = READINT16(save_p);
players[i].eliminated = (boolean)READUINT8(save_p);
players[i].tumbleBounces = READUINT8(save_p);
players[i].tumbleHeight = READUINT16(save_p);
players[i].tumbleLastBounce = (boolean)READUINT8(save_p);
// respawnvars_t
players[i].respawn.state = READUINT8(save_p);
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save_p);

View file

@ -4829,9 +4829,6 @@ DoneSection2:
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE)
break;
if (player->powers[pw_ignorelatch] & (1<<15))
break;
// Find line #3 tagged to this sector
lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1);

View file

@ -461,7 +461,7 @@ UINT8 P_FindHighestLap(void)
//
boolean P_PlayerInPain(player_t *player)
{
if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer])
if (player->kartstuff[k_spinouttimer] || player->tumbleBounces > 0)
return true;
return false;
@ -2145,18 +2145,41 @@ void P_MovePlayer(player_t *player)
P_3dMovement(player);
// Kart frames
if (player->kartstuff[k_squishedtimer] > 0)
if (player->tumbleBounces > 0)
{
P_SetPlayerMobjState(player->mo, S_KART_SQUISH);
fixed_t playerSpeed = P_AproxDistance(player->mo->momx, player->mo->momy); // maybe momz too?
const UINT8 minSpinSpeed = 4;
UINT8 spinSpeed = max(minSpinSpeed, min(8 + minSpinSpeed, (playerSpeed / player->mo->scale) * 2));
UINT8 rollSpeed = max(1, min(8, player->tumbleHeight / 10));
if (player->tumbleLastBounce == true)
spinSpeed = 2;
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
player->drawangle -= (ANGLE_11hh * spinSpeed);
player->mo->rollangle -= (ANGLE_11hh * rollSpeed);
if (player->tumbleLastBounce == true)
{
if (abs((signed)(player->mo->angle - player->drawangle)) < ANGLE_22h)
player->drawangle = player->mo->angle;
if (abs((signed)player->mo->rollangle) < ANGLE_22h)
player->mo->rollangle = 0;
}
}
else if (player->pflags & PF_SLIDING)
{
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
player->drawangle -= ANGLE_22h;
player->mo->rollangle = 0;
}
else if (player->kartstuff[k_spinouttimer] > 0)
{
INT32 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8));
UINT8 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8));
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
@ -2164,6 +2187,8 @@ void P_MovePlayer(player_t *player)
player->drawangle = player->mo->angle; // Face forward at the end of the animation
else
player->drawangle -= (ANGLE_11hh * speed);
player->mo->rollangle = 0;
}
else if (player->pflags & PF_FAULT)
{
@ -2173,6 +2198,8 @@ void P_MovePlayer(player_t *player)
player->drawangle += ANGLE_11hh;
else
player->drawangle -= ANGLE_11hh;
player->mo->rollangle = 0;
}
else
{
@ -2196,6 +2223,8 @@ void P_MovePlayer(player_t *player)
player->drawangle += a;
}
}
player->mo->rollangle = 0;
}
player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame.
@ -2350,7 +2379,7 @@ void P_MovePlayer(player_t *player)
// Crush test...
if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) && !(player->mo->flags & MF_NOCLIP))
{
if ((netgame || multiplayer) && player->spectator)
if (player->spectator)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators
else
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED);
@ -4257,7 +4286,8 @@ void P_PlayerThink(player_t *player)
// Track airtime
if (P_IsObjectOnGround(player->mo))
{
player->airtime = 0;
if (!P_PlayerInPain(player))
player->airtime = 0;
}
else
{
@ -4519,10 +4549,6 @@ void P_PlayerThink(player_t *player)
else
player->pflags &= ~PF_SPINDOWN;
// IF PLAYER NOT HERE THEN FLASH END IF
if (player->quittime && player->powers[pw_flashing] < K_GetKartFlashing(player) && !player->gotflag)
player->powers[pw_flashing] = K_GetKartFlashing(player);
// Counters, time dependent power ups.
// Time Bonus & Ring Bonus count settings
@ -4541,11 +4567,6 @@ void P_PlayerThink(player_t *player)
else
player->powers[pw_nocontrol] = 0;
if (player->powers[pw_ignorelatch] & ((1<<15)-1) && player->powers[pw_ignorelatch] < UINT16_MAX)
player->powers[pw_ignorelatch]--;
else
player->powers[pw_ignorelatch] = 0;
//pw_super acts as a timer now
if (player->powers[pw_super])
player->powers[pw_super]++;