Merge branch 'dragonbomber' into 'master'

Dragonbomber

See merge request STJr/SRB2Internal!489
This commit is contained in:
MascaraSnake 2019-11-18 17:10:30 -05:00
commit 7dc3484e5d
9 changed files with 377 additions and 2 deletions

View File

@ -2797,6 +2797,9 @@ static actionpointer_t actionpointers[] =
{{A_PterabyteHover}, "A_PTERABYTEHOVER"},
{{A_RolloutSpawn}, "A_ROLLOUTSPAWN"},
{{A_RolloutRock}, "A_ROLLOUTROCK"},
{{A_DragonbomberSpawn}, "A_DRAGONBOMERSPAWN"},
{{A_DragonWing}, "A_DRAGONWING"},
{{A_DragonSegment}, "A_DRAGONSEGMENT"},
{{NULL}, "NONE"},
// 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_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
"S_BOSSEXPLODE",
@ -7728,6 +7751,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_PTERABYTESPAWNER", // Pterabyte spawner
"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
"MT_PTERABYTE", // Pterabyte
"MT_DRAGONBOMBER", // Dragonbomber
"MT_DRAGONWING", // Dragonbomber wing
"MT_DRAGONTAIL", // Dragonbomber tail segment
"MT_DRAGONMINE", // Dragonbomber mine
// Generic Boss Items
"MT_BOSSEXPLODE",

View File

@ -184,6 +184,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_CANG
&lspr[NOLIGHT], // SPR_PYRE
&lspr[NOLIGHT], // SPR_PTER
&lspr[NOLIGHT], // SPR_DRAB
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes

View File

@ -72,6 +72,7 @@ char sprnames[NUMSPRITES + 1][5] =
"CANG", // Canarivore gas
"PYRE", // Pyre Fly
"PTER", // Pterabyte
"DRAB", // Dragonbomber
// Generic Boss Items
"JETF", // Boss jet fumes
@ -1163,6 +1164,26 @@ state_t states[NUMSTATES] =
{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
// 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
{SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE
@ -5238,6 +5259,114 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
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
-1, // doomednum
S_BOSSEXPLODE, // spawnstate

View File

@ -282,6 +282,9 @@ void A_SpawnPterabytes();
void A_PterabyteHover();
void A_RolloutSpawn();
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
#define NUMMOBJFREESLOTS 512
@ -334,6 +337,7 @@ typedef enum sprite
SPR_CANG, // Canarivore gas
SPR_PYRE, // Pyre Fly
SPR_PTER, // Pterabyte
SPR_DRAB, // Dragonbomber
// Generic Boss Items
SPR_JETF, // Boss jet fumes
@ -1355,6 +1359,26 @@ typedef enum state
S_PTERABYTE_SWOOPDOWN,
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
S_BOSSEXPLODE,
@ -4049,6 +4073,10 @@ typedef enum mobj_type
MT_PTERABYTESPAWNER, // Pterabyte spawner
MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
MT_PTERABYTE, // Pterabyte
MT_DRAGONBOMBER, // Dragonbomber
MT_DRAGONWING, // Dragonbomber wing
MT_DRAGONTAIL, // Dragonbomber tail segment
MT_DRAGONMINE, // Dragonbomber mine
// Generic Boss Items
MT_BOSSEXPLODE,

View File

@ -312,6 +312,9 @@ void A_SpawnPterabytes(mobj_t *actor);
void A_PterabyteHover(mobj_t *actor);
void A_RolloutSpawn(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
@ -14593,3 +14596,103 @@ void A_RolloutRock(mobj_t *actor)
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)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
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)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
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)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
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);
}

View File

@ -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;
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:
{
mobj_t *mo2;

View File

@ -1024,7 +1024,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& ((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)
&& ((!(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))))

View File

@ -9632,6 +9632,81 @@ void P_MobjThinker(mobj_t *mobj)
}
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;
fixed_t dist = P_AproxDistance(mobj->x - x, mobj->y - y);
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:
if (mobj->flags & MF_NOGRAVITY)
{

View File

@ -4425,7 +4425,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
}
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->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->tracer, NULL);