From a0896c63d7a02d1b90572d591a16a79b4274feac Mon Sep 17 00:00:00 2001 From: Alex Sweet Date: Tue, 10 Apr 2018 23:46:11 -0700 Subject: Smelting Gives Experience (#4094) * Smelting Exp Smelting now gives experience * Furnace.txt update Exp rewards are entered in furnace.txt, Reward calculation is now done is the furnaceentity class * furnace.txt update Changed alignment tabs to spaces Included documentation of exp in recipe * Updated StringToFloat changed strtod to strtof * Explicit Float to Int * Reworked Smelting Rewards * No C casts -Adds new function to the api -Sets reward counter to 0 in furnace constructor * Style and exp lock removed -Fixed style mistakes accoring to PR notes -XP isn't locked to a single player anymore * No Smelter API -Removed SetLastSmelter and GetLastSmelter -Fixed comments -Fixed log reward amounts --- src/BlockEntities/FurnaceEntity.cpp | 19 +++++++++++++++++++ src/BlockEntities/FurnaceEntity.h | 6 ++++++ src/FurnaceRecipe.cpp | 18 ++++++++++++++---- src/FurnaceRecipe.h | 1 + src/StringUtils.cpp | 12 ++++++++++++ src/StringUtils.h | 3 +++ src/UI/SlotArea.cpp | 7 ++++++- 7 files changed, 61 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/BlockEntities/FurnaceEntity.cpp b/src/BlockEntities/FurnaceEntity.cpp index 1f7f6e023..96a17782a 100644 --- a/src/BlockEntities/FurnaceEntity.cpp +++ b/src/BlockEntities/FurnaceEntity.cpp @@ -32,6 +32,7 @@ cFurnaceEntity::cFurnaceEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, in m_TimeCooked(0), m_FuelBurnTime(0), m_TimeBurned(0), + m_RewardCounter(0), m_IsLoading(false) { m_Contents.AddListener(*this); @@ -173,6 +174,23 @@ bool cFurnaceEntity::ContinueCooking(void) +int cFurnaceEntity::GetAndResetReward(void) +{ + int Reward = FloorC(m_RewardCounter); + float Remainder = m_RewardCounter - static_cast(Reward); + // Remainder is used as the percent chance of getting an extra xp point + if (GetRandomProvider().RandBool(Remainder)) + { + Reward++; + } + m_RewardCounter = 0.0; + return Reward; +} + + + + + void cFurnaceEntity::BroadcastProgress(short a_ProgressbarID, short a_Value) { cWindow * Window = GetWindow(); @@ -189,6 +207,7 @@ void cFurnaceEntity::BroadcastProgress(short a_ProgressbarID, short a_Value) void cFurnaceEntity::FinishOne() { m_TimeCooked = 0; + m_RewardCounter += m_CurrentRecipe->Reward; if (m_Contents.GetSlot(fsOutput).IsEmpty()) { diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h index 7b189be85..b1166c3bf 100644 --- a/src/BlockEntities/FurnaceEntity.h +++ b/src/BlockEntities/FurnaceEntity.h @@ -84,6 +84,9 @@ public: /** Returns true if there's time left before the current fuel is depleted */ bool HasFuelTimeLeft(void) const { return (GetFuelBurnTimeLeft() > 0); } + /** Calculates, resets, and returns the experience reward in this furnace */ + int GetAndResetReward(void); + // tolua_end void SetBurnTimes(int a_FuelBurnTime, int a_TimeBurned) @@ -130,6 +133,9 @@ protected: /** Amount of ticks that the current fuel has been burning */ int m_TimeBurned; + /** Running total of experience that can be picked up */ + float m_RewardCounter; + /** Is the block currently being loaded into the world? */ bool m_IsLoading; diff --git a/src/FurnaceRecipe.cpp b/src/FurnaceRecipe.cpp index a2199cd33..a4647b7a0 100644 --- a/src/FurnaceRecipe.cpp +++ b/src/FurnaceRecipe.cpp @@ -161,6 +161,7 @@ void cFurnaceRecipe::AddRecipeFromLine(const AString & a_Line, unsigned int a_Li Line.erase(std::remove_if(Line.begin(), Line.end(), isspace), Line.end()); int CookTime = 200; + float Reward = 0; std::unique_ptr InputItem = cpp14::make_unique(); std::unique_ptr OutputItem = cpp14::make_unique(); @@ -189,18 +190,27 @@ void cFurnaceRecipe::AddRecipeFromLine(const AString & a_Line, unsigned int a_Li return; } } - - if (!ParseItem(Sides[1], *OutputItem)) + const AStringVector & OutputSplit = StringSplit(Sides[1], "$"); + if (!ParseItem(OutputSplit[0], *OutputItem)) { - LOGWARNING("furnace.txt: line %d: Cannot parse output item \"%s\".", a_LineNum, Sides[1].c_str()); + LOGWARNING("furnace.txt: line %d: Cannot parse output item \"%s\".", a_LineNum, OutputSplit[0].c_str()); LOGINFO("Offending line: \"%s\"", a_Line.c_str()); return; } - + if (OutputSplit.size() > 1) + { + if (!StringToFloat(OutputSplit[1], Reward)) + { + LOGWARNING("furnace.txt: line %d: Cannot parse reward \"%s\".", a_LineNum, OutputSplit[1].c_str()); + LOGINFO("Offending line: \"%s\"", a_Line.c_str()); + return; + } + } cRecipe Recipe; Recipe.In = InputItem.release(); Recipe.Out = OutputItem.release(); Recipe.CookTime = CookTime; + Recipe.Reward = Reward; m_pState->Recipes.push_back(Recipe); } diff --git a/src/FurnaceRecipe.h b/src/FurnaceRecipe.h index 0779e18a4..84ee87092 100644 --- a/src/FurnaceRecipe.h +++ b/src/FurnaceRecipe.h @@ -30,6 +30,7 @@ public: cItem * In; cItem * Out; int CookTime; ///< How long this recipe takes to smelt, in ticks + float Reward; ///< Experience reward for creating 1 of this item }; /** Returns a recipe for the specified input, nullptr if no recipe found */ diff --git a/src/StringUtils.cpp b/src/StringUtils.cpp index b1f58f23c..ae0aec1ad 100644 --- a/src/StringUtils.cpp +++ b/src/StringUtils.cpp @@ -1051,3 +1051,15 @@ AString StringsConcat(const AStringVector & a_Strings, char a_Separator) } return res; } + +bool StringToFloat(const AString & a_String, float & a_Num) +{ + char *err; + a_Num = strtof(a_String.c_str(), &err); + if (*err != 0) + { + return false; + } + return true; +} + diff --git a/src/StringUtils.h b/src/StringUtils.h index a74239ec8..1c6cdf509 100644 --- a/src/StringUtils.h +++ b/src/StringUtils.h @@ -146,6 +146,9 @@ extern AStringVector MergeStringVectors(const AStringVector & a_Strings1, const /** Concatenates the specified strings into a single string, separated by the specified separator. */ extern AString StringsConcat(const AStringVector & a_Strings, char a_Separator); +/** Converts a string into a float. Returns false if the conversion fails. */ +extern bool StringToFloat(const AString & a_String, float & a_Num); + diff --git a/src/UI/SlotArea.cpp b/src/UI/SlotArea.cpp index d093bb337..ab1edf595 100644 --- a/src/UI/SlotArea.cpp +++ b/src/UI/SlotArea.cpp @@ -1909,7 +1909,6 @@ const cItem * cSlotAreaFurnace::GetSlot(int a_SlotNum, cPlayer & a_Player) const void cSlotAreaFurnace::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) { - UNUSED(a_Player); m_Furnace->SetSlot(a_SlotNum, a_Item); } @@ -1932,6 +1931,12 @@ void cSlotAreaFurnace::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Player) { + int Reward = m_Furnace->GetAndResetReward(); + if (Reward > 0) + { + a_Player.GetWorld()->SpawnExperienceOrb(a_Player.GetPosX(), a_Player.GetPosY(), a_Player.GetPosZ(), Reward); + } + /** TODO 2014-05-12 xdot: Figure out when to call this method. */ switch (a_Result.m_ItemType) { -- cgit v1.2.3