From 0bacda32692729e4b9743f91d92cd329e198d73a Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Sat, 21 Oct 2017 17:56:09 +0100 Subject: Implement horse inventory (#4053) * Implement horse inventory * Fix sign conversions * Add API doc for ItemCategory::IsHorseArmor * Improve HandleOpenHorseInventory comment and style fixes. --- src/Mobs/Horse.cpp | 134 +++++++++++++++++++++++++++++++++++++++++++++-------- src/Mobs/Horse.h | 28 +++++++++-- 2 files changed, 137 insertions(+), 25 deletions(-) (limited to 'src/Mobs') diff --git a/src/Mobs/Horse.cpp b/src/Mobs/Horse.cpp index 07d3f7481..77edc0d27 100644 --- a/src/Mobs/Horse.cpp +++ b/src/Mobs/Horse.cpp @@ -5,6 +5,7 @@ #include "../EffectID.h" #include "../Entities/Player.h" #include "Broadcaster.h" +#include "UI/HorseWindow.h" @@ -12,16 +13,15 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : super("Horse", mtHorse, "entity.horse.hurt", "entity.horse.death", 1.4, 1.6), + cEntityWindowOwner(this), m_bHasChest(false), m_bIsEating(false), m_bIsRearing(false), m_bIsMouthOpen(false), m_bIsTame(false), - m_bIsSaddled(false), m_Type(Type), m_Color(Color), m_Style(Style), - m_Armour(0), m_TimesToTame(TameTimes), m_TameAttemptTimes(0), m_RearTickCount(0), @@ -33,6 +33,19 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) : +cHorse::~cHorse() +{ + auto Window = GetWindow(); + if (Window != nullptr) + { + Window->OwnerDestroyed(); + } +} + + + + + void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) { super::Tick(a_Dt, a_Chunk); @@ -108,22 +121,24 @@ void cHorse::OnRightClicked(cPlayer & a_Player) if (m_bIsTame) { - if (!m_bIsSaddled) + if (a_Player.IsCrouched()) { - if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE) - { - // Saddle the horse: - if (!a_Player.IsGameModeCreative()) - { - a_Player.GetInventory().RemoveOneEquippedItem(); - } - m_bIsSaddled = true; - m_World->BroadcastEntityMetadata(*this); - } - else - { - a_Player.AttachTo(this); - } + PlayerOpenWindow(a_Player); + return; + } + + auto EquipedItemType = a_Player.GetEquippedItem().m_ItemType; + + if ( + !IsSaddled() && + ( + (EquipedItemType == E_ITEM_SADDLE) || + ItemCategory::IsHorseArmor(EquipedItemType) + ) + ) + { + // Player is holding a horse inventory item, open the window: + PlayerOpenWindow(a_Player); } else { @@ -167,6 +182,65 @@ void cHorse::OnRightClicked(cPlayer & a_Player) +void cHorse::SetHorseSaddle(cItem a_Saddle) +{ + if (a_Saddle.m_ItemType == E_ITEM_SADDLE) + { + m_World->BroadcastSoundEffect("entity.horse.saddle", GetPosition(), 1.0f, 0.8f); + } + else if (!a_Saddle.IsEmpty()) + { + return; // Invalid item + } + + m_Saddle = std::move(a_Saddle); + m_World->BroadcastEntityMetadata(*this); +} + + + + + +void cHorse::SetHorseArmor(cItem a_Armor) +{ + if (ItemCategory::IsHorseArmor(a_Armor.m_ItemType)) + { + m_World->BroadcastSoundEffect("entity.horse.armor", GetPosition(), 1.0f, 0.8f); + } + else if (!a_Armor.IsEmpty()) + { + return; // Invalid item + } + + m_Armor = std::move(a_Armor); + m_World->BroadcastEntityMetadata(*this); +} + + + + + +int cHorse::GetHorseArmour(void) const +{ + switch (m_Armor.m_ItemType) + { + case E_ITEM_EMPTY: return 0; + case E_ITEM_IRON_HORSE_ARMOR: return 1; + case E_ITEM_GOLD_HORSE_ARMOR: return 2; + case E_ITEM_DIAMOND_HORSE_ARMOR: return 3; + + default: + { + LOGWARN("cHorse::GetHorseArmour: Invalid armour item (%d)", m_Armor.m_ItemType); + return 0; + } + } +} + + + + + void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) { if (IsBaby()) @@ -180,9 +254,13 @@ void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting); } AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER); - if (m_bIsSaddled) + if (IsSaddled()) { - a_Drops.push_back(cItem(E_ITEM_SADDLE, 1)); + a_Drops.push_back(m_Saddle); + } + if (!m_Armor.IsEmpty()) + { + a_Drops.push_back(m_Armor); } } @@ -205,8 +283,24 @@ void cHorse::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) void cHorse::HandleSpeedFromAttachee(float a_Forward, float a_Sideways) { - if ((m_bIsTame) && (m_bIsSaddled)) + if ((m_bIsTame) && IsSaddled()) { super::HandleSpeedFromAttachee(a_Forward * m_MaxSpeed, a_Sideways * m_MaxSpeed); } } + + + + + +void cHorse::PlayerOpenWindow(cPlayer & a_Player) +{ + auto Window = GetWindow(); + if (Window == nullptr) + { + Window = new cHorseWindow(*this); + OpenWindow(Window); + } + + a_Player.OpenWindow(*Window); +} diff --git a/src/Mobs/Horse.h b/src/Mobs/Horse.h index 82026a0ee..38625001e 100644 --- a/src/Mobs/Horse.h +++ b/src/Mobs/Horse.h @@ -2,18 +2,21 @@ #pragma once #include "PassiveMonster.h" +#include "UI/WindowOwner.h" class cHorse : - public cPassiveMonster + public cPassiveMonster, + public cEntityWindowOwner { typedef cPassiveMonster super; public: cHorse(int Type, int Color, int Style, int TameTimes); + virtual ~cHorse() override; CLASS_PROTODEF(cHorse) @@ -23,7 +26,7 @@ public: virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; virtual void OnRightClicked(cPlayer & a_Player) override; - bool IsSaddled (void) const {return m_bIsSaddled; } + bool IsSaddled (void) const {return !m_Saddle.IsEmpty(); } bool IsChested (void) const {return m_bHasChest; } bool IsEating (void) const {return m_bIsEating; } bool IsRearing (void) const {return m_bIsRearing; } @@ -32,7 +35,18 @@ public: int GetHorseType (void) const {return m_Type; } int GetHorseColor (void) const {return m_Color; } int GetHorseStyle (void) const {return m_Style; } - int GetHorseArmour (void) const {return m_Armour;} + int GetHorseArmour (void) const; + + /** Set the horse's saddle to the given item. + @param a_SaddleItem should be either a saddle or empty. */ + void SetHorseSaddle(cItem a_SaddleItem); + + /** Set the horse's armor slot to the given item. + @param a_SaddleItem should be either a type of horse armor or empty. */ + void SetHorseArmor(cItem a_ArmorItem); + + const cItem & GetHorseSaddle() const { return m_Saddle; } + const cItem & GetHorseArmorItem() const { return m_Armor; } virtual void GetBreedingItems(cItems & a_Items) override { @@ -40,11 +54,15 @@ public: a_Items.Add(E_ITEM_GOLDEN_APPLE); } + void PlayerOpenWindow(cPlayer & a_Player); + private: - bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame, m_bIsSaddled; - int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; + bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame; + int m_Type, m_Color, m_Style, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount; float m_MaxSpeed; + cItem m_Saddle; + cItem m_Armor; } ; -- cgit v1.2.3