Skip to content

Commit

Permalink
MapInfo lump Episode and Class Skill detection
Browse files Browse the repository at this point in the history
Episodes are now dynamically added via MapInfo lumps, rough wip implementation
  • Loading branch information
Lemon-King committed Oct 20, 2023
1 parent afba1d0 commit 5fcd901
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 87 deletions.
3 changes: 2 additions & 1 deletion resources/assets/zscript/lib/_lib.zs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
186 changes: 186 additions & 0 deletions resources/assets/zscript/lib/gameinforeader.zs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@

/*
*
* GameInfoReader
* Parses MapInfo lumps for skill and episode information
*
*/



class GameInfoReader {
Array<SkillInfo> skills;
Array<EpisodeInfo> 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<String> 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<String> 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<String> 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<String> classes; // keys for list
Array<String> names;

String Get(String playerClass) {
let p = (class<PlayerPawn>)(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;
}
24 changes: 24 additions & 0 deletions resources/assets/zscript/lib/lemonutil.zs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> 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<Object> GetPlayerClass() {
// Hardcoded for single player atm
PlayerInfo p = players[0];
Expand Down Expand Up @@ -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));
Expand Down
112 changes: 26 additions & 86 deletions resources/assets/zscript/menu/newgame.zs
Original file line number Diff line number Diff line change
Expand Up @@ -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?
}
}
}
Expand Down Expand Up @@ -255,6 +257,8 @@ class ZFGameOptions ui {
W_KeyStatue headerStatueLeft;
W_KeyStatue headerStatueRight;

GameInfoReader gameinfo;

Array<HXDD_ZF_DropdownItems> listClassDifficulty;

void CreateDifficultyLists() {
Expand Down Expand Up @@ -452,23 +456,27 @@ 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");
}
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");
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
*/
}


Expand Down

0 comments on commit 5fcd901

Please sign in to comment.