1
0

Player Xp

This commit is contained in:
Daniel O'Brien 2013-11-14 00:50:47 +11:00
parent 293051eca8
commit 3b47a07bac
5 changed files with 862 additions and 748 deletions

View File

@ -12,5 +12,6 @@ rs2k
Duralex Duralex
mtilden mtilden
Luksor Luksor
marmot
Please add yourself to this list if you contribute to MCServer. Please add yourself to this list if you contribute to MCServer.

View File

@ -44,6 +44,9 @@ extern bool g_BlockIsSolid[256];
/// Can torches be placed on this block? /// Can torches be placed on this block?
extern bool g_BlockIsTorchPlaceable[256]; extern bool g_BlockIsTorchPlaceable[256];
/// Max Erperience that possible to be incremented at once
#define MAX_EXPERIENCE_ORB_SIZE 2000 //ie from a ender dragon

View File

@ -1,4 +1,4 @@

#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Player.h" #include "Player.h"
@ -33,6 +33,7 @@
cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName) cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
: super(etPlayer, 0.6, 1.8) : super(etPlayer, 0.6, 1.8)
, m_GameMode(eGameMode_NotSet) , m_GameMode(eGameMode_NotSet)
@ -65,6 +66,10 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
, m_EatingFinishTick(-1) , m_EatingFinishTick(-1)
, m_IsChargingBow(false) , m_IsChargingBow(false)
, m_BowCharge(0) , m_BowCharge(0)
, m_XpLevel(0)
, m_XpP(0.f)
, m_XpTotal(0)
, m_XpNextLevelTotal(0)
{ {
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d", LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
a_PlayerName.c_str(), a_Client->GetIPString().c_str(), a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
@ -260,6 +265,67 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
bool cPlayer::SetExperience(int a_XpTotal)
{
if(!(a_XpTotal >= 0) || (a_XpTotal > (INT_MAX - m_XpTotal)))
{
LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_XpTotal);
return false; //oops, they gave us a dodgey number
}
m_XpTotal = a_XpTotal;
//now calculate XpP and XpLevel
//First Calc current level using quadratic eqn
m_XpLevel = CalcLevelFromXp(m_XpTotal);
//calculate total Xp for next level
m_XpNextLevelTotal = XpAtLevel(m_XpLevel+1);
//calulate Xp Percentage
m_XpP = (float)m_XpLevel / (float)m_XpNextLevelTotal;
return true;//aka happy :)
}
bool cPlayer::AddExperience(int a_Xp_delta)
{
if(a_Xp_delta > MAX_EXPERIENCE_ORB_SIZE || a_Xp_delta < 0)
{
//value was too large or negative, abort and report
LOGWARNING("Attempt was made to increment Xp by %d, max is %d and must be positive",
a_Xp_delta, MAX_EXPERIENCE_ORB_SIZE);
return false;
}
LOGD("Player \"%s\" earnt %d experience", m_PlayerName.c_str(), a_Xp_delta);
//update Xp, note there is no min
m_XpTotal += a_Xp_delta;
//update Xp percentage
if(m_XpTotal >= m_XpNextLevelTotal)
{
//oh actually, update their level first
m_XpLevel++;
m_XpNextLevelTotal = XpAtLevel(m_XpLevel+1);
}
m_XpP = (float)m_XpLevel / (float)m_XpNextLevelTotal;
return true;
}
void cPlayer::StartChargingBow(void) void cPlayer::StartChargingBow(void)
{ {
LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str()); LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str());
@ -1268,7 +1334,7 @@ bool cPlayer::LoadFromDisk()
cFile f; cFile f;
if (!f.Open(SourceFile, cFile::fmRead)) if (!f.Open(SourceFile, cFile::fmRead))
{ {
// This is a new player whom we haven't seen yet, bail out, let them have the defaults // This is a new player whom we haven't seen yet, bail, let them have the defaults
return false; return false;
} }
@ -1278,7 +1344,7 @@ bool cPlayer::LoadFromDisk()
LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str()); LOGWARNING("Cannot read player data from file \"%s\"", SourceFile.c_str());
return false; return false;
} }
f.Close(); f.Close(); //cool kids play nice
Json::Value root; Json::Value root;
Json::Reader reader; Json::Reader reader;
@ -1308,6 +1374,7 @@ bool cPlayer::LoadFromDisk()
} }
m_Health = root.get("health", 0).asInt(); m_Health = root.get("health", 0).asInt();
m_XpLevel = root.get("experience", 0).asInt();
m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt(); m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt(); m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble(); m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
@ -1354,6 +1421,7 @@ bool cPlayer::SaveToDisk()
root["rotation"] = JSON_PlayerRotation; root["rotation"] = JSON_PlayerRotation;
root["inventory"] = JSON_Inventory; root["inventory"] = JSON_Inventory;
root["health"] = m_Health; root["health"] = m_Health;
root["experience"] = m_XpTotal;
root["air"] = m_AirLevel; root["air"] = m_AirLevel;
root["food"] = m_FoodLevel; root["food"] = m_FoodLevel;
root["foodSaturation"] = m_FoodSaturationLevel; root["foodSaturation"] = m_FoodSaturationLevel;

