1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-11-03 07:47:18 +01:00

Rename source to module.

This commit is contained in:
Sandu Liviu Catalin
2020-03-21 23:02:27 +02:00
parent a5c87bae5e
commit c0fd374404
237 changed files with 0 additions and 272718 deletions

920
module/Misc/Algo.cpp Normal file
View File

@@ -0,0 +1,920 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Algo.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"
// ------------------------------------------------------------------------------------------------
#define SQMOD_VALID_NAME_STR(t) if (!t) { STHROWF("The specified name is invalid"); }
// ------------------------------------------------------------------------------------------------
namespace SqMod {
namespace Algo {
/* ------------------------------------------------------------------------------------------------
* Used to fake a string so a raw buffer can be used with search algorithms.
*/
struct FakeString
{
// --------------------------------------------------------------------------------------------
SQChar mBuffer[SQMOD_PLAYER_TMP_BUFFER]; // Buffer to hold the data.
std::size_t mSize; // The size of the data in the buffer.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
FakeString()
: mBuffer(), mSize(0)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Grab the player name from the server into the buffer.
*/
void GrabName(int id)
{
// Clear any previous string (just in case)
mBuffer[0] = '\0';
mSize = 0;
// Query the server for the name of the managed player
if (_Func->GetPlayerName(id, mBuffer, sizeof(mBuffer)) == vcmpErrorNone)
{
mSize = std::strlen(mBuffer); // Calculate the name length
}
}
/* --------------------------------------------------------------------------------------------
* Retrieve the size of the name.
*/
std::size_t size() const
{
return mSize;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the string buffer.
*/
CSStr c_str() const
{
return mBuffer;
}
/* --------------------------------------------------------------------------------------------
* Find in buffer contents of another string.
*/
std::size_t find(CSStr s) const
{
CCStr r = std::strstr(mBuffer, s);
return (r == nullptr) ? String::npos : (r - mBuffer);
}
/* --------------------------------------------------------------------------------------------
* Compare the buffer contents with another string.
*/
int compare(CSStr s) const
{
return std::strcmp(mBuffer, s);
}
/* --------------------------------------------------------------------------------------------
* Compare the buffer contents with another string.
*/
int compare(std::size_t pos, std::size_t len, CSStr s) const
{
return std::strncmp(mBuffer + pos, s, len);
}
};
/* ------------------------------------------------------------------------------------------------
* Functor to retrieve the player name.
*/
struct PlayerName
{
// --------------------------------------------------------------------------------------------
FakeString mStr; // The string where the name is stored.
/* --------------------------------------------------------------------------------------------
* Function call operator.
*/
const FakeString & operator () (const typename InstSpec< CPlayer >::Instance & inst)
{
mStr.GrabName(inst.mID);
return mStr;
}
};
// ------------------------------------------------------------------------------------------------
static const LightObj & Blip_FindBySprID(Int32 sprid)
{
// Perform a range check on the specified identifier
if (sprid < 0)
{
STHROWF("The specified sprite identifier is invalid: %d", sprid);
}
// Obtain the ends of the entity pool
Core::Blips::const_iterator itr = Core::Get().GetBlips().cbegin();
Core::Blips::const_iterator end = Core::Get().GetBlips().cend();
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Does the identifier match the specified one?
if (itr->mSprID == sprid)
{
return itr->mObj; // Stop searching and return this entity
}
}
// Unable to locate a blip matching the specified identifier
return Core::Get().GetNullBlip();
}
/* ------------------------------------------------------------------------------------------------
* Collect all players where the name matches or not the specified one.
*/
static inline Array Player_AllWhereNameEquals(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Remember the current stack size
const StackGuard sg;
// Allocate an empty array on the stack
sq_newarray(DefaultVM::Get(), 0);
// Process each entity in the pool
EachEquals(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
AppendElemFunc< CPlayer >(), name, !neg, cs);
// Return the array at the top of the stack
return Var< Array >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Collect all players where the name begins or not with the specified string.
*/
static inline Array Player_AllWhereNameBegins(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Remember the current stack size
const StackGuard sg;
// Allocate an empty array on the stack
sq_newarray(DefaultVM::Get(), 0);
// Process each entity in the pool
EachBegins(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
AppendElemFunc< CPlayer >(), name, strlen(name), !neg, cs);
// Return the array at the top of the stack
return Var< Array >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Collect all players where the name ends or not with the specified string.
*/
static inline Array Player_AllWhereNameEnds(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Remember the current stack size
const StackGuard sg;
// Allocate an empty array on the stack
sq_newarray(DefaultVM::Get(), 0);
// Process each entity in the pool
EachEnds(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
AppendElemFunc< CPlayer >(), name, strlen(name), !neg, cs);
// Return the array at the top of the stack
return Var< Array >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Collect all players where the name contains or not the specified string.
*/
static inline Array Player_AllWhereNameContains(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Remember the current stack size
const StackGuard sg;
// Allocate an empty array on the stack
sq_newarray(DefaultVM::Get(), 0);
// Process each entity in the pool
EachContains(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
AppendElemFunc< CPlayer >(), name, !neg, cs);
// Return the array at the top of the stack
return Var< Array >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Collect all players where the name matches or not the specified filter.
*/
static inline Array Player_AllWhereNameMatches(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Remember the current stack size
const StackGuard sg;
// Allocate an empty array on the stack
sq_newarray(DefaultVM::Get(), 0);
// Process each entity in the pool
EachMatches(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
AppendElemFunc< CPlayer >(), name, !neg, cs);
// Return the array at the top of the stack
return Var< Array >(DefaultVM::Get(), -1).value;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the first player where the name matches or not the specified one.
*/
static inline LightObj Player_FirstWhereNameEquals(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element receiver
RecvElemFunc< CPlayer > recv;
// Process each entity in the pool
FirstEquals(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< RecvElemFunc< CPlayer > >(recv), name, !neg, cs);
// Return the received element, if any
return recv.mObj;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the first player where the name begins or not with the specified string.
*/
static inline LightObj Player_FirstWhereNameBegins(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element receiver
RecvElemFunc< CPlayer > recv;
// Process each entity in the pool
FirstBegins(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< RecvElemFunc< CPlayer > >(recv), name, strlen(name), !neg, cs);
// Return the received element, if any
return recv.mObj;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the first player where the name ends or not with the specified string.
*/
static inline LightObj Player_FirstWhereNameEnds(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element receiver
RecvElemFunc< CPlayer > recv;
// Process each entity in the pool
FirstEnds(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< RecvElemFunc< CPlayer > >(recv), name, strlen(name), !neg, cs);
// Return the received element, if any
return recv.mObj;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the first player where the name contains or not the specified string.
*/
static inline LightObj Player_FirstWhereNameContains(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element receiver
RecvElemFunc< CPlayer > recv;
// Process each entity in the pool
FirstContains(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< RecvElemFunc< CPlayer > >(recv), name, !neg, cs);
// Return the received element, if any
return recv.mObj;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the first player where the name matches or not the specified filter.
*/
static inline LightObj Player_FirstWhereNameMatches(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element receiver
RecvElemFunc< CPlayer > recv;
// Process each entity in the pool
FirstMatches(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< RecvElemFunc< CPlayer > >(recv), name, !neg, cs);
// Return the received element, if any
return recv.mObj;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name matches or not the specified one.
*/
static inline Uint32 Player_EachWhereNameEquals(bool neg, bool cs, CSStr name, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemFunc< CPlayer > fwd(env, func);
// Process each entity in the pool
EachEqualsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name matches or not the specified one.
*/
static inline Uint32 Player_EachWhereNameEqualsData(bool neg, bool cs, CSStr name, LightObj & data, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemDataFunc< CPlayer > fwd(data, env, func);
// Process each entity in the pool
EachEqualsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemDataFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name begins with the specified string.
*/
static inline Uint32 Player_EachWhereNameBegins(bool neg, bool cs, CSStr name, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemFunc< CPlayer > fwd(env, func);
// Process each entity in the pool
EachBeginsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemFunc< CPlayer > >(fwd), name, strlen(name), !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name begins with the specified string.
*/
static inline Uint32 Player_EachWhereNameBeginsData(bool neg, bool cs, CSStr name, LightObj & data, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemDataFunc< CPlayer > fwd(data, env, func);
// Process each entity in the pool
EachBeginsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemDataFunc< CPlayer > >(fwd), name, strlen(name), !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name ends or not with the specified string.
*/
static inline Uint32 Player_EachWhereNameEnds(bool neg, bool cs, CSStr name, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemFunc< CPlayer > fwd(env, func);
// Process each entity in the pool
EachEndsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemFunc< CPlayer > >(fwd), name, strlen(name), !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name ends or not with the specified string.
*/
static inline Uint32 Player_EachWhereNameEndsData(bool neg, bool cs, CSStr name, LightObj & data, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemDataFunc< CPlayer > fwd(data, env, func);
// Process each entity in the pool
EachEndsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemDataFunc< CPlayer > >(fwd), name, strlen(name), !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name contains the specified string.
*/
static inline Uint32 Player_EachWhereNameContains(bool neg, bool cs, CSStr name, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemFunc< CPlayer > fwd(env, func);
// Process each entity in the pool
EachContainsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name contains the specified string.
*/
static inline Uint32 Player_EachWhereNameContainsData(bool neg, bool cs, CSStr name, LightObj & data, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemDataFunc< CPlayer > fwd(data, env, func);
// Process each entity in the pool
EachContainsWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemDataFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name matches the specified filter.
*/
static inline Uint32 Player_EachWhereNameMatches(bool neg, bool cs, CSStr name, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemFunc< CPlayer > fwd(env, func);
// Process each entity in the pool
EachMatchesWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Process all entities of this type where the name matches the specified filter.
*/
static inline Uint32 Player_EachWhereNameMatchesData(bool neg, bool cs, CSStr name, LightObj & data, LightObj & env, Function & func)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element forwarder
ForwardElemDataFunc< CPlayer > fwd(data, env, func);
// Process each entity in the pool
EachMatchesWhile(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< ForwardElemDataFunc< CPlayer > >(fwd), name, !neg, cs);
// Return the forward count
return fwd.mCount;
}
/* --------------------------------------------------------------------------------------------
* Count all entities of this type where the name matches or not the specified one.
*/
static inline Uint32 Player_CountWhereNameEquals(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element counter
CountElemFunc< CPlayer > cnt;
// Process each entity in the pool
EachEquals(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< CountElemFunc< CPlayer > >(cnt), name, !neg, cs);
// Return the count
return cnt;
}
/* --------------------------------------------------------------------------------------------
* Count all entities of this type where the name begins with the specified string.
*/
static inline Uint32 Player_CountWhereNameBegins(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element counter
CountElemFunc< CPlayer > cnt;
// Process each entity in the pool
EachBegins(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< CountElemFunc< CPlayer > >(cnt), name, strlen(name), !neg, cs);
// Return the count
return cnt;
}
/* --------------------------------------------------------------------------------------------
* Count all entities of this type where the name ends or not with the specified string.
*/
static inline Uint32 Player_CountWhereNameEnds(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element counter
CountElemFunc< CPlayer > cnt;
// Process each entity in the pool
EachEnds(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< CountElemFunc< CPlayer > >(cnt), name, strlen(name), !neg, cs);
// Return the count
return cnt;
}
/* --------------------------------------------------------------------------------------------
* Count all entities of this type where the name contains the specified string.
*/
static inline Uint32 Player_CountWhereNameContains(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element counter
CountElemFunc< CPlayer > cnt;
// Process each entity in the pool
EachContains(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< CountElemFunc< CPlayer > >(cnt), name, !neg, cs);
// Return the count
return cnt;
}
/* --------------------------------------------------------------------------------------------
* Count all entities of this type where the name matches the specified filter.
*/
static inline Uint32 Player_CountWhereNameMatches(bool neg, bool cs, CSStr name)
{
SQMOD_VALID_NAME_STR(name)
// Create a new element counter
CountElemFunc< CPlayer > cnt;
// Process each entity in the pool
EachMatches(InstSpec< CPlayer >::CBegin(), InstSpec< CPlayer >::CEnd(),
ValidInstFunc< CPlayer >(), PlayerName(),
std::reference_wrapper< CountElemFunc< CPlayer > >(cnt), name, !neg, cs);
// Return the count
return cnt;
}
// ================================================================================================
void Register(HSQUIRRELVM vm)
{
Table collect_ns(vm);
collect_ns.Bind(_SC("Blip"), Table(vm)
.Func(_SC("Active"), &Entity< CBlip >::AllActive)
.Func(_SC("TagEquals"), &Entity< CBlip >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CBlip >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CBlip >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CBlip >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CBlip >::AllWhereTagMatches)
);
collect_ns.Bind(_SC("Checkpoint"), Table(vm)
.Func(_SC("Active"), &Entity< CCheckpoint >::AllActive)
.Func(_SC("TagEquals"), &Entity< CCheckpoint >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CCheckpoint >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CCheckpoint >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CCheckpoint >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CCheckpoint >::AllWhereTagMatches)
);
collect_ns.Bind(_SC("Keybind"), Table(vm)
.Func(_SC("Active"), &Entity< CKeybind >::AllActive)
.Func(_SC("TagEquals"), &Entity< CKeybind >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CKeybind >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CKeybind >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CKeybind >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CKeybind >::AllWhereTagMatches)
);
collect_ns.Bind(_SC("Object"), Table(vm)
.Func(_SC("Active"), &Entity< CObject >::AllActive)
.Func(_SC("TagEquals"), &Entity< CObject >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CObject >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CObject >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CObject >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CObject >::AllWhereTagMatches)
);
collect_ns.Bind(_SC("Pickup"), Table(vm)
.Func(_SC("Active"), &Entity< CPickup >::AllActive)
.Func(_SC("TagEquals"), &Entity< CPickup >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPickup >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPickup >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPickup >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPickup >::AllWhereTagMatches)
);
collect_ns.Bind(_SC("Player"), Table(vm)
.Func(_SC("Active"), &Entity< CPlayer >::AllActive)
.Func(_SC("TagEquals"), &Entity< CPlayer >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPlayer >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPlayer >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPlayer >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPlayer >::AllWhereTagMatches)
.Func(_SC("NameEquals"), &Player_AllWhereNameEquals)
.Func(_SC("NameBegins"), &Player_AllWhereNameBegins)
.Func(_SC("NameEnds"), &Player_AllWhereNameEnds)
.Func(_SC("NameContains"), &Player_AllWhereNameContains)
.Func(_SC("NameMatches"), &Player_AllWhereNameMatches)
);
collect_ns.Bind(_SC("Vehicle"), Table(vm)
.Func(_SC("Active"), &Entity< CVehicle >::AllActive)
.Func(_SC("TagEquals"), &Entity< CVehicle >::AllWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CVehicle >::AllWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CVehicle >::AllWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CVehicle >::AllWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CVehicle >::AllWhereTagMatches)
);
RootTable(vm).Bind(_SC("SqCollect"), collect_ns);
Table find_ns(vm);
find_ns.Bind(_SC("Blip"), Table(vm)
.Func(_SC("WithID"), &Entity< CBlip >::FindByID)
.Func(_SC("TagEquals"), &Entity< CBlip >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CBlip >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CBlip >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CBlip >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CBlip >::FirstWhereTagMatches)
.Func(_SC("WithSprID"), &Blip_FindBySprID)
);
find_ns.Bind(_SC("Checkpoint"), Table(vm)
.Func(_SC("WithID"), &Entity< CCheckpoint >::FindByID)
.Func(_SC("TagEquals"), &Entity< CCheckpoint >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CCheckpoint >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CCheckpoint >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CCheckpoint >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CCheckpoint >::FirstWhereTagMatches)
);
find_ns.Bind(_SC("Keybind"), Table(vm)
.Func(_SC("WithID"), &Entity< CKeybind >::FindByID)
.Func(_SC("TagEquals"), &Entity< CKeybind >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CKeybind >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CKeybind >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CKeybind >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CKeybind >::FirstWhereTagMatches)
);
find_ns.Bind(_SC("Object"), Table(vm)
.Func(_SC("WithID"), &Entity< CObject >::FindByID)
.Func(_SC("TagEquals"), &Entity< CObject >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CObject >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CObject >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CObject >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CObject >::FirstWhereTagMatches)
);
find_ns.Bind(_SC("Pickup"), Table(vm)
.Func(_SC("WithID"), &Entity< CPickup >::FindByID)
.Func(_SC("TagEquals"), &Entity< CPickup >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPickup >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPickup >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPickup >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPickup >::FirstWhereTagMatches)
);
find_ns.Bind(_SC("Player"), Table(vm)
.Func(_SC("WithID"), &Entity< CPlayer >::FindByID)
.Func(_SC("TagEquals"), &Entity< CPlayer >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPlayer >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPlayer >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPlayer >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPlayer >::FirstWhereTagMatches)
.Func(_SC("NameEquals"), &Player_FirstWhereNameEquals)
.Func(_SC("NameBegins"), &Player_FirstWhereNameBegins)
.Func(_SC("NameEnds"), &Player_FirstWhereNameEnds)
.Func(_SC("NameContains"), &Player_FirstWhereNameContains)
.Func(_SC("NameMatches"), &Player_FirstWhereNameMatches)
);
find_ns.Bind(_SC("Vehicle"), Table(vm)
.Func(_SC("WithID"), &Entity< CVehicle >::FindByID)
.Func(_SC("TagEquals"), &Entity< CVehicle >::FirstWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CVehicle >::FirstWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CVehicle >::FirstWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CVehicle >::FirstWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CVehicle >::FirstWhereTagMatches)
);
RootTable(vm).Bind(_SC("SqFind"), find_ns);
Table each_ns(vm);
each_ns.Bind(_SC("Blip"), Table(vm)
.Func(_SC("Active"), &Entity< CBlip >::EachActive)
.Func(_SC("TagEquals"), &Entity< CBlip >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CBlip >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CBlip >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CBlip >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CBlip >::EachWhereTagMatches)
);
each_ns.Bind(_SC("Checkpoint"), Table(vm)
.Func(_SC("Active"), &Entity< CCheckpoint >::EachActive)
.Func(_SC("TagEquals"), &Entity< CCheckpoint >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CCheckpoint >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CCheckpoint >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CCheckpoint >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CCheckpoint >::EachWhereTagMatches)
);
each_ns.Bind(_SC("Keybind"), Table(vm)
.Func(_SC("Active"), &Entity< CKeybind >::EachActive)
.Func(_SC("TagEquals"), &Entity< CKeybind >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CKeybind >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CKeybind >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CKeybind >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CKeybind >::EachWhereTagMatches)
);
each_ns.Bind(_SC("Object"), Table(vm)
.Func(_SC("Active"), &Entity< CObject >::EachActive)
.Func(_SC("TagEquals"), &Entity< CObject >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CObject >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CObject >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CObject >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CObject >::EachWhereTagMatches)
);
each_ns.Bind(_SC("Pickup"), Table(vm)
.Func(_SC("Active"), &Entity< CPickup >::EachActive)
.Func(_SC("TagEquals"), &Entity< CPickup >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPickup >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPickup >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPickup >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPickup >::EachWhereTagMatches)
);
each_ns.Bind(_SC("Player"), Table(vm)
.Func(_SC("Active"), &Entity< CPlayer >::EachActive)
.Func(_SC("TagEquals"), &Entity< CPlayer >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPlayer >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPlayer >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPlayer >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPlayer >::EachWhereTagMatches)
.Func(_SC("NameEquals"), &Player_EachWhereNameEquals)
.Func(_SC("NameBegins"), &Player_EachWhereNameBegins)
.Func(_SC("NameEnds"), &Player_EachWhereNameEnds)
.Func(_SC("NameContains"), &Player_EachWhereNameContains)
.Func(_SC("NameMatches"), &Player_EachWhereNameMatches)
);
each_ns.Bind(_SC("Vehicle"), Table(vm)
.Func(_SC("Active"), &Entity< CVehicle >::EachActive)
.Func(_SC("TagEquals"), &Entity< CVehicle >::EachWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CVehicle >::EachWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CVehicle >::EachWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CVehicle >::EachWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CVehicle >::EachWhereTagMatches)
);
RootTable(vm).Bind(_SC("SqForeach"), each_ns);
Table exeach_ns(vm);
exeach_ns.Bind(_SC("Blip"), Table(vm)
.Func(_SC("Active"), &Entity< CBlip >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CBlip >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CBlip >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CBlip >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CBlip >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CBlip >::EachWhereTagMatchesData)
);
exeach_ns.Bind(_SC("Checkpoint"), Table(vm)
.Func(_SC("Active"), &Entity< CCheckpoint >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CCheckpoint >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CCheckpoint >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CCheckpoint >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CCheckpoint >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CCheckpoint >::EachWhereTagMatchesData)
);
exeach_ns.Bind(_SC("Keybind"), Table(vm)
.Func(_SC("Active"), &Entity< CKeybind >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CKeybind >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CKeybind >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CKeybind >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CKeybind >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CKeybind >::EachWhereTagMatchesData)
);
exeach_ns.Bind(_SC("Object"), Table(vm)
.Func(_SC("Active"), &Entity< CObject >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CObject >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CObject >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CObject >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CObject >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CObject >::EachWhereTagMatchesData)
);
exeach_ns.Bind(_SC("Pickup"), Table(vm)
.Func(_SC("Active"), &Entity< CPickup >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CPickup >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CPickup >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CPickup >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CPickup >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CPickup >::EachWhereTagMatchesData)
);
exeach_ns.Bind(_SC("Player"), Table(vm)
.Func(_SC("Active"), &Entity< CPlayer >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CPlayer >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CPlayer >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CPlayer >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CPlayer >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CPlayer >::EachWhereTagMatchesData)
.Func(_SC("NameEquals"), &Player_EachWhereNameEqualsData)
.Func(_SC("NameBegins"), &Player_EachWhereNameBeginsData)
.Func(_SC("NameEnds"), &Player_EachWhereNameEndsData)
.Func(_SC("NameContains"), &Player_EachWhereNameContainsData)
.Func(_SC("NameMatches"), &Player_EachWhereNameMatchesData)
);
exeach_ns.Bind(_SC("Vehicle"), Table(vm)
.Func(_SC("Active"), &Entity< CVehicle >::EachActiveData)
.Func(_SC("TagEquals"), &Entity< CVehicle >::EachWhereTagEqualsData)
.Func(_SC("TagBegins"), &Entity< CVehicle >::EachWhereTagBeginsData)
.Func(_SC("TagEnds"), &Entity< CVehicle >::EachWhereTagEndsData)
.Func(_SC("TagContains"), &Entity< CVehicle >::EachWhereTagContainsData)
.Func(_SC("TagMatches"), &Entity< CVehicle >::EachWhereTagMatchesData)
);
RootTable(vm).Bind(_SC("SqForeachEx"), exeach_ns);
Table count_ns(vm);
count_ns.Bind(_SC("Blip"), Table(vm)
.Func(_SC("Active"), &Entity< CBlip >::CountActive)
.Func(_SC("TagEquals"), &Entity< CBlip >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CBlip >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CBlip >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CBlip >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CBlip >::CountWhereTagMatches)
);
count_ns.Bind(_SC("Checkpoint"), Table(vm)
.Func(_SC("Active"), &Entity< CCheckpoint >::CountActive)
.Func(_SC("TagEquals"), &Entity< CCheckpoint >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CCheckpoint >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CCheckpoint >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CCheckpoint >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CCheckpoint >::CountWhereTagMatches)
);
count_ns.Bind(_SC("Keybind"), Table(vm)
.Func(_SC("Active"), &Entity< CKeybind >::CountActive)
.Func(_SC("TagEquals"), &Entity< CKeybind >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CKeybind >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CKeybind >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CKeybind >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CKeybind >::CountWhereTagMatches)
);
count_ns.Bind(_SC("Object"), Table(vm)
.Func(_SC("Active"), &Entity< CObject >::CountActive)
.Func(_SC("TagEquals"), &Entity< CObject >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CObject >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CObject >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CObject >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CObject >::CountWhereTagMatches)
);
count_ns.Bind(_SC("Pickup"), Table(vm)
.Func(_SC("Active"), &Entity< CPickup >::CountActive)
.Func(_SC("TagEquals"), &Entity< CPickup >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPickup >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPickup >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPickup >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPickup >::CountWhereTagMatches)
);
count_ns.Bind(_SC("Player"), Table(vm)
.Func(_SC("Active"), &Entity< CPlayer >::CountActive)
.Func(_SC("TagEquals"), &Entity< CPlayer >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CPlayer >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CPlayer >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CPlayer >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CPlayer >::CountWhereTagMatches)
.Func(_SC("NameEquals"), &Player_CountWhereNameEquals)
.Func(_SC("NameBegins"), &Player_CountWhereNameBegins)
.Func(_SC("NameEnds"), &Player_CountWhereNameEnds)
.Func(_SC("NameContains"), &Player_CountWhereNameContains)
.Func(_SC("NameMatches"), &Player_CountWhereNameMatches)
);
count_ns.Bind(_SC("Vehicle"), Table(vm)
.Func(_SC("Active"), &Entity< CVehicle >::CountActive)
.Func(_SC("TagEquals"), &Entity< CVehicle >::CountWhereTagEquals)
.Func(_SC("TagBegins"), &Entity< CVehicle >::CountWhereTagBegins)
.Func(_SC("TagEnds"), &Entity< CVehicle >::CountWhereTagEnds)
.Func(_SC("TagContains"), &Entity< CVehicle >::CountWhereTagContains)
.Func(_SC("TagMatches"), &Entity< CVehicle >::CountWhereTagMatches)
);
RootTable(vm).Bind(_SC("SqCount"), count_ns);
}
} // Namespace:: Algo
// ================================================================================================
void Register_Algo(HSQUIRRELVM vm)
{
Algo::Register(vm);
}
} // Namespace:: SqMod

1649
module/Misc/Algo.hpp Normal file

File diff suppressed because it is too large Load Diff

476
module/Misc/Areas.cpp Normal file
View File

@@ -0,0 +1,476 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Areas.hpp"
// ------------------------------------------------------------------------------------------------
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(AreaTypename, _SC("SqArea"))
// ------------------------------------------------------------------------------------------------
AreaManager AreaManager::s_Inst;
// ------------------------------------------------------------------------------------------------
void Area::AddArray(const Sqrat::Array & a)
{
float values[2];
a.Foreach([this, &values, n = int(0)](HSQUIRRELVM vm) mutable -> bool {
// Retrieve the type of the value
const SQObjectType type = sq_gettype(vm, -1);
// Are we dealing with a vector?
if (type == OT_INSTANCE)
{
// Next time, start again for floats
n = 0;
// Grab the instance from the stack
this->AddPoint(*ClassType< Vector2 >::GetInstance(vm, -1));
}
else if (type & SQOBJECT_NUMERIC)
{
// Retrieve the value from the stack
values[n] = Var< float >(vm, -1).value;
// Do we have enough to form a vector?
if (++n == 2)
{
this->AddPointEx(values[0], values[1]);
// Reset the counter
n = 0;
}
}
// Ignore anything else
return true;
});
}
// ------------------------------------------------------------------------------------------------
bool Area::Manage()
{
// Are we connected to any cells?
if (!mCells.empty())
{
STHROWF("The area is already managed");
}
// We expect this to be called only from the script so that the first parameter in the vm
// is the area instance
LightObj obj(1, DefaultVM::Get());
// Attempt to manage this area
AreaManager::Get().InsertArea(*this, obj);
// Return whether the area is now managed by any cells
return !mCells.empty();
}
// ------------------------------------------------------------------------------------------------
bool Area::Unmanage()
{
// Are we connected to any cells?
if (mCells.empty())
{
return true; // Already unmanaged
}
// Attempt to unmanage this area
AreaManager::Get().RemoveArea(*this);
// Return whether the area is not managed by any cells
return mCells.empty();
}
// ------------------------------------------------------------------------------------------------
bool Area::IsInside(float x, float y) const
{
// Is the an area to test?
if (mPoints.size() < 3)
{
return false; // Can't possibly be in an area that doesn't exist
}
// http://sidvind.com/wiki/Point-in-polygon:_Jordan_Curve_Theorem
// The points creating the polygon
float x1, x2;
// How many times the ray crosses a line segment
int crossings = 0;
// Iterate through each line
for (Uint32 i = 0, n = static_cast< Uint32 >(mPoints.size()); i < n; ++i)
{
Points::const_reference a = mPoints[i];
Points::const_reference b = mPoints[(i + 1) % n];
// This is done to ensure that we get the same result when
// the line goes from left to right and right to left.
if (a.x < b.x)
{
x1 = a.x;
x2 = b.x;
}
else
{
x1 = b.x;
x2 = a.x;
}
// First check if the ray is able to cross the line
if (x > x1 && x <= x2 && (y < a.y || y <= b.y))
{
// Calculate the equation of the line
const float dx = (b.x - a.x);
const float dy = (b.y - a.y);
float k;
if (fabs(dx) < 0.000001f)
{
k = 0xffffffff;
}
else
{
k = (dy / dx);
}
const float m = (a.y - k * a.x);
const float y2 = (k * x + m);
// Does the ray cross the line?
if (y <= y2)
{
++crossings;
}
}
}
// Return if the crossings are not even
return (crossings % 2 == 1);
}
// ------------------------------------------------------------------------------------------------
AreaManager::AreaManager(size_t sz)
: m_Queue(), m_ProcList(), m_Grid{}
{
// Negative half grid size (left)
int l = (-GRIDH * CELLD);
// Positive half grid size minus one cell (bottom)
int b = (abs(l) - CELLD);
// Negative half grid size minus one cell (right)
int r = (l + CELLD);
// Positive half grid size (top)
int t = abs(l);
// Initialize the grid cells
for (int y = 0; y < GRIDN; ++y)
{
for (int x = 0; x < GRIDN; ++x)
{
// Grab a reference to the cell
AreaCell & c = m_Grid[y][x];
// Configure the range of the cell
c.mL = static_cast< float >(l);
c.mB = static_cast< float >(b);
c.mR = static_cast< float >(r);
c.mT = static_cast< float >(t);
// Reserve area memory if requested
c.mAreas.reserve(sz);
// Reset the locks on this area
c.mLocks = 0;
// Advance the left side
l = r;
// Advance the right side
r += CELLD;
// Should we advance to the next row?
if (r > (GRIDH * CELLD))
{
// Reset the left side
l = (-GRIDH * CELLD);
// Reset the right side
r = (l + CELLD);
// Advance the bottom
b -= CELLD;
// Advance the top
t -= CELLD;
}
}
}
// Reserve some space in the queue
m_Queue.reserve(128);
m_ProcList.reserve(128);
}
// ------------------------------------------------------------------------------------------------
void AreaManager::Insert(AreaCell & c, Area & a, LightObj & obj)
{
// Is this cell currently locked?
if (c.mLocks)
{
m_Queue.emplace_back(c, a, obj); // Queue this request for now
}
else
{
c.mAreas.emplace_back(&a, obj);
}
// Associate the area with this cell so it can't be managed again (even while in the queue)
a.mCells.push_back(&c);
}
// ------------------------------------------------------------------------------------------------
void AreaManager::Remove(AreaCell & c, Area & a)
{
// Is this cell currently locked?
if (c.mLocks)
{
m_Queue.emplace_back(c, a); // Queue this request for now
}
else
{
// Attempt to locate this area in the cell
AreaCell::Areas::iterator itr = std::find_if(c.mAreas.begin(), c.mAreas.end(),
[&a](AreaCell::Areas::reference p) -> bool {
return (p.first == &a);
});
// Have we found it?
if (itr != c.mAreas.end())
{
c.mAreas.erase(itr); // Erase it
}
}
// Dissociate the area with this cell so it can be managed again (even while in the queue)
Area::Cells::iterator itr = std::find(a.mCells.begin(), a.mCells.end(), &c);
// Was is associated?
if (itr != a.mCells.end())
{
a.mCells.erase(itr); // Dissociate them
}
}
// ------------------------------------------------------------------------------------------------
void AreaManager::ProcQueue()
{
// Look for actions that can be completed
for (Queue::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr)
{
// Was this cell unlocked in the meantime?
if (itr->mCell->mLocks <= 0)
{
m_ProcList.push_back(itr);
}
}
// Process the actions that are ready
for (auto & itr : m_ProcList)
{
// Was this a remove request?
if (itr->mObj.IsNull())
{
Remove(*(itr->mCell), *(itr->mArea));
}
else
{
Insert(*(itr->mCell), *(itr->mArea), itr->mObj);
}
}
// Remove processed requests
for (auto & itr : m_ProcList)
{
m_Queue.erase(itr);
}
// Actions were processed
m_ProcList.clear();
}
// ------------------------------------------------------------------------------------------------
void AreaManager::Clear()
{
// Clear the cells
for (AreaCell (&row)[GRIDN] : m_Grid)
{
for (AreaCell & c : row)
{
c.mAreas.clear();
}
}
// Clear the queue as well
m_Queue.clear();
m_ProcList.clear();
}
// ------------------------------------------------------------------------------------------------
void AreaManager::InsertArea(Area & a, LightObj & obj)
{
// See if this area is already managed
if (!a.mCells.empty() || a.mPoints.empty())
{
return; // Already managed or nothing to manage
}
// Go through each cell and check if the area touches it
for (int y = 0; y < GRIDN; ++y)
{
for (int x = 0; x < GRIDN; ++x)
{
AreaCell & c = m_Grid[y][x];
// Does the bounding box of this cell intersect with the one of the area?
if (a.mL <= c.mR && c.mL <= a.mR && a.mB <= c.mT && c.mB <= a.mT)
{
Insert(c, a, obj); // Attempt to insert the area into this cell
}
}
}
}
// ------------------------------------------------------------------------------------------------
void AreaManager::RemoveArea(Area & a)
{
// Just remove the associated cells
for (auto c : a.mCells)
{
Remove(*c, a);
}
}
// ------------------------------------------------------------------------------------------------
Vector2i AreaManager::LocateCell(float x, float y)
{
// Transform the world coordinates into a cell coordinates
// and cast to integral after rounding the value
int xc = static_cast< int >(std::round(x / CELLD));
int yc = static_cast< int >(std::round(y / CELLD));
// Grab the absolute cell coordinates for range checking
const int xca = std::abs(xc);
const int yca = std::abs(yc);
// Make sure the cell coordinates are within range
if (xca > (GRIDH+1) || yca > (GRIDH+1))
{
return Vector2i(NOCELL, NOCELL); // Out of our scanning area
}
// Clamp the x coordinate if necessary
if (xca >= (GRIDH))
{
xc = xc < 0 ? -(GRIDH-1) : (GRIDH-1);
}
// Clamp the y coordinate if necessary
if (yca >= (GRIDH))
{
yc = xc < 0 ? -(GRIDH-1) : (GRIDH-1);
}
// Return the identified cell row and column
return Vector2i(GRIDH+xc, GRIDH-yc);
}
// ------------------------------------------------------------------------------------------------
static void Areas_TestPointEx(Object & env, Function & func, float x, float y)
{
// Is the function valid?
if (func.IsNull())
{
STHROWF("Invalid callback object");
}
// Should we use a custom environment?
else if (!env.IsNull())
{
func = Function(env.GetVM(), env, func.GetFunc());
}
// Begin testing
AreaManager::Get().TestPoint([&func](AreaCell::Areas::reference ap) -> void {
func.Execute(ap.second);
}, x, y);
}
// ------------------------------------------------------------------------------------------------
static void Areas_TestPoint(Object & env, Function & func, const Vector2 & v)
{
Areas_TestPointEx(env, func, v.x, v.y);
}
// ------------------------------------------------------------------------------------------------
static void Areas_TestPointOnEx(Object & ctx, Object & env, Function & func, float x, float y)
{
// Is the function valid?
if (func.IsNull())
{
STHROWF("Invalid callback object");
}
// Should we use a custom environment?
else if (!env.IsNull())
{
func = Function(env.GetVM(), env, func.GetFunc());
}
// Begin testing
AreaManager::Get().TestPoint([&ctx, &func](AreaCell::Areas::reference ap) -> void {
func.Execute(ctx, ap.second);
}, x, y);
}
// ------------------------------------------------------------------------------------------------
static void Areas_TestPointOn(Object & ctx, Object & env, Function & func, const Vector2 & v)
{
Areas_TestPointOnEx(ctx, env, func, v.x, v.y);
}
// ------------------------------------------------------------------------------------------------
static Vector2i Areas_LocatePointCell(const Vector2 & v)
{
return AreaManager::Get().LocateCell(v.x, v.y);
}
// ------------------------------------------------------------------------------------------------
static Vector2i Areas_LocatePointCellEx(float x, float y)
{
return AreaManager::Get().LocateCell(x, y);
}
// ------------------------------------------------------------------------------------------------
void TerminateAreas()
{
AreaManager::Get().Clear();
}
// ================================================================================================
void Register_Areas(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqArea"),
Class< Area >(vm, AreaTypename::Str)
// Constructors
.Ctor()
.Ctor< StackStrF & >()
.Ctor< SQInteger, StackStrF & >()
.Ctor< const Vector2 &, const Vector2 &, const Vector2 & >()
.Ctor< const Vector2 &, const Vector2 &, const Vector2 &, StackStrF & >()
.Ctor< const Vector2 &, const Vector2 &, const Vector2 &, SQInteger, StackStrF & >()
.Ctor< float, float, float, float, float, float >()
.Ctor< float, float, float, float, float, float, StackStrF & >()
.Ctor< float, float, float, float, float, float, SQInteger, StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &AreaTypename::Fn)
.Func(_SC("_tostring"), &Area::ToString)
// Member Properties
.Prop(_SC("Name"), &Area::GetName, &Area::SetName)
.Prop(_SC("ID"), &Area::GetID, &Area::SetID)
.Prop(_SC("Locked"), &Area::IsLocked)
.Prop(_SC("IsLocked"), &Area::IsLocked)
.Prop(_SC("Center"), &Area::GetCenter)
.Prop(_SC("Box"), &Area::GetBoundingBox, &Area::SetBoundingBox)
.Prop(_SC("Empty"), &Area::Empty)
.Prop(_SC("Empty"), &Area::Empty)
.Prop(_SC("Size"), &Area::Size)
.Prop(_SC("Points"), &Area::Size)
.Prop(_SC("Capacity"), &Area::Capacity)
// Member Methods
.FmtFunc(_SC("SetName"), &Area::ApplyName)
.Func(_SC("SetID"), &Area::ApplyID)
.Func(_SC("Clear"), &Area::Clear)
.Func(_SC("Reserve"), &Area::Reserve)
.Func(_SC("SetBox"), &Area::SetBoundingBoxEx)
.Func(_SC("SetBoundingBox"), &Area::SetBoundingBoxEx)
.Func(_SC("Add"), &Area::AddPoint)
.Func(_SC("AddEx"), &Area::AddPointEx)
.Func(_SC("AddVirtual"), &Area::AddVirtualPoint)
.Func(_SC("AddVirtualEx"), &Area::AddVirtualPointEx)
.Func(_SC("AddFake"), &Area::AddVirtualPoint)
.Func(_SC("AddFakeEx"), &Area::AddVirtualPointEx)
.Func(_SC("AddArray"), &Area::AddArray)
.Func(_SC("Test"), &Area::Test)
.Func(_SC("TestEx"), &Area::TestEx)
.Func(_SC("Manage"), &Area::Manage)
.Func(_SC("Unmanage"), &Area::Unmanage)
// Static Functions
.StaticFunc(_SC("GlobalTest"), &Areas_TestPoint)
.StaticFunc(_SC("GlobalTestEx"), &Areas_TestPointEx)
.StaticFunc(_SC("GlobalTestOn"), &Areas_TestPointOn)
.StaticFunc(_SC("GlobalTestOnEx"), &Areas_TestPointOnEx)
.StaticFunc(_SC("LocatePointCell"), &Areas_LocatePointCell)
.StaticFunc(_SC("LocatePointCellEx"), &Areas_LocatePointCellEx)
.StaticFunc(_SC("UnmanageAll"), &TerminateAreas)
);
}
} // Namespace:: SqMod

716
module/Misc/Areas.hpp Normal file
View File

@@ -0,0 +1,716 @@
#ifndef _AREAS_HPP_
#define _AREAS_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
#include "Base/Vector2.hpp"
#include "Base/Vector4.hpp"
#include "Base/Vector2i.hpp"
// ------------------------------------------------------------------------------------------------
#include <vector>
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Various information associated with an area cell.
*/
struct AreaCell
{
// --------------------------------------------------------------------------------------------
typedef std::pair< Area *, LightObj > AreaPair; // A reference to an area object.
typedef std::vector< AreaPair > Areas; // A list of area objects.
// --------------------------------------------------------------------------------------------
float mL, mB, mR, mT; // Left-Bottom, Right-Top components of the cell bounding box.
// --------------------------------------------------------------------------------------------
Areas mAreas; // Areas that intersect with the cell.
// --------------------------------------------------------------------------------------------
int mLocks; // The amount of locks on the cell.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
AreaCell()
: mL(0), mB(0), mR(0), mT(0), mAreas(0), mLocks(0)
{
//...
}
};
/* ------------------------------------------------------------------------------------------------
* Area implementation used to store area points.
*/
struct Area
{
typedef std::vector< Vector2 > Points;
typedef std::vector< AreaCell * > Cells;
// --------------------------------------------------------------------------------------------
static constexpr float DEF_L = std::numeric_limits< float >::infinity();
static constexpr float DEF_B = std::numeric_limits< float >::infinity();
static constexpr float DEF_R = -std::numeric_limits< float >::infinity();
static constexpr float DEF_T = -std::numeric_limits< float >::infinity();
// --------------------------------------------------------------------------------------------
float mL, mB, mR, mT; // Left-Bottom, Right-Top components of the bounding box.
// --------------------------------------------------------------------------------------------
Points mPoints; // Collection of points that make up the area.
// --------------------------------------------------------------------------------------------
SQInteger mID; // The user identifier given to this area.
// --------------------------------------------------------------------------------------------
Cells mCells; // The cells covered by this area.
// --------------------------------------------------------------------------------------------
String mName; // The user name given to this area.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Area()
: mL(DEF_L), mB(DEF_B), mR(DEF_R), mT(DEF_T), mPoints(), mID(0), mCells(), mName()
{
//...
}
/* --------------------------------------------------------------------------------------------
* Named constructor.
*/
Area(StackStrF & name)
: Area(16, name)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Area(SQInteger sz, StackStrF & name)
: mL(DEF_L), mB(DEF_B), mR(DEF_R), mT(DEF_T), mPoints(), mID(0), mCells()
, mName(name.mPtr, name.mLen <= 0 ? 0 : name.mLen)
{
// Should we reserve some space for points in advance?
if (sz > 0)
{
mPoints.reserve(static_cast< size_t >(sz));
}
}
/* --------------------------------------------------------------------------------------------
* Vector2 constructor.
*/
Area(const Vector2 & a, const Vector2 & b, const Vector2 & c)
: Area(a.x, a.y, b.x, b.y, c.x, c.y, 16, StackStrF::Dummy())
{
//...
}
/* --------------------------------------------------------------------------------------------
* Vector2 constructor with name.
*/
Area(const Vector2 & a, const Vector2 & b, const Vector2 & c, StackStrF & name)
: Area(a.x, a.y, b.x, b.y, c.x, c.y, 16, name)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Vector2 constructor with name and memory to reserve.
*/
Area(const Vector2 & a, const Vector2 & b, const Vector2 & c, SQInteger sz, StackStrF & name)
: Area(a.x, a.y, b.x, b.y, c.x, c.y, sz, name)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Extended constructor.
*/
Area(float ax, float ay, float bx, float by, float cx, float cy)
: Area(ax, ay, bx, by, cx, cy, 16, StackStrF::Dummy())
{
//...
}
/* --------------------------------------------------------------------------------------------
* Extended constructor with name.
*/
Area(float ax, float ay, float bx, float by, float cx, float cy, StackStrF & name)
: Area(ax, ay, bx, by, cx, cy, 16, name)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
Area(float ax, float ay, float bx, float by, float cx, float cy, SQInteger sz, StackStrF & name)
: mL(DEF_L), mB(DEF_B), mR(DEF_R), mT(DEF_T), mPoints(), mID(0), mCells()
, mName(name.mPtr, name.mLen <= 0 ? 0 : name.mLen)
{
// Should we reserve some space for points in advance?
if (sz > 0)
{
mPoints.reserve(static_cast< size_t >(sz));
}
// Insert the given points
AddPointEx(ax, ay);
AddPointEx(bx, by);
AddPointEx(cx, cy);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Area(const Area & o)
: mL(o.mL), mB(o.mB), mR(o.mR), mT(o.mT), mPoints(o.mPoints), mID(o.mID), mCells(0), mName(o.mName)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Area(Area && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Area()
{
//...
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Area & operator = (const Area & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Area & operator = (Area && o) = delete;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert this instance to a string.
*/
const String & ToString() const
{
return mName;
}
/* --------------------------------------------------------------------------------------------
* Checks if the area is locked from changes and throws an exception if it is.
*/
void CheckLock()
{
// Are we connected to any cells?
if (!mCells.empty())
{
STHROWF("The area cannot be modified while being managed");
}
}
/* --------------------------------------------------------------------------------------------
* Retrieve the name of this area.
*/
const String & GetName() const
{
return mName;
}
/* --------------------------------------------------------------------------------------------
* Modify the name of this area.
*/
void SetName(StackStrF & name)
{
if (name.mLen <= 0)
{
mName.clear();
}
else
{
mName.assign(name.mPtr, static_cast< size_t >(name.mLen));
}
}
/* --------------------------------------------------------------------------------------------
* Modify the name of this area. (allows chaining function calls)
*/
Area & ApplyName(StackStrF & name)
{
SetName(name);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the identifier of this area.
*/
SQInteger GetID() const
{
return mID;
}
/* --------------------------------------------------------------------------------------------
* Modify the identifier of this area.
*/
void SetID(SQInteger id)
{
mID = id;
}
/* --------------------------------------------------------------------------------------------
* Modify the identifier of this area. (allows chaining function calls)
*/
Area & ApplyID(SQInteger id)
{
mID = id;
return *this;
}
/* --------------------------------------------------------------------------------------------
* Check if the area is locked from changes
*/
bool IsLocked() const
{
return mCells.empty();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the center of this area.
*/
Vector2 GetCenter() const
{
return Vector2((mL * 0.5f) + (mR * 0.5f), (mB * 0.5f) + (mT * 0.5f));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the bounding box of this area.
*/
Vector4 GetBoundingBox() const
{
return Vector4(mL, mB, mR, mT);
}
/* --------------------------------------------------------------------------------------------
* Modify the bounding box of this area.
*/
void SetBoundingBox(const Vector4 & b)
{
CheckLock();
// Apply the given bounding box
mL = b.x;
mB = b.y;
mR = b.z;
mT = b.w;
}
/* --------------------------------------------------------------------------------------------
* Modify the bounding box of this area.
*/
void SetBoundingBoxEx(float l, float b, float r, float t)
{
CheckLock();
// Apply the given bounding box
mL = l;
mB = b;
mR = r;
mT = t;
}
/* --------------------------------------------------------------------------------------------
* See whether the area has no points.
*/
bool Empty() const
{
return mPoints.empty();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of points in this area.
*/
SQInteger Size() const
{
return ConvTo< SQInteger >::From(mPoints.size());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of points this area has allocated for.
*/
SQInteger Capacity() const
{
return ConvTo< SQInteger >::From(mPoints.capacity());
}
/* --------------------------------------------------------------------------------------------
* Clear all points in this area.
*/
void Clear()
{
CheckLock();
// Perform the requested action
mPoints.clear();
}
/* --------------------------------------------------------------------------------------------
* Clear all points in this area.
*/
void Reserve(SQInteger sz)
{
// Perform the requested action
if (sz > 0)
{
mPoints.reserve(static_cast< size_t >(sz));
}
}
/* --------------------------------------------------------------------------------------------
* Add a 2D vector to the point list.
*/
void AddPoint(const Vector2 & v)
{
CheckLock();
// Perform the requested action
mPoints.emplace_back(v);
// Update the bounding box
Expand(v.x, v.y);
}
/* --------------------------------------------------------------------------------------------
* Add a point to the point list.
*/
void AddPointEx(float x, float y)
{
CheckLock();
// Perform the requested action
mPoints.emplace_back(x, y);
// Update the bounding box
Expand(x, y);
}
/* --------------------------------------------------------------------------------------------
* Add a 2D vector to the bounding box only. Not stored in the list.
*/
void AddVirtualPoint(const Vector2 & v)
{
CheckLock();
// Update the bounding box
Expand(v.x, v.y);
}
/* --------------------------------------------------------------------------------------------
* Add a point to the bounding box only. Not stored in the list.
*/
void AddVirtualPointEx(float x, float y)
{
CheckLock();
// Update the bounding box
Expand(x, y);
}
/* --------------------------------------------------------------------------------------------
* Add an array of points to the point list.
*/
void AddArray(const Sqrat::Array & a);
/* --------------------------------------------------------------------------------------------
* Test if a point is inside the bounding box and then the area.
*/
bool Test(const Vector2 & v)
{
// Is the given point in this bounding box at least?
if (mL <= v.x && mR >= v.x && mB <= v.y && mT >= v.y)
{
return mPoints.empty() ? true : IsInside(v.x, v.y);
}
// Not in this area
return false;
}
/* --------------------------------------------------------------------------------------------
* Test if a point is inside the bounding box and then the area.
*/
bool TestEx(float x, float y)
{
// Is the given point in this bounding box at least?
if (mL <= x && mR >= x && mB <= y && mT >= y)
{
return mPoints.empty() ? true : IsInside(x, y);
}
// Not in this area
return false;
}
/* --------------------------------------------------------------------------------------------
* Add this area to the manager to be scanned. MUST BE CALLED ONLY FROM SCRIPT!
*/
bool Manage();
/* --------------------------------------------------------------------------------------------
* Remove this area from the manager to no longer be scanned.
*/
bool Unmanage();
protected:
/* --------------------------------------------------------------------------------------------
* Test if a point is inside the area.
*/
bool IsInside(float x, float y) const;
/* --------------------------------------------------------------------------------------------
* Expand the bounding box area to include the given point.
*/
void Expand(float x, float y)
{
mL = std::fmin(mL, x);
mB = std::fmin(mB, y);
mR = std::fmax(mR, x);
mT = std::fmax(mT, y);
}
};
/* ------------------------------------------------------------------------------------------------
* Manager responsible for storing and partitioning areas.
*/
class AreaManager
{
private:
// --------------------------------------------------------------------------------------------
static AreaManager s_Inst; // Manager instance.
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
AreaManager(size_t sz = 16);
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
AreaManager(const AreaManager & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
AreaManager(AreaManager && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~AreaManager()
{
//...
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
AreaManager & operator = (const AreaManager & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
AreaManager & operator = (AreaManager && o) = delete;
protected:
/* --------------------------------------------------------------------------------------------
* Helper used to make sure a cell is properly processed after leaving the scope.
*/
struct CellGuard
{
AreaCell & mCell;
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
CellGuard(AreaCell & cell)
: mCell(cell)
{
++(cell.mLocks); // Place a lock on the cell to prevent iterator invalidation
}
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~CellGuard()
{
// Remove the lock from the cell so it can be processed
--(mCell.mLocks);
// Process requested actions during the lock
AreaManager::Get().ProcQueue();
}
};
// --------------------------------------------------------------------------------------------
static constexpr int GRIDN = 16; // Number of horizontal and vertical number of cells.
static constexpr int GRIDH = GRIDN/2; // Half of the grid horizontal and vertical size.
static constexpr int CELLS = GRIDN*GRIDN; // Total number of cells in the grid.
static constexpr int CELLH = CELLS/2; // Half total number of cells in the grid.
static constexpr int CELLD = 256; // Area covered by a cell in the world.
static constexpr int NOCELL = std::numeric_limits< int >::max(); // Inexistent cell index.
/* --------------------------------------------------------------------------------------------
* Helper used to queue a certain action if the cell is locked.
*/
struct QueueElement
{
// ----------------------------------------------------------------------------------------
AreaCell * mCell; // The cell to be affected.
Area * mArea; // The area that made the request.
LightObj mObj; // Strong reference to the object.
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
QueueElement(AreaCell & cell, Area & area)
: mCell(&cell), mArea(&area), mObj()
{
//...
}
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
QueueElement(AreaCell & cell, Area & area, LightObj & obj)
: mCell(&cell), mArea(&area), mObj(obj)
{
//...
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
QueueElement(const QueueElement & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
QueueElement(QueueElement && o)
: mCell(o.mCell), mArea(o.mArea), mObj(std::move(o.mObj))
{
// Take ownership
o.mCell = nullptr;
o.mArea = nullptr;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~QueueElement()
{
//...
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
QueueElement & operator = (const QueueElement & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
QueueElement & operator = (QueueElement && o)
{
// Avoid self assignment
if (this != &o)
{
// Transfer values
mCell = o.mCell;
mArea = o.mArea;
mObj = std::move(o.mObj);
// Take ownership
o.mCell = nullptr;
o.mArea = nullptr;
}
return *this;
}
};
// --------------------------------------------------------------------------------------------
typedef std::vector< QueueElement > Queue; // Queued actions.
typedef std::vector< Queue::iterator > ProcList; // Elements in the queue redy to process.
/* --------------------------------------------------------------------------------------------
* Attempt to insert an area into a cell or queue the action if not possible.
*/
void Insert(AreaCell & c, Area & a, LightObj & obj);
/* --------------------------------------------------------------------------------------------
* Attempt to remove an area from a cell or queue the action if not possible.
*/
void Remove(AreaCell & c, Area & a);
private:
// --------------------------------------------------------------------------------------------
Queue m_Queue; // Actions currently queued.
ProcList m_ProcList; // Actions ready to be completed.
// --------------------------------------------------------------------------------------------
AreaCell m_Grid[GRIDN][GRIDN]; // A grid of area lists.
public:
/* --------------------------------------------------------------------------------------------
* Retrieve the core instance.
*/
static AreaManager & Get()
{
return s_Inst;
}
/* --------------------------------------------------------------------------------------------
* Attempt to process elements in the queue that can be completed.
*/
void ProcQueue();
/* --------------------------------------------------------------------------------------------
* Clear all cell lists and release any script references.
*/
void Clear();
/* --------------------------------------------------------------------------------------------
* Add an area to be managed.
*/
void InsertArea(Area & a, LightObj & obj);
/* --------------------------------------------------------------------------------------------
* Add an area to be managed.
*/
void RemoveArea(Area & a);
/* --------------------------------------------------------------------------------------------
* Clear all cell lists and release any script references.
*/
Vector2i LocateCell(float x, float y);
/* --------------------------------------------------------------------------------------------
* Test a point to see whether it intersects with any areas
*/
template < typename F > void TestPoint(F && f, float x, float y)
{
// Transform the world coordinates into a cell coordinates
const Vector2i cc(LocateCell(x, y));
// Were these coordinates valid?
if (cc.x == NOCELL)
{
return; // Not our problem
}
// Retrieve a reference to the identified cell
AreaCell & c = m_Grid[cc.y][cc.x];
// Is this cell empty?
if (c.mAreas.empty())
{
return; // Nothing to test
}
// Guard the cell while processing
const CellGuard cg(c);
// Finally, begin processing the areas in this cell
for (auto & a : c.mAreas)
{
if (a.first->TestEx(x, y))
{
f(a);
}
}
}
};
} // Namespace:: SqMod
#endif // _AREAS_HPP_

712
module/Misc/Broadcast.cpp Normal file
View File

@@ -0,0 +1,712 @@
// ------------------------------------------------------------------------------------------------
#include "Core.hpp"
#include "Base/Shared.hpp"
#include "Base/Color3.hpp"
#include "Base/Color4.hpp"
#include "Entity/Player.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static inline bool SqCanBeInteger(HSQUIRRELVM vm, Int32 idx)
{
switch (sq_gettype(vm, idx))
{
case OT_NULL:
case OT_INTEGER:
case OT_FLOAT:
case OT_BOOL:
return true;
default:
return false;
}
}
// ------------------------------------------------------------------------------------------------
SQRESULT SqGrabPlayerMessageColor(HSQUIRRELVM vm, Int32 idx, Uint32 & color, Int32 & msgidx)
{
const Int32 top = sq_gettop(vm);
// Is the color argument a Color3/Color4 instance?
if (sq_gettype(vm, idx) == OT_INSTANCE)
{
// Whether it failed to retrieve a Color3 value
bool failed = false;
// Attempt to extract a Color3 value
try
{
color = (Var< Color3 >(vm, idx).value.GetRGBA() | 0xFF);
}
catch (...)
{
failed = true;
}
// Did we failed to retrieve a Color3 instance?
if (failed)
{
// Attempt to extract a Color4 value
try
{
color = Var< Color4 >(vm, idx).value.GetRGBA();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
}
// The message starts right after the color
msgidx += 1;
}
// Is the color argument an unpacked RGBA color?
else if ((top - msgidx) >= 4 && SqCanBeInteger(vm, idx)
&& SqCanBeInteger(vm, idx+1)
&& SqCanBeInteger(vm, idx+2)
&& SqCanBeInteger(vm, idx+3))
{
color = SQMOD_PACK_RGBA(ConvTo< Uint8 >::From(PopStackInteger(vm, idx)),
ConvTo< Uint8 >::From(PopStackInteger(vm, idx+1)),
ConvTo< Uint8 >::From(PopStackInteger(vm, idx+2)),
ConvTo< Uint8 >::From(PopStackInteger(vm, idx+3)));
// The message starts right after the color
msgidx += 4;
}
// Is the color argument an unpacked RGB color?
else if ((top - msgidx) >= 3 && SqCanBeInteger(vm, idx)
&& SqCanBeInteger(vm, idx+1)
&& SqCanBeInteger(vm, idx+2))
{
color = SQMOD_PACK_RGBA(ConvTo< Uint8 >::From(PopStackInteger(vm, idx)),
ConvTo< Uint8 >::From(PopStackInteger(vm, idx+1)),
ConvTo< Uint8 >::From(PopStackInteger(vm, idx+2)),
0xFF);
// The message starts right after the color
msgidx += 3;
}
// Is the color argument an packed RGBA color?
else if (SqCanBeInteger(vm, idx))
{
color = static_cast< Uint32 >(PopStackInteger(vm, idx));
// The message starts right after the color
msgidx += 1;
}
// Is the first argument a string which can be interpreted as a color?
else if (sq_gettype(vm, idx) == OT_STRING)
{
CSStr str = nullptr;
SQInteger len = 0;
// Attempt to retrieve the color argument as a string
if (SQ_FAILED(sq_getstringandsize(vm, idx, &str, &len)))
{
return sq_throwerror(vm, "Cannot retrieve the color string");
}
// Do we even have any color?
else if (!str || *str == '\0')
{
return sq_throwerror(vm, "Invalid or empty color string");
}
// Skip white space at the beginning
while (std::isspace(*str) != 0)
{
++str, --len;
}
// Is the first character a number sign?
if (*str == '#')
{
// Attempt to treat the value as a hex color
color = ConvTo< Uint32 >::From(std::strtoull(++str, nullptr, 16));
// Adjust the color if necessary
switch (ClampMin(--len, static_cast< SQInteger >(0)))
{
case 0:
{
color = 0x000000FF;
} break;
case 1:
{
color <<= 28;
color |= 0x00000FF;
} break;
case 2:
{
color <<= 24;
color |= 0x0000FF;
} break;
case 3:
{
color <<= 20;
color |= 0x000FF;
} break;
case 4:
{
color <<= 16;
color |= 0x00FF;
} break;
case 5:
{
color <<= 12;
color |= 0x0FF;
} break;
case 6:
{
color <<= 8;
color |= 0xFF;
} break;
case 7:
{
color <<= 4;
color |= 0x0;
} break;
}
}
// Are the first characters 0x so we can treat this as hex?
else if (*str == '0' && (*(str+1) == 'x' || *(str+1) == 'X'))
{
// Attempt to treat the value as a hex color
color = ConvTo< Uint32 >::From(std::strtoull(str, nullptr, 16));
// Adjust the color if necessary
switch (ClampMin(len-2, static_cast< SQInteger >(0)))
{
case 0:
{
color = 0x000000FF;
} break;
case 1:
{
color <<= 28;
color |= 0x00000FF;
} break;
case 2:
{
color <<= 24;
color |= 0x0000FF;
} break;
case 3:
{
color <<= 20;
color |= 0x000FF;
} break;
case 4:
{
color <<= 16;
color |= 0x00FF;
} break;
case 5:
{
color <<= 12;
color |= 0x0FF;
} break;
case 6:
{
color <<= 8;
color |= 0xFF;
} break;
case 7:
{
color <<= 4;
color |= 0x0;
} break;
}
}
else
{
// Attempt to treat the value as a color name
try
{
color = (::SqMod::GetColorStr(str).GetRGBA() | 0xFF);
}
catch (...)
{
return sq_throwerror(vm, "Cannot identify color string");
}
}
// The message starts right after the color
msgidx += 1;
}
else
{
return sq_throwerror(vm, "Unable to identify a valid color");
}
// At this point we've extracted the color
return SQ_OK;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastMsg(HSQUIRRELVM vm)
{
// The function needs at least 2 arguments
const Int32 top = sq_gettop(vm);
// Was the message color specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing message color");
}
// Was the message value specified?
else if (top <= 2)
{
return sq_throwerror(vm, "Missing message value");
}
// The index where the message should start
Int32 msgidx = 2;
// The message color
Uint32 color = 0;
// Attempt to identify and extract the color
const SQRESULT res = SqGrabPlayerMessageColor(vm, 2, color, msgidx);
// Did we fail to identify a color?
if (SQ_FAILED(res))
{
return res; // Propagate the error!
}
// Attempt to generate the string value
StackStrF val(vm, msgidx);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted message string
const vcmpError result = _Func->SendClientMessage(itr->mID, color,
"%s%s%s",
player->mMessagePrefix.c_str(),
val.mPtr,
player->mMessagePostfix.c_str());
// Check the result
if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Client message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastMsgP(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the index of the message prefix specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing prefix index");
}
// Was the message value specified?
else if (top <= 2)
{
return sq_throwerror(vm, "Missing message value");
}
// The prefix index
Uint32 index = 0;
// Attempt to extract the argument values
try
{
index = ConvTo< Uint32 >::From(Var< SQInteger >(vm, 2).value);
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Perform a range check on the specified prefix index
if (index >= SQMOD_PLAYER_MSG_PREFIXES)
{
return sq_throwerror(vm, ToStrF("Prefix index is out of range: %u >= %u",
index, SQMOD_PLAYER_MSG_PREFIXES));
}
// Attempt to generate the string value
StackStrF val(vm, 3);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
vcmpError result = vcmpErrorNone;
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted message string
if (player->mLimitPrefixPostfixMessage)
{
result = _Func->SendClientMessage(itr->mID, player->mMessageColor, "%s%s",
player->mMessagePrefixes[index].c_str(), val.mPtr);
}
else
{
result = _Func->SendClientMessage(itr->mID, player->mMessageColor, "%s%s%s%s",
player->mMessagePrefix.c_str(),
player->mMessagePrefixes[index].c_str(), val.mPtr,
player->mMessagePostfix.c_str());
}
// Check the result
if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Client message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastMsgEx(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the index of the message prefix specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing prefix index");
}
// Was the message color specified?
else if (top <= 2)
{
return sq_throwerror(vm, "Missing message color");
}
// Was the message value specified?
else if (top <= 3)
{
return sq_throwerror(vm, "Missing message value");
}
// The prefix index
Uint32 index = 0;
// Attempt to extract the argument values
try
{
index = ConvTo< Uint32 >::From(Var< SQInteger >(vm, 2).value);
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Perform a range check on the specified prefix index
if (index >= SQMOD_PLAYER_MSG_PREFIXES)
{
return sq_throwerror(vm, ToStrF("Prefix index is out of range: %u >= %u",
index, SQMOD_PLAYER_MSG_PREFIXES));
}
// The index where the message should start
Int32 msgidx = 3;
// The message color
Uint32 color = 0;
// Attempt to identify and extract the color
const SQRESULT res = SqGrabPlayerMessageColor(vm, 3, color, msgidx);
// Did we fail to identify a color?
if (SQ_FAILED(res))
{
return res; // Propagate the error!
}
// Attempt to generate the string value
StackStrF val(vm, msgidx);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
vcmpError result = vcmpErrorNone;
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted message string
if (player->mLimitPrefixPostfixMessage)
{
result = _Func->SendClientMessage(itr->mID, color, "%s%s",
player->mMessagePrefixes[index].c_str(), val.mPtr);
}
else
{
result = _Func->SendClientMessage(itr->mID, color, "%s%s%s%s",
player->mMessagePrefix.c_str(),
player->mMessagePrefixes[index].c_str(), val.mPtr,
player->mMessagePostfix.c_str());
}
// Check the result
if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Client message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastMessage(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the message value specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing message value");
}
// Attempt to generate the string value
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted message string
const vcmpError result = _Func->SendClientMessage(itr->mID, player->mMessageColor,
"%s%s%s",
player->mMessagePrefix.c_str(),
val.mPtr,
player->mMessagePostfix.c_str());
// Check the result
if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Client message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastAnnounce(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the announcement value specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing announcement value");
}
// Attempt to generate the string value
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted announcement string
const vcmpError result = _Func->SendGameMessage(itr->mID, player->mAnnounceStyle,
"%s%s%s",
player->mAnnouncePrefix.c_str(),
val.mPtr,
player->mAnnouncePostfix.c_str());
// Validate the result
if (result == vcmpErrorArgumentOutOfBounds)
{
return sq_throwerror(vm, ToStrF("Invalid announcement style %d [%s]",
player->mAnnounceStyle, player->GetTag().c_str()));
}
else if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Game message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqBroadcastAnnounceEx(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the announcement style specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing announcement style");
}
// Was the announcement value specified?
else if (top <= 2)
{
return sq_throwerror(vm, "Missing announcement value");
}
Int32 style;
// style to extract the argument values
try
{
style = Var< Int32 >(vm, 2).value;
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Attempt to generate the string value
StackStrF val(vm, 3);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Obtain the ends of the entity pool
Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin();
Core::Players::const_iterator end = Core::Get().GetPlayers().cend();
// The number of players that the message was sent to
Uint32 count = 0;
// Currently processed player
CPlayer * player = nullptr;
// Process each entity in the pool
for (; itr != end; ++itr)
{
// Grab the player instance
player = itr->mInst;
// Is this player instance valid?
if (VALID_ENTITYEX(itr->mID, SQMOD_PLAYER_POOL) && player != nullptr)
{
// Send the resulted announcement string
const vcmpError result = _Func->SendGameMessage(itr->mID, style,
"%s%s%s",
player->mAnnouncePrefix.c_str(),
val.mPtr,
player->mAnnouncePostfix.c_str());
// Validate the result
if (result == vcmpErrorArgumentOutOfBounds)
{
return sq_throwerror(vm, ToStrF("Invalid announcement style %d [%s]",
style, player->GetTag().c_str()));
}
else if (result == vcmpErrorTooLargeInput)
{
return sq_throwerror(vm, ToStrF("Game message too big [%s]", player->GetTag().c_str()));
}
// Add this player to the count
++count;
}
}
// Push the count count on the stack
sq_pushinteger(vm, count);
// Specify that this function returned a value
return 1;
}
// ================================================================================================
void Register_Broadcast(HSQUIRRELVM vm)
{
Table bns(vm);
bns
.SquirrelFunc(_SC("Msg"), &SqBroadcastMsg)
.SquirrelFunc(_SC("MsgP"), &SqBroadcastMsgP)
.SquirrelFunc(_SC("MsgEx"), &SqBroadcastMsgEx)
.SquirrelFunc(_SC("Message"), &SqBroadcastMessage)
.SquirrelFunc(_SC("Announce"), &SqBroadcastAnnounce)
.SquirrelFunc(_SC("AnnounceEx"), &SqBroadcastAnnounceEx)
.SquirrelFunc(_SC("Text"), &SqBroadcastAnnounce)
.SquirrelFunc(_SC("TextEx"), &SqBroadcastAnnounceEx);
RootTable(vm).Bind(_SC("SqBroadcast"), bns);
}
} // Namespace:: SqMod

1178
module/Misc/Command.cpp Normal file

File diff suppressed because it is too large Load Diff

2043
module/Misc/Command.hpp Normal file

File diff suppressed because it is too large Load Diff

1272
module/Misc/Constants.cpp Normal file

File diff suppressed because it is too large Load Diff

291
module/Misc/Exports.cpp Normal file
View File

@@ -0,0 +1,291 @@
// ------------------------------------------------------------------------------------------------
#include "Core.hpp"
// ------------------------------------------------------------------------------------------------
#include <cmath>
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <sqstdio.h>
#include <sqstdblob.h>
#include <sqstdstring.h>
#include <SqMod.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static HSQUIRRELVM GetSquirrelVM()
{
return Core::Get().GetVM();
}
// ------------------------------------------------------------------------------------------------
static SQRESULT SqModImpl_LoadScript(const SQChar * filepath, SQBool delay)
{
// Attempt to add the specified script to the load queue
if (Core::Get().LoadScript(filepath, delay))
{
return SQ_OK; // The script as added or already existed
}
// The path was invalid or was unable to pool the script
return SQ_ERROR;
}
// ------------------------------------------------------------------------------------------------
static int32_t SqExport_PopulateModuleAPI(HSQMODAPI api, size_t size)
{
if (!api)
{
return 0; // Nothing to populate!
}
else if (size != sizeof(SQMODAPI))
{
return -1; // Incompatible API!
}
//primitive functions
api->GetSquirrelVM = GetSquirrelVM;
//logging utilities
api->LogDbg = LogDbg;
api->LogUsr = LogUsr;
api->LogScs = LogScs;
api->LogInf = LogInf;
api->LogWrn = LogWrn;
api->LogErr = LogErr;
api->LogFtl = LogFtl;
api->LogSDbg = LogSDbg;
api->LogSUsr = LogSUsr;
api->LogSScs = LogSScs;
api->LogSInf = LogSInf;
api->LogSWrn = LogSWrn;
api->LogSErr = LogSErr;
api->LogSFtl = LogSFtl;
//script loading
api->LoadScript = SqModImpl_LoadScript;
return 1; // Successfully populated!
}
// ------------------------------------------------------------------------------------------------
static int32_t SqExport_PopulateSquirrelAPI(HSQLIBAPI api, size_t size)
{
if (!api)
{
return 0; // Nothing to populate!
}
else if (size != sizeof(SQLIBAPI))
{
return -1; // Incompatible API!
}
//vm
api->open = sq_open;
api->newthread = sq_newthread;
api->seterrorhandler = sq_seterrorhandler;
api->close = sq_close;
api->setforeignptr = sq_setforeignptr;
api->getforeignptr = sq_getforeignptr;
api->setsharedforeignptr = sq_setsharedforeignptr;
api->getsharedforeignptr = sq_getsharedforeignptr;
api->setvmreleasehook = sq_setvmreleasehook;
api->getvmreleasehook = sq_getvmreleasehook;
api->setsharedreleasehook = sq_setsharedreleasehook;
api->getsharedreleasehook = sq_getsharedreleasehook;
api->setprintfunc = sq_setprintfunc;
api->getprintfunc = sq_getprintfunc;
api->geterrorfunc = sq_geterrorfunc;
api->suspendvm = sq_suspendvm;
api->wakeupvm = sq_wakeupvm;
api->getvmstate = sq_getvmstate;
api->getversion = sq_getversion;
//compiler
api->compile = sq_compile;
api->compilebuffer = sq_compilebuffer;
api->enabledebuginfo = sq_enabledebuginfo;
api->notifyallexceptions = sq_notifyallexceptions;
api->setcompilererrorhandler = sq_setcompilererrorhandler;
//stack operations
api->push = sq_push;
api->pop = sq_pop;
api->poptop = sq_poptop;
api->remove = sq_remove;
api->gettop = sq_gettop;
api->settop = sq_settop;
api->reservestack = sq_reservestack;
api->cmp = sq_cmp;
api->move = sq_move;
//object creation handling
api->newuserdata = sq_newuserdata;
api->newtable = sq_newtable;
api->newtableex = sq_newtableex;
api->newarray = sq_newarray;
api->newclosure = sq_newclosure;
api->setparamscheck = sq_setparamscheck;
api->bindenv = sq_bindenv;
api->setclosureroot = sq_setclosureroot;
api->getclosureroot = sq_getclosureroot;
api->pushstring = sq_pushstring;
api->pushstringf = sq_pushstringf;
api->pushfloat = sq_pushfloat;
api->pushinteger = sq_pushinteger;
api->pushbool = sq_pushbool;
api->pushuserpointer = sq_pushuserpointer;
api->pushnull = sq_pushnull;
api->pushthread = sq_pushthread;
api->gettype = sq_gettype;
api->typeof_ = sq_typeof;
api->getsize = sq_getsize;
api->gethash = sq_gethash;
api->getbase = sq_getbase;
api->instanceof = sq_instanceof;
api->tostring = sq_tostring;
api->tobool = sq_tobool;
api->getstringandsize = sq_getstringandsize;
api->getstring = sq_getstring;
api->getinteger = sq_getinteger;
api->getfloat = sq_getfloat;
api->getbool = sq_getbool;
api->getthread = sq_getthread;
api->getuserpointer = sq_getuserpointer;
api->getuserdata = sq_getuserdata;
api->settypetag = sq_settypetag;
api->gettypetag = sq_gettypetag;
api->setreleasehook = sq_setreleasehook;
api->getreleasehook = sq_getreleasehook;
api->getscratchpad = sq_getscratchpad;
api->getfunctioninfo = sq_getfunctioninfo;
api->getclosureinfo = sq_getclosureinfo;
api->getclosurename = sq_getclosurename;
api->setnativeclosurename = sq_setnativeclosurename;
api->getnativeclosurepointer = sq_getnativeclosurepointer;
api->setinstanceup = sq_setinstanceup;
api->getinstanceup = sq_getinstanceup;
api->setclassudsize = sq_setclassudsize;
api->newclass = sq_newclass;
api->createinstance = sq_createinstance;
api->setattributes = sq_setattributes;
api->getattributes = sq_getattributes;
api->getclass = sq_getclass;
api->weakref = sq_weakref;
api->getdefaultdelegate = sq_getdefaultdelegate;
api->getmemberhandle = sq_getmemberhandle;
api->getbyhandle = sq_getbyhandle;
api->setbyhandle = sq_setbyhandle;
//object manipulation
api->pushroottable = sq_pushroottable;
api->pushregistrytable = sq_pushregistrytable;
api->pushconsttable = sq_pushconsttable;
api->setroottable = sq_setroottable;
api->setconsttable = sq_setconsttable;
api->newslot = sq_newslot;
api->deleteslot = sq_deleteslot;
api->set = sq_set;
api->get = sq_get;
api->rawget = sq_rawget;
api->rawset = sq_rawset;
api->rawdeleteslot = sq_rawdeleteslot;
api->newmember = sq_newmember;
api->rawnewmember = sq_rawnewmember;
api->arrayappend = sq_arrayappend;
api->arraypop = sq_arraypop;
api->arrayresize = sq_arrayresize;
api->arrayreverse = sq_arrayreverse;
api->arrayremove = sq_arrayremove;
api->arrayinsert = sq_arrayinsert;
api->setdelegate = sq_setdelegate;
api->getdelegate = sq_getdelegate;
api->clone = sq_clone;
api->setfreevariable = sq_setfreevariable;
api->next = sq_next;
api->getweakrefval = sq_getweakrefval;
api->clear = sq_clear;
//calls
api->call = sq_call;
api->resume = sq_resume;
api->getlocal = sq_getlocal;
api->getcallee = sq_getcallee;
api->getfreevariable = sq_getfreevariable;
api->getonefreevariable = sq_getonefreevariable;
api->throwerror = sq_throwerror;
api->throwerrorf = sq_throwerrorf;
api->throwobject = sq_throwobject;
api->reseterror = sq_reseterror;
api->getlasterror = sq_getlasterror;
//raw object handling
api->getstackobj = sq_getstackobj;
api->pushobject = sq_pushobject;
api->addref = sq_addref;
api->release = sq_release;
api->getrefcount = sq_getrefcount;
api->resetobject = sq_resetobject;
api->objtostring = sq_objtostring;
api->objtobool = sq_objtobool;
api->objtointeger = sq_objtointeger;
api->objtofloat = sq_objtofloat;
api->objtouserpointer = sq_objtouserpointer;
api->getobjtypetag = sq_getobjtypetag;
api->getvmrefcount = sq_getvmrefcount;
//GC
api->collectgarbage = sq_collectgarbage;
api->resurrectunreachable = sq_resurrectunreachable;
//serialization
api->writeclosure = sq_writeclosure;
api->readclosure = sq_readclosure;
//mem allocation
api->malloc = sq_malloc;
api->realloc = sq_realloc;
api->free = sq_free;
//debug
api->stackinfos = sq_stackinfos;
api->setdebughook = sq_setdebughook;
api->setnativedebughook = sq_setnativedebughook;
//compiler helpers
api->loadfile = sqstd_loadfile;
api->dofile = sqstd_dofile;
api->writeclosuretofile = sqstd_writeclosuretofile;
//blob
api->createblob = sqstd_createblob;
api->getblob = sqstd_getblob;
api->getblobsize = sqstd_getblobsize;
//string
api->format = sqstd_format;
return 1; // Successfully populated!
}
// ------------------------------------------------------------------------------------------------
static const SQMODEXPORTS g_SqModExports{
sizeof(SQMODEXPORTS),
SqExport_PopulateModuleAPI,
SqExport_PopulateSquirrelAPI
};
// ------------------------------------------------------------------------------------------------
void InitExports()
{
// The server needs a pointer to a pointer, and a persistent one
static const SQMODEXPORTS * sqmodexports = &g_SqModExports;
// Tell the server about the pointer to the exports structure
_Func->ExportFunctions(_Info->pluginId, reinterpret_cast< const void ** >(&sqmodexports),
sizeof(HSQMODEXPORTS));
}
} // Namespace:: SqMod

872
module/Misc/Functions.cpp Normal file
View File

@@ -0,0 +1,872 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Functions.hpp"
#include "Base/Shared.hpp"
#include "Base/Color3.hpp"
#include "Base/Vector2.hpp"
#include "Base/Vector3.hpp"
#include "Entity/Player.hpp"
#include "Core.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Helper structure used to represent the boundaries of a certain district.
*/
struct District
{
// District boundaries.
Float32 mMinX, mMinY, mMaxX, mMaxY;
// District name
CSStr mName;
};
// ------------------------------------------------------------------------------------------------
static ServerSettings g_SvSettings;
static PluginInfo g_PluginInfo;
// ------------------------------------------------------------------------------------------------
static SQChar g_SvNameBuff[SQMOD_SVNAMELENGTH] = {0};
static SQChar g_PasswdBuff[SQMOD_PASSWDLENGTH] = {0};
static SQChar g_GmNameBuff[SQMOD_GMNAMELENGTH] = {0};
// ------------------------------------------------------------------------------------------------
static const District g_Districts[] = {
{-1613.03f, 413.218f, -213.73f, 1677.32f, _SC("Downtown Vice City")},
{163.656f, -351.153f, 1246.03f, 1398.85f, _SC("Vice Point")},
{-103.97f, -930.526f, 1246.03f, -351.153f, _SC("Washington Beach")},
{-253.206f, -1805.37f, 1254.9f, -930.526f, _SC("Ocean Beach")},
{-1888.21f, -1779.61f, -1208.21f, 230.39f, _SC("Escobar International Airport")},
{-748.206f, -818.266f, -104.505f, -241.467f, _SC("Starfish Island")},
{-213.73f, 797.605f, 163.656f, 1243.47f, _SC("Prawn Island")},
{-213.73f, -241.429f, 163.656f, 797.605f, _SC("Leaf Links")},
{-1396.76f, -42.9113f, -1208.21f, 230.39f, _SC("Junkyard")},
{-1208.21f, -1779.61f, -253.206f, -898.738f, _SC("Viceport")},
{-1208.21f, -898.738f, -748.206f, -241.467f, _SC("Little Havana")},
{-1208.21f, -241.467f, -578.289f, 412.66f, _SC("Little Haiti")}
};
// ------------------------------------------------------------------------------------------------
static String CS_Keycode_Names[] = {"", /* index 0 is not used */
"Left Button **", "Right Button **", "Break", "Middle Button **", "X Button 1 **",
"X Button 2 **", "", "Backspace", "Tab", "",
"", "Clear", "Enter", "", "",
"", "", "", "Pause", "Caps Lock",
"Kana", "", "Junja", "Final", "Kanji",
"", "Esc", "Convert", "Non Convert", "Accept",
"Mode Change", "Space", "Page Up", "Page Down", "End",
"Home", "Arrow Left", "Arrow Up", "Arrow Right", "Arrow Down",
"Select", "Print", "Execute", "Print Screen", "Insert",
"Delete", "Help", "0", "1", "2",
"3", "4", "5", "6", "7",
"8", "9", "", "", "",
"", "", "", "", "A",
"B", "C", "D", "E", "F",
"G", "H", "I", "J", "K",
"L", "M", "N", "O", "P",
"Q", "R", "S", "T", "U",
"V", "W", "X", "Y", "Z",
"Left Win", "Right Win", "Context Menu", "", "Sleep",
"Numpad 0", "Numpad 1", "Numpad 2", "Numpad 3", "Numpad 4",
"Numpad 5", "Numpad 6", "Numpad 7", "Numpad 8", "Numpad 9",
"Numpad *", "Numpad +", "Separator", "Num -", "Numpad .",
"Numpad /", "F1", "F2", "F3", "F4",
"F5", "F6", "F7", "F8", "F9",
"F10", "F11", "F12", "F13", "F14",
"F15", "F16", "F17", "F18", "F19",
"F20", "F21", "F22", "F23", "F24",
"", "", "", "", "",
"", "", "", "Num Lock", "Scrol Lock",
"Jisho", "Mashu", "Touroku", "Loya", "Roya",
"", "", "", "", "",
"", "", "", "", "Left Shift",
"Right Shift", "Left Ctrl", "Right Ctrl", "Left Alt", "Right Alt",
"Browser Back", "Browser Forward", "Browser Refresh", "Browser Stop", "Browser Search",
"Browser Favorites", "Browser Home", "Volume Mute", "Volume Down", "Volume Up",
"Next Track", "Previous Track", "Stop", "Play / Pause", "Mail",
"Media", "App1", "App2", "", "",
"OEM_1 (: ;)", "OEM_PLUS (+ =)", "OEM_COMMA (< ,)", "OEM_MINUS (_ -)", "OEM_PERIOD (> .)",
"OEM_2 (? /)", "OEM_3 (~ `)", "Abnt C1", "Abnt C2", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "", "",
"", "", "", "OEM_4 ({ [)", "OEM_5 (| \\)",
"OEM_6 (} ])", "OEM_7 (\" ')", "OEM_8 (? !)", "", "Ax",
"OEM_102 (> <)", "IcoHlp", "Ico00 *", "Process", "IcoClr",
"Packet", "", "Reset", "Jump", "OemPa1",
"OemPa2", "OemPa3", "WsCtrl", "Cu Sel", "Oem Attn",
"Finish", "Copy", "Auto", "Enlw", "Back Tab",
"Attn", "Cr Sel", "Ex Sel", "Er Eof", "Play",
"Zoom", "NoName", "Pa1", "OemClr", "no mapping"
};
// ------------------------------------------------------------------------------------------------
CSStr GetKeyCodeName(Uint8 keycode)
{
return CS_Keycode_Names[keycode].c_str();
}
// ------------------------------------------------------------------------------------------------
void SetKeyCodeName(Uint8 keycode, StackStrF & name)
{
CS_Keycode_Names[keycode].assign(name.mPtr);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetServerVersion()
{
return _Func->GetServerVersion();
}
// ------------------------------------------------------------------------------------------------
Table GetServerSettings()
{
// Update the server settings structure
_Func->GetServerSettings(&g_SvSettings);
// Allocate a script table
Table tbl;
// Add the structure members to the script table
tbl.SetValue(_SC("Name"), g_SvSettings.serverName);
tbl.SetValue(_SC("MaxPlayers"), g_SvSettings.maxPlayers);
tbl.SetValue(_SC("Port"), g_SvSettings.port);
tbl.SetValue(_SC("Flags"), g_SvSettings.flags);
// Return the resulted table
return tbl;
}
// ------------------------------------------------------------------------------------------------
Uint32 GetNumberOfPlugins()
{
return _Func->GetNumberOfPlugins();
}
// ------------------------------------------------------------------------------------------------
Table GetPluginInfo(Int32 plugin_id)
{
// Attempt to update the plug-in info structure
if (_Func->GetPluginInfo(plugin_id, &g_PluginInfo) == vcmpErrorNoSuchEntity)
{
STHROWF("Unknown plug-in identifier: %d", plugin_id);
}
// Allocate a script table
Table tbl;
// Add the structure members to the script table
tbl.SetValue(_SC("Id"), g_PluginInfo.pluginId);
tbl.SetValue(_SC("Name"), g_PluginInfo.name);
tbl.SetValue(_SC("Version"), g_PluginInfo.pluginVersion);
tbl.SetValue(_SC("MajorAPI"), g_PluginInfo.apiMajorVersion);
tbl.SetValue(_SC("MinorAPI"), g_PluginInfo.apiMinorVersion);
// Return the resulted table
return tbl;
}
// ------------------------------------------------------------------------------------------------
Int32 FindPlugin(StackStrF & name)
{
return _Func->FindPlugin(name.mPtr);
}
// ------------------------------------------------------------------------------------------------
void SendPluginCommand(Uint32 identifier, StackStrF & payload)
{
_Func->SendPluginCommand(identifier, payload.mPtr);
}
// ------------------------------------------------------------------------------------------------
const ULongInt & GetTime()
{
return GetULongInt(_Func->GetTime());
}
// ------------------------------------------------------------------------------------------------
void SendLogMessage(StackStrF & msg)
{
if (_Func->LogMessage("%s", msg.mPtr) == vcmpErrorTooLargeInput)
{
STHROWF("Input is too big");
}
}
// ------------------------------------------------------------------------------------------------
Int32 GetLastError()
{
return _Func->GetLastError();
}
// ------------------------------------------------------------------------------------------------
Uint32 GetPluginVersion()
{
return SQMOD_VERSION;
}
// ------------------------------------------------------------------------------------------------
CSStr GetPluginVersionStr()
{
return SQMOD_VERSION_STR;
}
// ------------------------------------------------------------------------------------------------
CSStr GetPluginName()
{
return SQMOD_NAME;
}
// ------------------------------------------------------------------------------------------------
CSStr GetPluginAuthor()
{
return SQMOD_AUTHOR;
}
// ------------------------------------------------------------------------------------------------
Int32 GetPluginID()
{
return _Info->pluginId;
}
// ------------------------------------------------------------------------------------------------
Uint32 GetServerPort()
{
// Update the server settings structure
_Func->GetServerSettings(&g_SvSettings);
// Return the requested information
return g_SvSettings.port;
}
// ------------------------------------------------------------------------------------------------
Uint32 GetServerFlags()
{
// Update the server settings structure
_Func->GetServerSettings(&g_SvSettings);
// Return the requested information
return g_SvSettings.flags;
}
// ------------------------------------------------------------------------------------------------
Int32 GetMaxPlayers(void)
{
return _Func->GetMaxPlayers();
}
// ------------------------------------------------------------------------------------------------
void SetMaxPlayers(Int32 max)
{
_Func->SetMaxPlayers(max);
}
// ------------------------------------------------------------------------------------------------
CSStr GetServerName()
{
// The server is retarded and returns `vcmpErrorBufferTooSmall` regardless of the buffer size.
// Populate the buffer
//if (_Func->GetServerName(g_SvNameBuff, SQMOD_SVNAMELENGTH) == vcmpErrorBufferTooSmall)
//{
// STHROWF("Server name was too big for the available buffer: %u", sizeof(g_SvNameBuff));
//}
// TEMPORARY WROKAROUND
// Null initialize the buffer
memset(g_SvNameBuff, 0, sizeof(g_SvNameBuff));
// Forward the call to the server
_Func->GetServerName(g_SvNameBuff, SQMOD_SVNAMELENGTH);
// Return the result (without checking for errors!!!)
return g_SvNameBuff;
}
// ------------------------------------------------------------------------------------------------
void SetServerName(StackStrF & name)
{
_Func->SetServerName(name.mPtr);
}
// ------------------------------------------------------------------------------------------------
CSStr GetServerPassword()
{
// The server is retarded and returns `vcmpErrorBufferTooSmall` regardless of the buffer size.
// Populate the buffer
//if (_Func->GetServerPassword(g_PasswdBuff, SQMOD_PASSWDLENGTH) == vcmpErrorBufferTooSmall)
//{
// STHROWF("Server password was too big for the available buffer: %u", sizeof(g_PasswdBuff));
//}
// TEMPORARY WROKAROUND
// Null initialize the buffer
memset(g_PasswdBuff, 0, sizeof(g_PasswdBuff));
// Forward the call to the server
_Func->GetServerPassword(g_PasswdBuff, SQMOD_PASSWDLENGTH);
// Return the result (without checking for errors!!!)
return g_PasswdBuff;
}
// ------------------------------------------------------------------------------------------------
void SetServerPassword(StackStrF & passwd)
{
_Func->SetServerPassword(passwd.mPtr);
}
// ------------------------------------------------------------------------------------------------
CSStr GetGameModeText()
{
// The server is retarded and returns `vcmpErrorBufferTooSmall` regardless of the buffer size.
// Populate the buffer
//if (_Func->GetGameModeText(g_GmNameBuff, SQMOD_GMNAMELENGTH) == vcmpErrorBufferTooSmall)
//{
// STHROWF("Game-mode text was too big for the available buffer: %u", sizeof(g_GmNameBuff));
//}
// TEMPORARY WROKAROUND
// Null initialize the buffer
memset(g_GmNameBuff, 0, sizeof(g_GmNameBuff));
// Forward the call to the server
_Func->GetGameModeText(g_GmNameBuff, SQMOD_GMNAMELENGTH);
// Return the result (without checking for errors!!!)
return g_GmNameBuff;
}
// ------------------------------------------------------------------------------------------------
void SetGameModeText(StackStrF & text)
{
_Func->SetGameModeText(text.mPtr);
}
// ------------------------------------------------------------------------------------------------
void CreateRadioStream(bool listed, StackStrF & name, StackStrF & url)
{
if (_Func->AddRadioStream(-1, name.mPtr, url.mPtr, listed) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Invalid radio stream identifier");
}
}
// ------------------------------------------------------------------------------------------------
void CreateRadioStreamEx(Int32 id, bool listed, StackStrF & name, StackStrF & url)
{
if (_Func->AddRadioStream(id, name.mPtr, url.mPtr, listed) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Invalid radio stream identifier");
}
}
// ------------------------------------------------------------------------------------------------
void RemoveRadioStream(Int32 id)
{
if (_Func->RemoveRadioStream(id) == vcmpErrorNoSuchEntity)
{
STHROWF("No such radio stream exists");
}
}
// ------------------------------------------------------------------------------------------------
void ShutdownServer()
{
_Func->ShutdownServer();
}
// ------------------------------------------------------------------------------------------------
bool GetServerOption(Int32 option_id)
{
// Attempt to obtain the current value of the specified option
const bool value = _Func->GetServerOption(static_cast< vcmpServerOption >(option_id));
// Check for errors
if (_Func->GetLastError() == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Unknown option identifier: %d", option_id);
}
// Return the obtained value
return value;
}
// ------------------------------------------------------------------------------------------------
void SetServerOption(Int32 option_id, bool toggle)
{
if (_Func->SetServerOption(static_cast< vcmpServerOption >(option_id),
toggle) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Unknown option identifier: %d", option_id);
}
else
{
Core::Get().EmitServerOption(option_id, toggle, 0, NullLightObj());
}
}
// ------------------------------------------------------------------------------------------------
void SetServerOptionEx(Int32 option_id, bool toggle, Int32 header, LightObj & payload)
{
if (_Func->SetServerOption(static_cast< vcmpServerOption >(option_id),
toggle) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Unknown option identifier: %d", option_id);
}
else
{
Core::Get().EmitServerOption(option_id, toggle, header, payload);
}
}
// ------------------------------------------------------------------------------------------------
Table GetWorldBounds()
{
Vector2 max, min;
// Retrieve the current world bounds
_Func->GetWorldBounds(&max.x, &min.x, &max.y, &min.y);
// Allocate a script table
Table tbl;
// Populate the table with the obtained values
tbl.SetValue(_SC("max"), max);
tbl.SetValue(_SC("min"), min);
// Return the result
return tbl;
}
// ------------------------------------------------------------------------------------------------
void SetWorldBounds(const Vector2 & max, const Vector2 & min)
{
_Func->SetWorldBounds(max.x, min.x, max.y, min.y);
}
// ------------------------------------------------------------------------------------------------
void SetWorldBoundsEx(Float32 max_x, Float32 max_y, Float32 min_x, Float32 min_y)
{
_Func->SetWorldBounds(max_x, min_x, max_y, min_y);
}
Table GetWastedSettings()
{
Uint32 fc, dt, ft, cfs, cft;
Float32 fis, fos;
Color3 c;
// Retrieve the current wasted settings bounds
_Func->GetWastedSettings(&dt, &ft, &fis, &fos, &fc, &cfs, &cft);
// Convert the packed color
c.SetRGB(fc);
// Allocate a script table
Table tbl;
// Populate the table with the obtained values
tbl.SetValue(_SC("DeathTimerOut"), dt);
tbl.SetValue(_SC("FadeTimer"), ft);
tbl.SetValue(_SC("FadeInSpeed"), fis);
tbl.SetValue(_SC("FadeOutSpeed"), fos);
tbl.SetValue(_SC("FadeColor"), c);
tbl.SetValue(_SC("FadeColour"), c);
tbl.SetValue(_SC("CorpseFadeStart"), cfs);
tbl.SetValue(_SC("CorpseFadeTime"), cft);
// Return the result
return tbl;
}
// ------------------------------------------------------------------------------------------------
void SetWastedSettings(Uint32 dt, Uint32 ft, Float32 fis, Float32 fos,
const Color3 & fc, Uint32 cfs, Uint32 cft)
{
_Func->SetWastedSettings(dt, ft, fis, fos, fc.GetRGB(), cfs, cft);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetTimeRate(void)
{
return _Func->GetTimeRate();
}
// ------------------------------------------------------------------------------------------------
void SetTimeRate(Uint32 rate)
{
_Func->SetTimeRate(rate);
}
// ------------------------------------------------------------------------------------------------
Int32 GetHour(void)
{
return _Func->GetHour();
}
// ------------------------------------------------------------------------------------------------
void SetHour(Int32 hour)
{
_Func->SetHour(hour);
}
// ------------------------------------------------------------------------------------------------
Int32 GetMinute(void)
{
return _Func->GetMinute();
}
// ------------------------------------------------------------------------------------------------
void SetMinute(Int32 minute)
{
_Func->SetMinute(minute);
}
// ------------------------------------------------------------------------------------------------
Int32 GetWeather(void)
{
return _Func->GetWeather();
}
// ------------------------------------------------------------------------------------------------
void SetWeather(Int32 weather)
{
_Func->SetWeather(weather);
}
// ------------------------------------------------------------------------------------------------
Float32 GetGravity(void)
{
return _Func->GetGravity();
}
// ------------------------------------------------------------------------------------------------
void SetGravity(Float32 gravity)
{
_Func->SetGravity(gravity);
}
// ------------------------------------------------------------------------------------------------
Float32 GetGameSpeed(void)
{
return _Func->GetGameSpeed();
}
// ------------------------------------------------------------------------------------------------
void SetGameSpeed(Float32 speed)
{
_Func->SetGameSpeed(speed);
}
// ------------------------------------------------------------------------------------------------
Float32 GetWaterLevel(void)
{
return _Func->GetWaterLevel();
}
// ------------------------------------------------------------------------------------------------
void SetWaterLevel(Float32 level)
{
_Func->SetWaterLevel(level);
}
// ------------------------------------------------------------------------------------------------
Float32 GetMaximumFlightAltitude(void)
{
return _Func->GetMaximumFlightAltitude();
}
// ------------------------------------------------------------------------------------------------
void SetMaximumFlightAltitude(Float32 height)
{
_Func->SetMaximumFlightAltitude(height);
}
// ------------------------------------------------------------------------------------------------
Int32 GetKillCommandDelay(void)
{
return _Func->GetKillCommandDelay();
}
// ------------------------------------------------------------------------------------------------
void SetKillCommandDelay(Int32 delay)
{
_Func->SetKillCommandDelay(delay);
}
// ------------------------------------------------------------------------------------------------
Float32 GetVehiclesForcedRespawnHeight(void)
{
return _Func->GetVehiclesForcedRespawnHeight();
}
// ------------------------------------------------------------------------------------------------
void SetVehiclesForcedRespawnHeight(Float32 height)
{
_Func->SetVehiclesForcedRespawnHeight(height);
}
// ------------------------------------------------------------------------------------------------
void CreateExplosion(Int32 world, Int32 type, const Vector3 & pos, CPlayer & source, bool grounded)
{
if (_Func->CreateExplosion(world, type, pos.x, pos.y, pos.z,
source.GetID(), grounded) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Argument value out of bounds");
}
}
// ------------------------------------------------------------------------------------------------
void CreateExplosionEx(Int32 world, Int32 type, Float32 x, Float32 y, Float32 z, CPlayer & source, bool grounded)
{
if (_Func->CreateExplosion(world, type, x, y, z,
source.GetID(), grounded) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Argument value out of bounds");
}
}
// ------------------------------------------------------------------------------------------------
void PlaySound(Int32 world, Int32 sound, const Vector3 & pos)
{
if (_Func->PlaySound(world, sound, pos.x, pos.y, pos.z) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Argument value out of bounds");
}
}
// ------------------------------------------------------------------------------------------------
void PlaySoundEx(Int32 world, Int32 sound, Float32 x, Float32 y, Float32 z)
{
if (_Func->PlaySound(world, sound, x, y, z) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Argument value out of bounds");
}
}
// ------------------------------------------------------------------------------------------------
void PlaySoundForWorld(Int32 world, Int32 sound)
{
if (_Func->PlaySound(world, sound, NAN, NAN, NAN) == vcmpErrorArgumentOutOfBounds)
{
STHROWF("Argument value out of bounds");
}
}
// ------------------------------------------------------------------------------------------------
void HideMapObject(Int32 model, const Vector3 & pos)
{
_Func->HideMapObject(model,
static_cast< Int16 >(std::floor(pos.x * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(pos.y * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(pos.z * 10.0f) + 0.5f)
);
}
// ------------------------------------------------------------------------------------------------
void HideMapObjectEx(Int32 model, Float32 x, Float32 y, Float32 z)
{
_Func->HideMapObject(model,
static_cast< Int16 >(std::floor(x * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(y * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(z * 10.0f) + 0.5f)
);
}
// ------------------------------------------------------------------------------------------------
void HideMapObjectRaw(Int32 model, Int16 x, Int16 y, Int16 z)
{
_Func->HideMapObject(model, x, y, z);
}
// ------------------------------------------------------------------------------------------------
void ShowMapObject(Int32 model, const Vector3 & pos)
{
_Func->ShowMapObject(model,
static_cast< Int16 >(std::floor(pos.x * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(pos.y * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(pos.z * 10.0f) + 0.5f)
);
}
// ------------------------------------------------------------------------------------------------
void ShowMapObjectEx(Int32 model, Float32 x, Float32 y, Float32 z)
{
_Func->ShowMapObject(model,
static_cast< Int16 >(std::floor(x * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(y * 10.0f) + 0.5f),
static_cast< Int16 >(std::floor(z * 10.0f) + 0.5f)
);
}
// ------------------------------------------------------------------------------------------------
void ShowMapObjectRaw(Int32 model, Int16 x, Int16 y, Int16 z)
{
_Func->ShowMapObject(model, x, y, z);
}
// ------------------------------------------------------------------------------------------------
void ShowAllMapObjects(void)
{
_Func->ShowAllMapObjects();
}
// ------------------------------------------------------------------------------------------------
SQFloat GetWeaponDataValue(Int32 weapon, Int32 field)
{
return ConvTo< SQFloat >::From(_Func->GetWeaponDataValue(weapon, field));
}
// ------------------------------------------------------------------------------------------------
bool SetWeaponDataValue(Int32 weapon, Int32 field, SQFloat value)
{
return (_Func->SetWeaponDataValue(weapon, field, value) != vcmpErrorArgumentOutOfBounds);
}
// ------------------------------------------------------------------------------------------------
bool ResetWeaponDataValue(Int32 weapon, Int32 field)
{
return (_Func->ResetWeaponDataValue(weapon, field) != vcmpErrorArgumentOutOfBounds);
}
// ------------------------------------------------------------------------------------------------
bool IsWeaponDataValueModified(Int32 weapon, Int32 field)
{
return _Func->IsWeaponDataValueModified(weapon, field);
}
// ------------------------------------------------------------------------------------------------
bool ResetWeaponData(Int32 weapon)
{
return (_Func->ResetWeaponData(weapon) != vcmpErrorArgumentOutOfBounds);
}
// ------------------------------------------------------------------------------------------------
void ResetAllWeaponData()
{
_Func->ResetAllWeaponData();
}
// ------------------------------------------------------------------------------------------------
Int32 AddPlayerClass(Int32 team, const Color3 & color, Int32 skin, const Vector3 & pos, Float32 angle,
Int32 wep1, Int32 ammo1, Int32 wep2, Int32 ammo2, Int32 wep3, Int32 ammo3)
{
return _Func->AddPlayerClass(team, color.GetRGB(), skin, pos.x, pos.y, pos.z, angle,
wep1, ammo1, wep2, ammo2, wep3, ammo3);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnPlayerPosition(const Vector3 & pos)
{
_Func->SetSpawnPlayerPosition(pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnCameraPosition(const Vector3 & pos)
{
_Func->SetSpawnCameraPosition(pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnCameraLookAt(const Vector3 & pos)
{
_Func->SetSpawnCameraLookAt(pos.x, pos.y, pos.z);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnPlayerPositionEx(Float32 x, Float32 y, Float32 z)
{
_Func->SetSpawnPlayerPosition(x, y, z);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnCameraPositionEx(Float32 x, Float32 y, Float32 z)
{
_Func->SetSpawnCameraPosition(x, y, z);
}
// ------------------------------------------------------------------------------------------------
void SetSpawnCameraLookAtEx(Float32 x, Float32 y, Float32 z)
{
_Func->SetSpawnPlayerPosition(x, y, z);
}
// ------------------------------------------------------------------------------------------------
void BanIP(StackStrF & addr)
{
_Func->BanIP(const_cast< SStr >(addr.mPtr));
}
// ------------------------------------------------------------------------------------------------
bool UnbanIP(StackStrF & addr)
{
return _Func->UnbanIP(const_cast< SStr >(addr.mPtr));
}
// ------------------------------------------------------------------------------------------------
bool IsIPBanned(StackStrF & addr)
{
return _Func->IsIPBanned(const_cast< SStr >(addr.mPtr));
}
// ------------------------------------------------------------------------------------------------
Int32 GetPlayerIdFromName(StackStrF & name)
{
return _Func->GetPlayerIdFromName(name.mPtr);
}
// ------------------------------------------------------------------------------------------------
bool IsPlayerConnected(Int32 player_id)
{
return _Func->IsPlayerConnected(player_id);
}
// ------------------------------------------------------------------------------------------------
void ForceAllSelect()
{
_Func->ForceAllSelect();
}
// ------------------------------------------------------------------------------------------------
bool CheckEntityExists(Int32 type, Int32 index)
{
return _Func->CheckEntityExists(static_cast< vcmpEntityPool >(type), index);
}
// ------------------------------------------------------------------------------------------------
CSStr GetDistrictName(const Vector2 & point)
{
return GetDistrictNameEx(point.x, point.y);
}
// ------------------------------------------------------------------------------------------------
CSStr GetDistrictNameEx(SQFloat x, SQFloat y)
{
// Attempt to see if the specified point is within one of the known districts
for (Uint32 n = 0; n < (sizeof(g_Districts) / sizeof(District)); ++n)
{
// Grab the district
const District & d = g_Districts[n];
// Check for point intersection taking into account floating point comparison issues
if (EpsGt(x, d.mMinX) && EpsGt(y, d.mMinY) && EpsLt(x, d.mMaxX) && EpsLt(y, d.mMaxY))
{
return d.mName; // The specified point is within the bounds of this district
}
}
// Not a particular district!
return _SC("Vice City");
}
// ------------------------------------------------------------------------------------------------
Uint16 GetFallTimer()
{
return _Func->GetFallTimer();
}
// ------------------------------------------------------------------------------------------------
void SetFallTimer(Uint16 rate)
{
_Func->SetFallTimer(rate);
}
#if SQMOD_SDK_LEAST(2, 1)
// ------------------------------------------------------------------------------------------------
SQFloat GetNetworkStatisticsF(Int32 option_id)
{
// Retrieve the requested information
double value = _Func->GetNetworkStatistics(-1, static_cast< vcmpNetworkStatisticsOption >(option_id));
// Return it in the proper type
return static_cast< SQFloat >(value);
}
// ------------------------------------------------------------------------------------------------
SQInteger GetNetworkStatisticsI(Int32 option_id)
{
// Retrieve the requested information
double value = _Func->GetNetworkStatistics(-1, static_cast< vcmpNetworkStatisticsOption >(option_id));
// Return it in the proper type
return static_cast< SQInteger >(value);
}
#endif
} // Namespace:: SqMod

496
module/Misc/Functions.hpp Normal file
View File

@@ -0,0 +1,496 @@
#ifndef _MISC_FUNCTIONS_HPP_
#define _MISC_FUNCTIONS_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the name of a certain key-code.
*/
CSStr GetKeyCodeName(Uint8 keycode);
/* ------------------------------------------------------------------------------------------------
* Modify the name of a certain key-code.
*/
void SetKeyCodeName(Uint8 keycode, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Retrieve the server version.
*/
Uint32 GetServerVersion();
/* ------------------------------------------------------------------------------------------------
* Retrieve the server settings.
*/
Table GetServerSettings();
/* ------------------------------------------------------------------------------------------------
* Retrieve the number of loaded plug-ins.
*/
Uint32 GetNumberOfPlugins();
/* ------------------------------------------------------------------------------------------------
* Retrieve information about a certain plug-in.
*/
Table GetPluginInfo(Int32 plugin_id);
/* ------------------------------------------------------------------------------------------------
* Attempt to find a plug-in identifier by it's name.
*/
Int32 FindPlugin(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Send a custom command to the loaded plug-ins.
*/
void SendPluginCommand(Uint32 identifier, StackStrF & payload);
/* ------------------------------------------------------------------------------------------------
* Retrieve the server time.
*/
const ULongInt & GetTime();
/* ------------------------------------------------------------------------------------------------
* Send a log message to the server.
*/
void SendLogMessage(StackStrF & msg);
/* ------------------------------------------------------------------------------------------------
* Retrieve the last error that occurred on the server.
*/
Int32 GetLastError();
/* ------------------------------------------------------------------------------------------------
* Retrieve the version of the host Squirrel plug-in as an integer.
*/
Uint32 GetPluginVersion();
/* ------------------------------------------------------------------------------------------------
* Retrieve the version of the host Squirrel plug-in as a string.
*/
CSStr GetPluginVersionStr();
/* ------------------------------------------------------------------------------------------------
* Retrieve the name of the host Squirrel plug-in.
*/
CSStr GetPluginName();
/* ------------------------------------------------------------------------------------------------
* Retrieve the author of the host Squirrel plug-in.
*/
CSStr GetPluginAuthor();
/* ------------------------------------------------------------------------------------------------
* Retrieve the id of the host Squirrel plug-in.
*/
Int32 GetPluginID();
/* ------------------------------------------------------------------------------------------------
* Retrieve the port onto which the server was binded.
*/
Uint32 GetServerPort();
/* ------------------------------------------------------------------------------------------------
* Retrieve the server flags.
*/
Uint32 GetServerFlags();
/* ------------------------------------------------------------------------------------------------
* Retrieve the maximum number of clients allowed on the server.
*/
Int32 GetMaxPlayers(void);
/* ------------------------------------------------------------------------------------------------
* Modify the maximum number of clients allowed on the server.
*/
void SetMaxPlayers(Int32 max);
/* ------------------------------------------------------------------------------------------------
* Retrieve the server name.
*/
CSStr GetServerName();
/* ------------------------------------------------------------------------------------------------
* Modify the server name.
*/
void SetServerName(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Retrieve the server password.
*/
CSStr GetServerPassword();
/* ------------------------------------------------------------------------------------------------
* Modify the server password.
*/
void SetServerPassword(StackStrF & passwd);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game-mode text.
*/
CSStr GetGameModeText();
/* ------------------------------------------------------------------------------------------------
* Modify the game-mode text.
*/
void SetGameModeText(StackStrF & text);
/* ------------------------------------------------------------------------------------------------
* Create a radio stream.
*/
void CreateRadioStream(bool listed, StackStrF & name, StackStrF & url);
/* ------------------------------------------------------------------------------------------------
* Create a radio stream.
*/
void CreateRadioStreamEx(Int32 id, bool listed, StackStrF & name, StackStrF & url);
/* ------------------------------------------------------------------------------------------------
* Remove a radio stream.
*/
void RemoveRadioStream(Int32 id);
/* ------------------------------------------------------------------------------------------------
* Shutdown the server.
*/
void ShutdownServer();
/* ------------------------------------------------------------------------------------------------
* Retrieve a server option.
*/
bool GetServerOption(Int32 option_id);
/* ------------------------------------------------------------------------------------------------
* Modify a server option.
*/
void SetServerOption(Int32 option_id, bool toggle);
/* ------------------------------------------------------------------------------------------------
* Modify a server option.
*/
void SetServerOptionEx(Int32 option_id, bool toggle, Int32 header, LightObj & payload);
/* ------------------------------------------------------------------------------------------------
* Retrieve the world bounds.
*/
Table GetWorldBounds();
/* ------------------------------------------------------------------------------------------------
* Modify the world bounds.
*/
void SetWorldBounds(const Vector2 & max, const Vector2 & min);
/* ------------------------------------------------------------------------------------------------
* Modify the world bounds.
*/
void SetWorldBoundsEx(Float32 max_x, Float32 max_y, Float32 min_x, Float32 min_y);
/* ------------------------------------------------------------------------------------------------
* Retrieve the wasted settings.
*/
Table GetWastedSettings();
/* ------------------------------------------------------------------------------------------------
* Modify the wasted settings.
*/
void SetWastedSettings(Uint32 dt, Uint32 ft, Float32 fis, Float32 fos,
const Color3 & fc, Uint32 cfs, Uint32 cft);
/* ------------------------------------------------------------------------------------------------
* Retrieve the current time-rate.
*/
Uint32 GetTimeRate(void);
/* ------------------------------------------------------------------------------------------------
* Modify the current time-rate.
*/
void SetTimeRate(Uint32 rate);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game hour.
*/
Int32 GetHour(void);
/* ------------------------------------------------------------------------------------------------
* Modify the game hour.
*/
void SetHour(Int32 hour);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game minute.
*/
Int32 GetMinute(void);
/* ------------------------------------------------------------------------------------------------
* Modify the game minute.
*/
void SetMinute(Int32 minute);
/* ------------------------------------------------------------------------------------------------
* Retrieve the weather effects.
*/
Int32 GetWeather(void);
/* ------------------------------------------------------------------------------------------------
* Modify the weather effects.
*/
void SetWeather(Int32 weather);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game gravity.
*/
Float32 GetGravity(void);
/* ------------------------------------------------------------------------------------------------
* Modify the game gravity.
*/
void SetGravity(Float32 gravity);
/* ------------------------------------------------------------------------------------------------
* Retrieve the game speed.
*/
Float32 GetGameSpeed(void);
/* ------------------------------------------------------------------------------------------------
* Modify the game speed.
*/
void SetGameSpeed(Float32 speed);
/* ------------------------------------------------------------------------------------------------
* Retrieve the water level.
*/
Float32 GetWaterLevel(void);
/* ------------------------------------------------------------------------------------------------
* Modify the water level.
*/
void SetWaterLevel(Float32 level);
/* ------------------------------------------------------------------------------------------------
* Retrieve the maximum flight altitude.
*/
Float32 GetMaximumFlightAltitude(void);
/* ------------------------------------------------------------------------------------------------
* Modify the maximum flight altitude.
*/
void SetMaximumFlightAltitude(Float32 height);
/* ------------------------------------------------------------------------------------------------
* Retrieve the kill command delay.
*/
Int32 GetKillCommandDelay(void);
/* ------------------------------------------------------------------------------------------------
* Modify the kill command delay.
*/
void SetKillCommandDelay(Int32 delay);
/* ------------------------------------------------------------------------------------------------
* Retrieve the vehicles forced respawn height.
*/
Float32 GetVehiclesForcedRespawnHeight(void);
/* ------------------------------------------------------------------------------------------------
* Modify the vehicles forced respawn height.
*/
void SetVehiclesForcedRespawnHeight(Float32 height);
/* ------------------------------------------------------------------------------------------------
* Create a game explosion.
*/
void CreateExplosion(Int32 world, Int32 type, const Vector3 & pos, CPlayer & source, bool grounded);
/* ------------------------------------------------------------------------------------------------
* Create a game explosion.
*/
void CreateExplosionEx(Int32 world, Int32 type, Float32 x, Float32 y, Float32 z, CPlayer & source, bool grounded);
/* ------------------------------------------------------------------------------------------------
* Play a game sound.
*/
void PlaySound(Int32 world, Int32 sound, const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Play a game sound.
*/
void PlaySoundEx(Int32 world, Int32 sound, Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Play a game sound to a specific world.
*/
void PlaySoundForWorld(Int32 world, Int32 sound);
/* ------------------------------------------------------------------------------------------------
* Make a map object invisible.
*/
void HideMapObject(Int32 model, const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Make a map object invisible.
*/
void HideMapObjectEx(Int32 model, Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Make a map object invisible.
*/
void HideMapObjectRaw(Int32 model, Int16 x, Int16 y, Int16 z);
/* ------------------------------------------------------------------------------------------------
* Make a map object visible again.
*/
void ShowMapObject(Int32 model, const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Make a map object visible again.
*/
void ShowMapObjectEx(Int32 model, Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Make a map object visible again.
*/
void ShowMapObjectRaw(Int32 model, Int16 x, Int16 y, Int16 z);
/* ------------------------------------------------------------------------------------------------
* Make all map objects visible again.
*/
void ShowAllMapObjects(void);
/* ------------------------------------------------------------------------------------------------
* Retrieve field data of a certain weapon.
*/
SQFloat GetWeaponDataValue(Int32 weapon, Int32 field);
/* ------------------------------------------------------------------------------------------------
* Modify field data of a certain weapon.
*/
bool SetWeaponDataValue(Int32 weapon, Int32 field, SQFloat value);
/* ------------------------------------------------------------------------------------------------
* Reset field data of a certain weapon.
*/
bool ResetWeaponDataValue(Int32 weapon, Int32 field);
/* ------------------------------------------------------------------------------------------------
* See whether field data of a certain weapon was modified.
*/
bool IsWeaponDataValueModified(Int32 weapon, Int32 field);
/* ------------------------------------------------------------------------------------------------
* Reset all fields data of a certain weapon.
*/
bool ResetWeaponData(Int32 weapon);
/* ------------------------------------------------------------------------------------------------
* Reset all fields data of a all weapons.
*/
void ResetAllWeaponData();
/* ------------------------------------------------------------------------------------------------
* Create a new player class.
*/
Int32 AddPlayerClass(Int32 team, const Color3 & color, Int32 skin, const Vector3 & pos, Float32 angle,
Int32 wep1, Int32 ammo1, Int32 wep2, Int32 ammo2, Int32 wep3, Int32 ammo3);
/* ------------------------------------------------------------------------------------------------
* Set the player position when spawning.
*/
void SetSpawnPlayerPosition(const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Set the camera position when spawning.
*/
void SetSpawnCameraPosition(const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Set the camera focus when spawning.
*/
void SetSpawnCameraLookAt(const Vector3 & pos);
/* ------------------------------------------------------------------------------------------------
* Set the player position when spawning.
*/
void SetSpawnPlayerPositionEx(Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Set the camera position when spawning.
*/
void SetSpawnCameraPositionEx(Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Set the camera focus when spawning.
*/
void SetSpawnCameraLookAtEx(Float32 x, Float32 y, Float32 z);
/* ------------------------------------------------------------------------------------------------
* Ban an IP address from the server.
*/
void BanIP(StackStrF & addr);
/* ------------------------------------------------------------------------------------------------
* Unban an IP address from the server.
*/
bool UnbanIP(StackStrF & addr);
/* ------------------------------------------------------------------------------------------------
* See if an IP address is banned from the server.
*/
bool IsIPBanned(StackStrF & addr);
/* ------------------------------------------------------------------------------------------------
* Retrieve the identifier of the player with the specified name.
*/
Int32 GetPlayerIdFromName(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* See if a player with the specified identifier is connected.
*/
bool IsPlayerConnected(Int32 player_id);
/* ------------------------------------------------------------------------------------------------
* Force all players on the server to select a class.
*/
void ForceAllSelect();
/* ------------------------------------------------------------------------------------------------
* See if an entity exists on the server.
*/
bool CheckEntityExists(Int32 type, Int32 index);
/* ------------------------------------------------------------------------------------------------
* See if a certain point is within a known district on the bas game map.
*/
CSStr GetDistrictName(const Vector2 & point);
/* ------------------------------------------------------------------------------------------------
* See if a certain point is within a known district on the bas game map.
*/
CSStr GetDistrictNameEx(SQFloat x, SQFloat y);
/* ------------------------------------------------------------------------------------------------
* Retrieve the fall timer rate.
*/
Uint16 GetFallTimer();
/* ------------------------------------------------------------------------------------------------
* Modify the fall timer rate.
*/
void SetFallTimer(Uint16 rate);
#if SQMOD_SDK_LEAST(2, 1)
/* ------------------------------------------------------------------------------------------------
* Retrieve network statistics related to the server.
*/
SQFloat GetNetworkStatisticsF(Int32 option_id);
/* ------------------------------------------------------------------------------------------------
* Retrieve network statistics related to the server.
*/
SQInteger GetNetworkStatisticsI(Int32 option_id);
#endif
} // Namespace:: SqMod
#endif // _MISC_FUNCTIONS_HPP_

111
module/Misc/Model.cpp Normal file
View File

@@ -0,0 +1,111 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Model.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
CSStr GetModelName(Int32 /*id*/)
{
// @TODO Implement...
return _SC("");
}
// ------------------------------------------------------------------------------------------------
void SetModelName(Int32 /*id*/, StackStrF & /*name*/)
{
// @TODO Implement...
}
// ------------------------------------------------------------------------------------------------
bool IsModelWeapon(Int32 id)
{
switch (id)
{
case 258:
case 259:
case 260:
case 261:
case 262:
case 263:
case 264:
case 265:
case 266:
case 267:
case 268:
case 269:
case 270:
case 271:
case 272:
case 273:
case 274:
case 275:
case 276:
case 277:
case 278:
case 279:
case 280:
case 281:
case 282:
case 283:
case 284:
case 285:
case 286:
case 287:
case 288:
case 289:
case 290:
case 291:
case 292:
case 293:
case 294: return true;
default: return false;
}
}
// ------------------------------------------------------------------------------------------------
bool IsModelActuallyWeapon(Int32 id)
{
switch (id)
{
case 259:
case 260:
case 261:
case 262:
case 263:
case 264:
case 265:
case 266:
case 267:
case 268:
case 269:
case 270:
case 271:
case 272:
case 274:
case 275:
case 276:
case 277:
case 278:
case 279:
case 280:
case 281:
case 282:
case 283:
case 284:
case 285:
case 286:
case 287:
case 288:
case 289:
case 290:
case 291: return true;
default: return false;
}
}
} // Namespace:: SqMod

32
module/Misc/Model.hpp Normal file
View File

@@ -0,0 +1,32 @@
#ifndef _MISC_MODEL_HPP_
#define _MISC_MODEL_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the name associated with a model identifier.
*/
CSStr GetModelName(Int32 id);
/* ------------------------------------------------------------------------------------------------
* Modify the name associated with a model identifier.
*/
void SetModelName(Int32 id, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* See whether the given model identifier is used a weapon model.
*/
bool IsModelWeapon(Int32 id);
/* ------------------------------------------------------------------------------------------------
* See whether the given model identifier is an actual weapon model.
*/
bool IsModelActuallyWeapon(Int32 id);
} // Namespace:: SqMod
#endif // _MISC_MODEL_HPP_

763
module/Misc/Player.cpp Normal file
View File

@@ -0,0 +1,763 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Player.hpp"
#include "Base/Color3.hpp"
#include "Core.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static String CS_Skin_Names[] = {
/* 0 */ "Tommy Vercetti", /* 1 */ "Cop",
/* 2 */ "SWAT", /* 3 */ "FBI",
/* 4 */ "Army", /* 5 */ "Paramedic",
/* 6 */ "Firefighter", /* 7 */ "Golf Guy #1",
/* 8 */ "", /* 9 */ "Bum Lady #1",
/* 10 */ "Bum Lady #2", /* 11 */ "Punk #1",
/* 12 */ "Lawyer", /* 13 */ "Spanish Lady #1",
/* 14 */ "Spanish Lady #2", /* 15 */ "Cool Guy #1",
/* 16 */ "Arabic Guy", /* 17 */ "Beach Lady #1",
/* 18 */ "Beach Lady #2", /* 19 */ "Beach Guy #1",
/* 20 */ "Beach Guy #2", /* 21 */ "Office Lady #1",
/* 22 */ "Waitress #1", /* 23 */ "Food Lady",
/* 24 */ "Prostitute #1", /* 25 */ "Bum Lady #3",
/* 26 */ "Bum Guy #1", /* 27 */ "Garbageman #1",
/* 28 */ "Taxi Driver #1", /* 29 */ "Haitian #1",
/* 30 */ "Criminal #1", /* 31 */ "Hood Lady",
/* 32 */ "Granny #1", /* 33 */ "Businessman #1",
/* 34 */ "Church Guy", /* 35 */ "Club Lady",
/* 36 */ "Church Lady", /* 37 */ "Pimp",
/* 38 */ "Beach Lady #3", /* 39 */ "Beach Guy #3",
/* 40 */ "Beach Lady #4", /* 41 */ "Beach Guy #4",
/* 42 */ "Businessman #2", /* 43 */ "Prostitute #2",
/* 44 */ "Bum Lady #4", /* 45 */ "Bum Guy #2",
/* 46 */ "Haitian #2", /* 47 */ "Construction Worker #1",
/* 48 */ "Punk #2", /* 49 */ "Prostitute #3",
/* 50 */ "Granny #2", /* 51 */ "Punk #3",
/* 52 */ "Businessman #3", /* 53 */ "Spanish Lady #3",
/* 54 */ "Spanish Lady #4", /* 55 */ "Cool Guy #2",
/* 56 */ "Businessman #4", /* 57 */ "Beach Lady #5",
/* 58 */ "Beach Guy #5", /* 59 */ "Beach Lady #6",
/* 60 */ "Beach Guy #6", /* 61 */ "Construction Worker #2",
/* 62 */ "Golf Guy #2", /* 63 */ "Golf Lady",
/* 64 */ "Golf Guy #3", /* 65 */ "Beach Lady #7",
/* 66 */ "Beach Guy #7", /* 67 */ "Office Lady #2",
/* 68 */ "Businessman #5", /* 69 */ "Businessman #6",
/* 70 */ "Prostitute #2", /* 71 */ "Bum Lady #4",
/* 72 */ "Bum Guy #3", /* 73 */ "Spanish Guy",
/* 74 */ "Taxi Driver #2", /* 75 */ "Gym Lady",
/* 76 */ "Gym Guy", /* 77 */ "Skate Lady",
/* 78 */ "Skate Guy", /* 79 */ "Shopper #1",
/* 80 */ "Shopper #2", /* 81 */ "Tourist #1",
/* 82 */ "Tourist #2", /* 83 */ "Cuban #1",
/* 84 */ "Cuban #2", /* 85 */ "Haitian #3",
/* 86 */ "Haitian #4", /* 87 */ "Shark #1",
/* 88 */ "Shark #2", /* 89 */ "Diaz Guy #1",
/* 90 */ "Diaz Guy #2", /* 91 */ "DBP Security #1",
/* 92 */ "DBP Security #2", /* 93 */ "Biker #1",
/* 94 */ "Biker #2", /* 95 */ "Vercetti Guy #1",
/* 96 */ "Vercetti Guy #2", /* 97 */ "Undercover Cop #1",
/* 98 */ "Undercover Cop #2", /* 99 */ "Undercover Cop #3",
/* 100 */ "Undercover Cop #4", /* 101 */ "Undercover Cop #5",
/* 102 */ "Undercover Cop #6", /* 103 */ "Rich Guy",
/* 104 */ "Cool Guy #3", /* 105 */ "Prostitute #3",
/* 106 */ "Prostitute #4", /* 107 */ "Love Fist #1",
/* 108 */ "Ken Rosenburg", /* 109 */ "Candy Suxx",
/* 110 */ "Hilary", /* 111 */ "Love Fist #2",
/* 112 */ "Phil", /* 113 */ "Rockstar Guy",
/* 114 */ "Sonny", /* 115 */ "Lance",
/* 116 */ "Mercedes", /* 117 */ "Love Fist #3",
/* 118 */ "Alex Shrub", /* 119 */ "Lance (Cop)",
/* 120 */ "Lance", /* 121 */ "Cortez",
/* 122 */ "Love Fist #4", /* 123 */ "Columbian Guy #1",
/* 124 */ "Hilary (Robber)", /* 125 */ "Mercedes",
/* 126 */ "Cam", /* 127 */ "Cam (Robber)",
/* 128 */ "Phil (One Arm)", /* 129 */ "Phil (Robber)",
/* 130 */ "Cool Guy #4", /* 131 */ "Pizza Man",
/* 132 */ "Taxi Driver #1", /* 133 */ "Taxi Driver #2",
/* 134 */ "Sailor #1", /* 135 */ "Sailor #2",
/* 136 */ "Sailor #3", /* 137 */ "Chef",
/* 138 */ "Criminal #2", /* 139 */ "French Guy",
/* 140 */ "Garbageman #2", /* 141 */ "Haitian #5",
/* 142 */ "Waitress #2", /* 143 */ "Sonny Guy #1",
/* 144 */ "Sonny Guy #2", /* 145 */ "Sonny Guy #3",
/* 146 */ "Columbian Guy #2", /* 147 */ "Haitian #6",
/* 148 */ "Beach Guy #8", /* 149 */ "Garbageman #3",
/* 150 */ "Garbageman #4", /* 151 */ "Garbageman #5",
/* 152 */ "Tranny", /* 153 */ "Thug #5",
/* 154 */ "SpandEx Guy #1", /* 155 */ "SpandEx Guy #2",
/* 156 */ "Stripper #1", /* 157 */ "Stripper #2",
/* 158 */ "Stripper #3", /* 159 */ "Store Clerk",
/* 160 */ ""
};
// ------------------------------------------------------------------------------------------------
CCStr GetSkinName(Uint32 id)
{
return (id > 159) ? _SC("") : CS_Skin_Names[id].c_str();
}
// ------------------------------------------------------------------------------------------------
void SetSkinName(Uint32 id, StackStrF & name)
{
if (id <= 159)
{
CS_Skin_Names[id].assign(name.mPtr);
}
}
// ------------------------------------------------------------------------------------------------
Int32 GetSkinID(StackStrF & name)
{
// Clone the string into an editable version
String str(name.mPtr, name.mLen);
// Strip non alphanumeric characters from the name
str.erase(std::remove_if(str.begin(), str.end(), std::not1(std::ptr_fun(::isalnum))), str.end());
// Convert the string to lowercase
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
// See if we still have a valid name after the cleanup
if(str.empty())
{
return SQMOD_UNKNOWN;
}
// Grab the actual length of the string
const Uint32 len = ConvTo< Uint32 >::From(str.length());
// Get the most significant characters used to identify a skin
CharT a = str[0], b = 0, c = 0, d = str[len-1];
// Look for deeper specifiers
if (len > 2)
{
b = str[1];
c = str[2];
}
else if (len > 1)
{
b = str[1];
}
// Search for a pattern in the name
switch (a)
{
// [A]lex Srub, [A]rabic guy, [A]rmy
case 'a':
switch (b)
{
// [Al]ex [S]rub
case 'l':
case 's': return SQMOD_SKIN_ALEX_SRUB;
// [A]rabic [g]uy
case 'g': return SQMOD_SKIN_ARABIC_GUY;
// [Ara]bic guy, [Arm]y
case 'r':
if (c == 'a') return SQMOD_SKIN_ARABIC_GUY;
else if (c == 'm') return SQMOD_SKIN_ARMY;
}
// [B]each guy (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)/(#7|G)/(#8|H)
// [B]each lady (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)/(#7|G)
// [B]iker (#1|A)/(#2|B)
// [B]um guy (#1|A)/(#2|B)/(#3|C)
// [B]um lady (#1|A)/(#2|B)/(#2|C)/(#3|D)/(#4|E)
// [B]usiness man (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)
// fall through
case 'b':
// [Be]ach [g]uy (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)/(#7|G)/(#8|H)
if (b == 'e' && (c == 'g' || (len > 5 && str[5] == 'g')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_BEACH_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_BEACH_GUY_B;
case '3':
case 'c': return SQMOD_SKIN_BEACH_GUY_C;
case '4':
case 'd': return SQMOD_SKIN_BEACH_GUY_D;
case '5':
case 'e': return SQMOD_SKIN_BEACH_GUY_E;
case '6':
case 'f': return SQMOD_SKIN_BEACH_GUY_F;
case '7':
case 'g': return SQMOD_SKIN_BEACH_GUY_G;
case '8':
case 'h': return SQMOD_SKIN_BEACH_GUY_H;
}
}
// [Be]ach [l]ady (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)/(#7|G)
else if (b == 'e' && (c == 'l' || (len > 5 && str[5] == 'l')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_BEACH_LADY_A;
case '2':
case 'b': return SQMOD_SKIN_BEACH_LADY_B;
case '3':
case 'c': return SQMOD_SKIN_BEACH_LADY_C;
case '4':
case 'd': return SQMOD_SKIN_BEACH_LADY_D;
case '5':
case 'e': return SQMOD_SKIN_BEACH_LADY_E;
case '6':
case 'f': return SQMOD_SKIN_BEACH_LADY_F;
case '7':
case 'g': return SQMOD_SKIN_BEACH_LADY_G;
}
}
// [Bi]ker (#1|A)/(#2|B)
else if (b == 'i' && (d == '1' || d == 'a')) return SQMOD_SKIN_BIKER_A;
else if (b == 'i' && (d == '2' || d == 'b')) return SQMOD_SKIN_BIKER_B;
// [Bum] [g]uy (#1|A)/(#2|B)/(#3|C)
// [Bum] [l]ady (#1|A)/(#2|B)/(#2|C)/(#3|D)/(#4|E)
else if (b == 'u' && (c && (c == 'm' || c == 'g' || c == 'l')))
{
// [Bum] [g]uy (#1|A)/(#2|B)/(#3|C)
if (c == 'g' || (len > 3 && str[3] == 'g'))
{
if (d == '1' || d == 'a') return SQMOD_SKIN_BUM_GUY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_BUM_GUY_B;
else if (d == '3' || d == 'c') return SQMOD_SKIN_BUM_GUY_C;
}
// [Bum] [l]ady (#1|A)/(#2|B)/(#2|C)/(#3|D)/(#4|E)
else if (c == 'l' || (len > 3 && str[3] == 'l'))
{
if (d == '1' || d == 'a') return SQMOD_SKIN_BUM_LADY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_BUM_LADY_B;
else if (d == '2' || d == 'c') return SQMOD_SKIN_BUM_LADY_C;
else if (d == '3' || d == 'd') return SQMOD_SKIN_BUM_LADY_D;
else if (d == '4' || d == 'e') return SQMOD_SKIN_BUM_LADY_E;
}
}
// [Bus]iness [m]an (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)
else if (b == 'u' && (c == 's' || (len > 9 && str[9] == 'm')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_BUSINESS_MAN_A;
case '2':
case 'b': return SQMOD_SKIN_BUSINESS_MAN_B;
case '3':
case 'c': return SQMOD_SKIN_BUSINESS_MAN_C;
case '4':
case 'd': return SQMOD_SKIN_BUSINESS_MAN_D;
case '5':
case 'e': return SQMOD_SKIN_BUSINESS_MAN_E;
case '6':
case 'f': return SQMOD_SKIN_BUSINESS_MAN_F;
}
}
// [C]am, [C]am (Robber), [C]andy Suxx, [C]hef
// [C]hurch guy, [C]hurch lady, [C]lub lady
// [C]olumbian guy (#1|A)/(#2|B),
// [C]onstruction worker (#1|A)/(#2|B)
// [C]ool guy (#1|A)/(#2|B)/(#3|C)/(#4|D)
// [C]op, [C]ortez
// [C]riminal (#1|A)/(#2|B)
// [C]uban (#1|A)/(#2|B)
// fall through
case 'c':
// [Ca]m, [Ca]m (Robber), [Ca]ndy Suxx
if (b == 'a')
{
// [Cam] ([R]obbe[r])
if (c && (c == 'm' || c == 'r') && d == 'r') return SQMOD_SKIN_CAM_ROBBER;
// [Cam]
else if (c == 'm') return SQMOD_SKIN_CAM;
// [Can]dy [S]ux[x]
else if (c && (c == 'n' || c == 's' || d == 'x')) return SQMOD_SKIN_CANDY_SUXX;
}
// [Ch]ef, [Ch]urch guy, [Ch]urch lady
else if (b == 'h')
{
// [Che][f]
if (c && (c == 'e' || d == 'f')) return SQMOD_SKIN_CHEF;
// [Chu]rch [g]uy
else if (c && ((c == 'u' && len > 6 && str[6] == 'g') || (c == 'g')))
return SQMOD_SKIN_CHURCH_GUY;
// [Chu]rch [l]ady
else if (c && ((c == 'u' && len > 6 && str[6] == 'l') || (c == 'l')))
return SQMOD_SKIN_CHURCH_LADY;
}
// [Cl]ub [l]ady
else if (b == 'l') return SQMOD_SKIN_CLUB_LADY;
// [Co]lumbian guy (#1|A)/(#2|B)
// [Co]nstruction worker (#1|A)/(#2|B)
// [Co]ol guy (#1|A)/(#2|B)/(#3|C)/(#4|D)
// [Co]p, [Co]rtez
else if (b == 'o')
{
// [Col]umbian [g]uy (#1|A)/(#2|B)
if (c && ((c == 'l' && len > 9 && str[9] == 'g') || (c == 'g')))
{
if (d == '1' || d == 'a') return SQMOD_SKIN_COLUMBIAN_GUY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_COLUMBIAN_GUY_B;
}
// [Con]struction [w]orker (#1|A)/(#2|B)
else if (c && (c == 'n' || (len > 12 && str[12] == 'g')))
{
if (d == '1' || d == 'a') return SQMOD_SKIN_CONSTRUCTION_WORKER_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_CONSTRUCTION_WORKER_B;
}
// [Coo]l guy (#1|A)/(#2|B)/(#3|C)/(#4|D)
else if (c == 'o')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_COOL_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_COOL_GUY_B;
case '3':
case 'c': return SQMOD_SKIN_COOL_GUY_C;
case '4':
case 'd': return SQMOD_SKIN_COOL_GUY_D;
}
}
// [Cop]
else if (c == 'p') return SQMOD_SKIN_COP;
// [Cor]te[z]
else if (c && (c == 'r' || c == 'z' || d == 'z')) return SQMOD_SKIN_CORTEZ;
}
// [Cr]iminal (#1|A)/(#2|B)
else if (b == 'r' && (d == '1' || d == 'a')) return SQMOD_SKIN_CRIMINAL_A;
else if (b == 'r' && (d == '2' || d == 'b')) return SQMOD_SKIN_CRIMINAL_B;
// [Cu]ban (#1|A)/(#2|B)
else if (b == 'u' && (d == '1' || d == 'a')) return SQMOD_SKIN_CUBAN_A;
else if (b == 'u' && (d == '2' || d == 'b')) return SQMOD_SKIN_CUBAN_B;
// [D]BP security (#1|A)/(#2|B)
// [D]iaz guy (#1|A)/(#2|B)
// fall through
case 'd':
switch (b)
{
// [DB]P [s]ecurity (#1|A)/(#2|B)
case 'b':
case 's':
if (d == '1' || d == 'a') return SQMOD_SKIN_DBP_SECURITY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_DBP_SECURITY_B;
// [Di]a[z] [g]uy (#1|A)/(#2|B)
// fall through
case 'i':
case 'z':
case 'g':
if (d == '1' || d == 'a') return SQMOD_SKIN_DIAZ_GUY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_DIAZ_GUY_B;
}
// [F]BI, [F]ireman, [F]ood lady, [F]rench guy
// fall through
case 'f':
switch (b)
{
// [FB]I
case 'b': return SQMOD_SKIN_FBI;
// [Fi]re[m]an
case 'i':
case 'm': return SQMOD_SKIN_FIREMAN;
// [Fo]od [l]ady
case 'o':
case 'l': return SQMOD_SKIN_FOOD_LADY;
// [Fr]ench [g]uy
case 'r':
case 'g': return SQMOD_SKIN_FRENCH_GUY;
}
// [G]arbageman (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)
// [G]olf guy (#1|A)/(#2|B)/(#3|C)
// [G]olf lady
// [G]ranny (#1|A)/(#2|B)
// [G]ym guy, [G]ym lady
case 'g':
// [Ga]rbage[m]an (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)
if (b && (b == 'a' || b == 'm'))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_GARBAGEMAN_A;
case '2':
case 'b': return SQMOD_SKIN_GARBAGEMAN_B;
case '3':
case 'c': return SQMOD_SKIN_GARBAGEMAN_C;
case '4':
case 'd': return SQMOD_SKIN_GARBAGEMAN_D;
case '5':
case 'e': return SQMOD_SKIN_GARBAGEMAN_E;
}
}
// [Go]lf [g]uy (#1|A)/(#2|B)/(#3|C)
else if (b == 'o' && ((c == 'g') || (len > 4 && str[4] == 'g')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_GOLF_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_GOLF_GUY_B;
case '3':
case 'c': return SQMOD_SKIN_GOLF_GUY_C;
}
}
// [Go]lf [l]ady
else if (b == 'o' && ((c == 'l') || (len > 4 && str[4] == 'l')))
return SQMOD_SKIN_GOLF_LADY;
// [Gr]anny (#1|A)/(#2|B)
else if (b == 'r')
{
if (d == '1' || d == 'a') return SQMOD_SKIN_GRANNY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_GRANNY_B;
}
// [Gy]m [g]uy
else if (b && (b == 'g' || (b == 'y' && len > 3 && str[3] == 'g')))
return SQMOD_SKIN_GYM_GUY;
// [Gy]m [l]ady
else if (b && (b == 'l' || (b == 'y' && len > 3 && str[3] == 'l')))
return SQMOD_SKIN_GYM_LADY;
// [H]atian (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)
// [H]ilary, [H]ilary (Robber), [H]ood lady
// fall through
case 'h':
// [H]atian (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)
if (b == 'a')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_HATIAN_A;
case '2':
case 'b': return SQMOD_SKIN_HATIAN_B;
case '3':
case 'c': return SQMOD_SKIN_HATIAN_C;
case '4':
case 'd': return SQMOD_SKIN_HATIAN_D;
case '5':
case 'e': return SQMOD_SKIN_HATIAN_E;
}
}
// [Hi]lary ([R]obbe[r])
else if (b && (b == 'i' || b == 'r') && d == 'r') return SQMOD_SKIN_HILARY_ROBBER;
// [Hi]lary
else if (b == 'i') return SQMOD_SKIN_HILARY;
// [Ho]od [l]ady
if (b && (b == 'o' || b == 'l')) return SQMOD_SKIN_HOOD_LADY;
// [K]en Rosenburg
// fall through
case 'k':
return SQMOD_SKIN_KEN_ROSENBURG;
// [L]ance (#1|A)/(#1|B)
// [L]ance (Cop)
// [L]awyer
// [L]ove Fist (#1|A)/(#2|B)/(#3|C)/(#3|D)
case 'l':
//[Lan]ce ([C]o[p])
if ((b == 'a') && (c == 'n') && ((len > 5 && str[5] == 'c') || d == 'p'))
return SQMOD_SKIN_LANCE_COP;
else if (b && (b == 'c' || (b == 'a' && (c == 'n'))))
return SQMOD_SKIN_LANCE_COP;
// [La]nce (#1|A)/(#1|B)
else if (b == 'a' && c == 'n')
{
if (d == '1' || d == 'a') return SQMOD_SKIN_LANCE_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_LANCE_B;
}
// [Law]yer
else if (b && (b == 'w' || (b == 'a' && c == 'w'))) return SQMOD_SKIN_LAWYER;
// [Lo]ve [F]ist (#1|A)/(#2|B)/(#3|C)/(#3|D)
else if (b && (b == 'o' || b == 'f'))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_LOVE_FIST_A;
case '2':
case 'b': return SQMOD_SKIN_LOVE_FIST_B;
case '3':
case 'c': return SQMOD_SKIN_LOVE_FIST_C;
case 'd': return SQMOD_SKIN_LOVE_FIST_D;
}
}
// [M]ercades
// fall through
case 'm':
if (d == 'b') return SQMOD_SKIN_MERCADES_B;
else return SQMOD_SKIN_MERCADES_A;
// [O]ffice lady (#1|A)/(#2|B)
case 'o':
if (d == '1' || d == 'a') return SQMOD_SKIN_OFFICE_LADY_A;
else if (d == '2' || d == 'b') return SQMOD_SKIN_OFFICE_LADY_B;
// [P]aramedic, [P]hil, [P]hil (One arm), [P]hil (Robber)
// [P]imp, [P]izzaman
// [P]rostitute (#1|A)/(#2|B)/(#2|C)/(#2|D)/(#3|D)/(#4|D)
// [P]unk (#1|A)/(#2|B)/(#3|C)
// fall through
case 'p':
// [Pa]ramedic
if (b == 'a') return SQMOD_SKIN_PARAMEDIC;
// [Ph]il (One arm), [Ph]il (Robber)
else if (b == 'h')
{
// [Ph]il ([O]ne ar[m])
if (b == 'o' || (c == 'o') || (len > 4 && str[4] == 'o') || d == 'm')
return SQMOD_SKIN_PHIL_ONE_ARM;
// [Ph]il ([R]obbe[r])
else if (c && (c == 'r' || d == 'r' || (len > 4 && str[4] == 'r')))
return SQMOD_SKIN_PHIL_ROBBER;
// [Phi]l
else if (c == 'i') return SQMOD_SKIN_PHIL;
}
// [Pim][p]
else if (b == 'i' && ((c == 'm') || d == 'p')) return SQMOD_SKIN_PIMP;
// [Piz]zama[n]
else if (b == 'i' && ((c == 'z') || d == 'n')) return SQMOD_SKIN_PIZZAMAN;
// [Pr]ostitute (#1|A)/(#2|B)/(#2|C)/(#2|D)/(#3|D)/(#4|D)
else if (b == 'r')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_PROSTITUTE_A;
case '2':
case 'b': return SQMOD_SKIN_PROSTITUTE_B;
case 'c': return SQMOD_SKIN_PROSTITUTE_C;
case 'd': return SQMOD_SKIN_PROSTITUTE_D;
case '3':
case 'e': return SQMOD_SKIN_PROSTITUTE_E;
case '4':
case 'f': return SQMOD_SKIN_PROSTITUTE_F;
}
}
// [Pu]nk (#1|A)/(#2|B)/(#3|C)
else if (b == 'u')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_PUNK_A;
case '2':
case 'b': return SQMOD_SKIN_PUNK_B;
case '3':
case 'c': return SQMOD_SKIN_PUNK_C;
}
}
// [R]ich guy, [R]ockstar guy
// fall through
case 'r':
// [Ri]ch guy
if (b == 'i') return SQMOD_SKIN_RICH_GUY;
// [Ro]ckstar guy
else if (b == 'o') return SQMOD_SKIN_ROCKSTAR_GUY;
// [S]ailor (#1|A)/(#2|B)/(#3|C)
// [S]hark (#1|A)/(#2|B)
// [S]hopper (#1|A)/(#2|B)
// [S]kate guy, [S]kate lady, [S]onny
// [S]onny guy (#1|A)/(#2|B)/(#3|C)
// [S]pandEx (#1|A)/(#2|B)
// [S]panish guy
// [S]panish lady (#1|A)/(#2|B)/(#3|C)/(#4|D)
// [S]tore clerk
// [S]tripper (#1|A)/(#2|B)/(#3|C)
// [S]wat
// fall through
case 's':
// [Sa]ilor (#1|A)/(#2|B)/(#3|C)
if (b == 'a')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SAILOR_A;
case '2':
case 'b': return SQMOD_SKIN_SAILOR_B;
case '3':
case 'c': return SQMOD_SKIN_SAILOR_C;
}
}
// [S]hark (#1|A)/(#2|B)
else if (b == 'h' && c == 'a')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SHARK_A;
case '2':
case 'b': return SQMOD_SKIN_SHARK_B;
}
}
// [S]hopper (#1|A)/(#2|B)
else if (b == 'h' && c == 'o')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SHOPPER_A;
case '2':
case 'b': return SQMOD_SKIN_SHOPPER_B;
}
}
// [Sk]ate [g]uy
else if (b == 'k' && ((c == 'g') || (len > 5 && str[5] == 'g')))
return SQMOD_SKIN_SKATE_GUY;
// [Sk]ate [l]ady
else if (b == 'k' && ((c == 'l') || (len > 5 && str[5] == 'l')))
return SQMOD_SKIN_SKATE_LADY;
// [So]nny
// [So]nny guy (#1|A)/(#2|B)/(#3|C)
else if (b == 'o')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SONNY_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_SONNY_GUY_B;
case '3':
case 'c': return SQMOD_SKIN_SONNY_GUY_C;
}
}
else if (b == 'g')
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SONNY_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_SONNY_GUY_B;
case '3':
case 'c': return SQMOD_SKIN_SONNY_GUY_C;
}
}
// [Sp]andE[x] (#1|A)/(#2|B)
else if (b == 'p' && ((c == 'x') || (len > 6 && str[6] == 'x')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SPANDEX_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_SPANDEX_GUY_B;
}
}
// [Sp]anish [g]uy
else if (b == 'p' && ((c == 'g') || (len > 7 && str[7] == 'g')))
return SQMOD_SKIN_SPANISH_GUY;
// [Sp]anish [l]ady (#1|A)/(#2|B)/(#3|C)/(#4|D)
else if (b == 'p' && ((c == 'l') || (len > 7 && str[7] == 'l')))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_SPANISH_LADY_A;
case '2':
case 'b': return SQMOD_SKIN_SPANISH_LADY_B;
case '3':
case 'c': return SQMOD_SKIN_SPANISH_LADY_C;
case '4':
case 'd': return SQMOD_SKIN_SPANISH_LADY_D;
}
}
// [Sto]re clerk
else if ((b == 't') && (c == 'o')) return SQMOD_SKIN_STORE_CLERK;
// [Str]ipper (#1|A)/(#2|B)/(#3|C)
else if ((b == 't') && (c == 'r'))
{
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_STRIPPER_A;
case '2':
case 'b': return SQMOD_SKIN_STRIPPER_B;
case '3':
case 'c': return SQMOD_SKIN_STRIPPER_C;
}
}
// [Sw]at
else if (b == 'w') return SQMOD_SKIN_SWAT;
// [T]axi driver (#1|A)/(#1|B)/(#2|C)/(#2|D)
// [T]hug (#1|A)/(#2|B)
// [T]ommy Vercetti
// [T]ourist (#1|A)/(#2|B)
// [T]ranny
// fall through
case 't':
switch (b)
{
// [Ta]xi driver (#1|A)/(#1|B)/(#2|C)/(#2|D)
case 'a':
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_TAXI_DRIVER_A;
case '2':
case 'b': return SQMOD_SKIN_TAXI_DRIVER_B;
case 'c': return SQMOD_SKIN_TAXI_DRIVER_C;
case 'd': return SQMOD_SKIN_TAXI_DRIVER_D;
}
// [Th]ug (#1|A)/(#2|B)
case 'h':
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_THUG_A;
case '5':
case 'b': return SQMOD_SKIN_THUG_B;
}
// [To]mmy [V]ercetti
// [To]urist (#1|A)/(#2|B)
case 'v': return SQMOD_SKIN_TOMMY_VERCETTI;
case 'o':
if (c == 'm') return SQMOD_SKIN_TOMMY_VERCETTI;
else if (c == 'u' && (d == '1' || d == 'a')) return SQMOD_SKIN_TOURIST_A;
else if (c == 'u' && (d == '2' || d == 'b')) return SQMOD_SKIN_TOURIST_B;
// fall through
case 'r': return SQMOD_SKIN_TRANNY;
}
// [U]ndercover cop (#1|A)/(#2|B)/(#3|C)/(#4|D)/(#5|E)/(#6|F)
case 'u':
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_UNDERCOVER_COP_A;
case '2':
case 'b': return SQMOD_SKIN_UNDERCOVER_COP_B;
case '3':
case 'c': return SQMOD_SKIN_UNDERCOVER_COP_C;
case '4':
case 'd': return SQMOD_SKIN_UNDERCOVER_COP_D;
case '5':
case 'e': return SQMOD_SKIN_UNDERCOVER_COP_E;
case '6':
case 'f': return SQMOD_SKIN_UNDERCOVER_COP_F;
}
// [V]ercetti guy (#1|A)/(#2|B)
case 'v':
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_VERCETTI_GUY_A;
case '2':
case 'b': return SQMOD_SKIN_VERCETTI_GUY_B;
}
// [W]aitress (#1|A)/(#2|B)
case 'w':
switch (d)
{
case '1':
case 'a': return SQMOD_SKIN_WAITRESS_A;
case '2':
case 'b': return SQMOD_SKIN_WAITRESS_B;
}
// Default to unknown
default: return SQMOD_UNKNOWN;
}
}
// ------------------------------------------------------------------------------------------------
bool IsSkinValid(Int32 id)
{
CSStr name = GetSkinName(id);
return (name && *name != '\0');
}
} // Namespace:: SqMod

32
module/Misc/Player.hpp Normal file
View File

@@ -0,0 +1,32 @@
#ifndef _MISC_PLAYER_HPP_
#define _MISC_PLAYER_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the name associated with a skin model identifier.
*/
CCStr GetSkinName(Uint32 id);
/* ------------------------------------------------------------------------------------------------
* Modify the name associated with a skin model identifier.
*/
void SetSkinName(Uint32 id, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Convert a vehicle model name to a skin model identifier.
*/
Int32 GetSkinID(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* See whether the specified skin model identifier is valid.
*/
bool IsSkinValid(Int32 id);
} // Namespace:: SqMod
#endif // _MISC_PLAYER_HPP_

168
module/Misc/Register.cpp Normal file
View File

@@ -0,0 +1,168 @@
// ------------------------------------------------------------------------------------------------
#include "Core.hpp"
#include "Base/Shared.hpp"
#include "Base/Color3.hpp"
#include "Base/Vector2.hpp"
#include "Base/Vector3.hpp"
#include "Entity/Player.hpp"
#include "Library/Numeric/LongInt.hpp"
// ------------------------------------------------------------------------------------------------
#include "Misc/Functions.hpp"
#include "Misc/Model.hpp"
#include "Misc/Player.hpp"
#include "Misc/Vehicle.hpp"
#include "Misc/Weapon.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern SQInteger Player_FindAuto(HSQUIRRELVM vm);
extern SQInteger Player_ExistsAuto(HSQUIRRELVM vm);
// ------------------------------------------------------------------------------------------------
extern void Register_Broadcast(HSQUIRRELVM vm);
// ================================================================================================
void Register_Misc(HSQUIRRELVM vm)
{
Table srvns(vm);
srvns
.FmtFunc(_SC("SendLogMessage"), &SendLogMessage)
.Func(_SC("GetVersion"), &GetServerVersion)
.Func(_SC("GetSettings"), &GetServerSettings)
.Func(_SC("GetNumberOfPlugins"), &GetNumberOfPlugins)
.Func(_SC("GetPluginInfo"), &GetPluginInfo)
.FmtFunc(_SC("FindPlugin"), &FindPlugin)
.FmtFunc(_SC("SendPluginCommand"), &SendPluginCommand)
.Func(_SC("GetTime"), &GetTime)
.Func(_SC("GetLastError"), &GetLastError)
.Func(_SC("GetPluginVersion"), &GetPluginVersion)
.Func(_SC("GetPluginVersionStr"), &GetPluginVersionStr)
.Func(_SC("GetPluginName"), &GetPluginName)
.Func(_SC("GetPluginAuthor"), &GetPluginAuthor)
.Func(_SC("GetPluginID"), &GetPluginID)
.Func(_SC("GetServerPort"), &GetServerPort)
.Func(_SC("GetServerFlags"), &GetServerFlags)
.Func(_SC("GetMaxPlayers"), &GetMaxPlayers)
.Func(_SC("SetMaxPlayers"), &SetMaxPlayers)
.Func(_SC("GetServerName"), &GetServerName)
.FmtFunc(_SC("SetServerName"), &SetServerName)
.Func(_SC("GetPassword"), &GetServerPassword)
.FmtFunc(_SC("SetPassword"), &SetServerPassword)
.Func(_SC("GetGameModeText"), &GetGameModeText)
.FmtFunc(_SC("SetGameModeText"), &SetGameModeText)
.FmtFunc(_SC("CreateRadioStream"), &CreateRadioStream)
.FmtFunc(_SC("CreateRadioStreamEx"), &CreateRadioStreamEx)
.Func(_SC("RemoveRadioStream"), &RemoveRadioStream)
.Func(_SC("Shutdown"), &ShutdownServer)
.Func(_SC("GetOption"), &GetServerOption)
.Func(_SC("SetOption"), &SetServerOption)
.Func(_SC("SetOptionEx"), &SetServerOptionEx)
.Func(_SC("GetWorldBounds"), &GetWorldBounds)
.Func(_SC("SetWorldBounds"), &SetWorldBounds)
.Func(_SC("SetWorldBoundsEx"), &SetWorldBoundsEx)
.Func(_SC("GetWastedSettings"), &GetWastedSettings)
.Func(_SC("SetWastedSettings"), &SetWastedSettings)
.Func(_SC("GetTimeRate"), &GetTimeRate)
.Func(_SC("SetTimeRate"), &SetTimeRate)
.Func(_SC("GetHour"), &GetHour)
.Func(_SC("SetHour"), &SetHour)
.Func(_SC("GetMinute"), &GetMinute)
.Func(_SC("SetMinute"), &SetMinute)
.Func(_SC("GetWeather"), &GetWeather)
.Func(_SC("SetWeather"), &SetWeather)
.Func(_SC("GetGravity"), &GetGravity)
.Func(_SC("SetGravity"), &SetGravity)
.Func(_SC("GetGameSpeed"), &GetGameSpeed)
.Func(_SC("SetGameSpeed"), &SetGameSpeed)
.Func(_SC("GetWaterLevel"), &GetWaterLevel)
.Func(_SC("SetWaterLevel"), &SetWaterLevel)
.Func(_SC("GetMaximumFlightAltitude"), &GetMaximumFlightAltitude)
.Func(_SC("SetMaximumFlightAltitude"), &SetMaximumFlightAltitude)
.Func(_SC("GetKillCommandDelay"), &GetKillCommandDelay)
.Func(_SC("SetKillCommandDelay"), &SetKillCommandDelay)
.Func(_SC("GetVehiclesForcedRespawnHeight"), &GetVehiclesForcedRespawnHeight)
.Func(_SC("SetVehiclesForcedRespawnHeight"), &SetVehiclesForcedRespawnHeight)
.Func(_SC("CreateExplosion"), &CreateExplosion)
.Func(_SC("CreateExplosionEx"), &CreateExplosionEx)
.Func(_SC("PlaySound"), &PlaySound)
.Func(_SC("PlaySoundEx"), &PlaySoundEx)
.Func(_SC("PlaySoundForWorld"), &PlaySoundForWorld)
.Func(_SC("HideMapObject"), &HideMapObject)
.Func(_SC("HideMapObjectEx"), &HideMapObjectEx)
.Func(_SC("HideMapObjectRaw"), &HideMapObjectRaw)
.Func(_SC("ShowMapObject"), &ShowMapObject)
.Func(_SC("ShowMapObjectEx"), &ShowMapObjectEx)
.Func(_SC("ShowMapObjectRaw"), &ShowMapObjectRaw)
.Func(_SC("ShowAllMapObjects"), &ShowAllMapObjects)
.Func(_SC("GetWeaponDataValue"), &GetWeaponDataValue)
.Func(_SC("SetWeaponDataValue"), &SetWeaponDataValue)
.Func(_SC("ResetWeaponDataValue"), &ResetWeaponDataValue)
.Func(_SC("IsWeaponDataValueModified"), &IsWeaponDataValueModified)
.Func(_SC("ResetWeaponData"), &ResetWeaponData)
.Func(_SC("ResetAllWeaponData"), &ResetAllWeaponData)
.Func(_SC("AddPlayerClass"), &AddPlayerClass)
.Func(_SC("SetSpawnPlayerPosition"), &SetSpawnPlayerPosition)
.Func(_SC("SetSpawnCameraPosition"), &SetSpawnCameraPosition)
.Func(_SC("SetSpawnCameraLookAt"), &SetSpawnCameraLookAt)
.Func(_SC("SetSpawnPlayerPositionEx"), &SetSpawnPlayerPositionEx)
.Func(_SC("SetSpawnCameraPositionEx"), &SetSpawnCameraPositionEx)
.Func(_SC("SetSpawnCameraLookAtEx"), &SetSpawnCameraLookAtEx)
.FmtFunc(_SC("BanIP"), &BanIP)
.FmtFunc(_SC("UnbanIP"), &UnbanIP)
.FmtFunc(_SC("IsIPBanned"), &IsIPBanned)
.FmtFunc(_SC("GetPlayerIdFromName"), &GetPlayerIdFromName)
.Func(_SC("IsPlayerConnected"), &IsPlayerConnected)
.Func(_SC("ForceAllSelect"), &ForceAllSelect)
.Func(_SC("CheckEntityExists"), &CheckEntityExists)
.Func(_SC("GetDistrictName"), &GetDistrictName)
.Func(_SC("GetDistrictNameEx"), &GetDistrictNameEx)
.Func(_SC("GetFallTimer"), &GetFallTimer)
.Func(_SC("SetFallTimer"), &SetFallTimer)
#if SQMOD_SDK_LEAST(2, 1)
.Func(_SC("GetNetworkStatisticsF"), &GetNetworkStatisticsF)
.Func(_SC("GetNetworkStatisticsI"), &GetNetworkStatisticsI)
#endif
; // Uggly? I know. But does the job.
RootTable(vm).Bind(_SC("SqServer"), srvns);
RootTable(vm)
.SquirrelFunc(_SC("FindPlayer"), &Player_FindAuto)
.SquirrelFunc(_SC("PlayerExists"), &Player_ExistsAuto)
.Func(_SC("GetKeyCodeName"), &GetKeyCodeName)
.FmtFunc(_SC("SetKeyCodeName"), &SetKeyCodeName)
.Func(_SC("GetModelName"), &GetModelName)
.FmtFunc(_SC("SetModelName"), &SetModelName)
.Func(_SC("IsModelWeapon"), &IsModelWeapon)
.Func(_SC("IsModelActuallyWeapon"), &IsModelActuallyWeapon)
.Func(_SC("GetSkinName"), &GetSkinName)
.FmtFunc(_SC("SetSkinName"), &SetSkinName)
.FmtFunc(_SC("GetSkinID"), &GetSkinID)
.Func(_SC("IsSkinValid"), &IsSkinValid)
.Func(_SC("GetAutomobileName"), &GetAutomobileName)
.FmtFunc(_SC("SetAutomobileName"), &SetAutomobileName)
.FmtFunc(_SC("GetAutomobileID"), &GetAutomobileID)
.Func(_SC("IsAutomobileValid"), &IsAutomobileValid)
.Func(_SC("GetWeaponSlot"), &GetWeaponSlot)
.Func(_SC("GetWeaponName"), &GetWeaponName)
.FmtFunc(_SC("SetWeaponName"), &SetWeaponName)
.Func(_SC("GetCustomWeaponNamePoolSize"), &GetCustomWeaponNamePoolSize)
.Func(_SC("ClearCustomWeaponNamePool"), &ClearCustomWeaponNamePool)
.FmtFunc(_SC("GetWeaponID"), &GetWeaponID)
.Func(_SC("IsWeaponValid"), &IsWeaponValid)
.Func(_SC("WeaponToModel"), &WeaponToModel)
.Func(_SC("IsWeaponNatural"), &IsWeaponNatural)
.Func(_SC("PlaySound"), &PlaySound)
.Func(_SC("PlaySoundEx"), &PlaySoundEx)
.Func(_SC("PlaySoundForWorld"), &PlaySoundForWorld)
.Func(_SC("CreateExplosion"), &CreateExplosion)
.Func(_SC("CreateExplosionEx"), &CreateExplosionEx);
Register_Broadcast(vm);
}
} // Namespace:: SqMod

362
module/Misc/Routine.cpp Normal file
View File

@@ -0,0 +1,362 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Routine.hpp"
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqRoutineBase"))
// ------------------------------------------------------------------------------------------------
Routine::Time Routine::s_Last = 0;
Routine::Time Routine::s_Prev = 0;
Routine::Interval Routine::s_Intervals[SQMOD_MAX_ROUTINES];
Routine::Instance Routine::s_Instances[SQMOD_MAX_ROUTINES];
// ------------------------------------------------------------------------------------------------
void Routine::Process()
{
// Is this the first call?
if (s_Last == 0)
{
s_Last = Chrono::GetCurrentSysTime();
// We'll do it text time
return;
}
// Backup the last known time-stamp
s_Prev = s_Last;
// Get the current time-stamp
s_Last = Chrono::GetCurrentSysTime();
// Calculate the elapsed time
const Int32 delta = Int32((s_Last - s_Prev) / 1000L);
// Process all active routines
for (Interval * itr = s_Intervals; itr != (s_Intervals + SQMOD_MAX_ROUTINES); ++itr)
{
// Is this routine valid?
if (*itr)
{
// Decrease the elapsed time
(*itr) -= delta;
// Have we completed the routine interval?
if ((*itr) <= 0)
{
// Execute and reset the elapsed time
(*itr) = s_Instances[itr - s_Intervals].Execute();
}
}
}
}
// ------------------------------------------------------------------------------------------------
void Routine::Initialize()
{
std::memset(s_Intervals, 0, sizeof(s_Intervals));
}
// ------------------------------------------------------------------------------------------------
void Routine::Deinitialize()
{
// Release any script resources that the routines might store
for (auto & r : s_Instances)
{
r.Terminate();
}
}
// ------------------------------------------------------------------------------------------------
SQInteger Routine::Create(HSQUIRRELVM vm)
{
// Locate the identifier of a free slot
const SQInteger slot = FindUnused();
// See if we have where to store this routine
if (slot < 0)
{
return sq_throwerror(vm, "Reached the maximum number of active routines");
}
// Grab the top of the stack
const SQInteger top = sq_gettop(vm);
// See if too many arguments were specified
if (top >= 20) /* 5 base + 14 parameters = 19 */
{
return sq_throwerror(vm, "Too many parameters specified");
}
// Was there was an environment specified?
else if (top <= 1)
{
return sq_throwerror(vm, "Missing routine environment");
}
// Was there was a callback specified?
else if (top <= 2)
{
return sq_throwerror(vm, "Missing routine callback");
}
// Validate the callback type
else if (sq_gettype(vm, 3) != OT_CLOSURE && sq_gettype(vm, 3) != OT_NATIVECLOSURE)
{
return sq_throwerror(vm, "Invalid callback type");
}
SQRESULT res = SQ_OK;
// Prepare an object for the environment
HSQOBJECT env;
// Get the type of the environment object
const SQObjectType etype = sq_gettype(vm, 2);
// Whether to default to the root table
bool use_root = etype == OT_NULL;
// Is the specified environment a boolean (true) value?
if (etype == OT_STRING)
{
// Attempt to generate the string value
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc()))
{
return val.mRes; // Propagate the error!
}
// If the string is empty or "root" then we use the root table
else if (!val.mLen || sqmod_stricmp(val.mPtr, "root") == 0)
{
use_root = true;
}
// If the string is "self" then we leave it null and default to self
else if (sqmod_stricmp(val.mPtr, "self") == 0)
{
sq_resetobject(&env); // Make sure environment is null
use_root = false; // Just in case
}
}
// Is the specified environment a null value?
if (use_root)
{
// Preserve the stack state
const StackGuard sg(vm);
// Push the root table on the stack
sq_pushroottable(vm);
// Attempt to retrieve the table object
res = sq_getstackobj(vm, -1, &env);
}
// Should we treat it as a valid environment object?
else if (etype != OT_STRING)
{
sq_getstackobj(vm, 2, &env); // Just retrieve the specified environment
}
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Prepare an object for the function
HSQOBJECT func;
// Fetch the specified callback object
res = sq_getstackobj(vm, 3, &func);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// The number of iterations and interval to execute the routine
SQInteger intrv = 0, itr = 0;
// Was there an interval specified?
if (top > 3)
{
// Grab the interval from the stack
res = sq_getinteger(vm, 4, &intrv);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
}
// Was there a number of iterations specified?
if (top > 4)
{
// Grab the iterations from the stack
res = sq_getinteger(vm, 5, &itr);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
}
// Attempt to create a routine instance
try
{
ClassType< Routine >::PushInstance(vm, new Routine());
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, "Unable to create the routine instance");
}
// Prepare an object for the routine
HSQOBJECT obj;
// Fetch the created routine object
res = sq_getstackobj(vm, -1, &obj);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// At this point we can grab a reference to our slot
Instance & inst = s_Instances[slot];
// Were there any arguments specified?
if (top > 5)
{
// Grab a pointer to the arguments array
Argument * args = inst.mArgv;
// Reset the argument counter
inst.mArgc = 0;
// Grab the specified arguments from the stack
for (SQInteger i = 6; i <= top; ++i)
{
res = sq_getstackobj(vm, i, &(args[inst.mArgc].mObj));
// Validate the result
if (SQ_FAILED(res))
{
// Clear previous arguments
inst.Clear();
// Propagate the error
return res;
}
// Keep a strong reference to the argument
sq_addref(vm, &(args[inst.mArgc].mObj));
// Increase the argument counter
++inst.mArgc;
}
}
// Attempt to retrieve the routine from the stack and associate it with the slot
try
{
Var< Routine * >(vm, -1).value->m_Slot = ConvTo< Uint32 >::From(slot);
}
catch (const Sqrat::Exception & e)
{
// Clear extracted arguments
inst.Clear();
// Now it's safe to throw the error
return sq_throwerror(vm, "Unable to create the routine instance");
}
// Alright, at this point we can initialize the slot
inst.Init(env, func, obj, intrv, itr);
// Now initialize the timer
s_Intervals[slot] = intrv;
// We have the created routine on the stack, so let's return it
return 1;
}
// ------------------------------------------------------------------------------------------------
bool Routine::IsWithTag(StackStrF & tag)
{
// Is the specified tag valid?
if (tag.mPtr != nullptr)
{
// Iterate routine list
for (const auto & r : s_Instances)
{
if (!r.mInst.IsNull() && r.mTag.compare(tag.mPtr) == 0)
{
return true; // Yup, we're doing this
}
}
}
// Unable to find such routine
return false;
}
// ------------------------------------------------------------------------------------------------
bool Routine::TerminateWithTag(StackStrF & tag)
{
// Is the specified tag valid?
if (tag.mPtr != nullptr)
{
// Iterate routine list
for (auto & r : s_Instances)
{
if (!r.mInst.IsNull() && r.mTag.compare(tag.mPtr) == 0)
{
r.Terminate(); // Yup, we're doing this
return true; // A routine was terminated
}
}
}
// Unable to find such routine
return false;
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to process routines.
*/
void ProcessRoutines()
{
Routine::Process();
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to initialize routines.
*/
void InitializeRoutines()
{
Routine::Initialize();
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to terminate routines.
*/
void TerminateRoutines()
{
Routine::Deinitialize();
}
// ================================================================================================
void Register_Routine(HSQUIRRELVM vm)
{
RootTable(vm).Bind(Typename::Str,
Class< Routine, NoConstructor< Routine > >(vm, Typename::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Routine::ToString)
// Properties
.Prop(_SC("Tag"), &Routine::GetTag, &Routine::SetTag)
.Prop(_SC("Env"), &Routine::GetEnv, &Routine::SetEnv)
.Prop(_SC("Func"), &Routine::GetFunc, &Routine::SetFunc)
.Prop(_SC("Data"), &Routine::GetData, &Routine::SetData)
.Prop(_SC("Interval"), &Routine::GetInterval, &Routine::SetInterval)
.Prop(_SC("Iterations"), &Routine::GetIterations, &Routine::SetIterations)
.Prop(_SC("Suspended"), &Routine::GetSuspended, &Routine::SetSuspended)
.Prop(_SC("Quiet"), &Routine::GetQuiet, &Routine::SetQuiet)
.Prop(_SC("Endure"), &Routine::GetEndure, &Routine::SetEndure)
.Prop(_SC("Arguments"), &Routine::GetArguments)
// Member Methods
.FmtFunc(_SC("SetTag"), &Routine::ApplyTag)
.Func(_SC("SetData"), &Routine::ApplyData)
.Func(_SC("SetInterval"), &Routine::ApplyInterval)
.Func(_SC("SetIterations"), &Routine::ApplyIterations)
.Func(_SC("SetSuspended"), &Routine::ApplySuspended)
.Func(_SC("SetQuiet"), &Routine::AppplyQuiet)
.Func(_SC("SetEndure"), &Routine::ApplyEndure)
.Func(_SC("Terminate"), &Routine::Terminate)
.Func(_SC("GetArgument"), &Routine::GetArgument)
.Func(_SC("DropEnv"), &Routine::DropEnv)
);
// Global functions
RootTable(vm).SquirrelFunc(_SC("SqRoutine"), &Routine::Create);
RootTable(vm).FmtFunc(_SC("SqFindRoutineByTag"), &Routine::FindByTag);
RootTable(vm).FmtFunc(_SC("SqIsRoutineWithTag"), &Routine::IsWithTag);
RootTable(vm).FmtFunc(_SC("SqTerminateRoutineWithTag"), &Routine::TerminateWithTag);
}
} // Namespace:: SqMod

644
module/Misc/Routine.hpp Normal file
View File

@@ -0,0 +1,644 @@
#ifndef _ROUTINE_HPP_
#define _ROUTINE_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Execute callbacks after specific intervals of time.
*/
class Routine
{
public:
/* --------------------------------------------------------------------------------------------
* Simplify future changes to a single point of change.
*/
typedef Int64 Time;
typedef SQInteger Interval;
typedef Uint32 Iterator;
typedef LightObj Argument;
private:
/* --------------------------------------------------------------------------------------------
* Structure that represents an active routine and keeps track of the routine information.
*/
struct Instance
{
// ----------------------------------------------------------------------------------------
LightObj mEnv; // A reference to the managed environment object.
LightObj mFunc; // A reference to the managed function object.
LightObj mInst; // Reference to the routine associated with this instance.
LightObj mData; // A reference to the arbitrary data associated with this instance.
String mTag; // An arbitrary string which represents the tag.
Iterator mIterations; // Number of iterations before self destruct.
Interval mInterval; // Interval between routine invocations.
bool mSuspended; // Whether this instance is allowed to receive calls.
bool mQuiet; // Whether this instance is allowed to handle errors.
bool mEndure; // Whether this instance is allowed to terminate itself on errors.
Uint8 mArgc; // The number of arguments that the routine must forward.
Argument mArgv[14]; // The arguments that the routine must forward.
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
Instance()
: mEnv()
, mFunc()
, mInst()
, mData()
, mTag()
, mIterations(0)
, mInterval(0)
, mSuspended(false)
, mQuiet(ErrorHandling::IsEnabled())
, mEndure(false)
, mArgc(0)
, mArgv()
{
/* ... */
}
/* ----------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Instance(const Instance & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Instance(Instance && o) = delete;
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~Instance()
{
Terminate();
}
/* ----------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Instance & operator = (const Instance & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Instance & operator = (Instance && o) = delete;
/* ----------------------------------------------------------------------------------------
* Initializes the routine parameters. (assumes previous values are already released)
*/
void Init(HSQOBJECT & env, HSQOBJECT & func, HSQOBJECT & inst, Interval intrv, Iterator itr)
{
// Initialize the callback objects
if (!sq_isnull(env))
{
mEnv = LightObj(env);
}
if (!sq_isnull(func))
{
mFunc = LightObj(func);
}
// Associate with the routine instance
if (!sq_isnull(inst))
{
mInst = LightObj(inst);
}
// Initialize the routine options
mIterations = itr;
mInterval = intrv;
}
/* ----------------------------------------------------------------------------------------
* Release managed script resources.
*/
void Release()
{
mEnv.Release();
mFunc.Release();
mInst.Release();
mData.Release();
mIterations = 0;
mInterval = 0;
mTag.clear();
}
/* ----------------------------------------------------------------------------------------
* Execute the managed routine.
*/
Interval Execute()
{
// is this even a valid routine?
if (mInst.IsNull())
{
return 0; // Dunno how we got here but it ends now
}
// Are we allowed to forward calls?
else if (!mSuspended)
{
// Grab the virtual machine once
HSQUIRRELVM vm = DefaultVM::Get();
// Push the function on the stack
sq_pushobject(vm, mFunc);
// Push the environment on the stack
if (!mEnv.IsNull())
{
sq_pushobject(vm, mEnv); // Push object
}
else
{
sq_pushobject(vm, mInst); // Push self
}
// Push function parameters, if any
for (Uint32 n = 0; n < mArgc; ++n)
{
sq_pushobject(vm, mArgv[n].mObj);
}
// Make the function call and store the result
const SQRESULT res = sq_call(vm, mArgc + 1, false, !mQuiet);
// Pop the callback object from the stack
sq_pop(vm, 1);
// Validate the result
if (SQ_FAILED(res))
{
// Should we endure the errors?
if (!mEndure)
{
Terminate(); // Destroy ourself on error
}
}
}
// Decrease the number of iterations if necessary
if (mIterations && (--mIterations) == 0)
{
Terminate(); // This routine reached the end of it's life
}
// Return the current interval
return mInterval;
}
/* ----------------------------------------------------------------------------------------
* Clear the arguments.
*/
void Clear()
{
// Now release the arguments
for (auto & a : mArgv)
{
a.Release();
}
// Reset the counter
mArgc = 0;
}
/* ----------------------------------------------------------------------------------------
* Terminate the routine.
*/
void Terminate()
{
Release();
Clear();
}
};
private:
// --------------------------------------------------------------------------------------------
static Time s_Last; // Last time point.
static Time s_Prev; // Previous time point.
static Interval s_Intervals[SQMOD_MAX_ROUTINES]; // List of intervals to be processed.
static Instance s_Instances[SQMOD_MAX_ROUTINES]; // List of routines to be executed.
private:
/* --------------------------------------------------------------------------------------------
* The index of the slot in the pool of active routines.
*/
Uint32 m_Slot;
protected:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Routine()
: m_Slot(SQMOD_MAX_ROUTINES)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Routine(Uint32 slot)
: m_Slot(slot)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Routine(const Routine & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Routine(Routine && o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Routine & operator = (const Routine & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Routine & operator = (Routine && o) = delete;
/* --------------------------------------------------------------------------------------------
* Find an unoccupied routine slot.
*/
static SQInteger FindUnused()
{
for (const auto & r : s_Instances)
{
if (r.mInst.IsNull())
{
return (&r - s_Instances); // Return the index of this element
}
}
// No available slot
return -1;
}
public:
/* --------------------------------------------------------------------------------------------
* Retrieve the number of used routine slots.
*/
static SQInteger GetUsed()
{
SQInteger n = 0;
// Iterate routine list
for (const auto & r : s_Instances)
{
if (!r.mInst.IsNull())
{
++n;
}
}
// Return the final count
return n;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of used routine slots.
*/
static const LightObj & FindByTag(StackStrF & tag)
{
// Is the specified tag valid?
if (!tag.mPtr)
{
STHROWF("Invalid routine tag");
}
// Iterate routine list
for (const auto & r : s_Instances)
{
if (!r.mInst.IsNull() && r.mTag.compare(tag.mPtr) == 0)
{
return r.mInst; // Return this routine instance
}
}
// Unable to find such routine
STHROWF("Unable to find a routine with tag (%s)", tag.mPtr);
// Should not reach this point but if it did, we have to return something
return s_Instances[SQMOD_MAX_ROUTINES].mInst; // Intentional Buffer overflow!
}
/* --------------------------------------------------------------------------------------------
* Check if a routine with a certain tag exists.
*/
static bool IsWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Check if a routine with a certain tag exists.
*/
static bool TerminateWithTag(StackStrF & tag);
/* --------------------------------------------------------------------------------------------
* Process all active routines and update elapsed time.
*/
static void Process();
/* --------------------------------------------------------------------------------------------
* Initialize all resources and prepare for startup.
*/
static void Initialize();
/* --------------------------------------------------------------------------------------------
* Release all resources and prepare for shutdown.
*/
static void Deinitialize();
/* --------------------------------------------------------------------------------------------
* Create a routine with the specified parameters.
*/
static SQInteger Create(HSQUIRRELVM vm);
protected:
/* --------------------------------------------------------------------------------------------
* See whether this routine is valid otherwise throw an exception.
*/
void Validate() const
{
if (m_Slot >= SQMOD_MAX_ROUTINES)
{
STHROWF("This instance does not reference a valid routine");
}
}
/* --------------------------------------------------------------------------------------------
* See whether this routine is valid otherwise throw an exception.
*/
Instance & GetValid() const
{
if (m_Slot >= SQMOD_MAX_ROUTINES)
{
STHROWF("This instance does not reference a valid routine");
}
// We know it's valid so let's return it
return s_Instances[m_Slot];
}
public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return (m_Slot >= SQMOD_MAX_ROUTINES) ? NullString() : s_Instances[m_Slot].mTag;
}
/* --------------------------------------------------------------------------------------------
* Terminate the routine.
*/
void Terminate()
{
GetValid().Terminate();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
const String & GetTag() const
{
return GetValid().mTag;
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
void SetTag(StackStrF & tag)
{
GetValid().mTag.assign(tag.mPtr, ClampMin(tag.mLen, 0));
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
Routine & ApplyTag(StackStrF & tag)
{
SetTag(tag);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the environment object.
*/
const LightObj & GetEnv() const
{
return GetValid().mEnv;
}
/* --------------------------------------------------------------------------------------------
* Modify the environment object.
*/
void SetEnv(const LightObj & env)
{
GetValid().mEnv = env.IsNull() ? LightObj(RootTable().GetObject()) : env;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the function object.
*/
const LightObj & GetFunc() const
{
return GetValid().mFunc;
}
/* --------------------------------------------------------------------------------------------
* Modify the function object.
*/
void SetFunc(const Function & func)
{
// Validate the specified
if (!sq_isclosure(func.GetFunc()) && !sq_isnativeclosure(func.GetFunc()))
{
STHROWF("Invalid callback type %s", SqTypeName(GetValid().mFunc.GetType()));
}
// Store the function without the environment
GetValid().mFunc = LightObj(func.GetFunc());
}
/* --------------------------------------------------------------------------------------------
* Retrieve the arbitrary user data object.
*/
const LightObj & GetData() const
{
return GetValid().mData;
}
/* --------------------------------------------------------------------------------------------
* Modify the arbitrary user data object.
*/
void SetData(const LightObj & data)
{
GetValid().mData = data;
}
/* --------------------------------------------------------------------------------------------
* Modify the arbitrary user data object.
*/
Routine & ApplyData(const LightObj & data)
{
SetData(data);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the execution interval.
*/
SQInteger GetInterval() const
{
return ConvTo< SQInteger >::From(GetValid().mInterval);
}
/* --------------------------------------------------------------------------------------------
* Modify the execution interval.
*/
void SetInterval(SQInteger itr)
{
GetValid().mInterval = ClampMin(ConvTo< Interval >::From(itr), static_cast< Interval >(0));
}
/* --------------------------------------------------------------------------------------------
* Modify the execution interval.
*/
Routine & ApplyInterval(SQInteger itr)
{
SetInterval(itr);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of iterations.
*/
SQInteger GetIterations() const
{
return ConvTo< SQInteger >::From(GetValid().mIterations);
}
/* --------------------------------------------------------------------------------------------
* Modify the number of iterations.
*/
void SetIterations(SQInteger itr)
{
GetValid().mIterations = ConvTo< Iterator >::From(itr);
}
/* --------------------------------------------------------------------------------------------
* Modify the number of iterations.
*/
Routine & ApplyIterations(SQInteger itr)
{
SetIterations(itr);
return *this;
}
/* --------------------------------------------------------------------------------------------
* See whether the routine is suspended.
*/
bool GetSuspended() const
{
return GetValid().mSuspended;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be suspended.
*/
void SetSuspended(bool toggle)
{
GetValid().mSuspended = toggle;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be suspended.
*/
Routine & ApplySuspended(bool toggle)
{
SetSuspended(toggle);
return *this;
}
/* --------------------------------------------------------------------------------------------
* See whether the routine is quite.
*/
bool GetQuiet() const
{
return GetValid().mQuiet;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be quiet.
*/
void SetQuiet(bool toggle)
{
GetValid().mQuiet = toggle;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should be quiet.
*/
Routine & AppplyQuiet(bool toggle)
{
SetQuiet(toggle);
return *this;
}
/* --------------------------------------------------------------------------------------------
* See whether the routine endures.
*/
bool GetEndure() const
{
return GetValid().mEndure;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should endure.
*/
void SetEndure(bool toggle)
{
GetValid().mEndure = toggle;
}
/* --------------------------------------------------------------------------------------------
* Set whether the routine should endure.
*/
Routine & ApplyEndure(bool toggle)
{
SetEndure(toggle);
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of arguments to be forwarded.
*/
SQInteger GetArguments() const
{
return ConvTo< SQInteger >::From(GetValid().mArgc);
}
/* --------------------------------------------------------------------------------------------
* Retrieve a certain argument.
*/
const Argument & GetArgument(SQInteger arg) const
{
// Cast the index to the proper value
Uint8 idx = ConvTo< Uint8 >::From(arg);
// Validate the specified index
if (idx >= 14)
{
STHROWF("The specified index is out of range: %u >= %u", idx, 14);
}
// Return the requested argument
return GetValid().mArgv[idx];
}
/* --------------------------------------------------------------------------------------------
* Release the environment object and default to self.
*/
void DropEnv()
{
GetValid().mEnv.Release();
}
};
} // Namespace:: SqMod
#endif // _ROUTINE_HPP_

1716
module/Misc/Signal.cpp Normal file

File diff suppressed because it is too large Load Diff

767
module/Misc/Signal.hpp Normal file
View File

@@ -0,0 +1,767 @@
#ifndef _SIGNAL_HPP_
#define _SIGNAL_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <vector>
#include <utility>
#include <algorithm>
#include <functional>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
struct Signal;
struct SignalWrapper;
/* ------------------------------------------------------------------------------------------------
* Class used to deliver events to one or more listeners.
*/
struct Signal
{
friend class SignalWrapper;
// --------------------------------------------------------------------------------------------
typedef unsigned int SizeType; // Type of value used to represent sizes and/or indexes.
// --------------------------------------------------------------------------------------------
enum { SMB_SIZE = 8 };
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Signal();
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
explicit Signal(const char * name)
: Signal(String(name))
{
//...
}
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
explicit Signal(const String & name)
: Signal(String(name))
{
//...
}
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Signal(String && name);
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
Signal(const Signal & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
Signal(Signal && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Signal();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
Signal & operator = (const Signal & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
Signal & operator = (Signal && o) = delete;
protected:
/* --------------------------------------------------------------------------------------------
* Adjust the internal buffer size if necessary.
*/
bool AdjustSlots(SizeType capacity);
/* --------------------------------------------------------------------------------------------
* Structure responsible for storing information about a slot.
*/
struct Slot {
SQHash mThisHash; // The hash of the specified environment.
SQHash mFuncHash; // The hash of the specified callback.
HSQOBJECT mThisRef; // The specified script environment.
HSQOBJECT mFuncRef; // The specified script callback.
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
Slot()
: mThisHash(0)
, mFuncHash(0)
, mThisRef()
, mFuncRef()
{
sq_resetobject(&mThisRef);
sq_resetobject(&mFuncRef);
}
/* ----------------------------------------------------------------------------------------
* Forwarding constructor.
*/
Slot(Object & env, Function & func)
: Slot(env.GetObject(), func.GetFunc())
{
/* ... */
}
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
Slot(HSQOBJECT & env, HSQOBJECT & func)
: mThisHash(0)
, mFuncHash(0)
, mThisRef(env)
, mFuncRef(func)
{
HSQUIRRELVM vm = DefaultVM::Get();
// Remember the current stack size
const StackGuard sg(vm);
// Is there an explicit environment?
if (!sq_isnull(mThisRef))
{
// Keep a reference to this environment
sq_addref(vm, &mThisRef);
// Push the environment on the stack
sq_pushobject(vm, mThisRef);
// Grab the hash of the environment object
mThisHash = sq_gethash(vm, -1);
}
// Is there an explicit function?
if (!sq_isnull(mFuncRef))
{
// Keep a reference to this function
sq_addref(vm, &mFuncRef);
// Push the callback on the stack
sq_pushobject(vm, mFuncRef);
// Grab the hash of the callback object
mFuncHash = sq_gethash(vm, -1);
}
}
/* ----------------------------------------------------------------------------------------
* Base constructor.
*/
Slot(HSQOBJECT & env, HSQOBJECT & func, SQHash envh, SQHash funch)
: mThisHash(envh)
, mFuncHash(funch)
, mThisRef(env)
, mFuncRef(func)
{
}
/* ----------------------------------------------------------------------------------------
* Copy constructor.
*/
Slot(const Slot & o)
: mThisHash(o.mThisHash)
, mFuncHash(o.mFuncHash)
, mThisRef(o.mThisRef)
, mFuncRef(o.mFuncRef)
{
// Track reference
if (mFuncHash != 0)
{
sq_addref(DefaultVM::Get(), &mThisRef);
sq_addref(DefaultVM::Get(), &mFuncRef);
}
}
/* ----------------------------------------------------------------------------------------
* Move constructor.
*/
Slot(Slot && o)
: mThisHash(o.mThisHash)
, mFuncHash(o.mFuncHash)
, mThisRef(o.mThisRef)
, mFuncRef(o.mFuncRef)
{
// Take ownership
sq_resetobject(&o.mThisRef);
sq_resetobject(&o.mFuncRef);
}
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~Slot()
{
Release();
}
/* ----------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Slot & operator = (const Slot & o)
{
if (this != &o)
{
// Release current resources, if any
Release();
// Replicate data
mThisHash = o.mThisHash;
mFuncHash = o.mFuncHash;
mThisRef = o.mThisRef;
mFuncRef = o.mFuncRef;
// Track reference
sq_addref(DefaultVM::Get(), &const_cast< HSQOBJECT & >(o.mThisRef));
sq_addref(DefaultVM::Get(), &const_cast< HSQOBJECT & >(o.mFuncRef));
}
return *this;
}
/* ----------------------------------------------------------------------------------------
* Move assignment operator.
*/
Slot & operator = (Slot && o)
{
if (this != &o)
{
// Release current resources, if any
Release();
// Replicate data
mThisHash = o.mThisHash;
mFuncHash = o.mFuncHash;
mThisRef = o.mThisRef;
mFuncRef = o.mFuncRef;
// Take ownership
sq_resetobject(&o.mThisRef);
sq_resetobject(&o.mFuncRef);
}
return *this;
}
/* ----------------------------------------------------------------------------------------
* Equality comparison operator.
*/
bool operator == (const Slot & o) const
{
return (mThisHash == o.mThisHash) && (mFuncHash == o.mFuncHash);
}
/* ----------------------------------------------------------------------------------------
* Inequality comparison operator.
*/
bool operator != (const Slot & o) const
{
return (mThisHash != o.mThisHash) || (mFuncHash != o.mFuncHash);
}
/* ----------------------------------------------------------------------------------------
* Release managed script resources.
*/
bool Available() const
{
return (mFuncHash == 0);
}
/* ----------------------------------------------------------------------------------------
* Release managed script resources.
*/
void Release()
{
// Should we release any environment object?
if (mThisHash != 0)
{
sq_release(DefaultVM::Get(), &mThisRef);
sq_resetobject(&mThisRef);
// Also reset the hash
mThisHash = 0;
}
// Should we release any callback object?
if (mFuncHash != 0)
{
sq_release(DefaultVM::Get(), &mFuncRef);
sq_resetobject(&mFuncRef);
// Also reset the hash
mFuncHash = 0;
}
}
/* ----------------------------------------------------------------------------------------
* Swap the values of two slots.
*/
void Swap(Slot & s)
{
// Swap the environment hash
SQHash h = mThisHash;
mThisHash = s.mThisHash;
s.mThisHash = h;
// Swap the callback hash
h = mFuncHash;
mFuncHash = s.mFuncHash;
s.mFuncHash = h;
// Swap the environment object
HSQOBJECT o = mThisRef;
mThisRef = s.mThisRef;
s.mThisRef = o;
// Swap the callback object
o = mFuncRef;
mFuncRef = s.mFuncRef;
s.mFuncRef = o;
}
};
// --------------------------------------------------------------------------------------------
typedef Slot ValueType; // Value type used to represent a slot.
typedef ValueType & Reference; // Reference to the stored value type
typedef const ValueType & ConstReference; // Constant reference to the stored value type.
typedef ValueType * Pointer; // Pointer to the stored value type
typedef const ValueType * ConstPointer; // Constant pointer to the stored value type.
// --------------------------------------------------------------------------------------------
/// Execution scope used to adjust iterators when removing slots or adjusting the buffer.
struct Scope {
// ----------------------------------------------------------------------------------------
Pointer mItr; ///< Currently executed slot.
Pointer mEnd; ///< Where the execution ends.
Scope * mParent; ///< Previous execution scope.
Scope * mChild; ///< Next execution scope.
// ----------------------------------------------------------------------------------------
/// Default constructor.
Scope(Scope * parent, Pointer begin, Pointer end)
: mItr(begin), mEnd(end), mParent(parent), mChild(nullptr)
{
if (mParent != nullptr) mParent->mChild = this;
}
// ----------------------------------------------------------------------------------------
/// Destructor.
~Scope() {
if (mParent != nullptr) mParent->mChild = nullptr;
}
// ----------------------------------------------------------------------------------------
/// Adjust the iterators to account for the fact that the specified slot was removed.
void Descend(Pointer ptr);
/// Adjust the iterators to account for the fact that the specified slot is now leading.
void Lead(Pointer ptr);
/// Adjust the iterators to account for the fact that the specified slot is now tailing.
void Tail(Pointer ptr);
/// Adjust the iterators to finish the execution abruptly.
void Finish();
};
private:
// --------------------------------------------------------------------------------------------
SizeType m_Used; // The number of stored slots that are valid.
SizeType m_Size; // The size of the memory allocated for slots.
Pointer m_Slots; // Pointer to the memory containing the slots.
// --------------------------------------------------------------------------------------------
Scope * m_Scope; // Current execution state.
// --------------------------------------------------------------------------------------------
String m_Name; // The name that identifies this signal.
LightObj m_Data; // User data associated with this instance.
// --------------------------------------------------------------------------------------------
ValueType m_SMB[SMB_SIZE]{}; // Small buffer optimization.
public:
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return m_Name;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated user data.
*/
LightObj & GetData()
{
return m_Data;
}
/* --------------------------------------------------------------------------------------------
* Modify the associated user data.
*/
void SetData(LightObj & data)
{
m_Data = data;
}
/* --------------------------------------------------------------------------------------------
* The number of slots connected to the signal.
*/
SQInteger GetUsed() const
{
return static_cast< SQInteger >(m_Used);
}
/* --------------------------------------------------------------------------------------------
* Clear all slots connected to the signal.
*/
void ClearSlots();
/* --------------------------------------------------------------------------------------------
* See if there are any slots connected.
*/
bool IsEmpty() const
{
return (m_Used == 0);
}
protected:
/* --------------------------------------------------------------------------------------------
* Connect the specified slot to the signal.
*/
SQInteger Connect(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Connect the specified slot but not before disconnecting all other occurrences.
*/
SQInteger ConnectOnce(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Disconnect all occurrences of the specified slot from the signal.
*/
SQInteger Disconnect(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* See if the specified slot is connected to the signal.
*/
SQInteger Exists(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* See if the specified slot environment is connected to the signal.
*/
SQInteger ExistsThis(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* See if the specified slot callback is connected to the signal.
*/
SQInteger ExistsFunc(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Count all occurrences of the specified slot.
*/
SQInteger Count(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Count all occurrences of the specified slot environment.
*/
SQInteger CountThis(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Count all occurrences of the specified slot callback.
*/
SQInteger CountFunc(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot to the front.
*/
SQInteger Lead(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot environment to the front.
*/
SQInteger LeadThis(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot callback to the front.
*/
SQInteger LeadFunc(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot to the back.
*/
SQInteger Tail(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot environment to the back.
*/
SQInteger TailThis(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Move all occurrences of the specified slot callback to the back.
*/
SQInteger TailFunc(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Remove all occurrences of the specified slot.
*/
SQInteger Eliminate(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Remove all occurrences of the specified slot environment.
*/
SQInteger EliminateThis(SignalWrapper & w);
/* --------------------------------------------------------------------------------------------
* Remove all occurrences of the specified slot callback.
*/
SQInteger EliminateFunc(SignalWrapper & w);
public:
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Connect` method of this class.
*/
static SQInteger SqConnect(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `ConnectOnce` method of this class.
*/
static SQInteger SqConnectOnce(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Exists` method of this class.
*/
static SQInteger SqExists(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Disconnect` method of this class.
*/
static SQInteger SqDisconnect(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `ExistsThis` method of this class.
*/
static SQInteger SqExistsThis(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `ExistsFunc` method of this class.
*/
static SQInteger SqExistsFunc(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Count` method of this class.
*/
static SQInteger SqCount(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `CountThis` method of this class.
*/
static SQInteger SqCountThis(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `CountFunc` method of this class.
*/
static SQInteger SqCountFunc(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Lead` method of this class.
*/
static SQInteger SqLead(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `LeadThis` method of this class.
*/
static SQInteger SqLeadThis(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `LeadFunc` method of this class.
*/
static SQInteger SqLeadFunc(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Tail` method of this class.
*/
static SQInteger SqTail(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `TailThis` method of this class.
*/
static SQInteger SqTailThis(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `TailFunc` method of this class.
*/
static SQInteger SqTailFunc(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Eliminate` method of this class.
*/
static SQInteger SqEliminate(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `EliminateThis` method of this class.
*/
static SQInteger SqEliminateThis(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `EliminateFunc` method of this class.
*/
static SQInteger SqEliminateFunc(HSQUIRRELVM vm);
protected:
/* --------------------------------------------------------------------------------------------
* Emit the event to the connected slots.
*/
SQInteger Emit(HSQUIRRELVM vm, SQInteger top);
/* --------------------------------------------------------------------------------------------
* Emit the event to the connected slots and collect returned values.
*/
SQInteger Query(HSQUIRRELVM vm, SQInteger top);
/* --------------------------------------------------------------------------------------------
* Emit the event to the connected slots and see if they consume it.
*/
SQInteger Consume(HSQUIRRELVM vm, SQInteger top);
/* --------------------------------------------------------------------------------------------
* Emit the event to the connected slots and see if they approve it.
*/
SQInteger Approve(HSQUIRRELVM vm, SQInteger top);
/* --------------------------------------------------------------------------------------------
* Emit the event to the connected slots and see if they return something.
*/
SQInteger Request(HSQUIRRELVM vm, SQInteger top);
public:
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Emit` method of this class.
*/
static SQInteger SqEmit(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Query` method of this class.
*/
static SQInteger SqQuery(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Consume` method of this class.
*/
static SQInteger SqConsume(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Approve` method of this class.
*/
static SQInteger SqApprove(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Squirrel wrapper for the `Request` method of this class.
*/
static SQInteger SqRequest(HSQUIRRELVM vm);
protected:
// --------------------------------------------------------------------------------------------
typedef std::pair< std::size_t, SignalPair > SignalElement;
typedef std::vector< SignalElement > SignalPool;
typedef std::vector< Signal * > FreeSignals;
// --------------------------------------------------------------------------------------------
static SignalPool s_Signals; // List of all created signals.
static FreeSignals s_FreeSignals; // List of signals without a name.
/* --------------------------------------------------------------------------------------------
* Specialization for when there are no arguments given.
*/
void PushParameters()
{
//...
}
/* --------------------------------------------------------------------------------------------
* Specialization for when there's only one argument given/remaining.
*/
template < typename T > void PushParameters(T v)
{
Var< T >::push(DefaultVM::Get(), v);
}
/* --------------------------------------------------------------------------------------------
* Specialization for when there's more than one argument given.
*/
template < typename T, typename... Args > void PushParameters(T v, Args... args)
{
Var< T >::push(DefaultVM::Get(), v);
PushParameters(args...);
}
public:
/* --------------------------------------------------------------------------------------------
* Terminate all signal instances and release any script resources.
*/
static void Terminate();
/* --------------------------------------------------------------------------------------------
* Create a free signal without a specific name.
*/
static LightObj CreateFree();
/* --------------------------------------------------------------------------------------------
* Create a new signal with the specified name.
*/
static LightObj Create(StackStrF & name);
/* --------------------------------------------------------------------------------------------
* Remove the signal with the specified name.
*/
static void Remove(StackStrF & name);
/* --------------------------------------------------------------------------------------------
* Retrieve the signal with the specified name.
*/
static const LightObj & Fetch(StackStrF & name);
/* --------------------------------------------------------------------------------------------
* Emit a signal from the module.
*/
template < typename... Args > void operator () (Args&&... args)
{
// Are there any slots connected?
if (!m_Used) return;
// Enter a new execution scope
Scope scope(m_Scope, m_Slots, m_Slots + m_Used);
// Activate the current scope and create a guard to restore it
const AutoAssign< Scope * > aa(m_Scope, scope.mParent, &scope);
// Grab the default virtual machine
HSQUIRRELVM vm = DefaultVM::Get();
// Process the slots from this scope
while (scope.mItr != scope.mEnd)
{
// Grab a reference to the current slot
const Slot & slot = *(scope.mItr++);
// Push the callback object
sq_pushobject(vm, slot.mFuncRef);
// Is there an explicit environment?
if (slot.mThisHash == 0)
{
sq_pushroottable(vm);
}
else
{
sq_pushobject(vm, slot.mThisRef);
}
// Push the given parameters on the stack
PushParameters(args...);
// Make the function call and store the result
const SQRESULT res = sq_call(vm, 1 + sizeof...(Args), false, ErrorHandling::IsEnabled());
// Pop the callback object from the stack
sq_pop(vm, 1);
// Validate the result
if (SQ_FAILED(res))
{
SQTHROW(vm, LastErrorString(vm)); // Stop emitting signals
}
}
}
};
} // Namespace:: SqMod
#endif // _SIGNAL_HPP_

524
module/Misc/Tasks.cpp Normal file
View File

@@ -0,0 +1,524 @@
// ------------------------------------------------------------------------------------------------
#include "Tasks.hpp"
#include "Core.hpp"
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <utility>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqTask"))
// ------------------------------------------------------------------------------------------------
Tasks::Time Tasks::s_Last = 0;
Tasks::Time Tasks::s_Prev = 0;
Tasks::Interval Tasks::s_Intervals[SQMOD_MAX_TASKS];
Tasks::Task Tasks::s_Tasks[SQMOD_MAX_TASKS];
// ------------------------------------------------------------------------------------------------
void Tasks::Task::Init(HSQOBJECT & func, HSQOBJECT & inst, Interval intrv, Iterator itr, Int32 id, Int32 type)
{
// Initialize the callback hash
mHash = 0;
// Initialize the callback objects
mFunc = LightObj(func);
mInst = LightObj(inst);
// Initialize the task options
mIterations = itr;
mInterval = intrv;
// Initialize the entity information
mEntity = ConvTo< Int16 >::From(id);
mType = ConvTo< Uint8 >::From(type);
// Grab the virtual machine once
HSQUIRRELVM vm = DefaultVM::Get();
// Remember the current stack size
const StackGuard sg(vm);
// Is there a valid function?
if (!mFunc.IsNull())
{
// Push the callback on the stack
sq_pushobject(vm, mFunc);
// Grab the hash of the callback object
mHash = sq_gethash(vm, -1);
}
}
// ------------------------------------------------------------------------------------------------
void Tasks::Task::Release()
{
mHash = 0;
mTag.clear();
mFunc.Release();
mInst.Release();
mData.Release();
mIterations = 0;
mInterval = 0;
mEntity = -1;
mType = -1;
}
// ------------------------------------------------------------------------------------------------
Tasks::Interval Tasks::Task::Execute()
{
// Are we even a valid task?
if (INVALID_ENTITY(mEntity))
{
return 0; // Dunno how we got here but it ends now
}
// Grab the virtual machine once
HSQUIRRELVM vm = DefaultVM::Get();
// Push the function on the stack
sq_pushobject(vm, mFunc);
// Push the environment on the stack
sq_pushobject(vm, mSelf);
// Push function parameters, if any
for (Uint32 n = 0; n < mArgc; ++n)
{
sq_pushobject(vm, mArgv[n].mObj);
}
// Make the function call and store the result
const SQRESULT res = sq_call(vm, mArgc + 1, false, ErrorHandling::IsEnabled());
// Pop the callback object from the stack
sq_pop(vm, 1);
// Validate the result
if (SQ_FAILED(res))
{
Terminate(); // Destroy ourself on error
}
// Decrease the number of iterations if necessary
if (mIterations && (--mIterations) == 0)
{
Terminate(); // This routine reached the end of it's life
}
// Return the current interval
return mInterval;
}
// ------------------------------------------------------------------------------------------------
void Tasks::Process()
{
// Is this the first call?
if (s_Last == 0)
{
s_Last = Chrono::GetCurrentSysTime();
// We'll do it text time
return;
}
// Backup the last known time-stamp
s_Prev = s_Last;
// Get the current time-stamp
s_Last = Chrono::GetCurrentSysTime();
// Calculate the elapsed time
const Int32 delta = Int32((s_Last - s_Prev) / 1000L);
// Process all active tasks
for (Interval * itr = s_Intervals; itr != (s_Intervals + SQMOD_MAX_TASKS); ++itr)
{
// Is this task valid?
if (*itr)
{
// Decrease the elapsed time
(*itr) -= delta;
// Have we completed the routine interval?
if ((*itr) <= 0)
{
// Execute and reset the elapsed time
(*itr) = s_Tasks[itr - s_Intervals].Execute();
}
}
}
}
// ------------------------------------------------------------------------------------------------
void Tasks::Initialize()
{
std::memset(s_Intervals, 0, sizeof(s_Intervals));
// Transform all task instances to script objects
for (auto & t : s_Tasks)
{
// This is fine because they'll always outlive the virtual machine
t.mSelf = LightObj(&t);
}
}
// ------------------------------------------------------------------------------------------------
void Tasks::Register(HSQUIRRELVM vm)
{
RootTable(vm).Bind(Typename::Str,
Class< Task, NoDestructor< Task > >(vm, Typename::Str)
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Task::ToString)
// Properties
.Prop(_SC("Tag"), &Task::GetTag, &Task::SetTag)
.Prop(_SC("Entity"), &Task::GetInst)
.Prop(_SC("Func"), &Task::GetFunc, &Task::SetFunc)
.Prop(_SC("Data"), &Task::GetData, &Task::SetData)
.Prop(_SC("Interval"), &Task::GetInterval, &Task::SetInterval)
.Prop(_SC("Iterations"), &Task::GetIterations, &Task::SetIterations)
.Prop(_SC("Arguments"), &Task::GetArguments)
.Prop(_SC("Inst"), &Task::GetInst)
// Member Methods
.FmtFunc(_SC("SetTag"), &Task::SetTag)
.Func(_SC("Terminate"), &Task::Terminate)
.Func(_SC("GetArgument"), &Task::GetArgument)
// Static functions
.StaticFunc(_SC("Used"), &Tasks::GetUsed)
);
}
// ------------------------------------------------------------------------------------------------
void Tasks::Deinitialize()
{
// Release any script resources that the tasks might store
for (auto & t : s_Tasks)
{
t.Terminate();
t.mSelf.Release();
}
}
// ------------------------------------------------------------------------------------------------
LightObj & Tasks::FindEntity(Int32 id, Int32 type)
{
switch (type)
{
case ENT_BLIP: return Core::Get().GetBlip(id).mObj;
case ENT_CHECKPOINT: return Core::Get().GetCheckpoint(id).mObj;
case ENT_KEYBIND: return Core::Get().GetKeybind(id).mObj;
case ENT_OBJECT: return Core::Get().GetObject(id).mObj;
case ENT_PICKUP: return Core::Get().GetPickup(id).mObj;
case ENT_PLAYER: return Core::Get().GetPlayer(id).mObj;
case ENT_VEHICLE: return Core::Get().GetVehicle(id).mObj;
default: return NullLightObj();
}
}
// ------------------------------------------------------------------------------------------------
SQInteger Tasks::FindUnused()
{
for (const auto & t : s_Tasks)
{
if (INVALID_ENTITY(t.mEntity))
{
return (&t - s_Tasks); // Return the index of this element
}
}
// No available slot
return -1;
}
// ------------------------------------------------------------------------------------------------
SQInteger Tasks::Create(Int32 id, Int32 type, HSQUIRRELVM vm)
{
// Locate the identifier of a free slot
const SQInteger slot = FindUnused();
// See if we have where to store this task
if (slot < 0)
{
return sq_throwerror(vm, "Reached the maximum number of tasks");
}
// Grab the top of the stack
const SQInteger top = sq_gettop(vm);
// See if too many arguments were specified
if (top > 12) /* 4 base + 8 parameters = 12 */
{
return sq_throwerror(vm, "Too many parameters specified");
}
// Was there was a callback specified?
else if (top <= 1)
{
return sq_throwerror(vm, "Missing task callback");
}
// Validate the callback type
else if (sq_gettype(vm, 2) != OT_CLOSURE && sq_gettype(vm, 2) != OT_NATIVECLOSURE)
{
return sq_throwerror(vm, "Invalid callback type");
}
// Prepare an entity instance object
HSQOBJECT inst;
// Attempt to retrieve the entity instance
try
{
inst = FindEntity(id, type).GetObject();
}
catch (const std::exception & e)
{
return sq_throwerror(vm, e.what());
}
// Prepare the function object
HSQOBJECT func;
// Fetch the specified callback
SQRESULT res = sq_getstackobj(vm, 2, &func);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// The number of iterations and interval to execute the task
SQInteger intrv = 0, itr = 0;
// Was there an interval specified?
if (top > 2)
{
// Grab the interval from the stack
res = sq_getinteger(vm, 3, &intrv);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
}
// Was there a number of iterations specified?
if (top > 3)
{
// Grab the iterations from the stack
res = sq_getinteger(vm, 4, &itr);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
}
// At this point we can grab a reference to our slot
Task & task = s_Tasks[slot];
// Were there any arguments specified?
if (top > 4)
{
// Grab a pointer to the arguments array
Argument * args = task.mArgv;
// Reset the argument counter
task.mArgc = 0;
// Grab the specified arguments from the stack
for (SQInteger i = 5; i <= top; ++i)
{
res = sq_getstackobj(vm, i, &(args[task.mArgc].mObj));
// Validate the result
if (SQ_FAILED(res))
{
// Clear previous arguments
task.Clear();
// Propagate the error
return res;
}
// Keep a strong reference to the argument
sq_addref(vm, &(args[task.mArgc].mObj));
// Increase the argument counter
++task.mArgc;
}
}
// Alright, at this point we can initialize the slot
task.Init(func, inst, intrv, itr, id, type);
// Now initialize the timer
s_Intervals[slot] = intrv;
// Push the tag instance on the stack
sq_pushobject(vm, task.mSelf);
// Specify that this function returns a value
return 1;
}
// ------------------------------------------------------------------------------------------------
SQInteger Tasks::Find(Int32 id, Int32 type, SQInteger & pos, HSQUIRRELVM vm)
{
// Grab the top of the stack
const SQInteger top = sq_gettop(vm);
// Was there a callback specified?
if (top <= 1)
{
return sq_throwerror(vm, "Missing task callback");
}
SQRESULT res = SQ_OK;
// Grab the hash of the callback object
const SQHash chash = sq_gethash(vm, 2);
// Should we include the iterations in the criteria?
if (top > 3)
{
SQInteger intrv = 0;
// Grab the interval from the stack
res = sq_getinteger(vm, 3, &intrv);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Attempt to find the requested task
for (const auto & t : s_Tasks)
{
if (t.mHash == chash && t.mEntity == id && t.mType == type && t.mInterval == intrv)
{
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
}
}
}
// Should we include the interval in the criteria?
else if (top > 2)
{
SQInteger intrv = 0, sqitr = 0;
// Grab the interval from the stack
res = sq_getinteger(vm, 3, &intrv);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Grab the iterations from the stack
res = sq_getinteger(vm, 4, &sqitr);
// Validate the result
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Cast iterations to the right type
const Iterator itr = ConvTo< Iterator >::From(sqitr);
// Attempt to find the requested task
for (const auto & t : s_Tasks)
{
if (t.mHash == chash && t.mEntity == id && t.mType == type && t.mInterval == intrv && t.mIterations == itr)
{
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
}
}
}
else
{
// Attempt to find the requested task
for (const auto & t : s_Tasks)
{
if (t.mHash == chash && t.mEntity == id && t.mType == type)
{
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
}
}
}
// We could not find such task
return res;
}
// ------------------------------------------------------------------------------------------------
SQInteger Tasks::Remove(Int32 id, Int32 type, HSQUIRRELVM vm)
{
// Default to not found
SQInteger pos = -1;
// Perform a search
SQRESULT res = Find(id, type, pos, vm);
// Did the search failed?
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Did we find anything?
else if (pos < 0)
{
return sq_throwerror(vm, "Unable to locate such task");
}
else
{
// Release task resources
s_Tasks[pos].Terminate();
// Reset the timer
s_Intervals[pos] = 0;
}
// Specify that we don't return anything
return 0;
}
// ------------------------------------------------------------------------------------------------
SQInteger Tasks::Exists(Int32 id, Int32 type, HSQUIRRELVM vm)
{
// Default to not found
SQInteger pos = -1;
// Perform a search
SQRESULT res = Find(id, type, pos, vm);
// Did the search failed?
if (SQ_FAILED(res))
{
return res; // Propagate the error
}
// Push a boolean on whether this task was found
sq_pushbool(vm, pos >= 0);
// Specify that we're returning a value
return 1;
}
// ------------------------------------------------------------------------------------------------
const Tasks::Task & Tasks::FindByTag(Int32 id, Int32 type, StackStrF & tag)
{
// Attempt to find the requested task
for (const auto & t : s_Tasks)
{
if (t.mEntity == id && t.mType == type && t.mTag.compare(tag.mPtr) == 0)
{
return t; // Return this task instance
}
}
// Unable to find such task
STHROWF("Unable to find a task with tag (%s)", tag.mPtr);
// Should not reach this point but if it did, we have to return something
return s_Tasks[SQMOD_MAX_TASKS]; // Intentional Buffer overflow!
}
// ------------------------------------------------------------------------------------------------
void Tasks::Cleanup(Int32 id, Int32 type)
{
for (auto & t : s_Tasks)
{
if (t.mEntity == id && t.mType == type)
{
t.Terminate();
// Also disable the timer
s_Intervals[&t - s_Tasks] = 0;
}
}
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to process tasks.
*/
void ProcessTasks()
{
Tasks::Process();
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to initialize tasks.
*/
void InitializeTasks()
{
Tasks::Initialize();
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to register tasks.
*/
void RegisterTask(HSQUIRRELVM vm)
{
Tasks::Register(vm);
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to terminate tasks.
*/
void TerminateTasks()
{
Tasks::Deinitialize();
}
/* ------------------------------------------------------------------------------------------------
* Forward the call to cleanup certain tasks.
*/
void CleanupTasks(Int32 id, Int32 type)
{
Tasks::Cleanup(id, type);
}
} // Namespace:: SqMod

527
module/Misc/Tasks.hpp Normal file
View File

@@ -0,0 +1,527 @@
#ifndef _TASKS_HPP_
#define _TASKS_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Execute callbacks for specific entities after specific intervals of time.
*/
class Tasks
{
public:
/* --------------------------------------------------------------------------------------------
* Simplify future changes to a single point of change.
*/
typedef Int64 Time;
typedef SQInteger Interval;
typedef Uint32 Iterator;
typedef LightObj Argument;
private:
/* --------------------------------------------------------------------------------------------
* Structure that represents a task and keeps track of the task information.
*/
struct Task
{
// ----------------------------------------------------------------------------------------
SQHash mHash; // The hash of the referenced function object.
String mTag; // An arbitrary string which represents the tag.
LightObj mSelf; // A reference to `this`as a script object.
LightObj mFunc; // A reference to the managed function object.
LightObj mInst; // A reference to the associated entity object.
LightObj mData; // A reference to the arbitrary data associated with this instance.
Iterator mIterations; // Number of iterations before self destruct.
Interval mInterval; // Interval between task invocations.
Int16 mEntity; // The identifier of the entity to which is belongs.
Uint8 mType; // The type of the entity to which is belongs.
Uint8 mArgc; // The number of arguments that the task must forward.
Argument mArgv[8]; // The arguments that the task must forward.
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
Task()
: mHash(0)
, mTag()
, mSelf()
, mFunc()
, mInst()
, mData()
, mIterations(0)
, mInterval(0)
, mEntity(-1)
, mType(-1)
, mArgc(0)
, mArgv()
{
/* ... */
}
/* ----------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Task(const Task & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Task(Task && o) = delete;
/* ----------------------------------------------------------------------------------------
* Release managed script resources.
*/
~Task()
{
Terminate();
}
/* ----------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Task & operator = (const Task & o) = delete;
/* ----------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Task & operator = (Task && o) = delete;
/* ----------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
const String & ToString() const
{
return mTag;
}
/* ----------------------------------------------------------------------------------------
* Initializes the task parameters. (assumes previous values are already released)
*/
void Init(HSQOBJECT & inst, HSQOBJECT & func, Interval intrv, Iterator itr, Int32 id, Int32 type);
/* ----------------------------------------------------------------------------------------
* Release managed script resources.
*/
void Release();
/* ----------------------------------------------------------------------------------------
* Execute the managed task.
*/
Interval Execute();
/* ----------------------------------------------------------------------------------------
* Clear the arguments.
*/
void Clear()
{
// Now release the arguments
for (auto & a : mArgv)
{
a.Release();
}
// Reset the counter
mArgc = 0;
}
/* ----------------------------------------------------------------------------------------
* Terminate the task.
*/
void Terminate()
{
Release();
Clear();
}
/* ----------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
const String & GetTag() const
{
return mTag;
}
/* ----------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
void SetTag(StackStrF & tag)
{
mTag.assign(tag.mPtr, ClampMin(tag.mLen, 0));
}
/* ----------------------------------------------------------------------------------------
* Retrieve the instance to entity instance.
*/
const LightObj & GetInst() const
{
return mInst;
}
/* ----------------------------------------------------------------------------------------
* Retrieve the function object.
*/
const LightObj & GetFunc() const
{
return mFunc;
}
/* ----------------------------------------------------------------------------------------
* Modify the function object.
*/
void SetFunc(const Function & func)
{
// Validate the specified
if (!sq_isclosure(func.GetFunc()) && !sq_isnativeclosure(func.GetFunc()))
{
STHROWF("Invalid callback type %s", SqTypeName(mFunc.GetType()));
}
// Grab the virtual machine once
HSQUIRRELVM vm = DefaultVM::Get();
// Remember the current stack size
const StackGuard sg(vm);
// Push the callback on the stack
sq_pushobject(vm, func.GetFunc());
// Grab the hash of the callback object
mHash = sq_gethash(vm, -1);
// Now store the function without the environment
mFunc = LightObj(func.GetFunc());
}
/* ----------------------------------------------------------------------------------------
* Retrieve the arbitrary user data object.
*/
const LightObj & GetData() const
{
return mData;
}
/* ----------------------------------------------------------------------------------------
* Modify the arbitrary user data object.
*/
void SetData(const LightObj & data)
{
mData = data;
}
/* ----------------------------------------------------------------------------------------
* Retrieve the execution interval.
*/
SQInteger GetInterval() const
{
return ConvTo< SQInteger >::From(mInterval);
}
/* ----------------------------------------------------------------------------------------
* Modify the execution interval.
*/
void SetInterval(SQInteger itr)
{
mInterval = ClampMin(ConvTo< Interval >::From(itr), static_cast< Interval >(0));
}
/* ----------------------------------------------------------------------------------------
* Retrieve the number of iterations.
*/
SQInteger GetIterations() const
{
return ConvTo< SQInteger >::From(mIterations);
}
/* ----------------------------------------------------------------------------------------
* Modify the number of iterations.
*/
void SetIterations(SQInteger itr)
{
mIterations = ConvTo< Iterator >::From(itr);
}
/* ----------------------------------------------------------------------------------------
* Retrieve the number of arguments to be forwarded.
*/
SQInteger GetArguments() const
{
return ConvTo< SQInteger >::From(mArgc);
}
/* ----------------------------------------------------------------------------------------
* Retrieve a certain argument.
*/
const Argument & GetArgument(SQInteger arg) const
{
constexpr Uint32 argvn = (sizeof(mArgv) / sizeof(mArgv[0]));
// Cast the index to the proper value
Uint8 idx = ConvTo< Uint8 >::From(arg);
// Validate the specified index
if (idx >= argvn)
{
STHROWF("The specified index is out of range: %u >= %u", idx, argvn);
}
// Return the requested argument
return mArgv[idx];
}
};
// --------------------------------------------------------------------------------------------
static Time s_Last; // Last time point.
static Time s_Prev; // Previous time point.
static Interval s_Intervals[SQMOD_MAX_TASKS]; // List of intervals to be processed.
static Task s_Tasks[SQMOD_MAX_TASKS]; // List of tasks to be executed.
/* --------------------------------------------------------------------------------------------
* Default constructor. (disabled)
*/
Tasks() = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Tasks(const Tasks & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Tasks(Tasks && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor. (disabled)
*/
~Tasks() = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Tasks & operator = (const Tasks & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Tasks & operator = (Tasks && o) = delete;
public:
/* --------------------------------------------------------------------------------------------
* Process all active tasks and update elapsed time.
*/
static void Process();
/* --------------------------------------------------------------------------------------------
* Initialize all resources and prepare for startup.
*/
static void Initialize();
/* --------------------------------------------------------------------------------------------
* Register the task class.
*/
static void Register(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Release all resources and prepare for shutdown.
*/
static void Deinitialize();
protected:
/* --------------------------------------------------------------------------------------------
* Retrieve the instance of the specified entity.
*/
static LightObj & FindEntity(Int32 id, Int32 type);
/* --------------------------------------------------------------------------------------------
* Find an unoccupied task slot.
*/
static SQInteger FindUnused();
/* --------------------------------------------------------------------------------------------
* Locate the first task with the specified parameters.
*/
static SQInteger Find(Int32 id, Int32 type, SQInteger & pos, HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Attempt to create a task with the specified parameters.
*/
static SQInteger Create(Int32 id, Int32 type, HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Attempt to remove the task with the specified parameters.
*/
static SQInteger Remove(Int32 id, Int32 type, HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* See if a task with the specified parameters exists.
*/
static SQInteger Exists(Int32 id, Int32 type, HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Cleanup all tasks associated with the specified entity.
*/
static const Task & FindByTag(Int32 id, Int32 type, StackStrF & tag);
public:
/* --------------------------------------------------------------------------------------------
* Retrieve the number of used tasks slots.
*/
static SQInteger GetUsed()
{
SQInteger n = 0;
// Iterate task list
for (const auto & t : s_Tasks)
{
if (VALID_ENTITY(t.mEntity))
{
++n;
}
}
// Return the final count
return n;
}
/* --------------------------------------------------------------------------------------------
* Cleanup all tasks associated with the specified entity.
*/
static void Cleanup(Int32 id, Int32 type);
/* --------------------------------------------------------------------------------------------
* Forwards calls to create tasks.
*/
template < typename Entity, Int32 Type > static SQInteger MakeTask(HSQUIRRELVM vm)
{
// The entity instance
const Entity * inst = nullptr;
// Attempt to extract the instance
try
{
// Fetch the instance from the stack
inst = Var< const Entity * >(vm, 1).value;
// Do we have a valid instance?
if (!inst)
{
STHROWF("Invalid entity instance");
}
// Validate the actual entity instance
inst->Validate();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Forward the call and return the result
return Create(inst->GetID(), Type, vm);
}
/* --------------------------------------------------------------------------------------------
* Forwards calls to remove tasks.
*/
template < typename Entity, Int32 Type > static SQInteger DropTask(HSQUIRRELVM vm)
{
// The entity instance
const Entity * inst = nullptr;
// Attempt to extract the instance
try
{
// Fetch the instance from the stack
inst = Var< const Entity * >(vm, 1).value;
// Do we have a valid instance?
if (!inst)
{
STHROWF("Invalid entity instance");
}
// Validate the actual entity instance
inst->Validate();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Forward the call and return the result
return Remove(inst->GetID(), Type, vm);
}
/* --------------------------------------------------------------------------------------------
* Forwards calls to check tasks.
*/
template < typename Entity, Int32 Type > static SQInteger DoesTask(HSQUIRRELVM vm)
{
// The entity instance
const Entity * inst = nullptr;
// Attempt to extract the instance
try
{
// Fetch the instance from the stack
inst = Var< const Entity * >(vm, 1).value;
// Do we have a valid instance?
if (!inst)
{
STHROWF("Invalid entity instance");
}
// Validate the actual entity instance
inst->Validate();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Forward the call and return the result
return Exists(inst->GetID(), Type, vm);
}
/* --------------------------------------------------------------------------------------------
* Forwards calls to find tasks.
*/
template < typename Entity, Int32 Type > static SQInteger FindTask(HSQUIRRELVM vm)
{
// Was the tag string specified?
if (sq_gettop(vm) <= 1)
{
return sq_throwerror(vm, "Missing tag string");
}
// The entity instance
const Entity * inst = nullptr;
// Attempt to extract the instance
try
{
// Fetch the instance from the stack
inst = Var< const Entity * >(vm, 1).value;
// Do we have a valid instance?
if (!inst)
{
STHROWF("Invalid entity instance");
}
// Validate the actual entity instance
inst->Validate();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Attempt to generate the string value
StackStrF tag(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(tag.Proc(true)))
{
return tag.mRes; // Propagate the error!
}
// Attempt to find the specified task
try
{
// Perform the search
const Task & task = FindByTag(inst->GetID(), Type, tag);
// Now push the instance on the stack
sq_pushobject(vm, task.mSelf.mObj);
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Specify that this function returns a value
return 1;
}
};
} // Namespace:: SqMod
#endif // _TASKS_HPP_

708
module/Misc/Vehicle.cpp Normal file
View File

@@ -0,0 +1,708 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Vehicle.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static String CS_Vehicle_Names[] = {
/* 130 */ "Landstalker", /* 131 */ "Idaho",
/* 132 */ "Stinger", /* 133 */ "Linerunner",
/* 134 */ "Perennial", /* 135 */ "Sentinel",
/* 136 */ "Rio", /* 137 */ "Firetruck",
/* 138 */ "Trashmaster", /* 139 */ "Stretch",
/* 140 */ "Manana", /* 141 */ "Infernus",
/* 142 */ "Voodoo", /* 143 */ "Pony",
/* 144 */ "Mule", /* 145 */ "Cheetah",
/* 146 */ "Ambulance", /* 147 */ "FBI Washington",
/* 148 */ "Moonbeam", /* 149 */ "Esperanto",
/* 150 */ "Taxi", /* 151 */ "Washington",
/* 152 */ "Bobcat", /* 153 */ "Mr. Whoopee",
/* 154 */ "BF Injection", /* 155 */ "Hunter",
/* 156 */ "Police", /* 157 */ "Enforcer",
/* 158 */ "Securicar", /* 159 */ "Banshee",
/* 160 */ "Predator", /* 161 */ "Bus",
/* 162 */ "Rhino", /* 163 */ "Barracks OL",
/* 164 */ "Cuban Hermes", /* 165 */ "Helicopter",
/* 166 */ "Angel", /* 167 */ "Coach",
/* 168 */ "Cabbie", /* 169 */ "Stallion",
/* 170 */ "Rumpo", /* 171 */ "RC Bandit",
/* 172 */ "Romero's Hearse", /* 173 */ "Packer",
/* 174 */ "Sentinel XS", /* 175 */ "Admiral",
/* 176 */ "Squalo", /* 177 */ "Sea Sparrow",
/* 178 */ "Pizza Boy", /* 179 */ "Gang Burrito",
/* 180 */ "Airtrain", /* 181 */ "Deaddodo",
/* 182 */ "Speeder", /* 183 */ "Reefer",
/* 184 */ "Tropic", /* 185 */ "Flatbed",
/* 186 */ "Yankee", /* 187 */ "Caddy",
/* 188 */ "Zebra Cab", /* 189 */ "Top Fun",
/* 190 */ "Skimmer", /* 191 */ "PCJ-600",
/* 192 */ "Faggio", /* 193 */ "Freeway",
/* 194 */ "RC Baron", /* 195 */ "RC Raider",
/* 196 */ "Glendale", /* 197 */ "Oceanic",
/* 198 */ "Sanchez", /* 199 */ "Sparrow",
/* 200 */ "Patriot", /* 201 */ "Love Fist",
/* 202 */ "Coast Guard", /* 203 */ "Dinghy",
/* 204 */ "Hermes", /* 205 */ "Sabre",
/* 206 */ "Sabre Turbo", /* 207 */ "Phoenix",
/* 208 */ "Walton", /* 209 */ "Regina",
/* 210 */ "Comet", /* 211 */ "Deluxo",
/* 212 */ "Burrito", /* 213 */ "Spand Express",
/* 214 */ "Marquis", /* 215 */ "Baggage Handler",
/* 216 */ "Kaufman Cab", /* 217 */ "Maverick",
/* 218 */ "VCN Maverick", /* 219 */ "Rancher",
/* 220 */ "FBI Rancher", /* 221 */ "Virgo",
/* 222 */ "Greenwood", /* 223 */ "Cuban Jetmax",
/* 224 */ "Hotring Racer #1", /* 225 */ "Sandking",
/* 226 */ "Blista Compact", /* 227 */ "Police Maverick",
/* 228 */ "Boxville", /* 229 */ "Benson",
/* 230 */ "Mesa Grande", /* 231 */ "RC Goblin",
/* 232 */ "Hotring Racer #2", /* 233 */ "Hotring Racer #3",
/* 234 */ "Bloodring Banger #1", /* 235 */ "Bloodring Banger #2",
/* 236 */ "Vice Squad Cheetah", /* 237 */ ""
};
// ------------------------------------------------------------------------------------------------
static String CS_Custom_Vehicle_Names[100]{};
// ------------------------------------------------------------------------------------------------
struct InitCustomVehicleNames
{
InitCustomVehicleNames()
{
for (String & s : CS_Custom_Vehicle_Names)
{
s.assign("");
}
}
} g_InitCustomVehicleNames{};
// ------------------------------------------------------------------------------------------------
String GetAutomobileName(Uint32 id)
{
if (id > 129 && id < 237)
{
return CS_Vehicle_Names[id-130];
}
else if (id > 6399 && id < 6500)
{
return CS_Custom_Vehicle_Names[id-6400];
}
else
{
STHROWF("Vehicle identifier breaks these demands (%u > 129 and %u < 237) or (%u > 6399 and %u < 6500)", id, id, id, id);
}
// Should never reach this point
return NullString();
}
// ------------------------------------------------------------------------------------------------
void SetAutomobileName(Uint32 id, StackStrF & name)
{
if (id > 129 && id < 237)
{
CS_Vehicle_Names[id-130].assign(name.mPtr, ConvTo< size_t >::From(name.mLen));
}
else if (id > 6399 && id < 6500)
{
CS_Custom_Vehicle_Names[id-6400].assign(name.mPtr, name.mLen < 0 ? 0 : static_cast< size_t >(name.mLen));
}
else
{
STHROWF("Vehicle identifier breaks these demands (%u > 129 and %u < 237) or (%u > 6399 and %u < 6500)", id, id, id, id);
}
}
// ------------------------------------------------------------------------------------------------
Int32 GetAutomobileID(StackStrF & name)
{
// Clone the string into an editable version
String str(name.mPtr, name.mLen);
// Strip non alphanumeric characters from the name
str.erase(std::remove_if(str.begin(), str.end(), std::not1(std::ptr_fun(::isalnum))), str.end());
// Convert the string to lowercase
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
// See if we still have a valid name after the cleanup
if(str.empty())
{
return SQMOD_UNKNOWN;
}
// Grab the actual length of the string
const Uint32 len = ConvTo< Uint32 >::From(str.length());
// Get the most significant characters used to identify a vehicle
CharT a = str[0], b = 0, c = 0, d = str[len-1];
// Look for deeper specifiers
if(len > 2)
{
c = str[2];
b = str[1];
}
else if(len > 1)
{
b = str[1];
}
// Search for a pattern in the name
switch (a)
{
// [A]dmiral
// [A]irtrain
// [A]mbulance
// [A]ngel
case 'a':
switch (b)
{
// [Ad]miral
case 'd': return SQMOD_VEHICLE_ADMIRAL;
// [Ai]rtrain
case 'i': return SQMOD_VEHICLE_AIRTRAIN;
// [Am]bulance
case 'm': return SQMOD_VEHICLE_AMBULANCE;
// [An]gel
case 'n': return SQMOD_VEHICLE_ANGEL;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [B]aggage Handler
// [B]anshee
// [B]arracks OL
// [B]enson
// [B]F Injection
// [B]lista Compact
// [B]loodring Banger #1
// [B]loodring Banger #2
// [B]obcat
// [B]oxville
// [B]urrito
// [B]us
case 'b':
switch (b)
{
// [Ba]ggage Handler
// [Ba]nshee
// [Ba]rracks OL
case 'a':
// [Bag]gage Handler
if (c == 'g') return SQMOD_VEHICLE_BAGGAGEHANDLER;
// [Ban]shee
else if (c == 'n') return SQMOD_VEHICLE_BANSHEE;
// [Bar]racks OL
else if (c == 'r') return SQMOD_VEHICLE_BARRACKS;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Be]nson
case 'e': return SQMOD_VEHICLE_BENSON;
// [BF] [I]njection
case 'f':
case 'i': return SQMOD_VEHICLE_BFINJECTION;
// [Bl]ista Compact
// [Bl]oodring Banger #1
// [Bl]oodring Banger #2
case 'l':
// [Bli]sta [C]ompact
if (b == 'c' || c == 'i') return SQMOD_VEHICLE_BLISTACOMPACT;
// [Blo]odring [B]anger (#1|A)
else if ((b == 'b' || c == 'o') && (d == '1' || d == 'a')) return SQMOD_VEHICLE_BLOODRINGBANGER1;
// [Blo]odring [B]anger (#2|B)
else if ((b == 'b' || c == 'o') && (d == '2' || d == 'b')) return SQMOD_VEHICLE_BLOODRINGBANGER2;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Bo]bcat
// [Bo]xville
case 'o':
// [Bob]cat
if (c == 'b') return SQMOD_VEHICLE_BOBCAT;
// [Box]ville
else if (c == 'x') return SQMOD_VEHICLE_BOXVILLE;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Bu]rrito
// [Bu]s
case 'u':
// [Bur]rito
if (c == 'r') return SQMOD_VEHICLE_BURRITO;
// [Bus]
else if (c == 's') return SQMOD_VEHICLE_BUS;
// Default to unknwon
else return SQMOD_UNKNOWN;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [C]abbie
// [C]addy
// [C]heetah
// [C]oach
// [C]oast Guard
// [C]omet
// [C]uban Hermes
// [C]uban Jetmax
case 'c':
switch (b)
{
// [Ca]bbie
// [Ca]ddy
case 'a':
// [Cab]bie
if (c == 'b') return SQMOD_VEHICLE_CABBIE;
// [Cad]dy
else if (c == 'd') return SQMOD_VEHICLE_CADDY;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Ch]eetah
case 'h': return SQMOD_VEHICLE_CHEETAH;
// [Co]ach
// [Co]ast Guard
// [Co]met
case 'o':
// [Coa]c[h]
if (c == 'a' && d == 'h') return SQMOD_VEHICLE_COACH;
// [Coa]s[t] Guar[d]
else if (c == 'a' && (d == 't' || d == 'd')) return SQMOD_VEHICLE_COASTGUARD;
// [Co]met
else if (c == 'm') return SQMOD_VEHICLE_COMET;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Cu]ban Hermes
// [Cu]ban Jetmax
case 'u':
// [Cub]an [H]erme[s]
if ((len > 5 && str[5] == 'h') || (d == 's' || d == 'h')) return SQMOD_VEHICLE_CUBANHERMES;
// [Cub]an [J]etma[x]
if ((len > 5 && str[5] == 'j') || (d == 'x' || d == 'j')) return SQMOD_VEHICLE_CUBANJETMAX;
// Default to unknwon
else return SQMOD_UNKNOWN;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [D]eaddodo
// [D]eluxo
// [D]inghy
case 'd':
switch (b)
{
// [De]addodo
// [De]luxo
case 'e':
// [Dea]ddodo
if (c == 'a') return SQMOD_VEHICLE_DEADDODO;
// [Del]uxo
else if (c == 'l') return SQMOD_VEHICLE_DELUXO;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Di]nghy
case 'i': return SQMOD_VEHICLE_DINGHY;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [E]speranto
// [E]nforcer
case 'e':
// [Es]peranto
if (b && b == 's') return SQMOD_VEHICLE_ESPERANTO;
// [En]forcer
else if (b && b == 'n') return SQMOD_VEHICLE_ENFORCER;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [F]aggio
// [F]BI Rancher
// [F]BI Washington
// [F]iretruck
// [F]latbed
// [F]reeway
case 'f':
switch (b)
{
// [Fa]ggio
case 'a': return SQMOD_VEHICLE_FAGGIO;
// [FB]I Rancher
// [FB]I Washington
case 'b':
// [FB]I [R]anche[r]
if ((len > 3 && str[3] == 'r') || d == 'r') return SQMOD_VEHICLE_FBIRANCHER;
// [FB]I [W]ashingto[n]
else if ((len > 3 && str[3] == 'w') || (d == 'n' || d == 'w')) return SQMOD_VEHICLE_FBIWASHINGTON;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Fi]retruck
case 'i': return SQMOD_VEHICLE_FIRETRUCK;
// [Fl]atbed
case 'l': return SQMOD_VEHICLE_FLATBED;
// [Fr]eeway
case 'r': return SQMOD_VEHICLE_FREEWAY;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [G]ang Burrito
// [G]lendale
// [G]reenwood
case 'g':
switch (b)
{
// [Ga]ng Burrito
case 'a': return SQMOD_VEHICLE_GANGBURRITO;
// [Gl]endale
case 'l': return SQMOD_VEHICLE_GLENDALE;
// [Gr]eenwood
case 'r': return SQMOD_VEHICLE_GREENWOOD;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [H]elicopter
// [H]ermes
// [H]otring Racer (#1|A)(#2|B)(#3|C)
// [H]unter
case 'h':
switch (b)
{
// [He]licopter
// [He]rmes
case 'e':
// [Hel]icopter
if (c == 'l') return SQMOD_VEHICLE_HELICOPTER;
// [Her]mes
else if (c == 'r') return SQMOD_VEHICLE_HERMES;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Ho]tring Racer (#1|A)(#2|B)(#3|C)
case 'o':
switch (d)
{
case '1':
case 'a': return SQMOD_VEHICLE_HOTRINGRACER1;
case '2':
case 'b': return SQMOD_VEHICLE_HOTRINGRACER2;
case '3':
case 'c': return SQMOD_VEHICLE_HOTRINGRACER3;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [Hu]nter
case 'u': return SQMOD_VEHICLE_HUNTER;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [I]daho
// [I]nfernus
case 'i':
// [Id]aho
if (b && b == 'd') return SQMOD_VEHICLE_IDAHO;
// [In]fernus
else if (b && b == 'n') return SQMOD_VEHICLE_INFERNUS;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [K]aufman Cab
case 'k': return SQMOD_VEHICLE_KAUFMANCAB;
// [L]andstalker
// [L]inerunner
// [L]ove Fist
case 'l':
switch (b)
{
// [La]ndstalker
case 'a': return SQMOD_VEHICLE_LANDSTALKER;
// [Li]nerunner
case 'i': return SQMOD_VEHICLE_LINERUNNER;
// [Lo]ve Fist
case 'o': return SQMOD_VEHICLE_LOVEFIST;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [M]anana
// [M]arquis
// [M]averick
// [M]esa Grande
// [M]oonbeam
// [M]r. Whoopee
// [M]ule
case 'm':
switch (b)
{
// [Ma]nana
// [Ma]rquis
// [Ma]verick
case 'a':
// [Man]ana
if (c == 'n') return SQMOD_VEHICLE_MANANA;
// [Mar]quis
else if (c == 'r') return SQMOD_VEHICLE_MARQUIS;
// [Mav]erick
else if (c == 'v') return SQMOD_VEHICLE_MAVERICK;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Me]sa Grande
case 'e': return SQMOD_VEHICLE_MESAGRANDE;
// [Mo]onbeam
case 'o': return SQMOD_VEHICLE_MOONBEAM;
// [Mr]. Whoopee
case 'r': return SQMOD_VEHICLE_MRWHOOPEE;
// [Mu]le
case 'u': return SQMOD_VEHICLE_MULE;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [O]ceanic
case 'o': return SQMOD_VEHICLE_OCEANIC;
// [P]acker
// [P]atriot
// [P]CJ-600
// [P]erennial
// [P]hoenix
// [P]izza Boy
// [P]olice
// [P]olice Maverick
// [P]ony
// [P]redator
case 'p':
switch (b)
{
// [Pa]cker
// [Pa]triot
case 'a':
// [Pac]ker
if (c == 'c') return SQMOD_VEHICLE_PACKER;
// [Pat]riot
else if (c == 't') return SQMOD_VEHICLE_PATRIOT;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [PC]J-600
case 'c': return SQMOD_VEHICLE_PCJ600;
// [Pe]rennial
case 'e': return SQMOD_VEHICLE_PERENNIAL;
// [Ph]oenix
case 'h': return SQMOD_VEHICLE_PHOENIX;
// [Pi]zza Boy
case 'i': return SQMOD_VEHICLE_PIZZABOY;
// [Po]lice
// [Po]lice Maverick
// [Po]ny
case 'o':
// [Po]lice
if (d == 'e') return SQMOD_VEHICLE_POLICE;
// [Po]lice Maverick
else if ((len > 6 && str[6] == 'm') || (d == 'k' || d == 'm')) return SQMOD_VEHICLE_POLICEMAVERICK;
// [Po]ny
else if (c == 'n') return SQMOD_VEHICLE_PONY;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Pr]edator
case 'r': return SQMOD_VEHICLE_PREDATOR;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [R]ancher
// [R]C Bandit
// [R]C Baron
// [R]C Goblin
// [R]C Raider
// [R]eefer
// [R]egina
// [R]hino
// [R]io
// [R]omero's Hearse
// [R]umpo
case 'r':
switch (b)
{
// [Ra]ncher
case 'a': return SQMOD_VEHICLE_RANCHER;
// [RC] Bandit
// [RC] Baron
// [RC] Goblin
// [RC] Raider
case 'c':
// [RC] [B]andi[t]
if (c == 'b' && d == 't') return SQMOD_VEHICLE_RCBANDIT;
// [RC] [B]aro[n]
else if (c == 'b' && d == 'n') return SQMOD_VEHICLE_RCBARON;
// [RC] [G]oblin
else if (c == 'g') return SQMOD_VEHICLE_RCGOBLIN;
// [RC] [R]aide[r]
else if (c == 'r' || d == 'r') return SQMOD_VEHICLE_RCRAIDER;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Re]efer
// [Re]gina
case 'e':
// [Ree]fer
if (c == 'e' || d == 'r') return SQMOD_VEHICLE_REEFER;
// [Reg]ina
else if (c == 'g' || d == 'a') return SQMOD_VEHICLE_REGINA;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Rh]ino
case 'h': return SQMOD_VEHICLE_RHINO;
// [Ri]o
case 'i': return SQMOD_VEHICLE_RIO;
// [Ro]mero's Hearse
case 'o': return SQMOD_VEHICLE_HEARSE;
// [Ru]mpo
case 'u': return SQMOD_VEHICLE_RUMPO;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [S]abre
// [S]abre Turbo
// [S]anchez
// [S]andking
// [S]ea Sparrow
// [S]ecuricar
// [S]entinel
// [S]entinel XS
// [S]kimmer
// [S]pand Express
// [S]parrow
// [S]peeder
// [S]qualo
// [S]tallion
// [S]tinger
// [S]tretch
case 's':
switch (b)
{
// [Sa]bre
// [Sa]bre Turbo
// [Sa]nchez
// [Sa]ndking
case 'a':
// [Sab]r[e]
if (c == 'b' && d == 'e') return SQMOD_VEHICLE_SABRE;
// [Sab]re [T]urb[o]
else if ((c == 'b' && d == 'o') || (len > 5 && str[5 ]== 't')) return SQMOD_VEHICLE_SABRETURBO;
// [Sa]n[c]he[z]
else if (d == 'c' || d == 'z') return SQMOD_VEHICLE_SANCHEZ;
// [Sa]n[d]kin[g]
else if (d == 'd' || d == 'g') return SQMOD_VEHICLE_SANDKING;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Se]a Sparrow
// [Se]curicar
// [Se]ntinel
// [Se]ntinel XS
case 'e':
// [Sea] Sparro[w]
if (c == 'e' || d == 'w') return SQMOD_VEHICLE_SEASPARROW;
// [Sec]urica[r]
else if (c == 'c' || d == 'r') return SQMOD_VEHICLE_SECURICAR;
// [Sen]tine[l]
else if (c == 'n' && d == 'l') return SQMOD_VEHICLE_SENTINEL;
// [Sen]tinel X[S]
else if (c == 'n' && d == 's') return SQMOD_VEHICLE_SENTINELXS;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Sk]immer
case 'k': return SQMOD_VEHICLE_SKIMMER;
// [Sp]and Express
// [Sp]arrow
// [Sp]eeder
case 'p':
// [Spa]nd [E]xpres[s]
if (c == 'a' || ((len > 5 && str[5] == 'e') || d == 's')) return SQMOD_VEHICLE_SPANDEXPRESS;
// [Spa]rro[w]
else if (d == 'w' && (c == 'a' && d == 'w')) return SQMOD_VEHICLE_SPARROW;
// [Spe]ede[r]
else if (c == 'e' || d == 'r') return SQMOD_VEHICLE_SPEEDER;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Sq]ualo
case 'q': return SQMOD_VEHICLE_SQUALO;
// [St]allion
// [St]inger
// [St]retch
case 't':
// [Sta]llion
if (c == 'a') return SQMOD_VEHICLE_STALLION;
// [Sti]nger
if (c == 'i') return SQMOD_VEHICLE_STINGER;
// [Str]etch
if (c == 'r') return SQMOD_VEHICLE_STRETCH;
// Default to unknwon
else return SQMOD_UNKNOWN;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [T]axi
// [T]op Fun
// [T]rashmaster
// [T]ropic
case 't':
switch (b)
{
// [Ta]xi
case 'a': return SQMOD_VEHICLE_TAXI;
// [To]p Fun
case 'o': return SQMOD_VEHICLE_TOPFUN;
// [Tr]ashmaster
// [Tr]opic
case 'r':
// [Tr]ashmaster
if (c == 'a') return SQMOD_VEHICLE_TRASHMASTER;
// [Tr]opic
if (c == 'o') return SQMOD_VEHICLE_TROPIC;
// Default to unknwon
else return SQMOD_UNKNOWN;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [V]CN Maverick
// [V]ice Squad Cheetah
// [V]irgo
// [V]oodoo
case 'v':
switch (b)
{
// [VC]N Maverick
case 'c': return SQMOD_VEHICLE_VCNMAVERICK;
// [Vi]ce Squad Cheetah
// [Vi]rgo
case 'i':
// [Vic]e Squad Cheetah
if (c == 'a') return SQMOD_VEHICLE_VICECHEE;
// [Vir]go
if (c == 'r') return SQMOD_VEHICLE_VIRGO;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Vo]odoo
case 'o': return SQMOD_VEHICLE_VOODOO;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
// [W]alton
// [W]ashington
case 'w':
// [Wa]lton
if (b == 'a' && c == 'l') return SQMOD_VEHICLE_WALTON;
// [Wa]shington
else if (b == 'a' && c == 's') return SQMOD_VEHICLE_WASHINGTON;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [Y]ankee
case 'y': return SQMOD_VEHICLE_YANKEE;
// [Z]ebra Cab
case 'z': return SQMOD_VEHICLE_ZEBRACAB;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
}
// ------------------------------------------------------------------------------------------------
bool IsAutomobileValid(Int32 id)
{
try
{
return !GetAutomobileName(id).empty();
}
catch (...)
{
//... Ignore it
}
// If we reached here then no!
return false;
}
} // Namespace:: SqMod

32
module/Misc/Vehicle.hpp Normal file
View File

@@ -0,0 +1,32 @@
#ifndef _MISC_VEHICLE_HPP_
#define _MISC_VEHICLE_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the name associated with a vehicle model identifier.
*/
String GetAutomobileName(Uint32 id);
/* ------------------------------------------------------------------------------------------------
* Modify the name associated with a vehicle model identifier.
*/
void SetAutomobileName(Uint32 id, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Convert a vehicle model name to a vehicle model identifier.
*/
Int32 GetAutomobileID(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* See whether the specified vehicle model identifier is valid.
*/
bool IsAutomobileValid(Int32 id);
} // Namespace:: SqMod
#endif // _MISC_VEHICLE_HPP_

438
module/Misc/Weapon.cpp Normal file
View File

@@ -0,0 +1,438 @@
// ------------------------------------------------------------------------------------------------
#include "Misc/Weapon.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
#include <algorithm>
#include <unordered_map>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static String CS_Weapon_Names[] = {
/* 0 */ "Unarmed", /* 1 */ "Brass Knuckles",
/* 2 */ "Screwdriver", /* 3 */ "Golf Club",
/* 4 */ "Nightstick", /* 5 */ "Knife",
/* 6 */ "Baseball Bat", /* 7 */ "Hammer",
/* 8 */ "Meat Cleaver", /* 9 */ "Machete",
/* 10 */ "Katana", /* 11 */ "Chainsaw",
/* 12 */ "Grenade", /* 13 */ "Remote Detonation Grenade",
/* 14 */ "Tear Gas", /* 15 */ "Molotov Cocktails",
/* 16 */ "Missile", /* 17 */ "Colt .45",
/* 18 */ "Python", /* 19 */ "Pump-Action Shotgun",
/* 20 */ "SPAS-12 Shotgun", /* 21 */ "Stubby Shotgun",
/* 22 */ "TEC-9", /* 23 */ "Uzi",
/* 24 */ "Silenced Ingram", /* 25 */ "MP5",
/* 26 */ "M4", /* 27 */ "Ruger",
/* 28 */ "Sniper Rifle", /* 29 */ "Laserscope Sniper Rifle",
/* 30 */ "Rocket Launcher", /* 31 */ "Flamethrower",
/* 32 */ "M60", /* 33 */ "Minigun",
/* 34 */ "Bomb", /* 35 */ "Helicanon",
/* 36 */ "Camera", /* 37 */ "",
/* 38 */ "", /* 39 */ "Vehicle",
/* 40 */ "Heliblade", /* 41 */ "Explosion",
/* 42 */ "Driveby", /* 43 */ "Drowned",
/* 44 */ "Fall", /* 45 */ "",
/* 46 */ "", /* 47 */ "",
/* 48 */ "", /* 49 */ "",
/* 50 */ "", /* 51 */ "Explosion",
/* 52 */ "", /* 53 */ "",
/* 54 */ "", /* 55 */ "",
/* 56 */ "", /* 57 */ "",
/* 58 */ "", /* 59 */ "",
/* 60 */ "Heliblade", /* 61 */ "",
/* 62 */ "", /* 63 */ "",
/* 64 */ "", /* 65 */ "",
/* 66 */ "", /* 67 */ "",
/* 68 */ "", /* 69 */ "",
/* 70 */ "Suicide", /* 71 */ ""
};
/// Fall back for custom weapon names.
static std::unordered_map<Uint32, String> CS_Custom_Weapon_Names{};
// ------------------------------------------------------------------------------------------------
static inline bool IsCustomWeapon(Uint32 id)
{
return (id > 70);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetWeaponSlot(Uint32 id)
{
switch(id) {
case 0:
case 1:
return 0;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
return 1;
case 12:
case 13:
case 14:
case 15:
return 2;
case 17:
case 18:
return 3;
case 19:
case 20:
case 21:
return 4;
case 22:
case 23:
case 24:
case 25:
return 5;
case 26:
case 27:
return 6;
case 28:
case 29:
return 8;
case 30:
case 31:
case 32:
case 33:
return 7;
default:
return 255;
}
}
// ------------------------------------------------------------------------------------------------
CCStr GetWeaponName(Uint32 id)
{
// Can we consider this a custom weapon ID?
if (IsCustomWeapon(id))
{
// Attempt to look for the specified identifier
auto it = CS_Custom_Weapon_Names.find(id);
// If we found anything than return the associated name
if ((it != CS_Custom_Weapon_Names.end()))
{
return it->second.c_str();
}
}
else
{
return CS_Weapon_Names[id].c_str(); // Use the standard weapon name
}
// Fall back to an empty name
return _SC("");
}
// ------------------------------------------------------------------------------------------------
void SetWeaponName(Uint32 id, StackStrF & name)
{
// Can we consider this a custom weapon ID?
if (IsCustomWeapon(id))
{
// Attempt to insert or update the name into the custom weapon table
CS_Custom_Weapon_Names[id] = String(name.mPtr, name.mLen);
}
else
{
// Attempt to insert or update the name into the standard weapon table
CS_Weapon_Names[id].assign(name.mPtr);
}
}
// ------------------------------------------------------------------------------------------------
Uint32 GetCustomWeaponNamePoolSize()
{
return static_cast< Uint32 >(CS_Custom_Weapon_Names.size());
}
// ------------------------------------------------------------------------------------------------
void ClearCustomWeaponNamePool()
{
CS_Custom_Weapon_Names.clear();
}
// ------------------------------------------------------------------------------------------------
Int32 GetWeaponID(StackStrF & name)
{
// Clone the string into an editable version
String str(name.mPtr, name.mLen);
// Strip non alphanumeric characters from the name
str.erase(std::remove_if(str.begin(), str.end(), std::not1(std::ptr_fun(::isalnum))), str.end());
// Convert the string to lowercase
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
// See if we still have a valid name after the cleanup
if(str.length() < 1)
{
return SQMOD_UNKNOWN;
}
// Grab the actual length of the string
const Uint32 len = ConvTo< Uint32 >::From(str.length());
// Get the most significant characters used to identify a weapon
CharT a = str[0], b = 0, c = 0, d = str[len-1];
// Look for deeper specifiers
if(len > 2)
{
c = str[2];
b = str[1];
}
else if(len > 1)
{
b = str[1];
}
// Search for a pattern in the name
switch(a)
{
// [B]aseball Bat
// [B]omb
// [B]rass Knuckles
case 'b':
// [Ba]seball Bat
if (b == 'a') return SQMOD_WEAPON_BASEBALLBAT;
// [Bo]mb
else if (b == 'o') return SQMOD_WEAPON_BOMB;
// [Br]ass Knuckles
else if (b == 'r') return SQMOD_WEAPON_BRASSKNUCKLES;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [C]amera
// [C]hainsaw
// [C]olt .45
case 'c':
// [Ca]mera
if (b == 'a') return SQMOD_WEAPON_CAMERA;
// [Ch]ainsaw
else if (b == 'h') return SQMOD_WEAPON_CHAINSAW;
// [Co]lt .45
else if (b == 'o') return SQMOD_WEAPON_COLT45;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [D]riveby
// [D]rowned
case 'd':
// [Dr]iveby
if (b == 'r' && (c == 'i' || d == 'y')) return SQMOD_WEAPON_DRIVEBY;
// [Dr]owned
else if (b == 'r' && (c == 'o' || d == 'd')) return SQMOD_WEAPON_DROWNED;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [E]xplosion
case 'e': return SQMOD_WEAPON_EXPLOSION2;
// [F]all
// [F]lamethrower
case 'f':
// [Fa]ll
if (b == 'a') return SQMOD_WEAPON_FALL;
// [Fl]amethrower
else if (b == 'l') return SQMOD_WEAPON_FLAMETHROWER;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [G]olf Club
// [G]renade
case 'g':
// [Go]lf Club
if (b == 'o') return SQMOD_WEAPON_GOLFCLUB;
// [Gr]enade
else if (b == 'r') return SQMOD_WEAPON_GRENADE;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [H]ammer
// [H]eliblades1/A
// [H]eliblades2/B
// [H]elicannon
case 'h':
// [Ha]mmer
if (b == 'a') return SQMOD_WEAPON_HAMMER;
// [He]li[b]lades[1/A]
else if (b == 'e' && (c == 'b' || (len > 4 && str[4] == 'b')) && (d == '1' || d == 'a')) return SQMOD_WEAPON_HELIBLADES1;
// [He]li[b]lades[2/B]
else if (b == 'e' && (c == 'b' || (len > 4 && str[4] == 'b')) && (d == '2' || d == 'b')) return SQMOD_WEAPON_HELIBLADES2;
// [He]li[c]anno[n]
else if (b == 'e' && (d == 'c' || d == 'n' || (len > 4 && str[4] == 'c'))) return SQMOD_WEAPON_HELICANNON;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [K]atana
// [K]nife
case 'k':
// [Ka]tana
if (b == 'a') return SQMOD_WEAPON_KATANA;
// [Kn]ife
else if (b == 'n') return SQMOD_WEAPON_KNIFE;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [L]aserscope Sniper Rifle
case 'l': return SQMOD_WEAPON_LASERSCOPE;
// [M]4
// [M]60
// [M]achete
// [M]eat Cleaver
// [M]inigun
// [M]issile
// [M]olotov Cocktails
// [M]P5
case 'm':
// [M4]
if (b == '4') return SQMOD_WEAPON_M4;
// [M6]0
else if (b == '6') return SQMOD_WEAPON_M60;
// [Ma]chete
else if (b == 'a') return SQMOD_WEAPON_MACHETE;
// [Me]at Cleaver
else if (b == 'e') return SQMOD_WEAPON_MEATCLEAVER;
// [Min]igu[n]
else if (b == 'i' && (c == 'n' || d == 'n')) return SQMOD_WEAPON_MINIGUN;
// [Mis]sil[e]
else if (b == 'i' && (c == 's' || d == 's' || d == 'e')) return SQMOD_WEAPON_ROCKET;
// [Mo]lotov Cocktails
else if (b == 'o') return SQMOD_WEAPON_MOLOTOV;
// [MP]5
else if (b == 'p') return SQMOD_WEAPON_MP5;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [N]ightstick
case 'n': return SQMOD_WEAPON_NIGHTSTICK;
case 'i': return SQMOD_WEAPON_INGRAM;
// [P]ump-Action Shotgun
// [P]ython
case 'p':
// [Pu]mp-Action Shotgun
if (b == 'u') return SQMOD_WEAPON_SHOTGUN;
// [Py]thon
else if (b == 'y') return SQMOD_WEAPON_PYTHON;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [R]emote Detonation Grenade
// [R]ocket Launcher
// [R]uger
case 'r':
// [Re]mote Detonation Grenade
if (b == 'e') return SQMOD_WEAPON_REMOTE;
// [Ro]cket Launcher
else if (b == 'o') return SQMOD_WEAPON_ROCKETLAUNCHER;
// [Ru]ger
else if (b == 'u') return SQMOD_WEAPON_RUGER;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [S]crewdriver
// [S]ilenced Ingram
// [S]niper Rifle
// [S]PAS-12 Shotgun
// [S]tubby Shotgun
// [S]uicide
case 's':
// [Sc]rewdriver
if (b == 'c') return SQMOD_WEAPON_SCREWDRIVER;
// [Si]lenced Ingram
else if (b == 'i') return SQMOD_WEAPON_INGRAM;
// [Sn]iper Rifle
else if (b == 'n') return SQMOD_WEAPON_SNIPER;
// [SP]AS-12 Shotgun
else if (b == 'p') return SQMOD_WEAPON_SPAS12;
// [St]ubby Shotgun
else if (b == 't') return SQMOD_WEAPON_STUBBY;
// [Su]icide
else if (b == 'u') return SQMOD_WEAPON_SUICIDE;
// Pump action [Sh]otgun
else if (b == 'h') return SQMOD_WEAPON_SHOTGUN;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [T]ear Gas
// [T]EC-9
case 't':
// [Tea]r Ga[s]
if (b == 'e' && (c == 'a' || d == 's')) return SQMOD_WEAPON_TEARGAS;
// [TEC]-[9]
else if (b == 'e' && (c == 'c' || d == '9')) return SQMOD_WEAPON_TEC9;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [U]narmed
// [U]zi
case 'u':
// [Un]armed
if (b == 'n') return SQMOD_WEAPON_UNARMED;
// [Uz]i
else if (b == 'z') return SQMOD_WEAPON_UZI;
// Default to unknwon
else return SQMOD_UNKNOWN;
// [V]ehicle
case 'v': return SQMOD_WEAPON_VEHICLE;
// Default to unknwon
default: return SQMOD_UNKNOWN;
}
}
// ------------------------------------------------------------------------------------------------
bool IsWeaponValid(Int32 id)
{
CSStr name = GetWeaponName(id);
return (name && *name != '\0');
}
// ------------------------------------------------------------------------------------------------
Int32 WeaponToModel(Int32 id)
{
switch (id)
{
case SQMOD_WEAPON_UNARMED: return 293;
case SQMOD_WEAPON_BRASSKNUCKLES: return 259;
case SQMOD_WEAPON_SCREWDRIVER: return 260;
case SQMOD_WEAPON_GOLFCLUB: return 261;
case SQMOD_WEAPON_NIGHTSTICK: return 262;
case SQMOD_WEAPON_KNIFE: return 263;
case SQMOD_WEAPON_BASEBALLBAT: return 264;
case SQMOD_WEAPON_HAMMER: return 265;
case SQMOD_WEAPON_MEATCLEAVER: return 266;
case SQMOD_WEAPON_MACHETE: return 267;
case SQMOD_WEAPON_KATANA: return 268;
case SQMOD_WEAPON_CHAINSAW: return 269;
case SQMOD_WEAPON_GRENADE: return 270;
case SQMOD_WEAPON_REMOTE: return 291;
case SQMOD_WEAPON_TEARGAS: return 271;
case SQMOD_WEAPON_MOLOTOV: return 272;
case SQMOD_WEAPON_ROCKET: return 273;
case SQMOD_WEAPON_COLT45: return 274;
case SQMOD_WEAPON_PYTHON: return 275;
case SQMOD_WEAPON_SHOTGUN: return 277;
case SQMOD_WEAPON_SPAS12: return 278;
case SQMOD_WEAPON_STUBBY: return 279;
case SQMOD_WEAPON_TEC9: return 281;
case SQMOD_WEAPON_UZI: return 282;
case SQMOD_WEAPON_INGRAM: return 283;
case SQMOD_WEAPON_MP5: return 284;
case SQMOD_WEAPON_M4: return 280;
case SQMOD_WEAPON_RUGER: return 276;
case SQMOD_WEAPON_SNIPER: return 285;
case SQMOD_WEAPON_LASERSCOPE: return 286;
case SQMOD_WEAPON_ROCKETLAUNCHER: return 287;
case SQMOD_WEAPON_FLAMETHROWER: return 288;
case SQMOD_WEAPON_M60: return 289;
case SQMOD_WEAPON_MINIGUN: return 290;
case SQMOD_WEAPON_HELICANNON: return 294;
case SQMOD_WEAPON_CAMERA: return 292;
default: return SQMOD_UNKNOWN;
}
}
// ------------------------------------------------------------------------------------------------
bool IsWeaponNatural(Int32 id)
{
switch (id)
{
case SQMOD_WEAPON_VEHICLE:
case SQMOD_WEAPON_DRIVEBY:
case SQMOD_WEAPON_DROWNED:
case SQMOD_WEAPON_FALL:
case SQMOD_WEAPON_EXPLOSION2:
case SQMOD_WEAPON_SUICIDE: return true;
default: return false;
}
}
} // Namespace:: SqMod

62
module/Misc/Weapon.hpp Normal file
View File

@@ -0,0 +1,62 @@
#ifndef _MISC_WEAPON_HPP_
#define _MISC_WEAPON_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the slot associated with a weapon identifier.
*/
Uint32 GetWeaponSlot(Uint32 id);
/* ------------------------------------------------------------------------------------------------
* Retrieve the name associated with a weapon identifier.
*/
CSStr GetWeaponName(Uint32 id);
/* ------------------------------------------------------------------------------------------------
* Modify the name associated with a weapon identifier.
*/
void SetWeaponName(Uint32 id, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Retrieve the total number of identifiers in the pool of custom weapon names.
*/
Uint32 GetCustomWeaponNamePoolSize();
/* ------------------------------------------------------------------------------------------------
* Clear all identifiersand associated names from the pool of custom weapon names.
*/
void ClearCustomWeaponNamePool();
/* ------------------------------------------------------------------------------------------------
* Modify the name associated with a weapon identifier.
*/
void SetWeaponName(Uint32 id, StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* Convert a weapon name to a weapon identifier.
*/
Int32 GetWeaponID(StackStrF & name);
/* ------------------------------------------------------------------------------------------------
* See whether the specified weapon identifier is valid.
*/
bool IsWeaponValid(Int32 id);
/* ------------------------------------------------------------------------------------------------
* Convert the given weapon identifier to it's associated model identifier.
*/
Int32 WeaponToModel(Int32 id);
/* ------------------------------------------------------------------------------------------------
* See whether the given weapon identifier cannot be used by another player to inflict damage.
*/
bool IsWeaponNatural(Int32 id);
} // Namespace:: SqMod
#endif // _MISC_WEAPON_HPP_