Lots more UFO work

- UFO is able to be damaged. (No damage values set yet, so it has an obnoxious amount of health.)
- Emerald becomes collectible when fully damaged.
- Jawz can target the UFO.
- Tweaked some of the speed values.
This commit is contained in:
Sally Coolatta 2022-11-22 16:31:30 -05:00
parent dc6caf1eb3
commit d1b2e42560
7 changed files with 146 additions and 36 deletions

View file

@ -29061,7 +29061,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_SPECIAL_UFO
-1, // doomednum
S_CHAOSEMERALD1, // spawnstate
1000, // spawnhealth
101, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime

View file

@ -6716,12 +6716,18 @@ static void K_MoveHeldObjects(player_t *player)
}
}
player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
mobj_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
{
fixed_t best = INT32_MAX;
player_t *wtarg = NULL;
mobj_t *wtarg = NULL;
INT32 i;
if (specialStage.active == true)
{
// Always target the UFO.
return specialStage.ufo;
}
for (i = 0; i < MAXPLAYERS; i++)
{
angle_t thisang = ANGLE_MAX;
@ -6737,7 +6743,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
player = &players[i];
// Don't target yourself, stupid.
if (player == source)
if (source != NULL && player == source)
{
continue;
}
@ -6776,7 +6782,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
if (gametyperules & GTR_CIRCUIT)
{
if (player->position >= source->position)
if (source != NULL && player->position >= source->position)
{
// Don't pay attention to people who aren't above your position
continue;
@ -6818,7 +6824,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range)
if (thisScore < best)
{
wtarg = player;
wtarg = player->mo;
best = thisScore;
}
}
@ -7944,24 +7950,32 @@ void K_KartPlayerAfterThink(player_t *player)
// Jawz reticule (seeking)
if (player->itemtype == KITEM_JAWZ && (player->pflags & PF_ITEMOUT))
{
INT32 lastTargID = player->lastjawztarget;
player_t *lastTarg = NULL;
player_t *targ = NULL;
const INT32 lastTargID = player->lastjawztarget;
mobj_t *lastTarg = NULL;
INT32 targID = MAXPLAYERS;
mobj_t *targ = NULL;
mobj_t *ret = NULL;
if ((lastTargID >= 0 && lastTargID <= MAXPLAYERS)
if (specialStage.active == true && lastTargID == MAXPLAYERS)
{
// Aiming at the UFO.
lastTarg = specialStage.ufo;
}
else if ((lastTargID >= 0 && lastTargID <= MAXPLAYERS)
&& playeringame[lastTargID] == true)
{
if (players[lastTargID].spectator == false)
{
lastTarg = &players[lastTargID];
lastTarg = players[lastTargID].mo;
}
}
if (player->throwdir == -1)
{
// Backwards Jawz targets yourself.
targ = player;
targ = player->mo;
player->jawztargetdelay = 0;
}
else
@ -7970,9 +7984,14 @@ void K_KartPlayerAfterThink(player_t *player)
targ = K_FindJawzTarget(player->mo, player, ANGLE_45);
}
if (targ != NULL && targ->mo != NULL && P_MobjWasRemoved(targ->mo) == false)
if (targ != NULL && P_MobjWasRemoved(targ) == false)
{
if (targ - players == lastTargID)
if (targ->player != NULL)
{
targID = targ->player - players;
}
if (targID == lastTargID)
{
// Increment delay.
if (player->jawztargetdelay < 10)
@ -7991,33 +8010,33 @@ void K_KartPlayerAfterThink(player_t *player)
else
{
// Allow a swap.
if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ))
if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ->player))
{
S_StartSound(NULL, sfx_s3k89);
}
else
{
S_StartSound(targ->mo, sfx_s3k89);
S_StartSound(targ, sfx_s3k89);
}
player->lastjawztarget = targ - players;
player->lastjawztarget = targID;
player->jawztargetdelay = 5;
}
}
}
if (targ == NULL || targ->mo == NULL || P_MobjWasRemoved(targ->mo) == true)
if (targ == NULL || P_MobjWasRemoved(targ) == true)
{
player->lastjawztarget = -1;
player->jawztargetdelay = 0;
return;
}
ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE);
ret->old_x = targ->mo->old_x;
ret->old_y = targ->mo->old_y;
ret->old_z = targ->mo->old_z;
P_SetTarget(&ret->target, targ->mo);
ret = P_SpawnMobj(targ->x, targ->y, targ->z, MT_PLAYERRETICULE);
ret->old_x = targ->old_x;
ret->old_y = targ->old_y;
ret->old_z = targ->old_z;
P_SetTarget(&ret->target, targ);
ret->frame |= ((leveltime % 10) / 2);
ret->tics = 1;
ret->color = player->skincolor;

View file

@ -118,7 +118,7 @@ void K_UpdateHnextList(player_t *player, boolean clean);
void K_DropHnextList(player_t *player, boolean keepshields);
void K_RepairOrbitChain(mobj_t *orbit);
void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player);
player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range);
mobj_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range);
INT32 K_GetKartRingPower(player_t *player, boolean boosted);
void K_UpdateDistanceFromFinishLine(player_t *const player);
boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y);

View file

