Added stat-based item enchant checks. Remove friend class dependencies from unit tests and added appropriate publicly exposed functions. Release Build 10538.
This commit is contained in:
		
							parent
							
								
									d4d325503e
								
							
						
					
					
						commit
						2f244e21ff
					
				| @ -101,6 +101,10 @@ | ||||
|     <ClCompile Include="..\Adventures in Lestoria\discord-files\store_manager.cpp" /> | ||||
|     <ClCompile Include="..\Adventures in Lestoria\discord-files\user_manager.cpp" /> | ||||
|     <ClCompile Include="..\Adventures in Lestoria\discord-files\voice_manager.cpp" /> | ||||
|     <ClCompile Include="EnchantTests.cpp"> | ||||
|       <SubType> | ||||
|       </SubType> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="GeometryTests.cpp" /> | ||||
|     <ClCompile Include="ItemTests.cpp"> | ||||
|       <SubType> | ||||
|  | ||||
| @ -69,5 +69,8 @@ | ||||
|     <ClCompile Include="ItemTests.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="EnchantTests.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
							
								
								
									
										213
									
								
								Adventures in Lestoria Tests/EnchantTests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								Adventures in Lestoria Tests/EnchantTests.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,213 @@ | ||||
| #pragma region License | ||||
| /*
 | ||||
| License (OLC-3) | ||||
| ~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| Copyright 2024 Joshua Sigona <sigonasr2@gmail.com> | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without modification, | ||||
| are permitted provided that the following conditions are met: | ||||
| 
 | ||||
| 1. Redistributions or derivations of source code must retain the above copyright | ||||
| notice, this list of conditions and the following disclaimer. | ||||
| 
 | ||||
| 2. Redistributions or derivative works in binary form must reproduce the above | ||||
| copyright notice. This list of conditions and the following	disclaimer must be | ||||
| reproduced in the documentation and/or other materials provided with the distribution. | ||||
| 
 | ||||
| 3. Neither the name of the copyright holder nor the names of its contributors may | ||||
| be used to endorse or promote products derived from this software without specific | ||||
| prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS	"AS IS" AND ANY | ||||
| EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
| OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT | ||||
| SHALL THE COPYRIGHT	HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
| INCIDENTAL,	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
| TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | ||||
| BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
| CONTRACT, STRICT LIABILITY, OR TORT	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||||
| ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
| SUCH DAMAGE. | ||||
| 
 | ||||
| Portions of this software are copyright © 2024 The FreeType | ||||
| Project (www.freetype.org). Please see LICENSE_FT.txt for more information. | ||||
| All rights reserved. | ||||
| */ | ||||
| #pragma endregion | ||||
| #include "CppUnitTest.h" | ||||
| #include "AdventuresInLestoria.h" | ||||
| #include "Tutorial.h" | ||||
| #include <random> | ||||
| #include <format> | ||||
| #include "ItemDrop.h" | ||||
| #include "DamageNumber.h" | ||||
| #include <ranges> | ||||
| 
 | ||||
| using namespace Microsoft::VisualStudio::CppUnitTestFramework; | ||||
| using namespace olc::utils; | ||||
| 
 | ||||
| INCLUDE_GFX | ||||
| INCLUDE_ITEM_DATA | ||||
| INCLUDE_DAMAGENUMBER_LIST | ||||
| 
 | ||||
| extern std::mt19937 rng; | ||||
| 
 | ||||
