Added rings.

This commit is contained in:
TehRealSalt 2019-03-07 17:11:31 -05:00
parent 4096212282
commit 129268121d
14 changed files with 529 additions and 822 deletions

View file

@ -324,6 +324,7 @@ consvar_t cv_1up = {"tv_1up", "5", CV_NETVAR|CV_CHEAT, chanc
consvar_t cv_eggmanbox = {"tv_eggman", "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/
// SRB2kart
consvar_t cv_superring = {"superring", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sneaker = {"sneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_rocketsneaker = {"rocketsneaker", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_invincibility = {"invincibility", "On", CV_NETVAR|CV_CHEAT, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};

View file

@ -101,7 +101,7 @@ extern consvar_t cv_1up, cv_eggmanbox;
extern consvar_t cv_recycler;*/
// SRB2kart items
extern consvar_t cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana;
extern consvar_t cv_superring, cv_sneaker, cv_rocketsneaker, cv_invincibility, cv_banana;
extern consvar_t cv_eggmanmonitor, cv_orbinaut, cv_jawz, cv_mine;
extern consvar_t cv_ballhog, cv_selfpropelledbomb, cv_grow, cv_shrink;
extern consvar_t cv_thundershield, cv_hyudoro, cv_pogospring, cv_kitchensink;

View file

@ -234,6 +234,7 @@ typedef enum
{
KITEM_SAD = -1,
KITEM_NONE = 0,
KITEM_SUPERRING,
KITEM_SNEAKER,
KITEM_ROCKETSNEAKER,
KITEM_INVINCIBILITY,
@ -288,7 +289,7 @@ typedef enum
k_enginesnd, // Engine sound number you're on.
k_floorboost, // Prevents Sneaker sounds for a breif duration when triggered by a floor panel
k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still
k_spinouttype, // Determines whether to thrust forward or not while spinning out; 0 = move forwards, 1 = stay still, 2 = stay still & no flashing tics
k_drift, // Drifting Left or Right, plus a bigger counter = sharper turn
k_driftend, // Drift has ended, used to adjust character angle after drift
@ -296,6 +297,9 @@ typedef enum
k_driftboost, // Boost you get from drifting
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_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
k_offroad, // In Super Mario Kart, going offroad has lee-way of about 1 second before you start losing speed
k_pogospring, // Pogo spring bounce effect
@ -325,6 +329,7 @@ typedef enum
k_hyudorotimer, // Duration of the Hyudoro offroad effect itself
k_stealingtimer, // You are stealing an item, this is your timer
k_stolentimer, // You are being stolen from, this is your timer
k_superring, // Spawn rings on top of you every tic!
k_sneakertimer, // Duration of the Sneaker Boost itself
k_growshrinktimer, // > 0 = Big, < 0 = small
k_squishedtimer, // Squished frame timer

View file

@ -8283,6 +8283,9 @@ static const char *const KARTSTUFF_LIST[] = {
"DRIFTBOOST",
"BOOSTCHARGE",
"STARTBOOST",
"RINGS",
"RINGDELAY",
"RINGBOOST",
"JMP",
"OFFROAD",
"POGOSPRING",
@ -8309,6 +8312,7 @@ static const char *const KARTSTUFF_LIST[] = {
"HYUDOROTIMER",
"STEALINGTIMER",
"STOLENTIMER",
"SUPERRING",
"SNEAKERTIMER",
"GROWSHRINKTIMER",
"SQUISHEDTIMER",
@ -8866,6 +8870,7 @@ 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},

View file

@ -5444,8 +5444,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
38*FRACUNIT, // speed
16*FRACUNIT, // radius
24*FRACUNIT, // height
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
@ -5471,13 +5471,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate
sfx_itemup, // deathsound
38*FRACUNIT, // speed
15*FRACUNIT, // radius
24*FRACUNIT, // height
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SLIDEME|MF_SPECIAL, // flags
MF_SLIDEME|MF_BOUNCE|MF_SPECIAL|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},

View file

@ -397,6 +397,7 @@ UINT8 K_GetKartColorByName(const char *name)
void K_RegisterKartStuff(void)
{
CV_RegisterVar(&cv_superring);
CV_RegisterVar(&cv_sneaker);
CV_RegisterVar(&cv_rocketsneaker);
CV_RegisterVar(&cv_invincibility);
@ -496,12 +497,13 @@ boolean K_IsPlayerWanted(player_t *player)
static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] =
{
//P-Odds 0 1 2 3 4 5 6 7 8 9
/*Sneaker*/ {20, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker
/*Super Ring*/ {10, 2, 1, 1, 0, 0, 0, 0, 0, 0 }, // Super Ring
/*Sneaker*/ {10, 0, 0, 4, 6, 6, 0, 0, 0, 0 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 1, 3, 5, 3, 0 }, // Rocket Sneaker
/*Invincibility*/ { 0, 0, 0, 0, 0, 1, 4, 6,14, 0 }, // Invincibility
/*Banana*/ { 0,10, 4, 2, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 0, 3, 2, 1, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Orbinaut*/ { 0, 8, 6, 4, 2, 0, 0, 0, 0, 0 }, // Orbinaut
/*Orbinaut*/ { 0, 6, 5, 3, 2, 0, 0, 0, 0, 0 }, // Orbinaut
/*Jawz*/ { 0, 0, 3, 2, 1, 1, 0, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 0, 2, 2, 1, 0, 0, 0, 0, 0 }, // Mine
/*Ballhog*/ { 0, 0, 0, 2, 1, 0, 0, 0, 0, 0 }, // Ballhog
@ -523,6 +525,7 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS][10] =
static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] =
{
//P-Odds 0 1 2 3 4 5
/*Super Ring*/ { 0, 0, 0, 0, 0, 0 }, // Super Ring
/*Sneaker*/ { 3, 2, 2, 2, 0, 2 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker
/*Invincibility*/ { 0, 1, 2, 3, 4, 2 }, // Invincibility
@ -617,6 +620,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed)
SINT8 first = -1, second = -1;
INT32 secondist = 0;
boolean itemenabled[NUMKARTRESULTS-1] = {
cv_superring.value,
cv_sneaker.value,
cv_rocketsneaker.value,
cv_invincibility.value,
@ -1051,6 +1055,33 @@ static fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against)
return weight;
}
// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter.
static void K_BumpWipeoutPlayer(player_t *player, INT32 length)
{
if (player->health <= 0)
return;
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0
|| player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0
|| (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)))
return;
player->kartstuff[k_driftboost] = 0;
player->kartstuff[k_drift] = 0;
player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_pogospring] = 0;
player->kartstuff[k_spinouttype] = 2;
player->kartstuff[k_spinouttimer] = length;
player->kartstuff[k_wipeoutslow] = min(length-1, wipeoutslowtime+1);
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
K_DropHnextList(player);
return;
}
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
{
mobj_t *fx;
@ -1199,11 +1230,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
mobj1->player->rmomx = mobj1->momx - mobj1->player->cmomx;
mobj1->player->rmomy = mobj1->momy - mobj1->player->cmomy;
mobj1->player->kartstuff[k_justbumped] = bumptime;
if (mobj1->player->kartstuff[k_spinouttimer])
{
mobj1->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1;
mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]);
}
else if (mobj2->player) // Player VS player bumping only
{
if (mobj1->player->kartstuff[k_rings] <= 0)
{
K_BumpWipeoutPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight)));
P_PlayRinglossSound(mobj1);
}
P_PlayerRingBurst(mobj1->player, 1);
}
}
if (mobj2->player)
@ -1211,11 +1252,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid)
mobj2->player->rmomx = mobj2->momx - mobj2->player->cmomx;
mobj2->player->rmomy = mobj2->momy - mobj2->player->cmomy;
mobj2->player->kartstuff[k_justbumped] = bumptime;
if (mobj2->player->kartstuff[k_spinouttimer])
{
mobj2->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1;
mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]);
}
else if (mobj1->player) // Player VS player bumping only
{
if (mobj2->player->kartstuff[k_rings] <= 0)
{
K_BumpWipeoutPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight)));
P_PlayRinglossSound(mobj2);
}
P_PlayerRingBurst(mobj2->player, 1);
}
}
}
@ -1281,6 +1332,67 @@ static void K_UpdateOffroad(player_t *player)
player->kartstuff[k_offroad] = 0;
}
void K_KartPainEnergyFling(player_t *player)
{
static const UINT8 numfling = 5;
INT32 i;
mobj_t *mo;
angle_t fa;
fixed_t ns;
fixed_t z;
// Better safe than sorry.
if (!player)
return;
// P_PlayerRingBurst: "There's no ring spilling in kart, so I'm hijacking this for the same thing as TD"
// :oh:
for (i = 0; i < numfling; i++)
{
INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime;
fixed_t momxy, momz; // base horizonal/vertical thrusts
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
z += player->mo->height - mobjinfo[objType].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
mo->fuse = 8*TICRATE;
P_SetTarget(&mo->target, player->mo);
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle, then slightly offset by amount of fling
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((numfling-1)*FINEANGLES/32)) & FINEMASK;
if (i > 15)
{
momxy = 3*FRACUNIT;
momz = 4*FRACUNIT;
}
else
{
momxy = 28*FRACUNIT;
momz = 3*FRACUNIT;
}
ns = FixedMul(momxy, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
ns = momz;
P_SetObjectMomZ(mo, ns, false);
if (i & 1)
P_SetObjectMomZ(mo, ns, true);
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1;
}
}
// These have to go earlier than its sisters because of K_RespawnChecker...
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master)
{
@ -1447,6 +1559,7 @@ void K_RespawnChecker(player_t *player)
player->mo->colorized = false;
player->kartstuff[k_dropdash] = 0;
player->kartstuff[k_respawn] = 0;
P_PlayerRingBurst(player, 3);
}
}
}
@ -1572,6 +1685,16 @@ void K_PlayOvertakeSound(mobj_t *source)
K_RegularVoiceTimers(source->player);
}
void K_PlayPainSound(mobj_t *source)
{
sfxenum_t pick = P_RandomKey(2); // Gotta roll the RNG every time this is called for sync reasons
if (cv_kartvoices.value)
S_StartSound(source, sfx_khurt1 + pick);
K_RegularVoiceTimers(source->player);
}
void K_PlayHitEmSound(mobj_t *source)
{
if (cv_kartvoices.value)
@ -1667,6 +1790,12 @@ static void K_GetKartBoostPower(player_t *player)
speedboost = max(speedboost, FRACUNIT/5); // + 20%
}
if (player->kartstuff[k_ringboost]) // Ring Boost
{
speedboost = max(speedboost, FRACUNIT/8); // + 12.5%
accelboost = max(accelboost, 2*FRACUNIT); // + 200%
}
if (player->kartstuff[k_driftboost]) // Drift Boost
{
speedboost = max(speedboost, FRACUNIT/4); // + 25%
@ -1867,7 +1996,6 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
(void)inflictor; // in case some weirdo doesn't want Lua.
#endif
if (!trapitem && G_BattleGametype())
{
if (K_IsPlayerWanted(player))
@ -1879,7 +2007,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
if (player->health <= 0)
return;
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)
|| player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0
|| (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)))
{
@ -1949,7 +2077,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
player->kartstuff[k_spinouttype] = type;
if (player->kartstuff[k_spinouttype] <= 0) // type 0 is spinout, type 1 is wipeout
if (player->kartstuff[k_spinouttype] <= 0) // type 0 is spinout, type 1 is wipeout, type 2 is no-invuln wipeout
{
// At spinout, player speed is increased to 1/4 their regular speed, moving them forward
if (player->speed < K_GetKartSpeed(player, true)/4)
@ -1960,6 +2088,10 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto
player->kartstuff[k_spinouttimer] = (3*TICRATE/2)+2;
player->powers[pw_flashing] = K_GetKartFlashing(player);
P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 5);
K_PlayPainSound(player->mo);
if (player->mo->state != &states[S_KART_SPIN])
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
@ -2096,6 +2228,8 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor)
P_SetPlayerMobjState(player->mo, S_KART_SQUISH);
P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 5);
K_PlayPainSound(player->mo);
player->kartstuff[k_instashield] = 15;
if (cv_kartdebughuddrop.value && !modeattacking)
@ -2132,8 +2266,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
if (player->health <= 0)
return;
if (/*player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 // Explosions should combo, because of SPB and Eggman
||*/player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0
if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 // Do not check spinout, because SPB and Eggman should combo
|| (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)))
{
if (!force) // ShouldDamage can bypass that, again.
@ -2162,7 +2295,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
player->kartstuff[k_pogospring] = 0;
// This is the only part that SHOULDN'T combo :VVVVV
if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0))
if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)))
{
if (source && source->player && player != source->player)
{
@ -2216,6 +2349,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
P_SetPlayerMobjState(player->mo, S_KART_SPIN);
P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 5);
K_PlayPainSound(player->mo);
if (P_IsLocalPlayer(player))
{
@ -2250,7 +2385,7 @@ void K_StealBumper(player_t *player, player_t *victim, boolean force)
if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0)
return;
if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || victim->kartstuff[k_spinouttimer] > 0
if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || (victim->kartstuff[k_spinouttimer] > 0 && victim->kartstuff[k_spinouttype] != 2)
|| victim->kartstuff[k_invincibilitytimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_hyudorotimer] > 0)
{
K_DoInstashield(victim);
@ -4185,7 +4320,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_GetKartBoostPower(player);
// Speed lines
if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0)
if ((player->kartstuff[k_sneakertimer] || player->kartstuff[k_ringboost] || player->kartstuff[k_driftboost] || player->kartstuff[k_startboost]) && player->speed > 0)
{
mobj_t *fast = P_SpawnMobj(player->mo->x + (P_RandomRange(-36,36) * player->mo->scale),
player->mo->y + (P_RandomRange(-36,36) * player->mo->scale),
@ -4243,6 +4378,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->mo->color = player->skincolor;
}
}
else if (player->kartstuff[k_ringboost] && (leveltime & 1)) // ring boosting
{
player->mo->colorized = true;
}
else
{
player->mo->colorized = false;
@ -4280,8 +4419,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->kartstuff[k_timeovercam] = 0;
// Specific hack because it insists on setting flashing tics during this anyway...
if (player->kartstuff[k_spinouttype] == 2)
{
player->powers[pw_flashing] = 0;
}
// Make ABSOLUTELY SURE that your flashing tics don't get set WHILE you're still in hit animations.
if (player->kartstuff[k_spinouttimer] != 0
else if (player->kartstuff[k_spinouttimer] != 0
|| player->kartstuff[k_wipeoutslow] != 0
|| player->kartstuff[k_squishedtimer] != 0)
{
@ -4294,19 +4438,21 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->kartstuff[k_spinouttimer])
{
if ((P_IsObjectOnGround(player->mo) || player->kartstuff[k_spinouttype] == 1)
if ((P_IsObjectOnGround(player->mo)
|| (player->kartstuff[k_spinouttype] != 0))
&& (player->kartstuff[k_sneakertimer] == 0))
{
player->kartstuff[k_spinouttimer]--;
if (player->kartstuff[k_wipeoutslow] > 1)
player->kartstuff[k_wipeoutslow]--;
if (player->kartstuff[k_spinouttimer] == 0)
player->kartstuff[k_spinouttype] = 0; // Reset type
// Actually, this caused more problems than it solved. Just make sure you set type before you spinout. Which K_SpinPlayer always does.
/*if (player->kartstuff[k_spinouttimer] == 0)
player->kartstuff[k_spinouttype] = 0;*/ // Reset type
}
}
else
{
if (player->kartstuff[k_wipeoutslow] == 1)
if (player->kartstuff[k_wipeoutslow] >= 1)
player->mo->friction = ORIG_FRICTION;
player->kartstuff[k_wipeoutslow] = 0;
if (!comeback)
@ -4322,6 +4468,17 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
/*if (player->kartstuff[k_thunderanim])
player->kartstuff[k_thunderanim]--;*/
if (player->kartstuff[k_rings] > 20)
player->kartstuff[k_rings] = 20;
else if (player->kartstuff[k_rings] < -20)
player->kartstuff[k_rings] = -20;
if (player->kartstuff[k_ringdelay])
player->kartstuff[k_ringdelay]--;
if (player->kartstuff[k_ringboost])
player->kartstuff[k_ringboost]--;
if (player->kartstuff[k_sneakertimer])
{
player->kartstuff[k_sneakertimer]--;
@ -4353,6 +4510,20 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_RemoveGrowShrink(player);
}
if (player->kartstuff[k_superring])
{
if (player->kartstuff[k_superring] % 3 == 0)
{
mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING);
ring->extravalue1 = 1; // Ring collect animation timer
ring->angle = player->mo->angle; // animation angle
P_SetTarget(&ring->target, player->mo); // toucher for thinker
if (player->kartstuff[k_superring] <= 3)
ring->cvmem = 1; // play caching when collected
}
player->kartstuff[k_superring]--;
}
if (player->kartstuff[k_stealingtimer] == 0 && player->kartstuff[k_stolentimer] == 0
&& player->kartstuff[k_rocketsneakertimer])
player->kartstuff[k_rocketsneakertimer]--;
@ -5027,6 +5198,21 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->kartstuff[k_rocketsneakertimer] < 1)
player->kartstuff[k_rocketsneakertimer] = 1;
}
// Ring boosts with no item
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;
@ -5035,6 +5221,13 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
switch (player->kartstuff[k_itemtype])
{
case KITEM_SUPERRING:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->kartstuff[k_superring] += (10*3);
player->kartstuff[k_itemamount]--;
}
break;
case KITEM_SNEAKER:
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO)
{
@ -5373,6 +5566,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
}
// Prevent ring misfire
if (player->kartstuff[k_itemtype] != KITEM_NONE)
player->kartstuff[k_ringdelay] = 15;
// No more!
if (!player->kartstuff[k_itemamount])
{
@ -5899,6 +6096,10 @@ static patch_t *kp_winnernum[NUMPOSFRAMES];
static patch_t *kp_facenum[MAXPLAYERS+1];
static patch_t *kp_facehighlight[8];
static patch_t *kp_ringsticker[2];
static patch_t *kp_ring[6];
static patch_t *kp_ringdebtminus;
static patch_t *kp_rankbumper;
static patch_t *kp_tinybumper[2];
static patch_t *kp_ranknobumpers;
@ -5917,6 +6118,7 @@ static patch_t *kp_itemtimer[2];
static patch_t *kp_itemmulsticker[2];
static patch_t *kp_itemx;
static patch_t *kp_superring[2];
static patch_t *kp_sneaker[2];
static patch_t *kp_rocketsneaker[2];
static patch_t *kp_invincibility[13];
@ -6037,6 +6239,19 @@ void K_LoadKartHUDGraphics(void)
kp_facehighlight[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
}
// Rings & Lives
kp_ringsticker[0] = W_CachePatchName("RNGBACKA", PU_HUDGFX);
kp_ringsticker[1] = W_CachePatchName("RNGBACKB", PU_HUDGFX);
sprintf(buffer, "K_RINGx");
for (i = 0; i < 6; i++)
{
buffer[6] = '0'+(i+1);
kp_ring[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX);
}
kp_ringdebtminus = W_CachePatchName("RDEBTMIN", PU_HUDGFX);
// Extra ranking icons
kp_rankbumper = W_CachePatchName("K_BLNICO", PU_HUDGFX);
kp_tinybumper[0] = W_CachePatchName("K_BLNA", PU_HUDGFX);
@ -6060,6 +6275,7 @@ void K_LoadKartHUDGraphics(void)
kp_itemmulsticker[0] = W_CachePatchName("K_ITMUL", PU_HUDGFX);
kp_itemx = W_CachePatchName("K_ITX", PU_HUDGFX);
kp_superring[0] = W_CachePatchName("K_ITRING", PU_HUDGFX);
kp_sneaker[0] = W_CachePatchName("K_ITSHOE", PU_HUDGFX);
kp_rocketsneaker[0] = W_CachePatchName("K_ITRSHE", PU_HUDGFX);
@ -6095,6 +6311,7 @@ void K_LoadKartHUDGraphics(void)
kp_itemtimer[1] = W_CachePatchName("K_ISIMER", PU_HUDGFX);
kp_itemmulsticker[1] = W_CachePatchName("K_ISMUL", PU_HUDGFX);
kp_superring[1] = W_CachePatchName("K_ISRING", PU_HUDGFX);
kp_sneaker[1] = W_CachePatchName("K_ISSHOE", PU_HUDGFX);
kp_rocketsneaker[1] = W_CachePatchName("K_ISRSHE", PU_HUDGFX);
sprintf(buffer, "K_ISINVx");
@ -6205,6 +6422,8 @@ 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");
@ -6457,7 +6676,7 @@ static void K_drawKartItem(void)
if (stplyr->skincolor)
localcolor = stplyr->skincolor;
switch((stplyr->kartstuff[k_itemroulette] % (14*3)) / 3)
switch((stplyr->kartstuff[k_itemroulette] % (15*3)) / 3)
{
// Each case is handled in threes, to give three frames of in-game time to see the item on the roulette
case 0: // Sneaker
@ -6516,11 +6735,15 @@ static void K_drawKartItem(void)
localpatch = kp_thundershield[offset];
//localcolor = SKINCOLOR_CYAN;
break;
/*case 14: // Pogo Spring
case 14: // Super Ring
localpatch = kp_superring[offset];
//localcolor = SKINCOLOR_GOLD;
break;
/*case 15: // Pogo Spring
localpatch = kp_pogospring[offset];
localcolor = SKINCOLOR_TANGERINE;
break;
case 15: // Kitchen Sink
case 16: // Kitchen Sink
localpatch = kp_kitchensink[offset];
localcolor = SKINCOLOR_STEEL;
break;*/
@ -6581,6 +6804,9 @@ 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;
@ -6736,7 +6962,6 @@ static void K_drawKartItem(void)
// Quick Eggman numbers
if (stplyr->kartstuff[k_eggmanexplode] > 1 /*&& stplyr->kartstuff[k_eggmanexplode] <= 3*TICRATE*/)
V_DrawScaledPatch(fx+17, fy+13-offset, V_HUDTRANS|fflags, kp_eggnum[min(3, G_TicsToSeconds(stplyr->kartstuff[k_eggmanexplode]))]);
}
void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode)
@ -7327,6 +7552,47 @@ static void K_drawKartLaps(void)
}
}
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;
if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1))
debtmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, 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-17, V_HUDTRANS|splitflags, kp_ring[0], debtmap);
if (stplyr->kartstuff[k_rings] < 0)
{
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);
}
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);
}
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);
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)]);
}
}
static void K_drawKartSpeedometer(void)
{
fixed_t convSpeed;
@ -8287,6 +8553,7 @@ static void K_drawLapStartAnim(void)
void K_drawKartFreePlay(UINT32 flashtime)
{
// no splitscreen support because it's not FREE PLAY if you have more than one player in-game
// (you fool, you can take splitscreen online. :V)
if ((flashtime % TICRATE) < TICRATE/2)
return;
@ -8299,6 +8566,7 @@ static void K_drawDistributionDebugger(void)
{
patch_t *items[NUMKARTRESULTS] = {
kp_sadface[1],
kp_superring[1],
kp_sneaker[1],
kp_rocketsneaker[1],
kp_invincibility[7],
@ -8497,6 +8765,8 @@ void K_drawKartHUD(void)
#endif
K_drawKartLaps();
K_drawKartRingsAndLives();
if (!splitscreen)
{
// Draw the speedometer

View file

@ -23,6 +23,7 @@ void K_RegisterKartStuff(void);
boolean K_IsPlayerLosing(player_t *player);
boolean K_IsPlayerWanted(player_t *player);
void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid);
void K_KartPainEnergyFling(player_t *player);
void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master);
void K_RespawnChecker(player_t *player);
void K_KartMoveAnimation(player_t *player);
@ -69,6 +70,7 @@ void K_CheckSpectateStatus(void);
void K_PlayAttackTaunt(mobj_t *source);
void K_PlayBoostTaunt(mobj_t *source);
void K_PlayOvertakeSound(mobj_t *source);
void K_PlayPainSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source);
void K_PlayPowerGloatSound(mobj_t *source);

View file

@ -1205,37 +1205,6 @@ static int lib_pPlayerRingBurst(lua_State *L)
return 0;
}
static int lib_pPlayerWeaponPanelBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelBurst(player);
return 0;
}
static int lib_pPlayerWeaponAmmoBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponAmmoBurst(player);
return 0;
}
static int lib_pPlayerEmeraldBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerEmeraldBurst(player, toss);
return 0;
}
static int lib_pPlayerFlagBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@ -2163,6 +2132,16 @@ static int lib_kOvertakeSound(lua_State *L)
return 0;
}
static int lib_kPainSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
if (!mobj->player)
return luaL_error(L, "K_PlayPainSound: mobj_t isn't a player object."); //Nothing bad would happen if we let it run the func, but telling why it ain't doing anything is helpful.
K_PlayPainSound(mobj);
return 0;
}
static int lib_kHitEmSound(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -2682,9 +2661,6 @@ static luaL_Reg lib[] = {
{"P_DamageMobj",lib_pDamageMobj},
{"P_KillMobj",lib_pKillMobj},
{"P_PlayerRingBurst",lib_pPlayerRingBurst},
{"P_PlayerWeaponPanelBurst",lib_pPlayerWeaponPanelBurst},
{"P_PlayerWeaponAmmoBurst",lib_pPlayerWeaponAmmoBurst},
{"P_PlayerEmeraldBurst",lib_pPlayerEmeraldBurst},
{"P_PlayerFlagBurst",lib_pPlayerFlagBurst},
{"P_PlayRinglossSound",lib_pPlayRinglossSound},
{"P_PlayDeathSound",lib_pPlayDeathSound},
@ -2769,6 +2745,7 @@ static luaL_Reg lib[] = {
{"K_PlayPowerGloatSund", lib_kGloatSound},
{"K_PlayOvertakeSound", lib_kOvertakeSound},
{"K_PlayLossSound", lib_kLossSound},
{"K_PlayPainSound", lib_kPainSound},
{"K_PlayHitEmSound", lib_kHitEmSound},
{"K_GetKartColorByName",lib_kGetKartColorByName},
{"K_IsPlayerLosing",lib_kIsPlayerLosing},

View file

@ -1513,7 +1513,7 @@ static menuitem_t OP_AdvServerOptionsMenu[] =
{IT_STRING | IT_CVAR, NULL, "Karma Comeback", &cv_kartcomeback, 66},
};*/
#define ITEMTOGGLEBOTTOMRIGHT
//#define ITEMTOGGLEBOTTOMRIGHT
static menuitem_t OP_MonitorToggleMenu[] =
{
@ -1541,6 +1541,7 @@ static menuitem_t OP_MonitorToggleMenu[] =
{IT_KEYHANDLER | IT_NOTHING, NULL, "Thunder Shields", M_HandleMonitorToggles, KITEM_THUNDERSHIELD},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Hyudoros", M_HandleMonitorToggles, KITEM_HYUDORO},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Pogo Springs", M_HandleMonitorToggles, KITEM_POGOSPRING},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Super Rings", M_HandleMonitorToggles, KITEM_SUPERRING},
{IT_KEYHANDLER | IT_NOTHING, NULL, "Kitchen Sinks", M_HandleMonitorToggles, KITEM_KITCHENSINK},
#ifdef ITEMTOGGLEBOTTOMRIGHT
{IT_KEYHANDLER | IT_NOTHING, NULL, "---", M_HandleMonitorToggles, 255},
@ -9563,6 +9564,7 @@ static void M_HandleVideoMode(INT32 ch)
// Monitor Toggles
// ===============
static consvar_t *kartitemcvs[NUMKARTRESULTS-1] = {
&cv_superring,
&cv_sneaker,
&cv_rocketsneaker,
&cv_invincibility,

View file

@ -3615,57 +3615,137 @@ void A_AttractChase(mobj_t *actor)
if (LUA_CallAction("A_AttractChase", actor))
return;
#endif
if (actor->flags2 & MF2_NIGHTSPULL || !actor->health)
return;
// 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;
if (actor->extravalue1) // SRB2Kart
{
if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player)
{
P_RemoveMobj(actor);
return;
}
if (actor->extravalue2) // Using for ring boost
{
if (actor->extravalue1 >= 21)
{
#define RINGBOOSTPWR (((9 - actor->target->player->kartspeed) + (9 - actor->target->player->kartweight)) / 2)
// Base add is 3 tics for 9,9, adds 1.5 tics for each point closer to the 1,1 end
actor->target->player->kartstuff[k_ringboost] += ((3*RINGBOOSTPWR)/2) + 3;
S_StartSound(actor->target, sfx_s1b5);
actor->momx = (3*actor->target->momx)/4;
actor->momy = (3*actor->target->momy)/4;
actor->momz = (3*actor->target->momz)/4;
P_KillMobj(actor, actor->target, actor->target);
return;
}
else
{
fixed_t offz = FixedMul(80*actor->target->scale, FINESINE(FixedAngle((90 - (9 * abs(10 - actor->extravalue1))) << FRACBITS) >> ANGLETOFINESHIFT));
//P_SetScale(actor, (actor->destscale = actor->target->scale));
P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z + actor->target->height + offz);
actor->extravalue1++;
}
}
else // Collecting
{
if (actor->extravalue1 >= 16)
{
P_GivePlayerRings(actor->target->player, 1);
if (actor->cvmem) // caching
S_StartSound(actor->target, sfx_s1c5);
else
S_StartSound(actor->target, sfx_s227);
P_RemoveMobj(actor);
return;
}
else
{
fixed_t dist = (actor->target->radius/4) * (16 - actor->extravalue1);
P_SetScale(actor, (actor->destscale = actor->target->scale - ((actor->target->scale/14) * actor->extravalue1)));
P_TeleportMove(actor,
actor->target->x + FixedMul(dist, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)),
actor->target->y + FixedMul(dist, FINESINE(actor->angle >> ANGLETOFINESHIFT)),
actor->target->z + (24 * actor->target->scale));
actor->angle += ANG30;
actor->extravalue1++;
}
}
}
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)
{
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;
// Don't immediately pick up spilled rings
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
if (actor->type == (mobjtype_t)actor->info->reactiontime)
{
const fixed_t destspeed = FRACUNIT;
fixed_t oldspeed = R_PointToDist2(0, 0, actor->momx, actor->momy);
if (oldspeed > destspeed)
{
fixed_t newspeed = max(destspeed, oldspeed - (FRACUNIT / TICRATE));
actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), newspeed);
actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), newspeed);
}
}
// 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)
{
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;
}
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
{
// Lost attracted rings don't through walls anymore.
actor->flags &= ~MF_NOCLIP;
P_SetTarget(&actor->tracer, NULL);
return;
}
// 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);
}
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
{
// Lost attracted rings don't through walls anymore.
actor->flags &= ~MF_NOCLIP;
P_SetTarget(&actor->tracer, NULL);
return;
}
// 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);
}
// Function: A_DropMine

