diff --git a/resources/assets/zscript/lib/_lib.zs b/resources/assets/zscript/lib/_lib.zs index 9a8a378..aa320e6 100644 --- a/resources/assets/zscript/lib/_lib.zs +++ b/resources/assets/zscript/lib/_lib.zs @@ -2,7 +2,8 @@ #include "zscript/lib/ZJSON/Include.zs" #include "zscript/lib/ZForms/Include.ZSC" #include "zscript/lib/Gutamatics/include.zsc" -#include "zscript/lib/particles.zs" #include "zscript/lib/filejson.zs" +#include "zscript/lib/gameinforeader.zs" #include "zscript/lib/lemonutil.zs" +#include "zscript/lib/particles.zs" #include "zscript/lib/xgametranslation.zs" \ No newline at end of file diff --git a/resources/assets/zscript/lib/gameinforeader.zs b/resources/assets/zscript/lib/gameinforeader.zs new file mode 100644 index 0000000..c3701d5 --- /dev/null +++ b/resources/assets/zscript/lib/gameinforeader.zs @@ -0,0 +1,186 @@ + +/* + * + * GameInfoReader + * Parses MapInfo lumps for skill and episode information + * + */ + + + +class GameInfoReader { + Array skills; + Array episodes; + + void Find() { + for (int i = 0; i < Wads.GetNumLumps(); i++) { + //Wads.CheckNumForName(i) + String name = Wads.GetLumpName(i); + String fullname = Wads.GetLumpFullName(i); + if (name.MakeLower().IndexOf("mapinfo") != -1 || fullname.MakeLower().IndexOf("mapinfo.") != -1) { + Console.printf("Lump %d %d: %s %s", i, Wads.GetLumpNamespace(i), name, fullname); + String info = Wads.ReadLump(i); + String skInfo = Wads.ReadLump(i); + self.ParseEpisodeInfo(info); + self.ParseSkillInfo(skInfo); + } + } + } + + void ParseSkillInfo(String info) { + int CLEARSKILLS_SIZE = "clearskills".Length(); + int SKILL_SIZE = "skill".Length(); + + int pos = 0; + String minfo = info; + while (minfo.IndexOf("clearskills") != -1 || minfo.IndexOf("skill") != -1) { + pos++; + // valid + if (minfo.IndexOf("clearskills") != -1) { + int nextPos = info.IndexOf("clearskills"); + console.printf("clearskills"); + self.skills.Clear(); + + minfo = minfo.Mid(nextPos + CLEARSKILLS_SIZE); + } else if (minfo.IndexOf("skill") != -1) { + int idxSkill = minfo.IndexOf("skill"); + minfo = minfo.Mid(idxSkill); + int idxBraceOpen = minfo.IndexOf("{"); + int idxBraceClose = minfo.IndexOf("}"); + + // Sanity check if the skill is defined incorrectly + String skillName; + if (idxSkill != -1 && idxBraceOpen != -1 && idxBraceClose != -1) { + SkillInfo skInfo = new("SkillInfo"); + + String between = minfo.Mid(idxBraceOpen, idxBraceClose); + + //console.printf("info %s", between); + + Array split; + between.split(split, "\n"); + for (int i = 0; i < split.Size(); i++) { + String line = split[i]; + + int idxQuoteOpen = line.IndexOf('"'); + String value = line.Mid(idxQuoteOpen + 1); + int idxQuoteClosed = value.IndexOf('"'); + value = value.Mid(0, idxQuoteClosed); + + if (line.MakeLower().IndexOf("playerclassname") != -1) { + String className = value; + + Array splitLine; + line.split(splitLine, ","); + + String section = splitLine[splitLine.Size() - 1]; + idxQuoteOpen = section.IndexOf('"'); + String classSkill = section.Mid(idxQuoteOpen + 1); + idxQuoteClosed = classSkill.IndexOf('"'); + classSkill = classSkill.Mid(0, idxQuoteClosed); + console.printf("classSkill %s", classSkill); + + skInfo.classes.push(className); + skInfo.names.push(classSkill); + console.printf("class %s, skill %s", className, classSkill); + } else if (line.MakeLower().IndexOf("name") != -1) { + skInfo.name = value; + console.printf("skill %s", value); + } + + } + + self.skills.Push(skInfo); + + minfo = minfo.Mid(idxBraceClose + 1); + } + } + } + } + + void ParseEpisodeInfo(String info) { + int CLEAREPISODES_SIZE = "clearepisodes".Length(); + int EPISODE_SIZE = "episode".Length(); + + int pos = 0; + String minfo = info; + while (minfo.IndexOf("clearepisodes") != -1 || minfo.IndexOf("episode") != -1) { + pos++; + // valid + if (minfo.IndexOf("clearepisodes") != -1) { + int nextPos = info.IndexOf("clearepisodes"); + console.printf("clearepisodes"); + self.episodes.Clear(); + + minfo = minfo.Mid(nextPos + CLEAREPISODES_SIZE); + } else if (minfo.IndexOf("episode") != -1) { + int idxEpisode = minfo.IndexOf("episode"); + minfo = minfo.Mid(idxEpisode); + int idxBraceOpen = minfo.IndexOf("{"); + int idxBraceClose = minfo.IndexOf("}"); + + // Sanity check if the episode is defined incorrectly + String episodeName; + if (idxEpisode != -1 && idxBraceOpen != -1 && idxBraceClose != -1) { + EpisodeInfo epInfo = new("EpisodeInfo"); + + String between = minfo.Mid(idxBraceOpen, idxBraceClose); + + Array split; + between.split(split, "\n"); + for (int i = 0; i < split.Size(); i++) { + String line = split[i]; + + int idxQuoteOpen = line.IndexOf('"'); + String value = line.Mid(idxQuoteOpen + 1); + int idxQuoteClosed = value.IndexOf('"'); + + value = value.Mid(0, idxQuoteClosed); + if (line.IndexOf("name") != -1) { + epInfo.name = value; + } else if (line.IndexOf("description") != -1) { + epInfo.description = value; + } else if (line.IndexOf("gametype") != -1) { + epInfo.gametype = value; + } else if (line.IndexOf("development")) { + epInfo.development = true; + } + } + + self.episodes.Push(epInfo); + + minfo = minfo.Mid(idxBraceClose + 1); + } + } + } + } +} + +class SkillInfo { + String name; // default + Array classes; // keys for list + Array names; + + String Get(String playerClass) { + let p = (class)(playerClass); + String v; + if (p != null) { + v = PlayerPawn.GetPrintableDisplayName(playerClass); + v = v.MakeLower(); + } + int idx = self.classes.Find(v); + if (idx == self.classes.Size()) { + return name; + } else { + return self.names[idx]; + } + } +} + +class EpisodeInfo { + String name; + String gametype; + String description; + bool extended; + bool development; +} \ No newline at end of file diff --git a/resources/assets/zscript/lib/lemonutil.zs b/resources/assets/zscript/lib/lemonutil.zs index 1a01e54..bd9fe6f 100644 --- a/resources/assets/zscript/lib/lemonutil.zs +++ b/resources/assets/zscript/lib/lemonutil.zs @@ -35,6 +35,24 @@ class LemonUtil { return classes[id]; } + static void LaunchMap(String mapId, int skill) { + LemonUtil.CVAR_SetString("hxdd_map_select", String.format("%s,%d", mapId, skill)); + } + + static bool TryOpenMapByName() { + String mapOverride = LemonUtil.CVAR_GetString("hxdd_map_select", ""); + if (mapOverride.IndexOf(",") != -1) { + LemonUtil.CVAR_Reset("hxdd_map_select"); + //LemonUtil.CVAR_SetString("hxdd_map_select", "111"); + Array selected; + mapOverride.Split(selected, ","); + Console.printf("Map: %s, Skill: %s", selected[0], selected[1]); + LevelLocals.ChangeLevel(selected[0], 0, CHANGELEVEL_NOINTERMISSION|CHANGELEVEL_RESETINVENTORY|CHANGELEVEL_RESETHEALTH|CHANGELEVEL_CHANGESKILL, selected[1].ToInt()); + return true; + } + return false; + } + static Class GetPlayerClass() { // Hardcoded for single player atm PlayerInfo p = players[0]; @@ -157,6 +175,12 @@ class LemonUtil { static void CVAR_SetColor(string name, string value, PlayerInfo player = null) { CVAR_SetString(name, value, player); } + static void CVAR_Reset(string name, PlayerInfo player = null) { + cvar cv = GetCVAR(name, player); + if (cv) { + cv.ResetToDefault(); + } + } // General Math static vector3 RandomVector3(double x, double y, double z) { return (frandom(0.0-x,x), frandom(0.0-y,y), frandom(0.0-z,z)); diff --git a/resources/assets/zscript/menu/newgame.zs b/resources/assets/zscript/menu/newgame.zs index 4232652..537f683 100644 --- a/resources/assets/zscript/menu/newgame.zs +++ b/resources/assets/zscript/menu/newgame.zs @@ -40,8 +40,10 @@ class ZFPreGameSetupHandler : HXDD_ZF_Handler { LemonUtil.CVAR_SetInt("hxdd_waterstyle", menu.selectedTextureStyleWater); LemonUtil.CVAR_SetInt("hxdd_sludgestyle", menu.selectedTextureStyleSludge); LemonUtil.CVAR_SetInt("hxdd_icestyle", menu.selectedTextureStyleIce); - Console.printf("Episode #%d", menu.selectedEpisode); + + LemonUtil.LaunchMap("MAP47", menu.selectedSkill); Menu.StartGameDirect(true, false, menu.selectedClass, menu.selectedEpisode, menu.selectedSkill); + //LevelLocals.ChangeLevel("MAP02", 0, CHANGELEVEL_NOINTERMISSION|CHANGELEVEL_RESETINVENTORY|CHANGELEVEL_RESETHEALTH|CHANGELEVEL_CHANGESKILL, menu.selectedSkill); // NEEDS TITLEMAP? } } } @@ -255,6 +257,8 @@ class ZFGameOptions ui { W_KeyStatue headerStatueLeft; W_KeyStatue headerStatueRight; + GameInfoReader gameinfo; + Array listClassDifficulty; void CreateDifficultyLists() { @@ -452,14 +456,14 @@ class ZFGameOptions ui { cmdHandler.optMenu = self; HXDD_ZF_DropdownItems listEpisodes = new("HXDD_ZF_DropdownItems"); - listEpisodes.items.push("$MNU_COTD"); - listEpisodes.items.push("$MNU_HELLSMAW"); - listEpisodes.items.push("$MNU_DOME"); - listEpisodes.items.push("$MNU_OSSUARY"); - listEpisodes.items.push("$MNU_DEMESNE"); - listEpisodes.items.push("$MNU_FATEPTH"); - listEpisodes.items.push("$MNU_HEXEN"); - listEpisodes.items.push("$MNU_HEXDD"); + gameinfo = new("GameInfoReader"); + gameinfo.Find(); + bool isdev = LemonUtil.CVAR_GetBool("hxdd_isdev_environment", false); + for (let i = 0; i < gameinfo.episodes.Size(); i++) { + if (!gameinfo.episodes[i].development || (gameinfo.episodes[i].development && isdev)) { + listEpisodes.items.push(gameinfo.episodes[i].name); + } + } if (LemonUtil.CVAR_GetBool("hxdd_isdev_environment", false)) { listEpisodes.items.push("Heretic: Modder Test Map"); listEpisodes.items.push("Hexen: Modder Test Map"); @@ -467,8 +471,12 @@ class ZFGameOptions ui { DropDownCombo ddl_Episodes = new ("DropDownCombo"); ddl_Episodes.Create(optionArea, (0, 25), (optionArea.GetWidth() - 32, 50), Stringtable.Localize("$MNU_HEADER_EPISODE"), listEpisodes, parent.selectedEpisode, "episode", cmdHandler); + HXDD_ZF_DropdownItems skList = new("HXDD_ZF_DropdownItems"); + for (int i = 0; i < gameinfo.skills.Size(); i++) { + skList.items.push(gameinfo.skills[i].Get(parent.selectedClass)); + } self.ddl_Difficulty = new ("DropDownCombo"); - self.ddl_Difficulty.Create(optionArea, (0, 25 + 75), (optionArea.GetWidth() - 32, 50), Stringtable.Localize("$MNU_HEADER_SKILLSELECTION"), listClassDifficulty[0], parent.selectedSkill, "skill", cmdHandler); + self.ddl_Difficulty.Create(optionArea, (0, 25 + 75), (optionArea.GetWidth() - 32, 50), Stringtable.Localize("$MNU_HEADER_SKILLSELECTION"), skList, parent.selectedSkill, "skill", cmdHandler); HXDD_ZF_DropdownItems listArmorMode = new("HXDD_ZF_DropdownItems"); listArmorMode.items.push("$OPT_CLASS_DEFAULT"); @@ -531,10 +539,16 @@ class ZFGameOptions ui { void Refresh() { int selected = LemonUtil.ClassNameToID(parent.selectedClass); - if (selected > listClassDifficulty.Size() - 1) { + if (selected > gameinfo.skills.Size() - 1) { selected = 0; } - self.ddl_Difficulty.GetDropDownElement().setItems(listClassDifficulty[selected]); + + HXDD_ZF_DropdownItems skList = new("HXDD_ZF_DropdownItems"); + for (int i = 0; i < gameinfo.skills.Size(); i++) { + skList.items.push(gameinfo.skills[i].Get(parent.selectedClass)); + } + + self.ddl_Difficulty.GetDropDownElement().setItems(skList); int orbColor = self.headerStatueLeft.GetRandomOrb(); self.headerStatueLeft.SetOrb(orbColor); @@ -545,80 +559,6 @@ class ZFGameOptions ui { self.headerStatueLeft.Update(); self.headerStatueRight.Update(); } - - /* - - void CreateXSwapsOptions(HXDD_ZF_Frame optionArea, int pos, ZFGameOptionsHandler cmdHandler) { - int lumpIndex = Wads.CheckNumForFullName("xgt/xswap.xgt"); - if (lumpIndex == -1) { - // try json - lumpIndex = Wads.CheckNumForFullName("xgt/xswap.json"); - } - - if (lumpIndex != -1) { - String lumpData = Wads.ReadLump(lumpIndex); - let json = HXDD_JSON.parse(lumpData, false); - if (json is "HXDD_JsonElement") { - HXDD_JsonObject jsonObject = HXDD_JsonObject(json); - if (jsonObject) { - String ver = GetString(jsonObject, "version"); - //if (ver) { - // console.printf("XGameTranslation.CreateXSwapTranslation: Target Version %s", ver); - //} - HXDD_JsonArray arrListItems = HXDD_JsonArray(jsonObject.get("list")); - if (arrListItems) { - int size = arrListItems.Size(); - for (let i = 0; i < size; i++) { - HXDD_JsonObject objListItem = HXDD_JsonObject(arrListItems.Get(i)); - if (objListItem) { - String valKey = GetString(objListItem, "key"); - String valCategory = GetString(objListItem, "category"); - HXDD_JsonArray valLabels = GetArray(objListItem, "labels"); - HXDD_JsonArray valActors = GetArray(objListItem, "actors"); - if (valKey && valActors) { - int size = valActors.Size(); - - HXDD_ZF_DropdownItems list = new("HXDD_ZF_DropdownItems"); - list.items.push("Default"); - list.items.push("Random"); - for (int j = 0; j < size; j++) { - list.items.push(HXDD_JsonString(valLabels.get(j)).s); - } - - String label = HXDD_JsonString(valLabels.get(0)).s; - for (int j = 1; j < size; j++) { - label = String.format("%s %s", label, HXDD_JsonString(valLabels.get(j)).s); - } - String cvarKey = String.format("hxdd_xswap_%s", valKey); - DropDownCombo newDDL = new ("DropDownCombo"); - newDDL.Create(optionArea, (0, pos + (i * 75)), (optionArea.GetWidth() - 32, 50), label, list, 0, cvarKey, cmdHandler); - } - } - } - } - } - } - } - } - - String GetString(HXDD_JsonObject jo, String key) { - HXDD_JsonElement type_elem = jo.get(key); - if (!type_elem) { - return ""; - } - HXDD_JsonString type_str = HXDD_JsonString(type_elem); - return type_str.s; - } - HXDD_JsonArray GetArray(HXDD_JsonObject jo, String key) { - HXDD_JsonElement type_elem = jo.get(key); - if (!type_elem) { - return null; - } - HXDD_JsonArray type_arr = HXDD_JsonArray(type_elem); - return type_arr; - } - - */ }