Skip to content
Open
2 changes: 2 additions & 0 deletions src/Components/Loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include "Modules/Window.hpp"

#include "Modules/BotLib/lPrecomp.hpp"
#include "Modules/ViewModelFxSetup.hpp"

namespace Components
{
Expand Down Expand Up @@ -180,6 +181,7 @@ namespace Components
Register(new GSC::GSC());

Register(new BotLib::lPrecomp());
Register(new ViewModelFxSetup::Setup());

Pregame = false;
}
Expand Down
1 change: 1 addition & 0 deletions src/Components/Loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ namespace Components
#include "Modules/Rumble.hpp"

#include "Modules/GSC/GSC.hpp"
#include "Modules/ViewModelFxSetup.hpp"
98 changes: 98 additions & 0 deletions src/Components/Modules/ViewModelFx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include <STDInclude.hpp>
#include "Components/Modules/GSC/Script.hpp"
#include "Components/Modules/GSC/ScriptExtension.hpp"
#include "Components/Modules/Weapon.hpp"
#include "Components/Modules/ViewModelFxSetup.hpp"

namespace Components::ViewModelFxSetup
{
static char cg_weaponsArray[32 * Weapon::WEAPON_LIMIT];

void Add_GSC_Functions()
{
// 3arc function for iw game
GSC::Script::AddFunction("PlayViewmodelFX", []
{
if (Game::Scr_GetNumParam() != 2)
{
Game::Scr_Error("PlayViewmodelFX() called with wrong params.\n");
return;
}

const char* fxName = Game::Scr_GetString(0); // FX name string
Game::scr_string_t tagName = Game::Scr_GetConstString(1); // Bone/tag

Game::FxEffectDef* fx = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_FX, fxName).fx;
if (!fx)
{
Game::Scr_Error(Utils::String::VA("PlayViewmodelFX(): FX '%s' not found", fxName));
return;
}

int clientNum = 0; // local player
const Game::DObj* dobj = Game::Com_GetClientDObj(clientNum, 0);
if (!dobj)
{
Game::Scr_Error("PlayViewmodelFX(): Could not get DObj for local player");
return;
}

unsigned char boneIdx = 0;
if (!Game::DObjGetBoneIndex(reinterpret_cast<int>(dobj), tagName, &boneIdx))
{
Game::Scr_Error(Utils::String::VA(
"PlayViewmodelFX(): clientNum '%d' does not have bone '%s'",
clientNum,
Game::SL_ConvertToString(tagName)
));
return;
}

int dobjHandle = dobj->entnum;
Game::CG_PlayBoltedEffect(0, fx, dobjHandle, tagName);
});

GSC::Script::AddFunction("PVMFX_BOTH", []
{
if (Game::Scr_GetNumParam() != 2)
{
Game::Scr_Error("PVMFX_BOTH() called with wrong params. Expected 2.\n");
return;
}

const char* fxName = Game::Scr_GetString(0); // FX name string
Game::scr_string_t tagName = Game::Scr_GetConstString(1); // Bone/tag

Game::FxEffectDef* fx = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_FX, fxName).fx;
if (!fx)
{
Game::Scr_Error(Utils::String::VA("PVMFX_BOTH(): FX '%s' not found", fxName));
return;
}

for (int hand = 0; hand <= 1; ++hand)
{
int fpDObjHandle = Game::CG_WeaponDObjHandle(hand);
if (fpDObjHandle)
{
Game::CG_PlayBoltedEffect(0, fx, fpDObjHandle, tagName);

Game::CG_StopBoltedEffect(0, 0, fpDObjHandle, tagName);
}
}

int clientNum = 0;
const Game::DObj* tpDObj = Game::Com_GetClientDObj(clientNum, 0);
if (tpDObj)
{
Game::CG_PlayBoltedEffect(0, fx, tpDObj->entnum, tagName);

Game::CG_StopBoltedEffect(0, 0, tpDObj->entnum, tagName);
}
});

Setup::Setup()
{
Add_GSC_Functions();
}
}
10 changes: 10 additions & 0 deletions src/Components/Modules/ViewModelFxSetup.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

namespace Components::ViewModelFxSetup
{
class Setup : public Component
{
public:
Setup();
};
}
6 changes: 6 additions & 0 deletions src/Game/Functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@ namespace Game

const char* logFileName = reinterpret_cast<const char*>(0x730130);

DObjGetBoneIndex_t DObjGetBoneIndex = reinterpret_cast<DObjGetBoneIndex_t>(0x504F20);
Com_GetClientDObj_t Com_GetClientDObj = reinterpret_cast<Com_GetClientDObj_t>(0x41FF50);
CG_WeaponDObjHandle_t CG_WeaponDObjHandle = reinterpret_cast<CG_WeaponDObjHandle_t>(0x41DB70);
CG_StopBoltedEffect_t CG_StopBoltedEffect = reinterpret_cast<CG_StopBoltedEffect_t>(0x44C230);


const char* TableLookup(StringTable* stringtable, int row, int column)
{
if (!stringtable || !stringtable->values || row >= stringtable->rowCount || column >= stringtable->columnCount) return "";
Expand Down
12 changes: 12 additions & 0 deletions src/Game/Functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ namespace Game
typedef const DObj*(*CG_GetBoneIndex_t)(int localClientNum, unsigned int boneName, char* boneIndex);
extern CG_GetBoneIndex_t CG_GetBoneIndex;

typedef int(__cdecl* DObjGetBoneIndex_t)(int a1, int a2, unsigned char* a3);
extern DObjGetBoneIndex_t DObjGetBoneIndex;

typedef DObj* (__cdecl* Com_GetClientDObj_t)(int handle, int localClientNum);
extern Com_GetClientDObj_t Com_GetClientDObj;

typedef int(__cdecl* CG_WeaponDObjHandle_t)(int hand);
extern CG_WeaponDObjHandle_t CG_WeaponDObjHandle;

typedef char* (__cdecl* CG_StopBoltedEffect_t)(int localClientNum, int effectHandle, int dobjHandle, int tagName);
extern CG_StopBoltedEffect_t CG_StopBoltedEffect;

typedef void(*CG_ScoresDown_f_t)();
extern CG_ScoresDown_f_t CG_ScoresDown_f;

Expand Down