diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index f87c5ca20..8068b1cc0 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -32,6 +32,7 @@ #include "vm.h" #include "r_defs.h" #include "g_levellocals.h" +#include "gamedata/g_mapinfo.h" #include "s_sound.h" #include "p_local.h" #include "v_font.h" @@ -2503,12 +2504,150 @@ DEFINE_ACTION_FUNCTION(_Console, MidPrint) return 0; } +//========================================================================== +// +// +// +//========================================================================== + +static int isValid( level_info_t *info ) +{ + return info->isValid(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, isValid, isValid) +{ + PARAM_SELF_STRUCT_PROLOGUE(level_info_t); + ACTION_RETURN_BOOL(isValid(self)); +} + +static void LookupLevelName( level_info_t *info, FString *result ) +{ + *result = info->LookupLevelName(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, LookupLevelName, LookupLevelName) +{ + PARAM_SELF_STRUCT_PROLOGUE(level_info_t); + FString rets; + LookupLevelName(self,&rets); + ACTION_RETURN_STRING(rets); +} + +static int GetLevelInfoCount() +{ + return wadlevelinfos.Size(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, GetLevelInfoCount, GetLevelInfoCount) +{ + PARAM_PROLOGUE; + ACTION_RETURN_INT(GetLevelInfoCount()); +} + +static level_info_t* GetLevelInfo( unsigned int index ) +{ + if ( index >= wadlevelinfos.Size() ) + return nullptr; + return &wadlevelinfos[index]; +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, GetLevelInfo, GetLevelInfo) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + ACTION_RETURN_POINTER(GetLevelInfo(index)); +} + +static level_info_t* ZFindLevelInfo( const FString &mapname ) +{ + return FindLevelInfo(mapname.GetChars()); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, FindLevelInfo, ZFindLevelInfo) +{ + PARAM_PROLOGUE; + PARAM_STRING(mapname); + ACTION_RETURN_POINTER(ZFindLevelInfo(mapname)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, FindLevelByNum, FindLevelByNum) +{ + PARAM_PROLOGUE; + PARAM_INT(num); + ACTION_RETURN_POINTER(FindLevelByNum(num)); +} + +static int MapExists( const FString &mapname ) +{ + return P_CheckMapData(mapname.GetChars()); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_LevelInfo, MapExists, MapExists) +{ + PARAM_PROLOGUE; + PARAM_STRING(mapname); + ACTION_RETURN_BOOL(MapExists(mapname)); +} + +DEFINE_ACTION_FUNCTION(_LevelInfo, MapChecksum) +{ + PARAM_PROLOGUE; + PARAM_STRING(mapname); + char md5string[33] = ""; + MapData *map = P_OpenMapData(mapname.GetChars(), true); + if (map != nullptr) + { + uint8_t cksum[16]; + map->GetChecksum(cksum); + for (int j = 0; j < 16; ++j) + { + sprintf(md5string + j * 2, "%02x", cksum[j]); + } + delete map; + } + ACTION_RETURN_STRING((const char *)md5string); +} //========================================================================== // // // //========================================================================== +DEFINE_FIELD_X(LevelInfo, level_info_t, levelnum) +DEFINE_FIELD_X(LevelInfo, level_info_t, MapName) +DEFINE_FIELD_X(LevelInfo, level_info_t, NextMap) +DEFINE_FIELD_X(LevelInfo, level_info_t, NextSecretMap) +DEFINE_FIELD_X(LevelInfo, level_info_t, SkyPic1) +DEFINE_FIELD_X(LevelInfo, level_info_t, SkyPic2) +DEFINE_FIELD_X(LevelInfo, level_info_t, F1Pic) +DEFINE_FIELD_X(LevelInfo, level_info_t, cluster) +DEFINE_FIELD_X(LevelInfo, level_info_t, partime) +DEFINE_FIELD_X(LevelInfo, level_info_t, sucktime) +DEFINE_FIELD_X(LevelInfo, level_info_t, flags) +DEFINE_FIELD_X(LevelInfo, level_info_t, flags2) +DEFINE_FIELD_X(LevelInfo, level_info_t, flags3) +DEFINE_FIELD_X(LevelInfo, level_info_t, Music) +DEFINE_FIELD_X(LevelInfo, level_info_t, LevelName) +DEFINE_FIELD_X(LevelInfo, level_info_t, AuthorName) +DEFINE_FIELD_X(LevelInfo, level_info_t, musicorder) +DEFINE_FIELD_X(LevelInfo, level_info_t, skyspeed1) +DEFINE_FIELD_X(LevelInfo, level_info_t, skyspeed2) +DEFINE_FIELD_X(LevelInfo, level_info_t, cdtrack) +DEFINE_FIELD_X(LevelInfo, level_info_t, gravity) +DEFINE_FIELD_X(LevelInfo, level_info_t, aircontrol) +DEFINE_FIELD_X(LevelInfo, level_info_t, airsupply) +DEFINE_FIELD_X(LevelInfo, level_info_t, compatflags) +DEFINE_FIELD_X(LevelInfo, level_info_t, compatflags2) +DEFINE_FIELD_X(LevelInfo, level_info_t, deathsequence) +DEFINE_FIELD_X(LevelInfo, level_info_t, fogdensity) +DEFINE_FIELD_X(LevelInfo, level_info_t, outsidefogdensity) +DEFINE_FIELD_X(LevelInfo, level_info_t, skyfog) +DEFINE_FIELD_X(LevelInfo, level_info_t, pixelstretch) +DEFINE_FIELD_X(LevelInfo, level_info_t, RedirectType) +DEFINE_FIELD_X(LevelInfo, level_info_t, RedirectMapName) +DEFINE_FIELD_X(LevelInfo, level_info_t, teamdamage) + DEFINE_GLOBAL_NAMED(currentVMLevel, level) DEFINE_FIELD(FLevelLocals, sectors) DEFINE_FIELD(FLevelLocals, lines) @@ -2557,6 +2696,7 @@ DEFINE_FIELD(FLevelLocals, deathsequence) DEFINE_FIELD_BIT(FLevelLocals, frozenstate, frozen, 1) // still needed for backwards compatibility. DEFINE_FIELD_NAMED(FLevelLocals, i_compatflags, compatflags) DEFINE_FIELD_NAMED(FLevelLocals, i_compatflags2, compatflags2) +DEFINE_FIELD(FLevelLocals, info); DEFINE_FIELD_BIT(FLevelLocals, flags, noinventorybar, LEVEL_NOINVENTORYBAR) DEFINE_FIELD_BIT(FLevelLocals, flags, monsterstelefrag, LEVEL_MONSTERSTELEFRAG) diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 1ef1a7bb7..490cfc2cb 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1227,6 +1227,113 @@ enum EChangeLevelFlags CHANGELEVEL_PRERAISEWEAPON = 64, }; +enum ELevelFlags +{ + LEVEL_NOINTERMISSION = 0x00000001, + LEVEL_NOINVENTORYBAR = 0x00000002, // This effects Doom only, since it's the only one without a standard inventory bar. + LEVEL_DOUBLESKY = 0x00000004, + LEVEL_HASFADETABLE = 0x00000008, // Level uses Hexen's fadetable mapinfo to get fog + + LEVEL_MAP07SPECIAL = 0x00000010, + LEVEL_BRUISERSPECIAL = 0x00000020, + LEVEL_CYBORGSPECIAL = 0x00000040, + LEVEL_SPIDERSPECIAL = 0x00000080, + + LEVEL_SPECLOWERFLOOR = 0x00000100, + LEVEL_SPECOPENDOOR = 0x00000200, + LEVEL_SPECLOWERFLOORTOHIGHEST=0x00000300, + LEVEL_SPECACTIONSMASK = 0x00000300, + + LEVEL_MONSTERSTELEFRAG = 0x00000400, + LEVEL_ACTOWNSPECIAL = 0x00000800, + LEVEL_SNDSEQTOTALCTRL = 0x00001000, + LEVEL_FORCETILEDSKY = 0x00002000, + + LEVEL_CROUCH_NO = 0x00004000, + LEVEL_JUMP_NO = 0x00008000, + LEVEL_FREELOOK_NO = 0x00010000, + LEVEL_FREELOOK_YES = 0x00020000, + + // The absence of both of the following bits means that this level does not + // use falling damage (though damage can be forced with dmflags,. + LEVEL_FALLDMG_ZD = 0x00040000, // Level uses ZDoom's falling damage + LEVEL_FALLDMG_HX = 0x00080000, // Level uses Hexen's falling damage + + LEVEL_HEADSPECIAL = 0x00100000, // Heretic episode 1/4 + LEVEL_MINOTAURSPECIAL = 0x00200000, // Heretic episode 2/5 + LEVEL_SORCERER2SPECIAL = 0x00400000, // Heretic episode 3 + LEVEL_SPECKILLMONSTERS = 0x00800000, + + LEVEL_STARTLIGHTNING = 0x01000000, // Automatically start lightning + LEVEL_FILTERSTARTS = 0x02000000, // Apply mapthing filtering to player starts + LEVEL_LOOKUPLEVELNAME = 0x04000000, // Level name is the name of a language string + LEVEL_USEPLAYERSTARTZ = 0x08000000, // Use the Z position of player starts + + LEVEL_SWAPSKIES = 0x10000000, // Used by lightning + LEVEL_NOALLIES = 0x20000000, // i.e. Inside Strife's front base + LEVEL_CHANGEMAPCHEAT = 0x40000000, // Don't display cluster messages + LEVEL_VISITED = 0x80000000, // Used for intermission map + + // The flags uint64_t is now split into 2 DWORDs + LEVEL2_RANDOMPLAYERSTARTS = 0x00000001, // Select single player starts randomnly (no voodoo dolls) + LEVEL2_ALLMAP = 0x00000002, // The player picked up a map on this level + + LEVEL2_LAXMONSTERACTIVATION = 0x00000004, // Monsters can open doors depending on the door speed + LEVEL2_LAXACTIVATIONMAPINFO = 0x00000008, // LEVEL_LAXMONSTERACTIVATION is not a default. + + LEVEL2_MISSILESACTIVATEIMPACT=0x00000010, // Missiles are the activators of SPAC_IMPACT events, not their shooters + LEVEL2_NEEDCLUSTERTEXT = 0x00000020, // A map with this flag needs to retain its cluster intermission texts when being redefined in UMAPINFO + + LEVEL2_KEEPFULLINVENTORY = 0x00000040, // doesn't reduce the amount of inventory items to 1 + + LEVEL2_PRERAISEWEAPON = 0x00000080, // players should spawn with their weapons fully raised (but not when respawning it multiplayer) + LEVEL2_MONSTERFALLINGDAMAGE = 0x00000100, + LEVEL2_CLIPMIDTEX = 0x00000200, + LEVEL2_WRAPMIDTEX = 0x00000400, + + LEVEL2_CHECKSWITCHRANGE = 0x00000800, + + LEVEL2_PAUSE_MUSIC_IN_MENUS = 0x00001000, + LEVEL2_TOTALINFIGHTING = 0x00002000, + LEVEL2_NOINFIGHTING = 0x00004000, + + LEVEL2_NOMONSTERS = 0x00008000, + LEVEL2_INFINITE_FLIGHT = 0x00010000, + + LEVEL2_ALLOWRESPAWN = 0x00020000, + + LEVEL2_FORCETEAMPLAYON = 0x00040000, + LEVEL2_FORCETEAMPLAYOFF = 0x00080000, + + LEVEL2_CONV_SINGLE_UNFREEZE = 0x00100000, + LEVEL2_NOCLUSTERTEXT = 0x00200000, // ignore intermission texts fro clusters. This gets set when UMAPINFO is used to redefine its properties. + LEVEL2_DUMMYSWITCHES = 0x00400000, + LEVEL2_HEXENHACK = 0x00800000, // Level was defined in a Hexen style MAPINFO + + LEVEL2_SMOOTHLIGHTING = 0x01000000, // Level uses the smooth lighting feature. + LEVEL2_POLYGRIND = 0x02000000, // Polyobjects grind corpses to gibs. + LEVEL2_RESETINVENTORY = 0x04000000, // Resets player inventory when starting this level (unless in a hub) + LEVEL2_RESETHEALTH = 0x08000000, // Resets player health when starting this level (unless in a hub) + + LEVEL2_NOSTATISTICS = 0x10000000, // This level should not have statistics collected + LEVEL2_ENDGAME = 0x20000000, // This is an epilogue level that cannot be quit. + LEVEL2_NOAUTOSAVEHINT = 0x40000000, // tell the game that an autosave for this level does not need to be kept + LEVEL2_FORGETSTATE = 0x80000000, // forget this map's state in a hub + + // More flags! + LEVEL3_FORCEFAKECONTRAST = 0x00000001, // forces fake contrast even with fog enabled + LEVEL3_REMOVEITEMS = 0x00000002, // kills all INVBAR items on map change. + LEVEL3_ATTENUATE = 0x00000004, // attenuate lights? + LEVEL3_NOLIGHTFADE = 0x00000008, // no light fading to black. + LEVEL3_NOCOLOREDSPRITELIGHTING = 0x00000010, // draw sprites only with color-less light + LEVEL3_EXITNORMALUSED = 0x00000020, + LEVEL3_EXITSECRETUSED = 0x00000040, + LEVEL3_FORCEWORLDPANNING = 0x00000080, // Forces the world panning flag for all textures, even those without it explicitly set. + LEVEL3_HIDEAUTHORNAME = 0x00000100, + LEVEL3_PROPERMONSTERFALLINGDAMAGE = 0x00000200, // Properly apply falling damage to the monsters + LEVEL3_SKYBOXAO = 0x00000400, // Apply SSAO to sector skies +}; + // [RH] Compatibility flags. enum ECompatFlags { diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index aec68a3e9..f81596199 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -320,6 +320,53 @@ struct DropItem native native readonly int Amount; } +struct LevelInfo native +{ + native readonly int levelnum; + native readonly String MapName; + native readonly String NextMap; + native readonly String NextSecretMap; + native readonly String SkyPic1; + native readonly String SkyPic2; + native readonly String F1Pic; + native readonly int cluster; + native readonly int partime; + native readonly int sucktime; + native readonly int flags; + native readonly int flags2; + native readonly int flags3; + native readonly String Music; + native readonly String LevelName; + native readonly String AuthorName; + native readonly int musicorder; + native readonly float skyspeed1; + native readonly float skyspeed2; + native readonly int cdtrack; + native readonly double gravity; + native readonly double aircontrol; + native readonly int airsupply; + native readonly int compatflags; + native readonly int compatflags2; + native readonly name deathsequence; + native readonly int fogdensity; + native readonly int outsidefogdensity; + native readonly int skyfog; + native readonly float pixelstretch; + native readonly name RedirectType; + native readonly String RedirectMapName; + native readonly double teamdamage; + + native bool isValid() const; + native String LookupLevelName() const; + + native static int GetLevelInfoCount(); + native static LevelInfo GetLevelInfo(int index); + native static LevelInfo FindLevelInfo(String mapname); + native static LevelInfo FindLevelByNum(int num); + native static bool MapExists(String mapname); + native static String MapChecksum(String mapname); +} + struct LevelLocals native { enum EUDMF @@ -396,7 +443,7 @@ struct LevelLocals native native name deathsequence; native readonly int compatflags; native readonly int compatflags2; -// level_info_t *info cannot be done yet. + native readonly LevelInfo info; native String GetUDMFString(int type, int index, Name key); native int GetUDMFInt(int type, int index, Name key);