mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-12-27 21:01:04 +00:00
Logic for itemboxes, demonic red shells from hell, and bobomb explosions. Just a rough copy-paste.
This commit is contained in:
parent
dd4bb4259a
commit
b9db247d55
2 changed files with 381 additions and 11 deletions
|
@ -209,7 +209,6 @@ void A_BrakLobShot();
|
|||
void A_NapalmScatter();
|
||||
void A_SpawnFreshCopy();
|
||||
void A_ItemPop();
|
||||
void A_CapsulePop();
|
||||
void A_KartItems();
|
||||
void A_Hover();
|
||||
void A_Lakitu();
|
||||
|
|
385
src/p_enemy.c
385
src/p_enemy.c
|
@ -236,6 +236,16 @@ void A_BrakFireShot(mobj_t *actor);
|
|||
void A_BrakLobShot(mobj_t *actor);
|
||||
void A_NapalmScatter(mobj_t *actor);
|
||||
void A_SpawnFreshCopy(mobj_t *actor);
|
||||
// SRB2kart 16/03/27
|
||||
void A_ItemPop(mobj_t *actor);
|
||||
void A_AirBox(mobj_t *actor);
|
||||
void A_CapsulePop(mobj_t *actor);
|
||||
void A_KartItems(mobj_t *actor);
|
||||
void A_Hover(mobj_t *actor);
|
||||
void A_Lakitu(mobj_t *actor);
|
||||
void A_RedShellChase(mobj_t *actor);
|
||||
void A_BobombExplode(mobj_t *actor);
|
||||
//
|
||||
|
||||
//
|
||||
// ENEMY THINKING
|
||||
|
@ -844,6 +854,11 @@ void A_Look(mobj_t *actor)
|
|||
if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale)))
|
||||
return;
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
if (leveltime < 4*TICRATE && gametype == GT_RACE)
|
||||
return;
|
||||
//
|
||||
|
||||
// go into chase state
|
||||
if (!locvar2)
|
||||
{
|
||||
|
@ -3004,6 +3019,8 @@ void A_RingShield(mobj_t *actor)
|
|||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
if (!player->exiting)
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
|
@ -3030,8 +3047,11 @@ void A_RingBox(mobj_t *actor)
|
|||
|
||||
player = actor->target->player;
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
if (!player->exiting)
|
||||
P_GivePlayerRings(player, actor->info->reactiontime);
|
||||
if (actor->info->seesound)
|
||||
|
||||
if (!player->exiting && actor->info->seesound)
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
}
|
||||
|
||||
|
@ -3059,7 +3079,7 @@ void A_Invincibility(mobj_t *actor)
|
|||
player = actor->target->player;
|
||||
player->powers[pw_invulnerability] = invulntics + 1;
|
||||
|
||||
if (P_IsLocalPlayer(player) && !player->powers[pw_super])
|
||||
if (P_IsLocalPlayer(player) && !player->powers[pw_super] && !player->exiting)
|
||||
{
|
||||
S_StopMusic();
|
||||
if (mariomode)
|
||||
|
@ -3067,6 +3087,10 @@ void A_Invincibility(mobj_t *actor)
|
|||
S_ChangeMusic(mus_minvnc, false);
|
||||
G_GhostAddColor(GHC_INVINCIBLE);
|
||||
}
|
||||
else if (retrokart) // SRB2kart 16/03/27
|
||||
S_ChangeMusic(mus_rinvnc, true);
|
||||
else if (neokart)
|
||||
S_ChangeMusic(mus_rinvnc, true);
|
||||
else
|
||||
S_ChangeMusic(mus_invinc, false);
|
||||
}
|
||||
|
@ -3753,6 +3777,7 @@ void A_ThrownRing(mobj_t *actor)
|
|||
INT32 stop;
|
||||
player_t *player;
|
||||
fixed_t dist;
|
||||
fixed_t SHELL_DIST; // SRB2kart 16/03/27
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_ThrownRing", actor))
|
||||
return;
|
||||
|
@ -3819,13 +3844,13 @@ void A_ThrownRing(mobj_t *actor)
|
|||
// sure to stop the attraction!
|
||||
if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
|
||||
&& P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x,
|
||||
actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale)))
|
||||
actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST, actor->tracer->scale))) // SRB2kart 16/03/27
|
||||
{
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
}
|
||||
|
||||
if (actor->tracer && (actor->tracer->health)
|
||||
&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow.
|
||||
if (actor->tracer && (actor->tracer->health) && (retrokart || neokart)) // SRB2kart 16/03/27
|
||||
//&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow.
|
||||
{
|
||||
const INT32 temp = actor->threshold;
|
||||
actor->threshold = 32000;
|
||||
|
@ -3875,6 +3900,13 @@ void A_ThrownRing(mobj_t *actor)
|
|||
if (gametype == GT_CTF
|
||||
&& actor->target->player->ctfteam == player->ctfteam)
|
||||
continue;
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
if (actor->target->player->position < player->position) // Red Shells only go after people ahead of you
|
||||
continue;
|
||||
|
||||
SHELL_DIST = 2048;
|
||||
SHELL_DIST = SHELL_DIST*FRACUNIT;
|
||||
}
|
||||
|
||||
dist = P_AproxDistance(P_AproxDistance(player->mo->x-actor->x,
|
||||
|
@ -3894,7 +3926,7 @@ void A_ThrownRing(mobj_t *actor)
|
|||
continue; // out of sight
|
||||
|
||||
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
|
||||
&& dist < FixedMul(RING_DIST/4, player->mo->scale))
|
||||
&& dist < FixedMul(SHELL_DIST/4, player->mo->scale)) // SRB2kart 16/03/27
|
||||
P_SetTarget(&actor->tracer, player->mo);
|
||||
return;
|
||||
}
|
||||
|
@ -5257,8 +5289,13 @@ void A_RingExplode(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
for (d = 0; d < 16; d++)
|
||||
P_SpawnParaloop(actor->x, actor->y, actor->z, 32*FRACUNIT, 32, MT_EXPLOSION, d*(ANGLE_45/4), true, false); // 32 <-> 64
|
||||
/*
|
||||
for (d = 0; d < 16; d++)
|
||||
P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true);
|
||||
*/
|
||||
|
||||
S_StartSound(actor, sfx_prloop);
|
||||
|
||||
|
@ -7512,7 +7549,17 @@ void A_MoveAbsolute(mobj_t *actor)
|
|||
return;
|
||||
#endif
|
||||
|
||||
P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale));
|
||||
// SRB2kart 16/03/27
|
||||
INT32 newangle;
|
||||
if (actor->flags & MF_AMBUSH)
|
||||
newangle = actor->angle+FixedAngle(locvar1*FRACUNIT);
|
||||
else
|
||||
newangle = FixedAngle(locvar1*FRACUNIT);
|
||||
|
||||
P_InstaThrust(actor, newangle, locvar2*FRACUNIT);
|
||||
//
|
||||
|
||||
//P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale));
|
||||
}
|
||||
|
||||
// Function: A_Thrust
|
||||
|
@ -8006,6 +8053,330 @@ void A_ToggleFlameJet(mobj_t* actor)
|
|||
}
|
||||
}
|
||||
|
||||
// SRB2kart 16/03/27
|
||||
// Function: A_ItemPop
|
||||
//
|
||||
// Description: Used by Kart monitors when they explode.
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_ItemPop(mobj_t *actor)
|
||||
{
|
||||
mobj_t *remains;
|
||||
mobjtype_t item = 0;
|
||||
|
||||
// 16/03/27 TODO: Make Item boxes not 'solid', or make it less obvious when the player
|
||||
// hits more than one at once. It's very noticable if a player hits a
|
||||
// cluster of boxes, and you can see momentum changing from collision.
|
||||
|
||||
// de-solidify
|
||||
P_UnsetThingPosition(actor);
|
||||
actor->flags &= ~MF_SOLID;
|
||||
actor->flags |= MF_NOCLIP;
|
||||
P_SetThingPosition(actor);
|
||||
|
||||
remains = P_SpawnMobj(actor->x, actor->y, actor->z, MT_ITEMEXPLOSION);
|
||||
remains->type = actor->type; // Transfer type information
|
||||
P_UnsetThingPosition(remains);
|
||||
if (sector_list)
|
||||
{
|
||||
P_DelSeclist(sector_list);
|
||||
sector_list = NULL;
|
||||
}
|
||||
remains->flags = actor->flags; // Transfer flags
|
||||
P_SetThingPosition(remains);
|
||||
remains->flags2 = actor->flags2; // Transfer flags2
|
||||
remains->fuse = actor->fuse; // Transfer respawn timer
|
||||
remains->threshold = 68;
|
||||
remains->skin = NULL;
|
||||
|
||||
actor->flags2 |= MF2_BOSSNOTRAP; // Dummy flag to mark this as an exploded TV until it respawns
|
||||
tmthing = remains;
|
||||
|
||||
if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound);
|
||||
|
||||
switch (actor->type)
|
||||
{
|
||||
case MT_QUESTIONBOX2: // Random!
|
||||
{
|
||||
if (actor->target && actor->target->player
|
||||
&& !(actor->target->player->powers[pw_shell] & 2 || actor->target->player->powers[pw_tripleshell] & 8
|
||||
|| actor->target->player->powers[pw_redshell] & 2 || actor->target->player->powers[pw_tripleredshell] & 8
|
||||
|| actor->target->player->powers[pw_banana] & 2 || actor->target->player->powers[pw_triplebanana] & 8
|
||||
|| actor->target->player->powers[pw_fakeitem] & 2 || actor->target->player->powers[pw_kitchensink]
|
||||
|| actor->target->player->powers[pw_bomb] & 2 || actor->target->player->powers[pw_blueshell]
|
||||
|| actor->target->player->powers[pw_shroom]
|
||||
|| actor->target->player->powers[pw_star] || actor->target->player->powers[pw_goldshroom]
|
||||
|| actor->target->player->powers[pw_thunder] || actor->target->player->powers[pw_megamushroom]
|
||||
|| actor->target->player->powers[pw_kartitem] || actor->target->player->powers[pw_itemslot]
|
||||
|| actor->target->player->powers[pw_boo] || actor->target->player->powers[pw_bootake]
|
||||
|| actor->target->player->powers[pw_boostolen] || actor->target->player->powers[pw_greenboo])
|
||||
)
|
||||
actor->target->player->powers[pw_kartitem] = 1;
|
||||
else if(cv_debug && !(actor->target && actor->target->player))
|
||||
CONS_Printf("ERROR: Powerup has no target!\n");
|
||||
|
||||
remains->flags &= ~MF_AMBUSH;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
item = actor->info->damage;
|
||||
break;
|
||||
}
|
||||
|
||||
P_RemoveMobj(actor);
|
||||
}
|
||||
|
||||
// Function: A_Hover
|
||||
//
|
||||
// Description: Makes the Thing hover on the ground.
|
||||
//
|
||||
// var1 = slow hover
|
||||
// var2 = unused
|
||||
//
|
||||
void A_Hover(mobj_t *actor)
|
||||
{
|
||||
fixed_t thefloor;
|
||||
thefloor = actor->floorz;
|
||||
|
||||
if (actor->z < thefloor + (16*FRACUNIT))
|
||||
actor->momz += FRACUNIT;
|
||||
else if (actor->z < thefloor + (32*FRACUNIT))
|
||||
actor->momz += FRACUNIT/2;
|
||||
else
|
||||
actor->momz += 16;
|
||||
}
|
||||
|
||||
// Function: A_Lakitu
|
||||
//
|
||||
// Description: Lowers the object down, or it rises up.
|
||||
//
|
||||
// var1 = 1 is to descend, 2 is to ascend and disappear
|
||||
// var2 = unused
|
||||
//
|
||||
void A_Lakitu(mobj_t *actor)
|
||||
{
|
||||
fixed_t thefloor;
|
||||
thefloor = actor->target->player->mo->z;
|
||||
if (!actor->target->player)
|
||||
{
|
||||
P_SetMobjState(actor, S_DISS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (var1 == 1 || var1 > 3)
|
||||
{
|
||||
if (actor->target->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (actor->z < thefloor - (86*FRACUNIT))
|
||||
actor->momz += FRACUNIT/3;
|
||||
if (actor->z > thefloor - (60*FRACUNIT))
|
||||
actor->momz = 0;
|
||||
if (leveltime >= 52 && var1 == 1)
|
||||
P_SetMobjState(actor, S_LAKITUSL2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor->z > thefloor + (86*FRACUNIT))
|
||||
actor->momz -= FRACUNIT/3;
|
||||
if (actor->z < thefloor + (60*FRACUNIT))
|
||||
actor->momz = 0;
|
||||
if (leveltime >= 52 && var1 == 1)
|
||||
P_SetMobjState(actor, S_LAKITUSL2);
|
||||
}
|
||||
|
||||
if (actor->momz == 0 && var1 == 4)
|
||||
P_SetMobjState(actor, S_LAKITULAP1B);
|
||||
if (actor->momz == 0 && var1 == 5)
|
||||
P_SetMobjState(actor, S_LAKITULAP2B);
|
||||
if (actor->momz == 0 && var1 == 6)
|
||||
P_SetMobjState(actor, S_LAKITULAP3B);
|
||||
if (actor->momz == 0 && var1 == 7)
|
||||
P_SetMobjState(actor, S_LAKITULAP4B);
|
||||
if (actor->momz == 0 && var1 == 8)
|
||||
P_SetMobjState(actor, S_LAKITULAP5B);
|
||||
if (actor->momz == 0 && var1 == 9)
|
||||
P_SetMobjState(actor, S_LAKITULAP6B);
|
||||
if (actor->momz == 0 && var1 == 10)
|
||||
P_SetMobjState(actor, S_LAKITULAP7B);
|
||||
if (actor->momz == 0 && var1 == 11)
|
||||
P_SetMobjState(actor, S_LAKITULAP8B);
|
||||
if (actor->momz == 0 && var1 == 12)
|
||||
P_SetMobjState(actor, S_LAKITULAPFB);
|
||||
}
|
||||
else if (var1 == 2 || var1 == 3)
|
||||
{
|
||||
if (actor->target->eflags & MFE_VERTICALFLIP)
|
||||
actor->momz -= FRACUNIT;
|
||||
else
|
||||
actor->momz += FRACUNIT;
|
||||
|
||||
if (leveltime > 175 && actor->target->player->airtime == 0)
|
||||
P_SetMobjState(actor, S_DISS);
|
||||
}
|
||||
if (actor->target->player != &players[displayplayer] && !splitscreen)
|
||||
actor->flags2 |= MF2_DONTDRAW;
|
||||
else
|
||||
actor->flags2 &= ~MF2_DONTDRAW;
|
||||
}
|
||||
|
||||
// Function: A_RedShellChase
|
||||
//
|
||||
// Description: Chase routine for Red Shells
|
||||
//
|
||||
// var1 = unused
|
||||
// var2 = unused
|
||||
//
|
||||
void A_RedShellChase(mobj_t *actor)
|
||||
{
|
||||
|
||||
INT32 c = 0;
|
||||
INT32 stop;
|
||||
player_t *player;
|
||||
|
||||
if (actor->tracer)
|
||||
{
|
||||
if (!actor->tracer->health)
|
||||
{
|
||||
P_SetTarget(&actor->tracer, NULL);
|
||||
}
|
||||
|
||||
if (actor->tracer && (actor->tracer->health))
|
||||
{
|
||||
P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// first time init, this allow minimum lastlook changes
|
||||
if (actor->lastlook == -1)
|
||||
actor->lastlook = P_Random();
|
||||
|
||||
actor->lastlook %= MAXPLAYERS;
|
||||
|
||||
stop = (actor->lastlook - 1) & PLAYERSMASK;
|
||||
|
||||
if (actor->lastlook >= 0)
|
||||
{
|
||||
for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK)
|
||||
{
|
||||
if (!playeringame[actor->lastlook])
|
||||
continue;
|
||||
|
||||
if (c++ == 2)
|
||||
return;
|
||||
|
||||
player = &players[actor->lastlook];
|
||||
|
||||
if (!player->mo)
|
||||
continue;
|
||||
|
||||
if (player->mo->health <= 0)
|
||||
continue; // dead
|
||||
|
||||
if ((netgame || multiplayer) && player->spectator)
|
||||
continue; // spectator
|
||||
|
||||
if (actor->target && actor->target->player)
|
||||
{
|
||||
if (player->mo == actor->target)
|
||||
continue;
|
||||
|
||||
// Don't home in on teammates.
|
||||
if (gametype == GT_CTF
|
||||
&& actor->target->player->ctfteam == player->ctfteam)
|
||||
continue;
|
||||
|
||||
if (gametype == GT_RACE) // Only in races, in match and CTF you should go after any nearby players
|
||||
{
|
||||
// USER TARGET
|
||||
if (actor->target->player->position != (player->position + 1)) // Red Shells only go after the person directly ahead of you -Sryder
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(gametype == GT_RACE))
|
||||
{
|
||||
if (P_AproxDistance(P_AproxDistance(player->mo->x-actor->x,
|
||||
player->mo->y-actor->y), player->mo->z-actor->z) > RING_DIST)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((gametype == GT_RACE) || (gametype != GT_RACE // If in match etc. only home in when you get close enough, in race etc. home in all the time
|
||||
&& P_AproxDistance(P_AproxDistance(player->mo->x-actor->x,
|
||||
player->mo->y-actor->y), player->mo->z-actor->z) < RING_DIST))
|
||||
P_SetTarget(&actor->tracer, player->mo);
|
||||
return;
|
||||
|
||||
// Moved to bottom so it doesn't not check the last player
|
||||
// done looking
|
||||
if (actor->lastlook == stop)
|
||||
{
|
||||
if (gametype == GT_RACE)
|
||||
actor->lastlook = -2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// Function: A_BobombExplode
|
||||
//
|
||||
// Description: Slightly altered Ring Explode, allows you to use var1 to specify the object spawned
|
||||
//
|
||||
// var1 = Object spawned.
|
||||
// var2 = unused
|
||||
//
|
||||
void A_BobombExplode(mobj_t *actor)
|
||||
{
|
||||
mobj_t *mo2;
|
||||
thinker_t *th;
|
||||
INT32 d;
|
||||
INT32 locvar1 = var1;
|
||||
mobjtype_t type;
|
||||
|
||||
type = (mobjtype_t)locvar1;
|
||||
|
||||
for (d = 0; d < 16; d++)
|
||||
P_SpawnKartExplosion(actor->x, actor->y, actor->z, actor->info->painchance + 32*FRACUNIT, 32, type, d*(ANGLE_45/4), false, false); // 32 <-> 64
|
||||
|
||||
S_StartSound(actor, sfx_prloop);
|
||||
|
||||
for (th = thinkercap.next; th != &thinkercap; th = th->next)
|
||||
{
|
||||
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
|
||||
continue;
|
||||
|
||||
mo2 = (mobj_t *)th;
|
||||
|
||||
if (mo2 == actor) // Don't explode yourself! Endless loop!
|
||||
continue;
|
||||
|
||||
if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > actor->info->painchance)
|
||||
continue;
|
||||
|
||||
if ((mo2->flags & MF_SHOOTABLE) && !(mo2->flags & MF_SCENERY))
|
||||
{
|
||||
actor->flags2 |= MF2_DEBRIS;
|
||||
|
||||
if (mo2->player) // Looks like we're going to have to need a seperate function for this too
|
||||
P_ExplodePlayerMobj(mo2, actor->target);
|
||||
else
|
||||
P_DamageMobj(mo2, actor, actor->target, 1);
|
||||
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
// Function: A_OrbitNights
|
||||
//
|
||||
// Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.)
|
||||
|
|
Loading…
Reference in a new issue