mirror of
https://github.com/JezuzLizard/T4SP-Server-Plugin.git
synced 2025-04-20 05:25:44 +00:00
major cleanup
This commit is contained in:
parent
3f71e99a0b
commit
cdad6184dd
@ -1,3 +1,3 @@
|
|||||||
@echo off
|
@echo off
|
||||||
call git submodule update --init --recursive
|
call git submodule update --init --recursive
|
||||||
tools\windows\premake5.exe vs2022
|
premake5.exe vs2022
|
13
premake5.lua
13
premake5.lua
@ -77,6 +77,8 @@ workspace "t4sp-server-plugin"
|
|||||||
"./src/**.h",
|
"./src/**.h",
|
||||||
"./src/**.hpp",
|
"./src/**.hpp",
|
||||||
"./src/**.cpp",
|
"./src/**.cpp",
|
||||||
|
"./src/**.c",
|
||||||
|
"./src/**.asm"
|
||||||
}
|
}
|
||||||
|
|
||||||
includedirs
|
includedirs
|
||||||
@ -96,5 +98,16 @@ workspace "t4sp-server-plugin"
|
|||||||
|
|
||||||
dependencies.imports()
|
dependencies.imports()
|
||||||
|
|
||||||
|
exceptionhandling ("Off")
|
||||||
|
|
||||||
|
if _OPTIONS["copy-to"] then
|
||||||
|
postbuildcommands {"copy /y \"$(TargetPath)\" \"" .. _OPTIONS["copy-to"] .. "\""}
|
||||||
|
else
|
||||||
|
postbuildcommands {
|
||||||
|
"if \"%COMPUTERNAME%\" == \"NEW-BUILT\" ( copy /y \"$(TargetPath)\" \"$(CODWAW_PATH)\\t4staging\\plugins\\\" )",
|
||||||
|
"if \"%COMPUTERNAME%\" == \"JEZUZLIZARD\" ( copy /y \"$(TargetPath)\" \"C:/Users/Jezuz/Desktop/re-T4SP\" )"
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
group "Dependencies"
|
group "Dependencies"
|
||||||
dependencies.projects()
|
dependencies.projects()
|
@ -1,575 +0,0 @@
|
|||||||
#include <stdinc.hpp>
|
|
||||||
#include "loader/component_loader.hpp"
|
|
||||||
|
|
||||||
#include "scheduler.hpp"
|
|
||||||
#include "component/gsc.hpp"
|
|
||||||
|
|
||||||
#include <json.hpp>
|
|
||||||
#include <utils/io.hpp>
|
|
||||||
#include <utils/hook.hpp>
|
|
||||||
#include <utils/string.hpp>
|
|
||||||
|
|
||||||
namespace ai
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
int Path_GeneratePath_custom(game::path_t* pPath, game::team_t eTeam, const float* vStartPos, const float* vGoalPos, game::pathnode_t* pNodeFrom, game::pathnode_t* pNodeTo, int bIncludeGoalPos, int bAllowNegotiationLinks)
|
|
||||||
{
|
|
||||||
const char* v9; // eax
|
|
||||||
float v10; // [esp+10h] [ebp-68h]
|
|
||||||
int v12; // [esp+18h] [ebp-60h]
|
|
||||||
game::pathpoint_t* v16; // [esp+30h] [ebp-48h]
|
|
||||||
game::pathpoint_t* v17; // [esp+38h] [ebp-40h]
|
|
||||||
int excess; // [esp+54h] [ebp-24h]
|
|
||||||
game::pathnode_t* pPrevNode; // [esp+58h] [ebp-20h]
|
|
||||||
int iTotal; // [esp+5Ch] [ebp-1Ch]
|
|
||||||
game::pathnode_t* pNode; // [esp+64h] [ebp-14h]
|
|
||||||
game::pathnode_t* pNodea; // [esp+64h] [ebp-14h]
|
|
||||||
int negotiationStartNode; // [esp+68h] [ebp-10h]
|
|
||||||
int i; // [esp+6Ch] [ebp-Ch]
|
|
||||||
int ia; // [esp+6Ch] [ebp-Ch]
|
|
||||||
game::pathnode_t* pPrevPrevNode; // [esp+70h] [ebp-8h]
|
|
||||||
int prevFlags; // [esp+74h] [ebp-4h]
|
|
||||||
|
|
||||||
game::Path_AddTrimmedAmount(vStartPos, pPath);
|
|
||||||
iTotal = 0;
|
|
||||||
pNode = pNodeTo;
|
|
||||||
if (bIncludeGoalPos)
|
|
||||||
{
|
|
||||||
pPath->pts[0].vOrigPoint[0] = *vGoalPos;
|
|
||||||
pPath->pts[0].vOrigPoint[1] = vGoalPos[1];
|
|
||||||
pPath->pts[0].vOrigPoint[2] = vGoalPos[2];
|
|
||||||
if (*vGoalPos == pNodeTo->constant.vOrigin[0] && vGoalPos[1] == pNodeTo->constant.vOrigin[1])
|
|
||||||
{
|
|
||||||
pPath->pts[0].iNodeNum = game::Path_ConvertNodeToIndex(pNodeTo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pPath->pts[0].iNodeNum = -1;
|
|
||||||
iTotal = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pPath->pts[0].vOrigPoint[0] = pNodeTo->constant.vOrigin[0];
|
|
||||||
pPath->pts[0].vOrigPoint[1] = pNodeTo->constant.vOrigin[1];
|
|
||||||
pPath->pts[0].vOrigPoint[2] = pNodeTo->constant.vOrigin[2];
|
|
||||||
pPath->pts[0].iNodeNum = game::Path_ConvertNodeToIndex(pNodeTo);
|
|
||||||
}
|
|
||||||
prevFlags = pPath->flags;
|
|
||||||
pPath->flags = 0;
|
|
||||||
if (!pPath->wPathLen
|
|
||||||
|| (pPath->pts[0].vOrigPoint[0] != pPath->vFinalGoal[0]
|
|
||||||
|| pPath->pts[0].vOrigPoint[1] != pPath->vFinalGoal[1]
|
|
||||||
|| pPath->pts[0].vOrigPoint[2] != pPath->vFinalGoal[2] ? (v12 = 0) : (v12 = 1),
|
|
||||||
!v12))
|
|
||||||
{
|
|
||||||
if (pPath->pts[0].vOrigPoint[0] != pPath->vFinalGoal[0] || pPath->pts[0].vOrigPoint[1] != pPath->vFinalGoal[1])
|
|
||||||
{
|
|
||||||
pPath->iPathEndTime = 0;
|
|
||||||
}
|
|
||||||
pPath->vFinalGoal[0] = pPath->pts[0].vOrigPoint[0];
|
|
||||||
pPath->vFinalGoal[1] = pPath->pts[0].vOrigPoint[1];
|
|
||||||
pPath->vFinalGoal[2] = pPath->pts[0].vOrigPoint[2];
|
|
||||||
}
|
|
||||||
game::Path_Clear(pPath);
|
|
||||||
pPath->wDodgeCount = 0;
|
|
||||||
negotiationStartNode = 0;
|
|
||||||
if (pNodeTo)
|
|
||||||
{
|
|
||||||
for (pPrevNode = pNodeTo->transient.pParent; ; pPrevNode = pPrevPrevNode)
|
|
||||||
{
|
|
||||||
++iTotal;
|
|
||||||
if (pNode == pNodeFrom)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (pPrevNode->constant.type == game::NODE_NEGOTIATION_BEGIN
|
|
||||||
&& pNode->constant.type == game::NODE_NEGOTIATION_END
|
|
||||||
&& pPrevNode->constant.target == pNode->constant.targetname)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
if (!bAllowNegotiationLinks)
|
|
||||||
return 0;
|
|
||||||
*/
|
|
||||||
negotiationStartNode = iTotal;
|
|
||||||
}
|
|
||||||
pPrevPrevNode = pPrevNode->transient.pParent;
|
|
||||||
pPrevNode->transient.pParent = pNode;
|
|
||||||
pNode = pPrevNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
excess = iTotal - 32;
|
|
||||||
if (iTotal - 32 > 0)
|
|
||||||
{
|
|
||||||
iTotal = 32;
|
|
||||||
pPath->flags |= 4u;
|
|
||||||
negotiationStartNode -= excess;
|
|
||||||
if (negotiationStartNode < 0)
|
|
||||||
{
|
|
||||||
*reinterpret_cast<unsigned short*>(&negotiationStartNode) = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i = iTotal - 1;
|
|
||||||
pNodea = pNodeFrom;
|
|
||||||
while (i > 0)
|
|
||||||
{
|
|
||||||
v17 = &pPath->pts[i];
|
|
||||||
v17->vOrigPoint[0] = pNodea->constant.vOrigin[0];
|
|
||||||
v17->vOrigPoint[1] = pNodea->constant.vOrigin[1];
|
|
||||||
v17->vOrigPoint[2] = pNodea->constant.vOrigin[2];
|
|
||||||
v17->iNodeNum = game::Path_ConvertNodeToIndex(pNodea);
|
|
||||||
--i;
|
|
||||||
pNodea = pNodea->transient.pParent;
|
|
||||||
}
|
|
||||||
if (excess > 0)
|
|
||||||
{
|
|
||||||
pPath->pts[0].vOrigPoint[0] = pNodea->constant.vOrigin[0];
|
|
||||||
pPath->pts[0].vOrigPoint[1] = pNodea->constant.vOrigin[1];
|
|
||||||
pPath->pts[0].vOrigPoint[2] = pNodea->constant.vOrigin[2];
|
|
||||||
pPath->pts[0].iNodeNum = game::Path_ConvertNodeToIndex(pNodea);
|
|
||||||
}
|
|
||||||
pPath->wNegotiationStartNode = negotiationStartNode;
|
|
||||||
if (pPath->wNegotiationStartNode > 0)
|
|
||||||
{
|
|
||||||
game::Path_IncrementNodeUserCount(pPath);
|
|
||||||
}
|
|
||||||
pPath->pts[iTotal - 1].fOrigLength = 0.0;
|
|
||||||
pPath->pts[iTotal - 1].fDir2D[0] = 0.0;
|
|
||||||
pPath->pts[iTotal - 1].fDir2D[1] = 0.0;
|
|
||||||
v16 = &pPath->pts[iTotal - 1];
|
|
||||||
pPath->vCurrPoint[0] = v16->vOrigPoint[0];
|
|
||||||
pPath->vCurrPoint[1] = v16->vOrigPoint[1];
|
|
||||||
pPath->vCurrPoint[2] = v16->vOrigPoint[2];
|
|
||||||
for (ia = 0; ia < iTotal - 1; ++ia)
|
|
||||||
{
|
|
||||||
pPath->pts[ia].fOrigLength = game::Path_GetPathDir(
|
|
||||||
pPath->pts[ia].fDir2D,
|
|
||||||
pPath->pts[ia + 1].vOrigPoint,
|
|
||||||
pPath->pts[ia].vOrigPoint);
|
|
||||||
}
|
|
||||||
if (iTotal <= 1)
|
|
||||||
{
|
|
||||||
v10 = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v10 = pPath->pts[iTotal - 2].fOrigLength;
|
|
||||||
}
|
|
||||||
pPath->fCurrLength = v10;
|
|
||||||
pPath->wPathLen = iTotal;
|
|
||||||
pPath->wOrigPathLen = pPath->wPathLen;
|
|
||||||
if (bAllowNegotiationLinks)
|
|
||||||
{
|
|
||||||
pPath->flags |= 0x10u;
|
|
||||||
}
|
|
||||||
pPath->eTeam = eTeam;
|
|
||||||
pPath->iPathTime = game::level->time;
|
|
||||||
if (pPath->fLookaheadAmount == 0.0)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if ((prevFlags & 0x180) != 0)
|
|
||||||
{
|
|
||||||
if ((prevFlags & 0x80) != 0)
|
|
||||||
{
|
|
||||||
pPath->fLookaheadAmount = 32768.0;
|
|
||||||
pPath->minLookAheadNodes = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pPath->fLookaheadAmount = 4096.0;
|
|
||||||
pPath->minLookAheadNodes = 2;
|
|
||||||
}
|
|
||||||
pPath->lookaheadDir[0] = 0.0;
|
|
||||||
pPath->lookaheadDir[1] = 0.0;
|
|
||||||
pPath->lookaheadDir[2] = 0.0;
|
|
||||||
game::Path_UpdateLookahead(pPath, vStartPos, 0, 0, 1);
|
|
||||||
pPath->minLookAheadNodes = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
game::Path_TransferLookahead(pPath, vStartPos);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __cdecl Path_AStarAlgorithm_CustomSearchInfo_FindPath_custom(game::path_t* pPath, game::team_t eTeam, float* vStartPos, game::pathnode_t* pNodeFrom, float* vGoalPos, int bIncludeGoalInPath, const std::unordered_set<unsigned short>& allowedNegotiationLinks, game::CustomSearchInfo_FindPath* custom, int bIgnoreBadPlaces)
|
|
||||||
{
|
|
||||||
int success; // [esp+28h] [ebp-A0h]
|
|
||||||
game::pathnode_t* pCurrent; // [esp+2Ch] [ebp-9Ch]
|
|
||||||
game::pathnode_t TopParent; // [esp+30h] [ebp-98h] BYREF
|
|
||||||
float fApproxTotalCost; // [esp+B4h] [ebp-14h]
|
|
||||||
game::pathnode_t* pInsert; // [esp+B8h] [ebp-10h]
|
|
||||||
int i; // [esp+BCh] [ebp-Ch]
|
|
||||||
float fCost; // [esp+C0h] [ebp-8h]
|
|
||||||
game::pathnode_t* pSuccessor; // [esp+C4h] [ebp-4h]
|
|
||||||
|
|
||||||
pNodeFrom->transient.iSearchFrame = ++game::level->iSearchFrame;
|
|
||||||
pNodeFrom->transient.pParent = &TopParent;
|
|
||||||
pNodeFrom->transient.pNextOpen = 0;
|
|
||||||
pNodeFrom->transient.pPrevOpen = &TopParent;
|
|
||||||
pNodeFrom->transient.fCost = 0.0;
|
|
||||||
TopParent.transient.pNextOpen = pNodeFrom;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!TopParent.transient.pNextOpen)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCurrent = TopParent.transient.pNextOpen;
|
|
||||||
|
|
||||||
if (TopParent.transient.pNextOpen == custom->m_pNodeTo)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TopParent.transient.pNextOpen = TopParent.transient.pNextOpen->transient.pNextOpen;
|
|
||||||
if (TopParent.transient.pNextOpen)
|
|
||||||
{
|
|
||||||
TopParent.transient.pNextOpen->transient.pPrevOpen = &TopParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pCurrent->dynamic.wLinkCount; ++i)
|
|
||||||
{
|
|
||||||
if (bIgnoreBadPlaces || !pCurrent->constant.Links[i].ubBadPlaceCount[eTeam])
|
|
||||||
{
|
|
||||||
pSuccessor = game::Path_ConvertIndexToNode(pCurrent->constant.Links[i].nodeNum);
|
|
||||||
if (pCurrent->constant.type == game::NODE_NEGOTIATION_BEGIN && pSuccessor->constant.type == game::NODE_NEGOTIATION_END)
|
|
||||||
{
|
|
||||||
if (std::find(allowedNegotiationLinks.begin(), allowedNegotiationLinks.end(), pCurrent->constant.animscript) == allowedNegotiationLinks.end())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pCurrent->constant.type != game::NODE_NEGOTIATION_BEGIN
|
|
||||||
|| pSuccessor->constant.type != game::NODE_NEGOTIATION_END
|
|
||||||
|| (pCurrent->dynamic.wOverlapCount == 0 && pSuccessor->dynamic.wOverlapCount == 0))
|
|
||||||
{
|
|
||||||
if (pSuccessor->transient.iSearchFrame == game::level->iSearchFrame)
|
|
||||||
{
|
|
||||||
fCost = (pCurrent->constant.Links[i].fDist * 1.0) + pCurrent->transient.fCost;
|
|
||||||
if (fCost >= pSuccessor->transient.fCost)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pSuccessor->transient.pPrevOpen)
|
|
||||||
{
|
|
||||||
pSuccessor->transient.pPrevOpen->transient.pNextOpen = pSuccessor->transient.pNextOpen;
|
|
||||||
if (pSuccessor->transient.pNextOpen)
|
|
||||||
{
|
|
||||||
pSuccessor->transient.pNextOpen->transient.pPrevOpen = pSuccessor->transient.pPrevOpen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pSuccessor->transient.iSearchFrame = game::level->iSearchFrame;
|
|
||||||
pSuccessor->transient.fHeuristic = game::EvaluateHeuristic(custom, pSuccessor, vGoalPos);
|
|
||||||
fCost = (pCurrent->constant.Links[i].fDist * 1.0) + pCurrent->transient.fCost;
|
|
||||||
}
|
|
||||||
|
|
||||||
pSuccessor->transient.pParent = pCurrent;
|
|
||||||
pSuccessor->transient.fCost = fCost;
|
|
||||||
fApproxTotalCost = pSuccessor->transient.fCost + pSuccessor->transient.fHeuristic;
|
|
||||||
|
|
||||||
for (pInsert = &TopParent;
|
|
||||||
pInsert->transient.pNextOpen
|
|
||||||
&& (pInsert->transient.pNextOpen->transient.fCost
|
|
||||||
+ pInsert->transient.pNextOpen->transient.fHeuristic) < fApproxTotalCost;
|
|
||||||
pInsert = pInsert->transient.pNextOpen)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
pSuccessor->transient.pPrevOpen = pInsert;
|
|
||||||
pSuccessor->transient.pNextOpen = pInsert->transient.pNextOpen;
|
|
||||||
pInsert->transient.pNextOpen = pSuccessor;
|
|
||||||
|
|
||||||
if (pSuccessor->transient.pNextOpen)
|
|
||||||
{
|
|
||||||
pSuccessor->transient.pNextOpen->transient.pPrevOpen = pSuccessor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pCurrent->transient.pPrevOpen = 0;
|
|
||||||
}
|
|
||||||
if (!pPath)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
success = Path_GeneratePath_custom(
|
|
||||||
pPath,
|
|
||||||
eTeam,
|
|
||||||
vStartPos,
|
|
||||||
vGoalPos,
|
|
||||||
pNodeFrom,
|
|
||||||
TopParent.transient.pNextOpen,
|
|
||||||
bIncludeGoalInPath,
|
|
||||||
true);
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
//Original
|
|
||||||
int __userpurge Path_FindPathFromTo@<eax>(float *startPos@<eax>, pathnode_t *pNodeTo@<edx>, path_t *pPath, team_t eTeam, pathnode_t *pNodeFrom, float *vGoalPos, int bAllowNegotiationLinks, int bIgnoreBadplaces)
|
|
||||||
{
|
|
||||||
int v8; // xmm0_4
|
|
||||||
CustomSearchInfo_FindPath info; // [esp+0h] [ebp-14h] BYREF
|
|
||||||
|
|
||||||
v8 = ai_pathNegotiationOverlapCost->current.integer;
|
|
||||||
info.m_pNodeTo = pNodeTo;
|
|
||||||
LODWORD(info.negotiationOverlapCost) = v8;
|
|
||||||
info.startPos[0] = *startPos;
|
|
||||||
info.startPos[1] = startPos[1];
|
|
||||||
info.startPos[2] = startPos[2];
|
|
||||||
return Path_AStarAlgorithm_CustomSearchInfo_FindPath_(pPath, eTeam, startPos, pNodeFrom, vGoalPos, bAllowNegotiationLinks, &info, bIgnoreBadplaces, pNodeTo);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int Path_FindPathFromTo_custom(float* startPos, game::pathnode_t* pNodeTo, game::path_t* pPath, game::team_t eTeam, game::pathnode_t* pNodeFrom, float* vGoalPos, const std::unordered_set<unsigned short>& allowedNegotiationLinks, int bIgnoreBadplaces)
|
|
||||||
{
|
|
||||||
game::CustomSearchInfo_FindPath info = {}; // [esp+0h] [ebp-14h] BYREF
|
|
||||||
|
|
||||||
info.m_pNodeTo = pNodeTo;
|
|
||||||
info.negotiationOverlapCost = (*game::ai_pathNegotiationOverlapCost)->current.integer;
|
|
||||||
info.startPos[0] = startPos[0];
|
|
||||||
info.startPos[1] = startPos[1];
|
|
||||||
info.startPos[2] = startPos[2];
|
|
||||||
return Path_AStarAlgorithm_CustomSearchInfo_FindPath_custom(pPath, eTeam, startPos, pNodeFrom, vGoalPos, true, allowedNegotiationLinks, &info, bIgnoreBadplaces);;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
//Original
|
|
||||||
int __userpurge Path_FindPath@<eax>(path_t* pPath@<ecx>, team_t eTeam@<edx>, float* vStartPos, float* vGoalPos, int bAllowNegotiationLinks)
|
|
||||||
{
|
|
||||||
pathnode_t* pNodeTo; // esi
|
|
||||||
int result; // eax
|
|
||||||
pathnode_t* pNodeFrom; // eax
|
|
||||||
int a9; // [esp+2Ch] [ebp-304h] BYREF
|
|
||||||
int a4[192]; // [esp+30h] [ebp-300h] BYREF
|
|
||||||
|
|
||||||
pNodeTo = Path_NearestNodeNotCrossPlanes(NAN, COERCE_FLOAT(64), (int)vGoalPos, (int)a4, 192.0, 0, 0, 0, (int)&a9, 0);
|
|
||||||
if (pNodeTo && (pNodeFrom = Path_NearestNodeNotCrossPlanes(NAN, COERCE_FLOAT(64), (int)vStartPos, (int)a4, 192.0, 0, 0, 0, (int)&a9, 0)) != 0)
|
|
||||||
result = Path_FindPathFromTo(vStartPos, pNodeTo, pPath, eTeam, pNodeFrom, vGoalPos, bAllowNegotiationLinks, 0);
|
|
||||||
else
|
|
||||||
result = 0;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int Path_FindPath_custom(game::path_t* pPath, game::team_t eTeam, float* vStartPos, float* vGoalPos, const std::unordered_set<unsigned short>& allowedNegotiationLinks)
|
|
||||||
{
|
|
||||||
int result; // eax
|
|
||||||
int returnCount = 0; // [esp+2Ch] [ebp-304h] BYREF
|
|
||||||
const int maxNodes = 64;
|
|
||||||
auto nodes = std::make_unique<game::pathsort_t[]>(maxNodes);
|
|
||||||
|
|
||||||
game::pathnode_t* pNodeTo = game::Path_NearestNodeNotCrossPlanes(-2, maxNodes, vGoalPos, nodes.get(), 192.0f, 0.0f, 0.0f, 0.0f, &returnCount, game::NEAREST_NODE_DO_HEIGHT_CHECK);
|
|
||||||
if (!pNodeTo)
|
|
||||||
{
|
|
||||||
//printf("Couldn't find the node to\n");
|
|
||||||
}
|
|
||||||
game::pathnode_t* pNodeFrom = game::Path_NearestNodeNotCrossPlanes(-2, maxNodes, vStartPos, nodes.get(), 192.0f, 0.0f, 0.0f, 0.0f, &returnCount, game::NEAREST_NODE_DO_HEIGHT_CHECK);
|
|
||||||
if (pNodeTo && pNodeFrom)
|
|
||||||
{
|
|
||||||
result = Path_FindPathFromTo_custom(vStartPos, pNodeTo, pPath, eTeam, pNodeFrom, vGoalPos, allowedNegotiationLinks, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int actor_spawned_callback_handle = 0;
|
|
||||||
|
|
||||||
void actor_spawned_callback(game::actor_s* actor)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4B5550);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov esi, actor;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!actor_spawned_callback_handle)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto id = game::Scr_ExecEntThread(game::SCRIPTINSTANCE_SERVER, actor->ent->s.number, actor_spawned_callback_handle, 0, game::CLASS_NUM_ENTITY);
|
|
||||||
game::RemoveRefToObject(game::SCRIPTINSTANCE_SERVER, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __declspec(naked) actor_spawned_callback_stub()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push esi;
|
|
||||||
call actor_spawned_callback;
|
|
||||||
add esp, 0x4;
|
|
||||||
retn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class component final : public component_interface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void post_unpack() override
|
|
||||||
{
|
|
||||||
//Add support for codecallback_actorspawned GSC callback
|
|
||||||
utils::hook::call(0x4E06EB, actor_spawned_callback_stub);
|
|
||||||
//Initialize handle for codecallback_actorspawned
|
|
||||||
scheduler::on_postloadscripts([]()
|
|
||||||
{
|
|
||||||
int found_script = game::Scr_LoadScript("scripts/sp/callbacks_ext", game::SCRIPTINSTANCE_SERVER);
|
|
||||||
if (found_script)
|
|
||||||
{
|
|
||||||
actor_spawned_callback_handle = game::Scr_GetFunctionHandle(game::SCRIPTINSTANCE_SERVER, "scripts/sp/callbacks_ext", "codecallback_actorspawned");
|
|
||||||
printf("Adding actor_spawned_callback_handle\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Could not find callbacks_ext.gsc\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//utils::hook::jump(0x4CF280, Path_FindPath_stub);
|
|
||||||
|
|
||||||
gsc::method::add("getlinkednodes", [](game::scr_entref_s ent)
|
|
||||||
{
|
|
||||||
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
|
||||||
{
|
|
||||||
game::Scr_Error("Not a pathnode", game::SCRIPTINSTANCE_SERVER, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto primary_node = &(*game::gameWorldCurrent)->path.nodes[ent.entnum];
|
|
||||||
|
|
||||||
game::Scr_MakeArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
for (auto i = 0; i < primary_node->constant.totalLinkCount; i++)
|
|
||||||
{
|
|
||||||
auto linked_node = &(*game::gameWorldCurrent)->path.nodes[primary_node->constant.Links[i].nodeNum];
|
|
||||||
|
|
||||||
game::Scr_AddPathnode(game::SCRIPTINSTANCE_SERVER, linked_node);
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gsc::method::add("getnodenumber", [](game::scr_entref_s ent)
|
|
||||||
{
|
|
||||||
if (ent.classnum != game::CLASS_NUM_PATHNODE)
|
|
||||||
{
|
|
||||||
game::Scr_Error("Not a pathnode", game::SCRIPTINSTANCE_SERVER, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node = &(*game::gameWorldCurrent)->path.nodes[ent.entnum];
|
|
||||||
|
|
||||||
auto entnum = node - (*game::gameWorldCurrent)->path.nodes;
|
|
||||||
|
|
||||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, entnum);
|
|
||||||
});
|
|
||||||
|
|
||||||
gsc::function::add("getnodebynumber", []()
|
|
||||||
{
|
|
||||||
auto node_num = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto node = &(*game::gameWorldCurrent)->path.nodes[node_num];
|
|
||||||
|
|
||||||
game::Scr_AddPathnode(game::SCRIPTINSTANCE_SERVER, node);
|
|
||||||
});
|
|
||||||
|
|
||||||
gsc::function::add("generatepath", []()
|
|
||||||
{
|
|
||||||
auto path = std::make_unique<game::path_t>();
|
|
||||||
float start_pos[3] = {};
|
|
||||||
float goal_pos[3] = {};
|
|
||||||
auto team = "neutral"s;
|
|
||||||
std::unordered_set<unsigned short> allowed_animscripts;
|
|
||||||
|
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 0, start_pos);
|
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 1, goal_pos);
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
auto parent_id = game::Scr_GetObject(3, game::SCRIPTINSTANCE_SERVER).pointerValue;
|
|
||||||
auto script_array_size = GetArraySize(game::SCRIPTINSTANCE_SERVER, parent_id);
|
|
||||||
|
|
||||||
for (auto i = 0u; i < script_array_size; ++i)
|
|
||||||
{
|
|
||||||
auto id = game::GetArrayVariable(game::SCRIPTINSTANCE_SERVER, parent_id, i);
|
|
||||||
auto entry_value = &game::gScrVarGlob[0].childVariables[id];
|
|
||||||
|
|
||||||
if ((entry_value->w.type & 0x1F) != game::VAR_STRING)
|
|
||||||
{
|
|
||||||
game::Scr_Error(utils::string::va("index %d in array is not a string", i), game::SCRIPTINSTANCE_SERVER, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
allowed_animscripts.insert(entry_value->u.u.stringValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = Path_FindPath_custom(path.get(), eTeam, start_pos, goal_pos, allowed_animscripts);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::Scr_MakeArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
//Reverse the order of the array so index 0 is from the starting point instead of the end
|
|
||||||
for (auto i = path->wPathLen - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
if (path->pts[i].iNodeNum < 0)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
game::Scr_AddPathnode(game::SCRIPTINSTANCE_SERVER, &(*game::gameWorldCurrent)->path.nodes[path->pts[i].iNodeNum]);
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
REGISTER_COMPONENT(ai::component)
|
|
@ -1 +0,0 @@
|
|||||||
#include <stdinc.hpp>
|
|
@ -31,7 +31,7 @@ namespace gsc
|
|||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::BuiltinFunction __declspec(naked) scr_getfunction_stub()
|
game::BuiltinFunction NAKED scr_getfunction_stub()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
@ -87,7 +87,7 @@ namespace gsc
|
|||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::BuiltinMethod __declspec(naked) scr_getmethod_stub()
|
game::BuiltinMethod NAKED scr_getmethod_stub()
|
||||||
{
|
{
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
@ -99,30 +99,6 @@ namespace gsc
|
|||||||
ret;
|
ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hudelem_spawned_callback_handle = 0;
|
|
||||||
|
|
||||||
game::game_hudelem_s* hudelem_alloc_codecallback(game::game_hudelem_s* hud)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4FA310);
|
|
||||||
|
|
||||||
game::game_hudelem_s* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, hud;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hudelem_spawned_callback_handle)
|
|
||||||
{
|
|
||||||
auto id = game::Scr_ExecEntThread(game::SCRIPTINSTANCE_SERVER, hud - game::g_hudelems, hudelem_spawned_callback_handle, 0, game::CLASS_NUM_HUDELEM);
|
|
||||||
game::RemoveRefToObject(game::SCRIPTINSTANCE_SERVER, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace function
|
namespace function
|
||||||
@ -152,155 +128,6 @@ namespace gsc
|
|||||||
// custom gsc funcs
|
// custom gsc funcs
|
||||||
scr_getfunction_stub_ret_loc = utils::hook::get_displacement_addr(SELECT(0x0, 0x682D99));
|
scr_getfunction_stub_ret_loc = utils::hook::get_displacement_addr(SELECT(0x0, 0x682D99));
|
||||||
utils::hook::jump(SELECT(0x0, 0x682D99), scr_getfunction_stub);
|
utils::hook::jump(SELECT(0x0, 0x682D99), scr_getfunction_stub);
|
||||||
|
|
||||||
|
|
||||||
//Add support for codecallback_hudelemspawned GSC callback
|
|
||||||
//utils::hook::call(0x4FA40B, hudelem_alloc_stub);
|
|
||||||
//HudElem_Alloc_hook.create(0x4FA3E0, hudelem_alloc_stub2);
|
|
||||||
//Handle for codecallback_hudelemspawned
|
|
||||||
scheduler::on_postloadscripts([]()
|
|
||||||
{
|
|
||||||
auto found_script = game::Scr_LoadScript("scripts/sp/callbacks_ext", game::SCRIPTINSTANCE_SERVER);
|
|
||||||
if (found_script)
|
|
||||||
{
|
|
||||||
hudelem_spawned_callback_handle = game::Scr_GetFunctionHandle(game::SCRIPTINSTANCE_SERVER, "scripts/sp/callbacks_ext", "codecallback_hudelemspawned");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("Couldn't load script scripts/sp/callbacks_ext.gsc\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("funny_func", []()
|
|
||||||
{
|
|
||||||
printf("How funny\n");
|
|
||||||
printf("You found the funny monkey funkey\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
method::add("is_monkey", [](game::scr_entref_s ent)
|
|
||||||
{
|
|
||||||
printf("Monkey number %d\n", ent.entnum);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("inttest", []()
|
|
||||||
{
|
|
||||||
int answer = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
answer += 69;
|
|
||||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, answer);
|
|
||||||
});
|
|
||||||
function::add("floattest", []()
|
|
||||||
{
|
|
||||||
float answer = game::Scr_GetFloat(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
answer *= 69.0f;
|
|
||||||
game::Scr_AddFloat(game::SCRIPTINSTANCE_SERVER, answer);
|
|
||||||
});
|
|
||||||
function::add("stringtest", []()
|
|
||||||
{
|
|
||||||
char* answer = game::Scr_GetString(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
|
|
||||||
std::string string(answer);
|
|
||||||
|
|
||||||
string += " haha funny"s;
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, string.data());
|
|
||||||
});
|
|
||||||
function::add("istringtest", []()
|
|
||||||
{
|
|
||||||
const char* answer = game::Scr_GetIString(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
|
|
||||||
std::string string(answer);
|
|
||||||
|
|
||||||
string += " haha funny"s;
|
|
||||||
game::Scr_AddIString(game::SCRIPTINSTANCE_SERVER, string.data());
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("vectortest", []()
|
|
||||||
{
|
|
||||||
float answer[3] = {};
|
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 0, answer);
|
|
||||||
|
|
||||||
answer[0] += 69.0f;
|
|
||||||
game::Scr_AddVector(game::SCRIPTINSTANCE_SERVER, answer);
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("undefinedtest", []()
|
|
||||||
{
|
|
||||||
game::Scr_AddUndefined(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("pathnodetest", []()
|
|
||||||
{
|
|
||||||
game::pathnode_t* node = game::Scr_GetPathnode(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
game::Scr_AddPathnode(game::SCRIPTINSTANCE_SERVER, node);
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("numberindexedarraytest", []()
|
|
||||||
{
|
|
||||||
game::Scr_MakeArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
game::Scr_AddFloat(game::SCRIPTINSTANCE_SERVER, 69.0f);
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 420);
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, "ree");
|
|
||||||
game::Scr_AddArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("stringindexedarraytest", []()
|
|
||||||
{
|
|
||||||
game::Scr_MakeArray(game::SCRIPTINSTANCE_SERVER);
|
|
||||||
|
|
||||||
std::string key1("key1");
|
|
||||||
|
|
||||||
game::Scr_AddFloat(game::SCRIPTINSTANCE_SERVER, 69.0f);
|
|
||||||
game::Scr_AddArrayStringIndexed(game::SCRIPTINSTANCE_SERVER, game::SL_GetStringOfSize(game::SCRIPTINSTANCE_SERVER, key1.data(), 0, key1.length() + 1));
|
|
||||||
|
|
||||||
std::string key2("key2");
|
|
||||||
|
|
||||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 420);
|
|
||||||
game::Scr_AddArrayStringIndexed(game::SCRIPTINSTANCE_SERVER, game::SL_GetStringOfSize(game::SCRIPTINSTANCE_SERVER, key2.data(), 0, key2.length() + 1));
|
|
||||||
|
|
||||||
std::string key3("key3");
|
|
||||||
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, "ree");
|
|
||||||
game::Scr_AddArrayStringIndexed(game::SCRIPTINSTANCE_SERVER, game::SL_GetStringOfSize(game::SCRIPTINSTANCE_SERVER, key3.data(), 0, key3.length() + 1));
|
|
||||||
});
|
|
||||||
|
|
||||||
method::add("entitytest", [](game::scr_entref_s ent)
|
|
||||||
{
|
|
||||||
if (ent.classnum != game::CLASS_NUM_ENTITY)
|
|
||||||
{
|
|
||||||
game::Scr_Error("Not an entity", game::SCRIPTINSTANCE_SERVER, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::gentity_s* ent2 = &game::g_entities[ent.entnum];
|
|
||||||
|
|
||||||
game::Scr_AddEntity(game::SCRIPTINSTANCE_SERVER, ent2);
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("writefile", []()
|
|
||||||
{
|
|
||||||
const auto path = game::Scr_GetString(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
const auto data = game::Scr_GetString(game::SCRIPTINSTANCE_SERVER, 1);
|
|
||||||
|
|
||||||
auto append = false;
|
|
||||||
if (game::Scr_GetNumParam(game::SCRIPTINSTANCE_SERVER) > 2)
|
|
||||||
{
|
|
||||||
append = game::Scr_GetInt(game::SCRIPTINSTANCE_SERVER, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, utils::io::write_file(path, data, append));
|
|
||||||
});
|
|
||||||
|
|
||||||
function::add("readfile", []()
|
|
||||||
{
|
|
||||||
const auto path = game::Scr_GetString(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, utils::io::read_file(path).c_str());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,14 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdinc.hpp>
|
|
||||||
|
|
||||||
namespace gsc
|
namespace gsc
|
||||||
{
|
{
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace function
|
namespace function
|
||||||
{
|
{
|
||||||
void add(const std::string& name, const game::BuiltinFunction function);
|
void add(const std::string& name, const game::BuiltinFunction function);
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
#include <stdinc.hpp>
|
|
||||||
#include "loader/component_loader.hpp"
|
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
|
||||||
#include <utils/io.hpp>
|
|
||||||
#include <utils/string.hpp>
|
|
||||||
#include <utils/thread.hpp>
|
|
||||||
#include <utils/compression.hpp>
|
|
||||||
|
|
||||||
#include <exception/minidump.hpp>
|
|
||||||
|
|
||||||
namespace player
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
utils::hook::detour g_clientdoperframenotifies_hook;
|
|
||||||
|
|
||||||
void G_ClientDoPerFrameNotifies_custom(game::gentity_s* ent)
|
|
||||||
{
|
|
||||||
game::gclient_s* client; // esi
|
|
||||||
unsigned int weapon; // eax
|
|
||||||
bool clientIsFiring; // bl
|
|
||||||
|
|
||||||
client = ent->client;
|
|
||||||
weapon = client->ps.weapon;
|
|
||||||
if (weapon != client->lastWeapon)
|
|
||||||
{
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, game::BG_WeaponNames[weapon]->szInternalName);
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->weapon_change, 1);
|
|
||||||
weapon = client->ps.weapon;
|
|
||||||
client->lastWeapon = weapon;
|
|
||||||
}
|
|
||||||
if (!client->previouslyChangingWeapon || client->ps.weaponstate == game::WEAPON_RAISING || client->ps.weaponstate == game::WEAPON_RAISING_ALTSWITCH)
|
|
||||||
{
|
|
||||||
if (client->ps.weaponstate == game::WEAPON_RAISING || client->ps.weaponstate == game::WEAPON_RAISING_ALTSWITCH)
|
|
||||||
client->previouslyChangingWeapon = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
game::Scr_AddString(game::SCRIPTINSTANCE_SERVER, game::BG_WeaponNames[weapon]->szInternalName);
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->weapon_change_complete, 1);
|
|
||||||
client->previouslyChangingWeapon = 0;
|
|
||||||
}
|
|
||||||
clientIsFiring = client->ps.weaponstate == game::WEAPON_FIRING && client->ps.pm_type < game::PM_LASTSTAND_TRANSITION;
|
|
||||||
if (clientIsFiring != client->previouslyFiring)
|
|
||||||
{
|
|
||||||
if (clientIsFiring)
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->begin_firing, 0);
|
|
||||||
else
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->end_firing, 0);
|
|
||||||
client->previouslyFiring = clientIsFiring;
|
|
||||||
}
|
|
||||||
if ((client->ps.weapFlags & 0x40) != 0)
|
|
||||||
{
|
|
||||||
if (!client->previouslyUsingNightVision)
|
|
||||||
{
|
|
||||||
client->previouslyUsingNightVision = 1;
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->night_vision_on, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (client->previouslyUsingNightVision)
|
|
||||||
{
|
|
||||||
client->previouslyUsingNightVision = 0;
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::scr_const->night_vision_off, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//New addition
|
|
||||||
if (game::PM_IsSprinting(&client->ps))
|
|
||||||
{
|
|
||||||
if (!client->previouslySprinting)
|
|
||||||
{
|
|
||||||
client->previouslySprinting = true;
|
|
||||||
std::string sprintBeginNotifyStr("sprint_begin");
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::SL_GetStringOfSize(game::SCRIPTINSTANCE_SERVER, sprintBeginNotifyStr.data(), 0, sprintBeginNotifyStr.length()), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (client->previouslySprinting)
|
|
||||||
{
|
|
||||||
client->previouslySprinting = false;
|
|
||||||
std::string sprintBeginNotifyStr("sprint_end");
|
|
||||||
game::Scr_NotifyNum(game::SCRIPTINSTANCE_SERVER, ent->s.number, 0, game::SL_GetStringOfSize(game::SCRIPTINSTANCE_SERVER, sprintBeginNotifyStr.data(), 0, sprintBeginNotifyStr.length()), 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void __declspec(naked) G_ClientDoPerFrameNotifies_stub()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push edi;
|
|
||||||
|
|
||||||
call G_ClientDoPerFrameNotifies_custom;
|
|
||||||
add esp, 0x4;
|
|
||||||
ret;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class component final : public component_interface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void post_unpack() override
|
|
||||||
{
|
|
||||||
// test usercall detour!
|
|
||||||
g_clientdoperframenotifies_hook.create(game::G_ClientDoPerFrameNotifies(), G_ClientDoPerFrameNotifies_stub);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
REGISTER_COMPONENT(player::component)
|
|
@ -99,8 +99,6 @@ namespace scheduler
|
|||||||
|
|
||||||
std::vector<std::function<void()>> post_init_funcs;
|
std::vector<std::function<void()>> post_init_funcs;
|
||||||
bool com_inited = false;
|
bool com_inited = false;
|
||||||
std::vector<std::function<void()>> post_loadscripts_funcs;
|
|
||||||
bool postloadscripts_inited = false;
|
|
||||||
|
|
||||||
void on_post_init_hook()
|
void on_post_init_hook()
|
||||||
{
|
{
|
||||||
@ -120,26 +118,6 @@ namespace scheduler
|
|||||||
com_init_hook.invoke<void>();
|
com_init_hook.invoke<void>();
|
||||||
on_post_init_hook();
|
on_post_init_hook();
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_post_postloadscripts_hook()
|
|
||||||
{
|
|
||||||
if (postloadscripts_inited)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const auto& func : post_loadscripts_funcs)
|
|
||||||
{
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void postloadscripts_stub()
|
|
||||||
{
|
|
||||||
postloadscripts_inited = false;
|
|
||||||
gscr_postloadscripts_hook.invoke<void>();
|
|
||||||
on_post_postloadscripts_hook();
|
|
||||||
postloadscripts_inited = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void schedule(const std::function<bool()>& callback, const pipeline type,
|
void schedule(const std::function<bool()>& callback, const pipeline type,
|
||||||
@ -187,11 +165,6 @@ namespace scheduler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_postloadscripts(const std::function<void()>& callback)
|
|
||||||
{
|
|
||||||
post_loadscripts_funcs.push_back(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -207,9 +180,6 @@ namespace scheduler
|
|||||||
});
|
});
|
||||||
|
|
||||||
com_init_hook.create(SELECT(0x0, 0x59D710), com_init_stub);
|
com_init_hook.create(SELECT(0x0, 0x59D710), com_init_stub);
|
||||||
|
|
||||||
gscr_postloadscripts_hook.create(SELECT(0x0, 0x5150E0), postloadscripts_stub);
|
|
||||||
|
|
||||||
utils::hook::call(SELECT(0x0, 0x503B5D), execute_server);
|
utils::hook::call(SELECT(0x0, 0x503B5D), execute_server);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,4 @@ namespace scheduler
|
|||||||
std::chrono::milliseconds delay = 0ms);
|
std::chrono::milliseconds delay = 0ms);
|
||||||
|
|
||||||
void on_init(const std::function<void()>& callback);
|
void on_init(const std::function<void()>& callback);
|
||||||
|
|
||||||
void on_postloadscripts(const std::function<void()>& callback);
|
|
||||||
}
|
}
|
||||||
|
@ -7,154 +7,13 @@
|
|||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
|
#include <utils/http.hpp>
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
utils::hook::detour gscr_spawn_hook;
|
|
||||||
|
|
||||||
// a __usercall detour! :o
|
|
||||||
utils::hook::detour scr_getentityid_hook;
|
|
||||||
|
|
||||||
utils::hook::detour sv_clientthink_hook;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
game::dvar_s* custom_dvar;
|
|
||||||
game::dvar_s* custom_string_dvar;
|
|
||||||
|
|
||||||
void print_script_callstack(const char* msg, game::scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
int i; // [esp+4h] [ebp-4h]
|
|
||||||
printf("******* Callstack for %s *******\n", msg);
|
|
||||||
game::Scr_PrintPrevCodePos(game::function_stack[inst].pos, inst, game::CON_CHANNEL_DONT_FILTER, 0);
|
|
||||||
auto function_count = game::gScrVmPub[inst].function_count;
|
|
||||||
if (function_count)
|
|
||||||
{
|
|
||||||
for (i = function_count - 1; i >= 1; --i)
|
|
||||||
{
|
|
||||||
printf("Info: called from:\n");
|
|
||||||
game::Scr_PrintPrevCodePos(
|
|
||||||
game::gScrVmPub[inst].function_frame_start[i].fs.pos,
|
|
||||||
inst,
|
|
||||||
game::CON_CHANNEL_DONT_FILTER,
|
|
||||||
game::gScrVmPub[inst].function_frame_start[i].fs.localId == 0);
|
|
||||||
}
|
|
||||||
printf("started from:\n");
|
|
||||||
game::Scr_PrintPrevCodePos(game::gScrVmPub[inst].function_frame_start[0].fs.pos, inst, game::CON_CHANNEL_DONT_FILTER, 1u);
|
|
||||||
}
|
|
||||||
printf("************************************\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void gscr_spawn_stub()
|
|
||||||
{
|
|
||||||
auto classname = game::Scr_GetConstString(game::SCRIPTINSTANCE_SERVER, 0);
|
|
||||||
|
|
||||||
float origin[3] = {};
|
|
||||||
|
|
||||||
game::Scr_GetVector(game::SCRIPTINSTANCE_SERVER, 1, origin);
|
|
||||||
|
|
||||||
if (classname == game::scr_const->script_origin)
|
|
||||||
{
|
|
||||||
print_script_callstack(utils::string::va("GScr_Spawn() classname: script_origin at: (%f, %f, %f)", origin[0], origin[1], origin[2]), game::SCRIPTINSTANCE_SERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
gscr_spawn_hook.invoke<void>();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool our_funny_call(game::pathnode_t* begin_node, game::pathnode_t* end_node, bool allowNeg)
|
|
||||||
{
|
|
||||||
if (!allowNeg && begin_node->constant.type == game::NODE_NEGOTIATION_BEGIN && end_node->constant.type == game::NODE_NEGOTIATION_END)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __declspec(naked) our_funny_hook()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
pushad;
|
|
||||||
mov eax, [esp + 0x20 + 0x98 + 0x1C];
|
|
||||||
push eax;
|
|
||||||
push esi; // end
|
|
||||||
push edi; // begin
|
|
||||||
call our_funny_call;
|
|
||||||
add esp, 0xC;
|
|
||||||
test al, al;
|
|
||||||
popad;
|
|
||||||
|
|
||||||
jnz og;
|
|
||||||
|
|
||||||
push 0x4D3400;
|
|
||||||
retn;
|
|
||||||
|
|
||||||
og:
|
|
||||||
mov ecx, 0x18F78D4;
|
|
||||||
mov ecx, dword ptr [ecx]; // level.iSearchFrame
|
|
||||||
push 0x4D329C;
|
|
||||||
retn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int scr_getentityid_call(unsigned int entnum, [[maybe_unused]] void* caller_addr, game::scriptInstance_t inst, game::classNum_e classnum, unsigned int clientnum)
|
|
||||||
{
|
|
||||||
// minhook allocated space for the original asm, we want to execute that instead because the original gamecode has the jump from the detour
|
|
||||||
return game::Scr_GetEntityId(inst, entnum, classnum, clientnum, scr_getentityid_hook.get_original());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int __declspec(naked) scr_getentityid_stub()
|
|
||||||
{
|
|
||||||
// 00692520 unsigned int __usercall Scr_GetEntityId@<eax>(unsigned int entnum@<eax>, scriptInstance_t inst, classNum_e classnum, unsigned int clientnum)
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
// eax is a param, lets push it!
|
|
||||||
push eax;
|
|
||||||
|
|
||||||
// ok so scr_getentityid_call intentionally has more params than it should, so we can access everything on the stack
|
|
||||||
call scr_getentityid_call;
|
|
||||||
|
|
||||||
// clean up and return
|
|
||||||
add esp, 4;
|
|
||||||
ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sv_clientthink_call(game::client_s* client, [[maybe_unused]] void* caller_addr, game::usercmd_s* cmd)
|
|
||||||
{
|
|
||||||
const auto og_addr = sv_clientthink_hook.get_original();
|
|
||||||
|
|
||||||
if (client->bIsTestClient && client->gentity && client->gentity->client)
|
|
||||||
{
|
|
||||||
auto gclient = client->gentity->client;
|
|
||||||
|
|
||||||
cmd->wiimoteGunPitch = static_cast<unsigned short>((gclient->ps.viewangles[0]) * (65536 / 360.f)) & 0xFFFF;
|
|
||||||
cmd->wiimoteGunYaw = static_cast<unsigned short>((gclient->ps.viewangles[1]) * (65536 / 360.f)) & 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push cmd;
|
|
||||||
mov eax, client;
|
|
||||||
call og_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void __declspec(naked) sv_clientthink_stub()
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push eax;
|
|
||||||
|
|
||||||
call sv_clientthink_call;
|
|
||||||
|
|
||||||
add esp, 0x4;
|
|
||||||
|
|
||||||
ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -162,50 +21,6 @@ namespace test
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
game::Cmd_AddCommand("testcmd", []()
|
|
||||||
{
|
|
||||||
if (game::Cmd_Argc() == 2)
|
|
||||||
{
|
|
||||||
printf("test %s\n", game::Cmd_Argv(1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("test\n");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
custom_dvar = game::Dvar_RegisterInt("testdvar1", 69, -69, 420, game::DVAR_FLAG_NONE, "This dvar is a dvar");
|
|
||||||
|
|
||||||
scheduler::on_init([]()
|
|
||||||
{
|
|
||||||
custom_string_dvar = game::Dvar_RegisterString("testdvar2", "This might be a dvar value", game::DVAR_FLAG_NONE, "This dvar is a dvar");
|
|
||||||
printf("We initeded bois\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
scheduler::loop([]()
|
|
||||||
{
|
|
||||||
//printf("Biggie Spam McCheese\n");
|
|
||||||
});
|
|
||||||
|
|
||||||
gsc::function::add("getarraytest", []()
|
|
||||||
{
|
|
||||||
auto parent_id = game::Scr_GetObject(0, game::SCRIPTINSTANCE_SERVER).pointerValue;
|
|
||||||
|
|
||||||
auto script_array_size = GetArraySize(game::SCRIPTINSTANCE_SERVER, parent_id);
|
|
||||||
for (auto i = 0u; i < script_array_size; ++i)
|
|
||||||
{
|
|
||||||
auto id = game::GetArrayVariable(game::SCRIPTINSTANCE_SERVER, parent_id, i);
|
|
||||||
auto entry_value = &game::gScrVarGlob[0].childVariables[id];
|
|
||||||
if ((entry_value->w.type & 0x1F) != game::VAR_STRING)
|
|
||||||
{
|
|
||||||
game::Scr_Error(utils::string::va("index %d in array is not a string", i), game::SCRIPTINSTANCE_SERVER, false);
|
|
||||||
}
|
|
||||||
printf("%s\n", game::SL_ConvertToString(game::SCRIPTINSTANCE_SERVER, entry_value->u.u.stringValue));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gscr_spawn_hook.create(0x517630, gscr_spawn_stub);
|
|
||||||
|
|
||||||
//Disable AI print spam
|
//Disable AI print spam
|
||||||
utils::hook::nop(0x4BAB7D, 5);
|
utils::hook::nop(0x4BAB7D, 5);
|
||||||
utils::hook::nop(0x4BAAFA, 5);
|
utils::hook::nop(0x4BAAFA, 5);
|
||||||
@ -215,15 +30,6 @@ namespace test
|
|||||||
|
|
||||||
//Disable unknown dvar spam
|
//Disable unknown dvar spam
|
||||||
utils::hook::nop(0x5F04AF, 5);
|
utils::hook::nop(0x5F04AF, 5);
|
||||||
|
|
||||||
// fix NEGOTIATION links
|
|
||||||
//utils::hook::jump(0x4D3296, our_funny_hook);
|
|
||||||
|
|
||||||
// test usercall detour!
|
|
||||||
scr_getentityid_hook.create(game::Scr_GetEntityId(), scr_getentityid_stub);
|
|
||||||
// scr_getentityid_hook.create(game::SL_GetStringOfSize.get(), sl_getstringofsize_stub);
|
|
||||||
|
|
||||||
sv_clientthink_hook.create(0x630BF0, sv_clientthink_stub);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -24,915 +24,6 @@ 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 }
|
|
||||||
};
|
|
||||||
|
|
||||||
void G_ClientDoPerFrameNotifies(gentity_s* ent, void* call_addr)
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov edi, ent;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_PrintPrevCodePos(const char* codepos, int scriptInstance, con_channel_e channel, int index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x68B340);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push index;
|
|
||||||
push channel;
|
|
||||||
push scriptInstance;
|
|
||||||
mov eax, codepos;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0xC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoveRefToObject(scriptInstance_t inst/*<ecx>*/, unsigned int id/*<eax>*/)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x690040);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, inst;
|
|
||||||
mov eax, id;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scr_LoadScript(const char* file, scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x646DE0, 0x689C60);
|
|
||||||
int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, file;
|
|
||||||
mov edx, inst;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Scr_GetFunctionHandle/*<eax>*/(scriptInstance_t inst/*<ecx>*/, const char* file/*<eax>*/, const char* handle)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x6894B0);
|
|
||||||
|
|
||||||
unsigned int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push handle;
|
|
||||||
mov eax, file;
|
|
||||||
mov ecx, inst;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x699C50);
|
|
||||||
int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, arg_index;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddInt(game::scriptInstance_t inst, int value)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A610);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push value;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float Scr_GetFloat(game::scriptInstance_t inst, unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x699E90);
|
|
||||||
float answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, arg_index;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
movss answer, xmm0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddFloat(game::scriptInstance_t inst, float value)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A670);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push value;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char* Scr_GetString(game::scriptInstance_t inst, unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A0D0);
|
|
||||||
char* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov esi, inst;
|
|
||||||
mov eax, arg_index;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddString(game::scriptInstance_t inst, const char* string)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A7E0);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push string;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Scr_GetIString(game::scriptInstance_t inst, unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A1A0); //Scr_GetConstIString
|
|
||||||
|
|
||||||
int id;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, arg_index;
|
|
||||||
call call_addr;
|
|
||||||
mov id, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SL_ConvertToString(inst, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddIString(game::scriptInstance_t inst, const char* string)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A860);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov esi, string;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short Scr_GetConstString(game::scriptInstance_t inst, unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x699F30);
|
|
||||||
|
|
||||||
unsigned short answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push arg_index;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, cx;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddConstString(game::scriptInstance_t inst, unsigned short id)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A8D0);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov si, id;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_GetVector(game::scriptInstance_t inst, unsigned int arg_index, float* value)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A220);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push arg_index;
|
|
||||||
mov ecx, value;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddVector(game::scriptInstance_t inst, float* value)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A940);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push value;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddUndefined(game::scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A720);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gentity_s* Scr_GetEntity(unsigned int arg_index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x546E30);
|
|
||||||
gentity_s* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, arg_index;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddEntity(game::scriptInstance_t inst, gentity_s* ent)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x546D90);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov edi, inst;
|
|
||||||
mov eax, ent;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Scr_GetEntityId(scriptInstance_t inst, unsigned int entnum, classNum_e classnum, unsigned int clientnum, void* call_addr)
|
|
||||||
{
|
|
||||||
unsigned int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push clientnum;
|
|
||||||
push classnum;
|
|
||||||
push inst;
|
|
||||||
mov eax, entnum;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0xC;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddEntityNum(scriptInstance_t inst, unsigned int entid)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A770);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov esi, entid;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only supports getting the first argument as a path node
|
|
||||||
pathnode_t* Scr_GetPathnode(scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x559E20);
|
|
||||||
pathnode_t* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node)
|
|
||||||
{
|
|
||||||
unsigned int entnum = node - (*gameWorldCurrent)->path.nodes;
|
|
||||||
auto entid = Scr_GetEntityId(inst, entnum, CLASS_NUM_PATHNODE, 0);
|
|
||||||
Scr_AddEntityNum(inst, entid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddHudElem(game_hudelem_s* hud)
|
|
||||||
{
|
|
||||||
int entId = Scr_GetEntityId(SCRIPTINSTANCE_SERVER, hud - g_hudelems, CLASS_NUM_HUDELEM, 0);
|
|
||||||
Scr_AddObject(SCRIPTINSTANCE_SERVER, entId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddObject(scriptInstance_t inst/*<eax>*/, int entid/*<esi>*/)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A770);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov esi, entid;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_MakeArray(scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69A9D0);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_AddArrayStringIndexed(scriptInstance_t inst, unsigned short id)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x69AAF0);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov edi, inst;
|
|
||||||
movzx ecx, id;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short Scr_ExecThread/*<ax>*/(scriptInstance_t inst/*<edi>*/, int handle, int paramCount)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x699560);
|
|
||||||
|
|
||||||
unsigned short answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push paramCount;
|
|
||||||
push handle;
|
|
||||||
mov edi, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x8;
|
|
||||||
mov answer, ax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short Scr_ExecEntThread/*<ax>*/(scriptInstance_t inst/*<edi>*/, int entNum, int handle, int numParams, int entClass)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x699640);
|
|
||||||
|
|
||||||
unsigned short answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push entClass;
|
|
||||||
push numParams;
|
|
||||||
push handle;
|
|
||||||
push entNum;
|
|
||||||
mov edi, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x10;
|
|
||||||
mov answer, ax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Scr_NotifyNum(scriptInstance_t inst, int entNum, int entClass, unsigned int notifStr, int numParams, void* call_addr)
|
|
||||||
{
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push numParams;
|
|
||||||
push notifStr;
|
|
||||||
push entClass;
|
|
||||||
push entNum;
|
|
||||||
mov eax, inst;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetArrayVariableIndex(unsigned int unsignedValue, scriptInstance_t inst, unsigned int parentId, void* call_addr)
|
|
||||||
{
|
|
||||||
unsigned int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push parentId;
|
|
||||||
push inst;
|
|
||||||
mov eax, unsignedValue;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
add esp, 0x8;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Scr_GetNumParam(scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
return gScrVmPub[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, 0x4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* SL_ConvertToString(scriptInstance_t inst, int id)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x68D950);
|
|
||||||
const char* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, inst;
|
|
||||||
mov eax, id;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Cmd_Argv(int index)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x435CE0);
|
|
||||||
const char* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov eax, index;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Cmd_Argc()
|
|
||||||
{
|
|
||||||
return cmd_args->argc[cmd_args->nesting];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cmd_AddCommand(const char* name, void(__cdecl* function)())
|
|
||||||
{
|
|
||||||
auto newCmd = utils::memory::allocate<game::cmd_function_s>();
|
|
||||||
auto name_dup = utils::memory::duplicate_string(name);
|
|
||||||
|
|
||||||
*newCmd = {};
|
|
||||||
newCmd->next = *game::cmd_functions;
|
|
||||||
newCmd->function = function;
|
|
||||||
newCmd->name = name_dup;
|
|
||||||
|
|
||||||
*game::cmd_functions = newCmd;
|
|
||||||
}
|
|
||||||
|
|
||||||
dvar_s* Dvar_RegisterInt(const char* name, int value, int min, int max, DvarFlags flags, const char* desc)
|
|
||||||
{
|
|
||||||
DvarLimits limits;
|
|
||||||
DvarValue dvar_value;
|
|
||||||
limits.integer.min = min;
|
|
||||||
limits.integer.max = max;
|
|
||||||
dvar_value.integer = value;
|
|
||||||
return Dvar_RegisterVariant(name, game::DVAR_TYPE_INT, flags, dvar_value, limits, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
dvar_s* Dvar_RegisterString(const char* name, const char* value, DvarFlags flags, const char* desc)
|
|
||||||
{
|
|
||||||
DvarLimits limits = {};
|
|
||||||
DvarValue dvar_value;
|
|
||||||
dvar_value.string = value;
|
|
||||||
return Dvar_RegisterVariant(name, game::DVAR_TYPE_STRING, flags, dvar_value, limits, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Dvar_ValueToString(dvar_s* dvar, DvarValue dvarValue)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x5ECAB0);
|
|
||||||
|
|
||||||
const char* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push dvarValue;
|
|
||||||
mov ecx, dvar;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
add esp, 0x4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dvar_SetVariant(dvar_s* dvar, DvarValue val, DvarSetSource dvarSetSource)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x5EDA40);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push dvarSetSource;
|
|
||||||
push val;
|
|
||||||
push dvar;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0xC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Path_FindPath(path_t* pPath, team_t eTeam, float* vStartPos, float* vGoalPos, int bAllowNegotiationLinks)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4CF280);
|
|
||||||
|
|
||||||
int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push bAllowNegotiationLinks;
|
|
||||||
push vGoalPos;
|
|
||||||
push vStartPos;
|
|
||||||
mov edx, eTeam;
|
|
||||||
mov ecx, pPath;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
pathnode_t* Path_NearestNodeNotCrossPlanes(int typeFlags, int maxNodes, float* vOrigin, pathsort_t* nodes, float fMaxDist, float a6, float a7, int iPlaneCount, int* returnCount, nearestNodeHeightCheck heightCheck)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x55C210);
|
|
||||||
|
|
||||||
pathnode_t* answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push heightCheck;
|
|
||||||
push returnCount;
|
|
||||||
push iPlaneCount;
|
|
||||||
push a7;
|
|
||||||
push a6;
|
|
||||||
push fMaxDist;
|
|
||||||
push nodes;
|
|
||||||
push vOrigin;
|
|
||||||
mov ecx, maxNodes;
|
|
||||||
mov edx, typeFlags;
|
|
||||||
call call_addr;
|
|
||||||
add esp, 0x20;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is a __userpurge, which automatically cleans up the stack by itself so do not do add esp
|
|
||||||
int Path_FindPathFromTo(float* startPos, pathnode_t* pNodeTo, path_t* pPath, team_t eTeam, pathnode_t* pNodeFrom, float* vGoalPos, int bAllowNegotiationLinks, int bIgnoreBadplaces)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4CF3F0);
|
|
||||||
|
|
||||||
int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push bIgnoreBadplaces;
|
|
||||||
push bAllowNegotiationLinks;
|
|
||||||
push vGoalPos;
|
|
||||||
push pNodeFrom;
|
|
||||||
push eTeam;
|
|
||||||
push pPath;
|
|
||||||
mov edx, pNodeTo;
|
|
||||||
mov eax, startPos;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is a __userpurge, which automatically cleans up the stack by itself so do not do add esp
|
|
||||||
int Path_GeneratePath(path_t* pPath, team_t eTeam, const float* vStartPos, float* vGoalPos, pathnode_t* pNodeFrom, pathnode_t* pNodeTo, int bIncludeGoalPos, int bAllowNegotiationLinks)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4CED90);
|
|
||||||
|
|
||||||
int answer;
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push bAllowNegotiationLinks;
|
|
||||||
push bIncludeGoalPos;
|
|
||||||
push pNodeTo;
|
|
||||||
push pNodeFrom;
|
|
||||||
push vGoalPos;
|
|
||||||
push vStartPos;
|
|
||||||
push eTeam;
|
|
||||||
mov eax, pPath;
|
|
||||||
call call_addr;
|
|
||||||
mov answer, eax;
|
|
||||||
}
|
|
||||||
|
|
||||||
return answer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void /*__userpurge*/ Path_UpdateLookahead(path_t* pPath/*@<eax>*/, const float* vStartPos, int bReduceLookaheadAmount, int a4, int bAllowBacktrack)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4D2120);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push bAllowBacktrack;
|
|
||||||
push a4;
|
|
||||||
push bReduceLookaheadAmount;
|
|
||||||
push vStartPos;
|
|
||||||
mov eax, pPath;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void /*__usercall*/ Path_AddTrimmedAmount(const float* a1/*@<eax>*/, path_t* a2/*@<edi>*/)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4CE560);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov edi, a2;
|
|
||||||
mov eax, a1;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void /*__stdcall*/ Path_TransferLookahead(path_t* a1, const float* a2)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x4CE980);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
push a2;
|
|
||||||
push a1;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PM_IsSprinting(const playerState_s* ps)
|
|
||||||
{
|
|
||||||
return ps->sprintState.lastSprintStart && ps->sprintState.lastSprintStart > ps->sprintState.lastSprintEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::pathnode_t* Path_ConvertIndexToNode(int index)
|
|
||||||
{
|
|
||||||
return &(*game::gameWorldCurrent)->path.nodes[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int __cdecl Path_ConvertNodeToIndex(const game::pathnode_t* node)
|
|
||||||
{
|
|
||||||
return node - (*gameWorldCurrent)->path.nodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
game::pathnode_t* Path_GetNegotiationNode(const game::path_t* pPath)
|
|
||||||
{
|
|
||||||
return Path_ConvertIndexToNode(pPath->pts[pPath->wNegotiationStartNode].iNodeNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Path_IncrementNodeUserCount(game::path_t* pPath)
|
|
||||||
{
|
|
||||||
game::pathnode_t* negotiationNode; // [esp+4h] [ebp-4h]
|
|
||||||
|
|
||||||
negotiationNode = Path_GetNegotiationNode(pPath);
|
|
||||||
++negotiationNode->dynamic.userCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Path_DecrementNodeUserCount(game::path_t* pPath)
|
|
||||||
{
|
|
||||||
game::pathnode_t* negotiationNode; // [esp+4h] [ebp-4h]
|
|
||||||
|
|
||||||
negotiationNode = Path_GetNegotiationNode(pPath);
|
|
||||||
--negotiationNode->dynamic.userCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Path_Clear(game::path_t* pPath)
|
|
||||||
{
|
|
||||||
if (pPath->wNegotiationStartNode > 0)
|
|
||||||
{
|
|
||||||
Path_DecrementNodeUserCount(pPath);
|
|
||||||
pPath->wNegotiationStartNode = 0;
|
|
||||||
}
|
|
||||||
pPath->wPathLen = 0;
|
|
||||||
pPath->wOrigPathLen = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vec2Length(const float* v)
|
|
||||||
{
|
|
||||||
return sqrt((*v * *v) + (v[1] * v[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
float Path_GetPathDir(float* delta, const float* vFrom, const float* vTo)
|
|
||||||
{
|
|
||||||
float fDist; // [esp+18h] [ebp-4h]
|
|
||||||
|
|
||||||
delta[0] = *vTo - vFrom[0];
|
|
||||||
delta[1] = vTo[1] - vFrom[1];
|
|
||||||
fDist = Vec2Length(delta);
|
|
||||||
delta[0] = (1.0 / fDist) * delta[0];
|
|
||||||
delta[1] = (1.0 / fDist) * delta[1];
|
|
||||||
return fDist;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Vec3DistanceSq(const float* p1, const float* p2)
|
|
||||||
{
|
|
||||||
float vDiffY; // [esp+4h] [ebp-8h]
|
|
||||||
float vDiffZ; // [esp+8h] [ebp-4h]
|
|
||||||
|
|
||||||
vDiffY = p2[1] - p1[1];
|
|
||||||
vDiffZ = p2[2] - p1[2];
|
|
||||||
return vDiffZ * vDiffZ + vDiffY * vDiffY + (float)(*p2 - *p1) * (float)(*p2 - *p1);
|
|
||||||
}
|
|
||||||
|
|
||||||
float EvaluateHeuristic(game::CustomSearchInfo_FindPath* searchInfo, game::pathnode_t* pSuccessor, const float* vGoalPos)
|
|
||||||
{
|
|
||||||
float v[2]; // [esp+18h] [ebp-Ch] BYREF
|
|
||||||
float dist; // [esp+20h] [ebp-4h]
|
|
||||||
|
|
||||||
v[0] = *vGoalPos - pSuccessor->constant.vOrigin[0];
|
|
||||||
v[1] = vGoalPos[1] - pSuccessor->constant.vOrigin[1];
|
|
||||||
dist = Vec2Length(v);
|
|
||||||
dist = (pSuccessor->dynamic.userCount * searchInfo->negotiationOverlapCost) + dist;
|
|
||||||
if (pSuccessor->constant.minUseDistSq > 1.0
|
|
||||||
&& pSuccessor->constant.minUseDistSq > Vec3DistanceSq(pSuccessor->constant.vOrigin, searchInfo->startPos))
|
|
||||||
{
|
|
||||||
dist = dist + searchInfo->negotiationOverlapCost;
|
|
||||||
}
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableUnion Scr_GetObject(unsigned int index, scriptInstance_t inst)
|
|
||||||
{
|
|
||||||
const char* v3; // eax
|
|
||||||
const char* v4; // eax
|
|
||||||
VariableValue* value; // [esp+0h] [ebp-4h]
|
|
||||||
|
|
||||||
if (index < gScrVmPub[inst].outparamcount)
|
|
||||||
{
|
|
||||||
value = &gScrVmPub[inst].top[-index];
|
|
||||||
if (value->type == VAR_BEGIN_REF)
|
|
||||||
return value->u;
|
|
||||||
gScrVarPub[inst].error_index = index + 1;
|
|
||||||
v3 = utils::string::va("type %s is not an object", var_typename[value->type]);
|
|
||||||
Scr_Error(v3, inst, 0);
|
|
||||||
}
|
|
||||||
v4 = utils::string::va("parameter %d does not exist", index + 1);
|
|
||||||
Scr_Error(v4, inst, 0);
|
|
||||||
return value->u;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetArraySize(scriptInstance_t inst, unsigned int id)
|
|
||||||
{
|
|
||||||
VariableValueInternal* entryValue; // [esp+0h] [ebp-4h]
|
|
||||||
|
|
||||||
entryValue = &gScrVarGlob[inst].parentVariables[id + 1];
|
|
||||||
return entryValue->u.o.u.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int GetArrayVariable(scriptInstance_t inst, unsigned int parentId, unsigned int unsignedValue)
|
|
||||||
{
|
|
||||||
return gScrVarGlob[inst].childVariables[GetArrayVariableIndex(unsignedValue, inst, parentId)].hash.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int __cdecl Scr_GetFunc(scriptInstance_t inst, unsigned int index)
|
|
||||||
{
|
|
||||||
VariableValue* value; // [esp+0h] [ebp-4h]
|
|
||||||
|
|
||||||
if (index >= gScrVmPub[inst].outparamcount)
|
|
||||||
{
|
|
||||||
Scr_Error(utils::string::va("parameter %d does not exist", index + 1), inst, false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
value = &gScrVmPub[inst].top[-index];
|
|
||||||
if (value->type != VAR_FUNCTION)
|
|
||||||
{
|
|
||||||
gScrVarPub[inst].error_index = index + 1;
|
|
||||||
Scr_Error(utils::string::va("type %s is not a function", var_typename[value->type]), inst, false);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return value->u.intValue - (unsigned int)gScrVarPub[inst].programBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Dvar_Reset(DvarSetSource dvarSetSource, dvar_s* dvar)
|
|
||||||
{
|
|
||||||
return Dvar_SetVariant(dvar, dvar->reset, dvarSetSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SV_SendServerCommand(client_s* clientArg, svscmd_type type, char* Format, ...)
|
|
||||||
{
|
|
||||||
client_s* i; // esi
|
|
||||||
va_list ArgList; // [esp+18h] [ebp+Ch] BYREF
|
|
||||||
|
|
||||||
va_start(ArgList, Format);
|
|
||||||
_vsnprintf(tempServerCommandBuf, 0x20000u, Format, ArgList);
|
|
||||||
if (clientArg)
|
|
||||||
{
|
|
||||||
SV_AddServerCommand(clientArg, type, tempServerCommandBuf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((*com_dedicated)->current.integer && !strncmp(tempServerCommandBuf, "print", 5u))
|
|
||||||
{
|
|
||||||
Com_PrintF(CON_CHANNEL_SERVER, "broadcast: %s\n", SV_ExpandNewlines());
|
|
||||||
}
|
|
||||||
for (auto i = 0; i < (*sv_maxclients)->current.integer; ++i)
|
|
||||||
{
|
|
||||||
auto client = &svs->clients[i];
|
|
||||||
if (client->header.state >= CS_PRIMED)
|
|
||||||
{
|
|
||||||
SV_AddServerCommand(client, type, tempServerCommandBuf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sentient_GetVelocity(sentient_s* self, float* vVelOut)
|
|
||||||
{
|
|
||||||
static const auto call_addr = SELECT(0x0, 0x5662A0);
|
|
||||||
|
|
||||||
__asm
|
|
||||||
{
|
|
||||||
mov ecx, vVelOut;
|
|
||||||
mov eax, self;
|
|
||||||
call call_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace plutonium
|
namespace plutonium
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
#include "structs.hpp"
|
#include "structs.hpp"
|
||||||
|
|
||||||
#define SELECT(mp, sp) (game::environment::t4mp() ? mp : sp)
|
#define SELECT(mp, sp) (game::environment::t4mp() ? mp : sp)
|
||||||
#define CALL_ADDR(mp, sp) reinterpret_cast<void*>(SELECT(mp, sp))
|
#define ASSIGN(type, mp, sp) reinterpret_cast<type>(SELECT(mp, sp))
|
||||||
|
#define CALL_ADDR(mp, sp) ASSIGN(void*, mp, sp)
|
||||||
|
|
||||||
|
#define ARRAY_COUNT(arrayn) \
|
||||||
|
((sizeof(arrayn)) / (sizeof(arrayn[0])))
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
@ -22,91 +26,6 @@ namespace game
|
|||||||
bool t4sp();
|
bool t4sp();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::map<std::string, team_t> team_map;
|
|
||||||
|
|
||||||
__inline void* G_ClientDoPerFrameNotifies() { return CALL_ADDR(0x0, 0x503540); }
|
|
||||||
void G_ClientDoPerFrameNotifies(gentity_s* ent, void* call_addr = G_ClientDoPerFrameNotifies());
|
|
||||||
|
|
||||||
void Scr_PrintPrevCodePos(const char* codepos, int scriptInstance, con_channel_e channel, int index);
|
|
||||||
void RemoveRefToObject(scriptInstance_t inst, unsigned int id);
|
|
||||||
int Scr_LoadScript(const char* file, scriptInstance_t inst);
|
|
||||||
unsigned int Scr_GetFunctionHandle(scriptInstance_t inst, const char* file, const char* handle);
|
|
||||||
|
|
||||||
const char* Cmd_Argv(int index);
|
|
||||||
unsigned int Cmd_Argc();
|
|
||||||
void Cmd_AddCommand(const char* name, void(__cdecl* function)());
|
|
||||||
|
|
||||||
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);
|
|
||||||
const char* Dvar_ValueToString(dvar_s* dvar, DvarValue dvarValue);
|
|
||||||
void Dvar_SetVariant(dvar_s* dvar, DvarValue val, DvarSetSource dvarSetSource);
|
|
||||||
|
|
||||||
int Scr_GetInt(game::scriptInstance_t inst, unsigned int arg_index);
|
|
||||||
void Scr_AddInt(game::scriptInstance_t inst, int value);
|
|
||||||
float Scr_GetFloat(game::scriptInstance_t inst, unsigned int arg_index);
|
|
||||||
void Scr_AddFloat(game::scriptInstance_t inst, float value);
|
|
||||||
char* Scr_GetString(game::scriptInstance_t inst, unsigned int arg_index);
|
|
||||||
void Scr_AddString(game::scriptInstance_t inst, const char* string);
|
|
||||||
const char* Scr_GetIString(game::scriptInstance_t inst, unsigned int arg_index);
|
|
||||||
void Scr_AddIString(game::scriptInstance_t inst, const char* string);
|
|
||||||
unsigned short Scr_GetConstString(game::scriptInstance_t inst, unsigned int arg_index);
|
|
||||||
void Scr_AddConstString(game::scriptInstance_t inst, unsigned short id);
|
|
||||||
void Scr_GetVector(game::scriptInstance_t inst, unsigned int arg_index, float* value);
|
|
||||||
void Scr_AddVector(game::scriptInstance_t inst, float* value);
|
|
||||||
void Scr_AddUndefined(game::scriptInstance_t inst);
|
|
||||||
gentity_s* Scr_GetEntity(unsigned int arg_index);
|
|
||||||
void Scr_AddEntity(game::scriptInstance_t inst, gentity_s* ent);
|
|
||||||
__inline void* Scr_GetEntityId() { return CALL_ADDR(0x0, 0x692520); }
|
|
||||||
unsigned int Scr_GetEntityId(scriptInstance_t inst, unsigned int entnum, classNum_e classnum, unsigned int clientnum, void* call_addr = Scr_GetEntityId());
|
|
||||||
void Scr_AddEntityNum(scriptInstance_t inst, unsigned int entid);
|
|
||||||
pathnode_t* Scr_GetPathnode(scriptInstance_t inst);
|
|
||||||
void Scr_AddPathnode(scriptInstance_t inst, pathnode_t* node);
|
|
||||||
void Scr_AddHudElem(game_hudelem_s* hud);
|
|
||||||
void Scr_AddObject(scriptInstance_t inst, int entid);
|
|
||||||
void Scr_MakeArray(scriptInstance_t inst);
|
|
||||||
void Scr_AddArrayStringIndexed(scriptInstance_t inst, unsigned short id);
|
|
||||||
unsigned short Scr_ExecThread(scriptInstance_t inst, int handle, int paramCount);
|
|
||||||
unsigned short Scr_ExecEntThread(scriptInstance_t inst, int entNum, int handle, int numParams, int entClass);
|
|
||||||
__inline void* Scr_NotifyNum() { return CALL_ADDR(0x0, 0x698CC0); }
|
|
||||||
void Scr_NotifyNum(scriptInstance_t inst, int entNum, int entClass, unsigned int notifStr, int numParams, void* call_addr = Scr_NotifyNum());
|
|
||||||
|
|
||||||
__inline void* GetArrayVariableIndex() { return CALL_ADDR(0x0, 0x6902A0); }
|
|
||||||
unsigned int GetArrayVariableIndex(unsigned int unsignedValue, scriptInstance_t inst, unsigned int parentId, void* call_addr = GetArrayVariableIndex());
|
|
||||||
|
|
||||||
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);
|
|
||||||
pathnode_t* Path_NearestNodeNotCrossPlanes(int typeFlags, int maxNodes, float* vOrigin, pathsort_t* nodes, float fMaxDist, float a6, float a7, int iPlaneCount, int* returnCount, nearestNodeHeightCheck heightCheck);
|
|
||||||
int Path_FindPathFromTo(float* startPos, pathnode_t* pNodeTo, path_t* pPath, team_t eTeam, pathnode_t* pNodeFrom, float* vGoalPos, int bAllowNegotiationLinks, int bIgnoreBadplaces);
|
|
||||||
int Path_GeneratePath(path_t* pPath, team_t eTeam, const float* vStartPos, float* vGoalPos, pathnode_t* pNodeFrom, pathnode_t* pNodeTo, int bIncludeGoalPos, int bAllowNegotiationLinks);
|
|
||||||
void Path_UpdateLookahead(path_t* pPath, const float* vStartPos, int bReduceLookaheadAmount, int a4, int bAllowBacktrack);
|
|
||||||
void Path_AddTrimmedAmount(const float* a1, path_t* a2);
|
|
||||||
|
|
||||||
//Reimplemented functions
|
|
||||||
void Path_TransferLookahead(path_t* a1, const float* a2);
|
|
||||||
bool PM_IsSprinting(const playerState_s* ps);
|
|
||||||
pathnode_t* Path_ConvertIndexToNode(int index);
|
|
||||||
unsigned int __cdecl Path_ConvertNodeToIndex(const game::pathnode_t* node);
|
|
||||||
pathnode_t* Path_GetNegotiationNode(const path_t* pPath);
|
|
||||||
void Path_IncrementNodeUserCount(path_t* pPath);
|
|
||||||
void Path_DecrementNodeUserCount(path_t* pPath);
|
|
||||||
void Path_Clear(path_t* pPath);
|
|
||||||
float Vec2Length(const float* v);
|
|
||||||
float Path_GetPathDir(float* delta, const float* vFrom, const float* vTo);
|
|
||||||
float Vec3DistanceSq(const float* p1, const float* p2);
|
|
||||||
float EvaluateHeuristic(CustomSearchInfo_FindPath* searchInfo, pathnode_t* pSuccessor, const float* vGoalPos);
|
|
||||||
VariableUnion Scr_GetObject(unsigned int index, scriptInstance_t inst);
|
|
||||||
unsigned int GetArraySize(scriptInstance_t inst, unsigned int id);
|
|
||||||
unsigned int GetArrayVariable(scriptInstance_t inst, unsigned int parentId, unsigned int unsignedValue);
|
|
||||||
unsigned int __cdecl Scr_GetFunc(scriptInstance_t inst, unsigned int index);
|
|
||||||
void Dvar_Reset(DvarSetSource dvarSetSource, dvar_s* dvar);
|
|
||||||
void SV_SendServerCommand(client_s* clientArg, svscmd_type type, char* Format, ...);
|
|
||||||
|
|
||||||
void Sentient_GetVelocity(sentient_s* self, float* vVelOut);
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class symbol
|
class symbol
|
||||||
{
|
{
|
||||||
|
4415
src/game/structs.hpp
4415
src/game/structs.hpp
File diff suppressed because it is too large
Load Diff
@ -1,61 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define WEAK __declspec(selectany)
|
#define WEAK __declspec(selectany)
|
||||||
|
#define NAKED __declspec(naked)
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
{
|
{
|
||||||
// Functions
|
// Functions
|
||||||
|
WEAK symbol<void(con_channel_e channel, const char* fmt, ...)> Com_Printf{ 0x0, 0x59A2C0 };
|
||||||
WEAK symbol<void(con_channel_e channel, const char* fmt, ...)> Com_PrintF{ 0x0, 0x59A2C0 };
|
|
||||||
WEAK symbol<dvar_s*(const char* name, dvarType_t type, DvarFlags flags, DvarValue dval, DvarLimits dom, const char* desc)> Dvar_RegisterVariant{ 0x0, 0x5EED90 };
|
|
||||||
WEAK symbol<dvar_s* (char* name)> Dvar_FindMalleableVar{ 0x0, 0x5EDE30 };
|
|
||||||
WEAK symbol<void(client_s* client, svscmd_type type, const char* buffer)> SV_AddServerCommand{ 0x0, 0x633D30 };
|
|
||||||
WEAK symbol<char* ()> SV_ExpandNewlines{ 0x0, 0x633AD0 };
|
|
||||||
|
|
||||||
WEAK symbol<void(scriptInstance_t inst)> Scr_AddArray { 0x0, 0x69AA50 };
|
|
||||||
WEAK symbol<unsigned int(scriptInstance_t inst, char* string, int user, unsigned int len)> SL_GetStringOfSize { 0x0, 0x68DE50 };
|
|
||||||
|
|
||||||
WEAK symbol<int(path_t* pPath, team_t eTeam, const float* vStartPos, pathnode_t* pNodeFrom, const float* vGoalPos, int bAllowNegotiationLinks, CustomSearchInfo_FindPath* custom, int bIncludeGoalInPath, pathnode_t* bIgnoreBadPlaces)> Path_AStarAlgorithm_CustomSearchInfo_FindPath_{ 0x0, 0x4D3190 };
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
|
|
||||||
WEAK symbol<char> tempServerCommandBuf{ 0x0, 0x2FCDC00 };
|
WEAK symbol<char> tempServerCommandBuf{ 0x0, 0x2FCDC00 };
|
||||||
|
|
||||||
WEAK symbol<cmd_function_s*> cmd_functions{ 0x0, 0x1F416F4 };
|
|
||||||
WEAK symbol<CmdArgs> cmd_args{ 0x0, 0x1F41670 };
|
|
||||||
WEAK symbol<serverStatic_s> svs{ 0x0, 0x23D5C80 };
|
|
||||||
WEAK symbol<GameWorldSp*> gameWorldCurrent{ 0x0, 0x8E1D80 };
|
|
||||||
WEAK symbol<pathlocal_t> g_path{ 0x0, 0x1F2F700 };
|
|
||||||
WEAK symbol<gentity_s> g_entities{ 0x0, 0x176C6F0 };
|
|
||||||
WEAK symbol<game_hudelem_s> g_hudelems{ 0x0, 0x173C6F0 };
|
|
||||||
WEAK symbol<scrVarPub_t> gScrVarPub{ 0x0, 0x3882B70 };
|
|
||||||
WEAK symbol<scrVmPub_t> gScrVmPub{ 0x0, 0x3BD4700 };
|
|
||||||
WEAK symbol<level_locals_s> level{ 0x0, 0x18F5D88 };
|
|
||||||
WEAK symbol<float*> g_pathAttemptGoalPos{ 0x0, 0x16CFD6C };
|
|
||||||
//WEAK symbol<scrParserPub_t> scrParserPub{ 0x0, 0x3882B00 };
|
|
||||||
WEAK symbol<scrVarGlob_t> gScrVarGlob{ 0x0, 0x3914700 };
|
|
||||||
|
|
||||||
WEAK symbol<function_stack_t> function_stack{ 0x0, 0x3BDDDD0 };
|
|
||||||
WEAK symbol<scr_const_t> scr_const{0x0, 0x1F33B90};
|
|
||||||
WEAK symbol<char*> var_typename{ 0x0, 0x8CF4B0 };
|
|
||||||
|
|
||||||
WEAK symbol<WeaponDef*> BG_WeaponNames{ 0x0, 0x8F6770 };
|
|
||||||
|
|
||||||
// Dvars
|
|
||||||
|
|
||||||
WEAK symbol<dvar_s*> com_developer{ 0x0, 0x1F55288 };
|
|
||||||
WEAK symbol<dvar_s*> com_logfile{ 0x0, 0x1F552BC };
|
|
||||||
WEAK symbol<dvar_s*> com_developer_script{ 0x0, 0x1F9646C };
|
|
||||||
WEAK symbol<dvar_s*> com_dedicated{ 0x0, 0x212B2F4 };
|
|
||||||
WEAK symbol<dvar_s*> ai_pathNegotiationOverlapCost{ 0x0, 0x18FB224 };
|
|
||||||
WEAK symbol<dvar_s*> fs_homepath{ 0x0, 0x2123C1C };
|
|
||||||
WEAK symbol<dvar_s*> fs_game{ 0x0, 0x2122B00 };
|
|
||||||
WEAK symbol<dvar_s*> useFastFile{ 0x0, 0x1F552FC };
|
|
||||||
WEAK symbol<dvar_s*> sv_running{ 0x0, 0x1F552DC };
|
|
||||||
WEAK symbol<dvar_s*> sv_maxclients{ 0x0, 0x23D5C30 };
|
|
||||||
WEAK symbol<dvar_s*> g_connectpaths{ 0x0, 0x18ECF8C };
|
|
||||||
WEAK symbol<dvar_s*> r_reflectionProbeGenerate{ 0x0, 0x3BFD478 };
|
|
||||||
|
|
||||||
namespace plutonium
|
namespace plutonium
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -6,22 +6,17 @@ void component_loader::register_component(std::unique_ptr<component_interface>&&
|
|||||||
get_components().push_back(std::move(component_));
|
get_components().push_back(std::move(component_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool component_loader::post_start()
|
bool component_loader::post_start()
|
||||||
{
|
{
|
||||||
static auto handled = false;
|
static auto handled = false;
|
||||||
|
|
||||||
if (handled) return true;
|
if (handled) return true;
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
try
|
for (const auto& component_ : get_components())
|
||||||
{
|
{
|
||||||
for (const auto& component_ : get_components())
|
component_->post_start();
|
||||||
{
|
|
||||||
component_->post_start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (premature_shutdown_trigger&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -35,16 +30,9 @@ bool component_loader::post_load()
|
|||||||
|
|
||||||
clean();
|
clean();
|
||||||
|
|
||||||
try
|
for (const auto& component_ : get_components())
|
||||||
{
|
{
|
||||||
for (const auto& component_ : get_components())
|
component_->post_load();
|
||||||
{
|
|
||||||
component_->post_load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (premature_shutdown_trigger&)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -107,11 +95,6 @@ void* component_loader::load_import(const std::string& library, const std::strin
|
|||||||
return function_ptr;
|
return function_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void component_loader::trigger_premature_shutdown()
|
|
||||||
{
|
|
||||||
throw premature_shutdown_trigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<component_interface>>& component_loader::get_components()
|
std::vector<std::unique_ptr<component_interface>>& component_loader::get_components()
|
||||||
{
|
{
|
||||||
using component_vector = std::vector<std::unique_ptr<component_interface>>;
|
using component_vector = std::vector<std::unique_ptr<component_interface>>;
|
||||||
|
@ -4,14 +4,6 @@
|
|||||||
class component_loader final
|
class component_loader final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class premature_shutdown_trigger final : public std::exception
|
|
||||||
{
|
|
||||||
[[nodiscard]] const char* what() const noexcept override
|
|
||||||
{
|
|
||||||
return "Premature shutdown requested";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class installer final
|
class installer final
|
||||||
{
|
{
|
||||||
@ -48,8 +40,6 @@ public:
|
|||||||
|
|
||||||
static void* load_import(const std::string& library, const std::string& function);
|
static void* load_import(const std::string& library, const std::string& function);
|
||||||
|
|
||||||
static void trigger_premature_shutdown();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<std::unique_ptr<component_interface>>& get_components();
|
static std::vector<std::unique_ptr<component_interface>>& get_components();
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#pragma warning(disable: 26812)
|
#pragma warning(disable: 26812)
|
||||||
#pragma warning(disable: 28182)
|
#pragma warning(disable: 28182)
|
||||||
|
|
||||||
|
#pragma warning(disable: 4324)
|
||||||
|
|
||||||
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
#define DLL_EXPORT extern "C" __declspec(dllexport)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -57,6 +59,6 @@
|
|||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#define printf(__fmt__, ...) \
|
#define printf(__fmt__, ...) \
|
||||||
game::Com_PrintF(game::CON_CHANNEL_SERVER, __fmt__, __VA_ARGS__)
|
game::Com_Printf(game::CON_CHANNEL_SERVER, __fmt__, __VA_ARGS__)
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
@ -11,29 +11,24 @@ namespace utils::http
|
|||||||
{
|
{
|
||||||
struct progress_helper
|
struct progress_helper
|
||||||
{
|
{
|
||||||
const std::function<void(size_t)>* callback{};
|
const std::function<bool(size_t)>* callback{};
|
||||||
std::exception_ptr exception{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4244)
|
||||||
int progress_callback(void* clientp, const curl_off_t /*dltotal*/, const curl_off_t dlnow, const curl_off_t /*ultotal*/, const curl_off_t /*ulnow*/)
|
int progress_callback(void* clientp, const curl_off_t /*dltotal*/, const curl_off_t dlnow, const curl_off_t /*ultotal*/, const curl_off_t /*ulnow*/)
|
||||||
{
|
{
|
||||||
auto* helper = static_cast<progress_helper*>(clientp);
|
auto* helper = static_cast<progress_helper*>(clientp);
|
||||||
|
|
||||||
try
|
if (*helper->callback && !(*helper->callback)(dlnow))
|
||||||
{
|
{
|
||||||
if (*helper->callback)
|
|
||||||
{
|
|
||||||
(*helper->callback)(dlnow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
helper->exception = std::current_exception();
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
size_t write_callback(void* contents, const size_t size, const size_t nmemb, void* userp)
|
size_t write_callback(void* contents, const size_t size, const size_t nmemb, void* userp)
|
||||||
{
|
{
|
||||||
@ -45,7 +40,7 @@ namespace utils::http
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> get_data(const std::string& url, const headers& headers, const std::function<void(size_t)>& callback)
|
std::optional<std::string> get_data(const std::string& url, const headers& headers, const std::function<bool(size_t)>& callback)
|
||||||
{
|
{
|
||||||
curl_slist* header_list = nullptr;
|
curl_slist* header_list = nullptr;
|
||||||
auto* curl = curl_easy_init();
|
auto* curl = curl_easy_init();
|
||||||
@ -83,11 +78,6 @@ namespace utils::http
|
|||||||
return {std::move(buffer)};
|
return {std::move(buffer)};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (helper.exception)
|
|
||||||
{
|
|
||||||
std::rethrow_exception(helper.exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,6 @@ namespace utils::http
|
|||||||
{
|
{
|
||||||
using headers = std::unordered_map<std::string, std::string>;
|
using headers = std::unordered_map<std::string, std::string>;
|
||||||
|
|
||||||
std::optional<std::string> get_data(const std::string& url, const headers& headers = {}, const std::function<void(size_t)>& callback = {});
|
std::optional<std::string> get_data(const std::string& url, const headers& headers = {}, const std::function<bool(size_t)>& callback = {});
|
||||||
std::future<std::optional<std::string>> get_data_async(const std::string& url, const headers& headers = {});
|
std::future<std::optional<std::string>> get_data_async(const std::string& url, const headers& headers = {});
|
||||||
}
|
}
|
@ -1,393 +0,0 @@
|
|||||||
import idautils
|
|
||||||
import idc
|
|
||||||
import idaapi
|
|
||||||
import ida_funcs
|
|
||||||
import ida_idaapi
|
|
||||||
import ida_typeinf
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Operand types returned by get_operand_Type
|
|
||||||
# o_void = cvar.o_void
|
|
||||||
# o_reg = cvar.o_reg
|
|
||||||
# o_mem = cvar.o_mem
|
|
||||||
# o_phrase = cvar.o_phrase
|
|
||||||
# o_displ = cvar.o_displ
|
|
||||||
# o_imm = cvar.o_imm
|
|
||||||
# o_far = cvar.o_far # Jump
|
|
||||||
# o_near = cvar.o_near # Jump
|
|
||||||
# o_idpspec0 = cvar.o_idpspec0
|
|
||||||
# o_idpspec1 = cvar.o_idpspec1
|
|
||||||
# o_idpspec2 = cvar.o_idpspec2
|
|
||||||
# o_idpspec3 = cvar.o_idpspec3
|
|
||||||
# o_idpspec4 = cvar.o_idpspec4
|
|
||||||
# o_idpspec5 = cvar.o_idpspec5
|
|
||||||
|
|
||||||
# Output file to write function code
|
|
||||||
output_file_c = "function_code.c"
|
|
||||||
|
|
||||||
# Output file to write function declarations
|
|
||||||
output_file_h = "function_declarations.h"
|
|
||||||
|
|
||||||
dumpable_funcs_searched = 0
|
|
||||||
|
|
||||||
max_functions_to_dump = 50
|
|
||||||
|
|
||||||
dumped_func_addr_array = []
|
|
||||||
|
|
||||||
dumpable_func_calls = []
|
|
||||||
|
|
||||||
dumpable_func_names = []
|
|
||||||
|
|
||||||
global_objects_list = {}
|
|
||||||
|
|
||||||
debug_dump_extra_data = True
|
|
||||||
|
|
||||||
# array indexed by func names of pairs of a start addr
|
|
||||||
jump_locs = {}
|
|
||||||
|
|
||||||
jump_loc_names = {}
|
|
||||||
|
|
||||||
def is_integer(n):
|
|
||||||
try:
|
|
||||||
int(n)
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def item_in_array(array, item):
|
|
||||||
try:
|
|
||||||
array.index(item)
|
|
||||||
except ValueError:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def is_ida_hex_str(str):
|
|
||||||
for char in str:
|
|
||||||
if not is_integer(char) and char != "h":
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def convert_ida_hex_str_to_true_hex(str):
|
|
||||||
int_str = ""
|
|
||||||
for char in str:
|
|
||||||
if is_integer(char):
|
|
||||||
int_str += char
|
|
||||||
return hex(int(int_str))
|
|
||||||
|
|
||||||
def clean_func_name(func_name):
|
|
||||||
has_colon = item_in_array(func_name, ":")
|
|
||||||
has_semicolon = item_in_array(func_name, ";")
|
|
||||||
new_name = ""
|
|
||||||
if has_colon:
|
|
||||||
new_name = func_name.split(":")[1]
|
|
||||||
elif has_semicolon:
|
|
||||||
new_name = func_name.split(";")[0]
|
|
||||||
else:
|
|
||||||
new_name = func_name
|
|
||||||
# index = 0
|
|
||||||
# for char in func_name:
|
|
||||||
# if char == ";":
|
|
||||||
# continue
|
|
||||||
# new_name += char
|
|
||||||
return new_name
|
|
||||||
|
|
||||||
def get_func_name_in_register(insn):
|
|
||||||
tokens = insn.split()
|
|
||||||
index = 0
|
|
||||||
for token in tokens:
|
|
||||||
if token == ";":
|
|
||||||
fwd_index = index + 1
|
|
||||||
if fwd_index > len(tokens):
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
return tokens[index + 1]
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def funct_is_dumpable(func_name, addr):
|
|
||||||
called_func = idaapi.get_func(addr)
|
|
||||||
called_func_flags = idc.get_func_flags(addr)
|
|
||||||
# data_segment_for_addr = idaapi.get_segm_by_name(".idata")
|
|
||||||
if not idaapi.is_func_entry(called_func):
|
|
||||||
return False
|
|
||||||
if idc.get_segm_name(addr) != ".text":
|
|
||||||
return False
|
|
||||||
if called_func_flags & ida_funcs.FUNC_LIB:
|
|
||||||
return False
|
|
||||||
# if not data_segment_for_addr:
|
|
||||||
# return False
|
|
||||||
# if data_segment_for_addr.contains(called_ea):
|
|
||||||
# return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# def parse_addr_from_loc_name(loc_name):
|
|
||||||
# index = 0
|
|
||||||
# array_size = len(loc_name)
|
|
||||||
# for char in loc_name:
|
|
||||||
# while not is_integer(char) and
|
|
||||||
|
|
||||||
def parse_assembly_for_func_calls(func_addr):
|
|
||||||
global dumpable_funcs_searched
|
|
||||||
if dumpable_funcs_searched >= max_functions_to_dump:
|
|
||||||
print("Hit func search limit {}".format(dumpable_funcs_searched))
|
|
||||||
return
|
|
||||||
dumpable_funcs_searched += 1
|
|
||||||
func = idaapi.get_func(func_addr)
|
|
||||||
if not func:
|
|
||||||
print("Couldn't find func at addr {}".format(hex(func_addr)))
|
|
||||||
return
|
|
||||||
primary_func_name = idc.get_func_name(func_addr)
|
|
||||||
# Iterate over the function's basic blocks
|
|
||||||
print("Searching function {}".format(primary_func_name))
|
|
||||||
# Iterate over the instructions in the basic block
|
|
||||||
for insn in idautils.FuncItems(func_addr):
|
|
||||||
insn2 = idaapi.insn_t()
|
|
||||||
idaapi.decode_insn(insn2, insn)
|
|
||||||
# Write the instruction to the .c file
|
|
||||||
first_operand_type = idc.get_operand_type(insn, 0)
|
|
||||||
second_operand_type = idc.get_operand_type(insn, 1)
|
|
||||||
operand_name = insn2.get_canon_mnem()
|
|
||||||
insn_as_string = idc.GetDisasm(insn)
|
|
||||||
insn_tokens = insn_as_string.split()
|
|
||||||
if operand_name == "call":
|
|
||||||
called_func_name = insn_tokens[1]
|
|
||||||
cleaned_func_name = clean_func_name(called_func_name)
|
|
||||||
called_ea = idc.get_name_ea_simple(cleaned_func_name)
|
|
||||||
|
|
||||||
if called_ea == ida_idaapi.BADADDR:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Handle functions stored in registers
|
|
||||||
if cleaned_func_name == "eax":
|
|
||||||
# if get_func_name_in_register(insn_tokens) == "":
|
|
||||||
# print("Couldn't resolve function name for {} in primary func {}".format(insn_as_string, primary_func_name))
|
|
||||||
# continue
|
|
||||||
continue
|
|
||||||
|
|
||||||
if item_in_array(dumpable_func_calls, called_ea):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not funct_is_dumpable(clean_func_name, called_ea):
|
|
||||||
continue
|
|
||||||
|
|
||||||
dumpable_func_calls.append(called_ea)
|
|
||||||
dumpable_func_names.append(cleaned_func_name)
|
|
||||||
|
|
||||||
parse_assembly_for_func_calls(called_ea)
|
|
||||||
elif first_operand_type == idaapi.o_near: # TODO: Handle idaapi.o_far jump type
|
|
||||||
if insn_tokens[1] == "short":
|
|
||||||
start_loc_name = insn_tokens[2]
|
|
||||||
else:
|
|
||||||
start_loc_name = insn_tokens[1]
|
|
||||||
|
|
||||||
if not primary_func_name in jump_locs:
|
|
||||||
jump_locs[primary_func_name] = []
|
|
||||||
jump_loc_names[primary_func_name] = {}
|
|
||||||
|
|
||||||
loc_addr = idc.get_name_ea_simple(start_loc_name)
|
|
||||||
if loc_addr == ida_idaapi.BADADDR:
|
|
||||||
# TODO: Add logging for this
|
|
||||||
continue
|
|
||||||
if loc_addr in jump_locs[primary_func_name]:
|
|
||||||
continue
|
|
||||||
jump_locs[primary_func_name].append(loc_addr)
|
|
||||||
jump_loc_names[primary_func_name]["{}".format(loc_addr)] = start_loc_name
|
|
||||||
# if first_operand_type == idaapi.o_void:
|
|
||||||
# continue
|
|
||||||
# if first_operand_type == idaapi.o_mem:
|
|
||||||
# # get_operand_value # Returns the offset added to the operand
|
|
||||||
# # TODO: Get the base address of the object too so the offset isn't lost ida_name.get_name_base_ea
|
|
||||||
# global_object_addr = idc.get_operand_value(insn, 0)
|
|
||||||
# global_object_name = idc.get_name(global_object_addr) # This function can take in flags that determine what name it returns
|
|
||||||
# object_addr_as_str = "{}".format(global_object_addr)
|
|
||||||
# if global_object_addr == ida_idaapi.BADADDR:
|
|
||||||
# # Add logging warning here
|
|
||||||
# print("Failed to add global object to list")
|
|
||||||
# elif not (object_addr_as_str in global_objects_list):
|
|
||||||
# print("Object is not in list {}".format(hex(global_object_addr)))
|
|
||||||
# global_objects_list[object_addr_as_str] = global_object_name
|
|
||||||
# if (second_operand_type == idaapi.o_mem):
|
|
||||||
# global_object_addr = idc.get_operand_value(insn, 1)
|
|
||||||
# global_object_name = idc.get_name(global_object_addr)
|
|
||||||
# object_addr_as_str = "{}".format(global_object_addr)
|
|
||||||
# if global_object_addr == ida_idaapi.BADADDR:
|
|
||||||
# # Add logging warning here
|
|
||||||
# print("Failed to add global object to list")
|
|
||||||
# elif not (object_addr_as_str in global_objects_list):
|
|
||||||
# print("Object is not in list {}".format(hex(global_object_addr)))
|
|
||||||
# global_objects_list[object_addr_as_str] = global_object_name
|
|
||||||
|
|
||||||
def addr_is_end_loc(func_name, addr):
|
|
||||||
for jump_loc in jump_locs[func_name]:
|
|
||||||
# print("addr_is_end_loc: {} {} {}".format(func_name, addr, jump_loc))
|
|
||||||
if jump_loc == addr:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def pre_parse_instruction(insn_str):
|
|
||||||
index = 0
|
|
||||||
pre_string = ""
|
|
||||||
string_len = len(insn_str)
|
|
||||||
for char in insn_str:
|
|
||||||
if (index + 1) < string_len:
|
|
||||||
fwd_char = insn_str[index + 1]
|
|
||||||
if fwd_char == "+" or fwd_char == "-" or fwd_char == "*" or fwd_char == "/":
|
|
||||||
pre_string += char + " "
|
|
||||||
index += 1
|
|
||||||
continue
|
|
||||||
if char == "+" or char == "-" or char == "*" or char == "/":
|
|
||||||
pre_string += char + " "
|
|
||||||
index += 1
|
|
||||||
continue
|
|
||||||
if char == ";":
|
|
||||||
index += 1
|
|
||||||
continue
|
|
||||||
pre_string += char
|
|
||||||
index += 1
|
|
||||||
return pre_string
|
|
||||||
|
|
||||||
def post_parse_instruction_as_tokens(insn_str):
|
|
||||||
final_string = ""
|
|
||||||
index = 0
|
|
||||||
tokens = insn_str.split()
|
|
||||||
max_index = len(tokens)
|
|
||||||
for token in tokens:
|
|
||||||
if token == "short" or token == "offset":
|
|
||||||
index += 1
|
|
||||||
continue
|
|
||||||
if is_ida_hex_str(token):
|
|
||||||
token = convert_ida_hex_str_to_true_hex(token)
|
|
||||||
if index != max_index:
|
|
||||||
final_string += token + " "
|
|
||||||
else:
|
|
||||||
final_string += token
|
|
||||||
index += 1
|
|
||||||
return final_string
|
|
||||||
|
|
||||||
def dump_function_code(func_ea, mangled_name, f_c, f_h):
|
|
||||||
global debug_dump_extra_data
|
|
||||||
# Try to demangle the name
|
|
||||||
# demangled_name = idc.demangle_name(mangled_name, idc.INF_SHORT_DN)
|
|
||||||
func_name = mangled_name
|
|
||||||
# if demangled_name != "None":
|
|
||||||
# func_name = demangled_name
|
|
||||||
f_c.write("\n/*{}*/\n".format(hex(func_ea)))
|
|
||||||
cfunc_ptr = idaapi.decompile(func_ea)
|
|
||||||
arguments = cfunc_ptr.arguments
|
|
||||||
f_c.write("{}".format(func_name))
|
|
||||||
# lvar_t info
|
|
||||||
# type method on arguments index returns a tinfo_t
|
|
||||||
# name class var on arguments index
|
|
||||||
if arguments:
|
|
||||||
f_c.write(" /*(")
|
|
||||||
# arg is a tinfo_t object
|
|
||||||
index = 0
|
|
||||||
args_len = len(arguments)
|
|
||||||
# TODO: Dump arg registers too
|
|
||||||
for arg in arguments:
|
|
||||||
if index + 1 >= args_len:
|
|
||||||
f_c.write(" {} {}".format(arg.type().dstr(), arg.name))
|
|
||||||
continue
|
|
||||||
f_c.write(" {} {},".format(arg.type().dstr(), arg.name))
|
|
||||||
index += 1
|
|
||||||
f_c.write(" )*/\n")
|
|
||||||
else:
|
|
||||||
f_c.write("/*( )*/\n")
|
|
||||||
|
|
||||||
# Write the function declaration to the .h file
|
|
||||||
f_h.write("void {}();\n".format(func_name))
|
|
||||||
func_has_jump_locs = mangled_name in jump_locs
|
|
||||||
# func_object = idaapi.get_func(func_ea)
|
|
||||||
|
|
||||||
# Iterate over the instructions in the function
|
|
||||||
for insn in idautils.FuncItems(func_ea):
|
|
||||||
# Write the instruction to the .c file
|
|
||||||
insn_as_string = idc.GetDisasm(insn)
|
|
||||||
insn2 = idaapi.insn_t()
|
|
||||||
idaapi.decode_insn(insn2, insn)
|
|
||||||
instruction_name = insn2.get_canon_mnem()
|
|
||||||
if func_has_jump_locs:
|
|
||||||
|
|
||||||
if addr_is_end_loc(mangled_name, insn2.ea):
|
|
||||||
func_addr_as_str = "{}".format(insn2.ea)
|
|
||||||
if func_addr_as_str in jump_loc_names[func_name]:
|
|
||||||
f_c.write("{}:\n".format(jump_loc_names[func_name][func_addr_as_str]))
|
|
||||||
f_c.write("\t")
|
|
||||||
# pre_string = pre_parse_instruction(insn_as_string)
|
|
||||||
# final_string = post_parse_instruction_as_tokens(pre_string)
|
|
||||||
# f_c.write(final_string + "\n")
|
|
||||||
first_operand_type = idc.get_operand_type(insn, 0)
|
|
||||||
second_operand_type = idc.get_operand_type(insn, 1)
|
|
||||||
wrote_first_operand_addrs = False
|
|
||||||
wrote_second_operand_addrs = False
|
|
||||||
f_c.write(" {}".format(insn_as_string))
|
|
||||||
if not debug_dump_extra_data:
|
|
||||||
f_c.write("\n")
|
|
||||||
continue
|
|
||||||
if first_operand_type == idaapi.o_mem:
|
|
||||||
# get_operand_value # Returns the offset added to the operand
|
|
||||||
# TODO: Get the base address of the object too so the offset isn't lost
|
|
||||||
global_object_addr = idc.get_operand_value(insn, 0)
|
|
||||||
# object_addr_as_str = "{}".format(global_object_addr)
|
|
||||||
f_c.write(" //:Type: <{}> :Addr: <{}>".format(first_operand_type, hex(global_object_addr)))
|
|
||||||
wrote_first_operand_addrs = True
|
|
||||||
if second_operand_type == idaapi.o_mem:
|
|
||||||
global_object_addr = idc.get_operand_value(insn, 1)
|
|
||||||
# object_addr_as_str = "{}".format(global_object_addr)
|
|
||||||
if wrote_first_operand_addrs:
|
|
||||||
f_c.write(" {} {}".format(second_operand_type, hex(global_object_addr)))
|
|
||||||
else:
|
|
||||||
f_c.write(" //:Type: <{}> :Addr: <{}>".format(second_operand_type, hex(global_object_addr)))
|
|
||||||
wrote_second_operand_addrs = True
|
|
||||||
if instruction_name == "call":
|
|
||||||
# get_operand_value # Returns the offset added to the operand
|
|
||||||
# TODO: Get the base address of the object too so the offset isn't lost
|
|
||||||
call_addr = idc.get_operand_value(insn, 0)
|
|
||||||
# object_addr_as_str = "{}".format(global_object_addr)
|
|
||||||
f_c.write(" //:Type: <{}> :Addr: <{}>".format(first_operand_type, hex(call_addr)))
|
|
||||||
wrote_first_operand_addrs = True
|
|
||||||
if wrote_first_operand_addrs and not wrote_second_operand_addrs:
|
|
||||||
f_c.write(" {}".format(second_operand_type))
|
|
||||||
elif not wrote_first_operand_addrs and not wrote_second_operand_addrs:
|
|
||||||
f_c.write(" //:Type: <{}> :Type: <{}>".format(first_operand_type, second_operand_type))
|
|
||||||
|
|
||||||
f_c.write("\n")
|
|
||||||
f_c.write("\n")
|
|
||||||
|
|
||||||
# Open the output files in write mode
|
|
||||||
with open(output_file_c, "w") as f_c, open(output_file_h, "w") as f_h:
|
|
||||||
|
|
||||||
# Write the header guard for the .h file
|
|
||||||
f_h.write("#ifndef FUNCTION_DECLARATIONS_H\n#define FUNCTION_DECLARATIONS_H\n\n")
|
|
||||||
|
|
||||||
# Name of the input function to dump
|
|
||||||
# input_func_ea = 0x699E90 # Scr_GetFloat
|
|
||||||
|
|
||||||
input_func_ea = 0x40FAA0 # G_FindItem
|
|
||||||
|
|
||||||
# Get the address of the input function
|
|
||||||
input_func_name = idc.get_func_name(input_func_ea)
|
|
||||||
# Define a function to dump the code for a given function
|
|
||||||
dumpable_func_calls.append(input_func_ea)
|
|
||||||
dumpable_func_names.append(input_func_name)
|
|
||||||
# f_c.write(" //op: {}\n".format(insn2.get_canon_mnem()))
|
|
||||||
# Dump the code for the input function
|
|
||||||
|
|
||||||
print("Starting search for functions recursively")
|
|
||||||
parse_assembly_for_func_calls(input_func_ea)
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
function_count = len(dumpable_func_names)
|
|
||||||
print("Dumping {} functions max {}". format(function_count, max_functions_to_dump))
|
|
||||||
for func_addr in dumpable_func_calls:
|
|
||||||
if index >= max_functions_to_dump:
|
|
||||||
break
|
|
||||||
func_name = dumpable_func_names[index]
|
|
||||||
print("Now dumping {} at address {} count {}".format(func_name, hex(func_addr), index))
|
|
||||||
dump_function_code(func_addr, func_name, f_c, f_h)
|
|
||||||
index += 1
|
|
||||||
print("Successfully dumped {} of {} total functions".format(function_count, max_functions_to_dump))
|
|
||||||
# Write the footer guard for the .h file
|
|
||||||
f_h.write("\n#endif")
|
|
||||||
print("Function code written to {} and function declarations written to {}".format(output_file_c, output_file_h))
|
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user