#include "entity.h"
#include "item.h"
#include "layers.h"
#include <string>
#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 "map.h"
#include "SeasonI.h"
#include "trigger.h"

//#include "test/test.h"

#ifndef TEST_SUITE
#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h"
#define OLC_PGEX_SPLASHSCREEN
#include "splash.h"
#define OLC_SOUNDWAVE
#include "defines.h"
#endif

#define SetupMove(movename) MOVELIST[BattleMoveName::movename]=new Battle::Move{BattleMoveName::movename,
#define SetupItem(itemname) ITEMLIST[ItemName::itemname]=new Item(ItemName::itemname,

using namespace olc;

struct SaveFileData{
	std::string playTime;
	std::string playerName;
	int chapterNumber=-1;
};

std::vector<Object*> OBJECTS;
const vd2d NO_NEIGHBOR = {-999,-999};
SeasonI*GAME;

vd2d cameraPos={0,0};

std::vector<Item*> PARTY_INVENTORY;


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;
int partyTrailStepCount=0;
float elapsedTime=0;
const float TARGET_RATE = 1/60.0;
int MAP_WIDTH=-1;
int MAP_HEIGHT=-1;
Map*CURRENT_MAP=nullptr;
std::map<MapName::Map,Map*> MAPS;
int GAME_STATE=GameState::FILE_LOAD_SELECT;
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;
std::array<bool,512> GAME_FLAGS={};
std::array<NPC_Obj*,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*CurrentCutscene=nullptr;
ActionType CurrentAction=ActionType::NONE;
double CUTSCENE_FADE_VALUE=0;
std::vector<CutsceneAction*>CUTSCENE_QUEUE={};
std::map<BattleMoveName,Battle::Move*>MOVELIST={};
std::array<std::pair<vd2d,Direction>,PARTY_TRAIL_LENGTH> partyTrail={std::pair<vd2d,Direction>{{0,0},Direction::SOUTH}};
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.
int INVENTORY_CONSUMABLE_OFFSET[4]={-1,-1,-1,-1};
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;
extern std::map<TriggerName::Trigger,std::string> TRIGGERS;
TriggerName::Trigger SELECTED_TRIGGER;
int TRIGGER_OFFSET=0;
int WORLD_DISPLAY_OFFSET=0;
bool SELECTING_A_MAP_FOR_TRIGGER=false;
Trigger*LAST_PLACED_TRIGGER=nullptr;
Map* ORIGINATING_MAP=nullptr;
std::array<std::string,7> PARTY_MEMBER_NAMES={"PLAYER","NESS","PAULA","JEFF","ANNA","KING","POO"};
std::array<SaveFileData,3> SAVE_FILE_DATA={{}};
int CHAPTER_NUMBER=0;
int SAVE_FILE_CURSOR=0;
std::string CUTSCENE_DISPLAY_TEXT="";
int CUTSCENE_DISPLAY_TEXT_DELAY_TIME=0;

