diff --git a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj
index 5732d917..427e3b54 100644
--- a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj
+++ b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj
@@ -99,6 +99,10 @@
+
+
+
+
diff --git a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters
index 37b5ab11..48bb273a 100644
--- a/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters
+++ b/Adventures in Lestoria Tests/Adventures in Lestoria Tests.vcxproj.filters
@@ -66,5 +66,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/Adventures in Lestoria Tests/ItemTests.cpp b/Adventures in Lestoria Tests/ItemTests.cpp
new file mode 100644
index 00000000..7b8f5cc2
--- /dev/null
+++ b/Adventures in Lestoria Tests/ItemTests.cpp
@@ -0,0 +1,127 @@
+#pragma region License
+/*
+License (OLC-3)
+~~~~~~~~~~~~~~~
+
+Copyright 2024 Joshua Sigona
+
+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
+#include
+#include "ItemDrop.h"
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+using namespace olc::utils;
+
+INCLUDE_GFX
+INCLUDE_ITEM_DATA
+
+extern std::mt19937 rng;
+
+namespace ItemTests
+{
+ TEST_CLASS(ItemTest)
+ {
+ public:
+ std::unique_ptrtestGame;
+ InputGroup testKeyboardInput;
+ Player*player;
+ HWButton*testKey;
+ TEST_METHOD_INITIALIZE(ItemInitialize){
+ 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());
+ testGame->olc_SetTestingMode(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::drops.clear();
+ 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->pKeyboardState[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();
+ }
+ TEST_METHOD_CLEANUP(CleanupTests){
+ testGame->EndGame();
+ }
+ TEST_METHOD(ItemGiveTest){
+ Inventory::AddItem("Health Potion"s,3);
+ Assert::AreEqual(3U,Inventory::GetItemCount("Health Potion"s),L"Player has 3 Health Potions.");
+ }
+ TEST_METHOD(ItemRemoveTest){
+ Inventory::AddItem("Health Potion"s,3);
+ for(std::weak_ptr- &item:Inventory::GetItem("Health Potion"s))Inventory::RemoveItem(item,3);
+ Assert::AreEqual(0U,Inventory::GetItemCount("Health Potion"s),L"Player has no Health Potions.");
+ }
+ TEST_METHOD(ItemQuantityStackTest){
+ Inventory::AddItem("Health Potion"s,3);
+ Inventory::AddItem("Health Potion"s,3);
+ Assert::AreEqual(6U,Inventory::GetItemCount("Health Potion"s),L"Player has 6 Health Potions.");
+ }
+ TEST_METHOD(EquipmentNoStackTest){
+ Inventory::AddItem("Ring of the Slime King"s);
+ Inventory::AddItem("Ring of the Slime King"s);
+ Inventory::AddItem("Ring of the Slime King"s);
+ int itemCounter{};
+ for(std::weak_ptr
- &item:Inventory::GetItem("Ring of the Slime King"s))itemCounter++;
+ Assert::AreEqual(3,itemCounter,L"3 separate item entries for Ring of the Slime King.");
+ }
+ TEST_METHOD(UsingBlankLoadoutItemDoesNothing){
+ Assert::IsFalse(game->UseLoadoutItem(0),L"Using a blank loadout item slot (0) does not produce a result.");
+ Assert::IsFalse(game->UseLoadoutItem(1),L"Using a blank loadout item slot (1) does not produce a result.");
+ Assert::IsFalse(game->UseLoadoutItem(2),L"Using a blank loadout item slot (2) does not produce a result.");
+ }
+ };
+}
diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
index f5627b95..c92529b7 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj
@@ -681,6 +681,10 @@
+
+
+
+
diff --git a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
index 8b600ac8..7e6526ee 100644
--- a/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
+++ b/Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
@@ -660,6 +660,9 @@
Source Files\Effects
+
+ Header Files
+
diff --git a/Adventures in Lestoria/AdventuresInLestoria.cpp b/Adventures in Lestoria/AdventuresInLestoria.cpp
index 60152d1a..c1e4c421 100644
--- a/Adventures in Lestoria/AdventuresInLestoria.cpp
+++ b/Adventures in Lestoria/AdventuresInLestoria.cpp
@@ -3886,7 +3886,7 @@ void AiL::SetLoadoutItem(int slot,std::string itemName){
bool AiL::UseLoadoutItem(int slot){
if(slot<0||slot>GetLoadoutSize()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(GetLoadoutSize()-1)+").");
- if(GetLoadoutItem(slot).lock()->Amt()>0){
+ if(!ISBLANK(GetLoadoutItem(slot).lock())&&GetLoadoutItem(slot).lock()->Amt()>0){
Tutorial::GetTask(TutorialTaskName::USE_RECOVERY_ITEMS).I(A::ITEM_USE_COUNT)++;
Inventory::UseItem(GetLoadoutItem(slot).lock()->ActualName());
Inventory::AddLoadoutItemUsed(GetLoadoutItem(slot).lock()->ActualName(),slot);
diff --git a/Adventures in Lestoria/AdventuresInLestoria.h b/Adventures in Lestoria/AdventuresInLestoria.h
index 0ebf77a7..98c63e34 100644
--- a/Adventures in Lestoria/AdventuresInLestoria.h
+++ b/Adventures in Lestoria/AdventuresInLestoria.h
@@ -95,6 +95,7 @@ class AiL : public olc::PixelGameEngine
friend class Minimap;
friend class MonsterTests::MonsterTest;
friend class PlayerTests::PlayerTest;
+ friend class ItemTests::ItemTest;
std::unique_ptrplayer;
SplashScreen splash;
public:
@@ -324,7 +325,7 @@ public:
const std::string_view GetCurrentMapDisplayName()const;
int GetCurrentChapter();
void SetChapter(int chapter);
- const std::weak_ptr
- GetLoadoutItem(int slot);
+ const std::weak_ptr
- GetLoadoutItem(int slot); //Slot range is 0-2.
void SetLoadoutItem(int slot,std::string itemName);
int GetLoadoutSize()const;
void RestockLoadoutItems();
diff --git a/Adventures in Lestoria/ItemDrop.h b/Adventures in Lestoria/ItemDrop.h
index 8307fc58..359c4267 100644
--- a/Adventures in Lestoria/ItemDrop.h
+++ b/Adventures in Lestoria/ItemDrop.h
@@ -47,6 +47,7 @@ class ItemDrop{
friend class AiL;
friend class MonsterTests::MonsterTest;
friend class PlayerTests::PlayerTest;
+ friend class ItemTests::ItemTest;
vf2d pos;
vf2d speed{};
float zSpeed=0;
diff --git a/Adventures in Lestoria/TEST_DEFINES.h b/Adventures in Lestoria/TEST_DEFINES.h
new file mode 100644
index 00000000..fd0e92c4
--- /dev/null
+++ b/Adventures in Lestoria/TEST_DEFINES.h
@@ -0,0 +1,46 @@
+#pragma region License
+/*
+License (OLC-3)
+~~~~~~~~~~~~~~~
+
+Copyright 2024 Joshua Sigona
+
+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
+#pragma once
+
+namespace PlayerTests{
+ class PlayerTest;
+}
+
+namespace ItemTests{
+ class ItemTest;
+}
\ No newline at end of file
diff --git a/Adventures in Lestoria/Version.h b/Adventures in Lestoria/Version.h
index f36165f5..f0b8ec60 100644
--- a/Adventures in Lestoria/Version.h
+++ b/Adventures in Lestoria/Version.h
@@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
-#define VERSION_BUILD 9940
+#define VERSION_BUILD 9944
#define stringify(a) stringify_(a)
#define stringify_(a) #a
diff --git a/Adventures in Lestoria/olcPixelGameEngine.h b/Adventures in Lestoria/olcPixelGameEngine.h
index 244bce78..c51b9c38 100644
--- a/Adventures in Lestoria/olcPixelGameEngine.h
+++ b/Adventures in Lestoria/olcPixelGameEngine.h
@@ -407,6 +407,7 @@ return 0;
#include "Error.h"
#include "olcUTIL_Geometry2D.h"
#include "Pixel.h"
+#include "TEST_DEFINES.h"
#pragma endregion
#define PGE_VER 225
@@ -572,11 +573,6 @@ namespace X11
#endif
#pragma endregion
-
-namespace PlayerTests{
- class PlayerTest;
-}
-
// O------------------------------------------------------------------------------O
// | olcPixelGameEngine INTERFACE DECLARATION |
// O------------------------------------------------------------------------------O
@@ -942,6 +938,7 @@ namespace olc
{
friend class ViewPort;
friend class PlayerTests::PlayerTest;
+ friend class ItemTests::ItemTest;
struct StringDecalData{
char c;
vf2d sourcePos;