| namespace Test | ||||
| { | ||||
| 	template<class T> | ||||
| 	inline static void InRange(T initialVal,std::pair<T,T>range,std::wstring_view assertMessage){ | ||||
| 		Assert::IsTrue(initialVal>=range.first&&initialVal<=range.second,std::format(L"Expected: {}~{}   Actual: {} - {}",range.first,range.second,initialVal,assertMessage).c_str()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| namespace EnchantTests | ||||
| { | ||||
| 	TEST_CLASS(EnchantTest) | ||||
| 	{ | ||||
| 	public: | ||||
| 		std::unique_ptr<AiL>testGame; | ||||
| 		InputGroup testKeyboardInput; | ||||
| 		Player*player; | ||||
| 		const HWButton*testKey; | ||||
| 		TEST_METHOD_INITIALIZE(PlayerInitialize){ | ||||
| 			rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
 | ||||
| 			testGame.reset(new AiL(true)); | ||||
| 			ItemAttribute::Initialize(); | ||||
| 			ItemInfo::InitializeItems(); | ||||
| 			testGame->InitializeGraphics(); | ||||
| 			testGame->InitializeClasses(); | ||||
| 			sig::Animation::InitializeAnimations(); | ||||
| 			testGame->InitializeDefaultKeybinds(); | ||||
| 			testGame->InitializePlayer(); | ||||
| 			sig::Animation::SetupPlayerAnimations(); | ||||
| 			Menu::InitializeMenus(); | ||||
| 			Tutorial::Initialize(); | ||||
| 			Stats::InitializeDamageReductionTable(); | ||||
| 
 | ||||
| 			GameState::Initialize(); | ||||
| 			GameState::STATE=GameState::states.at(States::State::GAME_RUN); | ||||
| 			 | ||||
| 			#pragma region Setup a fake test map and test monster | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 				ItemDrop::ClearDrops(); | ||||
| 				MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f}; | ||||
| 				MONSTER_DATA["TestName"]=testMonsterData; | ||||
| 			#pragma endregion | ||||
| 
 | ||||
| 			player=testGame->GetPlayer(); | ||||
| 			//Setup key "0" as a test input
 | ||||
| 			testKeyboardInput.AddKeybind(Input{InputType::KEY,0}); | ||||
| 			testKey=testGame->GetKeyboardState(0); | ||||
| 			testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
 | ||||
| 			Menu::themes.SetInitialized(); | ||||
| 			GFX.SetInitialized(); | ||||
| 
 | ||||
| 			DAMAGENUMBER_LIST.clear(); | ||||
| 		} | ||||
| 		TEST_METHOD(HealthBoostCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100,player->GetMaxHealth(),L"Player starts with 100 health."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Health Boost"); | ||||
| 				Test::InRange(player->GetMaxHealth(),{103,105},L"Max Health not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(AttackBoostCheck){ | ||||
| 			player->SetBaseStat("Attack",100.f); | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100,player->GetAttack(),L"Player starts with 100 attack."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Attack Boost"); | ||||
| 				Test::InRange(player->GetAttack(),{103,105},L"Attack not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(MovementBoostCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100.0_Pct,player->GetMoveSpdMult(),L"Player starts with 100% Movespd."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Movement Boost"); | ||||
| 				Test::InRange(player->GetMoveSpdMult(),{103.0_Pct,105.0_Pct},L"Move Speed not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(AbilityHasteCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetCooldownReductionPct(),L"Player starts with 0% CDR."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Ability Haste"); | ||||
| 				Test::InRange(player->GetCooldownReductionPct(),{3.0_Pct,5.0_Pct},L"CDR not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(CritRateCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetCritRatePct(),L"Player starts with 0% Crit Rate."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Crit Rate"); | ||||
| 				Test::InRange(player->GetCritRatePct(),{3.0_Pct,5.0_Pct},L"Crit Rate not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(CritDamageCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(50.0_Pct,player->GetCritDmgPct(),L"Player starts with 50% Crit Damage."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Crit Damage"); | ||||
| 				Test::InRange(player->GetCritDmgPct(),{57.0_Pct,60.0_Pct},L"Crit Damage not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(StoneskinCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetDamageReductionPct(),L"Player starts with 0% Damage Reduction."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Stoneskin"); | ||||
| 				Test::InRange(player->GetDamageReductionPct(),{3.0_Pct,5.0_Pct},L"Damage Reduction not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(ManaPoolCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100,player->GetMaxMana(),L"Player starts with 100 mana."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Mana Pool"); | ||||
| 				Test::InRange(player->GetMaxMana(),{107,112},L"Mana Pool not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(MagicalProtectionCheck){ | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100,player->GetMaxHealth(),L"Player starts with 100 health."); | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetDamageReductionPct(),L"Player starts with 0% damage reduction."); | ||||
| 			Assert::AreEqual(100.0_Pct,player->GetMoveSpdMult(),L"Player starts with 100% move speed."); | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetHP6RecoveryPct(),L"Player starts with 0% HP/6 recovery."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Magical Protection"); | ||||
| 				Test::InRange(player->GetMaxHealth(),{102,103},L"Max Health not in expected range."); | ||||
| 				Test::InRange(player->GetDamageReductionPct(),{2.0_Pct,3.0_Pct},L"Damage Reduction not in expected range."); | ||||
| 				Test::InRange(player->GetMoveSpdMult(),{102.0_Pct,103.0_Pct},L"Move Speed % not in expected range."); | ||||
| 				Test::InRange(player->GetHP6RecoveryPct(),{1.0_Pct,1.0_Pct},L"HP/6 Recovery not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 		TEST_METHOD(AuraOfTheBeastCheck){ | ||||
| 			player->SetBaseStat("Attack",100.f); | ||||
| 			std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)}; | ||||
| 			Assert::AreEqual(100,player->GetAttack(),L"Player starts with 100 attack."); | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetCritRatePct(),L"Player starts with 0% crit rate."); | ||||
| 			Assert::AreEqual(0.0_Pct,player->GetCooldownReductionPct(),L"Player starts with 0% cooldown reduction."); | ||||
| 			Assert::AreEqual(50.0_Pct,player->GetCritDmgPct(),L"Player starts with 50% crit rate."); | ||||
| 			Inventory::EquipItem(nullRing,EquipSlot::RING1); | ||||
| 			for(int i:std::ranges::iota_view(0,1000)){ | ||||
| 				nullRing.lock()->EnchantItem("Aura of the Beast"); | ||||
| 				Test::InRange(player->GetAttack(),{102,103},L"Attack not in expected range."); | ||||
| 				Test::InRange(player->GetCritRatePct(),{2.0_Pct,3.0_Pct},L"Crit Rate not in expected range."); | ||||
| 				Test::InRange(player->GetCooldownReductionPct(),{2.0_Pct,3.0_Pct},L"Cooldown Reduction % not in expected range."); | ||||
| 				Test::InRange(player->GetCritDmgPct(),{53.0_Pct,57.0_Pct},L"Crit Damage not in expected range."); | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
| @ -74,13 +74,12 @@ namespace ItemTests | ||||
| 			Menu::InitializeMenus(); | ||||
| 			Tutorial::Initialize(); | ||||
| 			Stats::InitializeDamageReductionTable(); | ||||
| 
 | ||||
| 			GameState::Initialize(); | ||||
| 			GameState::STATE=GameState::states.at(States::State::GAME_RUN); | ||||
| 			 | ||||
| 			#pragma region Setup a fake test map and test monster | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 			ItemDrop::drops.clear(); | ||||
| 				ItemDrop::ClearDrops(); | ||||
| 				MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f}; | ||||
| 				MONSTER_DATA["TestName"]=testMonsterData; | ||||
| 			#pragma endregion | ||||
| @ -88,7 +87,7 @@ namespace ItemTests | ||||
| 			player=testGame->GetPlayer(); | ||||
| 			//Setup key "0" as a test input
 | ||||
| 			testKeyboardInput.AddKeybind(Input{InputType::KEY,0}); | ||||
| 			testKey=&testGame->pKeyboardState[0]; | ||||
| 			testKey=testGame->GetKeyboardState(0); | ||||
| 			testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
 | ||||
| 			Menu::themes.SetInitialized(); | ||||
| 			GFX.SetInitialized(); | ||||
|  | ||||
| @ -85,8 +85,8 @@ namespace MonsterTests | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"].ZoneData["UpperZone"]; | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"].ZoneData["LowerZone"]; | ||||
| 				game->currentLevel="CAMPAIGN_1_1"; | ||||
| 				ItemDrop::drops.clear(); | ||||
| 				game->_SetCurrentLevel("CAMPAIGN_1_1"); | ||||
| 				ItemDrop::ClearDrops(); | ||||
| 			#pragma endregion | ||||
| 
 | ||||
| 			MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f}; | ||||
| @ -98,7 +98,7 @@ namespace MonsterTests | ||||
| 		} | ||||
| 		void SetupMockMap(){ | ||||
| 			game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 			ItemDrop::drops.clear(); | ||||
| 			ItemDrop::ClearDrops(); | ||||
| 		} | ||||
| 		#pragma endregion | ||||
| 
 | ||||
|  | ||||
| @ -81,7 +81,7 @@ namespace PlayerTests | ||||
| 			 | ||||
| 			#pragma region Setup a fake test map and test monster | ||||
| 				game->MAP_DATA["CAMPAIGN_1_1"]; | ||||
| 				ItemDrop::drops.clear(); | ||||
| 				ItemDrop::ClearDrops(); | ||||
| 				MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f}; | ||||
| 				MONSTER_DATA["TestName"]=testMonsterData; | ||||
| 			#pragma endregion | ||||
| @ -89,7 +89,7 @@ namespace PlayerTests | ||||
| 			player=testGame->GetPlayer(); | ||||
| 			//Setup key "0" as a test input
 | ||||
| 			testKeyboardInput.AddKeybind(Input{InputType::KEY,0}); | ||||
| 			testKey=&testGame->pKeyboardState[0]; | ||||
| 			testKey=testGame->GetKeyboardState(0); | ||||
| 			testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
 | ||||
| 			Menu::themes.SetInitialized(); | ||||
| 			GFX.SetInitialized(); | ||||
|  | ||||
| @ -4448,3 +4448,7 @@ const std::map<std::string,TilesetData>&AiL::GetTilesets()const{ | ||||
| void AiL::AddToMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCount,MarkTime>markData){ | ||||
| 	lockOnTargets.emplace_back(markData); | ||||
| } | ||||
| 
 | ||||
| void AiL::_SetCurrentLevel(const MapName map){ | ||||
| 	currentLevel=map; | ||||
| } | ||||
| @ -95,9 +95,6 @@ class AiL : public olc::PixelGameEngine | ||||
| 	friend class sig::Animation; | ||||
| 	friend class Audio; | ||||
| 	friend class Minimap; | ||||
| 	friend class MonsterTests::MonsterTest; | ||||
| 	friend class PlayerTests::PlayerTest; | ||||
| 	friend class ItemTests::ItemTest; | ||||
| 	std::unique_ptr<Player>player; | ||||
| 	SplashScreen splash; | ||||
| public: | ||||
| @ -170,7 +167,6 @@ private: | ||||
| 	std::vector<TileGroup>upperForegroundTileGroups; | ||||
| 	int bridgeLayerIndex=-1; | ||||
| 	float bridgeFadeFactor=0.f; | ||||
| 	void InitializeClasses(); | ||||
| 	int DEBUG_PATHFINDING=0; | ||||
| 	std::vector<Monster*>monstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper; | ||||
| 	std::vector<IBullet*>bulletsLower,bulletsUpper; | ||||
| @ -386,6 +382,8 @@ public: | ||||
| 	void PlayFootstepSound(); | ||||
| 	const std::map<std::string,TilesetData>&GetTilesets()const; | ||||
| 	void AddToMarkedTargetList(std::tuple<std::weak_ptr<Monster>,StackCount,MarkTime>markData); | ||||
| 	void InitializeClasses(); | ||||
| 	void _SetCurrentLevel(const MapName map); //NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level.
 | ||||
| 
 | ||||
| 	struct TileGroupData{ | ||||
| 		vi2d tilePos; | ||||
|  | ||||
| @ -167,3 +167,7 @@ const ItemInfo*ItemDrop::GetItem()const{ | ||||
| const std::vector<ItemDrop>&ItemDrop::GetDrops(){ | ||||
| 	return ItemDrop::drops; | ||||
| } | ||||
| 
 | ||||
| void ItemDrop::ClearDrops(){ | ||||
| 	ItemDrop::drops.clear(); | ||||
| } | ||||
| @ -45,9 +45,6 @@ namespace MonsterTests{ | ||||
| 
 | ||||
| class ItemDrop{ | ||||
| 	friend class AiL; | ||||
| 	friend class MonsterTests::MonsterTest; | ||||
| 	friend class PlayerTests::PlayerTest; | ||||
| 	friend class ItemTests::ItemTest; | ||||
| 	vf2d pos; | ||||
| 	vf2d speed{}; | ||||
| 	float zSpeed=0; | ||||
| @ -66,6 +63,7 @@ public: | ||||
| 	void Draw()const; | ||||
| 	static void UpdateDrops(float fElapsedTime); | ||||
| 	static const std::vector<ItemDrop>&GetDrops(); | ||||
| 	static void ClearDrops(); | ||||
| 	float GetZ()const; | ||||
| 	static void SpawnItem(const ItemInfo*item,vf2d pos,bool isUpper); | ||||
| 	const ItemInfo*GetItem()const; | ||||
|  | ||||
| @ -155,7 +155,17 @@ void ItemEnchantInfo::Initialize(){ | ||||
| } | ||||
| 	 | ||||
| ItemEnchant::ItemEnchant(const std::string_view enchantName) | ||||
| :enchantName(std::string(enchantName)){} | ||||
| :enchantName(std::string(enchantName)){ | ||||
| 	for(const auto&[attr,val]:ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).minStatModifiers){ | ||||
| 		float minVal=ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).minStatModifiers.A_Read(attr); | ||||
| 		float maxVal=ItemEnchantInfo::ENCHANT_LIST.at(this->enchantName).maxStatModifiers.A_Read(attr); | ||||
| 		if(minVal==maxVal)A(attr)=minVal; | ||||
| 		else{ | ||||
| 			const auto&randRange{std::ranges::iota_view(int(minVal),int(maxVal))}; | ||||
| 			A(attr)=randRange[util::random()%randRange.size()]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const ItemEnchantInfo&ItemEnchantInfo::GetEnchant(const std::string_view enchantName){ | ||||
| 	return ENCHANT_LIST.at(std::string(enchantName)); | ||||
|  | ||||
| @ -1300,6 +1300,7 @@ void EntityStats::RecalculateEquipStats(){ | ||||
| 		for(auto&[key,size]:ItemAttribute::attributes){ | ||||
| 			equipStats.A(key)+=equip.lock()->GetStats().A_Read(key); | ||||
| 			equipStats.A(key)+=equip.lock()->RandomStats().A_Read(key); | ||||
| 			if(equip.lock()->HasEnchant())equipStats.A(key)+=equip.lock()->GetEnchant().value().A_Read(key); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -39,7 +39,7 @@ All rights reserved. | ||||
| #define VERSION_MAJOR 1 | ||||
| #define VERSION_MINOR 2 | ||||
| #define VERSION_PATCH 3 | ||||
| #define VERSION_BUILD 10532 | ||||
| #define VERSION_BUILD 10538 | ||||
| 
 | ||||
| #define stringify(a) stringify_(a) | ||||
| #define stringify_(a) #a | ||||
|  | ||||
| @ -937,8 +937,6 @@ namespace olc | ||||
| 	class PixelGameEngine | ||||
| 	{ | ||||
| 		friend class ViewPort; | ||||
| 		friend class PlayerTests::PlayerTest; | ||||
| 		friend class ItemTests::ItemTest; | ||||
| 		struct StringDecalData{ | ||||
| 			char c; | ||||
| 			vf2d sourcePos; | ||||
| @ -1205,6 +1203,8 @@ namespace olc | ||||
| 		const uint8_t GetMosaicEffect()const; | ||||
| 		void SetMosaicEffect(uint8_t effectLevel); | ||||
| 
 | ||||
| 		HWButton*const GetKeyboardState(uint8_t key); | ||||
| 
 | ||||
| 	public: | ||||
| 		static std::map<char,Pixel> charToColor; | ||||
| 		static std::string Grey; | ||||
| @ -4396,6 +4396,9 @@ namespace olc | ||||
| 	void PixelGameEngine::SetMosaicEffect(uint8_t effectLevel){ | ||||
| 		mosaic=std::max(uint8_t(1),effectLevel); | ||||
| 	} | ||||
| 	HWButton*const PixelGameEngine::GetKeyboardState(uint8_t key){ | ||||
| 		return &pKeyboardState[key]; | ||||
| 	} | ||||
| 
 | ||||
| 	void PixelGameEngine::UpdateTextEntry() | ||||
| 	{ | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| @ -6,7 +6,7 @@ ItemConfiguration | ||||
| 	Item Categories = ItemCategory.txt | ||||
| 	Equipment = Equipment-test.txt | ||||
| 	Weapons = Weapons.txt | ||||
| 	Accessories = Accessories.txt | ||||
| 	Accessories = Accessories-test.txt | ||||
| } | ||||
| Item | ||||
| { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user