mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-03-15 07:31:55 +00:00
Minor (but important!) polishing
- Thunder Shield now attracts rings - Colorize the ring counter at max yellow - Rings in the collecting animation are considered for determining if you can't pick up rings anymore, preventing a LOT of rings being deleted from the map over time. - Flung rings don't lose speed over time anymore - Flund rings last way longer - Using rings is much less touchy (holding the button from before an item roulette will let you continue using them until you let go, using certain items won't make you use a couple rings afterwards) - 0 rings is now counted as debt when getting hit, making debt easier to get out of (getting hit by a spike now would put you at -2 instead of -5) - Move Super Ring toward the end of the item (so I don't have to modify gfx.kart to fix dropped items)
This commit is contained in:
parent
4a68f98dc2
commit
db8f23561d
6 changed files with 545 additions and 471 deletions
|
|
@ -234,7 +234,6 @@ typedef enum
|
|||
{
|
||||
KITEM_SAD = -1,
|
||||
KITEM_NONE = 0,
|
||||
KITEM_SUPERRING,
|
||||
KITEM_SNEAKER,
|
||||
KITEM_ROCKETSNEAKER,
|
||||
KITEM_INVINCIBILITY,
|
||||
|
|
@ -250,6 +249,7 @@ typedef enum
|
|||
KITEM_THUNDERSHIELD,
|
||||
KITEM_HYUDORO,
|
||||
KITEM_POGOSPRING,
|
||||
KITEM_SUPERRING,
|
||||
KITEM_KITCHENSINK,
|
||||
|
||||
NUMKARTITEMS,
|
||||
|
|
@ -298,6 +298,8 @@ typedef enum
|
|||
k_boostcharge, // Charge-up for boosting at the start of the race
|
||||
k_startboost, // Boost you get from start of race or respawn drop dash
|
||||
k_rings, // Number of held rings
|
||||
k_pickuprings, // Number of rings being picked up before added to the counter (prevents rings from being deleted forever over 20)
|
||||
k_userings, // Have to be not holding the item button to change from using rings to using items (or vice versa), to prevent some weirdness with the button
|
||||
k_ringdelay, // 3 tic delay between every ring usage
|
||||
k_ringboost, // Ring boost timer
|
||||
k_jmp, // In Mario Kart, letting go of the jump button stops the drift
|
||||
|
|
|
|||
|
|
@ -8355,6 +8355,8 @@ static const char *const KARTSTUFF_LIST[] = {
|
|||
"BOOSTCHARGE",
|
||||
"STARTBOOST",
|
||||
"RINGS",
|
||||
"PICKUPRINGS",
|
||||
"USERINGS",
|
||||
"RINGDELAY",
|
||||
"RINGBOOST",
|
||||
"JMP",
|
||||
|
|
@ -8943,7 +8945,6 @@ struct {
|
|||
// kartitems_t
|
||||
{"KITEM_SAD",KITEM_SAD}, // Actual items (can be set for k_itemtype)
|
||||
{"KITEM_NONE",KITEM_NONE},
|
||||
{"KITEM_SUPERRING",KITEM_SUPERRING},
|
||||
{"KITEM_SNEAKER",KITEM_SNEAKER},
|
||||
{"KITEM_ROCKETSNEAKER",KITEM_ROCKETSNEAKER},
|
||||
{"KITEM_INVINCIBILITY",KITEM_INVINCIBILITY},
|
||||
|
|
@ -8959,6 +8960,7 @@ struct {
|
|||
{"KITEM_THUNDERSHIELD",KITEM_THUNDERSHIELD},
|
||||
{"KITEM_HYUDORO",KITEM_HYUDORO},
|
||||
{"KITEM_POGOSPRING",KITEM_POGOSPRING},
|
||||
{"KITEM_SUPERRING",KITEM_SUPERRING},
|
||||
{"KITEM_KITCHENSINK",KITEM_KITCHENSINK},
|
||||
{"NUMKARTITEMS",NUMKARTITEMS},
|
||||
{"KRITEM_TRIPLESNEAKER",KRITEM_TRIPLESNEAKER}, // Additional roulette IDs (not usable for much in Lua besides K_GetItemPatch)
|
||||
|
|
|
|||
863
src/k_kart.c
863
src/k_kart.c
|
|
@ -1136,6 +1136,24 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
|
||||
// SPECIAL CASE No. 4:
|
||||
// Being in ring debt occasionally forces Super Ring on you
|
||||
if (player->kartstuff[k_rings] <= 0 && cv_superring.value)
|
||||
{
|
||||
INT32 debtamount = min(20, abs(player->kartstuff[k_rings])+1);
|
||||
if (P_RandomChance((debtamount*FRACUNIT)/20))
|
||||
{
|
||||
K_KartGetItemResult(player, KITEM_SUPERRING);
|
||||
player->kartstuff[k_itemblink] = TICRATE;
|
||||
player->kartstuff[k_itemblinkmode] = (mashed ? 1 : 0);
|
||||
player->kartstuff[k_itemroulette] = 0;
|
||||
player->kartstuff[k_roulettetype] = 0;
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// SPECIAL CASE No. 5:
|
||||
// Force SPB onto 2nd if they get too far behind
|
||||
if (player->kartstuff[k_position] == 2 && pdis > (DISTVAR*6)
|
||||
&& spbplace == -1 && !indirectitemcooldown && !dontforcespb
|
||||
|
|
@ -1148,6 +1166,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd)
|
|||
player->kartstuff[k_roulettetype] = 0;
|
||||
if (P_IsLocalPlayer(player))
|
||||
S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf));
|
||||
return;
|
||||
}
|
||||
|
||||
// NOW that we're done with all of those specialized cases, we can move onto the REAL item roulette tables.
|
||||
|
|
@ -1418,6 +1437,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
|
|||
{
|
||||
mobj1->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1;
|
||||
mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]);
|
||||
//mobj1->player->kartstuff[k_spinouttype] = 1; // Enforce type
|
||||
}
|
||||
else if (mobj2->player) // Player VS player bumping only
|
||||
{
|
||||
|
|
@ -1440,6 +1460,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
|
|||
{
|
||||
mobj2->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1;
|
||||
mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]);
|
||||
//mobj2->player->kartstuff[k_spinouttype] = 1; // Enforce type
|
||||
}
|
||||
else if (mobj1->player) // Player VS player bumping only
|
||||
{
|
||||
|
|
@ -1742,6 +1763,7 @@ void K_RespawnChecker(player_t *player)
|
|||
player->mo->colorized = false;
|
||||
player->kartstuff[k_dropdash] = 0;
|
||||
player->kartstuff[k_respawn] = 0;
|
||||
//P_PlayRinglossSound(player->mo);
|
||||
P_PlayerRingBurst(player, 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -4804,6 +4826,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
ring->extravalue1 = 1; // Ring collect animation timer
|
||||
ring->angle = player->mo->angle; // animation angle
|
||||
P_SetTarget(&ring->target, player->mo); // toucher for thinker
|
||||
player->kartstuff[k_pickuprings]++;
|
||||
if (player->kartstuff[k_superring] <= 3)
|
||||
ring->cvmem = 1; // play caching when collected
|
||||
}
|
||||
|
|
@ -5428,7 +5451,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
else if (cmd->buttons & BT_ATTACK)
|
||||
player->pflags |= PF_ATTACKDOWN;
|
||||
|
||||
if (player && player->mo && player->mo->health > 0 && !player->spectator && !(player->exiting || mapreset)
|
||||
if (player && player->mo && player->mo->health > 0 && !player->spectator && !(player->exiting || mapreset) && leveltime > starttime
|
||||
&& player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0 && player->kartstuff[k_respawn] == 0)
|
||||
{
|
||||
// First, the really specific, finicky items that function without the item being directly in your item slot.
|
||||
|
|
@ -5464,418 +5487,436 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
S_StartSound(player->mo, sfx_s254);
|
||||
}
|
||||
}
|
||||
// Eggman Monitor exploding
|
||||
else if (player->kartstuff[k_eggmanexplode])
|
||||
{
|
||||
if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1)
|
||||
player->kartstuff[k_eggmanexplode] = 1;
|
||||
}
|
||||
// Eggman Monitor throwing
|
||||
else if (player->kartstuff[k_eggmanheld])
|
||||
{
|
||||
if (ATTACK_IS_DOWN)
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_eggmanheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
}
|
||||
// Rocket Sneaker usage
|
||||
else if (player->kartstuff[k_rocketsneakertimer] > 1)
|
||||
{
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
|
||||
{
|
||||
K_DoSneaker(player, 2);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE;
|
||||
if (player->kartstuff[k_rocketsneakertimer] < 1)
|
||||
player->kartstuff[k_rocketsneakertimer] = 1;
|
||||
}
|
||||
}
|
||||
// Grow Canceling
|
||||
else if (player->kartstuff[k_growshrinktimer] > 0)
|
||||
{
|
||||
if (cmd->buttons & BT_ATTACK)
|
||||
{
|
||||
player->kartstuff[k_growcancel]++;
|
||||
if (player->kartstuff[k_growcancel] > 26)
|
||||
K_RemoveGrowShrink(player);
|
||||
}
|
||||
else
|
||||
player->kartstuff[k_growcancel] = 0;
|
||||
}
|
||||
// Ring boosting
|
||||
else if (player->kartstuff[k_itemtype] == KITEM_NONE)
|
||||
{
|
||||
if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay]
|
||||
&& player->kartstuff[k_rings] > 0)
|
||||
{
|
||||
mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING);
|
||||
ring->extravalue1 = 1; // Ring use animation timer
|
||||
ring->extravalue2 = 1; // Ring use animation flag
|
||||
P_SetTarget(&ring->target, player->mo); // user
|
||||
player->kartstuff[k_rings]--;
|
||||
player->kartstuff[k_ringdelay] = 3;
|
||||
}
|
||||
}
|
||||
else if (player->kartstuff[k_itemamount] <= 0)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (player->kartstuff[k_itemtype])
|
||||
// Ring boosting
|
||||
if (player->kartstuff[k_userings])
|
||||
{
|
||||
case KITEM_SUPERRING:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
if ((player->pflags & PF_ATTACKDOWN) && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& !player->kartstuff[k_itemroulette] && !player->kartstuff[k_ringdelay]
|
||||
&& player->kartstuff[k_rings] > 0)
|
||||
{
|
||||
mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING);
|
||||
ring->extravalue1 = 1; // Ring use animation timer
|
||||
ring->extravalue2 = 1; // Ring use animation flag
|
||||
P_SetTarget(&ring->target, player->mo); // user
|
||||
player->kartstuff[k_rings]--;
|
||||
player->kartstuff[k_ringdelay] = 3;
|
||||
}
|
||||
}
|
||||
// Other items
|
||||
else
|
||||
{
|
||||
// Eggman Monitor exploding
|
||||
if (player->kartstuff[k_eggmanexplode])
|
||||
{
|
||||
if (ATTACK_IS_DOWN && player->kartstuff[k_eggmanexplode] <= 3*TICRATE && player->kartstuff[k_eggmanexplode] > 1)
|
||||
player->kartstuff[k_eggmanexplode] = 1;
|
||||
}
|
||||
// Eggman Monitor throwing
|
||||
else if (player->kartstuff[k_eggmanheld])
|
||||
{
|
||||
if (ATTACK_IS_DOWN)
|
||||
{
|
||||
player->kartstuff[k_superring] += (10*3);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_ThrowKartItem(player, false, MT_EGGMANITEM, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_eggmanheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
break;
|
||||
case KITEM_SNEAKER:
|
||||
}
|
||||
// Rocket Sneaker usage
|
||||
else if (player->kartstuff[k_rocketsneakertimer] > 1)
|
||||
{
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
|
||||
{
|
||||
K_DoSneaker(player, 1);
|
||||
K_DoSneaker(player, 2);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_rocketsneakertimer] -= 2*TICRATE;
|
||||
if (player->kartstuff[k_rocketsneakertimer] < 1)
|
||||
player->kartstuff[k_rocketsneakertimer] = 1;
|
||||
}
|
||||
break;
|
||||
case KITEM_ROCKETSNEAKER:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& player->kartstuff[k_rocketsneakertimer] == 0)
|
||||
}
|
||||
// Grow Canceling
|
||||
else if (player->kartstuff[k_growshrinktimer] > 0)
|
||||
{
|
||||
if (cmd->buttons & BT_ATTACK)
|
||||
{
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
//player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
//K_DoSneaker(player, 2);
|
||||
|
||||
player->kartstuff[k_rocketsneakertimer] = (itemtime*3);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, true);
|
||||
|
||||
for (moloop = 0; moloop < 2; moloop++)
|
||||
{
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER);
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = player->mo->angle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = moloop%2;
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
player->kartstuff[k_growcancel]++;
|
||||
if (player->kartstuff[k_growcancel] > 26)
|
||||
K_RemoveGrowShrink(player);
|
||||
}
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple
|
||||
else
|
||||
player->kartstuff[k_growcancel] = 0;
|
||||
}
|
||||
else if (player->kartstuff[k_itemamount] <= 0)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = player->kartstuff[k_itemheld] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (player->kartstuff[k_itemtype])
|
||||
{
|
||||
if (!player->kartstuff[k_invincibilitytimer])
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
overlay->destscale = player->mo->scale;
|
||||
P_SetScale(overlay, player->mo->scale);
|
||||
}
|
||||
player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds
|
||||
P_RestoreMusic(player);
|
||||
if (!P_IsLocalPlayer(player))
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_BANANA:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
INT32 moloop;
|
||||
mobj_t *mo;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD);
|
||||
if (!mo)
|
||||
case KITEM_SNEAKER:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
K_DoSneaker(player, 1);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_BANANA, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_EGGMAN:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_eggmanheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KITEM_ORBINAUT:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
angle_t newangle;
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD);
|
||||
if (!mo)
|
||||
break;
|
||||
case KITEM_ROCKETSNEAKER:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& player->kartstuff[k_rocketsneakertimer] == 0)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
//player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
//K_DoSneaker(player, 2);
|
||||
|
||||
player->kartstuff[k_rocketsneakertimer] = (itemtime*3);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, true);
|
||||
|
||||
for (moloop = 0; moloop < 2; moloop++)
|
||||
{
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER);
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = player->mo->angle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = moloop%2;
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = newangle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
mo->color = player->skincolor;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown
|
||||
{
|
||||
K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_JAWZ:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
angle_t newangle;
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD);
|
||||
if (!mo)
|
||||
break;
|
||||
case KITEM_INVINCIBILITY:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
if (!player->kartstuff[k_invincibilitytimer])
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
overlay->destscale = player->mo->scale;
|
||||
P_SetScale(overlay, player->mo->scale);
|
||||
}
|
||||
player->kartstuff[k_invincibilitytimer] = itemtime+(2*TICRATE); // 10 seconds
|
||||
P_RestoreMusic(player);
|
||||
if (!P_IsLocalPlayer(player))
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = newangle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
break;
|
||||
case KITEM_BANANA:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
INT32 moloop;
|
||||
mobj_t *mo;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_BANANA_SHIELD);
|
||||
if (!mo)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Banana x3 thrown
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_BANANA, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_EGGMAN:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_eggmanheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EGGMANITEM_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KITEM_ORBINAUT:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
angle_t newangle;
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ORBINAUT_SHIELD);
|
||||
if (!mo)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = newangle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
mo->color = player->skincolor;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld]) // Orbinaut x3 thrown
|
||||
{
|
||||
K_ThrowKartItem(player, true, MT_ORBINAUT, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_JAWZ:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
angle_t newangle;
|
||||
INT32 moloop;
|
||||
mobj_t *mo = NULL;
|
||||
mobj_t *prev = player->mo;
|
||||
|
||||
//K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s3k3a);
|
||||
|
||||
for (moloop = 0; moloop < player->kartstuff[k_itemamount]; moloop++)
|
||||
{
|
||||
newangle = (player->mo->angle + ANGLE_157h) + FixedAngle(((360 / player->kartstuff[k_itemamount]) * moloop) << FRACBITS) + ANGLE_90;
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_JAWZ_SHIELD);
|
||||
if (!mo)
|
||||
{
|
||||
player->kartstuff[k_itemamount] = moloop;
|
||||
break;
|
||||
}
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->angle = newangle;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = player->kartstuff[k_itemamount];
|
||||
mo->movedir = mo->lastlook = moloop+1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&mo->hprev, prev);
|
||||
P_SetTarget(&prev->hnext, mo);
|
||||
prev = mo;
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown
|
||||
{
|
||||
if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0)
|
||||
K_ThrowKartItem(player, true, MT_JAWZ, 1, 0);
|
||||
else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in
|
||||
K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_MINE:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld])
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_SSMINE, 1, 1);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_itemheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
break;
|
||||
case KITEM_BALLHOG:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_SPB:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_ThrowKartItem(player, true, MT_SPB, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_GROW:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage
|
||||
{
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
player->mo->scalespeed = mapobjectscale/TICRATE;
|
||||
player->mo->destscale = (3*mapobjectscale)/2;
|
||||
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
|
||||
player->mo->destscale = (6*player->mo->destscale)/8;
|
||||
player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds
|
||||
P_RestoreMusic(player);
|
||||
if (!P_IsLocalPlayer(player))
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow));
|
||||
S_StartSound(player->mo, sfx_kc5a);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_SHRINK:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
K_DoShrink(player);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_THUNDERSHIELD:
|
||||
if (player->kartstuff[k_curshield] != 1)
|
||||
{
|
||||
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD);
|
||||
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
|
||||
P_SetTarget(&shield->target, player->mo);
|
||||
S_StartSound(shield, sfx_s3k41);
|
||||
player->kartstuff[k_curshield] = 1;
|
||||
}
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
K_DoThunderShield(player);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_HYUDORO:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_DoHyudoroSteal(player); // yes. yes they do.
|
||||
}
|
||||
break;
|
||||
case KITEM_POGOSPRING:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& !player->kartstuff[k_pogospring])
|
||||
{
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
|
||||
player->kartstuff[k_pogospring] = 1;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_SUPERRING:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_superring] += (10*3);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_KITCHENSINK:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_SINK, 1, 2);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_itemheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
break;
|
||||
case KITEM_SAD:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& !player->kartstuff[k_sadtimer])
|
||||
{
|
||||
player->kartstuff[k_sadtimer] = stealtime;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Jawz thrown
|
||||
{
|
||||
if (player->kartstuff[k_throwdir] == 1 || player->kartstuff[k_throwdir] == 0)
|
||||
K_ThrowKartItem(player, true, MT_JAWZ, 1, 0);
|
||||
else if (player->kartstuff[k_throwdir] == -1) // Throwing backward gives you a dud that doesn't home in
|
||||
K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_UpdateHnextList(player, false);
|
||||
}
|
||||
break;
|
||||
case KITEM_MINE:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SSMINE_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && player->kartstuff[k_itemheld])
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_SSMINE, 1, 1);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_itemheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
break;
|
||||
case KITEM_BALLHOG:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_ThrowKartItem(player, true, MT_BALLHOG, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_SPB:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_ThrowKartItem(player, true, MT_SPB, 1, 0);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_GROW:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& player->kartstuff[k_growshrinktimer] <= 0) // Grow holds the item box hostage
|
||||
{
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
player->mo->scalespeed = mapobjectscale/TICRATE;
|
||||
player->mo->destscale = (3*mapobjectscale)/2;
|
||||
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
|
||||
player->mo->destscale = (6*player->mo->destscale)/8;
|
||||
player->kartstuff[k_growshrinktimer] = itemtime+(4*TICRATE); // 12 seconds
|
||||
P_RestoreMusic(player);
|
||||
if (!P_IsLocalPlayer(player))
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmg : sfx_kgrow));
|
||||
S_StartSound(player->mo, sfx_kc5a);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_SHRINK:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
K_DoShrink(player);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_THUNDERSHIELD:
|
||||
if (player->kartstuff[k_curshield] != 1)
|
||||
{
|
||||
mobj_t *shield = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THUNDERSHIELD);
|
||||
P_SetScale(shield, (shield->destscale = (5*shield->destscale)>>2));
|
||||
P_SetTarget(&shield->target, player->mo);
|
||||
S_StartSound(shield, sfx_s3k41);
|
||||
player->kartstuff[k_curshield] = 1;
|
||||
}
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
K_DoThunderShield(player);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
}
|
||||
break;
|
||||
case KITEM_HYUDORO:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->kartstuff[k_itemamount]--;
|
||||
K_DoHyudoroSteal(player); // yes. yes they do.
|
||||
}
|
||||
break;
|
||||
case KITEM_POGOSPRING:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO
|
||||
&& !player->kartstuff[k_pogospring])
|
||||
{
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
|
||||
player->kartstuff[k_pogospring] = 1;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
case KITEM_KITCHENSINK:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
mobj_t *mo;
|
||||
player->kartstuff[k_itemheld] = 1;
|
||||
S_StartSound(player->mo, sfx_s254);
|
||||
mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SINK_SHIELD);
|
||||
if (mo)
|
||||
{
|
||||
mo->flags |= MF_NOCLIPTHING;
|
||||
mo->threshold = 10;
|
||||
mo->movecount = 1;
|
||||
mo->movedir = 1;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
P_SetTarget(&player->mo->hnext, mo);
|
||||
}
|
||||
}
|
||||
else if (ATTACK_IS_DOWN && HOLDING_ITEM && player->kartstuff[k_itemheld]) // Sink thrown
|
||||
{
|
||||
K_ThrowKartItem(player, false, MT_SINK, 1, 2);
|
||||
K_PlayAttackTaunt(player->mo);
|
||||
player->kartstuff[k_itemamount]--;
|
||||
player->kartstuff[k_itemheld] = 0;
|
||||
K_UpdateHnextList(player, true);
|
||||
}
|
||||
break;
|
||||
case KITEM_SAD:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO
|
||||
&& !player->kartstuff[k_sadtimer])
|
||||
{
|
||||
player->kartstuff[k_sadtimer] = stealtime;
|
||||
player->kartstuff[k_itemamount]--;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent ring misfire
|
||||
if (player->kartstuff[k_itemtype] != KITEM_NONE)
|
||||
player->kartstuff[k_ringdelay] = 15;
|
||||
if (!ATTACK_IS_DOWN)
|
||||
{
|
||||
if (player->kartstuff[k_itemtype] == KITEM_NONE
|
||||
&& !(player->kartstuff[k_growshrinktimer]
|
||||
|| player->kartstuff[k_rocketsneakertimer]
|
||||
|| player->kartstuff[k_eggmanheld]
|
||||
|| player->kartstuff[k_eggmanexplode]
|
||||
|| player->kartstuff[k_rocketsneakertimer]
|
||||
|| player->kartstuff[k_growshrinktimer]))
|
||||
player->kartstuff[k_userings] = 1;
|
||||
else
|
||||
player->kartstuff[k_userings] = 0;
|
||||
}
|
||||
|
||||
// No more!
|
||||
if (!player->kartstuff[k_itemamount])
|
||||
|
|
@ -6732,8 +6773,6 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny)
|
|||
{
|
||||
switch (item)
|
||||
{
|
||||
case KITEM_SUPERRING:
|
||||
return (tiny ? "K_ISRING" : "K_ITRING");
|
||||
case KITEM_SNEAKER:
|
||||
case KRITEM_TRIPLESNEAKER:
|
||||
return (tiny ? "K_ISSHOE" : "K_ITSHOE");
|
||||
|
|
@ -6768,6 +6807,8 @@ const char *K_GetItemPatch(UINT8 item, boolean tiny)
|
|||
return (tiny ? "K_ISHYUD" : "K_ITHYUD");
|
||||
case KITEM_POGOSPRING:
|
||||
return (tiny ? "K_ISPOGO" : "K_ITPOGO");
|
||||
case KITEM_SUPERRING:
|
||||
return (tiny ? "K_ISRING" : "K_ITRING");
|
||||
case KITEM_KITCHENSINK:
|
||||
return (tiny ? "K_ISSINK" : "K_ITSINK");
|
||||
case KRITEM_TRIPLEORBINAUT:
|
||||
|
|
@ -7124,9 +7165,6 @@ static void K_drawKartItem(void)
|
|||
|
||||
switch(stplyr->kartstuff[k_itemtype])
|
||||
{
|
||||
case KITEM_SUPERRING:
|
||||
localpatch = kp_superring[offset];
|
||||
break;
|
||||
case KITEM_SNEAKER:
|
||||
localpatch = kp_sneaker[offset];
|
||||
break;
|
||||
|
|
@ -7175,6 +7213,9 @@ static void K_drawKartItem(void)
|
|||
case KITEM_POGOSPRING:
|
||||
localpatch = kp_pogospring[offset];
|
||||
break;
|
||||
case KITEM_SUPERRING:
|
||||
localpatch = kp_superring[offset];
|
||||
break;
|
||||
case KITEM_KITCHENSINK:
|
||||
localpatch = kp_kitchensink[offset];
|
||||
break;
|
||||
|
|
@ -7875,39 +7916,39 @@ static void K_drawKartRingsAndLives(void)
|
|||
INT32 splitflags = K_calcSplitFlags(V_SNAPTOBOTTOM|V_SNAPTOLEFT);
|
||||
UINT8 firstnum = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10);
|
||||
UINT8 secondnum = (abs(stplyr->kartstuff[k_rings]) % 10);
|
||||
UINT8 *debtmap = NULL;
|
||||
UINT8 *ringmap = NULL;
|
||||
|
||||
if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1))
|
||||
debtmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
|
||||
// Rings
|
||||
if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt
|
||||
ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE);
|
||||
else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out
|
||||
ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE);
|
||||
|
||||
if (netgame)
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[1]);
|
||||
else
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringsticker[0]);
|
||||
|
||||
V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+7, LAPS_Y-16, V_HUDTRANS|splitflags, kp_ring[0], (stplyr->kartstuff[k_rings] <= 0 ? ringmap : NULL)); // Don't do maxed out gold mapping
|
||||
|
||||
if (stplyr->kartstuff[k_rings] < 0)
|
||||
if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt
|
||||
{
|
||||
V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_ringdebtminus, ringmap);
|
||||
V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap);
|
||||
V_DrawMappedPatch(LAPS_X+35, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], debtmap);
|
||||
V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[firstnum], ringmap);
|
||||
V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[secondnum], ringmap);
|
||||
}
|
||||
|
||||
// Lives
|
||||
if (!netgame)
|
||||
{
|
||||
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE);
|
||||
|
||||
if (stplyr->mo->colorized)
|
||||
colormap = R_GetTranslationColormap(TC_RAINBOW, stplyr->mo->color, GTC_CACHE);
|
||||
|
||||
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE);
|
||||
V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|splitflags, facerankprefix[stplyr->skin], colormap);
|
||||
V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]);
|
||||
V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
116
src/p_enemy.c
116
src/p_enemy.c
|
|
@ -747,20 +747,24 @@ static boolean P_LookForShield(mobj_t *actor)
|
|||
if (player->health <= 0 || !player->mo)
|
||||
continue; // dead
|
||||
|
||||
if (!P_CheckSight(actor, player->mo))
|
||||
continue; // can't see
|
||||
|
||||
//When in CTF, don't pull rings that you cannot pick up.
|
||||
if ((actor->type == MT_REDTEAMRING && player->ctfteam != 1) ||
|
||||
(actor->type == MT_BLUETEAMRING && player->ctfteam != 2))
|
||||
continue;
|
||||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
|
||||
&& (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST/4, player->mo->scale)))
|
||||
if ((player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD) && ((player->kartstuff[k_rings]+player->kartstuff[k_pickuprings]) < 20)
|
||||
&& P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y) < FixedMul(RING_DIST/4, player->mo->scale)
|
||||
&& P_AproxDistance(0, actor->z-player->mo->z) < FixedMul(RING_DIST/8, player->mo->scale))
|
||||
{
|
||||
P_SetTarget(&actor->tracer, player->mo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef WEIGHTEDRECYCLER
|
||||
|
|
@ -3654,6 +3658,7 @@ void A_AttractChase(mobj_t *actor)
|
|||
if (actor->extravalue1 >= 16)
|
||||
{
|
||||
P_GivePlayerRings(actor->target->player, 1);
|
||||
actor->target->player->kartstuff[k_pickuprings]--;
|
||||
if (actor->cvmem) // caching
|
||||
S_StartSound(actor->target, sfx_s1c5);
|
||||
else
|
||||
|
|
@ -3682,69 +3687,76 @@ void A_AttractChase(mobj_t *actor)
|
|||
if (actor->threshold > 0)
|
||||
actor->threshold--;
|
||||
|
||||
// spilled rings flicker before disappearing
|
||||
if (leveltime & 1 && actor->type == (mobjtype_t)actor->info->reactiontime && actor->fuse && actor->fuse < 2*TICRATE)
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
else
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
|
||||
// Flung rings lose speed over time
|
||||
// spilled rings flicker before disappearing, and get capped to a certain speed
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
const fixed_t destspeed = FRACUNIT;
|
||||
const fixed_t maxspeed = 4<<FRACBITS;
|
||||
fixed_t oldspeed = R_PointToDist2(0, 0, actor->momx, actor->momy);
|
||||
|
||||
if (oldspeed > destspeed)
|
||||
if (oldspeed > maxspeed)
|
||||
{
|
||||
fixed_t newspeed = max(destspeed, oldspeed - (FRACUNIT / TICRATE));
|
||||
|
||||
fixed_t newspeed = max(maxspeed, oldspeed-FRACUNIT);
|
||||
actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed);
|
||||
actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed);
|
||||
}
|
||||
|
||||
if (actor->fuse && actor->fuse < 3*TICRATE && leveltime & 1)
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
else
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
}
|
||||
|
||||
// Turn flingrings back into regular rings if attracted.
|
||||
if (actor->tracer && actor->tracer->player
|
||||
&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT
|
||||
&& actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
|
||||
if (actor->tracer && actor->tracer->player && actor->tracer->health
|
||||
&& P_CheckSight(actor, actor->tracer)
|
||||
&& actor->tracer->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD
|
||||
&& (actor->tracer->player->kartstuff[k_rings]+actor->tracer->player->kartstuff[k_pickuprings]) < 20)
|
||||
{
|
||||
mobj_t *newring;
|
||||
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime);
|
||||
newring->momx = actor->momx;
|
||||
newring->momy = actor->momy;
|
||||
newring->momz = actor->momz;
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
fixed_t dist;
|
||||
angle_t hang, vang;
|
||||
|
||||
// If a flung ring gets attracted by a shield, change it into a normal ring.
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance);
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep stuff from going down inside floors and junk
|
||||
actor->flags &= ~MF_NOCLIPHEIGHT;
|
||||
|
||||
// Let attracted rings move through walls and such.
|
||||
actor->flags |= MF_NOCLIP;
|
||||
|
||||
// flag to show it's been attracted once before
|
||||
actor->cusval = 1;
|
||||
|
||||
// P_Attract is too "smart" for Kart; keep it simple, stupid!
|
||||
dist = P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z);
|
||||
hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y);
|
||||
vang = R_PointToAngle2(actor->z , 0, actor->tracer->z, dist);
|
||||
|
||||
actor->momx -= actor->momx>>4, actor->momy -= actor->momy>>4, actor->momz -= actor->momz>>4;
|
||||
actor->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), 2*actor->scale));
|
||||
actor->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), 2*actor->scale));
|
||||
actor->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), 2*actor->scale);
|
||||
}
|
||||
|
||||
P_LookForShield(actor); // Go find 'em, boy!
|
||||
|
||||
if (!actor->tracer
|
||||
|| !actor->tracer->player
|
||||
|| !actor->tracer->health
|
||||
|| !P_CheckSight(actor, actor->tracer)) // You have to be able to SEE it...sorta
|
||||
else
|
||||
{
|
||||
// Lost attracted rings don't through walls anymore.
|
||||
actor->flags &= ~MF_NOCLIP;
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
return;
|
||||
// Turn rings back into flung rings if lost
|
||||
if (actor->cusval && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
mobj_t *newring;
|
||||
newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime);
|
||||
P_InstaThrust(newring, P_RandomRange(0,7) * ANGLE_45, 2<<FRACBITS);
|
||||
newring->momz = 5<<FRACBITS;
|
||||
newring->fuse = 120*TICRATE;
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
}
|
||||
else
|
||||
P_LookForShield(actor); // Go find 'em, boy!
|
||||
}
|
||||
|
||||
// If a FlingRing gets attracted by a shield, change it into a normal ring.
|
||||
if (actor->type == (mobjtype_t)actor->info->reactiontime)
|
||||
{
|
||||
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance);
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep stuff from going down inside floors and junk
|
||||
actor->flags &= ~MF_NOCLIPHEIGHT;
|
||||
|
||||
// Let attracted rings move through walls and such.
|
||||
actor->flags |= MF_NOCLIP;
|
||||
|
||||
P_Attract(actor, actor->tracer, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -697,14 +697,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
return;
|
||||
|
||||
// Reached the cap, don't waste 'em!
|
||||
if (player->kartstuff[k_rings] >= 20)
|
||||
if ((player->kartstuff[k_rings] + player->kartstuff[k_pickuprings]) >= 20)
|
||||
return;
|
||||
|
||||
special->momx = special->momy = special->momz = 0;
|
||||
// SRB2Kart
|
||||
|
||||
special->extravalue1 = 1; // Ring collect animation timer
|
||||
special->angle = R_PointToAngle2(toucher->x, toucher->y, special->x, special->y); // animation angle
|
||||
P_SetTarget(&special->target, toucher); // toucher for thinker
|
||||
player->kartstuff[k_pickuprings]++;
|
||||
|
||||
return;
|
||||
|
||||
case MT_COIN:
|
||||
|
|
@ -3294,7 +3296,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
return;
|
||||
|
||||
// Cap the maximum loss automatically to 2 in ring debt
|
||||
if (player->kartstuff[k_rings] < 0 && num_rings > 2)
|
||||
if (player->kartstuff[k_rings] <= 0 && num_rings > 2)
|
||||
num_rings = 2;
|
||||
|
||||
P_GivePlayerRings(player, -num_rings);
|
||||
|
|
@ -3313,7 +3315,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
|
|||
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
|
||||
|
||||
mo->threshold = 10;
|
||||
mo->fuse = 15*TICRATE;
|
||||
mo->fuse = 120*TICRATE;
|
||||
P_SetTarget(&mo->target, player->mo);
|
||||
|
||||
mo->destscale = player->mo->scale;
|
||||
|
|
|
|||
19
src/p_mobj.c
19
src/p_mobj.c
|
|
@ -10729,6 +10729,8 @@ void P_PrecipitationEffects(void)
|
|||
//
|
||||
void P_RespawnSpecials(void)
|
||||
{
|
||||
UINT8 p, pcount = 0;
|
||||
tic_t time = 168*TICRATE;
|
||||
fixed_t x, y, z;
|
||||
subsector_t *ss;
|
||||
mobj_t *mo = NULL;
|
||||
|
|
@ -10787,9 +10789,22 @@ void P_RespawnSpecials(void)
|
|||
if (iquehead == iquetail)
|
||||
return;
|
||||
|
||||
// wait time depends on player count
|
||||
for (p = 0; p < MAXPLAYERS; p++)
|
||||
{
|
||||
if (!playeringame[p] || players[p].spectator)
|
||||
pcount++;
|
||||
}
|
||||
|
||||
if (pcount > 1)
|
||||
time -= pcount * (8*TICRATE);
|
||||
else if (pcount == 1) // No respawn when alone
|
||||
return;
|
||||
else
|
||||
time = 30*TICRATE; // Respawn things in empty dedicated servers
|
||||
|
||||
// the first item in the queue is the first to respawn
|
||||
// wait at least 30 seconds
|
||||
if (leveltime - itemrespawntime[iquetail] < (tic_t)cv_itemrespawntime.value*TICRATE)
|
||||
if (leveltime - itemrespawntime[iquetail] < time)
|
||||
return;
|
||||
|
||||
mthing = itemrespawnque[iquetail];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue