Merge remote-tracking branch 'origin/subtitlesubterfuge' into remove-unused-levelwipes
This commit is contained in:
commit
e0a9b3d695
334
src/b_bot.c
334
src/b_bot.c
|
@ -24,12 +24,48 @@ static boolean lastForward = false;
|
||||||
static boolean lastBlocked = false;
|
static boolean lastBlocked = false;
|
||||||
static boolean blocked = false;
|
static boolean blocked = false;
|
||||||
|
|
||||||
|
static boolean jump_last = false;
|
||||||
|
static boolean spin_last = false;
|
||||||
|
static UINT8 anxiety = 0;
|
||||||
|
static boolean panic = false;
|
||||||
|
static UINT8 flymode = 0;
|
||||||
|
static boolean spinmode = false;
|
||||||
|
static boolean thinkfly = false;
|
||||||
|
static mobj_t *overlay;
|
||||||
|
|
||||||
|
static inline void B_ResetAI(void)
|
||||||
|
{
|
||||||
|
jump_last = false;
|
||||||
|
spin_last = false;
|
||||||
|
anxiety = 0;
|
||||||
|
panic = false;
|
||||||
|
flymode = 0;
|
||||||
|
spinmode = false;
|
||||||
|
thinkfly = false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
||||||
{
|
{
|
||||||
boolean forward=false, backward=false, left=false, right=false, jump=false, spin=false;
|
boolean forward=false, backward=false, left=false, right=false, jump=false, spin=false;
|
||||||
angle_t angle;
|
|
||||||
INT16 rangle;
|
player_t *player = sonic->player, *bot = tails->player;
|
||||||
fixed_t dist;
|
ticcmd_t *pcmd = &player->cmd;
|
||||||
|
boolean water = tails->eflags & MFE_UNDERWATER;
|
||||||
|
SINT8 flip = P_MobjFlip(tails);
|
||||||
|
boolean _2d = (tails->flags2 & MF2_TWOD) || twodlevel;
|
||||||
|
fixed_t scale = tails->scale;
|
||||||
|
|
||||||
|
fixed_t dist = P_AproxDistance(sonic->x - tails->x, sonic->y - tails->y);
|
||||||
|
fixed_t zdist = flip * (sonic->z - tails->z);
|
||||||
|
angle_t ang = R_PointToAngle2(tails->x, tails->y, sonic->x, sonic->y);
|
||||||
|
fixed_t pmom = P_AproxDistance(sonic->momx, sonic->momy);
|
||||||
|
fixed_t bmom = P_AproxDistance(tails->momx, tails->momy);
|
||||||
|
fixed_t followmax = 128 * 8 * scale; // Max follow distance before AI begins to enter "panic" state
|
||||||
|
fixed_t followthres = 92 * scale; // Distance that AI will try to reach
|
||||||
|
fixed_t followmin = 32 * scale;
|
||||||
|
fixed_t comfortheight = 96 * scale;
|
||||||
|
fixed_t touchdist = 24 * scale;
|
||||||
|
boolean stalled = (bmom < scale >> 1) && dist > followthres; // Helps to see if the AI is having trouble catching up
|
||||||
|
|
||||||
// We can't follow Sonic if he's not around!
|
// We can't follow Sonic if he's not around!
|
||||||
if (!sonic || sonic->health <= 0)
|
if (!sonic || sonic->health <= 0)
|
||||||
|
@ -58,46 +94,260 @@ static inline void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cm
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather data about the environment
|
// Adapted from CobaltBW's tails_AI.wad
|
||||||
dist = P_AproxDistance(tails->x-sonic->x, tails->y-sonic->y);
|
|
||||||
if (tails->player->pflags & PF_STARTDASH)
|
// Check water
|
||||||
angle = sonic->angle;
|
if (water)
|
||||||
|
{
|
||||||
|
followmin = 0;
|
||||||
|
followthres = 16*scale;
|
||||||
|
followmax >>= 1;
|
||||||
|
thinkfly = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check anxiety
|
||||||
|
if (spinmode)
|
||||||
|
{
|
||||||
|
anxiety = 0;
|
||||||
|
panic = false;
|
||||||
|
}
|
||||||
|
else if (dist > followmax || zdist > comfortheight || stalled)
|
||||||
|
{
|
||||||
|
anxiety = min(anxiety + 2, 70);
|
||||||
|
if (anxiety >= 70)
|
||||||
|
panic = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
angle = R_PointToAngle2(tails->x, tails->y, sonic->x, sonic->y);
|
{
|
||||||
|
anxiety = max(anxiety - 1, 0);
|
||||||
// Decide which direction to turn
|
panic = false;
|
||||||
angle = (tails->angle - angle);
|
|
||||||
if (angle < ANGLE_180) {
|
|
||||||
right = true; // We need to turn right
|
|
||||||
rangle = AngleFixed(angle)>>FRACBITS;
|
|
||||||
} else {
|
|
||||||
left = true; // We need to turn left
|
|
||||||
rangle = 360-(AngleFixed(angle)>>FRACBITS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide to move forward if you're finished turning
|
// Orientation
|
||||||
if (abs(rangle) < 10) { // We're facing the right way?
|
if ((bot->pflags & (PF_SPINNING|PF_STARTDASH)) || flymode == 2)
|
||||||
left = right = false; // Stop turning
|
{
|
||||||
forward = true; // and walk forward instead.
|
cmd->angleturn = (sonic->angle - tails->angle) >> FRACBITS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd->angleturn = (ang - tails->angle) >> FRACBITS;
|
||||||
}
|
}
|
||||||
if (dist < (sonic->radius+tails->radius)*3) // We're close enough?
|
|
||||||
forward = false; // Stop walking.
|
|
||||||
|
|
||||||
// Decide when to jump
|
// ********
|
||||||
if (!(tails->player->pflags & (PF_JUMPED|PF_JUMPDOWN))) { // We're not jumping yet...
|
// FLY MODE
|
||||||
if (forward && lastForward && blocked && lastBlocked) // We've been stopped by a wall or something
|
// spinmode check
|
||||||
jump = true; // Try to jump up
|
if (spinmode)
|
||||||
} else if ((tails->player->pflags & (PF_JUMPDOWN|PF_JUMPED)) == (PF_JUMPDOWN|PF_JUMPED)) { // When we're already jumping...
|
thinkfly = false;
|
||||||
if (lastForward && blocked) // We're still stuck on something?
|
else
|
||||||
jump = true;
|
{
|
||||||
if (sonic->floorz > tails->floorz) // He's still above us? Jump HIGHER, then!
|
// Activate co-op flight
|
||||||
|
if (thinkfly && player->pflags & PF_JUMPED)
|
||||||
|
{
|
||||||
|
if (!jump_last)
|
||||||
|
{
|
||||||
jump = true;
|
jump = true;
|
||||||
|
flymode = 1;
|
||||||
|
thinkfly = false;
|
||||||
|
bot->pflags |= PF_CANCARRY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decide when to spin
|
// Check positioning
|
||||||
if (sonic->player->pflags & PF_STARTDASH
|
// Thinker for co-op flight
|
||||||
&& (tails->player->pflags & PF_STARTDASH || (P_AproxDistance(tails->momx, tails->momy) < 2*FRACUNIT && !forward)))
|
if (!(water || pmom || bmom)
|
||||||
|
&& (dist < touchdist)
|
||||||
|
&& !(pcmd->forwardmove || pcmd->sidemove || player->dashspeed)
|
||||||
|
&& P_IsObjectOnGround(sonic) && P_IsObjectOnGround(tails)
|
||||||
|
&& !(player->pflags & PF_STASIS)
|
||||||
|
&& bot->charability == CA_FLY)
|
||||||
|
thinkfly = true;
|
||||||
|
else
|
||||||
|
thinkfly = false;
|
||||||
|
|
||||||
|
// Ready for takeoff
|
||||||
|
if (flymode == 1)
|
||||||
|
{
|
||||||
|
thinkfly = false;
|
||||||
|
if (zdist < -64*scale || (flip * tails->momz) > scale) // Make sure we're not too high up
|
||||||
spin = true;
|
spin = true;
|
||||||
|
else if (!jump_last)
|
||||||
|
jump = true;
|
||||||
|
|
||||||
|
// Abort if the player moves away or spins
|
||||||
|
if (dist > followthres || player->dashspeed)
|
||||||
|
flymode = 0;
|
||||||
|
|
||||||
|
// Set carried state
|
||||||
|
if (player->powers[pw_carry] == CR_PLAYER && sonic->tracer == tails)
|
||||||
|
{
|
||||||
|
flymode = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Read player inputs while carrying
|
||||||
|
else if (flymode == 2)
|
||||||
|
{
|
||||||
|
cmd->forwardmove = pcmd->forwardmove;
|
||||||
|
cmd->sidemove = pcmd->sidemove;
|
||||||
|
if (pcmd->buttons & BT_USE)
|
||||||
|
{
|
||||||
|
spin = true;
|
||||||
|
jump = false;
|
||||||
|
}
|
||||||
|
else if (!jump_last)
|
||||||
|
jump = true;
|
||||||
|
// End flymode
|
||||||
|
if (player->powers[pw_carry] != CR_PLAYER)
|
||||||
|
{
|
||||||
|
flymode = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flymode && P_IsObjectOnGround(tails) && !(pcmd->buttons & BT_JUMP))
|
||||||
|
flymode = 0;
|
||||||
|
|
||||||
|
// ********
|
||||||
|
// SPINNING
|
||||||
|
if (panic || flymode || !(player->pflags & PF_SPINNING) || (player->pflags & PF_JUMPED))
|
||||||
|
spinmode = false;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!_2d)
|
||||||
|
{
|
||||||
|
// Spindash
|
||||||
|
if (player->dashspeed)
|
||||||
|
{
|
||||||
|
if (dist < followthres && dist > touchdist) // Do positioning
|
||||||
|
{
|
||||||
|
cmd->angleturn = (ang - tails->angle) >> FRACBITS;
|
||||||
|
cmd->forwardmove = 50;
|
||||||
|
spinmode = true;
|
||||||
|
}
|
||||||
|
else if (dist < touchdist)
|
||||||
|
{
|
||||||
|
if (!bmom && (!(bot->pflags & PF_SPINNING) || (bot->dashspeed && bot->pflags & PF_SPINNING)))
|
||||||
|
{
|
||||||
|
cmd->angleturn = (sonic->angle - tails->angle) >> FRACBITS;
|
||||||
|
spin = true;
|
||||||
|
}
|
||||||
|
spinmode = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
spinmode = false;
|
||||||
|
}
|
||||||
|
// Spin
|
||||||
|
else if (player->dashspeed == bot->dashspeed && player->pflags & PF_SPINNING)
|
||||||
|
{
|
||||||
|
if (bot->pflags & PF_SPINNING || !spin_last)
|
||||||
|
{
|
||||||
|
spin = true;
|
||||||
|
cmd->angleturn = (sonic->angle - tails->angle) >> FRACBITS;
|
||||||
|
cmd->forwardmove = MAXPLMOVE;
|
||||||
|
spinmode = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
spinmode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2D mode
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (((player->dashspeed && !bmom) || (player->dashspeed == bot->dashspeed && (player->pflags & PF_SPINNING)))
|
||||||
|
&& ((bot->pflags & PF_SPINNING) || !spin_last))
|
||||||
|
{
|
||||||
|
spin = true;
|
||||||
|
spinmode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ********
|
||||||
|
// FOLLOW
|
||||||
|
if (!(flymode || spinmode))
|
||||||
|
{
|
||||||
|
// Too far
|
||||||
|
if (panic || dist > followthres)
|
||||||
|
{
|
||||||
|
if (!_2d)
|
||||||
|
cmd->forwardmove = MAXPLMOVE;
|
||||||
|
else if (sonic->x > tails->x)
|
||||||
|
cmd->sidemove = MAXPLMOVE;
|
||||||
|
else
|
||||||
|
cmd->sidemove = -MAXPLMOVE;
|
||||||
|
}
|
||||||
|
// Within threshold
|
||||||
|
else if (!panic && dist > followmin && abs(zdist) < 192*scale)
|
||||||
|
{
|
||||||
|
if (!_2d)
|
||||||
|
cmd->forwardmove = FixedHypot(pcmd->forwardmove, pcmd->sidemove);
|
||||||
|
else
|
||||||
|
cmd->sidemove = pcmd->sidemove;
|
||||||
|
}
|
||||||
|
// Below min
|
||||||
|
else if (dist < followmin)
|
||||||
|
{
|
||||||
|
// Copy inputs
|
||||||
|
cmd->angleturn = (sonic->angle - tails->angle) >> FRACBITS;
|
||||||
|
bot->drawangle = ang;
|
||||||
|
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
||||||
|
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ********
|
||||||
|
// JUMP
|
||||||
|
if (!(flymode || spinmode))
|
||||||
|
{
|
||||||
|
// Flying catch-up
|
||||||
|
if (bot->pflags & PF_THOKKED)
|
||||||
|
{
|
||||||
|
cmd->forwardmove = min(MAXPLMOVE, (dist/scale)>>3);
|
||||||
|
if (zdist < -64*scale)
|
||||||
|
spin = true;
|
||||||
|
else if (zdist > 0 && !jump_last)
|
||||||
|
jump = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just landed
|
||||||
|
if (tails->eflags & MFE_JUSTHITFLOOR)
|
||||||
|
jump = false;
|
||||||
|
// Start jump
|
||||||
|
else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING)
|
||||||
|
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
||||||
|
|| (zdist > 64*scale && panic) // Vertical catch-up
|
||||||
|
|| (stalled && anxiety > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||||
|
//|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state
|
||||||
|
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
||||||
|
jump = true;
|
||||||
|
// Hold jump
|
||||||
|
else if (bot->pflags & PF_JUMPED && jump_last && tails->momz*flip > 0 && (zdist > 0 || panic))
|
||||||
|
jump = true;
|
||||||
|
// Start flying
|
||||||
|
else if (bot->pflags & PF_JUMPED && panic && !jump_last && bot->charability == CA_FLY)
|
||||||
|
jump = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ********
|
||||||
|
// HISTORY
|
||||||
|
jump_last = jump;
|
||||||
|
spin_last = spin;
|
||||||
|
|
||||||
|
// ********
|
||||||
|
// Thinkfly overlay
|
||||||
|
if (thinkfly)
|
||||||
|
{
|
||||||
|
if (overlay == NULL)
|
||||||
|
{
|
||||||
|
overlay = P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY);
|
||||||
|
P_SetTarget(&overlay->target, tails);
|
||||||
|
P_SetMobjState(overlay, S_FLIGHTINDICATOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (overlay != NULL)
|
||||||
|
{
|
||||||
|
P_RemoveMobj(overlay);
|
||||||
|
overlay = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Turn the virtual keypresses into ticcmd_t.
|
// Turn the virtual keypresses into ticcmd_t.
|
||||||
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
|
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, false, false, jump, spin);
|
||||||
|
@ -141,7 +391,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
||||||
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin)
|
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin)
|
||||||
{
|
{
|
||||||
// don't try to do stuff if your sonic is in a minecart or something
|
// don't try to do stuff if your sonic is in a minecart or something
|
||||||
if (players[consoleplayer].powers[pw_carry])
|
if (players[consoleplayer].powers[pw_carry] && players[consoleplayer].powers[pw_carry] != CR_PLAYER)
|
||||||
return;
|
return;
|
||||||
// Turn the virtual keypresses into ticcmd_t.
|
// Turn the virtual keypresses into ticcmd_t.
|
||||||
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
||||||
|
@ -179,6 +429,7 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
||||||
cmd->sidemove += MAXPLMOVE<<FRACBITS>>16;
|
cmd->sidemove += MAXPLMOVE<<FRACBITS>>16;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
angle_t angle;
|
||||||
if (forward)
|
if (forward)
|
||||||
cmd->forwardmove += MAXPLMOVE<<FRACBITS>>16;
|
cmd->forwardmove += MAXPLMOVE<<FRACBITS>>16;
|
||||||
if (backward)
|
if (backward)
|
||||||
|
@ -191,6 +442,15 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
||||||
cmd->sidemove -= MAXPLMOVE<<FRACBITS>>16;
|
cmd->sidemove -= MAXPLMOVE<<FRACBITS>>16;
|
||||||
if (straferight)
|
if (straferight)
|
||||||
cmd->sidemove += MAXPLMOVE<<FRACBITS>>16;
|
cmd->sidemove += MAXPLMOVE<<FRACBITS>>16;
|
||||||
|
|
||||||
|
// cap inputs so the bot can't accelerate faster diagonally
|
||||||
|
angle = R_PointToAngle2(0, 0, cmd->sidemove << FRACBITS, cmd->forwardmove << FRACBITS);
|
||||||
|
{
|
||||||
|
INT32 maxforward = abs(P_ReturnThrustY(NULL, angle, MAXPLMOVE));
|
||||||
|
INT32 maxside = abs(P_ReturnThrustX(NULL, angle, MAXPLMOVE));
|
||||||
|
cmd->forwardmove = max(min(cmd->forwardmove, maxforward), -maxforward);
|
||||||
|
cmd->sidemove = max(min(cmd->sidemove, maxside), -maxside);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (jump)
|
if (jump)
|
||||||
cmd->buttons |= BT_JUMP;
|
cmd->buttons |= BT_JUMP;
|
||||||
|
@ -217,7 +477,7 @@ boolean B_CheckRespawn(player_t *player)
|
||||||
// If he's doing any of these things, he probably doesn't want to see us.
|
// If he's doing any of these things, he probably doesn't want to see us.
|
||||||
if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_BOUNCING)
|
if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_BOUNCING)
|
||||||
|| (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK)
|
|| (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK)
|
||||||
|| (sonic->player->powers[pw_carry]))
|
|| (sonic->player->powers[pw_carry] && sonic->player->powers[pw_carry] != CR_PLAYER))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Low ceiling, do not want!
|
// Low ceiling, do not want!
|
||||||
|
@ -252,6 +512,8 @@ void B_RespawnBot(INT32 playernum)
|
||||||
if (!sonic || sonic->health <= 0)
|
if (!sonic || sonic->health <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
B_ResetAI();
|
||||||
|
|
||||||
player->bot = 1;
|
player->bot = 1;
|
||||||
P_SpawnPlayer(playernum);
|
P_SpawnPlayer(playernum);
|
||||||
tails = player->mo;
|
tails = player->mo;
|
||||||
|
|
|
@ -2797,6 +2797,9 @@ static actionpointer_t actionpointers[] =
|
||||||
{{A_PterabyteHover}, "A_PTERABYTEHOVER"},
|
{{A_PterabyteHover}, "A_PTERABYTEHOVER"},
|
||||||
{{A_RolloutSpawn}, "A_ROLLOUTSPAWN"},
|
{{A_RolloutSpawn}, "A_ROLLOUTSPAWN"},
|
||||||
{{A_RolloutRock}, "A_ROLLOUTROCK"},
|
{{A_RolloutRock}, "A_ROLLOUTROCK"},
|
||||||
|
{{A_DragonbomberSpawn}, "A_DRAGONBOMERSPAWN"},
|
||||||
|
{{A_DragonWing}, "A_DRAGONWING"},
|
||||||
|
{{A_DragonSegment}, "A_DRAGONSEGMENT"},
|
||||||
{{NULL}, "NONE"},
|
{{NULL}, "NONE"},
|
||||||
|
|
||||||
// This NULL entry must be the last in the list
|
// This NULL entry must be the last in the list
|
||||||
|
@ -5057,6 +5060,26 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_PTERABYTE_SWOOPDOWN",
|
"S_PTERABYTE_SWOOPDOWN",
|
||||||
"S_PTERABYTE_SWOOPUP",
|
"S_PTERABYTE_SWOOPUP",
|
||||||
|
|
||||||
|
// Dragonbomber
|
||||||
|
"S_DRAGONBOMBER",
|
||||||
|
"S_DRAGONWING1",
|
||||||
|
"S_DRAGONWING2",
|
||||||
|
"S_DRAGONWING3",
|
||||||
|
"S_DRAGONWING4",
|
||||||
|
"S_DRAGONTAIL_LOADED",
|
||||||
|
"S_DRAGONTAIL_EMPTY",
|
||||||
|
"S_DRAGONTAIL_EMPTYLOOP",
|
||||||
|
"S_DRAGONTAIL_RELOAD",
|
||||||
|
"S_DRAGONMINE",
|
||||||
|
"S_DRAGONMINE_LAND1",
|
||||||
|
"S_DRAGONMINE_LAND2",
|
||||||
|
"S_DRAGONMINE_SLOWFLASH1",
|
||||||
|
"S_DRAGONMINE_SLOWFLASH2",
|
||||||
|
"S_DRAGONMINE_SLOWLOOP",
|
||||||
|
"S_DRAGONMINE_FASTFLASH1",
|
||||||
|
"S_DRAGONMINE_FASTFLASH2",
|
||||||
|
"S_DRAGONMINE_FASTLOOP",
|
||||||
|
|
||||||
// Boss Explosion
|
// Boss Explosion
|
||||||
"S_BOSSEXPLODE",
|
"S_BOSSEXPLODE",
|
||||||
|
|
||||||
|
@ -7156,6 +7179,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
||||||
"S_FOUR2",
|
"S_FOUR2",
|
||||||
"S_FIVE2",
|
"S_FIVE2",
|
||||||
|
|
||||||
|
"S_FLIGHTINDICATOR",
|
||||||
|
|
||||||
"S_LOCKON1",
|
"S_LOCKON1",
|
||||||
"S_LOCKON2",
|
"S_LOCKON2",
|
||||||
"S_LOCKON3",
|
"S_LOCKON3",
|
||||||
|
@ -7728,6 +7753,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
||||||
"MT_PTERABYTESPAWNER", // Pterabyte spawner
|
"MT_PTERABYTESPAWNER", // Pterabyte spawner
|
||||||
"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
|
"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
|
||||||
"MT_PTERABYTE", // Pterabyte
|
"MT_PTERABYTE", // Pterabyte
|
||||||
|
"MT_DRAGONBOMBER", // Dragonbomber
|
||||||
|
"MT_DRAGONWING", // Dragonbomber wing
|
||||||
|
"MT_DRAGONTAIL", // Dragonbomber tail segment
|
||||||
|
"MT_DRAGONMINE", // Dragonbomber mine
|
||||||
|
|
||||||
// Generic Boss Items
|
// Generic Boss Items
|
||||||
"MT_BOSSEXPLODE",
|
"MT_BOSSEXPLODE",
|
||||||
|
|
|
@ -184,6 +184,7 @@ light_t *t_lspr[NUMSPRITES] =
|
||||||
&lspr[NOLIGHT], // SPR_CANG
|
&lspr[NOLIGHT], // SPR_CANG
|
||||||
&lspr[NOLIGHT], // SPR_PYRE
|
&lspr[NOLIGHT], // SPR_PYRE
|
||||||
&lspr[NOLIGHT], // SPR_PTER
|
&lspr[NOLIGHT], // SPR_PTER
|
||||||
|
&lspr[NOLIGHT], // SPR_DRAB
|
||||||
|
|
||||||
// Generic Boos Items
|
// Generic Boos Items
|
||||||
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
|
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
|
||||||
|
@ -505,6 +506,7 @@ light_t *t_lspr[NUMSPRITES] =
|
||||||
// Game Indicators
|
// Game Indicators
|
||||||
&lspr[NOLIGHT], // SPR_SCOR
|
&lspr[NOLIGHT], // SPR_SCOR
|
||||||
&lspr[NOLIGHT], // SPR_DRWN
|
&lspr[NOLIGHT], // SPR_DRWN
|
||||||
|
&lspr[NOLIGHT], // SPR_FLII
|
||||||
&lspr[NOLIGHT], // SPR_LCKN
|
&lspr[NOLIGHT], // SPR_LCKN
|
||||||
&lspr[NOLIGHT], // SPR_TTAG
|
&lspr[NOLIGHT], // SPR_TTAG
|
||||||
&lspr[NOLIGHT], // SPR_GFLG
|
&lspr[NOLIGHT], // SPR_GFLG
|
||||||
|
|
133
src/info.c
133
src/info.c
|
@ -72,6 +72,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
"CANG", // Canarivore gas
|
"CANG", // Canarivore gas
|
||||||
"PYRE", // Pyre Fly
|
"PYRE", // Pyre Fly
|
||||||
"PTER", // Pterabyte
|
"PTER", // Pterabyte
|
||||||
|
"DRAB", // Dragonbomber
|
||||||
|
|
||||||
// Generic Boss Items
|
// Generic Boss Items
|
||||||
"JETF", // Boss jet fumes
|
"JETF", // Boss jet fumes
|
||||||
|
@ -402,6 +403,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
||||||
// Game Indicators
|
// Game Indicators
|
||||||
"SCOR", // Score logo
|
"SCOR", // Score logo
|
||||||
"DRWN", // Drowning Timer
|
"DRWN", // Drowning Timer
|
||||||
|
"FLII", // Flight indicator
|
||||||
"LCKN", // Target
|
"LCKN", // Target
|
||||||
"TTAG", // Tag Sign
|
"TTAG", // Tag Sign
|
||||||
"GFLG", // Got Flag sign
|
"GFLG", // Got Flag sign
|
||||||
|
@ -1163,6 +1165,26 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN
|
{SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN
|
||||||
{SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP
|
{SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP
|
||||||
|
|
||||||
|
// Dragonbomber
|
||||||
|
{SPR_DRAB, 0, -1, {A_DragonbomberSpawn}, 6, 0, S_NULL}, // S_DRAGONBOMBER
|
||||||
|
{SPR_DRAB, FF_PAPERSPRITE|7, 1, {A_DragonWing}, 0, 0, S_DRAGONWING2}, // S_DRAGONWING1
|
||||||
|
{SPR_DRAB, FF_PAPERSPRITE|8, 1, {A_DragonWing}, 0, 0, S_DRAGONWING3}, // S_DRAGONWING2
|
||||||
|
{SPR_DRAB, FF_PAPERSPRITE|9, 1, {A_DragonWing}, 0, 0, S_DRAGONWING4}, // S_DRAGONWING3
|
||||||
|
{SPR_DRAB, FF_PAPERSPRITE|10, 1, {A_DragonWing}, 0, 0, S_DRAGONWING1}, // S_DRAGONWING4
|
||||||
|
{SPR_DRAB, 1, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_LOADED}, // S_DRAGONTAIL_LOADED
|
||||||
|
{SPR_DRAB, 2, 1, {A_DragonSegment}, 0, 0, S_DRAGONTAIL_EMPTYLOOP}, // S_DRAGONTAIL_EMPTY
|
||||||
|
{SPR_DRAB, 2, 0, {A_Repeat}, 3*TICRATE, S_DRAGONTAIL_EMPTY, S_DRAGONTAIL_RELOAD}, // S_DRAGONTAIL_EMPTYLOOP
|
||||||
|
{SPR_DRAB, 1, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONTAIL_LOADED}, // S_DRAGONTAIL_RELOAD
|
||||||
|
{SPR_DRAB, 3, 1, {A_MinusCheck}, S_DRAGONMINE_LAND1, 0, S_DRAGONMINE}, // S_DRAGONMINE
|
||||||
|
{SPR_DRAB, 4, 0, {A_PlayActiveSound}, 0, 0, S_DRAGONMINE_LAND2}, // S_DRAGONMINE_LAND1
|
||||||
|
{SPR_DRAB, 4, 2, {A_Thrust}, 0, 1, S_DRAGONMINE_SLOWFLASH1}, // S_DRAGONMINE_LAND2
|
||||||
|
{SPR_DRAB, 5, 11, {NULL}, 0, 0, S_DRAGONMINE_SLOWFLASH2}, // S_DRAGONMINE_SLOWFLASH1
|
||||||
|
{SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_SLOWLOOP}, // S_DRAGONMINE_SLOWFLASH2
|
||||||
|
{SPR_DRAB, 5, 0, {A_Repeat}, 4, S_DRAGONMINE_SLOWFLASH1, S_DRAGONMINE_FASTFLASH1}, // S_DRAGONMINE_SLOWLOOP
|
||||||
|
{SPR_DRAB, 5, 3, {NULL}, 0, 0, S_DRAGONMINE_FASTFLASH2}, // S_DRAGONMINE_FASTFLASH1
|
||||||
|
{SPR_DRAB, FF_FULLBRIGHT|6, 1, {A_PlayAttackSound}, 0, 0, S_DRAGONMINE_FASTLOOP}, // S_DRAGONMINE_FASTFLASH2
|
||||||
|
{SPR_DRAB, 5, 0, {A_Repeat}, 5, S_DRAGONMINE_FASTFLASH1, S_DEATHSTATE}, // S_DRAGONMINE_FASTLOOP
|
||||||
|
|
||||||
// Boss Explosion
|
// Boss Explosion
|
||||||
{SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE
|
{SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE
|
||||||
|
|
||||||
|
@ -3320,6 +3342,9 @@ state_t states[NUMSTATES] =
|
||||||
{SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR2
|
{SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR2
|
||||||
{SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE2
|
{SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE2
|
||||||
|
|
||||||
|
// Flight indicator
|
||||||
|
{SPR_FLII, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 4, S_NULL}, // S_FLIGHTINDICATOR
|
||||||
|
|
||||||
{SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1
|
{SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1
|
||||||
{SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2
|
{SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2
|
||||||
{SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3
|
{SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3
|
||||||
|
@ -5238,6 +5263,114 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
||||||
S_NULL // raisestate
|
S_NULL // raisestate
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{ // MT_DRAGONBOMBER
|
||||||
|
137, // doomednum
|
||||||
|
S_DRAGONBOMBER, // spawnstate
|
||||||
|
1, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
0, // reactiontime
|
||||||
|
sfx_None, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
6, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_XPLD_FLICKY, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_pop, // deathsound
|
||||||
|
10*FRACUNIT, // speed
|
||||||
|
28*FRACUNIT, // radius
|
||||||
|
48*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
100, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_BOUNCE|MF_RUNSPAWNFUNC, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // MT_DRAGONWING
|
||||||
|
-1, // doomednum
|
||||||
|
S_DRAGONWING1, // spawnstate
|
||||||
|
1000, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
0, // reactiontime
|
||||||
|
sfx_None, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
0, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_XPLD_FLICKY, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_pop, // deathsound
|
||||||
|
0, // speed
|
||||||
|
12*FRACUNIT, // radius
|
||||||
|
12*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
100, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_None, // activesound
|
||||||
|
MF_NOGRAVITY|MF_SCENERY|MF_NOBLOCKMAP|MF_NOCLIP, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // MT_DRAGONTAIL
|
||||||
|
-1, // doomednum
|
||||||
|
S_DRAGONTAIL_LOADED, // spawnstate
|
||||||
|
1000, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_None, // seesound
|
||||||
|
0, // reactiontime
|
||||||
|
sfx_None, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
MT_DRAGONMINE, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_XPLD1, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_None, // deathsound
|
||||||
|
0, // speed
|
||||||
|
20*FRACUNIT, // radius
|
||||||
|
40*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
100, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_tink, // activesound
|
||||||
|
MF_NOGRAVITY|MF_SLIDEME|MF_PAIN, // flags
|
||||||
|
S_DRAGONTAIL_EMPTY // raisestate
|
||||||
|
},
|
||||||
|
|
||||||
|
{ // MT_DRAGONMINE
|
||||||
|
-1, // doomednum
|
||||||
|
S_DRAGONMINE, // spawnstate
|
||||||
|
1, // spawnhealth
|
||||||
|
S_NULL, // seestate
|
||||||
|
sfx_s3k76, // seesound
|
||||||
|
0, // reactiontime
|
||||||
|
sfx_s3k89, // attacksound
|
||||||
|
S_NULL, // painstate
|
||||||
|
6, // painchance
|
||||||
|
sfx_None, // painsound
|
||||||
|
S_NULL, // meleestate
|
||||||
|
S_NULL, // missilestate
|
||||||
|
S_TNTBARREL_EXPL1, // deathstate
|
||||||
|
S_NULL, // xdeathstate
|
||||||
|
sfx_s3k6e, // deathsound
|
||||||
|
0, // speed
|
||||||
|
16*FRACUNIT, // radius
|
||||||
|
32*FRACUNIT, // height
|
||||||
|
0, // display offset
|
||||||
|
100, // mass
|
||||||
|
0, // damage
|
||||||
|
sfx_s3k5d, // activesound
|
||||||
|
MF_SPECIAL|MF_SHOOTABLE, // flags
|
||||||
|
S_NULL // raisestate
|
||||||
|
},
|
||||||
|
|
||||||
{ // MT_BOSSEXPLODE
|
{ // MT_BOSSEXPLODE
|
||||||
-1, // doomednum
|
-1, // doomednum
|
||||||
S_BOSSEXPLODE, // spawnstate
|
S_BOSSEXPLODE, // spawnstate
|
||||||
|
|
31
src/info.h
31
src/info.h
|
@ -282,6 +282,9 @@ void A_SpawnPterabytes();
|
||||||
void A_PterabyteHover();
|
void A_PterabyteHover();
|
||||||
void A_RolloutSpawn();
|
void A_RolloutSpawn();
|
||||||
void A_RolloutRock();
|
void A_RolloutRock();
|
||||||
|
void A_DragonbomberSpawn();
|
||||||
|
void A_DragonWing();
|
||||||
|
void A_DragonSegment();
|
||||||
|
|
||||||
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
||||||
#define NUMMOBJFREESLOTS 512
|
#define NUMMOBJFREESLOTS 512
|
||||||
|
@ -334,6 +337,7 @@ typedef enum sprite
|
||||||
SPR_CANG, // Canarivore gas
|
SPR_CANG, // Canarivore gas
|
||||||
SPR_PYRE, // Pyre Fly
|
SPR_PYRE, // Pyre Fly
|
||||||
SPR_PTER, // Pterabyte
|
SPR_PTER, // Pterabyte
|
||||||
|
SPR_DRAB, // Dragonbomber
|
||||||
|
|
||||||
// Generic Boss Items
|
// Generic Boss Items
|
||||||
SPR_JETF, // Boss jet fumes
|
SPR_JETF, // Boss jet fumes
|
||||||
|
@ -664,6 +668,7 @@ typedef enum sprite
|
||||||
// Game Indicators
|
// Game Indicators
|
||||||
SPR_SCOR, // Score logo
|
SPR_SCOR, // Score logo
|
||||||
SPR_DRWN, // Drowning Timer
|
SPR_DRWN, // Drowning Timer
|
||||||
|
SPR_FLII, // AI flight indicator
|
||||||
SPR_LCKN, // Target
|
SPR_LCKN, // Target
|
||||||
SPR_TTAG, // Tag Sign
|
SPR_TTAG, // Tag Sign
|
||||||
SPR_GFLG, // Got Flag sign
|
SPR_GFLG, // Got Flag sign
|
||||||
|
@ -1355,6 +1360,26 @@ typedef enum state
|
||||||
S_PTERABYTE_SWOOPDOWN,
|
S_PTERABYTE_SWOOPDOWN,
|
||||||
S_PTERABYTE_SWOOPUP,
|
S_PTERABYTE_SWOOPUP,
|
||||||
|
|
||||||
|
// Dragonbomber
|
||||||
|
S_DRAGONBOMBER,
|
||||||
|
S_DRAGONWING1,
|
||||||
|
S_DRAGONWING2,
|
||||||
|
S_DRAGONWING3,
|
||||||
|
S_DRAGONWING4,
|
||||||
|
S_DRAGONTAIL_LOADED,
|
||||||
|
S_DRAGONTAIL_EMPTY,
|
||||||
|
S_DRAGONTAIL_EMPTYLOOP,
|
||||||
|
S_DRAGONTAIL_RELOAD,
|
||||||
|
S_DRAGONMINE,
|
||||||
|
S_DRAGONMINE_LAND1,
|
||||||
|
S_DRAGONMINE_LAND2,
|
||||||
|
S_DRAGONMINE_SLOWFLASH1,
|
||||||
|
S_DRAGONMINE_SLOWFLASH2,
|
||||||
|
S_DRAGONMINE_SLOWLOOP,
|
||||||
|
S_DRAGONMINE_FASTFLASH1,
|
||||||
|
S_DRAGONMINE_FASTFLASH2,
|
||||||
|
S_DRAGONMINE_FASTLOOP,
|
||||||
|
|
||||||
// Boss Explosion
|
// Boss Explosion
|
||||||
S_BOSSEXPLODE,
|
S_BOSSEXPLODE,
|
||||||
|
|
||||||
|
@ -3455,6 +3480,8 @@ typedef enum state
|
||||||
S_FOUR2,
|
S_FOUR2,
|
||||||
S_FIVE2,
|
S_FIVE2,
|
||||||
|
|
||||||
|
S_FLIGHTINDICATOR,
|
||||||
|
|
||||||
S_LOCKON1,
|
S_LOCKON1,
|
||||||
S_LOCKON2,
|
S_LOCKON2,
|
||||||
S_LOCKON3,
|
S_LOCKON3,
|
||||||
|
@ -4049,6 +4076,10 @@ typedef enum mobj_type
|
||||||
MT_PTERABYTESPAWNER, // Pterabyte spawner
|
MT_PTERABYTESPAWNER, // Pterabyte spawner
|
||||||
MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
|
MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
|
||||||
MT_PTERABYTE, // Pterabyte
|
MT_PTERABYTE, // Pterabyte
|
||||||
|
MT_DRAGONBOMBER, // Dragonbomber
|
||||||
|
MT_DRAGONWING, // Dragonbomber wing
|
||||||
|
MT_DRAGONTAIL, // Dragonbomber tail segment
|
||||||
|
MT_DRAGONMINE, // Dragonbomber mine
|
||||||
|
|
||||||
// Generic Boss Items
|
// Generic Boss Items
|
||||||
MT_BOSSEXPLODE,
|
MT_BOSSEXPLODE,
|
||||||
|
|
|
@ -312,6 +312,9 @@ void A_SpawnPterabytes(mobj_t *actor);
|
||||||
void A_PterabyteHover(mobj_t *actor);
|
void A_PterabyteHover(mobj_t *actor);
|
||||||
void A_RolloutSpawn(mobj_t *actor);
|
void A_RolloutSpawn(mobj_t *actor);
|
||||||
void A_RolloutRock(mobj_t *actor);
|
void A_RolloutRock(mobj_t *actor);
|
||||||
|
void A_DragonbomberSpawn(mobj_t *actor);
|
||||||
|
void A_DragonWing(mobj_t *actor);
|
||||||
|
void A_DragonSegment(mobj_t *actor);
|
||||||
|
|
||||||
//for p_enemy.c
|
//for p_enemy.c
|
||||||
|
|
||||||
|
@ -14593,3 +14596,97 @@ void A_RolloutRock(mobj_t *actor)
|
||||||
actor->flags2 ^= MF2_DONTDRAW;
|
actor->flags2 ^= MF2_DONTDRAW;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function: A_DragonbomberSpawn
|
||||||
|
//
|
||||||
|
// Description: Spawns the body parts for Dragonbomber
|
||||||
|
//
|
||||||
|
// var1 = Tail segments to spawn
|
||||||
|
// var2 = unused
|
||||||
|
//
|
||||||
|
void A_DragonbomberSpawn(mobj_t *actor)
|
||||||
|
{
|
||||||
|
UINT8 i;
|
||||||
|
mobj_t *mo = actor;
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUA
|
||||||
|
if (LUA_CallAction("A_DragonbomberSpawn", actor))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < var1; i++) // spawn tail segments
|
||||||
|
{
|
||||||
|
mobj_t *segment;
|
||||||
|
fixed_t x, y;
|
||||||
|
x = P_ReturnThrustX(mo, mo->angle, -mo->radius << 1);
|
||||||
|
y = P_ReturnThrustY(mo, mo->angle, -mo->radius << 1);
|
||||||
|
segment = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRAGONTAIL);
|
||||||
|
P_SetTarget(&segment->target, mo);
|
||||||
|
P_SetTarget(&mo->tracer, segment);
|
||||||
|
segment->angle = mo->angle;
|
||||||
|
mo = segment;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 2; i++) // spawn wings
|
||||||
|
{
|
||||||
|
mo = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_DRAGONWING);
|
||||||
|
P_SetTarget(&mo->target, actor);
|
||||||
|
mo->movedir = ANGLE_90 + i * ANGLE_180;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function: A_DragonWing
|
||||||
|
//
|
||||||
|
// Description: Moves actor such that it is placed away from its target at a distance equal to the target's radius in the direction of its target's angle.
|
||||||
|
// The actor's movedir can be used to offset the angle.
|
||||||
|
//
|
||||||
|
// var1 = unused
|
||||||
|
// var2 = unused
|
||||||
|
//
|
||||||
|
void A_DragonWing(mobj_t *actor)
|
||||||
|
{
|
||||||
|
mobj_t *target = actor->target;
|
||||||
|
fixed_t x, y;
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUA
|
||||||
|
if (LUA_CallAction("A_DragonWing", actor))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (target == NULL || !target->health)
|
||||||
|
{
|
||||||
|
P_RemoveMobj(actor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actor->angle = target->angle + actor->movedir;
|
||||||
|
x = target->x + P_ReturnThrustX(actor, actor->angle, -target->radius);
|
||||||
|
y = target->y + P_ReturnThrustY(actor, actor->angle, -target->radius);
|
||||||
|
P_TeleportMove(actor, x, y, target->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function: A_DragonSegment
|
||||||
|
//
|
||||||
|
// Description: Moves actor such that it is placed away from its target at an absolute distance equal to the sum of the two mobjs' radii.
|
||||||
|
//
|
||||||
|
// var1 = unused
|
||||||
|
// var2 = unused
|
||||||
|
//
|
||||||
|
void A_DragonSegment(mobj_t *actor)
|
||||||
|
{
|
||||||
|
mobj_t *target = actor->target;
|
||||||
|
fixed_t dist = P_AproxDistance(P_AproxDistance(actor->x - target->x, actor->y - target->y), actor->z - target->z);
|
||||||
|
fixed_t radius = actor->radius + target->radius;
|
||||||
|
angle_t hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y);
|
||||||
|
angle_t zangle = R_PointToAngle2(0, target->z, dist, actor->z);
|
||||||
|
fixed_t hdist = P_ReturnThrustX(target, zangle, radius);
|
||||||
|
fixed_t xdist = P_ReturnThrustX(target, hangle, hdist);
|
||||||
|
fixed_t ydist = P_ReturnThrustY(target, hangle, hdist);
|
||||||
|
fixed_t zdist = P_ReturnThrustY(target, zangle, radius);
|
||||||
|
|
||||||
|
#ifdef HAVE_BLUA
|
||||||
|
if (LUA_CallAction("A_DragonSegment", actor))
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
actor->angle = hangle;
|
||||||
|
P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist);
|
||||||
|
}
|
||||||
|
|
|
@ -2678,6 +2678,17 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
||||||
target->flags = (target->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY;
|
target->flags = (target->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MT_DRAGONBOMBER:
|
||||||
|
{
|
||||||
|
mobj_t *segment = target;
|
||||||
|
while (segment->tracer != NULL)
|
||||||
|
{
|
||||||
|
P_KillMobj(segment->tracer, NULL, NULL, 0);
|
||||||
|
segment = segment->tracer;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MT_EGGMOBILE3:
|
case MT_EGGMOBILE3:
|
||||||
{
|
{
|
||||||
mobj_t *mo2;
|
mobj_t *mo2;
|
||||||
|
|
|
@ -595,9 +595,6 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
|
||||||
if (sonic->pflags & PF_FINISHED)
|
if (sonic->pflags & PF_FINISHED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (tails->bot == 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP))
|
if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP))
|
||||||
return; // Both should be in same gravity
|
return; // Both should be in same gravity
|
||||||
|
|
||||||
|
@ -1024,7 +1021,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
||||||
if ((thing->flags & MF_PUSHABLE) // not carrying a player
|
if ((thing->flags & MF_PUSHABLE) // not carrying a player
|
||||||
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
|
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
|
||||||
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
|
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
|
||||||
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
|
|
||||||
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
|
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
|
||||||
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|
||||||
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
|
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
|
||||||
|
|
74
src/p_mobj.c
74
src/p_mobj.c
|
@ -9632,6 +9632,80 @@ void P_MobjThinker(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MT_DRAGONBOMBER:
|
||||||
|
{
|
||||||
|
#define DRAGONTURNSPEED ANG2
|
||||||
|
mobj->movecount = (mobj->movecount + 9) % 360;
|
||||||
|
P_SetObjectMomZ(mobj, 4*FINESINE(((mobj->movecount*ANG1) >> ANGLETOFINESHIFT) & FINEMASK), false);
|
||||||
|
if (mobj->threshold > 0) // are we dropping mines?
|
||||||
|
{
|
||||||
|
mobj->threshold--;
|
||||||
|
if (mobj->threshold == 0) // if the timer hits 0, look for a mine to drop!
|
||||||
|
{
|
||||||
|
mobj_t *segment = mobj;
|
||||||
|
while (segment->tracer != NULL && !P_MobjWasRemoved(segment->tracer) && segment->tracer->state == &states[segment->tracer->info->spawnstate])
|
||||||
|
{
|
||||||
|
segment = segment->tracer;
|
||||||
|
}
|
||||||
|
if (segment != mobj) // found an unactivated segment?
|
||||||
|
{
|
||||||
|
mobj_t *mine = P_SpawnMobjFromMobj(segment, 0, 0, 0, segment->info->painchance);
|
||||||
|
mine->angle = segment->angle;
|
||||||
|
P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1);
|
||||||
|
P_SetObjectMomZ(mine, -2*FRACUNIT, true);
|
||||||
|
S_StartSound(mine, mine->info->seesound);
|
||||||
|
P_SetMobjState(segment, segment->info->raisestate);
|
||||||
|
mobj->threshold = mobj->info->painchance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mobj->target != NULL) // Are we chasing a player?
|
||||||
|
{
|
||||||
|
fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y);
|
||||||
|
if (dist > 2000 * mobj->scale) // Not anymore!
|
||||||
|
P_SetTarget(&mobj->target, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale);
|
||||||
|
fixed_t z = mobj->target->z + (mobj->height >> 1) + (mobj->flags & MFE_VERTICALFLIP ? -128*mobj->scale : 128*mobj->scale + mobj->target->height);
|
||||||
|
angle_t diff = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) - mobj->angle;
|
||||||
|
if (diff > ANGLE_180)
|
||||||
|
mobj->angle -= DRAGONTURNSPEED;
|
||||||
|
else
|
||||||
|
mobj->angle += DRAGONTURNSPEED;
|
||||||
|
if (!mobj->threshold && dist < 512 * mobj->scale) // Close enough to drop bombs
|
||||||
|
{
|
||||||
|
mobj->threshold = mobj->info->painchance;
|
||||||
|
}
|
||||||
|
mobj->momz += max(min(z - mobj->z, vspeed), -vspeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Can we find a player to chase?
|
||||||
|
{
|
||||||
|
if (mobj->tracer == NULL || mobj->tracer->state != &states[mobj->tracer->info->spawnstate]
|
||||||
|
|| !P_LookForPlayers(mobj, true, false, 2000*mobj->scale)) // if not, circle around the spawnpoint
|
||||||
|
{
|
||||||
|
if (!mobj->spawnpoint) // unless we don't have one, in which case uhhh just circle around wherever we currently are I guess??
|
||||||
|
mobj->angle += DRAGONTURNSPEED;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale);
|
||||||
|
fixed_t x = mobj->spawnpoint->x << FRACBITS;
|
||||||
|
fixed_t y = mobj->spawnpoint->y << FRACBITS;
|
||||||
|
fixed_t z = mobj->spawnpoint->z << FRACBITS;
|
||||||
|
angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle;
|
||||||
|
if (diff > ANGLE_180)
|
||||||
|
mobj->angle -= DRAGONTURNSPEED;
|
||||||
|
else
|
||||||
|
mobj->angle += DRAGONTURNSPEED;
|
||||||
|
mobj->momz += max(min(z - mobj->z, vspeed), -vspeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale));
|
||||||
|
#undef DRAGONTURNSPEED
|
||||||
|
}
|
||||||
|
break;
|
||||||
case MT_SPINFIRE:
|
case MT_SPINFIRE:
|
||||||
if (mobj->flags & MF_NOGRAVITY)
|
if (mobj->flags & MF_NOGRAVITY)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2805,12 +2805,12 @@ boolean P_SetupLevel(boolean skipprecip)
|
||||||
{
|
{
|
||||||
// Don't include these in the fade!
|
// Don't include these in the fade!
|
||||||
char tx[64];
|
char tx[64];
|
||||||
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
|
V_DrawSmallString(1, 191, V_ALLOWLOWERCASE|V_TRANSLUCENT, M_GetText("Speeding off to..."));
|
||||||
snprintf(tx, 63, "%s%s%s",
|
snprintf(tx, 63, "%s%s%s",
|
||||||
mapheaderinfo[gamemap-1]->lvlttl,
|
mapheaderinfo[gamemap-1]->lvlttl,
|
||||||
(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
|
(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " Zone",
|
||||||
(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
|
(mapheaderinfo[gamemap-1]->actnum > 0) ? va("%d",mapheaderinfo[gamemap-1]->actnum) : "");
|
||||||
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
|
V_DrawSmallString(1, 195, V_ALLOWLOWERCASE|V_TRANSLUCENT, tx);
|
||||||
I_UpdateNoVsync();
|
I_UpdateNoVsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/p_user.c
11
src/p_user.c
|
@ -4425,7 +4425,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
|
||||||
}
|
}
|
||||||
else if (player->powers[pw_carry] == CR_ROLLOUT)
|
else if (player->powers[pw_carry] == CR_ROLLOUT)
|
||||||
{
|
{
|
||||||
player->mo->momz = 9*FRACUNIT + player->mo->tracer->momz;
|
player->mo->momz = 9*FRACUNIT;
|
||||||
|
if (P_MobjFlip(player->mo->tracer)*player->mo->tracer->momz > 0)
|
||||||
|
player->mo->momz += player->mo->tracer->momz;
|
||||||
player->powers[pw_carry] = CR_NONE;
|
player->powers[pw_carry] = CR_NONE;
|
||||||
player->mo->tracer->flags |= MF_PUSHABLE;
|
player->mo->tracer->flags |= MF_PUSHABLE;
|
||||||
P_SetTarget(&player->mo->tracer->tracer, NULL);
|
P_SetTarget(&player->mo->tracer->tracer, NULL);
|
||||||
|
@ -5329,6 +5331,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
|
||||||
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
|
player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer
|
||||||
|
|
||||||
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH);
|
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH);
|
||||||
|
if (player->bot == 1)
|
||||||
|
player->pflags |= PF_THOKKED;
|
||||||
|
else
|
||||||
player->pflags |= (PF_THOKKED|PF_CANCARRY);
|
player->pflags |= (PF_THOKKED|PF_CANCARRY);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -8398,7 +8403,7 @@ static void P_MovePlayer(player_t *player)
|
||||||
|
|
||||||
// Tails Put-Put noise
|
// Tails Put-Put noise
|
||||||
if (player->charability == CA_FLY
|
if (player->charability == CA_FLY
|
||||||
&& player->bot != 1
|
&& (player->pflags & PF_CANCARRY)
|
||||||
&& !(player->mo->eflags & MFE_UNDERWATER)
|
&& !(player->mo->eflags & MFE_UNDERWATER)
|
||||||
&& leveltime % 10 == 0
|
&& leveltime % 10 == 0
|
||||||
&& !player->spectator)
|
&& !player->spectator)
|
||||||
|
@ -12328,7 +12333,7 @@ void P_PlayerAfterThink(player_t *player)
|
||||||
player->mo->momz = tails->momz;
|
player->mo->momz = tails->momz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gametype == GT_COOP)
|
if (gametype == GT_COOP && (!tails->player || tails->player->bot != 1))
|
||||||
{
|
{
|
||||||
player->mo->angle = tails->angle;
|
player->mo->angle = tails->angle;
|
||||||
|
|
||||||
|
|
|
@ -1333,7 +1333,7 @@ void ST_drawTitleCard(void)
|
||||||
V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl);
|
V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, V_PERPLAYER, lvlttl);
|
||||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||||
V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone"));
|
V_DrawLevelTitle(zonexpos + ttlscroll, 104, V_PERPLAYER, M_GetText("Zone"));
|
||||||
V_DrawCenteredString(subttlxpos - ttlscroll, 152, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
|
V_DrawCenteredString(subttlxpos - ttlscroll, 135, V_PERPLAYER|V_ALLOWLOWERCASE, subttl);
|
||||||
|
|
||||||
lt_lasttic = lt_ticker;
|
lt_lasttic = lt_ticker;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue