Readd SPB karma modes, remove every hit rewarding bumpers, allow flashtics again

This commit is contained in:
NepDisk 2024-12-17 17:33:05 -05:00
parent 8dcaba2d43
commit 3622b78b3e
9 changed files with 214 additions and 85 deletions

View file

@ -502,9 +502,10 @@ struct player_t
UINT32 roundscore; // battle score this round
UINT8 emeralds;
UINT8 bumper;
INT32 wanted;
INT16 wanted;
INT16 karmadelay;
tic_t overtimekarma; // time to live in overtime comeback
INT16 karmamode;
INT16 karmapoints;
INT16 spheres;
tic_t spheredigestion;

View file

@ -2234,6 +2234,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
INT32 roulettetype;
INT32 growshrinktimer;
INT32 bumper;
INT32 karmapoints;
INT32 wanted;
boolean songcredit = false;
tic_t spectatorreentry;
tic_t grieftime;
@ -2290,6 +2292,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
itemamount = 0;
growshrinktimer = 0;
bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0);
karmapoints = 0;
wanted = 0;
rings = ((gametyperules & GTR_SPHERES) ? 0 : 10);
spheres = 0;
kickstartaccel = 0;
@ -2335,6 +2339,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
growshrinktimer = 0;
bumper = players[player].bumper;
karmapoints = players[player].karmapoints;
wanted = players[player].wanted;
rings = players[player].rings;
spheres = players[player].spheres;
kickstartaccel = players[player].kickstartaccel;
@ -2444,7 +2450,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
p->growshrinktimer = growshrinktimer;
p->bumper = bumper;
p->karmadelay = comebacktime;
p->overtimekarma = 0;
p->karmapoints = karmapoints;
p->wanted = wanted;
p->eggmanblame = -1;
p->nocontrol = nocontrol;
p->kickstartaccel = kickstartaccel;

View file

@ -233,7 +233,9 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
if ((gametyperules & GTR_BUMPERS) && t2->player->bumper <= 0)
{
return true;
if (t2->player->karmamode || t2->player->karmadelay)
return true;
t2->player->karmamode = 2;
}
else
{

View file

@ -2584,28 +2584,36 @@ static void K_drawKartBumpersOrKarma(void)
}
else
{
INT32 maxbumper = K_StartingBumperCount();
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap);
if (stplyr->bumper > 9 || maxbumper > 9)
if (stplyr->bumper <= 0)
{
UINT8 ln[2];
ln[0] = (stplyr->bumper / 10 % 10);
ln[1] = (stplyr->bumper % 10);
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
ln[0] = ((abs(maxbumper) / 10) % 10);
ln[1] = (abs(maxbumper) % 10);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
V_DrawMappedPatch(fx, fy-1, V_HUDTRANS|splitflags, kp_splitkarmabomb, colormap);
V_DrawString(fx+13, fy+1, V_HUDTRANS|splitflags, va("%d/2", stplyr->karmapoints));
}
else
{
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->bumper) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(maxbumper) % 10]);
INT32 maxbumper = K_StartingBumperCount();
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|splitflags, kp_rankbumper, colormap);
if (stplyr->bumper > 9 || maxbumper > 9)
{
UINT8 ln[2];
ln[0] = (stplyr->bumper / 10 % 10);
ln[1] = (stplyr->bumper % 10);
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
ln[0] = ((abs(maxbumper) / 10) % 10);
ln[1] = (abs(maxbumper) % 10);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
}
else
{
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|splitflags, kp_facenum[(stplyr->bumper) % 10]);
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|splitflags, kp_facenum[(maxbumper) % 10]);
}
}
}
}
@ -2622,17 +2630,22 @@ static void K_drawKartBumpersOrKarma(void)
}
else
{
INT32 maxbumper = K_StartingBumperCount();
if (stplyr->bumper > 9 && maxbumper > 9)
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap);
if (stplyr->bumper <= 0)
{
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_karmasticker, NULL);
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/2", stplyr->karmapoints));
}
else
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap);
{
INT32 maxbumper = K_StartingBumperCount();
if (stplyr->bumper > 9 && maxbumper > 9)
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumperstickerwide, colormap);
else
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|splitflags, kp_bumpersticker, colormap);
if (bossinfo.boss)
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d", stplyr->bumper, maxbumper));
else // TODO BETTER HUD
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|splitflags, va("%d/%d %d", stplyr->bumper, maxbumper, stplyr->overtimekarma / TICRATE));
}
}
}
}

View file

