From aea866f5b10d5ab0226260b4d25c70b1cfd31d2a Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 12 May 2014 21:38:52 +0300 Subject: Movement Statistics --- src/Entities/Entity.cpp | 15 +++++++-- src/Entities/Player.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++------ src/Entities/Player.h | 6 ++++ src/Item.h | 2 +- src/Mobs/Monster.cpp | 4 ++- src/Statistics.cpp | 2 +- 6 files changed, 101 insertions(+), 14 deletions(-) diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp index 9eb03acde..c393f89fd 100644 --- a/src/Entities/Entity.cpp +++ b/src/Entities/Entity.cpp @@ -312,12 +312,16 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI) if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer())) { + cPlayer * Player = (cPlayer *)a_TDI.Attacker; + // IsOnGround() only is false if the player is moving downwards - if (!((cPlayer *)a_TDI.Attacker)->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) + if (!Player->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain) { a_TDI.FinalDamage += 2; m_World->BroadcastEntityAnimation(*this, 4); // Critical hit } + + Player->GetStatManager().AddValue(statDamageDealt, round(a_TDI.FinalDamage * 10)); } m_Health -= (short)a_TDI.FinalDamage; @@ -580,9 +584,16 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk) if (m_AttachedTo != NULL) { - if ((m_Pos - m_AttachedTo->GetPosition()).Length() > 0.5) + Vector3d DeltaPos = m_Pos - m_AttachedTo->GetPosition(); + if (DeltaPos.Length() > 0.5) { SetPosition(m_AttachedTo->GetPosition()); + + if (IsPlayer()) + { + cPlayer * Player = (cPlayer *)this; + Player->UpdateMovementStats(DeltaPos); + } } } else diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 48bb509b9..3df7c4c34 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -194,6 +194,8 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk) return; } } + + m_Stats.AddValue(statMinutesPlayed, 1); if (!a_Chunk.IsValid()) { @@ -835,6 +837,8 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI) // Any kind of damage adds food exhaustion AddFoodExhaustion(0.3f); SendHealth(); + + m_Stats.AddValue(statDamageTaken, round(a_TDI.FinalDamage * 10)); return true; } return false; @@ -865,6 +869,8 @@ void cPlayer::KilledBy(cEntity * a_Killer) Pickups.Add(cItem(E_ITEM_RED_APPLE)); } + m_Stats.AddValue(statItemsDropped, Pickups.Size()); + m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! @@ -1262,6 +1268,9 @@ void cPlayer::MoveTo( const Vector3d & a_NewPos ) // TODO: should do some checks to see if player is not moving through terrain // TODO: Official server refuses position packets too far away from each other, kicking "hacked" clients; we should, too + + Vector3d DeltaPos = a_NewPos - GetPosition(); + UpdateMovementStats(DeltaPos); SetPosition( a_NewPos ); SetStance(a_NewPos.y + 1.62); @@ -1492,10 +1501,7 @@ void cPlayer::TossEquippedItem(char a_Amount) Drops.push_back(DroppedItem); } - double vX = 0, vY = 0, vZ = 0; - EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); - vY = -vY * 2 + 1.f; - m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player + TossItems(Drops); } @@ -1511,6 +1517,7 @@ void cPlayer::TossHeldItem(char a_Amount) char OriginalItemAmount = Item.m_ItemCount; Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount); Drops.push_back(Item); + if (OriginalItemAmount > a_Amount) { Item.m_ItemCount = OriginalItemAmount - a_Amount; @@ -1521,10 +1528,7 @@ void cPlayer::TossHeldItem(char a_Amount) } } - double vX = 0, vY = 0, vZ = 0; - EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); - vY = -vY * 2 + 1.f; - m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player + TossItems(Drops); } @@ -1536,10 +1540,21 @@ void cPlayer::TossPickup(const cItem & a_Item) cItems Drops; Drops.push_back(a_Item); + TossItems(Drops); +} + + + + + +void cPlayer::TossItems(const cItems & a_Items) +{ + m_Stats.AddValue(statItemsDropped, a_Items.Size()); + double vX = 0, vY = 0, vZ = 0; EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY); vY = -vY * 2 + 1.f; - m_World->SpawnItemPickups(Drops, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player + m_World->SpawnItemPickups(a_Items, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player } @@ -1935,6 +1950,59 @@ void cPlayer::HandleFloater() +void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos) +{ + StatValue Value = round(a_DeltaPos.Length() * 100); + + if (m_AttachedTo == NULL) + { + int PosX = POSX_TOINT; + int PosY = POSY_TOINT; + int PosZ = POSZ_TOINT; + + BLOCKTYPE Block; + NIBBLETYPE Meta; + if (!m_World->GetBlockTypeMeta(PosX, PosY, PosZ, Block, Meta)) + { + return; + } + + if ((Block == E_BLOCK_LADDER) && (a_DeltaPos.y > 0.0)) // Going up + { + m_Stats.AddValue(statDistClimbed, round(a_DeltaPos.y * 100)); + } + else + { + // TODO 2014-05-12 xdot: Other types + m_Stats.AddValue(statDistWalked, Value); + } + } + else + { + switch (m_AttachedTo->GetEntityType()) + { + case cEntity::etMinecart: m_Stats.AddValue(statDistMinecart, Value); break; + case cEntity::etBoat: m_Stats.AddValue(statDistBoat, Value); break; + case cEntity::etMonster: + { + cMonster * Monster = (cMonster *)m_AttachedTo; + switch (Monster->GetMobType()) + { + case cMonster::mtPig: m_Stats.AddValue(statDistPig, Value); break; + case cMonster::mtHorse: m_Stats.AddValue(statDistHorse, Value); break; + default: break; + } + break; + } + default: break; + } + } +} + + + + + void cPlayer::ApplyFoodExhaustionFromMovement() { if (IsGameModeCreative()) diff --git a/src/Entities/Player.h b/src/Entities/Player.h index b5c9d75cc..3de5e9c68 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -391,6 +391,9 @@ public: /** If true the player can fly even when he's not in creative. */ void SetCanFly(bool a_CanFly); + /** Update movement-related statistics. */ + void UpdateMovementStats(const Vector3d & a_DeltaPos); + /** Returns wheter the player can fly or not. */ virtual bool CanFly(void) const { return m_CanFly; } // tolua_end @@ -524,6 +527,9 @@ protected: /** Called in each tick if the player is fishing to make sure the floater dissapears when the player doesn't have a fishing rod as equipped item. */ void HandleFloater(void); + /** Tosses a list of items. */ + void TossItems(const cItems & a_Items); + /** Adds food exhaustion based on the difference between Pos and LastPos, sprinting status and swimming (in water block) */ void ApplyFoodExhaustionFromMovement(); diff --git a/src/Item.h b/src/Item.h index 2f65d5344..acbc880dc 100644 --- a/src/Item.h +++ b/src/Item.h @@ -228,7 +228,7 @@ public: void Add (const cItem & a_Item) {push_back(a_Item); } void Delete(int a_Idx); void Clear (void) {clear(); } - size_t Size (void) {return size(); } + size_t Size (void) const { return size(); } void Set (int a_Idx, short a_ItemType, char a_ItemCount, short a_ItemDamage); void Add (short a_ItemType, char a_ItemCount, short a_ItemDamage) diff --git a/src/Mobs/Monster.cpp b/src/Mobs/Monster.cpp index 62670907f..f3b408e68 100644 --- a/src/Mobs/Monster.cpp +++ b/src/Mobs/Monster.cpp @@ -464,8 +464,10 @@ bool cMonster::DoTakeDamage(TakeDamageInfo & a_TDI) return false; } - if((m_SoundHurt != "") && (m_Health > 0)) + if ((m_SoundHurt != "") && (m_Health > 0)) + { m_World->BroadcastSoundEffect(m_SoundHurt, (int)(GetPosX() * 8), (int)(GetPosY() * 8), (int)(GetPosZ() * 8), 1.0f, 0.8f); + } if (a_TDI.Attacker != NULL) { diff --git a/src/Statistics.cpp b/src/Statistics.cpp index 65addb0dd..5950eb96c 100644 --- a/src/Statistics.cpp +++ b/src/Statistics.cpp @@ -64,7 +64,7 @@ cStatInfo cStatInfo::ms_Info[statCount] = { cStatInfo(statDistHorse, "stat.horseOneCm"), cStatInfo(statJumps, "stat.jump"), cStatInfo(statItemsDropped, "stat.drop"), - cStatInfo(statDamageDealt, "stat.damageDealth"), + cStatInfo(statDamageDealt, "stat.damageDealt"), cStatInfo(statDamageTaken, "stat.damageTaken"), cStatInfo(statDeaths, "stat.deaths"), cStatInfo(statMobKills, "stat.mobKills"), -- cgit v1.2.3