swwmgz_m/zscript/utility/swwm_utility_compat.zsc
Marisa the Magician 2aa0ea4680 More work towards Legacy of Rust support (with caveats).
As of this commit, do not consider the experience when playing that new
expansion to be complete. I've only partially written some of the mission texts
and rudimentarily enhanced some boss fights.

Currently there is one major limitation in that the intermission texts cannot
be replaced, as they're hardcoded inside the UMAPINFO. I don't know if I can
work around that.
2025-08-20 16:47:24 +02:00

154 lines
4 KiB
Text

// compat / detection code
extend Class SWWMUtility
{
// try to be as thorough as possible in checking if DEHACKED has altered this actor
static bool CheckDehackery( Class<Actor> cls )
{
let def = GetDefaultByType(cls);
for ( State s=def.SpawnState; s; s=s.NextState )
{
if ( s.bDEHACKED ) return true;
// keep checking until we hit a loop, just in case
if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break;
}
for ( State s=def.SeeState; s; s=s.NextState )
{
if ( s.bDEHACKED ) return true;
// keep checking until we hit a loop, just in case
if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break;
}
for ( State s=def.MissileState; s; s=s.NextState )
{
if ( s.bDEHACKED ) return true;
// keep checking until we hit a loop, just in case
if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break;
}
for ( State s=def.MeleeState; s; s=s.NextState )
{
if ( s.bDEHACKED ) return true;
// keep checking until we hit a loop, just in case
if ( s.NextState && (s.DistanceTo(s.NextState) <= 0) ) break;
}
return false;
}
// shorthand for some of these checks (these are generally used by the mission briefing system)
static bool IsKnownMap()
{
if ( (gameinfo.gametype&GAME_DOOM) && (IsKnownCustomWAD() || CheckMD5List("vanilladoom.lst")) )
return true;
if ( (gameinfo.gametype&GAME_HERETIC) && CheckMD5List("vanillaheretic.lst") )
return true;
if ( (gameinfo.gametype&GAME_HEXEN) && CheckMD5List("vanillahexen.lst") )
return true;
return false;
}
// to be filled
static bool IsKnownCustomWAD()
{
if ( gameinfo.gametype&GAME_DOOM )
{
if ( IsEviternity() ) return true;
if ( IsEviternityTwo() ) return true;
if ( IsUltDoom2() ) return true;
if ( IsLegacyOfRust() ) return true;
}
return false;
}
static bool IsLegacyOfRust()
{
return CheckMD5List("id1.lst");
}
// detect ultimate doom 2
static bool IsUltDoom2()
{
return CheckMD5List("ultdoom2.lst");
}
// detect eviternity (naive method)
static bool IsEviternity()
{
return FindClass('Archangelus','Actor');
}
// detect eviternity 2 (naive method)
static bool IsEviternityTwo()
{
return FindClass('The_Origin_Phase_1','Actor');
}
// detect doom vacation
static bool InDoomVacation()
{
// cheap, but hey, it should work
if ( Wads.FindLump("VACABEX") != -1 )
{
// just to make sure
return FindClass('Babe','Actor');
}
return false;
}
static bool IsDeathkings()
{
if ( (gameinfo.gametype&GAME_HEXEN) && LevelInfo.MapExists("MAP41") )
{
let inf = LevelInfo.FindLevelInfo("MAP41");
if ( inf.cluster == 1 ) return true;
}
return false;
}
// detect vanilla maps (across all IWAD versions)
static bool CheckMD5List( String fname )
{
String csum = level.GetChecksum();
let lmp = Wads.CheckNumForFullName(fname);
if ( lmp == -1 ) return false;
String dat = Wads.ReadLump(lmp);
// Windows pls
dat.Replace("\r","");
Array<String> list;
list.Clear();
dat.Split(list,"\n");
foreach ( l:list )
{
if ( (l.Length() == 0) || (l.Left(1) == "#") || (l.Left(1) == "") )
continue;
if ( csum ~== l )
return true;
}
return false;
}
// WHACK
static play void EndLevelDie( Actor victim )
{
victim.DamageMobj(null,null,victim.Health,'EndLevel',DMG_FORCED|DMG_THRUSTLESS);
}
// for Equinox
static play void SpawnVanillaBossBrain( int tid )
{
let ai = Level.CreateActorIterator(tid);
foreach ( a:ai )
{
let bb = a.Spawn('BossBrain',a.pos,NO_REPLACE);
bb.angle = a.angle;
}
}
// checks if we're playing in doom 1
// this is used so we can sometimes replace the shotgun with a SSG slot weapon
static bool IsDoomOne()
{
if ( !(gameinfo.GameType&GAME_DOOM) ) return false;
// is the map in ExMx format? Then it's likely we're playing a doom 1 map
if ( (level.mapname.Length() >= 4) && (level.mapname.Mid(0,1) == "E") && (level.mapname.ByteAt(1) >= 0x30) && (level.mapname.ByteAt(1) < 0x40) && (level.mapname.Mid(2,1) == "M") && (level.mapname.ByteAt(3) >= 0x30) && (level.mapname.ByteAt(3) < 0x40) )
return true;
return false;
}
}