From 1edc6c8601f9d00751bf7c9f7fcc69d1e18bb46a Mon Sep 17 00:00:00 2001 From: Persson-dev <66266021+Persson-dev@users.noreply.github.com> Date: Wed, 29 Dec 2021 20:30:09 +0100 Subject: Add skeleton bow pulling animation (#5355) * Added basic skeleton bow animation * Fixing style --- src/Mobs/Skeleton.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/Mobs/Skeleton.h | 8 ++++++++ src/Protocol/Protocol_1_10.cpp | 14 +++++++++++++- src/Protocol/Protocol_1_11.cpp | 14 +++++++++++++- src/Protocol/Protocol_1_12.cpp | 14 +++++++++++++- src/Protocol/Protocol_1_13.cpp | 14 ++++++++++++-- src/Protocol/Protocol_1_9.cpp | 11 +++++++++++ 7 files changed, 106 insertions(+), 6 deletions(-) diff --git a/src/Mobs/Skeleton.cpp b/src/Mobs/Skeleton.cpp index a32d38d03..12081207f 100644 --- a/src/Mobs/Skeleton.cpp +++ b/src/Mobs/Skeleton.cpp @@ -10,7 +10,8 @@ cSkeleton::cSkeleton(void) : - Super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6f, 1.99f) + Super("Skeleton", mtSkeleton, "entity.skeleton.hurt", "entity.skeleton.death", "entity.skeleton.ambient", 0.6f, 1.99f), + m_ChargingBow(false) { } @@ -36,10 +37,40 @@ void cSkeleton::GetDrops(cItems & a_Drops, cEntity * a_Killer) +void cSkeleton::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) +{ + Super::Tick(a_Dt, a_Chunk); + + if (!IsTicking()) + { + // The base class tick destroyed us + return; + } + + if (m_ChargingBow && (m_EMState == IDLE)) + { + // releasing bow if no more target is found + m_ChargingBow = false; + m_World->BroadcastEntityMetadata(*this); + } +} + + + + + bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) { StopMovingToPosition(); // Todo handle this in a better way, the skeleton does some uneeded recalcs due to inStateChasing auto & Random = GetRandomProvider(); + + if (!m_ChargingBow) + { + // updating pulling animation + m_ChargingBow = true; + m_World->BroadcastEntityMetadata(*this); + } + if ((GetTarget() != nullptr) && (m_AttackCoolDownTicksLeft == 0)) { Vector3d Inaccuracy = Vector3d(Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25), Random.RandReal(-0.25, 0.25)); @@ -53,6 +84,10 @@ bool cSkeleton::Attack(std::chrono::milliseconds a_Dt) return false; } + // releasing bow after arrow was shot + m_ChargingBow = false; + m_World->BroadcastEntityMetadata(*this); + ResetAttackCooldown(); return true; } diff --git a/src/Mobs/Skeleton.h b/src/Mobs/Skeleton.h index ee9c803c2..486bfe609 100644 --- a/src/Mobs/Skeleton.h +++ b/src/Mobs/Skeleton.h @@ -18,10 +18,18 @@ public: CLASS_PROTODEF(cSkeleton) + virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override; + virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = nullptr) override; virtual bool Attack(std::chrono::milliseconds a_Dt) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual bool IsUndead(void) override { return true; } + bool IsChargingBow() const { return m_ChargingBow; } + +private: + + bool m_ChargingBow; + } ; diff --git a/src/Protocol/Protocol_1_10.cpp b/src/Protocol/Protocol_1_10.cpp index 9f4413576..4f3e1a52b 100644 --- a/src/Protocol/Protocol_1_10.cpp +++ b/src/Protocol/Protocol_1_10.cpp @@ -795,6 +795,19 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_ break; } // case mtSheep + case mtSkeleton: + { + auto & Skeleton = static_cast(a_Mob); + a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); + + a_Pkt.WriteBEUInt8(SKELETON_ARMS_SWINGING); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Skeleton.IsChargingBow()); + break; + } // case mtSkeleton + case mtSlime: { auto & Slime = static_cast(a_Mob); @@ -958,7 +971,6 @@ void cProtocol_1_10_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_ case mtIronGolem: case mtMooshroom: case mtSilverfish: - case mtSkeleton: case mtSnowGolem: case mtStray: case mtSpider: diff --git a/src/Protocol/Protocol_1_11.cpp b/src/Protocol/Protocol_1_11.cpp index 30935574b..7a9a53e6f 100644 --- a/src/Protocol/Protocol_1_11.cpp +++ b/src/Protocol/Protocol_1_11.cpp @@ -1102,6 +1102,19 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_ break; } // case mtSheep + case mtSkeleton: + { + auto & Skeleton = static_cast(a_Mob); + a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); + + a_Pkt.WriteBEUInt8(ABSTRACT_SKELETON_ARMS_SWINGING); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Skeleton.IsChargingBow()); + break; + } // case mtSkeleton + case mtSlime: { auto & Slime = static_cast(a_Mob); @@ -1260,7 +1273,6 @@ void cProtocol_1_11_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_ case mtIronGolem: case mtMooshroom: case mtSilverfish: - case mtSkeleton: case mtStray: case mtSpider: case mtSquid: diff --git a/src/Protocol/Protocol_1_12.cpp b/src/Protocol/Protocol_1_12.cpp index d0e77ae80..c7f0ee31a 100644 --- a/src/Protocol/Protocol_1_12.cpp +++ b/src/Protocol/Protocol_1_12.cpp @@ -788,6 +788,19 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo break; } // case mtSheep + case mtSkeleton: + { + auto & Skeleton = static_cast(a_Mob); + a_Pkt.WriteBEUInt8(LIVING_ACTIVE_HAND); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); + + a_Pkt.WriteBEUInt8(ABSTRACT_SKELETON_ARMS_SWINGING); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BOOL); + a_Pkt.WriteBool(Skeleton.IsChargingBow()); + break; + } // case mtSkeleton + case mtSlime: { auto & Slime = static_cast(a_Mob); @@ -967,7 +980,6 @@ void cProtocol_1_12::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo case mtGiant: case mtSilverfish: - case mtSkeleton: case mtSquid: { // Mobs with no extra fields diff --git a/src/Protocol/Protocol_1_13.cpp b/src/Protocol/Protocol_1_13.cpp index f6919388c..80a1e9df1 100644 --- a/src/Protocol/Protocol_1_13.cpp +++ b/src/Protocol/Protocol_1_13.cpp @@ -337,6 +337,7 @@ UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) const case EntityMetadata::IllagerFlags: return Insentient; case EntityMetadata::SpeIlagerSpell: return Insentient + 1; case EntityMetadata::VexFlags: return Insentient; + case EntityMetadata::AbstractSkeletonArmsSwinging: return Insentient; case EntityMetadata::SpiderClimbing: return Insentient; case EntityMetadata::WitchAggresive: return Insentient; case EntityMetadata::WitherFirstHeadTarget: return Insentient; @@ -366,7 +367,6 @@ UInt8 cProtocol_1_13::GetEntityMetadataID(EntityMetadata a_Metadata) const case EntityMetadata::EntityPose: case EntityMetadata::AreaEffectCloudParticleParameter1: case EntityMetadata::AreaEffectCloudParticleParameter2: - case EntityMetadata::AbstractSkeletonArmsSwinging: case EntityMetadata::ZombieUnusedWasType: break; } UNREACHABLE("Retrieved invalid metadata for protocol"); @@ -1184,6 +1184,17 @@ void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo break; } // case mtSheep + case mtSkeleton: + { + auto & Skeleton = static_cast(a_Mob); + WriteEntityMetadata(a_Pkt, EntityMetadata::LivingActiveHand, EntityMetadataType::Byte); + a_Pkt.WriteBEUInt8(Skeleton.IsChargingBow() ? 0x01 : 0x00); + + WriteEntityMetadata(a_Pkt, EntityMetadata::AbstractSkeletonArmsSwinging, EntityMetadataType::Boolean); + a_Pkt.WriteBool(Skeleton.IsChargingBow()); + break; + } // case mtSkeleton + case mtSlime: { auto & Slime = static_cast(a_Mob); @@ -1354,7 +1365,6 @@ void cProtocol_1_13::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_Mo case mtGiant: case mtSilverfish: - case mtSkeleton: case mtSquid: case mtWitherSkeleton: { diff --git a/src/Protocol/Protocol_1_9.cpp b/src/Protocol/Protocol_1_9.cpp index 2cc087682..a36e3f53d 100644 --- a/src/Protocol/Protocol_1_9.cpp +++ b/src/Protocol/Protocol_1_9.cpp @@ -2110,9 +2110,20 @@ void cProtocol_1_9_0::WriteMobMetadata(cPacketizer & a_Pkt, const cMonster & a_M case mtSkeleton: { + auto & Skeleton = static_cast(a_Mob); a_Pkt.WriteBEUInt8(11); a_Pkt.WriteBEUInt8(METADATA_TYPE_VARINT); a_Pkt.WriteVarInt32(0); + + // Index 5 and 12 used for charging bow client animation. + a_Pkt.WriteBEUInt8(5); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBEInt8(0x02 | (Skeleton.IsChargingBow() ? 0x01 : 0x00)); + + a_Pkt.WriteBEUInt8(12); + a_Pkt.WriteBEUInt8(METADATA_TYPE_BYTE); + a_Pkt.WriteBool(Skeleton.IsChargingBow()); + break; } case mtSlime: -- cgit v1.2.3