mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-05 09:46:40 +00:00
Merge branch 'instashield' into 'master'
Instashield (and Guard!) See merge request KartKrew/Kart!1242
This commit is contained in:
commit
3f8ca964c7
25 changed files with 763 additions and 32 deletions
|
|
@ -740,6 +740,12 @@ struct player_t
|
|||
|
||||
mobj_t *stumbleIndicator;
|
||||
mobj_t *sliptideZipIndicator;
|
||||
mobj_t *whip;
|
||||
|
||||
UINT8 instaShieldCooldown;
|
||||
UINT8 guardCooldown;
|
||||
|
||||
INT16 incontrol; // -1 to -175 when spinning out or tumbling, 1 to 175 when not. Use to check for combo hits or emergency inputs.
|
||||
|
||||
uint8_t public_key[PUBKEYLENGTH];
|
||||
|
||||
|
|
|
|||
|
|
@ -3287,6 +3287,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
|
||||
"S_SLIPTIDEZIP",
|
||||
|
||||
"S_INSTAWHIP",
|
||||
"S_BLOCKRING",
|
||||
"S_BLOCKBODY",
|
||||
|
||||
// Signpost sparkles
|
||||
"S_SIGNSPARK1",
|
||||
"S_SIGNSPARK2",
|
||||
|
|
@ -4011,6 +4015,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_INSTASHIELDB7",
|
||||
|
||||
"S_POWERCLASH", // Invinc/Grow no damage collide VFX
|
||||
"S_GUARDBREAK", // Guard break
|
||||
|
||||
"S_PLAYERARROW", // Above player arrow
|
||||
"S_PLAYERARROW_BOX",
|
||||
|
|
@ -5318,6 +5323,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
|
||||
"MT_SLIPTIDEZIP",
|
||||
|
||||
"MT_INSTAWHIP",
|
||||
"MT_BLOCKRING",
|
||||
"MT_BLOCKBODY",
|
||||
|
||||
"MT_SIGNSPARKLE",
|
||||
|
||||
"MT_FASTLINE",
|
||||
|
|
@ -5487,7 +5496,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_INSTASHIELDB",
|
||||
|
||||
"MT_POWERCLASH", // Invinc/Grow no damage clash VFX
|
||||
|
||||
"MT_GUARDBREAK", // Guard break
|
||||
|
||||
"MT_PLAYERARROW",
|
||||
"MT_PLAYERWANTED",
|
||||
|
||||
|
|
|
|||
|
|
@ -2675,6 +2675,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
P_SetTarget(&players[player].follower, NULL);
|
||||
P_SetTarget(&players[player].awayview.mobj, NULL);
|
||||
P_SetTarget(&players[player].stumbleIndicator, NULL);
|
||||
P_SetTarget(&players[player].whip, NULL);
|
||||
P_SetTarget(&players[player].ringShooter, NULL);
|
||||
P_SetTarget(&players[player].followmobj, NULL);
|
||||
|
||||
|
|
|
|||
118
src/info.c
118
src/info.c
|
|
@ -555,6 +555,10 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
|
||||
"SLPT", // Sliptide zip indicator
|
||||
|
||||
"IWHP", // Instawhip
|
||||
"GRNG", // Guard ring
|
||||
"GBDY", // Guard body
|
||||
|
||||
"WIPD", // Wipeout dust trail
|
||||
"DRIF", // Drift Sparks
|
||||
"BDRF", // Brake drift sparks
|
||||
|
|
@ -634,6 +638,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"ISTB", // instashield layer B
|
||||
|
||||
"PWCL", // Invinc/grow clash VFX
|
||||
"GBRK", // Guard break
|
||||
|
||||
"ARRO", // player arrows
|
||||
"ITEM",
|
||||
|
|
@ -3946,6 +3951,10 @@ state_t states[NUMSTATES] =
|
|||
|
||||
{SPR_SLPT, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SLIPTIDEZIP
|
||||
|
||||
{SPR_IWHP, FF_FULLBRIGHT|FF_FLOORSPRITE|FF_ANIMATE|0, -1, {NULL}, 6, 2, S_NULL}, // S_INSTAWHIP
|
||||
{SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING
|
||||
{SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY
|
||||
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SIGNSPARK2}, // S_SIGNSPARK1
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SIGNSPARK3}, // S_SIGNSPARK2
|
||||
{SPR_SGNS, FF_ADD|FF_FULLBRIGHT|2, 1, {NULL}, 0, 0, S_SIGNSPARK4}, // S_SIGNSPARK3
|
||||
|
|
@ -4627,6 +4636,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_ISTB, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_NULL}, // S_INSTASHIELDB7
|
||||
|
||||
{SPR_PWCL, FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 10, {NULL}, 9, 1, S_NULL}, // S_POWERCLASH
|
||||
{SPR_GBRK, FF_ADD|FF_FULLBRIGHT|FF_ANIMATE|FF_PAPERSPRITE, 24, {NULL}, 5, 4, S_NULL}, // S_GUARDBREAK
|
||||
|
||||
// Above player arrow
|
||||
{SPR_ARRO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_PLAYERARROW
|
||||
|
|
@ -22632,6 +22642,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_INSTAWHIP
|
||||
-1, // doomednum
|
||||
S_INSTAWHIP, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
90*FRACUNIT, // radius
|
||||
90*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BLOCKRING
|
||||
-1, // doomednum
|
||||
S_BLOCKRING, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
67*FRACUNIT, // radius
|
||||
67*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BLOCKBODY
|
||||
-1, // doomednum
|
||||
S_BLOCKBODY, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
67*FRACUNIT, // radius
|
||||
67*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SIGNSPARKLE
|
||||
-1, // doomednum
|
||||
|
|
@ -26089,6 +26180,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_GUARDBREAK
|
||||
-1, // doomednum
|
||||
S_GUARDBREAK, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
8, // speed
|
||||
8*FRACUNIT, // radius
|
||||
8*FRACUNIT, // height
|
||||
2, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_PLAYERARROW
|
||||
-1, // doomednum
|
||||
S_PLAYERARROW, // spawnstate
|
||||
|
|
|
|||
15
src/info.h
15
src/info.h
|
|
@ -1108,6 +1108,10 @@ typedef enum sprite
|
|||
|
||||
SPR_SLPT, // Sliptide zip indicator
|
||||
|
||||
SPR_IWHP, // Instawhip
|
||||
SPR_GRNG, // Guard ring
|
||||
SPR_GBDY, // Guard body
|
||||
|
||||
SPR_WIPD, // Wipeout dust trail
|
||||
SPR_DRIF, // Drift Sparks
|
||||
SPR_BDRF, // Brake drift sparks
|
||||
|
|
@ -1187,6 +1191,7 @@ typedef enum sprite
|
|||
SPR_ISTB, // instashield layer B
|
||||
|
||||
SPR_PWCL, // Invinc/grow clash VFX
|
||||
SPR_GBRK, // Guard break
|
||||
|
||||
SPR_ARRO, // player arrows
|
||||
SPR_ITEM,
|
||||
|
|
@ -4357,6 +4362,10 @@ typedef enum state
|
|||
|
||||
S_SLIPTIDEZIP,
|
||||
|
||||
S_INSTAWHIP,
|
||||
S_BLOCKRING,
|
||||
S_BLOCKBODY,
|
||||
|
||||
// Signpost sparkles
|
||||
S_SIGNSPARK1,
|
||||
S_SIGNSPARK2,
|
||||
|
|
@ -5080,6 +5089,7 @@ typedef enum state
|
|||
S_INSTASHIELDB7,
|
||||
|
||||
S_POWERCLASH, // Grow/Invinc clash VFX
|
||||
S_GUARDBREAK,
|
||||
|
||||
S_PLAYERARROW, // Above player arrow
|
||||
S_PLAYERARROW_BOX,
|
||||
|
|
@ -6423,6 +6433,10 @@ typedef enum mobj_type
|
|||
MT_MAGICIANBOX,
|
||||
MT_SLIPTIDEZIP,
|
||||
|
||||
MT_INSTAWHIP,
|
||||
MT_BLOCKRING,
|
||||
MT_BLOCKBODY,
|
||||
|
||||
MT_SIGNSPARKLE,
|
||||
|
||||
MT_FASTLINE,
|
||||
|
|
@ -6592,6 +6606,7 @@ typedef enum mobj_type
|
|||
MT_INSTASHIELDB,
|
||||
|
||||
MT_POWERCLASH, // Grow/Invinc clash VFX
|
||||
MT_GUARDBREAK,
|
||||
|
||||
MT_PLAYERARROW,
|
||||
MT_PLAYERWANTED,
|
||||
|
|
|
|||
|
|
@ -197,9 +197,9 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT
|
|||
|
||||
P_Thrust(emerald,
|
||||
FixedAngle(P_RandomFixed(PR_ITEM_ROULETTE) * 180) + angle,
|
||||
24 * mapobjectscale);
|
||||
36 * mapobjectscale);
|
||||
|
||||
emerald->momz = flip * 24 * mapobjectscale;
|
||||
emerald->momz = flip * 36 * mapobjectscale;
|
||||
if (emerald->eflags & MFE_UNDERWATER)
|
||||
emerald->momz = (117 * emerald->momz) / 200;
|
||||
|
||||
|
|
@ -265,6 +265,9 @@ void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType)
|
|||
UINT8 i;
|
||||
SINT8 flip = P_MobjFlip(player->mo);
|
||||
|
||||
if (player->incontrol < TICRATE)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 14; i++)
|
||||
{
|
||||
UINT32 emeraldFlag = (1 << i);
|
||||
|
|
@ -275,6 +278,7 @@ void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType)
|
|||
P_SetTarget(&emerald->target, player->mo);
|
||||
|
||||
player->emeralds &= ~emeraldFlag;
|
||||
break; // Drop only one emerald. Emerald wins are hard enough!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1362,6 +1362,18 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
INT32 saferingsval = 16 - K_GetKartRingPower(player, false);
|
||||
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
// Don't use rings during POSITION!!
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd->buttons & BT_ACCELERATE) == 0)
|
||||
{
|
||||
// Don't use rings if you're not trying to accelerate.
|
||||
return;
|
||||
}
|
||||
|
||||
if (P_IsObjectOnGround(player->mo) == false)
|
||||
{
|
||||
// Don't use while mid-air.
|
||||
|
|
@ -1380,6 +1392,70 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotItemInstashield(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
Item usage for instashield.
|
||||
|
||||
Input Arguments:-
|
||||
player - Bot to do this for.
|
||||
cmd - Bot's ticcmd to edit.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_BotItemInstashield(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const fixed_t radius = FixedMul(mobjinfo[MT_INSTAWHIP].radius, player->mo->scale);
|
||||
size_t i = SIZE_MAX;
|
||||
|
||||
if (K_ItemButtonWasDown(player) == true)
|
||||
{
|
||||
// Release the button, dude.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->instaShieldCooldown || leveltime < starttime || player->spindash)
|
||||
{
|
||||
// Instashield is on cooldown.
|
||||
return;
|
||||
}
|
||||
|
||||
// Find players within the instashield's range.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
player_t *target = NULL;
|
||||
fixed_t dist = INT32_MAX;
|
||||
|
||||
if (!playeringame[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
target = &players[i];
|
||||
if (P_MobjWasRemoved(target->mo) == true
|
||||
|| player == target
|
||||
|| target->spectator == true
|
||||
|| target->flashing != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(
|
||||
player->mo->x - target->mo->x,
|
||||
player->mo->y - target->mo->y),
|
||||
(player->mo->z - target->mo->z) / 4
|
||||
);
|
||||
|
||||
if (dist <= radius)
|
||||
{
|
||||
// Use it!!
|
||||
cmd->buttons |= BT_ATTACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd)
|
||||
|
||||
|
|
@ -1453,12 +1529,16 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
|
|||
{
|
||||
if (player->pflags & PF_USERINGS)
|
||||
{
|
||||
// Use rings!
|
||||
|
||||
if (leveltime > starttime)
|
||||
if (player->rings > 0)
|
||||
{
|
||||
// Use rings!
|
||||
K_BotItemRings(player, cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the instashield!
|
||||
K_BotItemInstashield(player, cmd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -787,6 +787,140 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
|
||||
{
|
||||
int victimHitlag = 10;
|
||||
int attackerHitlag = 4;
|
||||
|
||||
// EV1 is used to indicate that we should no longer hit monitors.
|
||||
// EV2 indicates we should no longer hit anything.
|
||||
if (shield->extravalue2)
|
||||
return false;
|
||||
|
||||
mobj_t *attacker = shield->target;
|
||||
|
||||
if (!attacker || P_MobjWasRemoved(attacker) || !attacker->player)
|
||||
return false; // How did we even get here?
|
||||
|
||||
player_t *attackerPlayer = attacker->player;
|
||||
|
||||
if (victim->player)
|
||||
{
|
||||
player_t *victimPlayer = victim->player;
|
||||
|
||||
//if (victim != attacker && !P_PlayerInPain(victimPlayer) && victimPlayer->flashing == 0)
|
||||
if (victim != attacker && victim->hitlag == 0)
|
||||
{
|
||||
// If both players have a whip, hits are order-of-execution dependent and that sucks.
|
||||
// Player expectation is a clash here.
|
||||
if (victimPlayer->whip && !P_MobjWasRemoved(victimPlayer->whip))
|
||||
{
|
||||
victimPlayer->whip->extravalue2 = 1;
|
||||
shield->extravalue2 = 1;
|
||||
|
||||
K_DoPowerClash(victim, attacker);
|
||||
|
||||
victim->renderflags &= ~RF_DONTDRAW;
|
||||
attacker->renderflags &= ~RF_DONTDRAW;
|
||||
|
||||
angle_t thrangle = R_PointToAngle2(attacker->x, attacker->y, victim->x, victim->y);
|
||||
P_Thrust(victim, thrangle, FRACUNIT*7);
|
||||
P_Thrust(attacker, ANGLE_180 + thrangle, FRACUNIT*7);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Instawhip _always_ loses to guard.
|
||||
if (K_PlayerGuard(victimPlayer))
|
||||
//if (true)
|
||||
{
|
||||
victimHitlag = 3*victimHitlag;
|
||||
|
||||
if (P_PlayerInPain(attackerPlayer))
|
||||
return false; // never punish shield more than once
|
||||
|
||||
angle_t thrangle = R_PointToAngle2(victim->x, victim->y, shield->x, shield->y);
|
||||
attacker->momx = attacker->momy = 0;
|
||||
P_Thrust(attacker, thrangle, FRACUNIT*7);
|
||||
|
||||
// A little extra juice, so successful reads are usually positive or zero on spheres.
|
||||
victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40);
|
||||
|
||||
shield->renderflags &= ~RF_DONTDRAW;
|
||||
shield->flags |= MF_NOCLIPTHING;
|
||||
|
||||
// Attacker should be free to all reasonable followups.
|
||||
attacker->renderflags &= ~RF_DONTDRAW;
|
||||
attackerPlayer->spindashboost = 0;
|
||||
attackerPlayer->sneakertimer = 0;
|
||||
attackerPlayer->instaShieldCooldown = TICRATE*2;
|
||||
attackerPlayer->guardCooldown = TICRATE*2;
|
||||
attackerPlayer->flashing = 0;
|
||||
|
||||
// Localized broly for a local event.
|
||||
mobj_t *broly = Obj_SpawnBrolyKi(victim, victimHitlag);
|
||||
broly->extravalue2 = 16*mapobjectscale;
|
||||
|
||||
P_PlayVictorySound(victim);
|
||||
|
||||
P_DamageMobj(attacker, victim, victim, 1, DMG_STING);
|
||||
|
||||
S_StartSound(victim, sfx_mbv92);
|
||||
K_AddHitLag(attacker, victimHitlag, true);
|
||||
K_AddHitLag(victim, attackerHitlag, false);
|
||||
|
||||
K_DoPowerClash(shield, victim); // REJECTED
|
||||
|
||||
attacker->hitlag = victimHitlag; // No, seriously, we do not care about K_AddHitLag's idea of a normal maximum
|
||||
shield->hitlag = attacker->hitlag;
|
||||
|
||||
shield->extravalue2 = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// if you're here, you're getting hit
|
||||
// Damage is a bit hacky, we want only a small loss-of-control
|
||||
// while still behaving as if it's a "real" hit.
|
||||
P_PlayRinglossSound(victim);
|
||||
P_PlayerRingBurst(victimPlayer, 5);
|
||||
P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a special exception in P_DamageMobj for type==MT_INSTAWHIP
|
||||
|
||||
angle_t thrangle = ANGLE_180 + R_PointToAngle2(victim->x, victim->y, shield->x, shield->y);
|
||||
P_Thrust(victim, thrangle, FRACUNIT*10);
|
||||
|
||||
K_AddHitLag(victim, victimHitlag, true);
|
||||
K_AddHitLag(attacker, attackerHitlag, false);
|
||||
shield->hitlag = attacker->hitlag;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (victim->type == MT_ORBINAUT || victim->type == MT_JAWZ || victim->type == MT_GACHABOM
|
||||
|| victim->type == MT_BANANA || victim->type == MT_EGGMANITEM || victim->type == MT_BALLHOG
|
||||
|| victim->type == MT_SSMINE || victim->type == MT_LANDMINE || victim->type == MT_SINK
|
||||
|| victim->type == MT_GARDENTOP || victim->type == MT_DROPTARGET || victim->type == MT_BATTLECAPSULE
|
||||
|| victim->type == MT_MONITOR || victim->type == MT_SPECIAL_UFO)
|
||||
{
|
||||
// Monitor hack. We can hit monitors once per instawhip, no multihit shredding!
|
||||
// Damage values in Obj_MonitorGetDamage.
|
||||
if (victim->type == MT_MONITOR)
|
||||
{
|
||||
if (shield->extravalue1 == 1)
|
||||
return false;
|
||||
shield->extravalue1 = 1;
|
||||
}
|
||||
|
||||
P_DamageMobj(victim, shield, attacker, 1, DMG_NORMAL);
|
||||
K_AddHitLag(attacker, attackerHitlag, false);
|
||||
shield->hitlag = attacker->hitlag;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
|
||||
|
|
@ -872,12 +1006,13 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
|||
|| (t1->player->invincibilitytimer > 0)
|
||||
|| (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD)
|
||||
|| (t1->player->curshield == KSHIELD_TOP && !K_IsHoldingDownTop(t1->player))
|
||||
|| (t1->player->bubbleblowup > 0);
|
||||
|| (t1->player->bubbleblowup > 0)
|
||||
|| (t1->player->spheres > 0 && K_PlayerEBrake(t1->player));
|
||||
};
|
||||
|
||||
if (canClash(t1, t2) && canClash(t2, t1))
|
||||
{
|
||||
K_DoPowerClash(t1->player, t2->player);
|
||||
K_DoPowerClash(t1, t2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -975,7 +1110,7 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
bool stung = false;
|
||||
|
||||
if (t2->player->rings <= 0)
|
||||
if (t2->player->rings <= 0 && t2->player->spheres <= 0)
|
||||
{
|
||||
P_DamageMobj(t2, t1, t1, 1, DMG_STING|DMG_WOMBO);
|
||||
stung = true;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2);
|
|||
void K_LightningShieldAttack(mobj_t *actor, fixed_t size);
|
||||
boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2);
|
||||
|
||||
boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim);
|
||||
|
||||
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2);
|
||||
|
||||
boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2);
|
||||
|
|
|
|||
143
src/k_kart.c
143
src/k_kart.c
|
|
@ -933,6 +933,14 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2)
|
|||
|
||||
K_SpawnBumpForObjs(mobj1, mobj2);
|
||||
|
||||
if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER)
|
||||
{
|
||||
if (K_PlayerGuard(mobj1->player))
|
||||
K_DoGuardBreak(mobj1, mobj2);
|
||||
if (K_PlayerGuard(mobj2->player))
|
||||
K_DoGuardBreak(mobj2, mobj1);
|
||||
}
|
||||
|
||||
K_PlayerJustBumped(mobj1->player);
|
||||
K_PlayerJustBumped(mobj2->player);
|
||||
|
||||
|
|
@ -1979,6 +1987,7 @@ void K_SpawnMagicianParticles(mobj_t *mo, int spread)
|
|||
dust->frame |= FF_SUBTRACT|FF_TRANS90;
|
||||
dust->color = color;
|
||||
dust->colorized = true;
|
||||
dust->hitlag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3606,28 +3615,54 @@ void K_DoInstashield(player_t *player)
|
|||
P_SetTarget(&layerb->target, player->mo);
|
||||
}
|
||||
|
||||
void K_DoPowerClash(player_t *t1, player_t *t2) {
|
||||
void K_DoPowerClash(mobj_t *t1, mobj_t *t2) {
|
||||
mobj_t *clash;
|
||||
|
||||
// short-circuit instashield for vfx visibility
|
||||
t1->instashield = 1;
|
||||
t2->instashield = 1;
|
||||
if (t1->player)
|
||||
t1->player->instashield = 1;
|
||||
if (t2->player)
|
||||
t2->player->instashield = 1;
|
||||
|
||||
S_StartSound(t1->mo, sfx_parry);
|
||||
K_AddHitLag(t1->mo, 6, false);
|
||||
K_AddHitLag(t2->mo, 6, false);
|
||||
S_StartSound(t1, sfx_parry);
|
||||
K_AddHitLag(t1, 6, false);
|
||||
K_AddHitLag(t2, 6, false);
|
||||
|
||||
clash = P_SpawnMobj((t1->mo->x/2) + (t2->mo->x/2), (t1->mo->y/2) + (t2->mo->y/2), (t1->mo->z/2) + (t2->mo->z/2), MT_POWERCLASH);
|
||||
clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_POWERCLASH);
|
||||
|
||||
// needs to handle mixed scale collisions (t1 grow t2 invinc)...
|
||||
clash->z = clash->z + (t1->mo->height/4) + (t2->mo->height/4);
|
||||
clash->angle = R_PointToAngle2(clash->x, clash->y, t1->mo->x, t1->mo->y) + ANGLE_90;
|
||||
clash->z = clash->z + (t1->height/4) + (t2->height/4);
|
||||
clash->angle = R_PointToAngle2(clash->x, clash->y, t1->x, t1->y) + ANGLE_90;
|
||||
|
||||
// Shrink over time (accidental behavior that looked good)
|
||||
clash->destscale = (t1->mo->scale/2) + (t2->mo->scale/2);
|
||||
clash->destscale = (t1->scale) + (t2->scale);
|
||||
P_SetScale(clash, 3*clash->destscale/2);
|
||||
}
|
||||
|
||||
void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) {
|
||||
mobj_t *clash;
|
||||
|
||||
if (!(t1->player && t2->player))
|
||||
return;
|
||||
|
||||
// short-circuit instashield for vfx visibility
|
||||
t1->player->instaShieldCooldown = 2*TICRATE;
|
||||
t1->player->guardCooldown = 2*TICRATE;
|
||||
|
||||
S_StartSound(t1, sfx_gbrk);
|
||||
K_AddHitLag(t1, 24, true);
|
||||
P_DamageMobj(t1, t2, t2, 1, DMG_STING);
|
||||
|
||||
clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK);
|
||||
|
||||
// needs to handle mixed scale collisions
|
||||
clash->z = clash->z + (t1->height/4) + (t2->height/4);
|
||||
clash->angle = R_PointToAngle2(clash->x, clash->y, t1->x, t1->y) + ANGLE_90;
|
||||
clash->color = t1->color;
|
||||
|
||||
clash->destscale = 3*((t1->scale) + (t2->scale))/2;
|
||||
}
|
||||
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 damage)
|
||||
{
|
||||
UINT8 points = 1;
|
||||
|
|
@ -7777,7 +7812,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
// where's the < 0 check? see below the following block!
|
||||
|
||||
{
|
||||
tic_t spheredigestion = TICRATE; // Base rate of 1 every second when playing.
|
||||
tic_t spheredigestion = TICRATE*2; // Base rate of 1 every 2 seconds when playing.
|
||||
tic_t digestionpower = ((10 - player->kartspeed) + (10 - player->kartweight))-1; // 1 to 17
|
||||
|
||||
// currently 0-34
|
||||
|
|
@ -7789,7 +7824,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
else
|
||||
{
|
||||
spheredigestion -= digestionpower;
|
||||
spheredigestion -= digestionpower/2;
|
||||
}
|
||||
|
||||
if ((player->spheres > 0) && (player->spheredigestion > 0))
|
||||
|
|
@ -7807,6 +7842,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->spheres--;
|
||||
player->spheredigestion = spheredigestion;
|
||||
}
|
||||
|
||||
if (K_PlayerGuard(player) && (player->ebrakefor%6 == 0))
|
||||
player->spheres--;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -7877,6 +7915,19 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
if (player->gateBoost)
|
||||
player->gateBoost--;
|
||||
|
||||
if (player->instaShieldCooldown)
|
||||
{
|
||||
player->instaShieldCooldown--;
|
||||
if (!P_IsObjectOnGround(player->mo))
|
||||
player->instaShieldCooldown = max(player->instaShieldCooldown, 1);
|
||||
}
|
||||
|
||||
if (player->guardCooldown)
|
||||
player->guardCooldown--;
|
||||
|
||||
if (player->whip && P_MobjWasRemoved(player->whip))
|
||||
P_SetTarget(&player->whip, NULL);
|
||||
|
||||
if (player->startboost > 0 && onground == true)
|
||||
{
|
||||
player->startboost--;
|
||||
|
|
@ -7980,6 +8031,22 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
if (player->tiregrease)
|
||||
player->tiregrease--;
|
||||
|
||||
if (player->spinouttimer || player->tumbleBounces)
|
||||
{
|
||||
if (player->incontrol > 0)
|
||||
player->incontrol = 0;
|
||||
player->incontrol--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (player->incontrol < 0)
|
||||
player->incontrol = 0;
|
||||
player->incontrol++;
|
||||
}
|
||||
|
||||
player->incontrol = min(player->incontrol, 5*TICRATE);
|
||||
player->incontrol = max(player->incontrol, -5*TICRATE);
|
||||
|
||||
if (player->tumbleBounces > 0)
|
||||
{
|
||||
K_HandleTumbleSound(player);
|
||||
|
|
@ -8097,6 +8164,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->pflags &= ~PF_DRIFTINPUT;
|
||||
}
|
||||
|
||||
if (K_PlayerGuard(player))
|
||||
player->instaShieldCooldown = max(player->instaShieldCooldown, 12);
|
||||
|
||||
// Roulette Code
|
||||
K_KartItemRoulette(player, cmd);
|
||||
|
||||
|
|
@ -9784,6 +9854,11 @@ boolean K_PlayerEBrake(player_t *player)
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean K_PlayerGuard(player_t *player)
|
||||
{
|
||||
return (K_PlayerEBrake(player) && player->spheres > 0 && player->guardCooldown == 0);
|
||||
}
|
||||
|
||||
SINT8 K_Sliptiding(player_t *player)
|
||||
{
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
|
|
@ -9825,6 +9900,26 @@ void K_KartEbrakeVisuals(player_t *p)
|
|||
if (!S_SoundPlaying(p->mo, sfx_s3kd9s))
|
||||
S_ReducedVFXSound(p->mo, sfx_s3kd9s, p);
|
||||
|
||||
// Block visuals
|
||||
// (These objects track whether a player is block-eligible on their own, no worries)
|
||||
if (!p->ebrakefor)
|
||||
{
|
||||
mobj_t *ring = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_BLOCKRING);
|
||||
P_SetTarget(&ring->target, p->mo);
|
||||
P_SetScale(ring, p->mo->scale);
|
||||
K_MatchGenericExtraFlags(ring, p->mo);
|
||||
ring->renderflags &= ~RF_DONTDRAW;
|
||||
|
||||
mobj_t *body = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_BLOCKBODY);
|
||||
P_SetTarget(&body->target, p->mo);
|
||||
P_SetScale(body, p->mo->scale);
|
||||
K_MatchGenericExtraFlags(body, p->mo);
|
||||
body->renderflags |= RF_DONTDRAW;
|
||||
|
||||
if (K_PlayerGuard(p))
|
||||
S_StartSound(body, sfx_s1af);
|
||||
}
|
||||
|
||||
// HOLD! bubble.
|
||||
if (!p->ebrakefor)
|
||||
{
|
||||
|
|
@ -10538,6 +10633,28 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
// Ring boosting
|
||||
if (player->pflags & PF_USERINGS)
|
||||
{
|
||||
if (ATTACK_IS_DOWN && player->rings <= 0)
|
||||
{
|
||||
if (player->instaShieldCooldown || leveltime < starttime || player->spindash)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_kc50);
|
||||
}
|
||||
else
|
||||
{
|
||||
player->instaShieldCooldown = 50;
|
||||
player->guardCooldown = 50;
|
||||
S_StartSound(player->mo, sfx_iwhp);
|
||||
mobj_t *whip = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTAWHIP);
|
||||
P_SetTarget(&player->whip, whip);
|
||||
P_SetScale(whip, player->mo->scale);
|
||||
P_SetTarget(&whip->target, player->mo);
|
||||
K_MatchGenericExtraFlags(whip, player->mo);
|
||||
whip->fuse = 12; // Changing instawhip animation duration? Look here
|
||||
player->flashing = max(player->flashing, 12);
|
||||
player->mo->momz += 4*mapobjectscale;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd->buttons & BT_ATTACK) && !player->ringdelay && player->rings > 0)
|
||||
{
|
||||
mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING);
|
||||
|
|
@ -11841,7 +11958,7 @@ UINT32 K_PointLimitForGametype(void)
|
|||
{
|
||||
if (D_IsPlayerHumanAndGaming(i))
|
||||
{
|
||||
ptsCap += 3;
|
||||
ptsCap += 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,8 @@ void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
|
|||
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage);
|
||||
void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload);
|
||||
void K_DoInstashield(player_t *player);
|
||||
void K_DoPowerClash(player_t *t1, player_t *t2);
|
||||
void K_DoPowerClash(mobj_t *t1, mobj_t *t2);
|
||||
void K_DoGuardBreak(mobj_t *t1, mobj_t *t2);
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
|
||||
void K_RemoveGrowShrink(player_t *player);
|
||||
boolean K_IsBigger(mobj_t *compare, mobj_t *other);
|
||||
|
|
@ -178,6 +179,7 @@ SINT8 K_GetForwardMove(player_t *player);
|
|||
fixed_t K_GetNewSpeed(player_t *player);
|
||||
fixed_t K_3dKartMovement(player_t *player);
|
||||
boolean K_PlayerEBrake(player_t *player);
|
||||
boolean K_PlayerGuard(player_t *player);
|
||||
SINT8 K_Sliptiding(player_t *player);
|
||||
boolean K_FastFallBounce(player_t *player);
|
||||
fixed_t K_PlayerBaseFriction(player_t *player, fixed_t original);
|
||||
|
|
|
|||
|
|
@ -107,6 +107,14 @@ void Obj_LoopEndpointCollide(mobj_t *special, mobj_t *toucher);
|
|||
void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color);
|
||||
boolean Obj_DropTargetMorphThink(mobj_t *morph);
|
||||
|
||||
/* Instawhip */
|
||||
void Obj_InstaWhipThink(mobj_t *whip);
|
||||
|
||||
/* Block VFX */
|
||||
void Obj_BlockRingThink(mobj_t *ring);
|
||||
void Obj_BlockBodyThink(mobj_t *body);
|
||||
void Obj_GuardBreakThink(mobj_t *fx);
|
||||
|
||||
/* Ring Shooter */
|
||||
boolean Obj_RingShooterThinker(mobj_t *mo);
|
||||
boolean Obj_PlayerRingShooterFreeze(player_t *const player);
|
||||
|
|
|
|||
|
|
@ -319,6 +319,10 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->sliptideZipDelay);
|
||||
else if (fastcmp(field,"sliptideZipBoost"))
|
||||
lua_pushinteger(L, plr->sliptideZipBoost);
|
||||
else if (fastcmp(field,"instaShieldCooldown"))
|
||||
lua_pushinteger(L, plr->instaShieldCooldown);
|
||||
else if (fastcmp(field,"guardCooldown"))
|
||||
lua_pushinteger(L, plr->guardCooldown);
|
||||
/*
|
||||
else if (fastcmp(field,"itemroulette"))
|
||||
lua_pushinteger(L, plr->itemroulette);
|
||||
|
|
@ -713,6 +717,10 @@ static int player_set(lua_State *L)
|
|||
plr->sliptideZipDelay = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"sliptideZipBoost"))
|
||||
plr->sliptideZipBoost = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"instaShieldCooldown"))
|
||||
plr->instaShieldCooldown = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"guardCooldown"))
|
||||
plr->guardCooldown = luaL_checkinteger(L, 3);
|
||||
/*
|
||||
else if (fastcmp(field,"itemroulette"))
|
||||
plr->itemroulette = luaL_checkinteger(L, 3);
|
||||
|
|
|
|||
|
|
@ -17,4 +17,6 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
ring-shooter.c
|
||||
audience.c
|
||||
random-item.c
|
||||
instawhip.c
|
||||
block.c
|
||||
)
|
||||
|
|
|
|||
84
src/objects/block.c
Normal file
84
src/objects/block.c
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#include "../doomdef.h"
|
||||
#include "../info.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../p_local.h"
|
||||
#include "../k_kart.h"
|
||||
|
||||
void Obj_BlockRingThink (mobj_t *ring)
|
||||
{
|
||||
if (P_MobjWasRemoved(ring->target) || !ring->target->player || !ring->target->player->ebrakefor)
|
||||
{
|
||||
P_RemoveMobj(ring);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = ring->target;
|
||||
player_t *player = mo->player;
|
||||
|
||||
// Follow player
|
||||
ring->flags &= ~(MF_NOCLIPTHING);
|
||||
P_MoveOrigin(ring, mo->x, mo->y, mo->z + mo->height/2);
|
||||
ring->flags |= MF_NOCLIPTHING;
|
||||
ring->color = mo->color;
|
||||
|
||||
fixed_t baseScale = mo->scale / 2;
|
||||
baseScale += (mo->scale / 30) * player->spheres;
|
||||
P_SetScale(ring, baseScale);
|
||||
|
||||
// Twirl
|
||||
ring->angle = ring->target->angle + (ANG15 * leveltime);
|
||||
// Visuals
|
||||
ring->renderflags |= RF_ADD|RF_PAPERSPRITE;
|
||||
|
||||
if (leveltime%2)
|
||||
ring->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
ring->renderflags |= RF_DONTDRAW;
|
||||
|
||||
if (!K_PlayerGuard(player))
|
||||
ring->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_BlockBodyThink (mobj_t *body)
|
||||
{
|
||||
if (P_MobjWasRemoved(body->target) || !body->target->player || !body->target->player->ebrakefor)
|
||||
{
|
||||
P_RemoveMobj(body);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = body->target;
|
||||
player_t *player = mo->player;
|
||||
|
||||
// Follow player
|
||||
body->flags &= ~(MF_NOCLIPTHING);
|
||||
|
||||
fixed_t baseScale = mo->scale / 2;
|
||||
baseScale += (mo->scale / 30) * player->spheres;
|
||||
P_SetScale(body, baseScale);
|
||||
|
||||
P_MoveOrigin(body, mo->x, mo->y, mo->z + mo->height/2);
|
||||
body->flags |= MF_NOCLIPTHING;
|
||||
body->color = mo->color;
|
||||
|
||||
// Visuals
|
||||
body->renderflags |= RF_ADD;
|
||||
|
||||
if (leveltime%2 == 0)
|
||||
body->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
body->renderflags |= RF_DONTDRAW;
|
||||
|
||||
if (!K_PlayerGuard(player))
|
||||
body->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_GuardBreakThink (mobj_t *fx)
|
||||
{
|
||||
if (leveltime%2)
|
||||
fx->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
fx->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
42
src/objects/instawhip.c
Normal file
42
src/objects/instawhip.c
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include "../doomdef.h"
|
||||
#include "../info.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../p_local.h"
|
||||
|
||||
void Obj_InstaWhipThink (mobj_t *whip)
|
||||
{
|
||||
if (P_MobjWasRemoved(whip->target))
|
||||
{
|
||||
P_RemoveMobj(whip);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = whip->target;
|
||||
player_t *player = mo->player;
|
||||
|
||||
// Follow player
|
||||
whip->flags &= ~(MF_NOCLIPTHING);
|
||||
P_SetScale(whip, whip->target->scale);
|
||||
P_MoveOrigin(whip, mo->x, mo->y, mo->z + mo->height/2);
|
||||
whip->flags |= MF_NOCLIPTHING;
|
||||
|
||||
// Twirl
|
||||
whip->angle = whip->target->angle + (ANG30 * 2 * whip->fuse);
|
||||
whip->target->player->drawangle = whip->angle;
|
||||
if (player->follower)
|
||||
player->follower->angle = whip->angle;
|
||||
player->pflags |= PF_GAINAX;
|
||||
player->glanceDir = -2;
|
||||
|
||||
// Visuals
|
||||
whip->renderflags |= RF_NOSPLATBILLBOARD;
|
||||
|
||||
if (whip->renderflags & RF_DONTDRAW)
|
||||
whip->renderflags &= ~RF_DONTDRAW;
|
||||
else
|
||||
whip->renderflags |= RF_DONTDRAW;
|
||||
|
||||
if (whip->extravalue2) // Whip has no hitbox but removing it is a pain in the ass
|
||||
whip->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
}
|
||||
|
|
@ -440,9 +440,15 @@ adjust_monitor_drop
|
|||
( mobj_t * monitor,
|
||||
mobj_t * drop)
|
||||
{
|
||||
P_InstaThrust(drop, drop->angle, 4*mapobjectscale);
|
||||
|
||||
drop->momz *= 8;
|
||||
if (drop->type == MT_EMERALD)
|
||||
{
|
||||
drop->momx = drop->momy = drop->momz = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
P_InstaThrust(drop, drop->angle, 8*mapobjectscale);
|
||||
drop->momz *= 8;
|
||||
}
|
||||
|
||||
K_FlipFromObject(drop, monitor);
|
||||
|
||||
|
|
@ -615,7 +621,16 @@ Obj_MonitorGetDamage
|
|||
}
|
||||
else
|
||||
{
|
||||
damage = FRACUNIT; // kill instantly
|
||||
if (inflictor->type == MT_INSTAWHIP)
|
||||
{
|
||||
damage = FRACUNIT/3;
|
||||
if (K_IsPlayerWanted(inflictor->target->player))
|
||||
damage = FRACUNIT; // Emerald hunting time!
|
||||
}
|
||||
else
|
||||
{
|
||||
damage = FRACUNIT; // kill instantly
|
||||
}
|
||||
}
|
||||
|
||||
return damage;
|
||||
|
|
|
|||
|
|
@ -670,6 +670,7 @@ static UINT8 GetUFODamage(mobj_t *inflictor, UINT8 damageType)
|
|||
{
|
||||
case MT_JAWZ_SHIELD:
|
||||
case MT_ORBINAUT_SHIELD:
|
||||
case MT_INSTAWHIP:
|
||||
{
|
||||
// Shields deal chip damage.
|
||||
return 10;
|
||||
|
|
|
|||
|
|
@ -2188,6 +2188,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (!force)
|
||||
{
|
||||
boolean invincible = true;
|
||||
boolean clash = false;
|
||||
sfxenum_t sfx = sfx_None;
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS))
|
||||
|
|
@ -2208,6 +2209,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
{
|
||||
sfx = sfx_grownd;
|
||||
}
|
||||
else if (K_PlayerGuard(player))
|
||||
{
|
||||
sfx = sfx_s3k3a;
|
||||
clash = true;
|
||||
}
|
||||
else if (player->hyudorotimer > 0)
|
||||
;
|
||||
else
|
||||
|
|
@ -2249,6 +2255,15 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
S_StartSound(target, sfx);
|
||||
}
|
||||
|
||||
if (clash)
|
||||
{
|
||||
player->spheres = max(player->spheres - 10, 0);
|
||||
if (inflictor)
|
||||
K_DoPowerClash(target, inflictor);
|
||||
else if (source)
|
||||
K_DoPowerClash(target, source);
|
||||
}
|
||||
|
||||
// Full invulnerability
|
||||
K_DoInstashield(player);
|
||||
return false;
|
||||
|
|
@ -2306,7 +2321,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
damage = 0;
|
||||
}
|
||||
|
||||
if (type == DMG_STING || type == DMG_STUMBLE)
|
||||
// Instawhip breaks the rules and does "damaging stumble",
|
||||
// but sting and stumble shouldn't be rewarding Battle hits otherwise.
|
||||
if ((type == DMG_STING || type == DMG_STUMBLE) && (inflictor && inflictor->type != MT_INSTAWHIP))
|
||||
{
|
||||
damage = 0;
|
||||
}
|
||||
|
|
@ -2426,6 +2443,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
K_PlayPainSound(target, source);
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_BUMPERS)
|
||||
player->spheres = min(player->spheres + 5, 40);
|
||||
|
||||
if ((hardhit == true) || cv_kartdebughuddrop.value)
|
||||
{
|
||||
K_DropItems(player);
|
||||
|
|
|
|||
12
src/p_map.c
12
src/p_map.c
|
|
@ -741,7 +741,17 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
|||
return BMIT_ABORT; // stop moving
|
||||
}
|
||||
|
||||
// SRB2kart 011617 - Colission[sic] code for kart items //{
|
||||
// SRB2kart 011617 - Colission[sic] code for kart items //
|
||||
|
||||
if (tm.thing->type == MT_INSTAWHIP)
|
||||
{
|
||||
if (tm.thing->z > thing->z + thing->height)
|
||||
return BMIT_CONTINUE; // overhead
|
||||
if (tm.thing->z + tm.thing->height < thing->z)
|
||||
return BMIT_CONTINUE; // underneath
|
||||
K_InstaWhipCollide(tm.thing, thing);
|
||||
return BMIT_CONTINUE;
|
||||
}
|
||||
|
||||
if (thing->type == MT_SPB)
|
||||
{
|
||||
|
|
|
|||
20
src/p_mobj.c
20
src/p_mobj.c
|
|
@ -8356,6 +8356,26 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
Obj_GardenTopThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_INSTAWHIP:
|
||||
{
|
||||
Obj_InstaWhipThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BLOCKRING:
|
||||
{
|
||||
Obj_BlockRingThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BLOCKBODY:
|
||||
{
|
||||
Obj_BlockBodyThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_GUARDBREAK:
|
||||
{
|
||||
Obj_GuardBreakThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_GARDENTOPSPARK:
|
||||
{
|
||||
Obj_GardenTopSparkThink(mobj);
|
||||
|
|
|
|||
|
|
@ -74,7 +74,8 @@ typedef enum
|
|||
HOVERHYUDORO = 0x0020,
|
||||
STUMBLE = 0x0040,
|
||||
SLIPTIDEZIP = 0x0080,
|
||||
RINGSHOOTER = 0x0100
|
||||
RINGSHOOTER = 0x0100,
|
||||
WHIP = 0x0200,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(savebuffer_t *save)
|
||||
|
|
@ -225,6 +226,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (players[i].sliptideZipIndicator)
|
||||
flags |= SLIPTIDEZIP;
|
||||
|
||||
if (players[i].whip)
|
||||
flags |= WHIP;
|
||||
|
||||
if (players[i].ringShooter)
|
||||
flags |= RINGSHOOTER;
|
||||
|
||||
|
|
@ -251,6 +255,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (flags & SLIPTIDEZIP)
|
||||
WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum);
|
||||
|
||||
if (flags & WHIP)
|
||||
WRITEUINT32(save->p, players[i].whip->mobjnum);
|
||||
|
||||
if (flags & RINGSHOOTER)
|
||||
WRITEUINT32(save->p, players[i].ringShooter->mobjnum);
|
||||
|
||||
|
|
@ -419,6 +426,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEMEM(save->p, players[i].public_key, PUBKEYLENGTH);
|
||||
|
||||
WRITEUINT8(save->p, players[i].instaShieldCooldown);
|
||||
WRITEUINT8(save->p, players[i].guardCooldown);
|
||||
WRITEINT16(save->p, players[i].incontrol);
|
||||
|
||||
// respawnvars_t
|
||||
WRITEUINT8(save->p, players[i].respawn.state);
|
||||
WRITEUINT32(save->p, K_GetWaypointHeapIndex(players[i].respawn.wp));
|
||||
|
|
@ -635,6 +646,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
if (flags & SLIPTIDEZIP)
|
||||
players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & WHIP)
|
||||
players[i].whip = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & RINGSHOOTER)
|
||||
players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
|
|
@ -804,6 +818,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
READMEM(save->p, players[i].public_key, PUBKEYLENGTH);
|
||||
|
||||
players[i].instaShieldCooldown = READUINT8(save->p);
|
||||
players[i].guardCooldown = READUINT8(save->p);
|
||||
players[i].incontrol = READINT16(save->p);
|
||||
|
||||
// respawnvars_t
|
||||
players[i].respawn.state = READUINT8(save->p);
|
||||
players[i].respawn.wp = (waypoint_t *)(size_t)READUINT32(save->p);
|
||||
|
|
@ -4982,6 +5000,13 @@ static void P_RelinkPointers(void)
|
|||
if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].whip)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].whip;
|
||||
players[i].whip = NULL;
|
||||
if (!P_SetTarget(&players[i].whip, P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "whip not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].ringShooter)
|
||||
{
|
||||
temp = (UINT32)(size_t)players[i].ringShooter;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
#include "k_kart.h" // HITLAGJITTERS
|
||||
#include "r_fps.h"
|
||||
|
||||
#define MINZ (FRACUNIT*16)
|
||||
#define MINZ (FRACUNIT*4)
|
||||
#define BASEYCENTER (BASEVIDHEIGHT/2)
|
||||
|
||||
typedef struct
|
||||
|
|
|
|||
|
|
@ -901,7 +901,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"mbv8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv92", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Changed falloff for use in instashield parry.
|
||||
{"mbv93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"mbv95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
@ -1184,6 +1184,9 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"},
|
||||
|
||||
{"iwhp", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Instawhip attack
|
||||
{"gbrk", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Guard break!
|
||||
|
||||
// SRB2Kart - Engine sounds
|
||||
// Engine class A
|
||||
{"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
|
|||
|
|
@ -1253,6 +1253,9 @@ typedef enum
|
|||
sfx_monch,
|
||||
sfx_etexpl,
|
||||
|
||||
sfx_iwhp,
|
||||
sfx_gbrk,
|
||||
|
||||
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
|
||||
// Engine class A - Low Speed, Low Weight
|
||||
sfx_krta00,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue