mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
First pass on UFO visuals
This commit is contained in:
parent
2c5df772c8
commit
a524422071
7 changed files with 313 additions and 17 deletions
|
|
@ -4534,6 +4534,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
||||||
// Broly Ki Orb
|
// Broly Ki Orb
|
||||||
"S_BROLY1",
|
"S_BROLY1",
|
||||||
"S_BROLY2",
|
"S_BROLY2",
|
||||||
|
|
||||||
|
"S_SPECIAL_UFO_POD",
|
||||||
|
"S_SPECIAL_UFO_OVERLAY",
|
||||||
|
"S_SPECIAL_UFO_ARM",
|
||||||
|
"S_SPECIAL_UFO_STEM",
|
||||||
};
|
};
|
||||||
|
|
||||||
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
// RegEx to generate this from info.h: ^\tMT_([^,]+), --> \t"MT_\1",
|
||||||
|
|
@ -5631,6 +5636,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
||||||
"MT_BROLY",
|
"MT_BROLY",
|
||||||
|
|
||||||
"MT_SPECIAL_UFO",
|
"MT_SPECIAL_UFO",
|
||||||
|
"MT_SPECIAL_UFO_PIECE",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *const MOBJFLAG_LIST[] = {
|
const char *const MOBJFLAG_LIST[] = {
|
||||||
|
|
|
||||||
40
src/info.c
40
src/info.c
|
|
@ -785,6 +785,10 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
|
|
||||||
"FLBM",
|
"FLBM",
|
||||||
|
|
||||||
|
"UFOB",
|
||||||
|
"UFOA",
|
||||||
|
"UFOS",
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
"VIEW",
|
"VIEW",
|
||||||
};
|
};
|
||||||
|
|
@ -5146,6 +5150,11 @@ state_t states[NUMSTATES] =
|
||||||
// Broly Ki Orb
|
// Broly Ki Orb
|
||||||
{SPR_LSSJ, FF_REVERSESUBTRACT|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BROLY2}, // S_BROLY1
|
{SPR_LSSJ, FF_REVERSESUBTRACT|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_BROLY2}, // S_BROLY1
|
||||||
{SPR_NULL, 0, 5*TICRATE, {A_SSMineFlash}, 0, 0, S_NULL}, // S_BROLY2
|
{SPR_NULL, 0, 5*TICRATE, {A_SSMineFlash}, 0, 0, S_NULL}, // S_BROLY2
|
||||||
|
|
||||||
|
{SPR_UFOB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_POD
|
||||||
|
{SPR_UFOB, 1|FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_SPECIAL_UFO_OVERLAY
|
||||||
|
{SPR_UFOA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_ARM
|
||||||
|
{SPR_UFOS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_STEM
|
||||||
};
|
};
|
||||||
|
|
||||||
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
|
|
@ -29058,7 +29067,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
{ // MT_SPECIAL_UFO
|
{ // MT_SPECIAL_UFO
|
||||||
-1, // doomednum
|
-1, // doomednum
|
||||||
S_CHAOSEMERALD1, // spawnstate
|
S_CHAOSEMERALD1, // spawnstate
|
||||||
101, // spawnhealth
|
101, // spawnhealth
|
||||||
|
|
@ -29075,7 +29084,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL, // xdeathstate
|
S_NULL, // xdeathstate
|
||||||
sfx_None, // deathsound
|
sfx_None, // deathsound
|
||||||
0, // speed
|
0, // speed
|
||||||
72*FRACUNIT, // radius
|
108*FRACUNIT, // radius
|
||||||
72*FRACUNIT, // height
|
72*FRACUNIT, // height
|
||||||
0, // display offset
|
0, // display offset
|
||||||
16, // mass
|
16, // mass
|
||||||
|
|
@ -29084,6 +29093,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
MF_SHOOTABLE|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
MF_SHOOTABLE|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ // MT_SPECIAL_UFO_PIECE
|
||||||
|
-1, // doomednum
|
||||||
|
S_INVISIBLE, // spawnstate
|
||||||
|
1000, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
8, // reactiontime
|
||||||
|
sfx_None, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
0, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_NULL, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_None, // deathsound
|
||||||
|
0, // speed
|
||||||
|
8*FRACUNIT, // radius
|
||||||
|
16*FRACUNIT, // height
|
||||||
|
1, // display offset
|
||||||
|
100, // mass
|
||||||
|
1, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
skincolor_t skincolors[MAXSKINCOLORS] = {
|
skincolor_t skincolors[MAXSKINCOLORS] = {
|
||||||
|
|
|
||||||
10
src/info.h
10
src/info.h
|
|
@ -1332,6 +1332,10 @@ typedef enum sprite
|
||||||
|
|
||||||
SPR_FLBM, // Finish line beam
|
SPR_FLBM, // Finish line beam
|
||||||
|
|
||||||
|
SPR_UFOB,
|
||||||
|
SPR_UFOA,
|
||||||
|
SPR_UFOS,
|
||||||
|
|
||||||
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
|
||||||
SPR_VIEW,
|
SPR_VIEW,
|
||||||
|
|
||||||
|
|
@ -5569,6 +5573,11 @@ typedef enum state
|
||||||
S_BROLY1,
|
S_BROLY1,
|
||||||
S_BROLY2,
|
S_BROLY2,
|
||||||
|
|
||||||
|
S_SPECIAL_UFO_POD,
|
||||||
|
S_SPECIAL_UFO_OVERLAY,
|
||||||
|
S_SPECIAL_UFO_ARM,
|
||||||
|
S_SPECIAL_UFO_STEM,
|
||||||
|
|
||||||
S_FIRSTFREESLOT,
|
S_FIRSTFREESLOT,
|
||||||
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
S_LASTFREESLOT = S_FIRSTFREESLOT + NUMSTATEFREESLOTS - 1,
|
||||||
NUMSTATES
|
NUMSTATES
|
||||||
|
|
@ -6685,6 +6694,7 @@ typedef enum mobj_type
|
||||||
MT_BROLY,
|
MT_BROLY,
|
||||||
|
|
||||||
MT_SPECIAL_UFO,
|
MT_SPECIAL_UFO,
|
||||||
|
MT_SPECIAL_UFO_PIECE,
|
||||||
|
|
||||||
MT_FIRSTFREESLOT,
|
MT_FIRSTFREESLOT,
|
||||||
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
MT_LASTFREESLOT = MT_FIRSTFREESLOT + NUMMOBJFREESLOTS - 1,
|
||||||
|
|
|
||||||
|
|
@ -58,9 +58,12 @@ void Obj_DuelBombInit(mobj_t *bomb);
|
||||||
mobj_t *Obj_SpawnBrolyKi(mobj_t *source, tic_t duration);
|
mobj_t *Obj_SpawnBrolyKi(mobj_t *source, tic_t duration);
|
||||||
|
|
||||||
/* Special Stage UFO */
|
/* Special Stage UFO */
|
||||||
void Obj_SpecialUFOThinker(mobj_t *bomb);
|
void Obj_SpecialUFOThinker(mobj_t *ufo);
|
||||||
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType);
|
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType);
|
||||||
void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other);
|
void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other);
|
||||||
|
void Obj_UFOPieceThink(mobj_t *piece);
|
||||||
|
void Obj_UFOPieceDead(mobj_t *piece);
|
||||||
|
void Obj_UFOPieceRemoved(mobj_t *piece);
|
||||||
mobj_t *Obj_CreateSpecialUFO(void);
|
mobj_t *Obj_CreateSpecialUFO(void);
|
||||||
UINT32 K_GetSpecialUFODistance(void);
|
UINT32 K_GetSpecialUFODistance(void);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
// See the 'LICENSE' file for more details.
|
// See the 'LICENSE' file for more details.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// \file ufo.c
|
/// \file ufo.c
|
||||||
/// \brief Special Stage UFO
|
/// \brief Special Stage UFO + Emerald handler
|
||||||
|
|
||||||
#include "../doomdef.h"
|
#include "../doomdef.h"
|
||||||
#include "../doomstat.h"
|
#include "../doomstat.h"
|
||||||
|
|
@ -31,11 +31,29 @@
|
||||||
#define UFO_DEADZONE (2048 * FRACUNIT) // Deadzone where it won't update it's speed as much.
|
#define UFO_DEADZONE (2048 * FRACUNIT) // Deadzone where it won't update it's speed as much.
|
||||||
#define UFO_SPEEDFACTOR (FRACUNIT * 3 / 4) // Factor of player's best speed, to make it more fair.
|
#define UFO_SPEEDFACTOR (FRACUNIT * 3 / 4) // Factor of player's best speed, to make it more fair.
|
||||||
|
|
||||||
|
#define UFO_NUMARMS (3)
|
||||||
|
#define UFO_ARMDELTA (ANGLE_MAX / UFO_NUMARMS)
|
||||||
|
|
||||||
#define ufo_waypoint(o) ((o)->extravalue1)
|
#define ufo_waypoint(o) ((o)->extravalue1)
|
||||||
#define ufo_distancetofinish(o) ((o)->extravalue2)
|
#define ufo_distancetofinish(o) ((o)->extravalue2)
|
||||||
#define ufo_speed(o) ((o)->watertop)
|
#define ufo_speed(o) ((o)->watertop)
|
||||||
#define ufo_collectdelay(o) ((o)->threshold)
|
#define ufo_collectdelay(o) ((o)->threshold)
|
||||||
|
|
||||||
|
#define ufo_pieces(o) ((o)->hnext)
|
||||||
|
|
||||||
|
#define ufo_piece_type(o) ((o)->extravalue1)
|
||||||
|
|
||||||
|
#define ufo_piece_owner(o) ((o)->target)
|
||||||
|
#define ufo_piece_next(o) ((o)->hnext)
|
||||||
|
#define ufo_piece_prev(o) ((o)->hprev)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UFO_PIECE_TYPE_POD,
|
||||||
|
UFO_PIECE_TYPE_ARM,
|
||||||
|
UFO_PIECE_TYPE_STEM,
|
||||||
|
};
|
||||||
|
|
||||||
static void UFOMoveTo(mobj_t *ufo, fixed_t destx, fixed_t desty, fixed_t destz)
|
static void UFOMoveTo(mobj_t *ufo, fixed_t destx, fixed_t desty, fixed_t destz)
|
||||||
{
|
{
|
||||||
ufo->momx = destx - ufo->x;
|
ufo->momx = destx - ufo->x;
|
||||||
|
|
@ -55,6 +73,11 @@ static boolean UFOEmeraldChase(mobj_t *ufo)
|
||||||
return (ufo->health <= 1);
|
return (ufo->health <= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean UFOPieceValid(mobj_t *piece)
|
||||||
|
{
|
||||||
|
return (piece != NULL && P_MobjWasRemoved(piece) == false && piece->health > 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void UFOUpdateDistanceToFinish(mobj_t *ufo)
|
static void UFOUpdateDistanceToFinish(mobj_t *ufo)
|
||||||
{
|
{
|
||||||
waypoint_t *finishLine = K_GetFinishLineWaypoint();
|
waypoint_t *finishLine = K_GetFinishLineWaypoint();
|
||||||
|
|
@ -221,6 +244,7 @@ static void UFOMove(mobj_t *ufo)
|
||||||
fixed_t newX = ufo->x;
|
fixed_t newX = ufo->x;
|
||||||
fixed_t newY = ufo->y;
|
fixed_t newY = ufo->y;
|
||||||
fixed_t newZ = ufo->z;
|
fixed_t newZ = ufo->z;
|
||||||
|
const fixed_t floatHeight = 24 * ufo->scale;
|
||||||
|
|
||||||
const boolean useshortcuts = false;
|
const boolean useshortcuts = false;
|
||||||
const boolean huntbackwards = false;
|
const boolean huntbackwards = false;
|
||||||
|
|
@ -253,7 +277,7 @@ static void UFOMove(mobj_t *ufo)
|
||||||
{
|
{
|
||||||
fixed_t wpX = curWaypoint->mobj->x;
|
fixed_t wpX = curWaypoint->mobj->x;
|
||||||
fixed_t wpY = curWaypoint->mobj->y;
|
fixed_t wpY = curWaypoint->mobj->y;
|
||||||
fixed_t wpZ = curWaypoint->mobj->z;
|
fixed_t wpZ = curWaypoint->mobj->z + floatHeight;
|
||||||
|
|
||||||
fixed_t distToNext = GenericDistance(
|
fixed_t distToNext = GenericDistance(
|
||||||
newX, newY, newZ,
|
newX, newY, newZ,
|
||||||
|
|
@ -336,13 +360,19 @@ static void UFOMove(mobj_t *ufo)
|
||||||
|
|
||||||
static void UFOEmeraldVFX(mobj_t *ufo)
|
static void UFOEmeraldVFX(mobj_t *ufo)
|
||||||
{
|
{
|
||||||
|
const INT32 bobS = 32;
|
||||||
|
const angle_t bobA = (leveltime & (bobS - 1)) * (ANGLE_MAX / bobS);
|
||||||
|
const fixed_t bobH = 16 * ufo->scale;
|
||||||
|
|
||||||
|
ufo->sprzoff = FixedMul(bobH, FINESINE(bobA >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
if (leveltime % 3 == 0)
|
if (leveltime % 3 == 0)
|
||||||
{
|
{
|
||||||
mobj_t *sparkle = P_SpawnMobjFromMobj(
|
mobj_t *sparkle = P_SpawnMobjFromMobj(
|
||||||
ufo,
|
ufo,
|
||||||
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
|
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
|
||||||
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
|
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
|
||||||
P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT,
|
(P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT) + FixedDiv(ufo->sprzoff, ufo->scale),
|
||||||
MT_EMERALDSPARK
|
MT_EMERALDSPARK
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -370,6 +400,65 @@ void Obj_SpecialUFOThinker(mobj_t *ufo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UFOCopyHitlagToPieces(mobj_t *ufo)
|
||||||
|
{
|
||||||
|
mobj_t *piece = NULL;
|
||||||
|
|
||||||
|
piece = ufo_pieces(ufo);
|
||||||
|
while (UFOPieceValid(piece) == true)
|
||||||
|
{
|
||||||
|
piece->hitlag = ufo->hitlag;
|
||||||
|
piece->eflags = (piece->eflags & ~MFE_DAMAGEHITLAG) | (ufo->eflags & MFE_DAMAGEHITLAG);
|
||||||
|
piece = ufo_piece_next(piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UFOKillPiece(mobj_t *piece)
|
||||||
|
{
|
||||||
|
angle_t dir = ANGLE_MAX;
|
||||||
|
fixed_t thrust = 0;
|
||||||
|
|
||||||
|
if (UFOPieceValid(piece) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
piece->health = 0;
|
||||||
|
piece->tics = TICRATE;
|
||||||
|
piece->flags &= ~MF_NOGRAVITY;
|
||||||
|
|
||||||
|
switch (ufo_piece_type(piece))
|
||||||
|
{
|
||||||
|
case UFO_PIECE_TYPE_ARM:
|
||||||
|
{
|
||||||
|
dir = piece->angle;
|
||||||
|
thrust = 12 * piece->scale;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
dir = FixedAngle(P_RandomRange(PR_DECORATION, 0, 359) << FRACBITS);
|
||||||
|
thrust = 4 * piece->scale;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P_Thrust(piece, dir, -thrust);
|
||||||
|
P_SetObjectMomZ(piece, 12*FRACUNIT, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void UFOKillPieces(mobj_t *ufo)
|
||||||
|
{
|
||||||
|
mobj_t *piece = NULL;
|
||||||
|
|
||||||
|
piece = ufo_pieces(ufo);
|
||||||
|
while (UFOPieceValid(piece) == true)
|
||||||
|
{
|
||||||
|
UFOKillPiece(piece);
|
||||||
|
piece = ufo_piece_next(piece);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static UINT8 GetUFODamage(mobj_t *inflictor)
|
static UINT8 GetUFODamage(mobj_t *inflictor)
|
||||||
{
|
{
|
||||||
if (inflictor == NULL || P_MobjWasRemoved(inflictor) == true)
|
if (inflictor == NULL || P_MobjWasRemoved(inflictor) == true)
|
||||||
|
|
@ -408,18 +497,15 @@ static UINT8 GetUFODamage(mobj_t *inflictor)
|
||||||
|
|
||||||
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType)
|
boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType)
|
||||||
{
|
{
|
||||||
|
const fixed_t addSpeed = FixedMul(UFO_BASE_SPEED, K_GetKartGameSpeedScalar(gamespeed));
|
||||||
UINT8 damage = 1;
|
UINT8 damage = 1;
|
||||||
|
|
||||||
(void)source;
|
(void)source;
|
||||||
(void)damageType;
|
(void)damageType;
|
||||||
|
|
||||||
// Speed up on damage!
|
|
||||||
ufo_speed(ufo) += FixedMul(UFO_BASE_SPEED, K_GetKartGameSpeedScalar(gamespeed));
|
|
||||||
|
|
||||||
if (UFOEmeraldChase(ufo) == true)
|
if (UFOEmeraldChase(ufo) == true)
|
||||||
{
|
{
|
||||||
// Damaged fully already, no need for any more.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,13 +516,22 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Speed up on damage!
|
||||||
|
ufo_speed(ufo) += addSpeed;
|
||||||
|
|
||||||
K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true);
|
K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true);
|
||||||
|
UFOCopyHitlagToPieces(ufo);
|
||||||
|
|
||||||
if (damage >= ufo->health - 1)
|
if (damage >= ufo->health - 1)
|
||||||
{
|
{
|
||||||
// Destroy the UFO parts, and make the emerald collectible!
|
// Destroy the UFO parts, and make the emerald collectible!
|
||||||
|
UFOKillPieces(ufo);
|
||||||
|
|
||||||
ufo->health = 1;
|
ufo->health = 1;
|
||||||
ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW);
|
ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW);
|
||||||
|
ufo->shadowscale = FRACUNIT/3;
|
||||||
|
|
||||||
|
ufo_speed(ufo) += addSpeed; // Even more speed!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -462,10 +557,96 @@ void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Obj_UFOPieceThink(mobj_t *piece)
|
||||||
|
{
|
||||||
|
mobj_t *ufo = ufo_piece_owner(piece);
|
||||||
|
|
||||||
|
if (ufo == NULL || P_MobjWasRemoved(ufo) == true)
|
||||||
|
{
|
||||||
|
P_KillMobj(piece, NULL, NULL, DMG_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
piece->destscale = ufo->destscale;
|
||||||
|
piece->scalespeed = ufo->scalespeed;
|
||||||
|
|
||||||
|
switch (ufo_piece_type(piece))
|
||||||
|
{
|
||||||
|
case UFO_PIECE_TYPE_POD:
|
||||||
|
{
|
||||||
|
UFOMoveTo(piece, ufo->x, ufo->y, ufo->z + (120 * ufo->scale));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case UFO_PIECE_TYPE_ARM:
|
||||||
|
{
|
||||||
|
fixed_t dis = (104 * ufo->scale);
|
||||||
|
|
||||||
|
fixed_t x = ufo->x - FixedMul(dis, FINECOSINE(piece->angle >> ANGLETOFINESHIFT));
|
||||||
|
fixed_t y = ufo->y - FixedMul(dis, FINESINE(piece->angle >> ANGLETOFINESHIFT));
|
||||||
|
|
||||||
|
UFOMoveTo(piece, x, y, ufo->z + (24 * ufo->scale));
|
||||||
|
|
||||||
|
piece->angle -= FixedMul(ANG2, FixedDiv(ufo_speed(ufo), UFO_BASE_SPEED));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
P_KillMobj(piece, NULL, NULL, DMG_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_UFOPieceDead(mobj_t *piece)
|
||||||
|
{
|
||||||
|
piece->renderflags ^= RF_DONTDRAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_UFOPieceRemoved(mobj_t *piece)
|
||||||
|
{
|
||||||
|
// Repair piece list.
|
||||||
|
mobj_t *ufo = ufo_piece_owner(piece);
|
||||||
|
mobj_t *next = ufo_piece_next(piece);
|
||||||
|
mobj_t *prev = ufo_piece_prev(piece);
|
||||||
|
|
||||||
|
if (prev != NULL && P_MobjWasRemoved(prev) == false)
|
||||||
|
{
|
||||||
|
P_SetTarget(
|
||||||
|
&ufo_piece_next(prev),
|
||||||
|
(next != NULL && P_MobjWasRemoved(next) == false) ? next : NULL
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next != NULL && P_MobjWasRemoved(next) == false)
|
||||||
|
{
|
||||||
|
P_SetTarget(
|
||||||
|
&ufo_piece_prev(next),
|
||||||
|
(prev != NULL && P_MobjWasRemoved(prev) == false) ? prev : NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ufo != NULL && P_MobjWasRemoved(ufo) == false)
|
||||||
|
{
|
||||||
|
if (piece == ufo_pieces(ufo))
|
||||||
|
{
|
||||||
|
P_SetTarget(
|
||||||
|
&ufo_pieces(ufo),
|
||||||
|
next
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
P_SetTarget(&ufo_piece_next(piece), NULL);
|
||||||
|
P_SetTarget(&ufo_piece_prev(piece), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static mobj_t *InitSpecialUFO(waypoint_t *start)
|
static mobj_t *InitSpecialUFO(waypoint_t *start)
|
||||||
{
|
{
|
||||||
mobj_t *ufo = NULL;
|
mobj_t *ufo = NULL;
|
||||||
mobj_t *underlay = NULL;
|
mobj_t *overlay = NULL;
|
||||||
|
mobj_t *piece = NULL;
|
||||||
|
mobj_t *prevPiece = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
if (start == NULL)
|
if (start == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -487,12 +668,43 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
|
||||||
// TODO: Adjustable Special Stage emerald color
|
// TODO: Adjustable Special Stage emerald color
|
||||||
ufo->color = SKINCOLOR_CHAOSEMERALD1;
|
ufo->color = SKINCOLOR_CHAOSEMERALD1;
|
||||||
|
|
||||||
underlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY);
|
overlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY);
|
||||||
P_SetTarget(&underlay->target, ufo);
|
P_SetTarget(&overlay->target, ufo);
|
||||||
underlay->color = ufo->color;
|
overlay->color = ufo->color;
|
||||||
|
|
||||||
// TODO: Super Emeralds / Chaos Rings
|
// TODO: Super Emeralds / Chaos Rings
|
||||||
P_SetMobjState(underlay, S_CHAOSEMERALD_UNDER);
|
P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER);
|
||||||
|
|
||||||
|
// Create UFO pieces.
|
||||||
|
// First: UFO center.
|
||||||
|
piece = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_SPECIAL_UFO_PIECE);
|
||||||
|
P_SetTarget(&ufo_piece_owner(piece), ufo);
|
||||||
|
|
||||||
|
P_SetMobjState(piece, S_SPECIAL_UFO_POD);
|
||||||
|
ufo_piece_type(piece) = UFO_PIECE_TYPE_POD;
|
||||||
|
|
||||||
|
overlay = P_SpawnMobjFromMobj(piece, 0, 0, 0, MT_OVERLAY);
|
||||||
|
P_SetTarget(&overlay->target, piece);
|
||||||
|
P_SetMobjState(overlay, S_SPECIAL_UFO_OVERLAY);
|
||||||
|
|
||||||
|
P_SetTarget(&ufo_pieces(ufo), piece);
|
||||||
|
prevPiece = piece;
|
||||||
|
|
||||||
|
for (i = 0; i < UFO_NUMARMS; i++)
|
||||||
|
{
|
||||||
|
piece = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_SPECIAL_UFO_PIECE);
|
||||||
|
P_SetTarget(&ufo_piece_owner(piece), ufo);
|
||||||
|
|
||||||
|
P_SetMobjState(piece, S_SPECIAL_UFO_ARM);
|
||||||
|
ufo_piece_type(piece) = UFO_PIECE_TYPE_ARM;
|
||||||
|
|
||||||
|
piece->angle = UFO_ARMDELTA * i;
|
||||||
|
|
||||||
|
P_SetTarget(&ufo_piece_next(prevPiece), piece);
|
||||||
|
P_SetTarget(&ufo_piece_prev(piece), prevPiece);
|
||||||
|
|
||||||
|
prevPiece = piece;
|
||||||
|
}
|
||||||
|
|
||||||
return ufo;
|
return ufo;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1352,7 +1352,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
|
||||||
{
|
{
|
||||||
if (!(thing->flags & MF_SPECIAL))
|
if (!(thing->flags & MF_SPECIAL))
|
||||||
{
|
{
|
||||||
Obj_PlayerUFOCollide(thing, tmthing);
|
Obj_PlayerUFOCollide(thing, tm.thing);
|
||||||
return BMIT_CONTINUE;
|
return BMIT_CONTINUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/p_mobj.c
31
src/p_mobj.c
|
|
@ -5298,10 +5298,22 @@ void P_RunOverlays(void)
|
||||||
mo->pitch = mo->target->pitch;
|
mo->pitch = mo->target->pitch;
|
||||||
mo->roll = mo->target->roll;
|
mo->roll = mo->target->roll;
|
||||||
|
|
||||||
|
mo->spritexoffset = mo->target->spritexoffset;
|
||||||
|
mo->spriteyoffset = mo->target->spriteyoffset;
|
||||||
|
mo->spritexscale = mo->target->spritexscale;
|
||||||
|
mo->spriteyscale = mo->target->spriteyscale;
|
||||||
|
|
||||||
|
mo->sprxoff = mo->target->sprxoff;
|
||||||
|
mo->spryoff = mo->target->spryoff;
|
||||||
|
mo->sprzoff = mo->target->sprzoff;
|
||||||
|
|
||||||
|
mo->hitlag = mo->target->hitlag;
|
||||||
|
mo->eflags = (mo->eflags & ~MFE_DAMAGEHITLAG) | (mo->target->eflags & MFE_DAMAGEHITLAG);
|
||||||
|
|
||||||
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
|
if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP))
|
||||||
mo->flags ^= MF_DONTENCOREMAP;
|
mo->flags ^= MF_DONTENCOREMAP;
|
||||||
|
|
||||||
mo->dispoffset = mo->target->dispoffset + mo->info->dispoffset;
|
mo->dispoffset = mo->target->dispoffset;
|
||||||
|
|
||||||
if (!(mo->state->frame & FF_ANIMATE))
|
if (!(mo->state->frame & FF_ANIMATE))
|
||||||
{
|
{
|
||||||
|
|
@ -5321,6 +5333,7 @@ void P_RunOverlays(void)
|
||||||
// if you're using FF_ANIMATE on an overlay,
|
// if you're using FF_ANIMATE on an overlay,
|
||||||
// then you're on your own.
|
// then you're on your own.
|
||||||
zoffs = 0;
|
zoffs = 0;
|
||||||
|
mo->dispoffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
P_UnsetThingPosition(mo);
|
P_UnsetThingPosition(mo);
|
||||||
|
|
@ -6743,6 +6756,11 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
|
||||||
S_StartSound(dust, sfx_s3k3d);
|
S_StartSound(dust, sfx_s3k3d);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MT_SPECIAL_UFO_PIECE:
|
||||||
|
{
|
||||||
|
Obj_UFOPieceDead(mobj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -7297,6 +7315,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
||||||
Obj_SpecialUFOThinker(mobj);
|
Obj_SpecialUFOThinker(mobj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_SPECIAL_UFO_PIECE:
|
||||||
|
{
|
||||||
|
Obj_UFOPieceThink(mobj);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MT_EMERALD:
|
case MT_EMERALD:
|
||||||
{
|
{
|
||||||
if (battleovertime.enabled >= 10*TICRATE)
|
if (battleovertime.enabled >= 10*TICRATE)
|
||||||
|
|
@ -10050,6 +10073,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
||||||
case MT_PLAYER:
|
case MT_PLAYER:
|
||||||
case MT_KART_LEFTOVER:
|
case MT_KART_LEFTOVER:
|
||||||
case MT_BATTLECAPSULE:
|
case MT_BATTLECAPSULE:
|
||||||
|
case MT_SPECIAL_UFO:
|
||||||
thing->shadowscale = FRACUNIT;
|
thing->shadowscale = FRACUNIT;
|
||||||
break;
|
break;
|
||||||
case MT_SMALLMACE:
|
case MT_SMALLMACE:
|
||||||
|
|
@ -10906,6 +10930,11 @@ void P_RemoveMobj(mobj_t *mobj)
|
||||||
Obj_ShrinkGunRemoved(mobj);
|
Obj_ShrinkGunRemoved(mobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mobj->type == MT_SPECIAL_UFO_PIECE)
|
||||||
|
{
|
||||||
|
Obj_UFOPieceRemoved(mobj);
|
||||||
|
}
|
||||||
|
|
||||||
mobj->health = 0; // Just because
|
mobj->health = 0; // Just because
|
||||||
|
|
||||||
// unlink from sector and block lists
|
// unlink from sector and block lists
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue