Script struct support #132

This commit is contained in:
Federico Cecchetto 2021-05-09 21:15:47 +02:00
parent fbe83b9be7
commit f6aaf0a41c
8 changed files with 142 additions and 0 deletions

View File

@ -1490,4 +1490,33 @@ namespace scripting
{"sub_140320b40", 34155},
{"sub_140333710", 34156},
};
std::unordered_map<std::string, unsigned> token_map =
{
{"CodeCallback_BulletHitEntity", 180},
{"CodeCallback_CodeEndGame", 181},
{"CodeCallback_EntityDamage", 182},
{"CodeCallback_EntityOutOfWorld", 183},
{"CodeCallback_HostMigration", 185},
{"CodeCallback_PartyMembers", 187},
{"CodeCallback_PlayerConnect", 188},
{"CodeCallback_PlayerDamage", 189},
{"CodeCallback_PlayerDisconnect", 190},
{"CodeCallback_PlayerGrenadeSuicide", 191},
{"CodeCallback_PlayerKilled", 192},
{"CodeCallback_PlayerLastStand", 193},
{"CodeCallback_PlayerMigrated", 194},
{"CodeCallback_StartGameType", 195},
{"CodeCallback_VehicleDamage", 196},
{"CreateStruct", 221},
{"InitStructs", 522},
{"main", 619},
{"AbortLevel", 1727},
{"callbackVoid", 6662},
{"CodeCallback_GiveKillstreak", 8192},
{"SetDefaultCallbacks", 32577},
{"SetupCallbacks", 33531},
{"SetupDamageFlags", 33542},
{"struct", 36698},
};
}

View File

@ -71,6 +71,18 @@ namespace scripting
}
}
int find_token_id(const std::string& name)
{
const auto result = token_map.find(name);
if (result != token_map.end())
{
return result->second;
}
return -1;
}
script_function find_function(const std::string& name, const bool prefer_global)
{
const auto index = find_function_index(name, prefer_global);

View File

@ -5,8 +5,10 @@ namespace scripting
{
extern std::unordered_map<std::string, unsigned> method_map;
extern std::unordered_map<std::string, unsigned> function_map;
extern std::unordered_map<std::string, unsigned> token_map;
using script_function = void(*)(game::scr_entref_t);
int find_token_id(const std::string& name);
script_function find_function(const std::string& name, const bool prefer_global);
}

View File

@ -198,6 +198,13 @@ namespace scripting::lua
return convert(s, entity.get(field));
};
entity_type["getstruct"] = [](const entity& entity, const sol::this_state s)
{
const auto id = entity.get_entity_id();
return scripting::lua::entity_to_struct(s, id);
};
struct game
{
};

View File

@ -1,5 +1,6 @@
#include <std_include.hpp>
#include "value_conversion.hpp"
#include "../functions.hpp"
namespace scripting::lua
{
@ -110,6 +111,71 @@ namespace scripting::lua
}
}
sol::lua_value entity_to_struct(lua_State* state, unsigned int parent_id)
{
auto table = sol::table::create(state);
auto metatable = sol::table::create(state);
const auto offset = 64000 * (parent_id & 3);
metatable[sol::meta_function::new_index] = [offset, parent_id](const sol::table t, const sol::this_state s,
const sol::lua_value& field, const sol::lua_value& value)
{
const auto id = field.is<std::string>()
? scripting::find_token_id(field.as<std::string>())
: field.as<int>();
if (id == -1)
{
return;
}
const auto variable_id = game::GetVariable(parent_id, id);
if (!variable_id)
{
return;
}
const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + offset];
const auto new_variable = convert({s, value}).get_raw();
variable->type = (char)new_variable.type;
variable->u.u = new_variable.u;
};
metatable[sol::meta_function::index] = [offset, parent_id](const sol::table t, const sol::this_state s,
const sol::lua_value& field)
{
const auto id = field.is<std::string>()
? scripting::find_token_id(field.as<std::string>())
: field.as<int>();
if (id == -1)
{
return sol::lua_value{s};
}
const auto variable_id = game::GetVariable(parent_id, id);
if (!variable_id)
{
return sol::lua_value{s};
}
const auto variable = game::scr_VarGlob->childVariableValue[variable_id + offset];
game::VariableValue result{};
result.u = variable.u.u;
result.type = (game::scriptType_e)variable.type;
return convert(s, result);
};
table[sol::metatable_key] = metatable;
return {state, table};
}
script_value convert(const sol::lua_value& value)
{
if (value.is<int>())
@ -172,6 +238,11 @@ 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<std::vector<script_value>>())
{
return entity_to_array(state, value.get_raw().u.uintValue);

View File

@ -4,6 +4,8 @@
namespace scripting::lua
{
sol::lua_value entity_to_struct(lua_State* state, unsigned int parent_id);
script_value convert(const sol::lua_value& value);
sol::lua_value convert(lua_State* state, const script_value& value);
}

View File

@ -207,6 +207,24 @@ namespace scripting
return type == game::SCRIPT_ARRAY;
}
/***************************************************************
* Struct
**************************************************************/
template <>
bool script_value::is<std::map<std::string, script_value>>() const
{
if (this->get_raw().type != game::SCRIPT_OBJECT)
{
return false;
}
const auto id = this->get_raw().u.uintValue;
const auto type = game::scr_VarGlob->objectVariableValue[id].w.type;
return type == game::SCRIPT_ARRAY;
}
/***************************************************************
* Entity
**************************************************************/

View File

@ -101,6 +101,7 @@ namespace game
0x14031AAD0, 0x1403F72A0
};
WEAK symbol<unsigned int(unsigned int)> GetObjectType{0x140316F70, 0x1403F3670};
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x0, 0x1403F3730};
WEAK symbol<void()> G_Glass_Update{0x14021D540, 0x1402EDEE0};