diff --git a/Client/mods/deathmatch/logic/CClientBuilding.cpp b/Client/mods/deathmatch/logic/CClientBuilding.cpp index 5b356cbc219..31761a16cb6 100644 --- a/Client/mods/deathmatch/logic/CClientBuilding.cpp +++ b/Client/mods/deathmatch/logic/CClientBuilding.cpp @@ -21,6 +21,7 @@ CClientBuilding::CClientBuilding(class CClientManager* pManager, ElementID ID, u m_pBuilding(nullptr), m_usesCollision(true), m_ucAlpha(255), + m_vecScale(1.0f, 1.0f, 1.0f), m_pHighBuilding(nullptr), m_pLowBuilding(nullptr) { @@ -155,6 +156,26 @@ void CClientBuilding::SetAlpha(unsigned char ucAlpha) m_pBuilding->SetAlpha(ucAlpha); } +void CClientBuilding::SetScale(const CVector& vecScale) +{ + m_vecScale = vecScale; + + if (m_vecScale.fX == 1.0f && m_vecScale.fY == 1.0f && m_vecScale.fZ == 1.0f) + m_pBuildingManager->RemoveFromScaledList(this); + else + m_pBuildingManager->AddToScaledList(this); + + ApplyScale(); +} + +void CClientBuilding::ApplyScale() +{ + if (!m_pBuilding) + return; + + m_pBuilding->SetScaleInternal(m_vecScale); +} + void CClientBuilding::Create() { if (m_pBuilding) @@ -181,6 +202,9 @@ void CClientBuilding::Create() if (m_ucAlpha != 255) m_pBuilding->SetAlpha(m_ucAlpha); + if (m_vecScale.fX != 1.0f || m_vecScale.fY != 1.0f || m_vecScale.fZ != 1.0f) + ApplyScale(); + if (m_pHighBuilding) { m_pHighBuilding->GetBuildingEntity()->SetLod(m_pBuilding); diff --git a/Client/mods/deathmatch/logic/CClientBuilding.h b/Client/mods/deathmatch/logic/CClientBuilding.h index 68496e374f2..c6636be4262 100644 --- a/Client/mods/deathmatch/logic/CClientBuilding.h +++ b/Client/mods/deathmatch/logic/CClientBuilding.h @@ -56,6 +56,10 @@ class CClientBuilding : public CClientEntity unsigned char GetAlpha() const noexcept { return m_ucAlpha; } void SetAlpha(unsigned char ucAlpha); + const CVector& GetScale() const noexcept { return m_vecScale; } + void SetScale(const CVector& vecScale); + void ApplyScale(); + void Create(); void Destroy(); @@ -87,6 +91,7 @@ class CClientBuilding : public CClientEntity uint8_t m_interior; bool m_usesCollision; unsigned char m_ucAlpha; + CVector m_vecScale; CClientBuilding* m_pHighBuilding; CClientBuilding* m_pLowBuilding; diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp index 19671d3c131..3a615e96e4c 100644 --- a/Client/mods/deathmatch/logic/CClientBuildingManager.cpp +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.cpp @@ -38,6 +38,7 @@ void CClientBuildingManager::RemoveAll() } m_List.clear(); + m_ScaledBuildings.clear(); // Allow list removal again m_bRemoveFromList = true; @@ -63,6 +64,25 @@ void CClientBuildingManager::RemoveFromList(CClientBuilding* pBuilding) { m_List.remove(pBuilding); } + + RemoveFromScaledList(pBuilding); +} + +void CClientBuildingManager::AddToScaledList(CClientBuilding* pBuilding) +{ + if (std::find(m_ScaledBuildings.begin(), m_ScaledBuildings.end(), pBuilding) == m_ScaledBuildings.end()) + m_ScaledBuildings.push_back(pBuilding); +} + +void CClientBuildingManager::RemoveFromScaledList(CClientBuilding* pBuilding) +{ + m_ScaledBuildings.remove(pBuilding); +} + +void CClientBuildingManager::UpdateScaledBuildings() +{ + for (CClientBuilding* pBuilding : m_ScaledBuildings) + pBuilding->ApplyScale(); } bool CClientBuildingManager::IsValidModel(uint16_t modelId) diff --git a/Client/mods/deathmatch/logic/CClientBuildingManager.h b/Client/mods/deathmatch/logic/CClientBuildingManager.h index 96245dd5517..781d6c3d9c4 100644 --- a/Client/mods/deathmatch/logic/CClientBuildingManager.h +++ b/Client/mods/deathmatch/logic/CClientBuildingManager.h @@ -41,7 +41,12 @@ class CClientBuildingManager void RestoreDestroyed(); void RestoreDestroyedSafe(); + void UpdateScaledBuildings(); + private: + void AddToScaledList(CClientBuilding* pBuilding); + void RemoveFromScaledList(CClientBuilding* pBuilding); + bool DoPoolResize(size_t newCapacity); void AddToList(CClientBuilding* pBuilding) { @@ -51,6 +56,7 @@ class CClientBuildingManager void RemoveFromList(CClientBuilding* pBuilding); std::list m_List; + std::list m_ScaledBuildings; bool m_bRemoveFromList; unsigned short m_usDimension{0}; }; diff --git a/Client/mods/deathmatch/logic/CClientGame.cpp b/Client/mods/deathmatch/logic/CClientGame.cpp index 6ed7e017179..569f8985498 100644 --- a/Client/mods/deathmatch/logic/CClientGame.cpp +++ b/Client/mods/deathmatch/logic/CClientGame.cpp @@ -3959,6 +3959,9 @@ void CClientGame::PostWorldProcessHandler() void CClientGame::PostWorldProcessPedsAfterPreRenderHandler() { + if (CClientBuildingManager* pBuildingManager = m_pManager->GetBuildingManager()) + pBuildingManager->UpdateScaledBuildings(); + CLuaArguments Arguments; m_pRootEntity->CallEvent("onClientPedsProcessed", Arguments, false); } diff --git a/Client/mods/deathmatch/logic/CPacketHandler.cpp b/Client/mods/deathmatch/logic/CPacketHandler.cpp index e6a08146871..65764b10e08 100644 --- a/Client/mods/deathmatch/logic/CPacketHandler.cpp +++ b/Client/mods/deathmatch/logic/CPacketHandler.cpp @@ -4218,10 +4218,20 @@ void CPacketHandler::Packet_EntityAdd(NetBitStreamInterface& bitStream) modelId = 1700; bitStream.Read(LowLodObjectID); + + CVector vecScale(1.0f, 1.0f, 1.0f); + if (bitStream.Can(eBitStreamVersion::BuildingScale)) + { + bitStream.Read(vecScale.fX); + bitStream.Read(vecScale.fY); + bitStream.Read(vecScale.fZ); + } + CClientBuilding* pBuilding = new CClientBuilding(g_pClientGame->m_pManager, EntityID, modelId, position.data.vecPosition, rotationRadians.data.vecRotation, ucInterior); pBuilding->SetUsesCollision(bCollisonsEnabled); + pBuilding->SetScale(vecScale); pEntity = pBuilding; break; } diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index ab3313d9a19..d20e1d86275 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -463,6 +463,23 @@ bool CStaticFunctionDefinitions::GetElementRotation(CClientEntity& Entity, CVect return true; } +bool CStaticFunctionDefinitions::GetElementScale(CClientEntity& Entity, CVector& vecScale) +{ + if (IS_OBJECT(&Entity)) + { + static_cast(Entity).GetScale(vecScale); + return true; + } + + if (Entity.GetType() == CCLIENTBUILDING) + { + vecScale = static_cast(Entity).GetScale(); + return true; + } + + return false; +} + bool CStaticFunctionDefinitions::GetElementVelocity(CClientEntity& Entity, CVector& vecVelocity) { int iType = Entity.GetType(); @@ -1195,6 +1212,25 @@ bool CStaticFunctionDefinitions::SetElementRotation(CClientEntity& Entity, const return true; } +bool CStaticFunctionDefinitions::SetElementScale(CClientEntity& Entity, const CVector& vecScale) +{ + RUN_CHILDREN(SetElementScale(**iter, vecScale)) + + if (IS_OBJECT(&Entity)) + { + static_cast(Entity).SetScale(vecScale); + return true; + } + + if (Entity.GetType() == CCLIENTBUILDING) + { + static_cast(Entity).SetScale(vecScale); + return true; + } + + return false; +} + bool CStaticFunctionDefinitions::SetElementVelocity(CClientEntity& Entity, const CVector& vecVelocity) { RUN_CHILDREN(SetElementVelocity(**iter, vecVelocity)) diff --git a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 0d1bc5f2c48..19b6df64160 100644 --- a/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Client/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -62,6 +62,7 @@ class CStaticFunctionDefinitions static bool GetElementMatrix(CClientEntity& Entity, CMatrix& matrix); static bool GetElementPosition(CClientEntity& Entity, CVector& vecPosition); static bool GetElementRotation(CClientEntity& Entity, CVector& vecRotation, eEulerRotationOrder rotationOrder); + static bool GetElementScale(CClientEntity& Entity, CVector& vecScale); static bool GetElementVelocity(CClientEntity& Entity, CVector& vecVelocity); static bool GetElementTurnVelocity(CClientEntity& Entity, CVector& vecTurnVelocity); static bool GetElementInterior(CClientEntity& Entity, unsigned char& ucInterior); @@ -91,6 +92,7 @@ class CStaticFunctionDefinitions static bool SetElementMatrix(CClientEntity& Entity, const CMatrix& matrix); static bool SetElementPosition(CClientEntity& Entity, const CVector& vecPosition, bool bWarp = true); static bool SetElementRotation(CClientEntity& Entity, const CVector& vecRotation, eEulerRotationOrder rotationOrder, bool bNewWay); + static bool SetElementScale(CClientEntity& Entity, const CVector& vecScale); static bool SetElementVelocity(CClientEntity& Element, const CVector& vecVelocity); static bool SetElementAngularVelocity(CClientEntity& Element, const CVector& vecTurnVelocity); static bool SetElementParent(CClientEntity& Element, CClientEntity& Parent, CLuaMain* pLuaMain); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp index 6041d4768ef..61d79ae45c3 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp @@ -29,6 +29,8 @@ void CLuaBuildingDefs::AddClass(lua_State* luaVM) lua_newclass(luaVM); lua_classfunction(luaVM, "create", "createBuilding"); + lua_classfunction(luaVM, "getScale", "getElementScale"); + lua_classfunction(luaVM, "setScale", "setElementScale"); lua_registerclass(luaVM, "Building", "Element"); } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 0073f4f88bf..d3f720da0f1 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -28,6 +28,7 @@ void CLuaElementDefs::LoadFunctions() {"getElementMatrix", GetElementMatrix}, {"getElementPosition", GetElementPosition}, {"getElementRotation", GetElementRotation}, + {"getElementScale", GetElementScale}, {"getElementVelocity", GetElementVelocity}, {"getElementAngularVelocity", GetElementTurnVelocity}, {"getElementType", GetElementType}, @@ -82,6 +83,7 @@ void CLuaElementDefs::LoadFunctions() {"setElementMatrix", SetElementMatrix}, {"setElementPosition", SetElementPosition}, {"setElementRotation", SetElementRotation}, + {"setElementScale", SetElementScale}, {"setElementVelocity", SetElementVelocity}, {"setElementAngularVelocity", SetElementAngularVelocity}, {"setElementInterior", SetElementInterior}, @@ -549,6 +551,32 @@ int CLuaElementDefs::OOP_GetElementRotation(lua_State* luaVM) return 1; } +int CLuaElementDefs::GetElementScale(lua_State* luaVM) +{ + // float, float, float getElementScale ( element theElement ) + CClientEntity* pEntity = NULL; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pEntity); + + if (!argStream.HasErrors()) + { + CVector vecScale; + if (CStaticFunctionDefinitions::GetElementScale(*pEntity, vecScale)) + { + lua_pushnumber(luaVM, vecScale.fX); + lua_pushnumber(luaVM, vecScale.fY); + lua_pushnumber(luaVM, vecScale.fZ); + return 3; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaElementDefs::GetElementVelocity(lua_State* luaVM) { // Verify the argument @@ -1978,6 +2006,42 @@ int CLuaElementDefs::OOP_SetElementRotation(lua_State* luaVM) return 1; } +int CLuaElementDefs::SetElementScale(lua_State* luaVM) +{ + // bool setElementScale ( element theElement, float scale ) + // bool setElementScale ( element theElement, float x, float y, float z ) + CClientEntity* pEntity; + CVector vecScale; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pEntity); + + if (argStream.NextIsVector3D()) + { + argStream.ReadVector3D(vecScale); + } + else + { + argStream.ReadNumber(vecScale.fX); + argStream.ReadNumber(vecScale.fY, vecScale.fX); + argStream.ReadNumber(vecScale.fZ, vecScale.fX); + } + + if (!argStream.HasErrors()) + { + if (CStaticFunctionDefinitions::SetElementScale(*pEntity, vecScale)) + { + lua_pushboolean(luaVM, true); + return 1; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaElementDefs::SetElementVelocity(lua_State* luaVM) { CClientEntity* pEntity; diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index 1ab2775ce52..486de4e9d37 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -33,6 +33,7 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE_OOP(GetElementMatrix); LUA_DECLARE_OOP(GetElementPosition); LUA_DECLARE_OOP(GetElementRotation); + LUA_DECLARE(GetElementScale); LUA_DECLARE_OOP(GetElementVelocity); LUA_DECLARE_OOP(GetElementTurnVelocity); LUA_DECLARE(GetElementType); @@ -82,6 +83,7 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(SetElementMatrix); LUA_DECLARE(SetElementPosition); LUA_DECLARE_OOP(SetElementRotation); + LUA_DECLARE(SetElementScale); LUA_DECLARE(SetElementVelocity); LUA_DECLARE(SetElementAngularVelocity); LUA_DECLARE(SetElementParent); diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp index 1dc5f0d0c86..9d5bc008ae5 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaObjectDefs.cpp @@ -438,11 +438,11 @@ int CLuaObjectDefs::StopObject(lua_State* luaVM) int CLuaObjectDefs::SetObjectScale(lua_State* luaVM) { // bool setObjectScale ( object theObject, float scale ) - CClientEntity* pEntity; + CClientObject* pObject; CVector vecScale; CScriptArgReader argStream(luaVM); - argStream.ReadUserData(pEntity); + argStream.ReadUserData(pObject); // Caz - This function looks totally wrong // the function is designed to support the following syntaxes @@ -462,7 +462,7 @@ int CLuaObjectDefs::SetObjectScale(lua_State* luaVM) } if (!argStream.HasErrors()) { - if (CStaticFunctionDefinitions::SetObjectScale(*pEntity, vecScale)) + if (CStaticFunctionDefinitions::SetObjectScale(*pObject, vecScale)) { lua_pushboolean(luaVM, true); return 1; diff --git a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp index 44f24c6a872..1c31df2e5dd 100644 --- a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp +++ b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.cpp @@ -19,6 +19,7 @@ void CObjectRPCs::LoadFunctions() AddHandler(MOVE_OBJECT, MoveObject, "MoveObject"); AddHandler(STOP_OBJECT, StopObject, "StopObject"); AddHandler(SET_OBJECT_SCALE, SetObjectScale, "SetObjectScale"); + AddHandler(SET_ELEMENT_SCALE, SetElementScale, "SetElementScale"); AddHandler(SET_OBJECT_VISIBLE_IN_ALL_DIMENSIONS, SetObjectVisibleInAllDimensions, "SetObjectVisibleInAllDimensions"); AddHandler(SET_OBJECT_BREAKABLE, SetObjectBreakable, "SetObjectBreakable"); AddHandler(BREAK_OBJECT, BreakObject, "BreakObject"); @@ -116,6 +117,31 @@ void CObjectRPCs::SetObjectScale(CClientEntity* pSource, NetBitStreamInterface& } } +void CObjectRPCs::SetElementScale(CClientEntity* pSource, NetBitStreamInterface& bitStream) +{ + CVector vecScale; + + bitStream.Read(vecScale.fX); + vecScale.fY = vecScale.fX; + vecScale.fZ = vecScale.fX; + + bitStream.Read(vecScale.fY); + bitStream.Read(vecScale.fZ); + + if (pSource->GetType() == CCLIENTBUILDING) + { + static_cast(pSource)->SetScale(vecScale); + return; + } + + CDeathmatchObject* pObject = static_cast(m_pObjectManager->Get(pSource->GetID())); + + if (pObject) + { + pObject->SetScale(vecScale); + } +} + void CObjectRPCs::SetObjectVisibleInAllDimensions(CClientEntity* pSource, NetBitStreamInterface& bitStream) { CDeathmatchObject* pObject = static_cast(m_pObjectManager->Get(pSource->GetID())); diff --git a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h index ada761f0649..ad548a50aba 100644 --- a/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h +++ b/Client/mods/deathmatch/logic/rpc/CObjectRPCs.h @@ -24,6 +24,7 @@ class CObjectRPCs : public CRPCFunctions DECLARE_ELEMENT_RPC(MoveObject); DECLARE_ELEMENT_RPC(StopObject); DECLARE_ELEMENT_RPC(SetObjectScale); + DECLARE_ELEMENT_RPC(SetElementScale); DECLARE_ELEMENT_RPC(SetObjectVisibleInAllDimensions); DECLARE_ELEMENT_RPC(SetObjectBreakable); DECLARE_ELEMENT_RPC(BreakObject); diff --git a/Server/mods/deathmatch/logic/CBuilding.cpp b/Server/mods/deathmatch/logic/CBuilding.cpp index 1bfb69bb5f8..6424c35afc1 100644 --- a/Server/mods/deathmatch/logic/CBuilding.cpp +++ b/Server/mods/deathmatch/logic/CBuilding.cpp @@ -25,6 +25,7 @@ CBuilding::CBuilding(CElement* pParent, CBuildingManager* pBuildingManager) : CE m_pBuildingManager = pBuildingManager; m_model = 0xFFFF; + m_vecScale = CVector(1.0f, 1.0f, 1.0f); m_bDoubleSided = false; m_bCollisionsEnabled = true; m_ucAlpha = 255; @@ -46,6 +47,7 @@ CBuilding::CBuilding(const CBuilding& Copy) : CElement(Copy.m_pParent), m_pLowLo m_bDoubleSided = Copy.m_bDoubleSided; m_vecPosition = Copy.m_vecPosition; m_vecRotation = Copy.m_vecRotation; + m_vecScale = Copy.m_vecScale; m_bCollisionsEnabled = Copy.m_bCollisionsEnabled; m_ucAlpha = Copy.m_ucAlpha; m_pHighLodBuilding = nullptr; diff --git a/Server/mods/deathmatch/logic/CBuilding.h b/Server/mods/deathmatch/logic/CBuilding.h index 8bac0b479db..c252ba7f6d7 100644 --- a/Server/mods/deathmatch/logic/CBuilding.h +++ b/Server/mods/deathmatch/logic/CBuilding.h @@ -45,6 +45,9 @@ class CBuilding final : public CElement std::uint16_t GetModel() const noexcept { return m_model; } void SetModel(std::uint16_t model) noexcept { m_model = model; } + const CVector& GetScale() const noexcept { return m_vecScale; } + void SetScale(const CVector& vecScale) noexcept { m_vecScale = vecScale; } + bool GetCollisionEnabled() const noexcept { return m_bCollisionsEnabled; } void SetCollisionEnabled(bool bCollisionEnabled) noexcept { m_bCollisionsEnabled = bCollisionEnabled; } @@ -63,6 +66,7 @@ class CBuilding final : public CElement private: CBuildingManager* m_pBuildingManager; CVector m_vecRotation; + CVector m_vecScale; std::uint16_t m_model; protected: diff --git a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp index fb6c68baf50..57816f6d05b 100644 --- a/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp +++ b/Server/mods/deathmatch/logic/CPerfStat.RPCPacketUsage.cpp @@ -233,6 +233,7 @@ ADD_ENUM1(TOGGLE_OBJECT_RESPAWN) ADD_ENUM1(RESET_WORLD_PROPERTIES) ADD_ENUM1(SPAWN_VEHICLE_FLYING_COMPONENT) ADD_ENUM1(SET_ELEMENT_ON_FIRE) +ADD_ENUM1(SET_ELEMENT_SCALE) IMPLEMENT_ENUM_END("eElementRPCFunctions") DECLARE_ENUM(CRPCFunctions::eRPCFunctions); diff --git a/Server/mods/deathmatch/logic/CResourceChecker.Data.h b/Server/mods/deathmatch/logic/CResourceChecker.Data.h index a91d96f501a..eb37eac0f5b 100644 --- a/Server/mods/deathmatch/logic/CResourceChecker.Data.h +++ b/Server/mods/deathmatch/logic/CResourceChecker.Data.h @@ -87,6 +87,8 @@ namespace {false, "setPedSkin", "setElementModel"}, {false, "getObjectRotation", "getElementRotation"}, {false, "setObjectRotation", "setElementRotation"}, + {false, "getObjectScale", "getElementScale"}, + {false, "setObjectScale", "setElementScale"}, {false, "getVehicleIDFromName", "getVehicleModelFromName"}, {false, "getVehicleID", "getElementModel"}, {false, "getVehicleRotation", "getElementRotation"}, @@ -152,6 +154,8 @@ namespace {false, "setVehicleModel", "setElementModel"}, {false, "getObjectModel", "getElementModel"}, {false, "setObjectModel", "setElementModel"}, + {false, "getObjectScale", "getElementScale"}, + {false, "setObjectScale", "setElementScale"}, {false, "getVehicleID", "getElementModel"}, {false, "getVehicleIDFromName", "getVehicleModelFromName"}, {false, "getVehicleNameFromID", "getVehicleNameFromModel"}, diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 2bfc7345024..737794b11a7 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1253,6 +1253,27 @@ bool CStaticFunctionDefinitions::GetElementRotation(CElement* pElement, CVector& return true; } +bool CStaticFunctionDefinitions::GetElementScale(CElement* pElement, CVector& vecScale) +{ + assert(pElement); + + switch (pElement->GetType()) + { + case CElement::OBJECT: + { + vecScale = static_cast(pElement)->GetScale(); + return true; + } + case CElement::BUILDING: + { + vecScale = static_cast(pElement)->GetScale(); + return true; + } + default: + return false; + } +} + bool CStaticFunctionDefinitions::GetElementVelocity(CElement* pElement, CVector& vecVelocity) { assert(pElement); @@ -1449,6 +1470,34 @@ bool CStaticFunctionDefinitions::SetElementRotation(CElement* pElement, const CV return true; } +bool CStaticFunctionDefinitions::SetElementScale(CElement* pElement, const CVector& vecScale) +{ + assert(pElement); + RUN_CHILDREN(SetElementScale(*iter, vecScale)) + + switch (pElement->GetType()) + { + case CElement::OBJECT: + static_cast(pElement)->SetScale(vecScale); + break; + case CElement::BUILDING: + static_cast(pElement)->SetScale(vecScale); + break; + default: + return false; + } + + CBitStream BitStream; + + BitStream.pBitStream->Write(vecScale.fX); + BitStream.pBitStream->Write(vecScale.fY); + BitStream.pBitStream->Write(vecScale.fZ); + + m_pPlayerManager->BroadcastOnlyJoined(CElementRPCPacket(pElement, SET_ELEMENT_SCALE, *BitStream.pBitStream)); + + return true; +} + bool CStaticFunctionDefinitions::SetElementVelocity(CElement* pElement, const CVector& vecVelocity) { assert(pElement); diff --git a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h index 4578adb20ec..a5533ad88d4 100644 --- a/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/Server/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -57,6 +57,7 @@ class CStaticFunctionDefinitions static bool GetElementMatrix(CElement* pElement, CMatrix& matrix); static bool GetElementPosition(CElement* pElement, CVector& vecPosition); static bool GetElementRotation(CElement* pElement, CVector& vecRotation, eEulerRotationOrder rotationOrder); + static bool GetElementScale(CElement* pElement, CVector& vecScale); static bool GetElementVelocity(CElement* pElement, CVector& vecVelocity); static bool GetElementTurnVelocity(CElement* pElement, CVector& vecTurnVelocity); static bool GetElementInterior(CElement* pElement, unsigned char& ucInterior); @@ -93,6 +94,7 @@ class CStaticFunctionDefinitions static bool SetElementMatrix(CElement* pElement, const CMatrix& matrix); static bool SetElementPosition(CElement* pElement, const CVector& vecPosition, bool bWarp = true); static bool SetElementRotation(CElement* pElement, const CVector& vecRotation, eEulerRotationOrder rotationOrder, bool bNewWay); + static bool SetElementScale(CElement* pElement, const CVector& vecScale); static bool SetElementVelocity(CElement* pElement, const CVector& vecVelocity); static bool SetElementAngularVelocity(CElement* pElement, const CVector& vecTurnVelocity); static bool SetElementVisibleTo(CElement* pElement, CElement* pReference, bool bVisible); diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp index 661eb56581e..b41d413ee68 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaBuildingDefs.cpp @@ -31,6 +31,8 @@ void CLuaBuildingDefs::AddClass(lua_State* luaVM) lua_newclass(luaVM); lua_classfunction(luaVM, "create", "createBuilding"); + lua_classfunction(luaVM, "getScale", "getElementScale"); + lua_classfunction(luaVM, "setScale", "setElementScale"); lua_registerclass(luaVM, "Building", "Element"); } diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp index 078383c4b28..d7535345fbf 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.cpp @@ -44,6 +44,7 @@ void CLuaElementDefs::LoadFunctions() {"getElementMatrix", getElementMatrix}, {"getElementPosition", getElementPosition}, {"getElementRotation", getElementRotation}, + {"getElementScale", getElementScale}, {"getElementVelocity", getElementVelocity}, {"getElementAngularVelocity", getElementTurnVelocity}, {"getElementsByType", getElementsByType}, @@ -88,6 +89,7 @@ void CLuaElementDefs::LoadFunctions() {"setElementMatrix", setElementMatrix}, {"setElementPosition", setElementPosition}, {"setElementRotation", setElementRotation}, + {"setElementScale", setElementScale}, {"setElementVelocity", setElementVelocity}, {"setElementAngularVelocity", setElementTurnVelocity}, {"setElementVisibleTo", setElementVisibleTo}, @@ -741,6 +743,32 @@ int CLuaElementDefs::OOP_getElementRotation(lua_State* luaVM) return 1; } +int CLuaElementDefs::getElementScale(lua_State* luaVM) +{ + // float float float getElementScale ( element theElement ) + CElement* pElement; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pElement); + + if (!argStream.HasErrors()) + { + CVector vecScale; + if (CStaticFunctionDefinitions::GetElementScale(pElement, vecScale)) + { + lua_pushnumber(luaVM, vecScale.fX); + lua_pushnumber(luaVM, vecScale.fY); + lua_pushnumber(luaVM, vecScale.fZ); + return 3; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaElementDefs::getElementVelocity(lua_State* luaVM) { // float float float getElementVelocity ( element theElement ) @@ -1902,6 +1930,42 @@ int CLuaElementDefs::OOP_setElementRotation(lua_State* luaVM) return 1; } +int CLuaElementDefs::setElementScale(lua_State* luaVM) +{ + // bool setElementScale ( element theElement, float scale ) + // bool setElementScale ( element theElement, float x, float y, float z ) + CElement* pElement; + CVector vecScale; + + CScriptArgReader argStream(luaVM); + argStream.ReadUserData(pElement); + + if (argStream.NextIsVector3D()) + { + argStream.ReadVector3D(vecScale); + } + else + { + argStream.ReadNumber(vecScale.fX); + argStream.ReadNumber(vecScale.fY, vecScale.fX); + argStream.ReadNumber(vecScale.fZ, vecScale.fX); + } + + if (!argStream.HasErrors()) + { + if (CStaticFunctionDefinitions::SetElementScale(pElement, vecScale)) + { + lua_pushboolean(luaVM, true); + return 1; + } + } + else + m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage()); + + lua_pushboolean(luaVM, false); + return 1; +} + int CLuaElementDefs::setElementVelocity(lua_State* luaVM) { // bool setElementVelocity ( element theElement, float speedX, float speedY, float speedZ ) diff --git a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h index 89745b5a3fb..91ab63fabe9 100644 --- a/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h +++ b/Server/mods/deathmatch/logic/luadefs/CLuaElementDefs.h @@ -40,6 +40,7 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE_OOP(getElementMatrix); LUA_DECLARE_OOP(getElementPosition); LUA_DECLARE_OOP(getElementRotation); + LUA_DECLARE(getElementScale); LUA_DECLARE_OOP(getElementVelocity); LUA_DECLARE_OOP(getElementTurnVelocity); LUA_DECLARE(getElementType); @@ -94,6 +95,7 @@ class CLuaElementDefs : public CLuaDefs LUA_DECLARE(setElementMatrix); LUA_DECLARE(setElementPosition); LUA_DECLARE_OOP(setElementRotation); + LUA_DECLARE(setElementScale); LUA_DECLARE(setElementVelocity); LUA_DECLARE(setElementTurnVelocity); LUA_DECLARE(setElementInterior); diff --git a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp index 3ce2a0c39a2..4feea482675 100644 --- a/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp +++ b/Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp @@ -1139,6 +1139,15 @@ bool CEntityAddPacket::Write(NetBitStreamInterface& BitStream) const CBuilding* pLowLodBuilding = pBuilding->GetLowLodElement(); ElementID lowLodBuildingID = pLowLodBuilding ? pLowLodBuilding->GetID() : INVALID_ELEMENT_ID; BitStream.Write(lowLodBuildingID); + + if (BitStream.Can(eBitStreamVersion::BuildingScale)) + { + const CVector& vecScale = pBuilding->GetScale(); + BitStream.Write(vecScale.fX); + BitStream.Write(vecScale.fY); + BitStream.Write(vecScale.fZ); + } + break; } diff --git a/Shared/sdk/net/bitstream.h b/Shared/sdk/net/bitstream.h index 6b04aa6a305..9942fbdbc50 100644 --- a/Shared/sdk/net/bitstream.h +++ b/Shared/sdk/net/bitstream.h @@ -40,6 +40,10 @@ enum class eBitStreamVersion : unsigned short // YYYY-MM-DD // Name, + // Building scale is now included in the entity add packet and can be changed at runtime + // with setElementScale, so late-joining clients receive it. + BuildingScale, + // This allows us to automatically increment the BitStreamVersion when things are added to this enum. // Make sure you only add things above this comment. Next, diff --git a/Shared/sdk/net/rpc_enums.h b/Shared/sdk/net/rpc_enums.h index 113faf07d62..1f2a1244925 100644 --- a/Shared/sdk/net/rpc_enums.h +++ b/Shared/sdk/net/rpc_enums.h @@ -295,5 +295,7 @@ enum eElementRPCFunctions SET_CUSTOM_WEAPON_WEAPON_RANGE, + SET_ELEMENT_SCALE, + NUM_RPC_FUNCS // Add above this line };