View file

@ -116,7 +116,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon)
{
// Invulnerable
if (player->powers[pw_flashing] > 0
|| player->kartstuff[k_spinouttimer] > 0
|| (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)
|| player->kartstuff[k_squishedtimer] > 0
|| player->kartstuff[k_invincibilitytimer] > 0
|| player->kartstuff[k_growshrinktimer] > 0
@ -678,15 +678,26 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
/* FALLTHRU */
case MT_RING:
case MT_FLINGRING:
if (special->extravalue1)
return;
// Don't immediately pick up spilled rings
if (special->threshold > 0)
return;
if (!(P_CanPickupItem(player, 0)))
return;
special->momx = special->momy = special->momz = 0;
P_GivePlayerRings(player, 1);
// Reached the cap, don't waste 'em!
if (player->kartstuff[k_rings] >= 20)
return;
if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING)
P_DoNightsScore(player);
break;
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
return;
case MT_COIN:
case MT_FLINGCOIN:
@ -2806,16 +2817,8 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return true;
}
if (target->health <= 1) // Death
{
P_PlayDeathSound(target);
P_PlayVictorySound(source); // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!!
}
else if (target->health > 1) // Ring loss
{
P_PlayRinglossSound(target);
P_PlayerRingBurst(player, player->mo->health - 1);
}
P_PlayRinglossSound(target);
P_PlayerRingBurst(player, 5);
if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
@ -2871,14 +2874,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
{
player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE);
(void)source;
// Burst weapons and emeralds in Match/CTF only
if (source && (G_BattleGametype()))
{
P_PlayerRingBurst(player, player->health - 1);
P_PlayerEmeraldBurst(player, false);
}
player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE);
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
@ -2894,32 +2892,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
/*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 1);
}
// If the player was super, tell them he/she ain't so super nomore.
if (gametype != GT_COOP && player->powers[pw_super])
{
S_StartSound(NULL, sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}*/
if (player->pflags & PF_TIMEOVER)
{
mobj_t *boom;
@ -2952,66 +2924,6 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
}
}
/*
static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
fixed_t fallbackspeed;
angle_t ang;
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (player->mo->eflags & MFE_VERTICALFLIP)
player->mo->z--;
else
player->mo->z++;
if (player->mo->eflags & MFE_UNDERWATER)
P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false);
else
P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false);
ang = R_PointToAngle2(inflictor->x, inflictor->y, player->mo->x, player->mo->y);
// explosion and rail rings send you farther back, making it more difficult
// to recover
if (inflictor->flags2 & MF2_SCATTER && source)
{
fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z);
dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4;
if (dist < FixedMul(4*FRACUNIT, inflictor->scale))
dist = FixedMul(4*FRACUNIT, inflictor->scale);
fallbackspeed = dist;
}
else if (inflictor->flags2 & MF2_EXPLOSION)
{
if (inflictor->flags2 & MF2_RAILRING)
fallbackspeed = FixedMul(28*FRACUNIT, inflictor->scale); // 7x
else
fallbackspeed = FixedMul(20*FRACUNIT, inflictor->scale); // 5x
}
else if (inflictor->flags2 & MF2_RAILRING)
fallbackspeed = FixedMul(16*FRACUNIT, inflictor->scale); // 4x
else
fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force
P_InstaThrust(player->mo, ang, fallbackspeed);
// SRB2kart - This shouldn't be reachable, but this frame is invalid.
//if (player->charflags & SF_SUPERANIMS)
// P_SetPlayerMobjState(player->mo, S_PLAY_SUPERHIT);
//else
P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
P_ResetPlayer(player);
if (player->timeshit != UINT8_MAX)
++player->timeshit;
}
*/
void P_RemoveShield(player_t *player)
{
if (player->powers[pw_shield] & SH_FORCE)
@ -3040,75 +2952,6 @@ void P_RemoveShield(player_t *player)
player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK;
}
/*
static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) // SRB2kart - unused.
{
// Must do pain first to set flashing -- P_RemoveShield can cause damage
P_DoPlayerPain(player, source, inflictor);
P_RemoveShield(player);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes
S_StartSound(player->mo, sfx_spkdth);
else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss.
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25);
}
}
if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, cv_match_scoring.value == 1 ? 25 : 50);
}
}
*/
static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
//const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1);
if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])))
{
P_DoPlayerPain(player, source, inflictor);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes
S_StartSound(player->mo, sfx_spkdth);
}
/*if (source && source->player && !player->powers[pw_super]) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
P_PlayerFlagBurst(player, false);
if (source && source->player)
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, scoremultiply);
}
}*/
// Ring loss sound plays despite hitting spikes
P_PlayRinglossSound(player->mo); // Ringledingle!
}
/** Damages an object, which may or may not be a player.
* For melee attacks, source and inflictor are the same.
@ -3326,10 +3169,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|| inflictor->type == MT_SMK_THWOMP || inflictor->player))
{
player->kartstuff[k_sneakertimer] = 0;
K_SpinPlayer(player, source, 1, inflictor, false);
damage = player->mo->health - 1;
P_RingDamage(player, inflictor, source, damage);
P_PlayerRingBurst(player, 5);
K_KartPainEnergyFling(player);
if (P_IsLocalPlayer(player))
{
quake.intensity = 32*FRACUNIT;
@ -3337,110 +3180,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
}
else
{
K_SpinPlayer(player, source, 0, inflictor, false);
}
return true;
}
/* // SRB2kart - don't need these
else if (metalrecording)
{
if (!inflictor)
inflictor = source;
if (inflictor && inflictor->flags & MF_ENEMY)
{ // Metal Sonic destroy enemy !!
P_KillMobj(inflictor, NULL, target);
return false;
}
else if (inflictor && inflictor->flags & MF_MISSILE)
return false; // Metal Sonic walk through flame !!
else
{ // Oh no! Metal Sonic is hit !!
P_ShieldDamage(player, inflictor, source, damage);
return true;
}
}
else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] // ignore bouncing & such in invulnerability
|| (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player))))
{
if (force || (inflictor && (inflictor->flags & MF_MISSILE)
&& (inflictor->flags2 & MF2_SUPERFIRE)
&& player->powers[pw_super]))
{
#ifdef HAVE_BLUA
if (!LUAh_MobjDamage(target, inflictor, source, damage))
#endif
P_SuperDamage(player, inflictor, source, damage);
return true;
}
else
return false;
}
#ifdef HAVE_BLUA
else if (LUAh_MobjDamage(target, inflictor, source, damage))
return true;
#endif
else if (!player->powers[pw_super] && (player->powers[pw_shield] || player->bot)) //If One-Hit Shield
{
P_ShieldDamage(player, inflictor, source, damage);
damage = 0;
}
else if (player->mo->health > 1) // No shield but have rings.
{
damage = player->mo->health - 1;
P_RingDamage(player, inflictor, source, damage);
}
else // No shield, no rings, no invincibility.
{
// To reduce griefing potential, don't allow players to be killed
// by friendly fire. Spilling their rings and other items is enough.
if (force || !(G_GametypeHasTeams()
&& source && source->player && (source->player->ctfteam == player->ctfteam)
&& cv_friendlyfire.value))
{
damage = 1;
P_KillPlayer(player, source, damage);
}
else
{
damage = 0;
P_ShieldDamage(player, inflictor, source, damage);
}
}
*/
if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))
{
if (player->powers[pw_shield])
{
P_RemoveShield(player);
return true;
}
else
{
player->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500)));
if (player->health < 2)
player->health = 2;
}
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
P_PlayerFlagBurst(player, false);
}
else
{
player->health -= damage; // mirror mobj health here
if (damage < 10000)
{
target->player->powers[pw_flashing] = K_GetKartFlashing(target->player);
if (damage > 0) // don't spill emeralds/ammo/panels for shield damage
P_PlayerRingBurst(player, damage);
}
}
if (player->health < 0)
player->health = 0;
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
}
// Killing dead. Just for kicks.
@ -3515,7 +3258,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
/** Spills an injured player's rings.
*
* \param player The player who is losing rings.
* \param num_rings Number of rings lost. A maximum of 32 rings will be
* \param num_rings Number of rings lost. A maximum of 20 rings will be
* spawned.
* \sa P_PlayerFlagBurst
*/
@ -3526,32 +3269,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
angle_t fa;
fixed_t ns;
fixed_t z;
fixed_t momxy = 5<<FRACBITS, momz = 12<<FRACBITS; // base horizonal/vertical thrusts
// Rings shouldn't be in Battle!
if (G_BattleGametype())
return;
// Better safe than sorry.
if (!player)
return;
// Never have health in kart I think
if (player->mo->health <= 1)
num_rings = 5;
// 20 is the ring cap in kart
if (num_rings > 20)
num_rings = 20;
else if (num_rings <= 0)
return;
if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL))
num_rings = 32;
// Cap the maximum loss automatically to 2 in ring debt
if (player->kartstuff[k_rings] < 0 && num_rings > 2)
num_rings = 2;
if (player->powers[pw_emeralds])
P_PlayerEmeraldBurst(player, false);
P_GivePlayerRings(player, -num_rings);
// Spill weapons first
if (player->ringweapons)
P_PlayerWeaponPanelBurst(player);
// determine first angle
fa = player->mo->angle + ((P_RandomByte() & 1) ? -ANGLE_90 : ANGLE_90);
// Spill the ammo
P_PlayerWeaponAmmoBurst(player);
// There's no ring spilling in kart, so I'm hijacking this for the same thing as TD
for (i = 0; i < num_rings; i++)
{
INT32 objType = mobjinfo[MT_FLINGENERGY].reactiontime;
INT32 objType = mobjinfo[MT_RING].reactiontime;
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -3559,379 +3304,34 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
mo->fuse = 8*TICRATE;
mo->threshold = 10;
mo->fuse = 15*TICRATE;
P_SetTarget(&mo->target, player->mo);
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle, then slightly offset by amount of rings
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
if (player->pflags & PF_NIGHTSFALL)
// Angle / height offset changes every other ring
if (i != 0)
{
ns = FixedMul(((i*FRACUNIT)/16)+2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 8*FRACUNIT, false);
mo->fuse = 20*TICRATE; // Adjust fuse for NiGHTS
}
else
{
fixed_t momxy, momz; // base horizonal/vertical thrusts
if (i > 15)
{
momxy = 3*FRACUNIT;
momz = 4*FRACUNIT;
}
else
{
momxy = 28*FRACUNIT;
momz = 3*FRACUNIT;
}
ns = FixedMul(momxy, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
ns = momz;
P_SetObjectMomZ(mo, ns, false);
if (i & 1)
P_SetObjectMomZ(mo, ns, true);
{
momxy -= FRACUNIT;
momz += 2<<FRACBITS;
}
fa += ANGLE_180;
}
ns = FixedMul(momxy, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa>>ANGLETOFINESHIFT), ns);
mo->momy = FixedMul(FINESINE(fa>>ANGLETOFINESHIFT), ns);
ns = FixedMul(momz, mo->scale);
P_SetObjectMomZ(mo, ns, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1;
}
player->losstime += 10*TICRATE;
if (P_IsObjectOnGround(player->mo))
player->pflags &= ~PF_NIGHTSFALL;
return;
}
void P_PlayerWeaponPanelBurst(player_t *player)
{
mobj_t *mo;
angle_t fa;
fixed_t ns;
INT32 i;
fixed_t z;
INT32 num_weapons = M_CountBits((UINT32)player->ringweapons, NUM_WEAPONS-1);
UINT16 ammoamt = 0;
for (i = 0; i < num_weapons; i++)
{
mobjtype_t weptype = 0;
powertype_t power = 0;
if (player->ringweapons & RW_BOUNCE) // Bounce
{
weptype = MT_BOUNCEPICKUP;
player->ringweapons &= ~RW_BOUNCE;
power = pw_bouncering;
}
else if (player->ringweapons & RW_RAIL) // Rail
{
weptype = MT_RAILPICKUP;
player->ringweapons &= ~RW_RAIL;
power = pw_railring;
}
else if (player->ringweapons & RW_AUTO) // Auto
{
weptype = MT_AUTOPICKUP;
player->ringweapons &= ~RW_AUTO;
power = pw_automaticring;
}
else if (player->ringweapons & RW_EXPLODE) // Explode
{
weptype = MT_EXPLODEPICKUP;
player->ringweapons &= ~RW_EXPLODE;
power = pw_explosionring;
}
else if (player->ringweapons & RW_SCATTER) // Scatter
{
weptype = MT_SCATTERPICKUP;
player->ringweapons &= ~RW_SCATTER;
power = pw_scatterring;
}
else if (player->ringweapons & RW_GRENADE) // Grenade
{
weptype = MT_GRENADEPICKUP;
player->ringweapons &= ~RW_GRENADE;
power = pw_grenadering;
}
if (!weptype) // ???
continue;
if (player->powers[power] >= mobjinfo[weptype].reactiontime)
ammoamt = (UINT16)mobjinfo[weptype].reactiontime;
else
ammoamt = player->powers[power];
player->powers[power] -= ammoamt;
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
mo->reactiontime = ammoamt;
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
// >16 ring type spillout
ns = FixedMul(3*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa),ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 4*FRACUNIT, false);
if (i & 1)
P_SetObjectMomZ(mo, 4*FRACUNIT, true);
}
}
void P_PlayerWeaponAmmoBurst(player_t *player)
{
mobj_t *mo;
angle_t fa;
fixed_t ns;
INT32 i = 0;
fixed_t z;
mobjtype_t weptype = 0;
powertype_t power = 0;
while (true)
{
if (player->powers[pw_bouncering])
{
weptype = MT_BOUNCERING;
power = pw_bouncering;
}
else if (player->powers[pw_railring])
{
weptype = MT_RAILRING;
power = pw_railring;
}
else if (player->powers[pw_infinityring])
{
weptype = MT_INFINITYRING;
power = pw_infinityring;
}
else if (player->powers[pw_automaticring])
{
weptype = MT_AUTOMATICRING;
power = pw_automaticring;
}
else if (player->powers[pw_explosionring])
{
weptype = MT_EXPLOSIONRING;
power = pw_explosionring;
}
else if (player->powers[pw_scatterring])
{
weptype = MT_SCATTERRING;
power = pw_scatterring;
}
else if (player->powers[pw_grenadering])
{
weptype = MT_GRENADERING;
power = pw_grenadering;
}
else
break; // All done!
z = player->mo->z;
if (player->mo->eflags & MFE_VERTICALFLIP)
z += player->mo->height - mobjinfo[weptype].height;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, weptype);
mo->health = player->powers[power];
mo->flags2 |= MF2_DONTRESPAWN;
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
player->powers[power] = 0;
mo->fuse = 12*TICRATE;
mo->destscale = player->mo->scale;
P_SetScale(mo, player->mo->scale);
// Angle offset by player angle
fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT)) & FINEMASK;
// Spill them!
ns = FixedMul(2*FRACUNIT, mo->scale);
mo->momx = FixedMul(FINECOSINE(fa), ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
mo->momy = FixedMul(FINESINE(fa),ns);
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (i & 1)
P_SetObjectMomZ(mo, 3*FRACUNIT, true);
i++;
}
}
//
// P_PlayerEmeraldBurst
//
// Spills ONLY emeralds.
//
void P_PlayerEmeraldBurst(player_t *player, boolean toss)
{
INT32 i;
angle_t fa;
fixed_t ns;
fixed_t z = 0, momx = 0, momy = 0;
// Better safe than sorry.
if (!player)
return;
// Spill power stones
if (player->powers[pw_emeralds])
{
INT32 num_stones = 0;
if (player->powers[pw_emeralds] & EMERALD1)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD2)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD3)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD4)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD5)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD6)
num_stones++;
if (player->powers[pw_emeralds] & EMERALD7)
num_stones++;
for (i = 0; i < num_stones; i++)
{
INT32 stoneflag = 0;
statenum_t statenum = S_CEMG1;
mobj_t *mo;
if (player->powers[pw_emeralds] & EMERALD1)
{
stoneflag = EMERALD1;
statenum = S_CEMG1;
}
else if (player->powers[pw_emeralds] & EMERALD2)
{
stoneflag = EMERALD2;
statenum = S_CEMG2;
}
else if (player->powers[pw_emeralds] & EMERALD3)
{
stoneflag = EMERALD3;
statenum = S_CEMG3;
}
else if (player->powers[pw_emeralds] & EMERALD4)
{
stoneflag = EMERALD4;
statenum = S_CEMG4;
}
else if (player->powers[pw_emeralds] & EMERALD5)
{
stoneflag = EMERALD5;
statenum = S_CEMG5;
}
else if (player->powers[pw_emeralds] & EMERALD6)
{
stoneflag = EMERALD6;
statenum = S_CEMG6;
}
else if (player->powers[pw_emeralds] & EMERALD7)
{
stoneflag = EMERALD7;
statenum = S_CEMG7;
}
if (!stoneflag) // ???
continue;
player->powers[pw_emeralds] &= ~stoneflag;
if (toss)
{
fa = player->mo->angle>>ANGLETOFINESHIFT;
z = player->mo->z + player->mo->height;
if (player->mo->eflags & MFE_VERTICALFLIP)
z -= mobjinfo[MT_FLINGEMERALD].height + player->mo->height;
ns = FixedMul(8*FRACUNIT, player->mo->scale);
}
else
{
fa = ((255 / num_stones) * i) * FINEANGLES/256;
z = player->mo->z + (player->mo->height / 2);
if (player->mo->eflags & MFE_VERTICALFLIP)
z -= mobjinfo[MT_FLINGEMERALD].height;
ns = FixedMul(4*FRACUNIT, player->mo->scale);
}
momx = FixedMul(FINECOSINE(fa), ns);
if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
momy = FixedMul(FINESINE(fa),ns);
else
momy = 0;
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, MT_FLINGEMERALD);
mo->health = 1;
mo->threshold = stoneflag;
mo->flags2 |= (MF2_DONTRESPAWN|MF2_SLIDEPUSH);
mo->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT);
P_SetTarget(&mo->target, player->mo);
mo->fuse = 12*TICRATE;
P_SetMobjState(mo, statenum);
mo->momx = momx;
mo->momy = momy;
P_SetObjectMomZ(mo, 3*FRACUNIT, false);
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz = -mo->momz;
if (toss)
player->tossdelay = 2*TICRATE;
}
}
}
/** Makes an injured or dead player lose possession of the flag.

View file

@ -393,9 +393,6 @@ void P_RemoveShield(player_t *player);
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage);
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source);
void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c
void P_PlayerWeaponPanelBurst(player_t *player);
void P_PlayerWeaponAmmoBurst(player_t *player);
void P_PlayerEmeraldBurst(player_t *player, boolean toss);
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
void P_PlayerFlagBurst(player_t *player, boolean toss);

View file

@ -2021,7 +2021,7 @@ void P_XYMovement(mobj_t *mo)
#endif
//{ SRB2kart stuff
if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG) //(mo->type == MT_JAWZ && !mo->tracer))
if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ_DUD || mo->type == MT_JAWZ || mo->type == MT_BALLHOG || mo->type == MT_FLINGRING) //(mo->type == MT_JAWZ && !mo->tracer))
return;
if (mo->player && (mo->player->kartstuff[k_spinouttimer] && !mo->player->kartstuff[k_wipeoutslow]) && mo->player->speed <= mo->player->normalspeed/2)
@ -2572,11 +2572,11 @@ static boolean P_ZMovement(mobj_t *mo)
mom.z = -mom.z;
else
// Flingrings bounce
if (mo->type == MT_FLINGRING
if (/*mo->type == MT_FLINGRING
|| mo->type == MT_FLINGCOIN
|| P_WeaponOrPanel(mo->type)
|| mo->type == MT_FLINGEMERALD
|| mo->type == MT_BIGTUMBLEWEED
||*/ mo->type == MT_BIGTUMBLEWEED
|| mo->type == MT_LITTLETUMBLEWEED
|| mo->type == MT_CANNONBALLDECOR
|| mo->type == MT_FALLINGROCK)
@ -10371,8 +10371,8 @@ void P_RemoveMobj(mobj_t *mobj)
// Rings only, please!
if (mobj->spawnpoint &&
(mobj->type == MT_RING
|| mobj->type == MT_COIN
(/*mobj->type == MT_RING
||*/ mobj->type == MT_COIN
|| mobj->type == MT_BLUEBALL
|| mobj->type == MT_REDTEAMRING
|| mobj->type == MT_BLUETEAMRING
@ -12073,7 +12073,7 @@ ML_NOCLIMB : Direction not controllable
void P_SpawnHoopsAndRings(mapthing_t *mthing)
{
mobj_t *mobj = NULL;
INT32 /*r,*/ i;
INT32 r, i;
fixed_t x, y, z, finalx, finaly, finalz;
sector_t *sec;
TVector v, *res;
@ -12360,8 +12360,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
return;
}
else return; // srb2kart - no rings or ring-like objects in R1
/*
// Wing logo item.
else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
{
@ -12655,7 +12653,8 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
}
}
return;
}*/
}
else return;
}
//

View file

@ -946,50 +946,19 @@ void P_ResetPlayer(player_t *player)
//
void P_GivePlayerRings(player_t *player, INT32 num_rings)
{
if (player->bot)
player = &players[consoleplayer];
if (!player->mo)
return;
player->mo->health += num_rings;
player->health += num_rings;
if (G_BattleGametype()) // No rings in Battle Mode
return;
if (!G_IsSpecialStage(gamemap) || !useNightsSS)
player->totalring += num_rings;
player->kartstuff[k_rings] += num_rings;
//player->totalring += num_rings; // Used for GP lives later
//{ SRB2kart - rings don't really do anything, but we don't want the player spilling them later.
/*
// Can only get up to 9999 rings, sorry!
if (player->mo->health > 10000)
{
player->mo->health = 10000;
player->health = 10000;
}
else if (player->mo->health < 1)*/
{
player->mo->health = 1;
player->health = 1;
}
//}
// Now extra life bonuses are handled here instead of in P_MovePlayer, since why not?
if (!ultimatemode && !modeattacking && !G_IsSpecialStage(gamemap) && G_GametypeUsesLives())
{
INT32 gainlives = 0;
while (player->xtralife < maxXtraLife && player->health > 100 * (player->xtralife+1))
{
++gainlives;
++player->xtralife;
}
if (gainlives)
{
P_GivePlayerLives(player, gainlives);
P_PlayLivesJingle(player);
}
}
if (player->kartstuff[k_rings] > 20)
player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry!
else if (player->kartstuff[k_rings] < -20)
player->kartstuff[k_rings] = -20; // Chaotix ring debt!
}
//
@ -1114,11 +1083,10 @@ void P_PlayLivesJingle(player_t *player)
void P_PlayRinglossSound(mobj_t *source)
{
sfxenum_t key = P_RandomKey(2);
if (cv_kartvoices.value)
S_StartSound(source, (mariomode) ? sfx_mario8 : sfx_khurt1 + key);
if (source->player && source->player->kartstuff[k_rings] <= 0)
S_StartSound(source, sfx_s1a6);
else
S_StartSound(source, sfx_slip);
S_StartSound(source, sfx_s1c6);
}
void P_PlayDeathSound(mobj_t *source)
@ -9294,7 +9262,8 @@ void P_PlayerThink(player_t *player)
#if 1
// "Blur" a bit when you have speed shoes and are going fast enough
if ((player->powers[pw_super] || player->powers[pw_sneakers]
|| player->kartstuff[k_driftboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost]) && !player->kartstuff[k_invincibilitytimer] // SRB2kart
|| player->kartstuff[k_driftboost] || player->kartstuff[k_ringboost] || player->kartstuff[k_sneakertimer] || player->kartstuff[k_startboost])
&& !player->kartstuff[k_invincibilitytimer] // SRB2kart
&& (player->speed + abs(player->mo->momz)) > FixedMul(20*FRACUNIT,player->mo->scale))
{
mobj_t *gmobj = P_SpawnGhostMobj(player->mo);