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.
154 lines
4 KiB
Text
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;
|
|
}
|
|
}
|