int Scr_SetParameters(unsigned int Num){
return *(int*)(0x13C3140 + 0x203 = Num;
}
//This will set the parameter number
struct opd_s{
uint Sub;
uint Toc;
};
opd_s ParseAddr(int Address){
opd_s GLS = { Address, 0x724C38 };
return GLS;
}
//TOC
#define Scr_AddInt(Value) ((void(*)(int))&ParseAddr(0x20C60)(Value)
#define Scr_AddFloat(Value) ((void(*)(float))&ParseAddr(0x20C5C0))(Value)
#define Scr_AddString(String) ((void(*)(const char*))&ParseAddr(0x20C42)(String)
#define Scr_AddEntity(Entity) ((void(*)(int))&ParseAddr(0x1B7700))(Entity)
#define Scr_AddVector(Vec) ((void(*)(const float*))&ParseAddr(0x20C330))(Vec)
#define Scr_ClearOutParams() ((void(*)(void))&ParseAddr(0x20C19)()
void GScr_Earthquake(float scale, float duration, float* source, float radius){
Scr_AddFloat(radius);
Scr_AddVector(source);
Scr_AddFloat(duration);
Scr_AddFloat(scale);
Scr_SetParameters(4); //See how I set the parameter number after I finish calling the Scr_Adds?
((void(*)())&ParseAddr(0x1A80E)(); //Call the actual function
//((void(*)(int))&ParseAddr(0x1A80E)(ClientID << 16); //Only call this one if the one above doesn't work.
Scr_ClearOutParams();
}
void PatchInJump(int Address, int Destination){
int FuncBytes[4];
Destination = *(int*)Destination;
FuncBytes[0] = 0x3D600000 + ((Destination >> 16) & 0xFFFF);
if(Destination & 0x8000) FuncBytes[0] += 1;
FuncBytes[1] = 0x396B0000 + (Destination & 0xFFFF);
FuncBytes[2] = 0x7D6903A6;
FuncBytes[3] = 0x4E800420;
Memcpy((void*)Address, FuncBytes, 4*4);
}
void hookFunctionStart(int Address, int saveStub, int Destination){ //Works on every game
saveStub = *(int*)saveStub;
int BranchtoAddress = Address + (4*4);
int StubData[8];
StubData[0] = 0x3D600000 + ((BranchtoAddress >> 16) & 0xFFFF);
if(BranchtoAddress & 0x8000) StubData[0] += 1;
StubData[1] = 0x396B0000 + (BranchtoAddress & 0xFFFF);
StubData[2] = 0x7D6903A6;
Memcpy(&StubData[3], (void*)Address, 4*4);
StubData[7] = 0x4E800420;
Memcpy((void*)saveStub, StubData, 8*4);
PatchInJump(Address, Destination);
}
void VM_ResumeStub(int TimeId){
__asm("li %r3, 0x3");
}
void VM_ResumeHook(int TimeId){ // If this doesn't work, hook int VM_Execute() - 0x20CC08 with hookFunctionStart
//You would call GScr_Earthquake here. Obv not in the loop. Make sure you implement a check in here to make it // get called once
VM_ResumeStub(TimeId);
}
hookFunctionStart(0x210A48, (int)VM_ResumeStub, (int)VM_ResumeHook);
#define SL_ConvertToString(StringValue) ((const char*(*)(unsigned short))ParseAddr(0x200280))(StringValue)
hookFunctionStart(0x20B7C8, (int)VM_NotifyStub, (int)VM_NotifyHook);
void VM_NotifyStub(unsigned int self, short Stringvalue, unsigned int Paramcount){
__asm("li %r3, 0x4");
}
void VM_NotifyHook(unsigned int self, short Stringvalue, unsigned int Paramcount){
//Now if we wanted to monitor onPlayerSpawned we do
int ClientID = ((int(*)(int))&ParseAddr(0x201F90))(self); //Scr_GetSelf
const char* Notify = SL_ConvertToString(Stringvalue);
if(!strcmp(Notify, "spawned_player")){
//Executed on spawn. This monitors for ANY CLIENT THAT SPAWNS!
GScr_Earthquake(0.6f, 2, (float*)(Playerstate() + 0x1C), 800); //Yes you can call this in V
}
VM_NotifyStub(self, Stringvalue, Paramcount);
}
Copyright © 2024, NextGenUpdate.
All Rights Reserved.