mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-11 09:48:08 +08:00
feat(lua): add Vehicle
This commit is contained in:
1 parent
55f4e297a0
commit
d14031fc6b
6 files changed
+251
-6
No files matched your search
@@ -8,6 +8,7 @@ namespace YimMenu::Lua
|
||||
class Metatable
|
||||
{
|
||||
inline static int m_Index;
|
||||
inline static std::vector<int> m_Subclasses;
|
||||
|
||||
public:
|
||||
static inline void Register(lua_State* state)
|
||||
@@ -19,6 +20,17 @@ namespace YimMenu::Lua
|
||||
{
|
||||
return m_Index;
|
||||
}
|
||||
|
||||
static inline const std::vector<int>& GetSubclasses()
|
||||
{
|
||||
return m_Subclasses;
|
||||
}
|
||||
|
||||
template<typename T2>
|
||||
static inline void AddSubclass()
|
||||
{
|
||||
m_Subclasses.push_back(Metatable<T2>::Get());
|
||||
}
|
||||
};
|
||||
|
||||
// Tries to get the userdata or errors out
|
||||
@@ -34,12 +46,34 @@ namespace YimMenu::Lua
|
||||
|
||||
lua_rawgeti(state, LUA_REGISTRYINDEX, Metatable<T>::Get());
|
||||
auto equals = lua_rawequal(state, -1, -2);
|
||||
lua_pop(state, 2);
|
||||
lua_pop(state, 1);
|
||||
|
||||
if (!equals)
|
||||
luaL_argerror(state, idx, "the metatable for this userdata at this index is incorrect");
|
||||
if (equals)
|
||||
{
|
||||
lua_pop(state, 1);
|
||||
return *reinterpret_cast<T*>(data);
|
||||
}
|
||||
|
||||
return *reinterpret_cast<T*>(data);
|
||||
const auto& subclasses = Metatable<T>::GetSubclasses();
|
||||
if (!equals && subclasses.size())
|
||||
{
|
||||
for (const auto subclass : subclasses)
|
||||
{
|
||||
lua_rawgeti(state, LUA_REGISTRYINDEX, subclass);
|
||||
auto equals = lua_rawequal(state, -1, -2);
|
||||
lua_pop(state, 1);
|
||||
|
||||
if (equals)
|
||||
{
|
||||
lua_pop(state, 1);
|
||||
return *reinterpret_cast<T*>(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(state, 1);
|
||||
luaL_argerror(state, idx, "the metatable for this userdata at this index is incorrect");
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
inline void SetFunction(lua_State* state, lua_CFunction func, const char* name)
|
||||
|
||||
@@ -21,13 +21,72 @@ namespace YimMenu::Lua
|
||||
return 1;
|
||||
}
|
||||
|
||||
// returns three values
|
||||
static int GetCoords(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).x);
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).y);
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int GetX(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetY(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).y);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetZ(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).z);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetX(lua_State* state)
|
||||
{
|
||||
GetObject<rage::fvector3>(state, 1).x = luaL_checknumber(state, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetY(lua_State* state)
|
||||
{
|
||||
GetObject<rage::fvector3>(state, 1).y = luaL_checknumber(state, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetZ(lua_State* state)
|
||||
{
|
||||
GetObject<rage::fvector3>(state, 1).z = luaL_checknumber(state, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetDistance(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<rage::fvector3>(state, 1).GetDistance(GetObject<rage::fvector3>(state, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void Register(lua_State* state) override
|
||||
{
|
||||
luaL_newmetatable(state, "Vector3");
|
||||
{
|
||||
lua_newtable(state);
|
||||
{
|
||||
// TODO?
|
||||
SetFunction(state, GetCoords, "get_coords");
|
||||
SetFunction(state, GetX, "get_x");
|
||||
SetFunction(state, GetY, "get_y");
|
||||
SetFunction(state, GetZ, "get_z");
|
||||
SetFunction(state, SetX, "set_x");
|
||||
SetFunction(state, SetY, "set_y");
|
||||
SetFunction(state, SetZ, "set_z");
|
||||
SetFunction(state, SetZ, "set_z");
|
||||
SetFunction(state, GetDistance, "get_distance");
|
||||
}
|
||||
lua_setfield(state, -2, "__index"); // prototype
|
||||
}
|
||||
|
||||
@@ -115,6 +115,13 @@ namespace YimMenu
|
||||
VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, false);
|
||||
}
|
||||
|
||||
std::string Vehicle::GetPlateText()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
return VEHICLE::GET_VEHICLE_NUMBER_PLATE_TEXT(GetHandle());
|
||||
}
|
||||
|
||||
void Vehicle::SetPlateText(std::string_view text)
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace YimMenu
|
||||
|
||||
// mods
|
||||
void Upgrade();
|
||||
std::string GetPlateText();
|
||||
void SetPlateText(std::string_view text);
|
||||
std::map<int, int32_t> GetOwnedMods();
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ def create_lua_namespace(name: str, natives: list[NativeFunc]):
|
||||
|
||||
def create_lua_defs():
|
||||
with open("../../scripting/libraries/NativeDefs.cpp", "w+") as file:
|
||||
string = "#pragma once\n#include \"NativeDefs.hpp\"\n\nconst char* g_LuaNativeDefs[] = \n{\n"
|
||||
string = "#include \"NativeDefs.hpp\"\n\nconst char* g_LuaNativeDefs[] = \n{\n"
|
||||
for ns, natives_list in natives.items():
|
||||
string += create_lua_namespace(ns, natives_list)
|
||||
string += f"}};\n\nint g_NumLuaNativeDefs = {len(natives.items())};"
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "core/scripting/LuaLibrary.hpp"
|
||||
#include "core/scripting/LuaScript.hpp"
|
||||
#include "core/scripting/LuaUtils.hpp"
|
||||
#include "core/scripting/LatentFunction.hpp"
|
||||
#include "game/gta/Vehicle.hpp"
|
||||
#include "Entity.hpp"
|
||||
|
||||
namespace YimMenu::Lua
|
||||
{
|
||||
// TODO: we need to automate this
|
||||
class Vehicle : LuaLibrary
|
||||
{
|
||||
public:
|
||||
using LuaLibrary::LuaLibrary;
|
||||
|
||||
static int New(lua_State* state)
|
||||
{
|
||||
CreateObject<YimMenu::Vehicle>(state, luaL_checkinteger(state, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Create(lua_State* state)
|
||||
{
|
||||
CopyObject<YimMenu::Vehicle>(state, YimMenu::Vehicle::Create(GetHashArgument(state, 1), GetObject<rage::fvector3>(state, 2), lua_gettop(state) >= 3 ? luaL_checknumber(state, 3) : 0.0f));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Fix(lua_State* state)
|
||||
{
|
||||
GetObject<YimMenu::Vehicle>(state, 1).Fix();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetGear(lua_State* state)
|
||||
{
|
||||
lua_pushinteger(state, GetObject<YimMenu::Vehicle>(state, 1).GetGear());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetRevRatio(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<YimMenu::Vehicle>(state, 1).GetRevRatio());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetSpeed(lua_State* state)
|
||||
{
|
||||
lua_pushnumber(state, GetObject<YimMenu::Vehicle>(state, 1).GetSpeed());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int Upgrade(lua_State* state)
|
||||
{
|
||||
GetObject<YimMenu::Vehicle>(state, 1).Upgrade();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetPlateText(lua_State* state)
|
||||
{
|
||||
auto text = GetObject<YimMenu::Vehicle>(state, 1).GetPlateText();
|
||||
lua_pushlstring(state, text.c_str(), text.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetPlateText(lua_State* state)
|
||||
{
|
||||
GetObject<YimMenu::Vehicle>(state, 1).SetPlateText(CheckStringSafe(state, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GetOwnedMods
|
||||
|
||||
static int IsSeatFree(lua_State* state)
|
||||
{
|
||||
lua_pushboolean(state, GetObject<YimMenu::Vehicle>(state, 1).IsSeatFree(luaL_checkinteger(state, 2)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SupportsBoost(lua_State* state)
|
||||
{
|
||||
lua_pushboolean(state, GetObject<YimMenu::Vehicle>(state, 1).SupportsBoost());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int IsBoostActive(lua_State* state)
|
||||
{
|
||||
lua_pushboolean(state, GetObject<YimMenu::Vehicle>(state, 1).IsBoostActive());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SetBoostCharge(lua_State* state)
|
||||
{
|
||||
GetObject<YimMenu::Vehicle>(state, 1).SetBoostCharge(lua_gettop(state) >= 2 ? luaL_checkinteger(state, 3) : 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LowerStance(lua_State* state)
|
||||
{
|
||||
GetObject<YimMenu::Vehicle>(state, 1).LowerStance(CheckBooleanSafe(state, 2));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetFullName(lua_State* state)
|
||||
{
|
||||
auto name = GetObject<YimMenu::Vehicle>(state, 1).GetFullName();
|
||||
lua_pushlstring(state, name.c_str(), name.size());
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual void Register(lua_State* state) override
|
||||
{
|
||||
luaL_newmetatable(state, "Vehicle");
|
||||
{
|
||||
lua_newtable(state);
|
||||
{
|
||||
RegisterEntityMethods(state); // re-registering the entity methods under the vehicle table is more efficient than subclassing
|
||||
SetFunction(state, Fix, "fix");
|
||||
SetFunction(state, GetGear, "get_gear");
|
||||
SetFunction(state, GetRevRatio, "get_rev_ratio");
|
||||
SetFunction(state, GetSpeed, "get_speed");
|
||||
SetFunction(state, Upgrade, "upgrade");
|
||||
SetFunction(state, GetPlateText, "get_plate_text");
|
||||
SetFunction(state, SetPlateText, "set_plate_text");
|
||||
SetFunction(state, IsSeatFree, "is_seat_free");
|
||||
SetFunction(state, SupportsBoost, "supports_boost");
|
||||
SetFunction(state, IsBoostActive, "is_boost_active");
|
||||
SetFunction(state, SetBoostCharge, "set_boost_charge");
|
||||
SetFunction(state, LowerStance, "lower_stance");
|
||||
SetFunction(state, GetFullName, "get_full_name");
|
||||
}
|
||||
lua_setfield(state, -2, "__index"); // prototype
|
||||
}
|
||||
Metatable<YimMenu::Vehicle>::Register(state);
|
||||
Metatable<YimMenu::Entity>::AddSubclass<YimMenu::Vehicle>();
|
||||
|
||||
lua_newtable(state);
|
||||
SetConstructor<New>(state);
|
||||
SetFunction(state, LatentFunction<Create>, "create");
|
||||
lua_setglobal(state, "Vehicle");
|
||||
}
|
||||
};
|
||||
|
||||
Vehicle _Vehicle;
|
||||
}
|
||||
Reference in new issue
Block a user