@ -59,6 +59,7 @@ mobj_t *Obj_SpawnBrolyKi(mobj_t *source, tic_t duration);
/* Special Stage UFO */
void Obj_SpecialUFOThinker(mobj_t *bomb);
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType);
mobj_t *Obj_CreateSpecialUFO(void);
UINT32 K_GetSpecialUFODistance(void);

View file

@ -140,17 +140,21 @@ static void JawzChase(mobj_t *th, boolean grounded)
if (jawz_chase(th) == NULL || P_MobjWasRemoved(jawz_chase(th)) == true)
{
mobj_t *newChase = NULL;
player_t *owner = NULL;
th->angle = K_MomentumAngle(th);
if (jawz_owner(th) != NULL && P_MobjWasRemoved(jawz_owner(th)) == false
&& jawz_owner(th)->player != NULL)
if ((jawz_owner(th) != NULL && P_MobjWasRemoved(jawz_owner(th)) == false)
&& (jawz_owner(th)->player != NULL))
{
player_t *newPlayer = K_FindJawzTarget(th, jawz_owner(th)->player, ANGLE_90);
owner = jawz_owner(th)->player;
}
if (newPlayer != NULL)
{
P_SetTarget(&jawz_chase(th), newPlayer->mo);
}
newChase = K_FindJawzTarget(th, owner, ANGLE_90);
if (newChase != NULL)
{
P_SetTarget(&jawz_chase(th), newChase);
}
}

View file

@ -7,8 +7,8 @@
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file shrink.c
/// \brief Shrink laser item code.
/// \file ufo.c
/// \brief Special Stage UFO
#include "../doomdef.h"
#include "../doomstat.h"
@ -24,11 +24,11 @@
#include "../k_waypoint.h"
#include "../k_specialstage.h"
#define UFO_BASE_SPEED (12 * FRACUNIT) // UFO's slowest speed.
#define UFO_SPEEDUP (FRACUNIT)
#define UFO_BASE_SPEED (16 * FRACUNIT) // UFO's slowest speed.
#define UFO_SPEEDUP (FRACUNIT >> 3)
#define UFO_SLOWDOWN (FRACUNIT >> 2)
#define UFO_SPACING (1024 * FRACUNIT)
#define UFO_DEADZONE (512 * FRACUNIT)
#define UFO_DEADZONE (768 * FRACUNIT)
#define UFO_SPEEDFACTOR (FRACUNIT * 9 / 10)
#define ufo_waypoint(o) ((o)->extravalue1)
@ -49,6 +49,11 @@ static fixed_t GenericDistance(
return P_AproxDistance(P_AproxDistance(destx - curx, desty - cury), destz - curz);
}
static boolean UFOEmeraldChase(mobj_t *ufo)
{
return (ufo->health <= 1);
}
static void UFOUpdateDistanceToFinish(mobj_t *ufo)
{
waypoint_t *finishLine = K_GetFinishLineWaypoint();
@ -314,17 +319,86 @@ static void UFOMove(mobj_t *ufo)
}
}
static void UFOEmeraldVFX(mobj_t *ufo)
{
if (leveltime % 3 == 0)
{
mobj_t *sparkle = P_SpawnMobjFromMobj(
ufo,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT,
MT_EMERALDSPARK
);
sparkle->color = ufo->color;
sparkle->momz += 8 * ufo->scale * P_MobjFlip(ufo);
}
}
void Obj_SpecialUFOThinker(mobj_t *ufo)
{
UFOMove(ufo);
UFOUpdateAngle(ufo);
UFOUpdateDistanceToFinish(ufo);
UFOUpdateSpeed(ufo);
if (UFOEmeraldChase(ufo) == true)
{
// Spawn emerald sparkles
UFOEmeraldVFX(ufo);
}
}
static UINT8 GetUFODamage(mobj_t *inflictor)
{
if (inflictor == NULL || P_MobjWasRemoved(inflictor) == true)
{
return 1;
}
switch (inflictor->type)
{
default:
{
return 1;
}
}
}
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType)
{
UINT8 damage = 1;
(void)source;
(void)damageType;
if (UFOEmeraldChase(ufo) == true)
{
// Damaged fully already, no need for any more.
ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW); // Double check flags, just to be sure.
return false;
}
damage = GetUFODamage(inflictor);
if (damage >= ufo->health - 1)
{
// Turn into just an emerald, and make it collectible!
ufo->health = 1;
ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW);
return true;
}
ufo->health -= damage;
K_SetHitLagForObjects(ufo, inflictor, damage * 6, true);
return true;
}
static mobj_t *InitSpecialUFO(waypoint_t *start)
{
mobj_t *ufo = NULL;
mobj_t *underlay = NULL;
if (start == NULL)
{
@ -343,6 +417,13 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
ufo_speed(ufo) = UFO_BASE_SPEED;
ufo->color = SKINCOLOR_CHAOSEMERALD1;
underlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY);
P_SetTarget(&underlay->target, ufo);
P_SetMobjState(underlay, S_CHAOSEMERALD_UNDER);
underlay->color = ufo->color;
return ufo;
}

View file

@ -2222,6 +2222,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
else
{
if (target->type == MT_SPECIAL_UFO)
{
return Obj_SpecialUFODamage(target, inflictor, source, damagetype);
}
if (damagetype & DMG_STEAL)
{
// Not a player, steal damage is intended to not do anything