Merge branch 'develop' of https://github.com/ZoneTool/zonetool into develop

This commit is contained in:
RektInator 2020-12-28 13:33:38 +01:00
commit 7b8bee30d8
6 changed files with 1693 additions and 0 deletions

994
src/IW4/Assets/MenuDef.cpp Normal file
View File

@ -0,0 +1,994 @@
// ======================= ZoneTool =======================
// zonetool, a fastfile linker for various
// Call of Duty titles.
//
// Project: https://github.com/ZoneTool/zonetool
// Author: RektInator (https://github.com/RektInator)
// License: GNU GPL v3.0
// ========================================================
#include "stdafx.hpp"
namespace ZoneTool
{
namespace IW4
{
void IMenuDef::init(const std::string& name, ZoneMemory* mem)
{
this->name_ = name;
this->asset_ = DB_FindXAssetHeader(this->type(), this->name().data()).menu;
}
std::string IMenuDef::name()
{
return this->name_;
}
std::int32_t IMenuDef::type()
{
return menu;
}
int IMenuDef::indentCounter = 0;
FILE* IMenuDef::fp = nullptr;
static const char* g_expOperatorNames[]
{
"NOOP",
")",
"*",
"/",
"%",
"+",
"-",
"!",
"<",
"<=",
">",
">=",
"==",
"!=",
"&&",
"||",
"(",
",",
"&",
"|",
"~",
"<<",
">>",
"dvarint(static)",
"dvarbool(static)",
"dvarfloat(static)",
"dvarstring(static)",
"int",
"string",
"float",
"sin",
"cos",
"min",
"max",
"milliseconds",
"dvarint",
"dvarbool",
"dvarfloat",
"dvarstring",
"stat",
"ui_active",
"flashbanged",
"usingvehicle",
"missilecam",
"scoped",
"scopedthermal",
"scoreboard_visible",
"inkillcam",
"inkillcamnpc",
"player",
"getperk",
"selecting_location",
"selecting_direction",
"team",
"otherteam",
"marinesfield",
"opforfield",
"menuisopen",
"writingdata",
"inlobby",
"inprivateparty",
"privatepartyhost",
"privatepartyhostinlobby",
"aloneinparty",
"adsjavelin",
"weaplockblink",
"weapattacktop",
"weapattackdirect",
"weaplocking",
"weaplocked",
"weaplocktooclose",
"weaplockscreenposx",
"weaplockscreenposy",
"secondsastime",
"tablelookup",
"tablelookupbyrow",
"tablegetrownum",
"locstring",
"localvarint",
"localvarbool",
"localvarfloat",
"localvarstring",
"timeleft",
"secondsascountdown",
"gamemsgwndactive",
"gametypename",
"gametype",
"gametypedescription",
"scoreatrank",
"friendsonline",
"spectatingclient",
"spectatingfree",
"statrangeanybitsset",
"keybinding",
"actionslotusable",
"hudfade",
"maxrecommendedplayers",
"acceptinginvite",
"isintermission",
"gamehost",
"partyismissingmappack",
"partymissingmappackerror",
"anynewmappacks",
"amiselected",
"partystatusstring",
"attachedcontrollercount",
"issplitscreenonlinepossible",
"splitscreenplayercount",
"getplayerdata",
"getplayerdatasplitscreen",
"experienceforlevel",
"levelforexperience",
"isitemunlocked",
"isitemunlockedsplitscreen",
"debugprint",
"getplayerdataanybooltrue",
"weaponclassnew",
"weaponname",
"isreloading",
"savegameavailable",
"unlockeditemcount",
"unlockeditemcountsplitscreen",
"unlockeditem",
"unlockeditemsplitscreen",
"mailsubject",
"mailfrom",
"mailreceived",
"mailbody",
"maillootlocalized",
"mailgivesloot",
"anynewmail",
"mailtimetofollowup",
"mailloottype",
"mailranlottery",
"lotterylootlocalized",
"radarisjammed",
"radarjamintensity",
"radarisenabled",
"isempjammed",
"playerads",
"weaponheatactive",
"weaponheatvalue",
"weaponheatoverheated",
"getsplashtext",
"getsplashdescription",
"getsplashmaterial",
"splashhasicon",
"splashrownum",
"getfocuseditemname",
"getfocuseditemx",
"getfocuseditemy",
"getfocuseditemwidth",
"getfocuseditemheight",
"getitemx",
"getitemy",
"getitemwidth",
"getitemheight",
"playlist",
"scoreboardexternalmutenotice",
"getclientmatchdata",
"getclientmatchdatadef",
"getmapname",
"getmapimage",
"getmapcustom",
"getmigrationstatus",
"getplayercardinfo",
"isofflineprofileselected",
"coopplayer",
"iscoop",
"getpartystatus",
"getsearchparams",
"gettimeplayed",
"isselectedplayerfriend",
"getcharbyindex",
"getprofiledata",
"isprofilesignedin",
"getwaitpopupstatus",
"getnattype",
"getlocalizednattype",
"getadjustedsafeareahorizontal",
"getadjustedsafeareavertical",
"connectioninfo",
"offlineprofilecansave",
"allsplitscreenprofilescansave",
"allsplitscreenprofilesaresignedin",
"coopready"
};
const char* g_commandList[] =
{
"fadein",
"fadeout",
"show",
"hide",
"showMenu",
"hideMenu",
"setcolor",
"open",
"close",
"closeForAllPlayers",
"ingameopen",
"ingameclose",
"setbackground",
"setItemColor",
"focusfirst",
"setfocus",
"setfocusbydvar",
"setdvar",
"exec",
"execnow",
"execOnDvarStringValue",
"execOnDvarIntValue",
"execOnDvarFloatValue",
"execNowOnDvarStringValue",
"execNowOnDvarIntValue",
"execNowOnDvarFloatValue",
"play",
"scriptmenuresponse",
"scriptMenuRespondOnDvarStringValue",
"scriptMenuRespondOnDvarIntValue",
"scriptMenuRespondOnDvarFloatValue",
"setPlayerData",
"setPlayerDataSplitscreen",
"updateMail",
"openMail",
"deleteMail",
"doMailLottery",
"resetStatsConfirm",
"resetStatsCancel",
"setGameMode",
"setLocalVarBool",
"setLocalVarInt",
"setLocalVarFloat",
"setLocalVarString",
"feederTop",
"feederBottom",
"showGamerCard",
"openforgametype",
"closeforgametype",
"statclearperknew",
"statsetusingtable",
"statclearbitmask",
"kickPlayer",
"getKickPlayerQuestion",
"partyUpdateMissingMapPackDvar",
"getHostMigrateQuestion",
"makehost",
"togglePlayerMute",
"addFriendFromId",
"resolveError",
"lerp",
// added by me
"uiScript"
};
struct ItemFloatExpressionEntry
{
int target;
const char* s1;
const char* s2;
};
ItemFloatExpressionEntry g_itemFloatExpressions[19] =
{
{ 0, "rect", "x" },
{ 1, "rect", "y" },
{ 2, "rect", "w" },
{ 3, "rect", "h" },
{ 4, "forecolor", "r" },
{ 5, "forecolor", "g" },
{ 6, "forecolor", "b" },
{ 7, "forecolor", "rgb" },
{ 8, "forecolor", "a" },
{ 9, "glowcolor", "r" },
{ 10, "glowcolor", "g" },
{ 11, "glowcolor", "b" },
{ 12, "glowcolor", "rgb" },
{ 13, "glowcolor", "a" },
{ 14, "backcolor", "r" },
{ 15, "backcolor", "g" },
{ 16, "backcolor", "b" },
{ 17, "backcolor", "rgb" },
{ 18, "backcolor", "a" }
};
void IMenuDef::dump(menuDef_t* asset)
{
ZONETOOL_INFO("Dumping menu %s", asset->window.name);
fp = FileSystem::FileOpen("menus\\"s + asset->window.name + ".menu"s, "w");
indentCounter = 1;
if (fp)
{
emit_menu_def(asset);
}
FileSystem::FileClose(fp);
}
void IMenuDef::emit_open_brace()
{
fprintf(fp, "%s{\n", get_tabs());
}
void IMenuDef::emit_closing_brace()
{
fprintf(fp, "%s}\n", get_tabs());
}
void IMenuDef::push_indent()
{
emit_open_brace();
IMenuDef::indentCounter++;
}
void IMenuDef::pop_indent()
{
IMenuDef::indentCounter--;
emit_closing_brace();
}
void IMenuDef::emit_menu_def(menuDef_t* asset)
{
fputs("{\n\tmenuDef\n", fp);
push_indent();
emit_window_def(&asset->window, false);
emit_color("focuscolor", asset->focusColor);
emit_int("fullscreen", asset->fullscreen);
emit_float("fadeCycle", asset->fadeCycle);
emit_float("fadeClamp", asset->fadeClamp);
emit_float("fadeAmount", asset->fadeAmount);
emit_float("fadeInAmount", asset->fadeInAmount);
emit_float("blurWorld", asset->blurRadius);
emit_string("allowedBinding", asset->allowedBinding);
emit_statement("visible when", asset->visibleExp);
emit_statement("exp rect x", asset->rectXExp);
emit_statement("exp rect y", asset->rectYExp);
emit_statement("exp rect h", asset->rectHExp);
emit_statement("exp rect w", asset->rectWExp);
emit_statement("exp openSound", asset->openSoundExp);
emit_statement("exp closeSound", asset->closeSoundExp);
emit_item_key_handler("execKeyInt", asset->onKey);
emit_menu_event_handler_set("onOpen", asset->onOpen);
emit_menu_event_handler_set("onRequestClose", asset->onRequestClose);
emit_menu_event_handler_set("onClose", asset->onClose);
emit_menu_event_handler_set("onEsc", asset->onEsc);
for (auto i = 0; i < asset->itemCount; i++)
{
emit_item_def(asset->items[i]);
}
pop_indent();
fputs("}\n", fp);
}
void IMenuDef::emit_item_def(itemDef_t* item)
{
fputs("\t\titemDef\n", fp);
push_indent();
emit_window_def(&item->window, true);
emit_int("type", item->type);
emit_int("align", item->alignment);
emit_int("textfont", item->fontEnum);
emit_int("textalign", item->textAlignMode);
emit_float("textalignx", item->textAlignX);
emit_float("textaligny", item->textAlignY);
emit_float("textscale", item->textScale);
emit_color("glowColor", item->glowColor);
emit_bool("decodeEffect", item->decayActive);
if (item->type == ITEM_TYPE_GAME_MESSAGE_WINDOW)
{
emit_int("gamemsgwindowindex", item->gameMsgWindowIndex);
emit_int("gamemsgwindowmode", item->gameMsgWindowMode);
}
emit_string("text", item->text);
emit_bool("textsavegame", item->textSaveGameInfo & 1);
emit_bool("textcinematicsubtitle", item->textSaveGameInfo & 2);
emit_float("feeder", item->special);
emit_string("focusSound", item->focusSound);
if (item->type != ITEM_TYPE_SLIDER && item->type != ITEM_TYPE_DVARENUM)
{
emit_string("dvar", item->dvar);
emit_item_def_data(&item->typeData, item->type);
}
else
{
emit_item_def_data(&item->typeData, item->type);
}
emit_dvar_flags(item->dvarFlags, item->dvarTest, item->enableDvar);
emit_item_float_expressions(item->floatExpressions, item->floatExpressionCount);
emit_statement("visible when", item->visibleExp);
emit_statement("disabled when", item->disabledExp);
emit_statement("exp text", item->textExp);
emit_statement("exp material", item->materialExp);
emit_item_key_handler("execKeyInt", item->onKey);
emit_menu_event_handler_set("mouseEnterText", item->mouseEnterText);
emit_menu_event_handler_set("mouseExitText", item->mouseExitText);
emit_menu_event_handler_set("mouseEnter", item->mouseEnter);
emit_menu_event_handler_set("mouseExit", item->mouseExit);
emit_menu_event_handler_set("action", item->action);
emit_menu_event_handler_set("accept", item->accept);
emit_menu_event_handler_set("onFocus", item->onFocus);
emit_menu_event_handler_set("leaveFocus", item->leaveFocus);
pop_indent();
}
void IMenuDef::emit_window_def(windowDef_t* window, bool is_item)
{
emit_string("name", window->name);
if (is_item)
{
emit_rect("rect", window->rectClient);
}
else
{
emit_rect("rect", window->rect);
}
emit_static_flags(window->staticFlags);
emit_dynamic_flags(window->dynamicFlags);
emit_string("group", window->group);
emit_int("style", window->style);
emit_int("border", window->border);
emit_float("borderSize", window->borderSize);
emit_int("ownerdraw", window->ownerDraw);
emit_int("ownerdrawFlag", window->ownerDrawFlags);
emit_color("forecolor", window->foreColor);
emit_color("backcolor", window->backColor);
emit_color("bordercolor", window->borderColor);
emit_color("outlinecolor", window->outlineColor);
emit_color("disablecolor", window->disableColor);
if (window->background)
{
emit_string("background", window->background->name);
}
}
void IMenuDef::emit_set_local_var_data(SetLocalVarData* data, EventType type)
{
if (data)
{
std::string cmd;
switch (type)
{
case EVENT_SET_LOCAL_VAR_BOOL:
cmd = "setLocalVarBool";
break;
case EVENT_SET_LOCAL_VAR_INT:
cmd = "setLocalVarInt";
break;
case EVENT_SET_LOCAL_VAR_FLOAT:
cmd = "setLocalVarFloat";
break;
case EVENT_SET_LOCAL_VAR_STRING:
cmd = "setLocalVarString";
break;
}
fprintf(fp, "%s%s \"%s\"", get_tabs(), cmd.c_str(), data->localVarName);
emit_statement(nullptr, data->expression, true);
}
}
void IMenuDef::emit_dynamic_flags(int flags)
{
emit_bool("visible 1", flags & WINDOWDYNAMIC_VISIBLE);
}
void IMenuDef::emit_static_flags(int flags)
{
emit_bool("decoration", flags & WINDOWSTATIC_DECORATION);
emit_bool("horizontalscroll", flags & WINDOWSTATIC_HORIZONTALSCROLL);
emit_bool("screenSpace", flags & WINDOWSTATIC_SCREENSPACE);
emit_bool("autowrapped", flags & WINDOWSTATIC_AUTOWRAPPED);
emit_bool("popup", flags & WINDOWSTATIC_POPUP);
emit_bool("outOfBoundsClick", flags & WINDOWSTATIC_OUTOFBOUNDSCLICK);
emit_bool("legacySplitScreenScale", flags & WINDOWSTATIC_LEGACYSPLITSCREENSCALE);
emit_bool("hiddenDuringFlashbang", flags & WINDOWSTATIC_HIDDENDURINGFLASH);
emit_bool("hiddenDuringScope", flags & WINDOWSTATIC_HIDDENDURINGSCOPE);
emit_bool("hiddenDuringUI", flags & WINDOWSTATIC_HIDDENDURINGUI);
emit_bool("textOnlyFocus", flags & WINDOWSTATIC_TEXTONLYFOCUS);
}
void IMenuDef::emit_dvar_flags(int dvarFlags, const char* dvarTest, const char* enableDvar)
{
std::string command;
switch (dvarFlags)
{
case 0x01:
command = "enableDvar";
break;
case 0x02:
command = "disableDvar";
break;
case 0x04:
command = "showDvar";
break;
case 0x08:
command = "hideDvar";
break;
case 0x10:
command = "focusDvar";
break;
}
emit_string("dvarTest", dvarTest);
if (enableDvar)
{
fprintf(fp, "%s%s { %s}\n", get_tabs(), command.c_str(), enableDvar);
}
}
void IMenuDef::emit_item_def_data(itemDefData_t* data, int type)
{
if (data->data)
{
switch (type)
{
case ITEM_TYPE_LISTBOX:
emit_list_box(data->listBox);
break;
case ITEM_TYPE_MULTI:
emit_multi_def(data->multiDef);
break;
case ITEM_TYPE_DVARENUM:
fprintf(fp, "%s%s %s %s", get_tabs(), "dvar", "dvarEnumList", data->enumDvarName);
break;
case ITEM_TYPE_NEWSTICKER:
emit_int("newsfeed", data->ticker->feedId);
emit_int("speed", data->ticker->speed);
emit_int("spacing", data->ticker->spacing);
break;
case ITEM_TYPE_EDITFIELD:
case ITEM_TYPE_NUMERICFIELD:
case ITEM_TYPE_VALIDFILEFIELD:
case ITEM_TYPE_UPREDITFIELD:
case ITEM_TYPE_YESNO:
case ITEM_TYPE_BIND:
case ITEM_TYPE_TEXT:
case ITEM_TYPE_DECIMALFIELD:
case ITEM_TYPE_EMAILFIELD:
case ITEM_TYPE_PASSWORDFIELD:
emit_int("maxChars", data->editField->maxChars);
emit_int("maxCharsGotoNext", data->editField->maxCharsGotoNext);
emit_int("maxPaintChars", data->editField->maxPaintChars);
break;
case ITEM_TYPE_TEXTSCROLL:
default:
break;
}
}
}
void IMenuDef::emit_multi_def(multiDef_s* multiDef)
{
if (multiDef->strDef)
{
fprintf(fp, "%s%s {", get_tabs(), "dvarStrList");
}
else
{
fprintf(fp, "%s%s {", get_tabs(), "dvarFloatList");
}
for (auto i = 0; i < multiDef->count; i++)
{
fprintf(fp, " \"%s\"", multiDef->dvarList[i]);
if (multiDef->strDef)
{
fprintf(fp, " \"%s\"", multiDef->dvarStr[i]);
}
else
{
fprintf(fp, " %g", multiDef->dvarValue[i]);
}
}
fputs(" }\n", fp);
}
void IMenuDef::emit_list_box(listBoxDef_s* listBox)
{
emit_color("selectBorder", listBox->selectBorder);
if (listBox->selectIcon)
{
emit_string("selectIcon", listBox->selectIcon->name);
}
emit_float("elementWidth", listBox->elementWidth);
emit_float("elementHeight", listBox->elementHeight);
emit_int("elementtype", listBox->elementStyle);
emit_column_info(listBox->columnInfo, listBox->numColumns);
emit_bool("noscrollbars", listBox->noscrollbars);
emit_bool("notselectable", listBox->notselectable);
emit_bool("usepaging", listBox->usepaging);
emit_menu_event_handler_set("doubleClick", listBox->doubleClick);
}
void IMenuDef::emit_column_info(columnInfo_s* columns, int count)
{
fprintf(fp, "//%snumcol\t\t\txpos\txwidth\ttextlen\t alignment\n", get_tabs());
fprintf(fp, "%s%s %i\t\t%i\t\t%i\t\t%i\t\t %i\n", get_tabs(), "columns", count, columns[0].xpos, columns[0].width, columns[0].maxChars, columns[0].alignment);
for (int i = 1; i < count; i++)
{
fprintf(fp, "%s\t\t\t\t%i\t\t%i\t\t%i\t\t %i\n", get_tabs(), columns[i].xpos, columns[i].width, columns[i].maxChars, columns[i].alignment);
}
}
void IMenuDef::emit_item_float_expressions(ItemFloatExpression* expressions, int count)
{
if (expressions)
{
for (auto i = 0; i < count; i++)
{
std::string name;
name = "exp ";
name += g_itemFloatExpressions[expressions[i].target].s1;
name += " ";
name += g_itemFloatExpressions[expressions[i].target].s2;
emit_statement(name.c_str(), expressions[i].expression);
}
}
}
void IMenuDef::emit_item_key_handler(const char* name, ItemKeyHandler* handler)
{
if (handler)
{
emit_menu_event_handler_set("", handler->action);
emit_item_key_handler("execKeyInt", handler->next);
}
}
void IMenuDef::emit_menu_event_handler_set(const char* name, MenuEventHandlerSet* set)
{
if (set)
{
const bool formatStatement = true;
if (name)
{
fprintf(fp, "%s%s\n", get_tabs(), name);
push_indent();
}
for (auto i = 0; i < set->eventHandlerCount; i++)
{
switch (set->eventHandlers[i]->eventType)
{
case EVENT_UNCONDITIONAL:
fprintf(fp, "%s%s", get_tabs(), format_script(set->eventHandlers[i]->eventData.unconditionalScript).c_str());
break;
case EVENT_IF:
emit_conditional_script(set->eventHandlers[i]->eventData.conditionalScript);
break;
case EVENT_ELSE:
emit_menu_event_handler_set("else", set->eventHandlers[i]->eventData.elseScript);
break;
case EVENT_SET_LOCAL_VAR_BOOL:
case EVENT_SET_LOCAL_VAR_INT:
case EVENT_SET_LOCAL_VAR_FLOAT:
case EVENT_SET_LOCAL_VAR_STRING:
emit_set_local_var_data(set->eventHandlers[i]->eventData.setLocalVarData, set->eventHandlers[i]->eventType);
break;
default:
break;
}
}
if (name)
{
pop_indent();
}
}
}
void IMenuDef::emit_conditional_script(ConditionalScript* script)
{
if (script)
{
fprintf(fp, "%sif", get_tabs());
emit_statement(nullptr, script->eventExpression);
push_indent();
emit_menu_event_handler_set(nullptr, script->eventHandlerSet);
pop_indent();
}
}
void IMenuDef::emit_statement(const char* name, Statement_s* statement, bool semiColon)
{
if (statement)
{
const bool clean_statements = true;
bool needs_closing_parenthesis = false;
if (name)
{
fprintf(fp, "%s%s", get_tabs(), name);
}
if (clean_statements)
{
if (statement->entries[0].data.op != OP_LEFTPAREN)
{
fputs(" (", fp);
}
}
for (auto i = 0; i < statement->numEntries; i++)
{
int type = statement->entries[i].type;
if (type == OPERATOR)
{
needs_closing_parenthesis = true;
auto op = statement->entries[i].data.op;
if (op < OP_FIRSTFUNCTIONCALL)
{
if (statement->entries[i - 1].data.op == OP_RIGHTPAREN && op == OP_LEFTPAREN)
{
++i;
continue;
}
if (statement->entries[i - 1].data.op == OP_NOT)
{
fprintf(fp, "%s", g_expOperatorNames[op]);
}
else
{
fprintf(fp, " %s", g_expOperatorNames[op]);
}
}
else if (op >= OP_STATICDVARINT && op <= OP_STATICDVARSTRING)
{
i++;
std::string command;
switch (op)
{
case OP_STATICDVARINT:
command = "dvarstring";
break;
case OP_STATICDVARBOOL:
command = "dvarbool";
break;
case OP_STATICDVARFLOAT:
command = "dvarfloat";
break;
case OP_STATICDVARSTRING:
command = "dvarstring";
break;
}
command += "( \"";
command += statement->supportingData->staticDvarList.staticDvars[statement->entries[i].data.operand.internals.intVal]->dvarName;
command += "\" )";
if (statement->entries[i - 2].data.op == OP_NOT)
{
fprintf(fp, "%s", command.c_str());
}
else
{
fprintf(fp, " %s", command.c_str());
}
i++;
}
else
{
if (statement->entries[i - 1].data.op == OP_NOT)
fprintf(fp, "%s(", g_expOperatorNames[op]);
else
fprintf(fp, " %s(", g_expOperatorNames[op]);
}
}
else if (type == OPERAND)
{
switch (statement->entries[i].data.operand.dataType)
{
case VAL_INT:
fprintf(fp, " %i", statement->entries[i].data.operand.internals.intVal);
break;
case VAL_FLOAT:
fprintf(fp, " %g", statement->entries[i].data.operand.internals.floatVal);
break;
case VAL_STRING:
fprintf(fp, " \"%s\"", escape_string(statement->entries[i].data.operand.internals.stringVal.string).c_str());
break;
case VAL_FUNCTION:
emit_statement(nullptr, statement->entries[i].data.operand.internals.function);
break;
}
}
}
if (clean_statements)
{
if (needs_closing_parenthesis)
{
fputs(" )", fp);
}
if (statement->entries[0].data.op != OP_LEFTPAREN)
{
fputs(" )", fp);
}
if (semiColon)
{
fputs(";", fp);
}
}
fputs("\n", fp);
}
}
void IMenuDef::emit_string(const char* name, const char* value)
{
if (value && *value)
{
fprintf(fp, "%s%s \"%s\"\n", get_tabs(), name, value);
}
}
void IMenuDef::emit_bool(const char* name, bool value)
{
if (value)
{
fprintf(fp, "%s%s\n", get_tabs(), name);
}
}
void IMenuDef::emit_int(const char* name, int value)
{
if (value)
{
fprintf(fp, "%s%s %i\n", get_tabs(), name, value);
}
}
void IMenuDef::emit_float(const char* name, float value)
{
if (value)
{
fprintf(fp, "%s%s %g\n", get_tabs(), name, value);
}
}
void IMenuDef::emit_rect(const char* name, rectDef_s& rect)
{
// TODO: Some pre-processing may be needed
fprintf(fp, "%s%s %g %g %g %g %i %i\n", get_tabs(), name, rect.x, rect.y, rect.w, rect.h, rect.horzAlign, rect.vertAlign);
}
void IMenuDef::emit_color(const char* name, vec4_t& color)
{
if (color[0] > 0.0f || color[1] > 0.0f || color[2] > 0.0f || color[3] > 0.0f)
{
fprintf(fp, "%s%s %g %g %g %g\n", get_tabs(), name, color[0], color[1], color[2], color[3]);
}
}
const char* IMenuDef::get_tabs()
{
static char tabs[10];
for (auto i = 0; i < indentCounter && i < 10; i++)
{
tabs[i] = '\t';
}
tabs[indentCounter] = 0;
return tabs;
}
void IMenuDef::replace_all(std::string& str, std::string from, std::string to, bool case_insensitive)
{
if (case_insensitive)
{
auto replace = [&](std::string from, std::string to) -> bool
{
std::string lowered(str);
std::transform(str.begin(), str.end(), lowered.begin(), ::tolower);
auto pos = lowered.find(from);
if (pos == std::string::npos)
{
return false;
}
str.replace(pos, from.length(), to);
return true;
};
std::transform(from.begin(), from.end(), from.begin(), ::tolower);
while (replace(from, to));
}
else
{
std::size_t pos = 0;
while ((pos = str.find(from, pos)) != std::string::npos)
{
str.replace(pos, from.length(), to);
pos += to.length();
}
}
}
std::string IMenuDef::escape_string(const char* value)
{
std::string out(value);
replace_all(out, "\t", "\\t");
replace_all(out, "\n", "\\n");
return out;
}
std::string IMenuDef::format_script(const char* value)
{
std::string out = escape_string(value);
const std::string tabs = get_tabs();
// clean indentation and semi colons
out += "\n";
replace_all(out, "\t;", "\t");
replace_all(out, tabs + "\n", "");
replace_all(out, " ; \n", ";\n");
replace_all(out, " \n", ";\n");
replace_all(out, " ; ", ";\n" + tabs);
replace_all(out, "; ", ";\n" + tabs);
// remove quotes from keywords
replace_all(out, "\"self\"", "self");
replace_all(out, "\"forecolor\"", "forecolor");
replace_all(out, "\"backcolor\"", "backcolor");
replace_all(out, "\"bordercolor\"", "bordercolor");
// remove quotes from commands
for (auto i = 0; i < 62; i++)
{
replace_all(out, "\""s + g_commandList[i] + "\""s, g_commandList[i], true);
}
return out;
}
}
}