@ -2950,12 +2950,6 @@ UINT16 K_GetKartFlashing(player_t *player)
{
UINT16 tics = flashingtics;
if (gametype == GT_BATTLE)
{
// TODO: gametyperules
return 1;
}
if (player == NULL)
{
return tics;
@ -3484,6 +3478,7 @@ void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
}
player->bumper++;
player->karmapoints = 0;
victim->bumper--;
tookBumpers++;
}
@ -8275,8 +8270,37 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
// First, the really specific, finicky items that function without the item being directly in your item slot.
{
// Karma item dropping
if (ATTACK_IS_DOWN && player->karmamode && !player->karmadelay)
{
mobj_t *newitem;
if (player->karmamode == 1)
{
newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RANDOMITEM);
newitem->threshold = 69; // selected "randomly".
}
else
{
newitem = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM);
if (player->eggmanblame >= 0
&& player->eggmanblame < MAXPLAYERS
&& playeringame[player->eggmanblame]
&& !players[player->eggmanblame].spectator
&& players[player->eggmanblame].mo)
P_SetTarget(&newitem->target, players[player->eggmanblame].mo);
player->eggmanblame = -1;
}
newitem->flags2 = (player->mo->flags2 & MF2_OBJECTFLIP);
newitem->fuse = 15*TICRATE; // selected randomly.
player->karmamode = 0;
player->karmadelay = comebacktime;
S_StartSound(player->mo, sfx_s254);
}
// Ring boosting
if (player->pflags & PF_USERINGS)
else if (player->pflags & PF_USERINGS)
{
if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0)
{

View file

@ -280,6 +280,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!P_CanPickupItem(player, 1))
return;
if ((gametyperules & GTR_BUMPERS) && player->bumper <= 0)
{
if (player->karmamode || player->karmadelay)
return;
player->karmamode = 1;
}
special->momx = special->momy = special->momz = 0;
P_SetTarget(&special->target, toucher);
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
@ -326,6 +333,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (special->target->player->karmadelay > 0)
return;
if (!special->target->player->karmamode)
{
mobj_t *boom;
@ -350,6 +358,84 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
special->target->player->karmadelay = comebacktime;
}
else if (special->target->player->karmamode == 1 && P_CanPickupItem(player, 1))
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
S_StartSound(poof, special->info->seesound);
// Karma fireworks
for (i = 0; i < 5; i++)
{
mobj_t *firework = P_SpawnMobj(special->x, special->y, special->z, MT_KARMAFIREWORK);
firework->momx = (special->target->momx + toucher->momx) / 2;
firework->momy = (special->target->momy + toucher->momy) / 2;
firework->momz = (special->target->momz + toucher->momz) / 2;
P_Thrust(firework, FixedAngle((72*i)<<FRACBITS), P_RandomRange(1,8)*special->scale);
P_SetObjectMomZ(firework, P_RandomRange(1,8)*special->scale, false);
firework->color = special->target->color;
}
special->target->player->karmamode = 0;
special->target->player->karmapoints++;
if (special->target->player->karmapoints >= 2)
K_TakeBumpersFromPlayer(special->target->player, player, 1);
special->target->player->karmadelay = comebacktime;
player->itemroulette = 1;
player->roulettetype = 1;
}
else if (special->target->player->karmamode == 2 && P_CanPickupItem(player, 2))
{
mobj_t *poof = P_SpawnMobj(special->x, special->y, special->z, MT_EXPLODE);
UINT8 ptadd = 1; // No WANTED bonus for tricking
S_StartSound(poof, special->info->seesound);
if (player->bumper == 1) // If you have only one bumper left, and see if it's a 1v1
{
INT32 numingame = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].bumper <= 0)
continue;
numingame++;
}
if (numingame <= 2) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a fake kill
ptadd++;
}
special->target->player->karmamode = 0;
special->target->player->karmapoints += ptadd;
if (ptadd > 1)
special->target->player->karthud[khud_yougotem] = 2*TICRATE;
if (special->target->player->karmapoints >= 2)
K_TakeBumpersFromPlayer(special->target->player, player, 1);
special->target->player->karmadelay = comebacktime;
K_DropItems(player); //K_StripItems(player);
//K_StripOther(player);
player->itemroulette = 1;
player->roulettetype = 2;
if (special->target->player->eggmanblame >= 0
&& special->target->player->eggmanblame < MAXPLAYERS
&& playeringame[special->target->player->eggmanblame]
&& !players[special->target->player->eggmanblame].spectator)
player->eggmanblame = special->target->player->eggmanblame;
else
player->eggmanblame = -1;
special->target->player->eggmanblame = -1;
}
return;
case MT_SPB:
if ((special->target == toucher || special->target == toucher->target) && (special->threshold > 0))
@ -1882,7 +1968,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{
if (gametyperules & GTR_BUMPERS)
{
if (player->bumper <= 0 && player->karmadelay)
if ((player->bumper <= 0 && player->karmadelay) || (player->karmamode == 1))
{
// No bumpers & in WAIT, can't be hurt
K_DoInstashield(player);
@ -1923,51 +2009,32 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// We successfully damaged them! Give 'em some bumpers!
if (type != DMG_STING)
{
UINT8 takeBumpers = 1;
if (damagetype & DMG_STEAL)
{
takeBumpers = 2;
if (type == DMG_KARMA)
{
takeBumpers = player->bumper;
}
}
else
{
if (type == DMG_KARMA)
{
// Take half of their bumpers for karma comeback damage
takeBumpers = max(1, player->bumper / 2);
}
}
if (source && source != player->mo && source->player)
{
K_TryHurtSoundExchange(target, source);
K_BattleAwardHit(source->player, player, inflictor, takeBumpers);
K_TakeBumpersFromPlayer(source->player, player, takeBumpers);
if (type == DMG_KARMA)
{
// Destroy any remainder bumpers from the player for karma comeback damage
K_DestroyBumpers(player, player->bumper);
}
else
{
source->player->overtimekarma += 5*TICRATE;
}
K_BattleAwardHit(source->player, player, inflictor, 1);
if (damagetype & DMG_STEAL)
{
K_CheckBumpers();
K_TakeBumpersFromPlayer(source->player, player, 1);
}
else if (damage & DMG_KARMA)
{
source->player->karmapoints++;
if (source->player->karmapoints >= 2)
{
K_TakeBumpersFromPlayer(source->player, player, 1);
}
else
{
K_DestroyBumpers(player, 1);
}
}
else
{
K_DestroyBumpers(player, 1);
}
}
else
{
K_DestroyBumpers(player, takeBumpers);
}
}

View file

@ -7558,12 +7558,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
}
break;
case MT_KARMAHITBOX:
case MT_KARMAHITBOX:
{
statenum_t state = (mobj->state-states);
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|| (gametype == GT_RACE || mobj->target->player->bumper))
|| (gametyperules & GTR_CIRCUIT || mobj->target->player->bumper))
{
P_RemoveMobj(mobj);
return false;
@ -7577,13 +7577,17 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->color = mobj->target->color;
mobj->colorized = true;
mobj->radius = 24*mobj->target->scale;
// Give items an item-sized hitbox
if (mobj->target->player->karmamode == 1)
mobj->radius = 48*mobj->target->scale;
else
mobj->radius = 24*mobj->target->scale;
mobj->height = 2*mobj->radius;
if (mobj->target->player->karmadelay > 0)
{
if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)
P_SetMobjState(mobj, S_PLAYERBOMB1);
if (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19)
P_SetMobjState(mobj, mobj->info->spawnstate);
if (mobj->target->player->karmadelay < TICRATE && (leveltime & 1))
mobj->renderflags &= ~RF_DONTDRAW;
else
@ -7591,8 +7595,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
else
{
if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)
P_SetMobjState(mobj, S_PLAYERBOMB1);
if (!mobj->target->player->karmamode
&& (state < mobj->info->spawnstate || state > mobj->info->spawnstate+19))
P_SetMobjState(mobj, mobj->info->spawnstate);
else if (mobj->target->player->karmamode == 1
&& state != mobj->info->seestate)
P_SetMobjState(mobj, mobj->info->seestate);
else if (mobj->target->player->karmamode == 2
&& state != mobj->info->painstate)
P_SetMobjState(mobj, mobj->info->painstate);
if (mobj->target->player->flashing && (leveltime & 1))
mobj->renderflags |= RF_DONTDRAW;

View file

@ -333,7 +333,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEUINT8(save->p, players[i].emeralds);
WRITEUINT8(save->p, players[i].bumper);
WRITEINT16(save->p, players[i].karmadelay);
WRITEUINT32(save->p, players[i].overtimekarma);
WRITEINT16(save->p, players[i].karmamode);
WRITEINT16(save->p, players[i].karmapoints);
WRITEINT16(save->p, players[i].wanted);
WRITEINT16(save->p, players[i].spheres);
WRITEUINT32(save->p, players[i].spheredigestion);
@ -623,7 +625,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].emeralds = READUINT8(save->p);
players[i].bumper = READUINT8(save->p);
players[i].karmadelay = READINT16(save->p);
players[i].overtimekarma = READUINT32(save->p);
players[i].karmamode = READINT16(save->p);
players[i].karmapoints = READINT16(save->p);
players[i].wanted = READINT16(save->p);
players[i].spheres = READINT16(save->p);
players[i].spheredigestion = READUINT32(save->p);

View file

@ -4487,7 +4487,7 @@ void P_PlayerThink(player_t *player)
|| (player->pflags & PF_NOCONTEST) // NO CONTEST explosion
|| ((gametyperules & GTR_BUMPERS) && player->bumper <= 0 && player->karmadelay)))
{
if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player)
if (player->flashing > 0 && player->flashing < K_GetKartFlashing(player)
&& (leveltime & 1))
player->mo->renderflags |= RF_DONTDRAW;
else