mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-03 13:42:31 +00:00
Merge remote-tracking branch 'origin/bumpers-ARE-health'
This commit is contained in:
commit
1f70b9c63c
22 changed files with 348 additions and 441 deletions
|
|
@ -3374,7 +3374,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
|
|||
if (!P_IsObjectOnGround(players[respawnplayer].mo))
|
||||
return;
|
||||
|
||||
K_DoIngameRespawn(&players[respawnplayer]);
|
||||
P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
demo_extradata[playernum] |= DXD_RESPAWN;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ struct player_t
|
|||
UINT16 spinouttimer; // Spin-out from a banana peel or oil slick (was "pw_bananacam")
|
||||
UINT8 spinouttype; // Determines the mode of spinout/wipeout, see kartspinoutflags_t
|
||||
UINT8 instashield; // Instashield no-damage animation timer
|
||||
INT32 invulnhitlag; // Numbers of tics of hitlag added this tic for "potential" damage -- not real damage
|
||||
INT32 nullHitlag; // Numbers of tics of hitlag that will ultimately be ignored by subtracting from hitlag
|
||||
UINT8 wipeoutslow; // Timer before you slowdown when getting wiped out
|
||||
UINT8 justbumped; // Prevent players from endlessly bumping into each other
|
||||
UINT8 tumbleBounces;
|
||||
|
|
@ -602,9 +602,7 @@ struct player_t
|
|||
|
||||
UINT32 roundscore; // battle score this round
|
||||
UINT8 emeralds;
|
||||
UINT8 bumpers;
|
||||
INT16 karmadelay;
|
||||
tic_t overtimekarma; // time to live in overtime comeback
|
||||
INT16 spheres;
|
||||
tic_t spheredigestion;
|
||||
|
||||
|
|
@ -643,8 +641,10 @@ struct player_t
|
|||
|
||||
INT16 lastsidehit, lastlinehit;
|
||||
|
||||
// These track how many things tried to damage you, not
|
||||
// whether you actually took damage.
|
||||
// TimesHit tracks how many times something tried to
|
||||
// damage you or how many times you tried to damage
|
||||
// something else. It does not track whether damage was
|
||||
// actually dealt.
|
||||
UINT8 timeshit; // times hit this tic
|
||||
UINT8 timeshitprev; // times hit before
|
||||
// That's TIMES HIT, not TIME SHIT, you doofus! -- in memoriam
|
||||
|
|
|
|||
|
|
@ -5730,7 +5730,7 @@ const char *const MOBJFLAG2_LIST[] = {
|
|||
"JUSTATTACKED", // can be pushed by other moving mobjs
|
||||
"FIRING", // turret fire
|
||||
"SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
|
||||
"\x01", // free: 1<<20 (name un-matchable)
|
||||
"ALREADYHIT", // This object was already damaged THIS tic, resets even during hitlag
|
||||
"STRONGBOX", // Flag used for "strong" random monitors.
|
||||
"OBJECTFLIP", // Flag for objects that always have flipped gravity.
|
||||
"SKULLFLY", // Special handling: skull in flight.
|
||||
|
|
|
|||
17
src/g_demo.c
17
src/g_demo.c
|
|
@ -95,7 +95,8 @@ static struct {
|
|||
|
||||
// EZT_ITEMDATA
|
||||
SINT8 itemtype;
|
||||
UINT8 itemamount, bumpers;
|
||||
UINT8 itemamount;
|
||||
INT32 health;
|
||||
|
||||
// EZT_STATDATA
|
||||
UINT8 skinid, kartspeed, kartweight;
|
||||
|
|
@ -355,7 +356,7 @@ void G_ReadDemoExtraData(void)
|
|||
if (players[p].mo)
|
||||
{
|
||||
// Is this how this should work..?
|
||||
K_DoIngameRespawn(&players[p]);
|
||||
P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_DEATHPIT);
|
||||
}
|
||||
}
|
||||
if (extradata & DXD_WEAPONPREF)
|
||||
|
|
@ -813,13 +814,13 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
|||
if (ghost->player && (
|
||||
ghostext[playernum].itemtype != ghost->player->itemtype ||
|
||||
ghostext[playernum].itemamount != ghost->player->itemamount ||
|
||||
ghostext[playernum].bumpers != ghost->player->bumpers
|
||||
ghostext[playernum].health < ghost->health
|
||||
))
|
||||
{
|
||||
ghostext[playernum].flags |= EZT_ITEMDATA;
|
||||
ghostext[playernum].itemtype = ghost->player->itemtype;
|
||||
ghostext[playernum].itemamount = ghost->player->itemamount;
|
||||
ghostext[playernum].bumpers = ghost->player->bumpers;
|
||||
ghostext[playernum].health = ghost->health;
|
||||
}
|
||||
|
||||
if (ghost->player && (
|
||||
|
|
@ -881,7 +882,7 @@ void G_WriteGhostTic(mobj_t *ghost, INT32 playernum)
|
|||
{
|
||||
WRITESINT8(demobuf.p, ghostext[playernum].itemtype);
|
||||
WRITEUINT8(demobuf.p, ghostext[playernum].itemamount);
|
||||
WRITEUINT8(demobuf.p, ghostext[playernum].bumpers);
|
||||
WRITEINT32(demobuf.p, ghostext[playernum].health);
|
||||
}
|
||||
if (ghostext[playernum].flags & EZT_STATDATA)
|
||||
{
|
||||
|
|
@ -1064,7 +1065,7 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
{
|
||||
ghostext[playernum].itemtype = READSINT8(demobuf.p);
|
||||
ghostext[playernum].itemamount = READUINT8(demobuf.p);
|
||||
ghostext[playernum].bumpers = READUINT8(demobuf.p);
|
||||
ghostext[playernum].health = READINT32(demobuf.p);
|
||||
}
|
||||
if (xziptic & EZT_STATDATA)
|
||||
{
|
||||
|
|
@ -1134,7 +1135,7 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
|
||||
if (players[playernum].itemtype != ghostext[playernum].itemtype
|
||||
|| players[playernum].itemamount != ghostext[playernum].itemamount
|
||||
|| players[playernum].bumpers != ghostext[playernum].bumpers)
|
||||
|| testmo->health < ghostext[playernum].health)
|
||||
{
|
||||
if (demosynced)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced (item/bumpers)!\n"));
|
||||
|
|
@ -1142,7 +1143,7 @@ void G_ConsGhostTic(INT32 playernum)
|
|||
|
||||
players[playernum].itemtype = ghostext[playernum].itemtype;
|
||||
players[playernum].itemamount = ghostext[playernum].itemamount;
|
||||
players[playernum].bumpers = ghostext[playernum].bumpers;
|
||||
testmo->health = ghostext[playernum].health;
|
||||
}
|
||||
|
||||
if (players[playernum].kartspeed != ghostext[playernum].kartspeed
|
||||
|
|
|
|||
14
src/g_game.c
14
src/g_game.c
|
|
@ -1890,13 +1890,6 @@ boolean G_CouldView(INT32 playernum)
|
|||
if (( player->pflags & PF_NOCONTEST ))
|
||||
return false;
|
||||
|
||||
// I don't know if we want this actually, but I'll humor the suggestion anyway
|
||||
if ((gametyperules & GTR_BUMPERS) && !demo.playback)
|
||||
{
|
||||
if (player->bumpers <= 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
// SRB2Kart: we have no team-based modes, YET...
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
|
|
@ -2439,7 +2432,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT32 itemtype;
|
||||
INT32 itemamount;
|
||||
INT32 growshrinktimer;
|
||||
INT32 bumper;
|
||||
boolean songcredit = false;
|
||||
UINT16 nocontrol;
|
||||
INT32 khudfault;
|
||||
|
|
@ -2511,7 +2503,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
itemtype = 0;
|
||||
itemamount = 0;
|
||||
growshrinktimer = 0;
|
||||
bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0);
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
{
|
||||
rings = 0;
|
||||
|
|
@ -2556,7 +2547,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
else
|
||||
growshrinktimer = 0;
|
||||
|
||||
bumper = players[player].bumpers;
|
||||
rings = players[player].rings;
|
||||
spheres = players[player].spheres;
|
||||
kickstartaccel = players[player].kickstartaccel;
|
||||
|
|
@ -2654,9 +2644,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->itemtype = itemtype;
|
||||
p->itemamount = itemamount;
|
||||
p->growshrinktimer = growshrinktimer;
|
||||
p->bumpers = bumper;
|
||||
p->karmadelay = comebacktime;
|
||||
p->overtimekarma = 0;
|
||||
p->karmadelay = 0;
|
||||
p->eggmanblame = -1;
|
||||
p->lastdraft = -1;
|
||||
p->karthud[khud_fault] = khudfault;
|
||||
|
|
|
|||
|
|
@ -23907,7 +23907,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_NOCLIP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ UINT8 numtargets = 0; // Capsules busted
|
|||
INT32 K_StartingBumperCount(void)
|
||||
{
|
||||
if (battlecapsules)
|
||||
return 1; // always 1 hit in Break the Capsules
|
||||
return 0; // always 1 hit in Break the Capsules
|
||||
|
||||
return cv_kartbumpers.value;
|
||||
}
|
||||
|
|
@ -95,8 +95,6 @@ void K_CheckBumpers(void)
|
|||
UINT8 nobumpers = 0;
|
||||
UINT8 eliminated = 0;
|
||||
|
||||
const boolean singleplayer = (battlecapsules || bossinfo.valid);
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
return;
|
||||
|
||||
|
|
@ -113,7 +111,7 @@ void K_CheckBumpers(void)
|
|||
|
||||
numingame++;
|
||||
|
||||
if (players[i].bumpers <= 0) // if you don't have any bumpers, you're probably not a winner
|
||||
if (!P_MobjWasRemoved(players[i].mo) && players[i].mo->health <= 0) // if you don't have any bumpers, you're probably not a winner
|
||||
{
|
||||
nobumpers++;
|
||||
}
|
||||
|
|
@ -124,7 +122,7 @@ void K_CheckBumpers(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (singleplayer
|
||||
if (K_Cooperative()
|
||||
? nobumpers > 0 && nobumpers >= numingame
|
||||
: eliminated >= numingame - 1)
|
||||
{
|
||||
|
|
@ -135,7 +133,7 @@ void K_CheckBumpers(void)
|
|||
if (players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (singleplayer)
|
||||
if (K_Cooperative())
|
||||
players[i].pflags |= PF_NOCONTEST;
|
||||
|
||||
P_DoPlayerExit(&players[i]);
|
||||
|
|
@ -170,7 +168,7 @@ void K_CheckEmeralds(player_t *player)
|
|||
return;
|
||||
}
|
||||
|
||||
player->roundscore++; // lol
|
||||
player->roundscore = 100; // lmao
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
|
|
@ -179,11 +177,6 @@ void K_CheckEmeralds(player_t *player)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (&players[i] == player)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
P_DoPlayerExit(&players[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -319,6 +312,21 @@ static inline boolean IsOnInterval(tic_t interval)
|
|||
return ((leveltime - starttime) % interval) == 0;
|
||||
}
|
||||
|
||||
static UINT32 CountEmeraldsSpawned(const mobj_t *mo)
|
||||
{
|
||||
switch (mo->type)
|
||||
{
|
||||
case MT_EMERALD:
|
||||
return mo->extravalue1;
|
||||
|
||||
case MT_MONITOR:
|
||||
return Obj_MonitorGetEmerald(mo);
|
||||
|
||||
default:
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void K_RunPaperItemSpawners(void)
|
||||
{
|
||||
const boolean overtime = (battleovertime.enabled >= 10*TICRATE);
|
||||
|
|
@ -362,7 +370,7 @@ void K_RunPaperItemSpawners(void)
|
|||
emeraldsSpawned |= players[i].emeralds;
|
||||
|
||||
if ((players[i].exiting > 0 || (players[i].pflags & PF_ELIMINATED))
|
||||
|| ((gametyperules & GTR_BUMPERS) && players[i].bumpers <= 0))
|
||||
|| ((gametyperules & GTR_BUMPERS) && !P_MobjWasRemoved(players[i].mo) && players[i].mo->health <= 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -382,10 +390,7 @@ void K_RunPaperItemSpawners(void)
|
|||
|
||||
mo = (mobj_t *)th;
|
||||
|
||||
if (mo->type == MT_EMERALD)
|
||||
{
|
||||
emeraldsSpawned |= mo->extravalue1;
|
||||
}
|
||||
emeraldsSpawned |= CountEmeraldsSpawned(mo);
|
||||
}
|
||||
|
||||
if (canmakeemeralds)
|
||||
|
|
@ -444,15 +449,7 @@ void K_RunPaperItemSpawners(void)
|
|||
|
||||
mo = (mobj_t *)th;
|
||||
|
||||
if (mo->type == MT_EMERALD)
|
||||
{
|
||||
emeraldsSpawned |= mo->extravalue1;
|
||||
}
|
||||
|
||||
if (mo->type == MT_MONITOR)
|
||||
{
|
||||
emeraldsSpawned |= Obj_MonitorGetEmerald(mo);
|
||||
}
|
||||
emeraldsSpawned |= CountEmeraldsSpawned(mo);
|
||||
|
||||
if (mo->type != MT_PAPERITEMSPOT)
|
||||
continue;
|
||||
|
|
@ -738,16 +735,20 @@ void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj)
|
|||
|
||||
void K_SpawnPlayerBattleBumpers(player_t *p)
|
||||
{
|
||||
if (!p->mo || p->bumpers <= 0)
|
||||
const UINT8 bumpers = K_Bumpers(p);
|
||||
|
||||
if (bumpers <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
INT32 i;
|
||||
angle_t diff = FixedAngle(360*FRACUNIT/p->bumpers);
|
||||
angle_t diff = FixedAngle(360*FRACUNIT / bumpers);
|
||||
angle_t newangle = p->mo->angle;
|
||||
mobj_t *bump;
|
||||
|
||||
for (i = 0; i < p->bumpers; i++)
|
||||
for (i = 0; i < bumpers; i++)
|
||||
{
|
||||
bump = P_SpawnMobjFromMobj(p->mo,
|
||||
P_ReturnThrustX(p->mo, newangle + ANGLE_180, 64*FRACUNIT),
|
||||
|
|
@ -784,21 +785,49 @@ void K_BattleInit(boolean singleplayercontext)
|
|||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
INT32 maxbumpers = K_StartingBumperCount();
|
||||
const INT32 startingHealth = K_BumpersToHealth(K_StartingBumperCount());
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
players[i].bumpers = maxbumpers;
|
||||
|
||||
if (players[i].mo)
|
||||
{
|
||||
players[i].mo->health = maxbumpers;
|
||||
players[i].mo->health = startingHealth;
|
||||
}
|
||||
|
||||
K_SpawnPlayerBattleBumpers(players+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 K_Bumpers(player_t *player)
|
||||
{
|
||||
if ((gametyperules & GTR_BUMPERS) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (player->mo->health < 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (player->mo->health > UINT8_MAX)
|
||||
{
|
||||
return UINT8_MAX;
|
||||
}
|
||||
|
||||
return (player->mo->health - 1);
|
||||
}
|
||||
|
||||
INT32 K_BumpersToHealth(UINT8 bumpers)
|
||||
{
|
||||
return (bumpers + 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ void K_RunBattleOvertime(void);
|
|||
void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj);
|
||||
void K_SpawnPlayerBattleBumpers(player_t *p);
|
||||
void K_BattleInit(boolean singleplayercontext);
|
||||
UINT8 K_Bumpers(player_t *player);
|
||||
INT32 K_BumpersToHealth(UINT8 bumpers);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
{
|
||||
boolean damageitem = false;
|
||||
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
|
|
@ -133,9 +130,6 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
// Push fakes out of other item boxes
|
||||
if (t2->type == MT_RANDOMITEM || t2->type == MT_EGGMANITEM)
|
||||
{
|
||||
|
|
@ -154,14 +148,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (!P_CanPickupItem(t2->player, 2))
|
||||
return true;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && t2->player->bumpers <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
K_StartEggmanRoulette(t2->player);
|
||||
}
|
||||
K_StartEggmanRoulette(t2->player);
|
||||
|
||||
if (t2->player->flamedash && t2->player->itemtype == KITEM_FLAMESHIELD)
|
||||
{
|
||||
|
|
@ -182,10 +169,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t1->target && t1->target->player)
|
||||
{
|
||||
if ((gametyperules & GTR_CIRCUIT) || t1->target->player->bumpers > 0)
|
||||
t2->player->eggmanblame = t1->target->player-players;
|
||||
else
|
||||
t2->player->eggmanblame = t2->player-players;
|
||||
t2->player->eggmanblame = t1->target->player - players;
|
||||
|
||||
if (t1->target->hnext == t1)
|
||||
{
|
||||
|
|
@ -323,6 +307,10 @@ tic_t K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin)
|
|||
// Set this flag to ensure that the inital action won't be triggered twice.
|
||||
actor->flags2 |= MF2_DEBRIS;
|
||||
|
||||
// Set this flag to ensure the hitbox timer doesn't get extended with every player hit
|
||||
actor->flags |= MF_NOHITLAGFORME;
|
||||
actor->hitlag = 0; // same deal
|
||||
|
||||
if (!spin)
|
||||
{
|
||||
if (minehitlag == 0)
|
||||
|
|
@ -340,9 +328,6 @@ tic_t K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin)
|
|||
|
||||
boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
|
|
@ -394,9 +379,6 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
|
|
@ -475,9 +457,6 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2)
|
|||
{
|
||||
mobj_t *draggeddroptarget = (t1->type == MT_DROPTARGET_SHIELD) ? t1->target : NULL;
|
||||
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (t1->target == t2->target)) && ((t1->threshold > 0 && t2->type == MT_PLAYER) || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
|
|
@ -688,6 +667,17 @@ void K_LightningShieldAttack(mobj_t *actor, fixed_t size)
|
|||
|
||||
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (t1->type == MT_PLAYER)
|
||||
{
|
||||
// Bubble Shield already has a hitbox, and it gets
|
||||
// teleported every tic so the Bubble itself will
|
||||
// always make contact with other objects.
|
||||
//
|
||||
// Therefore, we don't need a second, smaller hitbox
|
||||
// on the player. It'll just cause unwanted hitlag.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t2->type == MT_PLAYER)
|
||||
{
|
||||
// Counter desyncs
|
||||
|
|
@ -707,8 +697,13 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
}
|
||||
|
||||
// Player Damage
|
||||
P_DamageMobj(t2, ((t1->type == MT_BUBBLESHIELD) ? t1->target : t1), t1, 1, DMG_NORMAL|DMG_WOMBO);
|
||||
S_StartSound(t1, sfx_s3k44);
|
||||
P_DamageMobj(t2, t1->target, t1, 1, DMG_NORMAL|DMG_WOMBO);
|
||||
|
||||
if (t2->player->timeshit > t2->player->timeshitprev)
|
||||
{
|
||||
// Don't play from t1 else it gets cut out... for some reason.
|
||||
S_StartSound(t2, sfx_s3k44);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -738,9 +733,6 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
|
||||
return true;
|
||||
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
return true;
|
||||
|
||||
|
|
|
|||
62
src/k_hud.c
62
src/k_hud.c
|
|
@ -1995,10 +1995,12 @@ static boolean K_drawKartPositionFaces(void)
|
|||
|
||||
if (LUA_HudEnabled(hud_battlebumpers))
|
||||
{
|
||||
if ((gametyperules & GTR_BUMPERS) && players[rankplayer[i]].bumpers > 0)
|
||||
const UINT8 bumpers = K_Bumpers(&players[rankplayer[i]]);
|
||||
|
||||
if (bumpers > 0)
|
||||
{
|
||||
V_DrawMappedPatch(bumperx-2, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[0], colormap);
|
||||
for (j = 1; j < players[rankplayer[i]].bumpers; j++)
|
||||
for (j = 1; j < bumpers; j++)
|
||||
{
|
||||
bumperx += 5;
|
||||
V_DrawMappedPatch(bumperx, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[1], colormap);
|
||||
|
|
@ -2023,7 +2025,7 @@ static boolean K_drawKartPositionFaces(void)
|
|||
if (i == strank)
|
||||
V_DrawScaledPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_facehighlight[(leveltime / 4) % 8]);
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && players[rankplayer[i]].bumpers <= 0)
|
||||
if ((gametyperules & GTR_BUMPERS) && (players[rankplayer[i]].pflags & PF_ELIMINATED))
|
||||
V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_ranknobumpers);
|
||||
else
|
||||
{
|
||||
|
|
@ -2356,7 +2358,7 @@ void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, IN
|
|||
if (tab[i].num == whiteplayer)
|
||||
V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]);
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && players[tab[i].num].bumpers <= 0)
|
||||
if ((gametyperules & GTR_BUMPERS) && (players[tab[i].num].pflags & PF_ELIMINATED))
|
||||
V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers);
|
||||
else
|
||||
{
|
||||
|
|
@ -2866,14 +2868,16 @@ static void K_drawKartBumpersOrKarma(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
INT32 maxbumper = K_StartingBumperCount();
|
||||
const INT32 maxbumper = K_StartingBumperCount();
|
||||
const UINT8 bumpers = K_Bumpers(stplyr);
|
||||
|
||||
V_DrawMappedPatch(fx+1, fy-2, V_HUDTRANS|V_SLIDEIN|splitflags, kp_rankbumper, colormap);
|
||||
|
||||
if (stplyr->bumpers > 9 || maxbumper > 9)
|
||||
if (bumpers > 9 || maxbumper > 9)
|
||||
{
|
||||
UINT8 ln[2];
|
||||
ln[0] = (stplyr->bumpers / 10 % 10);
|
||||
ln[1] = (stplyr->bumpers % 10);
|
||||
ln[0] = (bumpers / 10 % 10);
|
||||
ln[1] = (bumpers % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
|
||||
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
|
||||
|
|
@ -2886,7 +2890,7 @@ static void K_drawKartBumpersOrKarma(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->bumpers) % 10]);
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(bumpers) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(maxbumper) % 10]);
|
||||
}
|
||||
}
|
||||
|
|
@ -2903,17 +2907,15 @@ static void K_drawKartBumpersOrKarma(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
INT32 maxbumper = K_StartingBumperCount();
|
||||
const INT32 maxbumper = K_StartingBumperCount();
|
||||
const UINT8 bumpers = K_Bumpers(stplyr);
|
||||
|
||||
if (stplyr->bumpers > 9 && maxbumper > 9)
|
||||
if (bumpers > 9 && maxbumper > 9)
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumperstickerwide, colormap);
|
||||
else
|
||||
V_DrawMappedPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_bumpersticker, colormap);
|
||||
|
||||
if (gametyperules & GTR_KARMA) // TODO BETTER HUD
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d %d", stplyr->bumpers, maxbumper, stplyr->overtimekarma / TICRATE));
|
||||
else
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", stplyr->bumpers, maxbumper));
|
||||
V_DrawKartString(LAPS_X+47, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", bumpers, maxbumper));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3366,12 +3368,6 @@ static void K_drawKartNameTags(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && (ntplayer->bumpers <= 0))
|
||||
{
|
||||
// Dead in Battle
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!P_CheckSight(stplyr->mo, ntplayer->mo))
|
||||
{
|
||||
// Can't see
|
||||
|
|
@ -3644,6 +3640,10 @@ static void K_drawKartMinimap(void)
|
|||
if (!players[i].mo || players[i].spectator || !players[i].mo->skin || players[i].exiting)
|
||||
continue;
|
||||
|
||||
// This player is out of the game!
|
||||
if ((gametyperules & GTR_BUMPERS) && (players[i].pflags & PF_ELIMINATED))
|
||||
continue;
|
||||
|
||||
if (i == displayplayers[0] || i == displayplayers[1] || i == displayplayers[2] || i == displayplayers[3])
|
||||
{
|
||||
// Draw display players on top of everything else
|
||||
|
|
@ -3651,10 +3651,6 @@ static void K_drawKartMinimap(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
// Now we know it's not a display player, handle non-local player exceptions.
|
||||
if ((gametyperules & GTR_BUMPERS) && players[i].bumpers <= 0)
|
||||
continue;
|
||||
|
||||
if (players[i].hyudorotimer > 0)
|
||||
{
|
||||
if (!((players[i].hyudorotimer < TICRATE/2
|
||||
|
|
@ -3866,19 +3862,22 @@ static void K_drawKartFinish(boolean finish)
|
|||
|
||||
//else -- 1/2p, scrolling FINISH
|
||||
{
|
||||
INT32 x, xval, ox, interpx;
|
||||
INT32 x, xval, ox, interpx, pwidth;
|
||||
|
||||
x = ((vid.width<<FRACBITS)/vid.dupx);
|
||||
xval = (SHORT(kptodraw[pnum]->width)<<FRACBITS);
|
||||
x = ((TICRATE - timer)*(xval > x ? xval : x))/TICRATE;
|
||||
ox = ((TICRATE - (timer - 1))*(xval > x ? xval : x))/TICRATE;
|
||||
|
||||
pwidth = max(xval, x);
|
||||
|
||||
x = ((TICRATE - timer) * pwidth) / TICRATE;
|
||||
ox = ((TICRATE - (timer - 1)) * pwidth) / TICRATE;
|
||||
|
||||
interpx = R_InterpolateFixed(ox, x);
|
||||
|
||||
if (r_splitscreen && stplyr == &players[displayplayers[1]])
|
||||
interpx = -interpx;
|
||||
|
||||
V_DrawFixedPatch(interpx + (STCD_X<<FRACBITS) - (xval>>1),
|
||||
V_DrawFixedPatch(interpx + (STCD_X<<FRACBITS) - (pwidth / 2),
|
||||
(STCD_Y<<FRACBITS) - (SHORT(kptodraw[pnum]->height)<<(FRACBITS-1)),
|
||||
FRACUNIT,
|
||||
splitflags, kptodraw[pnum], NULL);
|
||||
|
|
@ -4160,7 +4159,7 @@ static void K_drawBattleFullscreen(void)
|
|||
|
||||
K_drawKartFinish(true);
|
||||
}
|
||||
else if (stplyr->bumpers <= 0 && stplyr->karmadelay && !stplyr->spectator && drawcomebacktimer)
|
||||
else if (stplyr->karmadelay && !stplyr->spectator && drawcomebacktimer)
|
||||
{
|
||||
UINT16 t = stplyr->karmadelay/(10*TICRATE);
|
||||
INT32 txoff, adjust = (r_splitscreen > 1) ? 4 : 6; // normal string is 8, kart string is 12, half of that for ease
|
||||
|
|
@ -4894,8 +4893,7 @@ void K_drawKartHUD(void)
|
|||
|
||||
battlefullscreen = (!(gametyperules & GTR_CIRCUIT)
|
||||
&& (stplyr->exiting
|
||||
|| ((gametyperules & GTR_BUMPERS) && (stplyr->bumpers <= 0)
|
||||
&& ((gametyperules & GTR_KARMA) && (stplyr->karmadelay > 0))
|
||||
|| (((gametyperules & GTR_KARMA) && (stplyr->karmadelay > 0))
|
||||
&& !(stplyr->pflags & PF_ELIMINATED)
|
||||
&& stplyr->playerstate == PST_LIVE)));
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
#include "core/static_vec.hpp"
|
||||
|
||||
#include "k_battle.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_hud.h"
|
||||
#include "k_kart.h"
|
||||
#include "k_objects.h"
|
||||
#include "m_fixed.h"
|
||||
#include "p_local.h"
|
||||
|
|
@ -314,7 +314,7 @@ bool is_player_tracking_target(player_t *player = stplyr)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (battlecapsules || bossinfo.valid)
|
||||
if (K_Cooperative())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -338,6 +338,23 @@ bool is_player_tracking_target(player_t *player = stplyr)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (player->emeralds != 0 && K_IsPlayerWanted(stplyr))
|
||||
{
|
||||
// The player who is about to win because of emeralds
|
||||
// gets a TARGET on them
|
||||
if (K_NumEmeralds(player) == 6) // 6 out of 7
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// WANTED player sees TARGETs on players holding
|
||||
// emeralds
|
||||
if (K_IsPlayerWanted(stplyr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return K_IsPlayerWanted(player);
|
||||
}
|
||||
|
||||
|
|
|
|||
188
src/k_kart.c
188
src/k_kart.c
|
|
@ -374,9 +374,6 @@ boolean K_IsPlayerLosing(player_t *player)
|
|||
if (battlecapsules && numtargets == 0)
|
||||
return true; // Didn't even TRY?
|
||||
|
||||
if (battlecapsules || (gametyperules & GTR_BOSS))
|
||||
return (player->bumpers <= 0); // anything short of DNF is COOL
|
||||
|
||||
if (player->position == 1)
|
||||
return false;
|
||||
|
||||
|
|
@ -3262,11 +3259,6 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberb
|
|||
{
|
||||
finalspeed = K_GetKartSpeedFromStat(player->kartspeed);
|
||||
|
||||
if (gametyperules & GTR_BUMPERS && player->bumpers <= 0)
|
||||
{
|
||||
finalspeed = 3 * finalspeed / 2;
|
||||
}
|
||||
|
||||
if (player->spheres > 0)
|
||||
{
|
||||
fixed_t sphereAdd = (FRACUNIT/40); // 100% at max
|
||||
|
|
@ -3326,12 +3318,6 @@ fixed_t K_GetKartAccel(player_t *player)
|
|||
return FixedMul(k_accel, FRACUNIT / 4);
|
||||
}
|
||||
|
||||
// karma bomb gets 2x acceleration
|
||||
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
|
||||
{
|
||||
k_accel *= 2;
|
||||
}
|
||||
|
||||
// Marble Garden Top gets 1200% accel
|
||||
if (player->curshield == KSHIELD_TOP)
|
||||
{
|
||||
|
|
@ -3647,7 +3633,7 @@ void K_DoPowerClash(player_t *t1, player_t *t2) {
|
|||
P_SetScale(clash, 3*clash->destscale/2);
|
||||
}
|
||||
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved)
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 damage)
|
||||
{
|
||||
UINT8 points = 1;
|
||||
boolean trapItem = false;
|
||||
|
|
@ -3685,7 +3671,7 @@ void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UIN
|
|||
}
|
||||
else if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
if ((victim->bumpers > 0) && (victim->bumpers <= bumpersRemoved))
|
||||
if ((victim->mo->health > 0) && (victim->mo->health <= damage))
|
||||
{
|
||||
// +2 points for finishing off a player
|
||||
points = 2;
|
||||
|
|
@ -4330,81 +4316,22 @@ void K_DebtStingPlayer(player_t *player, mobj_t *source)
|
|||
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
|
||||
}
|
||||
|
||||
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers)
|
||||
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
|
||||
{
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
// Bumpers aren't being used
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: replace all console text print-outs with a real visual
|
||||
|
||||
if (player->bumpers > 0 && prevBumpers == 0)
|
||||
{
|
||||
K_DoInvincibility(player, 8 * TICRATE);
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
|
||||
}
|
||||
}
|
||||
else if (player->bumpers == 0 && prevBumpers > 0)
|
||||
{
|
||||
if (battlecapsules || bossinfo.valid)
|
||||
{
|
||||
player->pflags |= (PF_NOCONTEST|PF_ELIMINATED);
|
||||
}
|
||||
}
|
||||
|
||||
K_CalculateBattleWanted();
|
||||
K_CheckBumpers();
|
||||
}
|
||||
|
||||
UINT8 K_DestroyBumpers(player_t *player, UINT8 amount)
|
||||
{
|
||||
UINT8 oldBumpers = player->bumpers;
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
amount = min(amount, player->bumpers);
|
||||
|
||||
if (amount == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
player->bumpers -= amount;
|
||||
K_HandleBumperChanges(player, oldBumpers);
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
UINT8 K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
|
||||
{
|
||||
UINT8 oldPlayerBumpers = player->bumpers;
|
||||
UINT8 oldVictimBumpers = victim->bumpers;
|
||||
const UINT8 oldPlayerBumpers = K_Bumpers(player);
|
||||
|
||||
UINT8 tookBumpers = 0;
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
amount = min(amount, victim->bumpers);
|
||||
amount = min(amount, K_Bumpers(victim));
|
||||
|
||||
if (amount == 0)
|
||||
{
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
while ((tookBumpers < amount) && (victim->bumpers > 0))
|
||||
while (tookBumpers < amount)
|
||||
{
|
||||
UINT8 newbumper = player->bumpers;
|
||||
const UINT8 newbumper = (oldPlayerBumpers + tookBumpers);
|
||||
|
||||
angle_t newangle, diff;
|
||||
fixed_t newx, newy;
|
||||
|
|
@ -4446,24 +4373,14 @@ UINT8 K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
|
|||
P_SetMobjState(newmo, S_BATTLEBUMPER1);
|
||||
}
|
||||
|
||||
player->bumpers++;
|
||||
victim->bumpers--;
|
||||
tookBumpers++;
|
||||
}
|
||||
|
||||
if (tookBumpers == 0)
|
||||
{
|
||||
// No change occured.
|
||||
return 0;
|
||||
}
|
||||
// :jartcookiedance:
|
||||
player->mo->health += tookBumpers;
|
||||
|
||||
// Play steal sound
|
||||
S_StartSound(player->mo, sfx_3db06);
|
||||
|
||||
K_HandleBumperChanges(player, oldPlayerBumpers);
|
||||
K_HandleBumperChanges(victim, oldVictimBumpers);
|
||||
|
||||
return tookBumpers;
|
||||
}
|
||||
|
||||
#define MINEQUAKEDIST 4096
|
||||
|
|
@ -5127,8 +5044,7 @@ void K_SpawnBoostTrail(player_t *player)
|
|||
I_Assert(!P_MobjWasRemoved(player->mo));
|
||||
|
||||
if (!P_IsObjectOnGround(player->mo)
|
||||
|| player->hyudorotimer != 0
|
||||
|| ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0 && player->karmadelay))
|
||||
|| player->hyudorotimer != 0)
|
||||
return;
|
||||
|
||||
if (player->mo->eflags & MFE_VERTICALFLIP)
|
||||
|
|
@ -7080,12 +6996,6 @@ mobj_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (player->bumpers <= 0)
|
||||
{
|
||||
// Don't pay attention to dead players
|
||||
continue;
|
||||
}
|
||||
|
||||
// Z pos too high/low
|
||||
if (abs(player->mo->z - (actor->z + actor->momz)) > FixedMul(RING_DIST/8, mapobjectscale))
|
||||
{
|
||||
|
|
@ -7801,13 +7711,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->spheres = 40;
|
||||
// where's the < 0 check? see below the following block!
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0))
|
||||
{
|
||||
// Deplete 1 every tic when removed from the game.
|
||||
player->spheres--;
|
||||
player->spheredigestion = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tic_t spheredigestion = TICRATE; // Base rate of 1 every second when playing.
|
||||
tic_t digestionpower = ((10 - player->kartspeed) + (10 - player->kartweight))-1; // 1 to 17
|
||||
|
|
@ -7852,12 +7755,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (!(gametyperules & GTR_KARMA) || (player->pflags & PF_ELIMINATED))
|
||||
{
|
||||
player->karmadelay = comebacktime;
|
||||
player->karmadelay = 0;
|
||||
}
|
||||
else if (player->karmadelay > 0 && !P_PlayerInPain(player))
|
||||
{
|
||||
player->karmadelay--;
|
||||
if (P_IsDisplayPlayer(player) && player->bumpers <= 0 && player->karmadelay <= 0)
|
||||
if (P_IsDisplayPlayer(player) && player->karmadelay <= 0)
|
||||
comebackshowninfo = true; // client has already seen the message
|
||||
}
|
||||
|
||||
|
|
@ -8021,14 +7924,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
K_UpdateTripwire(player);
|
||||
|
||||
if (battleovertime.enabled && !(player->pflags & PF_ELIMINATED) && player->bumpers <= 0 && player->karmadelay <= 0)
|
||||
{
|
||||
if (player->overtimekarma)
|
||||
player->overtimekarma--;
|
||||
else
|
||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER);
|
||||
}
|
||||
|
||||
if ((battleovertime.enabled >= 10*TICRATE) && !(player->pflags & PF_ELIMINATED) && !player->exiting)
|
||||
{
|
||||
fixed_t distanceToBarrier = 0;
|
||||
|
|
@ -8058,7 +7953,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (player->eggmanexplode)
|
||||
{
|
||||
if (player->spectator || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0))
|
||||
if (player->spectator)
|
||||
player->eggmanexplode = 0;
|
||||
else
|
||||
{
|
||||
|
|
@ -8399,30 +8294,14 @@ void K_KartPlayerAfterThink(player_t *player)
|
|||
K_LookForRings(player->mo);
|
||||
}
|
||||
|
||||
if (player->invulnhitlag > 0)
|
||||
if (player->nullHitlag > 0)
|
||||
{
|
||||
// Hitlag from what would normally be damage but the
|
||||
// player was invulnerable.
|
||||
//
|
||||
// If we're constantly getting hit the same number of
|
||||
// times, we're probably standing on a damage floor.
|
||||
//
|
||||
// Checking if we're hit more than before ensures
|
||||
// that:
|
||||
//
|
||||
// 1) repeating damage doesn't count
|
||||
// 2) new damage sources still count
|
||||
|
||||
if (player->timeshit <= player->timeshitprev)
|
||||
if (!P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
if (!P_MobjWasRemoved(player->mo))
|
||||
{
|
||||
player->mo->hitlag -= player->invulnhitlag;
|
||||
player->mo->eflags &= ~(MFE_DAMAGEHITLAG);
|
||||
}
|
||||
player->mo->hitlag -= player->nullHitlag;
|
||||
}
|
||||
|
||||
player->invulnhitlag = 0;
|
||||
player->nullHitlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9583,7 +9462,7 @@ void K_KartUpdatePosition(player_t *player)
|
|||
else if (yourEmeralds == myEmeralds)
|
||||
{
|
||||
// Bumpers are the second tier tie breaker
|
||||
if (players[i].bumpers > player->bumpers)
|
||||
if (K_Bumpers(&players[i]) > K_Bumpers(player))
|
||||
{
|
||||
position++;
|
||||
}
|
||||
|
|
@ -11207,18 +11086,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
player->mo->renderflags &= ~RF_DONTDRAW;
|
||||
}
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS) || player->bumpers > 0)
|
||||
{
|
||||
player->mo->renderflags &= ~(RF_TRANSMASK|RF_BRIGHTMASK);
|
||||
}
|
||||
else // dead in match? you da bomb
|
||||
{
|
||||
K_DropItems(player); //K_StripItems(player);
|
||||
K_StripOther(player);
|
||||
player->mo->renderflags |= RF_GHOSTLY;
|
||||
player->flashing = player->karmadelay;
|
||||
}
|
||||
|
||||
if (player->trickpanel == 1)
|
||||
{
|
||||
const angle_t lr = ANGLE_45;
|
||||
|
|
@ -11718,7 +11585,7 @@ UINT32 K_PointLimitForGametype(void)
|
|||
return cv_pointlimit.value;
|
||||
}
|
||||
|
||||
if (battlecapsules || bossinfo.valid)
|
||||
if (K_Cooperative())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -11742,4 +11609,19 @@ UINT32 K_PointLimitForGametype(void)
|
|||
return ptsCap;
|
||||
}
|
||||
|
||||
boolean K_Cooperative(void)
|
||||
{
|
||||
if (battlecapsules)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bossinfo.valid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -104,9 +104,7 @@ void K_UpdateStumbleIndicator(player_t *player);
|
|||
void K_UpdateSliptideZipIndicator(player_t *player);
|
||||
INT32 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);
|
||||
UINT8 K_DestroyBumpers(player_t *player, UINT8 amount);
|
||||
UINT8 K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
|
||||
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
|
||||
void K_MineFlashScreen(mobj_t *source);
|
||||
void K_SpawnMineExplosion(mobj_t *source, UINT8 color, tic_t delay);
|
||||
void K_RunFinishLineBeam(void);
|
||||
|
|
@ -210,6 +208,8 @@ void K_EggmanTransfer(player_t *source, player_t *victim);
|
|||
tic_t K_TimeLimitForGametype(void);
|
||||
UINT32 K_PointLimitForGametype(void);
|
||||
|
||||
boolean K_Cooperative(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -232,8 +232,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->spinouttimer);
|
||||
else if (fastcmp(field,"instashield"))
|
||||
lua_pushinteger(L, plr->instashield);
|
||||
else if (fastcmp(field,"invulnhitlag"))
|
||||
lua_pushinteger(L, plr->invulnhitlag);
|
||||
else if (fastcmp(field,"nullHitlag"))
|
||||
lua_pushinteger(L, plr->nullHitlag);
|
||||
else if (fastcmp(field,"wipeoutslow"))
|
||||
lua_pushinteger(L, plr->wipeoutslow);
|
||||
else if (fastcmp(field,"justbumped"))
|
||||
|
|
@ -398,8 +398,6 @@ static int player_get(lua_State *L)
|
|||
plr->roundscore = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"emeralds"))
|
||||
lua_pushinteger(L, plr->emeralds);
|
||||
else if (fastcmp(field,"bumpers"))
|
||||
lua_pushinteger(L, plr->bumpers);
|
||||
else if (fastcmp(field,"karmadelay"))
|
||||
lua_pushinteger(L, plr->karmadelay);
|
||||
else if (fastcmp(field,"spheres"))
|
||||
|
|
@ -616,8 +614,8 @@ static int player_set(lua_State *L)
|
|||
plr->spinouttimer = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"instashield"))
|
||||
plr->instashield = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"invulnhitlag"))
|
||||
plr->invulnhitlag = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"nullHitlag"))
|
||||
plr->nullHitlag = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"wipeoutslow"))
|
||||
plr->wipeoutslow = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"justbumped"))
|
||||
|
|
@ -782,8 +780,6 @@ static int player_set(lua_State *L)
|
|||
lua_pushinteger(L, plr->roundscore);
|
||||
else if (fastcmp(field,"emeralds"))
|
||||
plr->emeralds = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"bumpers"))
|
||||
plr->bumpers = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"karmadelay"))
|
||||
plr->karmadelay = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"spheres"))
|
||||
|
|
|
|||
|
|
@ -167,12 +167,6 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
boolean tumbleitem = false;
|
||||
boolean sprung = false;
|
||||
|
||||
if ((orbinaut_selfdelay(t1) > 0 && t2->hitlag > 0)
|
||||
|| (orbinaut_selfdelay(t2) > 0 && t1->hitlag > 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (t1->health <= 0 || t2->health <= 0)
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -13595,7 +13595,7 @@ void A_ReaperThinker(mobj_t *actor)
|
|||
continue;
|
||||
|
||||
player = &players[i];
|
||||
if (player && player->mo && player->bumpers && player->score >= maxscore)
|
||||
if (player && player->mo && K_Bumpers(player) && player->score >= maxscore)
|
||||
{
|
||||
targetplayermo = player->mo;
|
||||
maxscore = player->score;
|
||||
|
|
|
|||
207
src/p_inter.c
207
src/p_inter.c
|
|
@ -39,6 +39,7 @@
|
|||
#include "p_spec.h"
|
||||
#include "k_objects.h"
|
||||
#include "k_roulette.h"
|
||||
#include "k_boss.h"
|
||||
|
||||
// CTF player names
|
||||
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
|
||||
|
|
@ -114,13 +115,6 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
|
|||
if (player->exiting || mapreset || (player->pflags & PF_ELIMINATED))
|
||||
return false;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) // No bumpers in Match
|
||||
#ifndef OTHERKARMAMODES
|
||||
&& !weapon
|
||||
#endif
|
||||
&& player->bumpers <= 0)
|
||||
return false;
|
||||
|
||||
if (weapon)
|
||||
{
|
||||
// Item slot already taken up
|
||||
|
|
@ -285,9 +279,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (!P_CanPickupItem(player, 3) || (player->itemamount && player->itemtype != special->threshold))
|
||||
return;
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
|
||||
return;
|
||||
|
||||
player->itemtype = special->threshold;
|
||||
if ((UINT16)(player->itemamount) + special->movecount > 255)
|
||||
player->itemamount = 255;
|
||||
|
|
@ -320,9 +311,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
P_KillMobj(special, toucher, toucher, DMG_NORMAL);
|
||||
return;
|
||||
case MT_ITEMCAPSULE:
|
||||
if ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0)
|
||||
return;
|
||||
|
||||
if (special->scale < special->extravalue1) // don't break it while it's respawning
|
||||
return;
|
||||
|
||||
|
|
@ -350,8 +338,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
if (player == special->target->player)
|
||||
return;
|
||||
if (player->bumpers <= 0)
|
||||
return;
|
||||
if (special->target->player->exiting || player->exiting)
|
||||
return;
|
||||
|
||||
|
|
@ -452,7 +438,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
S_StartSound(special, sfx_s1a2);
|
||||
return;
|
||||
case MT_CDUFO: // SRB2kart
|
||||
if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0))
|
||||
if (special->fuse || !P_CanPickupItem(player, 1))
|
||||
return;
|
||||
|
||||
K_StartItemRoulette(player);
|
||||
|
|
@ -1395,6 +1381,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
|
||||
P_PlayDeathSound(target);
|
||||
}
|
||||
|
||||
if (K_Cooperative())
|
||||
{
|
||||
target->player->pflags |= (PF_NOCONTEST|PF_ELIMINATED);
|
||||
}
|
||||
break;
|
||||
|
||||
case MT_METALSONIC_RACE:
|
||||
|
|
@ -1937,13 +1928,23 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
switch (type)
|
||||
{
|
||||
case DMG_DEATHPIT:
|
||||
// Respawn kill types
|
||||
K_DoIngameRespawn(player);
|
||||
player->mo->health -= K_DestroyBumpers(player, 1);
|
||||
return false;
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
player->mo->health--;
|
||||
}
|
||||
|
||||
if (player->mo->health <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Quick respawn; does not kill
|
||||
return K_DoIngameRespawn(player), false;
|
||||
|
||||
case DMG_SPECTATOR:
|
||||
// disappearifies, but still gotta put items back in play
|
||||
break;
|
||||
|
||||
default:
|
||||
// Everything else REALLY kills
|
||||
if (leveltime < starttime)
|
||||
|
|
@ -1999,11 +2000,46 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
player->pflags |= PF_ELIMINATED;
|
||||
}
|
||||
|
||||
K_DestroyBumpers(player, player->bumpers);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void AddTimesHit(player_t *player)
|
||||
{
|
||||
const INT32 oldtimeshit = player->timeshit;
|
||||
|
||||
player->timeshit++;
|
||||
|
||||
// overflow prevention
|
||||
if (player->timeshit < oldtimeshit)
|
||||
{
|
||||
player->timeshit = oldtimeshit;
|
||||
}
|
||||
}
|
||||
|
||||
static void AddNullHitlag(player_t *player, tic_t oldHitlag)
|
||||
{
|
||||
if (player == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Hitlag from what would normally be damage but the
|
||||
// player was invulnerable.
|
||||
//
|
||||
// If we're constantly getting hit the same number of
|
||||
// times, we're probably standing on a damage floor.
|
||||
//
|
||||
// Checking if we're hit more than before ensures that:
|
||||
//
|
||||
// 1) repeating damage doesn't count
|
||||
// 2) new damage sources still count
|
||||
|
||||
if (player->timeshit <= player->timeshitprev)
|
||||
{
|
||||
player->nullHitlag += (player->mo->hitlag - oldHitlag);
|
||||
}
|
||||
}
|
||||
|
||||
/** Damages an object, which may or may not be a player.
|
||||
* For melee attacks, source and inflictor are the same.
|
||||
*
|
||||
|
|
@ -2024,6 +2060,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
|
|||
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
|
||||
{
|
||||
player_t *player;
|
||||
player_t *playerInflictor;
|
||||
boolean force = false;
|
||||
|
||||
INT32 laglength = 6;
|
||||
|
|
@ -2081,9 +2118,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (!(target->flags & MF_SHOOTABLE))
|
||||
return false; // shouldn't happen...
|
||||
}
|
||||
|
||||
if (!(damagetype & DMG_DEATHMASK) && (target->eflags & MFE_PAUSED))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target->flags2 & MF2_SKULLFLY)
|
||||
|
|
@ -2102,20 +2136,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
|
||||
player = target->player;
|
||||
playerInflictor = inflictor ? inflictor->player : NULL;
|
||||
|
||||
if (playerInflictor)
|
||||
{
|
||||
AddTimesHit(playerInflictor);
|
||||
}
|
||||
|
||||
if (player) // Player is the target
|
||||
{
|
||||
{
|
||||
const INT32 oldtimeshit = player->timeshit;
|
||||
|
||||
player->timeshit++;
|
||||
|
||||
// overflow prevention
|
||||
if (player->timeshit < oldtimeshit)
|
||||
{
|
||||
player->timeshit = oldtimeshit;
|
||||
}
|
||||
}
|
||||
AddTimesHit(player);
|
||||
|
||||
if (player->pflags & PF_GODMODE)
|
||||
return false;
|
||||
|
|
@ -2146,9 +2176,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
const boolean hardhit = (type == DMG_EXPLODE || type == DMG_KARMA || type == DMG_TUMBLE); // This damage type can do evil stuff like ALWAYS combo
|
||||
INT16 ringburst = 5;
|
||||
|
||||
// Do not die from damage outside of bumpers health system
|
||||
damage = 0;
|
||||
|
||||
// Check if the player is allowed to be damaged!
|
||||
// If not, then spawn the instashield effect instead.
|
||||
if (!force)
|
||||
|
|
@ -2156,16 +2183,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
boolean invincible = true;
|
||||
sfxenum_t sfx = sfx_None;
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
if (player->bumpers <= 0 && player->karmadelay)
|
||||
{
|
||||
// No bumpers & in WAIT, can't be hurt
|
||||
K_DoInstashield(player);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
if (damagetype & DMG_STEAL)
|
||||
{
|
||||
|
|
@ -2192,12 +2210,32 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
if (invincible && type != DMG_STUMBLE)
|
||||
{
|
||||
const INT32 oldhitlag = target->hitlag;
|
||||
const INT32 oldHitlag = target->hitlag;
|
||||
const INT32 oldHitlagInflictor = inflictor ? inflictor->hitlag : 0;
|
||||
|
||||
// Damage during hitlag should be a no-op
|
||||
// for invincibility states because there
|
||||
// are no flashing tics. If the damage is
|
||||
// from a constant source, a deadlock
|
||||
// would occur.
|
||||
|
||||
if (target->eflags & MFE_PAUSED)
|
||||
{
|
||||
player->timeshit--; // doesn't count
|
||||
|
||||
if (playerInflictor)
|
||||
{
|
||||
playerInflictor->timeshit--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
laglength = max(laglength / 2, 1);
|
||||
K_SetHitLagForObjects(target, inflictor, laglength, false);
|
||||
|
||||
player->invulnhitlag += (target->hitlag - oldhitlag);
|
||||
AddNullHitlag(player, oldHitlag);
|
||||
AddNullHitlag(playerInflictor, oldHitlagInflictor);
|
||||
|
||||
if (player->timeshit > player->timeshitprev)
|
||||
{
|
||||
|
|
@ -2227,6 +2265,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
allowcombo = false;
|
||||
}
|
||||
|
||||
if (allowcombo == false && (target->eflags & MFE_PAUSED))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// DMG_EXPLODE excluded from flashtic checks to prevent dodging eggbox/SPB with weak spinout
|
||||
if ((target->hitlag == 0 || allowcombo == false) && player->flashing > 0 && type != DMG_EXPLODE && type != DMG_STUMBLE)
|
||||
{
|
||||
|
|
@ -2234,31 +2277,35 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
K_DoInstashield(player);
|
||||
return false;
|
||||
}
|
||||
else if (target->flags2 & MF2_ALREADYHIT) // do not deal extra damage in the same tic
|
||||
{
|
||||
K_SetHitLagForObjects(target, inflictor, laglength, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We successfully damaged them! Give 'em some bumpers!
|
||||
if (type != DMG_STING && type != DMG_STUMBLE)
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
{
|
||||
UINT8 takeBumpers = 1;
|
||||
|
||||
if (damagetype & DMG_STEAL)
|
||||
{
|
||||
takeBumpers = 2;
|
||||
// Steals 2 bumpers
|
||||
damage = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not die from damage outside of bumpers health system
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
if (type == DMG_KARMA)
|
||||
{
|
||||
takeBumpers = player->bumpers;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (type == DMG_KARMA)
|
||||
{
|
||||
// Take half of their bumpers for karma comeback damage
|
||||
takeBumpers = max(1, player->bumpers / 2);
|
||||
}
|
||||
}
|
||||
if (type == DMG_STING || type == DMG_STUMBLE)
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We successfully damaged them! Give 'em some bumpers!
|
||||
|
||||
if (source && source != player->mo && source->player)
|
||||
{
|
||||
|
|
@ -2277,18 +2324,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
K_TryHurtSoundExchange(target, source);
|
||||
|
||||
K_BattleAwardHit(source->player, player, inflictor, takeBumpers);
|
||||
damage = K_TakeBumpersFromPlayer(source->player, player, takeBumpers);
|
||||
if (K_Cooperative() == false)
|
||||
{
|
||||
K_BattleAwardHit(source->player, player, inflictor, damage);
|
||||
}
|
||||
|
||||
if (type == DMG_KARMA)
|
||||
{
|
||||
// Destroy any remainder bumpers from the player for karma comeback damage
|
||||
damage = K_DestroyBumpers(player, player->bumpers);
|
||||
}
|
||||
else
|
||||
{
|
||||
source->player->overtimekarma += 5*TICRATE;
|
||||
}
|
||||
K_TakeBumpersFromPlayer(source->player, player, damage);
|
||||
|
||||
if (damagetype & DMG_STEAL)
|
||||
{
|
||||
|
|
@ -2304,10 +2345,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
Obj_GardenTopDestroy(source->player);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
damage = K_DestroyBumpers(player, takeBumpers);
|
||||
}
|
||||
|
||||
if (!(damagetype & DMG_STEAL))
|
||||
{
|
||||
|
|
@ -2425,6 +2462,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
|
||||
K_SetHitLagForObjects(target, inflictor, laglength, true);
|
||||
|
||||
target->flags2 |= MF2_ALREADYHIT;
|
||||
|
||||
if (target->health <= 0)
|
||||
{
|
||||
P_KillMobj(target, inflictor, source, damagetype);
|
||||
|
|
|
|||
11
src/p_map.c
11
src/p_map.c
|
|
@ -956,6 +956,8 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
|||
|| tm.thing->type == MT_BANANA || tm.thing->type == MT_EGGMANITEM || tm.thing->type == MT_BALLHOG
|
||||
|| tm.thing->type == MT_SSMINE || tm.thing->type == MT_LANDMINE || tm.thing->type == MT_SINK
|
||||
|| tm.thing->type == MT_GARDENTOP
|
||||
|| tm.thing->type == MT_MONITOR
|
||||
|| tm.thing->type == MT_BATTLECAPSULE
|
||||
|| (tm.thing->type == MT_PLAYER)))
|
||||
{
|
||||
// see if it went over / under
|
||||
|
|
@ -971,6 +973,8 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
|||
|| thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG
|
||||
|| thing->type == MT_SSMINE || thing->type == MT_LANDMINE || thing->type == MT_SINK
|
||||
|| thing->type == MT_GARDENTOP
|
||||
|| thing->type == MT_MONITOR
|
||||
|| thing->type == MT_BATTLECAPSULE
|
||||
|| (thing->type == MT_PLAYER)))
|
||||
{
|
||||
// see if it went over / under
|
||||
|
|
@ -1390,13 +1394,6 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
|||
return BMIT_CONTINUE;
|
||||
}
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS)
|
||||
&& ((thing->player->bumpers && !tm.thing->player->bumpers)
|
||||
|| (tm.thing->player->bumpers && !thing->player->bumpers)))
|
||||
{
|
||||
return BMIT_CONTINUE;
|
||||
}
|
||||
|
||||
if (!P_MobjWasRemoved(thing) && !P_MobjWasRemoved(tm.thing))
|
||||
{
|
||||
if (thing->player->eggmanexplode)
|
||||
|
|
|
|||
58
src/p_mobj.c
58
src/p_mobj.c
|
|
@ -4588,9 +4588,6 @@ boolean P_SupermanLook4Players(mobj_t *actor)
|
|||
if (players[c].mo->health <= 0)
|
||||
continue; // dead
|
||||
|
||||
if ((gametyperules & GTR_BUMPERS) && players[c].bumpers <= 0)
|
||||
continue; // other dead
|
||||
|
||||
playersinthegame[stop] = &players[c];
|
||||
stop++;
|
||||
}
|
||||
|
|
@ -6129,6 +6126,8 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player
|
||||
&& mobj->target->health > 0 && !mobj->target->player->spectator)
|
||||
{
|
||||
const UINT8 bumpers = K_Bumpers(mobj->target->player);
|
||||
|
||||
fixed_t rad = 32*mobj->target->scale;
|
||||
fixed_t offz;
|
||||
angle_t ang, diff;
|
||||
|
|
@ -6138,10 +6137,10 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
else
|
||||
ang = FixedAngle(mobj->info->speed);
|
||||
|
||||
if (mobj->target->player->bumpers <= 1)
|
||||
if (bumpers <= 1)
|
||||
diff = 0;
|
||||
else
|
||||
diff = FixedAngle(360*FRACUNIT/mobj->target->player->bumpers);
|
||||
diff = FixedAngle(360*FRACUNIT / bumpers);
|
||||
|
||||
ang = (ang*leveltime) + (diff * (mobj->threshold-1));
|
||||
|
||||
|
|
@ -6178,9 +6177,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
mobj->color = mobj->target->color;
|
||||
}
|
||||
|
||||
if (mobj->target->player->bumpers < 2)
|
||||
if (bumpers < 2)
|
||||
P_SetMobjState(mobj, S_BATTLEBUMPER3);
|
||||
else if (mobj->target->player->bumpers < 3)
|
||||
else if (bumpers < 3)
|
||||
P_SetMobjState(mobj, S_BATTLEBUMPER2);
|
||||
else
|
||||
P_SetMobjState(mobj, S_BATTLEBUMPER1);
|
||||
|
|
@ -6197,7 +6196,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
P_SetThingPosition(mobj);
|
||||
}
|
||||
|
||||
if (mobj->target->player->bumpers <= mobj->threshold)
|
||||
if (bumpers <= mobj->threshold)
|
||||
{
|
||||
// Do bumper destruction
|
||||
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
|
||||
|
|
@ -6231,7 +6230,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
mobj->color = mobj->target->color;
|
||||
K_MatchGenericExtraFlags(mobj, mobj->target);
|
||||
|
||||
if ((!(gametyperules & GTR_BUMPERS) || mobj->target->player->bumpers <= 0)
|
||||
if (!(gametyperules & GTR_BUMPERS)
|
||||
#if 1 // Set to 0 to test without needing to host
|
||||
|| (P_IsDisplayPlayer(mobj->target->player))
|
||||
#endif
|
||||
|
|
@ -8247,7 +8246,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
desty = mobj->target->y;
|
||||
}
|
||||
|
||||
mobj->flags &= ~(MF_NOCLIPTHING);
|
||||
P_MoveOrigin(mobj, destx, desty, mobj->target->z);
|
||||
mobj->flags |= MF_NOCLIPTHING;
|
||||
break;
|
||||
}
|
||||
case MT_FLAMESHIELD:
|
||||
|
|
@ -8428,7 +8429,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
statenum_t state = (mobj->state-states);
|
||||
|
||||
if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator
|
||||
|| (!(gametyperules & GTR_BUMPERS) || mobj->target->player->bumpers))
|
||||
|| !(gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
|
|
@ -9843,8 +9844,10 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<<mobj->spawnpoint->args[0])))
|
||||
return;
|
||||
|
||||
mobj->flags2 &= ~(MF2_ALREADYHIT);
|
||||
|
||||
// Don't run any thinker code while in hitlag
|
||||
if (mobj->hitlag > 0)
|
||||
if ((mobj->player ? mobj->hitlag - mobj->player->nullHitlag : mobj->hitlag) > 0)
|
||||
{
|
||||
mobj->eflags |= MFE_PAUSED;
|
||||
mobj->hitlag--;
|
||||
|
|
@ -11876,38 +11879,15 @@ void P_SpawnPlayer(INT32 playernum)
|
|||
P_SetScale(overheadarrow, mobj->destscale);
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
if ((gametyperules & GTR_BUMPERS) && !p->spectator)
|
||||
{
|
||||
if (p->spectator)
|
||||
// At leveltime == 2, K_TimerInit will get called and reset
|
||||
// the bumpers to the initial value for the level.
|
||||
if (leveltime > 2) // Reset those bumpers!
|
||||
{
|
||||
// HEY! No being cheap...
|
||||
p->bumpers = 0;
|
||||
}
|
||||
else if ((p->bumpers > 0) || (leveltime < starttime) || (pcount <= 1))
|
||||
{
|
||||
if ((leveltime < starttime) || (pcount <= 1)) // Start of the map?
|
||||
{
|
||||
if (leveltime > 2) // Reset those bumpers!
|
||||
{
|
||||
p->bumpers = K_StartingBumperCount();
|
||||
K_SpawnPlayerBattleBumpers(p);
|
||||
}
|
||||
else // temp, will get overwritten in K_BattleInit
|
||||
{
|
||||
p->bumpers = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p->bumpers <= 0)
|
||||
{
|
||||
p->bumpers = K_StartingBumperCount();
|
||||
mobj->health = K_BumpersToHealth(K_StartingBumperCount());
|
||||
K_SpawnPlayerBattleBumpers(p);
|
||||
}
|
||||
|
||||
if (p->bumpers > 0)
|
||||
{
|
||||
mobj->health = p->bumpers;
|
||||
}
|
||||
}
|
||||
|
||||
// I'm not refactoring the loop at the top of this file.
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ typedef enum
|
|||
MF2_JUSTATTACKED = 1<<16, // can be pushed by other moving mobjs
|
||||
MF2_FIRING = 1<<17, // turret fire
|
||||
MF2_SUPERFIRE = 1<<18, // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
|
||||
// free: 1<<19
|
||||
MF2_ALREADYHIT = 1<<19, // This object was already damaged THIS tic, resets even during hitlag
|
||||
MF2_STRONGBOX = 1<<20, // Flag used for "strong" random monitors.
|
||||
MF2_OBJECTFLIP = 1<<21, // Flag for objects that always have flipped gravity.
|
||||
MF2_SKULLFLY = 1<<22, // Special handling: skull in flight.
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT16(save->p, players[i].spinouttimer);
|
||||
WRITEUINT8(save->p, players[i].spinouttype);
|
||||
WRITEUINT8(save->p, players[i].instashield);
|
||||
WRITEINT32(save->p, players[i].invulnhitlag);
|
||||
WRITEINT32(save->p, players[i].nullHitlag);
|
||||
WRITEUINT8(save->p, players[i].wipeoutslow);
|
||||
WRITEUINT8(save->p, players[i].justbumped);
|
||||
WRITEUINT8(save->p, players[i].tumbleBounces);
|
||||
|
|
@ -381,9 +381,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT32(save->p, players[i].roundscore);
|
||||
WRITEUINT8(save->p, players[i].emeralds);
|
||||
WRITEUINT8(save->p, players[i].bumpers);
|
||||
WRITEINT16(save->p, players[i].karmadelay);
|
||||
WRITEUINT32(save->p, players[i].overtimekarma);
|
||||
WRITEINT16(save->p, players[i].spheres);
|
||||
WRITEUINT32(save->p, players[i].spheredigestion);
|
||||
|
||||
|
|
@ -653,7 +651,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].spinouttimer = READUINT16(save->p);
|
||||
players[i].spinouttype = READUINT8(save->p);
|
||||
players[i].instashield = READUINT8(save->p);
|
||||
players[i].invulnhitlag = READINT32(save->p);
|
||||
players[i].nullHitlag = READINT32(save->p);
|
||||
players[i].wipeoutslow = READUINT8(save->p);
|
||||
players[i].justbumped = READUINT8(save->p);
|
||||
players[i].tumbleBounces = READUINT8(save->p);
|
||||
|
|
@ -758,9 +756,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].roundscore = READUINT32(save->p);
|
||||
players[i].emeralds = READUINT8(save->p);
|
||||
players[i].bumpers = READUINT8(save->p);
|
||||
players[i].karmadelay = READINT16(save->p);
|
||||
players[i].overtimekarma = READUINT32(save->p);
|
||||
players[i].spheres = READINT16(save->p);
|
||||
players[i].spheredigestion = READUINT32(save->p);
|
||||
|
||||
|
|
|
|||
|
|
@ -526,10 +526,6 @@ INT32 P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
|
|||
if (!(gametyperules & GTR_SPHERES)) // No spheres in Race mode)
|
||||
return 0;
|
||||
|
||||
// Not alive
|
||||
if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= 0))
|
||||
return 0;
|
||||
|
||||
if (num_spheres > 40) // Reached the cap, don't waste 'em!
|
||||
num_spheres = 40;
|
||||
else if (num_spheres < 0)
|
||||
|
|
@ -4387,7 +4383,7 @@ void P_PlayerThink(player_t *player)
|
|||
|| player->growshrinktimer > 0 // Grow doesn't flash either.
|
||||
|| (player->respawn.state != RESPAWNST_NONE && player->respawn.truedeath == true) // Respawn timer (for drop dash effect)
|
||||
|| (player->pflags & PF_NOCONTEST) // NO CONTEST explosion
|
||||
|| ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0 && player->karmadelay)))
|
||||
|| player->karmadelay))
|
||||
{
|
||||
if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player)
|
||||
&& (leveltime & 1))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue