// 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 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 ( IsUltDoom2() ) return true; } return false; } // detect ultimate doom 2 static bool IsUltDoom2() { return CheckMD5List("ultdoom2.lst"); } // detect eviternity (naive method) static bool IsEviternity() { foreach ( cls:AllActorClasses ) { if ( cls.GetClassName() != "Archangelus" ) continue; return true; } return false; } // detect doom vacation static bool InDoomVacation() { // cheap, but hey, it should work if ( Wads.FindLump("VACABEX") != -1 ) { // just to make sure foreach ( cls:AllActorClasses ) { if ( cls.GetClassName() != "Babe" ) continue; return true; } } 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 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); Actor a; while ( a = ai.Next() ) { 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; } }