diff --git a/xlive/H2MOD.cpp b/xlive/H2MOD.cpp index 6c0b1c10c..5e1699432 100644 --- a/xlive/H2MOD.cpp +++ b/xlive/H2MOD.cpp @@ -281,7 +281,7 @@ tc_simulation_unit_entity_definition_creation_decode pc_simulation_unit_entity_d bool __stdcall c_simulation_unit_entity_definition_creation_decode(void *thisptr, int creation_data_size, void* creation_data, bitstream* stream) { //LOG_TRACE_GAME_N("c_simulation_unit_entity_definition_creation_decode()\r\nthisptr: %08X, creation_data_size: %i, creation_data: %08X, packet: %08X", thisptr, creation_data_size, creation_data, packet); - + if (stream->data_decode_bool("object-permutation-exists")) { //LOG_TRACE_GAME_N("c_simulation_unit_entity_decode - object-permutation-exists packet: %08X, *packet: %08X", packet, *(int*)packet); @@ -533,6 +533,8 @@ void H2MOD::set_unit_biped(Player::Biped biped_type, int playerIndex) PlayerIterator playersIt; if (playerIndex >= 0 && playerIndex < 16) playersIt.get_data_at_index(playerIndex)->properties.profile.player_character_type = biped_type; + + *(BYTE*)(((BYTE*)h2mod->GetAddress(0x977104) + 0x20CC * playerIndex) + 8) = (BYTE)biped_type; } BYTE H2MOD::get_unit_team_index(datum unit_datum_index) @@ -574,7 +576,7 @@ void H2MOD::set_unit_speed_patch(bool hackit) { } else { - memcpy(patch_addr, origBytes, 8); + WriteBytes((DWORD)patch_addr, origBytes, 8); } } @@ -667,6 +669,25 @@ void H2MOD::disable_sound(int sound) } } +void H2MOD::custom_sound_play(const char* soundName, int delay) +{ + auto playSound = [=]() + { + //std::unique_lock lck(h2mod->sound_mutex); + std::chrono::high_resolution_clock::time_point timePoint = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(delay); + + LOG_TRACE_GAME("[H2MOD-SoundQueue] - attempting to play sound {0} - delaying {1} miliseconds first", soundName, delay); + + if (delay > 0) + std::this_thread::sleep_until(timePoint); + + PlaySoundA(soundName, NULL, SND_FILENAME | SND_NODEFAULT); + }; + + if (!h2mod->Server) + std::thread(playSound).detach(); +} + void H2MOD::custom_sound_play(const wchar_t* soundName, int delay) { auto playSound = [=]() @@ -1573,7 +1594,27 @@ int __cdecl LoadSaveGameHook(int a1, SaveStackStruct *a2, char a3) wsprintf((wchar_t*)((BYTE*)a2->OutBuffer + 4), var_name_mod); *(BYTE*)((BYTE*)a2->OutBuffer + 0x44) = variant_engine[engine_name]; - + + short flags = *(short*)((BYTE*)a2->OutBuffer + 0x48); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sqTeamGame ^ flags) & (1UL << variant_flag_bitfield::_game_engine_teams_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sqMotionSensor ^ flags) & (1UL << variant_flag_bitfield::_game_engine_motion_sensor_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgAlwaysInvisible ^ flags) & (1UL << variant_flag_bitfield::_game_engine_always_invisible_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgRoundSwitchResetsMap ^ flags) & (1UL << variant_flag_bitfield::_game_engine_round_switch_resets_map_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgObservers ^ flags) & (1UL << variant_flag_bitfield::_game_engine_observers_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgAllowChangingTeams ^ flags) & (1UL << variant_flag_bitfield::_game_engine_changing_teams_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgFriendlyFire ^ flags) & (1UL << variant_flag_bitfield::_game_engine_friendly_fire_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgOvershieldsOnMap ^ flags) & (1UL << variant_flag_bitfield::_game_engine_overshields_on_map_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgInvisibilityOnMap ^ flags) & (1UL << variant_flag_bitfield::_game_engine_invisiblity_on_map_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgGrenadesOnMap ^ flags) & (1UL << variant_flag_bitfield::_game_engine_grenades_on_map_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgStartingGrenades ^ flags) & (1UL << variant_flag_bitfield::_game_engine_starting_grenades_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgExtraDamage ^ flags) & (1UL << variant_flag_bitfield::_game_engine_extra_damage_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgDamageResistant ^ flags) & (1UL << variant_flag_bitfield::_game_engine_extra_damage_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgForceEvenTeams ^ flags) & (1UL << variant_flag_bitfield::_game_engine_force_even_teams_bit); + *(short*)((BYTE*)a2->OutBuffer + 0x48) ^= (-(unsigned long)ScriptEngine::g_sgRoundSetting1Round ^ flags) & (1UL << variant_flag_bitfield::_game_engine_round_setting_1_round); + + + *(short*)((BYTE*)a2->OutBuffer + 0x54) = ScriptEngine::g_sqRoundTime; + return 1; } @@ -1705,6 +1746,7 @@ void H2MOD::ApplyHooks() { // bellow hooks applied to specific executables if (this->Server == false) { + HMODULE h = GetModuleHandleA("DiscordHook.dll"); //DWORD random_memory = malloc() LOG_TRACE_GAME("Applying client hooks..."); @@ -1788,8 +1830,7 @@ void H2MOD::ApplyHooks() { //Hooked to fix custom map images. Codecave(GetAddress(0x593F0), load_map_data_for_display,0); - - + //Initialise_tag_loader(); } else { diff --git a/xlive/H2MOD.h b/xlive/H2MOD.h index db79731dd..a1b077c4a 100644 --- a/xlive/H2MOD.h +++ b/xlive/H2MOD.h @@ -45,6 +45,25 @@ enum game_life_cycle : int life_cycle_matchmaking }; +enum variant_flag_bitfield : BYTE +{ + _game_engine_teams_bit = 0, + _game_engine_motion_sensor_bit, + _game_engine_always_invisible_bit, + _game_engine_round_switch_resets_map_bit, + _game_engine_tie_resolution_bit, + _game_engine_observers_bit, + _game_engine_changing_teams_bit, + _game_engine_friendly_fire_bit, + _game_engine_overshields_on_map_bit, + _game_engine_invisiblity_on_map_bit, + _game_engine_grenades_on_map_bit, + _game_engine_starting_grenades_bit, + _game_engine_extra_damage_bit, + _game_engine_damage_resistant_bit, + _game_engine_force_even_teams_bit, + _game_engine_round_setting_1_round +}; int __cdecl call_object_try_and_get_with_type(datum object_datum_index, int object_type); int __cdecl call_unit_reset_equipment(datum unit_datum_index); bool __cdecl call_add_object_to_sync(datum gamestate_object_datum); @@ -87,6 +106,8 @@ class H2MOD void set_player_unit_grenades_count(int playerIndex, BYTE type, BYTE count, bool resetEquipment); void disable_sound(int sound); void custom_sound_play(const wchar_t* soundName, int delay); + void custom_sound_play(const char* soundName, int delay); + void toggle_weapon_pickup(); void toggle_weapon_pickup(bool bEnable); void leave_session(); diff --git a/xlive/H2MOD/GUI/GUI.cpp b/xlive/H2MOD/GUI/GUI.cpp index c19e26e0e..ffc66b1ff 100644 --- a/xlive/H2MOD/GUI/GUI.cpp +++ b/xlive/H2MOD/GUI/GUI.cpp @@ -162,7 +162,7 @@ extern void handleHotkeyInput(WPARAM lpMsg); // #5030: XLivePreTranslateMessage BOOL WINAPI XLivePreTranslateMessage(const LPMSG lpMsg) { - if ((GetAsyncKeyState(lpMsg->wParam) & 0x8000) && (lpMsg->message == WM_KEYDOWN || lpMsg->message == WM_SYSKEYDOWN)) + if ((GetKeyState(lpMsg->wParam) & 0x8000) && (lpMsg->message == WM_KEYDOWN || lpMsg->message == WM_SYSKEYDOWN)) { // hotkeys handleHotkeyInput(lpMsg->wParam); diff --git a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp index 280ec0ec4..065b47043 100644 --- a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp +++ b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp @@ -96,7 +96,7 @@ void register_custom_packets(void* network_messages) register_packet_impl(network_messages, request_sq_script, "request-sq-script", 0, sizeof(s_request_script), sizeof(s_request_script), (void*)sqScriptDownloader::encode_sq_request_packet, (void*)sqScriptDownloader::decode_sq_request_packet, NULL); - register_packet_impl(network_messages, send_sq_script, "send-sq-script", 0, 4, 65535, (void*)sqScriptDownloader::encode_sq_send_packet,(void*)sqScriptDownloader::decode_sq_send_packet, NULL); + register_packet_impl(network_messages, send_sq_script, "send-sq-script", 1, 4, 0xFFFFF, (void*)sqScriptDownloader::encode_sq_send_packet,(void*)sqScriptDownloader::decode_sq_send_packet, NULL); } @@ -223,11 +223,13 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde size_t data_size = sizeof(s_send_script) + scriptData.size() + 1; s_send_script *data = (s_send_script*)malloc(data_size); ZeroMemory(data, sizeof(s_send_script) + scriptData.size()); - data->script_size = scriptData.size(); + data->script_size = scriptData.size() +1; strcpy(&data->script_data[0], scriptData.c_str()); data->script_data[scriptData.size() + 1] = 0; observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, false, send_sq_script, data_size, data); + + free(data); } } @@ -284,13 +286,16 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde return; } - case send_sq_script: + case send_sq_script: // received script from server { - if (*(int*)network_channel + 0x54 == 5) + if (*(int*)(network_channel + 0x54) == 5) { s_send_script* received_data = (s_send_script*)packet; LOG_INFO_FUNC("[H2MOD-CustomPackets] script_size: {}", received_data->script_size); LOG_INFO_FUNC("[H2MOD-CustomPackets] script: {}",(char*)&received_data->script_data); + + sqScriptDownloader::sq_process_script((char*)&received_data->script_data); + } return; } diff --git a/xlive/H2MOD/Modules/Networking/Networking.cpp b/xlive/H2MOD/Modules/Networking/Networking.cpp index 3a43a5c39..e92f9b1dd 100644 --- a/xlive/H2MOD/Modules/Networking/Networking.cpp +++ b/xlive/H2MOD/Modules/Networking/Networking.cpp @@ -43,7 +43,6 @@ bool __cdecl parameters_update_decode(bitstream* stream, int a2, int a3) int script_id = 0; bool ret = pparameters_update_decode(stream, a2, a3); bool script_loaded = stream->data_decode_bool("sqScript-loaded"); - if(script_loaded == true) script_id = stream->data_decode_integer("sqScript-id", 32); diff --git a/xlive/H2MOD/Modules/Scripting/ScriptDownloader.cpp b/xlive/H2MOD/Modules/Scripting/ScriptDownloader.cpp index 88df27b30..199bf1175 100644 --- a/xlive/H2MOD/Modules/Scripting/ScriptDownloader.cpp +++ b/xlive/H2MOD/Modules/Scripting/ScriptDownloader.cpp @@ -2,13 +2,14 @@ #include "ScriptDownloader.h" #include "H2MOD/Modules/Networking/Networking.h" #include "H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h" +#include "H2MOD.h" #include "xliveless.h" #include #include #undef max // windows.h defines max. -bool g_sqScriptDownloaded = false; +bool g_sqScriptDownloaded = true; namespace sqScriptDownloader { @@ -35,8 +36,8 @@ namespace sqScriptDownloader { { s_request_script data; XUserGetXUID(0, &data.user_identifier); - network_observer* observer = session->network_observer_ptr; + peer_observer_channel* observer_channel = NetworkSession::getPeerObserverChannel(session->session_host_peer_index); if (observer_channel->field_1) @@ -68,18 +69,19 @@ namespace sqScriptDownloader { void sq_process_script(char* script_data) { // process script data received + ScriptEngine::sqLoadScriptFromString(script_data); } void encode_sq_request_packet(bitstream* stream, int a2, s_request_script* data) { LOG_INFO_FUNC(" user_identifier: {}", data->user_identifier); - stream->data_encode_integer("user-identifier", data->user_identifier, 64); + stream->data_encode_bits("user-identifier", &data->user_identifier, 64); } bool decode_sq_request_packet(bitstream* stream, int a2, s_request_script* data) { - data->user_identifier = stream->data_decode_integer("user-identifier", 64); - + stream->data_decode_bits("user-identifier", (int)&data->user_identifier, 64); + LOG_INFO_FUNC(" user_idenitfier: {}", data->user_identifier); return stream->packet_is_valid() == false; @@ -97,10 +99,16 @@ namespace sqScriptDownloader { bool decode_sq_send_packet(bitstream* stream, int a2, s_send_script* data) { data->script_size = stream->data_decode_integer("sqScriptSize", 32); - stream->data_decode_bits("sqScriptData", (int)&data->script_data, data->script_size * CHAR_BIT); + + if (stream->packet_is_valid()) + LOG_CRITICAL_FUNC("stream->packet_is_valid()"); + + + if (data->script_size < 0 || data->script_size > 0xFFFF || a2 != data->script_size + 4) + LOG_CRITICAL_FUNC("data->script_size < 0 || data->script_size > 0xFFFF || a2 != data->script_size + 4"); - LOG_INFO_FUNC("data->script_size: {}", data->script_size); - LOG_INFO_FUNC("data->data: {}", (char*)&data->script_data); + stream->data_decode_bits("sqScriptData", (int)&data->script_data, data->script_size * CHAR_BIT); + g_sqScriptDownloaded = true; return stream->packet_is_valid() == false; diff --git a/xlive/H2MOD/Modules/Scripting/ScriptDownloader.h b/xlive/H2MOD/Modules/Scripting/ScriptDownloader.h index d374c0b99..f9ca12681 100644 --- a/xlive/H2MOD/Modules/Scripting/ScriptDownloader.h +++ b/xlive/H2MOD/Modules/Scripting/ScriptDownloader.h @@ -8,5 +8,6 @@ namespace sqScriptDownloader { void encode_sq_send_packet(bitstream* stream, int a2, s_send_script* data); bool decode_sq_send_packet(bitstream* stream, int a2, s_send_script* data); void send_sq_request_packet(); + void sq_process_script(char* script_data); std::string sq_send_script_fill_data(); } diff --git a/xlive/H2MOD/Modules/Scripting/Squirrel.cpp b/xlive/H2MOD/Modules/Scripting/Squirrel.cpp index 8b7908bf5..925106c85 100644 --- a/xlive/H2MOD/Modules/Scripting/Squirrel.cpp +++ b/xlive/H2MOD/Modules/Scripting/Squirrel.cpp @@ -4,17 +4,16 @@ #include "Squirrel.h" #include "H2MOD.h" #include "Globals.h" +#include "xliveless.h" bool g_sqScriptLoaded = false; int g_sqScriptId = 0; char* g_sqScriptPath = NULL; +extern bool g_sqScriptDownloaded; void sqAddDebugText(char* Msg) { - std::string dbgMsg; - dbgMsg.append("[Squirrel] - "); - dbgMsg.append(Msg); - addDebugText(dbgMsg.c_str()); + LOG_INFO_FUNC("{}",Msg); } static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v) @@ -45,8 +44,7 @@ void sqPrint(HSQUIRRELVM v, const SQChar* desc, ...) vsprintf(nDbgMsg, desc, arglist); va_end(arglist); - sqAddDebugText(nDbgMsg); - + LOG_INFO_FUNC("{}", nDbgMsg); } void sqError(HSQUIRRELVM v, const SQChar* desc, ...) @@ -58,26 +56,18 @@ void sqError(HSQUIRRELVM v, const SQChar* desc, ...) vsprintf(nDbgMsg, desc, arglist); va_end(arglist); - sqAddDebugText(nDbgMsg); + LOG_CRITICAL_FUNC("{}", nDbgMsg); } void compile_error_handler(HSQUIRRELVM v, const SQChar* desc, const SQChar* source, SQInteger line, SQInteger column) -{ - char* dbgMsg = new char[2000]; - sprintf(dbgMsg, "Compiler Error: line: %i, column: %i, desc: %s, source: %s", line, column, desc, source); - sqAddDebugText(dbgMsg); - +{ + LOG_CRITICAL_FUNC("[Squirrel] Compiler error - line {}, column {}, desc {}, souce {}", line, column, desc, source); } void debughook(HSQUIRRELVM vm, SQInteger type, const SQChar *sourcename, SQInteger line, const SQChar *funcname) { - char* dbgMsg = new char[2000]; - //std::string dbgMsg; - sprintf(dbgMsg, "Debug: type: %i, source: %s, line: %i, function: %s", type, sourcename, line, funcname); - sqAddDebugText(dbgMsg); - - + LOG_TRACE_FUNC("[Squirrel] Debug type {}, source {}, line {}, function {}", type, sourcename, line, funcname); } @@ -85,17 +75,83 @@ void debughook(HSQUIRRELVM vm, SQInteger type, const SQChar *sourcename, SQInteg namespace ScriptEngine { + std::string loaded_script; + bool g_sqTeamGame = false; + bool g_sqMotionSensor = true; + bool g_sgAlwaysInvisible = false; + bool g_sgRoundSwitchResetsMap = false; + bool g_sgTieResolution = false; + bool g_sgObservers = false; + bool g_sgAllowChangingTeams = true; + bool g_sgFriendlyFire = false; + bool g_sgOvershieldsOnMap = true; + bool g_sgInvisibilityOnMap = true; + bool g_sgGrenadesOnMap = true; + bool g_sgStartingGrenades = true; + bool g_sgExtraDamage = false; + bool g_sgDamageResistant = false; + bool g_sgForceEvenTeams = false; + bool g_sgRoundSetting1Round = false; + + short g_sqRoundTime = 0; + + int g_unit_datum = 0; + + void sqLoadScriptFromString(char* script_data) + { + LOG_TRACE_FUNC("[Squirrel] - Loading script data"); + sqSessionEnd(); + sqSessionStart(); + Sqrat::Script varScript; + sq_setprintfunc(Sqrat::DefaultVM::Get(), sqPrint, sqError); + sq_enabledebuginfo(Sqrat::DefaultVM::Get(), true); + sq_notifyallexceptions(Sqrat::DefaultVM::Get(), true); + sq_setcompilererrorhandler(Sqrat::DefaultVM::Get(), compile_error_handler); + sq_setnativedebughook(Sqrat::DefaultVM::Get(), debughook); + sq_newclosure(Sqrat::DefaultVM::Get(), _sqstd_aux_printerror, 0); + sq_seterrorhandler(Sqrat::DefaultVM::Get()); + sqstd_seterrorhandlers(Sqrat::DefaultVM::Get()); + + Sqrat::Table tblgSettings(Sqrat::DefaultVM::Get()); + tblgSettings.SetValue("isTeamGame", 0); + tblgSettings.SetValue("motionSensor", 1); + tblgSettings.SetValue("roundTime", 0); + tblgSettings.SetValue("alwaysInvisible", 0); + tblgSettings.SetValue("roundSwitchResetMap", 0); + tblgSettings.SetValue("tieResolution", 0); + tblgSettings.SetValue("observers", 0); + tblgSettings.SetValue("allowChangingTeams", 1); + tblgSettings.SetValue("friendlyFire", 0); + tblgSettings.SetValue("overshieldOnMap", 1); + tblgSettings.SetValue("invisibilityOnMap", 1); + tblgSettings.SetValue("grenadesOnMap", 1); + tblgSettings.SetValue("startingGrenades", 1); + tblgSettings.SetValue("extraDamage", 0); + tblgSettings.SetValue("damageResistant", 0); + tblgSettings.SetValue("forceEvenTeams", 0); + tblgSettings.SetValue("roundsEnable", 0); + + Sqrat::RootTable(Sqrat::DefaultVM::Get()).Bind(_SC("gameTypeSettings"), tblgSettings); + + + std::string errMsg; + if (varScript.CompileString(script_data, errMsg, "downloaded")) + { + varScript.Run(); + LOG_INFO_FUNC("[Squirrel] - Downloaded script compiled succesfully!"); + g_sqScriptLoaded = true; + } + else + LOG_CRITICAL_FUNC("[Squirrel] Failed to load downloaded script!"); + + } void sqLoadScript(std::string path) { - std::string dbgMsg; - dbgMsg.append("[Squirrel] - Loading script: "); - dbgMsg.append(path); - addDebugText(dbgMsg.c_str()); - + LOG_INFO_FUNC("[Squirrel] - Loading Script: {}", path); Sqrat::Script varScript; sq_setprintfunc(Sqrat::DefaultVM::Get(), sqPrint, sqError); @@ -107,11 +163,144 @@ namespace ScriptEngine { sq_seterrorhandler(Sqrat::DefaultVM::Get()); sqstd_seterrorhandlers(Sqrat::DefaultVM::Get()); + Sqrat::Table tblgSettings(Sqrat::DefaultVM::Get()); + + tblgSettings.SetValue("isTeamGame", 0); + tblgSettings.SetValue("motionSensor", 1); + tblgSettings.SetValue("roundTime", 0); + tblgSettings.SetValue("alwaysInvisible", 0); + tblgSettings.SetValue("roundSwitchResetMap", 0); + tblgSettings.SetValue("tieResolution", 0); + tblgSettings.SetValue("observers", 0); + tblgSettings.SetValue("allowChangingTeams", 1); + tblgSettings.SetValue("friendlyFire", 0); + tblgSettings.SetValue("overshieldOnMap", 1); + tblgSettings.SetValue("invisibilityOnMap", 1); + tblgSettings.SetValue("grenadesOnMap", 1); + tblgSettings.SetValue("startingGrenades", 1); + tblgSettings.SetValue("extraDamage", 0); + tblgSettings.SetValue("damageResistant", 0); + tblgSettings.SetValue("forceEvenTeams", 0); + tblgSettings.SetValue("roundsEnable", 0); + + Sqrat::RootTable(Sqrat::DefaultVM::Get()).Bind(_SC("gameTypeSettings"), tblgSettings); std::string errMsg; if (varScript.CompileFile(path.c_str(), errMsg)) { + varScript.Run(); + + Sqrat::SharedPtr spIsTeamGame = tblgSettings.GetValue("isTeamGame"); + if (spIsTeamGame != NULL) + g_sqTeamGame = *spIsTeamGame; + else + LOG_WARNING_FUNC("No gametype setting for isTeamGame was set."); + + Sqrat::SharedPtr spMotionSensor = tblgSettings.GetValue("motionSensor"); + if (spMotionSensor != NULL) + g_sqMotionSensor = *spMotionSensor; + else + LOG_WARNING_FUNC("No gametype setting for motionSensor was set."); + + Sqrat::SharedPtr spRoundTime = tblgSettings.GetValue("roundTime"); + if (spRoundTime != NULL) + g_sqRoundTime = *spRoundTime; + else + LOG_WARNING_FUNC("No gametype setting for roundTime was set."); + + Sqrat::SharedPtr spalwaysInvisible = tblgSettings.GetValue("alwaysInvisible"); + if (spalwaysInvisible != NULL) + g_sgAlwaysInvisible = *spalwaysInvisible; + else + LOG_WARNING_FUNC("No gametype setting for alwaysInvisible was set."); + + Sqrat::SharedPtr spRoundResetMap = tblgSettings.GetValue("roundSwitchResetMap"); + if (spRoundResetMap != NULL) + g_sgRoundSwitchResetsMap = *spRoundResetMap; + else + LOG_WARNING_FUNC("No gametype setting for roundSwitchResetMap was set"); + + Sqrat::SharedPtr sptieResolution = tblgSettings.GetValue("tieResolution"); + if (sptieResolution != NULL) + g_sgTieResolution = *sptieResolution; + else + LOG_WARNING_FUNC("No gametype setting for tieResolution was set."); + + Sqrat::SharedPtr spObservers = tblgSettings.GetValue("observers"); + if (spObservers != NULL) + g_sgObservers = *spObservers; + else + LOG_WARNING_FUNC("No gametype setting for observers was set."); + + Sqrat::SharedPtr spallowChangingTeams = tblgSettings.GetValue("allowChangingTeams"); + if (spallowChangingTeams != NULL) + g_sgAllowChangingTeams = *spallowChangingTeams; + else + LOG_WARNING_FUNC("No gametype setting for allowChangingTeams was set."); + + Sqrat::SharedPtr spfriendlyFire = tblgSettings.GetValue("friendlyFire"); + if (spfriendlyFire != NULL) + g_sgFriendlyFire = *spfriendlyFire; + else + LOG_WARNING_FUNC("No gametype setting for friendlyFire was set."); + + Sqrat::SharedPtr spoverShieldOnmap = tblgSettings.GetValue("overshieldOnMap"); + if (spoverShieldOnmap != NULL) + g_sgOvershieldsOnMap = *spoverShieldOnmap; + else + LOG_WARNING_FUNC("No gametype setting for overshieldOnMap was set."); + + Sqrat::SharedPtr spinvisiblityOnmap = tblgSettings.GetValue("invisibilityOnMap"); + if (spinvisiblityOnmap != NULL) + g_sgInvisibilityOnMap = *spinvisiblityOnmap; + else + LOG_WARNING_FUNC("No gametype setting for invisibilityOnMap was set."); + + Sqrat::SharedPtr spgrenadesOnMap = tblgSettings.GetValue("grenadesOnMap"); + if (spgrenadesOnMap != NULL) + { + LOG_INFO_FUNC("Updating gametype setting grenadesOnMap to {}", *spgrenadesOnMap); + g_sgGrenadesOnMap = *spgrenadesOnMap; + } + else + LOG_WARNING_FUNC("No gametype setting for grenadesOnMap was set."); + + Sqrat::SharedPtr spextramDamage = tblgSettings.GetValue("extraDamage"); + if (spextramDamage != NULL) + g_sgExtraDamage = *spextramDamage; + else + LOG_WARNING_FUNC("No gametype setting for extraDamage was set."); + + Sqrat::SharedPtr spdamageResistant = tblgSettings.GetValue("damageResistant"); + if (spdamageResistant != NULL) + g_sgDamageResistant = *spdamageResistant; + else + LOG_WARNING_FUNC("No gametype setting for damageResistant was set."); + + Sqrat::SharedPtr spforceEventTeams = tblgSettings.GetValue("forceEvenTeams"); + if (spforceEventTeams != NULL) + g_sgForceEvenTeams = *spforceEventTeams; + else + LOG_WARNING_FUNC("No gametype setting for forceEvenTeams was set."); + + Sqrat::SharedPtr spRoundsEnable = tblgSettings.GetValue("roundsEnable"); + if (spRoundsEnable != NULL) + g_sgRoundSetting1Round = *spRoundsEnable; + else + LOG_WARNING_FUNC("No gametype setting for roundsEnable was set."); + + Sqrat::SharedPtr spstartingGrenades = tblgSettings.GetValue("startingGrenades"); + if (spstartingGrenades != NULL) + g_sgStartingGrenades = *spstartingGrenades; + else + LOG_WARNING_FUNC("No gametype setting for startingGrenades was set."); + + + LOG_INFO_FUNC("Script compiled succesfully."); + + + g_sqScriptLoaded = true; g_sqScriptId = rand(); loaded_script = path; @@ -139,27 +328,29 @@ namespace ScriptEngine { GlobalScript.Run(); - addDebugText("[Squirrel] - Starting VM"); + LOG_INFO_FUNC("[Squirrel] - Starting VM"); } void sqSessionEnd() { - addDebugText("[Squirrel] - Killing VM"); + LOG_INFO_FUNC("[Squirrel] - Killing VM"); if (sq_getvmstate(Sqrat::DefaultVM::Get()) == SQ_VMSTATE_RUNNING) sq_close(Sqrat::DefaultVM::Get()); g_sqScriptLoaded = false; + g_sqScriptDownloaded = true; } void sqOnMapLoad() { + Sqrat::Function sqMapLoadFunc = Sqrat::RootTable().GetFunction("OnMapLoad"); if (!sqMapLoadFunc.IsNull()) sqMapLoadFunc.Execute(); else - addDebugText("[Squirrel] - No OnMapLoad function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnMapLoad function was found!"); } void sqPrePlayerSpawn(HSQUIRRELVM vm, int unit_datum) @@ -177,7 +368,7 @@ namespace ScriptEngine { } } else { - addDebugText("[Squirrel] - No OnPrePlayerSpawn function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnPrePlayerSpawn function was found!"); } } @@ -189,7 +380,7 @@ namespace ScriptEngine { if (!sqFunc.IsNull()) sqFunc.Execute(unit_datum); else - addDebugText("[Squirrel] - No OnPostPlayerSpawn function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnPostPlayerSpawn function was found!"); } @@ -200,7 +391,6 @@ namespace ScriptEngine { return *sqFunc.Evaluate(unit_datum, object_datum).Get(); else { - //addDebugText("[Squirrel] - No OnAutoPickup function was found!"); return true; } } @@ -212,18 +402,19 @@ namespace ScriptEngine { return *sqFunc.Evaluate(playerIndex,teamIndex).Get(); else { - addDebugText("[Squirrel] - No OnChangeTeam function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnChangeTeam function was found!"); return true; } } void sqOnPlayerDeath(HSQUIRRELVM vm, int unit_datum, int damaging_datum) { + g_unit_datum = unit_datum; Sqrat::Function sqFunc = Sqrat::RootTable().GetFunction("OnPlayerDeath"); if (!sqFunc.IsNull()) sqFunc.Execute(unit_datum, damaging_datum); else - addDebugText("[Squirrel] - No OnPlayerDeath function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnPlayerDeath function was found!"); } bool sqOnUpdateScore(HSQUIRRELVM vm, int playerDatum, int killType) @@ -233,7 +424,7 @@ namespace ScriptEngine { return *sqFunc.Evaluate(playerDatum, killType); else { - addDebugText("[Squirrel] - No OnPlayerScoreUpdate function was found!"); + LOG_WARNING_FUNC("[Squirrel] - No OnPlayerScoreUpdate function was found!"); return true; } } @@ -249,10 +440,13 @@ BYTE SqGetMapType() void sqGivePlayerWeapon(int PlayerIndex, int WeaponID,bool bReset) { + if (PlayerIndex == -1) + return; + call_give_player_weapon(PlayerIndex, WeaponID,bReset); } -void sqPlaySound(wchar_t* name, int sleep) +void sqPlaySound(char* name, int sleep) { h2mod->custom_sound_play(name, sleep); } @@ -269,11 +463,17 @@ int sqGetPlayerCount() bool sqPlayerIsActive(int playerIndex) { + if (playerIndex == -1) + return false; + return NetworkSession::playerIsActive(playerIndex); } wchar_t* sqGetPlayerNameFromIndex(int playerIndex) { + if (playerIndex == -1) + return L""; + return NetworkSession::getPlayerName(playerIndex); } @@ -289,11 +489,17 @@ int sqGetLocalPeerIndex() void sqSendTeamChange(int peerIndex,int teamIndex) { + if (peerIndex == -1) + return; + CustomPackets::sendTeamChange(peerIndex, teamIndex); } void sqSetLocalTeam(int peerIndex,int teamIndex) { + if (peerIndex == -1) + return; + h2mod->set_local_team_index(peerIndex, teamIndex); } @@ -304,15 +510,20 @@ BYTE sqGetLocalTeam() BYTE sqGetPlayerTeamFromXUID(std::string xuid) { + if (xuid.empty()) + return 0; + long long ll = std::stoll(xuid); return NetworkSession::getPlayerTeamFromXuid(ll); } std::string sqGetPlayerXUID(int playerIndex) { + playerIndex = playerIndex & 0xFFFF; + if (playerIndex == -1) + return std::string(""); + return std::to_string(NetworkSession::getPlayerXuid(playerIndex)); - //std::to_string() - //return NetworkSession::getPlayerXuid(playerIndex); } wchar_t* sqGetPlayerNameFromXUID(long long xuid) @@ -321,6 +532,18 @@ wchar_t* sqGetPlayerNameFromXUID(long long xuid) //TODO? } +void sqSetTeamGame(bool state) +{ + ScriptEngine::g_sqTeamGame = state; +} + +void sqToggleTeamGame() +{ + + BYTE *nIsTeamGame = (BYTE*)h2mod->GetAddress(0x50A5A4); + *nIsTeamGame ^= 1 << 0; +} + void sqSetUnitSpeedPatch(bool enabled) { h2mod->set_unit_speed_patch(enabled); @@ -328,6 +551,8 @@ void sqSetUnitSpeedPatch(bool enabled) void sqSetPlayerSpeed(int playerIndex, float speed) { + if(playerIndex == -1) + return; h2mod->set_unit_speed(speed, playerIndex); } @@ -348,31 +573,59 @@ void sqSetTeamPlayerIndicatorVisibility(bool bEnable) void sqSetPlayerBiped(int playerIndex,BYTE biped) { + if (playerIndex == -1) + return; + h2mod->set_unit_biped((Player::Biped)biped, playerIndex); } int sqGet_unit_datum_from_player_index(int playerIndex) { + if (playerIndex == -1) + return -1; + return h2mod->get_unit_datum_from_player_index(playerIndex).ToInt(); } +int sqget_player_index_from_unit_datum(int unit_datum) +{ + if (unit_datum == -1) + return -1; + + return h2mod->get_player_index_from_unit_datum(datum(unit_datum)); +} + int sqObject_try_and_get_with_type(int objectDatum,int objectType) { + if (objectDatum == -1) + return -1; + return call_object_try_and_get_with_type(objectDatum, objectType); } BYTE sqGet_team_from_unit(int unitDatum) { + if (unitDatum == -1) + return -1; + return h2mod->get_unit_team_index(unitDatum); } -bool sqIsObjectBiped(int objectDatum) +bool sqIsUnitAlive(int objectDatum) { + if (objectDatum == -1) + return false; + return (*(BYTE*)(objectDatum + 0xAA) == 0); } void squnit_reset_equipment(int unitDatum) { + if (unitDatum == -1) + { + LOG_WARNING_FUNC("unitDatum == -1"); + return; + } call_unit_reset_equipment(unitDatum); } @@ -388,16 +641,25 @@ void sqleave_session() float sqget_player_distance_from_player(int playerIndex, int playerIndex2) { + if (playerIndex == -1 || playerIndex2 == -1) + return 0; + return h2mod->get_distance(playerIndex, playerIndex2); } void sqset_player_grenades(int playerIndex, BYTE type, BYTE count, bool resetEquipment) { + if (playerIndex == -1) + return; + h2mod->set_player_unit_grenades_count(playerIndex, type, count, resetEquipment); } void sqhs_object_destroy(int object_datum) { + if (object_datum == -1) + return; + call_hs_object_destroy(object_datum); } @@ -411,11 +673,25 @@ int sqrand(int min_num, int max_num) int sqgetPeerIndex(int playerIndex) { + if (playerIndex == -1) + return -1; + return NetworkSession::getPeerIndex(playerIndex); } +int sqgetUnitTeam(int unit_index) +{ + if (unit_index == -1) + return -1; + + return h2mod->get_unit_team_index(datum(unit_index)); +} + int sqgetPlayerTeam(int playerIndex) { + if (playerIndex == -1) + return -1; + return NetworkSession::getPlayerTeam(playerIndex); } @@ -425,12 +701,18 @@ extern update_player_score pupdate_player_score; void squpdate_player_score(int PlayerDatumIndex) { + if (PlayerDatumIndex == -1) + return; + pupdate_player_score((void*)(h2mod->Server ? 0x30005508 : 0x3000595C), PlayerDatumIndex, 0, 1, -1, 0); } bool sqvalidate_object_type(int object_datum,int type) { + if (object_datum == -1) + return false; + DatumIterator objectIt(game_state_objects_header); BipedObjectDefinition* biped_unit = (BipedObjectDefinition*)objectIt.get_data_at_index(datum(object_datum).Index)->object; @@ -444,6 +726,9 @@ bool sqvalidate_object_type(int object_datum,int type) bool sqvalidate_object_datum(int object_datum,int object_validate) { + if (object_datum == -1) + return false; + DatumIterator objectIt(game_state_objects_header); WeaponObjectDefinition* weaponObject = (WeaponObjectDefinition*)objectIt.get_data_at_index(datum(object_datum).ToAbsoluteIndex())->object; @@ -457,6 +742,9 @@ bool sqvalidate_object_datum(int object_datum,int object_validate) int sqcontroller_2_player(int controller_index) { + if (controller_index == -1) + return 0; + int player_index = h2mod->get_player_datum_index_from_controller_index(controller_index).ToInt(); return player_index; } @@ -528,13 +816,18 @@ void BindSquirrel(HSQUIRRELVM vm) RootTable().Func("setUnitSpeed", &sqSetPlayerSpeed); RootTable().Func("toggleWeaponPickup", &sqToggleWeaponPickup); RootTable().Func("setWeaponPickup", &sqSetWeaponPickup); - RootTable().Func("setIndicatorVisiblity", &sqSetTeamPlayerIndicatorVisibility); + RootTable().Func("setIndicatorVisibility", &sqSetTeamPlayerIndicatorVisibility); RootTable().Func("setPlayerBiped", &sqSetPlayerBiped); - RootTable().Func("isObjectBiped", &sqIsObjectBiped); + RootTable().Func("isUnitAlive", &sqIsUnitAlive); RootTable().Func("sqRandom", &sqrand); RootTable().Func("playerIsActive", &sqPlayerIsActive); RootTable().Func("getPeerIndex", &sqgetPeerIndex); RootTable().Func("getPlayerTeam", &sqgetPlayerTeam); RootTable().Func("controller2player", &sqcontroller_2_player); RootTable().Func("endGame", &sqendGame); + RootTable().Func("toggleTeamGame", &sqToggleTeamGame); + RootTable().Func("setTeamGame", &sqSetTeamGame); + RootTable().Func("playerIndex2Datum", &sqGet_unit_datum_from_player_index); + RootTable().Func("unitDatum2PlayerIndex", &sqget_player_index_from_unit_datum); + RootTable().Func("getUnitTeam", &sqgetUnitTeam); } \ No newline at end of file diff --git a/xlive/H2MOD/Modules/Scripting/Squirrel.h b/xlive/H2MOD/Modules/Scripting/Squirrel.h index dfce5be24..5353c1f7e 100644 --- a/xlive/H2MOD/Modules/Scripting/Squirrel.h +++ b/xlive/H2MOD/Modules/Scripting/Squirrel.h @@ -15,5 +15,24 @@ namespace ScriptEngine { void sqSessionEnd(); void sqSessionStart(); void sqLoadScript(std::string); + void sqLoadScriptFromString(char* script_data); extern std::string loaded_script; + extern bool g_sqTeamGame; + extern bool g_sqMotionSensor; + extern short g_sqRoundTime; + extern bool g_sgAlwaysInvisible; + extern bool g_sgRoundSwitchResetsMap; + extern bool g_sgTieResolution; + extern bool g_sgObservers; + extern bool g_sgAllowChangingTeams; + extern bool g_sgFriendlyFire; + extern bool g_sgOvershieldsOnMap; + extern bool g_sgInvisibilityOnMap; + extern bool g_sgGrenadesOnMap; + extern bool g_sgStartingGrenades; + extern bool g_sgExtraDamage; + extern bool g_sgDamageResistant; + extern bool g_sgForceEvenTeams; + extern bool g_sgRoundSetting1Round; + } \ No newline at end of file