mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2025-07-03 09:41:51 +00:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
9ca07aca55 | |||
10b45027d0 | |||
d5c0063fee
|
|||
31920b0692 | |||
89e4edc00b | |||
379a21ff7e | |||
0ac5225114 | |||
e918bdf28f | |||
50b83787e7 | |||
e6ca925562 | |||
0f92a7ce25 | |||
d4d91de80f | |||
a508a7e3a4 |
@ -93,7 +93,7 @@ namespace gsc
|
||||
{
|
||||
if (id < 0x200)
|
||||
{
|
||||
return reinterpret_cast<builtin_function*>(0x20689DD8)[id]();
|
||||
return reinterpret_cast<builtin_function*>(game::plutonium::function_table.get())[id]();
|
||||
}
|
||||
|
||||
try
|
||||
@ -119,7 +119,7 @@ namespace gsc
|
||||
{
|
||||
if (id < 0x8400)
|
||||
{
|
||||
return reinterpret_cast<builtin_method*>(0x2068A5A8)[id - 0x8000](ent);
|
||||
return reinterpret_cast<builtin_method*>(game::plutonium::method_table.get())[id - 0x8000](ent);
|
||||
}
|
||||
|
||||
try
|
||||
@ -270,7 +270,7 @@ namespace gsc
|
||||
|
||||
namespace field
|
||||
{
|
||||
void add(classid classnum, const std::string& name,
|
||||
void add(const classid classnum, const std::string& name,
|
||||
const std::function<scripting::script_value(unsigned int entnum)>& getter,
|
||||
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter)
|
||||
{
|
||||
@ -416,6 +416,22 @@ namespace gsc
|
||||
return {};
|
||||
});
|
||||
|
||||
method::add("isbot", [](const game::scr_entref_t ent, const function_args& args) -> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
throw std::runtime_error("Invalid entity");
|
||||
}
|
||||
|
||||
const auto client = ent.entnum;
|
||||
if (game::g_entities[client].client == nullptr)
|
||||
{
|
||||
throw std::runtime_error("entity is not a player");
|
||||
}
|
||||
|
||||
return game::svs_clients[client].bIsTestClient;
|
||||
});
|
||||
|
||||
utils::hook::jump(0x56C8EB, call_builtin_stub);
|
||||
utils::hook::jump(0x56CBDC, call_builtin_method_stub);
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "game/scripting/array.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
@ -46,7 +48,7 @@ namespace gsc
|
||||
|
||||
namespace field
|
||||
{
|
||||
void add(classid classnum, const std::string& name,
|
||||
void add(const classid classnum, const std::string& name,
|
||||
const std::function<scripting::script_value(unsigned int entnum)>& getter,
|
||||
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter);
|
||||
}
|
||||
|
@ -2,12 +2,6 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
#include "game/scripting/array.hpp"
|
||||
|
||||
#include "gsc.hpp"
|
||||
#include "json.hpp"
|
||||
|
||||
|
@ -2,12 +2,6 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
#include "game/scripting/array.hpp"
|
||||
|
||||
#include "gsc.hpp"
|
||||
#include "json.hpp"
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/scripting/entity.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "gsc.hpp"
|
||||
#include "scripting.hpp"
|
||||
|
||||
namespace notifies
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::vector<scripting::function> say_callbacks;
|
||||
utils::hook::detour client_command_hook;
|
||||
|
||||
void client_command_stub(int clientNum)
|
||||
@ -17,19 +18,28 @@ namespace notifies
|
||||
|
||||
game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
|
||||
|
||||
auto hidden = false;
|
||||
if (cmd == "say"s || cmd == "say_team"s)
|
||||
{
|
||||
std::string message = game::ConcatArgs(1);
|
||||
message.erase(0, 1);
|
||||
|
||||
const scripting::entity level{*game::levelEntityId};
|
||||
const auto player = scripting::call("getEntByNum", {clientNum}).as<scripting::entity>();
|
||||
for (const auto& callback : say_callbacks)
|
||||
{
|
||||
const auto entity_id = game::Scr_GetEntityId(clientNum, 0);
|
||||
const auto result = callback(entity_id, {message, cmd == "say_team"s});
|
||||
|
||||
scripting::notify(level, cmd, {player, message});
|
||||
scripting::notify(player, cmd, {message});
|
||||
if (result.is<int>() && !hidden)
|
||||
{
|
||||
hidden = result.as<int>() == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return client_command_hook.invoke<void>(clientNum);
|
||||
if (!hidden)
|
||||
{
|
||||
client_command_hook.invoke<void>(clientNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +49,18 @@ namespace notifies
|
||||
void post_unpack() override
|
||||
{
|
||||
client_command_hook.create(0x502CB0, client_command_stub);
|
||||
|
||||
scripting::on_shutdown([]()
|
||||
{
|
||||
say_callbacks.clear();
|
||||
});
|
||||
|
||||
gsc::function::add("onplayersay", [](const gsc::function_args& args) -> scripting::script_value
|
||||
{
|
||||
const auto function = args[0].as<scripting::function>();
|
||||
say_callbacks.push_back(function);
|
||||
return {};
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -29,6 +29,8 @@ namespace scripting
|
||||
|
||||
std::string current_file;
|
||||
|
||||
std::vector<std::function<void()>> shutdown_callbacks;
|
||||
|
||||
void vm_notify_stub(const unsigned int notify_list_owner_id, const unsigned int string_value,
|
||||
game::VariableValue* top)
|
||||
{
|
||||
@ -77,6 +79,12 @@ namespace scripting
|
||||
{
|
||||
userinfo::clear_overrides();
|
||||
command::clear_script_commands();
|
||||
|
||||
for (const auto& callback : shutdown_callbacks)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
|
||||
g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||
}
|
||||
|
||||
@ -106,6 +114,11 @@ namespace scripting
|
||||
}
|
||||
}
|
||||
|
||||
void on_shutdown(const std::function<void()>& callback)
|
||||
{
|
||||
shutdown_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
@ -4,4 +4,6 @@ namespace scripting
|
||||
{
|
||||
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
||||
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||
|
||||
void on_shutdown(const std::function<void()>& callback);
|
||||
}
|
@ -2,12 +2,6 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
#include "game/scripting/array.hpp"
|
||||
|
||||
#include "gsc.hpp"
|
||||
|
||||
namespace userinfo
|
||||
@ -19,12 +13,17 @@ namespace userinfo
|
||||
{
|
||||
utils::hook::detour sv_getuserinfo_hook;
|
||||
|
||||
userinfo_map userinfo_to_map(const std::string& userinfo)
|
||||
userinfo_map userinfo_to_map(std::string userinfo)
|
||||
{
|
||||
userinfo_map map;
|
||||
const auto args = utils::string::split(userinfo, '\\');
|
||||
userinfo_map map{};
|
||||
|
||||
for (auto i = 1; i < args.size() - 1; i += 2)
|
||||
if (userinfo[0] == '\\')
|
||||
{
|
||||
userinfo = userinfo.substr(1);
|
||||
}
|
||||
|
||||
const auto args = utils::string::split(userinfo, '\\');
|
||||
for (size_t i = 0; !args.empty() && i < (args.size() - 1); i += 2)
|
||||
{
|
||||
map[args[i]] = args[i + 1];
|
||||
}
|
||||
@ -34,7 +33,7 @@ namespace userinfo
|
||||
|
||||
std::string map_to_userinfo(const userinfo_map& map)
|
||||
{
|
||||
std::string buffer;
|
||||
std::string buffer{};
|
||||
|
||||
for (const auto& value : map)
|
||||
{
|
||||
@ -49,9 +48,8 @@ namespace userinfo
|
||||
|
||||
void sv_getuserinfo_stub(int index, char* buffer, int bufferSize)
|
||||
{
|
||||
char _buffer[1024];
|
||||
sv_getuserinfo_hook.invoke<void>(index, _buffer, 1024);
|
||||
auto map = userinfo_to_map(_buffer);
|
||||
sv_getuserinfo_hook.invoke<void>(index, buffer, bufferSize);
|
||||
auto map = userinfo_to_map(buffer);
|
||||
|
||||
if (userinfo_overrides.find(index) == userinfo_overrides.end())
|
||||
{
|
||||
@ -109,8 +107,6 @@ namespace userinfo
|
||||
|
||||
gsc::method::add("resetname", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
|
||||
{
|
||||
const auto name = args[0].as<std::string>();
|
||||
|
||||
if (ent.classnum != 0 || ent.entnum > 17)
|
||||
{
|
||||
throw std::runtime_error("Invalid entity");
|
||||
@ -141,8 +137,6 @@ namespace userinfo
|
||||
|
||||
gsc::method::add("resetclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
|
||||
{
|
||||
const auto name = args[0].as<std::string>();
|
||||
|
||||
if (ent.classnum != 0 || ent.entnum > 17)
|
||||
{
|
||||
throw std::runtime_error("Invalid entity");
|
||||
|
@ -5,16 +5,18 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
{
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
const auto value = *reinterpret_cast<DWORD*>(0x20800000);
|
||||
if (value != 0xB9C9566)
|
||||
const auto value = *reinterpret_cast<DWORD*>(0x21000000);
|
||||
if (value != 0x7AC6)
|
||||
{
|
||||
printf("\x1b[31m\n**************************************************************************************\n\n");
|
||||
printf("This version of \x1b[33miw5-gsc-utils\x1b[31m is outdated.\n");
|
||||
printf("Download the latest dll from here:\x1b[34m https://github.com/fedddddd/iw5-gsc-utils/releases \x1b[31m\n");
|
||||
printf("\n**************************************************************************************\n\n\x1b[37m");
|
||||
MessageBoxA(NULL,
|
||||
"This version of iw5-gsc-utils is outdated.\n" \
|
||||
"Download the latest dll from here: https://github.com/fedddddd/iw5-gsc-utils/releases" \
|
||||
, "ERROR", MB_ICONERROR);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
utils::hook::jump(reinterpret_cast<uintptr_t>(&printf), game::plutonium::printf);
|
||||
component_loader::post_unpack();
|
||||
}
|
||||
|
||||
|
@ -60,13 +60,11 @@ namespace scripting
|
||||
array::array()
|
||||
{
|
||||
this->id_ = make_array();
|
||||
this->add();
|
||||
}
|
||||
|
||||
array::array(std::vector<script_value> values)
|
||||
{
|
||||
this->id_ = make_array();
|
||||
this->add();
|
||||
|
||||
for (const auto& value : values)
|
||||
{
|
||||
@ -77,7 +75,6 @@ namespace scripting
|
||||
array::array(std::unordered_map<std::string, script_value> values)
|
||||
{
|
||||
this->id_ = make_array();
|
||||
this->add();
|
||||
|
||||
for (const auto& value : values)
|
||||
{
|
||||
|
@ -59,8 +59,8 @@ namespace scripting
|
||||
|
||||
script_function get_function_by_index(const unsigned index)
|
||||
{
|
||||
static const auto function_table = 0x20689DD8;
|
||||
static const auto method_table = 0x2068A5A8;
|
||||
static const auto function_table = game::plutonium::function_table.get();
|
||||
static const auto method_table = game::plutonium::method_table.get();
|
||||
|
||||
if (index < 0x1C7)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ namespace scripting::safe_execution
|
||||
bool call(const script_function function, const game::scr_entref_t& entref)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0))
|
||||
{
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
@ -39,7 +39,7 @@ namespace scripting::safe_execution
|
||||
bool set_entity_field(const game::scr_entref_t& entref, const int offset)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0))
|
||||
{
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
@ -54,7 +54,7 @@ namespace scripting::safe_execution
|
||||
bool get_entity_field(const game::scr_entref_t& entref, const int offset, game::VariableValue* value)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level]))
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0, 0, 0))
|
||||
{
|
||||
value->type = game::SCRIPT_NONE;
|
||||
value->u.intValue = 0;
|
||||
|
@ -82,6 +82,11 @@ namespace scripting
|
||||
return "array";
|
||||
}
|
||||
|
||||
if (info == typeid(function))
|
||||
{
|
||||
return "function";
|
||||
}
|
||||
|
||||
if (info == typeid(vector))
|
||||
{
|
||||
return "vector";
|
||||
|
@ -327,4 +327,15 @@ namespace game
|
||||
int flags;
|
||||
char __pad2[0xEC];
|
||||
};
|
||||
|
||||
struct client_s
|
||||
{
|
||||
char __pad0[0x41CB2];
|
||||
unsigned __int16 scriptId; // 269490
|
||||
int bIsTestClient; // 269492
|
||||
int serverId; // 269496
|
||||
char __pad1[0x369DC];
|
||||
};
|
||||
|
||||
static_assert(sizeof(client_s) == 0x78698);
|
||||
}
|
@ -62,7 +62,7 @@ namespace game
|
||||
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x56DFE0};
|
||||
|
||||
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{0x7363BC};
|
||||
WEAK symbol<int(jmp_buf* Buf)> _setjmp{0x734CF8};
|
||||
WEAK symbol<int(jmp_buf* Buf, int a2, int a3, int a4)> _setjmp{0x734CF8};
|
||||
|
||||
// Variables
|
||||
|
||||
@ -79,10 +79,15 @@ namespace game
|
||||
WEAK symbol<gentity_s> g_entities{0x1A66E28};
|
||||
WEAK symbol<unsigned int> levelEntityId{0x208E1A4};
|
||||
|
||||
WEAK symbol<client_s> svs_clients{0x4B5CF90};
|
||||
|
||||
namespace plutonium
|
||||
{
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> function_map_rev{0x20691228};
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> method_map_rev{0x20691248};
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> token_map_rev{0x20691288};
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> function_map_rev{0x206964D0};
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> method_map_rev{0x206964F0};
|
||||
WEAK symbol<std::unordered_map<std::string, std::uint16_t>> token_map_rev{0x20696530};
|
||||
WEAK symbol<int(const char* fmt, ...)> printf{0x20887840};
|
||||
WEAK symbol<void*> function_table{0x2068F210};
|
||||
WEAK symbol<void*> method_table{0x2068F9E0};
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user