View File

@ -0,0 +1,65 @@
// ======================= ZoneTool =======================
// zonetool, a fastfile linker for various
// Call of Duty titles.
//
// Project: https://github.com/ZoneTool/zonetool
// Author: RektInator (https://github.com/RektInator)
// License: GNU GPL v3.0
// ========================================================
#pragma once
namespace ZoneTool
{
namespace IW4
{
class IMenuDef : public IAsset
{
private:
std::string name_;
menuDef_t* asset_ = nullptr;
public:
void init(const std::string& name, ZoneMemory* mem) override;
std::string name() override;
std::int32_t type() override;
static int indentCounter;
static FILE* fp;
static void dump(menuDef_t* asset);
static void emit_menu_def(menuDef_t* asset);
static void emit_item_def(itemDef_t* item);
static void emit_window_def(windowDef_t* window, bool is_item);
static void emit_set_local_var_data(SetLocalVarData* data, EventType type);
static void emit_conditional_script(ConditionalScript* script);
static void emit_statement(const char* name, Statement_s* statement, bool semiColon = false);
static void emit_menu_event_handler_set(const char* name, MenuEventHandlerSet* set);
static void emit_item_key_handler(const char* name, ItemKeyHandler* handler);
static void emit_item_float_expressions(ItemFloatExpression* expression, int count);
static void emit_column_info(columnInfo_s* columns, int count);
static void emit_list_box(listBoxDef_s* listBox);
static void emit_multi_def(multiDef_s* multiDef);
static void emit_item_def_data(itemDefData_t* data, int type);
static void emit_dvar_flags(int dvarFlags, const char* dvarTest, const char* enableDvar);
static void emit_static_flags(int flags);
static void emit_dynamic_flags(int flags);
static void emit_color(const char* name, vec4_t& color);
static void emit_rect(const char* name, rectDef_s& rect);
static void emit_string(const char* name, const char* value);
static void emit_float(const char* name, float value);
static void emit_int(const char* name, int value);
static void emit_bool(const char* name, bool value);
static void emit_open_brace();
static void emit_closing_brace();
static void push_indent();
static void pop_indent();
static const char* get_tabs();
static void replace_all(std::string& output, std::string from, std::string to, bool case_insensitive = false);
static std::string escape_string(const char* value);
static std::string format_script(const char* value);
};
}
}

