Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

309 lines
9.0 KiB
C++

//
// weapons/pedinventory.cpp
//
// Copyright (C) 1999-2010 Rockstar North. All Rights Reserved.
//
// File header
#include "Weapons/Inventory/PedInventory.h"
// Game headers
#include "modelinfo/PedModelInfo.h"
#include "Peds/Ped.h"
#include "Weapons/Inventory/PedInventoryLoadOut.h"
#include "Weapons/WeaponDebug.h"
#include "Stats/StatsInterface.h"
#if __ASSERT
#include "Stats/StatsMgr.h"
#include "Stats/StatsTypes.h"
#endif
// Macro to disable optimisations if set
AI_COVER_OPTIMISATIONS()
WEAPON_OPTIMISATIONS()
//////////////////////////////////////////////////////////////////////////
// CPedInventory
//////////////////////////////////////////////////////////////////////////
CPedInventory::CPedInventory()
: m_pPed(NULL)
, m_uCachedRechargeTime(0)
, m_uCachedWeaponState(0)
{
}
void CPedInventory::Init(CPed* pPed, const CPedModelInfo* pPedModelInfo)
{
// Assign the owner ped
m_pPed = pPed;
// Initialise default load out
CPedInventoryLoadOutManager::SetDefaultLoadOut(m_pPed, pPedModelInfo);
}
void CPedInventory::Process()
{
if(!m_weaponRepository.GetIsStreamedIn())
{
m_weaponRepository.ProcessStreaming();
}
if(!m_ammoRepository.GetIsStreamedIn())
{
m_ammoRepository.ProcessStreaming();
}
}
void CPedInventory::RegisterListener(CInventoryListener* pListener)
{
m_weaponRepository.RegisterListener(pListener);
m_ammoRepository.RegisterListener(pListener);
}
CWeaponItem* CPedInventory::AddWeapon(u32 uWeaponNameHash)
{
CWeaponItem* pWeaponItem = m_weaponRepository.GetItem(uWeaponNameHash);
if(!pWeaponItem)
{
pWeaponItem = m_weaponRepository.AddItem(uWeaponNameHash, m_pPed);
if(pWeaponItem)
{
weaponDebugf1("CPedInventory::AddWeapon: [%d][%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), m_pPed, m_pPed->GetModelName());
if(m_pPed->IsLocalPlayer())
{
if(uWeaponNameHash == ATSTRINGHASH("WEAPON_STUNGUN_MP", 0x45CD9CF3))
{
pWeaponItem->SetTimer(m_uCachedRechargeTime);
pWeaponItem->SetCachedWeaponState(m_uCachedWeaponState);
}
const CWeaponInfo* pWeaponInfo = pWeaponItem->GetInfo();
if(pWeaponInfo)
{
g_WeaponAudioEntity.AddPlayerInventoryWeapon();
}
}
}
}
return pWeaponItem;
}
const CAmmoItem* CPedInventory::AddAmmo(u32 uAmmoNameHash, s32 iAmmo)
{
if(const CAmmoItem* pAmmoItem = m_ammoRepository.AddAmmo(uAmmoNameHash, iAmmo, m_pPed))
{
weaponDebugf1("CPedInventory::AddAmmo: [%d][%s], Ammo:%d: Ped 0x%p [%s]", uAmmoNameHash, atHashString(uAmmoNameHash).TryGetCStr(), iAmmo, m_pPed, m_pPed->GetModelName());
return pAmmoItem;
}
return NULL;
}
void CPedInventory::SetAmmo(u32 uAmmoNameHash, s32 iAmmo)
{
m_ammoRepository.SetAmmo(uAmmoNameHash, iAmmo, m_pPed);
weaponDebugf1("CPedInventory::SetAmmo: [%d][%s], Ammo:%d: Ped 0x%p [%s]", uAmmoNameHash, atHashString(uAmmoNameHash).TryGetCStr(), iAmmo, m_pPed, m_pPed->GetModelName());
}
CWeaponItem* CPedInventory::AddWeaponAndAmmo(u32 uWeaponNameHash, s32 iAmmo)
{
CWeaponItem* pItem = AddWeapon(uWeaponNameHash);
if(pItem)
{
weaponDebugf1("CPedInventory::AddWeaponAndAmmo: [%d][%s], Ammo:%d: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), iAmmo, m_pPed, m_pPed->GetModelName());
if (iAmmo < 0) // treat -1 ammo as being a call for infinite ammo
{
AddWeaponAmmo(uWeaponNameHash, 0);
m_ammoRepository.SetWeaponUsingInfiniteAmmo(uWeaponNameHash, true, m_pPed);
}
else
AddWeaponAmmo(uWeaponNameHash, iAmmo);
}
return pItem;
}
const CAmmoItem* CPedInventory::AddWeaponAmmo(u32 uWeaponNameHash, s32 iAmmo)
{
const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfo<CWeaponInfo>(uWeaponNameHash);
#if !__NO_OUTPUT
const CAmmoInfo* pAmmoInfo = pWeaponInfo->GetAmmoInfo(m_pPed);
#endif // !__NO_OUTPUT
weaponDebugf1("CPedInventory::AddWeaponAmmo: [%d][%s], Ammo:%d [%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), iAmmo, pAmmoInfo ? pAmmoInfo->GetName() : "", m_pPed, m_pPed->GetModelName());
return m_ammoRepository.AddWeaponAmmo(pWeaponInfo, iAmmo, m_pPed);
}
void CPedInventory::SetWeaponAmmo(u32 uWeaponNameHash, s32 iAmmo)
{
const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfo<CWeaponInfo>(uWeaponNameHash);
#if !__NO_OUTPUT
const CAmmoInfo* pAmmoInfo = pWeaponInfo->GetAmmoInfo(m_pPed);
#endif // !__NO_OUTPUT
weaponDebugf1("CPedInventory::SetWeaponAmmo: [%d][%s], Ammo:%d [%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), iAmmo, pAmmoInfo ? pAmmoInfo->GetName() : "", m_pPed, m_pPed->GetModelName());
m_ammoRepository.SetWeaponAmmo(pWeaponInfo, iAmmo, m_pPed);
}
void CPedInventory::SetWeaponUsingInfiniteAmmo(u32 uWeaponNameHash, bool bInfinite)
{
m_ammoRepository.SetWeaponUsingInfiniteAmmo(uWeaponNameHash, bInfinite, m_pPed);
}
bool CPedInventory::RemoveWeapon(u32 uWeaponNameHash)
{
// Cache stungun recharge time and state so we can reapply it when we add the weapon again, url:bugstar:7461554
if(uWeaponNameHash == ATSTRINGHASH("WEAPON_STUNGUN_MP", 0x45CD9CF3))
{
const CWeaponItem* pWeaponItem = GetWeapon(uWeaponNameHash);
if(pWeaponItem)
{
m_uCachedRechargeTime = pWeaponItem->GetTimer();
m_uCachedWeaponState = pWeaponItem->GetCachedWeaponState();
}
}
if(m_weaponRepository.RemoveItem(uWeaponNameHash))
{
weaponDebugf1("CPedInventory::RemoveWeapon: [%d][%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), m_pPed, m_pPed->GetModelName());
return true;
}
return false;
}
bool CPedInventory::RemoveWeaponAndAmmo(u32 uWeaponNameHash)
{
if(RemoveWeapon(uWeaponNameHash))
{
weaponDebugf1("CPedInventory::RemoveWeaponAndAmmo: [%d][%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), m_pPed, m_pPed->GetModelName());
if(GetNumWeaponAmmoReferences(uWeaponNameHash) == 0)
{
const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfo<CWeaponInfo>(uWeaponNameHash);
if(pWeaponInfo && pWeaponInfo->GetAmmoInfo())
{
if(m_ammoRepository.RemoveItem(pWeaponInfo->GetAmmoInfo()->GetHash()))
{
weaponDebugf1("CPedInventory::RemoveWeaponAndAmmo: No weapon references left to %s, removed ammo type", pWeaponInfo->GetAmmoInfo()->GetName());
}
}
}
return true;
}
return false;
}
void CPedInventory::RemoveAllWeaponsExcept(u32 uWeaponNameHash, u32 uNextWeaponNameHash /* = 0 */)
{
weaponDebugf1("CPedInventory::RemoveAllWeaponsExcept [%d][%s], [%d][%s]: Ped 0x%p [%s]", uWeaponNameHash, atHashString(uWeaponNameHash).TryGetCStr(), uNextWeaponNameHash, atHashString(uNextWeaponNameHash).TryGetCStr(), m_pPed, m_pPed->GetModelName());
CWeaponItem* pExcludedWeapon = NULL;
if(uWeaponNameHash != 0)
{
pExcludedWeapon = GetWeapon(uWeaponNameHash);
}
CWeaponItem* pExcludedNextWeapon = NULL;
if(uNextWeaponNameHash != 0)
{
pExcludedNextWeapon = GetWeapon(uNextWeaponNameHash);
}
if((!pExcludedWeapon) && (!pExcludedNextWeapon))
{
RemoveAll();
}
else
{
m_weaponRepository.RemoveAllItemsExcept(uWeaponNameHash, uNextWeaponNameHash);
u32 uAmmoNameHash = 0;
if(pExcludedWeapon && pExcludedWeapon->GetInfo() && pExcludedWeapon->GetInfo()->GetAmmoInfo(m_pPed))
{
uAmmoNameHash = pExcludedWeapon->GetInfo()->GetAmmoInfo(m_pPed)->GetHash();
}
u32 uAmmoNextNameHash = 0;
if(pExcludedNextWeapon && pExcludedNextWeapon->GetInfo() && pExcludedNextWeapon->GetInfo()->GetAmmoInfo(m_pPed))
{
uAmmoNextNameHash = pExcludedNextWeapon->GetInfo()->GetAmmoInfo(m_pPed)->GetHash();
}
m_ammoRepository.RemoveAllItemsExcept(uAmmoNameHash, uAmmoNextNameHash);
}
}
void CPedInventory::RemoveAll()
{
weaponDebugf1("CPedInventory::RemoveAll: Ped 0x%p [%s]", m_pPed, m_pPed->GetModelName());
m_weaponRepository.RemoveAllItems();
m_ammoRepository.RemoveAllItems();
}
bool CPedInventory::GetIsStreamedIn(u32 uItemNameHash)
{
if(m_weaponRepository.GetIsStreamedIn(uItemNameHash) || m_ammoRepository.GetIsStreamedIn(uItemNameHash))
{
return true;
}
return false;
}
bool CPedInventory::GetIsStreamedIn()
{
if(!m_weaponRepository.GetIsStreamedIn())
{
return false;
}
if(!m_ammoRepository.GetIsStreamedIn())
{
return false;
}
return true;
}
s32 CPedInventory::GetNumWeaponAmmoReferences(u32 uWeaponNameHash) const
{
s32 iAmmoReferences = 0;
const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfo<CWeaponInfo>(uWeaponNameHash);
if(pWeaponInfo)
{
const atArray<CWeaponItem*>& weaponItems = m_weaponRepository.GetAllItems();
for(s32 i = 0; i < weaponItems.GetCount(); i++)
{
if(weaponItems[i]->GetInfo()->GetAmmoInfo() == pWeaponInfo->GetAmmoInfo())
{
iAmmoReferences++;
}
}
}
return iAmmoReferences;
}
bool CPedInventory::NotifyAmmoChange(u32 uWeaponNameHash, s32 iAmmo)
{
const CWeaponInfo* pWeaponInfo = CWeaponInfoManager::GetInfo<CWeaponInfo>(uWeaponNameHash);
if(!m_ammoRepository.GetIsWeaponUsingInfiniteAmmo(pWeaponInfo, m_pPed))
{
m_ammoRepository.SetWeaponAmmo(pWeaponInfo, iAmmo, m_pPed);
return true;
}
return false;
}
bool CPedInventory::NotifyTimerChange(u32 uWeaponNameHash, u32 uTimer)
{
CWeaponItem* pWeaponItem = GetWeapon(uWeaponNameHash);
if(pWeaponItem)
{
pWeaponItem->SetTimer(uTimer);
return true;
}
return false;
}