#define OLC_PGE_APPLICATION
#include "pixelGameEngine.h"
#include "data.h"
#define OLC_PGEX_SPLASHSCREEN
#include "splash.h"
#include <queue>
#define OLC_SOUNDWAVE
#include "soundwaveEngine.h"

using namespace olc;

//#define TEST_MAP1 //Toggle to just play around on map 1.
//#define TEST_MAP2 //Toggle on to just play around on map 2.

#define SKIP_INTRO true
#define SKIP_CHAPTER1 true
#define SKIP_CHAPTER2 false
#define SKIP_CHAPTER3 false

#define STARTING_MAP MAP_1
#define STARTING_STATE CUTSCENE_3
#define MOVE_SPD 0.075
#define PLAYER_X 14
#define PLAYER_Y 4

#ifdef TEST_MAP1
	#define STARTING_MAP "assets/maps/map1"
	#define STARTING_STATE GAMEWORLD
	#define MOVE_SPD 0.1
	#define PLAYER_X 40
	#define PLAYER_Y 31
#endif
#ifdef TEST_MAP2
	#define STARTING_MAP "assets/maps/map2"
	#define STARTING_STATE GAMEWORLD
	#define MOVE_SPD 0.1
	#define PLAYER_X 16
	#define PLAYER_Y 5
#endif

enum GAMESTATE{
	CUTSCENE_1,
	CUTSCENE_2,
	CUTSCENE_3,
	GAMEWORLD,
	WAITING_FOR_CUTSCENE_3,
	GAME_OVER,
	COLLECTED_SILICON,
	CUTSCENE_4, //First rover repaired.
	CUTSCENE_4_DONE,
	LATER_THAT_NIGHTFADEIN,
	LATER_THAT_NIGHTWAIT,
	LATER_THAT_NIGHTFADEOUT,
};

namespace cutscene{
	enum CUTSCENE{
		NONE,
		PAN_DOME,
		PAUSE_TO_CUTSCENE_3,
		CUTSCENE_4,
		TRANSITION_CUTSCENE, //Exit the dome.
		TRANSITION_CUTSCENE_2, //Enter the dome.
		NODE_COLLECT_CUTSCENE,
		PAN_OVER_TO_CROPS,
		RAINING_IN_DOME,
		AFTER_RAIN,
		WALK_TO_COMPUTER,
		INPUT_USERNAME,
		GO_OUTSIDE,
		WALK_TO_ROVER,
		DISPLAY_VOLCANIC_AREA,
		END_VOLCANIC_AREA_CUTSCENE,
		REPAIR_ROVER_1,
		GET_SOME_REST,
		IN_BED,
		SHAKE,
		INVESTIGATE_X_X,
	};
}

namespace battle{
	enum BATTLESTATE{
		NONE,
		WAITING_FOR_CAMERA,
		PLAYER_SELECTION,
		PLAYER_TARGET_SELECTION,
		ENEMY_SELECTION,
		MOVE_RESOLUTION,
		PERFORM_TURN,
		WAIT_TURN_ANIMATION,
		WAIT_TURN_ANIMATION2,
		DAMAGE_RESOLUTION,
	};
}

namespace gameflag{
	enum FLAG{
		TUTORIAL_WALKED_OFF_FARM,
		VISIT_BROKEN_ROVER,
		COLLECTED_SILICON_1,
		REPAIRED_ROVER_1,
		REST_IN_DOME,
		SLEEP,
		FIRST_ENCOUNTER_X_X,
		ANALYSIS_X_X,
		TUTORIAL1_X_X,
		TUTORIAL2_X_X,
	};
}

enum MOVEMENT_PRIORITY{
	HORZ_FIRST,
	VERT_FIRST,
	BOTH
};

class Seed{
	public:
		vf2d pos;
		Seed(vf2d pos) {
			this->pos=pos;
		}
};

namespace reasoncode{
	enum Code{
		SEED_GROWTH,
		TREE_BURN
	};
}

#define MAX_TERMINAL_NAME_LENGTH 6
#define WIDTH 256
#define HEIGHT 224
#define ALPHA_SCREEN1 128
#define ALPHA_SCREEN2 20
#define FADE_SPD 6
#define MESSAGE_SCROLL_WAIT_SPD 1 //Number of frames to wait.
#define BATTLE_CAMERA_SCROLL_SPD 0.05 //How fast to scroll over to the battle.

class DisplayNumber{
	public:
		int number; //Negative means healing.
		int frame; //Frame it was created.
		float x,y;
		int alpha=255;
		DisplayNumber(int numb,float x,float y,int frameCount) {
			this->number=numb;
			this->x=x;
			this->y=y;
			this->frame=frameCount;
		}
};

class Animation{
	public:
		Decal*spr;
		std::vector<vi2d> frames;
		int frame=0;
		bool flipped=false;
		int skip_frames=1; //Essentially the animation speed. Number of frames to wait for next frame.
		int width=32;
		int height=32;

		vi2d getCurrentFrame() {
			return frames[frame];
		}
};

std::vector<Animation*> updateAnimationsList; //Used to store animations in the game that we need to keep track of and update. Probably don't touch this.

class ObjectLoadInfo{
	public:
		Decal*spr;
		bool hasanim=false;
		Animation*anim;
		vi2d spos;
		vi2d size;
		Pixel col;
		bool hascut=false;
		ObjectLoadInfo(Decal*spr,Pixel col=WHITE) {
			this->spr=spr;
			this->col=col;
		}
		ObjectLoadInfo(Decal*spr,Animation*anim,Pixel col=WHITE) {
			this->spr=spr;
			this->anim=anim;
			this->hasanim=true;
			bool matches=false;
			for (int i=0;i<updateAnimationsList.size();i++) {
				if (updateAnimationsList[i]==anim) {
					matches=true;
					break;
				}
			}
			if (!matches) {
				updateAnimationsList.push_back(anim);
			}
			this->col=col;
		}
		ObjectLoadInfo(Decal*spr,vi2d spos,vi2d size,Pixel col=WHITE) {
			this->spr=spr;
			this->hascut=true;
			this->spos=spos;
			this->size=size;
			this->col=col;
		}
};

class Object{
	public:
		float x,y;
		Decal*spr;
		std::string name;
		bool hasAnim=false;
		Animation*anim;
		vi2d spos;
		vi2d size;
		bool flipped=false;
		bool hascut=false;
		bool tempObj=false;
		Pixel col;
		Object(){};
		Object(Decal*spr,Pixel col=WHITE) {
			this->spr=spr;
			this->col=col;
		}
		Object(Decal*spr,Animation*anim,Pixel col=WHITE) {
			this->spr=spr;
			this->anim=anim;
			this->hasAnim=true;
			bool matches=false;
			for (int i=0;i<updateAnimationsList.size();i++) {
				if (updateAnimationsList[i]==anim) {
					matches=true;
					break;
				}
			}
			if (!matches) {
				updateAnimationsList.push_back(anim);
			}
			this->col=col;
		}
		Object(Decal*spr,vi2d spos,vi2d size,Pixel col=WHITE) {
			this->spr=spr;
			this->hascut=true;
			this->spos=spos;
			this->size=size;
			this->col=col;
		}
};

class Map{
	public:
		std::string filename;
		Map(std::string filepath) {
			this->filename=filepath;
		}
};

class ParticleEffect{
	public:
		vf2d effectPos;
		vf2d effectSize;
		vf2d pos_low;
		vf2d pos_high;
		vf2d size_low;
		vf2d size_high;
		vf2d spd_low;
		vf2d spd_high;
		olc::Pixel col_low;
		olc::Pixel col_high;
		int amt;
		olc::Pixel foregroundColor;
		ParticleEffect(vf2d effectPos,vf2d effectSize,vf2d pos_low,vf2d pos_high,vf2d size_low,vf2d size_high,vf2d spd_low,vf2d spd_high,olc::Pixel col_low,olc::Pixel col_high,int amt,olc::Pixel foregroundColor) {
			this->effectPos=effectPos;
			this->effectSize=effectSize;
			this->pos_low=pos_low;
			this->pos_high=pos_high;
			this->size_low=size_high;
			this->spd_low=spd_low;
			this->spd_high=spd_high;
			this->col_low=col_low;
			this->col_high=col_high;
			this->amt=amt;
			this->foregroundColor=foregroundColor;
		}
};

class WEATHER_POWER{
	public:
		std::string description;
		std::string name;
		Animation*anim;
		Animation*effectAnim;
		int damage;
		int damageRoll;
		int range;
		int playerOwnCount=0;
		Pixel bgcol;
		Pixel textcol;
		int effectTime=0;
		ParticleEffect*effect;
		int seedProduction=0; //Number of seeds to add to field.
		float seedScatter=1; //Multiplier of current seeds on field.
		bool growSeeds=false; //If set to true, will trigger a growth of all seeds.
		bool burnTrees=false; //If set to true, will trigger a burning of trees.
		float treeBurnChance=1; //% chance of trees getting burned by this attack.
		WEATHER_POWER(std::string name,std::string desc,Animation*icon,Animation*effect,int dmg,int dmgRoll,int range,Pixel bgcol,Pixel textcol,int effectTime,ParticleEffect*parteff) {
			this->description=desc;
			this->name=name;
			this->anim=icon;
			this->effectAnim=effect;
			this->damage=dmg;
			this->damageRoll=dmgRoll;
			this->range=range;
			this->bgcol=bgcol;
			this->textcol=textcol;
			this->effectTime=effectTime;
			this->effect=parteff;
		}
};

class Entity{
	public:
		bool ally=false;
		int hp;
		int maxhp;
		Decal*spr;
		float x;
		float y;
		std::string name;
		WEATHER_POWER*selectedMove;
		std::vector<WEATHER_POWER*> moveSet;
		bool turnComplete=false;
		bool slowed=false;
		int damageFrame=0;
		int fixedTurnOrderInd=0;
		bool fixedTurnOrder=false; //If this is turned on, the selected move will increment in order of the move set (and loop accordingly.)
		vf2d sprScale;
		Entity(Decal*spr,std::string name,float x,float y,int hp,int maxhp,std::vector<WEATHER_POWER*>moveset,vf2d sprScale={1,1},bool fixedMoveset=false) {
			this->spr=spr;
			this->name=name;
			this->x=x;
			this->y=y;
			this->maxhp=hp;
			this->hp=hp;
			this->maxhp=maxhp;
			this->moveSet=moveset;
			this->fixedTurnOrder=fixedMoveset;
			this->sprScale=sprScale;
		}
};

class Encounter{
	public:
		int x,y;
		float playerX,playerY;
		std::vector<Entity*> entities;
		std::vector<int> turnOrder;
		Map*map;
};

class Zone{
	public:
		vi2d pos; //In tile coordinates.
		vi2d size; //In tile coordinates.
		ParticleEffect*eff;
		Zone(vi2d pos,vi2d size,vf2d effectPos,vf2d effectSize,vf2d pos_low,vf2d pos_high,vf2d size_low,vf2d size_high,vf2d spd_low,vf2d spd_high,olc::Pixel col_low,olc::Pixel col_high,int amt,olc::Pixel foregroundColor) {
			this->pos=pos;
			this->size=size;
			this->eff=new ParticleEffect(effectPos,effectSize,pos_low,pos_high,size_low,size_high,spd_low,spd_high,col_low,col_high,amt,foregroundColor);
		}
};

namespace effect {
	class Pixel{
		public:
			vf2d pos, size, spd;
			int r,g,b,a;
			int o_r,o_g,o_b,o_a;
			Pixel() {
				pos={0,0};
				size={0,0};
				spd={0,0};
			};
			Pixel(vf2d pos,vf2d size,vf2d spd,olc::Pixel col) {
				this->pos=pos;
				this->size=size;
				this->spd=spd;
				this->r=this->o_r=col.r;
				this->g=this->o_g=col.g;
				this->b=this->o_b=col.b;
				this->a=this->o_a=col.a;
			}
	};
};

