SeasonI/main.cpp
sigonasr2 5827bcb8a6 Test suite setup preparation
Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
2022-10-23 02:47:09 -05:00

4890 lines
224 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "entity.h"
#include "item.h"
#include "layers.h"
#include <string>
#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h"
#define OLC_PGEX_SPLASHSCREEN
#include "splash.h"
#define OLC_SOUNDWAVE
#include "defines.h"
#include "soundwaveEngine.h"
#include "tiles.h"
#include "references.h"
#include "states.h"
#include "flags.h"
#include <assert.h>
#include "cutscene.h"
#include "encounters.h"
#include "particle.h"
#include "effect.h"
#include "battleproperty.h"
//#include "test/test.h"
using namespace olc;
std::vector<Object*> OBJECTS;
const vd2d NO_NEIGHBOR = {-999,-999};
PixelGameEngine*GAME;
vd2d cameraPos={0,0};
std::vector<Item*> PARTY_INVENTORY;
enum{
ALPHA=α,
BETA=β,
GAMMA=γ,
OMEGA=Ω,
SIGMA=Σ,
};
class Map{
public:
std::string filename;
std::string l2filename;
std::string l3filename;
std::string l4filename;
std::string l5filename;
Decal*tileset;
std::vector<Encounter*> encounters;
Map(std::string fname,std::string layer2_fname,std::string layer3_fname,std::string layer4_fname,std::string layer5_fname,Decal*tileset) {
this->filename=fname;
this->l2filename=layer2_fname;
this->l3filename=layer3_fname;
this->l4filename=layer4_fname;
this->l5filename=layer5_fname;
this->tileset=tileset;
}
};
class DamageNumber{
public:
int damage; //If it's negative then it's a healing number.
vd2d pos;
int timer;
DamageNumber(int damage,vd2d pos,int timer=90)
:damage(damage),pos(pos),timer(timer){}
};
int frameCount=0;
float elapsedTime=0;
const float TARGET_RATE = 1/60.0;
int MAP_WIDTH=-1;
int MAP_HEIGHT=-1;
Map*CURRENT_MAP=nullptr;
Map*MAP_ONETT=nullptr;
int GAME_STATE = GameState::EDITOR;
vi2d SELECTED_TILE={0,0};
vi2d HIGHLIGHTED_TILE={0,0};
int EDITING_LAYER=layer::DYNAMIC;
int SELECTED_OBJ_ID = PLAYER;
int OBJ_DISPLAY_OFFSET = 0;
bool GAME_FLAGS[128]={};
std::array<Object*,4> PARTY_MEMBER_OBJ={};
std::array<int,4> PARTY_MEMBER_ID={};
std::array<Entity*,7> PARTY_MEMBER_STATS={};
bool messageBoxVisible=false;
std::string messageBoxText="";
std::string targetText="";
std::string messageBoxFinalText="";
int messageBoxMarker=0;
int messageBoxStartMarker=0; //Start of text display.
int messageBoxStopMarker=0; //End of text display for current printout.
int messageBoxFrameWaitTime=1;
bool messageBoxLoad=false; //Set to true when ready to load a message in.
std::map<int,vi2d> additionalChars={};
Cutscene*TestCutscene=nullptr;
Cutscene*CurrentCutscene=nullptr;
ActionType CurrentAction=ActionType::NONE;
double CUTSCENE_FADE_VALUE=0;
std::vector<CutsceneAction*>CUTSCENE_QUEUE={};
std::map<BattleMoveName,Battle::Move*>MOVELIST={};
std::array<vd2d,PARTY_TRAIL_LENGTH> partyTrail={vd2d{0,0}};
int PARTY_MEMBER_COUNT = 1;
int ENCOUNTER_SELECTED = 0;
int ENCOUNTER_OFFSET = 0;
std::vector<Encounter*>ENCOUNTER_LIST={};
Encounter*EDITING_ENCOUNTER=nullptr;
Encounter*BATTLE_ENCOUNTER=nullptr;
int BATTLE_STATE=BattleState::MOVE_CAMERA;
int CAMERA_WAIT_TIMER=0;
int player_rollhp_counter[4][3] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
int player_rollpp_counter[4][3] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
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.
int BATTLE_SELECTION_CURSOR=0;
int POWER_SELECTION_CURSOR[4]={0,0,0,0};
int POWER_GRADE_CURSOR[4]={0,0,0,0};
int ITEM_SELECTION_CURSOR=0;
int ITEM_SELECTION_OFFSET=0;
int TARGET_SELECTION_CURSOR=0;
bool ANYKEYPRESSED=false;
bool ACTIONKEYPRESSED=false;
std::vector<std::vector<Battle::Move*>> BATTLE_MOVELIST_DISPLAY;
std::map<int,int> ADDITIONAL_FONT_VALS = {
{α,0},{β,1},{γ,2},{Ω,3},{Σ,4},
};
int POWER_SELECTION_OFFSET[4]={0,0,0,0};
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;
std::string EQUIP_$ITEM_DISPLAY=" "; //Use this to change the $ITEM tag modifier for abilities.
std::vector<CustomItemMessage> BATTLE_CUSTOM_MSGS={}; //Used for displaying additional information during battles.
CustomItemMessage BATTLE_CURRENT_CUSTOM_MSG={};
int BATTLE_CUSTOM_MESSAGE_WAIT_TIME=0;
Item*BATTLE_CUSTOM_ITEM=nullptr;
std::vector<Item*> BATTLE_SPOILS_LIST={};
std::string BATTLE_SPOILS_MESSAGE="";
int OVERWORLD_MENU_SELECTION=0;
std::vector<std::string> INTERACTION_MESSAGES={};
bool CLOSE_OVERWORLD_WINDOW=false; //When set to true, should cause the overworld menu to close as well once the dialog box is closed.
int OVERWORLD_POWER_SELECTION_CURSOR[4]={0,0,0,0};
int OVERWORLD_POWER_GRADE_CURSOR=0;
int OVERWORLD_POWER_SELECTION_OFFSET[4]={0,0,0,0};
int OVERWORLD_GRADE_SELECTION_OFFSET=0;
int OVERWORLD_POWER_SELECTION_MEMBER=-1;
Battle::Move*OVERWORLD_SELECTED_POWER;
int OVERWORLD_TARGET_SELECTION=0;
bool HEALING_OVERWORLD_MEMBERS=false; //When set to true, members will be healed as dialog boxes are closed using the HEALING_OVERWORLD_MEMBER variable.
int HEALING_OVERWORLD_MEMBER=0;
bool HEALING_OVERWORLD_SINGLE_MEMBER=false; //When set to true, a single member is being healed.
bool OVERWORLD_ITEM_BEING_USED=false; //When set to true, we need to equip an item after target selected.
std::string DISPLAY_TARGET_MESSAGE=""; //Display some text while selecting a target.
Key KEY_LASTPRESSED=NONE;
int lastPress=0;
int lastRepeatedFrame=0;
EquipSlot::Equip EQUIP_MENU_SLOT=EquipSlot::WEAPON;
int EQUIP_ITEM_MENU_CURSOR=0;
int EQUIP_ITEM_MENU_OFFSET=0;
std::vector<int> EQUIP_ITEM_MENU_CONTENTS={};
int MESSAGE_BOX_DIALOG_ANSWER=-1;
int MESSAGE_BOX_DIALOG_CHOICES_MADE=0;
std::vector<std::string> MESSAGE_BOX_CHOICE_LIST={};
bool waitingForChoice=false;
int MESSAGE_BOX_DIALOG_CHOICE_CURSOR=0;
Object*INTERACTING_WITH=nullptr;
std::vector<std::pair<Item*,int>> SHOP_ITEMS={};
int MONEY=0;
int ENEMY_MONEY_SUM=0;
int SHOP_MENU_CURSOR=0;
Object*SHOPKEEPER_INTERACTING_WITH=nullptr;
/*
[Choice1,Choice2,Choice3]
After a choice, dialog parser will jump to appropriate branch labeled as:
0: Stuff
1: Stuff
2: Stuff
In addition, each branch will store its choice selector in an incrementing variable.
*/
void DisplayMessageBox(std::string targetT) {
targetText=targetT;
messageBoxText="";
messageBoxFinalText="";
messageBoxLoad=true;
messageBoxVisible=true;
messageBoxMarker=0;
messageBoxStartMarker=0;
messageBoxStopMarker=0;
}
void SetupShop(Object*shopkeeper,std::vector<std::pair<Item*,int>> shopItems){
SHOP_MENU_CURSOR=0;
SHOP_ITEMS.clear();
SHOP_ITEMS=shopItems;
SHOPKEEPER_INTERACTING_WITH=shopkeeper;
}
bool MOUSE_PRESSED_DOWN=false,MOUSE_DOWN=false,MOUSE_RELEASED=false; //TODO Implement Mouse things.
std::vector<std::vector<TILE*>> MAP={}; //The foreground layer.
std::vector<std::vector<TILE*>> MAP2={};
std::vector<std::vector<TILE*>> MAP3={};
std::vector<std::vector<TILE*>> MAP4={};
std::vector<std::vector<TILE*>> MAP5={}; //Collision Layer
std::map<std::string,Decal*> SPRITES;
std::map<std::string,Animation*> ANIMATIONS={};
std::map<int,Object*> OBJ_INFO={};
std::map<Property,BattleProperty*> BATTLE_PROPERTIES={};
std::vector<Particle*> PARTICLES={};
std::vector<DamageNumber*> DAMAGE_NUMBERS={};
std::map<std::pair<int,int>,vd2d> MOVEMENT_GRID={};
std::map<ItemName,Item*>ITEMLIST={};
vi2d SELECTED_MOVE_SQUARE={};
FountainEffect*FOUNTAIN_EFFECT=nullptr;
FireFountainEffect*FIREFOUNTAIN_EFFECT=nullptr;
Effect*CURRENT_EFFECT=nullptr;
class SeasonI : public PixelGameEngine
{
public:
SeasonI()
{
sAppName = "Season I: Winters of Loneliness";
}
public:
bool OnUserCreate() override
{
srand(time(NULL));
GAME=this;
for (int i=1;i<6;i++) {
CreateLayer();
EnableLayer(i,true);
}
SetPixelMode(Pixel::ALPHA);
ConsoleCaptureStdOut(true);
// Called once at the start, so create things here
FOUNTAIN_EFFECT = new FountainEffect(250,200);
FIREFOUNTAIN_EFFECT = new FireFountainEffect(400,200);
EnableLayer(layer::COLLISION,false);
SetupMoveList();
SetupItemList();
SetupPartyMemberStats();
SetupAnimations();
SetupObjectInfo();
SetupEncounters();
SetupBattleProperties();
SetGameFlag(Flag::TEST_FLAG1,false);
SetGameFlag(Flag::TEST_FLAG2,false);
SetGameFlag(Flag::TEST_FLAG3,false);
SetGameFlag(Flag::HAS_MAIN,true);
SetGameFlag(Flag::HAS_NESS,true);
SetGameFlag(Flag::HAS_PAULA,true);
SetGameFlag(Flag::HAS_ANNA,true);
additionalChars[α]={0,0};
additionalChars[β]={8,0};
additionalChars[Ω]={16,0};
additionalChars[Σ]={24,0};
additionalChars[γ]={32,0};
MAP_ONETT=new Map("map0","map0_2","map0_3","map0_4","map0_5",SPRITES["terrainmap.png"]);
CURRENT_MAP=MAP_ONETT;
//OBJ_INFO["PLAYER"]=PLAYER_ANIMATION;
LoadMap(MAP_ONETT);
TestCutscene=new Cutscene({
Fade(),
CreateObjects({
new Standard_Obj(PLAYER,"player",{64,64},ANIMATIONS["player.png"],{1,1},MAGENTA),
new Standard_Obj(PLAYER,"player",{136,136},ANIMATIONS["player.png"],{1,1},RED),
new Standard_Obj(PLAYER,"player",{96,96},ANIMATIONS["player.png"],{1,1},DARK_GREEN),
}),
Fade(true),
SetFlagWhenCutsceneEnds(Flag::TEST_FLAG1),
PanCamera({128,128},BOTH,1),
MoveCutsceneObjectAsync(1,{80,64},5),
PanCamera({64,0},BOTH),
DialogBoxAsync(R"(Hello!
This is a test message that lets us trigger straight from a cutscene! Cool!)"),
ModifyObject(0,ANIMATIONS["player.png"],{5,5},MAGENTA),
MoveCutsceneObject(1,{320,64},1),});
AddItemToPlayerInventory(ItemName::LIGHT_JACKET);
AddItemToPlayerInventory(ItemName::LIGHT_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::HEAVY_JACKET);
AddItemToPlayerInventory(ItemName::LIGHT_JACKET);
AddItemToPlayerInventory(ItemName::COPPER_BRACELET);
AddItemToPlayerInventory(ItemName::MIRACLE_FOOD_LUNCH);
AddItemToPlayerInventory(ItemName::MIRACLE_FOOD_LUNCH);
AddItemToPlayerInventory(ItemName::MIRACLE_FOOD_LUNCH);
AddItemToPlayerInventory(ItemName::BOMB);
AddItemToPlayerInventory(ItemName::BOMB);
AddItemToPlayerInventory(ItemName::BOMB);
AddItemToPlayerInventory(ItemName::BOMB);
AddItemToPlayerInventory(ItemName::SOME_STUPIDLY_LONG_FEATHER);
AddItemToPlayerInventory(ItemName::SOME_STUPIDLY_LONG_FEATHER);
AddItemToPlayerInventory(ItemName::SOME_STUPIDLY_LONG_FEATHER);
for (int i=0;i<20;i++) {
AddItemToPlayerInventory(ItemName::COOKIE);
}
AddItemToPlayerInventory(ItemName::CRACKED_BAT);
for (int i=0;i<8;i++) {
AddItemToPlayerInventory(ItemName::PIZZA);
}
AddItemToPlayerInventory(ItemName::TEE_BALL_BAT);
AddItemToPlayerInventory(ItemName::FREEZE_PACKET);
return true;
}
bool OnUserUpdate(float fElapsedTime) override
{
elapsedTime+=fElapsedTime;
while (elapsedTime>TARGET_RATE) {
elapsedTime-=TARGET_RATE;
updateGame();
}
keyUpdates();
SetDrawTarget(nullptr);
Clear(BLANK);
SetDrawTarget(layer::COLLISION);
if (EDITING_LAYER!=layer::COLLISION) {
Clear(MAGENTA);
} else {
Clear(BLANK);
}
SetDrawTarget(layer::HIGH);
Clear(BLANK);
SetDrawTarget(layer::DYNAMIC);
Clear(BLANK);
SetDrawTarget(layer::GROUND);
Clear(BLANK);
SetDrawTarget(layer::BACKGROUND);
Clear(BLANK);
drawGame();
return true;
}
void GetAnyKeyPress(olc::Key keypress) override {
if (keypress==UP||keypress==DOWN||keypress==RIGHT||keypress==LEFT||
keypress==W||keypress==A||keypress==S||keypress==D||
keypress==NP2||keypress==NP4||keypress==NP5||keypress==NP6||keypress==NP8) {
KEY_LASTPRESSED=keypress;
lastPress=frameCount;
lastRepeatedFrame=frameCount;
}
if (messageBoxVisible&&!waitingForChoice) {
if (messageBoxMarker==messageBoxFinalText.length()) {
if (messageBoxStartMarker+messageBoxStopMarker<targetText.length()) {
messageBoxStartMarker+=messageBoxStopMarker;
messageBoxStopMarker=0;
messageBoxFinalText="";
messageBoxText="";
messageBoxMarker=0;
messageBoxLoad=true;
} else {
messageBoxVisible=false;
if (CLOSE_OVERWORLD_WINDOW&&INTERACTION_MESSAGES.size()==0) {
GAME_STATE=GameState::GAME_WORLD;
CLOSE_OVERWORLD_WINDOW=false;
}
if (INTERACTING_WITH!=nullptr) {
INTERACTING_WITH->DialogClosed();
INTERACTING_WITH=nullptr;
}
if (HEALING_OVERWORLD_MEMBERS) {
if (HEALING_OVERWORLD_MEMBER==0||HEALING_OVERWORLD_MEMBER==2) {
DisplayMessageBox("");
}
Entity*castingMember=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]];
castingMember->selectedMove=OVERWORLD_SELECTED_POWER;
while (HEALING_OVERWORLD_MEMBER<PARTY_MEMBER_COUNT) {
Entity*target=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[HEALING_OVERWORLD_MEMBER]];
if (target->GetHP()>0) {
int healAmt = CalculateHealing(castingMember);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+HEALING_OVERWORLD_MEMBER*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(-healAmt,box+cameraPos));
target->AddHP(healAmt);
targetText+=target->obj->name+" recovered "+std::to_string(healAmt)+" hitpoints.\n";
messageBoxLoad=true;
messageBoxVisible=true;
HEALING_OVERWORLD_MEMBER++;
break;
}
HEALING_OVERWORLD_MEMBER++;
}
if (HEALING_OVERWORLD_MEMBER>=PARTY_MEMBER_COUNT) {
HEALING_OVERWORLD_MEMBERS=false;
}
castingMember->selectedMove=nullptr;
}
if (HEALING_OVERWORLD_SINGLE_MEMBER) {
Entity*castingMember=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]];
castingMember->selectedMove=OVERWORLD_SELECTED_POWER;
Entity*target=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_TARGET_SELECTION]];
int healAmt = CalculateHealing(castingMember);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+OVERWORLD_TARGET_SELECTION*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(-healAmt,box+cameraPos));
target->AddHP(healAmt);
if (target->GetHP()>0) {
targetText+=target->obj->name+" recovered "+std::to_string(healAmt)+" hitpoints.";
} else {
targetText+="But it failed.";
}
messageBoxLoad=true;
printf("Called 4\n");
messageBoxVisible=true;
HEALING_OVERWORLD_SINGLE_MEMBER=false;
castingMember->selectedMove=nullptr;
}
}
} else {
while (MessageBoxAllowedToAdvance()) {
AdvanceMessageBox();
}
}
} else {
ANYKEYPRESSED=true;
if (!UpPressed()&&!DownPressed()&&!LeftPressed()&&!RightPressed()) {
ACTIONKEYPRESSED=true;
}
}
}
void updateGame(){
frameCount++;
for (auto obj:OBJECTS) {
if (obj->animationSpd!=0&&obj->frameCount++>obj->animationSpd) {
obj->frameCount=0;
obj->frameIndex++;
}
}
if (!messageBoxVisible&&INTERACTION_MESSAGES.size()>0) {
DisplayMessageBox(INTERACTION_MESSAGES.front());
INTERACTION_MESSAGES.erase(INTERACTION_MESSAGES.begin());
}
for (int i=0;i<DAMAGE_NUMBERS.size();i++) {
DamageNumber*numb=DAMAGE_NUMBERS[i];
if (numb->timer>0) {
numb->pos.y-=(numb->timer/180.0F);
numb->timer--;
} else {
delete numb;
DAMAGE_NUMBERS.erase(DAMAGE_NUMBERS.begin()+i--);
continue;
}
}
for (int i=0;i<PARTICLES.size();i++) {
if (!PARTICLES[i]->update()) {
delete PARTICLES[i];
PARTICLES.erase(PARTICLES.begin()+i);
i--;
continue;
}
PARTICLES[i]->particleUpdate();
}
if (CURRENT_EFFECT!=nullptr) {
if (!CURRENT_EFFECT->update()) {
CURRENT_EFFECT=nullptr;
for (int i=0;i<PARTICLES.size();i++) {
delete PARTICLES[i];
}
PARTICLES.clear();
}
}
if (GetCurrentCutsceneAction()!=ActionType::NONE) {
CurrentAction=GetCurrentCutsceneAction();
CurrentCutscene->LockAction();
}
HandleRollingCounters();
HandleBattle();
HandleCutscenes();
switch (GAME_STATE) {
case GameState::TILE_SELECT:{
if (!TabHeld()) {
GAME_STATE=GameState::EDITOR;
}
if (GetMouse(0).bHeld) {
int selectedTileX=GetMouseX()/TILEMAP_EDITOR_TILESIZE;
int selectedTileY=GetMouseY()/TILEMAP_EDITOR_TILESIZE;
if (selectedTileX*TILEMAP_EDITOR_DRAW_MULT>=0&&selectedTileX*TILEMAP_EDITOR_DRAW_MULT<TILEMAP_SIZE_X&&selectedTileY*TILEMAP_EDITOR_DRAW_MULT<TILEMAP_SIZE_Y&&selectedTileY*TILEMAP_EDITOR_DRAW_MULT>=0) {
SELECTED_TILE={selectedTileX,selectedTileY};
}
}
}break;
case GameState::ENCOUNTER_SELECT:{
if (!GetKey(SHIFT).bHeld) {
GAME_STATE=GameState::EDITOR;
}
}break;
case GameState::GAME_WORLD:{
if (PlayerCanMove()) {
bool moved=false;
vd2d movementComponents = {0,0};
if (UpHeld()) {
movementComponents.y-=1;
}
if (DownHeld()) {
movementComponents.y+=1;
}
if (LeftHeld()) {
movementComponents.x-=1;
}
if (RightHeld()) {
movementComponents.x+=1;
}
if (movementComponents.mag()>0) {
if (PARTY_MEMBER_OBJ[0]->SmoothMove(movementComponents)) {
UpdatePlayerTrail(movementComponents);
moved=true;
}
}
if (moved) {
const vi2d cameraOffset={WIDTH/2,HEIGHT/2};
cameraPos=PARTY_MEMBER_OBJ[0]->GetPos()-cameraOffset;
}
if (moved&&BATTLE_ENCOUNTER==nullptr) {
for (int i=0;i<CURRENT_MAP->encounters.size();i++) {
if (CURRENT_MAP->encounters[i]->IsEncounterAlive()&&CURRENT_MAP->encounters[i]->IsInRange(PARTY_MEMBER_OBJ[0]->GetPos())) {
BATTLE_STATE=BattleState::MOVE_CAMERA;
SetupRollingHitpointCounters();
BATTLE_ENCOUNTER=CURRENT_MAP->encounters[i];
break;
}
}
}
}
}break;
case GameState::EDITOR:{
if (IsTextEntryEnabled()) {
return;
}
if (TabHeld()) {
GAME_STATE=GameState::TILE_SELECT;
}
if (GetKey(SHIFT).bHeld) {
GAME_STATE=GameState::ENCOUNTER_SELECT;
}
if (PlayerCanMove()) {
if (GetKey(I).bHeld) {
if (PARTY_MEMBER_OBJ[0]->SmoothMove({0,-1})) {
UpdatePlayerTrail({0,-1});
}
}
if (GetKey(K).bHeld) {
if (PARTY_MEMBER_OBJ[0]->SmoothMove({0,1})) {
UpdatePlayerTrail({0,1});
}
}
if (GetKey(J).bHeld) {
if (PARTY_MEMBER_OBJ[0]->SmoothMove({-1,0})) {
UpdatePlayerTrail({-1,0});
}
}
if (GetKey(L).bHeld) {
if (PARTY_MEMBER_OBJ[0]->SmoothMove({1,0})) {
UpdatePlayerTrail({1,0});
}
}
}
int selectedTileX=(GetMouseX()+cameraPos.x)/32;
int selectedTileY=(GetMouseY()+cameraPos.y)/32;
if (selectedTileX<MAP_WIDTH&&selectedTileY<MAP_HEIGHT&&selectedTileX>=0&&selectedTileY>=0) {
HIGHLIGHTED_TILE={selectedTileX,selectedTileY};
}
if (GetMouse(0).bHeld) {
switch (EDITING_LAYER) {
case layer::COLLISION:{
TILE*tile=MAP5[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=SELECTED_TILE.x;
tile->tileY=SELECTED_TILE.y;
}break;
case layer::HIGH:{
TILE*tile=MAP[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=SELECTED_TILE.x;
tile->tileY=SELECTED_TILE.y;
}break;
case layer::DYNAMIC:{
TILE*tile=MAP2[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=SELECTED_TILE.x;
tile->tileY=SELECTED_TILE.y;
}break;
case layer::GROUND:{
TILE*tile=MAP3[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=SELECTED_TILE.x;
tile->tileY=SELECTED_TILE.y;
}break;
case layer::BACKGROUND:{
TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=SELECTED_TILE.x;
tile->tileY=SELECTED_TILE.y;
}break;
}
} else
if (GetMouse(1).bHeld) {
switch (EDITING_LAYER) {
case layer::COLLISION:{
TILE*tile=MAP5[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=tile->tileY=15;
}break;
case layer::HIGH:{
TILE*tile=MAP[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=tile->tileY=15;
}break;
case layer::DYNAMIC:{
TILE*tile=MAP2[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=tile->tileY=15;
}break;
case layer::GROUND:{
TILE*tile=MAP3[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=tile->tileY=15;
}break;
case layer::BACKGROUND:{
TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
tile->tileX=tile->tileY=15;
}break;
}
}
}break;
}
if (messageBoxVisible) {
AdvanceMessageBox();
}
//CAMERA UPDATES MUST BE LAST!!! COLLISIONS RELY ON THE GAME POSITION STATES REMAINING THE SAME!
cameraUpdate();
}
void AdvanceMessageBox() {
if (messageBoxLoad) {
const int MESSAGE_BORDER_X=4;
const int MESSAGE_BORDER_Y=4;
bool charsWritten=false;
std::string lastLine="";
while (messageBoxStartMarker+messageBoxStopMarker<targetText.length()&&GetTextSizeProp(messageBoxFinalText).y<HEIGHT/4-MESSAGE_BORDER_Y) {
if (targetText[messageBoxStopMarker+messageBoxStartMarker]=='[') {
while (targetText[messageBoxStopMarker+messageBoxStartMarker]!='<') {
messageBoxFinalText+=targetText[messageBoxStopMarker+++messageBoxStartMarker];
}
messageBoxFinalText+=targetText[messageBoxStopMarker+++messageBoxStartMarker];
break;
}
while (messageBoxStartMarker+messageBoxStopMarker<targetText.length()&&GetTextSizeProp(messageBoxFinalText).x<WIDTH/2-MESSAGE_BORDER_X) {
if (!charsWritten&&targetText[messageBoxStopMarker+messageBoxStartMarker]!=' ') {
messageBoxFinalText+=targetText[messageBoxStopMarker+++messageBoxStartMarker];
charsWritten=true;
} else
if (charsWritten){
messageBoxFinalText+=targetText[messageBoxStopMarker+++messageBoxStartMarker];
} else {
messageBoxStartMarker++;
}
}
if (GetTextSizeProp(messageBoxFinalText).x>=WIDTH/2-MESSAGE_BORDER_X) {
while (messageBoxFinalText[messageBoxStopMarker]!=' ') {
messageBoxStopMarker--;
}
messageBoxFinalText.erase(messageBoxFinalText.begin()+messageBoxStopMarker,messageBoxFinalText.end());
messageBoxFinalText+='\n';
charsWritten=false;
}
}
messageBoxLoad=false;
} else {
if (MessageBoxAllowedToAdvance()) {
if (messageBoxFinalText[messageBoxMarker]=='[') {
messageBoxMarker++;
waitingForChoice=true;
MESSAGE_BOX_CHOICE_LIST.clear();
std::string newMessageBoxChoice="";
while (messageBoxFinalText[messageBoxMarker]!=']') {
if (messageBoxFinalText[messageBoxMarker]==',') {
MESSAGE_BOX_CHOICE_LIST.push_back(newMessageBoxChoice);
newMessageBoxChoice="";
messageBoxMarker++;
} else
{
newMessageBoxChoice+=messageBoxFinalText[messageBoxMarker++];
}
}
MESSAGE_BOX_CHOICE_LIST.push_back(newMessageBoxChoice);
newMessageBoxChoice="";
for (int i=0;i<MESSAGE_BOX_CHOICE_LIST.size();i++) {
printf("%s\n",MESSAGE_BOX_CHOICE_LIST[i].c_str());
}
MESSAGE_BOX_DIALOG_CHOICE_CURSOR=0;
messageBoxMarker++;
} else
if (!waitingForChoice){
messageBoxText+=messageBoxFinalText[messageBoxMarker++];
}
}
}
}
//CAMERA UPDATES MUST BE LAST!!! COLLISIONS RELY ON THE GAME POSITION STATES REMAINING THE SAME!
void cameraUpdate() {
switch (GAME_STATE) {
case GameState::EDITOR:{
//CAMERA MOVEMENTS MUST BE LAST!!!
if (UpHeld()) {
cameraPos.y-=CAMERA_MOVESPD;
}
if (RightHeld()) {
cameraPos.x+=CAMERA_MOVESPD;
}
if (LeftHeld()) {
cameraPos.x-=CAMERA_MOVESPD;
}
if (DownHeld()) {
cameraPos.y+=CAMERA_MOVESPD;
}
}break;
}
}
void OnTextEntryComplete(const std::string&text) override{
if (EDITING_LAYER==layer::ENCOUNTER&&EDITING_ENCOUNTER!=nullptr) {
int numb=0;
for (int i=0;i<text.size();i++) {
numb*=10;
numb+=text[i]-'0';
}
EDITING_ENCOUNTER->chance=numb;
}
}
void keyUpdates() {
if (GetKey(F1).bPressed) {
ConsoleShow(F1,false);
}
if (GetKey(O).bPressed) {
StartEffect(FOUNTAIN_EFFECT);
}
if (GetKey(KEY_LASTPRESSED).bReleased) {
KEY_LASTPRESSED=NONE;
}
if (waitingForChoice) {
if (UpPressed()) {
MESSAGE_BOX_DIALOG_CHOICE_CURSOR--;
if (MESSAGE_BOX_DIALOG_CHOICE_CURSOR<0) {
MESSAGE_BOX_DIALOG_CHOICE_CURSOR=MESSAGE_BOX_CHOICE_LIST.size()-1;
}
if (MESSAGE_BOX_DIALOG_CHOICE_CURSOR==0) {
KEY_LASTPRESSED=NONE;
}
}
if (DownPressed()) {
MESSAGE_BOX_DIALOG_CHOICE_CURSOR=(MESSAGE_BOX_DIALOG_CHOICE_CURSOR+1)%MESSAGE_BOX_CHOICE_LIST.size();
if (MESSAGE_BOX_DIALOG_CHOICE_CURSOR==MESSAGE_BOX_CHOICE_LIST.size()-1) {
KEY_LASTPRESSED=NONE;
}
}
if (ACTIONKEYPRESSED) {
MESSAGE_BOX_DIALOG_ANSWER=MESSAGE_BOX_DIALOG_CHOICE_CURSOR;
waitingForChoice=false;
std::string responseText="";
while (messageBoxFinalText[messageBoxMarker]=='\t') {
messageBoxMarker++;
}
if (messageBoxFinalText[messageBoxMarker]=='>') {
messageBoxMarker++;
int counter=0;
while (messageBoxFinalText[messageBoxMarker]-'0'!=MESSAGE_BOX_DIALOG_CHOICE_CURSOR) {
while(messageBoxFinalText[messageBoxMarker]!='>'&&messageBoxFinalText[messageBoxMarker]!='<'&&messageBoxFinalText[messageBoxMarker]!='\t') {
messageBoxMarker++;
}
messageBoxMarker++;
}
messageBoxMarker+=2;
}
while (messageBoxFinalText[messageBoxMarker]!='<'&&messageBoxFinalText[messageBoxMarker]!='>'&&messageBoxFinalText[messageBoxMarker]!='\t') {
responseText+=messageBoxFinalText[messageBoxMarker++];
}
if (INTERACTING_WITH!=nullptr) {
INTERACTING_WITH->ChoiceMade(MESSAGE_BOX_DIALOG_CHOICE_CURSOR);
}
DisplayMessageBox("");
targetText=responseText;
}
goto reset;
}
if (BATTLE_ENCOUNTER!=nullptr&&!messageBoxVisible) {
switch (BATTLE_STATE) {
case BattleState::SELECT_ACTION:{
if (CURRENT_TURN<0) {
if (UpPressed()||DownPressed()) {
KEY_LASTPRESSED=NONE;
if (BATTLE_SELECTION_CURSOR%2==0) {
BATTLE_SELECTION_CURSOR++;
} else {
BATTLE_SELECTION_CURSOR--;
}
}
if (RightPressed()) {
BATTLE_SELECTION_CURSOR=(BATTLE_SELECTION_CURSOR+2)%6;
if (BATTLE_SELECTION_CURSOR>=4) {
KEY_LASTPRESSED=NONE;
}
}
if (LeftPressed()) {
BATTLE_SELECTION_CURSOR-=2;
if (BATTLE_SELECTION_CURSOR<0) {
BATTLE_SELECTION_CURSOR+=6;
}
if (BATTLE_SELECTION_CURSOR<=1) {
KEY_LASTPRESSED=NONE;
}
}
if (ACTIONKEYPRESSED) {
switch (BATTLE_SELECTION_CURSOR) {
case 0:{ //Power selected.
BATTLE_STATE=BattleState::POWER_SELECT;
PopulateBattleMoveList(-CURRENT_TURN-1);
}break;
case 1:{ //Attack selected.
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::BASH];
SetupTargetSelect();
}break;
case 2:{ //Items selected.
BATTLE_STATE=BattleState::ITEM_SELECT;
//ITEM_SELECTION_CURSOR=0;
}break;
case 3:{ //Defend selected.
//DisplayMessageBox("Not implemented yet.");
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::DEFEND];
ConfirmPlayerTargetSelection();
BATTLE_STATE=BattleState::WAIT;
}break;
case 4:{ //Move selected.
//DisplayMessageBox("Not implemented yet.");
BATTLE_STATE=BattleState::MOVE_SELECT;
SELECTED_MOVE_SQUARE={0,0};
PopulateMovementGrid(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->obj->GetPosWithOrigin(),CalculateSpeedGridMovementAmount(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->stats.speed));
}break;
case 5:{ //Run selected.
DisplayMessageBox("Not implemented yet.");
}break;
}
}
}
}break;
case BattleState::POWER_SELECT:{
if (CURRENT_TURN<0) {
if (DownPressed()) {
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=0;
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]=0;
} else {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]+1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-POWER_SELECTION_OFFSET[-CURRENT_TURN-1]>=4) {
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]++;
}
}
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==0) {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=(int)BATTLE_MOVELIST_DISPLAY.size()-1;
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-3,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
} else {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]<POWER_SELECTION_OFFSET[-CURRENT_TURN-1]) {
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]--;
}
}
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==0) {
KEY_LASTPRESSED=NONE;
}
}
if (LeftPressed()) {
BATTLE_STATE=BattleState::SELECT_ACTION;
}
if (ACTIONKEYPRESSED||RightPressed()) {
BATTLE_STATE=BattleState::GRADE_SELECT;
}
}
}break;
case BattleState::GRADE_SELECT:{
if (CURRENT_TURN<0) {
if (RightPressed()) {
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=(POWER_GRADE_CURSOR[-CURRENT_TURN-1]+1)%BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size();
if (POWER_GRADE_CURSOR[-CURRENT_TURN-1]==BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size()-1) {
KEY_LASTPRESSED=NONE;
}
}
if (DownPressed()||UpPressed()||LeftPressed()&&POWER_GRADE_CURSOR[-CURRENT_TURN-1]==0) {
if (UpPressed()) {
if (BATTLE_MOVELIST_DISPLAY.size()>1) {
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==0) {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=(int)BATTLE_MOVELIST_DISPLAY.size()-1;
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_GRADE_CURSOR[-CURRENT_TURN-1],0,(int)BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size()-1);
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-3,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
} else {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_GRADE_CURSOR[-CURRENT_TURN-1],0,(int)BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size()-1);
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]<POWER_SELECTION_OFFSET[-CURRENT_TURN-1]) {
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]--;
}
}
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==0) {
KEY_LASTPRESSED=NONE;
}
}
} else
if (DownPressed()) {
if (BATTLE_MOVELIST_DISPLAY.size()>1) {
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=0;
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=0;
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]=0;
} else {
POWER_SELECTION_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_SELECTION_CURSOR[-CURRENT_TURN-1]+1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_GRADE_CURSOR[-CURRENT_TURN-1],0,(int)BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size()-1);
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]-POWER_SELECTION_OFFSET[-CURRENT_TURN-1]>=4) {
POWER_SELECTION_OFFSET[-CURRENT_TURN-1]++;
}
}
if (POWER_SELECTION_CURSOR[-CURRENT_TURN-1]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
KEY_LASTPRESSED=NONE;
}
}
} else {
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=0;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=nullptr;
BATTLE_STATE=BattleState::POWER_SELECT;
}
} else
if (LeftPressed()) {
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=std::clamp(POWER_GRADE_CURSOR[-CURRENT_TURN-1]-1,0,(int)(BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]].size())-1);
if (POWER_GRADE_CURSOR[-CURRENT_TURN-1]==0) {
KEY_LASTPRESSED=NONE;
}
}
if (ACTIONKEYPRESSED) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->GetPP()>=BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]][POWER_GRADE_CURSOR[-CURRENT_TURN-1]]->PPCost) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=BATTLE_MOVELIST_DISPLAY[POWER_SELECTION_CURSOR[-CURRENT_TURN-1]][POWER_GRADE_CURSOR[-CURRENT_TURN-1]];
SetupTargetSelect();
}
}
}
}break;
case BattleState::TARGET_SELECT:{
if (LeftPressed()) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->friendly) {
do {
SELECTED_TARGET++;
if (SELECTED_TARGET==0) {
SELECTED_TARGET=-4;
}
} while (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-SELECTED_TARGET-1]]->GetHP()<=0&&!getProperty(Property::REVIVE,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove));
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-SELECTED_TARGET-1]]->obj->GetPosWithOrigin();
} else {
do {
SELECTED_TARGET--;
if (SELECTED_TARGET<0) {
SELECTED_TARGET=BATTLE_ENCOUNTER->objs.size()-1;
}
} while (BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->GetHP()<=0);
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->GetPosWithOrigin();
}
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_OBJ[i]->highlighted=false;
}
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
BATTLE_ENCOUNTER->objs[i]->obj->highlighted=false;
}
for (auto&ent:GetEntitiesInRange(SELECTED_TARGET,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
ent->obj->highlighted=true;
}
}
if (RightPressed()) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->friendly) {
do {
SELECTED_TARGET-=1;
if (SELECTED_TARGET<-PARTY_MEMBER_COUNT) {
SELECTED_TARGET=-1;
}
} while (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-SELECTED_TARGET-1]]->GetHP()<=0&&!getProperty(Property::REVIVE,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove));
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-SELECTED_TARGET-1]]->obj->GetPosWithOrigin();
} else {
do {
SELECTED_TARGET=(SELECTED_TARGET+1)%BATTLE_ENCOUNTER->objs.size();
} while (BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->GetHP()<=0);
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->GetPosWithOrigin();
}
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_OBJ[i]->highlighted=false;
}
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
BATTLE_ENCOUNTER->objs[i]->obj->highlighted=false;
}
for (auto&ent:GetEntitiesInRange(SELECTED_TARGET,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
ent->obj->highlighted=true;
}
}
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;
}
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_OBJ[i]->highlighted=false;
}
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
BATTLE_ENCOUNTER->objs[i]->obj->highlighted=false;
}
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=nullptr;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=DEFAULT_CHANNELPOS;
ITEM_REQUIRES_EQUIPPING=false;
}
if (ACTIONKEYPRESSED) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget=SELECTED_TARGET;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->SubtractPP(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->PPCost);
ConfirmPlayerTargetSelection();
BATTLE_STATE=BattleState::WAIT;
}
}break;
case BattleState::MOVE_SELECT:{
if (LeftPressed()) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x-i,SELECTED_MOVE_SQUARE.y})) {
SELECTED_MOVE_SQUARE.x-=i;
goto escapeLeft;
}
}
for (int j=1;j<=8;j++) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x-i,SELECTED_MOVE_SQUARE.y+j})) {
SELECTED_MOVE_SQUARE.x-=i;
SELECTED_MOVE_SQUARE.y+=j;
goto escapeLeft;
}
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x-i,SELECTED_MOVE_SQUARE.y-j})) {
SELECTED_MOVE_SQUARE.x-=i;
SELECTED_MOVE_SQUARE.y-=j;
goto escapeLeft;
}
}
}
}
escapeLeft:
if (RightPressed()) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x+i,SELECTED_MOVE_SQUARE.y})) {
SELECTED_MOVE_SQUARE.x+=i;
goto escapeRight;
}
}
for (int j=1;j<=8;j++) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x+i,SELECTED_MOVE_SQUARE.y+j})) {
SELECTED_MOVE_SQUARE.x+=i;
SELECTED_MOVE_SQUARE.y+=j;
goto escapeRight;
}
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x+i,SELECTED_MOVE_SQUARE.y-j})) {
SELECTED_MOVE_SQUARE.x+=i;
SELECTED_MOVE_SQUARE.y-=j;
goto escapeRight;
}
}
}
}
escapeRight:
if (UpPressed()) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x,SELECTED_MOVE_SQUARE.y-i})) {
SELECTED_MOVE_SQUARE.y-=i;
goto escapeUp;
}
}
for (int j=1;j<=8;j++) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x-j,SELECTED_MOVE_SQUARE.y-i})) {
SELECTED_MOVE_SQUARE.x-=j;
SELECTED_MOVE_SQUARE.y-=i;
goto escapeUp;
}
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x+j,SELECTED_MOVE_SQUARE.y-i})) {
SELECTED_MOVE_SQUARE.x+=j;
SELECTED_MOVE_SQUARE.y-=i;
goto escapeUp;
}
}
}
}
escapeUp:
if (DownPressed()) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x,SELECTED_MOVE_SQUARE.y+i})) {
SELECTED_MOVE_SQUARE.y+=i;
goto escapeDown;
}
}
for (int j=1;j<=8;j++) {
for (int i=1;i<=8;i++) {
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x-j,SELECTED_MOVE_SQUARE.y+i})) {
SELECTED_MOVE_SQUARE.x-=j;
SELECTED_MOVE_SQUARE.y+=i;
goto escapeDown;
}
if (MOVEMENT_GRID.count({SELECTED_MOVE_SQUARE.x+j,SELECTED_MOVE_SQUARE.y+i})) {
SELECTED_MOVE_SQUARE.x+=j;
SELECTED_MOVE_SQUARE.y+=i;
goto escapeDown;
}
}
}
}
escapeDown:
if (ACTIONKEYPRESSED) {
if (SELECTED_MOVE_SQUARE.x==0&&SELECTED_MOVE_SQUARE.y==0) {
BATTLE_STATE=BattleState::SELECT_ACTION;
} else {
BATTLE_ENCOUNTER->playerPos[-CURRENT_TURN-1]=(BATTLE_ENCOUNTER->playerPos[-CURRENT_TURN-1]/32+SELECTED_MOVE_SQUARE)*32;
BATTLE_STATE=BattleState::MOVE_CAMERA;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->atb=400;
}
}
}break;
case BattleState::ITEM_SELECT:{
if (LeftPressed()&&!(ITEM_SELECTION_CURSOR&1)) {
BATTLE_STATE=BattleState::SELECT_ACTION;
} else {
HandleInventoryNavigation();
}
if (ACTIONKEYPRESSED) {
EQUIP_$ITEM_DISPLAY=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->name;
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip==EquipSlot::WEAPON) {
ITEM_REQUIRES_EQUIPPING=true;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::BASH_CHANGE];
SetupTargetSelect();
} else
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable!=Consumable::NOT_A_CONSUMABLE) {
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->battlemove!=nullptr) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->battlemove;
} else
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY_PERMANENT) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::CONSUMABLE];
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::CONSUMABLE_ENEMY];
}
SetupTargetSelect();
} else {
ITEM_REQUIRES_EQUIPPING=true;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::EQUIP_ARMOR];
ConfirmPlayerTargetSelection();
BATTLE_STATE=BattleState::WAIT;
}
}
}break;
}
}
switch (GAME_STATE) {
case GameState::TILE_SELECT:{
if (UpPressed()) {
SELECTED_TILE.y=SELECTED_TILE.y-1;
if (SELECTED_TILE.y<0) {
SELECTED_TILE.y=TILEMAP_SIZE_Y/32-1;
}
}
if (RightPressed()) {
SELECTED_TILE.x=(SELECTED_TILE.x+1)%(TILEMAP_SIZE_X/32);
}
if (LeftPressed()) {
SELECTED_TILE.x=SELECTED_TILE.x-1;
if (SELECTED_TILE.x<0) {
SELECTED_TILE.x=TILEMAP_SIZE_X/32-1;
}
}
if (DownPressed()) {
SELECTED_TILE.y=(SELECTED_TILE.y+1)%(TILEMAP_SIZE_Y/32);
}
}break;
case GameState::GAME_WORLD:{
if (GetKey(F5).bPressed) {
GAME_STATE=GameState::EDITOR;
} else
if (PlayerCanMove()&&ACTIONKEYPRESSED) {
GAME_STATE=GameState::OVERWORLD_MENU;
OVERWORLD_MENU_SELECTION=0;
SetupRollingHitpointCounters();
}
}break;
case GameState::OVERWORLD_MENU:{
if (LeftPressed()) {
GAME_STATE=GameState::GAME_WORLD;
}
if (DownPressed()) {
OVERWORLD_MENU_SELECTION=(OVERWORLD_MENU_SELECTION+1)%5;
if (OVERWORLD_MENU_SELECTION==4) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
OVERWORLD_MENU_SELECTION--;
if (OVERWORLD_MENU_SELECTION<0) {
OVERWORLD_MENU_SELECTION+=5;
}
if (OVERWORLD_MENU_SELECTION==0) {
KEY_LASTPRESSED=NONE;
}
}
if (ACTIONKEYPRESSED) {
switch (OVERWORLD_MENU_SELECTION) {
case 0:{//Check is selected.
Object*closest=nullptr;
float closestDist=999999;
for (int i=0;i<OBJECTS.size();i++) {
float dist;
for (int j=0;j<PARTY_MEMBER_COUNT;j++) {
if (OBJECTS[i]==PARTY_MEMBER_OBJ[j]) {
goto next;
}
} //Make sure it's not a party member.
dist = abs(PARTY_MEMBER_OBJ[0]->GetPos().x-OBJECTS[i]->GetPos().x)+abs(PARTY_MEMBER_OBJ[0]->GetPos().y-OBJECTS[i]->GetPos().y);
if (dist<closestDist) {
closestDist=dist;
closest=OBJECTS[i];
}
next:
continue;
}
if (closest!=nullptr) {
//Run the Interaction for this object.
INTERACTING_WITH=closest;
GAME_STATE=GameState::GAME_WORLD;
Interaction interaction = closest->Interact();
if (interaction.messages.size()>0) {
INTERACTION_MESSAGES=interaction.messages;
DisplayMessageBox(INTERACTION_MESSAGES.front());
INTERACTION_MESSAGES.erase(INTERACTION_MESSAGES.begin());
} else {
DisplayMessageBox("No problem here.");
}
GAME_FLAGS[(int)interaction.flag]=true;
CLOSE_OVERWORLD_WINDOW=true;
}
}break;
case 1:{//Power is selected.
OVERWORLD_POWER_SELECTION_MEMBER=0;
PopulateBattleMoveList(OVERWORLD_POWER_SELECTION_MEMBER,true);
if (PARTY_MEMBER_COUNT==1) {
GAME_STATE=GameState::OVERWORLD_POWER_MENU;
} else {
GAME_STATE=GameState::OVERWORLD_POWER_PLAYER_MENU;
}
}break;
case 2:{//Items is selected.
GAME_STATE=GameState::OVERWORLD_ITEMS_MENU;
}break;
case 3:{//Equip is selected.
OVERWORLD_POWER_SELECTION_MEMBER=0;
if (PARTY_MEMBER_COUNT==1) {
GAME_STATE=GameState::OVERWORLD_EQUIP_MENU;
} else {
GAME_STATE=GameState::OVERWORLD_EQUIP_PLAYER_MENU;
}
}break;
case 4:{//Status is selected.
GAME_STATE=GameState::OVERWORLD_STATUS_MENU;
OVERWORLD_POWER_SELECTION_MEMBER=0;
}break;
}
}
}break;
case GameState::OVERWORLD_POWER_PLAYER_MENU:{
if (LeftPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER--;
if (OVERWORLD_POWER_SELECTION_MEMBER<0) {
OVERWORLD_POWER_SELECTION_MEMBER=PARTY_MEMBER_COUNT-1;
}
PopulateBattleMoveList(OVERWORLD_POWER_SELECTION_MEMBER,true);
if (OVERWORLD_POWER_SELECTION_MEMBER==0) {
KEY_LASTPRESSED=NONE;
}
}
if (RightPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER=(OVERWORLD_POWER_SELECTION_MEMBER+1)%PARTY_MEMBER_COUNT;
PopulateBattleMoveList(OVERWORLD_POWER_SELECTION_MEMBER,true);
if (OVERWORLD_POWER_SELECTION_MEMBER==PARTY_MEMBER_COUNT-1) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
GAME_STATE=GameState::OVERWORLD_MENU;
OVERWORLD_POWER_SELECTION_MEMBER=-1;
}
if (ACTIONKEYPRESSED) {
if (BATTLE_MOVELIST_DISPLAY.size()>0) {
GAME_STATE=GameState::OVERWORLD_POWER_MENU;
}
}
}break;
case GameState::OVERWORLD_POWER_MENU:{
if (DownPressed()) {
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=0;
OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]=0;
} else {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]+1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]>=4) {
OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]++;
}
}
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==0) {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=(int)BATTLE_MOVELIST_DISPLAY.size()-1;
OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-3,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
} else {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]<OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]) {
OVERWORLD_POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]--;
}
}
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==0) {
KEY_LASTPRESSED=NONE;
}
}
if (LeftPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER=-1;
if (PARTY_MEMBER_COUNT==1) {
GAME_STATE=GameState::OVERWORLD_MENU;
} else {
GAME_STATE=GameState::OVERWORLD_POWER_PLAYER_MENU;
}
}
if (ACTIONKEYPRESSED||RightPressed()) {
GAME_STATE=GameState::OVERWORLD_GRADE_MENU;
}
}break;
case GameState::OVERWORLD_GRADE_MENU:{
if (RightPressed()) {
OVERWORLD_POWER_GRADE_CURSOR=(OVERWORLD_POWER_GRADE_CURSOR+1)%BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size();
if (OVERWORLD_POWER_GRADE_CURSOR==BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size()-1) {
KEY_LASTPRESSED=NONE;
}
}
if (DownPressed()||UpPressed()||LeftPressed()&&OVERWORLD_POWER_GRADE_CURSOR==0) {
if (UpPressed()) {
if (BATTLE_MOVELIST_DISPLAY.size()>1) {
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==0) {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=(int)BATTLE_MOVELIST_DISPLAY.size()-1;
OVERWORLD_POWER_GRADE_CURSOR=std::clamp(OVERWORLD_POWER_GRADE_CURSOR,0,(int)BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size()-1);
POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-3,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
} else {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
OVERWORLD_POWER_GRADE_CURSOR=std::clamp(OVERWORLD_POWER_GRADE_CURSOR,0,(int)BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size()-1);
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]<POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]) {
POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]--;
}
}
}
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==0) {
KEY_LASTPRESSED=NONE;
}
} else
if (DownPressed()) {
if (BATTLE_MOVELIST_DISPLAY.size()>1) {
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
OVERWORLD_POWER_GRADE_CURSOR=0;
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=0;
POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]=0;
} else {
OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]=std::clamp(OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]+1,0,(int)BATTLE_MOVELIST_DISPLAY.size()-1);
OVERWORLD_POWER_GRADE_CURSOR=std::clamp(OVERWORLD_POWER_GRADE_CURSOR,0,(int)BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size()-1);
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]-POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]>=4) {
POWER_SELECTION_OFFSET[OVERWORLD_POWER_SELECTION_MEMBER]++;
}
}
}
if (OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]==(int)BATTLE_MOVELIST_DISPLAY.size()-1) {
KEY_LASTPRESSED=NONE;
}
} else {
OVERWORLD_POWER_GRADE_CURSOR=0;
GAME_STATE=GameState::OVERWORLD_POWER_MENU;
}
} else
if (LeftPressed()) {
OVERWORLD_POWER_GRADE_CURSOR=std::clamp(OVERWORLD_POWER_GRADE_CURSOR-1,0,(int)(BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]].size())-1);
if (OVERWORLD_POWER_GRADE_CURSOR==0) {
KEY_LASTPRESSED=NONE;
}
}
if (ACTIONKEYPRESSED) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->GetPP()>=BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]][OVERWORLD_POWER_GRADE_CURSOR]->PPCost) {
PerformOverworldMove(BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]][OVERWORLD_POWER_GRADE_CURSOR],OVERWORLD_POWER_SELECTION_MEMBER);
}
}
}break;
case GameState::OVERWORLD_TARGET_MENU:{
if (RightPressed()) {
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=false;
OVERWORLD_TARGET_SELECTION=(OVERWORLD_TARGET_SELECTION+1)%PARTY_MEMBER_COUNT;
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=true;
}
if (LeftPressed()) {
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=false;
OVERWORLD_TARGET_SELECTION--;
if (OVERWORLD_TARGET_SELECTION<0) {
OVERWORLD_TARGET_SELECTION=PARTY_MEMBER_COUNT-1;
}
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=true;
}
if (UpPressed()){
if (OVERWORLD_ITEM_BEING_USED) {
GAME_STATE=GameState::OVERWORLD_ITEMS_MENU;
} else {
GAME_STATE=GameState::OVERWORLD_GRADE_MENU;
}
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=false;
}
if (ACTIONKEYPRESSED) {
if (OVERWORLD_ITEM_BEING_USED) { //Equipping an item.
int prevPartyInvenSize=PARTY_INVENTORY.size();
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip!=EquipSlot::NONE) {
DisplayMessageBox(PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->name+" equipped the "+PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->name+".");
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_TARGET_SELECTION]]->EquipItem(ITEM_SELECTION_CURSOR);
GAME_STATE=GameState::OVERWORLD_ITEMS_MENU;
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=true;
} else
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable!=Consumable::NOT_A_CONSUMABLE) {
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY_PERMANENT) {
//PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=MOVELIST[BattleMoveName::CONSUMABLE];
Entity*target=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_TARGET_SELECTION]];
Item*item=PARTY_INVENTORY[ITEM_SELECTION_CURSOR];
std::string messages=item->name+" is used.";
for (int i=0;i<item->messages.size();i++) {
CustomItemMessage msg = item->messages[i];
if (msg.s.find("$TARGET")!=std::string::npos) {
if (msg.a!=ItemAction::LEARNMOVE) {
messages+=" "+msg.s.replace(msg.s.find("$TARGET"),7,target->obj->name);
}
} else {
messages+=" "+msg.s;
}
switch (msg.a) {
case ItemAction::HPRECOVERY:{
target->AddHP(item->stats.hpRecovery);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+OVERWORLD_TARGET_SELECTION*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(-item->stats.hpRecovery,box+cameraPos));
}break;
case ItemAction::PPRECOVERY:{
target->AddPP(item->stats.ppRecovery);
}break;
case ItemAction::ATKINCREASE:{
target->stats.baseAtk+=item->stats.atkIncrease;
target->boosts[boost::ATK]+=item->stats.atkIncrease;
}break;
case ItemAction::HPINCREASE:{
target->stats.maxHP+=item->stats.hpIncrease;
target->AddHP(item->stats.hpIncrease);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+OVERWORLD_TARGET_SELECTION*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(-item->stats.hpIncrease,box+cameraPos));
target->boosts[boost::HP]+=item->stats.hpIncrease;
}break;
case ItemAction::PPINCREASE:{
target->stats.maxPP+=item->stats.ppIncrease;
target->AddPP(item->stats.ppIncrease);
target->boosts[boost::PP]+=item->stats.ppIncrease;
}break;
case ItemAction::SPDINCREASE:{
target->stats.speed+=item->stats.spdIncrease;
target->boosts[boost::SPD]+=item->stats.spdIncrease;
}break;
case ItemAction::LEARNMOVE:{
bool moveLearned=false;
for (int i=0;i<target->moveSet.size();i++) {
if (item->stats.learnAbility==target->moveSet[i]) {
moveLearned=true;
break;
}
}
if (!moveLearned) {
messages+=" "+msg.s.replace(msg.s.find("$TARGET"),7,target->obj->name);
target->moveSet.push_back(item->stats.learnAbility);
} else {
messages+=" Failed to learn "+item->stats.learnAbility->GetPowerName();
}
}break;
}
}
DisplayMessageBox(messages);
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_TARGET_SELECTION]]->RemoveItem(ITEM_SELECTION_CURSOR);
}
}
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()&&prevPartyInvenSize&1&&PARTY_INVENTORY.size()==prevPartyInvenSize-1) {
ITEM_SELECTION_OFFSET-=2;
}
ITEM_SELECTION_CURSOR=std::clamp(ITEM_SELECTION_CURSOR,0,(int)PARTY_INVENTORY.size()-1);
OVERWORLD_ITEM_BEING_USED=false;
GAME_STATE=GameState::OVERWORLD_ITEMS_MENU;
} else { //Using a power instead.
HEALING_OVERWORLD_SINGLE_MEMBER=true;
Battle::Move*move=BATTLE_MOVELIST_DISPLAY[OVERWORLD_POWER_SELECTION_CURSOR[OVERWORLD_POWER_SELECTION_MEMBER]][OVERWORLD_POWER_GRADE_CURSOR];
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->SubtractPP(move->PPCost);
DisplayMessageBox(PARTY_MEMBER_OBJ[OVERWORLD_POWER_SELECTION_MEMBER]->name+" begins to cast "+move->GetPowerName()+".\n");
GAME_STATE=GameState::OVERWORLD_GRADE_MENU;
}
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=false;
}
}break;
case GameState::OVERWORLD_ITEMS_MENU:{
if (LeftPressed()&&!(ITEM_SELECTION_CURSOR&1)) {
GAME_STATE=GameState::OVERWORLD_MENU;
} else {
HandleInventoryNavigation();
}
if (ACTIONKEYPRESSED) {
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip!=EquipSlot::NONE||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable!=Consumable::NOT_A_CONSUMABLE) {
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip!=EquipSlot::NONE||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY_PERMANENT) {
GAME_STATE=GameState::OVERWORLD_TARGET_MENU;
OVERWORLD_ITEM_BEING_USED=true;
OVERWORLD_TARGET_SELECTION=0;
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=true;
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip!=EquipSlot::NONE) {
DISPLAY_TARGET_MESSAGE="Equip "+PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->name+" to...";
} else {
DISPLAY_TARGET_MESSAGE="Use "+PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->name+" on...";
}
} else {
DisplayMessageBox("Cannot use that here.");
}
} else {
DisplayMessageBox("Cannot use that here.");
}
}
}break;
case GameState::OVERWORLD_STATUS_MENU:{
if (LeftPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER-=1;
if (OVERWORLD_POWER_SELECTION_MEMBER<0) {
OVERWORLD_POWER_SELECTION_MEMBER=PARTY_MEMBER_COUNT-1;
}
if (OVERWORLD_POWER_SELECTION_MEMBER==0) {
KEY_LASTPRESSED=NONE;
}
}
if (RightPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER=(OVERWORLD_POWER_SELECTION_MEMBER+1)%PARTY_MEMBER_COUNT;
if (OVERWORLD_POWER_SELECTION_MEMBER==PARTY_MEMBER_COUNT-1) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER=-1;
GAME_STATE=GameState::OVERWORLD_MENU;
}
}break;
case GameState::EDITOR:{
if (IsTextEntryEnabled()) {
return;
}
if (GetKey(F2).bPressed) {
SaveMap(CURRENT_MAP);
printf("Map Saved\n");
}
if (GetKey(F5).bPressed) {
GAME_STATE=GameState::GAME_WORLD;
EDITING_LAYER=layer::DYNAMIC;
EnableLayer(layer::COLLISION,false);
}
if (GetKey(K1).bPressed) {
EDITING_LAYER=layer::COLLISION;
EnableLayer(layer::COLLISION,true);
SetLayerTint(layer::COLLISION,{255,0,0,215});
}
if (GetKey(K2).bPressed) {
EDITING_LAYER=layer::HIGH;
EnableLayer(layer::COLLISION,false);
}
if (GetKey(K3).bPressed) {
EDITING_LAYER=layer::DYNAMIC;
EnableLayer(layer::COLLISION,false);
}
if (GetKey(K4).bPressed) {
EDITING_LAYER=layer::GROUND;
EnableLayer(layer::COLLISION,false);
}
if (GetKey(K5).bPressed) {
EDITING_LAYER=layer::BACKGROUND;
EnableLayer(layer::COLLISION,false);
}
if (GetKey(ESCAPE).bPressed) {
GAME_STATE=GameState::OBJ_SELECT;
}
if (EDITING_LAYER==layer::ENCOUNTER&&GetMouse(0).bPressed) {
for (int i=0;i<CURRENT_MAP->encounters.size();i++) {
if(CURRENT_MAP->encounters[i]->pos==(vd2d)HIGHLIGHTED_TILE*32) {
EDITING_ENCOUNTER=CURRENT_MAP->encounters[i];
TextEntryEnable(true);
break;
}
}
} else
if (EDITING_LAYER==layer::ENCOUNTER&&GetMouse(0).bPressed) {
LoadEncounter(CURRENT_MAP,HIGHLIGHTED_TILE*32,ENCOUNTER_LIST[ENCOUNTER_SELECTED]->chance,ENCOUNTER_SELECTED,true);
} else
if (EDITING_LAYER==layer::ENCOUNTER&&GetMouse(1).bPressed) {
for (int i=0;i<CURRENT_MAP->encounters.size();i++) {
if(CURRENT_MAP->encounters[i]->pos==(vd2d)HIGHLIGHTED_TILE*32) {
for (int j=0;j<CURRENT_MAP->encounters[i]->objs.size();j++) {
int index=CURRENT_MAP->encounters[i]->objs[j]->obj->objArrElement;
delete OBJECTS[index];
OBJECTS.erase(OBJECTS.begin()+index);
for (int k=0;k<OBJECTS.size();k++) {
OBJECTS[k]->objArrElement=k;
}
}
delete CURRENT_MAP->encounters[i];
CURRENT_MAP->encounters.erase(CURRENT_MAP->encounters.begin()+i--);
continue;
}
}
} else
if (EDITING_LAYER==layer::OBJECT&&GetMouse(0).bPressed) {
AddObjectToWorld(CreateObject(SELECTED_OBJ_ID,HIGHLIGHTED_TILE*32));
} else
if (EDITING_LAYER==layer::OBJECT&&GetMouse(1).bReleased) {
for (int i=0;i<OBJECTS.size();i++) {
if (OBJECTS[i]->GetPos()==(vd2d)HIGHLIGHTED_TILE*32) {
delete OBJECTS[i];
OBJECTS.erase(OBJECTS.begin()+i--);
} else {
OBJECTS[i]->objArrElement=i;
}
}
}
}break;
case GameState::OBJ_SELECT:{
if (GetKey(ESCAPE).bPressed) {
GAME_STATE=GameState::EDITOR;
}
if ((GetMouseWheel()<0||GetKey(PGDN).bHeld)&&OBJ_DISPLAY_OFFSET+(WIDTH/16)<OBJ_INFO.size()) {
OBJ_DISPLAY_OFFSET+=WIDTH/16;
} else
if ((GetMouseWheel()>0||GetKey(PGUP).bHeld)&&OBJ_DISPLAY_OFFSET-(WIDTH/16)>=0) {
OBJ_DISPLAY_OFFSET-=WIDTH/16;
}
}break;
case GameState::OVERWORLD_EQUIP_PLAYER_MENU:{
if (LeftPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER--;
if (OVERWORLD_POWER_SELECTION_MEMBER==0) {
KEY_LASTPRESSED=NONE;
}
if (OVERWORLD_POWER_SELECTION_MEMBER<0) {
OVERWORLD_POWER_SELECTION_MEMBER=PARTY_MEMBER_COUNT-1;
}
}
if (RightPressed()) {
OVERWORLD_POWER_SELECTION_MEMBER=(OVERWORLD_POWER_SELECTION_MEMBER+1)%PARTY_MEMBER_COUNT;
if (OVERWORLD_POWER_SELECTION_MEMBER==PARTY_MEMBER_COUNT-1) {
KEY_LASTPRESSED=NONE;
}
}
if (UpPressed()) {
GAME_STATE=GameState::OVERWORLD_MENU;
}
if (ACTIONKEYPRESSED) {
GAME_STATE=GameState::OVERWORLD_EQUIP_MENU;
EQUIP_MENU_SLOT=EquipSlot::WEAPON;
}
}break;
case GameState::OVERWORLD_EQUIP_MENU:{
if (UpPressed()) {
EQUIP_MENU_SLOT=(EquipSlot::Equip)(EQUIP_MENU_SLOT-1);
if (EQUIP_MENU_SLOT<0) {
EQUIP_MENU_SLOT=EquipSlot::Equip::ACCESSORY;
}
}
if (DownPressed()) {
EQUIP_MENU_SLOT=(EquipSlot::Equip)((EQUIP_MENU_SLOT+1)%3);
}
if (LeftPressed()) {
if (PARTY_MEMBER_COUNT==1) {
GAME_STATE=GameState::OVERWORLD_MENU;
} else {
GAME_STATE=GameState::OVERWORLD_EQUIP_PLAYER_MENU;
}
}
if (ACTIONKEYPRESSED) {
PopulateEquipMenuItems();
if (EQUIP_ITEM_MENU_CONTENTS.size()>0) {
GAME_STATE=GameState::OVERWORLD_EQUIP_ITEM_MENU;
}
}
}break;
case GameState::OVERWORLD_EQUIP_ITEM_MENU:{
if (UpPressed()) {
EQUIP_ITEM_MENU_CURSOR--;
if (EQUIP_ITEM_MENU_CURSOR==0) {
KEY_LASTPRESSED=NONE;
}
if (EQUIP_ITEM_MENU_CURSOR<0) {
EQUIP_ITEM_MENU_CURSOR=EQUIP_ITEM_MENU_CONTENTS.size()-1;
if (EQUIP_ITEM_MENU_OFFSET+8<=EQUIP_ITEM_MENU_CURSOR) {
EQUIP_ITEM_MENU_OFFSET=EQUIP_ITEM_MENU_CURSOR-7;
}
}
if (EQUIP_ITEM_MENU_OFFSET>EQUIP_ITEM_MENU_CURSOR) {
EQUIP_ITEM_MENU_OFFSET=EQUIP_ITEM_MENU_CURSOR;
}
}
if (DownPressed()) {
EQUIP_ITEM_MENU_CURSOR=(EQUIP_ITEM_MENU_CURSOR+1)%EQUIP_ITEM_MENU_CONTENTS.size();
if (EQUIP_ITEM_MENU_CURSOR==EQUIP_ITEM_MENU_CONTENTS.size()-1) {
KEY_LASTPRESSED=NONE;
}
if (EQUIP_ITEM_MENU_OFFSET+8<=EQUIP_ITEM_MENU_CURSOR) {
EQUIP_ITEM_MENU_OFFSET++;
}
if (EQUIP_ITEM_MENU_CURSOR==0) {
EQUIP_ITEM_MENU_OFFSET=0;
}
}
if (LeftPressed()) {
GAME_STATE=GameState::OVERWORLD_EQUIP_MENU;
}
if (ACTIONKEYPRESSED) {
if (EQUIP_ITEM_MENU_CONTENTS[EQUIP_ITEM_MENU_CURSOR]==-1) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->RemoveEquip(EQUIP_MENU_SLOT);
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->EquipItem(EQUIP_ITEM_MENU_CONTENTS[EQUIP_ITEM_MENU_CURSOR]);
}
if (EQUIP_ITEM_MENU_CURSOR>=EQUIP_ITEM_MENU_CONTENTS.size()) {
EQUIP_ITEM_MENU_CURSOR--;
}
if (EQUIP_ITEM_MENU_OFFSET>EQUIP_ITEM_MENU_CURSOR) {
EQUIP_ITEM_MENU_OFFSET=EQUIP_ITEM_MENU_CURSOR;
}
PopulateEquipMenuItems();
GAME_STATE=GameState::OVERWORLD_EQUIP_MENU;
}
}break;
case GameState::SHOPKEEPER_MENU:{
CursorControl(SHOP_MENU_CURSOR,SHOP_ITEMS.size()+1);
if (ACTIONKEYPRESSED) {
if (SHOP_MENU_CURSOR==SHOP_ITEMS.size()) {
if (SHOPKEEPER_INTERACTING_WITH!=nullptr) {
GAME_STATE=GameState::GAME_WORLD;
SHOPKEEPER_INTERACTING_WITH->ShoppingCompleted();
}
} else {
if (SHOP_ITEMS[SHOP_MENU_CURSOR].second<=MONEY) {
MONEY-=SHOP_ITEMS[SHOP_MENU_CURSOR].second;
DisplayMessageBox("You purchase "+A_An(SHOP_ITEMS[SHOP_MENU_CURSOR].first->name)+" for $"+std::to_string(SHOP_ITEMS[SHOP_MENU_CURSOR].second)+".");
PARTY_INVENTORY.push_back(SHOP_ITEMS[SHOP_MENU_CURSOR].first);
} else {
DisplayMessageBox("You do not have enough money to purchase "+A_An(SHOP_ITEMS[SHOP_MENU_CURSOR].first->name+"."));
}
}
}
}break;
}
reset:
ANYKEYPRESSED=ACTIONKEYPRESSED=false;
if (KEY_LASTPRESSED!=NONE) {
lastRepeatedFrame=frameCount;
}
}
void drawGame(){
SetDrawTarget(layer::DYNAMIC);
for (auto&obj:OBJECTS) {
obj->drawn=false;
}
if (BATTLE_ENCOUNTER!=nullptr) {
SetDrawTarget(layer::DYNAMIC);
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove!=nullptr&&PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelTimeRemaining>=0&&PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove->friendly) {
DrawTargetRangeGrid(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove->range,
Pixel(0,128,0,255),Pixel(0,128,0,64),Pixel(90,200,90,64),true);
}
}
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (BATTLE_ENCOUNTER->objs[i]->selectedMove!=nullptr&&BATTLE_ENCOUNTER->objs[i]->channelTimeRemaining>=0&&!BATTLE_ENCOUNTER->objs[i]->selectedMove->friendly) {
DrawTargetRangeGrid(BATTLE_ENCOUNTER->objs[i]->channelPos,BATTLE_ENCOUNTER->objs[i]->selectedMove->range,
Pixel(128,0,0,255),Pixel(128,0,0,64),Pixel(200,90,90,64),true);
}
}
if (BATTLE_STATE==BattleState::MOVE_SELECT) {
DrawMovementGrid(YELLOW,BLUE,BLUE);
}
}
if (BATTLE_ENCOUNTER!=nullptr&&BATTLE_STATE!=BattleState::MOVE_CAMERA&&BATTLE_STATE!=BattleState::MOVE_CAMERA_BACK||OverworldMenuOpen()&&GAME_STATE!=GameState::OVERWORLD_TARGET_MENU) {
SetDrawTarget(layer::INTERFACE);
vi2d screenShakeOffset = {0,0};
if (BATTLE_ENCOUNTER!=nullptr) {
cameraPos = BATTLE_ENCOUNTER->pos;
if (BATTLE_HIT_SCREENSHAKE>0) {
BATTLE_HIT_SCREENSHAKE--;
if (BATTLE_HIT_SCREENSHAKE%2==0) {
screenShakeOffset = {0,2};
} else {
screenShakeOffset = {0,-2};
}
}
cameraPos+=screenShakeOffset;
}
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
int boxAlpha=BATTLE_STATE==BattleState::TARGET_SELECT?64:255;
Entity*member=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]];
Object*obj=PARTY_MEMBER_OBJ[i];
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+i*64,160};
box+=screenShakeOffset;
if (CURRENT_TURN==-i-1||OVERWORLD_POWER_SELECTION_MEMBER==i) {
box.y-=20;
}
bool underAttack=false;
if (BATTLE_ENCOUNTER!=nullptr) {
std::vector<Entity*> attackedAllies;
if (CURRENT_TURN>=0&&BATTLE_STATE==BattleState::WAIT_ANIMATION&&BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget<0) {
attackedAllies=GetEntitiesInRange(BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->channelPos,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove);
}
for (int j=0;j<attackedAllies.size();j++) {
if (attackedAllies[j]->obj==PARTY_MEMBER_OBJ[i]) {
underAttack=true;
break;
}
}
}
if (CURRENT_TURN>=0&&BATTLE_STATE==BattleState::WAIT_ANIMATION&&underAttack) {
drawCheckerboardBox(box,{59,59},Pixel(180,159,194,boxAlpha),Pixel(200,179,214,boxAlpha),{6,6},RED,DARK_RED);
} else {
drawCheckerboardBox(box,{59,59},Pixel(180,159,194,boxAlpha),Pixel(200,179,214,boxAlpha),{6,6});
}
if (member->selectedMove==nullptr) {
DrawStringDecal({(float)(box.x+6),(float)(box.y+6)},obj->name,Pixel(0,0,0,boxAlpha));
} else {
DrawStringDecal({(float)(box.x+6),(float)(box.y+4)},obj->name,Pixel(0,0,0,boxAlpha),{1,0.8});
}
if (BATTLE_ENCOUNTER!=nullptr) {
DrawPartialDecal({(float)(box.x+4),(float)(box.y+5+8+2)},SPRITES["atbbar_back.png"],{0,0},{static_cast<float>(member->atb/1000.0*SPRITES["atbbar_back.png"]->sprite->width),static_cast<float>(SPRITES["atbbar_back.png"]->sprite->height)},{1,1},Pixel(255,255,255,boxAlpha));
DrawDecal({(float)(box.x+4),(float)(box.y+5+8+2)},SPRITES["atbbar_front.png"],{1,1},Pixel(255,255,255,boxAlpha));
}
if (member->selectedMove!=nullptr) {
DrawPartialDecal({(float)(box.x+4),(float)(box.y+5+8+2)},SPRITES["atbbar_back.png"],{0,0},{(1-((float)member->channelTimeRemaining/member->selectedMove->channelTime))*SPRITES["atbbar_back.png"]->sprite->width,static_cast<float>(SPRITES["atbbar_back.png"]->sprite->height)},{1,1},Pixel(0,178,0,boxAlpha));
std::string label=member->selectedMove->name;
label+=" ";
if (member->selectedMove->grade!=0) {
label+=member->selectedMove->grade;
}
vd2d textOffset=GetTextSize(label)*0.6;
textOffset.y+=10;
vd2d barPos = {(float)(box.x+4),(float)(box.y+5+8+2)};
DrawStringDecal(barPos-textOffset/2,label,Pixel(0,0,0,boxAlpha),{std::min((float)54/GetTextSize(label).x,(float)1),0.6});
}
const vi2d hpTextPos = {box.x+5,box.y+25};
for (int x=-1;x<=1;x++) {
for (int y=-1;y<=1;y++) {
if (x!=0&&y!=0) {
DrawStringDecal({(float)(hpTextPos.x+x),(float)(hpTextPos.y+y)},"HP",Pixel(255,255,255,boxAlpha));
}
}
}
DrawStringDecal(hpTextPos,"HP",Pixel(0,0,0,boxAlpha));
DrawRollingCounter(hpTextPos,member->GetHP(),player_rollhp_display[i],player_rollhp_counter[i]);
const vi2d mpTextPos = {box.x+5,hpTextPos.y+17};
for (int x=-1;x<=1;x++) {
for (int y=-1;y<=1;y++) {
if (x!=0&&y!=0) {
DrawStringDecal({(float)(mpTextPos.x+x),(float)(mpTextPos.y+y)},"PP",Pixel(255,255,255,boxAlpha));
}
}
}
DrawStringDecal(mpTextPos,"PP",Pixel(0,0,0,boxAlpha));
DrawRollingCounter(mpTextPos,member->GetPP(),player_rollpp_display[i],player_rollpp_counter[i]);
}
SetDrawTarget(layer::DYNAMIC);
}
switch (GAME_STATE) {
case GameState::GAME_WORLD:
case GameState::OVERWORLD_MENU:
case GameState::OVERWORLD_POWER_MENU:
case GameState::OVERWORLD_POWER_PLAYER_MENU:
case GameState::OVERWORLD_GRADE_MENU:
case GameState::OVERWORLD_ITEMS_MENU:
case GameState::OVERWORLD_EQUIP_ITEM_MENU:
case GameState::OVERWORLD_EQUIP_MENU:
case GameState::OVERWORLD_EQUIP_PLAYER_MENU:
case GameState::OVERWORLD_STATUS_MENU:
case GameState::OVERWORLD_TARGET_MENU:{
DrawGameWorld();
SetDrawTarget(layer::INTERFACE);
if (GAME_STATE!=GameState::GAME_WORLD&&GAME_STATE!=GameState::OVERWORLD_TARGET_MENU) {
vi2d boxPos = {2,2};
DrawDialogBox(boxPos,{(int)(WIDTH*0.25+4),5*16+4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
const std::array<std::string,5> MENU_ITEMS = {"Check","Power","Items","Equip","Status"};
for (int i=0;i<5;i++) {
vi2d textPos = {12,i*16+6};
DrawStringPropDecal(boxPos+textPos,MENU_ITEMS[i]);
}
DrawDecal({static_cast<float>(2+4),static_cast<float>(2+6+OVERWORLD_MENU_SELECTION*16)},SPRITES["cursor.png"]);
DrawMoneyBox({(float)boxPos.x,(float)boxPos.y+5*16+4},{WIDTH/4+4,HEIGHT/6});
}
if (GAME_STATE==GameState::OVERWORLD_EQUIP_PLAYER_MENU||GAME_STATE==GameState::OVERWORLD_EQUIP_MENU||GAME_STATE==GameState::OVERWORLD_EQUIP_ITEM_MENU) {
DrawDialogBox({4,4},{(int)(WIDTH/1.5),HEIGHT/4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
vi2d textSize=GetTextSizeProp(PARTY_MEMBER_OBJ[OVERWORLD_POWER_SELECTION_MEMBER]->name)/2;
DrawStringPropDecal({(float)(WIDTH/1.5-textSize.x)-4,4},PARTY_MEMBER_OBJ[OVERWORLD_POWER_SELECTION_MEMBER]->name,WHITE,{0.5,1});
if (GAME_STATE==GameState::OVERWORLD_EQUIP_PLAYER_MENU) {
DrawRotatedDecal({(float)(WIDTH/1.5-textSize.x-6),7},SPRITES["cursor.png"],M_PI,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
DrawRotatedDecal({(float)(WIDTH/1.5-2),7},SPRITES["cursor.png"],0,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
}
if (GAME_STATE==GameState::OVERWORLD_EQUIP_MENU) {
DrawDecal({8,(float)(19+EQUIP_MENU_SLOT*12)},SPRITES["cursor.png"]);
}
std::string labels[3]={"WEAPON:","ARMOR:","OTHER:"};
for (int i=0;i<3;i++) {
DrawStringPropDecal({16,(float)(19+i*12)},labels[i]);
std::string equipName = (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->equipment[i]!=nullptr)?PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->equipment[i]->name:"None";
DrawStringPropDecal({12+64,(float)(19+i*12)},equipName,WHITE,{std::min(1.0F,(float)((WIDTH/1.5)-84)/GetTextSizeProp(equipName).x),1});
}
}
if (GAME_STATE==GameState::OVERWORLD_EQUIP_ITEM_MENU) {
DrawDialogBox({4,4},{(int)(WIDTH/2+4),HEIGHT/2},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawDecal({8,(float)(12+(EQUIP_ITEM_MENU_CURSOR-EQUIP_ITEM_MENU_OFFSET)*12)},SPRITES["cursor.png"]);
for (int i=0;i<8;i++) {
if (EQUIP_ITEM_MENU_OFFSET+i<EQUIP_ITEM_MENU_CONTENTS.size()) {
std::string equipName = EQUIP_ITEM_MENU_CONTENTS[i+EQUIP_ITEM_MENU_OFFSET]==-1?"Unequip":PARTY_INVENTORY[EQUIP_ITEM_MENU_CONTENTS[i+EQUIP_ITEM_MENU_OFFSET]]->name;
DrawStringPropDecal({16,(float)(12+i*12)},equipName,WHITE,{std::min(1.0F,(float)((WIDTH/2)-12)/GetTextSizeProp(equipName).x),1});
}
}
if (EQUIP_ITEM_MENU_OFFSET>0) {
DrawRotatedDecal({WIDTH/2-20,8},SPRITES["cursor.png"],-M_PI_2,{4,4});
}
if (EQUIP_ITEM_MENU_OFFSET+8<EQUIP_ITEM_MENU_CONTENTS.size()) {
DrawRotatedDecal({WIDTH/2-20,4+HEIGHT/2-4},SPRITES["cursor.png"],M_PI_2,{4,4});
}
if (EQUIP_ITEM_MENU_CONTENTS[EQUIP_ITEM_MENU_CURSOR]!=-1) {
DrawDialogBox({(int)(WIDTH/2+8),HEIGHT/6+4},{(int)(WIDTH/2-8),HEIGHT/3},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal({(int)(WIDTH/2+8)+4,HEIGHT/6+8},Wrap(PARTY_INVENTORY[EQUIP_ITEM_MENU_CONTENTS[EQUIP_ITEM_MENU_CURSOR]]->description,(int)(WIDTH/2-8)-8,true,{1,1}));
}
DrawDialogBox({4,HEIGHT/2+4},{(int)(WIDTH/2),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawDialogBox({4,(int)(HEIGHT*(5.F/8)+4)},{(int)(WIDTH/2),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal({8,HEIGHT/2+12},"ATTACK",WHITE,{0.85,2});
DrawStringPropDecal({8,HEIGHT*(5.F/8)+12},"DEFENSE",WHITE,{0.85,2});
int equipAttack=0;
int equipDefense=0;
int newAttack=0;
int newDefense=0;
CalculateChangeInEquipmentStats(OVERWORLD_POWER_SELECTION_MEMBER,EQUIP_ITEM_MENU_CONTENTS[EQUIP_ITEM_MENU_CURSOR],equipAttack,equipDefense,newAttack,newDefense);
std::string atkStr = std::to_string(equipAttack)+" -> ";
DrawStringPropDecal({72,HEIGHT/2+12},atkStr,WHITE,{0.85,2});
DrawStringPropDecal({72+GetTextSizeProp(atkStr).x*0.85F,HEIGHT/2+12},std::to_string(newAttack),(newAttack>equipAttack)?GREEN:(newAttack<equipAttack)?RED:WHITE,{0.85,2});
std::string defStr = std::to_string(equipDefense)+" -> ";
DrawStringPropDecal({72,HEIGHT*(5.F/8)+12},defStr,WHITE,{0.85,2});
DrawStringPropDecal({72+GetTextSizeProp(defStr).x*0.85F,HEIGHT*(5.F/8)+12},std::to_string(newDefense),(newDefense>equipDefense)?GREEN:(newDefense<equipDefense)?RED:WHITE,{0.85,2});
}
if (GAME_STATE==GameState::OVERWORLD_STATUS_MENU) {
Entity*member=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]];
DrawDialogBox({4,4},{(int)(WIDTH-8),(int)(HEIGHT/2)},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
int nameWidth=GetTextSizeProp(member->obj->name).x/2;
DrawStringPropDecal({(float)(WIDTH-12-nameWidth),4},member->obj->name,WHITE,{0.5,1});
DrawRotatedDecal({(float)(WIDTH-nameWidth-16),7},SPRITES["cursor.png"],M_PI,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
DrawRotatedDecal({(float)(WIDTH-8),7},SPRITES["cursor.png"],0,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
vi2d drawPos={8,8};
DrawStringPropDecal(drawPos,member->obj->name);
drawPos.y+=12;
Property statusEffect = member->GetPrimaryStatusEffect();
if (statusEffect!=Property::NONE) {
DrawStringPropDecal(drawPos,BATTLE_PROPERTIES[statusEffect]->displayName);
}
drawPos.y+=24;
drawPos.x+=96;
std::string displayStr1 = "ATK Boosts: ";
std::string displayStr2 = "+"+std::to_string(member->boosts[boost::ATK]);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(drawPos.x+24-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "HP Boosts: ";
displayStr2 = "+"+std::to_string(member->boosts[boost::HP]);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(drawPos.x+24-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "PP Boosts: ";
displayStr2 = "+"+std::to_string(member->boosts[boost::PP]);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(drawPos.x+24-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "SPD Boosts: ";
displayStr2 = "+"+std::to_string(member->boosts[boost::SPD]);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(drawPos.x+24-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
drawPos={WIDTH-40,20};
int calculatedAtk=0;
int calculatedDef=0;
CalculateEquipmentStats(OVERWORLD_POWER_SELECTION_MEMBER,calculatedAtk,calculatedDef);
displayStr1 = "ATK: ";
displayStr2 = std::to_string(calculatedAtk);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(WIDTH-8-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "DEF: ";
displayStr2 = std::to_string(calculatedDef);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(WIDTH-8-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "HP: ";
displayStr2 = std::to_string(member->stats.maxHP);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(WIDTH-8-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "PP: ";
displayStr2 = std::to_string(member->stats.maxPP);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(WIDTH-8-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
drawPos.y+=12;
displayStr1 = "SPD: ";
displayStr2 = std::to_string(member->stats.speed);
DrawStringPropDecal({(float)(drawPos.x-GetTextSizeProp(displayStr1).x),(float)drawPos.y},displayStr1);
DrawStringPropDecal({(float)(WIDTH-8-GetTextSizeProp(displayStr2).x),(float)drawPos.y},displayStr2);
}
if (GAME_STATE==GameState::OVERWORLD_POWER_MENU||GAME_STATE==GameState::OVERWORLD_POWER_PLAYER_MENU||GAME_STATE==GameState::OVERWORLD_GRADE_MENU) {
DrawBattleMoveList(OVERWORLD_POWER_SELECTION_MEMBER);
}
}break;
case GameState::SHOPKEEPER_MENU:{
DrawGameWorld();
SetDrawTarget(layer::INTERFACE);
DrawDialogBox({1,1},{WIDTH/2-2,HEIGHT/2},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawDialogBox({(int)(WIDTH/2+2),2},{(int)(WIDTH/2-4),(int)(HEIGHT/4)},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
for (int i=0;i<SHOP_ITEMS.size();i++) {
DrawStringPropDecal({12,(float)(8+i*12)},SHOP_ITEMS[i].first->name,WHITE,AutoScaleText(SHOP_ITEMS[i].first->name,WIDTH*(1.f/3)-14));
std::string moneyText="$"+std::to_string(SHOP_ITEMS[i].second);
vf2d textSize=GetTextSizeProp(moneyText);
DrawStringPropDecal({WIDTH*(1.f/3)+4,(float)(8+i*12)},moneyText);
vf2d textSize2=(vf2d)GetTextSizeProp("00");
DrawStringPropDecal({WIDTH*(1.f/3)+4+textSize.x,(float)(8+i*12)},"00",WHITE,{0.4f,0.7f});
DrawLineDecal({WIDTH*(1.f/3)+4+textSize.x,(float)(8+i*12+textSize2.y*0.7f)},{WIDTH*(1.f/3)+4+textSize.x+textSize2.x*0.4f,(float)(8+i*12+textSize2.y*0.7f)});
}
DrawMoneyBox({2,HEIGHT/2+2});
DrawStringPropDecal({12,(float)(8+SHOP_ITEMS.size()*12)},"Exit",WHITE);
DrawDecal({4,(float)(8+SHOP_MENU_CURSOR*12)},SPRITES["cursor.png"]);
if (SHOP_MENU_CURSOR<SHOP_ITEMS.size()) {
DrawStringPropDecal({(int)(WIDTH/2)+6,6},Wrap(SHOP_ITEMS[SHOP_MENU_CURSOR].first->description,(int)(WIDTH/2)-6,true,{1,1}));
}
}break;
case GameState::EDITOR:{
DrawGameWorld();
SetDrawTarget(nullptr);
DrawRectDecal((HIGHLIGHTED_TILE)*32-cameraPos,{32,32},YELLOW);
if (EDITING_LAYER==layer::ENCOUNTER) {
if (IsTextEntryEnabled()) {
DrawStringPropDecal({2,2},"Input Chance: "+TextEntryGetString()+"%",YELLOW);
} else {
DrawStringPropDecal({2,2},"Editing Encounters");
}
for (auto&enc:CURRENT_MAP->encounters) {
FillRectDecal(enc->pos-cameraPos,{WIDTH,HEIGHT},Pixel(255,0,0,64));
DrawRectDecal(enc->pos-cameraPos,{WIDTH,HEIGHT},YELLOW);
vi2d textOffset={2,2};
DrawStringDecal(enc->pos-cameraPos+textOffset,std::to_string(enc->chance)+"%");
}
} else
if (EDITING_LAYER==layer::OBJECT) {
DrawStringPropDecal({2,2},"Editing Objects");
} else {
DrawStringPropDecal({2,2},"Editing Layer "+std::to_string(EDITING_LAYER));
}
}break;
case GameState::TILE_SELECT:{
//14x14 pixels per tile.
DrawDecal({0,0},SPRITES["terrainmap.png"],{TILEMAP_EDITOR_DRAW_MULT,TILEMAP_EDITOR_DRAW_MULT});
DrawRectDecal(SELECTED_TILE*(TILEMAP_EDITOR_TILESIZE),{TILEMAP_EDITOR_TILESIZE,TILEMAP_EDITOR_TILESIZE},RED);
}break;
case GameState::OBJ_SELECT:{
vd2d drawpos={0,0};
int counter=0;
for (std::map<int,Object*>::const_iterator it = OBJ_INFO.cbegin();it!=OBJ_INFO.cend();++it){
if (counter<OBJ_DISPLAY_OFFSET) {
counter++;
continue;
}
if (drawpos.y>HEIGHT) {
break;
}
Object*obj = it->second;
if (GetMouse(0).bHeld&&
GetMousePos().x>=drawpos.x&&
GetMousePos().x<drawpos.x+16&&
GetMousePos().y>=drawpos.y&&
GetMousePos().y<drawpos.y+24) {
SELECTED_OBJ_ID=obj->id;
EDITING_LAYER=layer::OBJECT;
EnableLayer(layer::COLLISION,false);
}
FillRectDecal(drawpos,{16,24},VERY_DARK_GREY);
DrawPartialDecal({(float)drawpos.x,(float)drawpos.y+8},{16,16},obj->spr->spr,{(float)((obj->frameIndex%obj->spr->frames)*obj->spr->width),0},{(float)obj->spr->width,(float)obj->spr->spr->sprite->height},obj->color);
DrawStringDecal({(float)(drawpos.x+2),(float)(drawpos.y)},obj->name,WHITE,{(float)(12.0/GetTextSize(obj->name).x),1.0});
if (SELECTED_OBJ_ID==obj->id) {
DrawRectDecal(drawpos,{16,24},YELLOW);
}
drawpos.x+=16;
if (drawpos.x>=WIDTH) {
drawpos.x=0;
drawpos.y+=24;
}
counter++;
}
}break;
case GameState::ENCOUNTER_SELECT:{
vd2d drawpos={0,0};
int counter=0;
for (int i=0;i<ENCOUNTER_LIST.size();i++){
if (counter<ENCOUNTER_OFFSET) {
counter++;
continue;
}
if (drawpos.y>HEIGHT) {
break;
}
Encounter*enc = ENCOUNTER_LIST[i];
if (GetMouse(0).bHeld&&
GetMousePos().x>=drawpos.x&&
GetMousePos().x<drawpos.x+16&&
GetMousePos().y>=drawpos.y&&
GetMousePos().y<drawpos.y+24) {
ENCOUNTER_SELECTED=enc->id;
EDITING_LAYER=layer::ENCOUNTER;
EnableLayer(layer::COLLISION,false);
}
FillRectDecal(drawpos,{16,24},VERY_DARK_GREY);
for (int i=0;i<enc->objs.size();i+=2) {
DrawPartialDecal({(float)(drawpos.x+((double)8/(enc->objs.size()))*i-4),(float)(drawpos.y)},{16,16},enc->objs[i]->obj->spr->spr,{(float)((enc->objs[i]->obj->frameIndex%enc->objs[i]->obj->spr->frames)*enc->objs[i]->obj->spr->width),0},{(float)(enc->objs[i]->obj->spr->width),(float)(enc->objs[i]->obj->spr->spr->sprite->height)},enc->objs[i]->obj->color);
}
for (int i=1;i<enc->objs.size();i+=2) {
DrawPartialDecal({(float)(drawpos.x+((double)8/(enc->objs.size()))*i-4),(float)(drawpos.y+6)},{16,16},enc->objs[i]->obj->spr->spr,{(float)((enc->objs[i]->obj->frameIndex%enc->objs[i]->obj->spr->frames)*enc->objs[i]->obj->spr->width),0},{(float)(enc->objs[i]->obj->spr->width),(float)(enc->objs[i]->obj->spr->spr->sprite->height)},enc->objs[i]->obj->color);
}
if (ENCOUNTER_SELECTED==enc->id) {
DrawRectDecal(drawpos,{16,24},YELLOW);
}
DrawStringDecal({(float)(drawpos.x+2),(float)(drawpos.y+24-GetTextSize(std::to_string(enc->id)).y)},std::to_string(enc->id),WHITE,{(float)(12.0/GetTextSize(std::to_string(enc->id)).x),1.0});
drawpos.x+=16;
if (drawpos.x>=WIDTH) {
drawpos.x=0;
drawpos.y+=24;
}
counter++;
}
}break;
}
if (BATTLE_ENCOUNTER!=nullptr&&BATTLE_STATE==BattleState::TARGET_SELECT||GAME_STATE==GameState::OVERWORLD_TARGET_MENU) {
SetDrawTarget(layer::GROUND);
if (SELECTED_TARGET<0||GAME_STATE==GameState::OVERWORLD_TARGET_MENU) {
int memberIndex = GAME_STATE==GameState::OVERWORLD_TARGET_MENU?OVERWORLD_TARGET_SELECTION:-SELECTED_TARGET-1;
Battle::Move*selectedMove= GAME_STATE==GameState::OVERWORLD_TARGET_MENU?OVERWORLD_SELECTED_POWER:PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove;
vd2d scale = {PARTY_MEMBER_OBJ[memberIndex]->spr->width/(double)SPRITES["targetCircle.png"]->sprite->width,PARTY_MEMBER_OBJ[memberIndex]->spr->spr->sprite->height/(double)SPRITES["targetCircle.png"]->sprite->height};
vi2d size = {SPRITES["targetCircle.png"]->sprite->width,SPRITES["targetCircle.png"]->sprite->height};
DrawDecal(PARTY_MEMBER_OBJ[memberIndex]->GetPosWithOrigin()-cameraPos-size/2*scale,SPRITES["targetCircle.png"],{static_cast<float>(PARTY_MEMBER_OBJ[memberIndex]->spr->width/(double)SPRITES["targetCircle.png"]->sprite->width),static_cast<float>(PARTY_MEMBER_OBJ[memberIndex]->spr->spr->sprite->height/(double)SPRITES["targetCircle.png"]->sprite->height)},GREEN);
if (BATTLE_STATE==BattleState::TARGET_SELECT) {
DrawTargetRangeGrid(PARTY_MEMBER_OBJ[memberIndex]->GetPosWithOrigin(),selectedMove->range);
}
} else {
vd2d scale = {BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->spr->width/(double)SPRITES["targetCircle.png"]->sprite->width,BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->spr->spr->sprite->height/(double)SPRITES["targetCircle.png"]->sprite->height};
vi2d size = {SPRITES["targetCircle.png"]->sprite->width,SPRITES["targetCircle.png"]->sprite->height};
DrawDecal(BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->GetPosWithOrigin()-cameraPos-size/2*scale,SPRITES["targetCircle.png"],scale,YELLOW);
DrawTargetRangeGrid(BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->GetPosWithOrigin(),PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->range);
}
vi2d textPos={2,2};
vi2d shadowOffset={1,1};
SetDrawTarget(layer::INTERFACE);
DrawStringPropDecal(textPos+shadowOffset,DISPLAY_TARGET_MESSAGE,BLACK,{1,2});
DrawStringPropDecal(textPos,DISPLAY_TARGET_MESSAGE,WHITE,{1,2});
}
if (BATTLE_ENCOUNTER!=nullptr&&BATTLE_STATE==BattleState::ITEM_SELECT||GAME_STATE==GameState::OVERWORLD_ITEMS_MENU&&!messageBoxVisible) {
SetDrawTarget(layer::INTERFACE);
DrawDialogBox({4,4},{(int)(WIDTH-8),(int)(HEIGHT/2)},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawDialogBox({(int)(WIDTH*(3.0F/8)),HEIGHT/2+4},{(int)(WIDTH*(5.0F/8)-4),(int)(HEIGHT/4)},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.equip!=EquipSlot::NONE) {
DrawDialogBox({(int)4,HEIGHT/2+4},{(int)(WIDTH*(3.0F/8)-4),(int)(HEIGHT/4)},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal({(float)4+WIDTH*(1.0F/8),(float)(HEIGHT/2+8)},"ATK",WHITE,{1,1});
DrawStringPropDecal({(float)4+WIDTH*(1.0F/4),(float)(HEIGHT/2+8)},"DEF",WHITE,{1,1});
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
DrawStringPropDecal({(float)4+4,(float)(HEIGHT/2+4+12+i*10)},PARTY_MEMBER_OBJ[i]->name,WHITE,{0.5,1});
int equipAttack=0;
int equipDefense=0;
int newAttack=0;
int newDefense=0;
CalculateChangeInEquipmentStats(i,ITEM_SELECTION_CURSOR,equipAttack,equipDefense,newAttack,newDefense);
DrawStringPropDecal({(float)4+WIDTH*(1.0F/8),(float)(HEIGHT/2+4+12+i*10)},std::to_string(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->stats.baseAtk+newAttack),(newAttack>equipAttack)?GREEN:(newAttack<equipAttack)?RED:WHITE,{0.5,1});
DrawStringPropDecal({(float)4+WIDTH*(1.0F/4),(float)(HEIGHT/2+4+12+i*10)},std::to_string(newDefense),(newDefense>equipDefense)?GREEN:(newDefense<equipDefense)?RED:WHITE,{0.5,1});
if (newAttack!=equipAttack) {DrawRotatedDecal({(float)4+WIDTH*(1.0F/4)-14,(float)(HEIGHT/2+4+12+i*10+2+((newAttack<equipAttack)?4:0))},SPRITES["cursor.png"],newAttack>equipAttack?-M_PI_2:M_PI_2,{4,4},{0.5,0.5},newAttack>equipAttack?GREEN:RED);}
if (newDefense!=equipDefense) {DrawRotatedDecal({(float)4+WIDTH*(3.0F/8)-14,(float)(HEIGHT/2+4+12+i*10+2+((newDefense<equipDefense)?4:0))},SPRITES["cursor.png"],newDefense>equipDefense?-M_PI_2:M_PI_2,{4,4},{0.5,0.5},newDefense>equipDefense?GREEN:RED);}
}
}
DrawDecal({static_cast<float>(8+(ITEM_SELECTION_CURSOR)%2*(WIDTH-8)/2),static_cast<float>(12*((ITEM_SELECTION_CURSOR-ITEM_SELECTION_OFFSET)/2)+8)},SPRITES["cursor.png"]);
DrawStringPropDecal({(int)(WIDTH*(3.0F/8))+4,HEIGHT/2+8},Wrap(PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->description,(int)(WIDTH*(5.0F/8))-4,true,{1,1}));
for (int i=0;i<18;i++) {
if (ITEM_SELECTION_OFFSET+i<PARTY_INVENTORY.size()) {
DrawStringPropDecal({static_cast<float>(16+i%2*(WIDTH-8)/2),static_cast<float>(12*(i/2)+8)},PARTY_INVENTORY[ITEM_SELECTION_OFFSET+i]->name,WHITE,{std::clamp((float)(WIDTH-48)/2/GetTextSizeProp(PARTY_INVENTORY[ITEM_SELECTION_OFFSET+i]->name).x,0.0F,1.0F),1.0F});
}
}
if (ITEM_SELECTION_OFFSET>0) {
DrawRotatedDecal({WIDTH-20,8},SPRITES["cursor.png"],-M_PI_2,{4,4});
}
if (ITEM_SELECTION_OFFSET+18<PARTY_INVENTORY.size()) {
DrawRotatedDecal({WIDTH-20,4+HEIGHT/2-4},SPRITES["cursor.png"],M_PI_2,{4,4});
}
}
if (BATTLE_ENCOUNTER!=nullptr) {
SetDrawTarget(layer::HIGH);
if (BATTLE_STATE==BattleState::SELECT_ACTION||BATTLE_STATE==BattleState::POWER_SELECT||BATTLE_STATE==BattleState::GRADE_SELECT||BATTLE_STATE==BattleState::ITEM_SELECT) {
DrawDialogBox({1,1},{(int)(WIDTH*0.75),HEIGHT/6},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
const std::string labels[6]={"Power","Attack","Item","Defend","Move","Run"};
for (int i=0;i<6;i+=2) {
DrawStringPropDecal({static_cast<float>(3+8+i/2*64),9},labels[i]);
DrawStringPropDecal({static_cast<float>(3+8+i/2*64),23},labels[i+1]);
}
DrawDecal({static_cast<float>(BATTLE_SELECTION_CURSOR/2*64+3),static_cast<float>(9+((BATTLE_SELECTION_CURSOR%2==0)?0:14))},SPRITES["cursor.png"]);
}
if (BATTLE_STATE==BattleState::POWER_SELECT||BATTLE_STATE==BattleState::GRADE_SELECT) {
DrawBattleMoveList(-CURRENT_TURN-1);
}
if (BATTLE_STATE==BattleState::WAIT_ANIMATION) {
SetDrawTarget(layer::INTERFACE);
vd2d text={2,2};
vd2d shadowOffset={1,1};
std::string label;
if (BATTLE_CURRENT_CUSTOM_MSG.s.length()>0) {
std::string baseStr = BATTLE_CURRENT_CUSTOM_MSG.s;
if (CURRENT_TURN<0) {
label=ParseBattleMessage(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]],baseStr);
} else {
label=ParseBattleMessage(BATTLE_ENCOUNTER->objs[CURRENT_TURN],baseStr);
}
} else {
if (CURRENT_TURN<0) {
std::string baseStr = PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->attackMsg;
label=ParseBattleMessage(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]],baseStr);
} else {
std::string baseStr = BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->attackMsg;
label=ParseBattleMessage(BATTLE_ENCOUNTER->objs[CURRENT_TURN],baseStr);
}
}
DrawStringDecal(text+shadowOffset,Wrap(label,ScreenWidth()-2,false,{1,2}),BLACK,{1,2});
DrawStringDecal(text,Wrap(label,ScreenWidth()-2,false,{1,2}),WHITE,{1,2});
}
if (BATTLE_STATE==BattleState::ENEMY_SPOILS) {
SetDrawTarget(layer::INTERFACE);
vd2d text={2,2};
vd2d shadowOffset={1,1};
DrawStringDecal(text+shadowOffset,Wrap(BATTLE_SPOILS_MESSAGE,ScreenWidth()-2,false,{1,2}),BLACK,{1,2});
DrawStringDecal(text,Wrap(BATTLE_SPOILS_MESSAGE,ScreenWidth()-2,false,{1,2}),WHITE,{1,2});
}
if (BATTLE_STATE!=BattleState::MOVE_CAMERA&&BATTLE_STATE!=BattleState::MOVE_CAMERA_BACK) {
SetDrawTarget(layer::INTERFACE);
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
Entity*obj = BATTLE_ENCOUNTER->objs[i];
if (obj->GetHP()>0&&obj->selectedMove!=nullptr) {
vi2d barOffset={-SPRITES["atbbar_front.png"]->sprite->width/2,8};
DrawPartialDecal(obj->obj->GetPos()+obj->obj->originPoint-cameraPos+barOffset,SPRITES["atbbar_back.png"],{0,0},{(1-((float)obj->channelTimeRemaining/obj->selectedMove->channelTime))*SPRITES["atbbar_back.png"]->sprite->width,static_cast<float>(SPRITES["atbbar_back.png"]->sprite->height)},{1,1},YELLOW*0.8);
DrawDecal(obj->obj->GetPos()+obj->obj->originPoint-cameraPos+barOffset,SPRITES["atbbar_front.png"]);
std::string label=obj->selectedMove->name;
if (obj->selectedMove->grade!=0) {
label+=" ";
label+=obj->selectedMove->grade;
}
vd2d textOffset=GetTextSize(label)*0.6;
textOffset.y-=6;
vi2d shadowOffset = {1,1};
DrawStringDecal(obj->obj->GetPos()+obj->obj->originPoint-cameraPos+barOffset-textOffset/2+shadowOffset,label,BLACK,{0.6,0.6});
DrawStringDecal(obj->obj->GetPos()+obj->obj->originPoint-cameraPos+barOffset-textOffset/2,label,WHITE,{0.6,0.6});
}
}
}
}
//////////////////INTERFACE LAYER.
SetDrawTarget(layer::INTERFACE);
if (BATTLE_ENCOUNTER!=nullptr&&BATTLE_STATE==BattleState::MOVE_SELECT) {
vd2d cursorOffset = {-2,-2};
vd2d cursorScale = {1,1};
if ((cos(frameCount*M_PI/20)/2+0.5)>0.8) {
cursorScale={1.08F,1.08F};
cursorOffset.x-=36*0.08;
cursorOffset.y-=36*0.08;
}
cursorOffset+=SELECTED_MOVE_SQUARE*32;
DrawDecal((vi2d)((PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->GetPosWithOrigin()-cameraPos)/32)*32+cursorOffset,SPRITES["crosshair.png"],cursorScale);
DrawArrow();
}
for (auto numb:DAMAGE_NUMBERS) {
vd2d shadowOffset={1,1};
vd2d textSize = GetTextSizeProp((numb->damage>=0)?"-"+std::to_string(numb->damage):"+"+std::to_string(-numb->damage));
DrawStringPropDecal(numb->pos+shadowOffset-cameraPos-textSize/2,(numb->damage>=0)?"-"+std::to_string(numb->damage):"+"+std::to_string(-numb->damage),BLACK,{1,2});
DrawStringPropDecal(numb->pos-cameraPos-textSize/2,(numb->damage>=0)?"-"+std::to_string(numb->damage):"+"+std::to_string(-numb->damage),(numb->damage>=0)?RED:GREEN,{1,2});
DrawStringPropDecal(numb->pos-cameraPos-textSize/2,(numb->damage>=0)?"-"+std::to_string(numb->damage):"+"+std::to_string(-numb->damage),Pixel(255,255,255,abs(sin((M_PI*frameCount)/30)*128)),{1,2});
}
if (messageBoxVisible) {
DrawDialogBox({1,1},{WIDTH/2,HEIGHT/4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal({6,6},messageBoxText);
if (waitingForChoice) {
DrawDialogBox({1,1+HEIGHT/4},{WIDTH/3,(int)MESSAGE_BOX_CHOICE_LIST.size()*12+4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
for (int i=0;i<MESSAGE_BOX_CHOICE_LIST.size();i++) {
DrawStringPropDecal({13,(float)(1+HEIGHT/4+4+i*12)},MESSAGE_BOX_CHOICE_LIST[i]);
}
DrawDecal({5,(float)(1+HEIGHT/4+MESSAGE_BOX_DIALOG_CHOICE_CURSOR*12+4)},SPRITES["cursor.png"]);
}
}
for (int i=0;i<PARTICLES.size();i++) {
PARTICLES[i]->render(this);
}
FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,(int)CUTSCENE_FADE_VALUE));
};
void DrawGameWorld() {
for (int y=-1;y<HEIGHT/32+2;y++) {
int yTileOffset = cameraPos.y/32;
for (auto&obj:OBJECTS) {
if (!obj->drawn&&(!obj->dead||EDITING_LAYER==layer::ENCOUNTER)&&obj->GetPos().y+obj->originPoint.y>(y+yTileOffset)*32&&obj->GetPos().y+obj->originPoint.y<=(y+yTileOffset+1)*32) {
obj->drawn=true;
if (obj->blinkFrames>0) {
obj->blinkFrames--;
}
if (obj->blinkFrames==0||obj->blinkFrames>0&&obj->blinkFrames%3==0) {
if (obj->highlighted) {
SetDrawTarget(layer::HIGH);
Pixel*data = obj->spr->spr->sprite->GetData();
double accX=0;
double accY=0;
int pixelOffsetX=0;
int pixelOffsetY=0;
for (int xx=0;xx<obj->spr->width;xx++) {
accX+=obj->GetScale().x;
for (int yy=0;yy<obj->spr->spr->sprite->height;yy++) {
accY+=obj->GetScale().y;
Pixel col = data[yy*96+xx+((obj->frameIndex%obj->spr->frames)*obj->spr->width)];
while (accY>=1) {
for (int xxx=0;xxx<accX;xxx++) {
if (col.a>64) {
GetDrawTarget()->SetPixel(obj->GetPos().x-cameraPos.x+pixelOffsetX+xxx,obj->GetPos().y-cameraPos.y+pixelOffsetY,Pixel(255,255,255,abs(sin(M_PI/60*frameCount)*210)));
}
}
accY-=1;
pixelOffsetY++;
}
}
while (accX>=1) {
accX-=1;
pixelOffsetX++;
}
pixelOffsetY=0;
}
SetDrawTarget(layer::DYNAMIC);
DrawPartialDecal(obj->GetPos()-cameraPos,obj->spr->spr,{(float)((obj->frameIndex%obj->spr->frames)*obj->spr->width),0},{(float)obj->spr->width,(float)obj->spr->spr->sprite->height},obj->GetScale(),obj->color);
vi2d nameOffset={0,8};
vi2d shadowOffset={1,1};
SetDrawTarget(layer::INTERFACE);
DrawStringDecal(obj->GetPosWithOrigin()-cameraPos-GetTextSize(obj->name)/2+shadowOffset+nameOffset,obj->name,BLACK);
DrawStringDecal(obj->GetPosWithOrigin()-cameraPos-GetTextSize(obj->name)/2+nameOffset,obj->name);
} else {
SetDrawTarget(layer::DYNAMIC);
DrawPartialDecal(obj->GetPos()-cameraPos,obj->spr->spr,{(float)((obj->frameIndex%obj->spr->frames)*obj->spr->width),0},{(float)obj->spr->width,(float)obj->spr->spr->sprite->height},obj->GetScale(),obj->color);
}
}
}
}
for (int x=-1;x<WIDTH/32+2;x++) {
int xTileOffset = cameraPos.x/32;
if (x+xTileOffset>=0&&x+xTileOffset<MAP_WIDTH&&y+yTileOffset>=0&&y+yTileOffset<MAP_HEIGHT) {
if(MAP5[y+yTileOffset][x+xTileOffset]->tileX*MAP5[y+yTileOffset][x+xTileOffset]->tileY!=225) {
SetDrawTarget(layer::COLLISION);
DrawPartialSprite({(int)(x*32-fmod(cameraPos.x,32)),(int)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"]->sprite,{(int)(MAP5[y+yTileOffset][x+xTileOffset]->tileX*32),(int)(MAP5[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
}
if(MAP4[y+yTileOffset][x+xTileOffset]->tileX*MAP4[y+yTileOffset][x+xTileOffset]->tileY!=225) {
SetDrawTarget(layer::BACKGROUND);
DrawPartialDecal({(float)(x*32-fmod(cameraPos.x,32)),(float)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"],{(float)(MAP4[y+yTileOffset][x+xTileOffset]->tileX*32),(float)(MAP4[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
}
if(MAP3[y+yTileOffset][x+xTileOffset]->tileX*MAP3[y+yTileOffset][x+xTileOffset]->tileY!=225) {
SetDrawTarget(layer::GROUND);
DrawPartialDecal({(float)(x*32-fmod(cameraPos.x,32)),(float)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"],{(float)(MAP3[y+yTileOffset][x+xTileOffset]->tileX*32),(float)(MAP3[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
}
if(MAP2[y+yTileOffset][x+xTileOffset]->tileX*MAP2[y+yTileOffset][x+xTileOffset]->tileY!=225) {
SetDrawTarget(layer::DYNAMIC);
DrawPartialDecal({(float)(x*32-fmod(cameraPos.x,32)),(float)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"],{(float)(MAP2[y+yTileOffset][x+xTileOffset]->tileX*32),(float)(MAP2[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
}
if(MAP[y+yTileOffset][x+xTileOffset]->tileX*MAP[y+yTileOffset][x+xTileOffset]->tileY!=225) {
SetDrawTarget(layer::HIGH);
DrawPartialDecal({(float)(x*32-fmod(cameraPos.x,32)),(float)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"],{(float)(MAP[y+yTileOffset][x+xTileOffset]->tileX*32),(float)(MAP[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
}
}
}
}
}
void LoadMap(Map*map) {
std::ifstream f("assets/maps/"+map->filename,std::ios::binary);
std::ifstream f2("assets/maps/"+map->l2filename,std::ios::binary);
std::ifstream f3("assets/maps/"+map->l3filename,std::ios::binary);
std::ifstream f4("assets/maps/"+map->l4filename,std::ios::binary);
std::ifstream f5("assets/maps/"+map->l5filename,std::ios::binary);
for (int i=0;i<MAP.size();i++) {
for (int j=0;j<MAP[i].size();j++) {
delete MAP[i][j];
}
MAP[i].clear();
}
for (int i=0;i<MAP.size();i++) {
for (int j=0;j<MAP[i].size();j++) {
delete MAP2[i][j];
}
MAP2[i].clear();
}
for (int i=0;i<MAP.size();i++) {
for (int j=0;j<MAP[i].size();j++) {
delete MAP3[i][j];
}
MAP3[i].clear();
}
for (int i=0;i<MAP.size();i++) {
for (int j=0;j<MAP[i].size();j++) {
delete MAP4[i][j];
}
MAP4[i].clear();
}
for (int i=0;i<MAP.size();i++) {
for (int j=0;j<MAP[i].size();j++) {
delete MAP5[i][j];
}
MAP5[i].clear();
}
MAP_WIDTH=-1;
MAP_HEIGHT=-1;
MAP.clear();
for (int i=0;i<OBJECTS.size();i++) {
delete OBJECTS[i];
}
OBJECTS.clear();
for (int i=0;i<4;i++) {
PARTY_MEMBER_OBJ[i]=nullptr;
PARTY_MEMBER_ID[i]=0;
}
std::string data;
while (f.good()) {
f>>data;
if (MAP_WIDTH==-1) {
MAP_WIDTH=data.length()/2;
}
if (data.find("OBJECT")!=std::string::npos||data.find("ENCOUNTER")!=std::string::npos) {
int marker=data.find_first_of(';');
int lastMarker=marker;
std::stringstream split1((data.find("OBJECT")!=std::string::npos)?data.substr(6,marker-6):data.substr(9,marker-9));
marker=data.find_first_of(';',marker+1);
std::stringstream split2(data.substr(lastMarker+1,marker-lastMarker-1));
lastMarker=marker;
marker=data.find_first_of(';',marker+1);
std::stringstream split3(data.substr(lastMarker+1,marker-lastMarker-1));
lastMarker=marker;
double x,y;
split1>>x;
split2>>y;
int id;
split3>>id;
if (data.find("OBJECT")!=std::string::npos) {
bool enabled=true;
if (OBJ_INFO[id]->disableFlag!=Flag::NONE) {
if (GetGameFlag(OBJ_INFO[id]->disableFlag)) {
enabled=false;
}
}
if (OBJ_INFO[id]->enableFlag!=Flag::NONE) {
if (!GetGameFlag(OBJ_INFO[id]->enableFlag)) {
enabled=false;
}
}
if (enabled) {
AddObjectToWorld(CreateObject(id,{x,y}));
}
printf("Object %s Loaded.\n",OBJ_INFO[id]->name.c_str());
} else
if (data.find("ENCOUNTER")!=std::string::npos) {
marker=data.find_first_of(';',marker+1);
std::stringstream split4(data.substr(lastMarker+1,marker-lastMarker-1));
lastMarker=marker;
int pct=id;
split4>>id;
LoadEncounter(map,{x,y},pct,id,rand()%100<pct);
printf("Encounter %d (%d%c) Loaded.\n",id,pct,'%');
}
} else {
std::vector<TILE*> tiles;
printf("%s\n",data.c_str());
for (int i=0;i<data.length();i+=2) {
unsigned char tileX,tileY;
tileX=data[i]-'0';
tileY=data[i+1]-'0';
tiles.push_back(new TILE(tileX,tileY));
}
MAP.push_back(tiles);
MAP_HEIGHT++;
}
}
while (f2.good()) {
f2>>data;
std::vector<TILE*> tiles;
for (int i=0;i<data.length();i+=2) {
unsigned char tileX,tileY;
tileX=data[i]-'0';
tileY=data[i+1]-'0';
tiles.push_back(new TILE(tileX,tileY));
}
MAP2.push_back(tiles);
}
while (f3.good()) {
f3>>data;
std::vector<TILE*> tiles;
for (int i=0;i<data.length();i+=2) {
unsigned char tileX,tileY;
tileX=data[i]-'0';
tileY=data[i+1]-'0';
tiles.push_back(new TILE(tileX,tileY));
}
MAP3.push_back(tiles);
}
while (f4.good()) {
f4>>data;
std::vector<TILE*> tiles;
for (int i=0;i<data.length();i+=2) {
unsigned char tileX,tileY;
tileX=data[i]-'0';
tileY=data[i+1]-'0';
tiles.push_back(new TILE(tileX,tileY));
}
MAP4.push_back(tiles);
}
while (f5.good()) {
f5>>data;
std::vector<TILE*> tiles;
for (int i=0;i<data.length();i+=2) {
unsigned char tileX,tileY;
tileX=data[i]-'0';
tileY=data[i+1]-'0';
tiles.push_back(new TILE(tileX,tileY));
}
MAP5.push_back(tiles);
}
MAP_WIDTH=MAP[0].size();
MAP_HEIGHT=MAP.size();
printf("Loaded map %s.\n",map->filename.c_str());
f.close();
f2.close();
f3.close();
f4.close();
f5.close();
}
void SaveMap(Map*map) {
std::ofstream f("assets/maps/"+map->filename,std::ios::binary);
std::ofstream f2("assets/maps/"+map->l2filename,std::ios::binary);
std::ofstream f3("assets/maps/"+map->l3filename,std::ios::binary);
std::ofstream f4("assets/maps/"+map->l4filename,std::ios::binary);
std::ofstream f5("assets/maps/"+map->l5filename,std::ios::binary);
printf("Map width: %d, Map Height: %d::\n",MAP_WIDTH,MAP_HEIGHT);
for (int y=0;y<MAP_HEIGHT;y++) {
for (int x=0;x<MAP_WIDTH;x++) {
f.put(MAP[y][x]->tileX+'0');f.put(MAP[y][x]->tileY+'0');
f2.put(MAP2[y][x]->tileX+'0');f2.put(MAP2[y][x]->tileY+'0');
f3.put(MAP3[y][x]->tileX+'0');f3.put(MAP3[y][x]->tileY+'0');
f4.put(MAP4[y][x]->tileX+'0');f4.put(MAP4[y][x]->tileY+'0');
f5.put(MAP5[y][x]->tileX+'0');f5.put(MAP5[y][x]->tileY+'0');
}
if (y!=MAP_HEIGHT-1) {
f.put('\n');
f2.put('\n');
f3.put('\n');
f4.put('\n');
f5.put('\n');
}
}
for (int i=0;i<OBJECTS.size();i++) {
bool allowed=true;
for (int j=1;j<PARTY_MEMBER_COUNT;j++) {
if (OBJECTS[i]==PARTY_MEMBER_OBJ[j]) {
allowed=false;
break;
}
}
if (OBJECTS[i]->temp||OBJECTS[i]->enc) {
continue;
}
if (!allowed) {
continue;
}
f.put('\n');
const std::string obj="OBJECT"+std::to_string(OBJECTS[i]->GetPos().x)+";"+std::to_string(OBJECTS[i]->GetPos().y)+";"+std::to_string(OBJECTS[i]->id);
for (int j=0;j<obj.length();j++) {
f.put(obj[j]);
}
}
for (int i=0;i<map->encounters.size();i++) {
f.put('\n');
const std::string enc="ENCOUNTER"+std::to_string(map->encounters[i]->pos.x)+";"+std::to_string(map->encounters[i]->pos.y)+";"+std::to_string(map->encounters[i]->chance)+";"+std::to_string(map->encounters[i]->id);
for (int j=0;j<enc.length();j++) {
f.put(enc[j]);
}
}
f.close();
f2.close();
f3.close();
f4.close();
f5.close();
}
Decal*CreateSprite(std::string spriteName) {
SPRITES[spriteName] = new Decal(new Sprite("assets/"+spriteName));
return SPRITES[spriteName];
}
//You're probably trying to add an object to the world. Use this function inside of AddObjectToWorld(CreateObject(...))
//You only need to use this function if you want to create an object from pre-defined OBJ_INFO variables.
Object*CreateObject(int id,vd2d pos) {
return OBJ_INFO[id]->CreateType(id,OBJ_INFO[id]->name,pos,OBJ_INFO[id]->spr,OBJ_INFO[id]->GetScale(),OBJ_INFO[id]->color,OBJ_INFO[id]->animationSpd);
}
Object*CreateObjectInfo(Object*obj,std::string spriteFileName,int sprWidth,Flag enableFlag=Flag::NONE,Flag disableFlag=Flag::NONE) {
if (!ANIMATIONS.count(spriteFileName)) {
ANIMATIONS[spriteFileName] = new Animation(SPRITES[spriteFileName]=CreateSprite(spriteFileName),sprWidth);
}
obj->spr=ANIMATIONS[spriteFileName];
obj->SetScale(obj->GetScale());
obj->disableFlag=disableFlag;
obj->enableFlag=enableFlag;
OBJ_INFO[obj->id]=obj;
return obj;
}
void SetupPartyMemberStats() {
for (int i=0;i<7;i++) {
PARTY_MEMBER_STATS[i]=new Entity({HP:120,maxHP:120,PP:30,maxPP:30,baseAtk:8,speed:8,resistances:{0,0,0,0}},{MOVELIST[BattleMoveName::TESTMOVE1]});
}
PARTY_MEMBER_STATS[PLAYER]->statusEffects[Property::MUSHROOMIZED]=4;
PARTY_MEMBER_STATS[PLAYER]->moveSet={
MOVELIST[BattleMoveName::HAILSTORM_A],
MOVELIST[BattleMoveName::HAILSTORM_B],
MOVELIST[BattleMoveName::HURRICANE_A],
MOVELIST[BattleMoveName::HURRICANE_B],
MOVELIST[BattleMoveName::HURRICANE_G],
MOVELIST[BattleMoveName::HURRICANE_O],
MOVELIST[BattleMoveName::METEORRAIN_A],
MOVELIST[BattleMoveName::PKFUN_A],
MOVELIST[BattleMoveName::PKLIFEUP_A],
MOVELIST[BattleMoveName::PKFREEZE_A],
MOVELIST[BattleMoveName::PKSHIELD_A]};
PARTY_MEMBER_STATS[NESS]->moveSet={
MOVELIST[BattleMoveName::PKFUN_A],
MOVELIST[BattleMoveName::PKFUN_B],
MOVELIST[BattleMoveName::PKLIFEUP_A],
MOVELIST[BattleMoveName::PKLIFEUP_B],
MOVELIST[BattleMoveName::PKLIFEUP_G],
MOVELIST[BattleMoveName::PKLIFEUP_O],};
PARTY_MEMBER_STATS[PAULA]->moveSet={
MOVELIST[BattleMoveName::PKFREEZE_A],
MOVELIST[BattleMoveName::PKFREEZE_B],
MOVELIST[BattleMoveName::PKFREEZE_G],
MOVELIST[BattleMoveName::PKFREEZE_O],
MOVELIST[BattleMoveName::PKFIRE_A],
MOVELIST[BattleMoveName::PKFIRE_B],};
PARTY_MEMBER_STATS[ANNA]->moveSet={
MOVELIST[BattleMoveName::PKFREEZE_A],
MOVELIST[BattleMoveName::PKSHIELD_A],
MOVELIST[BattleMoveName::PKSHIELD_B],
MOVELIST[BattleMoveName::PKLIFEUP_A],};
}
void SetupMoveList() {
MOVELIST[BattleMoveName::TESTMOVE1]=new Battle::Move{"Test Move 1","An attack",baseDmg:30,randomDmg:5,range:1,channelTime:0,friendly:false};
MOVELIST[BattleMoveName::TESTMOVE2]=new Battle::Move{"Test Move 2","An attack",baseDmg:40,randomDmg:10,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0}};
MOVELIST[BattleMoveName::TESTMOVE3]=new Battle::Move{"Test Move 3","An attack",baseDmg:25,randomDmg:5,PPCost:0,range:3,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::BASH]=new Battle::Move{"Bash","Regular attack.",baseDmg:5,randomDmg:5,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0}};
MOVELIST[BattleMoveName::BASH_CHANGE]=new Battle::Move{MOVELIST[BattleMoveName::BASH]->name,"Regular attack.",baseDmg:MOVELIST[BattleMoveName::BASH]->baseDmg,randomDmg:MOVELIST[BattleMoveName::BASH]->randomDmg,PPCost:MOVELIST[BattleMoveName::BASH]->PPCost,range:MOVELIST[BattleMoveName::BASH]->range,composition:MOVELIST[BattleMoveName::BASH]->composition,attackMsg:"$USER equipped the $ITEM instead and attacks.",eff:MOVELIST[BattleMoveName::BASH]->eff,pctDamage:MOVELIST[BattleMoveName::BASH]->pctDamage,properties:MOVELIST[BattleMoveName::BASH]->properties};
MOVELIST[BattleMoveName::DEFEND]=new Battle::Move{"Defend","Defend.",baseDmg:0,randomDmg:0,PPCost:0,range:1,channelTime:5*60,friendly:true,{0,0,0,0}};
MOVELIST[BattleMoveName::EQUIP_ARMOR]=new Battle::Move{"Equip Armor","Equip Armor.",baseDmg:0,randomDmg:0,PPCost:0,range:1,channelTime:0,friendly:true,composition:{0,0,0,0},"$USER equips the $ITEM"};
MOVELIST[BattleMoveName::CONSUMABLE]=new Battle::Move{"Consumable","Consumes an item.",baseDmg:0,randomDmg:0,PPCost:0,range:1,channelTime:0,friendly:true,composition:{0,0,0,0},"$USER uses $ITEM on $TARGET"};
MOVELIST[BattleMoveName::CONSUMABLE_ENEMY]=new Battle::Move{"Consumable","Consumes an item.",baseDmg:0,randomDmg:0,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0},"$USER uses $ITEM on $TARGET"};
MOVELIST[BattleMoveName::HAILSTORM_A]=new Battle::Move{"Hailstorm","Causes heavy ice rocks to crash",ALPHA,baseDmg:40,randomDmg:20,PPCost:4,range:4,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HAILSTORM_B]=new Battle::Move{"Hailstorm","Causes heavy ice rocks to crash",BETA,baseDmg:80,randomDmg:20,PPCost:12,range:4,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HAILSTORM_G]=new Battle::Move{"Hailstorm","Causes heavy ice rocks to crash",GAMMA,baseDmg:120,randomDmg:20,PPCost:28,range:4,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HAILSTORM_O]=new Battle::Move{"Hailstorm","Causes heavy ice rocks to crash",OMEGA,baseDmg:210,randomDmg:50,PPCost:69,range:4,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HURRICANE_A]=new Battle::Move{"Hurricane","Scatters seeds, causes heavy rains and winds",ALPHA,baseDmg:25,randomDmg:5,PPCost:7,range:6,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HURRICANE_B]=new Battle::Move{"Hurricane","Scatters seeds, causes heavy rains and winds",BETA,baseDmg:45,randomDmg:5,PPCost:13,range:6,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HURRICANE_G]=new Battle::Move{"Hurricane","Scatters seeds, causes heavy rains and winds",GAMMA,baseDmg:75,randomDmg:10,PPCost:25,range:8,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::HURRICANE_O]=new Battle::Move{"Hurricane","Scatters seeds, causes heavy rains and winds",OMEGA,baseDmg:125,randomDmg:20,PPCost:55,range:8,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::METEORRAIN_A]=new Battle::Move{"Meteor Rain","Causes fiery rocks to fall from the skies. Chance to burn trees.",ALPHA,baseDmg:60,randomDmg:10,PPCost:10,range:2,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::METEORRAIN_B]=new Battle::Move{"Meteor Rain","Causes fiery rocks to fall from the skies. Chance to burn trees.",BETA,baseDmg:110,randomDmg:30,PPCost:22,range:2,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::METEORRAIN_G]=new Battle::Move{"Meteor Rain","Causes fiery rocks to fall from the skies. Chance to burn trees.",GAMMA,baseDmg:200,randomDmg:50,PPCost:47,range:2,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::METEORRAIN_O]=new Battle::Move{"Meteor Rain","Causes fiery rocks to fall from the skies. Chance to burn trees.",OMEGA,baseDmg:390,randomDmg:60,PPCost:98,range:2,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKFREEZE_A]=new Battle::Move{"PK Freeze","A powerful chilling attack causing frostbite and slow.",ALPHA,baseDmg:10,randomDmg:10,PPCost:4,range:1,channelTime:0,friendly:false,composition:{0,0,20,10},properties:{{Property::SLOW,4}}};
MOVELIST[BattleMoveName::PKFREEZE_B]=new Battle::Move{"PK Freeze","A powerful chilling attack causing frostbite and slow.",BETA,baseDmg:120,randomDmg:20,PPCost:8,range:1,channelTime:0,friendly:false,composition:{0,0,20,0},properties:{{Property::SLOW,4}}};
MOVELIST[BattleMoveName::PKFREEZE_G]=new Battle::Move{"PK Freeze","A powerful chilling attack causing frostbite and slow.",GAMMA,baseDmg:240,randomDmg:40,PPCost:12,range:1,channelTime:0,friendly:false,composition:{0,0,20,0},properties:{{Property::SLOW,4}}};
MOVELIST[BattleMoveName::PKFREEZE_O]=new Battle::Move{"PK Freeze","A powerful chilling attack causing frostbite and slow.",OMEGA,baseDmg:480,randomDmg:50,PPCost:22,range:1,channelTime:0,friendly:false,composition:{0,0,20,0},properties:{{Property::SLOW,4}}};
MOVELIST[BattleMoveName::PKSHIELD_A]=new Battle::Move{"PK Shield","Protects against physical attacks.",ALPHA,baseDmg:0,randomDmg:0,PPCost:12,range:1,channelTime:0,friendly:true,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKSHIELD_B]=new Battle::Move{"PK Shield","Protects against physical attacks.",BETA,baseDmg:0,randomDmg:0,PPCost:20,range:1,channelTime:0,friendly:true,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKSHIELD_O]=new Battle::Move{"PK Shield","Protects against physical attacks.",OMEGA,baseDmg:0,randomDmg:0,PPCost:59,range:4,channelTime:0,friendly:true,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKSHIELD_S]=new Battle::Move{"PK Shield","Protects against physical attacks.",SIGMA,baseDmg:0,randomDmg:0,PPCost:80,range:10,channelTime:0,friendly:true,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKLIFEUP_A]=new Battle::Move{"PK Lifeup","Restores a small amount of health.",ALPHA,baseDmg:80,randomDmg:10,PPCost:4,range:1,channelTime:0,friendly:true,composition:{0,0,20,0},overworld:true};
MOVELIST[BattleMoveName::PKLIFEUP_B]=new Battle::Move{"PK Lifeup","Restores a moderate amount of health.",BETA,baseDmg:240,randomDmg:60,PPCost:9,range:1,channelTime:0,friendly:true,composition:{0,0,20,0},overworld:true};
MOVELIST[BattleMoveName::PKLIFEUP_G]=new Battle::Move{"PK Lifeup","Restores a large amount of health.",GAMMA,baseDmg:400,randomDmg:50,PPCost:21,range:3,channelTime:0,friendly:true,composition:{0,0,20,0},overworld:true};
MOVELIST[BattleMoveName::PKLIFEUP_O]=new Battle::Move{"PK Lifeup","Restores a great amount of health to all allies.",OMEGA,baseDmg:800,randomDmg:100,PPCost:64,range:6,channelTime:0,friendly:true,composition:{0,0,20,0},overworld:true};
MOVELIST[BattleMoveName::PKFUN_A]=new Battle::Move{"PK Fun","A very fun barrage. Hits for large damage.",ALPHA,baseDmg:100,randomDmg:10,PPCost:15,range:6,channelTime:0,friendly:false,composition:{0,0,20,0},"$USER uses $POWER",FOUNTAIN_EFFECT};
MOVELIST[BattleMoveName::PKFUN_B]=new Battle::Move{"PK Fun","A very fun barrage. Hits for large damage.",BETA,baseDmg:240,randomDmg:40,PPCost:30,range:6,channelTime:0,friendly:false,composition:{0,0,20,0},"$USER uses $POWER",FOUNTAIN_EFFECT};
MOVELIST[BattleMoveName::PKFUN_G]=new Battle::Move{"PK Fun","A very fun barrage. Hits for large damage.",GAMMA,baseDmg:360,randomDmg:80,PPCost:45,range:7,channelTime:0,friendly:false,composition:{0,0,20,0},"$USER uses $POWER",FOUNTAIN_EFFECT};
MOVELIST[BattleMoveName::PKFUN_O]=new Battle::Move{"PK Fun","A very fun barrage. Hits for large damage.",OMEGA,baseDmg:590,randomDmg:100,PPCost:90,range:8,channelTime:0,friendly:false,composition:{0,0,20,0},"$USER uses $POWER",FOUNTAIN_EFFECT};
MOVELIST[BattleMoveName::PKFIRE_A]=new Battle::Move{"PK Fire","Causes extreme heat to burn foes and scorch trees",ALPHA,baseDmg:60,randomDmg:20,PPCost:6,range:3,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKFIRE_B]=new Battle::Move{"PK Fire","Causes extreme heat to burn foes and scorch trees",BETA,baseDmg:120,randomDmg:40,PPCost:12,range:4,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKFIRE_G]=new Battle::Move{"PK Fire","Causes extreme heat to burn foes and scorch trees",GAMMA,baseDmg:190,randomDmg:50,PPCost:20,range:5,channelTime:0,friendly:false,composition:{0,0,20,0}};
MOVELIST[BattleMoveName::PKFIRE_O]=new Battle::Move{"PK Fire","Causes extreme heat to burn foes and scorch trees",OMEGA,baseDmg:360,randomDmg:100,PPCost:32,range:7,channelTime:0,friendly:false,composition:{0,0,20,0},"$USER uses $POWER",FIREFOUNTAIN_EFFECT};
MOVELIST[BattleMoveName::FREEZE_PACKET]=new Battle::Move{"Freeze Packet","",baseDmg:120,randomDmg:20,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0},"$USER uses the $POWER"};
}
void SetupItemList() { //hpRecovery,ppRecovery,attack,dmgReduction,equip,important,consumable
ITEMLIST[ItemName::COOKIE]=new Item("Cookie","A delightful little treat. Restores 40 HP.",2,{hpRecovery:40,consumable:Consumable::FRIENDLY});
ITEMLIST[ItemName::EGG]=new Item("Egg","Did it come before or after the chicken? Restores 60 HP.",3,{hpRecovery:60,consumable:Consumable::FRIENDLY});
ITEMLIST[ItemName::PIZZA]=new Item("Pizza","A scrumptious meal filled with lots of cheese. Restores 200 HP.",4,{hpRecovery:200,consumable:Consumable::FRIENDLY});
ITEMLIST[ItemName::MIRACLE_FOOD_LUNCH]=new Item("Miracle Food Lunch","It doesn't taste very good, but it's said to have miraculous powers when consumed.",16,{hpRecovery:30,ppRecovery:10,atkIncrease:30,spdIncrease:6,hpIncrease:150,ppIncrease:100,learnAbility:MOVELIST[BattleMoveName::PKFIRE_O],consumable:Consumable::FRIENDLY_PERMANENT});
ITEMLIST[ItemName::BOMB]=new Item("Bomb","A small explosive device. Deals around 120 damage.",256,{damage:110,rollDmg:30,consumable:Consumable::ENEMY});
ITEMLIST[ItemName::CRACKED_BAT]=new Item("Cracked Bat","Has some dents in it, but you can probably still dent things with it yourself.",256,{attack:10,equip:EquipSlot::WEAPON});
ITEMLIST[ItemName::TEE_BALL_BAT]=new Item("Tee Ball Bat","Great for playing some ball! Also great for beating your foes!",256,{attack:40,equip:EquipSlot::WEAPON});
ITEMLIST[ItemName::LIGHT_JACKET]=new Item("Light Jacket","Fits just fine.",256,{defense:10,equip:EquipSlot::ARMOR});
ITEMLIST[ItemName::HEAVY_JACKET]=new Item("Heavy Jacket","Are you sure this is good for your shoulders?",256,{defense:25,equip:EquipSlot::ARMOR});
ITEMLIST[ItemName::COPPER_BRACELET]=new Item("Copper Bracelet","It's not quite as shiny as a diamond, but it still makes you look good.",256,{defense:5,equip:EquipSlot::ACCESSORY});
ITEMLIST[ItemName::KEY_TO_THE_PALACE]=new Item("Key to the Palace","Lets you access a Palace.",256,{important:true});
ITEMLIST[ItemName::FREEZE_PACKET]=new Item("Freeze Packet","Lets out some blistering cold weather.",256,{consumable:Consumable::ENEMY},MOVELIST[BattleMoveName::FREEZE_PACKET]);
ITEMLIST[ItemName::SOME_STUPIDLY_LONG_FEATHER]=new Item("Some Stupidly Long Feather","Yeah, we don't know why this feather is so long either.",256,{attack:2,defense:3,equip:EquipSlot::ACCESSORY});
}
void SetupAnimations() {
CreateSprite("terrainmap.png");
CreateSprite("additionalFont.png");
CreateSprite("rollingcounter.png");
CreateSprite("atbbar_back.png");
CreateSprite("atbbar_front.png");
CreateSprite("cursor.png");
CreateSprite("targetCircle.png");
CreateSprite("targetRange.png");
CreateSprite("crosshair.png");
CreateSprite("arrow_connector.png");
CreateSprite("pixel.png");
CreateSprite("bufficons.png");
}
void SetupObjectInfo() {
CreateObjectInfo(new Standard_Obj(PLAYER,"player",{0,0},nullptr,{2,2},WHITE,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(NESS,"Ness",{0,0},nullptr,{1,1},YELLOW,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(PAULA,"Paula",{0,0},nullptr,{1,1},MAGENTA,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(JEFF,"Jeff",{0,0},nullptr,{1,1},DARK_GREEN,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(ANNA,"Anna",{0,0},nullptr,{1,1},DARK_MAGENTA,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(KING,"King",{0,0},nullptr,{1,1},GREY,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(POO,"Poo",{0,0},nullptr,{1,1},DARK_GREY,32),"player.png",32);
CreateObjectInfo(new Standard_Obj(NPC1,"npc1",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2,"npc2",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3,"npc3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4,"npc4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5,"npc5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6,"npc6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7,"npc7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8,"npc8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9,"npc9",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10,"npc10",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11,"npc11",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12,"npc12",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13,"npc13",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13,"npc14",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14,"npc15",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15,"npc16",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16,"npc17",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17,"npc18",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18,"npc19",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19,"npc20",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_2,"npc1_2",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_2,"npc2_2",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_2,"npc3_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_2,"npc4_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_2,"npc5_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_2,"npc6_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_2,"npc7_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_2,"npc8_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_2,"npc9_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_2,"npc10_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_2,"npc11_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_2,"npc12_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_2,"npc13_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_2,"npc14_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_2,"npc15_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_2,"npc16_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_2,"npc17_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_2,"npc18_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_2,"npc19_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_2,"npc20_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_3,"npc1_3",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_3,"npc2_3",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_3,"npc3_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_3,"npc4_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_3,"npc5_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_3,"npc6_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_3,"npc7_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_3,"npc8_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_3,"npc9_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_3,"npc10_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_3,"npc11_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_3,"npc12_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_3,"npc13_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_3,"npc14_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_3,"npc15_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_3,"npc16_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_3,"npc17_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_3,"npc18_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_3,"npc19_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_3,"npc20_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_4,"npc1_4",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_4,"npc2_4",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_4,"npc3_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_4,"npc4_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_4,"npc5_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_4,"npc6_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_4,"npc7_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_4,"npc8_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_4,"npc9_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_4,"npc10_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_4,"npc11_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_4,"npc12_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_4,"npc13_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_4,"npc14_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_4,"npc15_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_4,"npc16_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_4,"npc17_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_4,"npc18_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_4,"npc19_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_4,"npc20_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_5,"npc1_5",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_5,"npc2_5",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_5,"npc3_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_5,"npc4_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_5,"npc5_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_5,"npc6_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_5,"npc7_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_5,"npc8_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_5,"npc9_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_5,"npc10_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_5,"npc11_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_5,"npc12_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_5,"npc13_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_5,"npc14_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_5,"npc15_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_5,"npc16_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_5,"npc17_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_5,"npc18_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_5,"npc19_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_5,"npc20_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_6,"npc1_6",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_6,"npc2_6",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_6,"npc3_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_6,"npc4_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_6,"npc5_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_6,"npc6_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_6,"npc7_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_6,"npc8_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_6,"npc9_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_6,"npc10_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_6,"npc11_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_6,"npc12_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_6,"npc13_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_6,"npc14_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_6,"npc15_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_6,"npc16_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_6,"npc17_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_6,"npc18_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_6,"npc19_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_6,"npc20_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_7,"npc1_7",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_7,"npc2_7",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_7,"npc3_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_7,"npc4_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_7,"npc5_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_7,"npc6_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_7,"npc7_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_7,"npc8_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_7,"npc9_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_7,"npc10_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_7,"npc11_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_7,"npc12_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_7,"npc13_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_7,"npc14_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_7,"npc15_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_7,"npc16_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_7,"npc17_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_7,"npc18_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_7,"npc19_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC19_7,"npc20_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC1_8,"npc1_8",{0,0},nullptr,{1,1},RED,60),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC2_8,"npc2_8",{0,0},nullptr,{1,1},GREEN,2),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC3_8,"npc3_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC4_8,"npc4_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC5_8,"npc5_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC6_8,"npc6_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC7_8,"npc7_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC8_8,"npc8_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC9_8,"npc9_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC10_8,"npc10_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC11_8,"npc11_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC12_8,"npc12_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_8,"npc13_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC13_8,"npc14_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC14_8,"npc15_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC15_8,"npc16_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC16_8,"npc17_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC17_8,"npc18_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Standard_Obj(NPC18_8,"npc19_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new Shopkeeper_Obj(SHOPKEEPER,"Shopkeeper",{0,0},nullptr,{1,1},YELLOW,20),"player.png",32,Flag::NONE,Flag::NONE);
CreateObjectInfo(new TrashCan_Obj(TRASH_CAN,"trashCan",{0,0},nullptr,{1,1},WHITE,0),"trashcan.png",32,Flag::NONE,Flag::NONE);
}
void SetupEncounters() {
ENCOUNTER_LIST.push_back(new Encounter(encounter::ENCOUNTER_1,{0,0},std::array<vd2d,4>{vd2d
{grid(1,2)},{grid(2,2)},{grid(3,2)},{grid(4,2)}},
std::vector<Entity*>{
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",3,2,ANIMATIONS["player.png"]),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj 2",1,3,ANIMATIONS["player.png"]),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj 3",2,2,ANIMATIONS["player.png"]),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
}));//ENCOUNTER_1
ENCOUNTER_LIST.push_back(new Encounter(encounter::ENCOUNTER_2,{0,0},std::array<vd2d,4>{vd2d
{grid(1,1)},{grid(2,2)},{grid(3,2)},{grid(4,2)}},
std::vector<Entity*>{
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",1,4,ANIMATIONS["player.png"],{2,2},GREEN,20),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},{
ITEMLIST[ItemName::COOKIE],
ITEMLIST[ItemName::EGG],
ITEMLIST[ItemName::PIZZA],
ITEMLIST[ItemName::MIRACLE_FOOD_LUNCH],
},
35),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj 2",1,2,ANIMATIONS["player.png"],{2,2},GREEN,20),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},{
ITEMLIST[ItemName::COOKIE],
ITEMLIST[ItemName::EGG],
ITEMLIST[ItemName::PIZZA],
ITEMLIST[ItemName::MIRACLE_FOOD_LUNCH],
},
35),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj 3",2,1,ANIMATIONS["player.png"],{2,2},GREEN,20),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},{
ITEMLIST[ItemName::COOKIE],
ITEMLIST[ItemName::EGG],
ITEMLIST[ItemName::PIZZA],
ITEMLIST[ItemName::MIRACLE_FOOD_LUNCH],
},
35),
}));//ENCOUNTER_2
ENCOUNTER_LIST.push_back(new Encounter(encounter::ENCOUNTER_3,{0,0},std::array<vd2d,4>{vd2d
{grid(1,1)},{grid(2,2)},{grid(3,2)},{grid(4,2)}},
std::vector<Entity*>{
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",1,2,ANIMATIONS["player.png"],{1,1},MAGENTA),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
}));//ENCOUNTER_3
ENCOUNTER_LIST.push_back(new Encounter(encounter::ENCOUNTER_4,{0,0},std::array<vd2d,4>{vd2d
{grid(1,2)},{grid(2,2)},{grid(3,2)},{grid(4,2)}},
std::vector<Entity*>{
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",6,2,ANIMATIONS["player.png"],{1,1},MAGENTA),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",7,2,ANIMATIONS["player.png"],{1,1},MAGENTA),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
new Entity(new Standard_Obj(
NPC1_4,"Test Obj",3,5,ANIMATIONS["player.png"],{1,1},MAGENTA),
{HP:70,maxHP:70,PP:10,maxPP:10,baseAtk:14,speed:5,resistances:{0,0,0,0}},std::vector<Battle::Move*>{
MOVELIST[BattleMoveName::TESTMOVE1],
MOVELIST[BattleMoveName::TESTMOVE2],
MOVELIST[BattleMoveName::TESTMOVE3],
},
{},
0),
}));//ENCOUNTER_4
}
void SetupBattleProperties() {
BATTLE_PROPERTIES[Property::PETRIFY]=new Property_PETRIFY();
BATTLE_PROPERTIES[Property::PARALYZE]=new Property_PARALYZE();
BATTLE_PROPERTIES[Property::DIAMONDIZE]=new Property_DIAMONDIZE();
BATTLE_PROPERTIES[Property::CRYING]=new Property_CRYING();
BATTLE_PROPERTIES[Property::SLOW]=new Property_SLOW();
BATTLE_PROPERTIES[Property::MUSHROOMIZED]=new Property_MUSHROOMIZED();
BATTLE_PROPERTIES[Property::CONFUSE]=new Property_CONFUSE();
BATTLE_PROPERTIES[Property::POISON]=new Property_POISON();
BATTLE_PROPERTIES[Property::REGEN]=new Property_REGEN();
BATTLE_PROPERTIES[Property::DEFENSE_UP]=new Property_DEFENSE_UP();
BATTLE_PROPERTIES[Property::REVIVE]=new Property_REVIVE();
BATTLE_PROPERTIES[Property::NONE]=new Property_NONE();
}
Object* AddObjectToWorld(Object*obj) {
std::vector<Object*>::const_iterator it = OBJECTS.begin();
if (obj->id==PLAYER&&!obj->temp) {
PARTY_MEMBER_OBJ[0]=obj;
PARTY_MEMBER_ID[0]=0;
PARTY_MEMBER_OBJ[0]->name="PLAYER";
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[0]]->obj=PARTY_MEMBER_OBJ[0];
for (int i=toint(Flag::HAS_MAIN)+1;i<=toint(Flag::HAS_POO);i++) {
if (GetGameFlag(i)) {
PARTY_MEMBER_ID[PARTY_MEMBER_COUNT]=toint(PLAYER)+i-toint(Flag::HAS_MAIN);
PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]=AddObjectToWorld(CreateObject(toint(PLAYER)+i-toint(Flag::HAS_MAIN),PARTY_MEMBER_OBJ[0]->GetPos()));
switch (toint(PLAYER)+i-toint(Flag::HAS_MAIN)) {
case 0:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="PLAYER";}break;
case 1:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="NESS";}break;
case 2:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="PAULA";}break;
case 3:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="JEFF";}break;
case 4:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="ANNA";}break;
case 5:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="KING";}break;
case 6:{PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->name="POO";}break;
}
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[PARTY_MEMBER_COUNT]]->obj=PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT];
PARTY_MEMBER_COUNT++;
if (PARTY_MEMBER_COUNT==4) {
break;
}
}
}
}
bool inserted=false;
for (int i=0;i<OBJECTS.size();i++) {
if (!inserted&&OBJECTS[i]->GetPos().y+OBJECTS[i]->originPoint.y>obj->GetPos().y+obj->originPoint.y) {
OBJECTS.insert(it,obj);
obj->objArrElement=i;
inserted=true;
break;
}
it++;
}
if (!inserted) {
obj->objArrElement=OBJECTS.size();
OBJECTS.push_back(obj);
} else {
for (int i=0;i<OBJECTS.size();i++) {
OBJECTS[i]->objArrElement=i;
}
}
//printf("OBJECTS (%d):\n",OBJECTS.size());
for (int i=0;i<OBJECTS.size();i++) {
if (i!=OBJECTS[i]->objArrElement) {
printf("%d :: Object %s - %d (%lf,%lf)\n",i,OBJECTS[i]->name.c_str(),OBJECTS[i]->objArrElement,OBJECTS[i]->GetPos().x,OBJECTS[i]->GetPos().y);
}
assert(i==OBJECTS[i]->objArrElement);
}
return obj;
//printf("\n");
}
bool TabHeld(){
return GetKey(TAB).bHeld;
}
bool UpPressed(){
return GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed||MOUSE_PRESSED_DOWN&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128||KeyRepeat(UP);
}
bool DownPressed(){
return GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed||MOUSE_PRESSED_DOWN&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128||KeyRepeat(DOWN);
}
bool LeftPressed(){
return GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128||KeyRepeat(LEFT);
}
bool RightPressed(){
return GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128||KeyRepeat(RIGHT);
}
bool UpHeld(){
return GetKey(W).bHeld||GetKey(UP).bHeld||GetKey(NP8).bHeld||MOUSE_DOWN&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128;
}
bool DownHeld(){
return GetKey(S).bHeld||GetKey(DOWN).bHeld||GetKey(NP5).bHeld||GetKey(NP2).bHeld||MOUSE_DOWN&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128;
}
bool LeftHeld(){
return GetKey(A).bHeld||GetKey(LEFT).bHeld||GetKey(NP4).bHeld||MOUSE_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128;
}
bool RightHeld(){
return GetKey(D).bHeld||GetKey(RIGHT).bHeld||GetKey(NP6).bHeld||MOUSE_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128;
}
bool UpReleased(){
return GetKey(W).bReleased||GetKey(UP).bReleased||GetKey(NP8).bReleased||MOUSE_RELEASED&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128;
}
bool DownReleased(){
return GetKey(S).bReleased||GetKey(DOWN).bReleased||GetKey(NP5).bReleased||GetKey(NP2).bReleased||MOUSE_RELEASED&&GetMouseY()<=HEIGHT&&GetMouseY()>=HEIGHT-32&&GetMouseX()<=HEIGHT-128;
}
bool LeftReleased(){
return GetKey(A).bReleased||GetKey(LEFT).bReleased||GetKey(NP4).bReleased||MOUSE_RELEASED&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128;
}
bool RightReleased(){
return GetKey(D).bReleased||GetKey(RIGHT).bReleased||GetKey(NP6).bReleased||MOUSE_RELEASED&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128;
}
bool PlayerCanMove(){
return GAME_STATE==GameState::GAME_WORLD&&BATTLE_ENCOUNTER==nullptr&&!IsTextEntryEnabled()&&!messageBoxVisible&&PARTY_MEMBER_OBJ[0]!=nullptr&&CurrentCutscene==nullptr;
}
void DrawDialogBox(const vi2d &pos, const vi2d &size, Pixel p = WHITE, Pixel p2 = DARK_GREY, Pixel p3 = VERY_DARK_GREY) {
DrawDecal({(float)pos.x,(float)pos.y},SPRITES["pixel.png"],size,p2);
DrawDecal({(float)pos.x+1,(float)pos.y+1},SPRITES["pixel.png"],{(float)size.x-2,(float)size.y-2},p);
DrawDecal({(float)pos.x+2,(float)pos.y+2},SPRITES["pixel.png"],{(float)size.x-4,(float)size.y-4},p3);
DrawDecal({(float)pos.x+3,(float)pos.y+3},SPRITES["pixel.png"],{(float)size.x-5,(float)size.y-5},p);
DrawDecal({(float)pos.x,(float)pos.y},SPRITES["pixel.png"],{1,1},Pixel(77, 51, 125));
DrawDecal({(float)(pos.x+size.x-1),(float)(pos.y+size.y-1)},SPRITES["pixel.png"],{1,1},Pixel(77, 51, 125));
DrawDecal({(float)(pos.x+size.x-1),(float)(pos.y)},SPRITES["pixel.png"],{1,1},Pixel(77, 51, 125));
DrawDecal({(float)(pos.x),(float)(pos.y+size.y-1)},SPRITES["pixel.png"],{1,1},Pixel(77, 51, 125));
}
void StartCutscene(Cutscene*cutscene) {
CurrentCutscene=cutscene;
}
ActionType GetCurrentCutsceneAction() {
return (CurrentCutscene==nullptr)?ActionType::NONE:CurrentCutscene->CurrentAction();
}
bool MoveCameraTowardsPoint(vd2d targetPos,PriorityDirection dir,double spd,bool secondRun=false) {
bool reachedPosition=true;
if (dir==HORZ_FIRST||dir==BOTH) {
if (cameraPos.x!=targetPos.x) {
if (cameraPos.x<targetPos.x) {
cameraPos.x+=spd;
if (cameraPos.x>targetPos.x) {
cameraPos.x=targetPos.x;
}
} else {
cameraPos.x-=spd;
if (cameraPos.x<targetPos.x) {
cameraPos.x=targetPos.x;
}
}
reachedPosition=false;
} else
if (!secondRun&&dir!=BOTH) {
MoveCameraTowardsPoint(targetPos,dir,spd,true);
}
}
if (dir==VERT_FIRST||dir==BOTH) {
if (cameraPos.y!=targetPos.y) {
if (cameraPos.y<targetPos.y) {
cameraPos.y+=spd;
if (cameraPos.y>targetPos.y) {
cameraPos.y=targetPos.y;
}
} else {
cameraPos.y-=spd;
if (cameraPos.y<targetPos.y) {
cameraPos.y=targetPos.y;
}
}
reachedPosition=false;
} else
if (!secondRun&&dir!=BOTH) {
MoveCameraTowardsPoint(targetPos,dir,spd,true);
}
}
return reachedPosition;
}
bool MoveObjectTowardsPoint(Object*obj,vd2d targetPos,PriorityDirection dir,double moveSpd,bool secondRun=false) {
bool reachedPosition=true;
if (dir==HORZ_FIRST||dir==BOTH) {
if (obj->GetPos().x!=targetPos.x) {
if (obj->GetPos().x<targetPos.x) {
obj->Move({moveSpd,0});
if (obj->GetPos().x>targetPos.x) {
obj->SetPos({targetPos.x,obj->GetPos().y});
}
} else {
obj->Move({-moveSpd,0});
if (obj->GetPos().x<targetPos.x) {
obj->SetPos({targetPos.x,obj->GetPos().y});
}
}
reachedPosition=false;
} else
if (!secondRun&&dir!=BOTH) {
MoveObjectTowardsPoint(obj,targetPos,dir,moveSpd,true);
}
}
if (dir==VERT_FIRST||dir==BOTH) {
if (obj->GetPos().y!=targetPos.y) {
if (obj->GetPos().y<targetPos.y) {
obj->Move({0,moveSpd});
if (obj->GetPos().y>targetPos.y) {
obj->SetPos({obj->GetPos().x,targetPos.y});
}
} else {
obj->Move({0,-moveSpd});
if (obj->GetPos().y<targetPos.y) {
obj->SetPos({obj->GetPos().x,targetPos.y});
}
}
reachedPosition=false;
} else
if (!secondRun&&dir!=BOTH) {
MoveObjectTowardsPoint(obj,targetPos,dir,moveSpd,true);
}
}
return reachedPosition;
}
void SetGameFlag(Flag flag,bool val) {
GAME_FLAGS[toint(flag)]=val;
}
bool GetGameFlag(int flag) {
return GAME_FLAGS[flag];
}
bool GetGameFlag(Flag flag) {
return GAME_FLAGS[toint(flag)];
}
void LoadEncounter(Map*map,vd2d pos,int chance,int id,bool successful) {
std::vector<Entity*>ents;
for (int i=0;i<ENCOUNTER_LIST[id]->objs.size();i++) {
Entity*ent=ENCOUNTER_LIST[id]->objs[i];
Object*newObj=new Standard_Obj(ent->obj->id,ent->obj->name,ent->obj->GetPos(),ent->obj->spr,ent->obj->GetScale(),ent->obj->color,ent->obj->animationSpd,ent->obj->temp);
ents.push_back(new Entity(newObj,{ent->GetHP(),ent->GetPP(),ent->GetTargetHP(),ent->GetTargetPP(),ent->stats.maxHP,ent->stats.maxPP,ent->stats.baseAtk,ent->stats.speed,ent->stats.resistances,ent->stats.damageReduction,ent->stats.smart,ent->stats.dumb},ent->moveSet,ent->inventory,ent->money,ent->equipment));
}
Encounter*data=new Encounter(id,pos,ENCOUNTER_LIST[id]->playerPos,ents,chance);
data->chance=chance;
data->id=id;
for (int i=0;i<data->objs.size();i++) {
data->objs[i]->obj->enc=true;
if (!successful) {
data->objs[i]->_SetDirectHP(0);
data->objs[i]->obj->dead=true;
}
}
map->encounters.push_back(data);
for (int i=0;i<data->objs.size();i++) {
AddObjectToWorld(data->objs[i]->obj);
data->objs[i]->obj->SetPos(data->objs[i]->obj->GetPos()+pos);
}
}
void UpdatePlayerTrail(vd2d newMovement) {
for (int i=PARTY_TRAIL_LENGTH-1;i>0;i--) {
partyTrail[i]=partyTrail[i-1];
}
partyTrail[0]={PARTY_MEMBER_OBJ[0]->GetPos().x-newMovement.x+PARTY_MEMBER_OBJ[0]->spr->width*0.5*(PARTY_MEMBER_OBJ[0]->GetScale().x-1),
PARTY_MEMBER_OBJ[0]->GetPos().y-newMovement.y+(PARTY_MEMBER_OBJ[0]->spr->spr->sprite->height-4)*(PARTY_MEMBER_OBJ[0]->GetScale().y-1)};
for (int i=1;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_OBJ[i]->SetPos(partyTrail[PARTY_TRAIL_LENGTH*((double)i/4)]);
}
}
void drawBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p = olc::WHITE, olc::Pixel p2 = olc::DARK_GREY, olc::Pixel p3 = olc::VERY_DARK_GREY) {
FillRectDecal({(float)(pos.x+3),(float)(pos.y+3)},{(float)(size.x-5),(float)(size.y-5)},p);
DrawRectDecal({(float)pos.x,(float)pos.y},size,p2);
DrawRectDecal({(float)pos.x+2,(float)pos.y+2},{(float)size.x-4,(float)size.y-4},p3);
DrawRectDecal({(float)pos.x+1,(float)pos.y+1},{(float)size.x-2,(float)size.y-2},p);
Draw({pos.x,pos.y},olc::BLACK);
Draw({pos.x+size.x,pos.y+size.y},olc::BLACK);
Draw({pos.x+size.x,pos.y},olc::BLACK);
Draw({pos.x,pos.y+size.y},olc::BLACK);
}
void drawCheckerboardBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p = olc::WHITE, olc::Pixel alternatingCol = olc::WHITE, const olc::vi2d &checkerboardSize = {3,3}, olc::Pixel p2 = olc::DARK_GREY, olc::Pixel p3 = olc::VERY_DARK_GREY) {
drawBox(pos,size,p,p2,p3);
for (int x=3;x<size.x;x+=checkerboardSize.x*2) {
for (int y=3;y<size.y;y+=checkerboardSize.y*2) {
if (x+checkerboardSize.x<size.x&&y+checkerboardSize.y<size.y) {
FillRectDecal({(float)(x+pos.x),(float)(y+pos.y)},{(float)checkerboardSize.x,(float)checkerboardSize.y},alternatingCol);
}
}
}
}
void DrawRollingCounter(const olc::vi2d &pos,int val,int*rollcounter,int*rolloffset) {
int boxAlpha=BATTLE_STATE==BattleState::TARGET_SELECT?64:255;
FillRectDecal({(float)(pos.x+20),(float)(pos.y-3)},{30,13},Pixel(128,128,128,boxAlpha));
FillRectDecal({(float)(pos.x+21),(float)(pos.y-2)},{28,11},Pixel(192,192,192,boxAlpha));
DrawLineDecal({(float)(pos.x+30),(float)(pos.y-3)},{(float)(pos.x+30),(float)(pos.y+10)},Pixel(128,128,128,boxAlpha));
DrawLineDecal({(float)(pos.x+40),(float)(pos.y-3)},{(float)(pos.x+40),(float)(pos.y+10)},Pixel(128,128,128,boxAlpha));
DrawPartialDecal({(float)(pos.x+22),(float)(pos.y-1)},{7,9},SPRITES["rollingcounter.png"],{0,(float)(rollcounter[2]*13+rolloffset[2]+13)},{7,9},Pixel(255,255,255,boxAlpha));
DrawPartialDecal({(float)(pos.x+31),(float)(pos.y-1)},{7,9},SPRITES["rollingcounter.png"],{0,(float)(rollcounter[1]*13+rolloffset[1]+13)},{7,9},Pixel(255,255,255,boxAlpha));
DrawPartialDecal({(float)(pos.x+41),(float)(pos.y-1)},{7,9},SPRITES["rollingcounter.png"],{0,(float)(rollcounter[0]*13+rolloffset[0]+13)},{7,9},Pixel(255,255,255,boxAlpha));
}
void ResetBattleState() {
CAMERA_WAIT_TIMER=0;
}
std::string Wrap(std::string str,int width,bool proportional,vd2d scale) {
int marker=0;
std::string newStr="";
bool firstChar=false;
while (marker<str.length()) {
if (firstChar||!firstChar&&str[marker]!=' ') {
newStr+=str[marker];
}
vd2d siz;
if (proportional) {
siz={GetTextSizeProp(newStr).x*scale.x,GetTextSizeProp(newStr).y*scale.y};
} else {
siz={GetTextSize(newStr).x*scale.x,GetTextSize(newStr).y*scale.y};
}
if (siz.x>width) {
do {
if (newStr[newStr.length()-1]!=' ') {
marker--;
//printf("%s\n",newStr.c_str());
}
newStr.erase(newStr.end()-1);
} while (newStr[newStr.length()-1]!=' ');
//newStr.erase(newStr.end()-1);
newStr+='\n';
firstChar=false;
} else {
firstChar=true;
marker++;
}
}
return newStr;
}
//Returns 0 if not found.
int getProperty(Property prop,Battle::Move*move) {
return move->properties[prop];
}
void HandleBattle() {
if (BATTLE_ENCOUNTER!=nullptr) {
switch (BATTLE_STATE) {
case BattleState::MOVE_CAMERA:{
bool allDone=true;
if (!MoveCameraTowardsPoint(BATTLE_ENCOUNTER->pos,PriorityDirection::BOTH,BATTLE_CAMERA_MOVESPD)) {
allDone=false;
}
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (!MoveObjectTowardsPoint(PARTY_MEMBER_OBJ[i],
{BATTLE_ENCOUNTER->playerPos[i].x+BATTLE_ENCOUNTER->pos.x-PARTY_MEMBER_OBJ[i]->spr->width*0.5*(PARTY_MEMBER_OBJ[i]->GetScale().x-1),
BATTLE_ENCOUNTER->playerPos[i].y+BATTLE_ENCOUNTER->pos.y-(PARTY_MEMBER_OBJ[i]->spr->spr->sprite->height-4)*1*(PARTY_MEMBER_OBJ[i]->GetScale().y-1)},
PriorityDirection::BOTH,BATTLE_CAMERA_MOVESPD)) {
allDone=false;
}
}
if (allDone) {
CAMERA_WAIT_TIMER++;
if (CAMERA_WAIT_TIMER>=CAMERA_WAIT_TIME) {
BATTLE_STATE=BattleState::WAIT;
}
}
}break;
case BattleState::WAIT:{
BATTLE_ROLLING_COUNTER_WAITTIME=0;
bool done=false;
if (!done) {
for (int i=0;i<4;i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP()>0) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove!=nullptr) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelTimeRemaining>0) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelTimeRemaining--;
} else {
//Attack is being done.
printf("%s performs %s.\n",PARTY_MEMBER_OBJ[i]->name.c_str(),PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove->name.c_str());
BATTLE_STATE=BattleState::WAIT_ANIMATION;
BATTLE_ANIMATION_TIMER=0;
CURRENT_TURN=-i-1;
done=true;
break;
}
}
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove=nullptr;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelTimeRemaining=0;
}
}
}
if (!done) {
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (BATTLE_ENCOUNTER->objs[i]->GetHP()>0) {
if (BATTLE_ENCOUNTER->objs[i]->selectedMove!=nullptr) {
if (BATTLE_ENCOUNTER->objs[i]->channelTimeRemaining>0) {
BATTLE_ENCOUNTER->objs[i]->channelTimeRemaining--;
} else {
CURRENT_TURN=i;
printf("%s performs %s.\n",BATTLE_ENCOUNTER->objs[i]->obj->name.c_str(),BATTLE_ENCOUNTER->objs[i]->selectedMove->name.c_str());
BATTLE_STATE=BattleState::WAIT_ANIMATION;
BATTLE_ANIMATION_TIMER=0;
done=true;
break;
}
}
} else {
BATTLE_ENCOUNTER->objs[i]->selectedMove=nullptr;
BATTLE_ENCOUNTER->objs[i]->channelTimeRemaining=0;
}
}
}
if (!done) {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP()>0) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove==nullptr) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->atb>=1000) {
bool turnAllowed=true;
for (std::map<Property,int>::iterator it=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->statusEffects.begin();it!=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->statusEffects.end();++it) {
if (!BATTLE_PROPERTIES[it->first]->OnTurnStart(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]],it->second)) {
turnAllowed=false;
}
}
if (turnAllowed) {
printf("%s ready.\n",PARTY_MEMBER_OBJ[i]->name.c_str());
CURRENT_TURN=-i-1;
BATTLE_STATE=BattleState::SELECT_ACTION;
BATTLE_SELECTION_CURSOR=0;
POWER_GRADE_CURSOR[-CURRENT_TURN-1]=0;
done=true;
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->atb=0;
}
break;
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->atb+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->stats.speed;
}
}
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->atb=0;
}
}
}
if (!done) {
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (BATTLE_ENCOUNTER->objs[i]->GetHP()>0) {
if (BATTLE_ENCOUNTER->objs[i]->selectedMove==nullptr) {
if (BATTLE_ENCOUNTER->objs[i]->atb>=1000) {
printf("%s (%d) ready.\n",BATTLE_ENCOUNTER->objs[i]->obj->name.c_str(),i);
bool turnAllowed=true;
for (std::map<Property,int>::iterator it=BATTLE_ENCOUNTER->objs[i]->statusEffects.begin();it!=BATTLE_ENCOUNTER->objs[i]->statusEffects.end();++it) {
if (BATTLE_ENCOUNTER->objs[i]->statusEffects[it->first]) {
if (!BATTLE_PROPERTIES[it->first]->OnTurnStart(BATTLE_ENCOUNTER->objs[i],it->second)) {
turnAllowed=false;
}
}
}
if (turnAllowed) {
CURRENT_TURN=i;
//Enemy picks a random move from the movelist. And a random target.
BATTLE_ENCOUNTER->objs[i]->selectedMove=BATTLE_ENCOUNTER->objs[i]->moveSet[rand()%BATTLE_ENCOUNTER->objs[i]->moveSet.size()];
BATTLE_ENCOUNTER->objs[i]->channelTimeRemaining=BATTLE_ENCOUNTER->objs[i]->selectedMove->channelTime;
if (BATTLE_ENCOUNTER->objs[i]->selectedMove->friendly) {
do {
BATTLE_ENCOUNTER->objs[i]->selectedTarget=rand()%BATTLE_ENCOUNTER->objs.size();
} while (BATTLE_ENCOUNTER->objs[BATTLE_ENCOUNTER->objs[i]->selectedTarget]->GetHP()<=0);
BATTLE_ENCOUNTER->objs[i]->channelPos=BATTLE_ENCOUNTER->objs[BATTLE_ENCOUNTER->objs[i]->selectedTarget]->obj->GetPosWithOrigin();
} else {
bool playerAlive=false;
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP()>0) {
playerAlive=true;
break;
}
}
if (playerAlive) {
do {
BATTLE_ENCOUNTER->objs[i]->selectedTarget=-(rand()%PARTY_MEMBER_COUNT)-1;
} while (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-BATTLE_ENCOUNTER->objs[i]->selectedTarget-1]]->GetHP()<=0);
BATTLE_ENCOUNTER->objs[i]->channelPos=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-BATTLE_ENCOUNTER->objs[i]->selectedTarget-1]]->obj->GetPosWithOrigin();
printf("Selected Target: %d\n",BATTLE_ENCOUNTER->objs[i]->selectedTarget);
}
}
printf(" %s chose move %s.\n",BATTLE_ENCOUNTER->objs[i]->obj->name.c_str(),BATTLE_ENCOUNTER->objs[i]->selectedMove->name.c_str());
BATTLE_STATE=BattleState::WAIT;
BATTLE_SELECTION_CURSOR=0;
done=true;
} else {
BATTLE_ENCOUNTER->objs[i]->atb=0;
}
break;
} else {
BATTLE_ENCOUNTER->objs[i]->atb+=BATTLE_ENCOUNTER->objs[i]->stats.speed;
}
}
} else {
BATTLE_ENCOUNTER->objs[i]->atb=0;
}
}
}
}break;
case BattleState::WAIT_ANIMATION:{
BATTLE_ROLLING_COUNTER_WAITTIME=5;
BATTLE_ANIMATION_TIMER++;
if (CURRENT_TURN<0) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove==MOVELIST[BattleMoveName::DEFEND]) {
BATTLE_ANIMATION_TIMER=999;
}
} else {
if (BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove==MOVELIST[BattleMoveName::DEFEND]) {
BATTLE_ANIMATION_TIMER=999;
}
}
if (BATTLE_ANIMATION_TIMER==30) {
Effect*eff=(CURRENT_TURN<0)?PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->eff:BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->eff;
if (eff!=nullptr) {
StartEffect(eff);
}
}
if (BATTLE_ANIMATION_TIMER>=120&&(BATTLE_ANIMATION_TIMER-120)%90==0) {
int index = (BATTLE_ANIMATION_TIMER-120)/90;
if (index<BATTLE_CUSTOM_MSGS.size()) {
BATTLE_CURRENT_CUSTOM_MSG=BATTLE_CUSTOM_MSGS[index];
Entity*target = PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget-1]];
switch (BATTLE_CURRENT_CUSTOM_MSG.a) {
case ItemAction::HPRECOVERY:{
//
}break;
case ItemAction::PPRECOVERY:{
target->AddPP(BATTLE_CUSTOM_ITEM->stats.ppRecovery);
}break;
case ItemAction::ATKINCREASE:{
target->stats.baseAtk+=BATTLE_CUSTOM_ITEM->stats.atkIncrease;
target->boosts[boost::ATK]+=BATTLE_CUSTOM_ITEM->stats.atkIncrease;
}break;
case ItemAction::HPINCREASE:{
target->stats.maxHP+=BATTLE_CUSTOM_ITEM->stats.hpIncrease;
target->AddHP(BATTLE_CUSTOM_ITEM->stats.hpIncrease);
target->boosts[boost::HP]+=BATTLE_CUSTOM_ITEM->stats.hpIncrease;
}break;
case ItemAction::PPINCREASE:{
target->stats.maxPP+=BATTLE_CUSTOM_ITEM->stats.ppIncrease;
target->AddPP(BATTLE_CUSTOM_ITEM->stats.ppIncrease);
target->boosts[boost::PP]+=BATTLE_CUSTOM_ITEM->stats.ppIncrease;
}break;
case ItemAction::SPDINCREASE:{
target->stats.speed+=BATTLE_CUSTOM_ITEM->stats.spdIncrease;
target->boosts[boost::SPD]+=BATTLE_CUSTOM_ITEM->stats.spdIncrease;
}break;
case ItemAction::LEARNMOVE:{
bool moveLearned=false;
for (int i=0;i<target->moveSet.size();i++) {
if (BATTLE_CUSTOM_ITEM->stats.learnAbility==target->moveSet[i]) {
moveLearned=true;
break;
}
}
if (!moveLearned) {
target->moveSet.push_back(BATTLE_CUSTOM_ITEM->stats.learnAbility);
} else {
BATTLE_CURRENT_CUSTOM_MSG.s="Failed to learn "+BATTLE_CUSTOM_ITEM->stats.learnAbility->GetPowerName();
}
}break;
}
}
}
if (CURRENT_EFFECT==nullptr&&BATTLE_ANIMATION_TIMER==90||CURRENT_EFFECT!=nullptr&&BATTLE_ANIMATION_TIMER>CURRENT_EFFECT->maxLifeTime) {
if (CURRENT_TURN<0) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget!=NO_TARGET) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->friendly) {
if (PARTY_MEMBER_STATS[-PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget-1]->GetHP()>0) {
for (auto&ent:GetEntitiesInRange(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
int healAmt = CalculateHealing(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]);
if (ent->GetHP()>0) {
std::cout << PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->name << " uses " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->name << " " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->grade << " on " << ent->obj->name << " recovering " << healAmt << " health.\n";
ent->AddHP(healAmt);
int memberID = getMemberIDComparingObject(ent->obj);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+memberID*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(-healAmt,box+cameraPos));
}
for (std::map<Property,int>::iterator it=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->properties.begin();it!=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->properties.end();++it) {
BATTLE_PROPERTIES[it->first]->OnApplication(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget]],it->second);
}
}
} else {
std::cout << PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->name << " uses " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->name << " " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->grade << " on " << PARTY_MEMBER_OBJ[-PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget-1]->name << " but it failed.\n";
}
} else {
if (BATTLE_ENCOUNTER->objs[PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget]->GetHP()>0) {
//Enemies have their health directly set.
for (auto&ent:GetEntitiesInRange(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
int dmgAmt = CalculateDamage(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]],ent);
if (ent->GetHP()>0) {
std::cout << PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->name << " uses " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->name << " " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->grade << " on " << ent->obj->name << " dealing " << dmgAmt << " health.\n";
ent->_SetDirectHP(ent->GetHP()-dmgAmt);
ent->obj->blinkFrames=35;
if (ent->GetHP()<=0) {
ent->obj->dead=true;
}
DAMAGE_NUMBERS.push_back(new DamageNumber(dmgAmt,ent->obj->GetPosWithOrigin()));
}
}
for (std::map<Property,int>::iterator it=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->properties.begin();it!=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->properties.end();++it) {
BATTLE_PROPERTIES[it->first]->OnApplication(BATTLE_ENCOUNTER->objs[PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget],it->second);
}
} else {
std::cout << PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->name << " uses " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->name << " " << PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->grade << " on " << BATTLE_ENCOUNTER->objs[PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget]->obj->name << " but it failed.\n";
}
}
}
} else {
if (BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget!=-NO_TARGET) {
if (BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->friendly) {
if (BATTLE_ENCOUNTER->objs[BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget]->GetHP()>0) {
for (auto&ent:GetEntitiesInRange(BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->channelPos,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove)) {
int healAmt = CalculateHealing(BATTLE_ENCOUNTER->objs[CURRENT_TURN]);
if (ent->GetHP()>0) {
std::cout << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->obj->name << " uses " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->name << " " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->grade << " on " << ent->obj->name << " recovering " << healAmt << " health.\n";
ent->AddHP(healAmt);
DAMAGE_NUMBERS.push_back(new DamageNumber(-healAmt,ent->obj->GetPosWithOrigin()));
}
}
} else {
std::cout << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->obj->name << " uses " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->name << " " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->grade << " on " << BATTLE_ENCOUNTER->objs[BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget]->obj->name << " but it failed.\n";
}
for (std::map<Property,int>::iterator it=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->properties.begin();it!=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->properties.end();++it) {
BATTLE_PROPERTIES[it->first]->OnApplication(BATTLE_ENCOUNTER->objs[BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget],it->second);
}
} else {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget-1]]->GetHP()>0) {
for (auto&ent:GetEntitiesInRange(BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->channelPos,BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove)) {
int dmgAmt = CalculateDamage(BATTLE_ENCOUNTER->objs[CURRENT_TURN],ent);
if (ent->GetHP()>0) {
std::cout << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->obj->name << " uses " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->name << " " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->grade << " on " << ent->obj->name << " dealing " << dmgAmt << " health.\n";
ent->SubtractHP(dmgAmt);
if (ent->GetTargetHP()<0) {
BATTLE_HIT_SCREENSHAKE=75;
} else {
BATTLE_HIT_SCREENSHAKE=25;
}
int memberID = getMemberIDComparingObject(ent->obj);
vi2d box = {(128-32*PARTY_MEMBER_COUNT)+memberID*64+29,170};
DAMAGE_NUMBERS.push_back(new DamageNumber(dmgAmt,box+cameraPos));
}
}
for (std::map<Property,int>::iterator it=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->properties.begin();it!=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->properties.end();++it) {
BATTLE_PROPERTIES[it->first]->OnApplication(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget]],it->second);
}
} else {
std::cout << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->obj->name << " uses " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->name << " " << BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove->grade << " on " << PARTY_MEMBER_OBJ[-BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget-1]->name << " but it failed.\n";
}
}
}
}
} else
if (CURRENT_EFFECT==nullptr&&BATTLE_ANIMATION_TIMER>120+BATTLE_CUSTOM_MESSAGE_WAIT_TIME||CURRENT_EFFECT!=nullptr&&BATTLE_ANIMATION_TIMER>CURRENT_EFFECT->maxLifeTime+30+BATTLE_CUSTOM_MESSAGE_WAIT_TIME) {
//Turn's done!
if (CURRENT_TURN<0) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove=nullptr;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedTarget=NO_TARGET;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->atb=0;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=DEFAULT_CHANNELPOS;
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;
}
for (std::map<Property,int>::iterator it=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->statusEffects.begin();it!=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->statusEffects.end();++it) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->statusEffects[it->first]) {
BATTLE_PROPERTIES[it->first]->OnTurnEnd(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]],it->second);
}
}
} else {
BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedMove=nullptr;
BATTLE_ENCOUNTER->objs[CURRENT_TURN]->selectedTarget=NO_TARGET;
BATTLE_ENCOUNTER->objs[CURRENT_TURN]->atb=0;
BATTLE_ENCOUNTER->objs[CURRENT_TURN]->channelPos=DEFAULT_CHANNELPOS;
BATTLE_STATE=BattleState::WAIT;
for (std::map<Property,int>::iterator it=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->statusEffects.begin();it!=BATTLE_ENCOUNTER->objs[CURRENT_TURN]->statusEffects.end();++it) {
if (BATTLE_ENCOUNTER->objs[CURRENT_TURN]->statusEffects[it->first]) {
BATTLE_PROPERTIES[it->first]->OnTurnEnd(BATTLE_ENCOUNTER->objs[CURRENT_TURN],it->second);
}
}
}
bool enemyStillAlive=false;
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (BATTLE_ENCOUNTER->objs[i]->GetHP()>0) {
enemyStillAlive=true;
break;
}
}
if (!enemyStillAlive) {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->atb=0;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->selectedMove=nullptr;
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->channelTimeRemaining=0;
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetTargetHP()>PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP()) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->_SetDirectHP(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetTargetHP());
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->SetTargetHP(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP());
}
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->_SetDirectPP(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetTargetPP());
}
ENEMY_MONEY_SUM=0;
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
ENEMY_MONEY_SUM+=BATTLE_ENCOUNTER->objs[i]->money;
}
BATTLE_STATE=BattleState::ENEMY_SPOILS;
BATTLE_ROLLING_COUNTER_WAITTIME=0;
}
CURRENT_TURN=-99;
BATTLE_CUSTOM_MESSAGE_WAIT_TIME=0;
BATTLE_CUSTOM_MSGS.clear();
BATTLE_CURRENT_CUSTOM_MSG={};
BATTLE_ANIMATION_TIMER=0;
BATTLE_SPOILS_MESSAGE="";
}
}break;
case BattleState::ENEMY_SPOILS:{
if (BATTLE_ANIMATION_TIMER==0) {
BATTLE_SPOILS_LIST.clear();
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
for (int j=0;j<BATTLE_ENCOUNTER->objs[i]->inventory.size();j++) {
if (rand()%BATTLE_ENCOUNTER->objs[i]->inventory[j]->dropChance==0) {
BATTLE_SPOILS_LIST.push_back(BATTLE_ENCOUNTER->objs[i]->inventory[j]);
}
}
}
}
if (BATTLE_ANIMATION_TIMER%90==0) {
if (BATTLE_SPOILS_LIST.size()>0) {
BATTLE_SPOILS_MESSAGE="You obtained a";
BATTLE_SPOILS_MESSAGE+=((
BATTLE_SPOILS_LIST[0]->name[0]=='a'||
BATTLE_SPOILS_LIST[0]->name[0]=='e'||
BATTLE_SPOILS_LIST[0]->name[0]=='i'||
BATTLE_SPOILS_LIST[0]->name[0]=='o'||
BATTLE_SPOILS_LIST[0]->name[0]=='u'||
BATTLE_SPOILS_LIST[0]->name[0]=='A'||
BATTLE_SPOILS_LIST[0]->name[0]=='E'||
BATTLE_SPOILS_LIST[0]->name[0]=='I'||
BATTLE_SPOILS_LIST[0]->name[0]=='O'||
BATTLE_SPOILS_LIST[0]->name[0]=='U'
)?"n ":" ");
BATTLE_SPOILS_MESSAGE+=BATTLE_SPOILS_LIST[0]->name+".";
PARTY_INVENTORY.push_back(BATTLE_SPOILS_LIST[0]);
BATTLE_SPOILS_LIST.erase(BATTLE_SPOILS_LIST.begin());
} else
if (ENEMY_MONEY_SUM>0) {
BATTLE_SPOILS_MESSAGE="You gained $"+std::to_string(ENEMY_MONEY_SUM)+".";
MONEY+=ENEMY_MONEY_SUM;
ENEMY_MONEY_SUM=0;
} else
{
BATTLE_STATE=BattleState::MOVE_CAMERA_BACK;
}
}
BATTLE_ANIMATION_TIMER++;
}break;
case BattleState::MOVE_CAMERA_BACK:{
const vi2d cameraOffset={WIDTH/2,HEIGHT/2};
if (MoveCameraTowardsPoint(PARTY_MEMBER_OBJ[0]->GetPos()-cameraOffset,PriorityDirection::BOTH,BATTLE_CAMERA_MOVESPD)) {
BATTLE_ENCOUNTER=nullptr;
BATTLE_STATE=BattleState::MOVE_CAMERA;
}
}break;
case BattleState::SELECT_ACTION:
case BattleState::ITEM_SELECT:
case BattleState::GRADE_SELECT:
case BattleState::TARGET_SELECT:
case BattleState::POWER_SELECT:{
BATTLE_ROLLING_COUNTER_WAITTIME=5;
}break;
}
}
}
void HandleCutscenes() {
switch (CurrentAction) {
case ActionType::SET_FLAG_WHEN_CUTSCENE_ENDS:{
CurrentCutscene->SetupEndingCutsceneFlag(((SetFlagWhenCutsceneEnds*)CurrentCutscene->GetAction())->GetCutsceneEndingFlag(),((SetFlagWhenCutsceneEnds*)CurrentCutscene->GetAction())->GetCutsceneEndingVal());
CurrentCutscene->AdvanceAction();
}break;
case ActionType::PAN_CAMERA:{
PanCamera*cam=(PanCamera*)CurrentCutscene->GetAction();
if (MoveCameraTowardsPoint(cam->GetCameraTargetPos(),cam->GetPriorityDirection(),cam->GetCameraSpeed())) {
CurrentCutscene->AdvanceAction();
}
}break;
case ActionType::PAN_CAMERA_ASYNC:{
AddAsyncCutsceneAction(PanCameraAsync);
}break;
case ActionType::MOVE_CUTSCENE_OBJ:{
if (MoveObjectTowardsPoint(CurrentCutscene->GetCutsceneObjects()[((MoveCutsceneObject*)CurrentCutscene->GetAction())->GetObjectID()],((MoveCutsceneObject*)CurrentCutscene->GetAction())->GetTargetPos(),((MoveCutsceneObject*)CurrentCutscene->GetAction())->GetMovement(),((MoveCutsceneObject*)CurrentCutscene->GetAction())->GetMoveSpd())) {
CurrentCutscene->AdvanceAction();
}
}break;
case ActionType::MOVE_CUTSCENE_OBJ_ASYNC:{
AddAsyncCutsceneAction(MoveCutsceneObjectAsync);
}break;
case ActionType::CREATE_OBJECTS:{
for (auto&obj:((CreateObjects*)CurrentCutscene->GetAction())->GetObjects()) {
obj->temp=true;
AddObjectToWorld(CurrentCutscene->AddCutsceneObject(new Standard_Obj(obj->id,obj->name,obj->GetPos(),obj->spr,obj->GetScale(),obj->color,obj->animationSpd,true)));
}
CurrentCutscene->AdvanceAction();
}break;
case ActionType::CLEANUP:{
if (CUTSCENE_QUEUE.size()==0) {
for (int i=0;i<OBJECTS.size();i++) {
if (OBJECTS[i]->temp) {
delete OBJECTS[i];
OBJECTS.erase(OBJECTS.begin()+i--);
} else {
OBJECTS[i]->objArrElement=i;
}
}
CurrentCutscene->CleanupCutscene();
CurrentCutscene->ResetCutscene();
SetGameFlag(CurrentCutscene->GetEndingCutsceneFlag(),CurrentCutscene->GetEndingCutsceneVal());
CurrentCutscene=nullptr;
CurrentAction=ActionType::NONE;
}
}break;
case ActionType::FADE:{
if (((Fade*)CurrentCutscene->GetAction())->FadeIn()&&CUTSCENE_FADE_VALUE>0) {
CUTSCENE_FADE_VALUE=std::clamp(CUTSCENE_FADE_VALUE-((Fade*)CurrentCutscene->GetAction())->GetFadeSpd(),0.0,255.0);
if (CUTSCENE_FADE_VALUE==0) {
CurrentCutscene->AdvanceAction();
}
} else
if (!((Fade*)CurrentCutscene->GetAction())->FadeIn()&&CUTSCENE_FADE_VALUE<255) {
CUTSCENE_FADE_VALUE=std::clamp(CUTSCENE_FADE_VALUE+((Fade*)CurrentCutscene->GetAction())->GetFadeSpd(),0.0,255.0);
if (CUTSCENE_FADE_VALUE==255) {
CurrentCutscene->AdvanceAction();
}
}
}break;
case ActionType::FADE_ASYNC:{
AddAsyncCutsceneAction(FadeAsync);
}break;
case ActionType::DIALOG:{
if (!((DialogBox*)CurrentCutscene->GetAction())->MessageHasBeenShown()) {
DisplayMessageBox(((DialogBox*)CurrentCutscene->GetAction())->GetMessage());
((DialogBox*)CurrentCutscene->GetAction())->SetMessageBoxVisible();
} else
if (!messageBoxVisible) {
CurrentCutscene->AdvanceAction();
}
}break;
case ActionType::DIALOG_ASYNC:{
DisplayMessageBox(((DialogBox*)CurrentCutscene->GetAction())->GetMessage());
CurrentCutscene->AdvanceAction();
}break;
case ActionType::MODIFY_OBJECT:{
ModifyObject*action=(ModifyObject*)CurrentCutscene->GetAction();
Object*obj=CurrentCutscene->GetCutsceneObjects()[action->GetCutsceneObjID()];
obj->SetScale(action->GetObjScale());
obj->color=action->GetObjCol();
obj->spr=action->GetObjSpr();
if (action->GetFrameIndex()!=-1) {
obj->frameIndex=action->GetFrameIndex();
}
obj->animationSpd=action->GetAnimationSpeed();
CurrentCutscene->AdvanceAction();
}break;
}
for (int i=0;i<CUTSCENE_QUEUE.size();i++) {
switch (CUTSCENE_QUEUE[i]->GetActionType()) {
case ActionType::PAN_CAMERA_ASYNC:{
PanCameraAsync*cam=(PanCameraAsync*)CUTSCENE_QUEUE[i];
if (MoveCameraTowardsPoint(cam->GetCameraTargetPos(),cam->GetPriorityDirection(),cam->GetCameraSpeed())) {
CUTSCENE_QUEUE.erase(CUTSCENE_QUEUE.begin()+i--);
}
}break;
case ActionType::MOVE_CUTSCENE_OBJ_ASYNC:{
if (MoveObjectTowardsPoint(CurrentCutscene->GetCutsceneObjects()[((MoveCutsceneObjectAsync*)CUTSCENE_QUEUE[i])->GetObjectID()],((MoveCutsceneObjectAsync*)CUTSCENE_QUEUE[i])->GetTargetPos(),((MoveCutsceneObjectAsync*)CUTSCENE_QUEUE[i])->GetMovement(),((MoveCutsceneObjectAsync*)CUTSCENE_QUEUE[i])->GetMoveSpd())) {
CUTSCENE_QUEUE.erase(CUTSCENE_QUEUE.begin()+i--);
}
}break;
case ActionType::FADE_ASYNC:{
if (((FadeAsync*)CUTSCENE_QUEUE[i])->FadeIn()&&CUTSCENE_FADE_VALUE>0) {
CUTSCENE_FADE_VALUE=std::clamp(CUTSCENE_FADE_VALUE-((FadeAsync*)CUTSCENE_QUEUE[i])->GetFadeSpd(),0.0,255.0);
if (CUTSCENE_FADE_VALUE==0) {
CUTSCENE_QUEUE.erase(CUTSCENE_QUEUE.begin()+i--);
}
} else
if (!((FadeAsync*)CUTSCENE_QUEUE[i])->FadeIn()&&CUTSCENE_FADE_VALUE<255) {
CUTSCENE_FADE_VALUE=std::clamp(CUTSCENE_FADE_VALUE+((FadeAsync*)CUTSCENE_QUEUE[i])->GetFadeSpd(),0.0,255.0);
if (CUTSCENE_FADE_VALUE==255) {
CUTSCENE_QUEUE.erase(CUTSCENE_QUEUE.begin()+i--);
}
}
}break;
}
}
}
void SetupTargetSelect() {
BATTLE_STATE=BattleState::TARGET_SELECT;
//Set Default Target.
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->friendly) {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->GetHP()>0||getProperty(Property::REVIVE,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
SELECTED_TARGET=-i-1;
break;
}
}
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-SELECTED_TARGET-1]]->obj->GetPosWithOrigin();
} else {
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (BATTLE_ENCOUNTER->objs[i]->GetHP()>0) {
SELECTED_TARGET=i;
break;
}
}
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos=BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->GetPosWithOrigin();
}
for (auto&ent:GetEntitiesInRange(SELECTED_TARGET,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->channelPos,PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove)) {
ent->obj->highlighted=true;
}
DISPLAY_TARGET_MESSAGE="Use "+PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->GetPowerName()+" on...";
}
std::vector<Entity*> GetEntitiesInRange(int targetEnt, vd2d channelPos, Battle::Move*move) {
std::vector<Entity*>ents;
if (targetEnt<0) {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
//See if this target is also in range.
vi2d diff=(vi2d)PARTY_MEMBER_OBJ[i]->GetPosWithOrigin()/32-(vi2d)channelPos/32;
if (abs(diff.x)+abs(diff.y)<=move->range-1) {
ents.push_back(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]);
}
}
} else {
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
//See if this target is also in range.
vi2d diff=(vi2d)BATTLE_ENCOUNTER->objs[i]->obj->GetPosWithOrigin()/32-(vi2d)channelPos/32;
if (abs(diff.x)+abs(diff.y)<=move->range-1) {
ents.push_back(BATTLE_ENCOUNTER->objs[i]);
}
}
}
return ents;
}
void DrawTargetRangeGrid(vd2d pos,int range,Pixel outlinecol,Pixel box1col,Pixel box2col,bool connectedborder) {
vi2d gridCenter = (vi2d)pos/32*32;
for (int x=-range+1;x<range;x++) {
for (int y=-range+1;y<range;y++) {
int dist = abs(x)+abs(y);
if (dist<range) {
vi2d offset = {x,y};
//FillRectDecal(gridCenter-cameraPos+offset*32,{32,32},Pixel(255,255,0,128));
GradientFillRectDecal(gridCenter-cameraPos+offset*32,{32,32},box1col,box2col,box1col,box2col);
const vi2d outlineOffset = {1,1};
if (!connectedborder) {
DrawRectDecal(gridCenter-cameraPos+offset*32,{32,32},outlinecol);
DrawRectDecal(gridCenter-cameraPos+offset*32+outlineOffset,{30,30},outlinecol);
} else {
vd2d pos=gridCenter-cameraPos+offset*32;
vd2d pos2=gridCenter-cameraPos+offset*32+outlineOffset;
vd2d size={32,32};
vd2d size2={30,30};
if (abs(x)+abs(y-1)>=range) {
DrawLineDecal(pos,{static_cast<float>(pos.x+size.x),static_cast<float>(pos.y)},outlinecol); //Top
DrawLineDecal(pos2,{static_cast<float>(pos2.x+size2.x),static_cast<float>(pos2.y)},outlinecol); //Top
}
if (abs(x-1)+abs(y)>=range) {
DrawLineDecal({static_cast<float>(pos.x),static_cast<float>(pos.y)},{static_cast<float>(pos.x),static_cast<float>(pos.y+size.y)},outlinecol); //Left
DrawLineDecal({static_cast<float>(pos2.x),static_cast<float>(pos2.y)},{static_cast<float>(pos2.x),static_cast<float>(pos2.y+size2.y)},outlinecol); //Left
}
if (abs(x)+abs(y+1)>=range) {
DrawLineDecal({static_cast<float>(pos.x),static_cast<float>(pos.y+size.y)},{static_cast<float>(pos.x+size.x),static_cast<float>(pos.y+size.y)},outlinecol); //Bottom
DrawLineDecal({static_cast<float>(pos2.x),static_cast<float>(pos2.y+size2.y)},{static_cast<float>(pos2.x+size2.x),static_cast<float>(pos2.y+size2.y)},outlinecol); //Bottom
}
if (abs(x+1)+abs(y)>=range) {
DrawLineDecal({static_cast<float>(pos.x+size.x),static_cast<float>(pos.y)},{static_cast<float>(pos.x+size.x),static_cast<float>(pos.y+size.y)},outlinecol); //Right
DrawLineDecal({static_cast<float>(pos2.x+size2.x),static_cast<float>(pos2.y)},{static_cast<float>(pos2.x+size2.x),static_cast<float>(pos2.y+size2.y)},outlinecol); //Right
}
}
}
}
}
}
void DrawTargetRangeGrid(vd2d pos,int range) {
DrawTargetRangeGrid(pos,range,Pixel(abs(cos(M_PI/240*frameCount)*128),200,0,255),Pixel(0,161,255,abs(sin(M_PI/240*frameCount)*32)),Pixel(139,234,255,abs(sin(M_PI/240*frameCount)*64)),false);
}
void DrawMovementGrid(Pixel outlinecol,Pixel box1col,Pixel box2col) {
for (std::map<std::pair<int,int>,vd2d>::const_iterator it = MOVEMENT_GRID.cbegin();it!=MOVEMENT_GRID.cend();++it) {
if (it->second!=NO_NEIGHBOR) {
GradientFillRectDecal(MOVEMENT_GRID[it->first],{32,32},box1col,box2col,box1col,box2col);
const vi2d outlineOffset = {1,1};
DrawRectDecal(MOVEMENT_GRID[it->first],{32,32},outlinecol);
DrawRectDecal(MOVEMENT_GRID[it->first]+outlineOffset,{30,30},outlinecol);
}
}
}
void CheckGrid(int x,int y,vd2d pos,int lifetime) {
if (pos.x<0||pos.x>=WIDTH||pos.y<0||pos.y>=HEIGHT-64) {
return;
}
for (int xx=0;xx<32;xx++) {
for (int yy=0;yy<32;yy++) {
vi2d offset={xx,yy};
if (Collision(pos+offset)) {
//std::cout<<x<<","<<y<<"\n";
return;
}
}
}
bool nonSolid=false; //Ran into a non-solid instance, which means we can't mark the tile, but we can continue moving through.
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (CURRENT_TURN!=-i-1&&pos==(vd2d)((vi2d)(PARTY_MEMBER_OBJ[i]->GetPosWithOrigin()-cameraPos)/32*32)) {
nonSolid=true;
break;
}
}
if (!nonSolid) {
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
if (pos==(vd2d)((vi2d)(BATTLE_ENCOUNTER->objs[i]->obj->GetPosWithOrigin()-cameraPos)/32*32)) {
nonSolid=true;
break;
}
}
}
if (!nonSolid) {
MOVEMENT_GRID[{x,y}]=pos;
}
if (lifetime>0) {
vi2d offsetLeft = {-32,0};
CheckGrid(x-1,y,pos+offsetLeft,lifetime-1);
vi2d offsetRight = {32,0};
CheckGrid(x+1,y,pos+offsetRight,lifetime-1);
vi2d offsetUp = {0,-32};
CheckGrid(x,y-1,pos+offsetUp,lifetime-1);
vi2d offsetDown = {0,32};
CheckGrid(x,y+1,pos+offsetDown,lifetime-1);
}
}
void PopulateMovementGrid(vd2d pos,int range) {
vi2d gridCenter = (vi2d)pos/32*32;
MOVEMENT_GRID.clear();
CheckGrid(0,0,gridCenter-cameraPos,std::min(8,range));
}
vi2d grid(int x, int y) {
return {x*32,y*32};
}
void StartEffect(Effect*eff) {
CURRENT_EFFECT=eff;
eff->create(PARTICLES);
}
int getMemberIDComparingObject(Object*obj) {
int memberID=0;
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (obj==PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]]->obj) {
memberID=i;
break;
}
}
return memberID;
}
bool Collision(vd2d pos) {
SetDrawTarget(layer::COLLISION);
Pixel collisionData = GAME->GetDrawTarget()->GetPixel((int)pos.x,(int)pos.y);
return collisionData!=MAGENTA;
}
void DrawArrow() {
vi2d startingPos = {0,0};
vi2d drawingPos = {(vi2d)(PARTY_MEMBER_OBJ[-CURRENT_TURN-1]->GetPosWithOrigin()-cameraPos)/32};
vi2d center={16,16};
bool lastMoveWasX=false; //When set to true, the previous move was in the X axis. This is used for the elbow connector.
bool flippedX=(SELECTED_MOVE_SQUARE.x>startingPos.x);
bool flippedY=(SELECTED_MOVE_SQUARE.y<startingPos.y);
while (startingPos!=SELECTED_MOVE_SQUARE) {
if (startingPos.x!=SELECTED_MOVE_SQUARE.x) {
DrawPartialRotatedDecal((drawingPos+startingPos)*32+center,SPRITES["arrow_connector.png"],M_PI_2,{16,16},{0,0},{32,32});
startingPos.x+=SELECTED_MOVE_SQUARE.x>startingPos.x?1:-1;
lastMoveWasX=true;
continue;
}
if (startingPos.y!=SELECTED_MOVE_SQUARE.y) {
if (lastMoveWasX) {
//Elbow Connector
if (SELECTED_MOVE_SQUARE.y>startingPos.y) {
DrawPartialRotatedDecal((drawingPos+startingPos)*32+center,SPRITES["arrow_connector.png"],(flippedX)?M_PI:M_PI_2,{16,16},{32,0},{32,32});
} else {
DrawPartialRotatedDecal((drawingPos+startingPos)*32+center,SPRITES["arrow_connector.png"],(flippedX)?M_PI_2*3:0,{16,16},{32,0},{32,32});
}
lastMoveWasX=false;
} else {
//Straight Connector.
DrawPartialRotatedDecal((drawingPos+startingPos)*32+center,SPRITES["arrow_connector.png"],0,{16,16},{0,0},{32,32});
}
startingPos.y+=SELECTED_MOVE_SQUARE.y>startingPos.y?1:-1;
continue;
}
}
if (SELECTED_MOVE_SQUARE.x!=0||SELECTED_MOVE_SQUARE.y!=0) {
if (SELECTED_MOVE_SQUARE.y==0) {
DrawPartialRotatedDecal((SELECTED_MOVE_SQUARE+drawingPos)*32+center,SPRITES["arrow_connector.png"],(flippedX)?M_PI_2*3:M_PI_2,{16,16},{64,0},{32,32});
} else {
DrawPartialRotatedDecal((SELECTED_MOVE_SQUARE+drawingPos)*32+center,SPRITES["arrow_connector.png"],(flippedY)?M_PI:0,{16,16},{64,0},{32,32});
}
}
}
//Can run this after target selection to reset states.
void ConfirmPlayerTargetSelection() {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
PARTY_MEMBER_OBJ[i]->highlighted=false;
}
for (int i=0;i<BATTLE_ENCOUNTER->objs.size();i++) {
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;
int prevPartyInvenSize=PARTY_INVENTORY.size();
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;
}
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;
}
if ((PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove==MOVELIST[BattleMoveName::CONSUMABLE]||
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove==MOVELIST[BattleMoveName::CONSUMABLE_ENEMY])) {
BATTLE_CUSTOM_ITEM=PARTY_INVENTORY[ITEM_SELECTION_CURSOR];
if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY_PERMANENT) {
MOVELIST[BattleMoveName::CONSUMABLE]->baseDmg=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.hpRecovery;
MOVELIST[BattleMoveName::CONSUMABLE]->randomDmg=0;
BATTLE_CUSTOM_MESSAGE_WAIT_TIME=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->messages.size()*90;
BATTLE_CUSTOM_MSGS=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->messages;
} else {
MOVELIST[BattleMoveName::CONSUMABLE_ENEMY]->baseDmg=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.damage;
MOVELIST[BattleMoveName::CONSUMABLE_ENEMY]->randomDmg=PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.rollDmg;
}
if ((PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::FRIENDLY||PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.consumable==Consumable::ENEMY)) {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->RemoveItem(ITEM_SELECTION_CURSOR);
}
}
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()&&prevPartyInvenSize&1&&PARTY_INVENTORY.size()==prevPartyInvenSize-1) {
ITEM_SELECTION_OFFSET-=2;
}
ITEM_SELECTION_CURSOR=std::clamp(ITEM_SELECTION_CURSOR,0,(int)PARTY_INVENTORY.size()-1);
}
int CalculateHealing(Entity*user) {
return CalculateDamage(user,nullptr,false);
}
int CalculateDamage(Entity*attacker,Entity*defender,bool includeDefenses=true) {
int finalDamage = 0;
int equipDamage = 0;
for (int i=0;i<attacker->equipment.size();i++) {
if (attacker->equipment[i]!=nullptr) {
equipDamage+=attacker->equipment[i]->stats.attack;
}
}
int attackerDamage = (attacker->selectedMove->baseDmg+
((attacker->selectedMove->randomDmg>0)?rand()%attacker->selectedMove->randomDmg:0)
+attacker->stats.baseAtk
+equipDamage);
finalDamage += attackerDamage;
int equipDefense = 0;
if (includeDefenses) {
for (int i=0;i<defender->equipment.size();i++) {
if (defender->equipment[i]!=nullptr) {
equipDefense+=defender->equipment[i]->stats.defense;
}
}
}
finalDamage=std::max(1,finalDamage-equipDefense);
if (includeDefenses&&defender->selectedMove==MOVELIST[BattleMoveName::DEFEND]) {
finalDamage*=0.4;
}
return finalDamage;
}
void AddItemToPlayerInventory(ItemName item) {
PARTY_INVENTORY.push_back(ITEMLIST[item]);
}
void RemoveItemFromPlayerInventory(int slot) {
PARTY_INVENTORY.erase(PARTY_INVENTORY.begin()+slot);
}
void HandleInventoryNavigation() {
if (LeftPressed()||RightPressed()) {
ITEM_SELECTION_CURSOR+=ITEM_SELECTION_CURSOR&1?-1:1;
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()) {
ITEM_SELECTION_CURSOR--;
}
}
if (UpPressed()) {
ITEM_SELECTION_CURSOR-=2;
if (ITEM_SELECTION_CURSOR<0) {
if (PARTY_INVENTORY.size()&1) {
ITEM_SELECTION_CURSOR+=PARTY_INVENTORY.size()+1;
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()) {
ITEM_SELECTION_CURSOR-=2;
}
ITEM_SELECTION_OFFSET=std::clamp((int)PARTY_INVENTORY.size()/2*2-18+2,0,(int)PARTY_INVENTORY.size()-1);
} else {
ITEM_SELECTION_CURSOR+=PARTY_INVENTORY.size();
ITEM_SELECTION_OFFSET=std::clamp((int)PARTY_INVENTORY.size()/2*2-18,0,(int)PARTY_INVENTORY.size()-1);
}
}
if (ITEM_SELECTION_CURSOR<ITEM_SELECTION_OFFSET) {
ITEM_SELECTION_OFFSET=ITEM_SELECTION_CURSOR/2*2;
}
if (ITEM_SELECTION_CURSOR<2) {
KEY_LASTPRESSED=NONE;
}
}
if (DownPressed()) {
ITEM_SELECTION_CURSOR+=2;
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()) {
if (PARTY_INVENTORY.size()&1) {
if (ITEM_SELECTION_CURSOR&1) {
ITEM_SELECTION_CURSOR--;
} else {
ITEM_SELECTION_CURSOR-=PARTY_INVENTORY.size()+1;
}
} else {
ITEM_SELECTION_CURSOR-=PARTY_INVENTORY.size();
}
ITEM_SELECTION_OFFSET=0;
}
if (ITEM_SELECTION_CURSOR>=ITEM_SELECTION_OFFSET+18) {
ITEM_SELECTION_OFFSET=ITEM_SELECTION_CURSOR/2*2-16;
}
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()-2) {
KEY_LASTPRESSED=NONE;
}
}
}
void HandleRollingCounters(int i,int(&counter)[4][3],int(&display)[4][3],Entity*member,int maxVal,int currentVal,int targetVal,bool pp=false) {
if (currentVal>std::clamp(targetVal,0,targetVal)) {
if (counter[i][0]<=0&&player_rollwait_counter[i]==0) {
display[i][0]--;
counter[i][0]=13;
if (!pp) {
member->_SetDirectHP(currentVal-1);
} else {
member->_SetDirectPP(currentVal-1);
}
if (display[i][0]<0) {
display[i][0]=9;
counter[i][0]=13;
display[i][1]--;
counter[i][1]=13;
if (display[i][1]<0) {
display[i][1]=9;
counter[i][1]=13;
display[i][2]--;
counter[i][2]=13;
}
}
}
if (counter[i][0]>0) {
if (targetVal<-maxVal) {
counter[i][0]-=HEALTH_ROLLING_SPEED+(maxVal-targetVal)/10;
} else
if (targetVal<0) {
counter[i][0]-=HEALTH_ROLLING_SPEED+(maxVal-targetVal)/20;
} else {
if (!pp) {
counter[i][0]-=HEALTH_ROLLING_SPEED;
} else {
counter[i][0]-=HEALTH_ROLLING_SPEED*5;
}
}
}
if (counter[i][1]>0) {
counter[i][1]--;
}
if (counter[i][2]>0) {
counter[i][2]--;
}
} else
if (currentVal<targetVal) {
if (counter[i][0]>=0&&player_rollwait_counter[i]==0) {
display[i][0]++;
counter[i][0]=-13;
if (!pp) {
member->_SetDirectHP(currentVal+1);
} else {
member->_SetDirectPP(currentVal+1);
}
if (display[i][0]>9) {
display[i][0]=0;
counter[i][0]=-13;
display[i][1]++;
counter[i][1]=-13;
if (display[i][1]>9) {
display[i][1]=0;
counter[i][1]=-13;
display[i][2]++;
counter[i][2]=-13;
}
}
}
if (counter[i][0]<0) {
if (!pp) {
counter[i][0]+=HEALTH_ROLLING_SPEED;
} else {
counter[i][0]+=HEALTH_ROLLING_SPEED*5;
}
}
if (counter[i][1]<0) {
counter[i][1]++;
}
if (counter[i][2]<0) {
counter[i][2]++;
}
} else {
if (counter[i][0]<0) {
counter[i][0]++;
}
if (counter[i][1]<0) {
counter[i][1]++;
}
if (counter[i][2]<0) {
counter[i][2]++;
}
if (counter[i][0]>0) {
counter[i][0]--;
}
if (counter[i][1]>0) {
counter[i][1]--;
}
if (counter[i][2]>0) {
counter[i][2]--;
}
}
}
std::string GetTargetName(int target) {
if (target<0) {
return PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-target-1]]->obj->name;
} else {
return BATTLE_ENCOUNTER->objs[target]->obj->name;
}
}
std::string ParseBattleMessage(Entity*ent,std::string baseStr) {
std::string label="";
label=baseStr;
if (label.find("$USER")!=std::string::npos) {
label=label.replace(label.find("$USER"),5,ent->obj->name);
}
if (label.find("$POWER")!=std::string::npos) {
label=label.replace(label.find("$POWER"),6,ent->selectedMove->GetPowerName());
}
if (label.find("$ITEM")!=std::string::npos) {
label=label.replace(label.find("$ITEM"),5,EQUIP_$ITEM_DISPLAY);
}
if (label.find("$TARGET")!=std::string::npos) {
label=label.replace(label.find("$TARGET"),7,GetTargetName(ent->selectedTarget));
}
return label;
}
void PopulateBattleMoveList(int partyMemberSlot,bool overworld=false) {
BATTLE_MOVELIST_DISPLAY.clear();
Entity*member = PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]];
for (int i=0;i<member->moveSet.size();i++) {
Battle::Move*move = member->moveSet[i];
if (overworld&&move->overworld||!overworld) {
bool exists=false;
for (int j=0;j<BATTLE_MOVELIST_DISPLAY.size();j++) {
if (BATTLE_MOVELIST_DISPLAY[j][0]->name.compare(move->name)==0) {
bool found=false;
for (int k=0;k<BATTLE_MOVELIST_DISPLAY[j].size();k++) {
if (ADDITIONAL_FONT_VALS[move->grade]<ADDITIONAL_FONT_VALS[BATTLE_MOVELIST_DISPLAY[j][k]->grade]) {
BATTLE_MOVELIST_DISPLAY[j].insert(BATTLE_MOVELIST_DISPLAY[j].begin()+i,move);
found=true;
break;
}
}
if (!found) {
BATTLE_MOVELIST_DISPLAY[j].push_back(move);
}
exists=true;
break;
}
}
if (!exists) {
std::vector<Battle::Move*> vec;
vec.push_back(move);
BATTLE_MOVELIST_DISPLAY.push_back(vec);
}
}
}
}
void DrawBattleMoveList(int partyMemberSlot) {
int selectioncursor=0;
if (BATTLE_ENCOUNTER==nullptr) {
selectioncursor=OVERWORLD_POWER_SELECTION_CURSOR[partyMemberSlot];
} else {
selectioncursor=POWER_SELECTION_CURSOR[partyMemberSlot];
}
int gradeselectioncursor=0;
if (BATTLE_ENCOUNTER==nullptr) {
gradeselectioncursor=OVERWORLD_POWER_GRADE_CURSOR;
} else {
gradeselectioncursor=POWER_GRADE_CURSOR[partyMemberSlot];
}
int powerselectionoffset=0;
if (BATTLE_ENCOUNTER==nullptr) {
powerselectionoffset=OVERWORLD_POWER_SELECTION_OFFSET[partyMemberSlot];
} else {
powerselectionoffset=POWER_SELECTION_OFFSET[partyMemberSlot];
}
SetDrawTarget(layer::INTERFACE);
DrawDialogBox({1,1},{(int)(WIDTH/2),HEIGHT/4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
vd2d descBoxPos = {WIDTH-(int)(WIDTH/2.5)-2,1};
vi2d textStartingOffset = {4,4};
DrawDialogBox(descBoxPos,{(int)(WIDTH/2.5),HEIGHT/4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
if (BATTLE_MOVELIST_DISPLAY.size()>0) {
DrawStringPropDecal(descBoxPos+textStartingOffset,Wrap(BATTLE_MOVELIST_DISPLAY[selectioncursor][0]->desc,((int)(WIDTH/2.5-8)),true,{0.8,0.8}),WHITE,{0.8,0.8});
}
vd2d ppCostBoxPos = {WIDTH-WIDTH/3-2,HEIGHT/4+2};
DrawDialogBox(ppCostBoxPos,{(int)(WIDTH/6),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal(ppCostBoxPos+textStartingOffset,"PP Cost",WHITE,{0.7,0.8});
std::string label;
if (BATTLE_MOVELIST_DISPLAY.size()>0) {
label=std::to_string(BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->PPCost);
DrawStringPropDecal({static_cast<float>(ppCostBoxPos.x+textStartingOffset.x+(WIDTH/6)-8-GetTextSizeProp(label).x*1.5),static_cast<float>(ppCostBoxPos.y+textStartingOffset.y+8)},label,WHITE,{1.5,1.5});
}
vd2d damageBoxPos = {WIDTH-WIDTH/3+WIDTH/6-1,HEIGHT/4+2};
DrawDialogBox({WIDTH-WIDTH/3+WIDTH/6-1,HEIGHT/4+2},{(int)(WIDTH/6),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal(damageBoxPos+textStartingOffset,"Damage",WHITE,{0.7,0.8});
if (BATTLE_MOVELIST_DISPLAY.size()>0) {
label = (BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->baseDmg!=0)?std::to_string(BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->baseDmg+PARTY_MEMBER_STATS[partyMemberSlot]->stats.baseAtk)+"~"+std::to_string(BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->randomDmg+BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->baseDmg+PARTY_MEMBER_STATS[partyMemberSlot]->stats.baseAtk):"N/A";
DrawStringPropDecal({static_cast<float>(damageBoxPos.x+textStartingOffset.x+(WIDTH/6)-8-GetTextSizeProp(label).x*(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5))),static_cast<float>(damageBoxPos.y+textStartingOffset.y+8)},label,WHITE,{static_cast<float>(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5)),1.5});
}
if (BATTLE_ENCOUNTER!=nullptr) {
vd2d rangeBoxPos = {WIDTH-WIDTH/3+WIDTH/6-1,HEIGHT/4+HEIGHT/8+3};
DrawDialogBox({WIDTH-WIDTH/3+WIDTH/6-1,HEIGHT/4+HEIGHT/8+3},{(int)(WIDTH/6),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal(rangeBoxPos+textStartingOffset,"Range",WHITE,{0.7,0.8});
label = std::to_string(BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->range);
DrawStringPropDecal({static_cast<float>(rangeBoxPos.x+textStartingOffset.x+(WIDTH/6)-8-GetTextSizeProp(label).x*(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5))),static_cast<float>(rangeBoxPos.y+textStartingOffset.y+8)},label,WHITE,{static_cast<float>(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5)),1.5});
}
if (BATTLE_ENCOUNTER!=nullptr) {
vd2d channelTimeBoxPos = {WIDTH-WIDTH/3-1,HEIGHT/4+HEIGHT/8+3};
DrawDialogBox({WIDTH-WIDTH/3-1,HEIGHT/4+HEIGHT/8+3},{(int)(WIDTH/6),HEIGHT/8},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
DrawStringPropDecal(channelTimeBoxPos+textStartingOffset,"Cast",WHITE,{0.7,0.8});
label = std::to_string((float)BATTLE_MOVELIST_DISPLAY[selectioncursor][gradeselectioncursor]->channelTime/60).erase(3);
DrawStringPropDecal({static_cast<float>(channelTimeBoxPos.x+textStartingOffset.x+(WIDTH/6)-8-GetTextSizeProp(label).x*(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5))),static_cast<float>(channelTimeBoxPos.y+textStartingOffset.y+8)},label,WHITE,{static_cast<float>(std::min((double)((WIDTH/6)-8)/GetTextSizeProp(label).x,1.5)),1.5});
}
int counter=0;
int displayLimit=0;
for (int i=0;i<BATTLE_MOVELIST_DISPLAY.size();i++) {
if (counter>=powerselectionoffset&&counter<=powerselectionoffset+3) {
int displayYOffset=-powerselectionoffset*12;
std::vector<Battle::Move*> moves = BATTLE_MOVELIST_DISPLAY[i];
std::string name = moves[0]->name;
if (GetTextSizeProp(name).x>WIDTH/4) {
DrawStringPropDecal({12,static_cast<float>(12*counter+8+displayYOffset)},name,WHITE,{(WIDTH/4)/(float)GetTextSizeProp(name).x,1});
} else {
DrawStringPropDecal({12,static_cast<float>(12*counter+8+displayYOffset)},name);
}
for (int i=0;i<moves.size();i++) {
Pixel drawCol;
if ((GAME_STATE==GameState::OVERWORLD_GRADE_MENU||BATTLE_STATE==BattleState::GRADE_SELECT)&&selectioncursor==counter) {
if (gradeselectioncursor==i) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->GetPP()>=moves[i]->PPCost) {
drawCol=WHITE;
} else {
drawCol=RED;
}
} else {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->GetPP()>=moves[i]->PPCost) {
drawCol=DARK_GREY;
} else {
drawCol=DARK_RED;
}
}
} else {
drawCol=WHITE;
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->GetPP()>=moves[i]->PPCost) {
drawCol=WHITE;
} else {
drawCol=RED;
}
}
DrawStringDecal({static_cast<float>(8+WIDTH/4+12+i*8),static_cast<float>(12*counter+8+displayYOffset)},std::string(1,moves[i]->grade),drawCol);
}
}
++counter;
}
if (BATTLE_ENCOUNTER==nullptr) {
vi2d textSize = GetTextSizeProp(PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->obj->name)/2;
if (PARTY_MEMBER_COUNT>1) {
DrawStringPropDecal({(float)WIDTH/2.F-textSize.x-6,1},PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->obj->name,WHITE,{0.5,1});
if (GAME_STATE==GameState::OVERWORLD_POWER_PLAYER_MENU) {
DrawRotatedDecal({(float)WIDTH/2-textSize.x-8,5},SPRITES["cursor.png"],M_PI,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
DrawRotatedDecal({(float)WIDTH/2-4,5},SPRITES["cursor.png"],0,{(float)SPRITES["cursor.png"]->sprite->width/2,(float)SPRITES["cursor.png"]->sprite->height/2},{(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F,(sinf(frameCount/10.F*M_PI)>0)?0.5F:0.25F});
}
}
}
if (BATTLE_STATE==BattleState::POWER_SELECT||GAME_STATE==GameState::OVERWORLD_POWER_MENU) {
DrawDecal({4,static_cast<float>(12*(selectioncursor-powerselectionoffset)+8)},SPRITES["cursor.png"]);
} else
if (BATTLE_STATE==BattleState::GRADE_SELECT||GAME_STATE==GameState::OVERWORLD_GRADE_MENU){
DrawDecal({(float)(WIDTH/4+4+gradeselectioncursor*8+8),static_cast<float>(12*(selectioncursor-powerselectionoffset)+8)},SPRITES["cursor.png"]);
}
if (BATTLE_MOVELIST_DISPLAY.size()>4) {
if (powerselectionoffset>0) {
DrawRotatedDecal({WIDTH/2-16,7},SPRITES["cursor.png"],-M_PI_2,{4,4});
}
if (powerselectionoffset+3<BATTLE_MOVELIST_DISPLAY.size()-1) {
DrawRotatedDecal({WIDTH/2-16,HEIGHT/4-7},SPRITES["cursor.png"],M_PI_2,{4,4});
}
}
}
void PerformOverworldMove(Battle::Move*move,int partyMemberSlot) {
OVERWORLD_SELECTED_POWER=move;
OVERWORLD_TARGET_SELECTION=0;
if (move->name=="PK Lifeup") {
if (move->range==1) {
GAME_STATE=GameState::OVERWORLD_TARGET_MENU;
PARTY_MEMBER_OBJ[OVERWORLD_TARGET_SELECTION]->highlighted=true;
} else {
PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->SubtractPP(move->PPCost);
DisplayMessageBox(PARTY_MEMBER_OBJ[partyMemberSlot]->name+" begins to cast "+move->GetPowerName()+".\n");
HEALING_OVERWORLD_MEMBERS=true;
HEALING_OVERWORLD_MEMBER=0;
}
} else {
}
}
void HandleRollingCounters() {
if (BATTLE_ENCOUNTER!=nullptr||OverworldMenuOpen()) {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
if (player_rollwait_counter[i]>0) {
if (BATTLE_ROLLING_COUNTER_WAITTIME==0) {
player_rollwait_counter[i]=0;
} else {
player_rollwait_counter[i]--;
}
}
Entity*member=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]];
HandleRollingCounters(i,player_rollhp_counter,player_rollhp_display,member,member->stats.maxHP,member->GetHP(),member->GetTargetHP());
HandleRollingCounters(i,player_rollpp_counter,player_rollpp_display,member,member->stats.maxPP,member->GetPP(),member->GetTargetPP(),true);
if (player_rollwait_counter[i]==0) {
player_rollwait_counter[i]=BATTLE_ROLLING_COUNTER_WAITTIME*13;
}
}
}
}
bool OverworldMenuOpen() {
return GAME_STATE==GameState::OVERWORLD_MENU||
GAME_STATE==GameState::OVERWORLD_POWER_MENU||
GAME_STATE==GameState::OVERWORLD_GRADE_MENU||
GAME_STATE==GameState::OVERWORLD_POWER_PLAYER_MENU||
GAME_STATE==GameState::OVERWORLD_ITEMS_MENU||
GAME_STATE==GameState::OVERWORLD_EQUIP_ITEM_MENU||
GAME_STATE==GameState::OVERWORLD_EQUIP_MENU||
GAME_STATE==GameState::OVERWORLD_EQUIP_PLAYER_MENU||
GAME_STATE==GameState::OVERWORLD_STATUS_MENU||
GAME_STATE==GameState::OVERWORLD_TARGET_MENU;
}
void SetupRollingHitpointCounters() {
for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
Entity*member=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[i]];
for (int j=0;j<3;j++) {
switch (j) {
case 0:{
player_rollhp_display[i][j]=member->GetHP()%10;
player_rollpp_display[i][j]=member->GetPP()%10;
}break;
case 1:{
player_rollhp_display[i][j]=member->GetHP()/10%10;
player_rollpp_display[i][j]=member->GetPP()/10%10;
}break;
case 2:{
player_rollhp_display[i][j]=member->GetHP()/100%10;
player_rollpp_display[i][j]=member->GetPP()/100%10;
}break;
}
}
}
}
//Returns true if the key is meant to be continuously repeated because of being held down.
//dir should be UP,DOWN,LEFT,RIGHT
bool KeyRepeat(Key dir) {
if (KEY_LASTPRESSED!=NONE) {
bool allowed=false;
switch (dir) {
case UP:{
allowed=(KEY_LASTPRESSED==W||KEY_LASTPRESSED==NP8||KEY_LASTPRESSED==UP)&&frameCount-lastPress>20&&frameCount%4==0&&lastRepeatedFrame!=frameCount;
}break;
case DOWN:{
allowed=(KEY_LASTPRESSED==S||KEY_LASTPRESSED==NP2||KEY_LASTPRESSED==NP5||KEY_LASTPRESSED==DOWN)&&frameCount-lastPress>20&&frameCount%4==0&&lastRepeatedFrame!=frameCount;
}break;
case LEFT:{
allowed=(KEY_LASTPRESSED==A||KEY_LASTPRESSED==NP4||KEY_LASTPRESSED==LEFT)&&frameCount-lastPress>20&&frameCount%4==0&&lastRepeatedFrame!=frameCount;
}break;
case RIGHT:{
allowed=(KEY_LASTPRESSED==D||KEY_LASTPRESSED==NP6||KEY_LASTPRESSED==RIGHT)&&frameCount-lastPress>20&&frameCount%4==0&&lastRepeatedFrame!=frameCount;
}break;
}
if (allowed) {
return true;
}
}
return false;
}
void PopulateEquipMenuItems() {
EQUIP_ITEM_MENU_CONTENTS.clear();
EQUIP_ITEM_MENU_OFFSET=0;
EQUIP_ITEM_MENU_CURSOR=0;
for (int i=0;i<PARTY_INVENTORY.size();i++) {
if (PARTY_INVENTORY[i]->stats.equip==EQUIP_MENU_SLOT) {
EQUIP_ITEM_MENU_CONTENTS.push_back(i);
}
}
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[OVERWORLD_POWER_SELECTION_MEMBER]]->equipment[EQUIP_MENU_SLOT]!=nullptr) {
EQUIP_ITEM_MENU_CONTENTS.push_back(-1);
}
}
void CalculateEquipmentStats(int partyMemberSlot,int&atk,int&def) {
atk=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->stats.baseAtk;
def=0;
for (int i=0;i<PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment.size();i++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[i]!=nullptr) {
atk+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[i]->stats.attack;
def+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[i]->stats.defense;
}
}
}
void CalculateChangeInEquipmentStats(int partyMemberSlot,int itemSlot,int&equipAttack,int&equipDefense,int&newAttack,int&newDefense) {
EquipSlot::Equip slot;
if (itemSlot==-1) {
slot=EQUIP_MENU_SLOT;
} else {
slot=PARTY_INVENTORY[itemSlot]->stats.equip;
}
for (int j=0;j<PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment.size();j++) {
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]!=nullptr) {
equipAttack+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]->stats.attack;
equipDefense+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]->stats.defense;
if (PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]->stats.equip==slot) {
if (itemSlot!=-1) {
newAttack+=PARTY_INVENTORY[itemSlot]->stats.attack;
newDefense+=PARTY_INVENTORY[itemSlot]->stats.defense;
}
} else {
newAttack+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]->stats.attack;
newDefense+=PARTY_MEMBER_STATS[PARTY_MEMBER_ID[partyMemberSlot]]->equipment[j]->stats.defense;
}
} else {
if (j==slot) {
if (itemSlot!=-1) {
newAttack+=PARTY_INVENTORY[itemSlot]->stats.attack;
newDefense+=PARTY_INVENTORY[itemSlot]->stats.defense;
}
}
}
}
}
int CalculateSpeedGridMovementAmount(int spd) {
const std::array<int,8> spdRequirements={0,6,10,18,28,40,60,100};
for (int i=7;i>=0;i--) {
if (spd>spdRequirements[i]) {
return i+1;
}
}
return 1;
}
bool MessageBoxAllowedToAdvance() {
return messageBoxMarker<messageBoxFinalText.length()&&!waitingForChoice;
}
vf2d AutoScaleText(std::string str,int targetWidth,vf2d scale={1,1},bool prop=true) {
vf2d size = ((prop)?GetTextSizeProp(str):GetTextSize(str))*scale;
return {std::min(scale.x,targetWidth/size.x),scale.y};
}
void CursorControl(int&cursor,int max) {
if (UpPressed()) {
cursor--;
if (cursor<0) {
cursor=max-1;
}
if (cursor==0) {
KEY_LASTPRESSED=NONE;
}
}
if (DownPressed()) {
cursor=(cursor+1)%max;
if (cursor==max-1) {
KEY_LASTPRESSED=NONE;
}
}
}
//The player's money count. It's shown in a box that is WIDTH/4 and HEIGHT/6 in size.
void DrawMoneyBox(vf2d pos,vf2d size={(int)(WIDTH/4),(int)(HEIGHT/6)}) {
DrawDialogBox(pos,size,Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
std::string drawStr="$ "+std::to_string(MONEY);
vf2d textSize=GetTextSizeProp(drawStr);
vf2d stringOffset={4,2+(HEIGHT/12)-textSize.y};
DrawStringPropDecal(pos+stringOffset,drawStr,WHITE,{1,2});
vf2d textSize2=(vf2d)GetTextSizeProp("00");
DrawStringPropDecal({pos.x+stringOffset.x+textSize.x+2,pos.y+stringOffset.y},"00",WHITE,{0.4f,0.7f});
DrawLineDecal({pos.x+stringOffset.x+textSize.x+2,pos.y+stringOffset.y+textSize2.y*0.7f},{pos.x+stringOffset.x+textSize.x+textSize2.x*0.4f+2,pos.y+stringOffset.y+textSize2.y*0.7f});
}
//Returns a version of str with a/an and a space prepended to it followed by the str itself.
std::string A_An(std::string str) {
return startsWithVowel(str)?"an "+str:"a "+str;
}
bool startsWithVowel(std::string str) {
return str.length()>0&&(str[0]=='a'||str[0]=='e'||str[0]=='i'||str[0]=='o'||str[0]=='u'||str[0]=='A'||str[0]=='E'||str[0]=='I'||str[0]=='O'||str[0]=='U');
}
};
#ifndef TEST_SUITE
int main()
{
SeasonI demo;
if (demo.Construct(WIDTH, HEIGHT, 4, 4))
demo.Start();
return 0;
}
#endif