diff --git a/Client/mods/deathmatch/logic/CClientColPolygon.cpp b/Client/mods/deathmatch/logic/CClientColPolygon.cpp index 6f7b8fa1b21..c1140c43774 100644 --- a/Client/mods/deathmatch/logic/CClientColPolygon.cpp +++ b/Client/mods/deathmatch/logic/CClientColPolygon.cpp @@ -69,20 +69,77 @@ void CClientColPolygon::SetPosition(const CVector& vecPosition) // Add queued collider refresh for v1.1 } -void CClientColPolygon::AddPoint(CVector2D vecPoint) +bool CClientColPolygon::AddPoint(CVector2D vecPoint, int iPointIndex) { - float fDistanceX = vecPoint.fX - m_vecPosition.fX; - float fDistanceY = vecPoint.fY - m_vecPosition.fY; + if (iPointIndex < 0) + { + m_Points.push_back(vecPoint); + } + else + { + if (iPointIndex >= m_Points.size()) + return false; - float fDist = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY); + m_Points.insert(m_Points.begin() + iPointIndex, vecPoint); + } - if (fDist > m_fRadius) + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) { - m_fRadius = fDist; + m_fRadius = fDistance; SizeChanged(); } - m_Points.push_back(vecPoint); + return true; +} + +bool CClientColPolygon::RemovePoint(unsigned int uiPointIndex) +{ + if (m_Points.size() <= 3) + return false; + + if (uiPointIndex >= m_Points.size()) + return false; + + m_Points.erase(m_Points.begin() + uiPointIndex); + + m_fRadius = 0.0f; + for (auto vecPoint : m_Points) + { + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) + m_fRadius = fDistance; + } + + SizeChanged(); + + return true; +} + +bool CClientColPolygon::SetPointPosition(unsigned int uiPointIndex, const CVector2D& vecPoint) +{ + if (uiPointIndex >= m_Points.size()) + return false; + + m_Points[uiPointIndex] = vecPoint; + + m_fRadius = 0.0f; + for (auto vecPoint : m_Points) + { + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) + m_fRadius = fDistance; + } + + SizeChanged(); + + return true; } bool CClientColPolygon::IsInBounds(CVector vecPoint) diff --git a/Client/mods/deathmatch/logic/CClientColPolygon.h b/Client/mods/deathmatch/logic/CClientColPolygon.h index 1ee97716f6d..15c1f8acc04 100644 --- a/Client/mods/deathmatch/logic/CClientColPolygon.h +++ b/Client/mods/deathmatch/logic/CClientColPolygon.h @@ -26,7 +26,9 @@ class CClientColPolygon : public CClientColShape void SetPosition(const CVector& vecPosition); - void AddPoint(CVector2D vecPoint); + bool AddPoint(CVector2D vecPoint, int iPointIndex = -1); + bool SetPointPosition(unsigned int uiPointIndex, const CVector2D& vecPoint); + bool RemovePoint(unsigned int uiPointIndex); unsigned int CountPoints() const { return static_cast(m_Points.size()); }; std::vector::const_iterator IterBegin() { return m_Points.begin(); }; diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 61737ab0eea..f0e5cf3b365 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1441,7 +1441,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned case CCLIENTPLAYER: { // Grab the model - CClientPed& Ped = static_cast(Entity); + CClientPed& Ped = static_cast(Entity); const unsigned short usCurrentModel = static_cast(Ped.GetModel()); if (usCurrentModel == usModel) @@ -1458,7 +1458,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned } case CCLIENTVEHICLE: { - CClientVehicle& Vehicle = static_cast(Entity); + CClientVehicle& Vehicle = static_cast(Entity); const unsigned short usCurrentModel = Vehicle.GetModel(); if (usCurrentModel == usModel) @@ -1478,7 +1478,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned case CCLIENTOBJECT: case CCLIENTWEAPON: { - CClientObject& Object = static_cast(Entity); + CClientObject& Object = static_cast(Entity); const unsigned short usCurrentModel = Object.GetModel(); if (usCurrentModel == usModel) @@ -1497,7 +1497,7 @@ bool CStaticFunctionDefinitions::SetElementModel(CClientEntity& Entity, unsigned } case CCLIENTPROJECTILE: { - CClientProjectile& Projectile = static_cast(Entity); + CClientProjectile& Projectile = static_cast(Entity); const unsigned short usCurrentModel = Projectile.GetModel(); if (usCurrentModel == usModel) @@ -1665,11 +1665,11 @@ bool CStaticFunctionDefinitions::GetPedAnalogControlState(CClientPed& Ped, const if (Ped.GetType() == CCLIENTPLAYER) { CControllerState cs; - bool bOnFoot = (!Ped.GetRealOccupiedVehicle()); - unsigned int uiIndex; + bool bOnFoot = (!Ped.GetRealOccupiedVehicle()); + unsigned int uiIndex; if (bRawInput) - cs = Ped.m_rawControllerState; // use the raw controller values without MTA glitch fixes modifying our raw inputs + cs = Ped.m_rawControllerState; // use the raw controller values without MTA glitch fixes modifying our raw inputs else Ped.GetControllerState(cs); @@ -2165,7 +2165,7 @@ bool CStaticFunctionDefinitions::SetPedAnimation(CClientEntity& Entity, const SS // Play the gateway animation const SString& strGateWayBlockName = g_pGame->GetAnimManager()->GetGateWayBlockName(); std::unique_ptr pBlock = g_pGame->GetAnimManager()->GetAnimationBlock(strGateWayBlockName); - auto pCustomAnimBlendHierarchy = pIFP->GetAnimationHierarchy(szAnimName); + auto pCustomAnimBlendHierarchy = pIFP->GetAnimationHierarchy(szAnimName); if ((pBlock) && (pCustomAnimBlendHierarchy != nullptr)) { Ped.SetNextAnimationCustom(pIFP, szAnimName); @@ -7014,10 +7014,10 @@ bool CStaticFunctionDefinitions::GetAnalogControlState(const char* szControl, fl { CControllerState cs; CClientPlayer* pLocalPlayer = m_pPlayerManager->GetLocalPlayer(); - bool bOnFoot = (!pLocalPlayer->GetRealOccupiedVehicle()); + bool bOnFoot = (!pLocalPlayer->GetRealOccupiedVehicle()); if (bRawInput) - cs = pLocalPlayer->m_rawControllerState; // use the raw controller values without MTA glitch fixes modifying our raw inputs + cs = pLocalPlayer->m_rawControllerState; // use the raw controller values without MTA glitch fixes modifying our raw inputs else pLocalPlayer->GetControllerState(cs); @@ -7211,6 +7211,130 @@ CClientColTube* CStaticFunctionDefinitions::CreateColTube(CResource& Resource, c return pShape; } +bool CStaticFunctionDefinitions::GetColShapeRadius(CClientColShape* pColShape, float& fRadius) +{ + switch (pColShape->GetShapeType()) + { + case COLSHAPE_CIRCLE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + case COLSHAPE_SPHERE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + case COLSHAPE_TUBE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + default: + return false; + } + + return true; +} + +bool CStaticFunctionDefinitions::SetColShapeRadius(CClientColShape* pColShape, float fRadius) +{ + if (fRadius < 0.0f) + fRadius = 0.0f; + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_CIRCLE: + static_cast(pColShape)->SetRadius(fRadius); + break; + case COLSHAPE_SPHERE: + static_cast(pColShape)->SetRadius(fRadius); + break; + case COLSHAPE_TUBE: + static_cast(pColShape)->SetRadius(fRadius); + break; + default: + return false; + } + + RefreshColShapeColliders(pColShape); + + return true; +} + +bool CStaticFunctionDefinitions::SetColShapeSize(CClientColShape* pColShape, CVector& vecSize) +{ + if (vecSize.fX < 0.0f) + vecSize.fX = 0.0f; + if (vecSize.fY < 0.0f) + vecSize.fY = 0.0f; + if (vecSize.fZ < 0.0f) + vecSize.fZ = 0.0f; + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + static_cast(pColShape)->SetSize(vecSize); + break; + } + case COLSHAPE_CUBOID: + { + static_cast(pColShape)->SetSize(vecSize); + break; + } + case COLSHAPE_TUBE: + { + static_cast(pColShape)->SetHeight(vecSize.fX); + break; + } + default: + return false; + } + + RefreshColShapeColliders(pColShape); + + return true; +} + +bool CStaticFunctionDefinitions::GetColPolygonPointPosition(CClientColPolygon* pColPolygon, uint uiPointIndex, CVector2D& vecPoint) +{ + if (uiPointIndex < pColPolygon->CountPoints()) + { + vecPoint = *(pColPolygon->IterBegin() + uiPointIndex); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::SetColPolygonPointPosition(CClientColPolygon* pColPolygon, uint uiPointIndex, const CVector2D& vecPoint) +{ + if (pColPolygon->SetPointPosition(uiPointIndex, vecPoint)) + { + RefreshColShapeColliders(pColPolygon); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::AddColPolygonPoint(CClientColPolygon* pColPolygon, int iPointIndex, const CVector2D& vecPoint) +{ + if (pColPolygon->AddPoint(vecPoint, iPointIndex)) + { + RefreshColShapeColliders(pColPolygon); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::RemoveColPolygonPoint(CClientColPolygon* pColPolygon, uint uiPointIndex) +{ + if (pColPolygon->RemovePoint(uiPointIndex)) + { + RefreshColShapeColliders(pColPolygon); + return true; + } + + return false; +} + // Make sure all colliders for a colshape are up to date void CStaticFunctionDefinitions::RefreshColShapeColliders(CClientColShape* pColShape) { diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index bbdaf2c9be1..bb39d009ec8 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -665,6 +665,18 @@ class CStaticFunctionDefinitions static bool IsInsideColShape(CClientColShape* pColShape, const CVector& vecPosition, bool& inside); static void RefreshColShapeColliders(CClientColShape* pColShape); + // Shape get functions + static bool GetColShapeRadius(CClientColShape* pColShape, float& fRadius); + static bool GetColPolygonPointPosition(CClientColPolygon* pColPolygon, uint uiPointIndex, CVector2D& vecPoint); + + // Shape set functions + static bool SetColShapeRadius(CClientColShape* pColShape, float fRadius); + static bool SetColShapeSize(CClientColShape* pColShape, CVector& vecSize); + static bool SetColPolygonPointPosition(CClientColPolygon* pColPolygon, uint uiPointIndex, const CVector2D& vecPoint); + + static bool AddColPolygonPoint(CClientColPolygon* pColPolygon, int iPointIndex, const CVector2D& vecPoint); + static bool RemoveColPolygonPoint(CClientColPolygon* pColPolygon, uint iPointIndex); + // Weapon funcs static bool GetWeaponNameFromID(unsigned char ucID, SString& strOutName); static bool GetWeaponIDFromName(const char* szName, unsigned char& ucID); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp index a0624479e2b..4fb560266aa 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp @@ -21,6 +21,16 @@ void CLuaColShapeDefs::LoadFunctions() {"createColPolygon", CreateColPolygon}, {"createColTube", CreateColTube}, + {"getColShapeRadius", GetColShapeRadius}, + {"setColShapeRadius", SetColShapeRadius}, + {"getColShapeSize", GetColShapeSize}, + {"setColShapeSize", SetColShapeSize}, + {"getColPolygonPoints", GetColPolygonPoints}, + {"getColPolygonPointPosition", GetColPolygonPointPosition}, + {"setColPolygonPointPosition", SetColPolygonPointPosition}, + {"addColPolygonPoint", AddColPolygonPoint}, + {"removeColPolygonPoint", RemoveColPolygonPoint}, + {"isInsideColShape", IsInsideColShape}, {"getColShapeType", GetColShapeType}, }; @@ -47,9 +57,23 @@ void CLuaColShapeDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "isInside", "isInsideColShape"); lua_classfunction(luaVM, "getShapeType", "getColShapeType"); + lua_classfunction(luaVM, "getRadius", GetColShapeRadius); + lua_classfunction(luaVM, "setRadius", SetColShapeRadius); + lua_classfunction(luaVM, "getSize", GetColShapeSize); + lua_classfunction(luaVM, "setSize", SetColShapeSize); + lua_classfunction(luaVM, "getPoints", GetColPolygonPoints); + lua_classfunction(luaVM, "getPointPosition", GetColPolygonPointPosition); + lua_classfunction(luaVM, "setPointPosition", SetColPolygonPointPosition); + lua_classfunction(luaVM, "addPoint", AddColPolygonPoint); + lua_classfunction(luaVM, "removePoint", RemoveColPolygonPoint); + lua_classvariable(luaVM, "elementsWithin", nullptr, "getElementsWithinColShape"); lua_classvariable(luaVM, "shapeType", nullptr, "getColShapeType"); + lua_classvariable(luaVM, "radius", SetColShapeRadius, GetColShapeRadius); + lua_classvariable(luaVM, "size", SetColShapeSize, GetColShapeSize); + lua_classvariable(luaVM, "points", nullptr, GetColPolygonPoints); + lua_registerclass(luaVM, "ColShape", "Element"); } @@ -382,3 +406,294 @@ int CLuaColShapeDefs::IsInsideColShape(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +int CLuaColShapeDefs::GetColShapeRadius(lua_State* luaVM) +{ + CClientColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + float fRadius; + if (CStaticFunctionDefinitions::GetColShapeRadius(pColShape, fRadius)) + { + lua_pushnumber(luaVM, fRadius); + return 1; + } + + argStream.SetCustomError("ColShape must be Circle, Sphere or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColShapeRadius(lua_State* luaVM) +{ + CClientColShape* pColShape; + float fRadius; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(fRadius); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (CStaticFunctionDefinitions::SetColShapeRadius(pColShape, fRadius)) + { + lua_pushboolean(luaVM, true); + return 1; + } + + argStream.SetCustomError("ColShape must be Circle, Sphere or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::GetColShapeSize(lua_State* luaVM) +{ + CClientColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + CVector2D size = static_cast(pColShape)->GetSize(); + lua_pushvector(luaVM, size); + return 1; + } + case COLSHAPE_CUBOID: + { + CVector size = static_cast(pColShape)->GetSize(); + lua_pushvector(luaVM, size); + return 1; + } + case COLSHAPE_TUBE: + { + float fHeight = static_cast(pColShape)->GetHeight(); + lua_pushnumber(luaVM, fHeight); + return 1; + } + } + + argStream.SetCustomError("ColShape must be Rectangle, Cuboid or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColShapeSize(lua_State* luaVM) +{ + CClientColShape* pColShape; + CVector vecSize; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + CVector2D vecRectangleSize; + argStream.ReadVector2D(vecRectangleSize); + + if (!argStream.HasErrors()) + { + vecSize.fX = vecRectangleSize.fX; + vecSize.fY = vecRectangleSize.fY; + } + break; + } + case COLSHAPE_CUBOID: + { + argStream.ReadVector3D(vecSize); + break; + } + case COLSHAPE_TUBE: + { + argStream.ReadNumber(vecSize.fX); + break; + } + default: + argStream.SetCustomError("ColShape must be Rectangle, Cuboid or Tube"); + } + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + CStaticFunctionDefinitions::SetColShapeSize(pColShape, vecSize); + + lua_pushboolean(luaVM, true); + return 1; +} + +int CLuaColShapeDefs::GetColPolygonPoints(lua_State* luaVM) +{ + CClientColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CClientColPolygon* pColPolygon = static_cast(pColShape); + + lua_newtable(luaVM); + + uint uiIndex = 0; + for (auto iter = pColPolygon->IterBegin(); iter != pColPolygon->IterEnd(); ++iter) + { + lua_pushnumber(luaVM, ++uiIndex); + lua_pushvector(luaVM, *iter); + lua_settable(luaVM, -3); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::GetColPolygonPointPosition(lua_State* luaVM) +{ + CClientColShape* pColShape; + uint uiPointIndex; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CClientColPolygon* pColPolygon = static_cast(pColShape); + CVector2D vecPoint; + if (uiPointIndex > 0 && CStaticFunctionDefinitions::GetColPolygonPointPosition(pColPolygon, uiPointIndex - 1, vecPoint)) + { + lua_pushvector(luaVM, vecPoint); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColPolygonPointPosition(lua_State* luaVM) +{ + CClientColShape* pColShape; + uint uiPointIndex; + CVector2D vecPoint; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + argStream.ReadVector2D(vecPoint); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CClientColPolygon* pColPolygon = static_cast(pColShape); + if (uiPointIndex > 0 && CStaticFunctionDefinitions::SetColPolygonPointPosition(pColPolygon, uiPointIndex - 1, vecPoint)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::AddColPolygonPoint(lua_State* luaVM) +{ + CClientColShape* pColShape; + int iPointIndex; + CVector2D vecPoint; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadVector2D(vecPoint); + argStream.ReadNumber(iPointIndex, 0); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CClientColPolygon* pColPolygon = static_cast(pColShape); + if (CStaticFunctionDefinitions::AddColPolygonPoint(pColPolygon, iPointIndex - 1, vecPoint)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::RemoveColPolygonPoint(lua_State* luaVM) +{ + CClientColShape* pColShape; + uint uiPointIndex; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CClientColPolygon* pColPolygon = static_cast(pColShape); + if (pColPolygon->CountPoints() <= 3) + { + m_pScriptDebugging->LogWarning(luaVM, "Can't remove the last 3 points"); + lua_pushboolean(luaVM, false); + } + else if (uiPointIndex > 0 && CStaticFunctionDefinitions::RemoveColPolygonPoint(pColPolygon, uiPointIndex - 1)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h index 195084cbb41..5e784459166 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h @@ -25,6 +25,16 @@ class CLuaColShapeDefs : public CLuaDefs LUA_DECLARE(CreateColPolygon); LUA_DECLARE(CreateColTube); + LUA_DECLARE(GetColShapeRadius); + LUA_DECLARE(SetColShapeRadius); + LUA_DECLARE(GetColShapeSize); + LUA_DECLARE(SetColShapeSize); + LUA_DECLARE(GetColPolygonPoints); + LUA_DECLARE(GetColPolygonPointPosition); + LUA_DECLARE(SetColPolygonPointPosition); + LUA_DECLARE(AddColPolygonPoint); + LUA_DECLARE(RemoveColPolygonPoint); + LUA_DECLARE(IsInsideColShape); LUA_DECLARE(GetColShapeType); }; diff --git a/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.cpp new file mode 100644 index 00000000000..4ecdcb4d436 --- /dev/null +++ b/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.cpp @@ -0,0 +1,74 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/rpc/CColShapeRPC.cpp + * PURPOSE: Colshapes remote procedure calls + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include +#include "CColShapeRPCs.h" + +void CColShapeRPCs::LoadFunctions(void) +{ + AddHandler(SET_COLSHAPE_RADIUS, SetColShapeRadius, "SetColShapeRadius"); + AddHandler(SET_COLSHAPE_SIZE, SetColShapeSize, "SetColShapeSize"); + AddHandler(UPDATE_COLPOLYGON_POINT, UpdateColPolygonPoint, "UpdateColPolygonPoint"); + AddHandler(ADD_COLPOLYGON_POINT, AddColPolygonPoint, "AddColPolygonPoint"); + AddHandler(REMOVE_COLPOLYGON_POINT, RemoveColPolygonPoint, "RemoveColPolygonPoint"); +} + +void CColShapeRPCs::SetColShapeRadius(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + float fRadius; + if (bitStream.Read(fRadius)) + { + CClientColShape* pColShape = static_cast(pSource); + CStaticFunctionDefinitions::SetColShapeRadius(pColShape, fRadius); + } +} + +void CColShapeRPCs::SetColShapeSize(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + CVector vecSize; + if (bitStream.ReadVector(vecSize.fX, vecSize.fY, vecSize.fZ)) + { + CClientColShape* pColShape = static_cast(pSource); + CStaticFunctionDefinitions::SetColShapeSize(pColShape, vecSize); + } +} + +void CColShapeRPCs::UpdateColPolygonPoint(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + SPosition2DSync size(false); + unsigned int uiPointIndex; + if (bitStream.Read(&size) && bitStream.Read(uiPointIndex)) + { + CClientColPolygon* pColShape = static_cast(pSource); + CStaticFunctionDefinitions::SetColPolygonPointPosition(pColShape, uiPointIndex, size.data.vecPosition); + } +} + +void CColShapeRPCs::AddColPolygonPoint(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + SPosition2DSync size(false); + int iPointIndex; + if (bitStream.Read(&size) && bitStream.Read(iPointIndex)) + { + CClientColPolygon* pColShape = static_cast(pSource); + CStaticFunctionDefinitions::AddColPolygonPoint(pColShape, iPointIndex, size.data.vecPosition); + } +} + +void CColShapeRPCs::RemoveColPolygonPoint(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + unsigned int uiPointIndex; + if (bitStream.Read(uiPointIndex)) + { + CClientColPolygon* pColShape = static_cast(pSource); + CStaticFunctionDefinitions::RemoveColPolygonPoint(pColShape, uiPointIndex); + } +} diff --git a/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.h b/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.h new file mode 100644 index 00000000000..f0851c0e242 --- /dev/null +++ b/Client/mods/deathmatch/logic/rpc/CColShapeRPCs.h @@ -0,0 +1,26 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto + * LICENSE: See LICENSE in the top level directory + * FILE: mods/deathmatch/logic/rpc/CColShapeRPC.h + * PURPOSE: Header for colshape RPC class + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#pragma once + +#include "CRPCFunctions.h" + +class CColShapeRPCs : public CRPCFunctions +{ +public: + static void LoadFunctions(void); + + DECLARE_ELEMENT_RPC(SetColShapeRadius); + DECLARE_ELEMENT_RPC(SetColShapeSize); + DECLARE_ELEMENT_RPC(UpdateColPolygonPoint); + DECLARE_ELEMENT_RPC(AddColPolygonPoint); + DECLARE_ELEMENT_RPC(RemoveColPolygonPoint); +}; diff --git a/Client/mods/deathmatch/logic/rpc/CRPCFunctions.cpp b/Client/mods/deathmatch/logic/rpc/CRPCFunctions.cpp index c67a2a00855..cfc59c89d59 100644 --- a/Client/mods/deathmatch/logic/rpc/CRPCFunctions.cpp +++ b/Client/mods/deathmatch/logic/rpc/CRPCFunctions.cpp @@ -30,6 +30,7 @@ #include "CWeaponRPCs.h" #include "CWaterRPCs.h" #include "CWorldRPCs.h" +#include "CColShapeRPCs.h" CClientManager* CRPCFunctions::m_pManager; CClientCamera* CRPCFunctions::m_pCamera; @@ -98,6 +99,7 @@ void CRPCFunctions::AddHandlers() CWeaponRPCs::LoadFunctions(); CWaterRPCs::LoadFunctions(); CWorldRPCs::LoadFunctions(); + CColShapeRPCs::LoadFunctions(); } void CRPCFunctions::AddHandler(unsigned char ucID, pfnRPCHandler Callback, const char* szName) diff --git a/Server/mods/deathmatch/logic/CColPolygon.cpp b/Server/mods/deathmatch/logic/CColPolygon.cpp index aaf8d3dca17..fb988eca879 100644 --- a/Server/mods/deathmatch/logic/CColPolygon.cpp +++ b/Server/mods/deathmatch/logic/CColPolygon.cpp @@ -85,20 +85,74 @@ void CColPolygon::SetPosition(const CVector& vecPosition) // Add queued collider refresh for v1.1 } -void CColPolygon::AddPoint(CVector2D vecPoint) +bool CColPolygon::AddPoint(CVector2D vecPoint, int iPointIndex) { - float fDistanceX = vecPoint.fX - m_vecPosition.fX; - float fDistanceY = vecPoint.fY - m_vecPosition.fY; + if (iPointIndex < 0) + { + m_Points.push_back(vecPoint); + } + else + { + if (iPointIndex >= m_Points.size()) + return false; - float fDist = sqrt(fDistanceX * fDistanceX + fDistanceY * fDistanceY); + m_Points.insert(m_Points.begin() + iPointIndex, vecPoint); + } - if (fDist > m_fRadius) + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) { - m_fRadius = fDist; + m_fRadius = fDistance; SizeChanged(); } - m_Points.push_back(vecPoint); + return true; +} + +bool CColPolygon::RemovePoint(unsigned int uiPointIndex) +{ + if (m_Points.size() <= 3) + return false; + + m_Points.erase(m_Points.begin() + uiPointIndex); + + m_fRadius = 0.0f; + for (auto vecPoint : m_Points) + { + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) + m_fRadius = fDistance; + } + + SizeChanged(); + + return true; +} + +bool CColPolygon::SetPointPosition(unsigned int uiPointIndex, const CVector2D& vecPoint) +{ + if (uiPointIndex >= m_Points.size()) + return false; + + m_Points[uiPointIndex] = vecPoint; + + m_fRadius = 0.0f; + for (auto vecPoint : m_Points) + { + CVector2D vecDistance = vecPoint - m_vecPosition; + float fDistance = vecDistance.Length(); + + if (fDistance > m_fRadius) + m_fRadius = fDistance; + } + + SizeChanged(); + + return true; } bool CColPolygon::IsInBounds(CVector vecPoint) diff --git a/Server/mods/deathmatch/logic/CColPolygon.h b/Server/mods/deathmatch/logic/CColPolygon.h index a58e263aed6..a5219e06518 100644 --- a/Server/mods/deathmatch/logic/CColPolygon.h +++ b/Server/mods/deathmatch/logic/CColPolygon.h @@ -29,7 +29,9 @@ class CColPolygon : public CColShape void SetPosition(const CVector& vecPosition); - void AddPoint(CVector2D vecPoint); + bool AddPoint(CVector2D vecPoint, int iPointIndex = -1); + bool SetPointPosition(unsigned int uiPointIndex, const CVector2D& vecPoint); + bool RemovePoint(unsigned int uiPointIndex); unsigned int CountPoints() const { return static_cast(m_Points.size()); }; std::vector::const_iterator IterBegin() { return m_Points.begin(); }; diff --git a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp index 6d9d081a26d..a94f110b565 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp @@ -213,6 +213,11 @@ ADD_ENUM1(SET_PROPAGATE_CALLS_ENABLED) ADD_ENUM1(SET_TRAIN_TRACK) ADD_ENUM1(SET_TRAIN_POSITION) ADD_ENUM1(SET_ELEMENT_ANGULAR_VELOCITY) +ADD_ENUM1(SET_COLSHAPE_RADIUS) +ADD_ENUM1(SET_COLSHAPE_SIZE) +ADD_ENUM1(ADD_COLPOLYGON_POINT) +ADD_ENUM1(REMOVE_COLPOLYGON_POINT) +ADD_ENUM1(UPDATE_COLPOLYGON_POINT) IMPLEMENT_ENUM_END("eElementRPCFunctions") DECLARE_ENUM(CRPCFunctions::eRPCFunctions); diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index cc18ef999f9..bd11b334712 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -9288,7 +9288,7 @@ CColRectangle* CStaticFunctionDefinitions::CreateColRectangle(CResource* pResour CColPolygon* CStaticFunctionDefinitions::CreateColPolygon(CResource* pResource, const std::vector& vecPointList) { if (vecPointList.size() < 4) - return NULL; + return nullptr; CVector vecPosition(vecPointList[0].fX, vecPointList[0].fY, 0); CColPolygon* pColShape = new CColPolygon(m_pColManager, pResource->GetDynamicElementRoot(), vecPosition); @@ -9331,6 +9331,157 @@ CColTube* CStaticFunctionDefinitions::CreateColTube(CResource* pResource, const return pColShape; } +bool CStaticFunctionDefinitions::GetColShapeRadius(CColShape* pColShape, float& fRadius) +{ + switch (pColShape->GetShapeType()) + { + case COLSHAPE_CIRCLE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + case COLSHAPE_SPHERE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + case COLSHAPE_TUBE: + fRadius = static_cast(pColShape)->GetRadius(); + break; + default: + return false; + } + + return true; +} + +bool CStaticFunctionDefinitions::SetColShapeRadius(CColShape* pColShape, float fRadius) +{ + if (fRadius < 0.0f) + fRadius = 0.0f; + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_CIRCLE: + static_cast(pColShape)->SetRadius(fRadius); + break; + case COLSHAPE_SPHERE: + static_cast(pColShape)->SetRadius(fRadius); + break; + case COLSHAPE_TUBE: + static_cast(pColShape)->SetRadius(fRadius); + break; + default: + return false; + } + + RefreshColShapeColliders(pColShape); + + // Tell all players + CBitStream BitStream; + BitStream.pBitStream->Write(fRadius); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pColShape, SET_COLSHAPE_RADIUS, *BitStream.pBitStream)); + + return true; +} + +bool CStaticFunctionDefinitions::SetColShapeSize(CColShape* pColShape, CVector& vecSize) +{ + if (vecSize.fX < 0.0f) + vecSize.fX = 0.0f; + if (vecSize.fY < 0.0f) + vecSize.fY = 0.0f; + if (vecSize.fZ < 0.0f) + vecSize.fZ = 0.0f; + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + static_cast(pColShape)->SetSize(vecSize); + break; + } + case COLSHAPE_CUBOID: + { + static_cast(pColShape)->SetSize(vecSize); + break; + } + case COLSHAPE_TUBE: + { + static_cast(pColShape)->SetHeight(vecSize.fX); + break; + } + default: + return false; + } + + RefreshColShapeColliders(pColShape); + + CBitStream BitStream; + BitStream.pBitStream->WriteVector(vecSize.fX, vecSize.fY, vecSize.fZ); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pColShape, SET_COLSHAPE_SIZE, *BitStream.pBitStream)); + + return true; +} + +bool CStaticFunctionDefinitions::GetColPolygonPointPosition(CColPolygon* pColPolygon, uint uiPointIndex, CVector2D& vecPoint) +{ + if (uiPointIndex < pColPolygon->CountPoints()) + { + vecPoint = *(pColPolygon->IterBegin() + uiPointIndex); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::SetColPolygonPointPosition(CColPolygon* pColPolygon, uint uiPointIndex, const CVector2D& vecPoint) +{ + if (pColPolygon->SetPointPosition(uiPointIndex, vecPoint)) + { + RefreshColShapeColliders(pColPolygon); + + CBitStream BitStream; + SPosition2DSync size(false); + size.data.vecPosition = vecPoint; + BitStream.pBitStream->Write(&size); + BitStream.pBitStream->Write(uiPointIndex); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pColPolygon, UPDATE_COLPOLYGON_POINT, *BitStream.pBitStream)); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::AddColPolygonPoint(CColPolygon* pColPolygon, int iPointIndex, const CVector2D& vecPoint) +{ + if (pColPolygon->AddPoint(vecPoint, iPointIndex)) + { + RefreshColShapeColliders(pColPolygon); + + CBitStream BitStream; + SPosition2DSync size(false); + size.data.vecPosition = vecPoint; + BitStream.pBitStream->Write(&size); + BitStream.pBitStream->Write(iPointIndex); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pColPolygon, ADD_COLPOLYGON_POINT, *BitStream.pBitStream)); + return true; + } + + return false; +} + +bool CStaticFunctionDefinitions::RemoveColPolygonPoint(CColPolygon* pColPolygon, uint uiPointIndex) +{ + if (pColPolygon->RemovePoint(uiPointIndex)) + { + RefreshColShapeColliders(pColPolygon); + + CBitStream BitStream; + BitStream.pBitStream->Write(uiPointIndex); + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pColPolygon, REMOVE_COLPOLYGON_POINT, *BitStream.pBitStream)); + return true; + } + + return false; +} + bool CStaticFunctionDefinitions::IsInsideColShape(CColShape* pColShape, const CVector& vecPosition, bool& inside) { inside = pColShape->DoHitDetection(vecPosition); diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index a374e245858..e3806dc156a 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -454,6 +454,18 @@ class CStaticFunctionDefinitions static bool IsInsideColShape(CColShape* pColShape, const CVector& vecPosition, bool& inside); static void RefreshColShapeColliders(CColShape* pColShape); + // Shape get functions + static bool GetColShapeRadius(CColShape* pColShape, float& fRadius); + static bool GetColPolygonPointPosition(CColPolygon* pColPolygon, uint uiPointIndex, CVector2D& vecPoint); + + // Shape set functions + static bool SetColShapeRadius(CColShape* pColShape, float fRadius); + static bool SetColShapeSize(CColShape* pColShape, CVector& vecSize); + static bool SetColPolygonPointPosition(CColPolygon* pColPolygon, uint uiPointIndex, const CVector2D& vecPoint); + + static bool AddColPolygonPoint(CColPolygon* pColPolygon, int iPointIndex, const CVector2D& vecPoint); + static bool RemoveColPolygonPoint(CColPolygon* pColPolygon, uint iPointIndex); + // Weapon funcs static CCustomWeapon* CreateWeapon(CResource* pResource, eWeaponType weaponType, CVector vecPosition); static bool GetWeaponNameFromID(unsigned char ucID, char* szName); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp index 997cfc4ffc3..0f4505bf10a 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.cpp @@ -21,6 +21,16 @@ void CLuaColShapeDefs::LoadFunctions() {"createColPolygon", CreateColPolygon}, {"createColTube", CreateColTube}, + {"getColShapeRadius", GetColShapeRadius}, + {"setColShapeRadius", SetColShapeRadius}, + {"getColShapeSize", GetColShapeSize}, + {"setColShapeSize", SetColShapeSize}, + {"getColPolygonPoints", GetColPolygonPoints}, + {"getColPolygonPointPosition", GetColPolygonPointPosition}, + {"setColPolygonPointPosition", SetColPolygonPointPosition}, + {"addColPolygonPoint", AddColPolygonPoint}, + {"removeColPolygonPoint", RemoveColPolygonPoint}, + {"isInsideColShape", IsInsideColShape}, {"getColShapeType", GetColShapeType}, }; @@ -45,10 +55,24 @@ void CLuaColShapeDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "getElementsWithin", "getElementsWithinColShape"); lua_classfunction(luaVM, "isInside", "isInsideColShape"); - lua_classfunction(luaVM, "getShapeType", "getColShapeType"); + + lua_classfunction(luaVM, "getRadius", "getColShapeRadius", GetColShapeRadius); + lua_classfunction(luaVM, "setRadius", "setColShapeRadius", SetColShapeRadius); + lua_classfunction(luaVM, "getSize", "getColShapeSize", GetColShapeSize); + lua_classfunction(luaVM, "setSize", "setColShapeSize", SetColShapeSize); + lua_classfunction(luaVM, "getPoints", "getColPolygonPoints", GetColPolygonPoints); + lua_classfunction(luaVM, "getPointPosition", "getColPolygonPointPosition", GetColPolygonPointPosition); + lua_classfunction(luaVM, "setPointPosition", "setColPolygonPointPosition", SetColPolygonPointPosition); + lua_classfunction(luaVM, "addPoint", "addColPolygonPoint", AddColPolygonPoint); + lua_classfunction(luaVM, "removePoint", "removeColPolygonPoint", RemoveColPolygonPoint); + lua_classvariable(luaVM, "shapeType", nullptr, "getColShapeType"); + lua_classvariable(luaVM, "radius", "setColShapeRadius", "getColShapeRadius", SetColShapeRadius, GetColShapeRadius); + lua_classvariable(luaVM, "size", "setColShapeSize", "getColShapeSize", SetColShapeSize, GetColShapeSize); + lua_classvariable(luaVM, "points", nullptr, "getColPolygonPoints", nullptr, GetColPolygonPoints); + lua_registerclass(luaVM, "ColShape", "Element"); } @@ -363,3 +387,294 @@ int CLuaColShapeDefs::IsInsideColShape(lua_State* luaVM) lua_pushboolean(luaVM, false); return 1; } + +int CLuaColShapeDefs::GetColShapeRadius(lua_State* luaVM) +{ + CColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + float fRadius; + if (CStaticFunctionDefinitions::GetColShapeRadius(pColShape, fRadius)) + { + lua_pushnumber(luaVM, fRadius); + return 1; + } + + argStream.SetCustomError("ColShape must be Circle, Sphere or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColShapeRadius(lua_State* luaVM) +{ + CColShape* pColShape; + float fRadius; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(fRadius); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (CStaticFunctionDefinitions::SetColShapeRadius(pColShape, fRadius)) + { + lua_pushboolean(luaVM, true); + return 1; + } + + argStream.SetCustomError("ColShape must be Circle, Sphere or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::GetColShapeSize(lua_State* luaVM) +{ + CColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + CVector2D size = static_cast(pColShape)->GetSize(); + lua_pushvector(luaVM, size); + return 1; + } + case COLSHAPE_CUBOID: + { + CVector size = static_cast(pColShape)->GetSize(); + lua_pushvector(luaVM, size); + return 1; + } + case COLSHAPE_TUBE: + { + float fHeight = static_cast(pColShape)->GetHeight(); + lua_pushnumber(luaVM, fHeight); + return 1; + } + } + + argStream.SetCustomError("ColShape must be Rectangle, Cuboid or Tube"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColShapeSize(lua_State* luaVM) +{ + CColShape* pColShape; + CVector vecSize; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + switch (pColShape->GetShapeType()) + { + case COLSHAPE_RECTANGLE: + { + CVector2D vecRectangleSize; + argStream.ReadVector2D(vecRectangleSize); + + if (!argStream.HasErrors()) + { + vecSize.fX = vecRectangleSize.fX; + vecSize.fY = vecRectangleSize.fY; + } + break; + } + case COLSHAPE_CUBOID: + { + argStream.ReadVector3D(vecSize); + break; + } + case COLSHAPE_TUBE: + { + argStream.ReadNumber(vecSize.fX); + break; + } + default: + argStream.SetCustomError("ColShape must be Rectangle, Cuboid or Tube"); + } + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + CStaticFunctionDefinitions::SetColShapeSize(pColShape, vecSize); + + lua_pushboolean(luaVM, true); + return 1; +} + +int CLuaColShapeDefs::GetColPolygonPoints(lua_State* luaVM) +{ + CColShape* pColShape; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CColPolygon* pColPolygon = static_cast(pColShape); + + lua_newtable(luaVM); + + uint uiIndex = 0; + for (auto iter = pColPolygon->IterBegin(); iter != pColPolygon->IterEnd(); ++iter) + { + lua_pushnumber(luaVM, ++uiIndex); + lua_pushvector(luaVM, *iter); + lua_settable(luaVM, -3); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::GetColPolygonPointPosition(lua_State* luaVM) +{ + CColShape* pColShape; + uint uiPointIndex; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CColPolygon* pColPolygon = static_cast(pColShape); + CVector2D vecPoint; + if (uiPointIndex > 0 && CStaticFunctionDefinitions::GetColPolygonPointPosition(pColPolygon, uiPointIndex - 1, vecPoint)) + { + lua_pushvector(luaVM, vecPoint); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::SetColPolygonPointPosition(lua_State* luaVM) +{ + CColShape* pColShape; + uint uiPointIndex; + CVector2D vecPoint; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + argStream.ReadVector2D(vecPoint); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CColPolygon* pColPolygon = static_cast(pColShape); + if (uiPointIndex > 0 && CStaticFunctionDefinitions::SetColPolygonPointPosition(pColPolygon, uiPointIndex - 1, vecPoint)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::AddColPolygonPoint(lua_State* luaVM) +{ + CColShape* pColShape; + int iPointIndex; + CVector2D vecPoint; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadVector2D(vecPoint); + argStream.ReadNumber(iPointIndex, 0); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CColPolygon* pColPolygon = static_cast(pColShape); + if (CStaticFunctionDefinitions::AddColPolygonPoint(pColPolygon, iPointIndex - 1, vecPoint)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} + +int CLuaColShapeDefs::RemoveColPolygonPoint(lua_State* luaVM) +{ + CColShape* pColShape; + uint uiPointIndex; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pColShape); + argStream.ReadNumber(uiPointIndex); + + if (argStream.HasErrors()) + return luaL_error(luaVM, argStream.GetFullErrorMessage()); + + if (pColShape->GetShapeType() == COLSHAPE_POLYGON) + { + CColPolygon* pColPolygon = static_cast(pColShape); + if (pColPolygon->CountPoints() <= 3) + { + m_pScriptDebugging->LogWarning(luaVM, "Can't remove the last 3 points"); + lua_pushboolean(luaVM, false); + } + else if (uiPointIndex > 0 && CStaticFunctionDefinitions::RemoveColPolygonPoint(pColPolygon, uiPointIndex - 1)) + { + lua_pushboolean(luaVM, true); + } + else + { + m_pScriptDebugging->LogWarning(luaVM, "Invalid point index"); + lua_pushboolean(luaVM, false); + } + return 1; + } + + argStream.SetCustomError("ColShape must be Polygon"); + return luaL_error(luaVM, argStream.GetFullErrorMessage()); +} diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h index 938fe898699..6408671b560 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaColShapeDefs.h @@ -25,6 +25,16 @@ class CLuaColShapeDefs : public CLuaDefs LUA_DECLARE(CreateColRectangle); LUA_DECLARE(CreateColPolygon); LUA_DECLARE(CreateColTube); + + LUA_DECLARE(GetColShapeRadius); + LUA_DECLARE(SetColShapeRadius); + LUA_DECLARE(GetColShapeSize); + LUA_DECLARE(SetColShapeSize); + LUA_DECLARE(GetColPolygonPoints); + LUA_DECLARE(GetColPolygonPointPosition); + LUA_DECLARE(SetColPolygonPointPosition); + LUA_DECLARE(AddColPolygonPoint); + LUA_DECLARE(RemoveColPolygonPoint); LUA_DECLARE(IsInsideColShape); LUA_DECLARE(GetColShapeType); diff --git a/Shared/sdk/net/rpc_enums.h b/Shared/sdk/net/rpc_enums.h index 3658585b08e..1b0f6615b19 100644 --- a/Shared/sdk/net/rpc_enums.h +++ b/Shared/sdk/net/rpc_enums.h @@ -263,5 +263,11 @@ enum eElementRPCFunctions SET_PED_ANIMATION_SPEED, + SET_COLSHAPE_RADIUS, + SET_COLSHAPE_SIZE, + ADD_COLPOLYGON_POINT, + REMOVE_COLPOLYGON_POINT, + UPDATE_COLPOLYGON_POINT, + NUM_RPC_FUNCS // Add above this line };