diff --git a/Client/game_sa/CPedSA.cpp b/Client/game_sa/CPedSA.cpp index 79c00d37fff..b6541d7e71d 100644 --- a/Client/game_sa/CPedSA.cpp +++ b/Client/game_sa/CPedSA.cpp @@ -1120,3 +1120,9 @@ void CPedSA::GetAttachedSatchels(std::vector& satchelsList) const satchelsList.push_back({pProjectileInterface, &pProjectileInterface->m_vecAttachedOffset, &pProjectileInterface->m_vecAttachedRotation}); } } + +void CPedSA::Say(const ePedSpeechContext& speechId, float probability) +{ + // Call CPed::Say + ((void(__thiscall*)(CPedSAInterface*, ePedSpeechContext, int, float, bool, bool, bool))FUNC_CPed_Say)(GetPedInterface(), speechId, 0, probability, false, false, false); +} diff --git a/Client/game_sa/CPedSA.h b/Client/game_sa/CPedSA.h index 110fabea960..201cb494ac5 100644 --- a/Client/game_sa/CPedSA.h +++ b/Client/game_sa/CPedSA.h @@ -59,6 +59,7 @@ class CPedIntelligenceSAInterface; #define FUNC_DetachPedFromEntity 0x5E7EC0 #define FUNC_CPed_RemoveBodyPart 0x5f0140 #define FUNC_PreRenderAfterTest 0x5E65A0 +#define FUNC_CPed_Say 0x5EFFE0 #define VAR_LocalPlayer 0x94AD28 @@ -419,4 +420,6 @@ class CPedSA : public virtual CPed, public virtual CPhysicalSA ePedState GetPedState() { return GetPedInterface()->pedState; } void GetAttachedSatchels(std::vector &satchelsList) const override; + + void Say(const ePedSpeechContext& speechId, float probability) override; }; diff --git a/Client/mods/deathmatch/logic/CClientPed.cpp b/Client/mods/deathmatch/logic/CClientPed.cpp index 85c5e0d51e7..a7d7c7694a8 100644 --- a/Client/mods/deathmatch/logic/CClientPed.cpp +++ b/Client/mods/deathmatch/logic/CClientPed.cpp @@ -5272,6 +5272,14 @@ void CClientPed::Respawn(CVector* pvecPosition, bool bRestoreState, bool bCamera } } +void CClientPed::Say(const ePedSpeechContext& speechId, float probability) +{ + if (!m_pPlayerPed) + return; + + m_pPlayerPed->Say(speechId, probability); +} + const char* CClientPed::GetBodyPartName(unsigned char ucID) { if (ucID <= 10) diff --git a/Client/mods/deathmatch/logic/CClientPed.h b/Client/mods/deathmatch/logic/CClientPed.h index 65d84a0a4a6..6f2ba652fb4 100644 --- a/Client/mods/deathmatch/logic/CClientPed.h +++ b/Client/mods/deathmatch/logic/CClientPed.h @@ -598,6 +598,8 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void Respawn(CVector* pvecPosition = NULL, bool bRestoreState = false, bool bCameraCut = false); + void Say(const ePedSpeechContext& speechId, float probability = 1.0f); + void SetTaskToBeRestoredOnAnimEnd(bool bSetOnEnd) noexcept { m_bTaskToBeRestoredOnAnimEnd = bSetOnEnd; } bool IsTaskToBeRestoredOnAnimEnd() const noexcept { return m_bTaskToBeRestoredOnAnimEnd; } void SetTaskTypeToBeRestoredOnAnimEnd(eTaskType taskType) noexcept { m_eTaskTypeToBeRestoredOnAnimEnd = taskType; } diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp index 87cd379ea5d..9c1ce9981c7 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.cpp @@ -15,6 +15,7 @@ #include #include #include +#include "CLuaPedDefs.h" #define MIN_CLIENT_REQ_REMOVEPEDFROMVEHICLE_CLIENTSIDE "1.3.0-9.04482" #define MIN_CLIENT_REQ_WARPPEDINTOVEHICLE_CLIENTSIDE "1.3.0-9.04482" @@ -61,6 +62,7 @@ void CLuaPedDefs::LoadFunctions() {"setPedEnterVehicle", ArgumentParser}, {"setPedExitVehicle", ArgumentParser}, {"setPedBleeding", ArgumentParser}, + {"playPedVoiceLine", ArgumentParser}, {"getPedVoice", GetPedVoice}, {"getElementBonePosition", ArgumentParser}, @@ -210,6 +212,7 @@ void CLuaPedDefs::AddClass(lua_State* luaVM) lua_classfunction(luaVM, "setEnterVehicle", "setPedEnterVehicle"); lua_classfunction(luaVM, "setExitVehicle", "setPedExitVehicle"); lua_classfunction(luaVM, "setBleeding", "setPedBleeding"); + lua_classfunction(luaVM, "playPedVoiceLine", "playVoiceLine"); lua_classvariable(luaVM, "vehicle", OOP_WarpPedIntoVehicle, GetPedOccupiedVehicle); lua_classvariable(luaVM, "vehicleSeat", NULL, "getPedOccupiedVehicleSeat"); @@ -2497,3 +2500,15 @@ bool CLuaPedDefs::killPedTask(CClientPed* ped, taskType taskType, std::uint8_t t return false; } } + +void CLuaPedDefs::PlayPedVoiceLine(CClientPed* ped, int speechId, std::optional probabilty) +{ + auto speechContextId = static_cast(speechId); + if (speechContextId < ePedSpeechContext::NOTHING || speechContextId >= ePedSpeechContext::NUM_PED_CONTEXT) + throw LuaFunctionError("The argument speechId is invalid. The valid range is 0-359."); + + if (probabilty.has_value() && probabilty < 0.0f) + throw LuaFunctionError("The argument probabilty cannot have a negative value."); + + ped->Say(speechContextId, probabilty.value_or(1.0f)); +} diff --git a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h index 37169ddefb0..1b4881b0838 100644 --- a/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h +++ b/Client/mods/deathmatch/logic/luadefs/CLuaPedDefs.h @@ -118,4 +118,6 @@ class CLuaPedDefs : public CLuaDefs static bool SetPedBleeding(CClientPed* ped, bool bleeding); static bool killPedTask(CClientPed* ped, taskType taskType, std::uint8_t taskNumber, std::optional gracefully) noexcept; + + static void PlayPedVoiceLine(CClientPed* ped, int speechId, std::optional probabilty); }; diff --git a/Client/sdk/game/CPed.h b/Client/sdk/game/CPed.h index b67148c2c0b..03c81d64c71 100644 --- a/Client/sdk/game/CPed.h +++ b/Client/sdk/game/CPed.h @@ -15,6 +15,7 @@ #include "Common.h" #include "CPhysical.h" #include "CWeaponInfo.h" +#include "CPedSound.h" class CObject; class CPedIK; @@ -286,4 +287,6 @@ class CPed : public virtual CPhysical virtual ePedState GetPedState() = 0; virtual void GetAttachedSatchels(std::vector &satchelsList) const = 0; + + virtual void Say(const ePedSpeechContext& speechId, float probability) = 0; }; diff --git a/Client/sdk/game/CPedSound.h b/Client/sdk/game/CPedSound.h index a9520189db6..ead8605fa96 100644 --- a/Client/sdk/game/CPedSound.h +++ b/Client/sdk/game/CPedSound.h @@ -1,11 +1,11 @@ /***************************************************************************** * - * PROJECT: Multi Theft Auto v1.0 + * PROJECT: Multi Theft Auto * LICENSE: See LICENSE in the top level directory - * FILE: game_sa/CPedSound.h + * FILE: sdk/game/CPedSound.h * PURPOSE: Header file for ped sound interface * - * Multi Theft Auto is available from http://www.multitheftauto.com/ + * Multi Theft Auto is available from https://www.multitheftauto.com/ * *****************************************************************************/ @@ -13,6 +13,381 @@ class CPedSoundSAInterface; +enum class ePedSpeechContext +{ + NOTHING = 0, + ABUSE_GANG_BALLAS, + ABUSE_GANG_LSV, + ABUSE_GANG_VLA, + ABUSE_GANG_FAMILIES, + ABUSE_TRIAD, + ABUSE_MAFIA, + ABUSE_RIFA, + ABUSE_DA_WANG, + ACCEPT_DATE_CALL, + ACCEPT_DATE_REQUEST, + AFTER_SEX, + APOLOGY, + ARREST, + ARREST_CRIM, + ARRESTED, + ATTACK_BY_PLAYER, + ATTACK_GANG_BALLAS, + ATTACK_GANG_LSV, + ATTACK_GANG_VLA, + ATTACK_PLAYER, + BAR_CHAT, + BLOCKED, + BOOZE_RECEIVE, + BOOZE_REQUEST, + BUM_BACK_OFF, + BUM_BACK_OFF2, + BUM_LATCH, + BUMP, + CAR_CRASH, + CAR_DRIVEBY_BURN_RUBBER, + CAR_DRIVEBY_TOO_FAST, + CAR_FAST, + CAR_FIRE, + CAR_FLIPPED, + CAR_GET_IN, + CAR_HIT_PED, + CAR_JUMP, + CAR_POLICE_PURSUIT, + CAR_SLOW, + CAR_WAIT_FOR_ME, + CAR_SINGALONG, + CB_CHAT, + CHASE_FOOT, + CHASED, + CHAT, + COFFEE_ACCEPT, + COFFEE_DECLINE, + CONV_DISL_CAR, + CONV_DISL_CLOTHES, + CONV_DISL_HAIR, + CONV_DISL_PHYS, + CONV_DISL_SHOES, + CONV_DISL_SMELL, + CONV_DISL_TATTOO, + CONV_DISL_WEATHER, + CONV_IGNORED, + CONV_LIKE_CAR, + CONV_LIKE_CLOTHES, + CONV_LIKE_HAIR, + CONV_LIKE_PHYS, + CONV_LIKE_SHOES, + CONV_LIKE_SMELL, + CONV_LIKE_TATTOO, + CONV_LIKE_WEATHER, + COVER_ME, + CRASH_BIKE, + CRASH_CAR, + CRASH, + CRIMINAL_PLEAD, + DANCE_IMPR_HIGH, + DANCE_IMPR_MED, + DANCE_IMPR_LOW, + DANCE_IMPR_NOT, + DODGE, + DRUG_AGGRESSIVE_HIGH, + DRUG_AGGRESSIVE_LOW, + DRUG_DEALER_DISLIKE, + DRUG_DEALER_HATE, + DRUG_REASONABLE_HIGH, + DRUG_REASONABLE_LOW, + DRUGGED_CHAT, + DRUGGED_IGNORE, + DRUGS_BUY, + DRUGS_SELL, + DUCK, + EYEING_PED, + EYEING_PED_THREAT, + EYEING_PLAYER, + FIGHT, + FOLLOW_ARRIVE, + FOLLOW_CONST, + FOLLOW_REPLY, + GAMB_BJ_HIT, + GAMB_BJ_LOSE, + GAMB_BJ_STAY, + GAMB_BJ_WIN, + GAMB_BJ_STICK, + GAMB_BJ_DOUBLE, + GAMB_BJ_SPLIT, + GAMB_CASINO_WIN, + GAMB_CASINO_LOSE, + GAMB_CONGRATS, + GAMB_ROUL_CHAT, + GAMB_SLOT_WIN, + GANG_FULL, + GANGBANG_NO, + GANGBANG_YES, + HI_MALE, + HI_FEMALE, + INSULT_MALE, + INSULT_FEMALE, + GIVING_HEAD, + GOOD_CITIZEN, + GUN_COOL, + GUN_RUN, + HAVING_SEX, + HAVING_SEX_MUFFLED, + JACKED_CAR, + JACKED, + JACKED_ON_STREET, + JACKING_BIKE, + JACKING_CAR_FEMALE, + JACKING_CAR_MALE, + JACKING, + JOIN_GANG_NO, + JOIN_GANG_YES, + JOIN_ME_ASK, + JOIN_ME_REJECTED, + LIKE_CAR_REPLY, + LIKE_CLOTHES_REPLY, + LIKE_DISMISS_FEMALE, + LIKE_DISMISS_MALE, + LIKE_DISMISS_REPLY, + LIKE_HAIR_REPLY, + LIKE_NEAGTIVE_FEMALE, + LIKE_NEGATIVE_MALE, + LIKE_PHYS_REPLY, + LIKE_SHOES_REPLY, + LIKE_SMELL_REPLY, + LIKE_TATTOO_REPLY, + MEET_GF_AGAIN_MAYBE, + MEET_GF_AGAIN_NO, + MEET_GF_AGAIN_YES, + MOVE_IN, + MUGGED, + MUGGING, + ORDER_ATTACK_MANY, + ORDER_ATTACK_SINGLE, + ORDER_DISBAND_MANY, + ORDER_DISBAND_SINGLE, + ORDER_FOLLOW_FAR_MANY, + ORDER_FOLLOW_FAR_SINGLE, + ORDER_FOLLOW_NEAR_MANY, + ORDER_FOLLOW_NEAR_SINGLE, + ORDER_FOLLOW_VNEAR_MANY, + ORDER_FOLLOW_VNEAR_SINGLE, + ORDER_KEEP_UP_MANY, + ORDER_KEEP_UP_SINGLE, + ORDER_WAIT_MANY, + ORDER_WAIT_SINGLE, + + CONV_AGREE_BAD, + CONV_AGREE_GOOD, + CONV_ANS_NO, + CONV_DISMISS, + CONV_GREET_FEMALE, + CONV_GREET_MALE, + CONV_PART_FEMALE, + CONV_PART_MALE, + CONV_QUESTION, + CONV_STATE_BAD, + CONV_STATE_GOOD, + + PICKUP_CASH, + POLICE_BOAT, + POLICE_HELI, + POLICE_OVERBOARD, + PULL_GUN, + ROPE, + RUN_FROM_FIGHT, + SAVED, + SEARCH, + SHOCKED, + SHOOT, + SHOOT_BALLAS, + SHOOT_GENERIC, + SHOOT_LSV, + SHOOT_VLA, + SHOOT_FAMILIES, + SHOP_BROWSE, + SHOP_BUY, + SHOP_SELL, + SHOP_LEAVE, + SOLICIT, + SOLICIT_GEN_NO, + SOLICIT_GEN_YES, + SOLICIT_PRO_NO, + SOLICIT_PRO_YES, + SOLICIT_THANKS, + SOLICIT_UNREASONBALE, + SOLO, + SPLIFF_RECEIVE, + SPLIFF_REQUEST, + STEALTH_ALERT_SOUND, + STEALTH_ALERT_SIGHT, + STEALTH_ALERT_GENERIC, + STEALTH_DEF_SIGHTING, + STEALTH_NOTHING, + SURROUNDED, + + TAKE_TUF_LAS_COLINAS, + TAKE_TURF_LOS_FLORES, + TAKE_TURF_EAST_BEACH, + TAKE_TURF_EAST_LS, + TAKE_TUF_JEFFERSON, + TAKE_TURF_GLEN_PARK, + TAKE_TURF_IDLEWOOD, + TAKE_TURF_GANTON, + TAKE_TURF_LITTLE_MEXICO, + TAKE_TURF_WILLOWFIELD, + TAKE_TURF_PLAYA_DEL_SEVILLE, + TAKE_TURF_TEMPLE, + + TARGET, + TAXI_BAIL, + TAXI_HAIL, + TAXI_HIT_PED, + TAXI_START, + TAXI_SUCCESS, + TAXI_TIP, + TRAPPED, + VALET_BAD, + VALET_GOOD, + VALET_PARK_CAR, + VAN, + VICTIM, + WEATHER_DISL_REPLY, + WEATHER_LIKE_REPLY, + WHERE_YOU_FROM_NEG, + WHERE_YOU_FROM_POS, + SPANKED, + SPANKING, + SPANKING_MUFFLED, + GREETING_GF, + PARTING_GF, + UH_HUH, + CLEAR_ATTACHED_PEDS, + AGREE_TO_DO_DRIVEBY, + AGREE_TO_LET_DRIVE, + MICHELLE_TAKE_CAR, + ACCEPT_SEX, + DECLINE_SEX, + GIVE_NUMBER_YES, + GIVE_NUMBER_NO, + WHERE_YOU_FROM, + GANGBANG, + WHERE_YOU_FROM_POS_REPLY, + DRIVE_THROUGH_TAUNT, + ATTACK_CAR, + TIP_CAR, + CHASE_CAR, + ENEMY_GANG_WASTED, + PLAYER_WASTED, + CHASE, + + GF_REQ_DATE_DESPERATE, + GF_REQ_DATE_NORMAL, + GF_REQ_MEAL_DESPERATE, + GF_REQ_MEAL_NORMAL, + GF_REQ_DRIVE_DESPERATE, + GF_REQ_DRIVE_NORMAL, + GF_REQ_DANCE_DESPERATE, + GF_REQ_DANCE_NORMAL, + GF_REQ_SEX_DESPERATE, + GF_REQ_SEX_NORMAL, + GF_BORED_1, + GF_BORED_2, + GF_STORY, + GF_LIKE_MEAL_DEST, + GF_LIKE_CLUB_DEST, + GF_OFFER_DANCE, + GF_ENJOYED_MEAL_HIGH, + GF_ENJOYED_EVENT_LOW, + GF_ENJOYED_CLUB_HIGH, + GF_TAKE_HOME_HAPPY, + GF_TAKE_HOME_ANGRY, + GF_COFFEE, + GF_MOAN, + GF_MOAN_MUFFLED, + GF_HEAD, + GF_CLIMAX_HIGH, + GF_CLIMAX_HIGH_MUFFLED, + GF_CLIMAX_LOW, + GF_SEX_GOOD, + GF_SEX_GOOD_MUFFLED, + GF_SEX_BAD, + GF_MEET_AGAIN, + GF_JEALOUS, + GF_JEALOUS_REPLY, + GF_GOODBYE_HAPPY, + GF_GOODBYE_ANGRY, + GF_LEFT_BEHIND, + GF_HELLO, + GF_GOODBYE, + GF_PICKUP_LOCATION, + GF_PARK_UP, + GF_PARK_UP_LOCATION_HATE, + GF_GIFT_LIKE, + GF_CHANGE_RADIO_FAVE, + GF_CHANGE_RADIO_BACK, + GF_DO_A_DRIVEBY, + GF_START_A_FIGHT, + GF_REJECT_DATE, + GF_REQ_TO_DRIVE_CAR, + GF_DROP_PLAYER_DRIVE_AWAY, + GF_DISLIKE_CURRENT_ZONE, + GF_LIKE_CURRENT_ZONE, + GF_HIT_BY_PLAYER_WARNING, + GF_DUMP_PLAYER_LIVE, + GF_DUMP_PLAYER_PHONE, + GF_SEX_APPEAL_TOO_LOW, + GF_PHYS_CRITIQUE, + GF_INTRO, + GF_NEG_RESPONSE, + GF_POS_RESPONSE, + + BOXING_CHEER, + BOXING_ENOUGH, + GIVE_PRODUCT, + NO_MONEY, + PLAYER_SICK, + REMOVE_TATTOO, + SHOP_CLOSED, + SHOP_CHANGINGROOM, + SHOP_CHAT, + TAKE_A_SEAT, + THANKS_FOR_CUSTOM, + WELCOME_TO_SHOP, + WHAT_WANT, + PHOTO_CARL, + PHOTO_CHEESE, + SINGING, + STOMACH_RUMBLE, + BREATHING, + + PAIN_START, + PAIN_COUGH, + PAIN_DEATH_DROWN, + PAIN_DEATH_HIGH, + PAIN_DEATH_LOW, + PAIN_HIGH, + PAIN_LOW, + PAIN_ON_FIRE, + PAIN_PANIC, + PAIN_SPRAYED, + + PAIN_CJ_BOXING, + PAIN_CJ_GRUNT, + PAIN_CJ_PART_IN, + PAIN_CJ_PART_OUT, + PAIN_CJ_PUKE, + PAIN_CJ_STRAIN, + PAIN_CJ_STRAIN_EXHALE, + PAIN_CJ_SWIM_GASP, + PAIN_CJ_DROWNING, + PAIN_CJ_HIGH_FALL, + + PAIN_END, + + NUM_PED_CONTEXT, +}; + class CPedSound { public: