From 7cb02985f4707f95e4eecbb3102a2d8b8f5a261a Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 31 Jul 2019 23:17:17 +0100 Subject: [PATCH 1/4] * 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) --- src/p_enemy.c | 52 ++++++++++++++++++++++++++++++-------- src/p_mobj.c | 70 +++++++++++++++++++++++++++++---------------------- src/p_mobj.h | 1 + src/p_saveg.c | 2 ++ src/p_setup.c | 1 + src/p_spec.c | 48 ++++++++++++++++++++++++++++++++++- 6 files changed, 132 insertions(+), 42 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 88405437c..18d6f20c0 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -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) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1cb7f742d..fe0044634 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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<spawnpoint->extrainfo))) + return; + #ifdef HAVE_BLUA if (LUAh_BossThinker(mobj)) { diff --git a/src/p_mobj.h b/src/p_mobj.h index bfcb09210..77791f928 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -470,4 +470,5 @@ extern INT32 numhuntemeralds; extern boolean runemeraldmanager; extern UINT16 emeraldspawndelay; extern INT32 numstarposts; +extern UINT16 bossdisabled; #endif diff --git a/src/p_saveg.c b/src/p_saveg.c index 09df38eb0..24b68b971 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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); diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..4d713881d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -102,6 +102,7 @@ line_t *lines; side_t *sides; mapthing_t *mapthings; INT32 numstarposts; +UINT16 bossdisabled; boolean levelloading; UINT8 levelfadecol; diff --git a/src/p_spec.c b/src/p_spec.c index 3cd0461e2..f1fb5c82f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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<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< Date: Thu, 1 Aug 2019 11:35:04 +0100 Subject: [PATCH 2/4] Ok, now the MobjThinker Lua hook is neutralised properly as well. --- src/p_mobj.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fe0044634..fe45a799a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7011,6 +7011,9 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && !(mobj->spawnpoint->extrainfo & ~15) && (bossdisabled & (1<spawnpoint->extrainfo))) + return; + // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) P_SetTarget(&mobj->target, NULL); @@ -7674,9 +7677,6 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->flags & MF_BOSS) { - if (mobj->spawnpoint && (mobj->spawnpoint->extrainfo < 16) && (bossdisabled & (1<spawnpoint->extrainfo))) - return; - #ifdef HAVE_BLUA if (LUAh_BossThinker(mobj)) { From 8fa0641e99b47573184238ce03eb563ab3d890f4 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 1 Aug 2019 18:12:12 +0100 Subject: [PATCH 3/4] Instead of checking whether mobj->spawnpoint->extrainfo is in the correct range every tic, have a lua error for trying to set it outside (since there'll no doubt be other consequences to being outside the range too) --- src/lua_mobjlib.c | 7 ++++++- src/p_mobj.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 8bbbebe1d..5fc3babd3 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -804,7 +804,12 @@ static int mapthing_set(lua_State *L) else if(fastcmp(field,"z")) mt->z = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"extrainfo")) - mt->extrainfo = (UINT8)luaL_checkinteger(L, 3); + { + INT32 extrainfo = luaL_checkinteger(L, 3); + if (extrainfo & ~15) + return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); + mt->extrainfo = (UINT8)extrainfo; + } else if(fastcmp(field,"mobj")) mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); else diff --git a/src/p_mobj.c b/src/p_mobj.c index fe45a799a..5b924c3eb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7011,7 +7011,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; - if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && !(mobj->spawnpoint->extrainfo & ~15) && (bossdisabled & (1<spawnpoint->extrainfo))) + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<spawnpoint->extrainfo))) return; // Remove dead target/tracer. From 105df2395d4078bf7c6f318fbf1245cce50ff839 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 3 Aug 2019 12:09:18 +0100 Subject: [PATCH 4/4] MI made a good argument for bossdisabled not being conditional on fromnetsave. --- src/p_spec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f1fb5c82f..ce769ac52 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6422,10 +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; -- hooray, it's used! + (void)fromnetsave; - if (!fromnetsave) - bossdisabled = 0; + // yep, we do this here - "bossdisabled" is considered an apparatus of specials. + bossdisabled = 0; // Init special SECTORs. sector = sectors; @@ -7325,8 +7325,6 @@ void P_SpawnSpecials(INT32 fromnetsave) lines[i].tag); break; } - if (fromnetsave) - break; if (!(lines[i].flags & ML_NOCLIMB)) { bossdisabled |= (1<