mirror of
https://github.com/JezuzLizard/T4SP-Server-Plugin.git
synced 2025-04-19 21:22:54 +00:00
Add script errors for added builtins.
Fix generatepath() to return nodenums instead of pathnodes to workaround an obscure VM bug which is caused by sending a random origin as an argument and returning pathnodes.
This commit is contained in:
parent
bb8233cf86
commit
4135e7653a
@ -4,6 +4,7 @@
|
|||||||
#include <json.hpp>
|
#include <json.hpp>
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/string.hpp>
|
||||||
|
|
||||||
namespace gsc
|
namespace gsc
|
||||||
{
|
{
|
||||||
@ -250,6 +251,7 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
if (ent.classnum != game::CLASS_NUM_ENTITY)
|
if (ent.classnum != game::CLASS_NUM_ENTITY)
|
||||||
{
|
{
|
||||||
|
game::Scr_Error("Not an entity", game::SCRIPTINSTANCE_SERVER, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,6 +264,7 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
||||||
{
|
{
|
||||||
|
game::Scr_Error("Not a pathnode", game::SCRIPTINSTANCE_SERVER, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +285,7 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
||||||
{
|
{
|
||||||
|
game::Scr_Error("Not a pathnode", game::SCRIPTINSTANCE_SERVER, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,8 +300,15 @@ namespace gsc
|
|||||||
{
|
{
|
||||||
auto node_num = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 0);
|
auto node_num = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 0);
|
||||||
|
|
||||||
if (node_num < 0 || node_num >= game::g_path->actualNodeCount)
|
if (node_num == game::g_path->actualNodeCount)
|
||||||
{
|
{
|
||||||
|
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node_num < 0 || node_num > game::g_path->actualNodeCount)
|
||||||
|
{
|
||||||
|
game::Scr_Error(utils::string::va("Number %d is not valid for a node", node_num), game::SCRIPTINSTANCE_SERVER, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,15 +325,39 @@ namespace gsc
|
|||||||
|
|
||||||
float goal_pos[3] = {};
|
float goal_pos[3] = {};
|
||||||
|
|
||||||
auto team = game::TEAM_ALLIES;
|
auto team = "neutral"s;
|
||||||
|
|
||||||
|
auto allow_negotiation_links = false;
|
||||||
|
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 0, start_pos);
|
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 0, start_pos);
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 1, goal_pos);
|
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 1, goal_pos);
|
||||||
|
|
||||||
auto success = game::Path_FindPath(path.get(), team, start_pos, goal_pos, true);
|
if (game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 3)
|
||||||
|
{
|
||||||
|
if (game::Scr_GetType(game::SCRIPTINSTANCE_SERVER, 2) != game::VAR_UNDEFINED)
|
||||||
|
{
|
||||||
|
team = game::Scr_GetString(game::SCRIPTINSTANCE_SERVER, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) >= 4)
|
||||||
|
{
|
||||||
|
allow_negotiation_links = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!game::team_map.contains(team))
|
||||||
|
{
|
||||||
|
game::Scr_Error(utils::string::va("Team %s is not valid", team.data()), game::SCRIPTINSTANCE_SERVER, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto eTeam = game::team_map.at(team);
|
||||||
|
|
||||||
|
auto success = game::Path_FindPath(path.get(), eTeam, start_pos, goal_pos, allow_negotiation_links);
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
|
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,9 +365,8 @@ namespace gsc
|
|||||||
|
|
||||||
for (auto i = 0; i < path->wPathLen; i++)
|
for (auto i = 0; i < path->wPathLen; i++)
|
||||||
{
|
{
|
||||||
auto node_in_path = &(*game::gameWorldCurrent)->path.nodes[path->pts[i].iNodeNum];
|
//Return the number of the node instead of the node itself because of spooky GSC VM corruption
|
||||||
|
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, path->pts[i].iNodeNum);
|
||||||
game::Scr_AddPathnode(game::SCRIPTINSTANCE_SERVER, node_in_path);
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -23,6 +23,15 @@ namespace game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, team_t> team_map =
|
||||||
|
{
|
||||||
|
{ "free", TEAM_FREE },
|
||||||
|
{ "axis", TEAM_AXIS },
|
||||||
|
{ "allies", TEAM_ALLIES },
|
||||||
|
{ "neutral", TEAM_NEUTRAL },
|
||||||
|
{ "dead", TEAM_DEAD }
|
||||||
|
};
|
||||||
|
|
||||||
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index)
|
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index)
|
||||||
{
|
{
|
||||||
static const auto call_addr = SELECT(0x0, 0x699C50);
|
static const auto call_addr = SELECT(0x0, 0x699C50);
|
||||||
@ -252,13 +261,13 @@ namespace game
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scr_AddEntityNum(scriptInstance_t inst, unsigned short entid)
|
void Scr_AddEntityNum(scriptInstance_t inst, unsigned int entid)
|
||||||
{
|
{
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A770);
|
static const auto call_addr = SELECT(0x0, 0x69A770);
|
||||||
|
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
movzx esi, entid;
|
mov esi, entid;
|
||||||
mov eax, inst;
|
mov eax, inst;
|
||||||
call call_addr;
|
call call_addr;
|
||||||
}
|
}
|
||||||
@ -282,8 +291,8 @@ namespace game
|
|||||||
|
|
||||||
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node)
|
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node)
|
||||||
{
|
{
|
||||||
int entnum = node - (*gameWorldCurrent)->path.nodes;
|
unsigned int entnum = node - (*gameWorldCurrent)->path.nodes;
|
||||||
int entid = Scr_GetEntityId(inst, entnum, CLASS_NUM_PATHNODE, 0);
|
auto entid = Scr_GetEntityId(inst, entnum, CLASS_NUM_PATHNODE, 0);
|
||||||
Scr_AddEntityNum(inst, entid);
|
Scr_AddEntityNum(inst, entid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +319,41 @@ namespace game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int Scr_GetNumParam(scriptInstance_t inst)
|
||||||
|
{
|
||||||
|
return scrVmPub[inst].outparamcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
VariableType Scr_GetType(scriptInstance_t inst, unsigned int index)
|
||||||
|
{
|
||||||
|
static const auto call_addr = SELECT(0x0, 0x69A4E0);
|
||||||
|
VariableType answer;
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, inst;
|
||||||
|
mov ecx, index;
|
||||||
|
call call_addr;
|
||||||
|
mov answer, eax;
|
||||||
|
}
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scr_Error(const char* err, scriptInstance_t inst, bool is_terminal)
|
||||||
|
{
|
||||||
|
static const auto call_addr = SELECT(0x0, 0x69AB70);
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push is_terminal;
|
||||||
|
mov edi, inst;
|
||||||
|
mov ecx, err;
|
||||||
|
call call_addr;
|
||||||
|
add esp, 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char* SL_ConvertToString(scriptInstance_t inst, int id)
|
const char* SL_ConvertToString(scriptInstance_t inst, int id)
|
||||||
{
|
{
|
||||||
static const auto call_addr = SELECT(0x0, 0x68D950);
|
static const auto call_addr = SELECT(0x0, 0x68D950);
|
||||||
|
@ -21,6 +21,8 @@ namespace game
|
|||||||
bool t4sp();
|
bool t4sp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern std::map<std::string, team_t> team_map;
|
||||||
|
|
||||||
const char* Cmd_Argv(int index);
|
const char* Cmd_Argv(int index);
|
||||||
unsigned int Cmd_Argc();
|
unsigned int Cmd_Argc();
|
||||||
void Cmd_AddCommand(const char* name, void(__cdecl* function)());
|
void Cmd_AddCommand(const char* name, void(__cdecl* function)());
|
||||||
@ -28,28 +30,31 @@ namespace game
|
|||||||
dvar_s* Dvar_RegisterInt(const char* name, int value, int min, int max, DvarFlags flags, const char* desc);
|
dvar_s* Dvar_RegisterInt(const char* name, int value, int min, int max, DvarFlags flags, const char* desc);
|
||||||
dvar_s* Dvar_RegisterString(const char* name, const char* value, DvarFlags flags, const char* desc);
|
dvar_s* Dvar_RegisterString(const char* name, const char* value, DvarFlags flags, const char* desc);
|
||||||
|
|
||||||
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index); //testing
|
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index);
|
||||||
void Scr_AddInt(game::scriptInstance_t inst, int value); //testing
|
void Scr_AddInt(game::scriptInstance_t inst, int value);
|
||||||
float Scr_GetFloat(game::scriptInstance_t inst, unsigned int arg_index); //testing
|
float Scr_GetFloat(game::scriptInstance_t inst, unsigned int arg_index);
|
||||||
void Scr_AddFloat(game::scriptInstance_t inst, float value); //testing
|
void Scr_AddFloat(game::scriptInstance_t inst, float value);
|
||||||
char* Scr_GetString(game::scriptInstance_t inst, unsigned int arg_index); //testing
|
char* Scr_GetString(game::scriptInstance_t inst, unsigned int arg_index);
|
||||||
void Scr_AddString(game::scriptInstance_t inst, const char* string); //testing
|
void Scr_AddString(game::scriptInstance_t inst, const char* string);
|
||||||
const char* Scr_GetIString(game::scriptInstance_t inst, unsigned int arg_index); //testing
|
const char* Scr_GetIString(game::scriptInstance_t inst, unsigned int arg_index);
|
||||||
void Scr_AddIString(game::scriptInstance_t inst, const char* string); //testing
|
void Scr_AddIString(game::scriptInstance_t inst, const char* string);
|
||||||
unsigned short Scr_GetConstString(game::scriptInstance_t inst, unsigned int arg_index); //testing
|
unsigned short Scr_GetConstString(game::scriptInstance_t inst, unsigned int arg_index);
|
||||||
void Scr_AddConstString(game::scriptInstance_t inst, unsigned short id); //testing
|
void Scr_AddConstString(game::scriptInstance_t inst, unsigned short id);
|
||||||
void Scr_GetVector(game::scriptInstance_t inst, unsigned int arg_index, float* value); //testing
|
void Scr_GetVector(game::scriptInstance_t inst, unsigned int arg_index, float* value);
|
||||||
void Scr_AddVector(game::scriptInstance_t inst, float* value); //testing
|
void Scr_AddVector(game::scriptInstance_t inst, float* value);
|
||||||
void Scr_AddUndefined(game::scriptInstance_t inst); //testing
|
void Scr_AddUndefined(game::scriptInstance_t inst);
|
||||||
gentity_s* Scr_GetEntity(unsigned int arg_index); //testing
|
gentity_s* Scr_GetEntity(unsigned int arg_index);
|
||||||
void Scr_AddEntity(game::scriptInstance_t inst, gentity_s* ent); //testing
|
void Scr_AddEntity(game::scriptInstance_t inst, gentity_s* ent);
|
||||||
unsigned int Scr_GetEntityId(scriptInstance_t inst, int entNum, classNum_e classnum, unsigned int clientnum); //testing
|
unsigned int Scr_GetEntityId(scriptInstance_t inst, int entNum, classNum_e classnum, unsigned int clientnum);
|
||||||
void Scr_AddEntityNum(scriptInstance_t inst, unsigned short entid); //testing
|
void Scr_AddEntityNum(scriptInstance_t inst, unsigned int entid);
|
||||||
pathnode_t* Scr_GetPathnode(scriptInstance_t inst); //testing
|
pathnode_t* Scr_GetPathnode(scriptInstance_t inst);
|
||||||
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node); //testing
|
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node);
|
||||||
void Scr_MakeArray(scriptInstance_t inst); //testing
|
void Scr_MakeArray(scriptInstance_t inst);
|
||||||
void Scr_AddArrayStringIndexed(scriptInstance_t inst, unsigned short id); //testing
|
void Scr_AddArrayStringIndexed(scriptInstance_t inst, unsigned short id);
|
||||||
const char* SL_ConvertToString(scriptInstance_t inst, int id); //testing
|
unsigned int Scr_GetNumParam(scriptInstance_t inst);
|
||||||
|
VariableType Scr_GetType(scriptInstance_t inst, unsigned int index);
|
||||||
|
void Scr_Error(const char* err, scriptInstance_t inst, bool is_terminal);
|
||||||
|
const char* SL_ConvertToString(scriptInstance_t inst, int id);
|
||||||
|
|
||||||
int Path_FindPath(path_t* pPath, team_t eTeam, float* vStartPos, float* vGoalPos, int bAllowNegotiationLinks);
|
int Path_FindPath(path_t* pPath, team_t eTeam, float* vStartPos, float* vGoalPos, int bAllowNegotiationLinks);
|
||||||
|
|
||||||
|
@ -15,6 +15,8 @@ namespace game
|
|||||||
struct animscripted_s;
|
struct animscripted_s;
|
||||||
union pathnode_tree_info_t;
|
union pathnode_tree_info_t;
|
||||||
struct pathnode_tree_t;
|
struct pathnode_tree_t;
|
||||||
|
struct VariableValue;
|
||||||
|
struct function_frame_t;
|
||||||
|
|
||||||
typedef float vec_t;
|
typedef float vec_t;
|
||||||
typedef vec_t vec2_t[2];
|
typedef vec_t vec2_t[2];
|
||||||
@ -396,7 +398,7 @@ namespace game
|
|||||||
int duration;
|
int duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum team_t : __int32
|
enum team_t
|
||||||
{
|
{
|
||||||
TEAM_FREE = 0x0,
|
TEAM_FREE = 0x0,
|
||||||
TEAM_BAD = 0x0,
|
TEAM_BAD = 0x0,
|
||||||
@ -407,14 +409,14 @@ namespace game
|
|||||||
TEAM_NUM_TEAMS = 0x5,
|
TEAM_NUM_TEAMS = 0x5,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MissileStage : __int32
|
enum MissileStage
|
||||||
{
|
{
|
||||||
MISSILESTAGE_SOFTLAUNCH = 0x0,
|
MISSILESTAGE_SOFTLAUNCH = 0x0,
|
||||||
MISSILESTAGE_ASCENT = 0x1,
|
MISSILESTAGE_ASCENT = 0x1,
|
||||||
MISSILESTAGE_DESCENT = 0x2,
|
MISSILESTAGE_DESCENT = 0x2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MissileFlightMode : __int32
|
enum MissileFlightMode
|
||||||
{
|
{
|
||||||
MISSILEFLIGHTMODE_TOP = 0x0,
|
MISSILEFLIGHTMODE_TOP = 0x0,
|
||||||
MISSILEFLIGHTMODE_DIRECT = 0x1,
|
MISSILEFLIGHTMODE_DIRECT = 0x1,
|
||||||
@ -1587,4 +1589,89 @@ namespace game
|
|||||||
unsigned int originErrors;
|
unsigned int originErrors;
|
||||||
pathlocal_t_circle circle;
|
pathlocal_t_circle circle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum VariableType
|
||||||
|
{
|
||||||
|
VAR_UNDEFINED = 0x0,
|
||||||
|
VAR_BEGIN_REF = 0x1,
|
||||||
|
VAR_POINTER = 0x1,
|
||||||
|
VAR_STRING = 0x2,
|
||||||
|
VAR_ISTRING = 0x3,
|
||||||
|
VAR_VECTOR = 0x4,
|
||||||
|
VAR_END_REF = 0x5,
|
||||||
|
VAR_FLOAT = 0x5,
|
||||||
|
VAR_INTEGER = 0x6,
|
||||||
|
VAR_CODEPOS = 0x7,
|
||||||
|
VAR_PRECODEPOS = 0x8,
|
||||||
|
VAR_FUNCTION = 0x9,
|
||||||
|
VAR_BUILTIN_FUNCTION = 0xA,
|
||||||
|
VAR_BUILTIN_METHOD = 0xB,
|
||||||
|
VAR_STACK = 0xC,
|
||||||
|
VAR_ANIMATION = 0xD,
|
||||||
|
VAR_PRE_ANIMATION = 0xE,
|
||||||
|
VAR_THREAD = 0xF,
|
||||||
|
VAR_NOTIFY_THREAD = 0x10,
|
||||||
|
VAR_TIME_THREAD = 0x11,
|
||||||
|
VAR_CHILD_THREAD = 0x12,
|
||||||
|
VAR_OBJECT = 0x13,
|
||||||
|
VAR_DEAD_ENTITY = 0x14,
|
||||||
|
VAR_ENTITY = 0x15,
|
||||||
|
VAR_ARRAY = 0x16,
|
||||||
|
VAR_DEAD_THREAD = 0x17,
|
||||||
|
VAR_COUNT = 0x18,
|
||||||
|
VAR_FREE = 0x18,
|
||||||
|
VAR_THREAD_LIST = 0x19,
|
||||||
|
VAR_ENDON_LIST = 0x1A,
|
||||||
|
VAR_TOTAL_COUNT = 0x1B,
|
||||||
|
};
|
||||||
|
|
||||||
|
union VariableUnion
|
||||||
|
{
|
||||||
|
int intValue;
|
||||||
|
float floatValue;
|
||||||
|
unsigned int stringValue;
|
||||||
|
const float* vectorValue;
|
||||||
|
const char* codePosValue;
|
||||||
|
unsigned int pointerValue;
|
||||||
|
char* stackValue;
|
||||||
|
unsigned int entityOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VariableValue
|
||||||
|
{
|
||||||
|
VariableUnion u;
|
||||||
|
VariableType type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct function_stack_t
|
||||||
|
{
|
||||||
|
const char* pos;
|
||||||
|
unsigned int localId;
|
||||||
|
unsigned int localVarCount;
|
||||||
|
VariableValue* top;
|
||||||
|
VariableValue* startTop;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct function_frame_t
|
||||||
|
{
|
||||||
|
function_stack_t fs;
|
||||||
|
int topType;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __declspec(align(4)) scrVmPub_t
|
||||||
|
{
|
||||||
|
int* localVars;
|
||||||
|
VariableValue* maxstack;
|
||||||
|
int function_count;
|
||||||
|
function_frame_t* function_frame;
|
||||||
|
VariableValue* top;
|
||||||
|
bool debugCode;
|
||||||
|
bool abort_on_error;
|
||||||
|
char terminal_error;
|
||||||
|
char field_17;
|
||||||
|
unsigned int inparamcount;
|
||||||
|
unsigned int outparamcount;
|
||||||
|
function_frame_t function_frame_start[32];
|
||||||
|
VariableValue stack[2048];
|
||||||
|
};
|
||||||
}
|
}
|
@ -23,6 +23,8 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<gentity_s> g_entities{ 0x0, 0x176C6F0 };
|
WEAK symbol<gentity_s> g_entities{ 0x0, 0x176C6F0 };
|
||||||
|
|
||||||
|
WEAK symbol<scrVmPub_t> scrVmPub{ 0x0, 0x3BD4700 };
|
||||||
|
|
||||||
namespace plutonium
|
namespace plutonium
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user