- MBF21: implemented thing flags.

This commit is contained in:
Christoph Oelckers 2021-06-29 21:08:58 +02:00
parent 0bb5ec0d22
commit e2e8ec8b3e
12 changed files with 152 additions and 16 deletions

View file

@ -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;

View file

@ -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 },

View file

@ -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,
};

View file

@ -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 ---

View file

@ -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);
}

View file

@ -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),

View file

@ -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

View file

@ -16,6 +16,7 @@ class Arachnotron : Actor
Monster;
+FLOORCLIP
+BOSSDEATH
+MAP07BOSS2
SeeSound "baby/sight";
PainSound "baby/pain";
DeathSound "baby/death";

View file

@ -16,6 +16,7 @@ class BaronOfHell : Actor
Monster;
+FLOORCLIP
+BOSSDEATH
+E1M8BOSS
SeeSound "baron/sight";
PainSound "baron/pain";
DeathSound "baron/death";

View file

@ -22,6 +22,8 @@ class Cyberdemon : Actor
+NORADIUSDMG
+DONTMORPH
+BOSSDEATH
+E2M8BOSS
+E4M6BOSS
SeeSound "cyber/sight";
PainSound "cyber/pain";
DeathSound "cyber/death";

View file

@ -16,6 +16,7 @@ class Fatso : Actor
Monster;
+FLOORCLIP
+BOSSDEATH
+MAP07BOSS1
SeeSound "fatso/sight";
PainSound "fatso/pain";
DeathSound "fatso/death";

View file

@ -20,6 +20,8 @@ class SpiderMastermind : Actor
+NORADIUSDMG
+DONTMORPH
+BOSSDEATH
+E3M8BOSS
+E4M8BOSS
SeeSound "spider/sight";
AttackSound "spider/attack";
PainSound "spider/pain";