class SeasonsOfLoneliness : public PixelGameEngine
{
public:
	SeasonsOfLoneliness()
	{
		sAppName = "Seasons of Loneliness";
	}


public:
	sound::WaveEngine engine;
	GAMESTATE GAME_STATE=STARTING_STATE;
	int textInd=0;
	int cursorX=0;
	int transitionTime=0;
	int TIMER=0;
	bool fade=false;
	int transparency=0;
	int frameCount=0;
	float elapsedTime=0;
	const float TARGET_RATE = 1/60.0;
	std::string MAP_NAME = "";
	std::string CUTSCENE_CONSOLE_TEXT = "";
	bool GAME_FLAGS[128]={};
	int**MAP=NULL;
	int MAP_WIDTH=-1;
	int MAP_HEIGHT=-1;
	Decal*TILES;
	float PLAYER_COORDS[2] = {PLAYER_X,PLAYER_Y};
	std::vector<Object*> OBJECTS;
	bool CUTSCENE_ACTIVE=false;
	cutscene::CUTSCENE CURRENT_CUTSCENE=cutscene::NONE;
	int CUTSCENE_TIMER=0;
	bool CUTSCENE_FLAGS[8];
	Object*CUTSCENE_OBJS[8];
	int CUTSCENE_OBJ_INDICES[8];
	bool messageBoxVisible=false;
	int messageBoxCursor;
	std::string messageBoxSpeaker;
	std::string messageBoxText;
	std::string messageBoxRefText;
	bool firstNewline=false;
	bool secondNewline=false;
	bool foodMeterVisible=false;
	int foodCount=3;
	bool oxygenMeterVisible=false;
	int oxygenQualityLevel=34;
	int plantState=0b01001010010100010101010010010101;
	SplashScreen splash;
	Animation*current_playerAnim=new Animation();
	Animation*playerAnim=new Animation();
	Animation*playerAnimRight=new Animation();
	Animation*playerAnimLeft=new Animation();
	Animation*playerAnimDown=new Animation();
	Animation*playerAnimWalkUp=new Animation();
	Animation*playerAnimWalkDown=new Animation();
	Animation*playerAnimWalkRight=new Animation();
	Animation*playerAnimWalkLeft=new Animation();
	Animation*playerAnimPlantUp=new Animation();
	Animation*playerAnimPlantDown=new Animation();
	Animation*playerAnimPlantRight=new Animation();
	Animation*playerAnimPlantLeft=new Animation();
	Animation*POWER_HAILSTORM_ANIMATION=new Animation();
	Animation*POWER_HURRICANE_ANIMATION=new Animation();
	Animation*POWER_METEOR_SHOWER_ANIMATION=new Animation();
	Animation*POWER_METEOR_STORM_ANIMATION=new Animation();
	Animation*POWER_SNOWSTORM_ANIMATION=new Animation();
	Animation*CONSUME_SNACK_ANIMATION=new Animation();
	Animation*CONSUME_MEAL_ANIMATION=new Animation();
	Animation*NADO_ANIMATION=new Animation();
	Animation*PETAL_STORM_ANIMATION=new Animation();
	Animation*SLEEP_ANIMATION=new Animation();
	Animation*EMPTY_BED_ANIMATION=new Animation();
	Animation*POWER_FLASHFLOOD_ANIMATION=new Animation();
	Animation*POWER_SUNNYDAY_ANIMATION=new Animation();
	ParticleEffect*HAILSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{4,4},{-2,0.5},{-0.5,2},Pixel(143, 242, 255,255),Pixel(255,255,255,255),300,Pixel(220, 226, 227,0));
	ParticleEffect*HURRICANE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-4,1},{-1,4},Pixel(225, 248, 252,64),Pixel(255,255,255,128),300,Pixel(220, 226, 227,0));
	ParticleEffect*METEOR_RAIN_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{3,3},{6,6},{-1,0.2},{-0.2,1},Pixel(46, 31, 31,255),Pixel(43, 31, 46,255),50,Pixel(30, 10, 36,0));
	ParticleEffect*METEOR_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{3,3},{10,10},{-2,0.1},{-0.1,2},Pixel(46, 31, 31,255),Pixel(181, 72, 46,255),75,Pixel(30, 10, 36,48));
	ParticleEffect*SNOWSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-1,0.5},{1,2},Pixel(193, 198, 201,200),Pixel(255,255,255,255),400,Pixel(220, 226, 227,0));
	ParticleEffect*SANDSTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-20,1},{20,3},Pixel(133, 98, 66,130),Pixel(158, 93, 33,210),300,Pixel(87, 78, 69,0));
	ParticleEffect*SEED_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-0.5,-1},{0.5,-0.2},Pixel(65, 98, 66,130),Pixel(65, 117, 60,210),100,Pixel(70, 158, 62,0));
	ParticleEffect*AVALANCHE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{8,8},{-4,2},{4,4},Pixel(143, 242, 255,255),Pixel(255,255,255,255),300,Pixel(220, 226, 227,0));
	ParticleEffect*CONSUME_SNACK_EFF = new ParticleEffect({0,0},{64,64},{64,64},{64,64},{1,1},{2,2},{-0.1,-0.5},{0.1,-0.05},Pixel(255,255,255,130),Pixel(255,255,255,210),30,Pixel(147, 161, 90,0)); //Used for CONSUME_MEAL too.
	ParticleEffect*PETAL_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-4,0.6},{4,2},Pixel(127, 27, 130,130),Pixel(227, 218, 227,240),160,Pixel(147, 161, 90,0));
	ParticleEffect*LIGHT_STORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,HEIGHT/2},{2,HEIGHT},{0,4},{0,25},Pixel(214, 233, 255,130),Pixel(255, 255, 255,255),30,Pixel(0, 0, 0,32));
	ParticleEffect*SEED_BULLET_EFF = new ParticleEffect({0,0},{64,64},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-5,-5},{5,5},Pixel(138, 255, 153,200),Pixel(193, 245, 200,210),40,Pixel(70, 158, 62,0));
	ParticleEffect*SEED_PELLET_EFF = new ParticleEffect({0,0},{64,64},{0,0},{WIDTH,HEIGHT},{1,1},{1,1},{-3,-3},{3,3},Pixel(138, 255, 153,200),Pixel(193, 245, 200,210),10,Pixel(70, 158, 62,0));
	ParticleEffect*SUMMON_MINION_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{4,4},{12,12},{0,-6},{0,-20},Pixel(223, 242, 0,130),Pixel(223, 255, 114,210),50,Pixel(70, 158, 62,0));
	ParticleEffect*SEED_OF_LIFE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{2,2},{2,2},{-1,-2},{1,-0.2},Pixel(65, 98, 66,210),Pixel(65, 117, 60,255),140,Pixel(70, 158, 62,0));
	ParticleEffect*FIRESTORM_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{4,4},{12,12},{-12,-8},{12,-4},Pixel(209, 90, 69,130),Pixel(209, 141, 69,255),140,Pixel(255, 0, 0,32));
	ParticleEffect*ACID_RAIN_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-4,1},{-1,4},Pixel(117, 125, 57,128),Pixel(224, 245, 66,210),300,Pixel(220, 226, 227,0));
	ParticleEffect*DROUGHT_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-1,-4},{1,-0.5},Pixel(217, 79, 33,128),Pixel(217, 162, 33,210),70,Pixel(217, 204, 173,64));
	ParticleEffect*HEAT_WAVE_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{4,4},{12,12},{-8,4},{-4,8},Pixel(209, 90, 69,130),Pixel(209, 141, 69,255),80,Pixel(255, 0, 0,0));
	ParticleEffect*TORNADO_EFF = new ParticleEffect({0,0},{64,64},{0,0},{64,64},{1,2},{3,20},{-14,2},{14,12},Pixel(168, 155, 146,196),Pixel(196, 194, 192,220),45,Pixel(255, 0, 0,0));
	ParticleEffect*GUST_EFF = new ParticleEffect({0,0},{64,64},{0,0},{64,64},{1,2},{3,20},{-6,1},{6,6},Pixel(168, 155, 146,196),Pixel(196, 194, 192,220),20,Pixel(255, 0, 0,0));
	ParticleEffect*FLASH_FLOOD_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{2,2},{-4,1},{-1,4},Pixel(8, 54, 204,64),Pixel(255,255,255,128),500,Pixel(220, 226, 227,0));
	ParticleEffect*SUNNYDAY_EFF = new ParticleEffect({0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{4,4},{0,-2},{0,-6},Pixel(209, 207, 113,130),Pixel(255, 255, 255,210),50,Pixel(70, 158, 62,0));
	WEATHER_POWER*HAILSTORM = new WEATHER_POWER("Hailstorm","Causes a flurry of hard cold rocks to be unleashed in target area. 60+1d30",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,60,30,160,Pixel(72, 160, 212,255),Pixel(93, 161, 163,255),120,HAILSTORM_EFF);
	WEATHER_POWER*HURRICANE = new WEATHER_POWER("Hurricane","Causes heavy winds, scattering seeds, heavy rain. 20+1d10",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,20,10,200,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,HURRICANE_EFF);
	WEATHER_POWER*METEOR_RAIN = new WEATHER_POWER("Meteor Rain","Causes fiery space rocks to fall on target area. 50+1d50",POWER_METEOR_SHOWER_ANIMATION,POWER_METEOR_SHOWER_ANIMATION,50,50,96,Pixel(96, 86, 153,255),Pixel(170, 103, 201,255),120,METEOR_STORM_EFF);
	WEATHER_POWER*METEOR_STORM = new WEATHER_POWER("Meteor Storm","Larger burning space rocks. 120+60d",POWER_METEOR_STORM_ANIMATION,POWER_METEOR_STORM_ANIMATION,120,60,140,Pixel(89, 4, 33,255),Pixel(130, 56, 1,255),120,METEOR_RAIN_EFF);
	WEATHER_POWER*SNOWSTORM = new WEATHER_POWER("Snowstorm","Slows down targets and causes rapid temperature drops. 15+1d10",POWER_SNOWSTORM_ANIMATION,POWER_SNOWSTORM_ANIMATION,15,10,140,Pixel(183, 196, 194,255),Pixel(222, 255, 254,255),120,SNOWSTORM_EFF);
	WEATHER_POWER*SANDSTORM = new WEATHER_POWER("Sandstorm","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,5,10,64,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,SANDSTORM_EFF);
	WEATHER_POWER*SEED_STORM = new WEATHER_POWER("Seed Storm","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,-10,15,30,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,SEED_STORM_EFF);
	WEATHER_POWER*AVALANCHE = new WEATHER_POWER("Avalanche","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,15,10,200,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,AVALANCHE_EFF);
	WEATHER_POWER*LIGHT_STORM = new WEATHER_POWER("Light Storm","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,50,9,64,Pixel(171, 151, 53,255),Pixel(237, 237, 237,255),120,LIGHT_STORM_EFF);
	WEATHER_POWER*SEED_BULLET = new WEATHER_POWER("Seed Bullet","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,10,15,30,Pixel(57, 92, 63,255),Pixel(95, 232, 119,255),120,SEED_BULLET_EFF);
	WEATHER_POWER*SEED_PELLET = new WEATHER_POWER("Seed Pellet","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,5,10,30,Pixel(57, 92, 63,255),Pixel(95, 232, 119,255),120,SEED_PELLET_EFF);
	WEATHER_POWER*SEED_OF_LIFE = new WEATHER_POWER("Seed of Life","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,-10,15,30,Pixel(93, 161, 163,255),Pixel(72, 160, 212,255),120,SEED_OF_LIFE_EFF);
	WEATHER_POWER*SUMMON_MINIONS = new WEATHER_POWER("Summon Minions","",POWER_HAILSTORM_ANIMATION,POWER_HAILSTORM_ANIMATION,-75,15,255,Pixel(57, 92, 63,255),Pixel(95, 232, 119,255),120,SUMMON_MINION_EFF);
	WEATHER_POWER*CONSUME_SNACK = new WEATHER_POWER("Snack","Restores 33% health for 5 turns. If battle ends before effect ends, food is not consumed.",CONSUME_SNACK_ANIMATION,CONSUME_SNACK_ANIMATION,-1001,1,200,Pixel(147, 173, 66,255),Pixel(255, 188, 3,255),120,CONSUME_SNACK_EFF);
	WEATHER_POWER*CONSUME_MEAL = new WEATHER_POWER("Meal","Restores all health. Increases Maximum Health by 5.",CONSUME_MEAL_ANIMATION,CONSUME_MEAL_ANIMATION,-1002,1,200,Pixel(147, 173, 66,255),Pixel(255, 188, 3,255),120,CONSUME_SNACK_EFF);
	WEATHER_POWER*PETAL_STORM = new WEATHER_POWER("Petal Storm","Places seeds, causes minor healing. 20+1d20",PETAL_STORM_ANIMATION,PETAL_STORM_ANIMATION,20,20,110,Pixel(189, 132, 189,255),Pixel(235, 75, 235,255),120,PETAL_STORM_EFF);
	WEATHER_POWER*ACID_RAIN = new WEATHER_POWER("Acid Rain","",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,20,10,150,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,ACID_RAIN_EFF);
	WEATHER_POWER*DROUGHT = new WEATHER_POWER("Drought","Halves healing effects for the next turn.",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,8,3,150,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,DROUGHT_EFF);
	WEATHER_POWER*HEAT_WAVE = new WEATHER_POWER("Heat Wave","",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,25,10,150,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,HEAT_WAVE_EFF);
	WEATHER_POWER*TORNADO = new WEATHER_POWER("Tornado","",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,30,10,150,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,TORNADO_EFF);
	WEATHER_POWER*GUST = new WEATHER_POWER("Gust","",POWER_HURRICANE_ANIMATION,POWER_HURRICANE_ANIMATION,15,10,150,Pixel(99, 148, 132,255),Pixel(121, 132, 140,255),120,GUST_EFF);
	WEATHER_POWER*FLASH_FLOOD = new WEATHER_POWER("Flash Flood","Causes massive seed growth and heavy damage. 30+1d20",POWER_FLASHFLOOD_ANIMATION,POWER_FLASHFLOOD_ANIMATION,30,20,200,Pixel(27, 41, 87,255),Pixel(138, 161, 237,255),120,FLASH_FLOOD_EFF);
	WEATHER_POWER*SUNNY_DAY = new WEATHER_POWER("Sunny Day","Fertilize soil, multiplying seed growth and causing trees to drop seeds. 10+1d10",POWER_SUNNYDAY_ANIMATION,POWER_SUNNYDAY_ANIMATION,10,10,200,Pixel(27, 41, 87,255),Pixel(138, 161, 237,255),120,SUNNYDAY_EFF);
	bool IN_BATTLE_ENCOUNTER = false;
	int BATTLE_ENTRY_TIMER = 0;
	int EFFECT_TIMER = 0;
	#define WEATHER_POWER_COUNT 8 //Number of powers that are in the game. Update storage array accordingly.
	WEATHER_POWER*WEATHER_POWERS[WEATHER_POWER_COUNT] = {
		HAILSTORM,
		PETAL_STORM,
		HURRICANE,
		METEOR_RAIN,
		METEOR_STORM,
		SNOWSTORM,
		CONSUME_SNACK,
		CONSUME_MEAL};
	battle::BATTLESTATE BATTLE_STATE=battle::NONE;
	std::vector<WEATHER_POWER*> availablePowers;
	WEATHER_POWER*BATTLE_CARD_SELECTION=HAILSTORM;
	int BATTLE_CARD_SELECTION_IND=0;
	int PLAYER_SELECTED_TARGET=-1;
	int PLAYER_MAXHP=60;
	int PLAYER_HP=PLAYER_MAXHP;
	int BATTLE_CURRENT_TURN_ENTITY=-1;
	int CURRENT_ENCOUNTER_IND=-1;
	unsigned int RAND_CALLS=0;
	std::vector<DisplayNumber*> BATTLE_DISPLAY_NUMBERS;
	bool PLAYER_TURN_COMPLETE=false;
	int FOOD_REGEN_TURNS=0;
	WEATHER_POWER* CUTSCENE_DISPLAYED_CARD;
	Pixel FOREGROUND_EFFECT_COLOR;
	Pixel ORIGINAL_FOREGROUND_EFFECT_COLOR;
	int PIXEL_LIMIT=0;
	vf2d PIXEL_POS;
	vf2d PIXEL_SIZE;
	float PIXEL_EFFECT_TRANSPARENCY=0;
	int CUTSCENE_OBJ_COUNT=0;
	int TERMINAL_SELECTED_CHAR=0;
	std::string TERMINAL_INPUT="";
	std::string PLAYER_NAME="...";
	std::vector<Zone*>ZONES;
	std::vector<vi2d>COLLECTED_ITEMS;
	Zone*ACTIVE_ZONE=nullptr;
	std::vector<vi2d>REPAIRED_ROVERS;
	std::string CONSOLE_REF_TEXT;
	bool SOUND_IS_PLAYING=false;
	int MAIN_MENU_SELECTION=0;
	std::string MENU_OPTIONS[4]={"NEW GAME","CONTINUE","MUTE SOUND","EXIT"};
	int BATTLE_REASON_CODE=-1;

	Map*MAP_1=new Map("map1");
	Map*MAP_2=new Map("map2");

	Decal*DOME_DECAL,*FOOD_METER_DECAL,*OXYGEN_METER_DECAL,*PLANT_DECAL,
	*PLAYER_DECAL,
	*WEATHERNODE_EFFECT_DECAL,*POWER_HAILSTORM_DECAL,*POWER_HURRICANE_DECAL,*POWER_METEOR_SHOWER_DECAL,*POWER_METEOR_STORM_DECAL,*POWER_SNOWSTORM_DECAL,
	*SPIDEY_DECAL,*TARGETING_CIRCLE,*TARGETING_RANGE_CIRCLE,*HEALTHBAR_DECAL,
	*CONSUME_SNACK_DECAL,*CONSUME_MEAL_DECAL,*COMPUTER_DECAL,*BROKEN_ROVER_DECAL,
	*NADO_DECAL,*SILICON_ROCK_DECAL,*PETAL_STORM_DECAL,*ROVER_DECAL,*X_X_DECAL,
	*LATER_THAT_NIGHT_DECAL,*SLEEP_DECAL,*SEED_DECAL,*TREE_DECAL,*X_X_UNCHARGED_DECAL,
	*SANDWORM_DECAL,*SNAKE_DECAL,*MOTH_DECAL,*FLASH_FLOOD_DECAL;
	std::map<std::string,ObjectLoadInfo*> BASE_OBJECTS;
	std::vector<Encounter> ENCOUNTERS;
	Encounter ENCOUNTER_SPIDEY_1;
	Encounter ENCOUNTER_X_X;
	Encounter CURRENT_ENCOUNTER;
	std::vector<WEATHER_POWER*>MOVESET_SPIDEY;
	std::vector<WEATHER_POWER*>MOVESET_SANDWORM;
	std::vector<WEATHER_POWER*>MOVESET_SNAKE;
	std::vector<WEATHER_POWER*>MOVESET_MOTH;
	std::vector<WEATHER_POWER*>MOVESET_X_X;
	std::vector<WEATHER_POWER*>MOVESET_XMINION;
	std::vector<Seed*>SEEDS;
	std::vector<Seed*>TREES;
	bool SOUND_IS_MUTED=false;
	bool END_THE_GAME=false;
	bool audioFade=false;
	float audioLevel=0.6;
	int SEED_COUNT=0;
	vf2d BATTLE_PLAYER_COORDS;
	
	Map*CURRENT_MAP=MAP_1;


	sound::Wave SONG_MAIN;

	std::queue<int> turnOrder;

	#define MAX_PIXELS 500
	effect::Pixel*pixels[MAX_PIXELS];

	bool OnUserCreate() override
	{
		SetPixelMode(Pixel::ALPHA);
		ConsoleCaptureStdOut(true);
		engine.InitialiseAudio();

		#define LAYERS 3 //How many layers exist.
		for (int i=1;i<LAYERS;i++) {
			CreateLayer();
			EnableLayer(i,true);
		}

		if (SKIP_INTRO||SKIP_CHAPTER1||SKIP_CHAPTER2||SKIP_CHAPTER3) {
			GAME_FLAGS[gameflag::TUTORIAL_WALKED_OFF_FARM]=true;
			GAME_FLAGS[gameflag::VISIT_BROKEN_ROVER]=true;
			GAME_STATE=GAMEWORLD;
		}
		if (SKIP_CHAPTER1||SKIP_CHAPTER2||SKIP_CHAPTER3) {
			GAME_FLAGS[gameflag::COLLECTED_SILICON_1]=true;
			GAME_FLAGS[gameflag::REPAIRED_ROVER_1]=true;
			GAME_FLAGS[gameflag::REST_IN_DOME]=true;
			GAME_STATE=GAMEWORLD;
		}
		if (SKIP_CHAPTER2||SKIP_CHAPTER3) {

		}
		if (SKIP_CHAPTER3) {

		}


		SONG_MAIN = sound::Wave("./assets/SeasonsOfLoneliness.wav");

		//ConsoleShow(F1,false);
		// Called once at the start, so create things here
		TILES=new Decal(new Sprite("assets/tiles.png"));
		DOME_DECAL=new Decal(new Sprite("assets/dome.png"));
		FOOD_METER_DECAL=new Decal(new Sprite("assets/corn.png"));
		OXYGEN_METER_DECAL=new Decal(new Sprite("assets/co2.png"));
		PLANT_DECAL=new Decal(new Sprite("assets/plant.png"));
		PLAYER_DECAL=new Decal(new Sprite("assets/player.png"));
		WEATHERNODE_EFFECT_DECAL=new Decal(new Sprite("assets/weathernode_effect.png"));
		POWER_HAILSTORM_DECAL=new Decal(new Sprite("assets/hailstorm_icon.png"));
		POWER_HURRICANE_DECAL=new Decal(new Sprite("assets/hurricane_icon.png"));
		POWER_METEOR_SHOWER_DECAL=new Decal(new Sprite("assets/meteor_shower_icon.png"));
		POWER_METEOR_STORM_DECAL=new Decal(new Sprite("assets/meteor_storm.png"));
		POWER_SNOWSTORM_DECAL=new Decal(new Sprite("assets/snowstorm_icon.png"));
		CONSUME_SNACK_DECAL=new Decal(new Sprite("assets/snack.png"));
		CONSUME_MEAL_DECAL=new Decal(new Sprite("assets/meal.png"));
		SPIDEY_DECAL=new Decal(new Sprite("assets/spidey.png"));
		TARGETING_CIRCLE=new Decal(new Sprite("assets/targetCircle.png"));
		TARGETING_RANGE_CIRCLE=new Decal(new Sprite("assets/targetRange.png"));
		HEALTHBAR_DECAL=new Decal(new Sprite("assets/healthbar.png"));
		COMPUTER_DECAL=new Decal(new Sprite("assets/computerSystem.png"));
		BROKEN_ROVER_DECAL=new Decal(new Sprite("assets/brokenROVER.png"));
		NADO_DECAL=new Decal(new Sprite("assets/nado.png"));
		SILICON_ROCK_DECAL=new Decal(new Sprite("assets/siliconPiece.png"));
		PETAL_STORM_DECAL=new Decal(new Sprite("assets/petalstorm_icon.png"));
		ROVER_DECAL=new Decal(new Sprite("assets/ROVER.png"));
		X_X_DECAL=new Decal(new Sprite("assets/X.X.png"));
		X_X_UNCHARGED_DECAL=new Decal(new Sprite("assets/X.X_uncharged.png"));
		LATER_THAT_NIGHT_DECAL=new Decal(new Sprite("assets/LaterThatNight.png"));
		SLEEP_DECAL=new Decal(new Sprite("assets/sleep.png"));
		SEED_DECAL=new Decal(new Sprite("assets/seed.png"));
		TREE_DECAL=new Decal(new Sprite("assets/tree.png"));
		SANDWORM_DECAL=new Decal(new Sprite("assets/sandworm.png"));
		MOTH_DECAL=new Decal(new Sprite("assets/moth.png"));
		SNAKE_DECAL=new Decal(new Sprite("assets/snake.png"));
		FLASH_FLOOD_DECAL=new Decal(new Sprite("assets/flashflood_icon.png"));
		SUNNY_DAY_DECAL=new Decal(new Sprite("assets/sunny_day.png"));

		current_playerAnim->spr=PLAYER_DECAL;
		playerAnim->spr=PLAYER_DECAL;
		playerAnimRight->spr=PLAYER_DECAL;
		playerAnimLeft->spr=PLAYER_DECAL;
		playerAnimLeft->flipped=true;
		playerAnimDown->spr=PLAYER_DECAL;
		playerAnimWalkUp->spr=PLAYER_DECAL;
		playerAnimWalkDown->spr=PLAYER_DECAL;
		playerAnimWalkRight->spr=PLAYER_DECAL;
		playerAnimWalkLeft->spr=PLAYER_DECAL;
		playerAnimWalkLeft->flipped=true;
		playerAnimPlantUp->spr=PLAYER_DECAL;
		playerAnimPlantDown->spr=PLAYER_DECAL;
		playerAnimPlantRight->spr=PLAYER_DECAL;
		playerAnimPlantLeft->spr=PLAYER_DECAL;
		playerAnimPlantLeft->flipped=true;
		playerAnim->frames.push_back({64,0});
		playerAnimRight->frames.push_back({32,0});
		playerAnimLeft->frames.push_back({32,0});
		playerAnimDown->frames.push_back({0,0});
		playerAnimWalkUp->frames.push_back({0,96});
		playerAnimWalkUp->frames.push_back({32,96});
		playerAnimWalkUp->frames.push_back({64,96});
		playerAnimWalkRight->frames.push_back({0,64});
		playerAnimWalkLeft->frames.push_back({0,64});
		playerAnimWalkRight->frames.push_back({32,64});
		playerAnimWalkLeft->frames.push_back({32,64});
		playerAnimWalkRight->frames.push_back({64,64});
		playerAnimWalkLeft->frames.push_back({64,64});
		playerAnimWalkDown->frames.push_back({0,32});
		playerAnimWalkDown->frames.push_back({32,32});
		playerAnimWalkDown->frames.push_back({64,32});
		playerAnimPlantUp->frames.push_back({64,128});
		playerAnimPlantRight->frames.push_back({32,128});
		playerAnimPlantLeft->frames.push_back({32,128});
		playerAnimPlantDown->frames.push_back({0,128});
		current_playerAnim=playerAnimWalkDown;

		const int nodeAnimationSkipFrames=12;

		POWER_HAILSTORM_ANIMATION->spr=POWER_HAILSTORM_DECAL;
		POWER_HAILSTORM_ANIMATION->frames.push_back({0,0});
		POWER_HAILSTORM_ANIMATION->frames.push_back({32,0});
		POWER_HAILSTORM_ANIMATION->frames.push_back({64,0});
		POWER_HAILSTORM_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		POWER_HURRICANE_ANIMATION->spr=POWER_HURRICANE_DECAL;
		POWER_HURRICANE_ANIMATION->frames.push_back({0,0});
		POWER_HURRICANE_ANIMATION->frames.push_back({32,0});
		POWER_HURRICANE_ANIMATION->frames.push_back({64,0});
		POWER_HURRICANE_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		POWER_METEOR_SHOWER_ANIMATION->spr=POWER_METEOR_SHOWER_DECAL;
		POWER_METEOR_SHOWER_ANIMATION->frames.push_back({0,0});
		POWER_METEOR_SHOWER_ANIMATION->frames.push_back({32,0});
		POWER_METEOR_SHOWER_ANIMATION->frames.push_back({64,0});
		POWER_METEOR_SHOWER_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		POWER_METEOR_STORM_ANIMATION->spr=POWER_METEOR_STORM_DECAL;
		POWER_METEOR_STORM_ANIMATION->frames.push_back({0,0});
		POWER_METEOR_STORM_ANIMATION->frames.push_back({32,0});
		POWER_METEOR_STORM_ANIMATION->frames.push_back({64,0});
		POWER_METEOR_STORM_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		POWER_SNOWSTORM_ANIMATION->spr=POWER_SNOWSTORM_DECAL;
		POWER_SNOWSTORM_ANIMATION->frames.push_back({0,0});
		POWER_SNOWSTORM_ANIMATION->frames.push_back({32,0});
		POWER_SNOWSTORM_ANIMATION->frames.push_back({64,0});
		POWER_SNOWSTORM_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		CONSUME_SNACK_ANIMATION->spr=CONSUME_SNACK_DECAL;
		CONSUME_SNACK_ANIMATION->frames.push_back({0,0});
		CONSUME_SNACK_ANIMATION->frames.push_back({32,0});
		CONSUME_SNACK_ANIMATION->frames.push_back({64,0});
		CONSUME_SNACK_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		CONSUME_MEAL_ANIMATION->spr=CONSUME_MEAL_DECAL;
		CONSUME_MEAL_ANIMATION->frames.push_back({0,0});
		CONSUME_MEAL_ANIMATION->frames.push_back({32,0});
		CONSUME_MEAL_ANIMATION->frames.push_back({64,0});
		CONSUME_MEAL_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		NADO_ANIMATION->spr=NADO_DECAL;
		for (int i=0;i<8;i++) {
			NADO_ANIMATION->frames.push_back({i*32,0});
		}
		CONSUME_MEAL_ANIMATION->skip_frames=3;
		PETAL_STORM_ANIMATION->spr=PETAL_STORM_DECAL;
		for (int i=0;i<3;i++) {
			PETAL_STORM_ANIMATION->frames.push_back({i*32,0});
		}
		PETAL_STORM_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		SLEEP_ANIMATION->spr=SLEEP_DECAL;
		for (int i=0;i<3;i++) {
			SLEEP_ANIMATION->frames.push_back({i*32+32,0});
		}
		SLEEP_ANIMATION->skip_frames=15;
		SLEEP_ANIMATION->height=64;
		EMPTY_BED_ANIMATION->spr=SLEEP_DECAL;
		EMPTY_BED_ANIMATION->frames.push_back({0,0});
		EMPTY_BED_ANIMATION->skip_frames=1;
		EMPTY_BED_ANIMATION->height=64;
		POWER_FLASHFLOOD_ANIMATION->spr=FLASH_FLOOD_DECAL;
		for (int i=0;i<3;i++) {
			POWER_FLASHFLOOD_ANIMATION->frames.push_back({i*32,0});
		}
		POWER_FLASHFLOOD_ANIMATION->skip_frames=nodeAnimationSkipFrames;
		POWER_SUNNYDAY_ANIMATION->spr=SUNNY_DAY_DECAL;
		for (int i=0;i<3;i++) {
			POWER_SUNNYDAY_ANIMATION->frames.push_back({i*32,0});
		}
		POWER_SUNNYDAY_ANIMATION->skip_frames=nodeAnimationSkipFrames;

		HAILSTORM->playerOwnCount=3;
		HURRICANE->playerOwnCount=1;
		METEOR_RAIN->playerOwnCount=5;

		PETAL_STORM->seedProduction=2; //Produce two seeds.
		HURRICANE->seedScatter=2;
		HURRICANE->growSeeds=true;
		METEOR_STORM->burnTrees=true;
		METEOR_RAIN->burnTrees=true;
		METEOR_RAIN->treeBurnChance=0.5;

		MOVESET_SPIDEY.push_back(SANDSTORM);
		MOVESET_SPIDEY.push_back(SEED_STORM);
		MOVESET_SPIDEY.push_back(AVALANCHE);

		MOVESET_MOTH.push_back(GUST);
		MOVESET_MOTH.push_back(GUST);
		MOVESET_MOTH.push_back(TORNADO);

		MOVESET_SANDWORM.push_back(SANDSTORM);
		MOVESET_SANDWORM.push_back(HEAT_WAVE);
		MOVESET_SANDWORM.push_back(DROUGHT);

		MOVESET_SNAKE.push_back(ACID_RAIN);
		MOVESET_SNAKE.push_back(SANDSTORM);

		MOVESET_X_X.push_back(LIGHT_STORM);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SEED_OF_LIFE);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SUMMON_MINIONS);
		MOVESET_X_X.push_back(SEED_OF_LIFE);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SEED_BULLET);
		MOVESET_X_X.push_back(SEED_PELLET);

		MOVESET_XMINION.push_back(SEED_PELLET);
		MOVESET_XMINION.push_back(SEED_PELLET);
		MOVESET_XMINION.push_back(SEED_STORM);

		COLLECTED_ITEMS.push_back({20,5});
		COLLECTED_ITEMS.push_back({20,6});

		ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",2,3,80,80,MOVESET_SPIDEY));
		ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",4,4,80,80,MOVESET_SPIDEY));
		ENCOUNTER_SPIDEY_1.entities.push_back(new Entity(SPIDEY_DECAL,"Spidey",6,2,80,80,MOVESET_SPIDEY));
		ENCOUNTER_SPIDEY_1.x=79;
		ENCOUNTER_SPIDEY_1.y=47;
		ENCOUNTER_SPIDEY_1.playerX=4;
		ENCOUNTER_SPIDEY_1.playerY=3;
		ENCOUNTER_SPIDEY_1.map=MAP_1;
		ENCOUNTERS.push_back(ENCOUNTER_SPIDEY_1);
		ENCOUNTER_X_X.entities.push_back(new Entity(X_X_DECAL,"X_X",3,2.5,590,590,MOVESET_X_X,{2,2},true));
		ENCOUNTER_X_X.entities.push_back(new Entity(X_X_DECAL,"X Minion",1,4,0,80,MOVESET_XMINION,{0.7,0.7}));
		ENCOUNTER_X_X.entities.push_back(new Entity(X_X_DECAL,"X Minion",0,2,0,80,MOVESET_XMINION,{0.7,0.7}));
		ENCOUNTER_X_X.entities.push_back(new Entity(X_X_DECAL,"X Minion",4,2,0,80,MOVESET_XMINION,{0.7,0.7}));
		ENCOUNTER_X_X.x=38;
		ENCOUNTER_X_X.y=35;
		ENCOUNTER_X_X.playerX=3;
		ENCOUNTER_X_X.playerY=2;
		ENCOUNTER_X_X.map=MAP_1;
		//ENCOUNTERS.push_back(ENCOUNTER_X_X); //Activate at beginning of Chapter 2.

		BASE_OBJECTS["DOME"]=new ObjectLoadInfo(DOME_DECAL);
		BASE_OBJECTS["PLANT"]=new ObjectLoadInfo(PLANT_DECAL);
		BASE_OBJECTS["EXIT"]=new ObjectLoadInfo(NULL);
		BASE_OBJECTS["HAILSTORM_NODE"]=new ObjectLoadInfo(POWER_HAILSTORM_DECAL,POWER_HAILSTORM_ANIMATION);
		BASE_OBJECTS["HURRICANE_NODE"]=new ObjectLoadInfo(POWER_HURRICANE_DECAL,POWER_HURRICANE_ANIMATION);
		BASE_OBJECTS["METEORSHOWER_NODE"]=new ObjectLoadInfo(POWER_METEOR_SHOWER_DECAL,POWER_METEOR_SHOWER_ANIMATION);
		BASE_OBJECTS["METEORSTORM_NODE"]=new ObjectLoadInfo(POWER_METEOR_STORM_DECAL,POWER_METEOR_STORM_ANIMATION);
		BASE_OBJECTS["SNOWSTORM_NODE"]=new ObjectLoadInfo(POWER_SNOWSTORM_DECAL,POWER_SNOWSTORM_ANIMATION);
		BASE_OBJECTS["PETALSTORM_NODE"]=new ObjectLoadInfo(PETAL_STORM_DECAL,PETAL_STORM_ANIMATION);
		BASE_OBJECTS["COMPUTER"]=new ObjectLoadInfo(COMPUTER_DECAL);
		BASE_OBJECTS["BROKEN_ROVER"]=new ObjectLoadInfo(BROKEN_ROVER_DECAL);
		BASE_OBJECTS["NADO"]=new ObjectLoadInfo(NADO_DECAL,NADO_ANIMATION,Pixel(153, 137, 75,230));
		BASE_OBJECTS["SILICON_PIECE"]=new ObjectLoadInfo(SILICON_ROCK_DECAL);

		Zone*SILICON_DEPOSIT_ZONE = new Zone({109,7},{26,9},{0,0},{WIDTH,HEIGHT},{0,0},{WIDTH,HEIGHT},{1,1},{3,3},{-30,-3},{30,3},Pixel(133, 98, 66,180),Pixel(220, 120, 90,230),300,Pixel(87, 78, 69,64));

		ZONES.push_back(SILICON_DEPOSIT_ZONE);


		for (int i=0;i<MAX_PIXELS;i++) {
			pixels[i]=new effect::Pixel();
		}

		LoadMap(STARTING_MAP);
		return true;
	}

	void GetAnyKeyPress() override { 
		if (messageBoxVisible) {
			if (messageBoxCursor!=messageBoxRefText.length()) {
				while (messageBoxCursor<messageBoxRefText.length()) {
					advanceMessageBox();
				}
			} else {
				messageBoxVisible=false;
			}
			return;
		}
		if (!GetKey(W).bPressed&&!GetKey(A).bPressed&&!GetKey(S).bPressed&&!GetKey(D).bPressed&&
		!GetKey(UP).bPressed&&!GetKey(RIGHT).bPressed&&!GetKey(DOWN).bPressed&&!GetKey(LEFT).bPressed) {
			ActionButtonPress();
		} 
		switch (GAME_STATE) {
			case CUTSCENE_1:{
				if (textInd>=CONSOLE_REF_TEXT.length()) {
					fadeOut();
				}
			}break;
			case CUTSCENE_4:{
				if (textInd>=CONSOLE_REF_TEXT.length()) {
					GAME_STATE=CUTSCENE_4_DONE;
					fadeOut();
				}
			}break;
		}
	}

	void ActionButtonPress() {
		if (playerCanMove()) {
			switch (GAME_STATE) {
				case GAMEWORLD:{
					if (PLAYER_COORDS[0]>=8&&PLAYER_COORDS[0]<12&&
					PLAYER_COORDS[1]>=2&&PLAYER_COORDS[1]<6) {
						//cout<<"You are standing over plant "<<getPlantId((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1])<<" in state "<<getPlantStatus((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1]);
						if (getPlantStatus((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1])==2) {
							setPlantStatus((int)PLAYER_COORDS[0],(int)PLAYER_COORDS[1],0);
							foodCount++;
						}
					}
				}break;
			}
		}
		if (GAME_STATE==CUTSCENE_3) {
			switch (MAIN_MENU_SELECTION) {
				case 0:
				case 1:{
					fadeOut();
					audioFadeOut();
				}break;
				case 2:{
					SOUND_IS_MUTED=!SOUND_IS_MUTED;
					if (SOUND_IS_MUTED) {
						MENU_OPTIONS[2]="UNMUTE SOUND";
						engine.SetOutputVolume(0);
					} else {
						MENU_OPTIONS[2]="MUTE SOUND";
						engine.SetOutputVolume(0.6);
					}
				}break;
				case 3:{
					END_THE_GAME=true;
				}break;
			}
		}
		switch (BATTLE_STATE) {
			case battle::PLAYER_SELECTION:{
				if (BATTLE_CARD_SELECTION->playerOwnCount>0) {
					BATTLE_STATE=battle::PLAYER_TARGET_SELECTION;
					if (!(BATTLE_CARD_SELECTION->name.compare("Meal")==0||BATTLE_CARD_SELECTION->name.compare("Snack")==0)) {
						if (PLAYER_SELECTED_TARGET==-1||CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp<=0) {
							for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
								Entity*ent = CURRENT_ENCOUNTER.entities[i];
								if (!ent->ally&&ent->hp>0) {
									PLAYER_SELECTED_TARGET=i;
									break;
								}
							}
						}
					} else {
						PLAYER_SELECTED_TARGET=-2;
						setupBattleTurns();
					}
				}
			}break;
			case battle::PLAYER_TARGET_SELECTION:{
				setupBattleTurns();
			}break;
		}
		switch (CURRENT_CUTSCENE) {
			case cutscene::NODE_COLLECT_CUTSCENE:{
				EndCutscene();
			}break;
			case cutscene::INPUT_USERNAME:{
				if (TERMINAL_SELECTED_CHAR<26&&TERMINAL_INPUT.length()<MAX_TERMINAL_NAME_LENGTH) {
					TERMINAL_INPUT+=(char)('A'+TERMINAL_SELECTED_CHAR);
					if (TERMINAL_INPUT.length()==MAX_TERMINAL_NAME_LENGTH) {
						TERMINAL_SELECTED_CHAR=27;
					}
				} else 
				if (TERMINAL_SELECTED_CHAR==26&&TERMINAL_INPUT.length()>0) {
					TERMINAL_INPUT.erase(TERMINAL_INPUT.length()-1);
				} else
				if (TERMINAL_SELECTED_CHAR==27&&TERMINAL_INPUT.length()>0) {
					PLAYER_NAME=TERMINAL_INPUT;
					PlayCutscene(cutscene::GO_OUTSIDE);
				}
			}break;
		}
	}

	bool OnUserUpdate(float fElapsedTime) override
	{
		elapsedTime+=fElapsedTime;
		while (elapsedTime>TARGET_RATE) {
			elapsedTime-=TARGET_RATE;
			updateGame();
			rand();
		}
		if (GetKey(F1).bPressed) {
			ConsoleShow(F1,false);
		}
		if (playerCanMove()) {
			if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) {
				changeAnimation(playerAnimWalkRight);
			}
			if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) {
				changeAnimation(playerAnimWalkLeft);
			}
			if (GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) {
				changeAnimation(playerAnimWalkUp);
			}
			if (GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed) {
				changeAnimation(playerAnimWalkDown);
			}
			if (!GetKey(D).bHeld&&!GetKey(RIGHT).bHeld&&!GetKey(NP6).bHeld&&
				!GetKey(A).bHeld&&!GetKey(LEFT).bHeld&&!GetKey(NP4).bHeld&&
				!GetKey(S).bHeld&&!GetKey(UP).bHeld&&!GetKey(NP8).bHeld&&
				!GetKey(W).bHeld&&!GetKey(DOWN).bHeld&&!GetKey(NP5).bHeld&&!GetKey(NP2).bHeld) {
				if (GetKey(D).bReleased||GetKey(RIGHT).bReleased||GetKey(NP6).bReleased) {
					changeAnimation(playerAnimRight);
				}
				if (GetKey(A).bReleased||GetKey(LEFT).bReleased||GetKey(NP4).bReleased) {
					changeAnimation(playerAnimLeft);
				}
				if (GetKey(W).bReleased||GetKey(UP).bReleased||GetKey(NP8).bReleased) {
					changeAnimation(playerAnim);
				}
				if (GetKey(S).bReleased||GetKey(DOWN).bReleased||GetKey(NP5).bReleased||GetKey(NP2).bReleased) {
					changeAnimation(playerAnimDown);
				}
			}
		} else
		if (IN_BATTLE_ENCOUNTER) {
			switch (BATTLE_STATE) {
				case battle::PLAYER_SELECTION:{
					if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) {
						BATTLE_CARD_SELECTION_IND=(BATTLE_CARD_SELECTION_IND+1)%availablePowers.size();
						BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND];
					} 
					if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) {
						if (--BATTLE_CARD_SELECTION_IND<0) {
							BATTLE_CARD_SELECTION_IND=availablePowers.size()-1;
						}
						BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND];
					}
				}break;
				case battle::PLAYER_TARGET_SELECTION:{
					if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) {
						while (true) {
							PLAYER_SELECTED_TARGET=(PLAYER_SELECTED_TARGET+1)%CURRENT_ENCOUNTER.entities.size();
							if (CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0) {
								break;
							}
						}
					} 
					if (GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) {
						PLAYER_SELECTED_TARGET=-1;
						BATTLE_STATE=battle::PLAYER_SELECTION;
					}
					if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) {
						while (true) {
							if (--PLAYER_SELECTED_TARGET<0) {
								PLAYER_SELECTED_TARGET=CURRENT_ENCOUNTER.entities.size()-1;
							}
							if (CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0) {
								break;
							}
						}
					}
				}break;
			}
		} else {
			if (GAME_STATE==CUTSCENE_3) {
				if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed|GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) {
					MAIN_MENU_SELECTION--;
					if (MAIN_MENU_SELECTION<0) {
						MAIN_MENU_SELECTION=3;
					}
				}
				if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed||GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed) {
					MAIN_MENU_SELECTION=(MAIN_MENU_SELECTION+1)%4;
				}
			}
			switch (CURRENT_CUTSCENE) {
				case cutscene::INPUT_USERNAME:{
					if (GetKey(W).bPressed||GetKey(UP).bPressed||GetKey(NP8).bPressed) {
						TERMINAL_SELECTED_CHAR=TERMINAL_SELECTED_CHAR-7;
						if (TERMINAL_SELECTED_CHAR<0) {
							TERMINAL_SELECTED_CHAR+=28;
						}
					}
					if (GetKey(D).bPressed||GetKey(RIGHT).bPressed||GetKey(NP6).bPressed) {
						if ((TERMINAL_SELECTED_CHAR+1)%7==0) {
							TERMINAL_SELECTED_CHAR-=6;
						} else {
							TERMINAL_SELECTED_CHAR++;
						}
					}
					if (GetKey(A).bPressed||GetKey(LEFT).bPressed||GetKey(NP4).bPressed) {
						if ((TERMINAL_SELECTED_CHAR-1)%7==6||TERMINAL_SELECTED_CHAR-1<0) {
							TERMINAL_SELECTED_CHAR+=6;
						} else {
							TERMINAL_SELECTED_CHAR--;
						}
					}
					if (GetKey(S).bPressed||GetKey(DOWN).bPressed||GetKey(NP5).bPressed||GetKey(NP2).bPressed) {
						if (TERMINAL_SELECTED_CHAR+7>=28) {
							TERMINAL_SELECTED_CHAR=(TERMINAL_SELECTED_CHAR+7)%28;
						} else {
							TERMINAL_SELECTED_CHAR+=7;
						}
					}
				}break;
			}
		}
		SetDrawTarget(nullptr);
		Clear(BLANK);
		SetDrawTarget(1);
		Clear(BLANK);
		SetDrawTarget(2);
		drawGame();
		// called once per frame
		return !END_THE_GAME;
	}

	void fadeOutCompleted() {
		switch (GAME_STATE) {
			case CUTSCENE_1:{
				GAME_STATE=CUTSCENE_2;
				PlayCutscene(cutscene::PAN_DOME);
				fadeIn();
			}break;
			case CUTSCENE_2:{
				fadeIn();
				PlayCutscene(cutscene::CUTSCENE_4);
				GAME_STATE=GAMEWORLD;
			}break;
			case CUTSCENE_3:{
				GAME_STATE=CUTSCENE_1;
				fadeIn();
				ResetTerminal(STORY_TEXT1);
			}break;
			case CUTSCENE_4:{
				fadeIn();
			}break;
			case CUTSCENE_4_DONE:{
				GAME_STATE=GAMEWORLD;
				PlayCutscene(cutscene::GET_SOME_REST);	
				fadeIn();
			}break;
			case LATER_THAT_NIGHTFADEIN:{
				fadeIn();
			}break;
			case LATER_THAT_NIGHTFADEOUT:{
				fadeIn();
				GAME_STATE=GAMEWORLD;
				PlayCutscene(cutscene::IN_BED);
				PLAYER_HP=PLAYER_MAXHP;
			}break;
		}
		switch (CURRENT_CUTSCENE) {
			case cutscene::TRANSITION_CUTSCENE:{
				LoadMap(MAP_1);
				PLAYER_COORDS[0]=40.5;
				PLAYER_COORDS[1]=37.5;
				fadeIn();
				EndCutscene();
				if (!GAME_FLAGS[gameflag::VISIT_BROKEN_ROVER]) {
					GAME_FLAGS[gameflag::VISIT_BROKEN_ROVER]=true;
					PlayCutscene(cutscene::WALK_TO_ROVER);
				}
			}break;
			case cutscene::TRANSITION_CUTSCENE_2:{
				if (GAME_FLAGS[gameflag::REST_IN_DOME]&&!GAME_FLAGS[gameflag::SLEEP]) {
					for (int i=0;i<COLLECTED_ITEMS.size();i++) {
						if (COLLECTED_ITEMS[i].x==20&&COLLECTED_ITEMS[i].y==5) {
							COLLECTED_ITEMS.erase(COLLECTED_ITEMS.begin()+i--);
						} else
						if (COLLECTED_ITEMS[i].x==20&&COLLECTED_ITEMS[i].y==6) {
							COLLECTED_ITEMS.erase(COLLECTED_ITEMS.begin()+i--);
						}
					}
				}
				LoadMap(MAP_2);
				TeleportToMapFileCoords(8,17);
				fadeIn();
				EndCutscene();
				if (GAME_FLAGS[gameflag::REST_IN_DOME]&&!GAME_FLAGS[gameflag::SLEEP]) {
					GAME_FLAGS[gameflag::SLEEP]=true;
					//20,2
					GAME_STATE=LATER_THAT_NIGHTFADEIN;
					fadeOutCompleted();
				}
			}break;
			case cutscene::DISPLAY_VOLCANIC_AREA:{
				TeleportToMapFileCoords(13,122);
				fadeIn();
			}break;
			case cutscene::REPAIR_ROVER_1:{
				ResetTerminal(STORY_TEXT3);
				GAME_STATE=CUTSCENE_4;
				REPAIRED_ROVERS.push_back({33,35});
				fadeIn();
			}break;
			case cutscene::END_VOLCANIC_AREA_CUTSCENE:{
				PLAYER_COORDS[0]=33;
				PLAYER_COORDS[1]=34;
				ClearAllTemporaryObjects();
				fadeIn();
			}break;
		}
	}

	void fadeInCompleted() {
		switch (GAME_STATE) {
			case LATER_THAT_NIGHTFADEIN:{
				TIMER=0;
				GAME_STATE=LATER_THAT_NIGHTWAIT;
			}break;
		}
		switch (CURRENT_CUTSCENE) {
			case cutscene::DISPLAY_VOLCANIC_AREA:{
				CUTSCENE_FLAGS[0]=true;
			}break;
			case cutscene::END_VOLCANIC_AREA_CUTSCENE:{
				DisplayMessageBox(10);
				EndCutscene();
			}break;
		}
	}

	void StartCutscene(cutscene::CUTSCENE scene) {
		PlayCutscene(scene);
	}

	void RunCutscene(cutscene::CUTSCENE scene) {
		PlayCutscene(scene);
	}

	void PlayCutscene(cutscene::CUTSCENE scene) {
		CURRENT_CUTSCENE=scene;
		switch (scene) {
			case cutscene::PAN_DOME:{
				PLAYER_COORDS[0]=14;
				PLAYER_COORDS[1]=35+(64/2/32);
			}break;
			case cutscene::PAUSE_TO_CUTSCENE_3:{
				ResetTerminal(STORY_TEXT2);
			}break;
			case cutscene::CUTSCENE_4:{
				LoadMap(MAP_2);
				PLAYER_COORDS[0]=16;
				PLAYER_COORDS[1]=6;
			}break;
			case cutscene::RAINING_IN_DOME:{
				applyPixelEffect(HURRICANE,GetMapFileCoords(7,11),1);
				CUTSCENE_TIMER=0;
			}break;
			case cutscene::WALK_TO_ROVER:{
				CUTSCENE_OBJS[0]=CreateObject({PLAYER_COORDS[0],PLAYER_COORDS[1]},PLAYER_DECAL,{32,0},{32,32},true);
				CUTSCENE_OBJS[0]->flipped=true;
			}break;
			case cutscene::REPAIR_ROVER_1:{
				CUTSCENE_OBJS[0]=CreateObject({PLAYER_COORDS[0],PLAYER_COORDS[1]},PLAYER_DECAL,{64,0},{32,32},true);
			}break;
			case cutscene::GET_SOME_REST:{
				DisplayMessageBox(18);
			}break;
			case cutscene::IN_BED:{
				CUTSCENE_OBJS[0]=CreateObject({20,2},SLEEP_DECAL,SLEEP_ANIMATION,true);
			}break;
			case cutscene::INVESTIGATE_X_X:{
				CUTSCENE_OBJS[0]->anim=EMPTY_BED_ANIMATION;
				CUTSCENE_OBJS[1]=CreateObject({19,3},PLAYER_DECAL,{32,0},{32,32},true);
				CUTSCENE_OBJS[1]->flipped=true;
				DisplayMessageBox(20);
			}break;
		}
		for (int i=0;i<8;i++) {
			CUTSCENE_FLAGS[i]=false;
		}
		CUTSCENE_TIMER=0;
	}

	void updateGame(){
		frameCount++;
		TIMER++;
		if (CURRENT_CUTSCENE!=cutscene::NONE) {
			CUTSCENE_TIMER++;
		}
		if (audioFade&&audioLevel>0) {
			audioLevel-=0.01;
			engine.SetOutputVolume(audioLevel);
		} else
		if (!audioFade&&audioLevel<0.6) {
			audioLevel+=0.01;
			engine.SetOutputVolume(audioLevel);
		}
		if (fade&&transparency<255) {
			transparency=std::clamp(transparency+FADE_SPD,0,255);
			if (transparency==255) {
				fadeOutCompleted();
			}
		} else
		if (!fade&&transparency>0) {
			transparency=std::clamp(transparency-FADE_SPD,0,255);
			if (transparency==0) {
				fadeInCompleted();
			}
		}
		if (messageBoxVisible) {
			if (frameCount%MESSAGE_SCROLL_WAIT_SPD==0) {
				if (messageBoxCursor<messageBoxRefText.length()) {
					advanceMessageBox();
				}
			}
		}
		if(frameCount%current_playerAnim->skip_frames==0) {
			current_playerAnim->frame=(current_playerAnim->frame+1)%current_playerAnim->frames.size();
		}
		for (auto anim:updateAnimationsList) {
			if (frameCount%anim->skip_frames==0) {
				anim->frame=(anim->frame+1)%anim->frames.size();
			}
		}

		if (!IN_BATTLE_ENCOUNTER) {
			bool zoneEffectActive=false;
			for (int i=0;i<ZONES.size();i++) {
				Zone*z = ZONES[i];
				if (PLAYER_COORDS[0]>=z->pos.x&&PLAYER_COORDS[0]<=z->pos.x+z->size.x&&
					PLAYER_COORDS[1]>=z->pos.y&&PLAYER_COORDS[1]<=z->pos.y+z->size.y) {
					if (ACTIVE_ZONE==nullptr) {
						applyPixelEffect(z->eff,{PLAYER_COORDS[0],PLAYER_COORDS[1]},0.9);
						ACTIVE_ZONE=z;
					}
					zoneEffectActive=true;
				}
			}
			if (!zoneEffectActive&&ACTIVE_ZONE!=nullptr) {
				clearPixelEffect();
				ACTIVE_ZONE=nullptr;
			}
		}
		
		if (playerCanMove()) {
			bool animationchanged=false;
			bool positionModified=false;
			if (GetKey(D).bHeld||GetKey(RIGHT).bHeld||GetKey(NP6).bHeld) {
				if (MAP[(int)PLAYER_COORDS[1]][(int)std::clamp(PLAYER_COORDS[0]+MOVE_SPD,0.1,(double)MAP_WIDTH)]!=4) {
					PLAYER_COORDS[0]=std::clamp(PLAYER_COORDS[0]+MOVE_SPD,0.1,(double)MAP_WIDTH);
					positionModified=true;
				}
				//ConsoleClear();
				//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
				if (!animationchanged&&&current_playerAnim!=&playerAnimWalkRight) {
					changeAnimation(playerAnimWalkRight);
					animationchanged=true;
				}
			}
			if (GetKey(A).bHeld||GetKey(LEFT).bHeld||GetKey(NP4).bHeld) {
				if (MAP[(int)PLAYER_COORDS[1]][(int)std::clamp(PLAYER_COORDS[0]-MOVE_SPD,0.1,(double)MAP_WIDTH)]!=4) {
					PLAYER_COORDS[0]=std::clamp(PLAYER_COORDS[0]-MOVE_SPD,0.1,(double)MAP_WIDTH);
					positionModified=true;
				}
				//ConsoleClear();
				//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
				if (!animationchanged&&&current_playerAnim!=&playerAnimWalkLeft) {
					changeAnimation(playerAnimWalkLeft);
					animationchanged=true;
				}
			}
			if (GetKey(W).bHeld||GetKey(UP).bHeld||GetKey(NP8).bHeld) {
				if (MAP[(int)std::clamp(PLAYER_COORDS[1]-MOVE_SPD,0.1,(double)MAP_HEIGHT)][(int)PLAYER_COORDS[0]]!=4) {
					PLAYER_COORDS[1]=std::clamp(PLAYER_COORDS[1]-MOVE_SPD,0.1,(double)MAP_HEIGHT);
					positionModified=true;
				}
				//ConsoleClear();
				//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
				if (!animationchanged&&&current_playerAnim!=&playerAnimWalkUp) {
					changeAnimation(playerAnimWalkUp);
					animationchanged=true;
				}
			}
			if (GetKey(S).bHeld||GetKey(DOWN).bHeld||GetKey(NP5).bHeld||GetKey(NP2).bHeld) {
				if (MAP[(int)std::clamp(PLAYER_COORDS[1]+MOVE_SPD,0.1,(double)MAP_HEIGHT)][(int)PLAYER_COORDS[0]]!=4) {
					PLAYER_COORDS[1]=std::clamp(PLAYER_COORDS[1]+MOVE_SPD,0.1,(double)MAP_HEIGHT);
					positionModified=true;
				}
				//ConsoleClear();
				//cout<<"("<<PLAYER_COORDS[0]<<","<<PLAYER_COORDS[1]<<+")";
				if (!animationchanged&&&current_playerAnim!=&playerAnimWalkDown) {
					changeAnimation(playerAnimWalkDown);
					animationchanged=true;
				}
			}
			if (positionModified) {
				playerMoved();
			}
			for (int i=0;i<OBJECTS.size();i++) {
				Object*obj = OBJECTS[i];
				if (obj->name.compare("HAILSTORM_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					HAILSTORM->playerOwnCount+=amountGained;
					std::cout<<"Increased HAILSTORM power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(HAILSTORM);
				} else
				if (obj->name.compare("HURRICANE_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					HURRICANE->playerOwnCount+=amountGained;
					std::cout<<"Increased HURRICANE power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(HURRICANE);
				} else
				if (obj->name.compare("METEORSHOWER_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					METEOR_RAIN->playerOwnCount+=amountGained;
					std::cout<<"Increased METEORSHOWER power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(METEOR_RAIN);
				} else
				if (obj->name.compare("METEORSTORM_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					METEOR_STORM->playerOwnCount+=amountGained;
					std::cout<<"Increased METEORSTORM power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(METEOR_STORM);
				} else
				if (obj->name.compare("SNOWSTORM_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					SNOWSTORM->playerOwnCount+=amountGained;
					std::cout<<"Increased SNOWSTORM power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(SNOWSTORM);
				} else
				if (obj->name.compare("PETALSTORM_NODE")==0&&collidesWithPlayer(obj)) {
					int amountGained=rand()%4+2;
					PETAL_STORM->playerOwnCount+=amountGained;
					std::cout<<"Increased PETALSTORM power inventory count by "<<amountGained<<".\n";
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
					performCropUpdate(8);
					displayPowerInfo(PETAL_STORM);
				} else
				if (obj->name.compare("SILICON_PIECE")==0&&collidesWithPlayer(obj)) {
					GAME_STATE=COLLECTED_SILICON;
					DisplayMessageBox(14);
					COLLECTED_ITEMS.push_back({(int)obj->x,(int)obj->y});
					OBJECTS.erase(OBJECTS.begin()+i--);
					delete obj;
				} else
				if (obj->name.compare("EXIT")==0&&collidesWithPlayer(obj)) {
					fadeOut();
					PlayCutscene(cutscene::TRANSITION_CUTSCENE);
				} else
				if (obj->name.compare("DOME")==0&&collidesWithPlayer(obj)) {
					fadeOut();
					PlayCutscene(cutscene::TRANSITION_CUTSCENE_2);
				}
			}
		}

		if (!IN_BATTLE_ENCOUNTER) {
			for (int i=0;i<ENCOUNTERS.size();i++) {
				Encounter enc = ENCOUNTERS[i];
				if (enc.map==CURRENT_MAP&&collidesWithPlayer(enc)) {
					for (int i=0;i<WEATHER_POWER_COUNT;i++) {
						if (WEATHER_POWERS[i]->name.compare("Snack")==0||WEATHER_POWERS[i]->name.compare("Meal")==0) {
							WEATHER_POWERS[i]->playerOwnCount=foodCount;
						}
					}
					availablePowers.erase(availablePowers.begin(),availablePowers.end());
					IN_BATTLE_ENCOUNTER=true;
					CURRENT_ENCOUNTER=enc;
					CURRENT_ENCOUNTER_IND=i;
					BATTLE_ENTRY_TIMER=0;
					BATTLE_STATE=battle::WAITING_FOR_CAMERA;
					for (int i=0;i<WEATHER_POWER_COUNT;i++) {
						if (WEATHER_POWERS[i]->playerOwnCount>0) {
							availablePowers.push_back(WEATHER_POWERS[i]);
						}
					}
					BATTLE_PLAYER_COORDS={PLAYER_COORDS[0],PLAYER_COORDS[1]};
					BATTLE_CARD_SELECTION_IND=0;
					BATTLE_CARD_SELECTION=availablePowers[BATTLE_CARD_SELECTION_IND];
					PLAYER_SELECTED_TARGET=-1;
				}
			}
		}

		for (int i=0;i<BATTLE_DISPLAY_NUMBERS.size();i++) {
			DisplayNumber*numb=BATTLE_DISPLAY_NUMBERS[i];
			if (frameCount-numb->frame>60) {
				BATTLE_DISPLAY_NUMBERS.erase(BATTLE_DISPLAY_NUMBERS.begin()+i--);
				delete numb;
			} else {
				numb->y-=0.01;
				numb->alpha-=4;
			}
		}

		if (IN_BATTLE_ENCOUNTER&&!messageBoxVisible) {
			BATTLE_ENTRY_TIMER++;
			switch (BATTLE_STATE) {
				case battle::WAITING_FOR_CAMERA: {
					if (BATTLE_ENTRY_TIMER>45) {
						int TARGET_COORDS_X=CURRENT_ENCOUNTER.x+WIDTH/32/2;
						int TARGET_COORDS_Y=CURRENT_ENCOUNTER.y+HEIGHT/32/2;
						if (PLAYER_COORDS[0]==TARGET_COORDS_X&&PLAYER_COORDS[1]==TARGET_COORDS_Y
							&&BATTLE_PLAYER_COORDS.x==CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX&&BATTLE_PLAYER_COORDS.y==CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY) {
							if (!GAME_FLAGS[gameflag::FIRST_ENCOUNTER_X_X]&&GAME_FLAGS[gameflag::SLEEP]) {
								GAME_FLAGS[gameflag::FIRST_ENCOUNTER_X_X]=true;
								DisplayMessageBox(22);
								break;
							}
							BATTLE_STATE = battle::PLAYER_SELECTION;
							clearPixelEffect();
							EFFECT_TIMER = 0;
						}
						if (PLAYER_COORDS[0]!=TARGET_COORDS_X) {
							if (PLAYER_COORDS[0]<TARGET_COORDS_X) {
								PLAYER_COORDS[0]+=BATTLE_CAMERA_SCROLL_SPD;
								if (PLAYER_COORDS[0]>TARGET_COORDS_X) {
									PLAYER_COORDS[0]=TARGET_COORDS_X;
								}
							} else {
								PLAYER_COORDS[0]-=BATTLE_CAMERA_SCROLL_SPD;
								if (PLAYER_COORDS[0]<TARGET_COORDS_X) {
									PLAYER_COORDS[0]=TARGET_COORDS_X;
								}
							}
						}
						if (PLAYER_COORDS[1]!=TARGET_COORDS_Y) {
							if (PLAYER_COORDS[1]<TARGET_COORDS_Y) {
								PLAYER_COORDS[1]+=BATTLE_CAMERA_SCROLL_SPD;
								if (PLAYER_COORDS[1]>TARGET_COORDS_Y) {
									PLAYER_COORDS[1]=TARGET_COORDS_Y;
								}
							} else {
								PLAYER_COORDS[1]-=BATTLE_CAMERA_SCROLL_SPD;
								if (PLAYER_COORDS[1]<TARGET_COORDS_Y) {
									PLAYER_COORDS[1]=TARGET_COORDS_Y;
								}
							}
						}
						if (BATTLE_PLAYER_COORDS.x!=CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX) {
							if (BATTLE_PLAYER_COORDS.x<CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX) {
								BATTLE_PLAYER_COORDS.x+=BATTLE_CAMERA_SCROLL_SPD;
								if (BATTLE_PLAYER_COORDS.x>CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX) {
									BATTLE_PLAYER_COORDS.x=CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX;
								}
							} else {
								BATTLE_PLAYER_COORDS.x-=BATTLE_CAMERA_SCROLL_SPD;
								if (BATTLE_PLAYER_COORDS.x<CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX) {
									BATTLE_PLAYER_COORDS.x=CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX;
								}
							}
						}
						if (BATTLE_PLAYER_COORDS.y!=CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY) {
							if (BATTLE_PLAYER_COORDS.y<CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY) {
								BATTLE_PLAYER_COORDS.y+=BATTLE_CAMERA_SCROLL_SPD;
								if (BATTLE_PLAYER_COORDS.y>CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY) {
									BATTLE_PLAYER_COORDS.y=CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY;
								}
							} else {
								BATTLE_PLAYER_COORDS.y-=BATTLE_CAMERA_SCROLL_SPD;
								if (BATTLE_PLAYER_COORDS.y<CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY) {
									BATTLE_PLAYER_COORDS.y=CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY;
								}
							}
						}
					}
				}break;
				case battle::PLAYER_SELECTION:{
					if (!GAME_FLAGS[gameflag::TUTORIAL1_X_X]&&GAME_FLAGS[gameflag::ANALYSIS_X_X]) {
						GAME_FLAGS[gameflag::TUTORIAL1_X_X]=true;
						DisplayMessageBox(24);
					} else
					if (!GAME_FLAGS[gameflag::TUTORIAL2_X_X]&&GAME_FLAGS[gameflag::TUTORIAL1_X_X]) {
						GAME_FLAGS[gameflag::TUTORIAL2_X_X]=true;
						DisplayMessageBox(25);
					}
				}break;
				case battle::WAIT_TURN_ANIMATION:{
					if (EFFECT_TIMER==0) {
						PIXEL_EFFECT_TRANSPARENCY=0;
						if (BATTLE_CURRENT_TURN_ENTITY==-1) {
							if (PLAYER_SELECTED_TARGET==-2) {
								applyPixelEffect(BATTLE_CARD_SELECTION,{CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY},0);
							} else {
								applyPixelEffect(BATTLE_CARD_SELECTION,{(float)(CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x),(float)(CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y)},0);
							}
						} else {
							if (CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove->damage<0) {
								applyPixelEffect(CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove,{(float)CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->x,(float)CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->y},0);
							} else {
								applyPixelEffect(CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove,{CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY},0);
							}
						}
					}
					EFFECT_TIMER++;
					WEATHER_POWER*ref;
					if (BATTLE_CURRENT_TURN_ENTITY==-1) {
						ref=BATTLE_CARD_SELECTION;
					} else {
						ref=CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove;
					}
					PIXEL_EFFECT_TRANSPARENCY=(0.5*cos(((M_PI/(30.0*(ref->effectTime/120.0)))/2)*EFFECT_TIMER-M_PI)+0.5);
					if (EFFECT_TIMER==30&&ref->name.compare("Petal Storm")==0) {
						int healPower=30;
						int healRoll=healPower+rand()%ref->damageRoll*sign(healPower);
						if (BATTLE_CURRENT_TURN_ENTITY==-1) {
							effectRadius({(int)BATTLE_PLAYER_COORDS.x,(int)BATTLE_PLAYER_COORDS.y},ref,-healRoll,true);
						} else {
							effectRadius({CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->y+CURRENT_ENCOUNTER.y},ref,-healRoll,false);
						}
					}
					if (EFFECT_TIMER==30&&ref->name.compare("Seed Storm")==0) {
						if (BATTLE_CURRENT_TURN_ENTITY==-1) {
							effectRadius({(int)BATTLE_PLAYER_COORDS.x,(int)BATTLE_PLAYER_COORDS.y},ref,true);
						} else {
							effectRadius({CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->y+CURRENT_ENCOUNTER.y},ref,false);
						}
					} else 
					if (EFFECT_TIMER==ref->effectTime-10){
						if (BATTLE_CURRENT_TURN_ENTITY==-1) {
							if (FOOD_REGEN_TURNS>0) {
								FOOD_REGEN_TURNS--;	
								PLAYER_HP=std::clamp(PLAYER_HP+(int)(PLAYER_MAXHP*0.33),0,PLAYER_MAXHP);
								CreateDisplayNumber((int)(-PLAYER_MAXHP*0.33),CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY,frameCount);
								
							}
							if (PLAYER_SELECTED_TARGET==-2) {
								effectRadius({CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY},ref,true);
							} else {
								effectRadius({CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x+CURRENT_ENCOUNTER.x,CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y+CURRENT_ENCOUNTER.y},ref,true);							}
						} else {
							effectRadius({CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.playerX,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.playerY},ref,false);
							if (ref==LIGHT_STORM&&CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->name.compare("X_X")==0) {
								CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->spr=X_X_UNCHARGED_DECAL;
							} else
							if (ref==SEED_PELLET&&CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->name.compare("X_X")==0) {
								CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->spr=X_X_DECAL;
							}
						}
					} else 
					if (EFFECT_TIMER==ref->effectTime/2){
						addSeeds(ref->seedProduction);
						int newSeedCount=SEEDS.size()*ref->seedScatter;
						while (SEEDS.size()<newSeedCount) {
							addSeeds(1);
						}
					}
					if (EFFECT_TIMER>ref->effectTime) {
						EFFECT_TIMER=0;
						clearPixelEffect();
						if (ref->growSeeds&&SEEDS.size()>0) {
							BATTLE_REASON_CODE=reasoncode::SEED_GROWTH;
							BATTLE_STATE=battle::WAIT_TURN_ANIMATION2;
						} else 
						if (ref->burnTrees&&TREES.size()>0&&ref->treeBurnChance>range(0,1)){
							BATTLE_REASON_CODE=reasoncode::TREE_BURN;
							BATTLE_STATE=battle::WAIT_TURN_ANIMATION2;
						} else {
							BATTLE_REASON_CODE=-1;
							BATTLE_STATE=battle::DAMAGE_RESOLUTION;
						}
					}
				}break;
				case battle::WAIT_TURN_ANIMATION2:{
					EFFECT_TIMER++;
					PIXEL_EFFECT_TRANSPARENCY=0.5*cos(M_PI/60*EFFECT_TIMER-M_PI)+0.5;
					if (EFFECT_TIMER==10) {
						switch (BATTLE_REASON_CODE) {
							case reasoncode::SEED_GROWTH:{
								applyPixelEffect(SEED_STORM,BATTLE_PLAYER_COORDS,0);
							}break;
							case reasoncode::TREE_BURN:{
								applyPixelEffect(FIRESTORM_EFF,BATTLE_PLAYER_COORDS,0);
							}break;
						}
					}
					if (EFFECT_TIMER==60) {
						switch (BATTLE_REASON_CODE) {
							case reasoncode::SEED_GROWTH:{
								int healAmt=-10*SEEDS.size();
								CreateDisplayNumber(healAmt,BATTLE_PLAYER_COORDS.x,BATTLE_PLAYER_COORDS.y,frameCount);
								PLAYER_HP=std::clamp(PLAYER_HP+healAmt*-1,0,PLAYER_MAXHP);
								addTrees(SEEDS.size());
								clearSeeds();
							}break;
							case reasoncode::TREE_BURN:{
								int dmgAmt=10*TREES.size();
								for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
									if (CURRENT_ENCOUNTER.entities[i]->hp>0) {
										CreateDisplayNumber(dmgAmt,CURRENT_ENCOUNTER.x+CURRENT_ENCOUNTER.entities[i]->x+CURRENT_ENCOUNTER.entities[i]->spr->sprite->width*CURRENT_ENCOUNTER.entities[i]->sprScale.x/2/32,CURRENT_ENCOUNTER.y+CURRENT_ENCOUNTER.entities[i]->y+CURRENT_ENCOUNTER.entities[i]->spr->sprite->height*CURRENT_ENCOUNTER.entities[i]->sprScale.y/2/32,frameCount);
										CURRENT_ENCOUNTER.entities[i]->hp=std::clamp(CURRENT_ENCOUNTER.entities[i]->hp-dmgAmt,0,CURRENT_ENCOUNTER.entities[i]->maxhp);
									}
								}
								clearTrees();
							}break;
						}
					}
					if (EFFECT_TIMER==120) {
						EFFECT_TIMER=0;
						clearPixelEffect();
						BATTLE_REASON_CODE=-1;
						BATTLE_STATE=battle::DAMAGE_RESOLUTION;
					}
				}break;
				case battle::DAMAGE_RESOLUTION:{
					EFFECT_TIMER++;
					if (EFFECT_TIMER>60) {
						if (turnOrder.empty()) {
							bool allDead=true;
							for (auto&ent:CURRENT_ENCOUNTER.entities) {
								if (ent->hp>0) {
									allDead=false;
									break;
								}
							}
							if (allDead) {
								IN_BATTLE_ENCOUNTER=false;
								ENCOUNTERS.erase(ENCOUNTERS.begin()+CURRENT_ENCOUNTER_IND);
								BATTLE_CARD_SELECTION_IND=0;
								PLAYER_SELECTED_TARGET=-1;
								BATTLE_STATE=battle::NONE;
								PLAYER_COORDS[0]=BATTLE_PLAYER_COORDS.x;
								PLAYER_COORDS[1]=BATTLE_PLAYER_COORDS.y;	
								clearSeeds();
								clearTrees();
								performCropUpdate(8);
								if (FOOD_REGEN_TURNS>0) {
									FOOD_REGEN_TURNS=0;
									foodCount++;
								}
							} else {
								if (!GAME_FLAGS[gameflag::ANALYSIS_X_X]&&GAME_FLAGS[gameflag::FIRST_ENCOUNTER_X_X]) {
									GAME_FLAGS[gameflag::ANALYSIS_X_X]=true;
									DisplayMessageBox(23);
									break;
								}
								BATTLE_STATE=battle::PLAYER_SELECTION;
								PLAYER_SELECTED_TARGET=-1;
							}
						} else {
							BATTLE_CURRENT_TURN_ENTITY=turnOrder.front();
							turnOrder.pop();
							if (BATTLE_CURRENT_TURN_ENTITY==-1) {
								if (PLAYER_HP<=0) {
									GAME_STATE=GAME_OVER;
									break;
								}
							} else {
								if (CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->hp<=0) {
									break;
								}
							}
							BATTLE_STATE=battle::WAIT_TURN_ANIMATION;
							PIXEL_EFFECT_TRANSPARENCY=0;
							EFFECT_TIMER=0;
							for (int i=0;i<WEATHER_POWER_COUNT;i++) {
								if (WEATHER_POWERS[i]->name.compare("Snack")==0||WEATHER_POWERS[i]->name.compare("Meal")==0) {
									WEATHER_POWERS[i]->playerOwnCount=foodCount;
								}
							}
						}
					}
				}break;
			}
		}

		switch (CURRENT_CUTSCENE) {
			case cutscene::CUTSCENE_4:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_OBJS[0]=CreateObject(GetMapFileCoords(8,17),PLAYER_DECAL,{64,0},{32,32},true);
						CUTSCENE_FLAGS[0]=true;
						DisplayMessageBox(0);
					} else
					if (!CUTSCENE_FLAGS[1]) {
						CUTSCENE_FLAGS[1]=true;
						DisplayMessageBox(1);
					} else
					{
						PlayCutscene(cutscene::PAN_OVER_TO_CROPS);
					}
				}
			}break;
			case cutscene::PAN_OVER_TO_CROPS:{
				if (CUTSCENE_OBJS[0]->y>4) {
					CUTSCENE_OBJS[0]->y-=MOVE_SPD;
				} else
				if (CUTSCENE_OBJS[0]->x>13) {
					CUTSCENE_OBJS[0]->spos={32,0};
					CUTSCENE_OBJS[0]->flipped=true;
					CUTSCENE_OBJS[0]->x-=MOVE_SPD;
				}
				if (MoveCameraTowardsPoint(GetMapFileCoords(7,11))) {
					PlayCutscene(cutscene::RAINING_IN_DOME);
				}
			}break;
			case cutscene::RAINING_IN_DOME:{
				if (CUTSCENE_TIMER%60==0) {
					performCropUpdate(3);
				}
				if (CUTSCENE_TIMER>=60*6) {
					PIXEL_EFFECT_TRANSPARENCY=(60-(CUTSCENE_TIMER-60*6))/60;
				}
				if (CUTSCENE_TIMER>=60*7) {
					PlayCutscene(cutscene::AFTER_RAIN);
				}
			}break;
			case cutscene::AFTER_RAIN:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						DisplayMessageBox(2);	
						CUTSCENE_FLAGS[0]=true;
					} else
					if (!CUTSCENE_FLAGS[1]) {
						DisplayMessageBox(3);	
						CUTSCENE_FLAGS[1]=true;
						foodMeterVisible=true;
					} else {
						PLAYER_COORDS[0]=13;
						PLAYER_COORDS[1]=4;
						changeAnimation(playerAnimLeft);
						EndCutscene();
					}
				}
			}break; 
			case cutscene::WALK_TO_COMPUTER:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						DisplayMessageBox(11);	
						CUTSCENE_FLAGS[0]=true;
					} else
					if (!CUTSCENE_FLAGS[1]) {
						DisplayMessageBox(4);	
						CUTSCENE_FLAGS[1]=true;
					} else {
						vi2d targetPos = GetMapFileCoords(19,4);
						if (CUTSCENE_OBJS[0]->x<19) {
							CUTSCENE_OBJS[0]->x+=MOVE_SPD;
							if (CUTSCENE_OBJS[0]->x>19) {
								CUTSCENE_OBJS[0]->x=19;
							}
						}
						if (CUTSCENE_OBJS[0]->y<4) {
							CUTSCENE_OBJS[0]->y+=MOVE_SPD;
							if (CUTSCENE_OBJS[0]->y>4) {
								CUTSCENE_OBJS[0]->y=4;
							}
						}
						if (CUTSCENE_OBJS[0]->y>4) {
							CUTSCENE_OBJS[0]->y-=MOVE_SPD;
							if (CUTSCENE_OBJS[0]->y<4) {
								CUTSCENE_OBJS[0]->y=4;
							}
						}
						if (MoveCameraTowardsPoint({19,4})) {
							if (!CUTSCENE_FLAGS[2]) {
								DisplayMessageBox(5);
								CUTSCENE_FLAGS[2]=true;
							} else {
								PlayCutscene(cutscene::INPUT_USERNAME);
							}
						}
					}
				}
			}break; 
			case cutscene::GO_OUTSIDE:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_FLAGS[0]=true;
						DisplayMessageBox(12);
					} else
					if (!CUTSCENE_FLAGS[1]) {
						CUTSCENE_FLAGS[1]=true;
						DisplayMessageBox(6);
					} else {
						PLAYER_COORDS[0]=19;
						PLAYER_COORDS[1]=4;
						EndCutscene();
					}
				}
			}break;
			case cutscene::WALK_TO_ROVER:{
				if (MoveObjectTowardsPoint({33,36},CUTSCENE_OBJS[0],HORZ_FIRST)) {
					CUTSCENE_OBJS[0]->spos={64,0};
				}
				if (MoveCameraTowardsPoint({33,36})) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_FLAGS[0]=true;
						CUTSCENE_TIMER=0;
					}
					if (CUTSCENE_TIMER>60) {
						if (!messageBoxVisible) {
							if (!CUTSCENE_FLAGS[3]) {
								CUTSCENE_FLAGS[3]=true;
								DisplayMessageBox(13);
							} else
							if (!CUTSCENE_FLAGS[1]) {
								CUTSCENE_FLAGS[1]=true;
								DisplayMessageBox(7);
							} else
							if (!CUTSCENE_FLAGS[2]) {
								CUTSCENE_FLAGS[2]=true;
								DisplayMessageBox(8);
							} else {
								PlayCutscene(cutscene::DISPLAY_VOLCANIC_AREA);
								fadeOut();
							}
						}
					}
				}
			}break;
			case cutscene::DISPLAY_VOLCANIC_AREA:{
				if (CUTSCENE_FLAGS[0]&&!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[1]) {
						CUTSCENE_FLAGS[1]=true;
						DisplayMessageBox(9);
					} else {
						fadeOut();
						PlayCutscene(cutscene::END_VOLCANIC_AREA_CUTSCENE);
					}
				}
			}break;
			case cutscene::REPAIR_ROVER_1:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_FLAGS[0]=true;
						DisplayMessageBox(16);
					} else 
					if (!CUTSCENE_FLAGS[1]) {
						CUTSCENE_FLAGS[1]=true;
						CUTSCENE_TIMER=0;
					} else 
					if (!CUTSCENE_FLAGS[4]&&CUTSCENE_TIMER>60) {
						for (int i=0;i<OBJECTS.size();i++) {
							if (OBJECTS[i]->x==33&&OBJECTS[i]->y==35) {
								OBJECTS[i]->spr=ROVER_DECAL;
								CUTSCENE_FLAGS[4]=true;
								break;
							}
						}
					} else 
					if (!CUTSCENE_FLAGS[2]&&CUTSCENE_TIMER>120) {
						DisplayMessageBox(17);	
						CUTSCENE_FLAGS[2]=true;
					} else 
					if (!CUTSCENE_FLAGS[3]&&CUTSCENE_TIMER>120) {
						fadeOut();
						CUTSCENE_FLAGS[3]=true;
					}
				}
			}break;
			case cutscene::GET_SOME_REST:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_FLAGS[0]=true;
						DisplayMessageBox(19);
						GAME_FLAGS[gameflag::REST_IN_DOME]=true;
					} else 
					{
						EndCutscene();
					}
				}
			}break;
			case cutscene::IN_BED:{
				if (!CUTSCENE_FLAGS[0]&&MoveCameraTowardsPoint({CUTSCENE_OBJS[0]->x,CUTSCENE_OBJS[0]->y})) {
					CUTSCENE_FLAGS[0]=true;
					CUTSCENE_TIMER=0;
				} else
				if (CUTSCENE_FLAGS[0]&&!CUTSCENE_FLAGS[1]&&CUTSCENE_TIMER>60*4) {
					StartCutscene(cutscene::SHAKE);
				}
			}break;
			case cutscene::SHAKE:{
				if (CUTSCENE_TIMER<60*4) {
					if (frameCount%4==0) {
						PLAYER_COORDS[1]+=0.25;
					} else 
					if (frameCount%4==1) {
						PLAYER_COORDS[1]+=0.25;
					} else 
					if (frameCount%4==2) {
						PLAYER_COORDS[1]-=0.25;
					} else 
					if (frameCount%4==3) {
						PLAYER_COORDS[1]-=0.25;
					}
				} else {
					StartCutscene(cutscene::INVESTIGATE_X_X);
				}
			}break;
			case cutscene::INVESTIGATE_X_X:{
				if (!messageBoxVisible) {
					if (!CUTSCENE_FLAGS[0]) {
						CUTSCENE_FLAGS[0]=true;
						DisplayMessageBox(21);
					} else {
						PLAYER_COORDS[0]=CUTSCENE_OBJS[1]->x;
						PLAYER_COORDS[1]=CUTSCENE_OBJS[1]->y;
						EndCutscene();
						ENCOUNTERS.push_back(ENCOUNTER_X_X);
					}
				}
			}break;
		}

		if (GAME_STATE==CUTSCENE_3&&!SOUND_IS_PLAYING) {
			engine.SetOutputVolume(0.6);
			engine.PlayWaveform(&SONG_MAIN,true);
			SOUND_IS_PLAYING=true;
		}

		switch (GAME_STATE) {
			case CUTSCENE_1:
			case CUTSCENE_3:
			case CUTSCENE_4:{
				switch (GAME_STATE) {
					case CUTSCENE_1:{
						CONSOLE_REF_TEXT=STORY_TEXT1;
					}break;
					case CUTSCENE_3:{
						CONSOLE_REF_TEXT=STORY_TEXT2;
					}break;
					case CUTSCENE_4:{
						CONSOLE_REF_TEXT=STORY_TEXT3;
					}break;
				}
				if (GAME_STATE==CUTSCENE_3&&frameCount%4!=0) {break;}
				if (textInd<CONSOLE_REF_TEXT.length()) {
					char c = CONSOLE_REF_TEXT[textInd++];
					CUTSCENE_CONSOLE_TEXT+=c;
					if (c!='\n') {
						cursorX++;
					} else {
						cursorX=0;
					}
					if (GetTextSize(CUTSCENE_CONSOLE_TEXT).x>WIDTH-32) {
						int tempIndex=textInd;
						while (CUTSCENE_CONSOLE_TEXT[--tempIndex]!=' ') {
							CUTSCENE_CONSOLE_TEXT.erase(tempIndex);
							cursorX--;
						}
						CUTSCENE_CONSOLE_TEXT.erase(tempIndex++);
						CUTSCENE_CONSOLE_TEXT+='\n';
						cursorX=0;
						while (tempIndex<textInd) {
							CUTSCENE_CONSOLE_TEXT+=CONSOLE_REF_TEXT[tempIndex++];
							cursorX++;
						}
					}
				}
			}break;
			case CUTSCENE_2:{
				//FLAG 0 - When flipped on, camera stops.
				if (!CUTSCENE_FLAGS[0]) {
					PLAYER_COORDS[0]+=0.06;
				} else {
					if (CUTSCENE_TIMER>120) {
						fadeOut();
					}
				}
				if (PLAYER_COORDS[0]>38+(128/2/32)) {
					PLAYER_COORDS[0]=38+(128/2/32);
					CUTSCENE_FLAGS[0]=true;
					CUTSCENE_TIMER=0;
				}
			}break;
			case WAITING_FOR_CUTSCENE_3:{
				if (transparency>200) {
					GAME_STATE=CUTSCENE_3;
				}
			}break;
			case COLLECTED_SILICON:{
				if (!messageBoxVisible) {
					if (!GAME_FLAGS[gameflag::COLLECTED_SILICON_1]) {
						GAME_FLAGS[gameflag::COLLECTED_SILICON_1]=true;
						DisplayMessageBox(15);
					} else {
						GAME_STATE=GAMEWORLD;
					}
				}
			}break;
			case LATER_THAT_NIGHTWAIT:{
				if (TIMER>180) {
					fadeOut();
					GAME_STATE=LATER_THAT_NIGHTFADEOUT;
				}
			}break;
		}

		if (PIXEL_EFFECT_TRANSPARENCY>0) {
			for (int i=0;i<PIXEL_LIMIT;i++) {
				pixels[i]->pos+=pixels[i]->spd;
				if (pixels[i]->pos.x<PIXEL_POS.x) {
					pixels[i]->pos.x=PIXEL_POS.x+PIXEL_SIZE.x;
				}
				if (pixels[i]->pos.x>PIXEL_POS.x+PIXEL_SIZE.x) {
					pixels[i]->pos.x=PIXEL_POS.x;
				}
				if (pixels[i]->pos.y<PIXEL_POS.y) {
					pixels[i]->pos.y=PIXEL_POS.y+PIXEL_SIZE.y;
				}
				if (pixels[i]->pos.y>PIXEL_POS.y+PIXEL_SIZE.y) {
					pixels[i]->pos.y=PIXEL_POS.y;
				}
				pixels[i]->a=pixels[i]->o_a*PIXEL_EFFECT_TRANSPARENCY;
			}
		}
	}

	void advanceMessageBox() {
		char c = messageBoxRefText[messageBoxCursor++];
		printf("%c",c);
		if (c=='\n') {
			if (!firstNewline) {
				firstNewline=true;
				return;
			} else if (!secondNewline) {
				secondNewline=true;
				return;
			}
		}
		if (firstNewline&&!secondNewline) {
			messageBoxSpeaker+=c;
			return;
		}
		messageBoxText+=c;
		if (GetTextSizeProp(messageBoxText).x>WIDTH-16) {
			int tempIndex=messageBoxCursor;
			while (messageBoxText[--tempIndex]!=' ') {
				messageBoxText.erase(tempIndex);
			}
			messageBoxText.erase(tempIndex++);
			messageBoxText+='\n';
			while (tempIndex<messageBoxCursor) {
				messageBoxText+=messageBoxRefText[tempIndex++];
			}
		}
	}

	//Triggers when the player has successfully moved.
	void playerMoved(){
		if (!GAME_FLAGS[gameflag::TUTORIAL_WALKED_OFF_FARM]&&foodCount>3&&PLAYER_COORDS[0]>12) {
			GAME_FLAGS[gameflag::TUTORIAL_WALKED_OFF_FARM]=true;
			PlayCutscene(cutscene::WALK_TO_COMPUTER);
			CUTSCENE_OBJS[0]=CreateObject({PLAYER_COORDS[0],PLAYER_COORDS[1]},PLAYER_DECAL,{32,0},{32,32},true);
		} else
		if (!GAME_FLAGS[gameflag::REPAIRED_ROVER_1]&&GAME_FLAGS[gameflag::COLLECTED_SILICON_1]&&PLAYER_COORDS[0]>=31&&PLAYER_COORDS[0]<=35&&PLAYER_COORDS[1]>=33&&PLAYER_COORDS[1]<=37) {
			GAME_FLAGS[gameflag::REPAIRED_ROVER_1]=true;
			PlayCutscene(cutscene::REPAIR_ROVER_1);
		}
	}

	void drawGame(){
		switch (GAME_STATE) {
			case CUTSCENE_1:
			case CUTSCENE_4:{
				DrawStringDecal({16,16},CUTSCENE_CONSOLE_TEXT,GREEN,{1,1});
				if (textInd<STORY_TEXT1.length()) {
					FillRectDecal({(float)(16+(cursorX)*8%(WIDTH-32)),(float)(8+GetTextSize(CUTSCENE_CONSOLE_TEXT).y+((cursorX==28)?8:0))},{4,8},GREEN);
				} else {
					FillRectDecal({(float)(16+(cursorX)*8%(WIDTH-32)),(float)(8+GetTextSize(CUTSCENE_CONSOLE_TEXT).y+((cursorX==28)?8:0))},{4,8},Pixel(0,255,0,(0.5*sin(frameCount*4/60.0)+0.5)*256));
				}
				GradientFillRectDecal({0,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1});
				GradientFillRectDecal({WIDTH/2,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
				GradientFillRectDecal({0,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2});
				GradientFillRectDecal({WIDTH/2,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
			}break;
			case CUTSCENE_2:
			case GAMEWORLD:
			case COLLECTED_SILICON:{
				DrawGameWorld();
				int meterYOffset=2;
				if (CURRENT_CUTSCENE==cutscene::NONE) {
					SetDrawTarget(nullptr);
					if (foodMeterVisible) {
						DrawStringDecal({(float)(WIDTH-36*0.4-GetTextSize(std::to_string(foodCount)).x*1-8),(float)(meterYOffset+1)},std::to_string(foodCount),BLACK,{1,1});
						DrawStringDecal({(float)(WIDTH-36*0.4-GetTextSize(std::to_string(foodCount)).x*1-7),(float)(meterYOffset+2)},std::to_string(foodCount),WHITE,{1,1});
						DrawDecal({(float)(WIDTH-52*0.4),(float)(meterYOffset)},FOOD_METER_DECAL,{0.4,0.4});
						meterYOffset+=(2+48*0.4);
					}
					if (oxygenMeterVisible) {
						DrawStringDecal({(float)(WIDTH-36*0.4-GetTextSize(std::to_string(oxygenQualityLevel)+"%").x*1-8),(float)(meterYOffset+1)},std::to_string(oxygenQualityLevel)+"%",BLACK,{1,1});
						DrawStringDecal({(float)(WIDTH-36*0.4-GetTextSize(std::to_string(oxygenQualityLevel)+"%").x*1-7),(float)(meterYOffset+2)},std::to_string(oxygenQualityLevel)+"%",WHITE,{1,1});
						DrawDecal({(float)(WIDTH-52*0.4),(float)(meterYOffset)},OXYGEN_METER_DECAL,{0.4,0.4});
						meterYOffset+=(2+48*0.4);
					}
					SetDrawTarget(2);
					if (IN_BATTLE_ENCOUNTER) {
						DrawPartialDecal({(float)((BATTLE_PLAYER_COORDS.x-PLAYER_COORDS[0])*32+WIDTH/2-16+(current_playerAnim->flipped?32:0)),(float)((BATTLE_PLAYER_COORDS.y-PLAYER_COORDS[1])*32+HEIGHT/2-16)},current_playerAnim->spr,current_playerAnim->getCurrentFrame(),{32,32},{(float)(current_playerAnim->flipped?-1:1),1});
					} else {
						DrawPartialDecal({(float)(WIDTH/2-16+(current_playerAnim->flipped?32:0)),(float)(HEIGHT/2-16)},current_playerAnim->spr,current_playerAnim->getCurrentFrame(),{32,32},{(float)(current_playerAnim->flipped?-1:1),1});
					}
					if (IN_BATTLE_ENCOUNTER&&BATTLE_ENTRY_TIMER<45) {
						DrawStringDecal({(float)((BATTLE_PLAYER_COORDS.x-PLAYER_COORDS[0])*32+WIDTH/2-16+(current_playerAnim->flipped?32:0)),(float)((BATTLE_PLAYER_COORDS.y-PLAYER_COORDS[1])*32+HEIGHT/2-16-sin(frameCount*12/60.0)*4-12)},"!!",RED);
					}
				}
			}break;
			case CUTSCENE_3:{
				DrawStringDecal({48,16},CUTSCENE_CONSOLE_TEXT,Pixel(100, 10, 255),{2,2});
				if (textInd<STORY_TEXT2.length()) {
					FillRectDecal({(float)(48+(cursorX)*16%(WIDTH-32)),(float)(GetTextSize(CUTSCENE_CONSOLE_TEXT).y*2+((cursorX==28)?16:0))},{4*2,8*2},Pixel(100, 10, 255));
				} else {
					FillRectDecal({(float)(48+(cursorX)*16%(WIDTH-32)),(float)(GetTextSize(CUTSCENE_CONSOLE_TEXT).y*2+((cursorX==28)?16:0))},{4*2,8*2},Pixel(100, 10, 255,(0.5*sin(frameCount*4/60.0)+0.5)*256));
				}
				for (int i=0;i<4;i++) {
					std::string tempStr = MENU_OPTIONS[i];
					if (MAIN_MENU_SELECTION==i) {
						tempStr="> "+tempStr+" <";
					}
					DrawStringDecal({(float)(WIDTH/2-GetTextSize(tempStr).x*2/2),(float)(HEIGHT/2-GetTextSize(tempStr).y*2+32*i)},tempStr,(MAIN_MENU_SELECTION==i)?MAGENTA:WHITE,{2,2});
				}
				GradientFillRectDecal({0,0},{WIDTH/2,HEIGHT/2},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN2},{100, 10, 255,ALPHA_SCREEN1});
				GradientFillRectDecal({WIDTH/2,0},{WIDTH/2,HEIGHT/2},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN2},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1});
				GradientFillRectDecal({0,HEIGHT/2},{WIDTH/2,HEIGHT/2},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN2});
				GradientFillRectDecal({WIDTH/2,HEIGHT/2},{WIDTH/2,HEIGHT/2},{100, 10, 255,ALPHA_SCREEN2},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1},{100, 10, 255,ALPHA_SCREEN1});
			}break;
			case LATER_THAT_NIGHTFADEIN:
			case LATER_THAT_NIGHTFADEOUT:
			case LATER_THAT_NIGHTWAIT:{
				DrawDecal({(float)(WIDTH/2-LATER_THAT_NIGHT_DECAL->sprite->width/2),(float)(HEIGHT/2-LATER_THAT_NIGHT_DECAL->sprite->height/2)},LATER_THAT_NIGHT_DECAL);
			}break;
		}
		switch (BATTLE_STATE) {
			case battle::PLAYER_SELECTION:{
				SetDrawTarget(nullptr);
				DrawCard(availablePowers[(BATTLE_CARD_SELECTION_IND+1)%availablePowers.size()],{WIDTH-96,32},{0.7,0.7},0.4);
				DrawCard(availablePowers[(BATTLE_CARD_SELECTION_IND-1<0)?availablePowers.size()-1:BATTLE_CARD_SELECTION_IND-1],{-96,32},{0.7,0.7},0.4);
				DrawCard(BATTLE_CARD_SELECTION);
			}break;
			case battle::PLAYER_TARGET_SELECTION:{
				if (PLAYER_SELECTED_TARGET>=0) {
					DrawWrappedText({5,5},"Use "+BATTLE_CARD_SELECTION->name+" on "+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->name+" "+(char)('A'+PLAYER_SELECTED_TARGET),WIDTH-8,BLACK,{2,2});
					DrawWrappedText({4,4},"Use "+BATTLE_CARD_SELECTION->name+" on "+CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->name+" "+(char)('A'+PLAYER_SELECTED_TARGET),WIDTH-8,WHITE,{2,2});
					DrawStringDecal({(float)(WIDTH-GetTextSize("<UP> Back").x-1),(float)(HEIGHT-GetTextSize("<UP> Back").y-1)},"<UP> Back",BLACK,{1,1});
					DrawStringDecal({(float)(WIDTH-GetTextSize("<UP> Back").x-2),(float)(HEIGHT-GetTextSize("<UP> Back").y-2)},"<UP> Back",GREEN,{1,1});
				}
			}break;
			case battle::WAIT_TURN_ANIMATION:{
				if (BATTLE_CURRENT_TURN_ENTITY==-1) {
					DrawWrappedText({4,4},"Player uses "+BATTLE_CARD_SELECTION->name,WIDTH-8,WHITE,{2,2});
				} else {
					DrawWrappedText({4,4},CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->name+" "+(char)('A'+BATTLE_CURRENT_TURN_ENTITY)+" uses "+CURRENT_ENCOUNTER.entities[BATTLE_CURRENT_TURN_ENTITY]->selectedMove->name,WIDTH-8,WHITE,{2,2});
				}
			}break;
			case battle::WAIT_TURN_ANIMATION2:{
				switch (BATTLE_REASON_CODE) {
					case reasoncode::SEED_GROWTH:{
						DrawWrappedText({5,5},"The seeds grow into lush trees!",WIDTH-8,DARK_GREEN,{2,2});
						DrawWrappedText({4,4},"The seeds grow into lush trees!",WIDTH-8,WHITE,{2,2});
					}break;
					case reasoncode::TREE_BURN:{
						DrawWrappedText({5,5},"The trees cause rampaging fires!",WIDTH-8,DARK_RED,{2,2});
						DrawWrappedText({4,4},"The trees cause rampaging fires!",WIDTH-8,WHITE,{2,2});
					}break;
				}
			}break;
		}
		if (IN_BATTLE_ENCOUNTER||(GAME_STATE==GAMEWORLD&&!CUTSCENE_ACTIVE&&PLAYER_HP!=PLAYER_MAXHP)) {
			DrawStringDecal({4+1,(float)(HEIGHT-10-GetTextSize("HP:").y+1)},"HP: "+std::to_string(PLAYER_HP),BLACK);
			DrawStringDecal({4,(float)(HEIGHT-10-GetTextSize("HP:").y)},"HP: "+std::to_string(PLAYER_HP));
			DrawHealthbar({2,HEIGHT-10},WIDTH/2,(float)PLAYER_HP/PLAYER_MAXHP,BLACK);
			for (auto&numb:BATTLE_DISPLAY_NUMBERS) {
				std::string display=((numb->number>0)?"-"+std::to_string(numb->number):"+"+std::to_string(numb->number*-1));
				for (int x=-1;x<=1;x++) {
					for (int y=-1;y<=1;y++) {
						if (x!=0&&y!=0) {
							DrawStringDecal({((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x*1.3/2+x-8,((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-12-GetTextSize(display).y*1.3/2+y},display,(numb->number>0)?Pixel(255,0,0,numb->alpha):Pixel(0,255,0,numb->alpha),{1.3,1.3});
						}
 					}
				}
				DrawStringDecal({((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x*1.3/2-8,((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-12-GetTextSize(display).y*1.3/2},display,Pixel(255,255,255,numb->alpha),{1.3,1.3});
				//std::cout<<numb->x<<"/"<<numb->y<<" "<<(((numb->x-PLAYER_COORDS[0])*32+WIDTH/2)-GetTextSize(display).x/2)<<","<<(((numb->y-PLAYER_COORDS[1])*32+HEIGHT/2)-8-GetTextSize(display).y/2)<<": ("<<numb->alpha<<")"<<display<<"\n";
			}
		}
		if (PIXEL_EFFECT_TRANSPARENCY>0) {
			SetDrawTarget(1);
			for (int i=0;i<PIXEL_LIMIT;i++) {
				if (pixels[i]->size.x==1&&pixels[i]->size.y==1) {
					Draw(pixels[i]->pos,{(uint8_t)(pixels[i]->r),(uint8_t)(pixels[i]->g),(uint8_t)(pixels[i]->b),(uint8_t)(pixels[i]->a)});
				} else {
					FillRectDecal(pixels[i]->pos,pixels[i]->size,{(uint8_t)(pixels[i]->r),(uint8_t)(pixels[i]->g),(uint8_t)(pixels[i]->b),(uint8_t)(pixels[i]->a)});
				}
			}
			FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(ORIGINAL_FOREGROUND_EFFECT_COLOR.r,ORIGINAL_FOREGROUND_EFFECT_COLOR.g,ORIGINAL_FOREGROUND_EFFECT_COLOR.b,ORIGINAL_FOREGROUND_EFFECT_COLOR.a*PIXEL_EFFECT_TRANSPARENCY));
			SetDrawTarget(2);
		}
		if (messageBoxVisible) {
			SetDrawTarget(nullptr);
			DrawDialogBox({4,HEIGHT-60},{WIDTH/2,16},Pixel(18, 0, 33,180));
			DrawDialogBox({0,HEIGHT-48},{WIDTH,48},Pixel(18, 0, 33,180));
			DrawStringPropDecal({8,HEIGHT-40},messageBoxText);
			DrawStringPropDecal({8,HEIGHT-57},messageBoxSpeaker);
			if (messageBoxCursor==messageBoxRefText.length()) {
				DrawStringPropDecal({WIDTH-16-(float)sin(frameCount*8/60.0)*3,HEIGHT-8+(float)(cos(frameCount*6/60.0)*0.6)},"v",Pixel(173, 74, 255,(0.5*sin(frameCount*8/60.0)+0.5)*128+128),{(float)sin(frameCount*8/60.0),0.5});
			}
			SetDrawTarget(2);
		}
		switch (CURRENT_CUTSCENE) {
			case cutscene::NODE_COLLECT_CUTSCENE:{
				FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,128));
				DrawCard(CUTSCENE_DISPLAYED_CARD);
			}break;
			case cutscene::INPUT_USERNAME:{
				FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,128));
				DrawTerminal();
			}break;
			case cutscene::IN_BED:{
				FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,192));
			}break;
		}
		FillRectDecal({0,0},{WIDTH,HEIGHT},Pixel(0,0,0,transparency));
		//FillRectDecal({WIDTH/2-2,HEIGHT/2-2},{4,4},WHITE);
	}

	void DrawGameWorld() {
		for (int y=-1;y<=HEIGHT/32+1;y++) {
			for (int x=-1;x<=WIDTH/32+1;x++) {
				float xOffset=PLAYER_COORDS[0]-(WIDTH/32/2);
				float yOffset=PLAYER_COORDS[1]-(HEIGHT/32/2);
				srand((int)(yOffset+y)*MAP_WIDTH+(int)(xOffset+x));
				int tileX=0;
				int tileRot=0;
				while (tileX<3&&std::rand()%4==0) {
					tileX++;
				}
				while (tileRot<3&&std::rand()%8<5) {
					tileRot++;
				}
				if ((int)(xOffset+x)>=0&&(int)(xOffset+x)<MAP_WIDTH&&(int)(yOffset+y)>=0&&(int)(yOffset+y)<MAP_HEIGHT) {
					DrawPartialRotatedDecal({(float)((x-(PLAYER_COORDS[0]-(int)PLAYER_COORDS[0])+1)*32-16),(float)((y-(PLAYER_COORDS[1]-(int)PLAYER_COORDS[1])+1)*32)},TILES,tileRot*M_PI_2,{16,16},{(float)(tileX*32),0},{32,32},{1,1},TILE_COLORS[MAP[(int)(yOffset+y)][(int)(xOffset+x)]]);
				}
			}
		}
		for (auto&obj:OBJECTS) {
			if (obj->spr!=NULL) {
				if (obj->name.compare("PLANT")==0) {
					DrawPartialDecal({(float)((obj->x-PLAYER_COORDS[0])*32+WIDTH/2),(float)((obj->y-PLAYER_COORDS[1])*32+HEIGHT/2)},{32,32},obj->spr,{(float)(getPlantStatus(obj->x,obj->y)*32),0},{32,32});
				} else {
					if (obj->name.find("NODE")!=std::string::npos) {
						DrawDecal({(obj->x-PLAYER_COORDS[0])*32+WIDTH/2-32+18,(obj->y-PLAYER_COORDS[1])*32+HEIGHT/2-32+26},WEATHERNODE_EFFECT_DECAL);
						DrawPartialDecal({(float)((obj->x-PLAYER_COORDS[0])*32+WIDTH/2-16*(float)sin(frameCount*2/60.0)+16),(float)((obj->y-PLAYER_COORDS[1])*32+HEIGHT/2)},obj->anim->spr,{(float)(obj->anim->getCurrentFrame().x),(float)(obj->anim->getCurrentFrame().y)},{(float)(obj->anim->width),(float)(obj->anim->height)},{(float)sin(frameCount*2/60.0),1},Pixel((float)sin(frameCount*4/60.0)*55+200,(float)sin(frameCount*4/60.0)*55+200,(float)sin(frameCount*4/60.0+M_PI)+65*125,255));
					} else
					if (obj->hasAnim) {
						DrawPartialDecal({(obj->x-PLAYER_COORDS[0])*32+WIDTH/2+(obj->anim->flipped?obj->anim->width:0),(obj->y-PLAYER_COORDS[1])*32+HEIGHT/2},obj->anim->spr,{(float)(obj->anim->getCurrentFrame().x),(float)(obj->anim->getCurrentFrame().y)},{(float)(obj->anim->width),(float)(obj->anim->height)},{(float)(obj->anim->flipped?-1:1),1},obj->col);
					} else 
					if (obj->hascut) {
						DrawPartialDecal({(obj->x-PLAYER_COORDS[0])*32+WIDTH/2+(obj->flipped?obj->size.x:0),(obj->y-PLAYER_COORDS[1])*32+HEIGHT/2},obj->spr,obj->spos,obj->size,{(float)(obj->flipped?-1:1),1},obj->col);
					} else {
						DrawDecal({(obj->x-PLAYER_COORDS[0])*32+WIDTH/2,(obj->y-PLAYER_COORDS[1])*32+HEIGHT/2},obj->spr,{1,1},obj->col);
					}
				}
			} else 
			if (obj->name.compare("EXIT")==0) {
				GradientFillRectDecal({(obj->x-PLAYER_COORDS[0])*32+WIDTH/2,(obj->y-PLAYER_COORDS[1])*32+HEIGHT/2},{32,32},Pixel(0,0,0,0),WHITE,WHITE,Pixel(0,0,0,0));
			}
		}
		if (IN_BATTLE_ENCOUNTER) {
			const vi2d CENTER = {(float)((BATTLE_PLAYER_COORDS.x-PLAYER_COORDS[0])*32+WIDTH/2+(current_playerAnim->flipped?32:0)),(float)((BATTLE_PLAYER_COORDS.y-PLAYER_COORDS[1])*32+HEIGHT/2)};
			for (int i=0;i<SEEDS.size();i++) {
				DrawDecal(SEEDS[i]->pos+CENTER,SEED_DECAL,{0.5,0.5});
			}
			for (int i=0;i<TREES.size();i++) {
				DrawDecal(TREES[i]->pos+CENTER,TREE_DECAL,{1,1});
			}
		}
		for (auto&enc:ENCOUNTERS) {
			if (enc.map==CURRENT_MAP) {
				int targetX=-1,targetY=-1;
				for (auto&ent:enc.entities) {
						if (BATTLE_STATE==battle::PLAYER_TARGET_SELECTION&&PLAYER_SELECTED_TARGET>=0&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->hp>0&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->x==ent->x&&CURRENT_ENCOUNTER.entities[PLAYER_SELECTED_TARGET]->y==ent->y) {
							DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},TARGETING_CIRCLE,{(float)(ent->spr->sprite->width*ent->sprScale.x/32),(float)(ent->spr->sprite->height*ent->sprScale.y/32)},{255,210,0,255});
							DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},ent->spr,ent->sprScale,{(uint8_t)((0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175),(uint8_t)((0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175),(uint8_t)((0.5*(float)sin(frameCount*4/60.0)+0.5)*80+175),255});
							targetX=ent->x;targetY=ent->y;
						} else {
							if (ent->hp>0) {//Outside battles.
								DrawDecal({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2},ent->spr,ent->sprScale);
							}
						}
						if (ent->hp>0) {
							DrawHealthbar({(enc.x+ent->x-PLAYER_COORDS[0])*32+WIDTH/2,(enc.y+ent->y-PLAYER_COORDS[1])*32+HEIGHT/2+ent->spr->sprite->height*ent->sprScale.y+2},ent->spr->sprite->width*ent->sprScale.x,(float)ent->hp/ent->maxhp,BLACK);
						}
				}
				if (targetX!=-1&&targetY!=-1) {
					DrawDecal({(enc.x+targetX-PLAYER_COORDS[0])*32+enc.entities[PLAYER_SELECTED_TARGET]->spr->sprite->width/2*enc.entities[PLAYER_SELECTED_TARGET]->sprScale.x+WIDTH/2-BATTLE_CARD_SELECTION->range,(enc.y+targetY-PLAYER_COORDS[1])*32+enc.entities[PLAYER_SELECTED_TARGET]->spr->sprite->height/2*enc.entities[PLAYER_SELECTED_TARGET]->sprScale.y+HEIGHT/2-BATTLE_CARD_SELECTION->range},TARGETING_RANGE_CIRCLE,{(float)(BATTLE_CARD_SELECTION->range*2/32.0),(float)(BATTLE_CARD_SELECTION->range*2/32.0)},{255,60,0,(uint8_t)((0.5*(float)sin(frameCount*4/60.0)+0.5)*100)});
				}
			}
		}
	}

	void DrawHealthbar(vf2d pos,float width,float pct,Pixel col) {
		GradientFillRectDecal(pos,{width*pct,8},RED,RED,Pixel((1/pct)*255,255*pct,0,255),Pixel((1/pct)*255,255*pct,0,255));
		DrawDecal(pos,HEALTHBAR_DECAL,{width/32,1},col);
	}

	void DrawTerminal() {
		const int TERMINAL_WIDTH=7;
		for (int i=0;i<26;i++) {
			std::string s(1,(char)('A'+i));
			DrawStringDecal({(float)((32*(i%TERMINAL_WIDTH))+16),(float)(16*(i/TERMINAL_WIDTH)+HEIGHT/2)},s);
		}
		std::string backspace(1,(char)('<'));
		DrawStringDecal({(float)((32*(26%TERMINAL_WIDTH))+16),(float)(16*(26/TERMINAL_WIDTH)+HEIGHT/2)},backspace);
		DrawStringDecal({(float)((32*(27%TERMINAL_WIDTH))+16),(float)(16*(27/TERMINAL_WIDTH)+HEIGHT/2)},"ENTER");
		DrawStringDecal({(float)((32*((TERMINAL_SELECTED_CHAR)%TERMINAL_WIDTH))+8),(float)(16*(TERMINAL_SELECTED_CHAR/TERMINAL_WIDTH)+HEIGHT/2)},">");
		std::string terminal_name=TERMINAL_INPUT;
		for (int i=0;i<MAX_TERMINAL_NAME_LENGTH-TERMINAL_INPUT.length();i++) {
			terminal_name+="*";
		}
		DrawStringDecal({(float)(WIDTH/2-GetTextSize(terminal_name).x*2/2),(float)(HEIGHT/3-GetTextSize(terminal_name).y*2/2)}, terminal_name,olc::WHITE,{2.0,2.0});

		GradientFillRectDecal({0,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1});
		GradientFillRectDecal({WIDTH/2,0},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
		GradientFillRectDecal({0,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN2});
		GradientFillRectDecal({WIDTH/2,HEIGHT/2},{WIDTH/2,HEIGHT/2},{20, 28, 22,ALPHA_SCREEN2},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1},{20, 28, 22,ALPHA_SCREEN1});
	}

	int getPlantId(int x, int y) {
		return ((int)x-8)%4+((int)y-2)*4;
	}

	int getPlantStatusWithAbsoluteCoords(int x,int y) {
		return plantState>>getPlantId(x+8,y+2)*2&0b11;
	}

	//This uses MAP COORDS for determining bit location. The plants are offset by (X+8,Y+2)!! Use getPlantStatusWithAbsoluteCoords() to translate to map coords.
	int getPlantStatus(int x,int y) {
		return plantState>>getPlantId(x,y)*2&0b11;
	}

	void setPlantStatusWithAbsoluteCoords(int x,int y,char state) {
		setPlantStatus(x+8,y+2,state);
	}

	//This uses MAP COORDS for determining bit location. The plants are offset by (X+8,Y+2)!! Use setPlantStatusWithAbsoluteCoords() to translate to map coords.
	void setPlantStatus(int x,int y,char state) {
		int mask=0b11111111111111111111111111111111;
		mask-=3<<getPlantId(x,y)*2;
		plantState&=mask;
		plantState|=state<<getPlantId(x,y)*2;
	}

	void DrawDialogBox(const vi2d &pos, const vi2d &size, Pixel p = WHITE, Pixel p2 = DARK_GREY, Pixel p3 = VERY_DARK_GREY) {
		FillRectDecal({(float)pos.x,(float)pos.y},size,p2);
		FillRectDecal({(float)pos.x+1,(float)pos.y+1},{(float)size.x-2,(float)size.y-2},p);
		FillRectDecal({(float)pos.x+2,(float)pos.y+2},{(float)size.x-4,(float)size.y-4},p3);
		FillRectDecal({(float)pos.x+3,(float)pos.y+3},{(float)size.x-5,(float)size.y-5},p);
		Draw({pos.x,pos.y},BLACK);
		Draw({pos.x+size.x,pos.y+size.y},BLACK);
		Draw({pos.x+size.x,pos.y},BLACK);
		Draw({pos.x,pos.y+size.y},BLACK);
	}

	void fadeOut() {
		fade=true;
	}
	void fadeIn() {
		fade=false;
	}

	void audioFadeOut() {
		audioFade=true;
	}
	void audioFadeIn() {
		audioFade=false;
	}

	void StopCutscene() {
		EndCutscene();
	}

	void EndCutscene() {
		CURRENT_CUTSCENE=cutscene::NONE;
		ClearAllTemporaryObjects();
	}

	void DisplayMessageBox(int dialogNumber) {
		performCropUpdate(10);
		messageBoxVisible=true;
		messageBoxCursor=0;
		std::string split1=STORY_DIALOG[dialogNumber].substr(0,STORY_DIALOG[dialogNumber].find('\n')); //Unused for now.
		std::string split2=STORY_DIALOG[dialogNumber].substr(STORY_DIALOG[dialogNumber].find('\n')+1,STORY_DIALOG[dialogNumber].find('\n',STORY_DIALOG[dialogNumber].find('\n')+1)-(STORY_DIALOG[dialogNumber].find('\n')+1));
		std::string split3=STORY_DIALOG[dialogNumber].substr(STORY_DIALOG[dialogNumber].find('\n',STORY_DIALOG[dialogNumber].find('\n')+1)+1,STORY_DIALOG[dialogNumber].length()-(STORY_DIALOG[dialogNumber].find('\n',STORY_DIALOG[dialogNumber].find('\n')+1)+1));
		messageBoxSpeaker=(split2.compare("$PLAYER")==0)?split2.replace(0,split2.length(),PLAYER_NAME):split2;
		messageBoxText="";
		messageBoxRefText=split3;
	}

	void LoadMap(Map*map) {
		std::ifstream f("assets/maps/"+map->filename);
		std::string data;
		CURRENT_MAP=map;
		MAP_WIDTH=MAP_HEIGHT=-1;
		if (MAP!=NULL) {
			for (int y=0;y<MAP_HEIGHT;y++) {
				free(MAP[y]);
			}
			free(MAP);
			MAP=NULL;
		}
		for (int i=0;i<OBJECTS.size();i++) {
			delete OBJECTS[i];
		}
		OBJECTS.clear();

		int y=0;
		if (f.is_open()) {
			while (f.good()) {
				f>>data;
				if (MAP_WIDTH==-1) {
					std::stringstream stream(data);
					stream>>MAP_WIDTH;
				} else
				if (MAP_HEIGHT==-1) {
					std::stringstream stream(data);
					stream>>MAP_HEIGHT;
				} else 
				if (y<MAP_HEIGHT) {
					if (MAP==NULL) {
						MAP=(int**)malloc(sizeof(int**)*MAP_HEIGHT);
					}
					MAP[y]=(int*)malloc(sizeof(int*)*MAP_WIDTH);
					for (int i=0;i<data.length();i++) {
						MAP[y][i]=data[i]-'0';
					}
					y++;
				} else {
					std::stringstream split1(data.substr(0,data.find(';')));
					std::stringstream split2(data.substr(data.find(';')+1,data.find(';',data.find(";")+1)-(data.find(';')+1)));
					int x,y;
					split1>>x;
					split2>>y;
					bool alreadyCollected=false;
					bool alreadyRepaired=false;
					for (int i=0;i<COLLECTED_ITEMS.size();i++) {
						if (x==COLLECTED_ITEMS[i].x&&y==COLLECTED_ITEMS[i].y) {
							alreadyCollected=true;
							break;
						}
					}
					for (int i=0;i<REPAIRED_ROVERS.size();i++) {
						if (x==REPAIRED_ROVERS[i].x&&y==REPAIRED_ROVERS[i].y) {
							alreadyRepaired=true;
							break;
						}
					}
					if (!alreadyCollected) {
						Object*obj = new Object();
						obj->x=x;
						obj->y=y;
						std::string split3 = data.substr(data.find(';',data.find(";")+1)+1,data.length()-(data.find(';',data.find(";")+1)+1));
						if (split3.compare("NULL")!=0) {
							if (alreadyRepaired) {
								obj->spr=ROVER_DECAL;
							} else {
								obj->spr=BASE_OBJECTS[split3]->spr;
							}
							obj->col=BASE_OBJECTS[split3]->col;
							if (BASE_OBJECTS[split3]->hasanim) {
								obj->hasAnim=true;
								obj->anim=BASE_OBJECTS[split3]->anim;
							} else 
							if (BASE_OBJECTS[split3]->hascut){
								obj->hascut=true;
								obj->spos=BASE_OBJECTS[split3]->spos;
								obj->size=BASE_OBJECTS[split3]->size;
							}
						} else {
							obj->spr=NULL;
						}
						obj->name=split3;
						printf("Loaded object %s: (%f,%f)\n",split3.c_str(),obj->x,obj->y);
						OBJECTS.push_back(obj);
					}
				}
			}
		}
		printf("Loaded %dx%d map:\n",MAP_WIDTH,MAP_HEIGHT);
		for (int y=0;y<MAP_HEIGHT;y++) {
			for (int x=0;x<MAP_WIDTH;x++) {
				printf("%d",MAP[y][x]);
			}
			printf("\n");
		}
	}

	void changeAnimation(Animation*anim) {
		current_playerAnim=anim;
		current_playerAnim->frame=0;
	}

	bool collidesWithPlayer(Object*obj) {
		if (obj->hasAnim) {
			return PLAYER_COORDS[0]>=obj->x&&PLAYER_COORDS[0]<=obj->x+obj->anim->width/32.0&&
			PLAYER_COORDS[1]>=obj->y&&PLAYER_COORDS[1]<=obj->y+obj->anim->height/32.0;
		} else {
			if (obj->spr==NULL) {
				return PLAYER_COORDS[0]>=obj->x&&PLAYER_COORDS[0]<=obj->x+1&&
				PLAYER_COORDS[1]>=obj->y&&PLAYER_COORDS[1]<=obj->y+1;
			} else {
				return PLAYER_COORDS[0]>=obj->x&&PLAYER_COORDS[0]<=obj->x+obj->spr->sprite->width/32.0&&
				PLAYER_COORDS[1]>=obj->y&&PLAYER_COORDS[1]<=obj->y+obj->spr->sprite->height/32.0;
			}
		}
	}

	bool collidesWithPlayer(Encounter obj) {
		return PLAYER_COORDS[0]>=obj.x&&PLAYER_COORDS[0]<=obj.x+WIDTH/32&&
		PLAYER_COORDS[1]>=obj.y&&PLAYER_COORDS[1]<=obj.y+HEIGHT/32;
	}

	void DrawWrappedText(vf2d pos,std::string text,int targetWidth,Pixel col,vf2d scale) {
		std::string wrappedText;
		int marker=0;
		while (marker<text.length()) {
			wrappedText+=text[marker];
			if (GetTextSize(wrappedText).x*scale.x>targetWidth) {
				int tempMarker=marker;
				while (wrappedText[tempMarker]!=' ') {
					wrappedText.erase(tempMarker--);
				}
				wrappedText.erase(tempMarker++);
				wrappedText+='\n';
				while (tempMarker<marker+1) {
					wrappedText+=text[tempMarker++];
				}
			}
			marker++;
		}
		DrawStringDecal(pos,wrappedText,col,scale);
	}

	void DrawWrappedPropText(vf2d pos,std::string text,int targetWidth,Pixel col,vf2d scale) {
		std::string wrappedText;
		int marker=0;
		while (marker<text.length()) {
			wrappedText+=text[marker];
			if (GetTextSizeProp(wrappedText).x*scale.x>targetWidth) {
				int tempMarker=marker;
				while (wrappedText[tempMarker]!=' ') {
					wrappedText.erase(tempMarker--);
				}
				wrappedText.erase(tempMarker++);
				wrappedText+='\n';
				while (tempMarker<marker+1) {
					wrappedText+=text[tempMarker++];
				}
			}
			marker++;
		}
		DrawStringPropDecal(pos,wrappedText,col,scale);
	}

	bool playerCanMove() {
		return GAME_STATE==GAMEWORLD&&CURRENT_CUTSCENE==cutscene::NONE&&!messageBoxVisible&&!IN_BATTLE_ENCOUNTER;
	}

	void DrawCard(WEATHER_POWER*data,vf2d offset={0,0},vf2d scale={1,1},float darknessFactor=1.0) {
		float dimColor=data->playerOwnCount==0?0.4:1;
		
		GradientFillRectDecal({(WIDTH/6)*scale.x+offset.x,(HEIGHT/6)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor);
		GradientFillRectDecal({(WIDTH/6*3+1)*scale.x+offset.x,(HEIGHT/6)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor);
		GradientFillRectDecal({(WIDTH/6)*scale.x+offset.x,(HEIGHT/6*3)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,Pixel(72, 160, 212,0));
		GradientFillRectDecal({(WIDTH/6*3+1)*scale.x+offset.x,(HEIGHT/6*3)*scale.y+offset.y},{WIDTH/3*scale.x,HEIGHT/6*2*scale.y},Pixel(72, 160, 212,0),data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor,data->bgcol*darknessFactor*dimColor);
		
		DrawPartialDecal({(WIDTH/2-data->anim->width/2*3)*scale.x+offset.x,(HEIGHT/6+16-data->anim->height/2)*scale.y+offset.y},data->anim->spr,data->anim->getCurrentFrame(),{(float)(data->anim->width),(float)(data->anim->height)},{3*scale.x,3*scale.y},WHITE*darknessFactor*dimColor);
		for (int x=-1;x<=1;x++) {
			for (int y=-1;y<=1;y++) {
				if (x!=0&&y!=0) {
					DrawStringPropDecal({(WIDTH/6+4+x)*scale.x+offset.x,(HEIGHT/2+8+y)*scale.y+offset.y},data->name,BLACK,{2*scale.x,2*scale.y});
				}
			}
		}
		DrawStringPropDecal({(WIDTH/6+4)*scale.x+offset.x,(HEIGHT/2+8)*scale.y+offset.y},data->name,data->textcol*darknessFactor*dimColor,{2*scale.x,2*scale.y});
		DrawWrappedPropText({(WIDTH/6+4+1)*scale.x+offset.x,(HEIGHT/2+24+1)*scale.y+offset.y},data->description,(WIDTH/3*2-8)*scale.x,BLACK,{scale.x,scale.y});
		DrawWrappedPropText({(WIDTH/6+4)*scale.x+offset.x,(HEIGHT/2+24)*scale.y+offset.y},data->description,(WIDTH/3*2-8)*scale.x,Pixel(227, 245, 255,255)*darknessFactor*dimColor,{scale.x,scale.y});
		for (int x=-1;x<=1;x++) {
			for (int y=-1;y<=1;y++) {
				if (x!=0&&y!=0) {
					DrawStringPropDecal({(float)((WIDTH/6+4+WIDTH/3*2-8-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").x*1.5+x)*scale.x+offset.x),(float)((HEIGHT/6*3+HEIGHT/6*2-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").y*1.5-4+y))*scale.y+offset.y},std::to_string(data->playerOwnCount)+" uses remaining.",olc::BLACK,{(float)(1.5*scale.x),(float)(1.5*scale.y)});
				}
			}
		} 
		DrawStringPropDecal({(float)((WIDTH/6+4+WIDTH/3*2-8-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").x*1.5)*scale.x+offset.x),(float)((HEIGHT/6*3+HEIGHT/6*2-GetTextSizeProp(std::to_string(data->playerOwnCount)+" uses remaining.").y*1.5-4)*scale.y+offset.y)},std::to_string(data->playerOwnCount)+" uses remaining.",(data->playerOwnCount==0)?olc::RED:olc::WHITE*darknessFactor,{(float)(1.5*scale.x),(float)(1.5*scale.y)});
		
	}

	void effectRadius(vi2d coords,WEATHER_POWER*power,bool playerForce) {
		int finalDamage=power->damage+rand()%power->damageRoll*sign(power->damage);
		effectRadius(coords,power,finalDamage,playerForce);
	}

	void effectRadius(vi2d coords,WEATHER_POWER*power,int finalDamage,bool playerForce) {
		std::cout<<"Emitting effect radius for "<<power->name<<" for PlayerForce:"<<playerForce<<"\n";
		if (finalDamage<0) {
			//This is a healing effect.
			if (playerForce) {
				if (power->damage==-1002) {
					//Instead heal for their max health.
					PLAYER_MAXHP+=5;
					finalDamage=-PLAYER_MAXHP;
					foodCount--;
				} else
				if (power->damage==-1001) {
					//Instead heal for their max health.
					FOOD_REGEN_TURNS=4;
					finalDamage=-PLAYER_MAXHP*0.33;
					foodCount--;
				}
				PLAYER_HP=std::clamp(PLAYER_HP-finalDamage,0,PLAYER_MAXHP);
				CreateDisplayNumber(finalDamage,PLAYER_COORDS[0],PLAYER_COORDS[1],frameCount);
			} else {
				for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
					finalDamage=power->damage+rand()%power->damageRoll*sign(power->damage);
					Entity*ent=CURRENT_ENCOUNTER.entities[i];
					if (distancetoCoords({(float)((ent->x+CURRENT_ENCOUNTER.x)*32)+ent->spr->sprite->width/2,(float)((ent->y+CURRENT_ENCOUNTER.y)*32)+ent->spr->sprite->height/2},coords*32)<=power->range) {
						ent->hp=std::clamp(ent->hp-finalDamage,0,ent->maxhp);
						CreateDisplayNumber(finalDamage,ent->x+CURRENT_ENCOUNTER.x+ent->spr->sprite->width*ent->sprScale.x/2/32,ent->y+CURRENT_ENCOUNTER.y+ent->spr->sprite->height*ent->sprScale.y/2/32,frameCount);
						ent->damageFrame=frameCount;
					}
				}
			}
		} else {
			//Damaging effect.
			if (playerForce) {
				for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
					finalDamage=power->damage+rand()%power->damageRoll*sign(power->damage);
					Entity*ent=CURRENT_ENCOUNTER.entities[i];
					std::cout<<"Distance was "<<distancetoCoords({(float)((ent->x+CURRENT_ENCOUNTER.x)*32),(float)((ent->y+CURRENT_ENCOUNTER.y)*32)},coords*32)<<"\n";
					if (ent->hp>0&&distancetoCoords({(float)((ent->x+CURRENT_ENCOUNTER.x)*32)+ent->spr->sprite->width/2,(float)((ent->y+CURRENT_ENCOUNTER.y)*32)+ent->spr->sprite->height/2},coords*32)<=power->range) {
						ent->hp=std::clamp(ent->hp-finalDamage,0,ent->maxhp);
						CreateDisplayNumber(finalDamage,ent->x+CURRENT_ENCOUNTER.x+ent->spr->sprite->width*ent->sprScale.x/2/32,ent->y+CURRENT_ENCOUNTER.y+ent->spr->sprite->height*ent->sprScale.y/2/32,frameCount);
						ent->damageFrame=frameCount;
					}
				}
			} else {
				PLAYER_HP=std::clamp(PLAYER_HP-finalDamage,0,PLAYER_MAXHP);
				CreateDisplayNumber(finalDamage,PLAYER_COORDS[0],PLAYER_COORDS[1],frameCount);
			}
		}
	}

	double distancetoCoords(vf2d c1,vf2d c2) {
		return sqrt(pow(c1.x-c2.x,2)+pow(c2.y-c1.y,2));
	}

	int sign(int x) {
		return (x > 0) - (x < 0);
	}

	int rand() {
		srand(time(NULL)+RAND_CALLS);
		int randNumb = std::rand();
		RAND_CALLS=randNumb;
		return randNumb;
	}

	void performCropUpdate(int chanceToRegrow) {
		for (int x=0;x<4;x++) {
			for (int y=0;y<4;y++) {
				if (rand()%chanceToRegrow==0) {
					setPlantStatusWithAbsoluteCoords(x,y,std::clamp(getPlantStatusWithAbsoluteCoords(x,y)+1,0,2));
				}
			}
		}
	}

	void setupBattleTurns() {
		//Remove the card from inventory.
		BATTLE_CARD_SELECTION->playerOwnCount--;
		BATTLE_STATE=battle::ENEMY_SELECTION;
		for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
			if (CURRENT_ENCOUNTER.entities[i]->hp>0) {
				if (CURRENT_ENCOUNTER.entities[i]->fixedTurnOrder) {
					CURRENT_ENCOUNTER.entities[i]->selectedMove=CURRENT_ENCOUNTER.entities[i]->moveSet[CURRENT_ENCOUNTER.entities[i]->fixedTurnOrderInd++];
					if (CURRENT_ENCOUNTER.entities[i]->fixedTurnOrderInd>=CURRENT_ENCOUNTER.entities[i]->moveSet.size()) {
						CURRENT_ENCOUNTER.entities[i]->fixedTurnOrderInd=0;
					}
				} else {
					CURRENT_ENCOUNTER.entities[i]->selectedMove=CURRENT_ENCOUNTER.entities[i]->moveSet[rand()%CURRENT_ENCOUNTER.entities[i]->moveSet.size()];
				}
				CURRENT_ENCOUNTER.entities[i]->turnComplete=false;
			}
		}
		PLAYER_TURN_COMPLETE=false;
		BATTLE_STATE=battle::MOVE_RESOLUTION;
		//Seed Storm has prio.
		if (!PLAYER_TURN_COMPLETE&&isPriorityMove(BATTLE_CARD_SELECTION)) {
			turnOrder.push(-1);
			PLAYER_TURN_COMPLETE=true;
		}
		for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
			if (CURRENT_ENCOUNTER.entities[i]->hp>0&&!CURRENT_ENCOUNTER.entities[i]->turnComplete&&
				isPriorityMove(CURRENT_ENCOUNTER.entities[i]->selectedMove)) {
				turnOrder.push(i);
				CURRENT_ENCOUNTER.entities[i]->turnComplete=true;
				std::cout<<" Entity "<<i<<" added prio for Seed Storm.\n";
			}
		}
		//Healing has half prio for the player.
		if (rand()%2==0&&!PLAYER_TURN_COMPLETE&&isFoodMove(BATTLE_CARD_SELECTION)) {
			turnOrder.push(-1);
			PLAYER_TURN_COMPLETE=true;
		}
		//Otherwise, every enemy has a chance to go before the player unless they are slowed, then they always go after.
		for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
			Entity*ent = CURRENT_ENCOUNTER.entities[i];
			if (rand()%2==0&&!PLAYER_TURN_COMPLETE&&isFoodMove(BATTLE_CARD_SELECTION)) {
				turnOrder.push(-1);
				PLAYER_TURN_COMPLETE=true;
			}
			if (ent->hp>0&&!ent->turnComplete&&
				!ent->slowed&&rand()%2==0) {
				turnOrder.push(i);
				ent->turnComplete=true;
			}
		}
		if (!PLAYER_TURN_COMPLETE) {
			turnOrder.push(-1);
			PLAYER_TURN_COMPLETE=true;
		}
		//Finally, any enemies that haven't gone will now go.
		for (int i=0;i<CURRENT_ENCOUNTER.entities.size();i++) {
			Entity*ent = CURRENT_ENCOUNTER.entities[i];
			if (ent->hp>0&&!ent->turnComplete) {
				turnOrder.push(i);
				ent->turnComplete=true;
			}
		}
		BATTLE_STATE=battle::PERFORM_TURN;
		BATTLE_CURRENT_TURN_ENTITY=turnOrder.front();
		turnOrder.pop();
		BATTLE_STATE=battle::WAIT_TURN_ANIMATION;
		EFFECT_TIMER=0;
	}

	void displayPowerInfo(WEATHER_POWER*POWER){
		PlayCutscene(cutscene::NODE_COLLECT_CUTSCENE);
		CUTSCENE_DISPLAYED_CARD=POWER;
	}

	void applyPixelEffect(ParticleEffect*effect,vf2d pos,float startingTransparency) {
		applyPixelEffect(
			{(pos.x-PLAYER_COORDS[0])*32+WIDTH/2-effect->effectSize.x/2,(pos.y-PLAYER_COORDS[1])*32+HEIGHT/2-effect->effectSize.y/2},
			effect->effectSize,
			effect->pos_low,
			effect->pos_high,
			effect->size_low,
			effect->size_high,
			effect->spd_low,
			effect->spd_high,
			effect->col_low,
			effect->col_high,
			effect->amt,
			effect->foregroundColor,startingTransparency
		);
	}

	void applyPixelEffect(WEATHER_POWER*power,vf2d pos,float startingTransparency) {
		applyPixelEffect(
			{(pos.x-PLAYER_COORDS[0])*32+WIDTH/2-power->effect->effectSize.x/2,(pos.y-PLAYER_COORDS[1])*32+HEIGHT/2-power->effect->effectSize.y/2},
			power->effect->effectSize,
			power->effect->pos_low,
			power->effect->pos_high,
			power->effect->size_low,
			power->effect->size_high,
			power->effect->spd_low,
			power->effect->spd_high,
			power->effect->col_low,
			power->effect->col_high,
			power->effect->amt,
			power->effect->foregroundColor,startingTransparency
		);
	}

	void applyPixelEffect(vf2d effectPos,vf2d effectSize,vf2d pos_low,vf2d pos_high,vf2d size_low,vf2d size_high,vf2d spd_low,vf2d spd_high,olc::Pixel col_low,olc::Pixel col_high,int amt,olc::Pixel foregroundColor,float startingTransparency) {
		for (int i=0;i<amt;i++) {
			pixels[i]->pos={range(pos_low.x,pos_high.x),range(pos_low.y,pos_high.y)};
			pixels[i]->size={range(size_low.x,size_high.x),range(size_low.y,size_high.y)};
			std::cout<<std::to_string(pixels[i]->size.x)<<","<<std::to_string(pixels[i]->size.y)<<"\n";
			pixels[i]->spd={range(spd_low.x,spd_high.x),range(spd_low.y,spd_high.y)};
			pixels[i]->r=range(col_low.r,col_high.r);
			pixels[i]->g=range(col_low.g,col_high.g);
			pixels[i]->b=range(col_low.b,col_high.b);
			pixels[i]->a=range(col_low.a,col_high.a);
			pixels[i]->o_a=range(col_low.a,col_high.a);
		}
		ORIGINAL_FOREGROUND_EFFECT_COLOR=FOREGROUND_EFFECT_COLOR=foregroundColor;
		PIXEL_POS=effectPos;
		PIXEL_SIZE=effectSize;
		PIXEL_LIMIT=amt;
		PIXEL_EFFECT_TRANSPARENCY=startingTransparency;
	}

	void clearPixelEffect() {
		PIXEL_LIMIT=0;
		PIXEL_EFFECT_TRANSPARENCY=0;
	}

	//Returns a number between 0.0 and X.
	float random(float X) {
		return (float)rand()/RAND_MAX * X;
	}

	float range(float val1,float val2) {
		return random(val2-val1)+val1;
	}

	vf2d GetMapFileCoords(int ln,int col) {
		return {(float)col-1,(float)ln-3};
	}

	//Basically, click on a spot in the text editor and this function translates it into the proper teleport coords so you don't have to.
	void TeleportToMapFileCoords(int ln,int col) {
		vi2d teleLoc = GetMapFileCoords(ln,col);
		PLAYER_COORDS[0]=teleLoc.x+0.5;
		PLAYER_COORDS[1]=teleLoc.y+0.5;
	}

	Object*CreateObject(vf2d pos,Decal*spr,int ,bool temporary=false) {
		Object*newobj;
		OBJECTS.push_back(newobj=new Object(spr));
		newobj->x=pos.x;
		newobj->y=pos.y;
		newobj->tempObj=temporary;
		return newobj;
	}
	Object*CreateObject(vf2d pos,Decal*spr,Animation*anim,bool temporary=false) {
		Object*newobj;
		OBJECTS.push_back(newobj=new Object(spr,anim));
		newobj->x=pos.x;
		newobj->y=pos.y;
		newobj->tempObj=temporary;
		return newobj;
	}
	Object*CreateObject(vf2d pos,Decal*spr,vi2d spos,vi2d size,bool temporary=false) {
		Object*newobj;
		OBJECTS.push_back(newobj=new Object(spr,spos,size));
		newobj->x=pos.x;
		newobj->y=pos.y;
		newobj->tempObj=temporary;
		return newobj;
	}
	void ClearAllTemporaryObjects() {
		for (int i=0;i<8;i++) {
			for (int j=0;j<OBJECTS.size();j++) {
				if (OBJECTS[j]==CUTSCENE_OBJS[i]) {
					if (CUTSCENE_OBJS[i]->tempObj) {
							OBJECTS.erase(OBJECTS.begin()+j);
							std::cout<<"Erased at position "<<j<<".\n";
							break;
						}	
					delete CUTSCENE_OBJS[i];
				}
			}
		}
	}
	//Returns true if the camera reached the target position.
	bool MoveCameraTowardsPoint(vf2d pos,float spd=BATTLE_CAMERA_SCROLL_SPD) {
		bool reachedPosition=true;
		if (PLAYER_COORDS[0]!=pos.x) {
			if (PLAYER_COORDS[0]<pos.x) {
				PLAYER_COORDS[0]+=spd;
				if (PLAYER_COORDS[0]>pos.x) {
					PLAYER_COORDS[0]=pos.x;
				}
			} else {
				PLAYER_COORDS[0]-=spd;
				if (PLAYER_COORDS[0]<pos.x) {
					PLAYER_COORDS[0]=pos.x;
				}
			}
			reachedPosition=false;
		}
		if (PLAYER_COORDS[1]!=pos.y) {
			if (PLAYER_COORDS[1]<pos.y) {
				PLAYER_COORDS[1]+=spd;
				if (PLAYER_COORDS[1]>pos.y) {
					PLAYER_COORDS[1]=pos.y;
				}
			} else {
				PLAYER_COORDS[1]-=spd;
				if (PLAYER_COORDS[1]<pos.y) {
					PLAYER_COORDS[1]=pos.y;
				}
			}
			reachedPosition=false;
		}
		return reachedPosition;
	}
	bool MoveObjectTowardsPoint(vf2d pos,Object*obj,MOVEMENT_PRIORITY movementStyle,float spd=BATTLE_CAMERA_SCROLL_SPD,bool secondRun=false) {
		bool reachedPosition=true;
		if (movementStyle==HORZ_FIRST||movementStyle==BOTH) {
			if (obj->x!=pos.x) {
				if (obj->x<pos.x) {
					obj->x+=spd;
					if (obj->x>pos.x) {
						obj->x=pos.x;
					}
				} else {
					obj->x-=spd;
					if (obj->x<pos.x) {
						obj->x=pos.x;
					}
				}
				reachedPosition=false;
			} else 
			if (!secondRun&&movementStyle!=BOTH) {
				MoveObjectTowardsPoint(pos,obj,VERT_FIRST,spd,true);
			}
		}
		if (movementStyle==VERT_FIRST||movementStyle==BOTH) {
			if (obj->y!=pos.y) {
				if (obj->y<pos.y) {
					obj->y+=spd;
					if (obj->y>pos.y) {
						obj->y=pos.y;
					}
				} else {
					obj->y-=spd;
					if (obj->y<pos.y) {
						obj->y=pos.y;
					}
				}
				reachedPosition=false;
			} else 
			if (!secondRun&&movementStyle!=BOTH) {
				MoveObjectTowardsPoint(pos,obj,HORZ_FIRST,spd,true);
			}
		}
		return reachedPosition;
	}

	void ResetTerminal(std::string text){
		CUTSCENE_CONSOLE_TEXT.clear();
		textInd=0;
		CONSOLE_REF_TEXT=text;
	}

	bool isPriorityMove(WEATHER_POWER*power) {
		return 
			power->name.compare("Seed Storm")==0||
			power->name.compare("Seed of Life")==0||
			power->name.compare("Petal Storm")==0;
	}

	bool isFoodMove(WEATHER_POWER*power) {
		return 
			power->name.compare("Meal")==0||
			power->name.compare("Snack")==0;
	}

	void addSeeds(int seedCount) {
		for (int i=0;i<seedCount;i++) {
			SEEDS.push_back(new Seed({range(-32,32),range(-32,32)}));
		}
	}

	void clearSeeds() {
		for (int i=0;i<SEEDS.size();i++) {
			delete SEEDS[i];
		}
		SEEDS.clear();
	}

	void addTrees(int treeCount) {
		for (int i=0;i<treeCount;i++) {
			TREES.push_back(new Seed({range(-64,64),range(-64,64)}));
		}
	}

	void clearTrees() {
		for (int i=0;i<TREES.size();i++) {
			delete TREES[i];
		}
		TREES.clear();
	}

	DisplayNumber*CreateDisplayNumber(int numb,float x,float y,int frameCount) {
		DisplayNumber*number=new DisplayNumber(numb,x+range(-0.3,0.3),y+range(-0.1,0),frameCount);
		BATTLE_DISPLAY_NUMBERS.push_back(number);
		return number;
	}
};


int main()
{
	SeasonsOfLoneliness demo;
	if (demo.Construct(256, 224, 4, 4))
		demo.Start();
	return 0;
}