Mapents & scripting changes + some fixes
This commit is contained in:
parent
c71c20a29a
commit
a63ce4f254
@ -63,15 +63,22 @@ namespace asset_list
|
||||
ImGui::InputText("asset name", &assets_name_filter[type]);
|
||||
ImGui::BeginChild("assets list");
|
||||
|
||||
fastfiles::enum_assets(type, [type](const game::XAssetHeader header)
|
||||
size_t asset_num{};
|
||||
fastfiles::enum_assets(type, [type, &asset_num](const game::XAssetHeader header)
|
||||
{
|
||||
const auto asset = game::XAsset{type, header};
|
||||
const auto* const asset_name = game::DB_GetXAssetName(&asset);
|
||||
auto asset_name = game::DB_GetXAssetName(&asset);
|
||||
if (asset_name[0] == '\0')
|
||||
{
|
||||
asset_name = utils::string::va("__%i", asset_num);
|
||||
}
|
||||
|
||||
if (utils::string::strstr_lower(asset_name, assets_name_filter[type].data()) && ImGui::Button(asset_name))
|
||||
{
|
||||
gui::copy_to_clipboard(asset_name);
|
||||
}
|
||||
|
||||
asset_num++;
|
||||
}, true);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "scheduler.hpp"
|
||||
#include "mapents.hpp"
|
||||
#include "command.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
@ -22,7 +23,7 @@ namespace mapents
|
||||
game::dvar_t* addon_mapname = nullptr;
|
||||
utils::memory::allocator allocator;
|
||||
|
||||
std::unordered_map<std::string, int> keys =
|
||||
std::unordered_map<std::string, unsigned int> keys =
|
||||
{
|
||||
{"code_classname", 172},
|
||||
{"classname", 170},
|
||||
@ -50,7 +51,7 @@ namespace mapents
|
||||
{"skycolor", 34255},
|
||||
{"suncolor", 1049},
|
||||
{"sundirection", 1050},
|
||||
|
||||
{"modelscale", 23881},
|
||||
{"export", 13703},
|
||||
|
||||
{"script_flag", 31190},
|
||||
@ -72,8 +73,15 @@ namespace mapents
|
||||
{"script_parameters", 31388},
|
||||
{"script_combatmode", 31102},
|
||||
{"script_ammo_clip", 31034},
|
||||
{"script_moveoverride", 31299},
|
||||
{"script_forcegoal", 31212},
|
||||
{"script_ammo_max", 31036},
|
||||
};
|
||||
|
||||
std::unordered_map<unsigned int, game::scriptType_e> custom_fields;
|
||||
|
||||
unsigned int token_id_start = 0x16000;
|
||||
|
||||
// zonetool/iw4/addonmapents.cpp
|
||||
class asset_reader
|
||||
{
|
||||
@ -202,29 +210,27 @@ namespace mapents
|
||||
|
||||
empty = false;
|
||||
|
||||
auto key_id = 0;
|
||||
if (key[0] != '"')
|
||||
auto key_id = std::atoi(key.data());
|
||||
if (key_id != 0)
|
||||
{
|
||||
key_id = std::atoi(key.data());
|
||||
out_buffer.append(utils::string::va("%i \"%s\"\n", key_id, value.data()));
|
||||
continue;
|
||||
}
|
||||
else if (key.size() >= 3 && key[key.size() - 1] == '"')
|
||||
{
|
||||
const auto key_ = key.substr(1, key.size() - 2);
|
||||
if (keys.find(key_) == keys.end())
|
||||
{
|
||||
console::warn("[addon_map_ents parser] Key '%s' not found, on line %i", key_.data(), line_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
key_id = keys[key_];//
|
||||
}
|
||||
else
|
||||
if (key.size() < 3 || (!key.starts_with("\"") || !key.ends_with("\"")))
|
||||
{
|
||||
console::warn("[addon_map_ents parser] Bad key '%s' on line %i", key.data(), line_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
out_buffer.append(utils::string::va("%i \"%s\"\n", key_id, value.data()));
|
||||
const auto key_ = key.substr(1, key.size() - 2);
|
||||
if (keys.find(key_) == keys.end())
|
||||
{
|
||||
console::warn("[addon_map_ents parser] Key '%s' not found, on line %i", key_.data(), line_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
out_buffer.append(utils::string::va("%i \"%s\"\n", keys[key_], value.data()));
|
||||
}
|
||||
|
||||
return out_buffer;
|
||||
@ -257,6 +263,7 @@ namespace mapents
|
||||
void try_parse_mapents(const std::string& path, const std::string& data, game::AddonMapEnts* mapents)
|
||||
{
|
||||
const auto parsed = parse_mapents(data);
|
||||
utils::io::write_file("parsed_mapents.txt", parsed, false);
|
||||
|
||||
mapents->entityString = allocator.duplicate_string(parsed.data());
|
||||
mapents->numEntityChars = static_cast<int>(parsed.size()) + 1;
|
||||
@ -316,6 +323,26 @@ namespace mapents
|
||||
game::Com_Error(game::ERR_DROP, "CM_TriggerModelBounds: you are probably missing a mapents.triggers file");
|
||||
}
|
||||
}
|
||||
|
||||
void add_field(const std::string& name, game::scriptType_e type)
|
||||
{
|
||||
const auto id = token_id_start++;
|
||||
custom_fields[id] = type;
|
||||
keys[name] = id;
|
||||
scripting::token_map[name] = id;
|
||||
}
|
||||
|
||||
utils::hook::detour scr_find_field_hook;
|
||||
unsigned int scr_find_field_stub(unsigned int name, game::scriptType_e* type)
|
||||
{
|
||||
if (custom_fields.find(name) != custom_fields.end())
|
||||
{
|
||||
*type = custom_fields[name];
|
||||
return name;
|
||||
}
|
||||
|
||||
return scr_find_field_hook.invoke<unsigned int>(name, type);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_dvars()
|
||||
@ -333,6 +360,8 @@ namespace mapents
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
scr_find_field_hook.create(0x1405C5240, scr_find_field_stub);
|
||||
|
||||
scheduler::once([]()
|
||||
{
|
||||
addon_mapname = dvars::register_string("addon_mapname", "", 0, "");
|
||||
@ -365,6 +394,8 @@ namespace mapents
|
||||
utils::hook::call(0x14058BDD3, db_find_xasset_header_stub);
|
||||
utils::hook::call(0x14058BD6B, should_load_addon_mapents);
|
||||
utils::hook::call(0x1406B3384, cm_trigger_model_bounds_stub);
|
||||
|
||||
add_field("script_specialops", game::SCRIPT_INTEGER);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
animation::animation(unsigned int value)
|
||||
animation::animation(uint64_t value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace scripting
|
||||
class animation final
|
||||
{
|
||||
public:
|
||||
animation(unsigned int value);
|
||||
animation(uint64_t value);
|
||||
|
||||
uint64_t get_value() const;
|
||||
private:
|
||||
|
@ -39,6 +39,21 @@ namespace scripting
|
||||
|
||||
return script_value(game::scr_VmPub->top[1 - game::scr_VmPub->outparamcount]);
|
||||
}
|
||||
|
||||
bool is_entity_variable(const game::scr_entref_t& entref, const unsigned int id)
|
||||
{
|
||||
const auto type = game::scr_VarGlob->objectVariableValue[id].w.type;
|
||||
if (entref.classnum == 0)
|
||||
{
|
||||
return type == game::SCRIPT_ENTITY;
|
||||
}
|
||||
else if (entref.classnum > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void push_value(const script_value& value)
|
||||
@ -149,8 +164,9 @@ namespace scripting
|
||||
{
|
||||
const auto entref = entity.get_entity_reference();
|
||||
const int id = get_field_id(entref.classnum, field);
|
||||
const auto ent_id = entity.get_entity_id();
|
||||
|
||||
if (id != -1)
|
||||
if (id != -1 && is_entity_variable(entref, ent_id))
|
||||
{
|
||||
stack_isolation _;
|
||||
push_value(value);
|
||||
@ -165,7 +181,7 @@ namespace scripting
|
||||
}
|
||||
else
|
||||
{
|
||||
set_object_variable(entity.get_entity_id(), field, value);
|
||||
set_object_variable(ent_id, field, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,8 +189,9 @@ namespace scripting
|
||||
{
|
||||
const auto entref = entity.get_entity_reference();
|
||||
const auto id = get_field_id(entref.classnum, field);
|
||||
const auto ent_id = entity.get_entity_id();
|
||||
|
||||
if (id != -1)
|
||||
if (id != -1 && is_entity_variable(entref, ent_id))
|
||||
{
|
||||
stack_isolation _;
|
||||
|
||||
@ -192,7 +209,7 @@ namespace scripting
|
||||
return value;
|
||||
}
|
||||
|
||||
return get_object_variable(entity.get_entity_id(), field);
|
||||
return get_object_variable(ent_id, field);
|
||||
}
|
||||
|
||||
unsigned int make_array()
|
||||
|
@ -411,9 +411,9 @@ namespace scripting
|
||||
{"objective_delete", 0x1E4}, // 0x50FA30
|
||||
{"objective_state", 0x1E5}, // 0x50EFD0
|
||||
{"objective_icon", 0x1E6}, // 0x50F010
|
||||
{"objective_position", 0x1E7}, // 0x50F110
|
||||
{"objective_current", 0x1E8}, // 0x50F1B0
|
||||
{"_func_1e9", 0x1E9}, // similar to objective_current_nomessage
|
||||
{"_func_1e7", 0x1E7}, // 0x50F110
|
||||
{"objective_position", 0x1E8}, // 0x50F1B0
|
||||
{"objective_current", 0x1E9}, // similar to objective_current_nomessage
|
||||
{"weaponinventorytype", 0x1EA}, // 0x4EE760
|
||||
{"weaponstartammo", 0x1EB}, // 0x4EE920
|
||||
{"weaponmaxammo", 0x1EC}, // 0x4EEB40
|
||||
@ -1778,10 +1778,253 @@ namespace scripting
|
||||
|
||||
std::unordered_map<std::string, unsigned> token_map =
|
||||
{
|
||||
{"maps/_utility", 42407},
|
||||
{"common_scripts/utility", 42237},
|
||||
{"maps/_load", 42323},
|
||||
{"maps/_compass", 42272},
|
||||
{"maps/_spawner", 42372},
|
||||
|
||||
{"init", 521},
|
||||
{"main", 616},
|
||||
{"player", 794},
|
||||
{"default_start", 10126},
|
||||
{"maps/_utility", 42407},
|
||||
{"setupminimap", 33575},
|
||||
{"set_player_viewhand_model", 32417},
|
||||
|
||||
// built-in entity fields
|
||||
{"code_classname", 172},
|
||||
{"classname", 170},
|
||||
{"model", 669},
|
||||
{"count", 216},
|
||||
{"health", 486},
|
||||
{"dmg", 293},
|
||||
{"maxhealth", 626},
|
||||
{"anglelerprate", 64},
|
||||
{"activator", 19},
|
||||
{"slidevelocity", 974},
|
||||
{"disableplayeradsloscheck", 291},
|
||||
{"accuracy", 10},
|
||||
{"lookforward", 604},
|
||||
{"lookright", 605},
|
||||
{"lookup", 607},
|
||||
{"fovcosine", 411},
|
||||
{"fovcosinebusy", 412},
|
||||
{"fovcosinez", 413},
|
||||
{"upaimlimit", 1252},
|
||||
{"downaimlimit", 307},
|
||||
{"rightaimlimit", 894},
|
||||
{"leftaimlimit", 590},
|
||||
{"maxsightdistsqrd", 628},
|
||||
{"sightlatency", 967},
|
||||
{"defaultsightlatency", 968},
|
||||
{"ignoreclosefoliage", 508},
|
||||
{"interval", 525},
|
||||
{"teammovewaittime", 1199},
|
||||
{"damagetaken", 257},
|
||||
{"damagedir", 252},
|
||||
{"damageyaw", 259},
|
||||
{"damagelocation", 253},
|
||||
{"damageweapon", 258},
|
||||
{"damagemod", 254},
|
||||
{"proneok", 841},
|
||||
{"walkdistfacingmotion", 1299},
|
||||
{"walkdist", 1298},
|
||||
{"desiredangle", 278},
|
||||
{"pacifist", 744},
|
||||
{"pacifistwait", 745},
|
||||
{"footstepdetectdist", 398},
|
||||
{"footstepdetectdistwalk", 400},
|
||||
{"footstepdetectdistsprint", 399},
|
||||
{"reactiontargetpos", 859},
|
||||
{"newenemyreactiondistsq", 686},
|
||||
{"ignoreexplosionevents", 509},
|
||||
{"ignoresuppression", 513},
|
||||
{"suppressionwait", 1060},
|
||||
{"suppressionduration", 1056},
|
||||
{"suppressionstarttime", 1058},
|
||||
{"suppressionmeter", 1057},
|
||||
{"ignoreplayersuppression", 514},
|
||||
{"name", 680},
|
||||
{"weapon", 1302},
|
||||
{"dontavoidplayer", 304},
|
||||
{"grenadeawareness", 465},
|
||||
{"grenade", 458},
|
||||
{"grenadeweapon", 470},
|
||||
{"grenadeammo", 464},
|
||||
{"grenadetargetpos", 467},
|
||||
{"grenadetargetvalid", 468},
|
||||
{"grenadetossvel", 469},
|
||||
{"favoriteenemy", 377},
|
||||
{"highlyawareradius", 495},
|
||||
{"minpaindamage", 642},
|
||||
{"allowpain", 52},
|
||||
{"allowdeath", 49},
|
||||
{"delayeddeath", 274},
|
||||
{"diequietly", 287},
|
||||
{"forceragdollimmediate", 405},
|
||||
{"providecoveringfire", 842},
|
||||
{"doingambush", 302},
|
||||
{"combatmode", 199},
|
||||
{"alertlevel", 38},
|
||||
{"alertlevelint", 39},
|
||||
{"useable", 1257},
|
||||
{"ignoretriggers", 515},
|
||||
{"pushable", 846},
|
||||
{"script_pushable", 926},
|
||||
{"dropweapon", 309},
|
||||
{"drawoncompass", 308},
|
||||
{"groundtype", 474},
|
||||
{"anim_pose", 68},
|
||||
{"goalradius", 452},
|
||||
{"goalheight", 450},
|
||||
{"goalpos", 451},
|
||||
{"nodeoffsetpos", 705},
|
||||
{"ignoreforfixednodesafecheck", 510},
|
||||
{"fixednode", 381},
|
||||
{"fixednodesaferadius", 382},
|
||||
{"pathgoalpos", 762},
|
||||
{"pathrandompercent", 764},
|
||||
{"usechokepoints", 1258},
|
||||
{"stopanimdistsq", 1044},
|
||||
{"lastenemysightpos", 584},
|
||||
{"pathenemylookahead", 761},
|
||||
{"pathenemyfightdist", 760},
|
||||
{"meleeattackdist", 633},
|
||||
{"movemode", 675},
|
||||
{"script_move_distance_override", 31298},
|
||||
{"usecombatscriptatcover", 1259},
|
||||
{"safetochangescript", 906},
|
||||
{"keepclaimednode", 561},
|
||||
{"keepclaimednodeifvalid", 562},
|
||||
{"keepnodeduringscriptedanim", 563},
|
||||
{"dodangerreact", 295},
|
||||
{"dangerreactduration", 260},
|
||||
{"nododgemove", 706},
|
||||
{"noteammove", 707},
|
||||
{"leanamount", 587},
|
||||
{"pitchamount", 788},
|
||||
{"turnrate", 1230},
|
||||
{"turnanimactive", 1229},
|
||||
{"badplaceawareness", 107},
|
||||
{"damageshield", 256},
|
||||
{"nogrenadereturnthrow", 709},
|
||||
{"noattackeraccuracymod", 698},
|
||||
{"frontshieldanglecos", 426},
|
||||
{"lookaheaddir", 601},
|
||||
{"lookaheaddist", 602},
|
||||
{"lookaheadhitsstairs", 603},
|
||||
{"velocity", 1283},
|
||||
{"prevanimdelta", 821},
|
||||
{"exposedduration", 356},
|
||||
{"requestarrivalnotify", 875},
|
||||
{"scriptedarrivalent", 938},
|
||||
{"goingtoruntopos", 455},
|
||||
{"engagemindist", 334},
|
||||
{"engageminfalloffdist", 335},
|
||||
{"engagemaxdist", 332},
|
||||
{"engagemaxfalloffdist", 333},
|
||||
{"usingcovermoveup", 42987},
|
||||
{"finalaccuracy", 378},
|
||||
{"facemotion", 373},
|
||||
{"gunblockedbywall", 475},
|
||||
{"relativedir", 866},
|
||||
{"lockorientation", 597},
|
||||
{"maxfaceenemydist", 625},
|
||||
{"stairsstate", 1012},
|
||||
{"script", 912},
|
||||
{"prevscript", 823},
|
||||
{"headicon", 483},
|
||||
{"headiconteam", 484},
|
||||
{"coversearchinterval", 219},
|
||||
{"threatupdateinterval", 37018},
|
||||
{"canclimbladders", 150},
|
||||
{"swimmer", 1063},
|
||||
{"space", 986},
|
||||
{"doghandler", 301},
|
||||
{"sharpturnlookaheaddist", 961},
|
||||
{"postsharpturnlookaheaddist", 813},
|
||||
{"sharpturntooclosetodestdist", 963},
|
||||
{"usepathsmoothingvalues", 1262},
|
||||
{"pathlookaheaddist", 763},
|
||||
{"maxturnspeed", 629},
|
||||
{"sharpturn", 960},
|
||||
{"disablesightandthreatupdate", 54743},
|
||||
{"team", 1194},
|
||||
{"threatbias", 1204},
|
||||
{"threatbiasgroup", 1205},
|
||||
{"node", 700},
|
||||
{"prevnode", 822},
|
||||
{"enemy", 322},
|
||||
{"syncedmeleetarget", 1065},
|
||||
{"lastattacker", 583},
|
||||
{"lastpusher", 42997},
|
||||
{"ignoreme", 511},
|
||||
{"ignoreall", 507},
|
||||
{"maxvisibledist", 630},
|
||||
{"surprisedbymedistsq", 1062},
|
||||
{"attackeraccuracy", 86},
|
||||
{"ignorerandombulletdamage", 512},
|
||||
{"dodamagetoall", 294},
|
||||
{"turretinvulnerability", 1240},
|
||||
{"useorcaavoidance", 1261},
|
||||
{"reciprocality", 863},
|
||||
{"avoidanceboundshalfsize", 94},
|
||||
{"onlygoodnearestnodes", 735},
|
||||
{"playername", 803},
|
||||
{"deathinvulnerabletime", 266},
|
||||
{"criticalbulletdamagedist", 222},
|
||||
{"attackercount", 87},
|
||||
{"damagemultiplier", 255},
|
||||
{"laststand", 586},
|
||||
{"motiontrackerenabled", 672},
|
||||
{"veh_speed", 1276},
|
||||
{"veh_pathspeed", 1273},
|
||||
{"veh_transmission", 1279},
|
||||
{"veh_pathdir", 1272},
|
||||
{"veh_pathtype", 1274},
|
||||
{"veh_topspeed", 1278},
|
||||
{"veh_brake", 1266},
|
||||
{"veh_throttle", 1277},
|
||||
{"x", 1331},
|
||||
{"y", 1339},
|
||||
{"z", 1342},
|
||||
{"fontscale", 393},
|
||||
{"font", 392},
|
||||
{"alignx", 44},
|
||||
{"aligny", 45},
|
||||
{"horzalign", 499},
|
||||
{"vertalign", 1284},
|
||||
{"color", 196},
|
||||
{"alpha", 55},
|
||||
{"label", 578},
|
||||
{"sort", 983},
|
||||
{"foreground", 408},
|
||||
{"lowresbackground", 612},
|
||||
{"hidewhendead", 491},
|
||||
{"hidewheninmenu", 493},
|
||||
{"glowcolor", 445},
|
||||
{"glowalpha", 444},
|
||||
{"positioninworld", 812},
|
||||
{"relativeoffset", 867},
|
||||
{"enablehudlighting", 315},
|
||||
{"enableinputprogressicon", 42996},
|
||||
{"rotation", 902},
|
||||
{"targetname", 1193},
|
||||
{"target", 1191},
|
||||
{"animscript", 71},
|
||||
{"script_linkname", 920},
|
||||
{"script_noteworthy", 922},
|
||||
{"origin", 740},
|
||||
{"angles", 65},
|
||||
{"minusedistsq", 643},
|
||||
{"parentname", 749},
|
||||
{"spawnflags", 989},
|
||||
{"type", 1244},
|
||||
{"owner", 743},
|
||||
{"radius", 851},
|
||||
{"customangles", 9555},
|
||||
{"speed", 997},
|
||||
{"lookahead", 600},
|
||||
{"script_vehicle_anim", 40318},
|
||||
};
|
||||
}
|
||||
|
@ -326,6 +326,11 @@ namespace scripting::lua
|
||||
return keys;
|
||||
};
|
||||
|
||||
array_type["getentity"] = [](const array& array, const sol::this_state s)
|
||||
{
|
||||
return array.get_raw();
|
||||
};
|
||||
|
||||
auto entity_type = state.new_usertype<entity>("entity");
|
||||
|
||||
for (const auto& func : method_map)
|
||||
|
@ -176,6 +176,11 @@ namespace scripting::lua
|
||||
auto table = sol::table::create(state);
|
||||
auto metatable = sol::table::create(state);
|
||||
|
||||
table["getentity"] = [parent_id]()
|
||||
{
|
||||
return entity(parent_id);
|
||||
};
|
||||
|
||||
metatable[sol::meta_function::new_index] = [parent_id](const sol::table t, const sol::this_state s,
|
||||
const sol::lua_value& field, const sol::lua_value& value)
|
||||
{
|
||||
@ -287,11 +292,6 @@ namespace scripting::lua
|
||||
return {state, value.as<std::string>()};
|
||||
}
|
||||
|
||||
if (value.is<std::map<std::string, script_value>>())
|
||||
{
|
||||
return entity_to_struct(state, value.get_raw().u.uintValue);
|
||||
}
|
||||
|
||||
if (value.is<array>())
|
||||
{
|
||||
return {state, value.as<array>()};
|
||||
|
Loading…
Reference in New Issue
Block a user