Merge branch 'seaegg_tweaks' into 'master'

Sea Egg

See merge request STJr/SRB2Internal!244
This commit is contained in:
Monster Iestyn 2019-07-09 16:25:07 -04:00
commit 11a24b88ee
7 changed files with 300 additions and 249 deletions

View file

@ -4667,6 +4667,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Boss 3
"S_EGGMOBILE3_STND",
"S_EGGMOBILE3_LAUGH1",
"S_EGGMOBILE3_LAUGH2",
"S_EGGMOBILE3_LAUGH3",
"S_EGGMOBILE3_LAUGH4",
"S_EGGMOBILE3_LAUGH5",
"S_EGGMOBILE3_ATK1",
"S_EGGMOBILE3_ATK2",
"S_EGGMOBILE3_ATK3A",
@ -4675,11 +4680,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGMOBILE3_ATK3D",
"S_EGGMOBILE3_ATK4",
"S_EGGMOBILE3_ATK5",
"S_EGGMOBILE3_LAUGH1",
"S_EGGMOBILE3_LAUGH2",
"S_EGGMOBILE3_LAUGH3",
"S_EGGMOBILE3_LAUGH4",
"S_EGGMOBILE3_LAUGH5",
"S_EGGMOBILE3_LAUGH6",
"S_EGGMOBILE3_LAUGH7",
"S_EGGMOBILE3_LAUGH8",
@ -4732,8 +4732,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FAKEMOBILE_ATK3B",
"S_FAKEMOBILE_ATK3C",
"S_FAKEMOBILE_ATK3D",
"S_FAKEMOBILE_ATK4",
"S_FAKEMOBILE_ATK5",
"S_FAKEMOBILE_DIE1",
"S_FAKEMOBILE_DIE2",
// Boss 4
"S_EGGMOBILE4_STND",
@ -7263,6 +7263,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_EGGMOBILE3",
"MT_PROPELLER",
"MT_FAKEMOBILE",
"MT_SHOCK",
// Boss 4
"MT_EGGMOBILE4",

View file

