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:
920
module/Misc/Algo.cpp
Normal file
920
module/Misc/Algo.cpp
Normal 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
1649
module/Misc/Algo.hpp
Normal file
File diff suppressed because it is too large
Load Diff
476
module/Misc/Areas.cpp
Normal file
476
module/Misc/Areas.cpp
Normal 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
716
module/Misc/Areas.hpp
Normal 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
712
module/Misc/Broadcast.cpp
Normal 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
1178
module/Misc/Command.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2043
module/Misc/Command.hpp
Normal file
2043
module/Misc/Command.hpp
Normal file
File diff suppressed because it is too large
Load Diff
1272
module/Misc/Constants.cpp
Normal file
1272
module/Misc/Constants.cpp
Normal file
File diff suppressed because it is too large
Load Diff
291
module/Misc/Exports.cpp
Normal file
291
module/Misc/Exports.cpp
Normal 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
872
module/Misc/Functions.cpp
Normal 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
496
module/Misc/Functions.hpp
Normal 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
111
module/Misc/Model.cpp
Normal 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
32
module/Misc/Model.hpp
Normal 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
763
module/Misc/Player.cpp
Normal 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
32
module/Misc/Player.hpp
Normal 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
168
module/Misc/Register.cpp
Normal 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
362
module/Misc/Routine.cpp
Normal 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
644
module/Misc/Routine.hpp
Normal 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
1716
module/Misc/Signal.cpp
Normal file
File diff suppressed because it is too large
Load Diff
767
module/Misc/Signal.hpp
Normal file
767
module/Misc/Signal.hpp
Normal 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
524
module/Misc/Tasks.cpp
Normal 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
527
module/Misc/Tasks.hpp
Normal 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
708
module/Misc/Vehicle.cpp
Normal 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
32
module/Misc/Vehicle.hpp
Normal 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
438
module/Misc/Weapon.cpp
Normal 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
62
module/Misc/Weapon.hpp
Normal 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_
|
||||
Reference in New Issue
Block a user