diff --git a/C++ProjectTemplate b/C++ProjectTemplate index fdc8d7b..bd1bdb4 100755 Binary files a/C++ProjectTemplate and b/C++ProjectTemplate differ diff --git a/encounters.h b/encounters.h index 2ccc559..45c4759 100644 --- a/encounters.h +++ b/encounters.h @@ -7,6 +7,8 @@ using namespace olc; #include "battle.h" #include "item.h" +extern std::vector PARTY_INVENTORY; + namespace encounter{ enum{ ENCOUNTER_1, @@ -39,10 +41,13 @@ class Entity{ int channelTimeRemaining = 0; //The amount of channel time left until move can be performed. vd2d channelPos = {0,0}; //Where our channel is happening. std::vector inventory; //Used mostly for enemy spoils. - std::array equipment; //Equipment this character is using. + std::array equipment = {nullptr,nullptr,nullptr}; //Equipment this character is using. + bool isPlayer=false; //Whether or not this is a player entity. //Used for initializing players. Entity(int HP,int maxHP,int PP,int maxPP,int baseAtk,std::arrayresistances,int speed,std::vectormoveSet,std::vectoritems={},std::arrayequipment={},int damageReduction=0,bool smart=false,bool dumb=false) - :Entity(nullptr,HP,maxHP,PP,maxPP,baseAtk,resistances,speed,moveSet,items,equipment,damageReduction,smart,dumb){} + :Entity(nullptr,HP,maxHP,PP,maxPP,baseAtk,resistances,speed,moveSet,items,equipment,damageReduction,smart,dumb){ + isPlayer=true; + } //Use this for initializing enemies as it lets you specify an object. Entity(Object*obj,int HP,int maxHP,int PP,int maxPP,int baseAtk,std::arrayresistances,int speed,std::vectormoveSet,std::vectoritems={},std::arrayequipment={},int damageReduction=0,bool smart=false,bool dumb=false) :obj(obj),HP(HP),maxHP(maxHP),PP(PP),maxPP(maxPP),baseAtk(baseAtk),speed(speed),equipment(equipment),moveSet(moveSet),damageReduction(damageReduction),inventory(items),smart(smart),dumb(dumb){ @@ -100,6 +105,57 @@ class Entity{ void _SetDirectPP(int pp) { PP=pp; } + + //If index is -1, the item is inserted at the end of the list. Otherwise it's going to overwrite a certain slot. Be certain you swap the item before doing this! + void RemoveEquip(int slot,int index=-1) { + Item*CurrentEquip=equipment[slot]; + if (CurrentEquip==nullptr) { + return; + } + if (isPlayer) { + if (index==-1) { + PARTY_INVENTORY.push_back(CurrentEquip); + } else { + PARTY_INVENTORY[index]=CurrentEquip; + } + equipment[slot]=nullptr; + } else { + if (index==-1) { + inventory.push_back(CurrentEquip); + } else { + inventory[index]=CurrentEquip; + } + equipment[slot]=nullptr; + } + } + + //Will automatically swap items with current equipment so no need to call remove first. + void EquipItem(int index) { + Item*equip=nullptr; + if (isPlayer) { + equip=PARTY_INVENTORY[index]; + } else { + equip=inventory[index]; + } + if (equip==nullptr) { + return; + } + if (equip->stats.equip==EquipSlot::NONE) { + printf("Cannot equip %s! Does not have a valid Equip slot!\n",equip->name.c_str()); + return; + } + Item*CurrentEquip=equipment[equip->stats.equip]; + if (CurrentEquip==nullptr) { + if (isPlayer) { + PARTY_INVENTORY.erase(PARTY_INVENTORY.begin()+index); + } else { + inventory.erase(inventory.begin()+index); + } + } else { + RemoveEquip(CurrentEquip->stats.equip,index); + } + equipment[equip->stats.equip]=equip; + } }; class Encounter{ diff --git a/ideas b/ideas index 22d6a4c..0dc8ebc 100644 --- a/ideas +++ b/ideas @@ -158,4 +158,17 @@ When a move is selected, we'll visually display the tiles that are in range. If If no units are in range, you can perform the move, but no one will get hurt. Once a target is selected, if the move does not have a channel time, it will be immediately performed. Otherwise the channel will begin for that player. -Channels will be displayed in lieu of the ATB meter while channeling is happening. \ No newline at end of file +Channels will be displayed in lieu of the ATB meter while channeling is happening. + +==================== + +Items in Battle + +Equipment: + Weapons - Will use it instead for an attack (on that turn temporarily). + Armor - Equips the piece of armor. + +All Other Items: + If there is a Battle Move attached, performs that battle move. + + If the item has any restorative properties, they will be used at that time. diff --git a/item.h b/item.h index ccf57a3..c6d0819 100644 --- a/item.h +++ b/item.h @@ -24,6 +24,10 @@ namespace EquipSlot{ struct ItemStatsStruct{ int hpRecovery=0; int ppRecovery=0; + int atkIncrease=0; + int spdIncrease=0; + int hpIncrease=0; + Battle::Move*learnAbility=nullptr; int attack=0; int defense=0; EquipSlot::Equip equip=EquipSlot::NONE; //Whether or not this is equipment. @@ -37,7 +41,7 @@ class Item{ std::string description; Battle::Move*battlemove=nullptr; ItemStatsStruct stats; - Item(std::string name,std::string desc,ItemStatsStruct stats={0,0,0,0,EquipSlot::NONE,false,false},Battle::Move*battlemove=nullptr) + Item(std::string name,std::string desc,ItemStatsStruct stats={hpRecovery:0,ppRecovery:0,atkIncrease:0,spdIncrease:0,hpIncrease:0,learnAbility:nullptr,attack:0,defense:0,equip:EquipSlot::NONE,important:false,consumable:false},Battle::Move*battlemove=nullptr) :name(name),description(desc),stats(stats),battlemove(battlemove){} }; #endif \ No newline at end of file diff --git a/main.cpp b/main.cpp index 5e407d0..769bc96 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,4 @@ +#include "item.h" #define OLC_PGE_APPLICATION #include "pixelGameEngine.h" #define OLC_PGEX_SPLASHSCREEN @@ -22,6 +23,7 @@ const vd2d NO_NEIGHBOR = {-999,-999}; vd2d cameraPos={0,0}; PixelGameEngine*GAME; +std::vector PARTY_INVENTORY; enum{ ALPHA=α, @@ -158,6 +160,7 @@ public: int player_rollhp_display[4][3] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; int player_rollpp_display[4][3] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; int player_rollwait_counter[4] = {0,0,0,0}; + int previousEquip[4] = {-1,-1,-1,-1}; int SELECTED_TARGET=0; //Battle target that is selected. int BATTLE_TARGET=-99; //Negative numbers for players and positive numbers for enemy targets. int CURRENT_TURN=-99; //Who's turn we are enacting. @@ -170,7 +173,6 @@ public: bool ANYKEYPRESSED=false; bool ACTIONKEYPRESSED=false; std::vector> BATTLE_MOVELIST_DISPLAY; - std::vector PARTY_INVENTORY; std::map ADDITIONAL_FONT_VALS = { {α,0},{β,1},{γ,2},{Ω,3},{Σ,4}, }; @@ -178,6 +180,7 @@ public: int BATTLE_ANIMATION_TIMER=0; int BATTLE_ROLLING_COUNTER_WAITTIME = 0; //Number of frames to wait for each rolling counter. int BATTLE_HIT_SCREENSHAKE = 0; //Amount of time the screen will rapidly shake as getting hit. + bool ITEM_REQUIRES_EQUIPPING=false; bool MOUSE_PRESSED_DOWN=false,MOUSE_DOWN=false,MOUSE_RELEASED=false; //TODO Implement Mouse things. @@ -686,7 +689,7 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), }break; case 2:{ //Items selected. BATTLE_STATE=BattleState::ITEM_SELECT; - ITEM_SELECTION_CURSOR=0; + //ITEM_SELECTION_CURSOR=0; }break; case 3:{ //Defend selected. //DisplayMessageBox("Not implemented yet."); @@ -844,6 +847,9 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), if (UpPressed()) { if (BATTLE_SELECTION_CURSOR==0) { //Power was selected, so go back to the powers menu. BATTLE_STATE=BattleState::GRADE_SELECT; + } else + if (BATTLE_SELECTION_CURSOR==2) { //Item was selected, go back to item menu. + BATTLE_STATE=BattleState::ITEM_SELECT; } else { //This was a standard attack, go back to main menu. BATTLE_STATE=BattleState::SELECT_ACTION; } @@ -854,6 +860,7 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), BATTLE_ENCOUNTER->objs[i]->obj->highlighted=false; } PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=nullptr; + ITEM_REQUIRES_EQUIPPING=false; } if (ACTIONKEYPRESSED) { PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget=SELECTED_TARGET; @@ -965,7 +972,12 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), if (LeftPressed()&&!(ITEM_SELECTION_CURSOR&1)) { BATTLE_STATE=BattleState::SELECT_ACTION; } else { - HandleInventoryMenu(); + HandleInventoryNavigation(); + } + if (ACTIONKEYPRESSED) { + ITEM_REQUIRES_EQUIPPING=true; + PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::BASH]; + BATTLE_STATE=BattleState::TARGET_SELECT; } }break; } @@ -2800,6 +2812,12 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=nullptr; PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->atb=0; BATTLE_STATE=BattleState::WAIT; + if (previousEquip[-CURRENT_TURN-1]!=-1) { + Item*PrevEquip=PARTY_INVENTORY[previousEquip[-CURRENT_TURN-1]]; + PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->EquipItem(previousEquip[-CURRENT_TURN-1]); + printf("Equipped item: %s\n",PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->equipment[PrevEquip->stats.equip]->name.c_str()); + previousEquip[-CURRENT_TURN-1]=-1; + } CURRENT_TURN=-99; } else { BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove=nullptr; @@ -3193,6 +3211,21 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), BATTLE_ENCOUNTER->objs[i]->obj->highlighted=false; } PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelTimeRemaining=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->channelTime; + + if (ITEM_REQUIRES_EQUIPPING) { + Item*SelectedItem=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]; + if (SelectedItem->stats.equip==EquipSlot::WEAPON&&PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->equipment[SelectedItem->stats.equip]!=nullptr) { //Only swap back to the previous equip when there was nothing equipped to begin with. + previousEquip[-CURRENT_TURN-1]=ITEM_SELECTION_CURSOR; + } + int prevPartyInvenSize=PARTY_INVENTORY.size(); + PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->EquipItem(ITEM_SELECTION_CURSOR); + printf("Equipped item: %s\n",PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->equipment[SelectedItem->stats.equip]->name.c_str()); + ITEM_REQUIRES_EQUIPPING=false; + ITEM_SELECTION_CURSOR=std::clamp(ITEM_SELECTION_CURSOR,0,(int)PARTY_INVENTORY.size()-1); + if (prevPartyInvenSize&1&&PARTY_INVENTORY.size()==prevPartyInvenSize-1) { + ITEM_SELECTION_OFFSET-=2; + } + } } int CalculateDamage(Entity*attacker,Entity*defender) { @@ -3213,7 +3246,7 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), void RemoveItemFromPlayerInventory(int slot) { PARTY_INVENTORY.erase(PARTY_INVENTORY.begin()+slot); } - void HandleInventoryMenu() { + void HandleInventoryNavigation() { if (LeftPressed()||RightPressed()) { ITEM_SELECTION_CURSOR+=ITEM_SELECTION_CURSOR&1?-1:1; if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()) { @@ -3361,7 +3394,6 @@ This is a test message that lets us trigger straight from a cutscene! Cool!)"), } }; - int main() { SeasonI demo;