@ -1272,6 +1272,11 @@ state_t states[NUMSTATES] =
// Boss 3
{SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5
{SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1
{SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A
@ -1279,12 +1284,7 @@ state_t states[NUMSTATES] =
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C
{SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D
{SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH1}, // S_EGGMOBILE3_ATK5
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_LAUGH5
{SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6
{SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7
{SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8
@ -1331,14 +1331,14 @@ state_t states[NUMSTATES] =
// Boss 3 Pinch
{SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT
{SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1
{SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 2, S_FAKEMOBILE_ATK3B}, // S_FAKEMOBILE_ATK3A
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE_ATK4}, // S_FAKEMOBILE_ATK3D
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK5}, // S_FAKEMOBILE_ATK4
{SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK5
{SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D
{SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2
// Boss 4
{SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND
@ -2899,7 +2899,7 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11
// Thunder spark
{SPR_SSPK, FF_ANIMATE, 18, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
{SPR_SSPK, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK
// Invincibility Sparkles
{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP
@ -5516,7 +5516,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
MT_PROPELLER, // painchance
sfx_dmpain, // painsound
S_NULL, // meleestate
S_EGGMOBILE3_ATK1, // missilestate
S_EGGMOBILE3_LAUGH1,// missilestate
S_EGGMOBILE3_DIE1, // deathstate
S_EGGMOBILE3_FLEE1, // xdeathstate
sfx_cybdth, // deathsound
@ -5571,9 +5571,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_s3k7b, // painsound
S_NULL, // meleestate
S_FAKEMOBILE_ATK1, // missilestate
S_XPLD1, // deathstate
S_FAKEMOBILE_DIE1, // deathstate
S_NULL, // xdeathstate
sfx_pop, // deathsound
sfx_mswarp, // deathsound
8*FRACUNIT, // speed
32*FRACUNIT, // radius
116*FRACUNIT, // height
@ -5585,6 +5585,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SHOCK
-1, // doomednum
S_THUNDERCOIN_SPARK, // 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_SPRK1, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
10*FRACUNIT, // speed
16*FRACUNIT, // radius
35*FRACUNIT, // height
0, // display offset
DMG_ELECTRIC|(sfx_buzz2<<8), // mass
20, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
{ // MT_EGGMOBILE4
203, // doomednum
S_EGGMOBILE4_STND, // spawnstate
@ -9102,7 +9129,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_MINE_BOOM1, // deathstate
S_XPLD1, // deathstate
S_NULL, // xdeathstate
sfx_cybdth, // deathsound
20*FRACUNIT, // speed
@ -9129,7 +9156,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_MINE_BOOM1, // deathstate
S_XPLD1, // deathstate
S_NULL, // xdeathstate
sfx_cybdth, // deathsound
20*FRACUNIT, // speed

View file

@ -1425,6 +1425,11 @@ typedef enum state
// Boss 3
S_EGGMOBILE3_STND,
S_EGGMOBILE3_LAUGH1,
S_EGGMOBILE3_LAUGH2,
S_EGGMOBILE3_LAUGH3,
S_EGGMOBILE3_LAUGH4,
S_EGGMOBILE3_LAUGH5,
S_EGGMOBILE3_ATK1,
S_EGGMOBILE3_ATK2,
S_EGGMOBILE3_ATK3A,
@ -1433,11 +1438,6 @@ typedef enum state
S_EGGMOBILE3_ATK3D,
S_EGGMOBILE3_ATK4,
S_EGGMOBILE3_ATK5,
S_EGGMOBILE3_LAUGH1,
S_EGGMOBILE3_LAUGH2,
S_EGGMOBILE3_LAUGH3,
S_EGGMOBILE3_LAUGH4,
S_EGGMOBILE3_LAUGH5,
S_EGGMOBILE3_LAUGH6,
S_EGGMOBILE3_LAUGH7,
S_EGGMOBILE3_LAUGH8,
@ -1490,8 +1490,8 @@ typedef enum state
S_FAKEMOBILE_ATK3B,
S_FAKEMOBILE_ATK3C,
S_FAKEMOBILE_ATK3D,
S_FAKEMOBILE_ATK4,
S_FAKEMOBILE_ATK5,
S_FAKEMOBILE_DIE1,
S_FAKEMOBILE_DIE2,
// Boss 4
S_EGGMOBILE4_STND,
@ -4043,6 +4043,7 @@ typedef enum mobj_type
MT_EGGMOBILE3,
MT_PROPELLER,
MT_FAKEMOBILE,
MT_SHOCK,
// Boss 4
MT_EGGMOBILE4,

View file

@ -2863,6 +2863,7 @@ void A_BossFireShot(mobj_t *actor)
fixed_t x, y, z;
INT32 locvar1 = var1;
INT32 locvar2 = var2;
mobj_t *missile;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_BossFireShot", actor))
@ -2930,7 +2931,10 @@ void A_BossFireShot(mobj_t *actor)
break;
}
P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z);
missile = P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z);
if (missile && actor->tracer && (actor->tracer->flags & MF_BOSS)) // Don't harm your papa.
P_SetTarget(&missile->target, actor->tracer);
}
// Function: A_Boss7FireMissiles
@ -7761,9 +7765,11 @@ void A_Boss3TakeDamage(mobj_t *actor)
return;
#endif
actor->movecount = var1;
actor->movefactor = -512*FRACUNIT;
/*if (actor->target && actor->target->spawnpoint)
actor->threshold = actor->target->spawnpoint->extrainfo;*/
if (actor->target && actor->target->spawnpoint)
actor->threshold = actor->target->spawnpoint->extrainfo;
}
// Function: A_Boss3Path
@ -7800,21 +7806,31 @@ void A_Boss3Path(mobj_t *actor)
}
else if (actor->threshold >= 0) // Traveling mode
{
thinker_t *th;
mobj_t *mo2;
fixed_t dist, dist2;
fixed_t dist = 0;
fixed_t speed;
P_SetTarget(&actor->target, NULL);
// scan the thinkers
// to find a point that matches
// the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
if (!(actor->flags2 & MF2_STRONGBOX))
{
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold)
thinker_t *th;
mobj_t *mo2;
P_SetTarget(&actor->target, NULL);
// scan the thinkers
// to find a point that matches
// the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSS3WAYPOINT)
continue;
if (!mo2->spawnpoint)
continue;
if (mo2->spawnpoint->angle != actor->threshold)
continue;
if (mo2->spawnpoint->extrainfo != actor->cusval)
continue;
P_SetTarget(&actor->target, mo2);
break;
}
@ -7822,67 +7838,62 @@ void A_Boss3Path(mobj_t *actor)
if (!actor->target) // Should NEVER happen
{
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold);
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d, %d\n", actor->threshold, actor->cusval);
return;
}
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z);
if (dist < 1)
dist = 1;
if (actor->tracer && ((actor->tracer->movedir)
|| (actor->tracer->health <= actor->tracer->info->damage)))
speed = actor->info->speed * 2;
else
speed = actor->info->speed;
actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed);
actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed);
actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed);
if (actor->target->x == actor->x && actor->target->y == actor->y)
{
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z + actor->movefactor - actor->z);
if (actor->momx != 0 || actor->momy != 0)
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
if (dist < 1)
dist = 1;
dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz));
actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed);
actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed);
actor->momz = FixedMul(FixedDiv(actor->target->z + actor->movefactor - actor->z, dist), speed);
if (dist2 < 1)
dist2 = 1;
if (actor->momx != 0 || actor->momy != 0)
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
}
if ((dist >> FRACBITS) <= (dist2 >> FRACBITS))
if (dist <= speed)
{
// If further away, set XYZ of mobj to waypoint location
P_UnsetThingPosition(actor);
actor->x = actor->target->x;
actor->y = actor->target->y;
actor->z = actor->target->z;
actor->z = actor->target->z + actor->movefactor;
actor->momx = actor->momy = actor->momz = 0;
P_SetThingPosition(actor);
if (actor->threshold == 0)
if (!actor->movefactor) // firing mode
{
actor->movecount |= 2;
actor->movefactor = -512*FRACUNIT;
actor->flags2 &= ~MF2_STRONGBOX;
}
else if (!(actor->flags2 & MF2_STRONGBOX)) // just spawned or going down
{
actor->flags2 |= MF2_STRONGBOX;
actor->movefactor = -512*FRACUNIT;
}
else if (!(actor->flags2 & MF2_AMBUSH)) // just shifted tube
{
actor->flags2 |= MF2_AMBUSH;
actor->movefactor = 0;
}
else // just hit the bottom of your tube
{
P_RemoveMobj(actor); // Cycle completed. Dummy removed.
return;
}
// Set to next waypoint in sequence
if (actor->target->spawnpoint)
{
// From the center point, choose one of the five paths
if (actor->target->spawnpoint->angle == 0)
{
P_RemoveMobj(actor); // Cycle completed. Dummy removed.
return;
}
else
actor->threshold = actor->target->spawnpoint->extrainfo;
// If the deaf flag is set, go into firing mode
if (actor->target->spawnpoint->options & MTF_AMBUSH)
actor->movecount |= 2;
}
else // This should never happen, as well
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n");
}
}
}

