mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
947 lines
34 KiB
C++
947 lines
34 KiB
C++
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include "Core.hpp"
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
#include "Entity/Blip.hpp"
|
||
|
#include "Entity/Checkpoint.hpp"
|
||
|
#include "Entity/Keybind.hpp"
|
||
|
#include "Entity/Object.hpp"
|
||
|
#include "Entity/Pickup.hpp"
|
||
|
#include "Entity/Player.hpp"
|
||
|
#include "Entity/Vehicle.hpp"
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
namespace SqMod {
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::ImportBlips()
|
||
|
{
|
||
|
// Information about the blip entity
|
||
|
Int32 world = -1, scale = -1, sprid = -1;
|
||
|
Uint32 color = 0;
|
||
|
Float32 x = 0.0, y = 0.0, z = 0.0;
|
||
|
|
||
|
for (Int32 i = 0; i < SQMOD_BLIP_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->CheckEntityExists(vcmpEntityPoolBlip, i) && INVALID_ENTITY(m_Blips[i].mID))
|
||
|
{
|
||
|
_Func->GetCoordBlipInfo(i, &world, &x, &y, &z, &scale, &color, &sprid);
|
||
|
// Make the properties available before triggering the event
|
||
|
m_Blips[i].mWorld = world;
|
||
|
m_Blips[i].mScale = scale;
|
||
|
m_Blips[i].mSprID = sprid;
|
||
|
m_Blips[i].mPosition.Set(x, y, z);
|
||
|
m_Blips[i].mColor.SetRGBA(color);
|
||
|
// Attempt to allocate the instance
|
||
|
AllocBlip(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportCheckpoints()
|
||
|
{
|
||
|
for (Int32 i = 0; i < SQMOD_CHECKPOINT_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->CheckEntityExists(vcmpEntityPoolCheckPoint, i) && INVALID_ENTITY(m_Checkpoints[i].mID))
|
||
|
{
|
||
|
AllocCheckpoint(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportKeybinds()
|
||
|
{
|
||
|
// Information about the key-bind entity
|
||
|
Uint8 release = 0;
|
||
|
Int32 first = -1, second = -1, third = -1;
|
||
|
|
||
|
for (Int32 i = 0; i < SQMOD_KEYBIND_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if ((_Func->GetKeyBindData(i, &release, &first, &second, &third) != vcmpErrorNoSuchEntity)
|
||
|
&& (INVALID_ENTITY(m_Keybinds[i].mID)))
|
||
|
{
|
||
|
// Make the properties available before triggering the event
|
||
|
m_Keybinds[i].mFirst = first;
|
||
|
m_Keybinds[i].mSecond = second;
|
||
|
m_Keybinds[i].mThird = third;
|
||
|
m_Keybinds[i].mRelease = release;
|
||
|
// Attempt to allocate the instance
|
||
|
AllocKeybind(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportObjects()
|
||
|
{
|
||
|
for (Int32 i = 0; i < SQMOD_OBJECT_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->CheckEntityExists(vcmpEntityPoolObject, i) && INVALID_ENTITY(m_Objects[i].mID))
|
||
|
{
|
||
|
AllocObject(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportPickups()
|
||
|
{
|
||
|
for (Int32 i = 0; i < SQMOD_PICKUP_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->CheckEntityExists(vcmpEntityPoolPickup, i) && (INVALID_ENTITY(m_Pickups[i].mID)))
|
||
|
{
|
||
|
AllocPickup(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportPlayers()
|
||
|
{
|
||
|
for (Int32 i = 0; i < SQMOD_PLAYER_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->IsPlayerConnected(i) && (INVALID_ENTITY(m_Players[i].mID)))
|
||
|
{
|
||
|
ConnectPlayer(i, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
void Core::ImportVehicles()
|
||
|
{
|
||
|
for (Int32 i = 0; i < SQMOD_VEHICLE_POOL; ++i)
|
||
|
{
|
||
|
// See if this entity exists on the server and whether was not allocated already
|
||
|
if (_Func->CheckEntityExists(vcmpEntityPoolVehicle, i) && INVALID_ENTITY(m_Vehicles[i].mID))
|
||
|
{
|
||
|
AllocVehicle(i, false, SQMOD_CREATE_IMPORT, NullObject());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocBlip(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_BLIP_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate blip with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
BlipInst & inst = m_Blips[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CBlip(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a blip instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitBlipCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocCheckpoint(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_CHECKPOINT_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate checkpoint with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
CheckpointInst & inst = m_Checkpoints[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CCheckpoint(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a checkpoint instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitCheckpointCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocKeybind(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_KEYBIND_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate keybind with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
KeybindInst & inst = m_Keybinds[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CKeybind(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a keybind instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitKeybindCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocObject(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_OBJECT_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate object with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
ObjectInst & inst = m_Objects[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CObject(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a object instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitObjectCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocPickup(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_PICKUP_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate pickup with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
PickupInst & inst = m_Pickups[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CPickup(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a pickup instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitPickupCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::AllocVehicle(Int32 id, bool owned, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_VEHICLE_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate vehicle with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
VehicleInst & inst = m_Vehicles[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return inst.mObj; // Return the existing instance
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CVehicle(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a vehicle instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Specify whether the entity is owned by this plug-in
|
||
|
if (owned)
|
||
|
{
|
||
|
inst.mFlags |= ENF_OWNED;
|
||
|
}
|
||
|
else if (inst.mFlags & ENF_OWNED)
|
||
|
{
|
||
|
inst.mFlags ^= ENF_OWNED;
|
||
|
}
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitVehicleCreated(id, header, payload);
|
||
|
// Return the script object
|
||
|
return inst.mObj;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocBlip(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_BLIP_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate blip with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
BlipInst & inst = m_Blips[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitBlipDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->DestroyCoordBlip(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocCheckpoint(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_CHECKPOINT_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate checkpoint with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
CheckpointInst & inst = m_Checkpoints[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitCheckpointDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->DeleteCheckPoint(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocKeybind(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_KEYBIND_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate keybind with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
KeybindInst & inst = m_Keybinds[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitBlipDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->RemoveKeyBind(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocObject(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_OBJECT_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate object with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
ObjectInst & inst = m_Objects[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitObjectDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->DeleteObject(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocPickup(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_PICKUP_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate pickup with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
PickupInst & inst = m_Pickups[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitPickupDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->DeletePickup(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::DeallocVehicle(Int32 id, bool destroy, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_VEHICLE_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate vehicle with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
VehicleInst & inst = m_Vehicles[id];
|
||
|
// Make sure that the instance is even allocated
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitVehicleDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
}
|
||
|
// Should we delete this entity from the server as well?
|
||
|
if (destroy || (inst.mFlags & ENF_OWNED))
|
||
|
{
|
||
|
_Func->DeleteVehicle(inst.mID);
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewBlip(Int32 index, Int32 world, Float32 x, Float32 y, Float32 z,
|
||
|
Int32 scale, Uint32 color, Int32 sprid,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->CreateCoordBlip(index, world, x, y, z, scale, color, sprid);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorPoolExhausted)
|
||
|
{
|
||
|
STHROWF("Blip pool was exhausted: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_BLIP_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid blip: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocBlip(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewCheckpoint(Int32 player, Int32 world, bool sphere, Float32 x, Float32 y, Float32 z,
|
||
|
Uint8 r, Uint8 g, Uint8 b, Uint8 a, Float32 radius,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->CreateCheckPoint(player, world, sphere, x, y, z, r, g, b, a, radius);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorNoSuchEntity)
|
||
|
{
|
||
|
STHROWF("Invalid player reference: %d", player);
|
||
|
}
|
||
|
else if (_Func->GetLastError() == vcmpErrorPoolExhausted)
|
||
|
{
|
||
|
STHROWF("Checkpoint pool was exhausted: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_CHECKPOINT_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid checkpoint: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocCheckpoint(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewKeybind(Int32 slot, bool release, Int32 primary, Int32 secondary, Int32 alternative,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->RegisterKeyBind(slot, release, primary, secondary, alternative);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorArgumentOutOfBounds)
|
||
|
{
|
||
|
STHROWF("Out of bounds keybind argument: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_KEYBIND_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid keybind: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocKeybind(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewObject(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z, Int32 alpha,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->CreateObject(model, world, x, y, z, alpha);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorPoolExhausted)
|
||
|
{
|
||
|
STHROWF("Object pool was exhausted: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_OBJECT_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid object: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocObject(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewPickup(Int32 model, Int32 world, Int32 quantity,
|
||
|
Float32 x, Float32 y, Float32 z, Int32 alpha, bool automatic,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->CreatePickup(model, world, quantity, x, y, z, alpha, automatic);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorPoolExhausted)
|
||
|
{
|
||
|
STHROWF("Pickup pool was exhausted: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_PICKUP_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid pickup: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocPickup(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
Object & Core::NewVehicle(Int32 model, Int32 world, Float32 x, Float32 y, Float32 z,
|
||
|
Float32 angle, Int32 primary, Int32 secondary,
|
||
|
Int32 header, Object & payload)
|
||
|
{
|
||
|
// Request the server to create this entity
|
||
|
const Int32 id = _Func->CreateVehicle(model, world, x, y, z, angle, primary, secondary);
|
||
|
// See if the entity creation failed on the server
|
||
|
if (_Func->GetLastError() == vcmpErrorArgumentOutOfBounds)
|
||
|
{
|
||
|
STHROWF("Out of bounds vehicle argument: %d", id);
|
||
|
}
|
||
|
else if (_Func->GetLastError() == vcmpErrorPoolExhausted)
|
||
|
{
|
||
|
STHROWF("Vehicle pool was exhausted: %d", id);
|
||
|
}
|
||
|
// Validate the identifier returned by the server
|
||
|
else if (INVALID_ENTITYEX(id, SQMOD_VEHICLE_POOL))
|
||
|
{
|
||
|
STHROWF("Server returned invalid vehicle: %d", id);
|
||
|
}
|
||
|
// Attempt to allocate this entity and return the result
|
||
|
return AllocVehicle(id, true, header, payload);
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
bool Core::DelBlip(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocBlip(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Core::DelCheckpoint(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocCheckpoint(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Core::DelKeybind(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocKeybind(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Core::DelObject(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocObject(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Core::DelPickup(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocPickup(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
bool Core::DelVehicle(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Attempt to destroy and deallocate the specified entity instance
|
||
|
DeallocVehicle(id, true, header, payload);
|
||
|
// The entity could be destroyed
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------------------------
|
||
|
void Core::ConnectPlayer(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_PLAYER_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot allocate player with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
PlayerInst & inst = m_Players[id];
|
||
|
// Make sure that the instance isn't already allocated
|
||
|
if (VALID_ENTITY(inst.mID))
|
||
|
{
|
||
|
return; // Nothing to allocate!
|
||
|
}
|
||
|
// Instantiate the entity manager
|
||
|
inst.mInst = new CPlayer(id);
|
||
|
// Create the script object
|
||
|
inst.mObj = Object(inst.mInst, m_VM);
|
||
|
// Make sure that both the instance and script object could be created
|
||
|
if (!inst.mInst || inst.mObj.IsNull())
|
||
|
{
|
||
|
ResetInst(inst);
|
||
|
STHROWF("Unable to create a player instance for: %d", id);
|
||
|
}
|
||
|
// Assign the specified entity identifier
|
||
|
inst.mID = id;
|
||
|
// Initialize the position
|
||
|
_Func->GetPlayerPosition(id, &inst.mLastPosition.x, &inst.mLastPosition.y, &inst.mLastPosition.z);
|
||
|
// Initialize the remaining attributes
|
||
|
inst.mLastWeapon = _Func->GetPlayerWeapon(id);
|
||
|
inst.mLastHealth = _Func->GetPlayerHealth(id);
|
||
|
inst.mLastArmour = _Func->GetPlayerArmour(id);
|
||
|
inst.mLastHeading = _Func->GetPlayerHeading(id);
|
||
|
// Let the script callbacks know about this entity
|
||
|
EmitPlayerCreated(id, header, payload);
|
||
|
}
|
||
|
|
||
|
void Core::DisconnectPlayer(Int32 id, Int32 header, Object & payload)
|
||
|
{
|
||
|
// Make sure that the specified entity identifier is valid
|
||
|
if (INVALID_ENTITYEX(id, SQMOD_PLAYER_POOL))
|
||
|
{
|
||
|
STHROWF("Cannot deallocate player with invalid identifier: %d", id);
|
||
|
}
|
||
|
// Retrieve the specified entity instance
|
||
|
PlayerInst & inst = m_Players[id];
|
||
|
// Make sure that the instance is even allocated and we're allowed to deallocate it
|
||
|
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
|
||
|
{
|
||
|
return; // Nothing to deallocate!
|
||
|
}
|
||
|
// Prevent further attempts to delete this entity
|
||
|
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
|
||
|
// Let the script callbacks know this entity should no longer be used
|
||
|
try
|
||
|
{
|
||
|
EmitPlayerDestroyed(id, header, payload);
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// The error was probably dealt with already
|
||
|
}
|
||
|
// Is there a manager instance associated with this entity?
|
||
|
if (inst.mInst)
|
||
|
{
|
||
|
// Prevent further use of this entity
|
||
|
inst.mInst->m_ID = -1;
|
||
|
// Release user data to avoid dangling or circular references
|
||
|
inst.mInst->m_Data.Release();
|
||
|
// Release the used memory buffer
|
||
|
inst.mInst->m_Buffer.ResetAll();
|
||
|
}
|
||
|
// Reset the entity instance
|
||
|
ResetInst(inst);
|
||
|
// Release associated script callbacks
|
||
|
ResetFunc(inst);
|
||
|
// Prevent further use of the manager instance
|
||
|
inst.mInst = nullptr;
|
||
|
// Release the script object, if any
|
||
|
inst.mObj.Release();
|
||
|
}
|
||
|
|
||
|
} // Namespace:: SqMod
|