* Added boss enable linedef (type 449).

- Frontside x offset = boss ID (determined via parameter for all bosses)
	- Noclimb flag = disable mode
	- Bosses don't do a fuckin' THING - no state updates, no player searches, no sounds, no lua, no nothin' - and it's all totally netsynced.
	- The only thing they WILL do is flash infinitely if you hurt them, but this is designed for stuff where you're not meant to be in the same room as the boss til it's activated.
	- All bosses of all IDs are automatically enabled on mapload, then if an enable mode version of this linedef is present in the map for a specific boss id, that boss id is automatically disabled.
* Add multi-boss support via parameter for:
	- All bosses' MT_BOSSFLYPOINT search
	- Boss 5's waypoint search
	- Oldbrak's waypoint search (this one's for you, jood)
This commit is contained in:
toaster 2019-07-31 23:17:17 +01:00
parent b77780e1e7
commit 7cb02985f4
6 changed files with 132 additions and 42 deletions

View File

@ -3878,6 +3878,8 @@ bossjustdie:
}
default: //eggmobiles
{
UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0);
// Stop exploding and prepare to run.
P_SetMobjState(mo, mo->info->xdeathstate);
if (P_MobjWasRemoved(mo))
@ -3897,6 +3899,9 @@ bossjustdie:
if (mo2->type != MT_BOSSFLYPOINT)
continue;
if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo)
continue;
// If this one's further then the last one, don't go for it.
if (mo->target &&
P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) >
@ -12303,6 +12308,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
//INT32 locvar2 = var2;
boolean avoidcenter;
UINT32 i;
UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_Boss5FindWaypoint", actor))
return;
@ -12312,16 +12318,34 @@ void A_Boss5FindWaypoint(mobj_t *actor)
if (locvar1 == 2) // look for the boss waypoint
{
for (i = 0; i < nummapthings; i++)
thinker_t *th;
mobj_t *mo2;
P_SetTarget(&actor->tracer, NULL);
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
// scan the thinkers to find the runaway point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (!mapthings[i].mobj)
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
continue;
if (mapthings[i].mobj->type != MT_BOSSFLYPOINT)
mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSSFLYPOINT)
continue;
P_SetTarget(&actor->tracer, mapthings[i].mobj);
break;
if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo)
continue;
// If this one's further then the last one, don't go for it.
if (actor->tracer &&
P_AproxDistance(P_AproxDistance(actor->x - mo2->x, actor->y - mo2->y), actor->z - mo2->z) >
P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z))
continue;
// Otherwise... Do!
P_SetTarget(&actor->tracer, mo2);
}
if (i == nummapthings)
if (!actor->tracer)
return; // no boss flypoints found
}
else if (locvar1 == 1) // always go to ambush-marked waypoint
@ -12335,11 +12359,13 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (mapthings[i].mobj->type != MT_FANGWAYPOINT)
continue;
if (mapthings[i].options & MTF_AMBUSH)
{
P_SetTarget(&actor->tracer, mapthings[i].mobj);
break;
}
if (mapthings[i].extrainfo != extrainfo)
continue;
if (!(mapthings[i].options & MTF_AMBUSH))
continue;
P_SetTarget(&actor->tracer, mapthings[i].mobj);
break;
}
if (i == nummapthings)
@ -12363,6 +12389,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (actor->tracer == mapthings[i].mobj) // this was your tracer last time
continue;
if (mapthings[i].extrainfo != extrainfo)
continue;
if (mapthings[i].options & MTF_AMBUSH)
{
if (avoidcenter)
@ -12418,6 +12446,8 @@ void A_Boss5FindWaypoint(mobj_t *actor)
continue;
if (actor->tracer == mapthings[i].mobj) // this was your tracer last time
continue;
if (mapthings[i].extrainfo != extrainfo)
continue;
if (mapthings[i].options & MTF_AMBUSH)
{
if (avoidcenter)

View File

@ -5236,6 +5236,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
INT32 i;
boolean foundgoop = false;
INT32 closestNum;
UINT8 extrainfo = (mobj->spawnpoint ? mobj->spawnpoint->extrainfo : 0);
// Looks for players in goop. If you find one, try to jump on him.
for (i = 0; i < MAXPLAYERS; i++)
@ -5261,17 +5262,23 @@ static void P_Boss7Thinker(mobj_t *mobj)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint)
{
dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y);
if (mo2->type != MT_BOSS3WAYPOINT)
continue;
if (!mo2->spawnpoint)
continue;
if (mo2->spawnpoint->extrainfo != extrainfo)
continue;
if (mobj->health <= mobj->info->damage && !(mo2->spawnpoint->options & 7))
continue; // don't jump to center
if (closestNum == -1 || dist < closestdist)
{
closestNum = (mo2->spawnpoint->options & 7);
closestdist = dist;
foundgoop = true;
}
}
dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y);
if (!(closestNum == -1 || dist < closestdist))
continue;
closestNum = (mo2->spawnpoint->options & 7);
closestdist = dist;
foundgoop = true;
}
waypointNum = closestNum;
break;
@ -5280,17 +5287,14 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (!foundgoop)
{
if (mobj->z > 1056*FRACUNIT)
waypointNum = 0;
else
// Don't jump to the center when health is low.
// Force the player to beat you with missiles.
if (mobj->z <= 1056*FRACUNIT || mobj->health <= mobj->info->damage)
waypointNum = 1 + P_RandomKey(4);
else
waypointNum = 0;
}
// Don't jump to the center when health is low.
// Force the player to beat you with missiles.
if (mobj->health <= mobj->info->damage && waypointNum == 0)
waypointNum = 1 + P_RandomKey(4);
if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT
&& mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum)
{
@ -5299,15 +5303,12 @@ static void P_Boss7Thinker(mobj_t *mobj)
else
waypointNum--;
waypointNum %= 5;
if (waypointNum < 0)
waypointNum = 0;
if (mobj->health <= mobj->info->damage)
waypointNum = ((waypointNum + 3) % 4) + 1; // plus four to avoid modulo being negative, minus one to avoid waypoint #0
else
waypointNum = ((waypointNum + 5) % 5);
}
if (waypointNum == 0 && mobj->health <= mobj->info->damage)
waypointNum = 1 + (P_RandomFixed() & 1);
// scan the thinkers to find
// the waypoint to use
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
@ -5316,11 +5317,17 @@ static void P_Boss7Thinker(mobj_t *mobj)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum)
{
hitspot = mo2;
break;
}
if (mo2->type != MT_BOSS3WAYPOINT)
continue;
if (!mo2->spawnpoint)
continue;
if ((mo2->spawnpoint->options & 7) != waypointNum)
continue;
if (mo2->spawnpoint->extrainfo != extrainfo)
continue;
hitspot = mo2;
break;
}
if (hitspot == NULL)
@ -7667,6 +7674,9 @@ void P_MobjThinker(mobj_t *mobj)
}
else if (mobj->flags & MF_BOSS)
{
if (mobj->spawnpoint && (mobj->spawnpoint->extrainfo < 16) && (bossdisabled & (1<<mobj->spawnpoint->extrainfo)))
return;
#ifdef HAVE_BLUA
if (LUAh_BossThinker(mobj))
{

View File

@ -470,4 +470,5 @@ extern INT32 numhuntemeralds;
extern boolean runemeraldmanager;
extern UINT16 emeraldspawndelay;
extern INT32 numstarposts;
extern UINT16 bossdisabled;
#endif

View File

@ -3990,6 +3990,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, leveltime);
WRITEUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap);
WRITEUINT16(save_p, bossdisabled);
WRITEUINT16(save_p, emeralds);
WRITEUINT8(save_p, stagefailed);
@ -4067,6 +4068,7 @@ static inline boolean P_NetUnArchiveMisc(void)
leveltime = READUINT32(save_p);
ssspheres = READUINT32(save_p);
lastmap = READINT16(save_p);
bossdisabled = READUINT16(save_p);
emeralds = READUINT16(save_p);
stagefailed = READUINT8(save_p);

