diff --git a/src/xrGame/Actor.cpp b/src/xrGame/Actor.cpp index a74d4f1877d..8a75aef4771 100644 --- a/src/xrGame/Actor.cpp +++ b/src/xrGame/Actor.cpp @@ -1340,7 +1340,7 @@ void CActor::shedule_Update(u32 DT) CGameObject* game_object = smart_cast(RQ.O); m_pUsableObject = game_object; m_pInvBoxWeLookingAt = smart_cast(game_object); - m_pPersonWeLookingAt = smart_cast(game_object); + m_pPersonWeLookingAt = game_object->cast_inventory_owner(); m_pVehicleWeLookingAt = smart_cast(game_object); CEntityAlive* pEntityAlive = smart_cast(game_object); diff --git a/src/xrGame/ai/monsters/basemonster/base_monster.cpp b/src/xrGame/ai/monsters/basemonster/base_monster.cpp index 63163623118..980c64db2d9 100644 --- a/src/xrGame/ai/monsters/basemonster/base_monster.cpp +++ b/src/xrGame/ai/monsters/basemonster/base_monster.cpp @@ -744,6 +744,7 @@ IFactoryObject* CBaseMonster::_construct() inherited::_construct(); CStepManager::_construct(); + CInventoryOwner::_construct(); return (this); } @@ -871,10 +872,46 @@ bool CBaseMonster::check_start_conditions(ControlCom::EControlType type) void CBaseMonster::OnEvent(NET_Packet& P, u16 type) { inherited::OnEvent(P, type); + CInventoryOwner::OnEvent(P, type); u16 id; switch (type) { + case GE_TRADE_BUY: + case GE_OWNERSHIP_TAKE: + { + P.r_u16(id); + IGameObject* O = Level().Objects.net_Find(id); + VERIFY(O); + + CGameObject* GO = smart_cast(O); + CInventoryItem* pIItem = smart_cast(GO); + VERIFY(inventory().CanTakeItem(pIItem)); + pIItem->m_ItemCurrPlace.type = eItemPlaceRuck; + + O->H_SetParent(this); + inventory().Take(GO, true, true); + break; + } + case GE_TRADE_SELL: + case GE_OWNERSHIP_REJECT: + { + P.r_u16(id); + IGameObject* O = Level().Objects.net_Find(id); + VERIFY(O); + + const bool just_before_destroy = !P.r_eof() && P.r_u8(); + const bool dont_create_shell = (type == GE_TRADE_SELL) || just_before_destroy; + + O->SetTmpPreDestroy(just_before_destroy); + if (inventory().DropItem(smart_cast(O), just_before_destroy, dont_create_shell) && + !O->getDestroy()) + { + feel_touch_deny(O, 2000); + } + break; + } + case GE_KILL_SOMEONE: P.r_u16(id); IGameObject* O = Level().Objects.net_Find(id); diff --git a/src/xrGame/ai/monsters/basemonster/base_monster.h b/src/xrGame/ai/monsters/basemonster/base_monster.h index 1c551b4747f..7dc26b493d1 100644 --- a/src/xrGame/ai/monsters/basemonster/base_monster.h +++ b/src/xrGame/ai/monsters/basemonster/base_monster.h @@ -51,7 +51,7 @@ class text_tree; class anti_aim_ability; -class CBaseMonster : public CCustomMonster, public CStepManager +class CBaseMonster : public CCustomMonster, public CStepManager, public CInventoryOwner { protected: using inherited = CCustomMonster; @@ -73,8 +73,10 @@ class CBaseMonster : public CCustomMonster, public CStepManager virtual CScriptEntity* cast_script_entity() { return this; } virtual CBaseMonster* cast_base_monster() { return this; } virtual CGameObject* cast_game_object() { return this; } + virtual CInventoryOwner* cast_inventory_owner() override { return CallOfPripyatMode ? nullptr : this; } public: + virtual void renderable_Render(IRenderable* root) override { return inherited::renderable_Render(root); } virtual bool renderable_ShadowReceive() { return TRUE; } virtual void Die(IGameObject* who); virtual void HitSignal(float amount, Fvector& vLocalDir, IGameObject* who, s16 element); @@ -141,8 +143,11 @@ class CBaseMonster : public CCustomMonster, public CStepManager virtual void HitEntityInJump(const CEntity* pEntity) {} virtual void on_before_sell(CInventoryItem* item); + virtual bool unlimited_ammo() override { return false; } + float GetSatiety() { return 0.5f; } void ChangeSatiety(float v) {} + // --------------------------------------------------------------------------------- // Process scripts // --------------------------------------------------------------------------------- diff --git a/src/xrGame/ai/monsters/basemonster/base_monster_startup.cpp b/src/xrGame/ai/monsters/basemonster/base_monster_startup.cpp index 4f63edc8d7d..64c21ded356 100644 --- a/src/xrGame/ai/monsters/basemonster/base_monster_startup.cpp +++ b/src/xrGame/ai/monsters/basemonster/base_monster_startup.cpp @@ -213,6 +213,7 @@ void CBaseMonster::reload(LPCSTR section) if (!CCustomMonster::use_simplified_visual()) CStepManager::reload(section); + CInventoryOwner::reload(section); movement().reload(section); // load base sounds @@ -262,6 +263,7 @@ void CBaseMonster::reload(LPCSTR section) void CBaseMonster::reinit() { inherited::reinit(); + CInventoryOwner::reinit(); EnemyMemory.clear(); SoundMemory.clear(); @@ -330,6 +332,10 @@ bool CBaseMonster::net_Spawn(CSE_Abstract* DC) "There is no AI-Map, level graph, cross table, or graph is not compiled into the game graph!"); monster_squad().register_member((u8)g_Team(), (u8)g_Squad(), (u8)g_Group(), this); settings_overrides(); + + CHARACTER_COMMUNITY community; + community.set("monster"); + CInventoryOwner::SetCommunity(community.index()); if (GetScriptControl()) { @@ -384,6 +390,7 @@ void CBaseMonster::net_Destroy() StateMan->critical_finalize(); inherited::net_Destroy(); + CInventoryOwner::net_Destroy(); m_pPhysics_support->in_NetDestroy(); diff --git a/src/xrGame/ui/UIActorMenuTrade.cpp b/src/xrGame/ui/UIActorMenuTrade.cpp index 2051574edb8..1f6dd31110d 100644 --- a/src/xrGame/ui/UIActorMenuTrade.cpp +++ b/src/xrGame/ui/UIActorMenuTrade.cpp @@ -356,12 +356,12 @@ void CUIActorMenu::UpdateActor() void CUIActorMenu::UpdatePartnerBag() { - /*CBaseMonster* monster = smart_cast(m_pPartnerInvOwner); + CBaseMonster* monster = smart_cast(m_pPartnerInvOwner); if (monster || m_pPartnerInvOwner->use_simplified_visual()) { - m_PartnerWeight->SetText(""); + m_PartnerMoney->SetText(""); } - else*/ if (m_pPartnerInvOwner->InfinitiveMoney()) + else if (m_pPartnerInvOwner->InfinitiveMoney()) { m_PartnerMoney->SetText("--- RU"); }