View file

@ -2538,13 +2538,20 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
mo = (mobj_t *)th;
if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target)
{
P_RemoveMobj(mo);
i++;
}
if (i == 2) // we've already removed 2 of these, let's stop now
if (mo->type != (mobjtype_t)target->info->mass)
continue;
if (mo->tracer != target)
continue;
P_KillMobj(mo, inflictor, source, damagetype);
mo->destscale = mo->scale/8;
mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE);
mo->momz = mo->info->speed;
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
if (++i == 2) // we've already removed 2 of these, let's stop now
break;
else
S_StartSound(mo, mo->info->deathsound); // done once to prevent sound stacking
}
}
break;

View file

@ -4374,6 +4374,8 @@ static void P_Boss3Thinker(mobj_t *mobj)
}
if (mobj->health <= 0)
return;
/*
{
mobj->movecount = 0;
mobj->reactiontime = 0;
@ -4386,89 +4388,37 @@ static void P_Boss3Thinker(mobj_t *mobj)
mobj->momz = mobj->info->speed;
return;
}
}
else
{
mobj->flags |= MF_NOGRAVITY|MF_NOCLIP;
mobj->flags |= MF_NOCLIPHEIGHT;
mobj->threshold = -1;
return;
}
}*/
if (mobj->reactiontime) // Shock mode
if (mobj->reactiontime) // At the bottom of the water
{
UINT32 i;
SINT8 curpath = mobj->threshold;
// Choose one of the paths you're not already on
mobj->threshold = P_RandomKey(8-1);
if (mobj->threshold >= curpath)
mobj->threshold++;
if (mobj->state != &states[mobj->info->spawnstate])
P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->reactiontime--;
if (!mobj->reactiontime)
{
ffloor_t *rover;
// Shock the water
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
P_DamageMobj(players[i].mo, mobj, mobj, 1, 0);
}
// Make the water flash
for (i = 0; i < numsectors; i++)
{
if (!sectors[i].ffloors)
continue;
for (rover = sectors[i].ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
P_SpawnLightningFlash(rover->master->frontsector);
break;
}
}
if ((UINT32)mobj->extravalue1 + TICRATE*2 < leveltime)
{
mobj->extravalue1 = (INT32)leveltime;
S_StartSound(0, sfx_buzz1);
}
// If in the center, check to make sure
// none of the players are in the water
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo || players[i].bot)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
{ // Stay put
mobj->reactiontime = 2*TICRATE;
return;
}
}
}
if (!mobj->reactiontime && mobj->health <= mobj->info->damage)
{ // Spawn pinch dummies from the center when we're leaving it.
thinker_t *th;
mobj_t *mo2;
mobj_t *dummy;
SINT8 way = mobj->threshold - 1; // 0 through 4.
SINT8 way2;
SINT8 way0 = mobj->threshold; // 0 through 4.
SINT8 way1, way2;
i = 0; // reset i to 0 so we can check how many clones we've removed
@ -4477,63 +4427,68 @@ static void P_Boss3Thinker(mobj_t *mobj)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)mobj->info->mass && mo2->tracer == mobj)
{
P_RemoveMobj(mo2);
i++;
}
if (i == 2) // we've already removed 2 of these, let's stop now
if (mo2->type != (mobjtype_t)mobj->info->mass)
continue;
if (mo2->tracer != mobj)
continue;
P_RemoveMobj(mo2);
if (++i == 2) // we've already removed 2 of these, let's stop now
break;
}
way = (way + P_RandomRange(1,3)) % 5; // dummy 1 at one of the first three options after eggmobile
way1 = P_RandomKey(8-2);
if (way1 >= curpath)
way1++;
if (way1 >= way0)
{
way1++;
if (way1 == curpath)
way1++;
}
dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass);
dummy->angle = mobj->angle;
dummy->threshold = way + 1;
dummy->tracer = mobj;
dummy->threshold = way1;
P_SetTarget(&dummy->tracer, mobj);
dummy->movefactor = mobj->movefactor;
dummy->cusval = mobj->cusval;
way2 = P_RandomKey(8-3);
if (way2 >= curpath)
way2++;
if (way2 >= way0)
{
way2++;
if (way2 == curpath)
way2++;
}
if (way2 >= way1)
{
way2++;
if (way2 == curpath || way2 == way0)
way2++;
}
do
way2 = (way + P_RandomRange(1,3)) % 5; // dummy 2 has to be careful,
while (way2 == mobj->threshold - 1); // to make sure it doesn't try to go the Eggman Way if dummy 1 rolled high.
dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass);
dummy->angle = mobj->angle;
dummy->threshold = way2 + 1;
dummy->tracer = mobj;
dummy->threshold = way2;
P_SetTarget(&dummy->tracer, mobj);
dummy->movefactor = mobj->movefactor;
dummy->cusval = mobj->cusval;
CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", mobj->threshold, way + 1, dummy->threshold);
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", way0, way1, way2);
P_LinedefExecute(LE_PINCHPHASE+(mobj->cusval*LE_PARAMWIDTH), mobj, NULL);
}
}
else if (mobj->movecount) // Firing mode
{
UINT32 i;
// look for a new target
P_BossTargetPlayer(mobj, false);
if (!mobj->target || !mobj->target->player)
return;
// Are there any players underwater? If so, shock them!
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
continue;
if (!players[i].mo || players[i].bot)
continue;
if (players[i].mo->health <= 0)
continue;
if (players[i].mo->eflags & MFE_UNDERWATER)
{
mobj->movecount = 0;
P_SetMobjState(mobj, mobj->info->spawnstate);
return;
}
}
// Always face your target.
A_FaceTarget(mobj);
@ -4548,9 +4503,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
}
else if (mobj->threshold >= 0) // Traveling mode
{
thinker_t *th;
mobj_t *mo2;
fixed_t dist, dist2;
fixed_t dist = 0;
fixed_t speed;
P_SetTarget(&mobj->target, NULL);
@ -4559,86 +4512,101 @@ static void P_Boss3Thinker(mobj_t *mobj)
&& !(mobj->flags2 & MF2_FRET))
P_SetMobjState(mobj, mobj->info->spawnstate);
// scan the thinkers
// to find a point that matches
// the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
if (!(mobj->flags2 & MF2_STRONGBOX))
{
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold)
thinker_t *th;
mobj_t *mo2;
P_SetTarget(&mobj->tracer, NULL);
// scan the thinkers
// to find a point that matches
// the number
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
P_SetTarget(&mobj->target, mo2);
mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSS3WAYPOINT)
continue;
if (!mo2->spawnpoint)
continue;
if (mo2->spawnpoint->angle != mobj->threshold)
continue;
if (mo2->spawnpoint->extrainfo != mobj->cusval)
continue;
P_SetTarget(&mobj->tracer, mo2);
break;
}
}
if (!mobj->target) // Should NEVER happen
if (!mobj->tracer) // Should NEVER happen
{
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 was unable to find specified waypoint: %d\n", mobj->threshold);
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 was unable to find specified waypoint: %d, %d\n", mobj->threshold, mobj->cusval);
return;
}
dist = P_AproxDistance(P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y), mobj->target->z - mobj->z);
if (dist < 1)
dist = 1;
if ((mobj->movedir) || (mobj->health <= mobj->info->damage))
speed = mobj->info->speed * 2;
else
speed = mobj->info->speed;
mobj->momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed);
mobj->momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed);
mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed);
if (mobj->momx != 0 || mobj->momy != 0)
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
dist2 = P_AproxDistance(P_AproxDistance(mobj->target->x - (mobj->x + mobj->momx), mobj->target->y - (mobj->y + mobj->momy)), mobj->target->z - (mobj->z + mobj->momz));
if (dist2 < 1)
dist2 = 1;
if ((dist >> FRACBITS) <= (dist2 >> FRACBITS))
if (mobj->tracer->x == mobj->x && mobj->tracer->y == mobj->y)
{
// If further away, set XYZ of mobj to waypoint location
// apply ambush for old routing, otherwise whack a mole only
dist = P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z + mobj->movefactor - mobj->z);
if (dist < 1)
dist = 1;
mobj->momx = FixedMul(FixedDiv(mobj->tracer->x - mobj->x, dist), speed);
mobj->momy = FixedMul(FixedDiv(mobj->tracer->y - mobj->y, dist), speed);
mobj->momz = FixedMul(FixedDiv(mobj->tracer->z + mobj->movefactor - mobj->z, dist), speed);
if (mobj->momx != 0 || mobj->momy != 0)
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
}
if (dist <= speed)
{
// If distance to point is less than travel in that frame, set XYZ of mobj to waypoint location
P_UnsetThingPosition(mobj);
mobj->x = mobj->target->x;
mobj->y = mobj->target->y;
mobj->z = mobj->target->z;
mobj->x = mobj->tracer->x;
mobj->y = mobj->tracer->y;
mobj->z = mobj->tracer->z + mobj->movefactor;
mobj->momx = mobj->momy = mobj->momz = 0;
P_SetThingPosition(mobj);
if (mobj->threshold == 0)
if (!mobj->movefactor) // to firing mode
{
mobj->reactiontime = 1; // Bzzt! Shock the water!
mobj->movedir = 0;
UINT8 i;
angle_t ang = 0;
if (mobj->health <= 0)
mobj->movecount = mobj->health+1;
mobj->movefactor = -512*FRACUNIT;
// shock the water!
for (i = 0; i < 64; i++)
{
mobj->flags |= MF_NOGRAVITY|MF_NOCLIP;
mobj->flags |= MF_NOCLIPHEIGHT;
mobj->threshold = -1;
return;
mobj_t *shock = P_SpawnMobjFromMobj(mobj, 0, 0, 4*FRACUNIT, MT_SHOCK);
P_SetTarget(&shock->target, mobj);
P_InstaThrust(shock, ang, shock->info->speed);
P_CheckMissileSpawn(shock);
ang += (ANGLE_MAX/64);
}
S_StartSound(mobj, sfx_fizzle);
}
// Set to next waypoint in sequence
if (mobj->target->spawnpoint)
else if (mobj->flags2 & (MF2_STRONGBOX|MF2_CLASSICPUSH)) // just hit the bottom of your tube
{
// From the center point, choose one of the five paths
if (mobj->target->spawnpoint->angle == 0)
mobj->threshold = P_RandomRange(1,5);
else
mobj->threshold = mobj->target->spawnpoint->extrainfo;
// If the deaf flag is set, go into firing mode
if (mobj->target->spawnpoint->options & MTF_AMBUSH)
mobj->movecount = mobj->health+1;
mobj->flags2 &= ~(MF2_STRONGBOX|MF2_CLASSICPUSH);
mobj->reactiontime = 1; // spawn pinch dummies
mobj->movedir = 0;
}
else // just shifted to another tube
{
mobj->flags2 |= MF2_STRONGBOX;
if (mobj->health > 0)
mobj->movefactor = 0;
}
else // This should never happen, as well
CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 waypoint has no spawnpoint associated with it.\n");
}
}
}
@ -7679,6 +7647,34 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
break;
case MT_FAKEMOBILE:
if (mobj->scale == mobj->destscale)
{
if (!mobj->fuse)
{
S_StartSound(mobj, sfx_s3k77);
mobj->flags2 |= MF2_DONTDRAW;
mobj->fuse = TICRATE;
}
return;
}
if (!mobj->reactiontime)
{
if (P_RandomChance(FRACUNIT/2))
mobj->movefactor = FRACUNIT;
else
mobj->movefactor = -FRACUNIT;
if (P_RandomChance(FRACUNIT/2))
mobj->movedir = ANG20;
else
mobj->movedir = -ANG20;
mobj->reactiontime = 5;
}
mobj->momz += mobj->movefactor;
mobj->angle += mobj->movedir;
P_InstaThrust(mobj, mobj->angle, -mobj->info->speed);
mobj->reactiontime--;
break;
case MT_EGGSHIELD:
mobj->flags2 ^= MF2_DONTDRAW;
break;
@ -9445,6 +9441,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
// Special condition for the 2nd boss.
mobj->watertop = mobj->info->speed;
break;
case MT_EGGMOBILE3:
mobj->movefactor = -512*FRACUNIT;
mobj->flags2 |= MF2_CLASSICPUSH;
break;
case MT_FLICKY_08:
mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUA);
break;
@ -10853,6 +10853,9 @@ You should think about modifying the deathmatch starts to take full advantage of
else
skyboxviewpnts[mthing->extrainfo] = mobj;
break;
case MT_EGGMOBILE3:
mobj->cusval = mthing->extrainfo;
break;
case MT_FAN:
if (mthing->options & MTF_OBJECTSPECIAL)
{

View file

@ -4456,6 +4456,7 @@ void P_DoJumpShield(player_t *player)
P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale));
if (i % 2)
P_SetObjectMomZ(spark, -4*FRACUNIT, false);
spark->fuse = 18;
}
#undef limitangle
#undef numangles