View File

@ -102,6 +102,7 @@ line_t *lines;
side_t *sides;
mapthing_t *mapthings;
INT32 numstarposts;
UINT16 bossdisabled;
boolean levelloading;
UINT8 levelfadecol;

View File

@ -3554,6 +3554,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
break;
case 449: // Enable bosses with parameter
{
INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS;
if (bossid & ~15) // if any bits other than first 16 are set
{
CONS_Alert(CONS_WARNING,
M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"),
line->tag);
break;
}
if (line->flags & ML_NOCLIMB)
{
bossdisabled |= (1<<bossid);
CONS_Debug(DBG_GAMELOGIC, "Line type 449 Executor: bossid disabled = %d", bossid);
}
else
{
bossdisabled &= ~(1<<bossid);
CONS_Debug(DBG_GAMELOGIC, "Line type 449 Executor: bossid enabled = %d", bossid);
}
break;
}
case 450: // Execute Linedef Executor - for recursion
P_LinedefExecute(line->tag, mo, NULL);
break;
@ -6399,7 +6422,10 @@ void P_SpawnSpecials(INT32 fromnetsave)
// This used to be used, and *should* be used in the future,
// but currently isn't.
(void)fromnetsave;
//(void)fromnetsave; -- hooray, it's used!
if (!fromnetsave)
bossdisabled = 0;
// Init special SECTORs.
sector = sectors;
@ -7289,6 +7315,26 @@ void P_SpawnSpecials(INT32 fromnetsave)
case 431:
break;
case 449: // Enable bosses with parameter
{
INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS;
if (bossid & ~15) // if any bits other than first 16 are set
{
CONS_Alert(CONS_WARNING,
M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"),
lines[i].tag);
break;
}
if (fromnetsave)
break;
if (!(lines[i].flags & ML_NOCLIMB))
{
bossdisabled |= (1<<bossid); // gotta disable in the first place to enable
CONS_Debug(DBG_GAMELOGIC, "Line type 449 spawn effect: bossid disabled = %d", bossid);
}
break;
}
// 500 is used for a scroller
// 501 is used for a scroller
// 502 is used for a scroller