View File

@ -294,6 +294,7 @@ char**>(0x00799278)[type]);
DECLARE_ASSET(weapon, IWeaponDef);
DECLARE_ASSET(addon_map_ents, IAddonMapEnts);
DECLARE_ASSET(font, IFontDef);
DECLARE_ASSET(menu, IMenuDef);
}
}
}

View File

@ -2160,6 +2160,636 @@ namespace ZoneTool
};
#pragma pack(pop)
#pragma pack(push, 4)
struct rectDef_s
{
float x;
float y;
float w;
float h;
char horzAlign;
char vertAlign;
};
#pragma pack(pop)
struct expression_s;
struct statement_s;
struct menuDef_t;
//enum operationEnum;
struct MenuEventHandlerSet;
struct Statement_s;
enum operationEnum
{
OP_NOOP = 0x0,
OP_RIGHTPAREN = 0x1,
OP_MULTIPLY = 0x2,
OP_DIVIDE = 0x3,
OP_MODULUS = 0x4,
OP_ADD = 0x5,
OP_SUBTRACT = 0x6,
OP_NOT = 0x7,
OP_LESSTHAN = 0x8,
OP_LESSTHANEQUALTO = 0x9,
OP_GREATERTHAN = 0xA,
OP_GREATERTHANEQUALTO = 0xB,
OP_EQUALS = 0xC,
OP_NOTEQUAL = 0xD,
OP_AND = 0xE,
OP_OR = 0xF,
OP_LEFTPAREN = 0x10,
OP_COMMA = 0x11,
OP_BITWISEAND = 0x12,
OP_BITWISEOR = 0x13,
OP_BITWISENOT = 0x14,
OP_BITSHIFTLEFT = 0x15,
OP_BITSHIFTRIGHT = 0x16,
OP_FIRSTFUNCTIONCALL = 0x17,
OP_STATICDVARINT = 0x17,
OP_STATICDVARBOOL = 0x18,
OP_STATICDVARFLOAT = 0x19,
OP_STATICDVARSTRING = 0x1A,
OP_INT = 0x1B,
OP_STRING = 0x1C,
OP_FLOAT = 0x1D,
OP_SIN = 0x1E,
OP_COS = 0x1F,
OP_MIN = 0x20,
OP_MAX = 0x21,
OP_MILLISECONDS = 0x22,
OP_DVARINT = 0x23,
OP_DVARBOOL = 0x24,
OP_DVARFLOAT = 0x25,
OP_DVARSTRING = 0x26,
OP_STAT = 0x27,
OP_UIACTIVE = 0x28,
OP_FLASHBANGED = 0x29,
OP_USINGVEHICLE = 0x2A,
OP_MISSILECAM = 0x2B,
OP_SCOPED = 0x2C,
OP_SCOPEDTHERMAL = 0x2D,
OP_SCOREBOARDVISIBLE = 0x2E,
OP_INKILLCAM = 0x2F,
OP_INKILLCAMNPC = 0x30,
OP_PLAYERFIELD = 0x31,
OP_GETPERK = 0x32,
OP_SELECTINGLOCATION = 0x33,
OP_SELECTINGDIRECTION = 0x34,
OP_TEAMFIELD = 0x35,
OP_OTHERTEAMFIELD = 0x36,
OP_MARINESFIELD = 0x37,
OP_OPFORFIELD = 0x38,
OP_MENUISOPEN = 0x39,
OP_WRITINGDATA = 0x3A,
OP_INLOBBY = 0x3B,
OP_INPRIVATEPARTY = 0x3C,
OP_PRIVATEPARTYHOST = 0x3D,
OP_PRIVATEPARTYHOSTINLOBBY = 0x3E,
OP_ALONEINPARTY = 0x3F,
OP_ADSJAVELIN = 0x40,
OP_WEAPLOCKBLINK = 0x41,
OP_WEAPATTACKTOP = 0x42,
OP_WEAPATTACKDIRECT = 0x43,
OP_WEAPLOCKING = 0x44,
OP_WEAPLOCKED = 0x45,
OP_WEAPLOCKTOOCLOSE = 0x46,
OP_WEAPLOCKSCREENPOSX = 0x47,
OP_WEAPLOCKSCREENPOSY = 0x48,
OP_SECONDSASTIME = 0x49,
OP_TABLELOOKUP = 0x4A,
OP_TABLELOOKUPBYROW = 0x4B,
OP_TABLEGETROWNUM = 0x4C,
OP_LOCALIZESTRING = 0x4D,
OP_LOCALVARINT = 0x4E,
OP_LOCALVARBOOL = 0x4F,
OP_LOCALVARFLOAT = 0x50,
OP_LOCALVARSTRING = 0x51,
OP_TIMELEFT = 0x52,
OP_SECONDSASCOUNTDOWN = 0x53,
OP_GAMEMSGWNDACTIVE = 0x54,
OP_GAMETYPENAME = 0x55,
OP_GAMETYPE = 0x56,
OP_GAMETYPEDESCRIPTION = 0x57,
OP_SCORE = 0x58,
OP_FRIENDSONLINE = 0x59,
OP_SPECTATINGCLIENT = 0x5A,
OP_SPECTATINGFREE = 0x5B,
OP_STATRANGEBITSSET = 0x5C,
OP_KEYBINDING = 0x5D,
OP_ACTIONSLOTUSABLE = 0x5E,
OP_HUDFADE = 0x5F,
OP_MAXRECOMMENDEDPLAYERS = 0x60,
OP_ACCEPTINGINVITE = 0x61,
OP_ISINTERMISSION = 0x62,
OP_GAMEHOST = 0x63,
OP_PARTYISMISSINGMAPPACK = 0x64,
OP_PARTYMISSINGMAPPACKERROR = 0x65,
OP_ANYNEWMAPPACKS = 0x66,
OP_AMISELECTED = 0x67,
OP_PARTYSTATUSSTRING = 0x68,
OP_ATTACHEDCONTROLLERCOUNT = 0x69,
OP_ISSPLITSCREENONLINEPOSSIBLE = 0x6A,
OP_SPLITSCREENPLAYERCOUNT = 0x6B,
OP_GETPLAYERDATA = 0x6C,
OP_GETPLAYERDATASPLITSCREEN = 0x6D,
OP_EXPERIENCEFORLEVEL = 0x6E,
OP_LEVELFOREXPERIENCE = 0x6F,
OP_ISITEMUNLOCKED = 0x70,
OP_ISITEMUNLOCKEDSPLITSCREEN = 0x71,
OP_DEBUGPRINT = 0x72,
OP_GETPLAYERDATAANYBOOLTRUE = 0x73,
OP_WEAPONCLASSNEW = 0x74,
OP_WEAPONNAME = 0x75,
OP_ISRELOADING = 0x76,
OP_SAVEGAMEAVAILABLE = 0x77,
OP_UNLOCKEDITEMCOUNT = 0x78,
OP_UNLOCKEDITEMCOUNTSPLITSCREEN = 0x79,
OP_UNLOCKEDITEM = 0x7A,
OP_UNLOCKEDITEMSPLITSCREEN = 0x7B,
OP_MAILSUBJECT = 0x7C,
OP_MAILFROM = 0x7D,
OP_MAILRECEIVED = 0x7E,
OP_MAILBODY = 0x7F,
OP_MAILLOOTLOCALIZED = 0x80,
OP_MAILGIVESLOOT = 0x81,
OP_ANYNEWMAIL = 0x82,
OP_MAILTIMETOFOLLOWUP = 0x83,
OP_MAILLOOTTYPE = 0x84,
OP_MAILRANLOTTERY = 0x85,
OP_LOTTERYLOOTLOCALIZED = 0x86,
OP_RADARISJAMMED = 0x87,
OP_RADARJAMINTENSITY = 0x88,
OP_RADARISENABLED = 0x89,
OP_ISEMPJAMMED = 0x8A,
OP_PLAYERADS = 0x8B,
OP_WEAPONHEATACTIVE = 0x8C,
OP_WEAPONHEATVALUE = 0x8D,
OP_WEAPONHEATOVERHEATED = 0x8E,
OP_GETSPLASHTEXT = 0x8F,
OP_GETSPLASHDESCRIPTION = 0x90,
OP_GETSPLASHMATERIAL = 0x91,
OP_SPLASHHASICON = 0x92,
OP_SPLASHROWNUM = 0x93,
OP_GETFOCUSEDITEMNAME = 0x94,
OP_GETFOCUSEDITEMX = 0x95,
OP_GETFOCUSEDITEMY = 0x96,
OP_GETFOCUSEDITEMWIDTH = 0x97,
OP_GETFOCUSEDITEMHEIGHT = 0x98,
OP_GETITEMX = 0x99,
OP_GETITEMY = 0x9A,
OP_GETITEMWIDTH = 0x9B,
OP_GETITEMHEIGHT = 0x9C,
OP_PLAYLIST = 0x9D,
OP_SCOREBOARDEXTERNALMUTENOTICE = 0x9E,
OP_GETCLIENTMATCHDATA = 0x9F,
OP_GETCLIENTMATCHDATADEF = 0xA0,
OP_GETMAPNAME = 0xA1,
OP_GETMAPIMAGE = 0xA2,
OP_GETMAPCUSTOM = 0xA3,
OP_GETMIGRATIONSTATUS = 0xA4,
OP_GETPLAYERCARDINFO = 0xA5,
OP_ISOFFLINEPROFILESELECTED = 0xA6,
OP_COOPPLAYER = 0xA7,
OP_ISCOOP = 0xA8,
OP_GETPARTYSTATUS = 0xA9,
OP_GETSEARCHPARAMS = 0xAA,
OP_GETTIMEPLAYED = 0xAB,
OP_ISSELECTEDPLAYERFRIEND = 0xAC,
OP_GETCHARBYINDEX = 0xAD,
OP_GETPROFILEDATA = 0xAE,
OP_ISPROFILESIGNEDIN = 0xAF,
OP_GETWAITPOPUPSTATUS = 0xB0,
OP_GETNATTYPE = 0xB1,
OP_GETLOCALIZEDNATTYPE = 0xB2,
OP_GETADJUSTEDSAFEAREAHORIZONTAL = 0xB3,
OP_GETADJUSTEDSAFEAREAVERTICAL = 0xB4,
OP_CONNECTIONINFO = 0xB5,
OP_OFFLINEPROFILECANSAVE = 0xB6,
OP_ALLSPLITSCREENPROFILESCANSAVE = 0xB7,
OP_ALLSPLITSCREENPROFILESARESIGNEDIN = 0xB8,
OP_DOWEHAVEMAPPACK = 0xB9,
};
/* windowDef_t->dynamicFlags */
// 0x1
#define WINDOWDYNAMIC_HASFOCUS 0x00000002
#define WINDOWDYNAMIC_VISIBLE 0x00000004
#define WINDOWDYNAMIC_FADEOUT 0x00000010
#define WINDOWDYNAMIC_FADEIN 0x00000020
// 0x40
// 0x80
#define WINDOWDYNAMIC_CLOSED 0x00000800
// 0x2000
#define WINDOWDYNAMIC_BACKCOLOR 0x00008000
#define WINDOWDYNAMIC_FORECOLOR 0x00010000
/* windowDef_t->staticFlags */
#define WINDOWSTATIC_DECORATION 0x00100000
#define WINDOWSTATIC_HORIZONTALSCROLL 0x00200000
#define WINDOWSTATIC_SCREENSPACE 0x00400000
#define WINDOWSTATIC_AUTOWRAPPED 0x00800000
#define WINDOWSTATIC_POPUP 0x01000000
#define WINDOWSTATIC_OUTOFBOUNDSCLICK 0x02000000
#define WINDOWSTATIC_LEGACYSPLITSCREENSCALE 0x04000000
#define WINDOWSTATIC_HIDDENDURINGFLASH 0x10000000
#define WINDOWSTATIC_HIDDENDURINGSCOPE 0x20000000
#define WINDOWSTATIC_HIDDENDURINGUI 0x40000000
#define WINDOWSTATIC_TEXTONLYFOCUS 0x80000000
#define ITEM_TYPE_TEXT 0 // simple text
#define ITEM_TYPE_BUTTON 1 // button, basically text with a border
#define ITEM_TYPE_RADIOBUTTON 2 // toggle button, may be grouped
#define ITEM_TYPE_CHECKBOX 3 // check box
#define ITEM_TYPE_EDITFIELD 4 // editable text, associated with a dvar
#define ITEM_TYPE_COMBO 5 // drop down list
#define ITEM_TYPE_LISTBOX 6 // scrollable list
#define ITEM_TYPE_MODEL 7 // model
#define ITEM_TYPE_OWNERDRAW 8 // owner draw, name specs what it is
#define ITEM_TYPE_NUMERICFIELD 9 // editable text, associated with a dvar
#define ITEM_TYPE_SLIDER 10 // mouse speed, volume, etc.
#define ITEM_TYPE_YESNO 11 // yes no dvar setting
#define ITEM_TYPE_MULTI 12 // multiple list setting, enumerated
#define ITEM_TYPE_DVARENUM 13 // multiple list setting, enumerated from a dvar
#define ITEM_TYPE_BIND 14 // bind
#define ITEM_TYPE_MENUMODEL 15 // special menu model
#define ITEM_TYPE_VALIDFILEFIELD 16 // text must be valid for use in a dos filename
#define ITEM_TYPE_DECIMALFIELD 17 // editable text, associated with a dvar, which allows decimal input
#define ITEM_TYPE_UPREDITFIELD 18 // editable text, associated with a dvar
#define ITEM_TYPE_GAME_MESSAGE_WINDOW 19 // game message window
#define ITEM_TYPE_NEWSTICKER 20 // horizontal scrollbox
#define ITEM_TYPE_TEXTSCROLL 21 // vertical scrollbox
#define ITEM_TYPE_EMAILFIELD 22
#define ITEM_TYPE_PASSWORDFIELD 23
struct UIFunctionList
{
int totalFunctions;
Statement_s** functions;
};
struct StaticDvar
{
/*dvar_t*/
void* dvar;
const char* dvarName;
};
struct StaticDvarList
{
int numStaticDvars;
StaticDvar** staticDvars;
};
struct StringList
{
int totalStrings;
const char** strings;
};
struct ExpressionSupportingData
{
UIFunctionList uifunctions;
StaticDvarList staticDvarList;
StringList uiStrings;
};
enum expDataType : int
{
VAL_INT = 0x0,
VAL_FLOAT = 0x1,
VAL_STRING = 0x2,
VAL_FUNCTION = 0x3,
};
struct ExpressionString
{
const char* string;
};
union operandInternalDataUnion
{
int intVal;
float floatVal;
ExpressionString stringVal;
Statement_s* function;
};
struct Operand
{
expDataType dataType;
operandInternalDataUnion internals;
};
union entryInternalData
{
operationEnum op; /* operationEnum */
Operand operand;
};
/* expressionEntry->type */
#define OPERATOR 0
#define OPERAND 1
struct expressionEntry // 0xC
{
int type;
entryInternalData data;
};
struct Statement_s // 0x18
{
int numEntries;
expressionEntry* entries;
ExpressionSupportingData* supportingData;
int lastExecuteTime;
Operand lastResult;
};
struct SetLocalVarData
{
const char* localVarName;
Statement_s* expression;
};
struct ConditionalScript
{
MenuEventHandlerSet* eventHandlerSet;
Statement_s* eventExpression; // loads this first
};
union EventData
{
const char* unconditionalScript;
ConditionalScript* conditionalScript;
MenuEventHandlerSet* elseScript;
SetLocalVarData* setLocalVarData;
};
enum EventType
{
EVENT_UNCONDITIONAL = 0x0,
EVENT_IF = 0x1,
EVENT_ELSE = 0x2,
EVENT_SET_LOCAL_VAR_BOOL = 0x3,
EVENT_SET_LOCAL_VAR_INT = 0x4,
EVENT_SET_LOCAL_VAR_FLOAT = 0x5,
EVENT_SET_LOCAL_VAR_STRING = 0x6,
EVENT_COUNT = 0x7,
};
struct MenuEventHandler
{
EventData eventData;
EventType eventType;
};
struct MenuEventHandlerSet
{
int eventHandlerCount;
MenuEventHandler** eventHandlers;
};
struct ItemKeyHandler
{
int key;
MenuEventHandlerSet* action;
ItemKeyHandler* next;
};
struct windowDef_t // 0xA4
{
const char* name; // 0x00
rectDef_s rect;
rectDef_s rectClient;
char* group; // 0x2C
int style; // 0x30
int border; // 0x34
int ownerDraw; // 0x38
int ownerDrawFlags; // 0x3C
float borderSize; // 0x40
int staticFlags; // 0x44
int dynamicFlags; // 0x48
int nextTime; // 0x4C
float foreColor[4]; // 0x50
float backColor[4]; // 0x60
float borderColor[4];// 0x70
float outlineColor[4];// 0x80
float disableColor[4];// 0x90
Material* background; // 0xA0
};
enum ItemFloatExpressionTarget
{
ITEM_FLOATEXP_TGT_RECT_X = 0x0,
ITEM_FLOATEXP_TGT_RECT_Y = 0x1,
ITEM_FLOATEXP_TGT_RECT_W = 0x2,
ITEM_FLOATEXP_TGT_RECT_H = 0x3,
ITEM_FLOATEXP_TGT_FORECOLOR_R = 0x4,
ITEM_FLOATEXP_TGT_FORECOLOR_G = 0x5,
ITEM_FLOATEXP_TGT_FORECOLOR_B = 0x6,
ITEM_FLOATEXP_TGT_FORECOLOR_RGB = 0x7,
ITEM_FLOATEXP_TGT_FORECOLOR_A = 0x8,
ITEM_FLOATEXP_TGT_GLOWCOLOR_R = 0x9,
ITEM_FLOATEXP_TGT_GLOWCOLOR_G = 0xA,
ITEM_FLOATEXP_TGT_GLOWCOLOR_B = 0xB,
ITEM_FLOATEXP_TGT_GLOWCOLOR_RGB = 0xC,
ITEM_FLOATEXP_TGT_GLOWCOLOR_A = 0xD,
ITEM_FLOATEXP_TGT_BACKCOLOR_R = 0xE,
ITEM_FLOATEXP_TGT_BACKCOLOR_G = 0xF,
ITEM_FLOATEXP_TGT_BACKCOLOR_B = 0x10,
ITEM_FLOATEXP_TGT_BACKCOLOR_RGB = 0x11,
ITEM_FLOATEXP_TGT_BACKCOLOR_A = 0x12,
ITEM_FLOATEXP_TGT__COUNT = 0x13,
};
struct ItemFloatExpression
{
ItemFloatExpressionTarget target;
Statement_s* expression;
};
struct editFieldDef_s
{
float minVal;
float maxVal;
float defVal;
float range;
int maxChars;
int maxCharsGotoNext;
int maxPaintChars;
int paintOffset;
};
struct multiDef_s // 0x188
{
const char* dvarList[32];
const char* dvarStr[32];
float dvarValue[32];
int count;
int strDef;
};
struct columnInfo_s
{
int xpos;
int width;
int maxChars;
int alignment;
};
struct listBoxDef_s // 0x144
{
int mousePos;
int startPos[1];
int endPos[1];
int drawPadding;
float elementWidth;
float elementHeight;
int elementStyle;
int numColumns;
columnInfo_s columnInfo[16];
MenuEventHandlerSet* doubleClick; // 0xC8
int notselectable;
int noscrollbars;
int usepaging;
float selectBorder[4];
Material* selectIcon;
};
struct newsTickerDef_s
{
int feedId;
int speed;
int spacing;
int lastTime;
int start;
int end;
float x;
};
struct textScrollDef_s
{
int startTime;
};
union itemDefData_t
{
listBoxDef_s* listBox;
editFieldDef_s* editField;
newsTickerDef_s* ticker;
multiDef_s* multiDef;
const char* enumDvarName;
textScrollDef_s* scroll;
void* data;
};
struct itemDef_t
{
windowDef_t window;
rectDef_s textRect[1];
int type;
int dataType;
int alignment;
int fontEnum;
int textAlignMode;
float textAlignX;
float textAlignY;
float textScale;
int textStyle;
int gameMsgWindowIndex;
int gameMsgWindowMode;
const char* text;
int textSaveGameInfo;
int parent;
MenuEventHandlerSet* mouseEnterText;
MenuEventHandlerSet* mouseExitText;
MenuEventHandlerSet* mouseEnter;
MenuEventHandlerSet* mouseExit;
MenuEventHandlerSet* action;
MenuEventHandlerSet* accept;
MenuEventHandlerSet* onFocus;
MenuEventHandlerSet* leaveFocus;
const char* dvar;
const char* dvarTest;
ItemKeyHandler* onKey;
const char* enableDvar;
const char* localVar;
int dvarFlags;
const char* focusSound;
float special;
int cursorPos[1];
itemDefData_t typeData;
int imageTrack;
int floatExpressionCount;
ItemFloatExpression* floatExpressions;
Statement_s* visibleExp;
Statement_s* disabledExp;
Statement_s* textExp;
Statement_s* materialExp;
float glowColor[4];
bool decayActive;
int fxBirthTime;
int fxLetterTime;
int fxDecayStartTime;
int fxDecayDuration;
int lastSoundPlayedTime;
};
struct menuTransition // 0x1C
{
int transitionType;
int targetField;
int startTime;
float startVal;
float endVal;
float time;
int endTriggerType;
};
struct menuDef_t
{
windowDef_t window;
int font;
int fullscreen;
int itemCount;
int fontIndex;
int cursorItems;
int fadeCycle;
float fadeClamp;
float fadeAmount;
float fadeInAmount;
float blurRadius;
MenuEventHandlerSet* onOpen;
MenuEventHandlerSet* onRequestClose;
MenuEventHandlerSet* onClose;
MenuEventHandlerSet* onEsc;
ItemKeyHandler* onKey;
Statement_s* visibleExp;
const char* allowedBinding;
const char* soundLoop;
int imageTrack;
float focusColor[4];
Statement_s* rectXExp;
Statement_s* rectYExp;
Statement_s* rectHExp;
Statement_s* rectWExp;
Statement_s* openSoundExp;
Statement_s* closeSoundExp;
itemDef_t** items;
menuTransition scaleTransition[1];
menuTransition alphaTransition[1];
menuTransition xTransition[1];
menuTransition yTransition[1];
ExpressionSupportingData* expressionData;
};
struct MenuList
{
const char* name;
int menuCount;
menuDef_t** menus;
};
// Localized Strings
struct LocalizeEntry
{
@ -3482,6 +4112,7 @@ namespace ZoneTool
StringTable* stringtable;
ComWorld* comworld;
ComWorld* com_map;
menuDef_t* menu;
LocalizeEntry* localize;
SndCurve* soundcurve;
SndCurve* sndcurve;

View File

@ -128,6 +128,7 @@ namespace ZoneTool
DECLARE_ASSET(lightdef, ILightDef);
DECLARE_ASSET(structureddatadef, IStructuredDataDef);
DECLARE_ASSET(addon_map_ents, IAddonMapEnts);
DECLARE_ASSET(menu, IMenuDef);
}
void Zone::add_asset_of_type(const std::string& type, const std::string& name)

View File

@ -41,6 +41,7 @@ extern std::string currentzone;
#include "Assets/LightDef.hpp"
#include "Assets/StructuredDataDef.hpp"
#include "Assets/AddonMapEnts.hpp"
#include "Assets/MenuDef.hpp"
namespace ZoneTool
{