cEntity::Killed(cEntity *) Handler; Achievement triggers; cPlayer::AwardAchievement()
This commit is contained in:
parent
6cb3483954
commit
b3d2b5b2c9
@ -370,6 +370,11 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
||||
if (m_Health <= 0)
|
||||
{
|
||||
KilledBy(a_TDI.Attacker);
|
||||
|
||||
if (a_TDI.Attacker != NULL)
|
||||
{
|
||||
a_TDI.Attacker->Killed(this);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -299,6 +299,9 @@ public:
|
||||
/// Called when the health drops below zero. a_Killer may be NULL (environmental damage)
|
||||
virtual void KilledBy(cEntity * a_Killer);
|
||||
|
||||
/// Called when the entity kills another entity
|
||||
virtual void Killed(cEntity * a_Victim) {}
|
||||
|
||||
/// Heals the specified amount of HPs
|
||||
void Heal(int a_HitPoints);
|
||||
|
||||
|
@ -192,6 +192,16 @@ bool cPickup::CollectedBy(cPlayer * a_Dest)
|
||||
int NumAdded = a_Dest->GetInventory().AddItem(m_Item);
|
||||
if (NumAdded > 0)
|
||||
{
|
||||
// Check achievements
|
||||
switch (m_Item.m_ItemType)
|
||||
{
|
||||
case E_BLOCK_LOG: a_Dest->AwardAchievement(achMineWood); break;
|
||||
case E_ITEM_LEATHER: a_Dest->AwardAchievement(achKillCow); break;
|
||||
case E_ITEM_DIAMOND: a_Dest->AwardAchievement(achDiamonds); break;
|
||||
case E_ITEM_BLAZE_ROD: a_Dest->AwardAchievement(achBlazeRod); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
m_Item.m_ItemCount -= NumAdded;
|
||||
m_World->BroadcastCollectPickup(*this, *a_Dest);
|
||||
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "../Vector3.h"
|
||||
|
||||
#include "../WorldStorage/StatSerializer.h"
|
||||
#include "../CompositeChat.h"
|
||||
|
||||
#include "inifile/iniFile.h"
|
||||
#include "json/json.h"
|
||||
@ -876,10 +877,6 @@ void cPlayer::KilledBy(cEntity * a_Killer)
|
||||
cPlayer* Killer = (cPlayer*)a_Killer;
|
||||
|
||||
GetWorld()->BroadcastChatDeath(Printf("%s was killed by %s", GetName().c_str(), Killer->GetName().c_str()));
|
||||
|
||||
Killer->GetStatManager().AddValue(statPlayerKills);
|
||||
|
||||
m_World->GetScoreBoard().AddPlayerScore(Killer->GetName(), cObjective::otPlayerKillCount, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -898,6 +895,33 @@ void cPlayer::KilledBy(cEntity * a_Killer)
|
||||
|
||||
|
||||
|
||||
void cPlayer::Killed(cEntity * a_Victim)
|
||||
{
|
||||
cScoreboard & ScoreBoard = m_World->GetScoreBoard();
|
||||
|
||||
if (a_Victim->IsPlayer())
|
||||
{
|
||||
m_Stats.AddValue(statPlayerKills);
|
||||
|
||||
ScoreBoard.AddPlayerScore(GetName(), cObjective::otPlayerKillCount, 1);
|
||||
}
|
||||
else if (a_Victim->IsMob())
|
||||
{
|
||||
if (((cMonster *)a_Victim)->GetMobFamily() == cMonster::mfHostile)
|
||||
{
|
||||
AwardAchievement(achKillMonster);
|
||||
}
|
||||
|
||||
m_Stats.AddValue(statMobKills);
|
||||
}
|
||||
|
||||
ScoreBoard.AddPlayerScore(GetName(), cObjective::otTotalKillCount, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::Respawn(void)
|
||||
{
|
||||
m_Health = GetMaxHealth();
|
||||
@ -1116,6 +1140,44 @@ void cPlayer::SetIP(const AString & a_IP)
|
||||
|
||||
|
||||
|
||||
unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
|
||||
{
|
||||
eStatistic Prerequisite = cStatInfo::GetPrerequisite(a_Ach);
|
||||
|
||||
if (Prerequisite != statInvalid)
|
||||
{
|
||||
if (m_Stats.GetValue(Prerequisite) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
StatValue Old = m_Stats.GetValue(a_Ach);
|
||||
|
||||
if (Old > 0)
|
||||
{
|
||||
return m_Stats.AddValue(a_Ach);
|
||||
}
|
||||
else
|
||||
{
|
||||
cCompositeChat Msg;
|
||||
Msg.AddTextPart(m_PlayerName + " has just earned the achievement ");
|
||||
Msg.AddTextPart(cStatInfo::GetName(a_Ach)); // TODO 2014-05-12 xdot: Use the proper cCompositeChat submessage type and send the actual title
|
||||
m_World->BroadcastChat(Msg);
|
||||
|
||||
StatValue New = m_Stats.AddValue(a_Ach);
|
||||
|
||||
/* Achievement Get! */
|
||||
m_ClientHandle->SendStatistics(m_Stats);
|
||||
|
||||
return New;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
|
||||
{
|
||||
SetPosition(a_PosX, a_PosY, a_PosZ);
|
||||
|
@ -180,6 +180,15 @@ public:
|
||||
/** Return the associated statistic and achievement manager. */
|
||||
cStatManager & GetStatManager() { return m_Stats; }
|
||||
|
||||
/** Awards the player an achievement.
|
||||
*
|
||||
* If all prerequisites are met, this method will award the achievement and will broadcast a chat message.
|
||||
* If the achievement has been already awarded to the player, this method will just increment the stat counter.
|
||||
*
|
||||
* Returns the _new_ stat value. (0 = Could not award achievement)
|
||||
*/
|
||||
unsigned int AwardAchievement(const eStatistic a_Ach);
|
||||
|
||||
void SetIP(const AString & a_IP);
|
||||
|
||||
// Sets the current gamemode, doesn't check validity, doesn't send update packets to client
|
||||
@ -312,6 +321,8 @@ public:
|
||||
|
||||
virtual void KilledBy(cEntity * a_Killer) override;
|
||||
|
||||
virtual void Killed(cEntity * a_Victim) override;
|
||||
|
||||
void Respawn(void); // tolua_export
|
||||
|
||||
void SetVisible( bool a_bVisible ); // tolua_export
|
||||
|
@ -1879,11 +1879,7 @@ void cProtocol172::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer)
|
||||
case 2:
|
||||
{
|
||||
// Open Inventory achievement
|
||||
cStatManager & Manager = m_Client->GetPlayer()->GetStatManager();
|
||||
Manager.AddValue(achOpenInv);
|
||||
|
||||
SendStatistics(Manager);
|
||||
|
||||
m_Client->GetPlayer()->AwardAchievement(achOpenInv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -496,6 +496,8 @@ void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
|
||||
DraggingItem = Result;
|
||||
Recipe.ConsumeIngredients(Grid);
|
||||
Grid.CopyToItems(PlayerSlots);
|
||||
|
||||
HandleCraftItem(Result, a_Player);
|
||||
}
|
||||
else if (DraggingItem.IsEqual(Result))
|
||||
{
|
||||
@ -505,6 +507,8 @@ void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
|
||||
DraggingItem.m_ItemCount += Result.m_ItemCount;
|
||||
Recipe.ConsumeIngredients(Grid);
|
||||
Grid.CopyToItems(PlayerSlots);
|
||||
|
||||
HandleCraftItem(Result, a_Player);
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,6 +598,27 @@ cCraftingRecipe & cSlotAreaCrafting::GetRecipeForPlayer(cPlayer & a_Player)
|
||||
|
||||
|
||||
|
||||
void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Player)
|
||||
{
|
||||
switch (a_Result.m_ItemType)
|
||||
{
|
||||
case E_BLOCK_WORKBENCH: a_Player.AwardAchievement(achCraftWorkbench); break;
|
||||
case E_BLOCK_FURNACE: a_Player.AwardAchievement(achCraftFurnace); break;
|
||||
case E_BLOCK_CAKE: a_Player.AwardAchievement(achBakeCake); break;
|
||||
case E_BLOCK_ENCHANTMENT_TABLE: a_Player.AwardAchievement(achCraftEnchantTable); break;
|
||||
case E_BLOCK_BOOKCASE: a_Player.AwardAchievement(achBookshelf); break;
|
||||
case E_ITEM_WOODEN_PICKAXE: a_Player.AwardAchievement(achCraftPickaxe); break;
|
||||
case E_ITEM_WOODEN_SWORD: a_Player.AwardAchievement(achCraftSword); break;
|
||||
case E_ITEM_STONE_PICKAXE: a_Player.AwardAchievement(achCraftBetterPick); break;
|
||||
case E_ITEM_WOODEN_HOE: a_Player.AwardAchievement(achCraftHoe); break;
|
||||
case E_ITEM_BREAD: a_Player.AwardAchievement(achMakeBread); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSlotAreaAnvil:
|
||||
@ -1401,6 +1426,21 @@ void cSlotAreaFurnace::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
|
||||
|
||||
|
||||
|
||||
void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Player)
|
||||
{
|
||||
/** TODO 2014-05-12 xdot: Figure out when to call this method. */
|
||||
switch (a_Result.m_ItemType)
|
||||
{
|
||||
case E_ITEM_IRON: a_Player.AwardAchievement(achAcquireIron); break;
|
||||
case E_ITEM_COOKED_FISH: a_Player.AwardAchievement(achCookFish); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSlotAreaInventoryBase:
|
||||
|
||||
|
@ -254,6 +254,9 @@ protected:
|
||||
|
||||
/// Retrieves the recipe for the specified player from the map, or creates one if not found
|
||||
cCraftingRecipe & GetRecipeForPlayer(cPlayer & a_Player);
|
||||
|
||||
/// Called after an item has been crafted to handle statistics e.t.c.
|
||||
void HandleCraftItem(const cItem & a_Result, cPlayer & a_Player);
|
||||
} ;
|
||||
|
||||
|
||||
@ -397,6 +400,9 @@ protected:
|
||||
|
||||
// cItemGrid::cListener overrides:
|
||||
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
|
||||
|
||||
/// Called after an item has been smelted to handle statistics e.t.c.
|
||||
void HandleSmeltItem(const cItem & a_Result, cPlayer & a_Player);
|
||||
} ;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user