From e2e8ec8b3e0a31798da9c36d893235a09edd5ea0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Jun 2021 21:08:58 +0200 Subject: [PATCH] - MBF21: implemented thing flags. --- src/gamedata/d_dehacked.cpp | 87 +++++++++++++++++++ src/gamedata/g_mapinfo.cpp | 5 ++ src/gamedata/g_mapinfo.h | 5 ++ src/playsim/actor.h | 10 ++- src/playsim/p_enemy.cpp | 36 +++++--- src/scripting/thingdef_data.cpp | 8 ++ wadsrc/static/mapinfo/doom1.txt | 10 +-- .../static/zscript/actors/doom/arachnotron.zs | 1 + wadsrc/static/zscript/actors/doom/bruiser.zs | 1 + .../static/zscript/actors/doom/cyberdemon.zs | 2 + wadsrc/static/zscript/actors/doom/fatso.zs | 1 + .../zscript/actors/doom/spidermaster.zs | 2 + 12 files changed, 152 insertions(+), 16 deletions(-) diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index f69ae6714..0cba8f124 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -812,6 +812,48 @@ static void SetDehParams(FState *state, int codepointer, VMDisassemblyDumper &di } } +struct DehFlags2 +{ + const char* name; + void (*setter)(AActor* defaults); +}; + +// not all of these map to real flags so this table needs handler callbacks. +static const struct DehFlags2 deh_mobjflags_mbf21[] = { + {"LOGRAV", [](AActor* defaults) { defaults->Gravity = 1. / 8.; }}, // low gravity + {"SHORTMRANGE", [](AActor* defaults) { defaults->maxtargetrange = 896.; }}, // short missile range + {"DMGIGNORED", [](AActor* defaults) { defaults->flags3 |= MF3_NOTARGET; }}, // other things ignore its attacks + {"NORADIUSDMG", [](AActor* defaults) { defaults->flags3 |= MF3_NORADIUSDMG; }}, // doesn't take splash damage + {"FORCERADIUSDMG", [](AActor* defaults) { defaults->flags4 |= MF4_FORCERADIUSDMG; }}, // causes splash damage even if target immune + {"HIGHERMPROB", [](AActor* defaults) { defaults->MinMissileChance = 160; }}, // higher missile attack probability + {"RANGEHALF", [](AActor* defaults) { defaults->flags4 |= MF4_MISSILEMORE; }}, // use half distance for missile attack probability + {"NOTHRESHOLD", [](AActor* defaults) { defaults->flags4 |= MF4_QUICKTORETALIATE; }}, // no targeting threshold + {"LONGMELEE", [](AActor* defaults) { defaults->meleethreshold = 196; }}, // long melee range + {"BOSS", [](AActor* defaults) { defaults->flags2 |= MF2_BOSS; }}, // full volume see / death sound + splash immunity + {"MAP07BOSS1", [](AActor* defaults) { defaults->flags8 |= MF8_MAP07BOSS1; }}, // Tag 666 "boss" on doom 2 map 7 + {"MAP07BOSS2", [](AActor* defaults) { defaults->flags8 |= MF8_MAP07BOSS2; }}, // Tag 667 "boss" on doom 2 map 7 + {"E1M8BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E1M8BOSS; }}, // E1M8 boss + {"E2M8BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E2M8BOSS; }}, // E2M8 boss + {"E3M8BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E3M8BOSS; }}, // E3M8 boss + {"E4M6BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E4M6BOSS; }}, // E4M6 boss + {"E4M8BOSS", [](AActor* defaults) { defaults->flags8 |= MF8_E4M8BOSS; }}, // E4M8 boss + {"RIP", [](AActor* defaults) { defaults->flags2 |= MF2_RIP; }}, // projectile rips through targets + {"FULLVOLSOUNDS", [](AActor* defaults) { defaults->flags8 |= MF8_FULLVOLSEE; defaults->flags3 |= MF3_FULLVOLDEATH; } }, // full volume see / death sound +}; + +static void ClearBits2Stuff(AActor* defaults) +{ + defaults->Gravity = 1.; + defaults->maxtargetrange = 0; + defaults->MinMissileChance = 200; + defaults->meleethreshold = 0; + defaults->flags2 &= ~(MF2_BOSS | MF2_RIP); + defaults->flags3 &= ~(MF3_NOTARGET | MF3_NORADIUSDMG | MF3_FULLVOLDEATH); + defaults->flags4 &= ~(MF4_MISSILEMORE | MF4_QUICKTORETALIATE | MF4_FORCERADIUSDMG); + defaults->flags8 &= ~(MF8_E1M8BOSS | MF8_E2M8BOSS | MF8_E3M8BOSS | MF8_E4M8BOSS | MF8_E4M6BOSS | MF8_MAP07BOSS1 | MF8_MAP07BOSS2 | MF8_FULLVOLSEE); +} + + static int PatchThing (int thingy) { enum @@ -1265,6 +1307,51 @@ static int PatchThing (int thingy) DPrintf (DMSG_SPAMMY, "Bits: %d,%d (0x%08x,0x%08x)\n", info->flags.GetValue(), info->flags2.GetValue(), info->flags.GetValue(), info->flags2.GetValue()); } + else if (stricmp(Line1, "MBF21 Bits") == 0) + { + uint32_t value = 0; + bool vchanged = false; + + char* strval; + + for (strval = Line2; (strval = strtok(strval, ",+| \t\f\r")); strval = NULL) + { + if (IsNum(strval)) + { + value |= (unsigned long)strtoll(strval, NULL, 10); + vchanged = true; + } + else + { + unsigned i; + for (i = 0; i < countof(deh_mobjflags_mbf21); i++) + { + if (!stricmp(strval, deh_mobjflags_mbf21[i].name)) + { + vchanged = true; + value |= 1 << i; + break; + } + } + if (i == countof(deh_mobjflags_mbf21)) + { + DPrintf(DMSG_ERROR, "Unknown bit mnemonic %s\n", strval); + } + } + } + if (vchanged) + { + ClearBits2Stuff(info); + for (size_t i = 0; i < countof(deh_mobjflags_mbf21); i++) + { + if (value & (1 << i)) + { + deh_mobjflags_mbf21[i].setter(info); + } + } + } + DPrintf(DMSG_SPAMMY, "MBF21 Bits: %d (0x%08x)\n", info->flags.GetValue(), info->flags.GetValue()); + } else if (stricmp (Line1, "ID #") == 0) { *ednum = (int16_t)val; diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index fd7b79527..ac76ee076 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -1583,6 +1583,11 @@ MapFlagHandlers[] = { "minotaurspecial", MITYPE_SETFLAG, LEVEL_MINOTAURSPECIAL, 0 }, { "dsparilspecial", MITYPE_SETFLAG, LEVEL_SORCERER2SPECIAL, 0 }, { "ironlichspecial", MITYPE_SETFLAG, LEVEL_HEADSPECIAL, 0 }, + { "e1m8special", MITYPE_SETFLAG3,LEVEL3_E1M8SPECIAL, 0 }, + { "e2m8special", MITYPE_SETFLAG3,LEVEL3_E2M8SPECIAL, 0 }, + { "e3m8special", MITYPE_SETFLAG3,LEVEL3_E3M8SPECIAL, 0 }, + { "e4m8special", MITYPE_SETFLAG3,LEVEL3_E4M8SPECIAL, 0 }, + { "e4m6special", MITYPE_SETFLAG3,LEVEL3_E4M6SPECIAL, 0 }, { "specialaction_exitlevel", MITYPE_SCFLAGS, 0, ~LEVEL_SPECACTIONSMASK }, { "specialaction_opendoor", MITYPE_SCFLAGS, LEVEL_SPECOPENDOOR, ~LEVEL_SPECACTIONSMASK }, { "specialaction_lowerfloor", MITYPE_SCFLAGS, LEVEL_SPECLOWERFLOOR, ~LEVEL_SPECACTIONSMASK }, diff --git a/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index e96b1c458..a572fcce6 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -252,6 +252,11 @@ enum ELevelFlags : unsigned int LEVEL3_HIDEAUTHORNAME = 0x00000100, LEVEL3_PROPERMONSTERFALLINGDAMAGE = 0x00000200, // Properly apply falling damage to the monsters LEVEL3_SKYBOXAO = 0x00000400, // Apply SSAO to sector skies + LEVEL3_E1M8SPECIAL = 0x00000800, + LEVEL3_E2M8SPECIAL = 0x00001000, + LEVEL3_E3M8SPECIAL = 0x00002000, + LEVEL3_E4M8SPECIAL = 0x00004000, + LEVEL3_E4M6SPECIAL = 0x00008000, }; diff --git a/src/playsim/actor.h b/src/playsim/actor.h index dc7f2da0c..ed1f3dc2a 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -414,7 +414,15 @@ enum ActorFlag8 MF8_STOPRAILS = 0x00000200, // [MC] Prevent rails from going further if an actor has this flag. MF8_ABSVIEWANGLES = 0x00000400, // [MC] By default view angle/pitch/roll is an offset. This will make it absolute instead. MF8_FALLDAMAGE = 0x00000800, // Monster will take fall damage regardless of map settings. - MF8_ALLOWTHRUBITS = 0x00008000, // [MC] Enable ThruBits property + MF8_ALLOWTHRUBITS = 0x00008000, // [MC] Enable ThruBits property + MF8_FULLVOLSEE = 0x00010000, // Play see sound at full volume + MF8_E1M8BOSS = 0x00020000, // MBF21 boss death. + MF8_E2M8BOSS = 0x00040000, // MBF21 boss death. + MF8_E3M8BOSS = 0x00080000, // MBF21 boss death. + MF8_E4M8BOSS = 0x00100000, // MBF21 boss death. + MF8_E4M6BOSS = 0x00200000, // MBF21 boss death. + MF8_MAP07BOSS1 = 0x00400000, // MBF21 boss death. + MF8_MAP07BOSS2 = 0x00800000, // MBF21 boss death. }; // --- mobj.renderflags --- diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index be233dfa1..9a7ef9657 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -1846,7 +1846,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } else if (self->SeeSound) { - if (self->flags2 & MF2_BOSS) + if ((self->flags2 & MF2_BOSS) || (self->flags8 & MF8_FULLVOLSEE)) { // full volume S_Sound (self, CHAN_VOICE, 0, self->SeeSound, 1, ATTN_NONE); } @@ -3082,7 +3082,12 @@ void A_BossDeath(AActor *self) FName mytype = self->GetClass()->TypeName; // Ugh... - FName type = self->GetClass()->GetReplacee(self->Level)->TypeName; + auto replacee = self->GetClass()->GetReplacee(self->Level); + FName type = replacee->TypeName; + int flags8 = self->flags8; + + if (type != mytype) flags8 |= ((AActor*)replacee->Defaults)->flags8; + // Do generic special death actions first bool checked = false; @@ -3119,24 +3124,30 @@ void A_BossDeath(AActor *self) // [RH] These all depend on the presence of level flags now // rather than being hard-coded to specific levels/episodes. - if ((Level->flags & (LEVEL_MAP07SPECIAL| + if (((Level->flags & (LEVEL_MAP07SPECIAL| LEVEL_BRUISERSPECIAL| LEVEL_CYBORGSPECIAL| LEVEL_SPIDERSPECIAL| LEVEL_HEADSPECIAL| LEVEL_MINOTAURSPECIAL| - LEVEL_SORCERER2SPECIAL)) == 0) + LEVEL_SORCERER2SPECIAL)) == 0) && + ((Level->flags3 & (LEVEL3_E1M8SPECIAL | LEVEL3_E2M8SPECIAL | LEVEL3_E3M8SPECIAL | LEVEL3_E4M8SPECIAL | LEVEL3_E4M6SPECIAL)) == 0)) return; if ((Level->i_compatflags & COMPATF_ANYBOSSDEATH) || ( // [GZ] Added for UAC_DEAD - ((Level->flags & LEVEL_MAP07SPECIAL) && (type == NAME_Fatso || type == NAME_Arachnotron)) || + ((Level->flags & LEVEL_MAP07SPECIAL) && (flags8 & (MF8_MAP07BOSS1|MF8_MAP07BOSS2))) || ((Level->flags & LEVEL_BRUISERSPECIAL) && (type == NAME_BaronOfHell)) || ((Level->flags & LEVEL_CYBORGSPECIAL) && (type == NAME_Cyberdemon)) || ((Level->flags & LEVEL_SPIDERSPECIAL) && (type == NAME_SpiderMastermind)) || ((Level->flags & LEVEL_HEADSPECIAL) && (type == NAME_Ironlich)) || ((Level->flags & LEVEL_MINOTAURSPECIAL) && (type == NAME_Minotaur)) || - ((Level->flags & LEVEL_SORCERER2SPECIAL) && (type == NAME_Sorcerer2)) - )) + ((Level->flags & LEVEL_SORCERER2SPECIAL) && (type == NAME_Sorcerer2)) || + ((Level->flags3 & LEVEL3_E1M8SPECIAL) && (flags8 & MF8_E1M8BOSS)) || + ((Level->flags3 & LEVEL3_E2M8SPECIAL) && (flags8 & MF8_E2M8BOSS)) || + ((Level->flags3 & LEVEL3_E3M8SPECIAL) && (flags8 & MF8_E3M8BOSS)) || + ((Level->flags3 & LEVEL3_E4M8SPECIAL) && (flags8 & MF8_E4M8BOSS)) || + ((Level->flags3 & LEVEL3_E4M6SPECIAL) && (flags8 & MF8_E4M6BOSS)) + )) ; else return; @@ -3153,16 +3164,21 @@ void A_BossDeath(AActor *self) } if (Level->flags & LEVEL_MAP07SPECIAL) { + // samereplacement will only be considered if both Fatso and Arachnotron are flagged as MAP07 bosses and the current monster maps to one of them. PClassActor * fatso = PClass::FindActor(NAME_Fatso); PClassActor * arachnotron = PClass::FindActor(NAME_Arachnotron); - bool samereplacement = (type == NAME_Fatso || type == NAME_Arachnotron) && fatso && arachnotron && fatso->GetReplacement(Level) == arachnotron->GetReplacement(Level); + bool samereplacement = (type == NAME_Fatso || type == NAME_Arachnotron) && + fatso && arachnotron && + (GetDefaultByType(fatso)->flags8 & MF8_MAP07BOSS1) && + (GetDefaultByType(arachnotron)->flags8 & MF8_MAP07BOSS2) && + fatso->GetReplacement(Level) == arachnotron->GetReplacement(Level); - if (type == NAME_Fatso || samereplacement) + if ((flags8 & MF8_MAP07BOSS1) || samereplacement) { Level->EV_DoFloor (DFloor::floorLowerToLowest, NULL, 666, 1., 0, -1, 0, false); } - if (type == NAME_Arachnotron || samereplacement) + if ((flags8 & MF8_MAP07BOSS2) || samereplacement) { Level->EV_DoFloor (DFloor::floorRaiseByTexture, NULL, 667, 1., 0, -1, 0, false); } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index bcfced710..802782766 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -328,6 +328,14 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF8, FALLDAMAGE, AActor, flags8), DEFINE_FLAG(MF8, ABSVIEWANGLES, AActor, flags8), DEFINE_FLAG(MF8, ALLOWTHRUBITS, AActor, flags8), + DEFINE_FLAG(MF8, FULLVOLSEE, AActor, flags8), + DEFINE_FLAG(MF8, E1M8BOSS, AActor, flags8), + DEFINE_FLAG(MF8, E2M8BOSS, AActor, flags8), + DEFINE_FLAG(MF8, E3M8BOSS, AActor, flags8), + DEFINE_FLAG(MF8, E4M8BOSS, AActor, flags8), + DEFINE_FLAG(MF8, E4M6BOSS, AActor, flags8), + DEFINE_FLAG(MF8, MAP07BOSS1, AActor, flags8), + DEFINE_FLAG(MF8, MAP07BOSS2, AActor, flags8), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/wadsrc/static/mapinfo/doom1.txt b/wadsrc/static/mapinfo/doom1.txt index c28186c55..8d8be2295 100644 --- a/wadsrc/static/mapinfo/doom1.txt +++ b/wadsrc/static/mapinfo/doom1.txt @@ -149,7 +149,7 @@ map E1M8 lookup "HUSTR_E1M8" par = 30 nointermission nosoundclipping - baronspecial + e1m8special specialaction_lowerfloor music = "$MUSIC_E1M8" needclustertext @@ -264,7 +264,7 @@ map E2M8 lookup "HUSTR_E2M8" par = 30 nointermission nosoundclipping - cyberdemonspecial + e2m8special specialaction_exitlevel music = "$MUSIC_E2M8" needclustertext @@ -379,7 +379,7 @@ map E3M8 lookup "HUSTR_E3M8" par = 30 nointermission nosoundclipping - spidermastermindspecial + e3m8special specialaction_exitlevel music = "$MUSIC_E3M8" needclustertext @@ -468,7 +468,7 @@ map E4M6 lookup "HUSTR_E4M6" sky1 = "SKY4" cluster = 4 par = 390 - cyberdemonspecial + e4m6special specialaction_opendoor music = "$MUSIC_E2M4" } @@ -496,7 +496,7 @@ map E4M8 lookup "HUSTR_E4M8" par = 360 nointermission nosoundclipping - spidermastermindspecial + e4m8special specialaction_lowerfloor music = "$MUSIC_E2M5" needclustertext diff --git a/wadsrc/static/zscript/actors/doom/arachnotron.zs b/wadsrc/static/zscript/actors/doom/arachnotron.zs index 56ba94831..862f2bc60 100644 --- a/wadsrc/static/zscript/actors/doom/arachnotron.zs +++ b/wadsrc/static/zscript/actors/doom/arachnotron.zs @@ -16,6 +16,7 @@ class Arachnotron : Actor Monster; +FLOORCLIP +BOSSDEATH + +MAP07BOSS2 SeeSound "baby/sight"; PainSound "baby/pain"; DeathSound "baby/death"; diff --git a/wadsrc/static/zscript/actors/doom/bruiser.zs b/wadsrc/static/zscript/actors/doom/bruiser.zs index a34c91160..1bc1a20ed 100644 --- a/wadsrc/static/zscript/actors/doom/bruiser.zs +++ b/wadsrc/static/zscript/actors/doom/bruiser.zs @@ -16,6 +16,7 @@ class BaronOfHell : Actor Monster; +FLOORCLIP +BOSSDEATH + +E1M8BOSS SeeSound "baron/sight"; PainSound "baron/pain"; DeathSound "baron/death"; diff --git a/wadsrc/static/zscript/actors/doom/cyberdemon.zs b/wadsrc/static/zscript/actors/doom/cyberdemon.zs index 4817207fc..d795fc31a 100644 --- a/wadsrc/static/zscript/actors/doom/cyberdemon.zs +++ b/wadsrc/static/zscript/actors/doom/cyberdemon.zs @@ -22,6 +22,8 @@ class Cyberdemon : Actor +NORADIUSDMG +DONTMORPH +BOSSDEATH + +E2M8BOSS + +E4M6BOSS SeeSound "cyber/sight"; PainSound "cyber/pain"; DeathSound "cyber/death"; diff --git a/wadsrc/static/zscript/actors/doom/fatso.zs b/wadsrc/static/zscript/actors/doom/fatso.zs index 82ec4623b..493456dd8 100644 --- a/wadsrc/static/zscript/actors/doom/fatso.zs +++ b/wadsrc/static/zscript/actors/doom/fatso.zs @@ -16,6 +16,7 @@ class Fatso : Actor Monster; +FLOORCLIP +BOSSDEATH + +MAP07BOSS1 SeeSound "fatso/sight"; PainSound "fatso/pain"; DeathSound "fatso/death"; diff --git a/wadsrc/static/zscript/actors/doom/spidermaster.zs b/wadsrc/static/zscript/actors/doom/spidermaster.zs index c8b6eb091..3ad0b8846 100644 --- a/wadsrc/static/zscript/actors/doom/spidermaster.zs +++ b/wadsrc/static/zscript/actors/doom/spidermaster.zs @@ -20,6 +20,8 @@ class SpiderMastermind : Actor +NORADIUSDMG +DONTMORPH +BOSSDEATH + +E3M8BOSS + +E4M8BOSS SeeSound "spider/sight"; AttackSound "spider/attack"; PainSound "spider/pain";