Merge branch 'master' into fix-cache-openfile-fail

This commit is contained in:
Quentin 2024-04-03 20:06:04 +02:00 committed by GitHub
commit 4c36c15321
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
129 changed files with 1133 additions and 896 deletions

View File

@ -3,7 +3,7 @@ include(FetchContent)
FetchContent_Declare(
gtav_classes
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
GIT_TAG 09a586011a296cf8ce3ffb9c15db7ce474ea4363
GIT_TAG ddd118410c5ede28e3a5978ebda93b83634d3293
GIT_PROGRESS TRUE
CONFIGURE_COMMAND ""
BUILD_COMMAND ""

View File

@ -2,7 +2,7 @@
Table containing helper functions related to gta scripts.
## Functions (2)
## Functions (3)
### `register_looped(name, func)`
@ -75,4 +75,15 @@ end)
script.run_in_fiber(func)
```
### `execute_as_script(script_name, func)`
- **Parameters:**
- `script_name` (string): target script thread.
- `func` (function): function that will be executed once in the script thread.
**Example Usage:**
```lua
script.execute_as_script(script_name, func)
```

View File

@ -21,7 +21,7 @@ namespace big
return;
if (!scripts::force_host("freemode"_J))
{
g_notification_service->push_error("END_KICK"_T.data(), "BACKEND_END_SESSION_KICK_FORCE_SCRIPT_HOST_FAILED"_T.data());
g_notification_service.push_error("END_KICK"_T.data(), "BACKEND_END_SESSION_KICK_FORCE_SCRIPT_HOST_FAILED"_T.data());
return;
}

View File

@ -18,7 +18,7 @@ namespace big
return;
if (!g_player_service->get_self()->is_host())
{
g_notification_service->push_error("HOST_KICK"_T.data(), "BACKEND_HOST_KICK_FAILED"_T.data());
g_notification_service.push_error("HOST_KICK"_T.data(), "BACKEND_HOST_KICK_FAILED"_T.data());
return;
}
@ -27,4 +27,4 @@ namespace big
};
host_kick g_host_kick("hostkick", "HOST_KICK", "HOST_KICK_DESC", 0, false);
}
}

View File

@ -21,7 +21,7 @@ namespace big
return;
if (!scripts::force_host("freemode"_J))
{
g_notification_service->push_error("Kick", "Force script host failed!");
g_notification_service.push_error("Kick", "Force script host failed!");
return;
}

View File

@ -23,11 +23,11 @@ namespace big
{
if (!NETWORK::NETWORK_IS_PLAYER_A_PARTICIPANT_ON_SCRIPT(id, "am_launcher", -1))
{
g_notification_service->push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_CANNOT_START_AM_LAUNCHER"_T.data());
g_notification_service.push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_CANNOT_START_AM_LAUNCHER"_T.data());
return;
}
g_notification_service->push("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_STARTING"_T.data());
g_notification_service.push("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_STARTING"_T.data());
scripts::start_launcher_script(47);
@ -35,7 +35,7 @@ namespace big
{
if (i >= 1000)
{
g_notification_service->push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED"_T.data());
g_notification_service.push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED"_T.data());
return;
}
@ -48,7 +48,7 @@ namespace big
if (!scripts::force_host("am_hunt_the_beast"_J))
{
g_notification_service->push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED_CONTROL"_T.data());
g_notification_service.push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED_CONTROL"_T.data());
return;
}
@ -89,7 +89,7 @@ namespace big
{
if (i >= 7000)
{
g_notification_service->push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED"_T.data());
g_notification_service.push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED"_T.data());
return;
}
@ -100,7 +100,7 @@ namespace big
if (!scripts::force_host("am_hunt_the_beast"_J))
{
g_notification_service->push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED_CONTROL"_T.data());
g_notification_service.push_error("TURN_INTO_BEAST"_T.data(), "BACKEND_TURN_INTO_BEAST_FAILED_CONTROL"_T.data());
return;
}

View File

@ -14,7 +14,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -26,11 +26,11 @@ namespace big
}
else
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
};
boost_vehicle g_boost_vehicle("boostveh", "BACKEND_BOOST_VEHICLE", "BACKEND_BOOST_VEHICLE_DESC", 0);
}
}

View File

@ -15,7 +15,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{

View File

@ -14,7 +14,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -26,11 +26,11 @@ namespace big
}
else
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
};
close_doors g_close_doors("closedoors", "BACKEND_CLOSE_VEHICLE_DOORS", "BACKEND_CLOSE_VEHICLE_DOORS_DESC", 0);
}
}

View File

@ -16,7 +16,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -34,4 +34,4 @@ namespace big
};
downgrade_vehicle g_downgrade_vehicle("downgradeveh", "BACKEND_DOWNGRADE_VEHICLE", "BACKEND_DOWNGRADE_VEHICLE_DESC", 0);
}
}

View File

@ -18,7 +18,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(player_ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -41,4 +41,4 @@ namespace big
};
flip_180 g_flip_180("flip180", "BACKEND_FLIP", "BACKEND_FLIP_DESC", 0);
}
}

View File

@ -15,7 +15,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(ent, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -30,4 +30,4 @@ namespace big
};
flying_vehicle g_flying_vehicle("flyingveh", "BACKEND_FLYING_VEHICLE", "BACKEND_FLYING_VEHICLE_DESC", 0);
}
}

View File

@ -13,7 +13,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -25,11 +25,11 @@ namespace big
}
else
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
};
kill_engine g_kill_engine("killengine", "BACKEND_KILL_VEHICLE_ENGINE", "BACKEND_KILL_VEHICLE_ENGINE_DESC", 0);
}
}

View File

@ -14,7 +14,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -27,4 +27,4 @@ namespace big
};
lock_vehicle g_lock_vehicle("lockveh", "BACKEND_LOCK_VEHICLE", "BACKEND_LOCK_VEHICLE_DESC", 0);
}
}

View File

@ -14,7 +14,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -29,11 +29,11 @@ namespace big
}
else
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
};
open_doors g_open_doors("opendoors", "BACKEND_OPEN_VEHICLE_DOORS", "BACKEND_OPEN_VEHICLE_DOORS_DESC", 0);
}
}

View File

@ -15,9 +15,9 @@ namespace big
if (veh == 0)
{
if (g.player.spectating)
g_notification_service->push_warning("REMOTE_CONTROL"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("REMOTE_CONTROL"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
else
g_notification_service->push_warning("REMOTE_CONTROL"_T.data(), std::format("{} {}", "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T, "BACKEND_REMOTE_CONTROL_VEHICLE_SPECTATE"_T).c_str());
g_notification_service.push_warning("REMOTE_CONTROL"_T.data(), std::format("{} {}", "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T, "BACKEND_REMOTE_CONTROL_VEHICLE_SPECTATE"_T).c_str());
return;
}
@ -27,4 +27,4 @@ namespace big
};
remote_control_vehicle g_remote_control_vehicle("rcplayer", "BACKEND_REMOTE_CONTROL_VEHICLE", "BACKEND_REMOTE_CONTROL_VEHICLE_DESC", 0, false);
}
}

View File

@ -15,7 +15,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -28,4 +28,4 @@ namespace big
vehicle_special_ability<1> g_special_boost_vehicle("svehboost", "BACKEND_SPECIAL_ABILITY_BOOST", "BACKEND_SPECIAL_ABILITY_BOOST_DESC", 0);
vehicle_special_ability<3> g_special_shunt_left("sshuntleft", "BACKEND_SPECIAL_ABILITY_LEFT", "BACKEND_SPECIAL_ABILITY_LEFT_DESC", 0);
vehicle_special_ability<2> g_special_shunt_right("sshuntright", "BACKEND_SPECIAL_ABILITY_RIGHT", "BACKEND_SPECIAL_ABILITY_RIGHT_DESC", 0);
}
}

View File

@ -13,7 +13,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -25,11 +25,11 @@ namespace big
}
else
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
};
stop_vehicle g_stop_vehicle("stopveh", "BACKEND_STOP_VEHICLE", "BACKEND_STOP_VEHICLE_DESC", 0);
}
}

View File

@ -14,7 +14,7 @@ namespace big
Ped ped = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("VEHICLE"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("VEHICLE"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -27,4 +27,4 @@ namespace big
};
unlock_vehicle g_unlock_vehicle("unlockveh", "BACKEND_UNLOCK_DOORS", "BACKEND_UNLOCK_DOORS_DESC", 0);
}
}

View File

@ -17,7 +17,7 @@ namespace big
if (!PED::IS_PED_IN_ANY_VEHICLE(ped, true))
{
g_notification_service->push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "ERROR_PLAYER_IS_NOT_IN_VEHICLE"_T.data());
}
else
{
@ -27,4 +27,4 @@ namespace big
};
upgrade_vehicle g_upgrade_vehicle("upgradeveh", "MAX_VEHICLE", "BACKEND_UPGRADE_VEHICLE_DESC", 0);
}
}

View File

@ -15,8 +15,8 @@ namespace big
{
player_mgr->RemovePlayer(plyr->get_net_game_player());
}
g_notification_service->push("EMPTY_SESSION"_T.data(), "BACKEND_WIPE_SESSION_COMPLETE"_T.data());
g_notification_service.push("EMPTY_SESSION"_T.data(), "BACKEND_WIPE_SESSION_COMPLETE"_T.data());
}
};
empty_session g_empty_session("emptysession", "EMPTY_SESSION", "BACKEND_WIPE_SESSION_DESC", 0);
}
}

View File

@ -42,7 +42,7 @@ namespace big
if (veh == 0)
{
g_notification_service->push_error("GUI_TAB_SPAWN_VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data());
g_notification_service.push_error("GUI_TAB_SPAWN_VEHICLE"_T.data(), "UNABLE_TO_SPAWN_VEHICLE"_T.data());
}
else
{

View File

@ -2,7 +2,7 @@
#include "fiber_pool.hpp"
#include "hooking/hooking.hpp"
#include "util/notify.hpp"
#include "util/chat.hpp"
namespace big
{
@ -26,18 +26,7 @@ namespace big
void chat_command_context::report_output(const std::string& output) const
{
g_fiber_pool->queue_job([this, output] {
char msg[265]{};
msg[0] = g.session.chat_output_prefix;
msg[1] = ' ';
strncpy(msg + 2, output.c_str(), sizeof(msg) - 2);
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
msg,
false))
notify::draw_chat(msg, g_player_service->get_self()->get_name(), false);
});
chat::send_message(output, this->get_sender(), true, true);
}
void chat_command_context::report_error(const std::string& error) const

View File

@ -14,11 +14,11 @@ namespace big
void default_command_context::report_output(const std::string& output) const
{
g_notification_service->push("BACKEND_COMMAND"_T.data(), output);
g_notification_service.push("BACKEND_COMMAND"_T.data(), output);
}
void default_command_context::report_error(const std::string& error) const
{
g_notification_service->push_error("BACKEND_COMMAND"_T.data(), error);
g_notification_service.push_error("BACKEND_COMMAND"_T.data(), error);
}
}
}

View File

@ -1,11 +1,11 @@
#include "backend/looped/looped.hpp"
#include "core/scr_globals.hpp"
#include "file_manager.hpp"
#include "gta/enums.hpp"
#include "logger/logger.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "services/outfit/outfit_service.hpp"
#include "gta/enums.hpp"
#include "core/scr_globals.hpp"
#include "services/tunables/tunables_service.hpp"
namespace big
@ -15,13 +15,13 @@ namespace big
int offset = 0;
switch (model)
{
case "mp_m_freemode_01"_J: break;
case "mp_f_freemode_01"_J:
{
offset = 1;
break;
}
default: return false; //For non-normal models
case "mp_m_freemode_01"_J: break;
case "mp_f_freemode_01"_J:
{
offset = 1;
break;
}
default: return false; //For non-normal models
}
return PED::GET_PED_DRAWABLE_VARIATION(self::ped, ComponentId::AUXILIARY) == 15 && PED::GET_PED_DRAWABLE_VARIATION(self::ped, ComponentId::TORSO) == 15 && PED::GET_PED_DRAWABLE_VARIATION(self::ped, ComponentId::LEGS) == (14 + offset);
@ -52,11 +52,28 @@ namespace big
if (persisting_outfit != g.self.persist_outfit)
{
persisting_outfit = g.self.persist_outfit;
folder saved_outfit_path = g_file_manager.get_project_folder("saved_outfits");
std::ifstream i(saved_outfit_path.get_file(persisting_outfit).get_path());
outfit.clear();
i >> outfit;
persisting_outfit = g.self.persist_outfit;
folder saved_outfit_path = g_file_manager.get_project_folder("saved_outfits");
const auto persist_outfit_file_path = saved_outfit_path.get_file(persisting_outfit).get_path();
if (std::filesystem::exists(persist_outfit_file_path))
{
std::ifstream i(persist_outfit_file_path);
if (i.is_open())
{
outfit.clear();
try
{
i >> outfit;
}
catch (const std::exception& e)
{
LOG(INFO) << e.what();
outfit = {};
g.self.persist_outfit = "";
}
}
}
}
if (outfit.contains("model") && outfit["model"].get<uint32_t>() == model)

View File

@ -391,7 +391,7 @@ namespace big
virtual void on_enable() override
{
g_notification_service->push("SUPER_HERO_FLY"_T.data(), "SUPER_HERO_FLY_ENABLE_NOTIFICATION"_T.data());
g_notification_service.push("SUPER_HERO_FLY"_T.data(), "SUPER_HERO_FLY_ENABLE_NOTIFICATION"_T.data());
}
virtual void on_disable() override

View File

@ -19,7 +19,7 @@ namespace big
{
on_disable();
g.self.passive = false;
g_notification_service->push_warning("PASSIVE"_T.data(), "BACKEND_LOOPED_SELF_TOGGLE_PASSIVE_DISABLED_PASSIVE_MODE_MESSAGE"_T.data());
g_notification_service.push_warning("PASSIVE"_T.data(), "BACKEND_LOOPED_SELF_TOGGLE_PASSIVE_DISABLED_PASSIVE_MODE_MESSAGE"_T.data());
return;
}
*g_tunables_service->get_tunable<int*>(-29732167) = 0; // End Passive Time = 0s

View File

@ -29,7 +29,7 @@ namespace big
{
current_destination = AutoDriveDestination::STOPPED;
changing_driving_styles = false;
g_notification_service->push_warning("AUTO_DRIVE"_T.data(), "PLAYER_INFO_NO_VEHICLE"_T.data());
g_notification_service.push_warning("AUTO_DRIVE"_T.data(), "PLAYER_INFO_NO_VEHICLE"_T.data());
}
else if (current_driving_flag != driving_style_flags[g.vehicle.auto_drive_style] || current_speed != g.vehicle.auto_drive_speed)
{
@ -77,11 +77,11 @@ namespace big
if (to_waypoint && !does_waypoint_exist)
{
g_notification_service->push_warning("AUTO_DRIVE"_T.data(), "TELEPORT_NO_WAYPOINT_SET"_T.data());
g_notification_service.push_warning("AUTO_DRIVE"_T.data(), "TELEPORT_NO_WAYPOINT_SET"_T.data());
}
else
{
g_notification_service->push_warning("AUTO_DRIVE"_T.data(), "BACKEND_LOOPED_VEHICLE_AUTO_DRIVE_STOPPED"_T.data());
g_notification_service.push_warning("AUTO_DRIVE"_T.data(), "BACKEND_LOOPED_VEHICLE_AUTO_DRIVE_STOPPED"_T.data());
}
started = false;

View File

@ -125,7 +125,7 @@ namespace big
virtual void on_enable() override
{
g_notification_service->push("TURN_SIGNALS"_T.data(), "BACKEND_LOOPED_VEHICLE_TURN_SIGNALS_HELP"_T.data());
g_notification_service.push("TURN_SIGNALS"_T.data(), "BACKEND_LOOPED_VEHICLE_TURN_SIGNALS_HELP"_T.data());
}
virtual void on_tick() override

View File

@ -24,7 +24,7 @@ namespace big
}
else
{
g_notification_service->push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
g_notification_service.push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
}
}
}

View File

@ -20,7 +20,7 @@ namespace big
{
if (ENTITY::IS_ENTITY_A_PED(entity) && PED::IS_PED_A_PLAYER(entity))
{
g_notification_service->push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_PLAYER"_T.data());
g_notification_service.push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_PLAYER"_T.data());
}
else
{
@ -29,7 +29,7 @@ namespace big
if (dist > 500)
{
g_notification_service->push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_TOO_FAR"_T.data());
g_notification_service.push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_TOO_FAR"_T.data());
}
else
{
@ -38,13 +38,13 @@ namespace big
entity::delete_entity(entity);
}
else
g_notification_service->push_error("CUSTOM_WEAPONS"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_error("CUSTOM_WEAPONS"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data());
}
}
}
else
{
g_notification_service->push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
g_notification_service.push_error("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
}
}
}

View File

@ -65,7 +65,7 @@ namespace big
{
if (ENTITY::IS_ENTITY_A_PED(ent_to_add) && PED::IS_PED_A_PLAYER(ent_to_add))
{
g_notification_service->push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_PLAYER"_T.data());
g_notification_service.push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_PLAYER"_T.data());
}
else
{
@ -79,7 +79,7 @@ namespace big
if (temp_dist > 500)
{
g_notification_service->push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_TOO_FAR"_T.data());
g_notification_service.push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_DELETE_GUN_TOO_FAR"_T.data());
}
else
{
@ -87,7 +87,7 @@ namespace big
{
TASK::SET_HIGH_FALL_TASK(ent_to_add, 0, 0, 0);
g_notification_service->push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_SET"_T.data());
g_notification_service.push_warning("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_SET"_T.data());
}
ents.push_back(ent_to_add);
@ -121,7 +121,7 @@ namespace big
ents.clear();
g_notification_service->push_success("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_UNSET"_T.data());
g_notification_service.push_success("CUSTOM_WEAPONS"_T.data(), "BACKEND_LOOPED_WEAPONS_GRAVITY_GUN_UNSET"_T.data());
}
}
}

View File

@ -24,15 +24,15 @@ namespace big
}
else
{
g_notification_service->push_warning("BACKEND_LOOPED_WEAPONS_REPAIR_GUN"_T.data(), "VEHICLE_INVALID"_T.data());
g_notification_service.push_warning("BACKEND_LOOPED_WEAPONS_REPAIR_GUN"_T.data(), "VEHICLE_INVALID"_T.data());
}
}
else
{
g_notification_service->push_warning("BACKEND_LOOPED_WEAPONS_REPAIR_GUN"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
g_notification_service.push_warning("BACKEND_LOOPED_WEAPONS_REPAIR_GUN"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
}
}
}
}
}
}
}

View File

@ -31,12 +31,12 @@ namespace big
}
else
{
g_notification_service->push_warning("BACKEND_LOOPED_WEAPONS_STEAL_VEHICLE_GUN"_T.data(), "VEHICLE_INVALID"_T.data());
g_notification_service.push_warning("BACKEND_LOOPED_WEAPONS_STEAL_VEHICLE_GUN"_T.data(), "VEHICLE_INVALID"_T.data());
}
}
else
{
g_notification_service->push_warning("BACKEND_LOOPED_WEAPONS_STEAL_VEHICLE_GUN"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
g_notification_service.push_warning("BACKEND_LOOPED_WEAPONS_STEAL_VEHICLE_GUN"_T.data(), "BACKEND_LOOPED_WEAPONS_CAGE_GUN_NO_ENTITY_FOUND"_T.data());
}
}
}

View File

@ -11,7 +11,7 @@ namespace big
virtual void on_enable() override
{
g_notification_service->push("Auto disarm", "Nearby hostile peds will be disarmed");
g_notification_service.push("Auto disarm", "Nearby hostile peds will be disarmed");
}
virtual void on_tick() override

View File

@ -5,7 +5,7 @@
#include "hooking/hooking.hpp"
#include "pointers.hpp"
#include "script.hpp"
#include "util/notify.hpp"
#include "util/chat.hpp"
namespace big
{
@ -36,23 +36,16 @@ namespace big
if (announce_in_chat)
{
g_fiber_pool->queue_job([attacker, victim, this] {
auto chat = std::format("{} {}", g.session.chat_output_prefix, g_translation_service.get_translation(m_announce_message));
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat.data(),
is_team_only))
notify::draw_chat(chat.c_str(), g_player_service->get_self()->get_name(), is_team_only);
});
auto msg = std::format("{} {}", g.session.chat_output_prefix, g_translation_service.get_translation(m_announce_message));
chat::send_message(msg);
}
if (notify)
{
g_notification_service->push_warning("PROTECTIONS"_T.data(),
g_notification_service.push_warning("PROTECTIONS"_T.data(),
std::vformat(g_translation_service.get_translation(m_notify_message), std::make_format_args(attacker->get_name(), victim->get_name())));
}
process_common(attacker);
}
}
}

View File

@ -6,7 +6,7 @@
#include "pointers.hpp"
#include "script.hpp"
#include "services/player_database/player_database_service.hpp"
#include "util/notify.hpp"
#include "util/chat.hpp"
namespace big
{
@ -62,20 +62,16 @@ namespace big
if (announce_in_chat)
{
g_fiber_pool->queue_job([player, this] {
auto chat = std::format("{} {}", g.session.chat_output_prefix, std::vformat(g_translation_service.get_translation(m_announce_message), std::make_format_args(player->get_name())));
auto msg = std::format("{} {}",
g.session.chat_output_prefix,
std::vformat(g_translation_service.get_translation(m_announce_message), std::make_format_args(player->get_name())));
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat.data(),
is_team_only))
notify::draw_chat(chat.c_str(), g_player_service->get_self()->get_name(), is_team_only);
});
chat::send_message(msg);
}
if (notify)
{
g_notification_service->push_warning("PROTECTIONS"_T.data(),
g_notification_service.push_warning("PROTECTIONS"_T.data(),
std::vformat(g_translation_service.get_translation(m_notify_message), std::make_format_args(player->get_name())));
}

View File

@ -293,8 +293,7 @@ namespace big
GOD = 1 << 8,
EXPLOSION = 1 << 11,
STEAM = 1 << 15,
DROWN = 1 << 16,
WATER = 1 << 24,
WATER = 1 << 16,
};
enum ePedType : uint32_t
{

View File

@ -336,7 +336,6 @@ namespace big
bool proof_melee = false;
bool proof_explosion = false;
bool proof_steam = false;
bool proof_drown = false;
bool proof_water = false;
uint32_t proof_mask = 0;
bool mobile_radio = false;
@ -388,7 +387,7 @@ namespace big
NLOHMANN_DEFINE_TYPE_INTRUSIVE(super_hero_fly, gradual, explosions, auto_land, charge, ptfx, fly_speed, initial_launch)
} super_hero_fly{};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, force_wanted_level, passive, free_cam, invisibility, local_visibility, never_wanted, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_drown, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis, interaction_menu_freedom, super_hero_fly)
NLOHMANN_DEFINE_TYPE_INTRUSIVE(self, ipls, ptfx_effects, clean_player, force_wanted_level, passive, free_cam, invisibility, local_visibility, never_wanted, no_ragdoll, noclip, noclip_aim_speed_multiplier, noclip_speed_multiplier, off_radar, super_run, no_collision, unlimited_oxygen, no_water_collision, wanted_level, god_mode, part_water, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, mobile_radio, fast_respawn, auto_tp, super_jump, beast_jump, healthregen, healthregenrate, hud, superman, custom_weapon_stop, prompt_ambient_animations, persist_outfit, persist_outfits_mis, interaction_menu_freedom, super_hero_fly)
} self{};
struct session

View File

@ -210,4 +210,6 @@ namespace big::functions
using get_ped_seat = CGetPedSeatReturnClass*(*)(PVOID seat_info, CPed* ped);
using received_clone_remove = void (*)(CNetworkObjectMgr*, CNetGamePlayer*, CNetGamePlayer*, int16_t, uint32_t);
using can_create_vehicle = bool (*)();
}

View File

@ -91,9 +91,9 @@ namespace rage
{
return big::g_pointers->m_gta.m_read_bitbuf_bool(this, boolean, 1);
}
bool ReadPeerId(uint64_t* peer_id)
bool ReadRockstarId(int64_t* rockstar_id)
{
return this->ReadQWord(peer_id, 0x40);
return this->ReadInt64(rockstar_id, sizeof(rockstar_id) * 8);
}
uint64_t ReadBits(size_t numBits)
{
@ -207,6 +207,10 @@ namespace rage
{
return big::g_pointers->m_gta.m_write_bitbuf_int64(this, integer, bits);
}
bool WriteRockstarId(int64_t rockstar_id)
{
return big::g_pointers->m_gta.m_write_bitbuf_int64(this, rockstar_id, sizeof(rockstar_id) * 8);
}
bool ReadInt64(int64_t* integer, int bits)
{
uint32_t v8;

View File

@ -365,6 +365,8 @@ namespace big
functions::received_clone_remove m_received_clone_remove;
CWeaponInfoManager* m_weapon_info_manager;
functions::can_create_vehicle m_can_create_vehicle;
};
#pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");

View File

@ -140,6 +140,8 @@ namespace big
detour_hook_helper::add<hooks::received_clone_remove>("RCR", g_pointers->m_gta.m_received_clone_remove);
detour_hook_helper::add<hooks::can_create_vehicle>("CCV", g_pointers->m_gta.m_can_create_vehicle);
g_hooking = this;
}

View File

@ -191,6 +191,8 @@ namespace big
static bool sync_reader_serialize_vec3(void* _this, rage::fvector3* vec, float divisor, int size);
static bool sync_reader_serialize_vec3_signed(void* _this, rage::fvector3* vec, float divisor, int size);
static bool sync_reader_serialize_array(void* _this, void* array, int size);
static bool can_create_vehicle();
};
class minhook_keepalive

View File

@ -64,11 +64,11 @@ namespace big
g_fiber_pool->queue_job([] {
session::join_session(gta_util::get_network()->m_last_joined_session.m_session_info);
});
g_notification_service->push_warning("KICKED"_T.data(), "You have been desync kicked. Rejoining previous session...");
g_notification_service.push_warning("KICKED"_T.data(), "You have been desync kicked. Rejoining previous session...");
}
else
{
g_notification_service->push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data());
g_notification_service.push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data());
}
break;
}

View File

@ -5,36 +5,19 @@
#include "hooking/hooking.hpp"
#include "packet.hpp"
#include "services/players/player_service.hpp"
#include "util/spam.hpp"
#include "util/chat.hpp"
namespace big
{
inline void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
constexpr int PC_PLATFORM = 3;
buf.Write<uint8_t>(PC_PLATFORM, 8);
buf.WriteInt64(*(int64_t*)&hnd.m_rockstar_id, 64);
buf.Write<uint8_t>(hnd.unk_0009, 8);
}
bool hooks::send_chat_message(void* team_mgr, rage::rlGamerInfo* local_gamer_info, char* message, bool is_team)
{
if (g.session.chat_commands && message[0] == g.session.chat_command_prefix)
command::process(std::string(message + 1), std::make_shared<chat_command_context>(g_player_service->get_self()));
packet msg{};
msg.write_message(rage::eNetMessage::MsgTextMessage);
msg.m_buffer.WriteString(message ? message : "", 256);
gamer_handle_serialize(g_player_service->get_self()->get_net_data()->m_gamer_handle, msg.m_buffer);
msg.write<bool>(is_team, 1);
chat::send_message(message, nullptr, false, is_team);
if (g.session.log_chat_messages)
spam::log_chat(message, g_player_service->get_self(), SpamReason::NOT_A_SPAMMER, is_team);
if (*g_pointers->m_gta.m_is_session_started)
for (auto& player : g_player_service->players())
if (player.second && player.second->is_valid())
msg.send(player.second->get_net_game_player()->m_msg_id);
chat::log_chat(message, g_player_service->get_self(), SpamReason::NOT_A_SPAMMER, is_team);
return true;
}

View File

@ -41,7 +41,7 @@ namespace big
if (g.notifications.player_leave.notify)
{
g_notification_service->push("PLAYER_LEFT"_T.data(),
g_notification_service.push("PLAYER_LEFT"_T.data(),
std::vformat("PLAYER_LEFT_INFO"_T,
std::make_format_args(net_player_data->m_name,
player->m_player_id,
@ -60,7 +60,7 @@ namespace big
{
if (admin_rids.contains(net_player_data->m_gamer_handle.m_rockstar_id))
{
g_notification_service->push_warning("POTENTIAL_ADMIN_FOUND"_T.data(),
g_notification_service.push_warning("POTENTIAL_ADMIN_FOUND"_T.data(),
std::format("{} {}", net_player_data->m_name, "PLAYER_DETECTED_AS_ADMIN"_T));
LOG(WARNING) << net_player_data->m_name << " (" << net_player_data->m_gamer_handle.m_rockstar_id << ") has been detected as an admin";
@ -82,7 +82,7 @@ namespace big
if (g.notifications.player_join.notify)
{
g_notification_service->push("PLAYER_JOINED"_T.data(),
g_notification_service.push("PLAYER_JOINED"_T.data(),
std::vformat("PLAYER_JOINED_INFO"_T,
std::make_format_args(net_player_data->m_name,
player->m_player_id,
@ -109,7 +109,7 @@ namespace big
if (strcmp(plyr->get_name(), entry->name.data()))
{
g_notification_service->push("PLAYERS"_T.data(),
g_notification_service.push("PLAYERS"_T.data(),
std::format("{} {}: {}", entry->name, "PLAYER_CHANGED_NAME"_T, plyr->get_name()));
entry->name = plyr->get_name();
g_player_database_service->save();
@ -133,14 +133,14 @@ namespace big
{
if ((plyr->is_friend() && g.session.allow_friends_into_locked_session) || plyr->is_trusted)
{
g_notification_service->push_success("LOBBY_LOCK"_T.data(),
g_notification_service.push_success("LOBBY_LOCK"_T.data(),
std::vformat("LOBBY_LOCK_ALLOWED"_T.data(),
std::make_format_args(plyr->get_net_data()->m_name)));
}
else
{
dynamic_cast<player_command*>(command::get("multikick"_J))->call(plyr, {});
g_notification_service->push_warning("LOBBY_LOCK"_T.data(),
g_notification_service.push_warning("LOBBY_LOCK"_T.data(),
std::vformat("LOBBY_LOCK_DENIED"_T.data(), std::make_format_args(plyr->get_net_data()->m_name)));
}
}

View File

@ -13,7 +13,7 @@ namespace big
if (g.notifications.network_player_mgr_init.log)
LOG(INFO) << "CNetworkPlayerMgr#init got called, we're probably entering a session.";
if (g.notifications.network_player_mgr_init.notify)
g_notification_service->push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_INIT"_T.data());
g_notification_service.push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_INIT"_T.data());
bool result = g_hooking->get_original<hooks::network_player_mgr_init>()(_this, a2, a3, a4);
@ -32,7 +32,7 @@ namespace big
if (g.notifications.network_player_mgr_shutdown.log)
LOG(INFO) << "CNetworkPlayerMgr#shutdown got called, we're probably leaving our session.";
if (g.notifications.network_player_mgr_shutdown.notify)
g_notification_service->push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_DESTROY"_T.data());
g_notification_service.push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_DESTROY"_T.data());
g.session.trust_session = false;
g_hooking->get_original<hooks::network_player_mgr_shutdown>()(_this);

View File

@ -73,8 +73,8 @@ namespace big
if (memory)
return memory;
g_notification_service->push_error("Protections", "The network message allocator is out of memory"); // this never reaches here but why not
g_notification_service.push_error("Protections", "The network message allocator is out of memory"); // this never reaches here but why not
return nullptr;
}
}
}

View File

@ -716,13 +716,9 @@ namespace big
case sync_node_id("CPlayerExtendedGameStateNode"):
LOG_FIELD(CPlayerExtendedGameStateNode, waypoint_x);
LOG_FIELD(CPlayerExtendedGameStateNode, waypoint_y);
LOG_FIELD_B(CPlayerExtendedGameStateNode, unk1);
LOG_FIELD_B(CPlayerExtendedGameStateNode, unk2);
LOG_FIELD_B(CPlayerExtendedGameStateNode, unk3);
LOG_FIELD_B(CPlayerExtendedGameStateNode, unk4);
LOG_FIELD_B(CPlayerExtendedGameStateNode, unk5);
LOG_FIELD_B(CPlayerExtendedGameStateNode, has_waypoint_data);
LOG_FIELD_B(CPlayerExtendedGameStateNode, is_waypoint_set);
LOG_FIELD(CPlayerExtendedGameStateNode, waypoint_entity);
LOG_FIELD(CPlayerExtendedGameStateNode, has_active_waypoint);
LOG_FIELD(CPlayerExtendedGameStateNode, owns_waypoint);
break;
case sync_node_id("CPlayerGameStateDataNode"):
LOG_FIELD(CPlayerGameStateDataNode, m_player_state);

View File

@ -16,7 +16,7 @@ namespace big
CMsgJoinResponse response{};
response.m_status_code = player->block_join_reason;
g_pointers->m_gta.m_write_join_response_data(&response, ctx->m_join_response_data, 512, &ctx->m_join_response_size);
g_notification_service->push("BLOCK_JOIN"_T.data(),
g_notification_service.push("BLOCK_JOIN"_T.data(),
std::vformat("BLOCK_JOIN_INFO"_T, std::make_format_args(player->name)));
return false;
}
@ -25,4 +25,4 @@ namespace big
return g_hooking->get_original<hooks::handle_join_request>()(network, session, player_info, ctx, is_transition_session);
}
}
}
}

View File

@ -10,7 +10,7 @@
#include "script/scriptIdBase.hpp"
#include "services/players/player_service.hpp"
#include "util/session.hpp"
#include "util/spam.hpp"
#include "util/chat.hpp"
#include "gta/enums.hpp"
#include <network/Network.hpp>
@ -19,12 +19,11 @@
inline void gamer_handle_deserialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
constexpr int PC_PLATFORM = 3;
if ((hnd.m_platform = buf.Read<uint8_t>(8)) != PC_PLATFORM)
if ((hnd.m_platform = buf.Read<uint8_t>(sizeof(hnd.m_platform) * 8)) != rage::rlPlatforms::PC)
return;
buf.ReadInt64((int64_t*)&hnd.m_rockstar_id, 64);
hnd.unk_0009 = buf.Read<uint8_t>(8);
buf.ReadRockstarId(&hnd.m_rockstar_id);
hnd.m_padding = buf.Read<uint8_t>(sizeof(hnd.m_padding) * 8);
}
inline bool is_kick_instruction(rage::datBitBuffer& buffer)
@ -107,18 +106,21 @@ namespace big
case rage::eNetMessage::MsgTextMessage2:
{
char message[256];
buffer.ReadString(message, 256);
rage::rlGamerHandle handle{};
bool is_team;
buffer.ReadString(message, sizeof(message));
gamer_handle_deserialize(handle, buffer);
buffer.ReadBool(&is_team);
if (player->is_spammer)
return true;
if (auto spam_reason = spam::is_text_spam(message, player))
if (auto spam_reason = chat::is_text_spam(message, player))
{
if (g.session.log_chat_messages)
spam::log_chat(message, player, spam_reason, is_team);
g_notification_service->push("PROTECTIONS"_T.data(),
chat::log_chat(message, player, spam_reason, is_team);
g_notification_service.push("PROTECTIONS"_T.data(),
std::format("{} {}", player->get_name(), "IS_A_SPAMMER"_T.data()));
player->is_spammer = true;
if (g.session.kick_chat_spammers
@ -136,7 +138,7 @@ namespace big
else
{
if (g.session.log_chat_messages)
spam::log_chat(message, player, SpamReason::NOT_A_SPAMMER, is_team);
chat::log_chat(message, player, SpamReason::NOT_A_SPAMMER, is_team);
if (g.session.chat_commands && message[0] == g.session.chat_command_prefix)
command::process(std::string(message + 1), std::make_shared<chat_command_context>(player));
@ -145,16 +147,8 @@ namespace big
if (msgType == rage::eNetMessage::MsgTextMessage && g_pointers->m_gta.m_chat_data && player->get_net_data())
{
rage::rlGamerHandle temp{};
gamer_handle_deserialize(temp, buffer);
bool is_team = buffer.Read<bool>(1);
g_pointers->m_gta.m_handle_chat_message(*g_pointers->m_gta.m_chat_data,
nullptr,
&player->get_net_data()->m_gamer_handle,
message,
is_team);
return true;
buffer.Seek(0);
return g_hooking->get_original<hooks::receive_net_message>()(netConnectionManager, a2, frame); // Call original function since we can't seem to handle it
}
}
break;
@ -166,7 +160,7 @@ namespace big
if (player->m_host_migration_rate_limit.exceeded_last_process())
{
session::add_infraction(player, Infraction::TRIED_KICK_PLAYER);
g_notification_service->push_error("PROTECTIONS"_T.data(),
g_notification_service.push_error("PROTECTIONS"_T.data(),
std::vformat("OOM_KICK"_T, std::make_format_args(player->get_name())));
}
return true;
@ -209,7 +203,7 @@ namespace big
if (reason == KickReason::VOTED_OUT)
{
g_notification_service->push_warning("PROTECTIONS"_T.data(), "YOU_HAVE_BEEN_KICKED"_T.data());
g_notification_service.push_warning("PROTECTIONS"_T.data(), "YOU_HAVE_BEEN_KICKED"_T.data());
return true;
}
@ -225,7 +219,7 @@ namespace big
if (player->m_radio_request_rate_limit.exceeded_last_process())
{
session::add_infraction(player, Infraction::TRIED_KICK_PLAYER);
g_notification_service->push_error("PROTECTIONS"_T.data(),
g_notification_service.push_error("PROTECTIONS"_T.data(),
std::vformat("OOM_KICK"_T, std::make_format_args(player->get_name())));
player->block_radio_requests = true;
}

View File

@ -6,10 +6,10 @@ namespace big
{
if (g.protections.receive_pickup)
{
g_notification_service->push_error("PROTECTIONS"_T.data(), "Blocked pickup");
g_notification_service.push_error("PROTECTIONS"_T.data(), "Blocked pickup");
return false;
}
return g_hooking->get_original<hooks::receive_pickup>()(object, unk, ped);
}
}
}

View File

@ -355,7 +355,7 @@ namespace big
&& player->m_player_info->m_ped && player->m_player_info->m_ped->m_net_object
&& ownerNetId != player->m_player_info->m_ped->m_net_object->m_object_id && !offset_object)
{
g_notification_service->push_error("WARNING"_T.data(),
g_notification_service.push_error("WARNING"_T.data(),
std::vformat("BLAMED_FOR_EXPLOSION"_T,
std::make_format_args(player->get_name(),
reinterpret_cast<CPed*>(entity)->m_player_info->m_net_player_data.m_name)));
@ -615,7 +615,7 @@ namespace big
if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id)
{
weapon_item weapon = g_gta_data_service->weapon_by_hash(hash);
g_notification_service->push_warning("PROTECTIONS"_T.data(),
g_notification_service.push_warning("PROTECTIONS"_T.data(),
std::format("{} {} {}.", source_player->get_name(), "REMOVE_WEAPON_ATTEMPT_MESSAGE"_T, weapon.m_display_name));
g_pointers->m_gta.m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset);
return;
@ -632,7 +632,7 @@ namespace big
if (g_local_player && g_local_player->m_net_object && g_local_player->m_net_object->m_object_id == net_id)
{
weapon_item weapon = g_gta_data_service->weapon_by_hash(hash);
g_notification_service->push_warning("PROTECTIONS"_T.data(),
g_notification_service.push_warning("PROTECTIONS"_T.data(),
std::format("{} {} {}.", source_player->get_name(), "GIVE_WEAPON_ATTEMPT_MESSAGE"_T, weapon.m_display_name));
g_pointers->m_gta.m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset);
return;

View File

@ -20,7 +20,7 @@ namespace big
LOG(WARNING) << "BLOCKED_SCRIPT_EVENT From: " << player_name << " Event Type: " << protection_type;
if (should_notify)
g_notification_service->push_warning("Script Event Protection",
g_notification_service.push_warning("Script Event Protection",
std::format("From: {}\nEvent Type: {}", player_name.data(), protection_type.data()));
}

View File

@ -16,7 +16,7 @@ namespace big
if (plyr && plyr->block_join && *g_pointers->m_gta.m_is_session_started)
{
data->m_bubble_id = 10;
g_notification_service->push("BLOCK_JOIN"_T.data(), std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(plyr->get_name())));
g_notification_service.push("BLOCK_JOIN"_T.data(), std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(plyr->get_name())));
}
bool result = g_hooking->get_original<hooks::send_non_physical_player_data>()(player, message, flags, a4, a5);
@ -25,4 +25,4 @@ namespace big
return result;
}
}
}

View File

@ -0,0 +1,10 @@
#include "hooking/hooking.hpp"
#include "gta/pools.hpp"
namespace big
{
bool hooks::can_create_vehicle()
{
return (**g_pointers->m_gta.m_vehicle_pool)->m_item_count < (**g_pointers->m_gta.m_vehicle_pool)->m_size;
}
}

View File

@ -11,7 +11,7 @@ namespace big
LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated (" << thread->m_exit_message << ").";
if (g.notifications.gta_thread_kill.notify)
g_notification_service->push("Script Thread Termination",
g_notification_service.push("Script Thread Termination",
std::format("Script Thread '{}' terminated.", thread->m_name));
if (thread == g.m_hunt_the_beast_thread)

View File

@ -12,7 +12,7 @@ namespace big
if (g.notifications.gta_thread_kill.log)
LOG(INFO) << "Script Thread '" << name << "' started.";
if (g.notifications.gta_thread_kill.notify)
g_notification_service->push("Script Thread Startup", std::format("Script Thread '{}' started.", name));
g_notification_service.push("Script Thread Startup", std::format("Script Thread '{}' started.", name));
}
return new_thread;

View File

@ -22,7 +22,6 @@ namespace big
m_console_logger = &logger::format_console_simple;
}
toggle_external_console(attach_console);
create_backup();
m_file_out.open(m_file.get_path(), std::ios_base::out | std::ios_base::trunc);
@ -33,6 +32,8 @@ namespace big
Logger::AddSink([this](LogMessagePtr msg) {
format_file(std::move(msg));
});
toggle_external_console(attach_console);
}
void logger::destroy()
@ -44,6 +45,19 @@ namespace big
void logger::toggle_external_console(bool toggle)
{
if (m_is_console_open == toggle)
{
return;
}
m_is_console_open = toggle;
m_console_out.close();
if (m_did_console_exist)
SetConsoleMode(m_console_handle, m_original_console_mode);
if (!m_did_console_exist)
FreeConsole();
if (toggle)
{
if (m_did_console_exist = ::AttachConsole(GetCurrentProcessId()); !m_did_console_exist)
@ -60,23 +74,12 @@ namespace big
// terminal like behaviour enable full color support
console_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
// prevent clicking in terminal from suspending our main thread
console_mode &= ~(ENABLE_QUICK_EDIT_MODE);
SetConsoleMode(m_console_handle, console_mode);
}
m_console_out.open("CONOUT$", std::ios_base::out | std::ios_base::app);
return;
}
m_console_out.close();
if (m_did_console_exist)
SetConsoleMode(m_console_handle, m_original_console_mode);
if (!m_did_console_exist)
FreeConsole();
}
void logger::create_backup()
@ -119,6 +122,11 @@ namespace big
void logger::format_console(const LogMessagePtr msg)
{
if (!m_is_console_open)
{
return;
}
const auto color = get_color(msg->Level());
const auto timestamp = std::format("{0:%H:%M:%S}", msg->Timestamp());
@ -133,6 +141,11 @@ namespace big
void logger::format_console_simple(const LogMessagePtr msg)
{
if (!m_is_console_open)
{
return;
}
const auto color = get_color(msg->Level());
const auto timestamp = std::format("{0:%H:%M:%S}", msg->Timestamp());

View File

@ -28,6 +28,7 @@ namespace big
private:
bool m_attach_console = true;
bool m_did_console_exist = false;
bool m_is_console_open = false;
void (logger::*m_console_logger)(const LogMessagePtr msg) = &logger::format_console;
@ -59,4 +60,4 @@ namespace big
};
inline logger g_log{};
}
}

View File

@ -251,7 +251,7 @@ namespace lua::gui
// Shows a message to the user with the given title and message.
static void show_message(const std::string& title, const std::string& message)
{
big::g_notification_service->push(title, message);
big::g_notification_service.push(title, message);
}
// Lua API: Function
@ -262,7 +262,7 @@ namespace lua::gui
// Shows a warning to the user with the given title and message.
static void show_warning(const std::string& title, const std::string& message)
{
big::g_notification_service->push_warning(title, message);
big::g_notification_service.push_warning(title, message);
}
// Lua API: Function
@ -273,7 +273,7 @@ namespace lua::gui
// Shows an error to the user with the given title and message.
static void show_error(const std::string& title, const std::string& message)
{
big::g_notification_service->push_error(title, message);
big::g_notification_service.push_error(title, message);
}
// Lua API: Function
@ -373,4 +373,4 @@ namespace lua::gui
tab_ut["add_input_string"] = &tab::add_input_string;
tab_ut["add_imgui"] = &tab::add_imgui;
}
}
}

View File

@ -5,6 +5,7 @@
#include "pointers.hpp"
#include "services/player_database/player_database_service.hpp"
#include "util/notify.hpp"
#include "util/chat.hpp"
#include "util/scripts.hpp"
#include "util/session.hpp"
#include "util/system.hpp"
@ -183,13 +184,22 @@ namespace lua::network
// Sends a message to the in game chat.
static void send_chat_message(const std::string& msg, bool team_only)
{
big::g_fiber_pool->queue_job([msg, team_only] {
if (big::g_hooking->get_original<big::hooks::send_chat_message>()(*big::g_pointers->m_gta.m_send_chat_ptr,
big::g_player_service->get_self()->get_net_data(),
(char*)msg.c_str(),
team_only))
big::notify::draw_chat((char*)msg.data(), big::g_player_service->get_self()->get_name(), team_only);
});
big::chat::send_message(msg, nullptr, true, team_only);
}
// Lua API: Function
// Table: network
// Name: send_chat_message_to_player
// Param: player_idx: integer: Index of the player.
// Param: msg: string: Message to be sent.
// Sends a chat message to the specified player. Other players would not be able to see the message
static void send_chat_message_to_player(int player_idx, const std::string& msg)
{
if (auto player = big::g_player_service->get_by_id(player_idx))
{
big::chat::send_message(msg, player);
}
}
void bind(sol::state& state)
@ -229,5 +239,6 @@ namespace lua::network
ns["get_flagged_modder_reason"] = get_flagged_modder_reason;
ns["force_script_host"] = force_script_host;
ns["send_chat_message"] = send_chat_message;
ns["send_chat_message_to_player"] = send_chat_message_to_player;
}
}

View File

@ -3,6 +3,7 @@
#include "lua/lua_manager.hpp"
#include "script_mgr.hpp"
#include "gta_util.hpp"
namespace lua::script
{
@ -151,15 +152,26 @@ namespace lua::script
module->m_registered_scripts.push_back(std::move(lua_script));
}
// Lua API: function
// Table: script
// Name: execute_as_script
// Param: script_name: string: target script thread.
// Param: func: function: function that will be executed once in the script thread.
static void execute_as_script(const std::string& script_name, sol::protected_function func)
{
big::gta_util::execute_as_script(rage::joaat(script_name), func);
}
void bind(sol::state& state)
{
auto ns = state["script"].get_or_create<sol::table>();
ns["register_looped"] = register_looped;
ns["run_in_fiber"] = run_in_fiber;
ns["execute_as_script"] = execute_as_script;
auto usertype = state.new_usertype<script_util>("script_util");
usertype["yield"] = sol::yielding(&script_util::yield);
usertype["sleep"] = sol::yielding(&script_util::sleep);
}
}
}

View File

@ -152,9 +152,8 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
g_file_manager.init(base_dir);
g.init(g_file_manager.get_project_file("./settings.json"));
LOG(INFO) << "Settings Loaded.";
g_log.initialize("YimMenu", g_file_manager.get_project_file("./cout.log"), g.debug.external_console);
LOG(INFO) << "Settings Loaded and logger initialized.";
LOG(INFO) << "Yim's Menu Initializing";
LOGF(INFO, "Git Info\n\tBranch:\t{}\n\tHash:\t{}\n\tDate:\t{}", version::GIT_BRANCH, version::GIT_SHA1, version::GIT_DATE);
@ -211,7 +210,6 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
auto context_menu_service_instance = std::make_unique<context_menu_service>();
auto custom_text_service_instance = std::make_unique<custom_text_service>();
auto mobile_service_instance = std::make_unique<mobile_service>();
auto notification_service_instance = std::make_unique<notification_service>();
auto pickup_service_instance = std::make_unique<pickup_service>();
auto player_service_instance = std::make_unique<player_service>();
auto gta_data_service_instance = std::make_unique<gta_data_service>();
@ -229,6 +227,9 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID)
auto xml_maps_service_instance = std::make_unique<xml_map_service>();
LOG(INFO) << "Registered service instances...";
g_notification_service.initialise();
LOG(INFO) << "Finished initialising services.";
g_script_mgr.add_script(std::make_unique<script>(&gui::script_func, "GUI", false));
g_script_mgr.add_script(std::make_unique<script>(&backend::loop, "Backend Loop", false));

View File

@ -13,7 +13,7 @@ namespace big
if (g.notifications.transaction_rate_limit.log)
LOG(WARNING) << "Received transaction rate limit";
if (g.notifications.transaction_rate_limit.notify)
g_notification_service->push_warning("TRANSACTION_RATE_LIMIT"_T.data(), "TRANSACTION_RATE_LIMIT_MESSAGE"_T.data());
g_notification_service.push_warning("TRANSACTION_RATE_LIMIT"_T.data(), "TRANSACTION_RATE_LIMIT_MESSAGE"_T.data());
*scr_globals::transaction_overlimit.as<PBOOL>() = FALSE;
@ -23,4 +23,4 @@ namespace big
HUD::SET_WARNING_MESSAGE_WITH_HEADER(src->get_arg<const char*>(0), src->get_arg<const char*>(1), src->get_arg<int>(2), src->get_arg<const char*>(3), src->get_arg<BOOL>(4), src->get_arg<Any>(5), src->get_arg<Any*>(6), src->get_arg<Any*>(7), src->get_arg<BOOL>(8), src->get_arg<Any>(9));
}
}
}
}

View File

@ -1772,6 +1772,15 @@ namespace big
{
g_pointers->m_gta.m_weapon_info_manager = ptr.add(3).rip().sub(72).as<CWeaponInfoManager*>();
}
},
// Can Create Vehicle
{
"CCV",
"8B 0D ? ? ? ? 39 0D ? ? ? ? 0F 9C C0",
[](memory::handle ptr)
{
g_pointers->m_gta.m_can_create_vehicle = ptr.as<functions::can_create_vehicle>();
}
}
>(); // don't leave a trailing comma at the end

View File

@ -71,7 +71,7 @@ namespace big
VEHICLE::SET_VEHICLE_ENGINE_ON(m_handle, false, true, false);
}
else
g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"FIX VEHICLE",
[this] {
@ -83,7 +83,7 @@ namespace big
VEHICLE::SET_VEHICLE_DIRT_LEVEL(m_handle, 0.f);
}
else
g_notification_service->push_warning("WARNING"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("WARNING"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"BURST TIRES",
[this] {
@ -97,7 +97,7 @@ namespace big
}
}
else
g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"HALT",
[this] {
@ -106,7 +106,7 @@ namespace big
VEHICLE::BRING_VEHICLE_TO_HALT(m_handle, 1, 5, true);
}
else
g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"COPY VEHICLE",
[this] {
@ -119,14 +119,14 @@ namespace big
if (entity::take_control_of(m_handle))
VEHICLE::SET_VEHICLE_FORWARD_SPEED(m_handle, 79);
else
g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"LAUNCH",
[this] {
if (entity::take_control_of(m_handle))
ENTITY::APPLY_FORCE_TO_ENTITY(m_handle, 1, 0.f, 0.f, 50000.f, 0.f, 0.f, 0.f, 0, 0, 1, 1, 0, 1);
else
g_notification_service->push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("TOXIC"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
}},
{"EJECT",
[this] {
@ -225,7 +225,7 @@ namespace big
{
{"COPY HASH", [this] {
ImGui::SetClipboardText(std::format("0x{:08X}", (rage::joaat_t)m_pointer->m_model_info->m_hash).c_str());
g_notification_service->push("Context Menu",
g_notification_service.push("Context Menu",
std::format("Copy hash 0x{:08X}", (rage::joaat_t)m_pointer->m_model_info->m_hash).c_str());
}},
{"EXPLODE",

View File

@ -46,7 +46,7 @@ namespace big
if (!buffer)
{
g_notification_service->push_error("CREATOR_STORAGE_SAVE_JOB"_T.data(),
g_notification_service.push_error("CREATOR_STORAGE_SAVE_JOB"_T.data(),
"CREATOR_STORAGE_CANNOT_OBTAIN_JSON"_T.data());
return;
}

View File

@ -70,7 +70,7 @@ namespace big
file_out << j.dump(4);
file_out.close();
g_notification_service->push_success("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::format("Succesfully saved location {}", t.name));
g_notification_service.push_success("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::format("Succesfully saved location {}", t.name));
return true;
}

View File

@ -65,7 +65,7 @@ namespace big
struct navigation_struct
{
char name[48] = "";
char name[80] = "";
std::function<void()> func = nullptr;
std::map<tabs, navigation_struct> sub_nav{};
rage::joaat_t hash = rage::joaat(name);

View File

@ -22,107 +22,92 @@ namespace big
void model_preview_service::show_ped(Hash hash)
{
m_ped_clone = 0;
m_veh_model_hash = 0;
m_veh_owned_mods.clear();
if (m_running && m_ped_model_hash != hash)
{
stop_preview();
return;
}
if (m_ped_model_hash != hash)
if (!m_running)
{
m_ped_model_hash = hash;
if (m_ped_model_hash != 0)
{
m_new_model = true;
preview_loop();
}
}
preview_loop();
}
void model_preview_service::show_ped(Hash hash, Ped clone)
{
m_veh_model_hash = 0;
m_veh_owned_mods.clear();
if (m_running && (m_ped_model_hash != hash || m_ped_clone != clone ))
{
stop_preview();
return;
}
if (m_ped_model_hash != hash || m_ped_clone != clone)
if (!m_running)
{
m_ped_model_hash = hash;
m_ped_clone = clone;
if (m_ped_model_hash != 0)
{
m_new_model = true;
preview_loop();
}
m_ped_clone = clone;
}
preview_loop();
}
void model_preview_service::show_vehicle(Hash hash, bool spawn_max)
{
m_ped_model_hash = 0;
m_ped_clone = 0;
m_veh_owned_mods.clear();
if (m_running && m_veh_model_hash != hash)
{
stop_preview();
return;
}
if (m_veh_model_hash != hash || m_veh_spawn_max != spawn_max)
if (!m_running)
{
m_veh_model_hash = hash;
m_current_persisted_vehicle_name.clear();
if (m_veh_model_hash != 0)
{
m_veh_spawn_max = spawn_max;
m_new_model = true;
preview_loop();
}
}
preview_loop();
}
void model_preview_service::show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max)
{
m_ped_model_hash = 0;
m_ped_clone = 0;
m_current_persisted_vehicle_name.clear();
if (m_veh_spawn_max != spawn_max || m_veh_owned_mods.size() != owned_mods.size()
|| !std::equal(m_veh_owned_mods.begin(), m_veh_owned_mods.end(), owned_mods.begin()))
if (m_running && m_veh_owned_mods != owned_mods)
{
m_veh_owned_mods.clear();
stop_preview();
return;
}
if (!m_running)
{
auto hash_item = owned_mods.find(MOD_MODEL_HASH);
m_veh_model_hash = hash_item->second;
if (m_veh_model_hash != 0)
{
m_veh_owned_mods.insert(owned_mods.begin(), owned_mods.end());
m_veh_spawn_max = spawn_max;
m_new_model = true;
preview_loop();
}
m_veh_owned_mods.insert(owned_mods.begin(), owned_mods.end());
m_veh_spawn_max = spawn_max;
}
preview_loop();
}
void model_preview_service::show_vehicle_persisted(std::string vehicle_name)
{
m_ped_model_hash = 0;
m_ped_clone = 0;
m_veh_model_hash = 0;
if (m_current_persisted_vehicle_name != vehicle_name)
if (m_running && m_current_persisted_vehicle_name != vehicle_name)
{
stop_preview();
return;
}
if (!m_running)
{
m_current_persisted_vehicle_name = vehicle_name;
m_new_model = true;
preview_loop();
}
preview_loop();
}
void model_preview_service::preview_loop()
{
if (m_running || m_loop_running)
if (m_running)
{
return;
}
@ -130,26 +115,15 @@ namespace big
m_running = true;
g_fiber_pool->queue_job([this] {
m_loop_running = true;
m_heading = 0.f;
m_rotation_start_time = std::chrono::steady_clock::now();
while (g_running && m_running && g_gui->is_open() && (m_ped_model_hash || m_veh_model_hash || !m_current_persisted_vehicle_name.empty()))
while (!m_shutdown_preview && g_running && g_gui->is_open() )
{
Vector3 location;
if (m_ped_model_hash)
{
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 5.f, -.5f);
}
else if (m_veh_model_hash || !m_current_persisted_vehicle_name.empty())
{
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
}
Vector3 location{};
if (m_current_ent == 0)
{
m_new_model = false;
location.z = -10.f;
if (m_ped_model_hash)
{
m_current_ent = ped::spawn(ePedType::PED_TYPE_ARMY, m_ped_model_hash, m_ped_clone, location, 0.f, false);
@ -172,7 +146,7 @@ namespace big
}
else if (!m_current_persisted_vehicle_name.empty())
{
m_current_ent = persist_car_service::load_vehicle(m_current_persisted_vehicle_name, g.persist_car.persist_vehicle_sub_folder, Vector3());
m_current_ent = persist_car_service::preview_vehicle(m_current_persisted_vehicle_name, g.persist_car.persist_vehicle_sub_folder, location);
}
if (m_current_ent)
@ -189,44 +163,56 @@ namespace big
OBJECT::SET_OBJECT_ALLOW_LOW_LOD_BUOYANCY(m_current_ent, false);
}
}
else if (m_new_model)
{
entity::delete_entity(m_current_ent, true);
}
else
{
if (const int alpha = ENTITY::GET_ENTITY_ALPHA(m_current_ent); alpha < 255)
if (m_ped_model_hash)
{
ENTITY::SET_ENTITY_ALPHA(m_current_ent, std::min<int>(255, alpha + 20), false);
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 5.f, -.5f);
}
else
{
location = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(self::ped, 0.f, 10.f, .5f);
}
ENTITY::SET_ENTITY_HEADING(m_current_ent, m_heading);
ENTITY::SET_ENTITY_COORDS(m_current_ent, location.x, location.y, location.z, 0, 0, 0, 0);
}
if (m_heading += 0.5f; m_heading > 359)
if (auto alpha = ENTITY::GET_ENTITY_ALPHA(m_current_ent); alpha < 255)
{
m_heading = 0;
ENTITY::SET_ENTITY_ALPHA(m_current_ent, std::min<int>(255, alpha + 20), false);
}
script::get_current()->yield(15ms);
ENTITY::SET_ENTITY_HEADING(m_current_ent, m_heading);
ENTITY::SET_ENTITY_COORDS(m_current_ent, location.x, location.y, location.z, 0, 0, 0, 0);
auto now = std::chrono::steady_clock::now();
auto elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_rotation_start_time).count() / 1000.0; // Convert to seconds
m_heading = (elapsed_time / 10.0) * 360.0; // Rotate 360 degrees every 10 seconds
m_heading = fmod(m_heading, 360.0); // Ensure rotation is always between 0 and 360
script::get_current()->yield();
}
entity::delete_entity(m_current_ent, true);
ENTITY::DELETE_ENTITY(&m_current_ent);
m_current_ent = 0;
m_ped_model_hash = 0;
m_veh_model_hash = 0;
m_veh_owned_mods.clear();
m_current_persisted_vehicle_name.clear();
m_running = false;
m_loop_running = false;
clear_data();
});
}
void model_preview_service::clear_data()
{
m_veh_owned_mods.clear();
m_ped_model_hash = {};
m_veh_model_hash = {};
m_ped_clone = {};
m_current_persisted_vehicle_name = {};
m_shutdown_preview = false;
m_running = false;
m_current_ent = NULL;
}
void model_preview_service::stop_preview()
{
m_veh_owned_mods.clear();
m_running = false;
if (m_running)
m_shutdown_preview = true;
}
}

View File

@ -5,25 +5,21 @@ namespace big
{
class model_preview_service
{
std::condition_variable m_cond;
std::mutex m_mutex;
Entity m_current_ent{};
float m_heading{};
Entity m_current_ent = 0;
Hash m_ped_model_hash{};
Hash m_veh_model_hash{};
Ped m_ped_clone{};
std::string m_current_persisted_vehicle_name;
Hash m_veh_model_hash = 0;
std::map<int, int32_t> m_veh_owned_mods;
bool m_veh_spawn_max = false;
Hash m_ped_model_hash = 0;
Ped m_ped_clone = 0;
bool m_new_model = false;
float m_heading = 0.f;
bool m_loop_running = false;
bool m_running = false;
std::string m_current_persisted_vehicle_name;
bool m_running = false;
bool m_shutdown_preview = false;
std::chrono::time_point<std::chrono::steady_clock> m_rotation_start_time;
public:
model_preview_service();
~model_preview_service();
@ -35,9 +31,11 @@ namespace big
void show_vehicle(const std::map<int, int32_t>& owned_mods, bool spawn_max);
void show_vehicle_persisted(std::string vehicle_name);
void show_vehicle(Vehicle veh);
void preview_loop();
void stop_preview();
private:
void clear_data();
void preview_loop();
};
inline model_preview_service* g_model_preview_service{};

View File

@ -0,0 +1,46 @@
#include "notification.hpp"
namespace big
{
notification::notification(const std::string title, const std::string message, NotificationType type, const std::chrono::high_resolution_clock::duration lifetime) :
m_title(title),
m_message(message),
m_identifier(std::hash<std::string>{}(title + message)),
m_type(type),
m_lifetime(lifetime),
m_destroy_time(std::chrono::high_resolution_clock::now() + lifetime),
m_counter(1)
{
switch (type)
{
case NotificationType::DANGER: m_color = ImVec4(0.69f, 0.29f, 0.29f, 1.00f); break;
case NotificationType::WARNING: m_color = ImVec4(0.69f, 0.49f, 0.29f, 1.00f); break;
case NotificationType::SUCCESS: m_color = ImVec4(0.29f, 0.69f, 0.34f, 1.00f); break;
default:
case NotificationType::INFO: m_color = ImVec4(0.80f, 0.80f, 0.83f, 1.00f); break;
}
}
// linear fade out in the last 600ms
const float notification::alpha() const
{
const auto remaining_time = std::chrono::duration_cast<std::chrono::milliseconds>(m_destroy_time - std::chrono::high_resolution_clock::now());
if (remaining_time < 300ms)
{
return (float)remaining_time.count() / 300.f;
}
return 1.0f;
}
void notification::reset()
{
++m_counter;
m_destroy_time = std::chrono::high_resolution_clock::now() + m_lifetime;
}
bool notification::should_be_destroyed() const
{
return m_destroy_time < std::chrono::high_resolution_clock::now();
}
}

View File

@ -0,0 +1,89 @@
#pragma once
namespace big
{
enum class NotificationType
{
INFO,
SUCCESS,
WARNING,
DANGER,
};
class notification
{
private:
std::string m_title;
std::string m_message;
std::size_t m_identifier;
NotificationType m_type;
std::chrono::high_resolution_clock::duration m_lifetime;
std::chrono::steady_clock::time_point m_destroy_time;
ImVec4 m_color;
std::size_t m_counter;
public:
notification() = default;
virtual ~notification() = default;
notification(const notification&) = default;
notification(notification&&) noexcept = default;
notification& operator=(const notification&) = default;
notification& operator=(notification&&) noexcept = default;
notification(const std::string title, const std::string message, NotificationType type, const std::chrono::high_resolution_clock::duration lifetime = std::chrono::seconds(5));
const std::string& title() const
{
return m_title;
}
const std::string& message() const
{
return m_message;
}
const std::size_t identifier() const
{
return m_identifier;
}
const NotificationType type() const
{
return m_type;
}
const std::chrono::steady_clock::time_point destroy_time() const
{
return m_destroy_time;
}
const float alpha() const;
const ImVec4 color() const
{
return m_color;
}
/**
* @brief Returns the amount of times the notification was refreshed because the same notification was pushed.
*
* @return const std::size_t
*/
const std::size_t counter() const
{
return m_counter;
}
/**
* @brief Resets the destroy timer on a notification, extending its lifetime and incrementing the show counter.
*/
void reset();
/**
* @brief Indicates if the notification is ready to be destroyed (it has gone past its lifetime).
*
* @return true
* @return false
*/
bool should_be_destroyed() const;
};
}

View File

@ -4,69 +4,64 @@
namespace big
{
notification_service::notification_service()
bool notification_service::initialise()
{
push("NOTIFICATION_WELCOME_TITLE"_T.data(),
std::vformat("NOTIFICATION_WELCOME_TEXT"_T, std::make_format_args(ImGui::key_names[g.settings.hotkeys.menu_toggle])));
g_notification_service = this;
}
notification_service::~notification_service()
{
g_notification_service = nullptr;
}
void notification_service::push(notification n)
{
this->notifications.emplace(std::hash<std::string>{}(n.message + n.title), n);
return true;
}
void notification_service::push(const std::string& title, const std::string& message)
{
this->push({NotificationType::INFO, title, message, std::chrono::system_clock::now(), 5000.f, 1.f});
push({title, message, NotificationType::INFO});
}
void notification_service::push_warning(const std::string& title, const std::string& message)
{
this->push({NotificationType::WARNING, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
push({title, message, NotificationType::WARNING, 7s});
}
void notification_service::push_error(const std::string& title, const std::string& message)
{
this->push({NotificationType::DANGER, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
push({title, message, NotificationType::DANGER, 7s});
}
void notification_service::push_success(const std::string& title, const std::string& message)
{
this->push({NotificationType::SUCCESS, title, message, std::chrono::system_clock::now(), 7000.f, 1.f});
push({title, message, NotificationType::SUCCESS, 7s});
}
std::vector<notification> notification_service::get()
{
std::vector<notification> notifications_to_sent;
std::vector<std::size_t> to_remove;
for (auto& n : this->notifications)
// remove old notifications
for (auto it = m_notifications.begin(); it != m_notifications.end();)
{
std::chrono::time_point<std::chrono::system_clock> curTime = std::chrono::system_clock::now();
const float time_diff =
(float)std::chrono::duration_cast<std::chrono::milliseconds>(curTime - n.second.created_on).count();
n.second.alpha = 1;
if (n.second.destroy_in <= time_diff)
if (it->second.should_be_destroyed())
{
n.second.alpha = 1.f - ((time_diff - n.second.destroy_in) / 600);
n.second.alpha = n.second.alpha < 0.f ? 0.f : n.second.alpha;
it = m_notifications.erase(it++);
continue;
}
if (n.second.alpha > 0.f)
notifications_to_sent.push_back(n.second);
else
to_remove.push_back(n.first);
++it;
}
for (std::size_t k : to_remove)
this->notifications.erase(k);
return notifications_to_sent;
// grab only the notifications, no need for the keys
auto sorted = m_notifications | std::views::values | std::ranges::to<std::vector<notification>>();
std::sort(sorted.begin(), sorted.end(), [](auto const& a, auto const& b) {
// inverse sorting, highest remaining time goes to top
return a.destroy_time() > b.destroy_time();
});
return sorted;
}
}
void notification_service::push(notification n)
{
const auto [pair, inserted] = m_notifications.insert({n.identifier(), n});
if (!inserted)
{
pair->second.reset();
}
}
}

View File

@ -1,46 +1,31 @@
#pragma once
#include "notification.hpp"
namespace big
{
enum class NotificationType
{
INFO,
SUCCESS,
WARNING,
DANGER,
};
struct notification
{
NotificationType type;
const std::string title;
const std::string message;
const std::chrono::time_point<std::chrono::system_clock> created_on;
const float destroy_in;
float alpha;
};
class notification_service final
{
std::unordered_map<std::size_t, notification> notifications;
std::unordered_map<std::size_t, notification> m_notifications;
public:
notification_service();
virtual ~notification_service();
notification_service() = default;
virtual ~notification_service() = default;
void push(notification);
void push(const std::string&, const std::string&);
void push_warning(const std::string&, const std::string&);
void push_error(const std::string&, const std::string&);
void push_success(const std::string&, const std::string&);
bool initialise();
void push(const std::string& title, const std::string& message);
void push_warning(const std::string& title, const std::string& message);
void push_error(const std::string& title, const std::string& message);
void push_success(const std::string& title, const std::string& message);
// cleans up old notifications from the map and returns a sorted list based on the destroy time
std::vector<notification> get();
std::map<NotificationType, ImVec4> notification_colors = {
{NotificationType::INFO, ImVec4(0.80f, 0.80f, 0.83f, 1.00f)},
{NotificationType::SUCCESS, ImVec4(0.29f, 0.69f, 0.34f, 1.00f)},
{NotificationType::WARNING, ImVec4(0.69f, 0.49f, 0.29f, 1.00f)},
{NotificationType::DANGER, ImVec4(0.69f, 0.29f, 0.29f, 1.00f)},
};
private:
void push(notification notification);
};
inline notification_service* g_notification_service{};
}
inline notification_service g_notification_service{};
}

View File

@ -82,7 +82,7 @@ namespace big
file_out << j.dump(4);
file_out.close();
g_notification_service->push_success("Animations", std::format("Succesfully saved location {}", p.name));
g_notification_service.push_success("Animations", std::format("Succesfully saved location {}", p.name));
return true;
}
@ -177,4 +177,4 @@ namespace big
}
}
}
}
}

View File

@ -115,7 +115,7 @@ namespace big
}
catch (std::exception& e)
{
g_notification_service->push_warning("Persist Weapons", "Failed to load JSON file from disk.");
g_notification_service.push_warning("Persist Weapons", "Failed to load JSON file from disk.");
LOG(WARNING) << "Persist Weapons failed to load JSON file: " << g.persist_weapons.weapon_loadout_file << " because " << e.what();
}
}
@ -193,4 +193,4 @@ namespace big
}
}
}
}
}

View File

@ -35,24 +35,24 @@ namespace big
if (g.player_db.notify_when_joinable && !is_joinable_session(player.session_type) && is_joinable_session(new_session_type))
{
g_notification_service->push_success("Player DB", std::format("{} is now in a joinable session", player.name));
g_notification_service.push_success("Player DB", std::format("{} is now in a joinable session", player.name));
}
else if (g.player_db.notify_when_online && (player.session_type == GSType::Invalid || player.session_type == GSType::Unknown) && new_session_type != GSType::Invalid)
{
g_notification_service->push_success("Player DB", std::format("{} is now online", player.name));
g_notification_service.push_success("Player DB", std::format("{} is now online", player.name));
}
else if (g.player_db.notify_when_unjoinable && is_joinable_session(player.session_type) && !is_joinable_session(new_session_type) && new_session_type != GSType::Invalid)
{
g_notification_service->push("Player DB", std::format("{} is no longer in a joinable session", player.name));
g_notification_service.push("Player DB", std::format("{} is no longer in a joinable session", player.name));
}
else if (g.player_db.notify_when_offline && player.session_type != GSType::Invalid && player.session_type != GSType::Unknown && new_session_type == GSType::Invalid)
{
g_notification_service->push("Player DB", std::format("{} is no longer online", player.name));
g_notification_service.push("Player DB", std::format("{} is no longer online", player.name));
}
if (g.player_db.notify_on_session_type_change && (int)new_session_type >= (int)GSType::InviteOnly && (int)new_session_type < (int)GSType::Max)
{
g_notification_service->push("Player DB", std::format("{} is now in a{} {} session", player.name, new_session_type == GSType::InviteOnly ? "n" : "", get_session_type_str(new_session_type)));
g_notification_service.push("Player DB", std::format("{} is now in a{} {} session", player.name, new_session_type == GSType::InviteOnly ? "n" : "", get_session_type_str(new_session_type)));
}
}
@ -64,14 +64,14 @@ namespace big
if (new_game_mode == GameMode::None && old_game_mode != GameMode::None && old_game_mode_str != "None")
{
g_notification_service->push("Player DB", std::format("{} is no longer in a {}", player->name, old_game_mode_str));
g_notification_service.push("Player DB", std::format("{} is no longer in a {}", player->name, old_game_mode_str));
return;
}
if (!can_fetch_name(new_game_mode))
{
if (new_game_mode_str != "None")
g_notification_service->push("Player DB", std::format("{} is now in a {}", player->name, new_game_mode_str));
g_notification_service.push("Player DB", std::format("{} is now in a {}", player->name, new_game_mode_str));
return;
}
@ -83,11 +83,11 @@ namespace big
if (mission_name.empty())
{
g_notification_service->push("Player DB", std::format("{} is now in a {}", player->name, new_game_mode_str));
g_notification_service.push("Player DB", std::format("{} is now in a {}", player->name, new_game_mode_str));
return;
}
g_notification_service->push("Player DB", std::format("{} has joined the {} \"{}\"", player->name, new_game_mode_str, mission_name));
g_notification_service.push("Player DB", std::format("{} has joined the {} \"{}\"", player->name, new_game_mode_str, mission_name));
player->game_mode_name = mission_name;
}
@ -413,7 +413,7 @@ namespace big
else if (it->second->notify_online && it->second->session_id != info.m_session_token
&& g.player_db.notify_on_session_change)
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} has joined a new session", it->second->name));
}
@ -424,12 +424,12 @@ namespace big
{
if (is_spectating)
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} is now spectating", it->second->name));
}
else
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} is no longer spectating", it->second->name));
}
}
@ -437,7 +437,7 @@ namespace big
if (it->second->notify_online && is_host_of_session != it->second->is_host_of_session
&& g.player_db.notify_on_become_host && is_host_of_session && it->second->session_id == info.m_session_token)
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} is now the host of their session", it->second->name));
}
@ -446,19 +446,19 @@ namespace big
{
if (is_host_of_transition_session)
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} has hosted a job lobby", it->second->name));
}
else
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} has joined a job lobby", it->second->name));
}
}
else if (it->second->notify_online && g.player_db.notify_on_transition_change
&& transition_info.m_session_token == -1 && it->second->transition_session_id != -1)
{
g_notification_service->push("Player DB",
g_notification_service.push("Player DB",
std::format("{} is no longer in a job lobby", it->second->name));
}
@ -549,4 +549,4 @@ namespace big
return false;
}
}
}

View File

@ -153,7 +153,7 @@ namespace big
static auto reset_spawn_pos_to_offset = [&]() -> void {
Ped player_ped_handle = g_pointers->m_gta.m_ptr_to_handle(s.target->get_ped());
s.m_spawn_pos = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(player_ped_handle, 0, -7, 0);
g_notification_service->push_warning("Squad Spawner", "No suitable spot found, spawning at an offset");
g_notification_service.push_warning("Squad Spawner", "No suitable spot found, spawning at an offset");
};
static auto is_pos_valid = [&]() -> bool {
@ -206,7 +206,7 @@ namespace big
if (!s.target->get_net_game_player() || s.m_squad_size < 1 || !STREAMING::IS_MODEL_VALID(rage::joaat(s.m_ped_model)))
{
g_notification_service->push_error("Squad spawner", "Error spawning squad");
g_notification_service.push_error("Squad spawner", "Error spawning squad");
return false;
}
@ -225,7 +225,7 @@ namespace big
if (VEHICLE::GET_VEHICLE_MODEL_NUMBER_OF_SEATS(veh_model_hash) < s.m_squad_size)
{
s.m_squad_size = VEHICLE::GET_VEHICLE_MODEL_NUMBER_OF_SEATS(veh_model_hash);
g_notification_service->push_warning("Squad Spawner", "The squad vehicle has insufficient seats, decreasing the squad size");
g_notification_service.push_warning("Squad Spawner", "The squad vehicle has insufficient seats, decreasing the squad size");
}
}

View File

@ -61,7 +61,7 @@ namespace big
{
write << std::setw(4) << j << std::endl;
write.close();
g_notification_service->push_success("Squad spawner", std::string("Succesfully saved ").append(s.m_name));
g_notification_service.push_success("Squad spawner", std::string("Succesfully saved ").append(s.m_name));
fetch_squads();
return true;
}
@ -101,4 +101,4 @@ namespace big
m_templates.push_back(squad("Mobile squad", "s_m_m_highsec_01", "WEAPON_MICROSMG", "komoda", 4, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::FAR_AWAY, eCombatAbilityLevel::PROFESSIONAL, true, true, "This squad makes use of 'Vehicle catchup'"));
m_templates.push_back(squad("Altruists", "a_m_m_acult_01", "WEAPON_SNSPISTOL", "", 8, false, false, ped_proofs, 0, 0, 0, 100, eSquadSpawnDistance::CLOSEBY, eCombatAbilityLevel::PROFESSIONAL, false, false, "Cannibals from the alrtuist cult will surround the victim using 'Disperse'", true));
}
}
}

View File

@ -13,7 +13,7 @@ namespace big
{
if (!ENTITY::DOES_ENTITY_EXIST(vehicle) || !ENTITY::IS_ENTITY_A_VEHICLE(vehicle))
{
g_notification_service->push_warning("PERSIST_CAR_TITLE"_T.data(),
g_notification_service.push_warning("PERSIST_CAR_TITLE"_T.data(),
"PERSIST_CAR_INVALID_VEHICLE_SAVE_ATTEMPT"_T.data());
return;
}
@ -27,6 +27,28 @@ namespace big
file_stream.close();
}
Vehicle persist_car_service::preview_vehicle(std::string_view file_name, std::string folder_name, const std::optional<Vector3>& spawn_coords)
{
const auto file = check_vehicle_folder(folder_name).get_file(file_name);
std::ifstream file_stream(file.get_path());
nlohmann::json vehicle_json;
try
{
file_stream >> vehicle_json;
file_stream.close();
}
catch (std::exception& e)
{
g_notification_service.push_warning("PERSIST_CAR_TITLE"_T.data(), "Failed to load JSON file");
return NULL;
}
return spawn_vehicle_json(vehicle_json, self::ped, spawn_coords, true);
}
Vehicle persist_car_service::load_vehicle(std::string_view file_name, std::string folder_name, const std::optional<Vector3>& spawn_coords)
{
const auto file = check_vehicle_folder(folder_name).get_file(file_name);
@ -42,7 +64,7 @@ namespace big
}
catch (std::exception& e)
{
g_notification_service->push_warning("PERSIST_CAR_TITLE"_T.data(), "Failed to load JSON file");
g_notification_service.push_warning("PERSIST_CAR_TITLE"_T.data(), "Failed to load JSON file");
return NULL;
}
@ -188,16 +210,16 @@ namespace big
return vehicle;
}
Vehicle persist_car_service::spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords)
Vehicle persist_car_service::spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords, bool is_preview)
{
const Hash vehicle_hash = vehicle_json[vehicle_model_hash_key];
const Vector3& spawn_location = spawn_coords.has_value() ? spawn_coords.value() : vehicle::get_spawn_location(g.persist_car.spawn_inside, vehicle_hash);
const float spawn_heading = ENTITY::GET_ENTITY_HEADING(self::ped);
Vehicle vehicle = self::veh;
if (spawn_coords.has_value() || (!spawn_coords.has_value() && ENTITY::GET_ENTITY_MODEL(vehicle) != vehicle_hash))
if (is_preview || (!is_preview && ENTITY::GET_ENTITY_MODEL(vehicle) != vehicle_hash))
{
vehicle = big::vehicle::spawn(vehicle_hash, spawn_location, spawn_heading);
vehicle = big::vehicle::spawn(vehicle_hash, spawn_location, spawn_heading, !is_preview);
if (spawn_location.x + spawn_location.y + spawn_location.z != 0)
script::get_current()->yield(); //This is needed to wait for the engine to instantiate things like the radio station so it won't overwrite it on the next frame.

View File

@ -13,6 +13,7 @@ namespace big
static Vehicle clone_ped_car(Ped ped, Vehicle vehicle);
static void save_vehicle(Vehicle vehicle, std::string_view file_name, std::string folder_name);
static Vehicle load_vehicle(std::string_view file_name, std::string folder_name = "", const std::optional<Vector3>& = std::nullopt);
static Vehicle preview_vehicle(std::string_view file_name, std::string folder_name = "", const std::optional<Vector3>& = std::nullopt);
static void delete_vehicle(std::string_view file_name, std::string folder_name);
private:
@ -68,7 +69,7 @@ namespace big
static Vehicle spawn_vehicle_full(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt);
static Vehicle spawn_vehicle(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords);
static Vehicle spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt);
static Vehicle spawn_vehicle_json(nlohmann::json vehicle_json, Ped ped, const std::optional<Vector3>& spawn_coords = std::nullopt, bool is_preview = false);
static nlohmann::json get_full_vehicle_json(Vehicle vehicle);

View File

@ -172,7 +172,7 @@ namespace big
4.f,
5.f);
//LOG(INFO) << "Navmesh probably failed, issiuing regular task ";
g_notification_service->push_warning("VEHICLE_CONTROLLER"_T.data(),
g_notification_service.push_warning("VEHICLE_CONTROLLER"_T.data(),
"VEHICLE_CONTROLLER_TRY_ALT_PATHFINDING"_T.data());
script::get_current()->yield(500ms);
}
@ -308,13 +308,13 @@ namespace big
if (vehicle_control::find_suitable_destination_near_player(destination, heading))
{
//LOG(INFO) << "Suitable destination found";
g_notification_service->push_success("VEHICLE_CONTROLLER"_T.data(),
g_notification_service.push_success("VEHICLE_CONTROLLER"_T.data(),
"VEHICLE_CONTROLLER_FOUND_LOCATION"_T.data());
}
else
{
//LOG(INFO) << "Couldn't find suitable destionation, defaulting to offset of player\nThis might go wrong";
g_notification_service->push_error("VEHICLE_CONTROLLER"_T.data(),
g_notification_service.push_error("VEHICLE_CONTROLLER"_T.data(),
"VEHICLE_CONTROLLER_FORCE_PATHFINDING"_T.data());
destination = behind_pos;
}
@ -338,7 +338,7 @@ namespace big
else
{
//LOG(INFO) << "Navmesh load failed";
g_notification_service->push_error("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_NAVMESH_FAILURE"_T.data());
g_notification_service.push_error("VEHICLE_CONTROLLER"_T.data(), "VEHICLE_CONTROLLER_NAVMESH_FAILURE"_T.data());
m_driver_performing_task = false;
}
}

View File

@ -92,7 +92,7 @@ namespace big::animations
if (!std::filesystem::exists(g_file_manager.get_project_file("animDictsCompact.json").get_path()))
{
LOG(WARNING) << "Animations file is not in directory. https://raw.githubusercontent.com/DurtyFree/gta-v-data-dumps/master/animDictsCompact.json";
g_notification_service->push_warning("Animations", "Please download the appropriate animations json and put it in the mod directory.");
g_notification_service.push_warning("Animations", "Please download the appropriate animations json and put it in the mod directory.");
return;
}
@ -120,4 +120,4 @@ namespace big::animations
LOG(WARNING) << "Failed fetching all anims: " << e.what();
}
}
}
}

253
src/util/chat.hpp Normal file
View File

@ -0,0 +1,253 @@
#pragma once
#include "file_manager/file.hpp"
#include "services/players/player_service.hpp"
#include "core/enums.hpp"
#include "packet.hpp"
#include "natives.hpp"
#include "script.hpp"
#include "fiber_pool.hpp"
#include "core/scr_globals.hpp"
#include <network/CNetGamePlayer.hpp>
#include <script/HudColor.hpp>
#include <network/ChatData.hpp>
#include <script/globals/GPBD_FM_3.hpp>
namespace
{
static void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
buf.Write<uint8_t>(hnd.m_platform, sizeof(hnd.m_platform) * 8);
if (hnd.m_platform == rage::rlPlatforms::PC)
{
buf.WriteRockstarId(hnd.m_rockstar_id);
buf.Write<uint8_t>(hnd.m_padding, sizeof(hnd.m_padding) * 8);
}
}
static const char* spam_texts[] =
{
"qq", //a chinese chat app
"QQ",
"WWW.",
"www.",
".cn",
".CN",
".cc",
".CC",
".TOP",
".COM",
".top",
"\xE3\x80\x90", //left bracket in Chinese input method
"/Menu",
"Money/",
"Money\\\\",
"Money\\",
".gg",
"--->",
"shopgta5",
"doit#",
"krutka#",
"<b>",
"P888",
"gtacash",
"\xE6\x89\xA3\xE6\x89\xA3", // no clue what this is
"\xE5\xBE\xAE\xE4\xBF\xA1", // "wechat" in Chinese
".cc",
"<font s",
"sellix.io",
"ezcars",
"PLANO INICIAL", // "initial plan"
"REP +",
"20R$", // Brazil currency?
"l55.me",
"\xE5\xBA\x97", //"shop" in Chinese
"\xE9\x92\xB1", //"money" in Chinese
"\xE5\x88\xB7", //"make(money)" in Chinese
"\xE8\x90\x9D\xE8\x8E\x89", // "cute girl" in Chinese
"\xE5\xA6\x88", // "mother" in Chinese
"\xE7\xBE\x8E\xE5\xA5\xB3", // "sexy girl" in Chinese
"\xE5\xBC\xBA\xE5\xA5\xB8", // "rape" in Chinese
"\xE8\x90\x9D", // "loli" in Chinese
"\xE6\x8C\x82", // "hack" in Chinese
"\xE5\x85\x83", // chinese dollar
"\xE9\x98\xB4\xE4\xBC\xA0\xE5\xAA\x92", // "Yin Media" in Chinese
"\xE7\xBD\x91\xE7\xBA\xA2", // "internet celebrities" in Chinese
"TRUSTPILOT",
"cashlounge",
"Fast Delivery",
"yosativa",
"rich2day",
"LevelLifters",
". com",
"$1,000,000,000",
"Instant Delivery",
"0 Ban Risk",
"Discord For Cheap Money",
"10-30m",
"Discord todo",
};
}
namespace big::chat
{
inline SpamReason is_text_spam(const char* text, player_ptr player)
{
if (g.session.use_spam_timer)
{
if (player->last_message_time.has_value())
{
auto currentTime = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::seconds>(currentTime - player->last_message_time.value());
player->last_message_time.emplace(currentTime);
if (strlen(text) > g.session.spam_length && diff.count() <= g.session.spam_timer)
return SpamReason::TIMER_DETECTION;
}
else
{
player->last_message_time.emplace(std::chrono::steady_clock::now());
}
}
for (auto e : spam_texts)
if (strstr(text, e) != 0)
return SpamReason::STATIC_DETECTION;
return SpamReason::NOT_A_SPAMMER;
}
inline void log_chat(char* msg, player_ptr player, SpamReason spam_reason, bool is_team)
{
std::ofstream log(
g_file_manager.get_project_file(spam_reason != SpamReason::NOT_A_SPAMMER ? "./spam.log" : "./chat.log").get_path(),
std::ios::app);
auto& data = *player->get_net_data();
auto ip = player->get_ip_address();
auto now = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
auto timer = std::chrono::system_clock::to_time_t(now);
auto local_time = *std::localtime(&timer);
std::string spam_reason_str = "";
switch (spam_reason)
{
case SpamReason::STATIC_DETECTION: spam_reason_str = "(Static Detection) "; break;
case SpamReason::TIMER_DETECTION: spam_reason_str = "(Timer Detection) "; break;
}
log << spam_reason_str << "[" << std::put_time(&local_time, "%m/%d/%Y %I:%M:%S") << ":" << std::setfill('0') << std::setw(3) << ms.count() << " " << std::put_time(&local_time, "%p") << "] ";
if (ip)
log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") <" << (int)ip.value().m_field1 << "."
<< (int)ip.value().m_field2 << "." << (int)ip.value().m_field3 << "." << (int)ip.value().m_field4 << "> " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl;
else
log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") <UNKNOWN> " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl;
log.close();
}
inline void draw_chat(const char* msg, const char* player_name, bool is_team)
{
int scaleform = GRAPHICS::REQUEST_SCALEFORM_MOVIE("MULTIPLAYER_CHAT");
while (!GRAPHICS::HAS_SCALEFORM_MOVIE_LOADED(scaleform))
script::get_current()->yield();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "ADD_MESSAGE");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player name
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_LITERAL_STRING(msg); // content
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_TEXTURE_NAME_STRING(HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(is_team ? "MP_CHAT_TEAM" : "MP_CHAT_ALL")); // scope
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(false); // teamOnly
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "SET_FOCUS");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(1); // VISIBLE_STATE_DEFAULT
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scopeType (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scope (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::DRAW_SCALEFORM_MOVIE_FULLSCREEN(scaleform, 255, 255, 255, 255, 0);
// fix broken scaleforms, when chat alrdy opened
if (const auto chat_data = *g_pointers->m_gta.m_chat_data; chat_data && (chat_data->m_chat_open || chat_data->m_timer_two))
HUD::CLOSE_MP_TEXT_CHAT();
}
inline bool is_on_same_team(CNetGamePlayer* player)
{
auto target_id = player->m_player_id;
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
{
// mission
return PLAYER::GET_PLAYER_TEAM(target_id) == PLAYER::GET_PLAYER_TEAM(self::id);
}
else
{
auto boss_goon = &scr_globals::gpbd_fm_3.as<GPBD_FM_3*>()->Entries[self::id].BossGoon;
if (boss_goon->Boss == target_id)
return true;
if (boss_goon->Boss == -1)
return false;
if (boss_goon->Boss != self::id)
boss_goon = &scr_globals::gpbd_fm_3.as<GPBD_FM_3*>()->Entries[boss_goon->Boss].BossGoon; // get their structure
// bypass some P2Cs
for (int i = 0; i < boss_goon->Goons.Size; i++)
{
if (boss_goon->Goons[i] == target_id)
{
return true;
}
}
return false;
}
}
// set target to send to a specific player
inline void send_message(const std::string& message, player_ptr target = nullptr, bool draw = true, bool is_team = false)
{
if (!*g_pointers->m_gta.m_is_session_started)
return;
packet msg{};
msg.write_message(rage::eNetMessage::MsgTextMessage);
msg.m_buffer.WriteString(message.c_str(), 256);
gamer_handle_serialize(g_player_service->get_self()->get_net_data()->m_gamer_handle, msg.m_buffer);
msg.write<bool>(is_team, 1);
for (auto& player : g_player_service->players())
{
if (player.second && player.second->is_valid())
{
if (target && player.second != target)
continue;
if (!target && is_team && !is_on_same_team(player.second->get_net_game_player()))
continue;
msg.send(player.second->get_net_game_player()->m_msg_id);
}
}
if (draw)
if (rage::tlsContext::get()->m_is_script_thread_active)
draw_chat(message.c_str(), g_player_service->get_self()->get_name(), is_team);
else
g_fiber_pool->queue_job([message, target, is_team] {
draw_chat(message.c_str(), g_player_service->get_self()->get_name(), is_team);
});
}
}

View File

@ -26,7 +26,10 @@ namespace big::entity
void delete_entity(Entity& ent, bool force)
{
if (!ENTITY::DOES_ENTITY_EXIST(ent))
{
ent = NULL;
return;
}
if (!force && !take_control_of(ent))
{
LOG(VERBOSE) << "Failed to take control of entity before deleting";

View File

@ -142,7 +142,7 @@ namespace big::mobile
inline void summon_vehicle_by_index(int veh_idx)
{
if (*scr_globals::freemode_global.at(985).as<int*>() != -1)
return g_notification_service->push_warning("Vehicle", "Mechanic is not ready to deliver a vehicle right now.");
return g_notification_service.push_warning("Vehicle", "Mechanic is not ready to deliver a vehicle right now.");
if (g.clone_pv.spawn_inside && self::veh)
TASK::CLEAR_PED_TASKS_IMMEDIATELY(PLAYER::PLAYER_PED_ID());
@ -208,10 +208,10 @@ namespace big::mobile
{
*scr_globals::gun_van.as<Vector3*>() = spawn_point;
return g_notification_service->push_success("GUI_TAB_MOBILE"_T.data(), "REQUEST_GUN_VAN_NOTIFY_SUCCESS"_T.data());
return g_notification_service.push_success("GUI_TAB_MOBILE"_T.data(), "REQUEST_GUN_VAN_NOTIFY_SUCCESS"_T.data());
}
g_notification_service->push_warning("GUI_TAB_MOBILE"_T.data(), "REQUEST_GUN_VAN_NOTIFY_FAILED"_T.data());
g_notification_service.push_warning("GUI_TAB_MOBILE"_T.data(), "REQUEST_GUN_VAN_NOTIFY_FAILED"_T.data());
}
}
}

86
src/util/notify.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "notify.hpp"
#include "chat.hpp"
#include "fiber_pool.hpp"
#include "gta/enums.hpp"
#include "hooking/hooking.hpp"
#include "natives.hpp"
#include "network/CNetGamePlayer.hpp"
#include "network/ChatData.hpp"
#include "pointers.hpp"
#include "script.hpp"
#include "services/players/player_service.hpp"
namespace big::notify
{
void above_map(std::string_view text)
{
HUD::SET_TEXT_OUTLINE();
HUD::BEGIN_TEXT_COMMAND_THEFEED_POST("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_THEFEED_POST_TICKER(false, false);
}
void crash_blocked(CNetGamePlayer* player, const char* crash)
{
if (player)
{
if ((g_player_service->get_by_id(player->m_player_id)->is_friend() && g.session.trust_friends)
|| g_player_service->get_by_id(player->m_player_id)->is_trusted || g.session.trust_session)
return;
if (g.reactions.crash.notify)
g_notification_service.push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name()));
if (g.reactions.crash.log)
LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " ("
<< (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")";
if (g.reactions.crash.announce_in_chat)
{
auto msg = std::vformat("NOTIFICATION_CRASH_TYPE_BLOCKED"_T, std::make_format_args(player->get_name(), crash));
msg = std::format("{} {}", g.session.chat_output_prefix, msg);
chat::send_message(msg);
}
g.reactions.crash.process_common(g_player_service->get_by_id(player->m_player_id));
}
else
{
if (g.reactions.crash.notify)
g_notification_service.push_error("Protections", std::format("Blocked {} crash from unknown player", crash));
}
}
// Shows a busy spinner till the value at the address equals the value passed or if timeout is hit
void busy_spinner(std::string_view text, int* address, int value, int timeout)
{
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(3);
for (size_t i = 0; *address != value && i < (size_t)timeout * 100; i++)
script::get_current()->yield(10ms);
HUD::BUSYSPINNER_OFF();
}
void show_subtitle(std::string_view text, int ms)
{
HUD::BEGIN_TEXT_COMMAND_PRINT("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_PRINT(ms, 1);
}
void display_help_text(std::string_view text)
{
HUD::BEGIN_TEXT_COMMAND_DISPLAY_HELP("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_DISPLAY_HELP(0, 0, 1, -1);
}
void player_joined(CNetGamePlayer* net_game_player)
{
above_map(std::format("<C>{}</C> joined.", net_game_player->get_name()));
}
}

View File

@ -8,118 +8,22 @@
#include "services/players/player_service.hpp"
#include "fiber_pool.hpp"
#include "hooking/hooking.hpp"
#include "chat.hpp"
#include <script/HudColor.hpp>
namespace big::notify
{
inline void above_map(std::string_view text)
{
HUD::SET_TEXT_OUTLINE();
HUD::BEGIN_TEXT_COMMAND_THEFEED_POST("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_THEFEED_POST_TICKER(false, false);
}
void above_map(std::string_view text);
inline void draw_chat(const char* msg, const char* player_name, bool is_team)
{
int scaleform = GRAPHICS::REQUEST_SCALEFORM_MOVIE("MULTIPLAYER_CHAT");
while (!GRAPHICS::HAS_SCALEFORM_MOVIE_LOADED(scaleform))
script::get_current()->yield();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "ADD_MESSAGE");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player name
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_LITERAL_STRING(msg); // content
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_TEXTURE_NAME_STRING(HUD::GET_FILENAME_FOR_AUDIO_CONVERSATION(is_team ? "MP_CHAT_TEAM" : "MP_CHAT_ALL")); // scope
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(false); // teamOnly
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(scaleform, "SET_FOCUS");
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(1); // VISIBLE_STATE_DEFAULT
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scopeType (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0); // scope (unused)
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_PLAYER_NAME_STRING(player_name); // player
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT((int)HudColor::HUD_COLOUR_PURE_WHITE); // eHudColour
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
GRAPHICS::DRAW_SCALEFORM_MOVIE_FULLSCREEN(scaleform, 255, 255, 255, 255, 0);
// fix broken scaleforms, when chat alrdy opened
if (const auto chat_data = *g_pointers->m_gta.m_chat_data; chat_data && (chat_data->m_chat_open || chat_data->m_timer_two))
HUD::CLOSE_MP_TEXT_CHAT();
}
inline void crash_blocked(CNetGamePlayer* player, const char* crash)
{
if (player)
{
if ((g_player_service->get_by_id(player->m_player_id)->is_friend() && g.session.trust_friends)
|| g_player_service->get_by_id(player->m_player_id)->is_trusted
|| g.session.trust_session)
return;
if (g.reactions.crash.notify)
g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name()));
if (g.reactions.crash.log)
LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " ("
<< (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")";
if (g.reactions.crash.announce_in_chat)
{
g_fiber_pool->queue_job([player, crash] {
auto chat = std::vformat("NOTIFICATION_CRASH_TYPE_BLOCKED"_T, std::make_format_args(player->get_name(), crash));
chat = std::format("{} {}", g.session.chat_output_prefix, chat);
if (g_hooking->get_original<hooks::send_chat_message>()(*g_pointers->m_gta.m_send_chat_ptr,
g_player_service->get_self()->get_net_data(),
chat.data(),
g.reactions.crash.is_team_only))
draw_chat(chat.c_str(), g_player_service->get_self()->get_name(), g.reactions.crash.is_team_only);
});
}
g.reactions.crash.process_common(g_player_service->get_by_id(player->m_player_id));
}
else
{
if (g.reactions.crash.notify)
g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash));
}
}
void crash_blocked(CNetGamePlayer* player, const char* crash);
// Shows a busy spinner till the value at the address equals the value passed or if timeout is hit
inline void busy_spinner(std::string_view text, int* address, int value, int timeout = 15)
{
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_BUSYSPINNER_ON(3);
void busy_spinner(std::string_view text, int* address, int value, int timeout = 15);
for (size_t i = 0; *address != value && i < (size_t)timeout * 100; i++)
script::get_current()->yield(10ms);
void show_subtitle(std::string_view text, int ms = 2000);
HUD::BUSYSPINNER_OFF();
}
void display_help_text(std::string_view text);
inline void show_subtitle(std::string_view text, int ms = 2000)
{
HUD::BEGIN_TEXT_COMMAND_PRINT("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_PRINT(ms, 1);
}
inline void display_help_text(std::string_view text)
{
HUD::BEGIN_TEXT_COMMAND_DISPLAY_HELP("STRING");
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(text.data());
HUD::END_TEXT_COMMAND_DISPLAY_HELP(0, 0, 1, -1);
}
inline void player_joined(CNetGamePlayer* net_game_player)
{
above_map(std::format("<C>{}</C> joined.", net_game_player->get_name()));
}
}
void player_joined(CNetGamePlayer* net_game_player);
}

View File

@ -4,7 +4,7 @@
namespace big::protection
{
constexpr auto crash_objects = {"prop_dummy_01"_J, "prop_dummy_car"_J, "prop_dummy_light"_J, "prop_dummy_plane"_J, "prop_distantcar_night"_J, "prop_distantcar_day"_J, "hei_bh1_08_details4_em_night"_J, "dt1_18_sq_night_slod"_J, "ss1_12_night_slod"_J, "hash_b334b5e2_qyquzxq_collision"_J, "h4_prop_bush_bgnvla_med_01"_J, "h4_prop_bush_bgnvla_lrg_01"_J, "h4_prop_bush_buddleia_low_01"_J, "h4_prop_bush_ear_aa"_J, "h4_prop_bush_ear_ab"_J, "h4_prop_bush_fern_low_01"_J, "h4_prop_bush_fern_tall_cc"_J, "h4_prop_bush_mang_ad"_J, "h4_prop_bush_mang_low_aa"_J, "h4_prop_bush_mang_low_ab"_J, "h4_prop_bush_seagrape_low_01"_J, "prop_h4_ground_cover"_J, "h4_prop_weed_groundcover_01"_J, "h4_prop_grass_med_01"_J, "h4_prop_grass_tropical_lush_01"_J, "h4_prop_grass_wiregrass_01"_J, "h4_prop_weed_01_plant"_J, "h4_prop_weed_01_row"_J, "urbanweeds02_l1"_J, "proc_forest_grass01"_J, "prop_small_bushyba"_J, "v_res_d_dildo_a"_J, "v_res_d_dildo_b"_J, "v_res_d_dildo_c"_J, "v_res_d_dildo_d"_J, "v_res_d_dildo_e"_J, "v_res_d_dildo_f"_J, "v_res_skateboard"_J, "prop_battery_01"_J, "prop_barbell_01"_J, "prop_barbell_02"_J, "prop_bandsaw_01"_J, "prop_bbq_3"_J, "v_med_curtainsnewcloth2"_J, "bh1_07_flagpoles"_J, "hash_058a7eb5_deihiws_collision"_J, "proc_dry_plants_01"_J, "proc_leafyplant_01"_J, "proc_grassplantmix_02"_J, "proc_dryplantsgrass_01"_J, "proc_dryplantsgrass_02"_J, "proc_dryplantsgrass_02"_J, "proc_grasses01"_J, "prop_dryweed_002_a"_J, "prop_fernba"_J, "prop_weed_001_aa"_J, "urbangrnfrnds_01"_J, "urbanweeds01"_J, "prop_dandy_b"_J, "v_proc2_temp"_J, "prop_fernbb"_J, "proc_drygrassfronds01"_J, "prop_log_ae"_J, "prop_grass_da"_J, "prop_fragtest_cnst_04"_J};
constexpr auto crash_objects = {"prop_facgate_05_r_dam_l1"_J, "v_61_lng_mesh_unita_swap"_J, "prop_crt_mon_02"_J, "xs_prop_arena_pit_fire_01a_wl"_J, "prop_billboard_07"_J, "prop_recyclebin_02_d"_J, "prop_billboard_14"_J, "v_res_fa_book02"_J, "sf_int1_dropdownlight041"_J, "w_sg_pumpshotgunmk2_camo6"_J, "ch_prop_cash_low_trolly_01b"_J, "prop_ld_headset_01"_J, "sf_int1_office_wpaper_6"_J, "v_74_it3_ceiling_smoke_01_skin"_J, "prop_sh_tt_fridgedoor"_J, "ch_prop_arcade_race_02a"_J, "v_61_kit_over_dec_cruma"_J, "gr_prop_gr_rsply_crate01a"_J, "prop_snow_streetlight_01_frag_"_J, "v_34_sm_proc"_J, "tr_int1_lightcap_proxy001"_J, "v_ilev_tort_door"_J, "ch_prop_arcade_street_01b"_J, "prop_ic_repair_p"_J, "sf_int2_elevator_details_02"_J, "prop_cs4_05_tdoor"_J, "vfx_it1_02"_J, "cloudhat_wispy_b"_J, "hei_p_pre_heist_trash"_J, "v_ilev_trev_patiodoor"_J, "prop_bin_10a"_J, "sm_prop_offchair_smug_01"_J, "stt_prop_stunt_tube_fn_02"_J, "m23_2_prop_m32_hat_captain_01a"_J, "vw_prop_vw_arcade_04d_screen"_J, "prop_food_juice02"_J, "m23_2_prop_m32_mazebankcard_01a"_J, "v_28_alrm_case011"_J, "apa_mp_h_acc_pot_pouri_01"_J, "xm3_prop_xm3_crate_ammo_01a"_J, "prop_blackjack_01"_J, "prop_cs_mini_tv"_J, "v_res_fa_basket"_J, "prop_plant_int_02b"_J, "prop_umpire_01"_J, "gr_prop_gr_fnclink_03g"_J, "prop_rub_tyre_dam3"_J, "ba_prop_battle_lights_support"_J, "prop_fnclink_09a"_J, "ba_prop_battle_dj_mixer_01e"_J, "ar_prop_ar_neon_gate8x_04a"_J, "xs_propintarena_structure_f_03b"_J, "des_plog_door_end"_J, "v_ret_fh_chair01"_J, "gr_prop_gr_offchair_01a"_J, "hei_p_pre_heist_coke"_J, "cloudhat_puff_b"_J, "v_ind_cfbucket"_J, "p_hw1_22_doors_s"_J, "arbitergt"_J, "slod_human"_J, "prop_dummy_01"_J, "prop_dummy_car"_J, "prop_dummy_light"_J, "prop_dummy_plane"_J, "prop_distantcar_night"_J, "prop_distantcar_day"_J, "hei_bh1_08_details4_em_night"_J, "dt1_18_sq_night_slod"_J, "ss1_12_night_slod"_J, "hash_b334b5e2_qyquzxq_collision"_J, "h4_prop_bush_bgnvla_med_01"_J, "h4_prop_bush_bgnvla_lrg_01"_J, "h4_prop_bush_buddleia_low_01"_J, "h4_prop_bush_ear_aa"_J, "h4_prop_bush_ear_ab"_J, "h4_prop_bush_fern_low_01"_J, "h4_prop_bush_fern_tall_cc"_J, "h4_prop_bush_mang_ad"_J, "h4_prop_bush_mang_low_aa"_J, "h4_prop_bush_mang_low_ab"_J, "h4_prop_bush_seagrape_low_01"_J, "prop_h4_ground_cover"_J, "h4_prop_weed_groundcover_01"_J, "h4_prop_grass_med_01"_J, "h4_prop_grass_tropical_lush_01"_J, "h4_prop_grass_wiregrass_01"_J, "h4_prop_weed_01_plant"_J, "h4_prop_weed_01_row"_J, "urbanweeds02_l1"_J, "proc_forest_grass01"_J, "prop_small_bushyba"_J, "v_res_d_dildo_a"_J, "v_res_d_dildo_b"_J, "v_res_d_dildo_c"_J, "v_res_d_dildo_d"_J, "v_res_d_dildo_e"_J, "v_res_d_dildo_f"_J, "v_res_skateboard"_J, "prop_battery_01"_J, "prop_barbell_01"_J, "prop_barbell_02"_J, "prop_bandsaw_01"_J, "prop_bbq_3"_J, "v_med_curtainsnewcloth2"_J, "bh1_07_flagpoles"_J, "hash_058a7eb5_deihiws_collision"_J, "proc_dry_plants_01"_J, "proc_leafyplant_01"_J, "proc_grassplantmix_02"_J, "proc_dryplantsgrass_01"_J, "proc_dryplantsgrass_02"_J, "proc_dryplantsgrass_02"_J, "proc_grasses01"_J, "prop_dryweed_002_a"_J, "prop_fernba"_J, "prop_weed_001_aa"_J, "urbangrnfrnds_01"_J, "urbanweeds01"_J, "prop_dandy_b"_J, "v_proc2_temp"_J, "prop_fernbb"_J, "proc_drygrassfronds01"_J, "prop_log_ae"_J, "prop_grass_da"_J, "prop_fragtest_cnst_04"_J};
bool is_crash_object(rage::joaat_t model)
{
if (!model_info::get_model(model))

View File

@ -120,7 +120,7 @@ namespace big::scripts
if (!force_host("am_launcher"_J))
{
// 2F) Failed to force host of launcher
g_notification_service->push_error("Script", "Cannot force script host of am_launcher");
g_notification_service.push_error("Script", "Cannot force script host of am_launcher");
return;
}
@ -178,7 +178,7 @@ namespace big::scripts
else
{
// 1F) Cannot find launcher
g_notification_service->push_error("Script", "Cannot start script, am_launcher not running locally");
g_notification_service.push_error("Script", "Cannot start script, am_launcher not running locally");
}
}
@ -216,13 +216,13 @@ namespace big::scripts
if (g.m_mission_creator_thread || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("creator"_J) != 0 || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("maintransition"_J) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() || CUTSCENE::IS_CUTSCENE_ACTIVE())
{
g_notification_service->push_warning("Creator", "Cannot start creator now");
g_notification_service.push_warning("Creator", "Cannot start creator now");
return;
}
if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(60500) == 0)
{
g_notification_service->push_warning("Creator", "No free stacks for MISSION stack size");
g_notification_service.push_warning("Creator", "No free stacks for MISSION stack size");
}

View File

@ -24,16 +24,6 @@
namespace big::session
{
static void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
buf.Write<uint8_t>(*reinterpret_cast<uint8_t*>(&hnd.m_platform), 8);
if (*reinterpret_cast<uint8_t*>(&hnd.m_platform) == 3)
{
buf.WriteInt64(*(int64_t*)&hnd.m_rockstar_id, 64);
buf.Write<uint8_t>(*reinterpret_cast<uint8_t*>(reinterpret_cast<__int64>(&hnd) + 9), 8);
}
}
inline bool join_type(eSessionType session)
{
SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("pausemenu_multiplayer"_J);
@ -100,7 +90,7 @@ namespace big::session
{
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("maintransition"_J) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS())
{
g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit.");
g_notification_service.push_error("RID Joiner", "Player switch in progress, wait a bit.");
return;
}
@ -110,7 +100,7 @@ namespace big::session
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("maintransition"_J) == 0)
{
g.session.join_queued = false;
g_notification_service->push_error("RID Joiner", "Unable to launch maintransition");
g_notification_service.push_error("RID Joiner", "Unable to launch maintransition");
}
return;
}
@ -119,7 +109,7 @@ namespace big::session
{
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("maintransition"_J) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS())
{
g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit.");
g_notification_service.push_error("RID Joiner", "Player switch in progress, wait a bit.");
return;
}
@ -140,7 +130,7 @@ namespace big::session
}
}
g_notification_service->push_error("RID Joiner", "Target player is offline?");
g_notification_service.push_error("RID Joiner", "Target player is offline?");
}
inline void join_by_username(std::string username)
@ -154,7 +144,7 @@ namespace big::session
});
return;
}
g_notification_service->push_error("RID Joiner", "Target player is offline?");
g_notification_service.push_error("RID Joiner", "Target player is offline?");
});
}
@ -165,9 +155,9 @@ namespace big::session
bool success = g_pointers->m_gta.m_invite_player_by_gamer_handle(g_pointers->m_gta.m_network_config, &player_handle, 1, 0, 0, 0);
if (!success)
return g_notification_service->push_error("Network", "Target player could not be invited, they might be offline?");
return g_notification_service.push_error("Network", "Target player could not be invited, they might be offline?");
g_notification_service->push_success("Network", "Target player has been invited to your session!");
g_notification_service.push_success("Network", "Target player has been invited to your session!");
}
inline void show_profile_by_rockstar_id(uint64_t rid)

View File

@ -1,128 +0,0 @@
#pragma once
#include "file_manager/file.hpp"
#include "services/players/player_service.hpp"
#include "core/enums.hpp"
namespace
{
static const char* spam_texts[] = {
"qq", //a chinese chat app
"QQ",
"WWW.",
"www.",
".cn",
".CN",
".cc",
".CC",
".TOP",
".COM",
".top",
"\xE3\x80\x90", //left bracket in Chinese input method
"/Menu",
"Money/",
"Money\\\\",
"Money\\",
".gg",
"--->",
"shopgta5",
"doit#",
"krutka#",
"<b>",
"P888",
"gtacash",
"\xE6\x89\xA3\xE6\x89\xA3", // no clue what this is
"\xE5\xBE\xAE\xE4\xBF\xA1", // "wechat" in Chinese
".cc",
"<font s",
"sellix.io",
"ezcars",
"PLANO INICIAL", // "initial plan"
"REP +",
"20R$", // Brazil currency?
"l55.me",
"\xE5\xBA\x97", //"shop" in Chinese
"\xE9\x92\xB1", //"money" in Chinese
"\xE5\x88\xB7", //"make(money)" in Chinese
"\xE8\x90\x9D\xE8\x8E\x89", // "cute girl" in Chinese
"\xE5\xA6\x88", // "mother" in Chinese
"\xE7\xBE\x8E\xE5\xA5\xB3", // "sexy girl" in Chinese
"\xE5\xBC\xBA\xE5\xA5\xB8", // "rape" in Chinese
"\xE8\x90\x9D", // "loli" in Chinese
"\xE6\x8C\x82", // "hack" in Chinese
"\xE5\x85\x83", // chinese dollar
"\xE9\x98\xB4\xE4\xBC\xA0\xE5\xAA\x92", // "Yin Media" in Chinese
"\xE7\xBD\x91\xE7\xBA\xA2", // "internet celebrities" in Chinese
"TRUSTPILOT",
"cashlounge",
"Fast Delivery",
"yosativa",
"rich2day",
"LevelLifters",
". com",
"$1,000,000,000",
"Instant Delivery",
"0 Ban Risk",
"Discord For Cheap Money",
"10-30m",
"Discord todo",
};
}
namespace big::spam
{
inline SpamReason is_text_spam(const char* text, player_ptr player)
{
if (g.session.use_spam_timer)
{
if (player->last_message_time.has_value())
{
auto currentTime = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::seconds>(currentTime - player->last_message_time.value());
player->last_message_time.emplace(currentTime);
if (strlen(text) > g.session.spam_length && diff.count() <= g.session.spam_timer)
return SpamReason::TIMER_DETECTION;
}
else
{
player->last_message_time.emplace(std::chrono::steady_clock::now());
}
}
for (auto e : spam_texts)
if (strstr(text, e) != 0)
return SpamReason::STATIC_DETECTION;
return SpamReason::NOT_A_SPAMMER;
}
inline void log_chat(char* msg, player_ptr player, SpamReason spam_reason, bool is_team)
{
std::ofstream log(g_file_manager.get_project_file(spam_reason != SpamReason::NOT_A_SPAMMER ? "./spam.log" : "./chat.log").get_path(), std::ios::app);
auto& data = *player->get_net_data();
auto ip = player->get_ip_address();
auto now = std::chrono::system_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
auto timer = std::chrono::system_clock::to_time_t(now);
auto local_time = *std::localtime(&timer);
std::string spam_reason_str = "";
switch (spam_reason)
{
case SpamReason::STATIC_DETECTION: spam_reason_str = "(Static Detection) "; break;
case SpamReason::TIMER_DETECTION: spam_reason_str = "(Timer Detection) "; break;
}
log << spam_reason_str << "[" << std::put_time(&local_time, "%m/%d/%Y %I:%M:%S") << ":" << std::setfill('0') << std::setw(3) << ms.count() << " " << std::put_time(&local_time, "%p") << "] ";
if (ip)
log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") <" << (int)ip.value().m_field1 << "."
<< (int)ip.value().m_field2 << "." << (int)ip.value().m_field3 << "." << (int)ip.value().m_field4 << "> " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl;
else
log << player->get_name() << " (" << data.m_gamer_handle.m_rockstar_id << ") <UNKNOWN> " << ((is_team == true) ? "[TEAM]: " : "[ALL]: ") << msg << std::endl;
log.close();
}
}

View File

@ -48,7 +48,7 @@ namespace big::teleport
if (ENTITY::IS_ENTITY_DEAD(ent, true))
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_PLAYER_IS_DEAD"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_PLAYER_IS_DEAD"_T.data());
return false;
}
@ -66,7 +66,7 @@ namespace big::teleport
}
else
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data());
}
return true;
@ -131,7 +131,7 @@ namespace big::teleport
{
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh))
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_INVALID_VEHICLE"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_INVALID_VEHICLE"_T.data());
return false;
}
@ -144,7 +144,7 @@ namespace big::teleport
if (seat_index == 255)
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_NO_SEATS_FREE"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_NO_SEATS_FREE"_T.data());
return false;
}
@ -196,7 +196,7 @@ namespace big::teleport
{
if (!to_blip((int)BlipIcons::Waypoint))
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_NO_WAYPOINT_SET"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_NO_WAYPOINT_SET"_T.data());
return false;
}
@ -209,7 +209,7 @@ namespace big::teleport
if (!blip::get_objective_location(location))
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_NO_OBJECTIVE"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_NO_OBJECTIVE"_T.data());
return false;
}
@ -222,14 +222,14 @@ namespace big::teleport
{
if (!*g_pointers->m_gta.m_is_session_started)
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_NOT_ONLINE"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_NOT_ONLINE"_T.data());
return false;
}
auto blip = blip::get_selected_blip();
if (blip == nullptr)
{
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_NOTHING_SELECTED"_T.data());
g_notification_service.push_warning("TELEPORT"_T.data(), "TELEPORT_NOTHING_SELECTED"_T.data());
return false;
}
Entity entity = self::ped;

View File

@ -55,13 +55,13 @@ namespace big::toxic
{
if (!g_player_service->get_self()->is_host())
{
g_notification_service->push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_HOST_REQUIRED"_T.data());
g_notification_service.push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_HOST_REQUIRED"_T.data());
return false;
}
if (!target->player_time_value.has_value())
{
g_notification_service->push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_NO_PLAYER_TIMESTAMP"_T.data());
g_notification_service.push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_NO_PLAYER_TIMESTAMP"_T.data());
return false;
}
@ -98,7 +98,7 @@ namespace big::toxic
{
if (!target->player_time_value.has_value())
{
g_notification_service->push_error("WARP_TIME_TITLE"_T.data(), "MODIFY_TIME_NO_PLAYER_TIMESTAMP"_T.data());
g_notification_service.push_error("WARP_TIME_TITLE"_T.data(), "MODIFY_TIME_NO_PLAYER_TIMESTAMP"_T.data());
return;
}
@ -114,7 +114,7 @@ namespace big::toxic
{
if (!g_player_service->get_self()->is_host())
{
g_notification_service->push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_HOST_REQUIRED"_T.data());
g_notification_service.push_error("MODIFY_TIME"_T.data(), "MODIFY_TIME_HOST_REQUIRED"_T.data());
return;
}
@ -167,4 +167,4 @@ namespace big::toxic
{
set_time_all((*g_pointers->m_gta.m_network_time)->m_time + millis);
}
}
}

View File

@ -28,11 +28,11 @@ namespace big::train
TASK::CLEAR_PED_TASKS_IMMEDIATELY(ped);
PED::SET_PED_INTO_VEHICLE(PLAYER::PLAYER_PED_ID(), train, -1);
g_notification_service->push_success("HIJACK_TRAIN"_T.data(), "HIJACK_TRAIN_FOUND_TRAIN"_T.data());
g_notification_service.push_success("HIJACK_TRAIN"_T.data(), "HIJACK_TRAIN_FOUND_TRAIN"_T.data());
}
else
{
g_notification_service->push_warning("HIJACK_TRAIN"_T.data(), "Cannot find any trains nearby");
g_notification_service.push_warning("HIJACK_TRAIN"_T.data(), "Cannot find any trains nearby");
}
}
@ -44,7 +44,7 @@ namespace big::train
}
else
{
g_notification_service->push_warning("HIJACK_TRAIN"_T.data(), "Cannot find any trains nearby");
g_notification_service.push_warning("HIJACK_TRAIN"_T.data(), "Cannot find any trains nearby");
}
}

View File

@ -56,13 +56,13 @@ namespace big::vehicle
void bring(Vehicle veh, Vector3 location, bool put_in, int seatIdx)
{
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh))
return g_notification_service->push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data());
return g_notification_service.push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data());
auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true);
entity::load_ground_at_3dcoord(vecVehicleLocation);
if (!entity::take_control_of(veh))
return g_notification_service->push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
return g_notification_service.push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
auto ped = self::ped;
ENTITY::SET_ENTITY_COORDS(veh, location.x, location.y, location.z + 1.f, 0, 0, 0, 0);
@ -354,9 +354,9 @@ namespace big::vehicle
}
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked)
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked, bool is_script_vehicle)
{
auto vehicle = spawn(owned_mods[MOD_MODEL_HASH], location, heading, is_networked);
auto vehicle = spawn(owned_mods[MOD_MODEL_HASH], location, heading, is_networked, is_script_vehicle);
if (vehicle == 0)
{
return 0;
@ -371,12 +371,12 @@ namespace big::vehicle
}
VEHICLE::SET_VEHICLE_MOD_KIT(vehicle, 0);
script::get_current()->yield(10ms);
//script::get_current()->yield(10ms);
VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(vehicle, owned_mods[MOD_PLATE_STYLE]);
VEHICLE::SET_VEHICLE_WINDOW_TINT(vehicle, owned_mods[MOD_WINDOW_TINT]);
VEHICLE::SET_VEHICLE_WHEEL_TYPE(vehicle, owned_mods[MOD_WHEEL_TYPE]);
script::get_current()->yield(10ms);
//script::get_current()->yield(10ms);
VEHICLE::SET_VEHICLE_COLOURS(vehicle, owned_mods[MOD_PRIMARY_COL], owned_mods[MOD_SECONDARY_COL]);
VEHICLE::SET_VEHICLE_EXTRA_COLOURS(vehicle, owned_mods[MOD_PEARLESCENT_COL], owned_mods[MOD_WHEEL_COL]);
@ -605,7 +605,7 @@ namespace big::vehicle
if (current_vehicle)
VEHICLE::SET_VEHICLE_ENGINE_ON(current_vehicle, state, immediately, disable_auto_start);
else
return g_notification_service->push_warning("VEHICLE"_T.data(), "PLEASE_ENTER_VEHICLE"_T.data());
return g_notification_service.push_warning("VEHICLE"_T.data(), "PLEASE_ENTER_VEHICLE"_T.data());
}
void downgrade(Vehicle vehicle)
@ -621,7 +621,7 @@ namespace big::vehicle
{
if (!entity::take_control_of(veh, 4000))
{
g_notification_service->push_warning("REMOTE_CONTROL"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
g_notification_service.push_warning("REMOTE_CONTROL"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
return false;
}

View File

@ -29,7 +29,7 @@ namespace big::vehicle
Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked = true, bool script_veh = false);
Vehicle clone_from_vehicle_data(std::map<int, int32_t>& data, Vector3 location, float heading);
std::map<int, int32_t> get_owned_mods_from_vehicle_idx(script_global vehicle_idx);
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked = true);
Vehicle clone_from_owned_mods(std::map<int, int32_t> owned_mods, Vector3 location, float heading, bool is_networked = true, bool is_script_vehicle = false);
std::map<int, int32_t> get_owned_mods_from_vehicle(Vehicle vehicle);
void teleport_into_vehicle(Vehicle veh);
void max_vehicle(Vehicle veh);

Some files were not shown because too many files have changed in this diff Show More