View File

@ -63,6 +63,27 @@ public:
/// Returns the currently equipped boots; empty item if none /// Returns the currently equipped boots; empty item if none
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); } virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
/** Sets the experience total - XpTotal, updates XpLevel and XpP as appropriate
Returns true on success
should really only be called at init or player death
*/
bool SetExperience(int a_XpTotal);
/* Adds Xp, will not inc more than MAX_EXPERIENCE_ORB_SIZE!
Returns true on success
Updates XpLevel and XpP appropriately
*/
bool AddExperience(int a_Xp_delta);
/// Gets the experience total - XpTotal
inline int GetExperience(void) { return m_XpTotal; }
/// Gets the current level - XpLevel
inline int GetExperienceLevel(void) { return m_XpLevel; }
/// Gets the experience bar percentage - XpP
inline float GetExperiencePercentage(void) { return m_XpP; }
/// Starts charging the equipped bow /// Starts charging the equipped bow
void StartChargingBow(void); void StartChargingBow(void);
@ -289,7 +310,7 @@ public:
virtual bool IsSubmerged(void) const{ return m_IsSubmerged; } virtual bool IsSubmerged(void) const{ return m_IsSubmerged; }
// tolua_end // tolua_end
// cEntity overrides: // cEntity overrides:
virtual bool IsCrouched (void) const { return m_IsCrouched; } virtual bool IsCrouched (void) const { return m_IsCrouched; }
virtual bool IsSprinting(void) const { return m_IsSprinting; } virtual bool IsSprinting(void) const { return m_IsSprinting; }
@ -378,6 +399,27 @@ protected:
/// The world tick in which eating will be finished. -1 if not eating /// The world tick in which eating will be finished. -1 if not eating
Int64 m_EatingFinishTick; Int64 m_EatingFinishTick;
/// Player Xp levels etc
int m_XpLevel; //store this and m_XpP to save calculating each time
float m_XpP; //between 0 & 1
int m_XpTotal;
int m_XpNextLevelTotal; //save calculating this often
//Xp level defines
#define XP_TO_LEVEL15 255
#define XP_PER_LEVEL_TO15 17
#define XP_TO_LEVEL30 825
/// Caculates the Xp at a given level, ref: http://minecraft.gamepedia.com/XP
inline int XpAtLevel(int level) { return (int) ((level <= 15)? (15*level) :
((level <= 31)? (1.5*level*level - 29.5*level + 360) :
(3.5*level*level - 151.5*level + 2220))); }
/// inverse of XpAtLevel, ref: http://minecraft.gamepedia.com/XP values are as per this with pre-calculations
inline int CalcLevelFromXp(int XpTotal) { return (int) ((XpTotal <= XP_TO_LEVEL15)? XpTotal / XP_PER_LEVEL_TO15 : //level 0-15 or...
(XpTotal <= XP_TO_LEVEL30)? ( 29.5 + sqrt( 870.25 - (6 * ( 360 - XpTotal )))) / 3 : //level 15-30
(151.5 + sqrt( 22952.25 - (14 * (2220 - XpTotal)))) / 7); }//level 30+
bool m_IsChargingBow; bool m_IsChargingBow;
int m_BowCharge; int m_BowCharge;

File diff suppressed because it is too large Load Diff