/*
	[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::vector<std::vector<TILE*>> MAP6={}; 
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={};
std::map<CutsceneName::Cutscene,Cutscene*> CUTSCENES={};
vi2d SELECTED_MOVE_SQUARE={};

FountainEffect*FOUNTAIN_EFFECT=nullptr;
FireFountainEffect*FIREFOUNTAIN_EFFECT=nullptr;

Effect*CURRENT_EFFECT=nullptr;

#ifndef TEST_SUITE
bool SeasonI::OnUserCreate(){
	srand(time(NULL));
	GAME=this;
	for (int i=1;i<7;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();
	SetupCutscenes();
	SetupMapList();
	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};

	CURRENT_MAP=MAPS[MapName::ONETT];
	//OBJ_INFO["PLAYER"]=PLAYER_ANIMATION;
	LoadMap(CURRENT_MAP);

	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);


	for (int i=0;i<3;i++) {
		if (std::filesystem::exists("save"+std::to_string(i))) {
			std::ifstream f("save"+std::to_string(i));
			std::string data;
			std::getline(f,data);
			int commaPos=data.find_last_of(" ",data.size()-2)+1;
			std::string chapterNumber=data.substr(commaPos,data.size());
			int prevCommaPos=commaPos;
			commaPos=data.find_last_of(" ",commaPos-2)+1;
			std::string playerName=data.substr(commaPos,prevCommaPos-commaPos);
			prevCommaPos=commaPos;
			commaPos=data.find_last_of(" ",commaPos-2)+1;
			int frameTime=stoi(data.substr(commaPos,prevCommaPos-commaPos));
			std::string fileTime="";
			int seconds=frameTime/60;
			int minutes=seconds/60;
			int hours=minutes/60;
			if (hours<10) {
				fileTime+="0";
			}
			fileTime+=std::to_string(hours)+":";
			if (minutes%60<10) {
				fileTime+="0";
			}
			fileTime+=std::to_string(minutes%60)+":";
			if (seconds%60<10) {
				fileTime+="0";
			}
			fileTime+=std::to_string(seconds%60);
			//printf("File time detected is %s\n",fileTime.c_str());
			SAVE_FILE_DATA[i]={playTime:fileTime,playerName:playerName,chapterNumber:stoi(chapterNumber)};
		}
	}

	return true;
}
#endif

void SeasonI::SetupMoveList() {
	SetupMove(TESTMOVE1)"Test Move 1","An attack",baseDmg:30,randomDmg:5,range:1,channelTime:0,friendly:false};
	SetupMove(TESTMOVE2)"Test Move 2","An attack",baseDmg:40,randomDmg:10,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0}};
	SetupMove(TESTMOVE3)"Test Move 3","An attack",baseDmg:25,randomDmg:5,PPCost:0,range:3,channelTime:0,friendly:false,composition:{0,0,20,0}};
	SetupMove(BASH)"Bash","Regular attack.",baseDmg:5,randomDmg:5,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0}};
	SetupMove(BASH_CHANGE)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};
	SetupMove(DEFEND)"Defend","Defend.",baseDmg:0,randomDmg:0,PPCost:0,range:1,channelTime:5*60,friendly:true,{0,0,0,0}};
	SetupMove(EQUIP_ARMOR)"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"};
	SetupMove(CONSUMABLE)"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"};
	SetupMove(CONSUMABLE_ENEMY)"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"};
	SetupMove(HAILSTORM_A)"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}};
	SetupMove(HAILSTORM_B)"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}};
	SetupMove(HAILSTORM_G)"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}};
	SetupMove(HAILSTORM_O)"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}};
	SetupMove(HURRICANE_A)"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}};
	SetupMove(HURRICANE_B)"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}};
	SetupMove(HURRICANE_G)"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}};
	SetupMove(HURRICANE_O)"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}};
	SetupMove(METEORRAIN_A)"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}};
	SetupMove(METEORRAIN_B)"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}};
	SetupMove(METEORRAIN_G)"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}};
	SetupMove(METEORRAIN_O)"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}};
	SetupMove(PKFREEZE_A)"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}}};
	SetupMove(PKFREEZE_B)"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}}};
	SetupMove(PKFREEZE_G)"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}}};
	SetupMove(PKFREEZE_O)"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}}};
	SetupMove(PKSHIELD_A)"PK Shield","Protects against physical attacks.",ALPHA,baseDmg:0,randomDmg:0,PPCost:12,range:1,channelTime:0,friendly:true,composition:{0,0,20,0}};
	SetupMove(PKSHIELD_B)"PK Shield","Protects against physical attacks.",BETA,baseDmg:0,randomDmg:0,PPCost:20,range:1,channelTime:0,friendly:true,composition:{0,0,20,0}};
	SetupMove(PKSHIELD_O)"PK Shield","Protects against physical attacks.",OMEGA,baseDmg:0,randomDmg:0,PPCost:59,range:4,channelTime:0,friendly:true,composition:{0,0,20,0}};
	SetupMove(PKSHIELD_S)"PK Shield","Protects against physical attacks.",SIGMA,baseDmg:0,randomDmg:0,PPCost:80,range:10,channelTime:0,friendly:true,composition:{0,0,20,0}};
	SetupMove(PKLIFEUP_A)"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};
	SetupMove(PKLIFEUP_B)"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};
	SetupMove(PKLIFEUP_G)"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};
	SetupMove(PKLIFEUP_O)"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};
	SetupMove(PKFUN_A)"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};
	SetupMove(PKFUN_B)"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};
	SetupMove(PKFUN_G)"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};
	SetupMove(PKFUN_O)"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};
	SetupMove(PKFIRE_A)"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}};
	SetupMove(PKFIRE_B)"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}};
	SetupMove(PKFIRE_G)"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}};
	SetupMove(PKFIRE_O)"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};
	SetupMove(FREEZE_PACKET)"Freeze Packet","",baseDmg:120,randomDmg:20,PPCost:0,range:1,channelTime:0,friendly:false,composition:{0,0,0,0},"$USER uses the $POWER"};
}

void SeasonI::SetupItemList() { //hpRecovery,ppRecovery,attack,dmgReduction,equip,important,consumable
	SetupItem(COOKIE)"Cookie","A delightful little treat. Restores 40 HP.",2,{hpRecovery:40,consumable:Consumable::FRIENDLY,sellPrice:2});
	SetupItem(EGG)"Egg","Did it come before or after the chicken? Restores 60 HP.",3,{hpRecovery:60,consumable:Consumable::FRIENDLY,sellPrice:6});
	SetupItem(PIZZA)"Pizza","A scrumptious meal filled with lots of cheese. Restores 200 HP.",4,{hpRecovery:200,consumable:Consumable::FRIENDLY,sellPrice:12});
	SetupItem(MIRACLE_FOOD_LUNCH)"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,sellPrice:180});
	SetupItem(BOMB)"Bomb","A small explosive device. Deals around 120 damage.",256,{damage:110,rollDmg:30,consumable:Consumable::ENEMY,sellPrice:30});
	SetupItem(CRACKED_BAT)"Cracked Bat","Has some dents in it, but you can probably still dent things with it yourself.",256,{attack:10,equip:EquipSlot::WEAPON,sellPrice:4});
	SetupItem(TEE_BALL_BAT)"Tee Ball Bat","Great for playing some ball! Also great for beating your foes!",256,{attack:40,equip:EquipSlot::WEAPON,sellPrice:36});
	SetupItem(LIGHT_JACKET)"Light Jacket","Fits just fine.",256,{defense:10,equip:EquipSlot::ARMOR,sellPrice:25});
	SetupItem(HEAVY_JACKET)"Heavy Jacket","Are you sure this is good for your shoulders?",256,{defense:25,equip:EquipSlot::ARMOR,sellPrice:79});
	SetupItem(COPPER_BRACELET)"Copper Bracelet","It's not quite as shiny as a diamond, but it still makes you look good.",256,{defense:5,equip:EquipSlot::ACCESSORY,sellPrice:64});
	SetupItem(KEY_TO_THE_PALACE)"Key to the Palace","Lets you access a Palace.",256,{important:true});
	SetupItem(FREEZE_PACKET)"Freeze Packet","Lets out some blistering cold weather.",256,{consumable:Consumable::ENEMY,sellPrice:36},MOVELIST[BattleMoveName::FREEZE_PACKET]);
	SetupItem(SOME_STUPIDLY_LONG_FEATHER)"Some Stupidly Long Feather","Yeah, we don't know why this feather is so long either.",256,{attack:2,defense:3,equip:EquipSlot::ACCESSORY,sellPrice:36});
}

Entity::pstats_t partyMemberDefaultStats{HP:120,maxHP:120,PP:30,maxPP:30,baseAtk:8,speed:8,resistances:{0,0,0,0}};

void SeasonI::SetupPartyMemberStats() {
	for (int i=0;i<7;i++) {
		PARTY_MEMBER_STATS[i]=new Entity(i,partyMemberDefaultStats,{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 SeasonI::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 SeasonI::SetupObjectInfo() {
	CreateObjectInfo(new NPC_Obj(PLAYER,"player",{0,0},nullptr,{1,1},WHITE,16),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(NESS,"Ness",{0,0},nullptr,{1,1},YELLOW,14),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(PAULA,"Paula",{0,0},nullptr,{1,1},MAGENTA,13),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(JEFF,"Jeff",{0,0},nullptr,{1,1},DARK_GREEN,15),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(ANNA,"Anna",{0,0},nullptr,{1,1},DARK_MAGENTA,12),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(KING,"King",{0,0},nullptr,{1,1},GREY,10),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(POO,"Poo",{0,0},nullptr,{1,1},DARK_GREY,17),"player.png",{32,32});
	CreateObjectInfo(new NPC_Obj(NPC1,"npc1",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2,"npc2",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3,"npc3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4,"npc4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5,"npc5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6,"npc6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7,"npc7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8,"npc8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9,"npc9",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10,"npc10",{0,0},nullptr,{2,2},CYAN,20,false,{moveTime:180,moveFreq:60,moveSpd:1}),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11,"npc11",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12,"npc12",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13,"npc13",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13,"npc14",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14,"npc15",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15,"npc16",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16,"npc17",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17,"npc18",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18,"npc19",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19,"npc20",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_2,"npc1_2",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_2,"npc2_2",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_2,"npc3_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_2,"npc4_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_2,"npc5_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_2,"npc6_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_2,"npc7_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_2,"npc8_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_2,"npc9_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_2,"npc10_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_2,"npc11_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_2,"npc12_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_2,"npc13_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_2,"npc14_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_2,"npc15_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_2,"npc16_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_2,"npc17_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_2,"npc18_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_2,"npc19_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_2,"npc20_2",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_3,"npc1_3",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_3,"npc2_3",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_3,"npc3_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_3,"npc4_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_3,"npc5_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_3,"npc6_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_3,"npc7_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_3,"npc8_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_3,"npc9_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_3,"npc10_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_3,"npc11_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_3,"npc12_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_3,"npc13_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_3,"npc14_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_3,"npc15_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_3,"npc16_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_3,"npc17_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_3,"npc18_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_3,"npc19_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_3,"npc20_3",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_4,"npc1_4",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_4,"npc2_4",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_4,"npc3_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_4,"npc4_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_4,"npc5_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_4,"npc6_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_4,"npc7_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_4,"npc8_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_4,"npc9_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_4,"npc10_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_4,"npc11_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_4,"npc12_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_4,"npc13_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_4,"npc14_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_4,"npc15_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_4,"npc16_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_4,"npc17_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_4,"npc18_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_4,"npc19_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_4,"npc20_4",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_5,"npc1_5",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_5,"npc2_5",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_5,"npc3_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_5,"npc4_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_5,"npc5_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_5,"npc6_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_5,"npc7_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_5,"npc8_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_5,"npc9_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_5,"npc10_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_5,"npc11_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_5,"npc12_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_5,"npc13_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_5,"npc14_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_5,"npc15_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_5,"npc16_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_5,"npc17_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_5,"npc18_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_5,"npc19_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_5,"npc20_5",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_6,"npc1_6",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_6,"npc2_6",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_6,"npc3_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_6,"npc4_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_6,"npc5_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_6,"npc6_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_6,"npc7_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_6,"npc8_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_6,"npc9_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_6,"npc10_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_6,"npc11_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_6,"npc12_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_6,"npc13_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_6,"npc14_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_6,"npc15_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_6,"npc16_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_6,"npc17_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_6,"npc18_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_6,"npc19_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_6,"npc20_6",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_7,"npc1_7",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_7,"npc2_7",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_7,"npc3_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_7,"npc4_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_7,"npc5_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_7,"npc6_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_7,"npc7_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_7,"npc8_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_7,"npc9_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_7,"npc10_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_7,"npc11_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_7,"npc12_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_7,"npc13_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_7,"npc14_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_7,"npc15_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_7,"npc16_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_7,"npc17_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_7,"npc18_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_7,"npc19_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC19_7,"npc20_7",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC1_8,"npc1_8",{0,0},nullptr,{1,1},RED,60),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC2_8,"npc2_8",{0,0},nullptr,{1,1},GREEN,2),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC3_8,"npc3_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC4_8,"npc4_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC5_8,"npc5_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC6_8,"npc6_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC7_8,"npc7_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC8_8,"npc8_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC9_8,"npc9_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC10_8,"npc10_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC11_8,"npc11_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC12_8,"npc12_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_8,"npc13_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC13_8,"npc14_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC14_8,"npc15_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC15_8,"npc16_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC16_8,"npc17_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC17_8,"npc18_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new NPC_Obj(NPC18_8,"npc19_8",{0,0},nullptr,{2,2},BLUE,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new Shopkeeper_Obj(SHOPKEEPER,"Shopkeeper",{0,0},nullptr,{1,1},YELLOW,20),"player.png",{32,32},Flag::NONE,Flag::NONE);
	CreateObjectInfo(new TrashCan_Obj(TRASH_CAN,"trashCan",{0,0},nullptr,{1,1},WHITE,0),"trashcan.png",{32,32},Flag::NONE,Flag::NONE);
}

void SeasonI::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 SeasonI::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();
}

void SeasonI::SetGameFlag(Flag flag,bool val) {
	GAME_FLAGS[(int)flag]=val;
}

void SeasonI::LoadMap(Map*map) {
	CURRENT_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);
	std::ifstream f6("assets/maps/"+map->l6filename,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<MAP2.size();i++) {
		for (int j=0;j<MAP2[i].size();j++) {
			delete MAP2[i][j];
		}
		MAP2[i].clear();
	}
	
	for (int i=0;i<MAP3.size();i++) {
		for (int j=0;j<MAP3[i].size();j++) {
			delete MAP3[i][j];
		}
		MAP3[i].clear();
	}
	for (int i=0;i<MAP4.size();i++) {
		for (int j=0;j<MAP4[i].size();j++) {
			delete MAP4[i][j];
		}
		MAP4[i].clear();
	}
	for (int i=0;i<MAP5.size();i++) {
		for (int j=0;j<MAP5[i].size();j++) {
			delete MAP5[i][j];
		}
		MAP5[i].clear();
	}
	for (int i=0;i<MAP6.size();i++) {
		for (int j=0;j<MAP6[i].size();j++) {
			delete MAP6[i][j];
		}
		MAP6[i].clear();
	}
	for (int i=0;i<map->encounters.size();i++) {
		for (int j=0;j<map->encounters[i]->objs.size();j++) {
			delete map->encounters[i]->objs[j];
		}
		map->encounters[i]->objs.clear();
		delete map->encounters[i];
	}
	map->encounters.clear();
	for (int i=0;i<map->triggers.size();i++) {
		delete map->triggers[i];
	}
	map->triggers.clear();
	MAP_WIDTH=-1;
	MAP_HEIGHT=-1;
	MAP.clear();
	MAP2.clear();
	MAP3.clear();
	MAP4.clear();
	MAP5.clear();
	MAP6.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;
	}
	PARTY_MEMBER_COUNT=1;
	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
			||data.find("TRIGGER")!=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.find("ENCOUNTER")!=std::string::npos)?data.substr(9,marker-9):
				(data.find("TRIGGER")!=std::string::npos)?data.substr(7,marker-7):"");
			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 
			if (data.find("TRIGGER")!=std::string::npos) {
				marker=data.find_first_of(';',marker+1);
				std::stringstream split4(data.substr(lastMarker+1,marker-lastMarker-1));
				lastMarker=marker;
				int size_x,size_y;
				split4>>size_x;
				marker=data.find_first_of(';',marker+1);
				std::stringstream split5(data.substr(lastMarker+1,marker-lastMarker-1));
				lastMarker=marker;
				split5>>size_y;
				Map*mapTrigger=nullptr;
				vd2d triggerCoords;
				if (marker!=std::string::npos) {
					//This means there's extra data we should grab. Should be map, and two positional coordinates.
					marker=data.find_first_of(';',marker+1);
					std::stringstream split6(data.substr(lastMarker+1,marker-lastMarker-1));
					lastMarker=marker;
					int mapVal=0;
					split6>>mapVal;
					if (MAPS.count((MapName::Map)mapVal)) {
						mapTrigger=MAPS[(MapName::Map)mapVal];
						marker=data.find_first_of(';',marker+1);
						std::stringstream split7(data.substr(lastMarker+1,marker-lastMarker-1));
						lastMarker=marker;
						split7>>triggerCoords.x;
						marker=data.find_first_of(';',marker+1);
						std::stringstream split8(data.substr(lastMarker+1,marker-lastMarker-1));
						lastMarker=marker;
						split8>>triggerCoords.y;
						printf("  Found extra data. Map:%s\n",mapTrigger->mapname.c_str());
						map->triggers.push_back(new Trigger({(int)x,(int)y},{size_x,size_y},(TriggerName::Trigger)id,triggerCoords,mapTrigger));
					} else {
						printf("  Failed to load extra data.\n");
					}
				} else {
					map->triggers.push_back(new Trigger({(int)x,(int)y},{size_x,size_y},(TriggerName::Trigger)id));
				}
				printf("Trigger %d Loaded.\n",id);
			}
		} 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,TILE::GetTileDegree(map,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,TILE::GetTileDegree(map,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,TILE::GetTileDegree(map,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,TILE::GetTileDegree(map,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,TILE::GetTileDegree(map,tileX,tileY)));
		}
		MAP5.push_back(tiles);
	}
	while (f6.good()) {
		f6>>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,TILE::GetTileDegree(map,tileX,tileY)));
		}
		MAP6.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();
	f6.close();
}

void SeasonI::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);
	std::ofstream f6("assets/maps/"+map->l6filename,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');
			f6.put(MAP6[y][x]->tileX+'0');f6.put(MAP6[y][x]->tileY+'0');
		}
		if (y!=MAP_HEIGHT-1) {
			f.put('\n');
			f2.put('\n');
			f3.put('\n');
			f4.put('\n');
			f5.put('\n');
			f6.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]);
		}
	}

	for (int i=0;i<map->triggers.size();i++) {
		f.put('\n');
		std::string trigger="TRIGGER"+std::to_string(map->triggers[i]->GetPosX())+";"+std::to_string(map->triggers[i]->GetPosY())+";"+std::to_string(map->triggers[i]->GetID())+";"+std::to_string(map->triggers[i]->GetSizeX())+";"+std::to_string(map->triggers[i]->GetSizeY());
		if (map->triggers[i]->GetMapPtr()!=nullptr) {
			trigger+=";"+std::to_string(map->triggers[i]->GetMapPtr()->myID)+";"+std::to_string(map->triggers[i]->GetAdditionalCoordData().x)+";"+std::to_string(map->triggers[i]->GetAdditionalCoordData().y);
		}
		for (int j=0;j<trigger.length();j++) {
			f.put(trigger[j]);
		}
	}

	f.close();
	f2.close();
	f3.close();
	f4.close();
	f5.close();
	f6.close();
}

void SeasonI::AddItemToPlayerInventory(ItemName item) {
	PARTY_INVENTORY.push_back(ITEMLIST[item]);
}

Decal*SeasonI::CreateSprite(std::string spriteName) {
	SPRITES[spriteName] = new Decal(new Sprite("assets/"+spriteName));
	return SPRITES[spriteName];
}

Object*SeasonI::CreateObjectInfo(Object*obj,std::string spriteFileName,vi2d sprSize,Flag enableFlag,Flag disableFlag) {
	if (!ANIMATIONS.count(spriteFileName)) {
		ANIMATIONS[spriteFileName] = new Animation(CreateSprite(spriteFileName),sprSize);
	}
	obj->spr=ANIMATIONS[spriteFileName];
	obj->SetScale(obj->GetScale());
	obj->disableFlag=disableFlag;
	obj->enableFlag=enableFlag;
	OBJ_INFO[obj->id]=obj;
	return obj;
}

vi2d SeasonI::grid(int x, int y) {
	return {x*32,y*32};
}

bool SeasonI::GetGameFlag(int flag) {
	return GAME_FLAGS[flag];
}

bool SeasonI::GetGameFlag(Flag flag) {
	return GAME_FLAGS[(int)flag];
}

Object*SeasonI::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,OBJ_INFO[id]->temp,OBJ_INFO[id]->extraData);
}

Object*SeasonI::AddObjectToWorld(Object*obj) {
	std::vector<Object*>::const_iterator it = OBJECTS.begin();
	if (obj->id==PLAYER&&!obj->temp) {
		PARTY_MEMBER_OBJ[0]=(NPC_Obj*)obj;
		PARTY_MEMBER_ID[0]=0;
		PARTY_MEMBER_OBJ[0]->name="PLAYER";
		PARTY_MEMBER_OBJ[0]->hasCollision=false;
		PARTY_MEMBER_STATS[PARTY_MEMBER_ID[0]]->obj=PARTY_MEMBER_OBJ[0];
		for (int i=(int)Flag::HAS_MAIN+1;i<=(int)Flag::HAS_POO;i++) {
			if (GetGameFlag(i)) {
				PARTY_MEMBER_ID[PARTY_MEMBER_COUNT]=(int)PLAYER+i-(int)Flag::HAS_MAIN;
				PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]=(NPC_Obj*)AddObjectToWorld(CreateObject((int)PLAYER+i-(int)Flag::HAS_MAIN,PARTY_MEMBER_OBJ[0]->GetPos()));
				PARTY_MEMBER_OBJ[PARTY_MEMBER_COUNT]->hasCollision=false;
				switch ((int)PLAYER+i-(int)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");
}

void SeasonI::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);
	}
}

#ifndef TEST_SUITE
bool SeasonI::OnUserUpdate(float fElapsedTime)
{
	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::SUPPORT_GROUND);
	Clear(BLANK);
	SetDrawTarget(layer::BACKGROUND);
	Clear(BLANK);
	drawGame();
	return true;
}
#endif

void SeasonI::updateGame(){
	frameCount++;
	for (auto obj:OBJECTS) {
		if (obj->animated&&obj->animationSpd!=0&&obj->frameCount++>obj->animationSpd) {
			obj->frameCount=0;
			obj->frameIndex++;
		}
		if (NPCCanMove()) {
			obj->Update();
		}
	}

	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::TRIGGER_SELECT:{
			if (!GetKey(CTRL).bHeld) {
				GAME_STATE=GameState::EDITOR;
			}
		}break;
		case GameState::GAME_WORLD:{
			if (!GetGameFlag(Flag::INTRO_COMPLETED)) {
				SetGameFlag(Flag::INTRO_COMPLETED,true);
				StartCutscene(CUTSCENES[CutsceneName::INTRO_CUTSCENE]);
			}
			if (PlayerCanMove()) {
				bool moved=false;
				vd2d movementComponents = {0,0};
				Direction facingDir=(Direction)PARTY_MEMBER_OBJ[0]->animationSubIndex;
				if (UpHeld()) {
					movementComponents.y-=1;
					facingDir=Direction::NORTH;
					if (RightHeld()) {
						facingDir=Direction::NORTHEAST;
					}
					if (LeftHeld()) {
						facingDir=Direction::NORTHWEST;
					}
				}
				if (DownHeld()) {
					movementComponents.y+=1;
					facingDir=Direction::SOUTH;
					if (RightHeld()) {
						facingDir=Direction::SOUTHEAST;
					}
					if (LeftHeld()) {
						facingDir=Direction::SOUTHWEST;
					}
				}
				if (LeftHeld()) {
					movementComponents.x-=1;
					facingDir=Direction::WEST;
					if (UpHeld()) {
						facingDir=Direction::NORTHWEST;
					}
					if (DownHeld()) {
						facingDir=Direction::SOUTHWEST;
					}
				}
				if (RightHeld()) {
					movementComponents.x+=1;
					facingDir=Direction::EAST;
					if (UpHeld()) {
						facingDir=Direction::NORTHEAST;
					}
					if (DownHeld()) {
						facingDir=Direction::SOUTHEAST;
					}
				}
				PARTY_MEMBER_OBJ[0]->animationSubIndex=(int)facingDir;
				if (movementComponents.mag()>0) {
					movementComponents=movementComponents.norm();
					PARTY_MEMBER_OBJ[0]->frameIndex+=frameCount%PARTY_MEMBER_OBJ[0]->animationSpd==0;
					if (PARTY_MEMBER_OBJ[0]->SmoothMove(movementComponents)) {
						UpdatePlayerTrail(movementComponents,facingDir);
						for (int i=0;i<CURRENT_MAP->triggers.size();i++) {
							if (CURRENT_MAP->triggers[i]->IsInside(PARTY_MEMBER_OBJ[0]->GetPosWithOrigin())) {
								CURRENT_MAP->triggers[i]->Interact();
							}
						}
						moved=true;
					}
				}
				if (moved) {
					CenterCameraOnPlayer();
				}
				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::MAP_POSITION_SELECT:{
			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};
			}
		}break;
		case GameState::EDITOR:{
			if (IsTextEntryEnabled()) {
				return;
			}
			if (TabHeld()) {
				GAME_STATE=GameState::TILE_SELECT;
			}
			if (GetKey(SHIFT).bHeld) {
				GAME_STATE=GameState::ENCOUNTER_SELECT;
			}
			if (GetKey(CTRL).bHeld) {
				GAME_STATE=GameState::TRIGGER_SELECT;
				SELECTED_TRIGGER=TriggerName::NONE;
			}
			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:{
						if (EDITING_LAYER==layer::COLLISION&&SELECTED_TRIGGER!=TriggerName::NONE) {
							for (int i=0;i<CURRENT_MAP->triggers.size();i++) {
								if (CURRENT_MAP->triggers[i]->GetPos()==HIGHLIGHTED_TILE*32) {
									delete CURRENT_MAP->triggers[i];
									CURRENT_MAP->triggers.erase(CURRENT_MAP->triggers.begin()+i--);
								}
							}
							if (SELECTED_TRIGGER==TriggerName::GOTO_MAP) {
								SELECTING_A_MAP_FOR_TRIGGER=true;
								GAME_STATE=GameState::MAP_SELECT;
								ORIGINATING_MAP=CURRENT_MAP;
								LAST_PLACED_TRIGGER=new Trigger(HIGHLIGHTED_TILE*32,{32,32},SELECTED_TRIGGER); //Don't add it to the list of map triggers yet...It'll be wiped out if we do.
							} else {
								CURRENT_MAP->triggers.push_back(new Trigger(HIGHLIGHTED_TILE*32,{32,32},SELECTED_TRIGGER));
							}
						} else {
							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::SUPPORT_GROUND:{
						TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
						tile->tileX=SELECTED_TILE.x;
						tile->tileY=SELECTED_TILE.y;
					}break;
					case layer::BACKGROUND:{
						TILE*tile=MAP6[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:{
						if (EDITING_LAYER==layer::COLLISION&&SELECTED_TRIGGER!=TriggerName::NONE) {
							for (int i=0;i<CURRENT_MAP->triggers.size();i++) {
								if (CURRENT_MAP->triggers[i]->GetPos()==HIGHLIGHTED_TILE*32) {
									delete CURRENT_MAP->triggers[i];
									CURRENT_MAP->triggers.erase(CURRENT_MAP->triggers.begin()+i--);
								}
							}
						} else {
							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::SUPPORT_GROUND:{
						TILE*tile=MAP4[HIGHLIGHTED_TILE.y][HIGHLIGHTED_TILE.x];
						tile->tileX=tile->tileY=15;
					}break;
					case layer::BACKGROUND:{
						TILE*tile=MAP6[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 SeasonI::keyUpdates() {
	if (GetKey(F1).bPressed) {
		ConsoleShow(F1,false);
	}

	if (GetKey(F6).bPressed) {
		SaveGameSaveData(0);
	}
	if (GetKey(F7).bPressed) {
		LoadGameSaveData(0);
	}

	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);
			}
			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()||BackPressed()) {
						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||BackPressed()) {
						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()||BackPressed()) {
					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||BackPressed()) {
					if (SELECTED_MOVE_SQUARE.x==0&&SELECTED_MOVE_SQUARE.y==0||BackPressed()) {
						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)||BackPressed()) {
					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;
							INVENTORY_CONSUMABLE_OFFSET[-CURRENT_TURN-1]=ITEM_SELECTION_CURSOR;
						} 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::FILE_LOAD_SELECT:{
			CursorControl(SAVE_FILE_CURSOR,3);
			if (ACTIONKEYPRESSED&&SAVE_FILE_DATA[SAVE_FILE_CURSOR].chapterNumber!=-1) {
				StartCutscene(CUTSCENES[CutsceneName::LOAD_FILE_CUTSCENE]);
			}
		}break;
		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;
				for (int i=0;i<OBJECTS.size();i++) {
					if (!OBJECTS[i]->enc) {
						OBJECTS[i]->SetPos(OBJECTS[i]->GetStartPos());
					}
				}
				CenterCameraOnPlayer();
			} else
			if (PlayerCanMove()&&ACTIONKEYPRESSED) {
				GAME_STATE=GameState::OVERWORLD_MENU;
				OVERWORLD_MENU_SELECTION=0;
				SetupRollingHitpointCounters();
			}
		}break;
		case GameState::OVERWORLD_MENU:{
			if (LeftPressed()||BackPressed()) {
				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 = std::abs(PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x-OBJECTS[i]->GetPosWithOrigin().x)+std::abs(PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y-OBJECTS[i]->GetPosWithOrigin().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()||BackPressed()) {
				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()||BackPressed()) {
				if (PARTY_MEMBER_COUNT==1) {
					OVERWORLD_POWER_SELECTION_MEMBER=-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||BackPressed()) {
				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()||BackPressed()){
				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.
					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.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.hp+=item->stats.hpIncrease;
									}break;
									case ItemAction::PPINCREASE:{
										target->stats.maxPP+=item->stats.ppIncrease;
										target->AddPP(item->stats.ppIncrease);
										target->boosts.pp+=item->stats.ppIncrease;
									}break;
									case ItemAction::SPDINCREASE:{
										target->stats.speed+=item->stats.spdIncrease;
										target->boosts.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);
						}
					}
					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)||BackPressed()) {
				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()||BackPressed()) {
				OVERWORLD_POWER_SELECTION_MEMBER=-1;
				GAME_STATE=GameState::OVERWORLD_MENU;
			}
		}break;
		case GameState::MAP_POSITION_SELECT:{
			if (GetMouse(0).bReleased) {
				LAST_PLACED_TRIGGER->SetExtraCoords(HIGHLIGHTED_TILE*32);
				LoadMap(ORIGINATING_MAP);
				CURRENT_MAP->triggers.push_back(LAST_PLACED_TRIGGER);
				LAST_PLACED_TRIGGER=nullptr;
				GAME_STATE=GameState::EDITOR;
				SELECTING_A_MAP_FOR_TRIGGER=false;
			}
		}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);
				CenterCameraOnPlayer();
			}
			if (GetKey(K1).bPressed) {
				EDITING_LAYER=layer::COLLISION;
				SELECTED_TRIGGER=TriggerName::NONE;
				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::SUPPORT_GROUND;
				EnableLayer(layer::COLLISION,false);
			}
			if (GetKey(K6).bPressed) {
				EDITING_LAYER=layer::BACKGROUND;
				EnableLayer(layer::COLLISION,false);
			}
			if (GetKey(HOME).bPressed) {
				GAME_STATE=GameState::MAP_SELECT;
			}
			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) {
						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;
					}
				}
				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) {
				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;
					}
				}
				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::MAP_SELECT:{
			if (GetKey(ESCAPE).bPressed) {
				if (SELECTING_A_MAP_FOR_TRIGGER) {
					SELECTING_A_MAP_FOR_TRIGGER=false;
					LAST_PLACED_TRIGGER->SetMap(CURRENT_MAP);
					printf("Trigger Map Location set to %s\n",CURRENT_MAP->mapname.c_str());
					GAME_STATE=GameState::MAP_POSITION_SELECT;
				} else {
					GAME_STATE=GameState::EDITOR;
				}
			}
			if ((GetMouseWheel()<0||GetKey(PGDN).bHeld)&&WORLD_DISPLAY_OFFSET+(WIDTH/16)<MAPS.size()) {
				WORLD_DISPLAY_OFFSET+=WIDTH/16;
			} else
			if ((GetMouseWheel()>0||GetKey(PGUP).bHeld)&&WORLD_DISPLAY_OFFSET-(WIDTH/16)>=0) {
				WORLD_DISPLAY_OFFSET-=WIDTH/16;
			}
		}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::ENCOUNTER_SELECT:{
			if (GetKey(ESCAPE).bPressed) {
				GAME_STATE=GameState::EDITOR;
			}
			if ((GetMouseWheel()<0||GetKey(PGDN).bHeld)&&ENCOUNTER_OFFSET+(WIDTH/16)<OBJ_INFO.size()) {
				ENCOUNTER_OFFSET+=WIDTH/16;
			} else
			if ((GetMouseWheel()>0||GetKey(PGUP).bHeld)&&ENCOUNTER_OFFSET-(WIDTH/16)>=0) {
				ENCOUNTER_OFFSET-=WIDTH/16;
			}
		}break;
		case GameState::TRIGGER_SELECT:{
			if (GetKey(ESCAPE).bPressed) {
				GAME_STATE=GameState::EDITOR;
			}
			if ((GetMouseWheel()<0||GetKey(PGDN).bHeld)&&TRIGGER_OFFSET+(WIDTH/16)<OBJ_INFO.size()) {
				TRIGGER_OFFSET+=WIDTH/16;
			} else
			if ((GetMouseWheel()>0||GetKey(PGUP).bHeld)&&TRIGGER_OFFSET-(WIDTH/16)>=0) {
				TRIGGER_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()||BackPressed()) {
				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()||BackPressed()) {
				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()||BackPressed()) {
				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||BackPressed()) {
				if (SHOP_MENU_CURSOR==SHOP_ITEMS.size()||BackPressed()) {
					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;
		case GameState::SHOPKEEPER_SELL_MENU:{
			if (LeftPressed()&&!(ITEM_SELECTION_CURSOR&1)||BackPressed()) {
				GAME_STATE=GameState::GAME_WORLD;
				SHOPKEEPER_INTERACTING_WITH->ShoppingCompleted();
			} else {
				HandleInventoryNavigation();
			}
			if (ACTIONKEYPRESSED) {
				if (PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.important) {
					DisplayMessageBox("You shouldn't get rid of that!");
				} else {
					GAME_STATE=GameState::SHOPKEEPER_CONFIRM_SELL_MENU;
					Item*item=PARTY_INVENTORY[ITEM_SELECTION_CURSOR];
					DisplayMessageBox(A_An(PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->name,true)+" sells for $"+std::to_string(PARTY_INVENTORY[ITEM_SELECTION_CURSOR]->stats.sellPrice)+". Would you like to sell it? [Yes,No]>0:You sell "+A_An(item->name)+" for $"+std::to_string(item->stats.sellPrice)+".>1:You decide against selling "+A_An(item->name)+".<");
				}
			}
		}break;
	}
	reset:
	ANYKEYPRESSED=ACTIONKEYPRESSED=false;
	if (KEY_LASTPRESSED!=NONE) {
		lastRepeatedFrame=frameCount;
	}
}

void SeasonI::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-((member->selectedMove->channelTime==0)?0:((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)50/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::FILE_LOAD_SELECT:{
			DrawDialogBox({4,4},{(int)(WIDTH-8),HEIGHT/4},Pixel(70, 33, 105,220),Pixel(62, 54, 69,220),Pixel(185, 148, 255,220));
			for (int i=0;i<3;i++) {
				if (SAVE_FILE_DATA[i].chapterNumber!=-1) {
					DrawStringDecal({16.f,(float)(12+i*16)},SAVE_FILE_DATA[i].playerName+"  Chapter "+std::to_string(SAVE_FILE_DATA[i].chapterNumber)+"  "+SAVE_FILE_DATA[i].playTime);
				} else {
					DrawStringDecal({16.f,(float)(12+i*16)},"New Game");
				}
			}
			DrawRotatedDecal({10.F,(float)16+SAVE_FILE_CURSOR*16},SPRITES["cursor.png"],0,{4,4});
		}break;
		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});
				if (PARTY_MEMBER_COUNT>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.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.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.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.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::SHOPKEEPER_SELL_MENU:
		case GameState::SHOPKEEPER_CONFIRM_SELL_MENU:{
			DrawGameWorld();
			DrawInventory();
			DrawMoneyBox({WIDTH-WIDTH/4-4,HEIGHT*(3.f/4)+4});
		}break;
		case GameState::EDITOR:{
			DrawGameWorld();
			SetDrawTarget(nullptr);
			DrawRectDecal((HIGHLIGHTED_TILE)*32-cameraPos,{32,32},YELLOW);
			if (EDITING_LAYER==layer::COLLISION&&SELECTED_TRIGGER!=TriggerName::NONE) {
				DrawStringPropDecal({2,2},Wrap("Editing Triggers - Selected "+TRIGGERS[SELECTED_TRIGGER],WIDTH-4,true,{1,1}));
				DrawTriggers();
			} else
			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));
			}
			std::string coords="("+std::to_string(HIGHLIGHTED_TILE.x)+","+std::to_string(HIGHLIGHTED_TILE.y)+")";
			std::string coords2="("+std::to_string(HIGHLIGHTED_TILE.x*32)+","+std::to_string(HIGHLIGHTED_TILE.y*32)+")";
			DrawStringPropDecal({(float)WIDTH-1-GetTextSizeProp(coords).x,(float)HEIGHT-1-GetTextSizeProp(coords).y-(float)GetTextSizeProp(coords2).y*0.5f},coords);
			DrawStringPropDecal({(float)WIDTH-1-GetTextSizeProp(coords2).x*0.5f,(float)HEIGHT-1-GetTextSizeProp(coords2).y*0.5f},coords2,Pixel(160,160,255),{0.5,0.5});
		}break;
		case GameState::MAP_POSITION_SELECT:{
			DrawGameWorld();
			SetDrawTarget(layer::INTERFACE);
			DrawRectDecal((HIGHLIGHTED_TILE)*32-cameraPos,{32,32},YELLOW);
			DrawStringPropDecal({2,2},"Select target tile");
		}break;
		case GameState::TILE_SELECT:{
			//14x14 pixels per tile.
			Clear(Pixel(64,64,128));
			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->sprSize.x),(float)obj->spr->sprSize.y*obj->animationSubIndex},{(float)obj->spr->sprSize.x,(float)obj->spr->sprSize.y},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->sprSize.x),(float)(enc->objs[i]->obj->spr->sprSize.y*enc->objs[i]->obj->animationSubIndex)},{(float)(enc->objs[i]->obj->spr->sprSize.x),(float)(enc->objs[i]->obj->spr->sprSize.y)},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->sprSize.x),(float)(enc->objs[i]->obj->spr->sprSize.y*enc->objs[i]->obj->animationSubIndex)},{(float)(enc->objs[i]->obj->spr->sprSize.x),(float)(enc->objs[i]->obj->spr->sprSize.y)},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;
		case GameState::TRIGGER_SELECT:{
			vd2d drawpos={0,0};
			int counter=0;
			for (std::map<TriggerName::Trigger,std::string>::const_iterator it = TRIGGERS.cbegin();it!=TRIGGERS.cend();++it){
				if (counter<TRIGGER_OFFSET) {
					counter++;
					continue;
				}
				if (drawpos.y>HEIGHT) {
					break;
				}
				TriggerName::Trigger trigger = it->first;
				if (GetMouse(0).bHeld&&
					GetMousePos().x>=drawpos.x&&
					GetMousePos().x<drawpos.x+16&&
					GetMousePos().y>=drawpos.y&&
					GetMousePos().y<drawpos.y+24) {
					SELECTED_TRIGGER=trigger;
					EDITING_LAYER=layer::COLLISION;
					EnableLayer(layer::COLLISION,false);
				}
				FillRectDecal(drawpos,{16,24},VERY_DARK_GREY);
				DrawStringDecal({(float)(drawpos.x+2),(float)(drawpos.y)},it->second,WHITE,{(float)(12.0/GetTextSize(it->second).x),1.0});
				if (SELECTED_TRIGGER==it->first) {
					DrawRectDecal(drawpos,{16,24},YELLOW);
				}
				drawpos.x+=16;
				if (drawpos.x>=WIDTH) {
					drawpos.x=0;
					drawpos.y+=24;
				}
				counter++;
			}
		}break;
		case GameState::MAP_SELECT:{
			vd2d drawpos={0,0};
			int counter=0;
			for (std::map<MapName::Map,Map*>::const_iterator it = MAPS.cbegin();it!=MAPS.cend();++it){
				if (counter<WORLD_DISPLAY_OFFSET) {
					counter++;
					continue;
				}
				if (drawpos.y>HEIGHT) {
					break;
				}
				Map*map = it->second;
				if (GetMouse(0).bHeld&&
					GetMousePos().x>=drawpos.x&&
					GetMousePos().x<drawpos.x+16&&
					GetMousePos().y>=drawpos.y&&
					GetMousePos().y<drawpos.y+24) {
					LoadMap(map);
					EDITING_LAYER=layer::COLLISION;
					EnableLayer(layer::COLLISION,false);
				}
				FillRectDecal(drawpos,{16,24},VERY_DARK_GREY);
				DrawStringDecal({(float)(drawpos.x+2),(float)(drawpos.y)},it->second->mapname,WHITE,{(float)(12.0/GetTextSize(it->second->mapname).x),1.0});
				if (CURRENT_MAP==it->second) {
					DrawRectDecal(drawpos,{16,24},YELLOW);
				}
				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->sprSize.x/(double)SPRITES["targetCircle.png"]->sprite->width,PARTY_MEMBER_OBJ[memberIndex]->spr->sprSize.y/(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->sprSize.x/(double)SPRITES["targetCircle.png"]->sprite->width),static_cast<float>(PARTY_MEMBER_OBJ[memberIndex]->spr->sprSize.y/(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->sprSize.x/(double)SPRITES["targetCircle.png"]->sprite->width,BATTLE_ENCOUNTER->objs[SELECTED_TARGET]->obj->spr->sprSize.y/(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) {
		DrawInventory();
	}

	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-((obj->selectedMove->channelTime==0)?0:((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);
	}
	if (GAME_FLAGS[(int)Flag::IS_NIGHTTIME]) {
		FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,64,128));
	}
	FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,(int)CUTSCENE_FADE_VALUE));
	if (GAME_STATE==GameState::DISPLAY_CUTSCENE_TEXT) {
		vi2d textSize=GetTextSizeProp(Wrap(CUTSCENE_DISPLAY_TEXT,WIDTH,true,{2,2}))*2;
		DrawStringPropDecal(GetScreenSize()/2-textSize/2,Wrap(CUTSCENE_DISPLAY_TEXT,WIDTH,true,{2,2}),WHITE,{2,2});
	}
};

ActionType SeasonI::GetCurrentCutsceneAction() {
	return (CurrentCutscene==nullptr)?ActionType::NONE:CurrentCutscene->CurrentAction();
}

void SeasonI::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;
				}
			}
		}
	}

void SeasonI::HandleRollingCounters(int i,int(&counter)[4][3],int(&display)[4][3],Entity*member,int maxVal,int currentVal,int targetVal,bool pp) {
	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]--;
		}
	}
}

void SeasonI::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->sprSize.x*0.5*(PARTY_MEMBER_OBJ[i]->GetScale().x-1),
						BATTLE_ENCOUNTER->playerPos[i].y+BATTLE_ENCOUNTER->pos.y-(PARTY_MEMBER_OBJ[i]->spr->sprSize.y-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;
					}
					if (INVENTORY_CONSUMABLE_OFFSET[-CURRENT_TURN-1]>=0) {
						PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->RemoveItem(INVENTORY_CONSUMABLE_OFFSET[-CURRENT_TURN-1]);
						INVENTORY_CONSUMABLE_OFFSET[-CURRENT_TURN-1]=-1;
					}
				} 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.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.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.pp+=BATTLE_CUSTOM_ITEM->stats.ppIncrease;
							}break;
							case ItemAction::SPDINCREASE:{
								target->stats.speed+=BATTLE_CUSTOM_ITEM->stats.spdIncrease;
								target->boosts.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;
							INVENTORY_CONSUMABLE_OFFSET[i]=-1;
							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 SeasonI::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();
				}
			} else {
				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;
		case ActionType::LOAD_MAP:{
			class LoadMap*action=(class LoadMap*)CurrentCutscene->GetAction();
			Map*map=action->GetTargetMap();
			LoadMap(map);
			CurrentCutscene->AdvanceAction();
		}break;
		case ActionType::MOVE_PLAYER_OBJS:{
			MovePlayerObjects*action=(MovePlayerObjects*)CurrentCutscene->GetAction();
			vd2d pos=action->GetTargetPos();
			for (int i=0;i<PARTY_MEMBER_COUNT;i++) {
				PARTY_MEMBER_OBJ[i]->SetPos(pos);
			}
			CenterCameraOnPlayer();
			CurrentCutscene->AdvanceAction();
		}break;
		case ActionType::LOAD_FILE:{
			LoadGameSaveData(SAVE_FILE_CURSOR);
			CenterCameraOnPlayer();
			GAME_STATE=GameState::GAME_WORLD;
			CurrentCutscene->AdvanceAction();
		}break;
		case ActionType::SET_FLAG:{
			SetFlag*action=(SetFlag*)CurrentCutscene->GetAction();
			SetGameFlag(action->GetFlag(),action->GetValue());
			CurrentCutscene->AdvanceAction();
		}break;
		case ActionType::SET_CUTSCENE_DISPLAY_TEXT:{
			SetCutsceneDisplayText*action=(SetCutsceneDisplayText*)CurrentCutscene->GetAction();
			if (CUTSCENE_DISPLAY_TEXT_DELAY_TIME==0) {
				CUTSCENE_DISPLAY_TEXT=action->GetCutsceneText();
				CUTSCENE_DISPLAY_TEXT_DELAY_TIME=action->GetDelay();
				GAME_STATE=GameState::DISPLAY_CUTSCENE_TEXT;
			} else
			if (--CUTSCENE_DISPLAY_TEXT_DELAY_TIME==0) {
				CurrentCutscene->AdvanceAction();
				GAME_STATE=GameState::GAME_WORLD;
			}
		}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;
		}
	}
}

bool SeasonI::TabHeld(){
	return GetKey(TAB).bHeld;
}
bool SeasonI::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 SeasonI::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 SeasonI::LeftPressed(){
	return GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128||KeyRepeat(LEFT);
}
bool SeasonI::RightPressed(){
	return GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed||MOUSE_PRESSED_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128||KeyRepeat(RIGHT);
}
bool SeasonI::BackPressed(){
	return GetKey(BACK).bPressed||GetKey(ESCAPE).bPressed||GetKey(X).bPressed||GetKey(CTRL).bPressed||GetKey(DEL).bPressed||GetKey(END).bPressed||GetKey(NP_DECIMAL).bPressed||GetKey(NP_SUB).bPressed||GetKey(MINUS).bPressed||GetKey(PAUSE).bPressed||GetKey(TAB).bPressed;
}
bool SeasonI::UpHeld(){
	return GetKey(W).bHeld||GetKey(UP).bHeld||GetKey(NP8).bHeld||MOUSE_DOWN&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128;
}
bool SeasonI::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 SeasonI::LeftHeld(){
	return GetKey(A).bHeld||GetKey(LEFT).bHeld||GetKey(NP4).bHeld||MOUSE_DOWN&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128;
}
bool SeasonI::RightHeld(){
	return GetKey(D).bHeld||GetKey(RIGHT).bHeld||GetKey(NP6).bHeld||MOUSE_DOWN&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128;
}
bool SeasonI::BackHeld(){
	return GetKey(BACK).bHeld||GetKey(ESCAPE).bHeld||GetKey(X).bHeld||GetKey(CTRL).bHeld||GetKey(DEL).bHeld||GetKey(END).bHeld||GetKey(NP_DECIMAL).bHeld||GetKey(NP_SUB).bHeld||GetKey(MINUS).bHeld||GetKey(PAUSE).bHeld||GetKey(TAB).bHeld;
}
bool SeasonI::UpReleased(){
	return GetKey(W).bReleased||GetKey(UP).bReleased||GetKey(NP8).bReleased||MOUSE_RELEASED&&GetMouseY()<=HEIGHT-128+32&&GetMouseY()>=HEIGHT-128&&GetMouseX()<=HEIGHT-128;
}
bool SeasonI::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 SeasonI::LeftReleased(){
	return GetKey(A).bReleased||GetKey(LEFT).bReleased||GetKey(NP4).bReleased||MOUSE_RELEASED&&GetMouseX()<=32&&GetMouseX()>=0&&GetMouseY()>=HEIGHT-128;
}
bool SeasonI::RightReleased(){
	return GetKey(D).bReleased||GetKey(RIGHT).bReleased||GetKey(NP6).bReleased||MOUSE_RELEASED&&GetMouseX()<=128&&GetMouseX()>=96&&GetMouseY()>=HEIGHT-128;
}
bool SeasonI::BackReleased(){
	return GetKey(BACK).bReleased||GetKey(ESCAPE).bReleased||GetKey(X).bReleased||GetKey(CTRL).bReleased||GetKey(DEL).bReleased||GetKey(END).bReleased||GetKey(NP_DECIMAL).bReleased||GetKey(NP_SUB).bReleased||GetKey(MINUS).bReleased||GetKey(PAUSE).bReleased||GetKey(TAB).bReleased;
}

bool SeasonI::PlayerCanMove(){
	return GAME_STATE==GameState::GAME_WORLD&&BATTLE_ENCOUNTER==nullptr&&!IsTextEntryEnabled()&&!messageBoxVisible&&PARTY_MEMBER_OBJ[0]!=nullptr&&CurrentCutscene==nullptr;
}

bool SeasonI::NPCCanMove(){
	return GAME_STATE==GameState::GAME_WORLD&&BATTLE_ENCOUNTER==nullptr&&!IsTextEntryEnabled()&&!messageBoxVisible;
}

void SeasonI::UpdatePlayerTrail(vd2d newMovement,Direction newFacingDir) {
	for (int i=PARTY_TRAIL_LENGTH-1;i>0;i--) {
		partyTrail[i]=partyTrail[i-1];
	}
	partyTrailStepCount++;
	partyTrail[0]={{PARTY_MEMBER_OBJ[0]->GetPos().x-newMovement.x+PARTY_MEMBER_OBJ[0]->spr->sprSize.x*0.5*(PARTY_MEMBER_OBJ[0]->GetScale().x-1),
	PARTY_MEMBER_OBJ[0]->GetPos().y-newMovement.y+(PARTY_MEMBER_OBJ[0]->spr->sprSize.y-4)*(PARTY_MEMBER_OBJ[0]->GetScale().y-1)},newFacingDir};
	for (int i=1;i<PARTY_MEMBER_COUNT;i++) {
		PARTY_MEMBER_OBJ[i]->SetPos(partyTrail[PARTY_TRAIL_LENGTH*((double)i/4)].first);
		PARTY_MEMBER_OBJ[i]->animationSubIndex=(int)partyTrail[PARTY_TRAIL_LENGTH*((double)i/4)].second;
		PARTY_MEMBER_OBJ[i]->frameIndex+=partyTrailStepCount%PARTY_MEMBER_OBJ[i]->animationSpd==0;
	}
}

void SeasonI::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;
			}
		}
	}
}

void SeasonI::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++];
			}
		}
	}
}

void SeasonI::cameraUpdate() {
	switch (GAME_STATE) {
		case GameState::EDITOR:
		case GameState::MAP_POSITION_SELECT:{
			//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 SeasonI::StartEffect(Effect*eff) {
	CURRENT_EFFECT=eff;
	eff->create(PARTICLES);
}

void SeasonI::PopulateBattleMoveList(int partyMemberSlot,bool overworld) {
	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 SeasonI::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;
	}
	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]) {
		DISPLAY_TARGET_MESSAGE="Use "+EQUIP_$ITEM_DISPLAY+" on...";
	} else {
		DISPLAY_TARGET_MESSAGE="Use "+PARTY_MEMBER_STATS[PARTY_MEMBER_ID[-CURRENT_TURN-1]]->selectedMove->GetPowerName()+" on...";
	}
}

void SeasonI::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;

	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);
		}
	}
}

std::vector<Entity*> SeasonI::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;
}

int SeasonI::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;
}

void SeasonI::PopulateMovementGrid(vd2d pos,int range) {
	vi2d gridCenter = (vi2d)pos/32*32;
	MOVEMENT_GRID.clear();
	CheckGrid(0,0,gridCenter-cameraPos,std::min(8,range));
}

int SeasonI::getProperty(Property prop,Battle::Move*move) {
	return move->properties[prop];
}

void SeasonI::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 SeasonI::PerformOverworldMove(Battle::Move*move,int partyMemberSlot) {
	OVERWORLD_SELECTED_POWER=move;
	OVERWORLD_TARGET_SELECTION=0;
	DISPLAY_TARGET_MESSAGE="Use "+move->GetPowerName()+" on...";
	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 {
		//Other types of moves will go here.
	}
}

void SeasonI::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 SeasonI::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;
		}
	}
}

std::string SeasonI::A_An(std::string str,bool capitalized) {
	return startsWithVowel(str)?(capitalized?"An ":"an ")+str:(capitalized?"A ":"a ")+str;
}

void SeasonI::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 SeasonI::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 SeasonI::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 SeasonI::drawCheckerboardBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p, olc::Pixel alternatingCol,  const olc::vi2d &checkerboardSize, olc::Pixel p2, olc::Pixel p3) {
	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);
			}
		}
	}
}

bool SeasonI::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 SeasonI::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 SeasonI::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)&&
				(GetTileDegreeSafely(MAP2)==0&&
				obj->GetPos().y+obj->originPoint.y>(y+yTileOffset)*32&&
				obj->GetPos().y+obj->originPoint.y<=(y+yTileOffset+1)*32||
				GetTileDegreeSafely(MAP2)==-1&&
				GetPointQuadrantRelativeToLine({(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x/32,(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y/32+32}, {(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x/32+32,(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y/32}, PARTY_MEMBER_OBJ[0]->GetPosWithOrigin())<0||
				GetTileDegreeSafely(MAP2)==1&&
				GetPointQuadrantRelativeToLine({(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x/32,(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y/32}, {(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x/32+32,(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y/32+32}, PARTY_MEMBER_OBJ[0]->GetPosWithOrigin())>0)) {
				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->sprSize.x;xx++) {
							accX+=obj->GetScale().x;
							for (int yy=0;yy<obj->spr->sprSize.y;yy++) {
								accY+=obj->GetScale().y;
								Pixel col = data[(yy+obj->animationSubIndex*obj->spr->sprSize.y)*obj->spr->spr->sprite->width+xx+((obj->frameIndex%obj->spr->frames)*obj->spr->sprSize.x)];
								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,std::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->sprSize.x),(float)obj->spr->sprSize.y*obj->animationSubIndex},{(float)obj->spr->sprSize.x,(float)obj->spr->sprSize.y},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->sprSize.x),(float)obj->spr->sprSize.y*obj->animationSubIndex},{(float)obj->spr->sprSize.x,(float)obj->spr->sprSize.y},obj->GetScale(),obj->color);
					}
				}
			}
		}
		for (int x=-1;x<WIDTH/32+2;x++) {
			int xTileOffset = cameraPos.x/32;
			char tiles=0;
			if (x+xTileOffset>=0&&x+xTileOffset<MAP_WIDTH&&y+yTileOffset>=0&&y+yTileOffset<MAP_HEIGHT) {
				if(MAP5[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP5[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					SetDrawTarget(layer::COLLISION);
					DrawPartialSprite({(int)(x*32-fmod(cameraPos.x,32)),(int)(y*32-fmod(cameraPos.y,32))},CURRENT_MAP->tileset->sprite,{(int)(MAP5[y+yTileOffset][x+xTileOffset]->tileX*32),(int)(MAP5[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
					tiles|=1<<5;
				}
				if(MAP6[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP6[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					SetDrawTarget(layer::BACKGROUND);
					DrawPartialDecal({(float)(x*32-fmod(cameraPos.x,32)),(float)(y*32-fmod(cameraPos.y,32))},SPRITES["terrainmap.png"],{(float)(MAP6[y+yTileOffset][x+xTileOffset]->tileX*32),(float)(MAP6[y+yTileOffset][x+xTileOffset]->tileY*32)},{32,32});
					tiles|=1<<4;
				}
				if(MAP4[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP4[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					SetDrawTarget(layer::SUPPORT_GROUND);
					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});
					tiles|=1<<3;
				}
				if(MAP3[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP3[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					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});
					tiles|=1<<2;
				}
				if(MAP2[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP2[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					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});
					tiles|=1<<1;
				}
				if(MAP[y+yTileOffset][x+xTileOffset]->tileX!=15||MAP[y+yTileOffset][x+xTileOffset]->tileY!=15) {
					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});
					tiles|=1;
				}
			}
			if (GAME_STATE==GameState::EDITOR) {
				std::string tileDisplays = std::string((tiles>>5&1)?"C":"")+std::string((tiles&1)?"2":"")+std::string((tiles>>1&1)?"3":"")+std::string((tiles>>2&1)?"4":"")+std::string((tiles>>3&1)?"5":"")+((tiles>>4&1)?"6":"");
				for (int i=0;i<tileDisplays.size();i++) {
					if (tileDisplays[i]-'0'==2&&EDITING_LAYER==layer::HIGH||
						tileDisplays[i]-'0'==3&&EDITING_LAYER==layer::DYNAMIC||
						tileDisplays[i]-'0'==4&&EDITING_LAYER==layer::GROUND||
						tileDisplays[i]-'0'==5&&EDITING_LAYER==layer::SUPPORT_GROUND||
						tileDisplays[i]-'0'==6&&EDITING_LAYER==layer::BACKGROUND||
						tileDisplays[i]-'0'==1&&EDITING_LAYER==layer::COLLISION) {
						DrawStringDecal({(float)(x*32-fmod(cameraPos.x,32)+31-GetTextSize(tileDisplays).x*0.5f+4*i),(float)(y*32-fmod(cameraPos.y,32))+1},std::string(1,tileDisplays[i]),Pixel(168,168,255),{0.5,0.5});
					} else {
						DrawStringDecal({(float)(x*32-fmod(cameraPos.x,32)+31-GetTextSize(tileDisplays).x*0.5f+4*i),(float)(y*32-fmod(cameraPos.y,32))+1},std::string(1,tileDisplays[i]),DARK_GREY,{0.5,0.5});
					}
				}
			}
		}
	}
}

void SeasonI::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 SeasonI::DrawMoneyBox(vf2d pos,vf2d size) {
	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});
}

void SeasonI::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;
				}
			}
		}
	}
}

void SeasonI::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;
		}
	}
}

std::string SeasonI::Wrap(std::string str,int width,bool proportional,vd2d scale) {
	std::string newStr;
	while (true) {
		std::string word;
		if (str.find(" ")==std::string::npos) {
			word=str;
		} else {
			word = str.substr(0,str.find(" "));
		}
		vi2d newSize = vd2d(proportional?GetTextSizeProp(newStr+(newStr.size()>0?" ":"")+word):GetTextSize(newStr+(newStr.size()>0?" ":"")+word))*scale;
		if (newSize.x>width) {
			newStr+="\n"+word;
		} else {
			newStr+=(newStr.size()>0?" ":"")+word;
		}
		if (str.find(" ")==std::string::npos) {
			break;
		} else {
			str.erase(0,str.find(" ")+1);
		}
	}
	return newStr;
}

void SeasonI::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});
		}
	}
}

vf2d SeasonI::AutoScaleText(std::string str,int targetWidth,vf2d scale,bool prop) {
	vf2d size = ((prop)?GetTextSizeProp(str):GetTextSize(str))*scale;
	return {std::min(scale.x,targetWidth/size.x),scale.y};
}

std::string SeasonI::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 SeasonI::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});
		}
	}
}

bool SeasonI::MoveCameraTowardsPoint(vd2d targetPos,PriorityDirection dir,double spd,bool secondRun) {
	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 SeasonI::MoveObjectTowardsPoint(Object*obj,vd2d targetPos,PriorityDirection dir,double moveSpd,bool secondRun) {
	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;
}

int SeasonI::CalculateHealing(Entity*user) {
	return CalculateDamage(user,nullptr,false);
}

int SeasonI::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;
}

int SeasonI::CalculateDamage(Entity*attacker,Entity*defender,bool includeDefenses) {
	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;
}

bool SeasonI::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;
}

bool SeasonI::MessageBoxAllowedToAdvance() {
	return messageBoxMarker<messageBoxFinalText.length()&&!waitingForChoice;
}

void SeasonI::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);
	}
}

bool SeasonI::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');
}

void SeasonI::drawBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p, olc::Pixel p2, olc::Pixel p3) {
	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);
}

std::string SeasonI::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;
	}
}

void SeasonI::OnTextEntryComplete(const std::string&text){
	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 SeasonI::GetAnyKeyPress(olc::Key keypress){
	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()&&!BackPressed()) {
			ACTIONKEYPRESSED=true;
		}
	}
}

bool SeasonI::Collision(vd2d pos) {
	SetDrawTarget(layer::COLLISION);
	Pixel collisionData = GAME->GetDrawTarget()->GetPixel((int)pos.x,(int)pos.y);
	return collisionData!=MAGENTA;
}

void SeasonI::DrawInventory() {
	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});
	}
}

void SeasonI::ChoiceMade(int choice) {
	switch (GAME_STATE) {
		case GameState::SHOPKEEPER_CONFIRM_SELL_MENU:{
			if (!choice) {
				Item*item=PARTY_INVENTORY[ITEM_SELECTION_CURSOR];
				MONEY+=item->stats.sellPrice;
				PARTY_MEMBER_STATS[PARTY_MEMBER_ID[0]]->RemoveItem(ITEM_SELECTION_CURSOR);
				if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()) {
					ITEM_SELECTION_CURSOR--;
				}
			} else {
				Item*item=PARTY_INVENTORY[ITEM_SELECTION_CURSOR];
			}
			GAME_STATE=GameState::SHOPKEEPER_SELL_MENU;
		}break;
	}
}

void SeasonI::StartCutscene(Cutscene*cutscene) {
	CurrentCutscene=cutscene;
}

void SeasonI::SetupCutscenes(){
	CUTSCENES={
		{CutsceneName::TEST_CUTSCENE,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),})},
		{CutsceneName::TRANSFER_MAP_CUTSCENE,new MapTransitionCutscene()},
		{CutsceneName::LOAD_FILE_CUTSCENE,new LoadFileCutscene()},
		{CutsceneName::INTRO_CUTSCENE,new Cutscene({
			액션 Fade(),
			액션 SetFlag(Flag::IS_NIGHTTIME,true),
			액션 PanCamera({64,512},BOTH,999),
			액션 FadeAsync(true),
			액션 PanCamera({64+128,512-128},BOTH,0.5),
			액션 Fade(),
			액션 SetCutsceneDisplayText("Eagleland...",60*5),
			액션 PanCamera({360,256},BOTH,999),
			액션 FadeAsync(true),
			액션 PanCamera({360-128,256-128},BOTH,0.5),
			액션 Fade(),
			액션 SetCutsceneDisplayText("A faraway region",60*5),
			액션 MovePlayerObjects({128,128}),
			액션 PanCamera({128,128},BOTH,999),
			액션 SetFlag(Flag::IS_NIGHTTIME,false),
			액션 Fade(true),
		})},
	};
}

void SeasonI::DrawTriggers(){
	for (auto&trigger:CURRENT_MAP->triggers) {
		FillRectDecal(trigger->GetPos()-cameraPos,trigger->GetSize(),Pixel(255,0,0,64));
		DrawRectDecal(trigger->GetPos()-cameraPos,trigger->GetSize(),YELLOW);
		vi2d textOffset={2,2};
		std::string triggerText=TRIGGERS[(TriggerName::Trigger)trigger->GetID()];
		if ((TriggerName::Trigger)trigger->GetID()==TriggerName::GOTO_MAP) {
			triggerText="GOTO "+trigger->GetMapPtr()->mapname+"\n"+std::to_string(trigger->GetAdditionalCoordData().x)+"\n"+std::to_string(trigger->GetAdditionalCoordData().y);
		}
		DrawStringDecal(trigger->GetPos()-cameraPos+textOffset,triggerText,WHITE,{28.f/GetTextSize(triggerText).x,1.f});
	}
}

void SeasonI::SetupMapList(){
	int MAP_ENUM_COUNT=0;
	MAPS={
		{(MapName::Map)MAP_ENUM_COUNT++,new Map("map0",SPRITES["terrainmap.png"],"Onett",(MapName::Map)(MAP_ENUM_COUNT-1))},
		{(MapName::Map)MAP_ENUM_COUNT++,new Map("newmap",SPRITES["terrainmap.png"],"Twoson",(MapName::Map)(MAP_ENUM_COUNT-1))},
	};
}

void SeasonI::SaveGameSaveData(int saveSlot) {
	std::ofstream file("save"+std::to_string(saveSlot));
	for (int i=PLAYER;i<7;i++) {
		file<<*(PARTY_MEMBER_STATS[i]);
	}
	file<<PARTY_INVENTORY.size()<<" ";
	for (int i=0;i<PARTY_INVENTORY.size();i++) {
		file<<(int)PARTY_INVENTORY[i]->id<<" ";
	}
	file<<GAME_FLAGS.size()<<" ";
	for (int i=0;i<GAME_FLAGS.size();i++) {
		file<<GAME_FLAGS[i]<<" ";
	}
	file<<CURRENT_MAP->myID<<" ";
	file<<MONEY<<" ";
	file<<frameCount<<" ";
	file<<PARTY_MEMBER_NAMES[0]<<" ";
	file<<CHAPTER_NUMBER<<" ";
	file.close();
}

int SeasonI::ReadIntFromStream(std::ifstream&f) {
	int temp;
	f>>temp;
	printf("READ %d\n",temp);
	return temp;
};
float SeasonI::ReadFloatFromStream(std::ifstream&f) {
	float temp;
	f>>temp;
	printf("READ %f\n",temp);
	return temp;
};
double SeasonI::ReadDoubleFromStream(std::ifstream&f) {
	double temp;
	f>>temp;
	printf("READ %lf\n",temp);
	return temp;
};
std::string SeasonI::ReadStringFromStream(std::ifstream&f) {
	std::string temp;
	f>>temp;
	printf("READ %s\n",temp.c_str());
	return temp;
};

void SeasonI::LoadGameSaveData(int saveSlot) {
	std::ifstream file("save"+std::to_string(saveSlot));
	std::array<vd2d,4> positions={vd2d{0,0}};
	int playerCount=0;
	for (int i=PLAYER;i<7;i++) {
		PARTY_MEMBER_STATS[i]->_SetDirectHP(ReadIntFromStream(file));
		PARTY_MEMBER_STATS[i]->stats.maxHP=ReadIntFromStream(file);
		std::string memberName=ReadStringFromStream(file);
		if (PARTY_MEMBER_STATS[i]->obj!=nullptr) {
			PARTY_MEMBER_STATS[i]->obj->name=memberName;
		}
		PARTY_MEMBER_STATS[i]->_SetDirectPP(ReadIntFromStream(file));
		PARTY_MEMBER_STATS[i]->stats.maxPP=ReadIntFromStream(file);
		PARTY_MEMBER_STATS[i]->stats.baseAtk=ReadIntFromStream(file);
		PARTY_MEMBER_STATS[i]->stats.speed=ReadIntFromStream(file);
		int resistanceSize = ReadIntFromStream(file);
		for (int j=0;j<resistanceSize;j++) {
			PARTY_MEMBER_STATS[i]->stats.resistances[j]=ReadIntFromStream(file);
		}
		PARTY_MEMBER_STATS[i]->stats.damageReduction=ReadIntFromStream(file);
		PARTY_MEMBER_STATS[i]->stats.smart=ReadIntFromStream(file)?true:false;
		PARTY_MEMBER_STATS[i]->stats.dumb=ReadIntFromStream(file)?true:false;
		int movesetSize=ReadIntFromStream(file);
		PARTY_MEMBER_STATS[i]->moveSet.clear();
		for (int j=0;j<movesetSize;j++) {
			PARTY_MEMBER_STATS[i]->moveSet.push_back(MOVELIST[(BattleMoveName)ReadIntFromStream(file)]);
		}
		int statusEffectsSize=ReadIntFromStream(file);
		PARTY_MEMBER_STATS[i]->statusEffects.clear();
		for (int j=0;j<statusEffectsSize;j++) {
			PARTY_MEMBER_STATS[i]->statusEffects[(Property)ReadIntFromStream(file)]=ReadIntFromStream(file);
		}
		int equipmentSize=ReadIntFromStream(file);
		for (int j=0;j<equipmentSize;j++) {
			int equipID=ReadIntFromStream(file);
			if (equipID!=-1) {
				PARTY_MEMBER_STATS[i]->equipment[j]=ITEMLIST[(ItemName)equipID];
			}
		}
		double xPos=ReadDoubleFromStream(file);
		double yPos=ReadDoubleFromStream(file);
		if (PARTY_MEMBER_STATS[i]->obj!=nullptr) {
			positions[playerCount++]={xPos,yPos};
		}
	}
	int inventorySize=ReadIntFromStream(file);
	PARTY_INVENTORY.clear();
	for (int i=0;i<inventorySize;i++) {
		PARTY_INVENTORY.push_back(ITEMLIST[(ItemName)ReadIntFromStream(file)]);
	}
	int gameFlagSize=ReadIntFromStream(file);
	for (int i=0;i<gameFlagSize;i++) {
		GAME_FLAGS[i]=ReadIntFromStream(file)?true:false;
	}
	playerCount=0;
	for (int f=(int)Flag::HAS_MAIN;f<(int)Flag::HAS_POO;f++) {
		if (GetGameFlag((Flag)f)) {
			playerCount++;
		}
	}
	CURRENT_MAP=MAPS[(MapName::Map)ReadIntFromStream(file)];
	MONEY=ReadIntFromStream(file);
	LoadMap(CURRENT_MAP);
	printf("Player count: %d\n",playerCount);
	for (int i=0;i<playerCount;i++) {
		PARTY_MEMBER_OBJ[i]->SetPos(positions[i]);
	}
	frameCount=ReadIntFromStream(file);
	ReadStringFromStream(file);
	CHAPTER_NUMBER=ReadIntFromStream(file);
}

void SeasonI::CenterCameraOnPlayer(){
	const vi2d cameraOffset={WIDTH/2,HEIGHT/2};
	cameraPos=PARTY_MEMBER_OBJ[0]->GetPos()+PARTY_MEMBER_OBJ[0]->originPoint/2-cameraOffset;
}

int SeasonI::GetPointQuadrantRelativeToLine(vi2d x1y1,vi2d x2y2,vi2d point){
	return (x2y2.y - x1y1.y) * point.x + (x1y1.x - x2y2.x) * point.y + (x2y2.x * x1y1.y - x1y1.x * x2y2.y);
}

TILE SeasonI::GetSafeTileData(std::vector<std::vector<TILE*>>&data){
	int tileY=(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().y/32;
	int tileX=(int)PARTY_MEMBER_OBJ[0]->GetPosWithOrigin().x/32;
	return tileX>=0&&tileY>=0&&tileX<data[0].size()&&tileY<data.size()?*data[tileY][tileX]:TILE(0,0,0);
}

char SeasonI::GetTileDegreeSafely(std::vector<std::vector<TILE*>>&data){
	return GetSafeTileData(data).tileDegree;
}

#ifndef TEST_SUITE
int main()
{
	SeasonI demo;
	if (demo.Construct(WIDTH, HEIGHT, 4, 4))
		demo.Start();

	return 0;
}
#endif