Greetings,




Here is the source code for Knights of Grumthorr(2) along with required dependency information.
First of all you will need to purchase and download the game to have access to the media.
Second you will need to create a folder on your pc called 'fantasyrts'
Put the contents of the media folder into a folder fantasyrts/media.




Create a folder called fantasyrts/sdl
Copy the .cs files for the c# version of sdl2 into this folder.
Download the sdl dlls as well.
The sdl components you will require include sdl2, sdl2_image, sdl2_ttf and sdl2_mixer.




Finally copy the two source files as found below this text into fantasyrts/




The first is fantasyrts.csproj
This is a small file that contains some parameters that determine how the program compiles.
The second is Program.cs.




You will need a recent version of .NET (c#) to run and test and compile the program.
Go to your command prompt (run->cmd) and navigate to the fantasyrts folder




"cd\fantasyrts" for example.




Then you can use the following:
dotnet run
to run the program.




Or you can use dotnet publish -r win-x64 to compile the program into a release version.




Before I attach the two files I will give a basic licence for you to use my code with:
Licence:




"You may use this Program.cs and associated source code and files as you see fit. This licence is
supplied on a 'common sense' basis - in other words - use it as you would hope someone might use
your own code and treat it with respect. Beyond that - go nuts with it. As a small time one man
developer if I put a law-speak licence in do you really think I'm going to have the ability to enforce it?"




Here are the two files:




fantasyrts.csproj
<Project Sdk="Microsoft.NET.Sdk">




<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>




</Project>




And Program.cs




You can edit both of them with a simple text editor such as notepad++ or notepad.exe




Have fun!///////////////////////////////////////////////////
//fantasyrts - Knights of Grumthorr 2 - Version 2.00
//Version 18-Mar-2021 - Matt Lloyd
///////////////////////////////////////////////////
//


////////////////////////////////

Total Lines of Code:28923

Code

//Fantasy RTS Engine - KOG2
//Matt Lloyd 2020/2021
//'Knights of Grumthorr - 2'
//
//1-Oct-2020 - Bug Fix - data/data2 with 'description='
//26-Oct-2020 - Bug Fix - Count Varna 700+ times on skirmish mode in report
//26-Oct-2020 - Enhancements - snow/desert mode, overrides for scenery, multiple factions possible now.
//1-Nov-2020 - Enhancements - override for rgbbk
//1-Nov-2020 - Enhancements - gui.txt file modified for simpler gui arrangement..less cluttered.
//1-Nov-2020 - Release Version 1.0
//24-Feb-2021 - Enhancements - greater modding capability and adjustments to gui things
//25-Feb-2021 - Enhancements - death animation support added, high rate of fire support added.
//25-Feb-2021 - Enhancements - better mod support.
//26-Feb-2021 - Enhancements relating to fog
//28-Feb-2021 - Enhancements - gui link better to missions
//28-Feb-2021 - Enhancements - playable faction specific to missions....
//28-Feb-2021 - Enhancements - added second idle animation
//28-Feb-2021 - Enhancements - more flexible image loading
//28-Feb-2021 - Enhancements - better mod support.
//28-Feb-2021 - Bug Fix/Enhancements - better resource loading error handling.
//1-Mar-2021 - Enhancements - allow mission choice by name rather than index as well.
//2-Mar-2021 - Enhancements - map details (decor)
//5-Mar-2021 - Release Version 1.1
//7-Mar-2021 - Enhancements - "extraunits=" - to add more units without changing units.txt file
//7-Mar-2021 - Enhancements - new unit characteristics coded in, mob, animosity, hatred, craftsman, planar, slow, woodsman, stupidity, frenzy
//7-Mar-2021 - Bug Fix with decor
//9-Mar-2021 - Enhancements - formations, in-battle ui,
//10-Mar-2021 - Enhancements - controllable spawners (choose what to build).
//11-Mar-2021 - Enhancements to gui and AI spawners...
//////////////////////////////////////////////////////////
//12-Mar-2021 - Enhancements Officially changed to Version 2.0, KoG2 - grumthorr2 as well.
//12-Mar-2021 - KOG2 maxmission defaults to 36 at the beginning.
//12-Mar-2021 - Planar Bug Fix - Shouldn't be able to build planar units at a builder (design decision)
//12-Mar-2021 - LocalStorage.getitem, LocalStorage.setitem
//12-Mar-2021 - Marked missions as complete or incomplete.
//13-Mar-2021 - Enhancements - Language Localisation Features
//15-Mar-2021 - Enhancements to handle Chinese text. Also shield added for defend units. And a bug fix for missing check on a -1 value for an array index (would never occur though).
//15-Mar-2021 - Bug Fix - Chinese Text was being truncated - this has now been fixed with a user defined variable 'fontwmultiplier' which should be 1 or greater or left unassigned.
//15-Mar-2021 - Bug Fix / Other - Removed Network commands and Bug fix for record=1 flag when quitting and thread running causing a crash..
//16-Mar-2021 - Fix for wmultiplier on Fonts. for ascii only strings.
//16-Mar-2021 - Released to Steam for build verification by Valve.
//17-Mar-2021 - Bug Fix for chinese Text - additional fix for wmultiplier for unicode fonts.
//17-Mar-2021 - Bug fix in TranslateWord returning "" instead of the word at times.
//18-Mar-2021 - Culture Info added ?
//19-Mar-2021 - Enhancement - spellcasters buff friendly units now.
//19-Mar-2021 - Re-Enabled Network Command
//20-Mar-2021 - Enhancement - armour/attack modifier (percentage multiplier) enabled via config file.
//20-Mar-2021 - Graphical Glitch fixed with Unit drawing...
//21-Mar-2021 - Added +/- and unit circles
//21-Mar-2021 - Enhancement - added custom scenarios via level editor to game.
//21-Mar-2021 - Language Enhancement/Translation
//22-Mar-2021 - Bug Fix - scaling of sprites in Gui due to comma/period difference in region settings.
//22-Mar-2021 - Editor language allowed for, Selection indicator added. Pause with pause key on keyboard.
//23-Mar-2021 - Minor graphical glitch fixed. Trigger enhancements.
//24-Mar-2021 - Updated ALTMODE in Gui.ALTMODE to change more often. Improved Targeting.
//25-Mar-2021 - Threaded music loading....Trigger *ANY, *FRIEND, *ENEMY and CREATE and REMOVE
//26-Mar-2021 - Optimisation added (MAXINDEX)...to units and a few others.
//27-Mar-2021 - Bug Fix....
//Important note about the Bug fix on 27-Mar-2021
//The bug was introduced on 26-Mar-2021 when 'selectingtime' was added to the code
//This has now been altered so that the bug does not occur.
//That means the versions of the game released prior to 26-Mar-2021 were fine
//And now those released after are fine again too.
//27-Mar-2021 - Disabled Zoom. Adjusted WAITSELECTINGTIME from 30 to 6. Added Bullet.MAXINDEX = 0 on change gamestate. tmpbrave added...
//28-Mar-2021 - Translation Class optimised search by sorting based on length of string....(NOT IMPLEMENTED)
//28-Mar-2021 - Building spells in...minimap gui enhanced/bug fix, language reporting...
//30-Mar-2021 - added uid
//1-apr-2021 - tidied up web request.
//2-apr-2021 - enhanced some graphical features....And After Action 10 minute Replay
//2-apr-2021 - Action Replay added at end of battle. (actually 3-apr, but code changes recorded as 2-Apr)
///////////////////////////////////////////
//7apr2021 - fixed Editor restart
//9apr2021 - new spells...
//11apr2021 - fixed some minor frame+id glitches, added extra altimage handling, some saving of seeds as an attempt to fix replay (didn't work)
//12-16apr2021 - various minor enhancements
//17apr2021 - moved clicker and targeticon into gui section without hardcoding their presence.
//17apr2021 - altered AI//hmultiplier
//18apr2021 - gamestate transitions implemented....fadeout/fadein added.
//19apr2021 - fixed glitch with editor trees...
//20apr2021 - toggle gui panels, auto calculate offy/offx
//24apr2021 - addressed spawner selection bug
//25apr2021 - addressed replay bug with onscreen feature, Translation binary search (in case list gets long)
//26apr2021 - enabled demo mode
//28apr2021 - pathfinding quick pathing added.
//2may2021 - note Matt - eventually ADD the following: Transforming Units, Flying Units including dual ground/air units and Transports. All are possible with simple changes/additions.
//3may2021 Transforming units added but not tested.....Transported units added but not tested also....
//4may2021 - adding flying units....
//6may2021 - added replay MAXLENGTH back in....
//22may2021 resizable window in windowed mode.....
//29may2021 - sprite rotations through directions takes time rather than instant
//29may2021 - multithreaded pathfinding
//2jun2021 - sprite batching in part.....
//12jul2021 - bound demon code added but not tested or used yet.
//28jul2021 - added deathfx code for sound effects....
//2sep2021 - minor addition - allowed shock to be specified in file instead of shocktrooper. Also allowed TITLE set in text file.
//2sep2021 - tech addition (large update) (seems complete sort of)....
//2sep2021 - bug fix - canflyandwalk units fixed...somewhat. transform bug fix also. transporting also works now.
//4sep2021 - bug fix with transporting units.
///////////////////////////////////////////
//9sep2021 - spawners can be constrained.
//10sep2021 - defaultgridw/h, and mission based gridw/h, trigger for chatter image....and audio,
//10sep2021 - adding individual character names to units in the armies.
//12sep2021 - allow 'exit to mission name' via a trigger
//13sep2021 - bug fix with dead units (if dead animation present)
//14sep2021 - a few changes...
//15sep2021 - need los added
//////////////////////////////////
//Space Squad Began Here
//16sep2021 - NOSHOWABILITY added
//17sep2021 - added menu mini map feature.
//18sep2021 - various additions.
//19sep2021 - bug fix.
//////////////////////////////////
//Everything After 20 Sep Can be Ignored If Desired.
//////////////////////////////////
//27dec2021 - Added VARIABLE trigger for complex trigger arrangements.
//31dec2021 - Added ability from gui to affect VARIABLE trigger data.
//12feb2021 - coding test - evaluating the number of lines written on average in a 10 minute window or thereabouts. Need to therefore write some code...described below.
//12feb2021 11:31am code update - "displayunitname" to allow for text as well as a number, where if it is neither 0, nor 1, then it assigns it as the name to the unit.....11:40 finished...10 minutes to write:12 lines of code.
//Therefore approximately 1 minute per line of code added. Total 26,000 lines of code is equivalent to 26,000 minutes OR approximately 400+ hours of work in this file. If I were billing $150 per Hour like at work I'd be charging $60,000AUD to write this.
//But that is merely the code, there's also the data files, the debugging and testing, the graphics and sound...and more. Let's take a guess and say development cost would therefore be equivalent to $100,000 to develop for a company.
//////////////////////////////////
//21feb2022 and 22feb2022 various changes for conflict3048 with some bug fixes that never mattered to grumthorr.
//23feb2022 and 24feb2022 various changes for conflict3048.
//6mar2022 allowed EDITOR to be switched OUT OF with the TAB key
//22apr2022 added Particles and Emitters

using System;
using System.Diagnostics;
using System.Threading;
using System.Net; //15mar2021
using System.IO;
using System.Text;//13Mar2021//1apr2021
using System.Runtime.InteropServices;
using SDL2;
using System.Globalization;

namespace fantasyrts
{


///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Config
    {
        public static int dointro = 0;//1mar2022
        public static bool NonEnglishAllowed = false;//1mar2022
        //start-----//28feb2022
        public static int options_fog = 1;
        public static int options_overlay = 1;
        //end-------//28feb2022
        public static int highseas = 0;//28feb2022
        public static int CurrentMonth;//23feb2022
        public static int Season;//23feb2022
        public static int WINTER = 2;//24feb2022
        public static int SUMMER = 1;//24feb2022
        public static int useseasons;//23feb2022
        public static int Night;//24feb2022
        public static int DEFAULTRESX = 1600;//23sep2021
        public static int DEFAULTRESY = 900;//23sep2021
        public static int NOUPDATEINDEMOMODE = 0;//18sep2021
        public static int USEDELTATIME = 0;//18sep2021
        public static int delta;//18sep2021
        public static int UNLOCKFRAMERATE = 0;//18sep2021
        public static int AUTOPLAY = 0;//18sep2021
        public static int NOSHOWABILITY = 0;//16sep2021
        public static int OPTIMISEFIRES = 0;//15sep2021
        public static int TILEFOG = 0;//15sep2021
        public static int CLUMP = 0;//15sep2021
        public static int NOREPLAY = 0;//15sep2021
        public static int FASTFRAMECHECK = 0;//14sep2021
        public static bool USETECH = true;//false;//2sep2021
        public static bool THREADEDPATHING = false;//29may2021
        public static bool SLOWROTATE = true;//29may2021
        public static int WINDOWRESIZE = 0;//22may2021
        public static bool ALLOWFLYING = true;//4may2021 //flag while debugging...will set to true later....
        public static bool FREEDEMO = false;
        public static int freedemo = 60 * 60 * 10;//26apr2021
        public static bool AUTOCALCOFFSETS = false;//20apr2021
        public static uint FRAMETIME = 15;//18apr2021
        public static bool BLOCKPRECALC = true;//11apr2021
        public static bool ALLOWREPLAY = true;//2apr2021
        public static bool GETDATA = false;//1apr2021
        public static string autodetectlang = "";
//30mar2021
        public static string uid = "1234";//30mar2021
        public static bool DEBUG = false; //23mar2021 moved up here from below...
        public static bool NOMETRICS = false;//remember to change this appropriately...
        public static bool TRANSLATEGUI = true;//21mar2021
        public static bool USEICONCIRCLES = false;//21mar2021
        public static bool USECOVERFLAG = false;//21mar2021
        public static bool USEFEETCIRCLES = false;//21mar2021
        public static int ARMOURPCT = 100;//20mar2021
        public static int ATTACKPCT = 100;//20mar2021
        public static int HEALTHPCT = 100;//20mar2021
        public static bool useUNICODE = false; //ml15mar2021
        public static bool bestiarychk = false; //5apr2021
        public static bool KOG2 = true;
        public static bool RECORD = false;
        public static bool STREAMLOAD = true; //28Feb2021
        public static bool STREAMLOADAUDIO = false;//25mar2021
        public static int USEHEIGHTS = 0;
        public static bool DODEBRIEF = true;
        public static bool TESTDEBRIEF = false;
        public static bool USEPATHFILE = false;
        public static int FACTOR = 10; //determines size of armies and so on.....10 seems to be about sufficient for the game to run very well still with lots of units on the map.
        public static int NORMALSPEED = 10;//23mar2021 (not used yet...)
        public static int LOWSPECSPEED = 6;//23mar2021 (not used yet...)
        public static string configfile; //28Feb2021
        public static string guifile;
        public static string campaignfile;
        public static string customcampaignfile;
        public static string unitsfile;
        public static string wordsfile = ""; //13mar2021
        public static string techfile = "";//2sep2021
        public static string defaultfontfile;
        public static int largefontsize;
        public static int smallfontsize;
        public static int normalfontsize;
        public static string audioclickfile;
        public static string offsetfile = "";//20apr2021
        public static bool FINISHEDOFFSETS = false;//20apr2021
        public static string logofile;
        public static string fogfile;
        public static int logowidth;
        public static int logoheight;
        public static int fogwidth;
        public static int fogheight;
        public static int hires = 0;
        public static string custommapfolder;
        public static string usercampaignfolder = "";
        public static string usercampaignfile = "";
        public static string custommapprefix = "custom_";
        public static string skirmishmessage = "Take control of the portals to spawn units.|Eliminate the enemy.";
        public static int FONTALIAS = 4;
        public static long precalcused = 0;
        public static long seekpathused = 0;
        public static long seekpathfailed = 0;
        public static long seekpathsuccess = 0 ;
        public static long maxbmenutime = 0;
        public static long maxumusictime = 0;
        public static long maxmapupdatepostime = 0;
        public static long maxmapcorrecttime = 0;
        public static long maxmaperrors = 0;
        public static long maxunitupdatetime = 0;
        public static long maxbullettime = 0;
        public static long maxbloodtime = 0;
        public static long maxselecttime = 0;
        public static long maxtriggertime = 0;
        public static long maxdrawtime = 0;
        public static long maxanimate = 0;
        public static long maxwalk = 0;
        public static long maxupdate = 0;
        public static long maxatt = 0;
        public static long[] totrtime = new long[600];
        public static long[] totutime = new long[600];
        public static long sumr = 0;
        public static long sumu = 0;
        public static long UTIMELOW = 800;
        public static long RUNNINGSPEED = 0;
        public static long runningspeed = 0;
        public static bool loaded = false;
        public static int loadpct = 0;
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Game
    {
        public static int LoadingPct = 0;
        public static string NETTITLE = "grumthorr";
        public static string TITLE = "Knights of Grumthorr";
        public static string AUTHOR = "Matt Lloyd";
        public static string MUSIC = "Eric Matyas, soundimage.org";
        public static string YEAR = "2021";
        public static string VERSION = "2.00";
        public static int VERSIONINT = 200;
        public static string VERSIONSTR = "20210603"; //14apr2021(and subsequent)
        //
        public static bool restart = false;//13mar2021
        public IntPtr renderer;
        public IntPtr window;
        public IntPtr screen;
        public bool takepicture;
        //public int recordframe;
        public static bool running = true;
        //for screenshots.....
        //unsafe takepicture Pointer
        //
        public static bool EDITOR = false;
        public static int EDITED = -1; //7apr2021
        public RenderList[] renderlist;
        public static Replay[] replay;//2apr2021
        public Images[] images;
        public Fonts[] fonts;
        public Audios[] audios;
        //public static long killcount; //13mar2021
        public static int killcount; //13mar2021
        //
        public Map map;
        public Unit[] units;
        public Unit[] templates;
        public Mission[] missions;
        public Tech[] techs;//2sep2021
        //public Mission tutorial;
        public int missionid;
        public int nextmissionid;
        public int failedmissionid;
        public Gui[] gui;
        public Bullet[] bullets;
        public Trigger[] triggers;
        public Blood[] blood;
        public Gibbet[] gibbet; //2apr2021
        //
        //
        public static int neutralfog = 0; //26Feb2021
        public static int fogoff = 0; //26Feb2021
        //
        public static int topmissionindex = 0;
        public static int previousmissionindex = -1;//2apr2021
        public static int chosenmissionindex = -1;
        public static int ochosenmissionindex = -1;//17sep2021
        public static int maxmission = 1;
        public static int overridemaxmission = 0;//13sep2021
        public static int countcustoms = 0;
        //
        public int SW;
        public int SH;
        //public static int SSW;
        //public static int SSH;
        public int frame;
        public int gamestartframe;//2apr2021
        //
        public int mx;
        public int my;
        public int rmx;//21apr2021
        public int rmy;//21apr2021
        public int wmx;//21apr2021
        public int wmy;//21apr2021
        public static int RCORNERX;//21apr2021
        public static int RCORNERY;//21apr2021
        public static int TMPCORNERX;//21apr2021
        public static int TMPCORNERY;//21apr2021
        //public int exitmx;//2apr2021
        //public int exitmy;//2apr2021
        public int omx;
        public int omy;
        public int smx;
        public int smy;
        public int fmx;
        public int fmy;
        public bool mlclick;
        public bool mldown;
        //public bool exitclick;//2apr2021
        //public bool exitdown;//2apr2021
        public bool mrclick;
        public int mlclickframe;
        public bool mrdown;
        public int mwheel;
        public float zoom;
        public int zoomcornerx;
        public int zoomcornery;
        public bool paused;
        public int minimapframe;
        public bool demomode;
        public static int checksum;//2apr2021
        public static int ordergivenframe;
        public static int EXTRAPATHINGTIME = 60 * 4;
        public static int leftcontrolkey = 0;
        public static int[] numberkeys = new int[10];
        public static int[] numberkeysframe = new int[10];
        public static bool SPAWNERSELECTED = false; //10mar2021
        public static bool NONSPAWNERSELECTED = false;//11mar2021
        public static int SPELLCASTERSELECTED = -1;//28mar2021
        public static int SPELLCASTERLEVEL = 0;//28mar2021
        public static bool SPELLSACTIVE = true;//false;//28mar2021
        public static int EDITMODE_TREE = 1;
        public static int EDITMODE_ROCK = 2;
        public static int EDITMODE_WALL = 3;
        public static int EDITMODE_UNIT = 0;
        public static int EDITMODE_TRIGGER = 4;
        public static int EDITMODE_ENTERTEXT = 5; //from triggers....
        public static int EDITMODE_HEIGHT = 6;
        public static int EDITMODE;
        public static int editgridx;
        public static int editgridy;
        public static int editindex;
        public static string editname;
        public static int editkeypressed = 0;
        public static int recordkeypressed = 0;
        public static int backupkeypressed = 0;
        public static string edittriggerstring = "";
        public static bool editshiftheld = false;
        //
        public static int FULLSCREEN = 0;
        public static int FXVOLUME = 100;
        public static int MUSICVOLUME = 100;
        public static int oFXVOLUME = 100;
        public static int oMUSICVOLUME = 100;
        //
        public static int RESOLUTIONX;
        public static int RESOLUTIONY;
        public static int FRAMERATE;
        public static bool NODELAY = true;
        //
        public static int CORNERX = 0;
        public static int CORNERY = 0;
        public static int CORNERSPEED = 5;
        public static int CORNEREDGEDIST = 50;
        public static int LOCKCORNER = 0;
        public static int HORIZONTALFORMATION = 0; //14apr2021
        public static int VERTICALFORMATION = 0; //14apr2021
        //
        //
        public int gamestate;
        public int oldgamestate;
        public int newgamestate;
        public static int restartgamestate; //26mar2021
        public static int selectingtime;//26mar2021
        public static int WAITSELECTINGTIME = 6;//26mar2021
        //public static int transitionframe;
        //public static int TRANSITIONTIME = 30;
        public bool playerready;
        public bool skirmish;
        public bool onscreen;
        public bool victorymessage;
        public bool playingtutorial;
        
        public static int CAT_GAMESTATE_INTRO = 4;//28feb2022
        public static int CAT_GAMESTATE_LOGO = 0;
        public static int CAT_GAMESTATE_OUTRO = 5;//28feb2022
        public static int CAT_GAMESTATE_OUTROBAD = 6;//28feb2022
        public static int CAT_GAMESTATE_CREDITS2 = 7;//28feb2022
        
        public static int CAT_GAMESTATE_MENU = 10;
        public static int CAT_GAMESTATE_NEWCONTINUE = 20;
        public static int CAT_GAMESTATE_GAME = 1000;
        public static int CAT_GAMESTATE_DEBRIEF = 999;
        public static int CAT_GAMESTATE_DEBRIEF2 = 998;
        public static int CAT_GAMESTATE_REPLAY = 997; //2apr2021
        public static int CAT_GAMESTATE_MATCH_PLAY = 1000;
        public static int CAT_GAMESTATE_STARTLEVEL = 1050;
        public static int CAT_GAMESTATE_GAMEOVER = 1100;
        public static int CAT_GAMESTATE_NEWLEVEL = 1200;
        public static int CAT_GAMESTATE_ENDLEVEL = 1300;
        public static int CAT_GAMESTATE_GUIMENUS = 10000;
        //
        public static int PLAYERFACTION = 0;
        public static int SKIRMISHENEMYFACTION = 0;
        public static int EDITORPFACTION = 0; //22mar2021
        public static int EDITOREFACTION = 0; //22mar2021
        public static int GAMEENDSTATE = 0;
        public static int GAMEENDSTATE_VICTORY = 1;
        public static int GAMEENDSTATE_DEFEAT = 2;
        public static int EXITPRESSED = 0;//1mar2022
        public static int MAXFACTIONS = 16;
        //
        public int gameovertime;
        //public int nextleveltime;
        //
        public static int MissionScore = 0;//1mar2022
        public static int TopScore = 0;//1mar2022
        public static int quoteindex = 0;//1mar2022
        public static int outroframe = 0;//28feb2022
        public static int outrodelay = 0;//28feb2022
        public static int healthbar = -1;
        public static int whiteflag = -1;
        public static int highseas_hi = -1;//28feb2022
        public static int highseas_lo = -1;//28feb2022
        public static int shadowup = -1;//15sep2021
        public static int shadowleft = -1;//15sep2021
        public static int shadowright = -1;//15sep2021
        public static int shadowoffy = -1;//15sep2021
        public static int shadowoffx = -1;//15sep2021
        public static int shield = -1; //15mar2021
        public static int lightning = -1;//28mar2021
        public static int whirlwind = -1;//28mar2021
        public static int targeticon = -1;//16apr2021
        public static int spellball = -1;//12apr2021
        public static int clicker = -1;//15apr2021
        public static int clickerframe = -1;//15apr2021
        public static int clickerrow = 0;//15apr2021
        public static int clickerx = 0;//15apr2021
        public static int clickery = 0;//15apr2021
        public static int BLUEBALL = 0;
        public static int GREENBALL = 1;
        public static int PURPLEBALL = 2;
        public static int ORANGEBALL = 3;
        public static int REDBALL = 4;
        public static bool audioon;
        public static int iconplus = -1;//21mar2021
        public static int iconminus = -1;//21mar2021
        public static int iconcircles = -1;//21mar2021
        public static int groupselected = -1;//21mar2021
        public static bool showingselectedicons = false; //22mar2021
        public static bool togglepause = false;//22mar2021
        public static int mouseoverunitid = -1;
        public static bool anyselected = false;//16apr2021
        public static int formation = 0;//2apr2021
        public static int ai_direction = 0;//17apr2021
        public static int[] newtrees;//24apr2021
        public static int totalscore = 0;//18sep2021
        public static int maxtotalscore = 0;//18sep2021
        public static bool scoredirty = true;//18sep2021
        //

///////////////////Method Definition///////////////
        public static void DisplayQuote(Game game)//1mar2022
        {
            string txt = "";
            string[] quotes = new string[10];
            for(int i=0;i<quotes.Length;i++)
            {
                quotes[i] = "";
            }
            quotes[0] = "In general, the pattern of invasion is that invaders become more intense the farther they enter alien territory. - Sun Tzu";
            quotes[1] = "If half their force advances and half retreats, they are trying to lure you. - Sun Tzu";
            quotes[2] = "Do not follow a feigned retreat. Do not attack crack troops. - Sun Tzu";
            quotes[3] = "...even if you have many more troops than others, how can that help you to victory? - Sun Tzu";
            quotes[4] = "If you can strike few with many, you will thus minimise the number of those with whom you do battle. - Sun Tzu";
            quotes[5] = "To advance irresistibly, push through their gaps. To retreat elusively, outspeed them. - Sun Tzu";
            quotes[6] = "To unfailingly take what you attack, attack where there is no defense. - Sun Tzu";
            quotes[7] = "Therefore good warriors cause others to come to them, and do not go to others. - Sun Tzu";
            quotes[8] = "Governing a large number as though governing a small number is a matter of division into groups. - Sun Tzu";
            quotes[9] = "...if you know others and know yourself, you will not be imperiled in a hundred battles.... - Sun Tzu";
            txt = quotes[Game.quoteindex % quotes.Length];
            
            RenderList.drawtext(game,800,850,txt,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
        }
///////////////////Method Definition///////////////
        public static void ExtremelySimplePiracyCheck()//27feb2022
        {
            //piracy check does this:
            //if the game was not first run through Steam on the first time it ever
            //ran then it is marked as a pirate
            //if it ever is run through steam though it loses this piracy status
            //it's a really simple check that asks whether or not
            //the game is running inside the Steam's apps common folder
            //if it is not, and has never been, then mark it as a potential pirate
            //that means a legitimate user can MOVE the files to another location
            //and there won't be a problem.
            //but yeah - if it is not run inside Steam ever, then it will indicate it is potentially
            //a pirate copy....
            
            try
            {
                string path = Directory.GetCurrentDirectory();
                if(path.IndexOf("steamapps")<0)
                {
                    if(LocalStorage.getitem("highseas")=="0" || LocalStorage.getitem("highseas")=="")
                    {
                        VERSIONSTR = "20220230";
//haha
                        Config.highseas = 1;//28feb2022//maybe a pirate....
                        
                    }
                }
                else
                {
                    LocalStorage.setitem("highseas","1");
                    Config.highseas = 0;//not a pirate
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            //debugging
            //Config.highseas = 1;//28feb2022
            Config.highseas = 0;//1mar2022
        }
        
///////////////////Method Definition///////////////
        public Game(IntPtr r)
        {
            ////////////////////////
            //primary initialisation
            gamestate = Game.CAT_GAMESTATE_LOGO;
            renderlist = new RenderList[0];
            images = new Images[0];
            fonts = new Fonts[0];
            audios = new Audios[0];
            replay = new Replay[0];//2apr2021
            newtrees = new int[0];//24apr2021
            renderer = r;
            frame = 0;
            mx = 0;
            my = 0;
            omx = 0;
            omy = 0;
            mlclick = false;
            mldown = false;
            mrclick = false;
            mrdown = false;
            Game.audioon = true;
            //Game.NODELAY = true;
            //start--------------//13mar2021
            units = new Unit[0];
            templates = new Unit[0];
            missions = new Mission[0];
            techs = new Tech[0];//2sep2021
            gui = new Gui[0];
            bullets = new Bullet[0];
            triggers = new Trigger[0];
            blood = new Blood[0];
            topmissionindex = 0;
            chosenmissionindex = -1;
            ochosenmissionindex = -1;//17sep2021
            maxmission = 1;
            countcustoms = 0;
            leftcontrolkey = 0;
            numberkeys = new int[10];
            numberkeysframe = new int[10];
            SPAWNERSELECTED = false; //10mar2021
            NONSPAWNERSELECTED = false;//11mar2021
            healthbar = -1;
            whiteflag = -1;
            zoom = 1;//24apr2022
            highseas_hi = -1;//28feb2022
            highseas_lo = -1;//28feb2022
            shadowleft = -1;//15sep2021
            shadowup = -1;//15sep2021
            shadowright = -1;//15sep2021
            shadowoffx = -1;//15sep2021
            shadowoffy = -1;//15sep2021
            shield = -1;
            spellball = -1;//12apr2021
            whirlwind = -1;//28mar2021
            targeticon = -1;//16apr2021
            clicker = -1;//15apr2021
            lightning=-1; //28mar2021
            iconplus = -1; //21mar2021
            iconminus = -1; //21mar2021
            iconcircles = -1; //21mar2021
            Resources.blackcat = -1;//18apr2021//minor bug fix
            Resources.outro = -1;//28feb2022
            Resources.intro = -1;//1mar2022
            Resources.outrobad = -1;//28feb2022
            Map.init();
            //end----------------//13mar2021
            initgame();
        }

        public static void LoadingProgress(Game game)
        {
            LoadingPct+=(1000 - LoadingPct) / 100;
            if(LoadingPct>999)
            {
                LoadingPct = 999;
            }
            if(LoadingPct<0)
            {
                LoadingPct = 0;
            }
            SDL.SDL_Event e;
            SDL.SDL_Delay(1);
            while(SDL.SDL_PollEvent(out e) != 0)
            {
                SDL.SDL_Delay(1);//
            }
            RenderList.transitionmode = -1;
            //RenderList.drawanimimage(game,game.images[Resources.LoadingBack].texture,800,450,0,1,1,0,0,false,1,Resources.LoadingBack);
            RenderList.drawrect(game,10,880,(1580 * LoadingPct) / 1000,16,RenderList.getrgb(40,255,255),0);
            RenderList.drawunfilledrect(game,10,880,1580,16,RenderList.getrgb(120,120,120),0);
            if(game.fonts.Length>0)
            {
                if(Resources.FONT>=0 && Resources.FONT<game.fonts.Length)
                {
                    RenderList.drawtext(game,800,450,"Loading....Please Wait",RenderList.getrgb(220,220,200),game.fonts[Resources.FONT].font,true);
                }
            }
            SDL.SDL_RenderClear(game.renderer);
            RenderList.render(game);    
            SDL.SDL_RenderPresent(game.renderer);
        }
        
///////////////////Method Definition///////////////
        public void killed(Game game,int i)
        {
            ////////////////////////
            //this method handles the elimination of units from the game.
            //when a unit's hp goes to zero this method ought to be called.
            //it sets the animation mode to the death animation if any exists
            //and handles the removing of the body from the map and so forth
            //start-----------//25Feb2021
            bool gibbets = false;
            //start-----------//4may2021
            if(units[i].hp<=0 && units[i].isdead<2)
            {
                units[i].hp = units[i].basehp;
                units[i].isdead = 1;
                return;
            }
            if(units[i].isdead==2)
            {
                units[i].hp = 0;
                units[i].isdead = 0;
            }
            if(units[i].flightlevel!=-1)
            {
                Map.removeflyer(i,units[i].x,units[i].y,units[i].flightlevel);
                units[i].flightlevel = -1;
            }
            //end-------------//4may2021
            if(units[i].animmode!=Unit.ANIMMODE_DEAD)
            {
                int gb = Functions.rand(0,(Gibbet.GIBMOD + 1));//17sep2021
                //if(units[i].animmodedeadframeend>0)//17sep2021
                if(units[i].animmodedeadframeend>0 && gb <= (Gibbet.GIBMOD + 1)/2)//17sep2021
                {
                    units[i].animmode = Unit.ANIMMODE_DEAD;
                    return;                
                }
                else//2apr2021
                {
                    Gibbet.GIBCOUNTER++;
                    if((Gibbet.GIBCOUNTER % Gibbet.GIBMOD)==0)
                    {
                        Gibbet.makegibbets(game,i);
                        gibbets = true;
                    }
                }
            }
            else
            {
                if(units[i].animframe < units[i].animmodedeadframeend)
                {
                    return;
                }
            }
            //end-------------//25Feb2021
            units[i].playdeathsound(game,i); //28jul2021
            Map.addbones(units[i].x,units[i].y);
            game.templates[units[i].templateid].deaths++;
            Map.removeunit(i,units[i].x,units[i].y);
            if(units[i].faction!=6)//1mar2022
            {
                Game.MissionScore+=units[i].basehp + units[i].damage + units[i].armour;//1mar2022
            }
            if(units[i].deathanim!=null && units[i].infected<=0)//22apr2022 added infected
            {
                if(units[i].deathanim!="")
                {
                    for(int t=0;t<game.templates.Length;t++)
                    {
                        if(game.templates[t].name==units[i].deathanim)
                        {
                            game.units[i].createunitatxy(game,i,game.templates[t],units[i].x,units[i].y);
                            break;
                        }
                    }
                    
                }
            }
            if(!gibbets)
            {
                Blood.makeblood(game,units[i].x,units[i].y+units[i].offy,(int)Functions.sign(units[i].zombie));
                if(units[i].bossmonster>0)
                {
                    for(int j=0;j<4;j++)
                    {
                        Blood.makeblood(game,units[i].x+(int)Functions.rand(-Map.GRIDW/2,Map.GRIDW/2),units[i].y+units[i].offy+(int)Functions.rand(-Map.GRIDH/2,Map.GRIDH/2),0);
                    }
                }
            }
            Game.killcount++;
        }
        private void initgame()
        {
        }

///////////////////Method Definition///////////////
        public void quit()
        {
            ////////////////////////
            //finalisation of the game upon exiting the main loop
            //handles removing all textures and sounds
            
            Game.running = false;
            Emitter.pimages = null;//12apr2022/bug fix
            try//13mar2021 added try catch
            {
                for(int i=0;i<images.Length;i++)
                {
                    if(images[i].texture!=IntPtr.Zero && images[i].loaded==true) //28Feb2021
                    {
                        LocalStorage.setitem("FREE IMAGE:"+images[i].file,"FAILED"); //24mar2021
                        SDL.SDL_DestroyTexture(images[i].texture);
                        LocalStorage.setitem("FREE IMAGE:"+images[i].file,"SUCCESS"); //24mar2021
                    }
                }
                for(int i=0;i<fonts.Length;i++)
                {
                    LocalStorage.setitem("FREE FONT:"+fonts[i].file,"FAILED"); //24mar2021
                    SDL_ttf.TTF_CloseFont(fonts[i].font);
                    LocalStorage.setitem("FREE FONT:"+fonts[i].file,"SUCCESS"); //24mar2021
                }
                for(int i=0;i<audios.Length;i++)
                {
                    if(audios[i].audio==IntPtr.Zero)//10sep2021
                    {
                        continue;//10sep2021
                    }
                    LocalStorage.setitem("FREE AUDIO:"+audios[i].file,"FAILED"); //24mar2021
                    if(audios[i].ismusic)
                    {
                        SDL_mixer.Mix_FreeMusic(audios[i].audio);
                    }
                    else
                    {
                        SDL_mixer.Mix_FreeChunk(audios[i].audio);
                    }
                    LocalStorage.setitem("FREE AUDIO:"+audios[i].file,"SUCCESS"); //24mar2021
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Error on exit:"+e.Message);
                //LocalStorage.WriteLog("Error on exit:"+e.Message);
            }
        }

///////////////////Method Definition///////////////
        public void clearkeys()
        {
            ////////////////////////
            //reset the key state of the number keys and left control key
            Game.leftcontrolkey = 0;
            for(int i=0;i<10;i++)
            {
                Game.numberkeys[i] = 0;
            }
        }

///////////////////Method Definition///////////////
        public void getmouse()
        {
            ////////////////////////
            //get the mouse coordinates, and the click states
            //and also the drag select coordinates
            uint mouse = SDL.SDL_GetMouseState(out mx,out my);
            mlclick = false;
            mrclick = false;
            //exitclick = false;//2apr2021
            if(mouse==SDL.SDL_BUTTON(SDL.SDL_BUTTON_LEFT))
            {
                mldown = true;
                //exitdown = true;//2apr2021
            }
            else
            {
                if(mldown)
                {
                    mlclick = true;
                }
                //if(exitdown)
                //{
                //    exitclick = true;
                //}
                mldown = false;
                //exitdown = false;//2apr2021
            }
            if(mouse==SDL.SDL_BUTTON(SDL.SDL_BUTTON_RIGHT))
            {
                mrdown = true;
            }
            else
            {
                if(mrdown)
                {
                    mrclick = true;
                }
                mrdown = false;
            }
            if(SH>0 && SW>0)
            {
                float gxscale = (float)Game.RESOLUTIONX/ (float)SW;
                float gyscale = (float)Game.RESOLUTIONY/ (float)SH;
                mx = (int)((float)mx*gxscale);
                my = (int)((float)my*gyscale);
                //exitmx = mx; //2apr2021
                //exitmy = my; //2apr2021
                rmx = mx; //21apr2021
                rmy = my; //21apr2021
                wmx = mx; //21apr2021
                wmy = my; //21apr2021
            }
            if(mldown==false)
            {
                smx = mx;
                smy = my;
            }
            else
            {
                fmx = mx;
                fmy = my;
            }    
            //if(!Replay.PLAYBACK)
            //{
            //    exitclick = false;
            //    exitdown = false;
            //}
        }
    }
    //
    //start-------------//28Feb2021

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class StreamResources
    {
        public static int TOLERANCE = 60 * 5;
        public static int SHORTTOLERANCE = 60 * 5;
        public static int LONGTOLERANCE = 60 * 60;
        public static int STARTTOLERANCE = 60 * 15;
        //public static bool threadrunning = false;//25mar2021//24feb2022
        //public static Audios audio = null;//24feb2022
        
///////////////////Method Definition///////////////
        public static void streamloadhelper(Game game)
        {
            ////////////////////////
            //handles loading of resources during the game
            //and also freeing the resources
            //manages them so that we do not hog memory with
            //graphics that are unecessarily being kept when not in use for long periods
            if(!Config.STREAMLOAD)
            {
                return;
            }
            //start------------//25mar2021
            //24feb2022 commented out this audio part
            //if(threadrunning==false && Config.STREAMLOADAUDIO==true)
            //{
//                for(int i=0;i<game.audios.Length;i++)
                //{
//                    if(game.audios[i].audio==IntPtr.Zero && game.audios[i].ismusic==true)
                    //{
//                        threadrunning = true;
                        //audio = game.audios[i];
                        //Thread thread = new Thread(new ThreadStart(ThreadFunction));
                        //thread.Start();    
                        //break;
                    //}
                //}
            //}
            //end--------------//25mar2021
            bool imgloaded = false;//25apr2022
            for(int i=0;i<game.images.Length;i++)
            {
                //start-----//18apr2021
                //if(i==Resources.blackcat)
                //{
                //    continue;
                //}
                //end-------//18apr2021
                if(imgloaded)//25apr2022
                {
                    break;//25apr2022
                }
                if(game.images[i].texture!=IntPtr.Zero)
                {
                    game.images[i].okloaded = true;
                }
                if(game.frame - game.images[i].drawframe > TOLERANCE)// && game.frame > STARTTOLERANCE)
                {
                    //if(game.gamestate!=Game.CAT_GAMESTATE_GAME)//2apr2021
                    if(game.gamestate!=Game.CAT_GAMESTATE_GAME && game.gamestate!=Game.CAT_GAMESTATE_REPLAY)//2apr2021
                    {
                        Resources.FreeImage(game,i);
                    }
                }
                else
                {
                    if(game.images[i].loaded == false && game.images[i].texture==IntPtr.Zero && (game.images[i].okloaded==true || game.images[i].neverloaded==true))
                    {
                        if(Config.useseasons>0 && Config.Night>0)
                        {
                            /////start---------//24feb2022
                            //check if the nighttime file version exists....
                            //if it does - use it.....
                            string sfile = game.images[i].file;
                            int index = sfile.Length - 1;
                            while(index>=0)
                            {
                                if(sfile.Substring(index,1) == "/")

                                {
                                    break;
                                }
                                index--;
                            }
                            if(index>=0)
                            {
                                string prefix = sfile.Substring(0,index + 1);
                                string suffix = sfile.Substring(index + 1,sfile.Length - (index + 1));
                                string nightfile = prefix + "night_" + suffix;
                                if(File.Exists(nightfile))
                                {
                                    //file = nightfile;
                                    game.images[i].texture = SDL_image.IMG_LoadTexture(game.renderer,nightfile);
                                    if(game.images[i].texture!=IntPtr.Zero)
                                    {
                                        game.images[i].loaded = true;
                                        game.images[i].okloaded = true;
                                        game.images[i].neverloaded = false;
                                        LocalStorage.setitem("FILE LOAD:"+nightfile,"LOADED");//24mar2021
                                        imgloaded = true;//25apr2022
                                    }
                                    else //24mar2021
                                    {
                                        LocalStorage.setitem("FILE LOAD:"+nightfile,"FAILED TO LOAD");//24mar2021
                                    }            
                                }
                                else
                                {
                                    game.images[i].texture = SDL_image.IMG_LoadTexture(game.renderer,game.images[i].file);
                                    if(game.images[i].texture!=IntPtr.Zero)
                                    {
                                        game.images[i].loaded = true;
                                        game.images[i].okloaded = true;
                                        game.images[i].neverloaded = false;
                                        LocalStorage.setitem("FILE LOAD:"+game.images[i].file,"LOADED");//24mar2021
                                        imgloaded = true;//25apr2022
                                    }
                                    else //24mar2021
                                    {
                                        LocalStorage.setitem("FILE LOAD:"+game.images[i].file,"FAILED TO LOAD");//24mar2021
                                    }            
                                }
                            }
                        ////end------------//24feb2022
                        }
                        else//24feb2022
                        {
                            game.images[i].texture = SDL_image.IMG_LoadTexture(game.renderer,game.images[i].file);
                            if(game.images[i].texture!=IntPtr.Zero)
                            {
                                game.images[i].loaded = true;
                                game.images[i].okloaded = true;
                                game.images[i].neverloaded = false;
                                LocalStorage.setitem("FILE LOAD:"+game.images[i].file,"LOADED");//24mar2021
                                imgloaded = true;//25apr2022
                            }
                            else //24mar2021
                            {
                                LocalStorage.setitem("FILE LOAD:"+game.images[i].file,"FAILED TO LOAD");//24mar2021
                            }
                        }
                    }
                }
            }
        }
        //24feb2022 commented out
        //private static void ThreadFunction()
        //{
//            if(audio.file!="" && audio.file!=null)//28Feb2021
            //{
//                audio.audio = SDL_mixer.Mix_LoadMUS(audio.file);
            //}
            //if(audio.audio==IntPtr.Zero)
            //{
//                Console.WriteLine("Could Not Load Music:"+audio.file+". Error:"+SDL.SDL_GetError());
                //Network.reporterror("MusicLoadFailure:"+audio.file,false);//15mar2021
                //LocalStorage.setitem("FILE LOAD:"+audio.file,"FAILED TO LOAD"); //24mar2021
            //}
            //else //24mar2021
            //{
//                LocalStorage.setitem("FILE LOAD:"+audio.file,"LOADED"); //24mar2021
            //}
            //threadrunning = false;
        //}
    }
    //end---------------//28Feb2021

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Resources
    {
        //
        //put all resource names in here.....
        public static int LOGO = 0;
        public static int FONT = 0;
        public static int SMALLFONT = 0;
        public static int LARGEFONT = 0;
        public static int FOG = 0;
        public static int CLICK = 0;
        public static int blackcat = -1;
        public static int outro = -1;//28feb2022
        public static int intro = -1;//1mar2022
        public static int outrobad = -1;//28feb2022
        public static int credits = -1;//28feb2022
        public static int page01 = -1;//28feb2022
        //public static int loadingbk = -1; //27mar2021
        //public static int loadingbar = -1;//27mar2021
        //temporarily do this
        //start-------------//28Feb2021

///////////////////Method Definition///////////////
        public static bool readbool(string data)
        {
            ////////////////////////
            //takes a string that contains 'true' or 'false' and returns a bool value
            //string is form left identifier=right value
            //swapped if statements around 12sep2021
            if(data.Substring(data.IndexOf("=") + 1)=="false")//this was below the other if block earlier//12sep2021
            {
                return false;
            }
            else
            {
                if(data.Substring(data.IndexOf("=") + 1)=="true")
                {
                    return true;
                }
            }
            int i;
            Int32.TryParse(data.Substring(data.IndexOf("=") + 1),out i);
            if(i<=0)
            {
                return false;
            }
            else
            {
                if(i>0)
                {
                    return true;
                }
            }
            return false; //have to return something by default...so make it false by default....
        }
        //end---------------//28Feb2021

///////////////////Method Definition///////////////
        public static uint readuint(string data)//2apr2021
        {
            uint i;
            UInt32.TryParse(data.Substring(data.IndexOf("=")+1),out i);

            return i;
        
        }
        
///////////////////Method Definition///////////////
        public static int readint(string data)
        {
            //takes a string that contains an int, with no commas or period symbols
            //and converts to an integer.
            //string is of form left identifier=right value
            int i;
            Int32.TryParse(data.Substring(data.IndexOf("=") + 1),out i);
            return i;
        }

///////////////////Method Definition///////////////
        public static float readfloat(string data)
        {
            //takes a string in 100.01 format (ie one hundred point oh-one)
            //and returns the float value
            //string is of form left identifier=right value
            
            float i;
            try
            {
                System.Globalization.NumberStyles style = System.Globalization.NumberStyles.AllowDecimalPoint; //22mar2021
                CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US"); //22mar2021
                if(!Single.TryParse(data.Substring(data.IndexOf("=") + 1),style,culture,out i)) //22mar2021
                {
                    if(data.IndexOf("-")>=0)
                    {
                        if(!Single.TryParse(data.Substring(data.IndexOf("=") + 2),style,culture,out i)) //22mar2021
                        {
                            Console.WriteLine("Error reading float:"+data);
                            i = 1.0f;
                            LocalStorage.setitem("READ FLOAT:"+readstring(data),"FAILED 1");//24mar2021
                        }
                        else
                        {
                            i*=-1f;
                            LocalStorage.setitem("READ FLOAT:"+readstring(data),"SUCCESS");//24mar2021
                        }
                    }
                    else
                    {
                    Console.WriteLine("Error reading float:"+data);
                    i = 1.0f;
                    LocalStorage.setitem("READ FLOAT:"+readstring(data),"FAILED 1");//24mar2021
                    }
                }
                else
                {
                    LocalStorage.setitem("READ FLOAT:"+readstring(data),"SUCCESS");//24mar2021
                }
            }
            catch(Exception e)
            {
                i = 1f;
                Console.WriteLine("Error reading float:"+e.Message);
                LocalStorage.setitem("READ FLOAT:"+readstring(data),"FAILED 2");//24mar2021
            }
            return i;
        }

///////////////////Method Definition///////////////
        public static string readstring(string data)
        {
            //simply returns a string from a line that looks like x=abc
            //ie left identifier=right value
            return data.Substring(data.IndexOf("=") + 1);
        }
    
///////////////////Method Definition///////////////
        public static void AssignOffsets(Game game,string file)//20apr2021
        {
            if(file=="")
            {
                return;
            }
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);
                for(int i=0;i<data.Length;i++)
                {
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "image":
                                string value = readstring(data[i]);
                                string[] values = value.Split(",");
                                if(values!=null)
                                {
                                    if(values.Length==3)
                                    {
                                        string tmpname = values[0];
                                        int offx = 0;
                                        int offy = 0;
                                        Int32.TryParse(values[1],out offx);
                                        Int32.TryParse(values[2],out offy);
                                        for(int j=0;j<game.templates.Length;j++)
                                        {
                                            if(game.templates[j].catfile==tmpname)
                                            {
                                                game.templates[j].offx = offx;
                                                game.templates[j].offy = offy;
                                                game.templates[j].autocalcedoffsets = true;
                                            }
                                        }
                                    }
                                }
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                string msg = e.Message;
            }
        }
        
        
///////////////////Method Definition///////////////
        public static void LoadGui(Game game, string file)
        {
            ////////////////////////
            //load the gui elements into the game.gui array
            //so that we can reference them later on
            int alti = 0;//11apr2021
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);//13mar2021
                //string[] data = System.IO.File.ReadAllLines(file,System.Text.Encoding.UTF8);//13mar2021
                int count = 0;
                for(int i=0;i<data.Length;i++)
                {
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "newgui":
                            count++;
                            break;
                        }
                    }
                }
                if(count>0)
                {
                    game.gui = new Gui[count];
                    int id = -1;
                    int cw = 0;
                    int ch = 0;
                    int nw = 0;
                    int nh = 0;
                    int fontsize = 0;
                    string fontfile = "";
                    for(int i=0;i<data.Length;i++)
                    {
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "newgui":
                                id++;
                                game.gui[id] = new Gui(game);
                                game.gui[id].reset(game,id);
                                alti = 0;//11apr2021
                                Game.LoadingProgress(game);
                                break;
                                case "type":
                                game.gui[id].type = readint(data[i]);    
                                break;
                                case "screenname":
                                game.gui[id].screenname = readstring(data[i]);
                                break;
                                case "missionindex":
                                game.gui[id].missionindex = readint(data[i]);
                                break;
                                case "index": //28mar2021
                                game.gui[id].index = readint(data[i]); //28mar2021
                                break;//28mar2021
                                case "techlinkid"://2sep2021
                                game.gui[id].index = readint(data[i]);//2sep2021
                                break;//2sep2021
                                //start-------------//28Feb2021
                                case "missionname":
                                game.gui[id].missionname = readstring(data[i]);
                                break;
                                //end---------------//28Feb2021
                                case "topindexzero": //24Feb2021
                                game.gui[id].topindexzero = (int)Functions.abs(Functions.sign(readint(data[i])));//24Feb2021
                                break;//24Feb2021
                                case "link":
                                game.gui[id].link = readstring(data[i]);
                                break;
                                case "command":
                                game.gui[id].command = readstring(data[i]);
                                break;
                                case "title":
                                game.gui[id].title = readstring(data[i]);
                                if(Config.TRANSLATEGUI)//21mar2021
                                {
                                    game.gui[id].title = Translation.TranslateWord(game.gui[id].title,false);
                                }
                                break;
                                case "tooltip":
                                game.gui[id].tooltip = readstring(data[i]);
                                if(Config.TRANSLATEGUI)//21mar2021
                                {
                                    game.gui[id].tooltip = Translation.TranslateWord(game.gui[id].tooltip,false);
                                }
                                break;
                                case "action":
                                game.gui[id].action = readint(data[i]);
                                break;
                                case "hidden":
                                game.gui[id].hidden = readint(data[i]);
                                break;
                                case "backgroundrect":
                                    string[] tmpbk = readstring(data[i]).Split(",");
                                    if(tmpbk.Length==7)
                                    {
                                        int rx = 0;
                                        int ry = 0;
                                        int rw = 0;
                                        int rh = 0;
                                        int rgb_r = 0;
                                        int rgb_b = 0;
                                        int rgb_g = 0;
                                        Int32.TryParse(tmpbk[0],out rx);
                                        Int32.TryParse(tmpbk[1],out ry);
                                        Int32.TryParse(tmpbk[2],out rw);
                                        Int32.TryParse(tmpbk[3],out rh);
                                        Int32.TryParse(tmpbk[4],out rgb_r);
                                        Int32.TryParse(tmpbk[5],out rgb_g);
                                        Int32.TryParse(tmpbk[6],out rgb_b);
                                        game.gui[id].backgroundrect = true;
                                        game.gui[id].backgroundrectcoords[0] = rx;
                                        game.gui[id].backgroundrectcoords[1] = ry;
                                        game.gui[id].backgroundrectcoords[2] = rw;
                                        game.gui[id].backgroundrectcoords[3] = rh;
                                        game.gui[id].backgroundrectcolor[0] = (byte)rgb_r;
                                        game.gui[id].backgroundrectcolor[1] = (byte)rgb_g;
                                        game.gui[id].backgroundrectcolor[2] = (byte)rgb_b;
                                    }
                                break;
                                //start-------------//11mar2021
                                case "horizontal":
                                game.gui[id].horizontal = readint(data[i]);
                                break;
                                case "vertical":
                                game.gui[id].vertical = readint(data[i]);
                                break;
                                //end---------------//11mar2021
                                case "triggerlink":
                                game.gui[id].triggerlink = readint(data[i]);
                                break;
                                //start-------------//31dec2021
                                case "triggervariable":
                                game.gui[id].triggervariable = readint(data[i]);
                                break;
                                case "triggerop":
                                game.gui[id].triggerop = readint(data[i]);
                                break;
                                case "triggernum":
                                game.gui[id].triggernum = readint(data[i]);
                                break;
                                //end---------------//31dec2021
                                case "mission":
                                game.gui[id].mission = readint(data[i]);
                                break;
                                case "gamestate":
                                game.gui[id].gamestate = 10000 + readint(data[i]);
                                break;
                                case "nextscreenname":
                                game.gui[id].nextscreenname = readstring(data[i]);
                                break;
                                case "nextgamestate":
                                game.gui[id].nextgamestate = 10000 + readint(data[i]);
                                break;
                                case "x":
                                game.gui[id].x = readint(data[i]);
                                break;
                                case "y":
                                game.gui[id].y = readint(data[i]);
                                break;
                                case "w":
                                game.gui[id].w = readint(data[i]);
                                break;
                                case "h":
                                game.gui[id].h = readint(data[i]);
                                break;
                                case "cw":
                                cw = readint(data[i]);
                                break;
                                case "ch":
                                ch = readint(data[i]);
                                break;
                                case "nw":
                                nw = readint(data[i]);
                                break;
                                case "nh":
                                nh = readint(data[i]);
                                break;
                                case "altimage":
                                //11apr2021 - modified to be an array
                                if(alti>4)
                                {
                                    continue;
                                }
                                game.gui[id].altimagefile[alti] = readstring(data[i]);
                                bool found = false;
                                for(int j=0;j<id;j++)
                                {
                                    for(int k=0;k<alti+1;k++)
                                    {
                                        if(game.gui[j].altimagefile[alti]==game.gui[id].altimagefile[k])
                                        {
                                            found = true;
                                            game.gui[id].altimage[alti] = game.gui[j].altimage[k];
                                            break;
                                        }
                                    }
                                }
                                for(int j=0;j<id;j++)
                                {
                                    for(int k=0;k<alti+1;k++)
                                    {
                                        if(game.gui[j].imagefile==game.gui[id].altimagefile[k])
                                        {
                                            found = true;
                                            game.gui[id].altimage[alti] = game.gui[j].image;
                                            break;
                                        }
                                    }
                                }
                                if(!found){game.gui[id].altimage[alti] = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);}
                                alti++;
                                break;
                                case "image":
                                game.gui[id].imagefile = readstring(data[i]);
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.gui[j].imagefile==game.gui[id].imagefile)
                                    {
                                        found = true;
                                        game.gui[id].image = game.gui[j].image;
                                        break;
                                    }
                                }
                                if(!found){game.gui[id].image = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);}
                                game.gui[id].tmpimage = game.gui[id].image; //30apr2021
                                break;
                                case "scale":
                                game.gui[id].scale = readfloat(data[i]);
                                break;
                                case "font":
                                fontfile = readstring(data[i]);
                                game.gui[id].fontfile = fontfile;
                                break;
                                case "ptsize":
                                fontsize = readint(data[i]);
                                game.gui[id].fontsize = fontsize;// * Config.FONTALIAS;
                                break;
                                case "loadfont":
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.gui[j].fontfile==game.gui[id].fontfile && game.gui[j].fontsize==game.gui[id].fontsize)
                                    {
                                        found = true;
                                        game.gui[id].font = game.gui[j].font;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    if(fontfile!="" && fontsize>0)
                                    {
                                        game.gui[id].font = Resources.LoadFont(game,fontfile,fontsize);
                                    }
                                }
                                fontfile = "";
                                fontsize = 0;
                                break;
                            }
                        }
                    }
                }
                LocalStorage.setitem("FILE LOAD:"+file,"SUCCESS");//24mar2021
            }
            catch(Exception e)
            {
                Console.WriteLine("403:"+e.Message);
                LocalStorage.setitem("FILE LOAD:"+file,"FAILED");//24mar2021
            }
        }

///////////////////Method Definition///////////////
        public static string[] processextraunits() //7mar2021
        {
            ////////////////////////
            //in the config files we can have multiple lines indicating
            //multiple files for creatures and so forth
            //this method handles getting this data before we create all our
            //templates in LoadTemplates
            string[] data = new string[0];
            try
            {
                string[] config = System.IO.File.ReadAllLines(Config.configfile);
                for(int i=0;i<config.Length;i++)
                {
                    if(config[i].IndexOf("=")>0)
                    {
                        switch(config[i].Substring(0,config[i].IndexOf("=")))
                        {
                            case "extraunits":
                            try
                            {
                                string filename = readstring(config[i]);
                                string[] data2 = System.IO.File.ReadAllLines(filename);
                                if(data2!=null && data2.Length>0)
                                {
                                    int ii = data.Length;
                                    Array.Resize<string>(ref data,data.Length + data2.Length);
                                    for(int j=0;j<data2.Length;j++)
                                    {
                                        data[ii + j] = data2[j];
                                    }                
                                }
                            }
                            catch(Exception f)
                            {
                                Console.WriteLine("Error:"+f.Message);
                            }
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Error:"+e.Message);
            }
            return data;
        }
        
///////////////////Method Definition///////////////
        public static void LoadTech(Game game, string file) //2sep2021
        {
            ////////////////////////
            //load all the tech templates
            //that we will use in the game.
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);
                int count = 0;
                for(int i=0;i<data.Length;i++)
                {
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "newtech":
                            count++;
                            break;                            
                        }
                    }
                }
                if(count>0)
                {
                    game.techs = new Tech[count];
                    int id = -1;
                    for(int i=0;i<data.Length;i++)
                    {
                        //Unit Template.....
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "newtech":
                                id++;
                                game.techs[id] = new Tech();
                                game.techs[id].reset(game,id,false);
                                game.techs[id].name = readstring(data[i]);
                                game.techs[id].description = readstring(data[i]).Split("|");
                                count++;
                                break;    
                                case "description":
                                game.techs[id].description = readstring(data[i]).Split("|");
                                break;
                                case "tooltip":
                                game.techs[id].tooltip = readstring(data[i]);
                                break;
                                case "displayname":
                                game.techs[id].displayname = readstring(data[i]);
                                break;
                                case "cellwidth":
                                game.techs[id].cw = readint(data[i]);
                                break;
                                case "cellheight":
                                game.techs[id].ch = readint(data[i]);
                                break;
                                case "cellswide":
                                game.techs[id].nw = readint(data[i]);
                                break;
                                case "cellshigh":
                                game.techs[id].nh = readint(data[i]);
                                break;
                                //start----------//23sep2021
                                case "salecellwidth":
                                game.techs[id].scw = readint(data[i]);
                                break;
                                case "salecellheight":
                                game.techs[id].sch = readint(data[i]);
                                break;
                                case     "salecellswide":
                                game.techs[id].snw = readint(data[i]);
                                break;
                                case "salecellshigh":
                                game.techs[id].snh = readint(data[i]);
                                break;
                                //end----------//23sep2021
                            
                                case "effectname":
                                game.techs[id].effectname = readstring(data[i]);
                                break;
                                case "effectint":
                                game.techs[id].effectint = readint(data[i]);
                                break;
                                case "parseeffect": //needed to parse the effect name and apply the effect int as required....
                                Tech.parseeffect(game,id);
                                break;
                                case "researchtime":
                                game.techs[id].researchtime = 60 * readint(data[i]); //multiply by frames per second....
                                break;
                                case "image":
                                game.techs[id].imgfile = readstring(data[i]);
                                bool found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.techs[j].imgfile==game.techs[id].imgfile)
                                    {
                                        found = true;
                                        game.techs[id].img = game.techs[j].img;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    game.techs[id].img = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,game.techs[id].cw,game.techs[id].ch,game.techs[id].nw,game.techs[id].nh);
                                }
                                break;
                                case "frame":
                                game.techs[id].imgframe = readint(data[i]);
                                break;
                                //start----------//23sep2021
                                case "saleimage"://23sep2021
                                game.techs[id].saleimgfile = readstring(data[i]);
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.techs[j].saleimgfile==(game.techs[id].saleimgfile))
                                    {
                                        found = true;
                                        game.techs[id].saleimg = game.techs[j].saleimg;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    game.techs[id].saleimg = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,game.techs[id].scw,game.techs[id].sch,game.techs[id].snw,game.techs[id].snh);
                                }
                                break;
                                case "techclass":
                                game.techs[id].techclass = readstring(data[i]);
                                break;
                                case "saleframe":
                                game.techs[id].saleimgframe = readint(data[i]);
                                break;
                                //end------------//23sep2021
                                case "guilinkid":
                                game.techs[id].guilinkid = readint(data[i]);
                                break;
                                case "faction":
                                game.techs[id].faction = readint(data[i]);
                                break;
                                //start----------//23sep2021
                                case "goldcost":
                                game.techs[id].goldcost = readint(data[i]);
                                break;
                                case "unlimited":
                                game.techs[id].unlimited = readint(data[i]);
                                break;
                                case "purchaseguilink":
                                game.techs[id].purchaseguilink = readint(data[i]);
                                break;
                                case "temporary":
                                game.techs[id].temporary = readint(data[i]);    
                                break;
                                case "manacost":
                                game.techs[id].manacost = readint(data[i]);
                                break;
                                case "attackaction":
                                game.techs[id].attackaction = readint(data[i]);    
                                break;
                                case "guiactionid":
                                game.techs[id].guiactionid = readint(data[i]);
                                break;
                                //end------------//23sep2021

                            }
                        }
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("222:"+e.Message);
                LocalStorage.setitem("FILE LOAD:"+file,"FAILED");//24mar2021
            }
        }
///////////////////Method Definition///////////////
        public static void LoadTemplates(Game game, string file)
        {
            ////////////////////////
            //load all the creature/unit templates
            //that we will use in the game.
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);
                //start-------------//7mar2021
                string[] data2 = processextraunits();
                if(data2!=null && data2.Length>0)
                {
                    int ii = data.Length;
                    Array.Resize<string>(ref data,data.Length + data2.Length);
                    for(int i=0;i<data2.Length;i++)
                    {
                        data[ii + i] = data2[i];
                    }
                }
                //end---------------//7mar2021
                int count = 0;
                for(int i=0;i<data.Length;i++)
                {
                    //Unit Template.....
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "newtemplate":
                            count++;
                            break;                            
                        }
                    }
                }
                if(count>0)
                {
                    game.templates = new Unit[count];
                    int id = -1;
                    int cw = 0;
                    int ch = 0;
                    int nw = 0;
                    int nh = 0;
                    for(int i=0;i<data.Length;i++)
                    {
                        //Unit Template.....
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "newtemplate":
                                id++;
                                game.templates[id] = new Unit(game);
                                game.templates[id].reset(game,id);
                                game.templates[id].name = readstring(data[i]);
                                game.templates[id].description = readstring(data[i]).Split("|");
                                game.templates[id].charactername = "";//10sep2021 default it to blank to start with....
                                game.templates[id].displaycharactername = 0;//10sep2021
                                count++;
                                Game.LoadingProgress(game);
                                break;    
                                //start--------------//13mar2021
                                case "displayname":
                                game.templates[id].displayname = readstring(data[i]);
                                //start-----------------//20mar2021
                                if(game.templates[id].description[0]==game.templates[id].name)
                                {
                                    game.templates[id].description[0] = readstring(data[i]);
                                }
                                //end-------------------//20mar2021
                                break;
                                //end----------------//13mar2021
                                case "faction":
                                game.templates[id].faction = readint(data[i]);
                                break;
                                case "cellwidth":
                                cw = readint(data[i]);
                                game.templates[id].cw = cw;
                                break;
                                case "cellheight":
                                ch = readint(data[i]);
                                game.templates[id].ch = ch;
                                break;
                                case "frameswide":
                                nw = readint(data[i]);
                                break;
                                case "frameshigh":
                                nh = readint(data[i]);
                                break;
                                //9apr2021 hires stuff
                                case "hires":
                                if(Config.hires==0) //can switch it off if we wish....
                                {
                                    continue;
                                }
                                game.templates[id].cathiresfile = readstring(data[i]);
                                bool found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.templates[j].cathiresfile==game.templates[id].cathiresfile)
                                    {
                                        found = true;
                                        game.templates[id].cathires = game.templates[j].cathires;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    //9apr2021 observe - double the resolution, otherwise the same....
                                    //"hires=filename" should appear in the txt file immediately following the original 'image=' line....
                                    game.templates[id].cathires = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw * 2,ch * 2,nw,nh);
                                }
                                break;
                                case "image":
                                game.templates[id].catfile = readstring(data[i]);
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.templates[j].catfile==game.templates[id].catfile)
                                    {
                                        found = true;
                                        game.templates[id].cat = game.templates[j].cat;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    game.templates[id].cat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.templates[id].offxa = new int[nw*nh]; //20apr2021
                                    game.templates[id].offya = new int[nw*nh]; //20apr2021
                                }
                                break;
                                case "dropshadow"://25sep2021
                                game.templates[id].dropshadow = readint(data[i]);
                                break;
                                case "enemyimage":
                                game.templates[id].ecatfile = readstring(data[i]);
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.templates[j].ecatfile==game.templates[id].ecatfile)
                                    {
                                        found = true;
                                        game.templates[id].ecat = game.templates[j].ecat;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    game.templates[id].ecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                }
                                break;
                                case "friendlyimage":
                                game.templates[id].fcatfile = readstring(data[i]);
                                found = false;
                                for(int j=0;j<id;j++)
                                {
                                    if(game.templates[j].fcatfile==game.templates[id].fcatfile)
                                    {
                                        found = true;
                                        game.templates[id].fcat = game.templates[j].fcat;
                                        break;
                                    }
                                }
                                if(!found)
                                {
                                    game.templates[id].fcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                }
                                break;
                                case "controlpoint":
                                game.templates[id].controlpoint = readint(data[i]);
                                break;
                                case "framesperdirn":
                                game.templates[id].framesperdirn = readint(data[i]);
                                break;
                                case "nodirn":
                                game.templates[id].nodirn = readint(data[i]);
                                break;
                                case "offy":
                                game.templates[id].offy = readint(data[i]);
                                break;
                                case "controlmode"://24sep2021
                                game.templates[id].controlmode = readstring(data[i]);
                                break;
                                case "mirror":
                                if(readint(data[i])==1)
                                {
                                    game.templates[id].mirrorleftright = true;
                                }
                                break;
                                case "description":
                                game.templates[id].description = readstring(data[i]).Split("|");
                                break;
                                case "basehp":
                                //game.templates[id].basehp = readint(data[i]);//20mar2021
                                game.templates[id].basehp = readint(data[i]) * Config.HEALTHPCT / 100;//20mar2021
                                //round to the nearest 5 points
                                game.templates[id].basehp += (5 - (game.templates[id].basehp % 5)) * Functions.sign(game.templates[id].basehp % 5);//20mar2021
                                game.templates[id].hp = game.templates[id].basehp;
                                break;
                                //start----------------//23sep2021
                                case "basemana":
                                    game.templates[id].basemana = readint(data[i]);
                                    game.templates[id].mana = readint(data[i]);
                                break;
                                case "manarate":
                                    game.templates[id].manarate = readint(data[i]);
                                break;
                                case "attacklimit"://23sep2021
                                game.templates[id].guiattackdisplaylimit = readint(data[i]);
                                break;
                                case "gold"://23sep2021
                                game.templates[id].gold = readint(data[i]);//23sep2021    
                                break;
                                case "canpickup"://23sep2021
                                game.templates[id].canpickup = readint(data[i]);//23sep2021    
                                break;
                                //end------------------//23sep2021
                                case "armour":
                                //game.templates[id].armour = readint(data[i]); //20mar2021
                                game.templates[id].armour = readint(data[i]) * Config.ARMOURPCT / 100;//20mar2021
                                break;
                                case "damage":
                                //game.templates[id].damage = readint(data[i]);//20mar2021
                                game.templates[id].damage = readint(data[i]) * Config.ATTACKPCT / 100;//20mar2021
                                break;
                                //start--------------//2sep2021
                                case "guilinkid":
                                //game.templates[id].techguilinkid = readint(data[i]);//26feb2022
                                //start---//26feb2022
                                int[] oldtech = new int[game.templates[id].techguilinkid.Length + 1];//26feb2022
                                for(int tt=0;tt<oldtech.Length - 1;tt++)
                                {
                                    oldtech[tt] = game.templates[id].techguilinkid[tt];
                                }
                                game.templates[id].techguilinkid = new int[oldtech.Length];
                                for(int tt=0;tt<oldtech.Length - 1;tt++)
                                {
                                    game.templates[id].techguilinkid[tt] = oldtech[tt];
                                }
                                game.templates[id].techguilinkid[oldtech.Length - 1] = readint(data[i]);
                                //end---//26feb2022
                                break;
                                case "researchneeded":
                                game.templates[id].unresearchedbydefault = readint(data[i]);
                                break;
                                //end----------------//2sep2021
                                case "firebullet":
                                game.templates[id].firebullet = readint(data[i]);
                                break;
                                case "range":
                                game.templates[id].firerange = readint(data[i]);
                                //start------------//24feb2022
                                //if(Config.useseasons>0 && Config.Night>0)
                                //{
//                                    //units that fire bullets do so at lesser range at night...by a little.
                                    //if(game.templates[id].firerange > 100)
                                    //{
//                                        game.templates[id].firerange *= 4;
                                        //game.templates[id].firerange /= 5;
                                    //}
                                //}
                                //end--------------//24feb2022
                                break;
                                case "needlos"://15sep2021
                                game.templates[id].needlos = readint(data[i]);
                                break;
                                case "damage2":
                                //game.templates[id].damage2 = readint(data[i]);//20mar2021
                                game.templates[id].damage2 = readint(data[i]) * Config.ATTACKPCT / 100;//20mar2021
                                break;
                                case "range2":
                                game.templates[id].firerange2 = readint(data[i]);
                                //start------------//24feb2022
                                //if(Config.useseasons>0 && Config.Night>0)
                                //{
//                                    //units that fire bullets do so at lesser range at night...by a little.
                                    //if(game.templates[id].firerange2 > 100)
                                    //{
//                                        game.templates[id].firerange2 *= 4;
                                        //game.templates[id].firerange2 /= 5;
                                    //}
                                //}
                                //end--------------//24feb2022
                                break;
                                case "splash"://2sep2021
                                game.templates[id].splash = readint(data[i]);
                                break;
                                case "levelxp":
                                game.templates[id].levelxp = readint(data[i]);
                                break;
                                case "xpvalue":
                                game.templates[id].xpvalue = readint(data[i]);
                                break;
                                case "prefermobiletargets"://18sep2021
                                game.templates[id].prefermobiletargets = readint(data[i]);
                                break;
                                case "spellcaster":
                                game.templates[id].spellcaster = readint(data[i]);
                                break;
                                case "notabuffer": //15apr2021
                                game.templates[id].notabuffer = readint(data[i]);
                                break;
                                case "extragibbet"://18sep2021
                                game.templates[id].extragibbet = readint(data[i]);
                                break;
                                case "firespell":
                                game.templates[id].firespell = readint(data[i]);
                                break;
                                case "points"://17sep2021
                                game.templates[id].points = readint(data[i]);
                                break;
                                case "powerspell":
                                game.templates[id].powerspell = readint(data[i]);
                                break;
                                case "infectchanceonhit"://22apr2022
                                game.templates[id].infectchanceonhit = readint(data[i]);
                                break;
                                case "infectchanceonkill"://22apr2022
                                game.templates[id].infectchanceonkill = readint(data[i]);
                                break;
                                case "infectinto"://22apr2022
                                game.templates[id].infectinto = readstring(data[i]);
                                break;
                                case "healer":
                                game.templates[id].healer = readint(data[i]);
                                break;
                                case "zombiemaster":
                                game.templates[id].zombiemaster = readint(data[i]);
                                break;
                                case "banishment": //12mar2021
                                game.templates[id].banish = readint(data[i]);
                                break;
                                case "dustcloud":
                                game.templates[id].dustcloud = readint(data[i]);
                                break;
                                case "timid":
                                game.templates[id].timid = readint(data[i]);
                                break;
                                case "hitandrun":
                                game.templates[id].hitandrun = readint(data[i]);
                                break;
                                case "buildpenalty": //20mar2021
                                game.templates[id].buildpenalty = readint(data[i]);//20mar2021
                                break;//20mar2021
                                case "brave":
                                game.templates[id].brave = readint(data[i]);
                                break;
                                //start-----------//01apr2021
                                case "spellability":
                                game.templates[id].spellability = readint(data[i]);
                                break;
                                case "ping"://16sep2021
                                game.templates[id].ping = readint(data[i]);
                                break;
                                case "spelldefense": //magic resistance....
                                game.templates[id].spelldefense = readint(data[i]);
                                break;
                                //start--------------//4may2021
                                case "canfly":
                                game.templates[id].canfly = readint(data[i]);
                                break;
                                case "canflyandwalk":
                                game.templates[id].canflyandwalk = readint(data[i]);
                                break;
                                case "canattackair":
                                game.templates[id].canattackair = readint(data[i]);
                                break;
                                //end----------------//4may2021
                                //start--------------//3may2021
                                case "magicrelease": //for getting out of transports
                                game.templates[id].magicrelease = readint(data[i]);
                                if(game.templates[id].magicrelease>0)
                                {
                                    game.templates[id].magicrelease = Unit.MAGICRELEASE;
                                }
                                break;
                                case "magictransform": //for transforming into a different unit
                                game.templates[id].magictransform = readint(data[i]);
                                if(game.templates[id].magictransform>0)
                                {
                                    game.templates[id].magictransform = Unit.MAGICTRANSFORM;
                                }
                                break;
                                case "transforminto":
                                game.templates[id].transforminto = readstring(data[i]);
                                break;
                                case "transformrequires":
                                game.templates[id].transformrequires = readstring(data[i]); //pipe separated list of entries....
                                //currently we don't have any requirements...
                                break;
                                case "transportcapacity":
                                game.templates[id].transportcapacity = readint(data[i]);
                                if(game.templates[id].transportcapacity>0)
                                {
                                    game.templates[id].transportarray = new int[game.templates[id].transportcapacity];
                                }
                                break;
                                case "transportsize":
                                game.templates[id].transportsize = readint(data[i]);
                                break;
                                //end----------------//3may2021
                                //start--------------//9apr2021
                                case "magicsummoner":
                                game.templates[id].magiczombiemaster = readint(data[i]);
                                if(game.templates[id].magiczombiemaster>0)
                                {
                                    game.templates[id].magiczombiemaster = Unit.MAGICZOMBIEMASTER;
                                }
                                break;
                                case "magiczombiemaster"://redundant version alias
                                game.templates[id].magiczombiemaster = readint(data[i]);
                                if(game.templates[id].magiczombiemaster>0)
                                {
                                    game.templates[id].magiczombiemaster = Unit.MAGICZOMBIEMASTER;
                                }
                                break;
                                case "magicleader":
                                game.templates[id].magicleader = readint(data[i]);
                                if(game.templates[id].magicleader>0)
                                {
                                    game.templates[id].magicleader = Unit.MAGICLEADER;
                                }
                                break;
                                //end----------------//9apr2021
                                case "magicfrenzy":
                                game.templates[id].magicfrenzy = readint(data[i]);
                                if(game.templates[id].magicfrenzy>0)
                                {
                                    game.templates[id].magicfrenzy = Unit.MAGICFRENZY;
                                }
                                break;
                                case "magicdoom":
                                game.templates[id].magicdoom = readint(data[i]);
                                if(game.templates[id].magicdoom>0)
                                {
                                    game.templates[id].magicdoom = Unit.MAGICDOOM;
                                }
                                break;
                                case "magicdefense":
                                game.templates[id].magicdef = readint(data[i]);
                                if(game.templates[id].magicdef>0)
                                {
                                    game.templates[id].magicdef = Unit.MAGICDEF;
                                }
                                break;
                                case "magicdef": //redundancy
                                game.templates[id].magicdef = readint(data[i]);
                                if(game.templates[id].magicdef>0)
                                {
                                    game.templates[id].magicdef = Unit.MAGICDEF;
                                }
                                break;
                                //end-------------//01apr2021
                                //start---------------//28mar2021
                                case "magicweb":
                                game.templates[id].magicweb = readint(data[i]);
                                if(game.templates[id].magicweb>0)
                                {
                                    game.templates[id].magicweb = Unit.MAGICWEB;
                                }
                                break;
                                case "magicgas":
                                game.templates[id].magicgas = readint(data[i]);
                                if(game.templates[id].magicgas>0)
                                {
                                    game.templates[id].magicgas = Unit.MAGICGAS;
                                }
                                break;
                                case "magichaste":
                                game.templates[id].magichaste = readint(data[i]);
                                if(game.templates[id].magichaste>0)
                                {
                                    game.templates[id].magichaste = Unit.MAGICHASTE;
                                }
                                break;
                                case "magicfear":
                                game.templates[id].magicfear = readint(data[i]);
                                if(game.templates[id].magicfear>0)
                                {
                                    game.templates[id].magicfear = Unit.MAGICFEAR;
                                }
                                break;
                                case "magicshield":
                                game.templates[id].magicshield = readint(data[i]);
                                if(game.templates[id].magicshield>0)
                                {
                                    game.templates[id].magicshield = Unit.MAGICSHIELD;
                                }
                                break;
                                case "magicstorm":
                                game.templates[id].magicstorm = readint(data[i]);
                                if(game.templates[id].magicstorm>0)
                                {
                                    game.templates[id].magicstorm = Unit.MAGICSTORM;
                                }
                                break;
                                case "magicsword":
                                game.templates[id].magicsword = readint(data[i]);
                                if(game.templates[id].magicsword>0)
                                {
                                    game.templates[id].magicsword = Unit.MAGICSWORD;
                                }
                                break;
                                case "magicstealth":
                                game.templates[id].magicstealth = readint(data[i]);
                                if(game.templates[id].magicstealth>0)
                                {
                                    game.templates[id].magicstealth = Unit.MAGICSTEALTH;
                                }
                                break;
                                case "magicplant":
                                game.templates[id].magicplant = readint(data[i]);
                                if(game.templates[id].magicplant>0)
                                {
                                    game.templates[id].magicplant = Unit.MAGICPLANT;
                                }
                                break;
                                case "magicwind":
                                game.templates[id].magicwind = readint(data[i]);
                                if(game.templates[id].magicwind>0)
                                {
                                    game.templates[id].magicwind = Unit.MAGICWIND;
                                }
                                break;
                                //end-----------------//28mar2021
                                case "highfirerate": //25Feb2021
                                game.templates[id].highfirerate = readint(data[i]);
                                break;
                                //start-------------//7mar2021
                                case "mob":
                                game.templates[id].mob = readint(data[i]);
                                break;
                                case "hatred":
                                game.templates[id].hatred = readint(data[i]);
                                break;
                                case "craftsman":
                                game.templates[id].craftsman = readint(data[i]);
                                break;
                                case "dieonplace"://21feb2022
                                game.templates[id].dieonplace = readint(data[i]);
                                break;
                                case "deathanim"://21feb2022
                                game.templates[id].deathanim = readstring(data[i]);
                                break;
                                case "planar":
                                game.templates[id].planar = readint(data[i]);
                                break;
                                case "slow":
                                game.templates[id].slow = readint(data[i]);
                                break;
                                case "woodsman":
                                game.templates[id].woodsman = readint(data[i]);
                                break;
                                case "stupid":
                                game.templates[id].stupid = readint(data[i]);
                                break;
                                case "frenzy":
                                game.templates[id].frenzy = readint(data[i]);
                                break;
                                //end---------------//7mar2021
                                case "shocktroops":
                                game.templates[id].shock = readint(data[i]);
                                break;
                                case "shock": //2sep2021
                                game.templates[id].shock = readint(data[i]);//2sep2021
                                break;//2sep2021
                                case "stealth":
                                game.templates[id].stealth = readint(data[i]);
                                break;
                                case "accuracy"://28feb2022
                                game.templates[id].accuracy = readint(data[i]);
                                break;
                                case "damagex":
                                game.templates[id].damagex = readint(data[i]);
                                break;
                                case "fearsome":
                                game.templates[id].fearsome = readint(data[i]);
                                break;
                                case "leader":
                                game.templates[id].leader = readint(data[i]);
                                break;
                                case "scale"://25sep2021
                                game.templates[id].scale = readfloat(data[i]);
                                break;
                                case "bounddemon"://12jul2021
                                game.templates[id].bounddemon = readint(data[i]);
                                break;
                                case "spawner":
                                game.templates[id].spawner = readstring(data[i]);
                                game.templates[id].spawnerconstraint = "*";
                                break;
                                case "spawnerconstraint": //9sep2021
                                game.templates[id].spawnerconstraint = readstring(data[i]);
                                break;
                                case "spawnercount":
                                game.templates[id].spawnercount = readint(data[i]);
                                break;
                                case "spawnertime":
                                game.templates[id].spawnertime = readint(data[i]);
                                break;
                                case "bossmonster":
                                game.templates[id].bossmonster = readint(data[i]);
                                break;
                                case "flammable":
                                game.templates[id].flammable = readint(data[i]);
                                break;
                                case "regeneration":
                                game.templates[id].regeneration = readint(data[i]);
                                break;
                                case "zombie":
                                game.templates[id].zombie = readint(data[i]);
                                break;
                                case "evilfire":
                                game.templates[id].firespell = - readint(data[i]);
                                break;
                                case "sacrificial":
                                game.templates[id].sacrificial = readint(data[i]);
                                break;
                                case "cansacrifice":
                                game.templates[id].cansacrifice = readint(data[i]);
                                break;
                                case "animosity":
                                game.templates[id].animosity = readint(data[i]);
                                break;
                                //start-----------//25Feb2021
                                case "deadframestart":
                                game.templates[id].animmodedeadframestart = readint(data[i]);
                                break;
                                case "deadframeend":
                                game.templates[id].animmodedeadframeend = readint(data[i]);
                                break;
                                //end-------------//25Feb2021
                                //start-------------//28Feb2021
                                case "idle2framestart":
                                game.templates[id].animmodeidle2framestart = readint(data[i]);
                                break;
                                case "idle2frameend":
                                game.templates[id].animmodeidle2frameend = readint(data[i]);
                                break;
                                //end---------------//28Feb2021
                                case "idleframestart":
                                game.templates[id].animmodeidleframestart = readint(data[i]);
                                break;
                                case "idleframeend":
                                game.templates[id].animmodeidleframeend = readint(data[i]);
                                break;
                                case "walkframestart":
                                game.templates[id].animmodewalkframestart = readint(data[i]);
                                break;
                                case "walkframeend":
                                game.templates[id].animmodewalkframeend = readint(data[i]);
                                break;
                                //2sep2021 bug fix
                                case "flyframestart":
                                game.templates[id].animmodeflyframestart = readint(data[i]);
                                break;
                                case "flyframeend":
                                game.templates[id].animmodeflyframeend = readint(data[i]);
                                break;
                                //end 2sep2021
                                case "att1framestart":
                                game.templates[id].animmodeattframestart = readint(data[i]);
                                break;
                                case "att1frameend":
                                game.templates[id].animmodeattframeend = readint(data[i]);
                                break;
                                case "att2framestart":
                                game.templates[id].animmodeatt2framestart = readint(data[i]);
                                break;
                                case "att2frameend":
                                game.templates[id].animmodeatt2frameend = readint(data[i]);
                                break;
                                case "walkspeed":
                                game.templates[id].walkspeed = readint(data[i]);
                                break;
                                case "animspeed":
                                game.templates[id].animspeed = (5 * readint(data[i])) / 4;//29sep2021
                                break;
                                case "targetfx":
                                for(int a=0;a<game.templates[id].targetfx.Length;a++)
                                {
                                    if(game.templates[id].targetfx[a]==-1)
                                    {
                                        game.templates[id].targetfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "magicfx":
                                for(int a=0;a<game.templates[id].magicfx.Length;a++)
                                {
                                    if(game.templates[id].magicfx[a]==-1)
                                    {
                                        game.templates[id].magicfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "impactfx":
                                for(int a=0;a<game.templates[id].impactfx.Length;a++)
                                {
                                    if(game.templates[id].impactfx[a]==-1)
                                    {
                                        game.templates[id].impactfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "selectfx":
                                for(int a=0;a<game.templates[id].selectfx.Length;a++)
                                {
                                    if(game.templates[id].selectfx[a]==-1)
                                    {
                                        game.templates[id].selectfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "ackfx":
                                for(int a=0;a<game.templates[id].ackfx.Length;a++)
                                {
                                    if(game.templates[id].ackfx[a]==-1)
                                    {
                                        game.templates[id].ackfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "attackfx":
                                for(int a=0;a<game.templates[id].attackfx.Length;a++)
                                {
                                    if(game.templates[id].attackfx[a]==-1)
                                    {
                                        game.templates[id].attackfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                case "deathfx": //28jul2021
                                for(int a=0;a<game.templates[id].deathfx.Length;a++)
                                {
                                    if(game.templates[id].deathfx[a]==-1)
                                    {
                                        game.templates[id].deathfx[a] = Resources.LoadAudio(game,readstring(data[i]),false);
                                        break;
                                    }
                                }
                                break;
                                
                            }
                        }
                    }
                    //start-----------------//22mar2021
                    //in the event we don't set the displayname we can always look it up in the translation table..in case we have it there...makes it easier sometimes.
                    for(int i=0;i<game.templates.Length;i++)
                    {
                        if(game.templates[i].displayname=="")
                        {
                            game.templates[i].displayname = Translation.TranslateWord(game.templates[i].name,false);
                        }
                    }
                    //end-------------------//22mar2021
                }
                LocalStorage.setitem("FILE LOAD:"+file,"SUCCESS");//24mar2021
            }
            catch(Exception e)
            {
                Console.WriteLine("569:"+e.Message);
                LocalStorage.setitem("FILE LOAD:"+file,"FAILED");//24mar2021
            }
        }

///////////////////Method Definition///////////////
        public static bool comparecustomversions()
        {
            //compare the custom usercampaign.txt file with the one in the
            //install directory. This is so that we can make a copy in the user'sacrificial
            //local area for them to play around with
            int userversion = 0;
            int gameversion = 1;
            try
            {
                string[] datag = System.IO.File.ReadAllLines(Config.customcampaignfile);
                for(int i=0;i<datag.Length;i++)
                {
                    if(datag[i].IndexOf("=")>0)
                    {
                        switch(datag[i].Substring(0,datag[i].IndexOf("=")))
                        {
                            case "version":
                            gameversion = readint(datag[i]);
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                string msg0 = e.Message;
            }
            try
            {
                string[] datau = System.IO.File.ReadAllLines(Config.usercampaignfile);
                for(int i=0;i<datau.Length;i++)
                {
                    if(datau[i].IndexOf("=")>0)
                    {
                        switch(datau[i].Substring(0,datau[i].IndexOf("=")))
                        {
                            case "version":
                            userversion = readint(datau[i]);
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                string msg1 = e.Message;
            }
            if(userversion<gameversion)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

///////////////////Method Definition///////////////
        public static bool custommissionvalid(Game game,string[] data2,int i) //24Feb2021
        {
            //verify if the mission loaded by LoadCampaign is a valid mission
            //checks factions and existence of units
            bool anyplayers = false;
            int pfaction = Unit.HUMAN; //28Feb2021
            for(int j=i+1;j<data2.Length;j++)
            {
                if(data2[j].IndexOf("=")>0)
                {
                    if(data2[j].Substring(0,data2[j].IndexOf("="))=="mission")
                    {
                        break;
                    }
                    //start-------------//28Feb2021
                    if(data2[j].Substring(0,data2[j].IndexOf("="))=="playerfaction")
                    {
                        pfaction = Resources.readint(data2[j]);
                    }
                    //end---------------//28Feb2021
                    if(data2[j].Substring(0,data2[j].IndexOf("="))=="unit")
                    {
                        string[] unitlist = readstring(data2[j]).Split(",");
                        string unitname = unitlist[0];
                        bool found = false;
                        for(int k=0;k<game.templates.Length;k++)
                        {
                            if(unitname==game.templates[k].name)
                            {
                                //if(game.templates[k].faction==Unit.HUMAN) //28Feb2021
                                if(game.templates[k].faction==pfaction)//28Feb2021
                                {
                                    anyplayers = true;
                                }
                                found = true;
                                break;
                            }
                        }
                        if(!found)
                        {
                            return false;
                        }
                    }
                }
            }
            if(!anyplayers)
            {
                return false;
            }
            return true;
        }

///////////////////Method Definition///////////////
        public static void LoadCampaign(Game game,string file)
        {
            ////////////////////////
            //load the Campaign files including both custom and core campaigns.
            string errline = "";
            int toomanytrees = 0;
            int toomanyrocks = 0;
            int toomanywalls = 0;
            bool getnewversion = comparecustomversions();
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);
                string[] data2 = new string[0];
                try
                {
                    data2 = System.IO.File.ReadAllLines(Config.usercampaignfile);
                    LocalStorage.setitem("FILE LOAD:"+Config.usercampaignfile,"SUCCESS");
                }
                catch(Exception gge)
                {
                    Console.WriteLine(gge.Message);
                    LocalStorage.setitem("FILE LOAD:"+Config.usercampaignfile,"FAILED");
                }
                if(data2.Length<=0 || getnewversion==true)
                {
                    data2 = System.IO.File.ReadAllLines(Config.customcampaignfile);    
                    try
                    {
                        string txt = "";
                        for(int i=0;i<data2.Length;i++)
                        {
                            txt+=data2[i]+Environment.NewLine;
                        }
                        System.IO.File.WriteAllText(Config.usercampaignfile,txt);
                    }
                    catch(Exception ffe)
                    {
                        Console.WriteLine(ffe.Message);
                    }
                }
                int cw = 0;
                int ch = 0;
                int nw = 0;
                int nh = 0;
                int offy = 0;
                int countmissions = 0;
                int countcustoms = 0;
                for(int d=0;d<Map.deadcell.Length;d++)
                {
                    Map.deadcell[d] = -1;
                }
                for(int i=0;i<data2.Length;i++)
                {
                    errline = data2[i];
                    if(data2[i].IndexOf("=")>0)
                    {
                        switch(data2[i].Substring(0,data2[i].IndexOf("=")))
                        {
                            case "mission":
                            //check mission valid....24Feb2021
                            if(custommissionvalid(game,data2,i))//24Feb2021
                            {
                                countcustoms++;
                                LocalStorage.setitem("CUSTOM MISSION:"+readstring(data2[i]),"SUCCESS");//24mar2021
                            }
                            else //17mar21
                            {
                                Console.WriteLine("Error with custom map:"+readstring(data2[i]));
                                //LocalStorage.WriteLog("Error with custom map:"+readstring(data2[i]));
                                LocalStorage.setitem("CUSTOM MISSION:"+readstring(data2[i]),"FAIL");//24mar2021
                            }
                            break;
                        }
                    }
                }
                int id = -1;
                int countunits = 0;
                int unitid = -1;
                Game.countcustoms = countcustoms;
                //Console.WriteLine("Count Customs:"+countcustoms);
                //start---------//28feb2022
                if(Config.highseas!=0)
                {
                    Game.highseas_hi = Resources.LoadAnimImage(game,"media/units/highseas_hi.png",game.renderer,192,192,1,5);
                    Game.highseas_lo = Resources.LoadAnimImage(game,"media/units/highseas_lo.png",game.renderer,192,192,1,5);
                }
                //end-----------//28feb2022
                for(int i=0;i<data.Length;i++)
                {
                    //Unit Template.....
                    errline = data[i];
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "shield": //15mar2021
                                Game.shield = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "spellball"://12apr2021
                                Game.spellball = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "whirlwind"://28mar2021
                                Game.whirlwind = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "lightning"://28mar2021
                                Game.lightning = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "whiteflag":
                                Game.whiteflag = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            //start-------------//15sep2021
                            case "shadowup":
                                Game.shadowup = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "shadowleft":
                                Game.shadowleft = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "shadowright":
                                Game.shadowright = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "shadowoffx":
                                Game.shadowoffx = Resources.readint(data[i]);
                            break;
                            case "shadowoffy":
                                Game.shadowoffy = Resources.readint(data[i]);
                            break;
                            //end---------------//15sep2021
                            //start-----------------//21mar2021
                            case "plus":
                                Game.iconplus = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "minus":
                                Game.iconminus = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "circles":
                                //110,110,13,1 - standard
                                Game.iconcircles = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            //end-------------------//21mar2021
                            case "healthbar":
                                Game.healthbar = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                            break;
                            case "cw":
                                cw = readint(data[i]);
                            break;
                            case "ch":
                                ch = readint(data[i]);
                            break;
                            case "nw":
                                nw = readint(data[i]);
                            break;
                            case "nh":
                                nh = readint(data[i]);
                            break;
                            case "offy":
                                offy = readint(data[i]);
                            break;
                            case "menumusic":
                                string[] tmpmenumusic = readstring(data[i]).Split(",");
                                if(tmpmenumusic.Length==2)
                                {
                                    string menumusicfile = tmpmenumusic[0];
                                    int menuduration = -1;
                                    Int32.TryParse(tmpmenumusic[1],out menuduration);
                                    if(menuduration!=-1)
                                    {
                                        Map.menumusicfile = menumusicfile;//25mar2021
                                        Map.menumusic = Resources.LoadAudio(game,menumusicfile,true);
                                        Map.menumusicplaying = -1;
                                    }
                                }
                            break;
                            case "musictrack":
                                string[] tmpmusic = readstring(data[i]).Split(",");
                                if(tmpmusic.Length==2)
                                {
                                    string musfile = tmpmusic[0];
                                    int duration = -1;
                                    Int32.TryParse(tmpmusic[1],out duration);
                                    if(duration!=-1)
                                    {
                                        if(Map.musictrack==null)
                                        {
                                            Map.musictrack = new int[Map.MAXMUSIC];
                                            Map.musicduration = new int[Map.MAXMUSIC];
                                            Map.musictrackfile = new string[Map.MAXMUSIC];//25mar2021
                                            for(int m=0;m<Map.musictrack.Length;m++)
                                            {
                                                Map.musictrack[m]=-1;
                                                Map.musicduration[m]=-1;
                                                Map.musictrackfile[m]=""; //25mar2021
                                            }
                                            Map.musicplaying = -1;
                                            Map.musicstartframe = -1;
                                        }
                                        for(int m=0;m<Map.musictrack.Length;m++)
                                        {
                                            if(Map.musictrack[m]==-1)
                                            {
                                                Map.musictrackfile[m] = musfile;//25mar2021
                                                Map.musictrack[m] = Resources.LoadAudio(game,musfile,true);
                                                if(Map.musictrack[m]!=-1)
                                                {
                                                    Map.musicduration[m] = duration;
                                                }
                                                break;
                                            }
                                        }
                                    }
                                }
                            break;
                            case "dead":
                                for(int d=0;d<Map.deadcell.Length;d++)
                                {
                                    if(Map.deadcell[d]==-1)
                                    {
                                        Map.deadcell[d] = readint(data[i]);
                                    }
                                }
                            break;
                            case "environment_ground":
                                //Map.tilecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);//23feb2022
                                string seasonalground = readstring(data[i]);//23feb2022
                                if(Config.useseasons>0)//23feb2022
                                {
                                    //hardcoded crap...
                                    if(Config.Season==Config.SUMMER)
                                    {
                                        //seasonalground = readstring(data[i].Substring(0,readstring(data[i]).IndexOf(".") )) + "desert" + readstring(data[i].Substring(readstring(data[i]).IndexOf("."),4));
                                        seasonalground = "media/environment/grounddesert.png";
                                    }
                                    if(Config.Season==Config.WINTER)
                                    {
                                        //seasonalground = readstring(data[i].Substring(0,readstring(data[i]).IndexOf(".") )) + "snow" + readstring(data[i].Substring(readstring(data[i]).IndexOf(".") ,4));
                                        seasonalground = "media/environment/groundsnow.png";
                                    }
                                }
                                Map.tilecat = Resources.LoadAnimImage(game,seasonalground,game.renderer,cw,ch,nw,nh);//23feb2022
                                Map.tileframes = nw * nh;
                            break;
                            case "environment_trees":
                                Map.treecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                Map.treeframes = nw * nh;
                                Map.treeoffsety = offy;
                            break;
                            //start--------------//2mar2021
                            case "environment_decor":
                                Map.decorcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                Map.decorframes = nw * nh;
                                Map.decoroffsety = offy;
                            break;
                            //end----------------//2mar2021
                            case "environment_rocks":
                                Map.rockcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                Map.rockframes = nw * nh;
                                Map.rockoffsety = offy;
                            break;
                            case "environment_walls":
                                Map.wallcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                Map.wallframes = nw * nh;
                                Map.walloffsety = offy;
                            break;
                            case "environment_fire":
                                Map.firecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                Map.fireframes = nw * nh;
                            break;
                            case "mission":
                                countmissions++;
                            break;
                        }
                    }
                }
                if(countmissions>0 || countcustoms>0)
                {
                    game.missions = new Mission[countmissions+countcustoms];
                    Game.overridemaxmission = countmissions;//13sep2021
                    int countobjectives = 0;
                    int objective = -1;
                    for(int i=0;i<data.Length;i++)
                    {
                        //Unit Template.....
                        errline = data[i];
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "mission":
                                id++;
                                game.missions[id] = new Mission();
                                game.missions[id].name = readstring(data[i]);
                                game.missions[id].custom = false;
                                game.missions[id].gridw = Map.DEFAULTGRIDW;//10sep2021
                                game.missions[id].gridh = Map.DEFAULTGRIDH;//10sep2021
                                toomanytrees = 0;
                                toomanyrocks = 0;
                                toomanywalls = 0;
                                countunits = 0;
                                for(int j=i+1;j<data.Length;j++)
                                {
                                    if(data[j].IndexOf("=")>0)
                                    {
                                        if(data[j].Substring(0,data[j].IndexOf("="))=="unit")
                                        {
                                            countunits++;
                                        }
                                        if(data[j].Substring(0,data[j].IndexOf("="))=="mission")
                                        {
                                            break;
                                        }
                                        if(data[j].Substring(0,data[j].IndexOf("="))=="tutorial")
                                        {
                                            break;
                                        }
                                        if(data[j].Substring(0,data[j].IndexOf("="))=="objective")
                                        {
                                            countobjectives++;
                                        }
                                    }
                                }
                                if(countunits>0)
                                {
                                    game.missions[id].units = new Unit[countunits];
                                    unitid = -1;
                                }
                                if(countobjectives>0)
                                {
                                    game.missions[id].objectives = new string[countobjectives];
                                }
                                Game.LoadingProgress(game);
                                break;
                                //26oct2020 start
                                case "cw":
                                    cw = readint(data[i]);
                                break;
                                case "ch":
                                    ch = readint(data[i]);
                                break;
                                case "nw":
                                    nw = readint(data[i]);
                                break;
                                case "nh":
                                    nh = readint(data[i]);
                                break;
                                case "offy":
                                    offy = readint(data[i]);
                                break;
                                //start-----------------//10sep2021
                                case "gridw":
                                game.missions[id].gridw = readint(data[i]);
                                break;
                                case "gridh":
                                game.missions[id].gridh = readint(data[i]);
                                break;
                                //end-------------------//10sep2021
                                //start-----------------//21feb2022
                                case "overlayimage":
                                cw = game.missions[id].gridw * Map.MAXX;
                                ch = game.missions[id].gridh * Map.MAXY;
                                game.missions[id].overlayimage = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,1,1);
                                break;
                                case "overlaysnow"://4mar2022
                                    cw = game.missions[id].gridw * Map.MAXX;
                                    ch = game.missions[id].gridh * Map.MAXY;
                                    game.missions[id].overlaysnow = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,1,1);
                                break;
                                //end-------------------//21feb2022
                                //1nov2020 start
                                case "override_bk_red":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_r = readint(data[i]);
                                break;
                                case "override_bk_green":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_g = readint(data[i]);
                                break;
                                case "override_bk_blue":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_b = readint(data[i]);
                                break;
                                //1nov2020 end
                                case "override_ground":
                                    game.missions[id].tilecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].tileframes = nw * nh;
                                    if(readstring(data[i]).IndexOf("snow")>0)
                                    {
                                        game.missions[id].issnow = true;
                                    }
                                    if(readstring(data[i]).IndexOf("desert")>0)
                                    {
                                        game.missions[id].isdesert = true;
                                    }
                                break;
                                //start--------------//2mar2021
                                case "override_decor":
                                    game.missions[id].decorcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].decorframes = nw * nh;
                                    game.missions[id].decoroffsety = offy;
                                break;
                                //end----------------//2mar2021
                                case "override_trees":
                                    game.missions[id].treecat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].treeframes = nw * nh;
                                    game.missions[id].treeoffsety = offy;
                                break;
                                case "override_rocks":
                                    game.missions[id].rockcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].rockframes = nw * nh;
                                    game.missions[id].rockoffsety = offy;
                                break;
                                case "override_walls":
                                    game.missions[id].wallcat = Resources.LoadAnimImage(game,readstring(data[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].wallframes = nw * nh;
                                    game.missions[id].walloffsety = offy;
                                break;
                                //26oct2020 end
                                case "nextmissionid":
                                    game.missions[id].nextmissionid = readint(data[i]);
                                break;
                                case "debrief":
                                    game.missions[id].debrief = readint(data[i]);
                                break;
                                case "failedmissionid":
                                    game.missions[id].failedmissionid = readint(data[i]);
                                break;
                                case "floorpattern"://16sep2021
                                game.missions[id].floorpattern = readint(data[i]);
                                break;
                                //start--------------//1mar2021
                                case "nextmissionname":
                                    game.missions[id].nextmissionname = readstring(data[i]);
                                break;
                                case "failedmissionname":
                                    game.missions[id].failedmissionname = readstring(data[i]);
                                break;
                                case "indoor"://23sep2021
                                game.missions[id].indoor = readint(data[i]);    
                                break;
                                //end----------------//1mar2021
                                case "demo":
                                    game.missions[id].demo = readint(data[i]);
                                break;
                                case "flavourtext"://18sep2021
                                    game.missions[id].flavourtext = readstring(data[i]);
                                break;
                                //start-----------//26Feb2021
                                case "fogoff":
                                    game.missions[id].fogoff = readint(data[i]);
                                break;
                                case "neutralfog":
                                    game.missions[id].neutralfog = readint(data[i]);
                                break;
                                //end-------------//26Feb2021
                                //start-------------//28Feb2021
                                case "playerfaction":
                                    game.missions[id].playerfaction = readint(data[i]);
                                break;
                                case "enemyfaction":
                                    game.missions[id].skirmishenemyfaction = readint(data[i]);
                                break;
                                case "unlocked":
                                    game.missions[id].alwaysunlocked = readint(data[i]);
                                break;
                                //end---------------//28Feb2021
                                //start--------------//1mar2021
                                case "lockcorner":
                                    game.missions[id].lockcorner = readint(data[i]);
                                break;
                                //end----------------//1mar2021
                                case "corner":
                                    string[] tmpcorner = readstring(data[i]).Split(",");
                                    if(tmpcorner.Length==2)
                                    {
                                        Int32.TryParse(tmpcorner[0],out game.missions[id].cornerx);
                                        Int32.TryParse(tmpcorner[1],out game.missions[id].cornery);
                                    }
                                break;
                                case "seed":
                                    game.missions[id].seed = readint(data[i]);
                                break;
                                case "skirmish":
                                    game.missions[id].skirmish = readint(data[i]);
                                break;
                                case "description":
                                    if(game.missions[id].description[0] == "")
                                    {
                                        game.missions[id].description[0] = readstring(data[i]);
                                    }
                                    else
                                    {
                                        if(game.missions[id].description[1] == "")
                                        {
                                            game.missions[id].description[1] = readstring(data[i]);
                                        }
                                        else
                                        {
                                            game.missions[id].description[2] = readstring(data[i]);
                                        }
                                    }
                                break;
                                case "mapgen":
                                    game.missions[id].mapgen = 1;
                                break;
                                case "ai":
                                    game.missions[id].ai = readint(data[i]);
                                break;
                                case "istutorial":
                                    game.missions[id].istutorial = readint(data[i]);
                                break;
                                case "toomanytrees":
                                    toomanytrees=1;
                                break;
                                case "toomanyrocks":
                                    toomanyrocks=1;
                                break;
                                case "toomanywalls":
                                    toomanywalls = 1;
                                break;
                                //start--------------//2mar2021
                                case "decor":
                                if(id>=0)
                                {
                                    string[] tmpdecor = readstring(data[i]).Split(",");
                                    game.missions[id].decorimage = new int[tmpdecor.Length];
                                    for(int j=0;j<tmpdecor.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmpdecor[j],out tt);
                                        game.missions[id].decorimage[j] = tt;
                                    }
                                }
                                break;
                                //end----------------//2mar2021
                                case "trees":
                                if(id>=0)
                                {
                                    string[] tmptrees = readstring(data[i]).Split(",");
                                    game.missions[id].treeimage = new int[tmptrees.Length];
                                    for(int j=0;j<tmptrees.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmptrees[j],out tt);
                                        if(toomanytrees>0)
                                        {
                                            if(j % 3<2)
                                            {
                                                continue;
                                            }
                                        }
                                        game.missions[id].treeimage[j] = tt;
                                    }
                                }
                                break;
                                case "walls":
                                if(id>=0)
                                {
                                    string[] tmpwalls = readstring(data[i]).Split(",");
                                    game.missions[id].wallimage = new int[tmpwalls.Length];
                                    for(int j=0;j<tmpwalls.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmpwalls[j],out tt);
                                        if(toomanywalls==1)
                                        {
                                            if((Functions.rand(0,1000) % 4)>0)
                                            {
                                                continue;
                                            }
                                        }
                                        game.missions[id].wallimage[j] = tt;
                                    }
                                }
                                break;
                                case "rocks":
                                if(id>=0)
                                {
                                    string[] tmprocks = readstring(data[i]).Split(",");
                                    game.missions[id].rockimage = new int[tmprocks.Length];
                                    for(int j=0;j<tmprocks.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmprocks[j],out tt);
                                        if(toomanyrocks>0)
                                        {
                                            if(j % 3<2)
                                            {
                                                continue;
                                            }
                                        }
                                        game.missions[id].rockimage[j] = tt;
                                    }
                                }
                                break;
                                case "setfire":
                                if(id>=0)
                                {
                                    string[] tmpfire = readstring(data[i]).Split(",");
                                    if(tmpfire.Length==2)
                                    {
                                        game.missions[id].campfirex = -1;
                                        game.missions[id].campfirey = -1;
                                        Int32.TryParse(tmpfire[0],out game.missions[id].campfirex);
                                        Int32.TryParse(tmpfire[1],out game.missions[id].campfirey);
                                    }
                                }
                                break;
                                case "objective":
                                    objective++;
                                    game.missions[id].objectives[objective] = readstring(data[i]);
                                break;
                                case "showkills":
                                    game.missions[id].showkills = readint(data[i]);
                                break;
                                case "unit":
                                    string[] unitlist = readstring(data[i]).Split(",");
                                    if(unitlist.Length==3)
                                    {
                                        bool success1 = true;
                                        bool success2 = true;
                                        string name = unitlist[0];
                                        int x = 0;
                                        int y = 0;
                                        if(unitlist[1]=="random")
                                        {
                                            x = Functions.rand(Map.GRIDW * 35,Map.GRIDW*65);
                                            success1 = true;
                                        }
                                        else
                                        {
                                            success1 = Int32.TryParse(unitlist[1],out x);
                                        }
                                        if(unitlist[2]=="random")
                                        {
                                            y = Functions.rand(Map.GRIDH * 35,Map.GRIDH*65);
                                            success2 = true;
                                        }
                                        else
                                        {
                                            success2 = Int32.TryParse(unitlist[2],out y);
                                        }
                                        if(success1 && success2)
                                        {
                                            unitid++;
                                            game.missions[id].units[unitid] = new Unit(game);
                                            game.missions[id].units[unitid].x = x;
                                            game.missions[id].units[unitid].y = y;
                                            game.missions[id].units[unitid].name = name;
                                        }
                                    }
                                break;
                                //start--------------//10sep2021
                                case "unitname"://unit name must immediately follow the unit that was just created....
                                if(game.missions[id].units!=null)
                                {
                                    if(unitid<game.missions[id].units.Length && unitid>=0)
                                    {
                                        game.missions[id].units[unitid].charactername = readstring(data[i]);
                                    }
                                }
                                break;
                                case "displayunitname"://unit name must immediately follow the unit that was just created....
                                if(game.missions[id].units!=null)
                                {
                                    if(unitid<game.missions[id].units.Length && unitid>=0)
                                    {
                                        game.missions[id].units[unitid].displaycharactername = readint(data[i]);
                                        //start--------------------//12feb2021
                                        if(readint(data[i])!=1)
                                        {
                                            //potentially mixed up data
                                            game.missions[id].units[unitid].charactername = readstring(data[i]);
                                            game.missions[id].units[unitid].displaycharactername = 1;
                                        }
                                        //end----------------------//12feb2021
                                    }
                                }
                                break;
                                //end----------------//10sep2021
                                case "trigger":
                                //type,num,comparator,name,xx,yy,ww,hh
                                //type == 1 Victory
                                //type == 2 Defeat
                                //comparator == 0 equal
                                //comparator == -1 less than
                                //comparator == 1 greater than
                                    if(id>=0)
                                    {
                                        string[] trigger = readstring(data[i]).Split(",");
                                        if(trigger.Length==8)
                                        {
                                            int typ = 0;
                                            int num = 0;
                                            int comp = 0;
                                            Int32.TryParse(trigger[0],out typ);
                                            Int32.TryParse(trigger[1],out num);
                                            Int32.TryParse(trigger[2],out comp);
                                            int xx = 0;
                                            int yy = 0;
                                            int ww = 0;
                                            int hh = 0;
                                            Int32.TryParse(trigger[4],out xx);
                                            Int32.TryParse(trigger[5],out yy);
                                            Int32.TryParse(trigger[6],out ww);
                                            Int32.TryParse(trigger[7],out hh);
                                            game.missions[id].createtrigger(typ,num,comp,trigger[3].Replace("^",","),xx,yy,ww,hh);
                                        }
                                    }
                                break;
                            }
                        }
                    }
                    //
                    //customs
                    bool validblock = true; //24Feb2021
                    for(int i=0;i<data2.Length;i++)
                    {
                        //Unit Template.....
                        errline = data2[i];
                        if(data2[i].IndexOf("=")>0)
                        {
                            if((data2[i].Substring(0,data2[i].IndexOf("="))=="mission")) //24Feb2021
                            {//24Feb2021
                                validblock = true;//24Feb2021
                            }//24Feb2021
                            if(!validblock)//24Feb2021
                            {//24Feb2021
                                continue;//24Feb2021
                            }//24Feb2021
                            switch(data2[i].Substring(0,data2[i].IndexOf("=")))
                            {
                                case "mission":
                                validblock = true; //24Feb2021
                                if(!custommissionvalid(game,data2,i))//24Feb2021
                                {//24Feb2021
                                    validblock = false;
                                    continue;
                                }//24Feb2021
                                id++;
                                game.missions[id] = new Mission();
                                game.missions[id].name = readstring(data2[i]);
                                game.missions[id].custom = true;
                                game.missions[id].gridw = Map.DEFAULTGRIDW;//10sep2021
                                game.missions[id].gridh = Map.DEFAULTGRIDH;//10sep2021
                                toomanytrees = 0;
                                toomanyrocks = 0;
                                countunits = 0;
                                for(int j=i+1;j<data2.Length;j++)
                                {
                                    if(data2[j].IndexOf("=")>0)
                                    {
                                        if(data2[j].Substring(0,data2[j].IndexOf("="))=="unit")
                                        {
                                            countunits++;
                                        }
                                        if(data2[j].Substring(0,data2[j].IndexOf("="))=="mission")
                                        {
                                            break;
                                        }
                                        if(data2[j].Substring(0,data2[j].IndexOf("="))=="tutorial")
                                        {
                                            break;
                                        }
                                        if(data2[j].Substring(0,data2[j].IndexOf("="))=="objective")
                                        {
                                            countobjectives++;
                                        }
                                    }
                                }
                                if(countunits>0)
                                {
                                    game.missions[id].units = new Unit[countunits];
                                    unitid = -1;
                                }
                                if(countobjectives>0)
                                {
                                    game.missions[id].objectives = new string[countobjectives];
                                }
                                Game.LoadingProgress(game);
                                break;
                                //26oct2020 start
                                case "cw":
                                    cw = readint(data2[i]);
                                break;
                                case "ch":
                                    ch = readint(data2[i]);
                                break;
                                case "nw":
                                    nw = readint(data2[i]);
                                break;
                                case "nh":
                                    nh = readint(data2[i]);
                                break;
                                case "offy":
                                    offy = readint(data2[i]);
                                break;
                                //start-----------------//10sep2021
                                case "gridw":
                                game.missions[id].gridw = readint(data2[i]);
                                break;
                                case "gridh":
                                game.missions[id].gridh = readint(data2[i]);
                                break;
                                //end-------------------//10sep2021
                                //start-----------------//21feb2022
                                case "overlayimage":
                                cw = game.missions[id].gridw * Map.MAXX;
                                ch = game.missions[id].gridh * Map.MAXY;
                                game.missions[id].overlayimage = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,1,1);
                                break;
                                case "overlaysnow"://4mar2022
                                    cw = game.missions[id].gridw * Map.MAXX;
                                    ch = game.missions[id].gridh * Map.MAXY;
                                    game.missions[id].overlaysnow = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,1,1);
                                break;
                                //end-------------------//21feb2022
                                //1nov2020 start
                                case "override_bk_red":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_r = readint(data2[i]);
                                break;
                                case "override_bk_green":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_g = readint(data2[i]);
                                break;
                                case "override_bk_blue":
                                game.missions[id].overridergbbk = true;
                                game.missions[id].overridergbbk_b = readint(data2[i]);
                                break;
                                //1nov2020 end
                                case "override_ground":
                                    game.missions[id].tilecat = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].tileframes = nw * nh;
                                    if(readstring(data2[i]).IndexOf("snow")>0)
                                    {
                                        game.missions[id].issnow = true;
                                    }
                                    if(readstring(data2[i]).IndexOf("desert")>0)
                                    {
                                        game.missions[id].isdesert = true;
                                    }
                                break;
                                case "override_trees":
                                    game.missions[id].treecat = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].treeframes = nw * nh;
                                    game.missions[id].treeoffsety = offy;
                                break;
                                //start--------------//2mar2021
                                case "override_decor":
                                    game.missions[id].decorcat = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].decorframes = nw * nh;
                                    game.missions[id].decoroffsety = offy;
                                break;
                                //end----------------//2mar2021
                                case "override_rocks":
                                    game.missions[id].rockcat = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].rockframes = nw * nh;
                                    game.missions[id].rockoffsety = offy;
                                break;
                                case "override_walls":
                                    game.missions[id].wallcat = Resources.LoadAnimImage(game,readstring(data2[i]),game.renderer,cw,ch,nw,nh);
                                    game.missions[id].wallframes = nw * nh;
                                    game.missions[id].walloffsety = offy;
                                break;
                                //26oct2020 end
                                case "nextmissionid":
                                    game.missions[id].nextmissionid = readint(data2[i]);
                                break;
                                case "debrief":
                                    game.missions[id].debrief = readint(data2[i]);
                                break;
                                case "failedmissionid":
                                    game.missions[id].failedmissionid = readint(data2[i]);
                                break;
                                //start--------------//1mar2021
                                case "nextmissionname":
                                    game.missions[id].nextmissionname = readstring(data2[i]);
                                break;
                                case "failedmissionname":
                                    game.missions[id].failedmissionname = readstring(data2[i]);
                                break;
                                //end----------------//1mar2021
                                case "demo":
                                    game.missions[id].demo = 0;//readint(data2[i]);
                                break;
                                //start-----------//26Feb2021
                                case "fogoff":
                                    game.missions[id].fogoff = readint(data2[i]);
                                break;
                                case "neutralfog":
                                    game.missions[id].neutralfog = readint(data2[i]);
                                break;
                                //end-------------//26Feb2021
                                //start-------------//28Feb2021
                                case "playerfaction":
                                    game.missions[id].playerfaction = readint(data2[i]);
                                break;
                                case "enemyfaction":
                                    game.missions[id].skirmishenemyfaction = readint(data2[i]);
                                break;
                                case "flavourtext"://18sep2021
                                    game.missions[id].flavourtext = readstring(data2[i]);
                                break;
                                case "floorpattern"://16sep2021
                                    game.missions[id].floorpattern = readint(data2[i]);
                                break;
                                case "unlocked":
                                    game.missions[id].alwaysunlocked = readint(data2[i]);
                                break;
                                //end---------------//28Feb2021
                                //start--------------//1mar2021
                                case "lockcorner":
                                    game.missions[id].lockcorner = readint(data2[i]);
                                break;
                                //end----------------//1mar2021
                                case "corner":
                                    string[] tmpcorner = readstring(data2[i]).Split(",");
                                    if(tmpcorner.Length==2)
                                    {
                                        Int32.TryParse(tmpcorner[0],out game.missions[id].cornerx);
                                        Int32.TryParse(tmpcorner[1],out game.missions[id].cornery);
                                    }
                                break;
                                case "seed":
                                    game.missions[id].seed = readint(data2[i]);
                                break;
                                case "skirmish":
                                    game.missions[id].skirmish = readint(data2[i]);
                                break;
                                case "indoor"://23sep2021
                                game.missions[id].indoor = readint(data2[i]);    
                                break;
                                case "mapgen":
                                    game.missions[id].mapgen = 1;
                                break;
                                case "ai":
                                    game.missions[id].ai = readint(data2[i]);
                                break;
                                case "description":
                                    if(game.missions[id].description[0] == "")
                                    {
                                        //game.missions[id].description[0] = readstring(data2[i]);//21mar2021
                                        game.missions[id].description[0] = Translation.TranslateWord(readstring(data2[i]),false);//21mar2021
                                    }
                                    else
                                    {
                                        if(game.missions[id].description[1] == "")
                                        {
                                            //game.missions[id].description[1] = readstring(data2[i]);//22mar2021
                                            game.missions[id].description[1] = Translation.TranslateWord(readstring(data2[i]),false);//22mar2021
                                        }
                                        else
                                        {
                                            //game.missions[id].description[2] = readstring(data2[i]);//22mar2021
                                            game.missions[id].description[2] = Translation.TranslateWord(readstring(data2[i]),false);//22mar2021
                                        }
                                    }
                                break;
                                case "istutorial":
                                    game.missions[id].istutorial = 0;//readint(data[i]);
                                break;
                                //start--------------//2mar2021
                                case "decor":
                                if(id>=0)
                                {
                                    string[] tmpdecor = readstring(data2[i]).Split(",");
                                    game.missions[id].decorimage = new int[tmpdecor.Length];
                                    for(int j=0;j<tmpdecor.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmpdecor[j],out tt);
                                        game.missions[id].decorimage[j] = tt;
                                    }
                                }
                                break;
                                //end----------------//2mar2021
                                case "trees":
                                if(id>=0)
                                {
                                    string[] tmptrees = readstring(data2[i]).Split(",");
                                    game.missions[id].treeimage = new int[tmptrees.Length];
                                    for(int j=0;j<tmptrees.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmptrees[j],out tt);
                                        game.missions[id].treeimage[j] = tt;
                                    }
                                }
                                break;
                                case "walls":
                                if(id>=0)
                                {
                                    string[] tmpwalls = readstring(data2[i]).Split(",");
                                    game.missions[id].wallimage = new int[tmpwalls.Length];
                                    for(int j=0;j<tmpwalls.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmpwalls[j],out tt);
                                        game.missions[id].wallimage[j] = tt;
                                    }
                                }
                                break;
                                case "rocks":
                                if(id>=0)
                                {
                                    string[] tmprocks = readstring(data2[i]).Split(",");
                                    game.missions[id].rockimage = new int[tmprocks.Length];
                                    for(int j=0;j<tmprocks.Length;j++)
                                    {
                                        int tt = -1;
                                        Int32.TryParse(tmprocks[j],out tt);
                                        game.missions[id].rockimage[j] = tt;
                                    }
                                }
                                break;
                                case "setfire":
                                if(id>=0)
                                {
                                    string[] tmpfire = readstring(data2[i]).Split(",");
                                    if(tmpfire.Length==2)
                                    {
                                        game.missions[id].campfirex = -1;
                                        game.missions[id].campfirey = -1;
                                        Int32.TryParse(tmpfire[0],out game.missions[id].campfirex);
                                        Int32.TryParse(tmpfire[1],out game.missions[id].campfirey);
                                    }
                                }
                                break;
                                case "objective":
                                    objective++;
                                    //game.missions[id].objectives[objective] = readstring(data2[i]);//22mar2021
                                    game.missions[id].objectives[objective] = Translation.TranslateWord(readstring(data2[i]),false);//22mar2021
                                break;
                                case "showkills":
                                    game.missions[id].showkills = readint(data2[i]);
                                break;
                                case "unit":
                                    string[] unitlist = readstring(data2[i]).Split(",");
                                    if(unitlist.Length==3)
                                    {
                                        bool success1 = true;
                                        bool success2 = true;
                                        string name = unitlist[0];
                                        int x = 0;
                                        int y = 0;
                                        if(unitlist[1]=="random")
                                        {
                                            x = Functions.rand(Map.GRIDW * 35,Map.GRIDW*65);
                                            success1 = true;
                                        }
                                        else
                                        {
                                            success1 = Int32.TryParse(unitlist[1],out x);
                                        }
                                        if(unitlist[2]=="random")
                                        {
                                            y = Functions.rand(Map.GRIDH * 35,Map.GRIDH*65);
                                            success2 = true;
                                        }
                                        else
                                        {
                                            success2 = Int32.TryParse(unitlist[2],out y);
                                        }
                                        if(success1 && success2)
                                        {
                                            unitid++;
                                            game.missions[id].units[unitid] = new Unit(game);
                                            game.missions[id].units[unitid].x = x;
                                            game.missions[id].units[unitid].y = y;
                                            game.missions[id].units[unitid].name = name;
                                        }
                                    }
                                break;
                                //start--------------//10sep2021
                                case "unitname"://unit name must immediately follow the unit that was just created....
                                if(game.missions[id].units!=null)
                                {
                                    if(unitid<game.missions[id].units.Length && unitid>=0)
                                    {
                                        game.missions[id].units[unitid].charactername = readstring(data2[i]);
                                    }
                                }
                                break;
                                case "displayunitname":
                                if(game.missions[id].units!=null)
                                {
                                    if(unitid<game.missions[id].units.Length && unitid>=0)
                                    {
                                        game.missions[id].units[unitid].displaycharactername = readint(data2[i]);
                                        //start--------------------//12feb2021
                                        if(readint(data2[i])!=1)
                                        {
                                            //potentially mixed up data
                                            game.missions[id].units[unitid].charactername = readstring(data2[i]);
                                            game.missions[id].units[unitid].displaycharactername = 1;
                                        }
                                        //end----------------------//12feb2021
                                    }
                                }
                                break;
                                //end----------------//10sep2021
                                case "trigger":
                                //type,num,comparator,name,xx,yy,ww,hh
                                //type == 1 Victory
                                //type == 2 Defeat
                                //comparator == 0 equal
                                //comparator == -1 less than
                                //comparator == 1 greater than
                                    if(id>=0)
                                    {
                                        string[] trigger = readstring(data2[i]).Split(",");
                                        if(trigger.Length==8)
                                        {
                                            int typ = 0;
                                            int num = 0;
                                            int comp = 0;
                                            Int32.TryParse(trigger[0],out typ);
                                            Int32.TryParse(trigger[1],out num);
                                            Int32.TryParse(trigger[2],out comp);
                                            int xx = 0;
                                            int yy = 0;
                                            int ww = 0;
                                            int hh = 0;
                                            Int32.TryParse(trigger[4],out xx);
                                            Int32.TryParse(trigger[5],out yy);
                                            Int32.TryParse(trigger[6],out ww);
                                            Int32.TryParse(trigger[7],out hh);
                                            game.missions[id].createtrigger(typ,num,comp,trigger[3].Replace("^",","),xx,yy,ww,hh);
                                        }
                                    }
                                break;
                            }
                        }
                    }
                }
                LocalStorage.setitem("FILE LOAD:"+file,"SUCCESS");//24mar2021
            }
            catch(Exception e)
            {
                Console.WriteLine("766:"+"Error in file on line containing:"+errline+" "+e.Message);
                //LocalStorage.WriteLog("766:"+"Error in file on line containing:"+errline+" "+e.Message);
                LocalStorage.setitem("FILE LOAD:"+file,"FAILED");//24mar2021
            }
        }

///////////////////Method Definition///////////////
        public static int LoadFont(Game game,string file,int ptsize)
        {
            ////////////////////////
            //Load a font in the game for use
            Fonts f = new Fonts();
            //ptsize*=Config.FONTALIAS;
            if(file!="" && file!=null)//28Feb2021
            {
                if(ptsize>=20)
                {
                    f.font = SDL_ttf.TTF_OpenFont(file,ptsize*Config.FONTALIAS);
                }
                else
                {
                    f.font = SDL_ttf.TTF_OpenFont(file,ptsize);
                }
            }
            if(f.font==IntPtr.Zero)
            {
                Console.WriteLine("Could Not Open Font:"+file+". Error:"+SDL.SDL_GetError());
                Network.reporterror("FontLoadFailure:"+file,false);//15mar2021
                LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD");
            }
            else
            {
                LocalStorage.setitem("FILE LOAD:"+file,"LOADED");
            }
            int i = game.fonts.Length;
            Array.Resize<Fonts>(ref game.fonts,i+1);
            f.file = file;//24mar2021
            game.fonts[i] = f;
            game.fonts[i].font = f.font;
            game.fonts[i].ptsize = ptsize;
            i++;
            return i - 1;
        }
        //

///////////////////Method Definition///////////////
        public static int LoadAudio(Game game,string file,bool music)
        {
            ////////////////////////
            //Load an Audio file of .wav type
            for(int j=0;j<game.audios.Length;j++)
            {
                if(game.audios[j].file==file)
                {
                    return j;
                }
            }
            Audios a = new Audios();
            a.loop = music;
            a.file = file; //25mar2021
            if(music)
            {
                if(!Config.STREAMLOADAUDIO)//25mar2021
                {
                    if(file!="" && file!=null)//28Feb2021
                    {
                        a.audio = SDL_mixer.Mix_LoadMUS(file);
                    }
                    if(a.audio==IntPtr.Zero)
                    {
                        Console.WriteLine("Could Not Load Music:"+file+". Error:"+SDL.SDL_GetError());
                        Network.reporterror("MusicLoadFailure:"+file,false);//15mar2021
                        LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD"); //24mar2021
                    }
                    else //24mar2021
                    {
                        LocalStorage.setitem("FILE LOAD:"+file,"LOADED"); //24mar2021
                    }
                }
                else
                {
                    //do nothing yet...
                }
                a.ismusic = true;
            }
            else
            {
                if(file!="" && file!=null)//28Feb2021
                {
                    a.audio = SDL_mixer.Mix_LoadWAV(file);
                }
                if(a.audio==IntPtr.Zero)
                {
                    Console.WriteLine("Could Not Load Sound:"+file+". Error:"+SDL.SDL_GetError());
                    Network.reporterror("SoundLoadFailure:"+file,false);//15mar2021
                    LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD"); //24mar2021
                }
                else//24mar2021
                {
                    LocalStorage.setitem("FILE LOAD:"+file,"LOADED"); //24mar2021
                }
            
            }
            int i = game.audios.Length;
            Array.Resize<Audios>(ref game.audios,i+1);
            game.audios[i] = a;
            game.audios[i].index = i;
            game.audios[i].loop = music;
            game.audios[i].volume = 1;
            game.audios[i].file = file;
            i++;
            return i - 1;
        }
        //
        //start-------------//28Feb2021

///////////////////Method Definition///////////////
        public static void StreamImage(Game game,int i)
        {
            ////////////////////////
            //not used
            //used after an image is released...and we want to reload it in game....in a separate thread.
            if(i>=0 && i<game.images.Length)
            {
                if(game.images[i].loaded==false && game.images[i].stream==false)
                {
                    if(game.images[i].texture==IntPtr.Zero)
                    {
                        game.images[i].stream = true;
                    }
                }
            }
        }
        
///////////////////Method Definition///////////////
        public static void FreeAllImages(Game game)
        {
            //gameplay ones only - the name is a bit of a misnomer......
            for(int i=0;i<game.images.Length;i++)
            {
                bool found = false;
                for(int g=0;g<game.gui.Length;g++)
                {
                    if(game.gui[g].image==i || game.gui[g].tmpimage==i)
                    {
                        found = true;
                        break;
                    }
                }
                if(found)
                {
                    continue;
                }
                if(game.images[i].texture!=IntPtr.Zero && game.images[i].loaded==true)
                {
                    //LocalStorage.setitem("FREE IMAGE:"+game.images[i].file,"FAILED"); //24mar2021
                    SDL.SDL_DestroyTexture(game.images[i].texture);
                    //LocalStorage.setitem("FREE IMAGE:"+game.images[i].file,"SUCCESS"); //24mar2021
                    game.images[i].loaded = false;
                    game.images[i].texture = IntPtr.Zero;
                }
            }
        }
///////////////////Method Definition///////////////
        public static bool FreeImage(Game game,int i)
        {
            ////////////////////////
            //frees images from memory
            if(i>=0 && i<game.images.Length)
            {
                if(game.images[i].texture!=IntPtr.Zero && game.images[i].loaded==true)
                {
                    LocalStorage.setitem("FREE IMAGE:"+game.images[i].file,"FAILED"); //24mar2021
                    SDL.SDL_DestroyTexture(game.images[i].texture);
                    LocalStorage.setitem("FREE IMAGE:"+game.images[i].file,"SUCCESS"); //24mar2021
                    game.images[i].loaded = false;
                    game.images[i].texture = IntPtr.Zero;
                    return true;
                }
            }
            return false;
        }
        //end---------------//28Feb2021
        //

///////////////////Method Definition///////////////
        public static int LoadImage(Game game,string file,IntPtr renderer,int w,int h) //note the slight change.....added w and h as can't work out how to do it otherwise....
        {
            ////////////////////////
            /////start---------//24feb2022
            //if(Config.useseasons>0 && Config.Night>0)
            //{
//                //check if the nighttime file version exists....
                ////if it does - use it.....
                //string sfile = file;
                //int index = sfile.Length - 1;
                //while(index>=0)
                //{
//                    if(sfile.Substring(index,1) == "/")
                    //{
//                        break;
                    //}
                    //index--;
                //}
                //if(index>=0)
                //{
//                    string prefix = sfile.Substring(0,index + 1);
                    //string suffix = sfile.Substring(index + 1,sfile.Length - (index + 1));
                    //string nightfile = prefix + "night_" + suffix;
                    //if(File.Exists(nightfile))
                    //{
//                        file = nightfile;
                    //}
                //}
            //}
            ////end------------//24feb2022
            //Load an image of the form .png or .jpg into memory
            bool loaded = false;//28Feb2021
            for(int j=0;j<game.images.Length;j++)//26oct2020
            {
                if(game.images[j].file==file)
                {
                    //start-------------//28Feb2021
                    if(game.images[j].loaded==false) //assumes the image was loaded once before successfully, cleared out and needs to be loaded again.....
                    {
                        game.images[j].texture = SDL_image.IMG_LoadTexture(renderer,file);
                        if(game.images[j].texture==IntPtr.Zero)
                        {
                            Console.WriteLine("Could Not Load Texture:"+file+". Error:"+SDL.SDL_GetError());
                            Network.reporterror("TextureLoadFailure:"+file,false);//15mar2021
                            LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD");//24mar2021
                        }
                        else
                        {
                            game.images[j].loaded = true;
                            LocalStorage.setitem("FILE LOAD:"+file,"LOADED"); //24mar2021
                        }
                    }
                    //end---------------//28Feb2021
                    return j;
                }
            }
            Images img = new Images();
            if(!Config.STREAMLOAD) //28Feb2021
            {
                if(file!="" && file!=null)//28Feb2021
                {
                    img.texture = SDL_image.IMG_LoadTexture(renderer,file);
                }
                if(img.texture==IntPtr.Zero)
                {
                    Console.WriteLine("Could Not Load Texture:"+file+". Error:"+SDL.SDL_GetError());
                    Network.reporterror("TextureLoadFailure:"+file,false);//15mar2021
                    LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD");//24mar2021
                }
                else
                {
                    loaded = true;
                    LocalStorage.setitem("FILE LOAD:"+file,"LOADED");//24mar2021
                }
            }
            int i = game.images.Length;
            Array.Resize<Images>(ref game.images,i+1);
            game.images[i] = img;
            game.images[i].file = file;//26oct2020
            game.images[i].texture = img.texture;
            game.images[i].anim = false;
            game.images[i].index = i;
            game.images[i].cwx = w;//??
            game.images[i].chy = h;//??
            game.images[i].chn = 1;
            game.images[i].cwn = 1;
            game.images[i].stream = Config.STREAMLOAD;//28Feb2021
            game.images[i].loaded = loaded; ///28Feb2021
            game.images[i].okloaded = loaded; //28Feb2021
            game.images[i].neverloaded = !loaded; //28Feb2021
            i++;
            return i - 1;
        }
        //

///////////////////Method Definition///////////////
        public static int LoadAnimImage(Game game,string file,IntPtr renderer,int cellwidth, int cellheight, int cellswide, int cellshigh)
        {
            /////start---------//24feb2022
//            if(Config.useseasons>0 && Config.Night>0)
            //{
//                //check if the nighttime file version exists....
                ////if it does - use it.....
                //string sfile = file;
                //int index = sfile.Length - 1;
                //while(index>=0)
                //{
//                    if(sfile.Substring(index,1) == "/")
                    //{
//                        break;
                    //}
                    //index--;
                //}
                //if(index>=0)
                //{
//                    string prefix = sfile.Substring(0,index + 1);
                    //string suffix = sfile.Substring(index + 1,sfile.Length - (index + 1));
                    //string nightfile = prefix + "night_" + suffix;
                    //if(File.Exists(nightfile))
                    //{
//                        file = nightfile;
                    //}
                //}
            //}
            ////end------------//24feb2022
            ////////////////////////
            //Load an animated image of the form .png or .jpg into memory
            bool loaded = false; //28Feb2021
            for(int j=0;j<game.images.Length;j++)//26oct2020
            {
                if(game.images[j].file==file)
                {
                    //start-------------//28Feb2021
                    if(game.images[j].loaded==false) //assumes the image was loaded once before successfully, cleared out and needs to be loaded again.....
                    {
                        game.images[j].texture = SDL_image.IMG_LoadTexture(renderer,file);
                        if(game.images[j].texture==IntPtr.Zero)
                        {
                            Console.WriteLine("Could Not Load Texture:"+file+". Error:"+SDL.SDL_GetError());
                            Network.reporterror("TextureLoadFailure:"+file,false);//15mar2021
                            LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD");//24mar2021
                        }
                        else
                        {
                            game.images[j].loaded = true;
                            LocalStorage.setitem("FILE LOAD:"+file,"LOADED");//24mar2021
                        }
                    }
                    //end---------------//28Feb2021
                    return j;
                }
            }
            Images img = new Images();
            if(!Config.STREAMLOAD) //28Feb2021
            {
                if(file!="" && file!=null) //28Feb2021
                {
                    img.texture = SDL_image.IMG_LoadTexture(renderer,file);
                }
                if(img.texture==IntPtr.Zero)
                {
                    Console.WriteLine("Could Not Load Texture:"+file+". Error:"+SDL.SDL_GetError());
                    Network.reporterror("TextureLoadFailure:"+file,false);//15mar2021
                    LocalStorage.setitem("FILE LOAD:"+file,"FAILED TO LOAD");//24mar2021
                }
                else
                {
                    loaded = true;
                    LocalStorage.setitem("FILE LOAD:"+file,"LOADED");//24mar2021
                }
            }
            int i = game.images.Length;
            Array.Resize<Images>(ref game.images,i+1);
            game.images[i] = img;
            game.images[i].file = file;//26oct2020
            game.images[i].texture = img.texture;
            game.images[i].anim = true;
            game.images[i].index = i;
            game.images[i].cwx = cellwidth;
            game.images[i].chy = cellheight;
            game.images[i].chn = cellshigh;
            game.images[i].cwn = cellswide;
            game.images[i].stream = Config.STREAMLOAD;//28Feb2021
            game.images[i].loaded = loaded;//28Feb2021
            game.images[i].okloaded = loaded; //28Feb2021
            game.images[i].neverloaded = !loaded; //28Feb2021
            i++;
            return i - 1;
        }
    }
    //

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Fonts
    {
        public IntPtr font;
        public int ptsize;
        public static int WMULTIPLIER = 1; //15mar2021
        public static int HMULTIPLIER = 1; //17apr2021
        public string file;

///////////////////Method Definition///////////////
        public Fonts()
        {
            file = "";
        }
    }
    //

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Audios
    {
        public int index;
        public bool loop;
        public int volume;
        //
        public IntPtr audio;
        public bool ismusic;
        public bool ispaused;
        public int[] channel;
        public static int maxchannels = 8;
        public string file;
        public int previousmusicchannel;
        public int currentmusicchannel;
        //
        //

///////////////////Method Definition///////////////
        public Audios()
        {
            loop = false;
            volume = 1;
            index = 0;
            ismusic = false;
            channel = new int[Audios.maxchannels];
            ispaused = false;
            file = "";//25mar2021
        }
        //

///////////////////Method Definition///////////////
        public static int playsound(Audios a,int vol)
        {
            ////////////////////////
            //play an audio clip at a specified volume from 0 to 100
            if(!Game.audioon)
            {
                return -1;
            }
            if(!a.ismusic)
            {
                //start-------------//10sep2021
                //in case we freed at a certain point.....
                //in the game....
                if(a.audio==IntPtr.Zero)
                {
                    if(a.file!=null)
                    {
                        if(a.file!="")
                        {
                            a.audio = SDL_mixer.Mix_LoadWAV(a.file);
                        }
                    }
                }
                //end---------------//10sep2021
                int i = SDL_mixer.Mix_PlayChannel(-1,a.audio,0);
                SDL_mixer.Mix_Volume(i,vol);
                return i;
            }
            return -1;
        }

///////////////////Method Definition///////////////
        public static void playmusic(Audios a,int vol,bool loop)
        {
            //play a music clip at a specified volume from 0 to 100, and perhaps loop it
            if(!Game.audioon)
            {
                return;
            }
            if(a.ismusic)
            {
                if(a.ispaused)
                {
                    SDL_mixer.Mix_ResumeMusic();
                    a.ispaused = false;
                }
                else
                {
                    int i = SDL_mixer.Mix_PlayMusic(a.audio,-1);
                    SDL_mixer.Mix_VolumeMusic(vol);
                    a.previousmusicchannel = a.currentmusicchannel;
                    a.currentmusicchannel = i;
                    a.ispaused = false;
                }
            }
        }

///////////////////Method Definition///////////////
        public static void FreeAudio(Audios a)//10sep2021
        {
            //alias for freeaudio(Audios a)
            freeaudio(a);
        }
///////////////////Method Definition///////////////
        public static void freeaudio(Audios a)//10sep2021
        {
            if(a.ismusic)
            {
                return;
            }
            try
            {
                SDL_mixer.Mix_FreeChunk(a.audio);
                LocalStorage.setitem("FREE AUDIO:"+a.file,"SUCCESS"); //24mar2021
                a.audio = IntPtr.Zero;
            }
            catch(Exception e)
            {
                string txt = e.Message;
            }
        }
///////////////////Method Definition///////////////
        public static void stopchannel(int i)//10sep2021
        {
            try
            {
                SDL_mixer.Mix_HaltChannel(i);
            }
            catch(Exception e)
            {
                string txt = e.Message;
            }
        }
///////////////////Method Definition///////////////
        public static void pauseaudio(Audios a)
        {
            //pause an audio music track that is playing
            //and stop all other audio at the same time.
            if(a.ismusic)
            {
                SDL_mixer.Mix_PauseMusic();
                a.ispaused = true;
            }
            else
            {
            }
            SDL_mixer.Mix_HaltChannel(-1);
        }

///////////////////Method Definition///////////////
        public static void resumemusic(Audios a)
        {
            //resume a music track that is paused.
            if(!Game.audioon)
            {
                return;
            }
            if(a.ismusic)
            {
                SDL_mixer.Mix_ResumeMusic();
                a.ispaused = false;
            }
        }
    }
    //

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Images
    {
        public IntPtr texture;
        public int index;
        public bool anim;
        public int cwx;
        public int chy;
        public int chn;
        public int cwn;
        public string file; //26oct2020
        public bool loaded;//28Feb2021
        public bool stream; //28Feb2021
        public int drawframe; //28Feb2021
        public bool okloaded; //28Feb2021
        public bool neverloaded; //28Feb2021

///////////////////Method Definition///////////////
        public Images()
        {
        }

///////////////////Method Definition///////////////
        public Images(int i,bool a,int cw, int ch, int xn, int yn)
        {
            index = i;
            anim = a;
            cwx = cw;
            chy = ch;
            cwn = xn;
            chn = yn;
            loaded = false;//28Feb2021
            okloaded = false; //28Feb2021
            stream = Config.STREAMLOAD; //28Feb2021
            neverloaded = true;//28Feb2021
        }
    }
    //

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class RenderList
    {
        //
        public static int transitionmode = -1; //18apr2021
        public static int HALFTRANSIT = 30;//18apr2021
        public static int TRANSITIONRATE = 1;//18apr2021
        public static int STARTTRANSITION = 60;//18apr2021
        public static int screenshake = 0;
        public static bool IGNOREZOOM;
        public static int RENDERMODE = 0;
        public static int RENDERMODE_POOL = 0;
        public static int RENDERMODE_NONPOOL = 1;
        public IntPtr texture;
        public bool istext;
        public bool isrect;
        public bool isline;
        public bool filled;
        public int x;
        public int y;
        public int w;
        public int h;
        public int blend;
        public int index;
        public int frame;
        public uint color;
        public float sx;
        public float sy;
        public bool flipx;
        public bool flipy;
        public float alpha;
        public float angle;
        public string text;
        public IntPtr font;
        public int fontindex;//2apr2021//7apr2021
        public bool drawn;
        public bool centre;
        public bool ignorezoom;
        public bool ignorefontalias;
        //
        public static int renderi = 0;
        public static int maxrenderi = 0;
        //
        public static int offsetx = 0;
        public static int offsety = 0;
        //
        public static bool threadrunning = false;
        public static int recordframe = 0;
        public static IntPtr screenshotsurface;

        //start--------------//2apr2021
        public bool subimage;
        public int subx;
        public int suby;
        public int subw;
        public int subh;
        //end----------------//2apr2021
        
///////////////////Method Definition///////////////
        public static void init()
        {
            //RenderList has an init function that is called once before drawing
            renderi = 0;
            maxrenderi = 0;
        }

///////////////////Method Definition///////////////
        public static bool CaptureThread(IntPtr screenshotsurface)
        {
            //Separate thread used for capturing screenshots
            //screenshot is captured in the main thread
            //but the file is saved in a secondary thread to
            //prevent performance hits
            //if we had a faster hard drive we could capture movies this way..!
            if(threadrunning)
            {
                return false;
            }
            threadrunning = true;
            RenderList.screenshotsurface = screenshotsurface;
            Thread thread = new Thread(new ThreadStart(ThreadFunction));
            thread.Start();    
            return true;
        }

///////////////////Method Definition///////////////
        private static void ThreadFunction()
        {
            //screenshot saving thread
            recordframe++;
            //SDL.SDL_SaveBMP(screenshotsurface,"media/screenshots/img_"+Functions.zstr(recordframe,6)+".bmp");
            try //13mar2021 - try catch block added....
            {
            SDL_image.IMG_SavePNG(screenshotsurface,"media/screenshots/img_"+Functions.zstr(recordframe,6)+".png");    

            }
            catch(Exception e)
            {
                Console.WriteLine("Thread Error Taking Screenshot:"+e.Message);
            }
            try
            {
                SDL.SDL_FreeSurface(screenshotsurface);
            }
            catch(Exception e)
            {
                string msg = e.Message;
            }
            threadrunning = false;
        }

///////////////////Method Definition///////////////
        public RenderList()
        {
            drawn = false;    
            text = "";
            font = IntPtr.Zero;
            texture = IntPtr.Zero;
            centre = false;
            ignorezoom = true;
            ignorefontalias = false;
            subimage = false;//2apr2021
            subx = 0;
            suby = 0;
            subw = 0;
            subh = 0;
        }

///////////////////Method Definition///////////////
        public static void render(Game game)
        {
            ////////////////////////
            //Core Render function that is called in the game
            //Takes all the drawimage/drawrect/drawtext calls that were stored
            //in an array and draws them one after the other
            //start------//15mar2021
            bool chinese = false;
            Functions.saveseed(Functions.seed);
            if(Translation.GetLanguage()=="chinesesimplified")
            {
                chinese = true;
            }
            if(Config.useUNICODE)
            {
                chinese = true;
            }
            //end--------//15mar2021
            SDL.SDL_Rect src;
            SDL.SDL_Rect dst;
            int SW = 0;
            int SH = 0;
            SDL.SDL_GetRendererOutputSize(game.renderer,out SW,out SH);
            game.SW = SW;
            game.SH = SH;
            float gxscale = 1f;
            float gyscale = 1f;
            gxscale = (float)SW / (float)Game.RESOLUTIONX;
            gyscale = (float)SH / (float)Game.RESOLUTIONY;
            int offsetx = 0;//23feb2022
            int offsety = 0;
            if(screenshake>0)//23feb2022
            {
                screenshake--;
                offsetx=(int)(gxscale*(float)(Functions.rand(0,screenshake+1)-screenshake/2));
                offsety=(int)(gyscale*(float)(Functions.rand(0,screenshake+1)-screenshake/2));
            }
            for(int i=0;i<RenderList.renderi;i++)
            {
                //start----//19apr2021
                int origx = game.renderlist[i].x;
                int origy = game.renderlist[i].y;
                float origsx = game.renderlist[i].sx;
                float origsy = game.renderlist[i].sy;
                int origw = game.renderlist[i].w;
                int origh = game.renderlist[i].h;
                //end------//19apr2021
                game.renderlist[i].x+=RenderList.offsetx;
                game.renderlist[i].y+=RenderList.offsety;
                if(game.renderlist[i].ignorezoom==false)
                {
                    game.renderlist[i].x = Convert.ToInt32((float)game.renderlist[i].x*gxscale*game.zoom) + game.zoomcornerx;
                    game.renderlist[i].y = Convert.ToInt32((float)game.renderlist[i].y*gyscale*game.zoom) + game.zoomcornery;
                    game.renderlist[i].sx = ((float)game.renderlist[i].sx*gxscale*game.zoom);
                    game.renderlist[i].sy = ((float)game.renderlist[i].sy*gyscale*game.zoom);
                    game.renderlist[i].w = Convert.ToInt32((float)game.renderlist[i].w*gxscale*game.zoom);
                    game.renderlist[i].h = Convert.ToInt32((float)game.renderlist[i].h*gyscale*game.zoom);    
                }
                else
                {
                    game.renderlist[i].x = Convert.ToInt32((float)game.renderlist[i].x*gxscale);
                    game.renderlist[i].y = Convert.ToInt32((float)game.renderlist[i].y*gyscale);
                    game.renderlist[i].sx = ((float)game.renderlist[i].sx*gxscale);
                    game.renderlist[i].sy = ((float)game.renderlist[i].sy*gyscale);
                    game.renderlist[i].w = Convert.ToInt32((float)game.renderlist[i].w*gxscale);
                    game.renderlist[i].h = Convert.ToInt32((float)game.renderlist[i].h*gyscale);
                }
                //if(screenshake>0)//23feb2022
                //{
//                    screenshake--;
                    //int offsetx=(int)(gxscale*(float)(Functions.rand(0,screenshake+1)-screenshake/2));
                    //int offsety=(int)(gyscale*(float)(Functions.rand(0,screenshake+1)-screenshake/2));
                    //game.renderlist[i].x+=offsetx;
                    //game.renderlist[i].y+=offsety;
                //}
                game.renderlist[i].x+=offsetx;//23feb2022
                game.renderlist[i].y+=offsety;
                //
                if(game.renderlist[i].sx<0)
                {
                    game.renderlist[i].sx*=-1;
                    game.renderlist[i].flipx = true;
                }
                else
                {
                    game.renderlist[i].flipx = false;
                }
                if(game.renderlist[i].sy<0)
                {
                    game.renderlist[i].sy*=-1;
                    game.renderlist[i].flipy = true;
                }
                else
                {
                    game.renderlist[i].flipy = false;
                }
                SDL.SDL_SetRenderDrawColor(game.renderer,RenderList.getcomponents(game.renderlist[i].color)[1],RenderList.getcomponents(game.renderlist[i].color)[2],RenderList.getcomponents(game.renderlist[i].color)[3],RenderList.getcomponents(game.renderlist[i].color)[0]);
                if(game.renderlist[i].isrect)
                {
                    dst.x = game.renderlist[i].x;
                    dst.y = game.renderlist[i].y;
                    dst.w = game.renderlist[i].w;
                    dst.h = game.renderlist[i].h;
                    if(game.renderlist[i].filled)
                    {
                        SDL.SDL_RenderFillRect(game.renderer,ref dst);
                    }
                    else
                    {
                        SDL.SDL_RenderDrawRect(game.renderer,ref dst);
                    }
                }
                if(game.renderlist[i].isline)
                {
                    SDL.SDL_RenderDrawLine(game.renderer,game.renderlist[i].x,game.renderlist[i].y,game.renderlist[i].x+game.renderlist[i].w,game.renderlist[i].y+game.renderlist[i].h);
                }
                if(game.renderlist[i].istext)
                {
                    SDL.SDL_Color color;
                    color.r = RenderList.getcomponents(game.renderlist[i].color)[1];
                    color.g = RenderList.getcomponents(game.renderlist[i].color)[2];
                    color.b = RenderList.getcomponents(game.renderlist[i].color)[3];
                    color.a = (byte)Convert.ToInt32(255f * game.renderlist[i].alpha);
                    IntPtr text_surface;
                    if(!chinese) //15mar2021
                    {
                        text_surface = SDL_ttf.TTF_RenderText_Solid(game.renderlist[i].font,game.renderlist[i].text,color);
                    }
                    else
                    {
                        text_surface = SDL_ttf.TTF_RenderUNICODE_Solid(game.renderlist[i].font,game.renderlist[i].text,color); //15mar2021
                    }
                    dst.x = game.renderlist[i].x;
                    dst.y = game.renderlist[i].y;
                    if(!chinese) //15mar2021
                    {
                        SDL_ttf.TTF_SizeText(game.renderlist[i].font,game.renderlist[i].text,out dst.w,out dst.h);
                    }
                    else
                    {
                        SDL_ttf.TTF_SizeText(game.renderlist[i].font,game.renderlist[i].text,out dst.w,out dst.h);
                        if(!Translation.AllAscii(game.renderlist[i].text)) //16mar2021
                        {
                            //dst.w*=Fonts.WMULTIPLIER;//17mar2021
                            if(game.renderlist[i].text!=null)//17mar2021
                            {
                                if(game.renderlist[i].text.Length>0)
                                {
                                    dst.w*=(int)System.Math.Ceiling((double)((float)Fonts.WMULTIPLIER * (float)Translation.CountNonAscii(game.renderlist[i].text)) / (float)game.renderlist[i].text.Length); //Huh!?//17mar2021
                                    dst.h*=(int)System.Math.Ceiling((double)((float)Fonts.HMULTIPLIER * (float)Translation.CountNonAscii(game.renderlist[i].text)) / (float)game.renderlist[i].text.Length);//17apr2021
                                }
                            }
                        }
                    }
                    src.x = 0;
                    src.y = 0;
                    src.w = dst.w;
                    src.h = dst.h;
                    if(game.renderlist[i].ignorefontalias)
                    {
                        dst.w = Convert.ToInt32((float)dst.w*game.renderlist[i].sx);
                        dst.h = Convert.ToInt32((float)dst.h*game.renderlist[i].sy);
                    }
                    else
                    {
                        dst.w = Convert.ToInt32((float)dst.w*game.renderlist[i].sx)/Config.FONTALIAS;
                        dst.h = Convert.ToInt32((float)dst.h*game.renderlist[i].sy)/Config.FONTALIAS;
                    }
                    if(game.renderlist[i].centre)
                    {
                        dst.x-=dst.w/2;
                        dst.y-=dst.h/2;
                    }
                    IntPtr tex = SDL.SDL_CreateTextureFromSurface(game.renderer,text_surface);
                    //SDL.SDL_SetTextureScaleMode(tex,SDL.SDL_ScaleMode.SDL_ScaleModeNearest); //already commented out a while ago
                    SDL.SDL_FreeSurface(text_surface);
                    SDL.SDL_RenderCopyEx(game.renderer,tex,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);
                    SDL.SDL_DestroyTexture(tex);
                }
                SDL.SDL_SetRenderDrawColor(game.renderer,0,0,0,0);
                if(game.renderlist[i].texture!=IntPtr.Zero)
                {
                    SDL.SDL_SetTextureAlphaMod(game.renderlist[i].texture,Convert.ToByte(255.0f*game.renderlist[i].alpha));    
                    switch(game.renderlist[i].blend)
                    {
                        case 0:
                        SDL.SDL_SetTextureBlendMode(game.renderlist[i].texture,SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
                        break;
                        case 1:
                        SDL.SDL_SetTextureBlendMode(game.renderlist[i].texture,SDL.SDL_BlendMode.SDL_BLENDMODE_ADD);
                        break;
                    }
                    //start--------------//2apr2021
                    if(game.renderlist[i].subimage)
                    {
                        src.x = game.renderlist[i].subx;
                        src.y = game.renderlist[i].suby;
                        src.w = game.renderlist[i].subw;
                        src.h = game.renderlist[i].subh;
                        dst.x = game.renderlist[i].x;
                        dst.y = game.renderlist[i].y;
                        dst.w = Convert.ToInt32(game.renderlist[i].subw * game.renderlist[i].sx);
                        dst.h = Convert.ToInt32(game.renderlist[i].subh * game.renderlist[i].sy);
                        dst.x -= dst.w/2;
                        dst.y -= dst.h/2;
                        //SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);
                        if(game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL | SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL);
                        }
                        if(!game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(!game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);    
                        }
                        continue;
                    }
                    //end----------------//2apr2021
                    if(game.images[game.renderlist[i].index].anim)
                    {
                        src.x = game.images[game.renderlist[i].index].cwx * (game.renderlist[i].frame % game.images[game.renderlist[i].index].cwn);
                        src.y = game.images[game.renderlist[i].index].chy * ((game.renderlist[i].frame - (game.renderlist[i].frame % game.images[game.renderlist[i].index].cwn))/game.images[game.renderlist[i].index].cwn);
                        src.w = game.images[game.renderlist[i].index].cwx;
                        src.h = game.images[game.renderlist[i].index].chy;
                        dst.x = game.renderlist[i].x;
                        dst.y = game.renderlist[i].y;
                        dst.w = Convert.ToInt32(src.w * game.renderlist[i].sx);
                        dst.h = Convert.ToInt32(src.h * game.renderlist[i].sy);
                        dst.x -= dst.w/2;
                        dst.y -= dst.h/2;
                        if(game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL | SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL);
                        }
                        if(!game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(!game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);    
                        }
                    }
                    else
                    {
                        src.x = 0;
                        src.y = 0;
                        src.w = game.images[game.renderlist[i].index].cwx;
                        src.h = game.images[game.renderlist[i].index].chy;
                        dst.x = game.renderlist[i].x;
                        dst.y = game.renderlist[i].y;
                        dst.w = Convert.ToInt32(game.images[game.renderlist[i].index].cwx * game.renderlist[i].sx);
                        dst.h = Convert.ToInt32(game.images[game.renderlist[i].index].chy * game.renderlist[i].sy);
                        dst.x -= dst.w/2;
                        dst.y -= dst.h/2;
                        //SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);
                        if(game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL | SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_HORIZONTAL);
                        }
                        if(!game.renderlist[i].flipx && game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_VERTICAL);
                        }
                        if(!game.renderlist[i].flipx && !game.renderlist[i].flipy)
                        {
                            SDL.SDL_RenderCopyEx(game.renderer,game.renderlist[i].texture,ref src,ref dst,Convert.ToDouble(game.renderlist[i].angle),IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);    
                        }
                    }
                }
                //start----//19apr2021
                game.renderlist[i].x = origx;
                game.renderlist[i].y = origy;
                game.renderlist[i].sx = origsx;
                game.renderlist[i].sy = origsy;
                game.renderlist[i].w = origw;
                game.renderlist[i].h = origh;
                //end------//19apr2021
            }        
            if(RenderList.renderi>RenderList.maxrenderi)
            {
                RenderList.maxrenderi = RenderList.renderi;
            }
            //start-----//18apr2021
            if(transitionmode>=0)
            {
                //byte alpha = 255;
                int alpha = 255;
                if(transitionmode < HALFTRANSIT)
                {
                    RenderList.renderi = 0;
                    //alpha = (byte)(transitionmode * 8);
                    alpha = transitionmode * 8;
                }
                else
                {
                    //alpha = (byte)((60 - transitionmode) * 8);
                    alpha = (60 - transitionmode) * 8;
                }
                src.x = 0;
                src.y = 0;
                src.w = 1;
                src.h = 1;
                dst.x = 0;
                dst.y = 0;
                dst.w = SW;
                dst.h = SH;
                //if(Resources.blackcat!=-1)
                //{
                    //SDL.SDL_SetRenderDrawColor(game.renderer,(byte)(255-alpha),(byte)(255-alpha),(byte)(255-alpha),(byte)255);
                    SDL.SDL_SetRenderDrawBlendMode(game.renderer,SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
                    SDL.SDL_SetRenderDrawColor(game.renderer,0,0,0,(byte)alpha);
                    //SDL.SDL_SetRenderDrawBlendMode(game.renderer,SDL.SDL_BlendMode.SDL_BLENDMODE_MUL);
                    //SDL.SDL_SetTextureAlphaMod(game.images[Resources.blackcat].texture,alpha);    
                    //SDL.SDL_SetTextureBlendMode(game.images[Resources.blackcat].texture,SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
                    //SDL.SDL_RenderCopyEx(game.renderer,game.images[Resources.blackcat].texture,ref src,ref dst,0,IntPtr.Zero,SDL.SDL_RendererFlip.SDL_FLIP_NONE);    
                    SDL.SDL_RenderFillRect(game.renderer,ref dst);
                    SDL.SDL_SetRenderDrawBlendMode(game.renderer,SDL.SDL_BlendMode.SDL_BLENDMODE_NONE);
                    SDL.SDL_SetRenderDrawColor(game.renderer,0,0,0,0);
                    
                    
                //}
                transitionmode-=TRANSITIONRATE;
                Functions.restoreseed();
                return;
                //in other words don't clear the drawing list
                //so that we can draw over the top of it in some way
                //such as a black fade out screen......
            }
            //end-------//18apr2021
            RenderList.renderi = 0;
            Functions.restoreseed();
        }
        //draw an image

///////////////////Method Definition///////////////
        public static void drawimage(Game game,IntPtr img,int x,int y,float angle,float scalex,float scaley,int framenumber,int blend,bool istext,float alpha,int celltype)
        {
            //draw an image on the screen
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //RenderList r = new RenderList();
            //
            r.texture = img;
            r.x = x;
            r.y = y;
            r.w = 0;
            r.h = 0;
            r.isline = false;
            r.color = 0;
            r.alpha = alpha;
            r.angle = angle;
            r.sx = scalex;
            r.sy = scaley;
            r.frame = framenumber;
            r.blend = blend;
            r.istext = false;
            r.isrect = false;
            r.filled = false;
            r.index = celltype;
            //start-------------//28Feb2021
            if(celltype >= 0 && celltype < game.images.Length)
            {
                game.images[celltype].drawframe = game.frame;
            }
            //end---------------//28Feb2021
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }
        //

///////////////////Method Definition///////////////
        public static void drawanimimage(Game game,IntPtr img,int x,int y,float angle,float scalex,float scaley,int framenumber,int blend,bool istext,float alpha,int index)
        {
            //draw an animated image on the screen
            //can be used as an alternative to drawimage, but they are mostly identical now.
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = img;
            r.x = x;
            r.y = y;
            r.w = 0;
            r.h = 0;
            r.isline = false;
            r.color = 0;
            r.alpha = alpha;
            r.angle = angle;
            r.sx = scalex;
            r.sy = scaley;
            r.frame = framenumber;
            r.blend = blend;
            r.istext = false;
            r.isrect = false;
            r.filled = false;
            r.index = index;
            //start-------------//28Feb2021
            if(index >= 0 && index < game.images.Length)
            {
                game.images[index].drawframe = game.frame;
            }
            //end---------------//28Feb2021
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }

///////////////////Method Definition///////////////
        public static void drawsubimage(Game game,IntPtr img,int x,int y,float angle,float scalex,float scaley,int framenumber,int blend,bool istext,float alpha,int celltype,int ssx,int ssy,int ssw,int ssh)//2apr2021
        {
            //draw an image on the screen
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //RenderList r = new RenderList();
            //
            r.subimage = true;//2apr2021
            r.subx = ssx;//2apr2021
            r.suby = ssy;//2apr2021
            r.subw = ssw;//2apr2021
            r.subh = ssh;//2apr2021
            r.texture = img;
            r.x = x;
            r.y = y;
            r.w = 0;
            r.h = 0;
            r.isline = false;
            r.color = 0;
            r.alpha = alpha;
            r.angle = angle;
            r.sx = scalex;
            r.sy = scaley;
            r.frame = framenumber;
            r.blend = blend;
            r.istext = false;
            r.isrect = false;
            r.filled = false;
            r.index = celltype;
            //start-------------//28Feb2021
            if(celltype >= 0 && celltype < game.images.Length)
            {
                game.images[celltype].drawframe = game.frame;
            }
            //end---------------//28Feb2021
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }
        //

        //draw primitives

///////////////////Method Definition///////////////
        public static void drawrect(Game game,int x,int y,int w,int h,uint color,int blend)
        {
            //draw a filled rect on the screen
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = IntPtr.Zero;
            r.x = x;
            r.y = y;
            r.w = w;
            r.h = h;
            r.isline = false;
            r.color = color;
            r.alpha = 1;
            r.angle = 0;
            r.sx = 1;
            r.sy = 1;
            r.frame = 0;
            r.blend = blend;
            r.istext = false;
            r.isrect = true;
            r.filled = true;
            r.index = 0;
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }

///////////////////Method Definition///////////////
        public static void drawunfilledrect(Game game,int x,int y,int w,int h,uint color,int blend)
        {
            //draw an unfilled rect on the screen
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = IntPtr.Zero;
            r.x = x;
            r.y = y;
            r.w = w;
            r.h = h;
            r.isline = false;
            r.color = color;
            r.alpha = 1;
            r.angle = 0;
            r.sx = 1;
            r.sy = 1;
            r.frame = 0;
            r.blend = blend;
            r.istext = false;
            r.isrect = true;
            r.filled = false;
            r.index = 0;
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }

///////////////////Method Definition///////////////
        public static void drawline(Game game,int sx,int sy,int fx,int fy,uint color,int blend)
        {
            //draw a solid line on the screen
            //can also draw points.
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = IntPtr.Zero;
            r.x = sx;
            r.y = sy;
            r.w = (int)Functions.abs(fx - sx);
            r.h = (int)Functions.abs(fy - sy);
            if(fx<sx)
            {
                sx = fx;
            }
            if(fy<sy)
            {
                sy = fy;
            }
            r.isline = true;
            r.color = color;
            r.alpha = 1;
            r.angle = 0;
            r.sx = 1;
            r.sy = 1;
            r.frame = 0;
            r.blend = blend;
            r.istext = false;
            r.isrect = false;
            r.filled = false;
            r.index = 0;
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }
        //draw text
///////////////////Method Definition///////////////
        public static void drawtext(Game game,int x,int y,string text,uint color,IntPtr font,bool centre)
        {
            //draw text with a certain font on the screen
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = IntPtr.Zero;
            r.x = x;
            r.y = y;
            r.w = 0;
            r.h = 0;
            r.isline = false;
            r.color = color;
            r.alpha = 1;
            r.angle = 0;
            r.sx = 1;
            r.sy = 1;
            r.frame = 0;
            r.blend = 0;
            r.istext = true;
            r.isrect = false;
            r.filled = false;
            r.index = 0;
            r.text = text;
            r.font = font;
            r.ignorefontalias = false;
            if(font==game.fonts[Resources.SMALLFONT].font)
            {
                if(game.fonts[Resources.SMALLFONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.SMALLFONT;//7apr2021
            }
            if(font==game.fonts[Resources.FONT].font)
            {
                if(game.fonts[Resources.FONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.FONT;//7apr2021
            }
            if(font==game.fonts[Resources.LARGEFONT].font)
            {
                if(game.fonts[Resources.LARGEFONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.LARGEFONT;//7apr2021
            }
            r.centre = centre;
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }

///////////////////Method Definition///////////////
        public static void drawtext(Game game,IntPtr font,int x,int y,float angle,float scalex,float scaley,bool centre,int blend,string text,float alpha,uint color)
        {
            //alternative drawtext command
            //RenderList r = new RenderList();
            RenderList r;
            if(RenderList.renderi<game.renderlist.Length && RENDERMODE==RENDERMODE_POOL)
            {
                r = game.renderlist[RenderList.renderi];
                r.drawn = false;    
                r.text = "";
                r.font = IntPtr.Zero;
                r.texture = IntPtr.Zero;
                r.centre = false;
                r.ignorezoom = true;
                r.ignorefontalias = false;
                r.subimage = false;//2apr2021
            }
            else
            {
                r = new RenderList();
            }
            //
            r.texture = IntPtr.Zero;
            r.x = x;
            r.y = y;
            r.w = 0;
            r.h = 0;
            r.isline = false;
            r.color = color;
            r.alpha = alpha;
            r.angle = angle;
            r.sx = scalex;
            r.sy = scaley;
            r.frame = 0;
            r.blend = blend;
            r.istext = true;
            r.isrect = false;
            r.filled = false;
            r.index = 0;
            r.text = text;
            r.font = font;
            r.ignorefontalias = false;
            if(font==game.fonts[Resources.SMALLFONT].font)
            {
                if(game.fonts[Resources.SMALLFONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.SMALLFONT;//7apr2021
            }
            if(font==game.fonts[Resources.FONT].font)
            {
                if(game.fonts[Resources.FONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.FONT;//7apr2021
            }
            if(font==game.fonts[Resources.LARGEFONT].font)
            {
                if(game.fonts[Resources.LARGEFONT].ptsize<20)
                {
                    r.ignorefontalias = true;
                }
                r.fontindex = Resources.LARGEFONT;//7apr2021
            }
            r.centre = centre;
            if(RenderList.renderi>=RenderList.maxrenderi)
            {
                Array.Resize<RenderList>(ref game.renderlist,game.renderlist.Length + 1);
            }
            game.renderlist[RenderList.renderi] = r;
            game.renderlist[RenderList.renderi].ignorezoom = IGNOREZOOM;
            RenderList.renderi++;
        }
        //rgb helper functions.

///////////////////Method Definition///////////////
        public static uint getrgb(int r, int g, int b)
        {
            //return the rgb value by its components
            return (uint)(255 << 24 | (byte)r << 16 | (byte)g << 8 | (byte)b);
        }

///////////////////Method Definition///////////////
        public static uint getrgb(byte r,byte g, byte b)
        {
            //return the rgb value by its components
            return (uint)(255 << 24 | r << 16 | g << 8 | b);
        }

///////////////////Method Definition///////////////
        public static byte[] getcomponents(uint argb)
        {
            //get the components of an argb colour and return an array of alpha, red, green, blue as a bunch of byte values
            byte[] rgbarray = {0,0,0,0};
            rgbarray[0] = (byte)((argb >> 24) & (255));
            rgbarray[1] = (byte)((argb >> 16) & (255));
            rgbarray[2] = (byte)((argb >> 8) & 255);
            rgbarray[3] = (byte)((argb & 255));
            return rgbarray;
        }
    }
    //
    

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Network
    {
        //Network.url = "https://www.mattiesgames.com/metrics/metric.php?game="+Game.NETTITLE+"&event=[your event here]&value="[your value here];
        //Network.httpget(Network.url);
        public static string url = "";

        public static string errorreport = "";    
        public static string ERRORURL = "https://www.mattiesgames.com/metrics/metric.php?game=grumthorr&event=errorlog&value=error:";

///////////////////Method Definition///////////////
        private static void ThreadFunction()
        {
            //send a network message to a website
            //typically used for sending metrics
            //or such. return values are ignored
            if(Network.url=="")
            {
                return;
            }
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Network.url);
                request.Timeout = 10000;
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                //start---//1apr2021
                Stream stream = response.GetResponseStream();
                Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
                StreamReader read = new StreamReader(stream,encode);
                Char[] chararray = new Char[256];
                if(Config.GETDATA)
                {
                    int count = read.Read(chararray,0,256);
                    while(count>0)
                    {
                        String str = new String(chararray,0,count);
                        //Console.WriteLine(str);
                        count = read.Read(chararray,0,256);
                    }
                }
                response.Close();//1apr2021
                read.Close();
                //end---//1apr2021
            }
            catch(Exception e)
            {
                string message = (e.Message);
            }
        }

///////////////////Method Definition///////////////
        private static void ErrorFunction()
        {
            //send error information to a location
            //should the game have an error on intialisation
            Network.url = Network.ERRORURL+Network.errorreport;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Network.url);
                request.Timeout = 10000;
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                //start---//1apr2021
                Stream stream = response.GetResponseStream();
                Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
                StreamReader read = new StreamReader(stream,encode);
                Char[] chararray = new Char[256];
                int count = read.Read(chararray,0,256);
                if(Config.GETDATA)
                {
                    while(count>0)
                    {
                        String str = new String(chararray,0,count);
                        //Console.WriteLine(str);
                        count = read.Read(chararray,0,256);
                    }
                }
                response.Close();//1apr2021
                read.Close();
                //end---//1apr2021
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Network.url = "";
        }

///////////////////Method Definition///////////////
        public static void httpget(string u)
        {
            //basic function for performing a http get operation
            //runs in a separate thread
            if(Config.NOMETRICS)
            {
                return;
            }
            Network.url = u;
            try
            {
            Thread thread = new Thread(new ThreadStart(ThreadFunction));
            thread.Start();
            }
            catch(Exception e)
            {
                string message = e.Message;
            }
        }

///////////////////Method Definition///////////////
        public static void reporterror(bool send)
        {
            //report an error in intialisation of the game
            if(Network.errorreport=="")
            {
                return;
            }
            if(send)
            {
                Network.errorreport+="endoferrors";
                Thread thread = new Thread(new ThreadStart(ErrorFunction));
                thread.Start();
            }
        }

///////////////////Method Definition///////////////
        public static void reporterror(string report,bool send)
        {
            //alternative reporting of an error method
            Network.errorreport+=report+":";
            if(send)
            {
                Network.errorreport+="endoferrors";
                Thread thread = new Thread(new ThreadStart(ErrorFunction));
                thread.Start();
            }
        }
    }
    

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Functions
    {
        public static int oseed = 12345678;
        public static int seed = 12345678;
        public static int[] seeds = new int[0];
        //
///////////////////Method Definition///////////////
        public static string ClockTime(int seconds)
        {
            int mins = (seconds - (seconds % 60)) / 60;
            int secs = seconds % 60;
            return zstr(mins,2) + ":" + zstr(secs,2);
        }
        
///////////////////Method Definition///////////////
        public static string zstr(int i,int n)
        {
            //return an integer number such as 123 as 00123,
            //i = the number
            //n = the number of digits to use
            string s = "" + i;
            while(s.Length<n)
            {
                s = "0" + s;
            }
            return s;
        }

///////////////////Method Definition///////////////
        public static void saveseed() //11apr2021
        {
            oseed = seed;
            Array.Resize(ref seeds,seeds.Length + 1); //11apr2021
            seeds[seeds.Length - 1] = seed;//11apr2021
        }
        
///////////////////Method Definition///////////////
        public static void saveseed(int s)
        {
            //save the random number seed for later use
            oseed = seed;
            seed = s;
            Array.Resize(ref seeds,seeds.Length + 1);//11apr2021
            seeds[seeds.Length - 1] = s;//11apr2021
        }

///////////////////Method Definition///////////////
        public static void restoreseed()
        {
            //restore the random number seed which was saved earlier
            //seed = oseed;//11apr2021
            if(seeds.Length>0)//11apr2021
            {
                seed = seeds[seeds.Length - 1];//11apr2021
                Array.Resize(ref seeds,seeds.Length -1);//11apr2021
            }
            else//11apr2021
            {
                seed = oseed;//11apr2021
                Console.WriteLine("Warning:Seeds Out of Sync");//11apr2021
            }
        }

///////////////////Method Definition///////////////
        public static float abs(float value)
        {
            //absolute value
            if(value<0)
            {
                return -1* value;
            }
            return value;
        }

///////////////////Method Definition///////////////
        public static int Rand(int min,int max)
        {
            //random number generator
            return min + Convert.ToInt32(random()*(double)(max-min));
        }        
        //

///////////////////Method Definition///////////////
        public static int Sign(float value)
        {
            //return the sign positive or negative of the number, or zero
            if(value>0){return 1;}
            if(value<0){return -1;}
            return 0;    
        }
        //

///////////////////Method Definition///////////////
        public static int rand(int min,int max)
        {
            //random number generator
            return Rand(min,max);
        }
        //

///////////////////Method Definition///////////////
        public static int sign(float value)
        {
            //alias of Sign
            return Sign(value);
        }
        //

///////////////////Method Definition///////////////
        public static double random()
        {
            //pseudo random number generator
            Functions.seed = ((89723453 * Functions.seed + 42854321) % 1000000);
            double r = ((double)Functions.seed / 1000000.0);
            if(r<0)
            {
                r*=-1.0;
            }
            return r;
        }
        /*

///////////////////Method Definition///////////////
        public static float calcangle(float x, float y)
        {
        //    return Math.atan2(y, x) ;
        }
        //
        *
/

///////////////////Method Definition///////////////
        public static int isox(int x,int y,int w)
        {
            //isometric calculation
            //pass in the grid square and return a location in screen coordinates
            return (w/2) * (1 + x - y);
        }
        //

///////////////////Method Definition///////////////
        public static int isoy(int x,int y,int w)
        {
            //isometric calculation
            //pass in the grid square and return a location in screen coordinates
            return (w/4) * (1 + y + x);
        }
        //

///////////////////Method Definition///////////////
        public static int screentoisox(int sx,int sy,int w,int offsetx,int offsety)
        {
            //isometric calculation
            //pass in screen coordinates and convert to iso x grid
            sx-=offsetx;
            sy-=offsety;
            return Convert.ToInt32((((float)sx + 2f * (float)sy)/(float)w) - 1f);
        }
        //

///////////////////Method Definition///////////////
        public static int screentoisoy(int sx,int sy,int w,int offsetx,int offsety)
        {
            //isometric calculation
            //pass in screen coordinates and convert to iso y grid
            sx-=offsetx;
            sy-=offsety;
            return Convert.ToInt32((2f*(float)sy - (float)sx)/(float)w);
        }
    }
    //

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
     class Program
     {
        //game specific stuff here
        //
        //RTS Components
        //

///////////////////Method Definition///////////////
        static void Main(string[] args)
                     {
            if(args!=null)
            {
                if(args.Length>0)
                {
                    if(args[0] == "-editor")
                    {
                        Game.EDITOR = true;
                    }
                }
            }
            //init(); //13mar2021
            //start--------------//13mar2021
            Game.restart = true;
            Game.restartgamestate = -1;//26mar2021
            while(Game.restart)
            {
                Game.restart = false;
                init();
            }
            //end----------------//13mar2021
                     }

///////////////////Method Definition///////////////
        //static void checkconfig() //28Feb2021

///////////////////Method Definition///////////////
        static bool checkconfig() //28Feb2021
        {
            //Game initialisation - check the config file
            //and setup initial parameters including the filenames and paths
            //to check for all the various game components
            //language also set here
            //start-------------//23feb2022
            //remember it is an alien planet so perhaps the seasons are different?
            Int32.TryParse(DateTime.Now.ToString("HH"),out Config.CurrentMonth);
            Config.Season = Config.CurrentMonth % 3;
            //Config.Season = Config.WINTER;//debugging 4mar2022
            //Config.Season = Config.SUMMER;
            //Config.Season = 0;
            //int timeofday = 12;
            //Int32.TryParse(DateTime.Now.ToString("HH"),out timeofday);
            //Config.Night = 0;
            //if(timeofday<6 || timeofday>18)
            //{
//                Config.Night = 1;
            //}
            //end---------------//23feb2022
            //start-------------//12mar2021
            Config.useUNICODE = false; //15mar2021
            if(Config.KOG2)
            {
                Game.NETTITLE = "grumthorr2";
                Game.TITLE = "Knights of Grumthorr 2";
            }
            //end---------------//12mar2021
            //25Feb2021 - altered order of try/catch statements...config file read first.
            string folder = "";
            string folderu = "";
            string folderd = "";
            //start-------------//28Feb2021
            Config.configfile = "media/txt/config.txt"; //28Feb2021
            try
            {
                string[] cdata = System.IO.File.ReadAllLines("media/txt/init.txt");
                for(int i=0;i<cdata.Length;i++)
                {
                    if(cdata[i].IndexOf("=")>0)
                    {
                        switch(cdata[i].Substring(0,cdata[i].IndexOf("=")))
                        {
                            case "config":
                            Config.configfile = Resources.readstring(cdata[i]);
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                //do nothing
                Console.WriteLine("Warning - Error reading init.txt:"+e.Message);
                Config.configfile = "media/txt/config.txt"; //28Feb2021
            }
            //end---------------//28Feb2021
            try
            {
                //string[] data = System.IO.File.ReadAllLines("media/txt/config.txt"); //28Feb2021
                string[] data = System.IO.File.ReadAllLines(Config.configfile); //28Feb2021
                for(int i=0;i<data.Length;i++)
                {
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "useseasons"://23feb2022
                            Config.useseasons = Resources.readint(data[i]);
                            break;
                            case "resolutionx"://23sep2021
                            Config.DEFAULTRESX = Resources.readint(data[i]);
                            break;
                            case "resolutiony"://23sep2021
                            Config.DEFAULTRESY = Resources.readint(data[i]);
                            break;
                            case "fastframecheck"://14sep2021
                            Config.FASTFRAMECHECK = Resources.readint(data[i]);//14sep2021
                            break;
                            case "usedelta"://18sep2021
                            Config.USEDELTATIME = Resources.readint(data[i]);//18sep2021
                            break;
                            case "noupdateindemomode"://18sep2021
                            Config.NOUPDATEINDEMOMODE = Resources.readint(data[i]);//18sep2021
                            break;
                            case "maxfps"://18sep2021
                            Config.UNLOCKFRAMERATE = Resources.readint(data[i]);//18sep2021
                            break;
                            case "autoplay"://18sep2021
                            Config.AUTOPLAY = Resources.readint(data[i]);//18sep2021
                            break;
                            case "noshowability"://16sep2021
                            Config.NOSHOWABILITY = Resources.readint(data[i]);//16sep2021
                            break;
                            case "optimisefires"://15sep2021
                            Config.OPTIMISEFIRES = Resources.readint(data[i]);//15sep2021
                            break;
                            case "clump"://15sep2021
                            Config.CLUMP = Resources.readint(data[i]);//15sep2021
                            break;
                            case "fudgefactor"://20sep2012
                            Config.FACTOR = Resources.readint(data[i]);
                            if(Config.FACTOR<1)
                            {
                                Config.FACTOR=1;
                            }
                            if(Config.FACTOR>10000)
                            {
                                Config.FACTOR = 10000;
                            }
                            break;
                            case "tilefog"://15sep2021
                            Config.TILEFOG = Resources.readint(data[i]);//15sep2021
                            break;
                            case "noreplay"://15sep2021
                            Config.NOREPLAY = Resources.readint(data[i]);//15sep2021
                            break;
                            case "gridw"://10sep2021
                            Map.DEFAULTGRIDW = Resources.readint(data[i]);//10sep2021
                            break;//10sep2021
                            case "gridh"://10sep2021
                            Map.DEFAULTGRIDH = Resources.readint(data[i]);//10sep2021
                            break;//10sep2021
                            case "VER"://16apr2021
                            Game.VERSIONSTR = Resources.readstring(data[i]);//16apr2021
                            break;
                            case "NETTITLE": //25Feb2021
                            Game.NETTITLE = Resources.readstring(data[i]);//25Feb2021;
                            break;//25Feb2021
                            case "TITLE"://2sep2021
                            Game.TITLE = Resources.readstring(data[i]);//2sep2021
                            break;//2sep2021
                            case "PATHTHREADING"://29may2021
                            if(Resources.readint(data[i])>0 && Environment.ProcessorCount>=4)
                            {
                                Config.THREADEDPATHING = true;
                            }
                            else
                            {
                                Config.THREADEDPATHING = false;
                            }
                            break;
                            case "KEYFRAME": //21apr2021
                            Replay.KEYFRAME = Resources.readint(data[i]);
                            if(Replay.KEYFRAME<1)
                            {
                                Replay.KEYFRAME = 1;
                            }
                            break;
                            //start-----------------//21mar2021
                            case "usecoverflag":
                            if(Resources.readstring(data[i])=="1")
                            {
                                Config.USECOVERFLAG = true;
                            }
                            if(Resources.readstring(data[i])=="0")
                            {
                                Config.USECOVERFLAG = false;
                            }
                            break;
                            case "usefeetcircles":
                            if(Resources.readstring(data[i])=="1")
                            {
                                Config.USEFEETCIRCLES = true;
                            }
                            if(Resources.readstring(data[i])=="0")
                            {
                                Config.USEFEETCIRCLES = false;
                            }
                            break;
                            case "translategui":
                            if(Resources.readstring(data[i])=="1")
                            {
                                Config.TRANSLATEGUI = true;
                            }
                            if(Resources.readstring(data[i])=="0")
                            {
                                Config.TRANSLATEGUI = false;
                            }
                            break;
                            case "useiconcircles":
                            if(Resources.readstring(data[i])=="1")
                            {
                                Config.USEICONCIRCLES = true;
                            }
                            if(Resources.readstring(data[i])=="0")
                            {
                                Config.USEICONCIRCLES = false;
                            }
                            break;
                            //end-------------------//21mar2021
                            case "fullscreen":
                            Game.FULLSCREEN = Resources.readint(data[i]);
                            break;
                            case "resize"://22may2021
                            Config.WINDOWRESIZE = Resources.readint(data[i]);//22may2021
                            break;//22may2021
                            case "hires"://10apr2021
                            Config.hires = Resources.readint(data[i]);//10apr202
                            break;//10apr2021
                            case "musicvolume":
                            Game.MUSICVOLUME = Resources.readint(data[i]);
                            Game.oMUSICVOLUME = Game.MUSICVOLUME;
                            if(Game.EDITOR)
                            {
                                Game.MUSICVOLUME = 0;
                            }
                            break;
                            //start--------------//13mar2021
                            case "words":
                            Config.wordsfile = Resources.readstring(data[i]);
                            break;
                            //end----------------//13mar2021
                            case "fxvolume":
                            Game.FXVOLUME = Resources.readint(data[i]);
                            Game.oFXVOLUME = Game.FXVOLUME;
                            break;
                            case "guifile":
                            Config.guifile = Resources.readstring(data[i]);
                            break;
                            case "fontalias":
                            Config.FONTALIAS = Resources.readint(data[i]);
                            if(Config.FONTALIAS<1)
                            {
                                Config.FONTALIAS = 1;
                            }
                            break;
                            //start-----------------//20mar2021
                            case "healthmod":
                            Config.HEALTHPCT = Resources.readint(data[i]);
                            break;
                            case "armourmod":
                            Config.ARMOURPCT = Resources.readint(data[i]);
                            break;
                            case "attackmod":
                            Config.ATTACKPCT = Resources.readint(data[i]);
                            break;
                            //end-------------------//20mar2021
                            case "campaignfile":
                            Config.campaignfile = Resources.readstring(data[i]);
                            break;
                            case "skirmishmessage":
                            Config.skirmishmessage = Resources.readstring(data[i]);
                            break;
                            case "customcampaignfile":
                            Config.customcampaignfile = Resources.readstring(data[i]);
                            break;
                            case "unitsfile":
                            Config.unitsfile = Resources.readstring(data[i]);
                            break;
                            case "techfile": //2sep2021
                            Config.techfile = Resources.readstring(data[i]);//2sep2021
                            break;//2sep2021
                            case "defaultfontfile":
                            Config.defaultfontfile = Resources.readstring(data[i]);
                            break;
                            case "normalfontsize":
                            Config.normalfontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                            break;
                            case "dointro"://1mar2022
                            Config.dointro = Resources.readint(data[i]);//1mar2022
                            break;
                            case "smallfontsize":
                            Config.smallfontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                            break;
                            case "largefontsize":
                            Config.largefontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                            break;
                            case "audioclickfile":
                            Config.audioclickfile = Resources.readstring(data[i]);
                            break;
                            case "offsetfile"://20apr2021
                            Config.offsetfile = Resources.readstring(data[i]);//20apr2021
                            break;
                            case "DOCALCOFFSETS"://20apr2021
                            if(Resources.readint(data[i])==1)
                            {
                                Config.AUTOCALCOFFSETS = true;
                            }
                            else
                            {
                                Config.AUTOCALCOFFSETS = false;
                            }
                            break;
                            case "logofile":
                            Config.logofile = Resources.readstring(data[i]);
                            break;
                            case "fogfile":
                            Config.fogfile = Resources.readstring(data[i]);
                            break;
                            case "logowidth":
                            Config.logowidth = Resources.readint(data[i]);
                            break;
                            case "logoheight":
                            Config.logoheight = Resources.readint(data[i]);
                            break;
                            case "fogwidth":
                            Config.fogwidth = Resources.readint(data[i]);
                            break;
                            case "fogheight":
                            Config.fogheight = Resources.readint(data[i]);
                            break;
                            case "record": //13mar2021
                            if(Resources.readint(data[i])==1)
                            {
                                Config.RECORD = true;
                            }
                            break;
                            case "useunicode": //15mar2021
                                if(Resources.readint(data[i])==1)
                                {
                                    Config.useUNICODE = true;
                                }
                                if(Resources.readint(data[i])==0)
                                {
                                    Config.useUNICODE = false;
                                }
                            break;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Error reading config.txt:"+e.Message);
                return false; //28Feb2021
            }
            try
            {
                folderd = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\\"+Game.NETTITLE;
                if(!Directory.Exists(folderd))
                {
                    Directory.CreateDirectory(folderd);
                }
            }
            catch(Exception e)
            {
                string message = e.Message;
            }
            try
            {
                string[] datad = System.IO.File.ReadAllLines(folderd+"\\nometrics.txt");
                if(datad.Length>0)
                {
                    Config.NOMETRICS = true;
                }
            }
            catch(Exception e)
            {
                string mm = e.Message;
            }
            try
            {
                folderu = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\\"+Game.NETTITLE+"\\usercampaign";
                if(!Directory.Exists(folderu))
                {
                    Directory.CreateDirectory(folderu);
                }
                if(Directory.Exists(folderu))
                {
                    Config.usercampaignfolder = folderu;
                    Config.usercampaignfile = folderu + "\\usercampaign.txt";
                }
            }
            catch(Exception e)
            {
                string message = e.Message;
            }
            try
            {
                folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\\"+Game.NETTITLE+"\\custommaps";
                if(!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }
                if(Directory.Exists(folder))
                {
                    Config.custommapfolder = folder;
                }
            }
            catch(Exception e)
            {
                string message = e.Message;
            }
            if(Game.EDITOR)
            {
                Game.FULLSCREEN = 0;
            }
            LocalStorage.init();//12mar2021
            //LocalStorage.WriteLog("Begin");
            LocalStorage.finalise();//13mar2021
            applyprefs();
            return true; //28Feb2021
        }

///////////////////Method Definition///////////////
        static void applyprefs() //12mar2021
        {
            //start---------------//30mar2021
            if(LocalStorage.getitem("uid")!="")
            {
                Config.uid = LocalStorage.getitem("uid");
            }
            else
            {
                long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
                Config.uid = ""+milliseconds;
                LocalStorage.setitem("uid",Config.uid);
            }
            //end-----------------//30mar2021
            //apply preferences and language settings
            Fonts.WMULTIPLIER = 1;//15mar2021
            Fonts.HMULTIPLIER = 1;//17apr2021
            //start-------//28feb2022
            if(LocalStorage.getitem("options_fog")=="off")
            {
                Config.options_fog = 0;
            }
            if(LocalStorage.getitem("options_fog")=="on")
            {
                Config.options_fog = 1;
            }
            if(LocalStorage.getitem("options_overlay")=="off")
            {
                Config.options_overlay = 0;
            }
            if(LocalStorage.getitem("options_overlay")=="on")
            {
                Config.options_overlay = 1;
            }
            //end---------//28feb2022
            if(LocalStorage.getitem("sfx")=="off")
            {
                Game.oFXVOLUME = Game.FXVOLUME;
                Game.FXVOLUME = 0;
            }
            if(LocalStorage.getitem("music")=="off")
            {
                Game.oMUSICVOLUME = Game.MUSICVOLUME;
                Game.MUSICVOLUME = 0;
            }
            //start------------//17apr2021
            if(LocalStorage.getitem("hires")=="0")
            {
                Config.hires = 0;
            }
            if(LocalStorage.getitem("hires")=="1")
            {
                Config.hires = 1;
            }
            if(LocalStorage.getitem("fullscreen")=="0")
            {
                Game.FULLSCREEN = 0;
            }
            if(LocalStorage.getitem("fullscreen")=="1")
            {
                Game.FULLSCREEN = 1;
            }
            //end--------------//17apr2021
            //start--------------//13mar2021
            string language = Translation.GetLanguage();
            //start------------------//18mar2021
            if(Config.NonEnglishAllowed)//1mar2022
            {
                if(language=="")
                {
                    try
                    {
                        string langcode = CultureInfo.CurrentUICulture.Name;
                        switch(langcode.Substring(0,2))
                        {
                            case "en": //English
                                language = "english";
                            break;
                            case "de": //German
                                language = "german";
                            break;
                            case "fr": //French
                                language = "french";
                            break;
                            case "es": //Spanish
                                language = "spanish";
                            break;
                            case "zh": //Chinese
                                if(langcode=="zh-CN")
                                {
                                    language = "chinesesimplified";
                                }
                            break;
                            case "tr": //Turkish//22mar2021
                                language = "turkish";
                            break;
                            case "ru": //Russian
                                language = "russian";
                            break;
                            case "ro": //Romanian //21mar2021
                                language = "romanian";
                            break;
                        }
                        if(language!="")
                        {
                            Console.WriteLine("Language Found and Chosen:"+language);
                            //LocalStorage.WriteLog("Language Found and Chosen:"+language);
                            Config.autodetectlang = language;//30mar2021
                        }
                        else
                        {
                            Console.WriteLine("Possible language not supported");
                            //LocalStorage.WriteLog("Possible language not supported");
                        }
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine("Error getting UI Language:"+e.Message);
                        //LocalStorage.WriteLog("Error getting UI Language:"+e.Message);
                    }
                }
            }
            else//1mar2022
            {
                language = "english";
            }
            //end--------------------//18mar2021
            if(language!="")
            {
                string altconfigfile = Config.configfile + language;
                try
                {
                    string[] data = System.IO.File.ReadAllLines(altconfigfile); //28Feb2021
                    for(int i=0;i<data.Length;i++)
                    {
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "useseasons"://23feb2022
                                    Config.useseasons = Resources.readint(data[i]);
                                break;
                                case "foreignnumbers":
                                Translation.init(Resources.readstring(data[i]));
                                break;
                                //start--------------//13mar2021
                                case "words":
                                Config.wordsfile = Resources.readstring(data[i]);
                                break;
                                //end----------------//13mar2021
//                                case "NETTITLE": //25Feb2021
//                                Game.NETTITLE = Resources.readstring(data[i]);//25Feb2021;
//                                break;//25Feb2021
//                                case "fullscreen":
//                                Game.FULLSCREEN = Resources.readint(data[i]);
//                                break;
//                                case "musicvolume":
//                                Game.MUSICVOLUME = Resources.readint(data[i]);
//                                Game.oMUSICVOLUME = Game.MUSICVOLUME;
//                                if(Game.EDITOR)
//                                {
//                                    Game.MUSICVOLUME = 0;
//                                }
//                                break;
//                                case "fxvolume":
//                                Game.FXVOLUME = Resources.readint(data[i]);
//                                Game.oFXVOLUME = Game.FXVOLUME;
//                                break;
                                case "guifile":
                                Config.guifile = Resources.readstring(data[i]);
                                break;
                                case "fontalias":
                                Config.FONTALIAS = Resources.readint(data[i]);
                                if(Config.FONTALIAS<1)
                                {
                                    Config.FONTALIAS = 1;
                                }
                                break;
                                case "resolutionx"://23sep2021
                                Config.DEFAULTRESX = Resources.readint(data[i]);
                                break;
                                case "resolutiony"://23sep2021
                                Config.DEFAULTRESY = Resources.readint(data[i]);
                                break;
                                case "fastframecheck"://14sep2021
                                Config.FASTFRAMECHECK = Resources.readint(data[i]);//14sep2021
                                break;
                                case "noreplay"://15sep2021
                                Config.NOREPLAY = Resources.readint(data[i]);//15sep2021
                                break;
                                case "noupdateindemomode"://18sep2021
                                Config.NOUPDATEINDEMOMODE = Resources.readint(data[i]);//18sep2021
                                break;
                                case "usedelta"://18sep2021
                                Config.USEDELTATIME = Resources.readint(data[i]);//18sep2021
                                break;
                                case "maxfps"://18sep2021
                                Config.UNLOCKFRAMERATE = Resources.readint(data[i]);//18sep2021
                                break;
                                case "autoplay"://18sep2021
                                Config.AUTOPLAY = Resources.readint(data[i]);//18sep2021
                                break;
                                case "noshowability"://16sep2021
                                Config.NOSHOWABILITY = Resources.readint(data[i]);//16sep2021
                                break;
                                case "optimisefires"://15sep2021
                                Config.OPTIMISEFIRES = Resources.readint(data[i]);//15sep2021
                                break;
                                case "fudgefactor"://20sep2012
                                Config.FACTOR = Resources.readint(data[i]);
                                if(Config.FACTOR<1)
                                {
                                    Config.FACTOR=1;
                                }
                                if(Config.FACTOR>10000)
                                {
                                    Config.FACTOR = 10000;
                                }
                                break;
                                case "clump"://15sep2021
                                Config.CLUMP = Resources.readint(data[i]);//15sep2021
                                break;
                                case "tilefog"://15sep2021
                                Config.TILEFOG = Resources.readint(data[i]);//15sep2021
                                break;
                                case "campaignfile":
                                Config.campaignfile = Resources.readstring(data[i]);
                                break;
                                case "skirmishmessage":
                                Config.skirmishmessage = Resources.readstring(data[i]);
                                break;
                                case "customcampaignfile":
                                Config.customcampaignfile = Resources.readstring(data[i]);
                                break;
                                case "unitsfile":
                                Config.unitsfile = Resources.readstring(data[i]);
                                break;
                                case "gridw"://10sep2021
                                Map.DEFAULTGRIDW = Resources.readint(data[i]);//10sep2021
                                break;//10sep2021
                                case "gridh"://10sep2021
                                Map.DEFAULTGRIDH = Resources.readint(data[i]);//10sep2021
                                break;//10sep2021
                                case "techfile"://2sep2021
                                Config.techfile = Resources.readstring(data[i]);//2sep2021
                                break;//2sep2021
                                case "defaultfontfile":
                                Config.defaultfontfile = Resources.readstring(data[i]);
                                break;
                                case "normalfontsize":
                                Config.normalfontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                                break;
                                case "dointro"://1mar2022
                                Config.dointro = Resources.readint(data[i]);//1mar2022
                                break;
                                case "smallfontsize":
                                Config.smallfontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                                break;
                                case "largefontsize":
                                Config.largefontsize = Resources.readint(data[i]);// * Config.FONTALIAS;
                                break;
                                case "fonthmultiplier"://17apr2021
                                Fonts.HMULTIPLIER = Resources.readint(data[i]);
                                if(Fonts.HMULTIPLIER<1)
                                {
                                    Fonts.HMULTIPLIER = 1;
                                }
                                break;
                                case "fontwmultiplier": //15mar2021
                                Fonts.WMULTIPLIER = Resources.readint(data[i]);
                                if(Fonts.WMULTIPLIER<1)
                                {
                                    Fonts.WMULTIPLIER = 1;
                                }
                                break;
                                case "offsetfile"://20apr2021
                                Config.offsetfile = Resources.readstring(data[i]);//20apr2021
                                break;
                                case "audioclickfile":
                                Config.audioclickfile = Resources.readstring(data[i]);
                                break;
//                                case "logofile":
//                                Config.logofile = Resources.readstring(data[i]);
//                                break;
//                                case "fogfile":
//                                Config.fogfile = Resources.readstring(data[i]);
//                                break;
//                                case "logowidth":
//                                Config.logowidth = Resources.readint(data[i]);
//                                break;
//                                case "logoheight":
//                                Config.logoheight = Resources.readint(data[i]);
//                                break;
//                                case "fogwidth":
//                                Config.fogwidth = Resources.readint(data[i]);
//                                break;
//                                case "fogheight":
//                                Config.fogheight = Resources.readint(data[i]);
//                                break;
//                                case "record": //13mar2021
//                                if(Resources.readint(data[i])==1)
//                                {
//                                    Config.RECORD = true;
//                                }
//                                break;
                                case "translategui": //21mar2021
                                if(Resources.readstring(data[i])=="1")
                                {
                                    Config.TRANSLATEGUI = true;
                                }
                                if(Resources.readstring(data[i])=="0")
                                {
                                    Config.TRANSLATEGUI = false;
                                }
                                break;
                            
                                case "useunicode": //15mar2021
                                if(Resources.readint(data[i])==1)
                                {
                                    Config.useUNICODE = true;
                                }
                                if(Resources.readint(data[i])==0)
                                {
                                    Config.useUNICODE = false;
                                }
                                break;
                            }
                        }
                    }
                    Config.configfile = altconfigfile;
                }
                catch(Exception e)
                {
                    Console.WriteLine("Error reading language config.txt:"+e.Message);
                    //LocalStorage.WriteLog("Error reading language config.txt:"+e.Message);
                    return;
                }
            }
            if(Config.wordsfile!="")
            {
                Translation.CollectWords();
            }
            //end----------------//13mar2021
        }

///////////////////Method Definition///////////////
        static void init()
        {
            //core window initialisation routine
            RenderList.init(); //13mar2021
            Game.RESOLUTIONX = 1600;
            Game.RESOLUTIONY = 900;
            //start-------------//28Feb2021
            //checkconfig();
            if(!checkconfig())
            {
                return;
            }
            Game.ExtremelySimplePiracyCheck();//27feb2022
            Game.RESOLUTIONX = Config.DEFAULTRESX;//25sep2021
            Game.RESOLUTIONY = Config.DEFAULTRESY;//25sep2021
            
            //end---------------//28Feb2021
            SDL.SDL_SetHint(SDL.SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
            if(SDL.SDL_Init(SDL.SDL_INIT_VIDEO | SDL.SDL_INIT_AUDIO)<0)
            {
                Console.WriteLine("Could Not Initialise Window. Error:"+SDL.SDL_GetError());
                Network.reporterror("WindowOpenFailure",true);//15mar2021
                return;
            }
            var window = IntPtr.Zero;
            switch(Game.FULLSCREEN)
            {
                case 0:
                    //window = SDL.SDL_CreateWindow(Game.TITLE,SDL.SDL_WINDOWPOS_CENTERED,SDL.SDL_WINDOWPOS_CENTERED,Game.RESOLUTIONX,Game.RESOLUTIONY,SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED); //22may2021
                    //window = SDL.SDL_CreateWindow(Game.TITLE,SDL.SDL_WINDOWPOS_CENTERED,SDL.SDL_WINDOWPOS_CENTERED,Game.RESOLUTIONX,Game.RESOLUTIONY,SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE); //22may2021
                    //start---------//22may2021
                    if(Config.WINDOWRESIZE==0)
                    {
                        window = SDL.SDL_CreateWindow(Game.TITLE,SDL.SDL_WINDOWPOS_CENTERED,SDL.SDL_WINDOWPOS_CENTERED,Game.RESOLUTIONX,Game.RESOLUTIONY,SDL.SDL_WindowFlags.SDL_WINDOW_MAXIMIZED); //22may2021
                    }
                    else
                    {
                        window = SDL.SDL_CreateWindow(Game.TITLE,SDL.SDL_WINDOWPOS_CENTERED,SDL.SDL_WINDOWPOS_CENTERED,Game.RESOLUTIONX,Game.RESOLUTIONY,SDL.SDL_WindowFlags.SDL_WINDOW_RESIZABLE); //22may2021
                    }
                    //end----------//22may2021
                break;
                case 1:
                    window = SDL.SDL_CreateWindow(Game.TITLE,SDL.SDL_WINDOWPOS_CENTERED,SDL.SDL_WINDOWPOS_CENTERED,Game.RESOLUTIONX,Game.RESOLUTIONY,SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN);
                break;
            }
            if(window == IntPtr.Zero)
            {
                Console.WriteLine("Could Not Create Window. Error:"+SDL.SDL_GetError());
                Network.reporterror("WindowOpenFailure",true);//15mar2021
                SDL.SDL_Quit();
                return;
            }
            SDL_image.IMG_Init(SDL_image.IMG_InitFlags.IMG_INIT_JPG | SDL_image.IMG_InitFlags.IMG_INIT_PNG);
            SDL_ttf.TTF_Init();
            //
            var renderer = IntPtr.Zero;
            renderer = SDL.SDL_CreateRenderer(window,-1,SDL.SDL_RendererFlags.SDL_RENDERER_ACCELERATED);
            //
            if(SDL_mixer.Mix_Init(SDL_mixer.MIX_InitFlags.MIX_INIT_MP3)<0)
            {
                Console.WriteLine("Could Not Initialise Audio Mixer. Error:"+SDL.SDL_GetError());
                Network.reporterror("MixerOpenFailure",false);//15mar2021
            }
            if(SDL_mixer.Mix_OpenAudio(SDL_mixer.MIX_DEFAULT_FREQUENCY,SDL_mixer.MIX_DEFAULT_FORMAT,8,1024)<0)
            {
                Console.WriteLine("Could Not Open Audio Mixer. Error:"+SDL.SDL_GetError());
                Network.reporterror("MixerOpenFailure",false);//15mar2021
            }
            game(window,renderer);
            LocalStorage.finalise();//12mar2021
            //
            SDL_mixer.Mix_CloseAudio();
            SDL_mixer.Mix_Quit();
            //
            SDL_ttf.TTF_Quit();
            SDL_image.IMG_Quit();
            SDL.SDL_DestroyRenderer(renderer);
            SDL.SDL_DestroyWindow(window);
            SDL.SDL_Quit();
        }

///////////////////Method Definition///////////////
        static void loadprogress(Game game, string txt)
        {
            //not used
            RenderList.drawtext(game,800,400,txt,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
        }

///////////////////Method Definition///////////////
        static void resourceload(Game game)
        {
            //load all resources for the game here
            //call this prior to entering the main game loop
            //Resources.loadingbk = Resources.LoadAnimImage(game,"media/gui/loading.png",game.renderer,648,100,1,1);//27mar2021
            //Resources.loadingbar = Resources.LoadAnimImage(game,"media/gui/loadinglight.png",game.renderer,8,100,81,1);//27mar2021
            Resources.blackcat = Resources.LoadAnimImage(game,"media/gui/black.png",game.renderer,64,64,1,1);
            Resources.LOGO = Resources.LoadAnimImage(game,Config.logofile,game.renderer,Config.logowidth,Config.logoheight,1,1);
            Resources.FOG = Resources.LoadAnimImage(game,Config.fogfile,game.renderer,Config.fogwidth,Config.fogheight,1,1);
            Resources.FONT = Resources.LoadFont(game,Config.defaultfontfile,Config.normalfontsize);
            Game.LoadingPct = 0;
            Resources.SMALLFONT = Resources.LoadFont(game,Config.defaultfontfile,Config.smallfontsize);
            Resources.LARGEFONT = Resources.LoadFont(game,Config.defaultfontfile,Config.largefontsize);
            Game.LoadingProgress(game);
            Resources.LoadGui(game,Config.guifile);
            Game.LoadingProgress(game);
            Resources.LoadTemplates(game,Config.unitsfile);
            Game.LoadingProgress(game);
            Resources.LoadCampaign(game,Config.campaignfile);
            Game.LoadingProgress(game);
            Resources.LoadTech(game,Config.techfile);//2sep2021
            Game.LoadingProgress(game);
            Gui.matchcampaign(game); //28Feb2021
            Resources.CLICK = Resources.LoadAudio(game,Config.audioclickfile,false);
            Resources.AssignOffsets(game,Config.offsetfile);//20apr2021
            Game.LoadingProgress(game);
            Resources.intro = Resources.LoadAnimImage(game,"media/gui/intro.jpg",game.renderer,400,225,10,10);//28feb2022
            Game.LoadingProgress(game);
            Resources.outro = Resources.LoadAnimImage(game,"media/gui/outro.jpg",game.renderer,400,225,7,7);//28feb2022
            Game.LoadingProgress(game);
            Resources.outrobad = Resources.LoadAnimImage(game,"media/gui/outrobad.jpg",game.renderer,3911,900,1,1);//28feb2022
            Game.LoadingProgress(game);
            Resources.page01 = Resources.LoadAnimImage(game,"media/gui/01.jpg",game.renderer,1600,900,1,1);//28feb2022
            Game.LoadingProgress(game);
            Resources.credits = Resources.LoadAnimImage(game,"media/gui/credits.png",game.renderer,1600,900,1,1);//28feb2022
            Game.LoadingProgress(game);
            //Game.clicker = Resources.LoadAnimImage(game,"media/gui/clicker.png",game.renderer,32,32,8,2);//15apr2021
            //Game.targeticon = Resources.LoadAnimImage(game,"media/gui/targeticon.png",game.renderer,64,64,1,1);//16apr2021
            Emitter.pimages = null;//22apr2022
            Game.LoadingProgress(game);
            Emitter.Reset(game);//22apr2022
            Particle.Reset();//22apr2022
            Game.LoadingProgress(game);
        }

        //static void drawloadingbar(Game game,int w,int pct,int offy) //27mar2021
        //{
        //    if(Resources.loadingbk!=-1 && Resources.loadingbar!=-1)
        //    {
        //        int f = (pct * game.images[Resources.loadingbar].cwn) / 100;
        //        for(int i=0;i<f;i++)
        //        {
        //            RenderList.drawanimimage(game,game.images[Resources.loadingbar].texture,Game.RESOLUTIONX/2 - (w/2) + i * game.images[Resources.loadingbar].cwx,offy + Game.RESOLUTIONY/2,0,1,1,i,0,false,1,Resources.loadingbar);
        //        }
        //        RenderList.drawanimimage(game,game.images[Resources.loadingbk].texture,Game.RESOLUTIONX/2,offy + Game.RESOLUTIONY/2,0,1,1,0,0,false,1,Resources.loadingbk);
        //    }
        //}
        
///////////////////Method Definition///////////////
        static void render(Game game,IntPtr window)
        {
            //core render method
            //clears the screen buffer, draws to it, then flips it into view
            SDL.SDL_RenderClear(game.renderer);
            RenderList.render(game);    
            SDL.SDL_RenderPresent(game.renderer);
        }

///////////////////Method Definition///////////////
        static void drawlogo(Game game)
        {
            //draw game logo at start of game
            int fr = game.frame;// - 100;//27mar2021
            float sx = 1f;
            float sy = 1f;
            //27mar2021
            //sx = (0.01f+(float)game.frame / 100f);
            //sy = (0.01f+(float)game.frame / 100f);
            //float alpha = 0.01f + (float)game.frame / 100f;
            sx = (0.01f+(float)fr / 100f);
            sy = (0.01f+(float)fr / 100f);
            float alpha = 0.01f + (float)fr / 100f;
            if(alpha>1)
            {
                alpha = 1f;
            }
            if(sx>1)
            {
                sx = 1f;
            }
            if(sy>1)
            {
                sy = 1f;
            }
            RenderList.drawimage(game,game.images[Resources.LOGO].texture,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,0,1,1,0,0,false,alpha,Resources.LOGO);
            //if(game.frame>180)27mar2021
            if(fr>180)//27mar2021
            {
                game.gamestate=Game.CAT_GAMESTATE_MENU;
                Config.loaded = false;
                Config.loadpct = 0;
                //debugging
                //game.gamestate=Game.CAT_GAMESTATE_INTRO;
                //Game.outroframe = 0;
                //Game.outrodelay = 10;
            }
        }

///////////////////Method Definition///////////////
        public static void drawintro(Game game)//28feb2022
        {
            float alpha = 1f;
            if(Game.outroframe > 86)
            {
                alpha = (float)(96 - Game.outroframe)/10f;
            }
            string txt = Translation.TranslateWord("Transport en-route to Warzone.....",false);
            int l = 1 + ((Game.outroframe * txt.Length) / 70);
            if(l>txt.Length)
            {
                l = txt.Length;
            }
            txt = txt.Substring(0,l);
            RenderList.drawanimimage(game,game.images[Resources.intro].texture,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,0,4,4,Game.outroframe,0,false,alpha,Resources.intro);
            RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 330,txt,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            //RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 410,Translation.TranslateWord("The End",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            Game.outrodelay--;
            if(Game.outrodelay<=0)
            {
                Game.outrodelay = 5;
                Game.outroframe++;
                if(Game.outroframe>96)
                {
                    game.gamestate=Game.CAT_GAMESTATE_GAME;
                    Game.outroframe = 0;
                }
            }
            if(game.mlclick)
            {
                game.gamestate=Game.CAT_GAMESTATE_GAME;
                Game.outroframe = 0;
            }
        }
        
        
///////////////////Method Definition///////////////
        public static void drawoutro(Game game)//28feb2022
        {
            float alpha = 1f;
            if(Game.outroframe > 33)
            {
                alpha = (float)(43 - Game.outroframe)/10f;
            }
            RenderList.drawanimimage(game,game.images[Resources.outro].texture,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,0,4,4,Game.outroframe,0,false,alpha,Resources.outro);
            RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 380,Translation.TranslateWord("You Return Home A Hero From Your Tour Of Duty",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 410,Translation.TranslateWord("The End",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            Game.outrodelay--;
            if(Game.outrodelay<=0)
            {
                Game.outrodelay = 15;
                Game.outroframe++;
                if(Game.outroframe>43)
                {
                    game.gamestate=Game.CAT_GAMESTATE_CREDITS2;
                    Game.outroframe = 0;
                }
            }
            if(game.mlclick)
            {
                game.gamestate=Game.CAT_GAMESTATE_MENU;
                Game.outroframe = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void drawoutrobad(Game game)//28feb2022
        {
            int x = - Game.outroframe;
            if(Game.outroframe > 3911 - 1600)
            {
                x = - (3911 - 1600);
            }
            RenderList.drawanimimage(game,game.images[Resources.outrobad].texture,x + (3911/2),Game.RESOLUTIONY/2,0,1,1,0,0,false,1,Resources.outrobad);
            RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 380,Translation.TranslateWord("You were killed in the line of duty. There was a small but loving funeral.",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2 + 410,Translation.TranslateWord("The End",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
            {
                Game.outroframe++;
                if(Game.outroframe>3911 - 1600 + 60*5)
                {
                    game.gamestate=Game.CAT_GAMESTATE_CREDITS2;
                    Game.outroframe = 0;
                }
            }
            if(game.mlclick)
            {
                game.gamestate=Game.CAT_GAMESTATE_MENU;
                Game.outroframe = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void drawcredits(Game game)//28feb2022
        {
            RenderList.drawanimimage(game,game.images[Resources.page01].texture,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,0,1,1,0,0,false,1,Resources.page01);
            RenderList.drawanimimage(game,game.images[Resources.credits].texture,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,0,1,1,0,0,false,1,Resources.credits);
            {
                Game.outroframe++;
                if(Game.outroframe>60*10)
                {
                    game.gamestate=Game.CAT_GAMESTATE_MENU;
                    Game.outroframe = 0;
                }
            }
            if(game.mlclick)
            {
                game.gamestate=Game.CAT_GAMESTATE_MENU;
                Game.outroframe = 0;
            }
        }



        
///////////////////Method Definition///////////////
        public static void skirmishmission(Game game)
        {
            //setup the skirmish mission settings
            /////////////////////////////
            //unit positions and types..
                    Game.fogoff = 0; //26Feb2021
                    Game.neutralfog = 0; //26Feb2021
                    Game.LOCKCORNER = 0;//1mar2021
                    game.skirmish = true;
                    game.zoom = 0;
                    game.mwheel = 0;
                    game.playingtutorial = false;
                    game.victorymessage = true;
                    cleardeaths(game);
                    int id = 0;
                    int tmpid = -1;
                    int jjj = - 1;
                    for(int i=0;i<Unit.MAXUNITS;i++)
                    {
                        game.units[i] = new Unit(game);
                    }
                    //remove some of the woods, rocks and walls
                    for(int i=0;i<Map.treeimage.Length;i++)
                    {
                        if(Functions.rand(0,1000)<750)
                        {
                            Map.treeimage[i] = -1;
                        }
                    }
                    for(int i=0;i<Map.rockimage.Length;i++)
                    {
                        if(Functions.rand(0,1000)<750)
                        {
                            Map.rockimage[i] = -1;
                        }
                    }
                    for(int i=0;i<Map.wallimage.Length;i++)
                    {
                        if(Functions.rand(0,1000)<750)
                        {
                            Map.wallimage[i] = -1;
                        }
                    }
                    //setup control points
                    int cpoint = (4 + (Functions.rand(0,1000) % 10));
                    for(int i=0;i<cpoint;i++)
                    {
                        int xx = (int)Functions.rand(0,10000) % Map.MAXX;
                        int yy = (int)Functions.rand(0,10000) % Map.MAXY;
                        if(xx>=0 && yy>=0 && xx<Map.MAXX && yy<Map.MAXY)
                        {
                            for(int j=0;j<game.templates.Length;j++)
                            {
                                if(game.templates[j].controlpoint==1)
                                {
                                    jjj++;
                                    game.units[jjj].createunitatxy(game,jjj,game.templates[j],xx * Map.GRIDW,yy * Map.GRIDH);
                                    break;
                                }
                            }
                        }
                    }
                    int maxj = 10;
                    for(int y=80;y<95;y++)
                    {
                        for(int i=0;i<game.templates.Length;i++)
                        {
                            if(game.templates[i].faction==Game.PLAYERFACTION)
                            {
                                if(game.templates[i].walkspeed>0)
                                {
                                    id++;
                                }
                            }
                        }
                        if(id>0)
                        {
                            id = 1 + (Functions.rand(1,1000) % id);
                            for(int i=0;i<game.templates.Length;i++)
                            {
                                if(game.templates[i].faction==Game.PLAYERFACTION)
                                {
                                    if(game.templates[i].walkspeed>0)
                                    {
                                        id--;
                                        if(id<=0)
                                        {
                                            tmpid = i;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if(tmpid>=0)
                        {
                            for(int x=40;x<60;x++)
                            {
                                Map.treeimage[x + y * Map.MAXX] = -1;
                                Map.rockimage[x + y * Map.MAXX] = -1;
                                Map.wallimage[x + y * Map.MAXX] = -1;
                                if(Functions.rand(0,100)<20 && Map.passable(x * Map.GRIDW, y * Map.GRIDH)==true && maxj>0)
                                {
                                    jjj++;
                                    if(jjj<game.units.Length)
                                    {
                                        game.units[jjj].createunitatxy(game,jjj,game.templates[tmpid],x * Map.GRIDW,y * Map.GRIDH);
                                        game.units[jjj].orderframe = 300;
                                        Game.CORNERX = game.units[jjj].x - Game.RESOLUTIONX/2;
                                        Game.CORNERY = game.units[jjj].y - Game.RESOLUTIONY/2;
                                        maxj--;
                                    }
                                }
                            }
                        }
                    }
                    maxj = 10;
                    //enemy units
                    for(int y=5;y<20;y++)
                    {
                        for(int i=0;i<game.templates.Length;i++)
                        {
                            if(game.templates[i].faction!=Game.PLAYERFACTION && game.templates[i].faction!=Unit.NULLFACTION)
                            {
                                if(game.templates[i].walkspeed>0)
                                {
                                    id++;
                                }
                            }
                        }
                        if(id>0)
                        {
                            id = 1 + (Functions.rand(1,1000) % id);
                            for(int i=0;i<game.templates.Length;i++)
                            {
                                if(game.templates[i].faction!=Game.PLAYERFACTION && game.templates[i].faction!=Unit.NULLFACTION)
                                {
                                    if(game.templates[i].walkspeed>0)
                                    {
                                        id--;
                                        if(id<=0)
                                        {
                                            tmpid = i;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        if(tmpid>=0)
                        {
                            int aa = Functions.rand(10,79);
                            int bb = aa + 20;
                            for(int x=aa;x<bb;x++)
                            {
                                Map.treeimage[x + y * Map.MAXX] = -1;
                                Map.rockimage[x + y * Map.MAXX] = -1;
                                Map.wallimage[x + y * Map.MAXX] = -1;
                                if(Functions.rand(0,100)<20 && jjj<game.units.Length && Map.passable(x * Map.GRIDW, y * Map.GRIDH)==true && maxj>0)
                                {
                                    game.units[jjj].createunitatxy(game,jjj,game.templates[tmpid],x * Map.GRIDW,y * Map.GRIDH);
                                    game.units[jjj].ai = Unit.AI_EXTRAASSAULT;
                                    game.units[jjj].orderframe = 300;
                                    jjj++;
                                    maxj--;
                                }
                            }
                        }
                    }
                    //copy the triggers.....
                    for(int i=0;i<game.triggers.Length;i++)
                    {
                        game.triggers[i] = new Trigger();
                    }
                    Trigger.number = 0;
                    id = 0;
                    bool found = false;
                    for(int i=0;i<game.templates.Length;i++)
                    {
                        if(game.templates[i].faction==Game.PLAYERFACTION && game.templates[i].walkspeed>0 && game.templates[i].faction!=Unit.NULLFACTION)
                        {
                            string enemyunitname = game.templates[i].name;
                            found = false;
                            for(int j=0;j<game.units.Length;j++)
                            {
                                if(game.units[j].name==enemyunitname && game.units[j].hp>0)
                                {
                                    found = true;
                                }
                            }
                            if(found)
                            {
                                game.triggers[id] = new Trigger(game,Trigger.TYPE_OR_DEFEAT,0,0,enemyunitname,0 ,0,100, 100);
                                id++;                        
                            }
                        }
                        if(game.templates[i].faction!=Game.PLAYERFACTION && game.templates[i].walkspeed>0 && game.templates[i].faction!=Unit.NULLFACTION)
                        {
                            string unitname = game.templates[i].name;
                            found = false;
                            for(int j=0;j<game.units.Length;j++)
                            {
                                if(game.units[j].name==unitname && game.units[j].hp>0)
                                {
                                    found = true;
                                }
                            }
                            if(found)
                            {
                                game.triggers[id] = new Trigger(game,Trigger.TYPE_VICTORY,0,0,unitname,0 ,0,100, 100);
                                id++;
                            }
                        }
                    }
                    game.triggers[id] = new Trigger(game,Trigger.TYPE_CHATTER,((int)Functions.rand(0,1000)%20),1,Config.skirmishmessage,300,780,0,0);
                    Game.GAMEENDSTATE = 0;
                    game.gameovertime = 0;
                    game.paused = false;
        }

///////////////////Method Definition///////////////
        public static void testdebrief(Game game)
        {
            //debugging only
            for(int i=0;i<game.templates.Length;i++)
            {
                game.templates[i].prevdeaths = (int) Functions.rand(10,100);
                game.templates[i].prevkills = (int) Functions.rand(10,100);
                game.templates[i].prevcreates = (int) Functions.rand(10,100);
                game.templates[i].deaths = 0;
                game.templates[i].kills = 0;
                game.templates[i].creates = 0;
                game.templates[i].dispcreates = 0;
                game.templates[i].dispdeaths = 0;
                game.templates[i].dispkills = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void cleardeaths(Game game)
        {
            //clear all deaths and counts before and after a mission starts - a reset procedure
            for(int i=0;i<game.templates.Length;i++)
            {
                game.templates[i].prevdeaths = game.templates[i].deaths;
                game.templates[i].prevkills = game.templates[i].kills;
                game.templates[i].prevcreates = game.templates[i].creates;
                game.templates[i].deaths = 0;
                game.templates[i].kills = 0;
                game.templates[i].creates = 0;
                game.templates[i].dispcreates = 0;
                game.templates[i].dispdeaths = 0;
                game.templates[i].dispkills = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void setupeditor(Game game)
        {
            //setup the editor for first use
            //clear the trees etc from the map
            for(int i=0;i<Map.treeimage.Length;i++)
            {
                Map.treeimage[i] = -1;
                Map.decorimage[i] = -1; //2mar2021
            }
            for(int i=0;i<Map.rockimage.Length;i++)
            {
                Map.rockimage[i] = -1;
            }
            for(int i=0;i<Map.wallimage.Length;i++)
            {
                Map.wallimage[i] = -1;
            }
            for(int i=0;i<Unit.MAXUNITS;i++)
            {
                game.units[i] = new Unit(game);
            }
            for(int i=0;i<game.triggers.Length;i++)
            {
                game.triggers[i] = new Trigger();
            }
            Functions.saveseed(Functions.seed);
            game.zoom = 0;
            game.mwheel = 0;
            game.playerready = false;
            game.playingtutorial = false;
            game.skirmish = false;
            game.victorymessage = false;
            cleardeaths(game);
            game.playingtutorial = false;
            Game.GAMEENDSTATE = 0;
            game.gameovertime = 0;
            game.paused = false;
            Map.adddecor();//2mar2021
            Map.marktreepos(game);
            game.nextmissionid = -1;
            game.failedmissionid = -1;
            Game.fogoff = 0; //26Feb2021
            Game.neutralfog = 0; //26Feb2021
            Game.LOCKCORNER = 0;//1mar2021
        }

///////////////////Method Definition///////////////
        public static void setupbackdrop(Game game)
        {
            //setup the backdrop for the game window
            //to display a demo screen
            //of some sort based on a game mission cinematic or such
            int mission = 0;
            for(int i=0;i<game.missions.Length;i++)
            {
                if(game.missions[i].demo>0)
                {
                    mission = i;
                    break;
                }
            }
            setupmission(game,mission,1);
            game.playingtutorial = false;
        }

///////////////////Method Definition///////////////
        public static void setupmission(Game game,int mission,int tutorial)
        {
            //apply all mission settings prior to starting the mission
            //start--------//17sep2021
            Game.EXITPRESSED = 0;//1mar2022
            
            //start------//4mar2022
            Config.Season = Functions.rand(1,100) % 3;
            if(Config.Season<0)
            {
                Config.Season*=-1;
                Config.Season%=3;
            }
            //end-------//4mar2022
            bool minimap = false;
            if(tutorial==99)
            {
                minimap = true;
                tutorial = 2;
            }
            //end----------//17sep2021
            MapThread.complete = false;//29may2021
            if(!Replay.PLAYBACK)//2apr2021
            {
                game.gamestartframe = game.frame;//2apr2021
            }
            Tech.resetall(game);//2sep2021
            if(mission==1)//24sep2021
            {
                Tech.unpurchase(game);
            }
            Config.precalcused = 0;
            Config.seekpathfailed = 0;
            Config.seekpathsuccess = 0;
            Config.seekpathused = 0;
            Game.fogoff = 0; //26Feb2021
            Game.neutralfog = 0; //26Feb2021
            Game.LOCKCORNER = 0; //1mar2021
            game.zoom = 0;
            game.mwheel = 0;
            game.playerready = false;
            game.playingtutorial = false;
            game.skirmish = false;
            game.victorymessage = false;
            cleardeaths(game);
            string folder = "";
            try
            {
                folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"/"+Game.NETTITLE;
                if(!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }
            }
            catch(Exception e)
            {
                string message = e.Message;
            }
            if(mission<0 && mission!=-999 && tutorial==0)
            {
                try
                {
                    string[] savegame = System.IO.File.ReadAllLines(folder+"/"+"savegame.txt");
                    if(savegame.Length>0)
                    {
                        Int32.TryParse(savegame[0],out mission);
                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
            if(mission<0 && mission!=-999 && tutorial==0)
            {
                mission = 0;
            }
            if(mission>0 && mission!=-999 && tutorial==0 && tutorial!=2)
            {
                if(mission>Game.maxmission)
                {
                    Game.maxmission = mission;
                    try
                    {
                        System.IO.File.WriteAllText(folder+"/"+"savegame.txt",""+mission);
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
            }
            if(game.missions.Length>0 && mission!=-999)
            {
                if(mission>=0 && mission<game.missions.Length)
                {
                    //map layout...
                    if(game.missions[mission].istutorial>0)
                    {
                        game.playingtutorial = true;
                    }
                    game.missionid = mission;
                    Map.loadpath(mission); //try and get the precalced path.....
                    game.nextmissionid = game.missions[mission].nextmissionid;
                    game.failedmissionid = game.missions[mission].failedmissionid;
                    //start--------------//1mar2021
                    if(game.missions[mission].nextmissionname!="")
                    {
                        for(int mi=0;mi<game.missions.Length;mi++)
                        {
                            if(game.missions[mi].name==game.missions[mission].nextmissionname)
                            {
                                game.nextmissionid = mi;
                                break;
                            }
                        }
                    }
                    if(game.missions[mission].failedmissionname!="")
                    {
                        for(int mi=0;mi<game.missions.Length;mi++)
                        {
                            if(game.missions[mi].name==game.missions[mission].failedmissionname)
                            {
                                game.failedmissionid = mi;
                                break;
                            }
                        }
                    }
                    //start--------------//10sep2021
                    Map.GRIDW = game.missions[mission].gridw;
                    Map.GRIDH = game.missions[mission].gridh;
                    //start--------------//18sep2021
                    Map.FOGW = (160 * Map.GRIDW) / 32;
                    Map.FOGH = (160 * Map.GRIDH) / 32;
                    Map.FOGSCALE = (float)Map.GRIDW / 32f;
                    if(Map.FOGSCALE<=0)
                    {
                        Map.FOGSCALE = 1f;
                    }
                    //end----------------//18sep2021
                    //end----------------//10sep2021
                    //end----------------//1mar2021
                    Map.indoor = game.missions[mission].indoor;//23sep2021
                    Game.CORNERX = game.missions[mission].cornerx;
                    Game.CORNERY = game.missions[mission].cornery;
                    Game.fogoff = Functions.sign(game.missions[mission].fogoff); //26Feb2021
                    Game.neutralfog = Functions.sign(game.missions[mission].neutralfog); //26Feb2021
                    Game.LOCKCORNER = game.missions[mission].lockcorner; //1mar2021
                    //4apr2021 added network command in here
                    //
                    //if(game.missions[mission].name!="demo") //5apr2021//17sep2021
                    if(game.missions[mission].name!="demo" && minimap==false) //5apr2021//17sep2021
                    {
                        try
                        {
                            Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=kog2mission&event="+game.missions[mission].name.Replace(" ","_")+"&value=1&uid="+Config.uid;//30mar2021
                            Network.httpget(Network.url);
                        }
                        catch(Exception e)
                        {
                            string message = e.Message;
                        }
                    }
                    //
                    //
                    //start-------------//28Feb2021
                    Game.PLAYERFACTION = game.missions[mission].playerfaction;
                    Game.SKIRMISHENEMYFACTION = game.missions[mission].skirmishenemyfaction;
                    //end---------------//28Feb2021
                    if(game.missions[mission].skirmish==1)
                    {
                        game.skirmish = true;
                    }
                    for(int i=0;i<Map.treeimage.Length;i++)
                    {
                        Map.treeimage[i] = -1;
                        Map.decorimage[i] = -1; //2mar2021
                    }
                    for(int i=0;i<Map.rockimage.Length;i++)
                    {
                        Map.rockimage[i] = -1;
                    }
                    for(int i=0;i<Map.wallimage.Length;i++)
                    {
                        Map.wallimage[i] = -1;
                    }
                    //start--------------//2mar2021
                    Map.odecorframes = Map.decorframes;//15mar2021
                    Map.decorframes = game.missions[mission].decorframes;//15mar2021
                    if(game.missions[mission].decorimage!=null)//17sep2021
                    if(game.missions[mission].decorimage!=null && minimap==false)//17sep2021
                    {
                        for(int i=0;i<game.missions[mission].decorimage.Length;i++)
                        {
                            if(game.missions[mission].decorframes > 0) //26oct2020
                            {
                                Map.decorimage[game.missions[mission].decorimage[i]] = Functions.rand(0,1000) % game.missions[mission].decorframes;//8;
                            }
                            else
                            {
                                if(Map.decorframes>0)//19sep2021 bugfix
                                {
                                    Map.decorimage[game.missions[mission].decorimage[i]] = Functions.rand(0,1000) % Map.decorframes;//8;
                                }
                            }
                            //Console.WriteLine("Index:"+game.missions[mission].treeimage[i]+ " Value:"+Map.treeimage[game.missions[mission].treeimage[i]]);
                        }
                    }
                    //end----------------//2mar2021
                    Map.missiontreeframes = Map.treeframes;//28mar2021
                    if(game.missions[mission].treeimage!=null)
                    {
                        for(int i=0;i<game.missions[mission].treeimage.Length;i++)
                        {
                            if(game.missions[mission].treeframes > 0) //26oct2020
                            {
                                Map.treeimage[game.missions[mission].treeimage[i]] = Functions.rand(0,1000) % game.missions[mission].treeframes;//8;
                                Map.missiontreeframes = game.missions[mission].treeframes;
                            }
                            else
                            {
                                Map.treeimage[game.missions[mission].treeimage[i]] = Functions.rand(0,1000) % Map.treeframes;//8;
                            }
                            //Console.WriteLine("Index:"+game.missions[mission].treeimage[i]+ " Value:"+Map.treeimage[game.missions[mission].treeimage[i]]);
                        }
                    }
                    if(game.missions[mission].rockimage!=null)
                    {
                        for(int i=0;i<game.missions[mission].rockimage.Length;i++)
                        {
                            if(game.missions[mission].rockframes > 0) //26oct2020
                            {
                                Map.rockimage[game.missions[mission].rockimage[i]] = Functions.rand(0,1000) % game.missions[mission].rockframes;//4;
                            }
                            else
                            {                        
                                Map.rockimage[game.missions[mission].rockimage[i]] = Functions.rand(0,1000) % Map.rockframes;//4;
                            }
                        }
                    }
                    if(game.missions[mission].wallimage!=null)
                    {
                        for(int i=0;i<game.missions[mission].wallimage.Length;i++)
                        {
                            if(game.missions[mission].wallframes> 0) //26oct2020
                            {
                                Map.wallimage[game.missions[mission].wallimage[i]] = Functions.rand(0,1000) % game.missions[mission].wallframes;//;
                            }
                            else
                            {
                                Map.wallimage[game.missions[mission].wallimage[i]] = Functions.rand(0,1000) % Map.wallframes;//;
                            }
                        }
                    }
                    //start--------//16sep2021
                    //if(game.missions[mission].floorpattern>0)//17sep2021
                    if(game.missions[mission].floorpattern>0 && minimap==false)//17sep2021
                    {
                        int mainfloor = 0;//25sep2021
                        int secondaryfloor = 0;//25sep2021
                        int thirdfloor = 0;//25sep2021
                        bool other = false;//25sep2021
                        int its = 0;
                        int row1 = 0;
                        int row2 = 0;
                        int row3 = 0;
                        int[] assigned = new int[Map.MAXX * Map.MAXY];
                        if(game.missions[mission].floorpattern==2 && Map.tileframes>4)//25sep2021
                        {
                            for(int x=1;x<Map.MAXX - 1;x++)
                            {
                                for(int y=1;y<Map.MAXY - 1;y++)
                                {
                                    if(assigned[x + y * Map.MAXX]==1)
                                    {
                                        continue;
                                    }
                                    if((x % 8==0 && y % 8==0) || (x==1 && y==1))
                                    {
                                        row1 = Functions.rand(0,1000) % (Map.tileframes / 4);
                                        row2 = Functions.rand(0,1000) % (Map.tileframes / 4);
                                        row3 = Functions.rand(0,1000) % (Map.tileframes / 4);
                                        mainfloor = row1 * 4 + (Functions.rand(0,1000) % 3);//25sep2021
                                        secondaryfloor = row2 * 4 + (Functions.rand(0,1000) % 3);//25sep2021
                                        thirdfloor = row3 * 4 + (Functions.rand(0,1000) % 3);//25sep2021
                                        
                                        if(mainfloor<0)
                                        {
                                            mainfloor = 0;
                                        }
                                        if(secondaryfloor<0)
                                        {
                                            secondaryfloor = 0;
                                        }
                                        if(thirdfloor<0)
                                        {
                                            thirdfloor = 0;
                                        }
                                        its = 0;
                                        while(secondaryfloor == mainfloor || secondaryfloor<0)
                                        {
                                            its++;
                                            secondaryfloor = Functions.rand(0,1000) % Map.tileframes;//25sep2021
                                            if(its>100)
                                            {
                                                break;
                                            }
                                        }
                                        its = 0;
                                        while(thirdfloor == mainfloor || thirdfloor<0 || thirdfloor == secondaryfloor)
                                        {
                                            its++;
                                            thirdfloor = Functions.rand(0,1000) % Map.tileframes;//25sep2021
                                            if(its>100)
                                            {
                                                break;
                                            }
                                        }
                                    }
                                    Map.tileimage[x + y * Map.MAXX] = mainfloor;
                                    if(Map.wallimage[x + y * Map.MAXX] != -1)
                                    {
                                        for(int ix=x-1;ix<x+2;ix++)
                                        {
                                            for(int iy=y-1;iy<y+2;iy++)
                                            {
                                                if(ix>=0 && iy>=0 && ix<Map.MAXX - 1 && iy<Map.MAXY -1)
                                                {
                                                    if(assigned[ix + iy * Map.MAXX]==0)
                                                    {
                                                        Map.tileimage[ix + iy * Map.MAXX] = thirdfloor;
                                                        assigned[ix + iy * Map.MAXX] = 1;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    if(x % 8 == 0 && y % 8 == 0)
                                    {
                                        if(x>4 && y>4 && x<Map.MAXX - 4 && y < Map.MAXY - 4)
                                        {
                                            for(int ix=x-1;ix<x+2;ix++)
                                            {
                                                for(int iy=y-1;iy<y+2;iy++)
                                                {
                                                    if(assigned[ix + iy * Map.MAXX]==0 && (Map.wallimage[(ix - 2) + iy * Map.MAXX]!=-1 || Map.wallimage[(ix + 1) + iy * Map.MAXX]!=-1))
                                                    {
                                                        Map.tileimage[ix + iy * Map.MAXX] = secondaryfloor;
                                                        assigned[ix + iy * Map.MAXX] = 1;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            for(int x=0;x<Map.MAXX - 1;x++)
                            {
                                for(int y=0;y<Map.MAXY - 1;y++)
                                {
                                    if(assigned[x + y * Map.MAXX]==0)
                                    {
                                        Map.tileimage[x + y * Map.MAXX] = mainfloor;
                                    }
                                }
                            }
                        }
                        if(game.missions[mission].floorpattern==1 && Map.tileframes>3)
                        {
                            mainfloor = Functions.rand(0,1000) % 3;//25sep2021
                            secondaryfloor = Functions.rand(0,1000) % 3;//25sep2021
                            if(mainfloor<0)
                            {
                                mainfloor = 0;
                            }
                            if(secondaryfloor<0)
                            {
                                secondaryfloor = 0;
                                if(secondaryfloor == mainfloor)
                                {
                                    secondaryfloor = 1;
                                }
                            }
                            for(int a=0;a<10;a++)
                            {
                                if(secondaryfloor==mainfloor)
                                {
                                    secondaryfloor = Functions.rand(0,1000) % 3;
                                }
                                else
                                {
                                    break;
                                }
                            }
                            thirdfloor = 0;//25sep2021
                            if(mainfloor==0 || secondaryfloor==0)
                            {
                                thirdfloor = 1;
                            }
                            if(mainfloor==1 || secondaryfloor==1)
                            {
                                thirdfloor = 2;
                            }
                            
                            for(int x=1;x<Map.MAXX-1;x++)
                            {
                                for(int y=1;y<Map.MAXY-1;y++)
                                {
                                    Map.tileimage[x + y * Map.MAXX] = mainfloor;
                                    if(Map.wallimage[x + y * Map.MAXX]!=-1)
                                    {
                                        Map.tileimage[(x) + (y) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x - 1) + (y) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x + 1) + (y) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x) + (y - 1) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x - 1) + (y - 1) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x + 1) + (y - 1) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x) + (y + 1) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x - 1) + (y + 1) * Map.MAXX] = secondaryfloor;
                                        Map.tileimage[(x + 1) + (y + 1) * Map.MAXX] = secondaryfloor;
                                    }
                                }
                            }
                            for(int x=3;x<Map.MAXX-3;x++)
                            {
                                for(int y=3;y<Map.MAXY-3;y++)
                                {
                                    if(Map.tileimage[x + y * Map.MAXX]==mainfloor)
                                    {
                                        other = false;
                                        for(int xx=x-1;xx<=x+1;xx++)
                                        {
                                            for(int yy=y-1;yy<=y+1;yy++)
                                            {
                                                if(Map.tileimage[xx + yy * Map.MAXX]==secondaryfloor)
                                                {
                                                    other = true;
                                                    break;
                                                }
                                            }
                                            if(other)
                                            {
                                                break;
                                            }
                                        }
                                        if(!other)
                                        {
                                            Map.tileimage[x + y * Map.MAXX] = thirdfloor;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    //end----------//16sep2021
                    if(game.missions[mission].mapgen>0)
                    {
                        Functions.saveseed(game.missions[mission].seed);
                        Map.generate(game);
                        Functions.restoreseed();
                    }
                    //unit positions and types..
                    for(int i=0;i<Unit.MAXUNITS;i++)
                    {
                        game.units[i] = new Unit(game);
                    }
                    if(game.missions[mission].units!=null)
                    {
                        for(int i=0;i<game.missions[mission].units.Length;i++)
                        {
                            if(i>=Unit.MAXUNITS)
                            {
                                continue;
                            }
                            for(int j=0;j<game.templates.Length;j++)
                            {
                                if(game.templates[j].name==game.missions[mission].units[i].name)
                                {
                                    game.units[i].createunitatxy(game,i,game.templates[j],game.missions[mission].units[i].x,game.missions[mission].units[i].y);
                                    game.units[i].ai = game.missions[mission].ai;
                                    //start---------------------//10sep2021
                                    game.units[i].charactername = game.missions[mission].units[i].charactername; //is going to be either "" or have a value.
                                    game.units[i].displaycharactername = game.missions[mission].units[i].displaycharactername;
                                    //end-----------------------//10sep2021
                                    if(game.units[i].faction!=Game.PLAYERFACTION)
                                    {
                                        game.victorymessage = true;
                                        if(game.missions[mission].demo>0)
                                        {
                                            if(game.units[i].faction!=Unit.HUMAN)
                                            {
                                                game.units[i].hp=0;
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    //copy the triggers.....
                    for(int i=0;i<game.triggers.Length;i++)
                    {
                        game.triggers[i] = new Trigger();
                    }
                    //start-----------27dec2021
                    for(int i=0;i<Trigger.VARIABLE.Length;i++)
                    {
                        Trigger.VARIABLE[i] = 0;
                    }
                    Trigger.tmpMilliSeconds = 0;//23feb2022
                    Trigger.ElapsedMilliSeconds = 0;//23feb2022
                    Trigger.TTimer.Reset();
                    //end-------------27dec2021
                    Trigger.number = 0;
                    if(game.missions[mission].triggers!=null)
                    {
                        for(int i=0;i<game.missions[mission].triggers.Length;i++)
                        {
                            if(i>=game.triggers.Length)
                            {
                                continue;
                            }
                            game.triggers[i] = new Trigger(game,game.missions[mission].triggers[i].type,game.missions[mission].triggers[i].comparator,game.missions[mission].triggers[i].n,game.missions[mission].triggers[i].unitname,game.missions[mission].triggers[i].x , game.missions[mission].triggers[i].y, game.missions[mission].triggers[i].fx, game.missions[mission].triggers[i].fy);
                        }
                    }
                    if(game.missions[mission].campfirex!=-1)
                    {
                        Map.setonfire(game.missions[mission].campfirex,game.missions[mission].campfirey,true);
                    }
                    Game.GAMEENDSTATE = 0;
                    game.gameovertime = 0;
                    game.paused = false;
                    Map.adddecor();//2mar2021
                    Map.marktreepos(game);
                }
            }
        }

///////////////////Method Definition///////////////
        public static void resetlevel(Game game)
        {
            //reset procedure
            //temporary
            Game.GAMEENDSTATE = 0;
            game.gameovertime = 0;
            game.zoom = 1;
            //start--------//2apr2021
            game.gibbet = new Gibbet[Gibbet.MAXGIBBET];
            for(int i=0;i<Gibbet.MAXGIBBET;i++)
            {
                game.gibbet[i] = new Gibbet();
            }
            //end----------//2apr2021
            game.blood = new Blood[Blood.MAXBLOOD];
            for(int i=0;i<Blood.MAXBLOOD;i++)
            {
                game.blood[i] = new Blood();
            }
            game.bullets = new Bullet[Bullet.MAXBULLET];
            for(int i=0;i<Bullet.MAXBULLET;i++)
            {
                game.bullets[i] = new Bullet();
            }
            Bullet.nextfree = 0;
            game.units = new Unit[Unit.MAXUNITS];
            for(int i=0;i<game.units.Length;i++)
            {
                game.units[i] = new Unit(game);
                game.units[i].createunitatxy(game,i,game.templates[0],Functions.rand(100,Game.RESOLUTIONX-100),Functions.rand(100,Game.RESOLUTIONY-100));
                game.units[i].hp-=Functions.rand(5,55);
            }
            Game.CORNERX = 0;
            Game.CORNERY = 0;
            game.triggers = new Trigger[Trigger.MAXTRIGGER];
            for(int i=0;i<Trigger.MAXTRIGGER;i++)
            {
                game.triggers[i] = new Trigger();
            }
        }

///////////////////Method Definition///////////////
        public static void resetgame(Game game)
        {
            //reset procedure
            //RTS
            //temporary
            game.map = new Map();
            game.zoom = 1f;
            Game.killcount = 0;
            game.gibbet = new Gibbet[Gibbet.MAXGIBBET];//2apr2021
            //start--------------------//2apr2021
            Gibbet.MAXINDEX = 0;
            //Blood.MAXINDEX = 0;
            Bullet.MAXINDEX = 0;
            Bullet.nextfree = 0;
            Unit.MAXINDEX = 0;
            //end----------------------//2apr2021
            for(int i=0;i<Gibbet.MAXGIBBET;i++)
            {
                game.gibbet[i] = new Gibbet();
            }
            
            game.blood = new Blood[Blood.MAXBLOOD];
            for(int i=0;i<Blood.MAXBLOOD;i++)
            {
                game.blood[i] = new Blood();
            }
            game.bullets = new Bullet[Bullet.MAXBULLET];
            for(int i=0;i<Bullet.MAXBULLET;i++)
            {
                game.bullets[i] = new Bullet();
            }
            game.triggers = new Trigger[Trigger.MAXTRIGGER];
            for(int i=0;i<Trigger.MAXTRIGGER;i++)
            {
                game.triggers[i] = new Trigger();
            }
            Map.generate(game);
            //game.templates = new Unit[1];
            //game.templates[0] = new Unit(game);
            //game.templates[0].reset(game,0);
            //Unit.debugtemplate(game.templates[0]);
            game.units = new Unit[Unit.MAXUNITS];
            for(int i=0;i<game.units.Length;i++)
            {
                game.units[i] = new Unit(game);
                game.units[i].createunitatxy(game,i,game.templates[0],Functions.rand(100,Game.RESOLUTIONX-100),Functions.rand(100,Game.RESOLUTIONY-100));
                game.units[i].hp-=Functions.rand(5,55);
            }
            Game.GAMEENDSTATE = 0;
            game.gameovertime = 0;
        }

///////////////////Method Definition///////////////
        static void resetunits(Game game)
        {
            //not used
        }

///////////////////Method Definition///////////////
        static void guimenus(Game game)
        {
            //manage the gui
            RenderList.IGNOREZOOM = true;
            if(game.mlclick || game.mrclick) //15apr2021
            {
                if(game.gamestate==Game.CAT_GAMESTATE_GAME)
                {
                    Game.clickerframe = 0;
                    Game.clickerx = game.mx;
                    Game.clickery = game.my;
                }
            }
            int gstate = game.gamestate;//30apr2021
            Gui.updateall(game);
            Gui.drawall(game);
            if(gstate!=game.gamestate)//30apr2021
            {
                Gui.updatealtimages(game);
            }
            if(Game.togglepause)//12apr2021
            {
                RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY - 100,Translation.TranslateWord("Paused",false),RenderList.getrgb(255,255,200),game.fonts[Resources.LARGEFONT].font,true);
            }
            if(game.gamestate!=Game.CAT_GAMESTATE_GAME && game.gamestate!=Game.CAT_GAMESTATE_REPLAY)//3jun2021
            {
                RenderList.drawtext(game,0,Game.RESOLUTIONY - 20,Translation.TranslateWord("Ver:",false)+Game.VERSIONSTR,RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);//3jun2021
            }
            //if(Game.clicker!=-1)//15apr2021//17apr2021 commented out and removed inside part.
            //{
            //}
            //start------//24feb2022
            if(Config.useseasons>0 && Config.Night>0)// && (game.gamestate==Game.CAT_GAMESTATE_GAME || game.gamestate==Game.CAT_GAMESTATE_REPLAY))
            {
                RenderList.drawtext(game,1380,Game.RESOLUTIONY - 20,Translation.TranslateWord("Night Battles Currently",false),RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);//3jun2021
            }
            //end--------//24feb2022
            if(Game.targeticon!=-1)//16apr2021
            {
                if(Game.mouseoverunitid!=-1)
                {
                    if(Game.anyselected)
                    {
                        int i = Game.mouseoverunitid;
                        if(game.units[i].faction==Game.SKIRMISHENEMYFACTION && game.units[i].hp>0)
                        {
                            //draw the target icon......
                            float ss = 0.2f*(float)Math.Sin((float)game.frame/20f);
                            RenderList.drawanimimage(game,game.images[Game.targeticon].texture,game.mx,game.my,0,0.4f+ss,0.4f+ss,0,0,false,1f,Game.targeticon);
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        static void basemenus(Game game)
        {
            //part of core update loop
            if(game.gamestate==Game.CAT_GAMESTATE_MENU)
            {
                game.skirmish = false;
                Config.loaded = true;
                if(game.mlclick==true || game.frame>5)
                {
                    if(Config.loaded)
                    {
                        game.gamestate=Game.CAT_GAMESTATE_NEWCONTINUE;
                    }
                    if(Config.TESTDEBRIEF)
                    {
                        game.gamestate=Game.CAT_GAMESTATE_DEBRIEF2;
                        testdebrief(game);
                    }
                    //Audios.playsound(game.audios[Resources.CAT_AUDIO_CLICK],1f);
                    //level = Game.LEVEL1;
                }
                /*
                if(!Config.loaded)
                {
                    if((game.frame % 20)==0)
                    {
                        Config.loadpct+=(int)Functions.rand(5,25);
                    }
                    if(Config.loadpct>100)
                    {
                        Config.loaded = true;
                        Config.loadpct = 100;
                    }
                    RenderList.drawtext(game,800,800,"Loading..."+Config.loadpct+"%",RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
                }
                *
/
                return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_NEWCONTINUE)
            {
                    resetgame(game);
                    //Audios.playsound(game.audios[Resources.CAT_AUDIO_CLICK],1f);
                    //level = Game.LEVEL1;
                    //newlevelframe = 200;
                    if(Game.EDITOR)
                    {
                        game.gamestate = Game.CAT_GAMESTATE_GAME;
                        game.map = new Map();
                        Program.setupeditor(game);
                        Game.PLAYERFACTION = Unit.HUMAN;
                    }
                    else
                    {
                        game.gamestate = Game.CAT_GAMESTATE_GUIMENUS;
                        game.map = new Map();
                        Program.setupbackdrop(game);
                        game.demomode = true;
                        Game.PLAYERFACTION = Unit.HUMAN;
                    }
                    return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_STARTLEVEL)
            {
                //temporary
                game.gamestate = Game.CAT_GAMESTATE_GAME;
            }
        }
        /*

///////////////////Method Definition///////////////
        static void drawcreditsinfo(Game game)
        {
            string[] consoletext = new string[3];
            consoletext[0] = "Art, Design, Development, Programming";
            consoletext[1] = Game.AUTHOR + " " + Game.YEAR;
            consoletext[2] = "Music by Eric Matyas, soundimage.org";
            int a = 3;
            for(int i=0;i<a;i++)
            {
                RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY - 45 + i * 16,consoletext[i],RenderList.getrgb(255,255,255),game.fonts[Resources.SMALLFONT].font,true);
            }
        }
        *
/

///////////////////Method Definition///////////////
        static void handlezoom(Game game)
        {
            //handle the zoom in the game map to scale things
            //correctly
            if(Game.EDITOR)
            {
                return;
            }
            if(game.mwheel<0)
            {
                game.zoom -= 0.25f;
            }
            if(game.mwheel>0)
            {
                game.zoom += 0.25f;
            }
            game.mwheel = 0;
            if(game.zoom>4)
            {
                game.zoom = 4;
            }
            if(game.zoom<1)
            {
                game.zoom = 1;
            }
            game.zoom = 1;//27mar2021 // no more zoom.....?
            game.zoomcornerx = (int)(-1f * (float)(Game.RESOLUTIONX/2)*(game.zoom - 1));
            game.zoomcornery = (int)(-1f * (float)(Game.RESOLUTIONY/2)*(game.zoom - 1));
        }

///////////////////Method Definition///////////////
        static void handleedit(Game game)
        {
            //handle editing the map in the editor
            if(game.frame % 200==0)
            {
                Map.marktreepos(game);
            }
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].type==Gui.TYPE_MINIMAP)
                {
                    if(game.gui[i].mouseover)
                    {
                        return;
                    }                
                }
            }
            game.zoom = 1;
            int dirn = Functions.sign(game.mwheel);
            game.mwheel = 0;
            Game.editgridx = (Game.CORNERX + game.mx)/ Map.GRIDW;
            Game.editgridy = (Game.CORNERY + game.my)/ Map.GRIDH;
            if(Game.EDITMODE==Game.EDITMODE_TRIGGER || Game.EDITMODE==Game.EDITMODE_ENTERTEXT)
            {
                //Game.editname = "TRIGGERS"; //22mar2021
                Game.editname = Translation.TranslateWord("TRIGGERS",false);
                if(Game.EDITMODE==Game.EDITMODE_ENTERTEXT)
                {
                    TriggerHelper.constructorstring(game,false,false,0);
                    TriggerHelper.gettext(game);
                }
                else
                {
                    TriggerHelper.constructorstring(game,game.mlclick,game.mrclick,dirn);
                }
            }
            if(Game.EDITMODE==Game.EDITMODE_ROCK)
            {
                //Game.editname = "ROCKS";//22mar2021
                Game.editname = Translation.TranslateWord("ROCKS",false);//22mar2021
                if(game.mldown)
                {
                    Map.rockimage[Game.editgridx + Game.editgridy * Map.MAXX] = 0;    
                }
                if(game.mrdown)
                {
                    Map.rockimage[Game.editgridx + Game.editgridy * Map.MAXX] = Map.VACANT;
                }
            }
            if(Game.EDITMODE==Game.EDITMODE_TREE)
            {
                //Game.editname = "TREES";//22mar2021
                Game.editname = Translation.TranslateWord("TREES",false);//22mar2021
                if(game.mldown)
                {
                    Map.treeimage[Game.editgridx + Game.editgridy * Map.MAXX] = 0;    
                }
                if(game.mrdown)
                {
                    Map.treeimage[Game.editgridx + Game.editgridy * Map.MAXX] = Map.VACANT;
                }
            }
            if(Game.EDITMODE==Game.EDITMODE_WALL)
            {
                //Game.editname = "WALLS";//22mar2021
                Game.editname = Translation.TranslateWord("WALLS",false);//22mar2021
                if(game.mldown)
                {
                    Map.wallimage[Game.editgridx + Game.editgridy * Map.MAXX] = 0;    
                }
                if(game.mrdown)
                {
                    Map.wallimage[Game.editgridx + Game.editgridy * Map.MAXX] = Map.VACANT;
                }
            }
            if(Game.EDITMODE==Game.EDITMODE_HEIGHT && Config.USEHEIGHTS>0)
            {
                //Game.editname = "HEIGHT";//22mar2021
                Game.editname = Translation.TranslateWord("HEIGHT",false);//22mar2021
                if(game.mldown)
                {
                    //Map.heightmap[Game.editgridx + Game.editgridy * Map.MAXX]--;    
                    Map.pushmap(Game.editgridx * Map.GRIDW,Game.editgridy * Map.GRIDH,-1);
                }
                if(game.mrdown)
                {
                    //Map.heightmap[Game.editgridx + Game.editgridy * Map.MAXX]++;
                    Map.pushmap(Game.editgridx * Map.GRIDW,Game.editgridy * Map.GRIDH,+1);
                }
            }
            if(Game.EDITMODE==Game.EDITMODE_UNIT)
            {
                if(dirn>0)
                {
                    Game.editindex++;
                }
                if(dirn<0)
                {
                    Game.editindex--;
                }
                if(Game.editindex<0)
                {
                    Game.editindex = game.templates.Length - 1;
                }
                if(Game.editindex>game.templates.Length - 1)
                {
                    Game.editindex = 0;
                }
                //Game.editname = game.templates[Game.editindex].name + " Faction:"+game.templates[Game.editindex].faction;//22mar2021
                Game.editname = game.templates[Game.editindex].dname() + " " + Translation.TranslateWord("Faction:",false)+game.templates[Game.editindex].faction;
                if(game.mldown)
                {
                    for(int k=0;k<game.units.Length;k++)
                    {
                        if(game.units[k].hp<=0)
                        {
                            game.units[k].createunitatxy(game,k,game.templates[Game.editindex],Game.editgridx * Map.GRIDW,Game.editgridy * Map.GRIDH);    
                            break;
                        }
                    }
                }
                if(game.mrdown)
                {
                    int nid = Map.cellunit(Game.editgridx * Map.GRIDW,Game.editgridy * Map.GRIDH);
                    if(nid!=-1)
                    {
                        Map.removeunit(nid,Game.editgridx * Map.GRIDW,Game.editgridy * Map.GRIDH);
                        game.units[nid].hp=0;
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        static void handlegroupselection(Game game)
        {
            //handle selecting groups and assigning groups
            bool found = false;
            int sumx = 0;
            int sumy = 0;
            int count = 0;
            for(int i=0;i<10;i++)
            {
                if(Game.numberkeys[i]!=0)
                {
                    //for(int j=0;j<game.units.Length;j++)//26mar2021
                    for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                    {
                        if(game.units[j].hp>0 && game.units[j].faction==Game.PLAYERFACTION && Game.leftcontrolkey>0 && game.units[j].selected>Unit.SELECTIONNONE)
                        {
                            if(!found)
                            {
                                found = true;
                                //for(int k=0;k<game.units.Length;k++)//26mar2021
                                for(int k=0;k<=Unit.MAXINDEX;k++)//26mar2021
                                {
                                    if(game.units[k].groupid==i)
                                    {
                                        game.units[k].groupid = -1;
                                    }
                                }
                            }
                            game.units[j].groupid = i;
                        }
                        if(game.units[j].hp>0 && game.units[j].faction==Game.PLAYERFACTION && game.units[j].groupid==i && Game.leftcontrolkey==0)
                        {
                            if(!found)
                            {
                                //for(int k=0;k<game.units.Length;k++)//26mar2021
                                for(int k=0;k<=Unit.MAXINDEX;k++)//26mar2021
                                {
                                    game.units[k].selected=Unit.SELECTIONNONE;
                                }
                                found = true;
                            }
                            game.units[j].selected=Unit.SELECTIONFROZEN;
                            count++;
                            sumx+=game.units[j].x;
                            sumy+=game.units[j].y;
                            if(Game.numberkeys[i]>1)
                            {
                                Game.CORNERX = (sumx / count) - Game.RESOLUTIONX/2;
                                Game.CORNERY = (sumy / count) - Game.RESOLUTIONY/2;
                                if(Game.CORNERX<0)
                                {
                                    Game.CORNERX = 0;
                                }
                                if(Game.CORNERY<0)
                                {
                                    Game.CORNERY = 0;
                                }
                                if(Game.CORNERX > Map.MAXX*Map.GRIDW - Game.RESOLUTIONX)
                                {
                                    Game.CORNERX = Map.MAXX*Map.GRIDW - Game.RESOLUTIONX;
                                }
                                if(Game.CORNERY > Map.MAXY*Map.GRIDH - Game.RESOLUTIONY)
                                {
                                    Game.CORNERY = Map.MAXY*Map.GRIDH - Game.RESOLUTIONY;
                                }    
                                for(int k=0;k<10;k++)
                                {
                                    Game.numberkeys[k]=0;
                                }
                            }
                        }
                    }
                    if(game.frame > Game.numberkeysframe[i]+15)
                    {
                        Game.numberkeys[i] = 0;
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        static void updatestats(Game game)
        {
            //update the display statistics at the debriefing
            for(int i=0;i<game.templates.Length;i++)
            {
                if(game.templates[i].dispdeaths<game.templates[i].prevdeaths)
                {
                    game.templates[i].dispdeaths++;
                    return;
                }
                if(game.templates[i].dispkills<game.templates[i].prevkills)
                {
                    game.templates[i].dispkills++;
                    return;
                }
                if(game.templates[i].dispcreates<game.templates[i].prevcreates)
                {
                    game.templates[i].dispcreates++;
                    return;
                }
            }
        }

///////////////////Method Definition///////////////
        static void drawdebriefbk(Game game)
        {
            //draw the debriefing screen
            int iiline = 0;
            int ofaction = -1;
            int yb = 125;
            uint color = RenderList.getrgb(255,255,222);
            //13mar2021 - need translations! Grr.
            //RenderList.drawtext(game,500,yb + (-1) * game.fonts[Resources.FONT].ptsize,"Unit",color,game.fonts[Resources.FONT].font,false);
            //RenderList.drawtext(game,700,yb + (-1) * game.fonts[Resources.FONT].ptsize,"Created",color,game.fonts[Resources.FONT].font,false);
            //RenderList.drawtext(game,900,yb + (-1) * game.fonts[Resources.FONT].ptsize,"Kills",color,game.fonts[Resources.FONT].font,false);
            //RenderList.drawtext(game,1100,yb + (-1) * game.fonts[Resources.FONT].ptsize,"Deaths",color,game.fonts[Resources.FONT].font,false);
            //12apr2021 changed 500 to 300 here.....
            RenderList.drawtext(game,400,yb + (-1) * game.fonts[Resources.FONT].ptsize,Translation.TranslateWord("Unit",false),color,game.fonts[Resources.FONT].font,false);

            RenderList.drawtext(game,700,yb + (-1) * game.fonts[Resources.FONT].ptsize,Translation.TranslateWord("Created",false),color,game.fonts[Resources.FONT].font,false);
            RenderList.drawtext(game,900,yb + (-1) * game.fonts[Resources.FONT].ptsize,Translation.TranslateWord("Kills",false),color,game.fonts[Resources.FONT].font,false);
            RenderList.drawtext(game,1100,yb + (-1) * game.fonts[Resources.FONT].ptsize,Translation.TranslateWord("Deaths",false),color,game.fonts[Resources.FONT].font,false);
            for(int i=0;i<game.templates.Length;i++)
            {
                if(game.templates[i].faction==Unit.NULLFACTION && game.templates[i].walkspeed<=0)
                {
                    continue;
                }
                if(game.templates[i].prevcreates>0 || game.templates[i].prevkills>0 || game.templates[i].prevdeaths>0)
                {
                    color = RenderList.getrgb(255,255,200);
                    if(game.templates[i].faction!=Game.PLAYERFACTION)
                    {
                        color = RenderList.getrgb(255,200,200);
                    }
                    if(game.templates[i].faction==Unit.NULLFACTION)
                    {
                        color = RenderList.getrgb(200,200,200);
                    }
                    iiline++;
                    if(game.templates[i].faction!=ofaction)
                    {
                        ofaction = game.templates[i].faction;
                        iiline++;
                        RenderList.drawtext(game,800,yb + iiline * game.fonts[Resources.FONT].ptsize,"----------------------------------------------------------------------------",RenderList.getrgb(200,200,200),game.fonts[Resources.FONT].font,true);
                        iiline++;
                    }
                    //RenderList.drawtext(game,500,yb + iiline * game.fonts[Resources.FONT].ptsize,game.templates[i].name,color,game.fonts[Resources.FONT].font,false); //13mar2021
                    //RenderList.drawtext(game,700,yb + iiline * game.fonts[Resources.FONT].ptsize,""+game.templates[i].dispcreates,color,game.fonts[Resources.FONT].font,false);//13mar2021
                    //RenderList.drawtext(game,900,yb + iiline * game.fonts[Resources.FONT].ptsize,""+game.templates[i].dispkills,color,game.fonts[Resources.FONT].font,false);//13mar2021
                    //RenderList.drawtext(game,1100,yb + iiline * game.fonts[Resources.FONT].ptsize,""+game.templates[i].dispdeaths,color,game.fonts[Resources.FONT].font,false);//13mar2021
                    RenderList.drawtext(game,400,yb + iiline * game.fonts[Resources.FONT].ptsize,game.templates[i].dname(),color,game.fonts[Resources.FONT].font,false); //13mar2021
                    RenderList.drawtext(game,700,yb + iiline * game.fonts[Resources.FONT].ptsize,""+Translation.TranslateNumber(game.templates[i].dispcreates),color,game.fonts[Resources.FONT].font,false);//13mar2021
                    RenderList.drawtext(game,900,yb + iiline * game.fonts[Resources.FONT].ptsize,""+Translation.TranslateNumber(game.templates[i].dispkills),color,game.fonts[Resources.FONT].font,false);//13mar2021
                    RenderList.drawtext(game,1100,yb + iiline * game.fonts[Resources.FONT].ptsize,""+Translation.TranslateNumber(game.templates[i].dispdeaths),color,game.fonts[Resources.FONT].font,false);//13mar2021
                    updatestats(game);
                }
            }
            //1mar2022 added the mission score...
            iiline++;
            RenderList.drawtext(game,800,yb + iiline * game.fonts[Resources.FONT].ptsize,"----------------------------------------------------------------------------",RenderList.getrgb(200,200,200),game.fonts[Resources.FONT].font,true);
            iiline++;            
            RenderList.drawtext(game,400,yb + iiline * game.fonts[Resources.FONT].ptsize,Translation.TranslateWord("Mission Score:",false)+Game.MissionScore + " " + Translation.TranslateWord("Top Score:",false) + Game.TopScore,color,game.fonts[Resources.FONT].font,false);
            iiline++;            
            
        }

///////////////////Method Definition///////////////
        static void update(Game game)
        {
            //core game update routine
            //handles all updates
            Stopwatch utimer = new Stopwatch();
            utimer.Start();
            long bmenutime = 0;
            long umusictime = 0;
            long mapupdatepostime = 0;
            long mapcorrecttime = 0;
            long unitupdatetime = 0;
            long bullettime = 0;
            long bloodtime = 0;
            long selecttime = 0;
            long triggertime = 0;
            long drawtime = 0;
            Game.newtrees = new int[0];//24apr2021
            //int dieroll = Functions.rand(0,100);//2apr2021
            //start---------------------//20apr2021
            if(Config.AUTOCALCOFFSETS==true && Config.FINISHEDOFFSETS==false)
            {
                for(int i=0;i<game.templates.Length;i++)
                {
                    if(game.templates[i].autocalcedoffsets==false)
                    {
                        Unit.AutoCalcOffsets(game,i);
                        if(game.templates[i].autocalcedoffsets)
                        {
                            break;
                        }
                        if(i==game.templates.Length - 1)
                        {
                            Config.FINISHEDOFFSETS = true;
                        }
                    }
                }
                if(Config.FINISHEDOFFSETS)
                {
                    Unit.WriteOffsets(game,Config.offsetfile);
                }
            }
            //end-----------------------//20apr2021
            //start---------------//26mar2021
            if(Game.selectingtime>0)
            {
                Game.selectingtime--;
            }
            //end-----------------//26mar2021
            if(game.gamestate==Game.CAT_GAMESTATE_LOGO)
            {
                //if(game.frame<100) //27mar2021
                //{
                    //drawloadingbar(game,648,game.frame,300);
                    //return;
                //}
                drawlogo(game);
                return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_OUTRO)
            {
                drawoutro(game);
                return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_INTRO)
            {
                drawintro(game);
                return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_OUTROBAD)
            {
                drawoutrobad(game);
                return;
            }
            if(game.gamestate==Game.CAT_GAMESTATE_CREDITS2)
            {
                drawcredits(game);
                return;
            }
        
            //END RTS
            //
            bmenutime = utimer.ElapsedMilliseconds;
            basemenus(game);
            bmenutime = Math.Abs(utimer.ElapsedMilliseconds - bmenutime);
            umusictime = utimer.ElapsedMilliseconds;
            Map.updatemusic(game);
            umusictime = Math.Abs(utimer.ElapsedMilliseconds - umusictime);
            if(game.gamestate==Game.CAT_GAMESTATE_GAME)
            {
                if(Game.editkeypressed==10)
                {
                    Game.editkeypressed=11;
                    Game.EDITOR = true;
                    //start----------//5apr2021
                    try
                    {
                        Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=kog2mission&event=editor&value=1&uid="+Config.uid;//30mar2021
                        Network.httpget(Network.url);
                    }
                    catch(Exception e)
                    {
                        string message = e.Message;
                    }
                    //end-----------//5apr2021
                    Game.EDITORPFACTION = Game.PLAYERFACTION; //22mar2021
                    Game.EDITOREFACTION = Game.SKIRMISHENEMYFACTION; //22mar2021
                    Functions.saveseed(Functions.seed);
                    game.zoom = 0;
                    game.mwheel = 0;
                    game.playerready = false;
                    game.playingtutorial = false;
                    game.skirmish = false;
                    game.victorymessage = false;
                    cleardeaths(game);
                    game.playingtutorial = false;
                    Game.GAMEENDSTATE = 0;
                    game.gameovertime = 0;
                    game.paused = false;
                    Map.adddecor();//2mar2021
                    Map.marktreepos(game);
                    return;
                }
                if(Game.EDITOR)
                {
                    if(Game.backupkeypressed>=10)
                    {
                        Game.backupkeypressed = 0;
                        try
                        {
                            System.Diagnostics.Process.Start(@"restoreall.bat");
                            Console.WriteLine("Original Settings Restored");
                        }
                        catch(Exception eee)
                        {
                            Console.WriteLine(eee.Message);
                        }
                    }
                }
                else
                {
                    Game.backupkeypressed = 0;
                }
                game.demomode = false;
                mapupdatepostime = Math.Abs(utimer.ElapsedMilliseconds);
                Map.updatepos(ref game);
                mapupdatepostime = Math.Abs(utimer.ElapsedMilliseconds - mapupdatepostime);
                if((game.frame % 121)==0 && Config.RUNNINGSPEED<90)
                {
                    mapcorrecttime = utimer.ElapsedMilliseconds;
                    Map.correct(game);
                    mapcorrecttime = Math.Abs(utimer.ElapsedMilliseconds - mapcorrecttime);
                }
                unitupdatetime = utimer.ElapsedMilliseconds;
                if(!Game.togglepause)//22mar2021
                {
                    Unit.updateall(game); //this is where optimisation will make the most difference....
                    Tech.updateall(game);//2sep2021
                }
                unitupdatetime = Math.Abs(utimer.ElapsedMilliseconds - unitupdatetime);
                if(!Game.EDITOR)
                {
                    if(!Game.togglepause)//22mar2021
                    {
                        bullettime = utimer.ElapsedMilliseconds;
                        Bullet.updateall(game);
                        bullettime = Math.Abs(utimer.ElapsedMilliseconds - bullettime);
                        bloodtime = utimer.ElapsedMilliseconds;
                        Blood.updateall(game);
                        bloodtime = Math.Abs(utimer.ElapsedMilliseconds - bloodtime);
                        Gibbet.updateall(game);//2apr2021
                        Emitter.UpdateAll(game);//22apr2022
                        Particle.UpdateAll(game);//22apr2022
                
                    }
                    handlezoom(game);
                }
                else
                {
                    handleedit(game);
                    Game.recordkeypressed = 0;
                }
                RenderList.IGNOREZOOM = false;
                drawtime = utimer.ElapsedMilliseconds;
                Game.mouseoverunitid = -1; //24mar2021
                Unit.drawall(game);
                if(!Game.EDITOR)
                {
                    Bullet.drawall(game);
                    Blood.drawall(game);
                    Gibbet.drawall(game);//2apr2021
                    Particle.DrawAll(game);//22apr2022
                }
                else
                {
                    //13mar2021 editor not translated yet.....
                    if(Game.editname!="")
                    {
                        RenderList.drawtext(game,game.mx,game.my,Game.editname+","+Game.editgridx+","+Game.editgridy,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);
                    }
                    //RenderList.drawtext(game,0,800,"w-Wall Mode,r-Rock Mode,t-Tree Mode,u-Unit Mode,x-Triggers,o-Map File,c-Campaign File,Left Mouse Place, Right Mouse Remove",RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//22mar2021
                    RenderList.drawtext(game,0,800,Translation.TranslateWord("w-Wall Mode,r-Rock Mode,t-Tree Mode,u-Unit Mode,x-Triggers,o-Map File,c-Campaign File,Left Mouse Place, Right Mouse Remove",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//22mar2021
                    RenderList.drawtext(game,0,830,Translation.TranslateWord("TAB - Test Map",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//6mar2022
                    if(Config.USEHEIGHTS>0)
                    {
                        //RenderList.drawtext(game,0,830,"h-Height Mode",RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);/22mar2021
                        RenderList.drawtext(game,0,830,Translation.TranslateWord("h-Height Mode",false),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//22mar2021
                    }
                    //RenderList.drawtext(game,0,860,"Map Saved In:"+Config.custommapfolder,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//22mar2021
                    RenderList.drawtext(game,0,860,Translation.TranslateWord("Map Saved In:",false)+Config.custommapfolder,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);//22mar2021
                    if(Game.EDITMODE==Game.EDITMODE_TRIGGER || Game.EDITMODE==Game.EDITMODE_ENTERTEXT)
                    {
                        RenderList.drawtext(game,0,700,TriggerHelper.constructorstring(game,false,false,0),RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);
                        //RenderList.drawtext(game,0,750,"INFO: You will have to edit the triggers in a text file for some features.",RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                        RenderList.drawtext(game,0,750,Translation.TranslateWord("INFO: You will have to edit the triggers in a text file for some features.",false),RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                        if(Game.EDITMODE==Game.EDITMODE_ENTERTEXT)
                        {
                            if(Game.edittriggerstring.Length>0)
                            {
                                if(game.frame % 60 < 30)
                                {
                                    RenderList.drawtext(game,0,725,Game.edittriggerstring+"__",RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);
                                }
                                else
                                {
                                    RenderList.drawtext(game,0,725,Game.edittriggerstring,RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);
                                }
                            }
                            else
                            {
                                if(game.frame % 60 < 30)
                                {
                                    //RenderList.drawtext(game,0,725,"[CHATTER]__",RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                                    RenderList.drawtext(game,0,725,Translation.TranslateWord("[CHATTER]__",false),RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                                }
                                else
                                {
                                    //RenderList.drawtext(game,0,725,"[CHATTER]",RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                                    RenderList.drawtext(game,0,725,Translation.TranslateWord("[CHATTER]",false),RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);//22mar2021
                                }
                            }
                        }
                        for(int i=0;i<TriggerHelper.triggers.Length;i++)
                        {
                            if(TriggerHelper.triggers!=null)
                            {
                                RenderList.drawtext(game,0,15 + i * 20,TriggerHelper.triggers[i],RenderList.getrgb(32,32,32),game.fonts[Resources.SMALLFONT].font,false);
                            }
                        }
                    }
                }
                RenderList.IGNOREZOOM = true;
                drawtime = Math.Abs(utimer.ElapsedMilliseconds - drawtime);
                selecttime = utimer.ElapsedMilliseconds;
                //if(game.mldown && !game.paused)//22mar2021
                Game.TMPCORNERX = Game.CORNERX;//21apr2021
                Game.TMPCORNERY = Game.CORNERY;//21apr2021
                if(Replay.IsPlaying())//21apr2021
                {
                    Game.CORNERX = Game.RCORNERX;
                    Game.CORNERY = Game.RCORNERY;
                }
                if(game.mldown && !game.paused && !Game.togglepause)//22mar2021
                {
                    int x = game.smx;
                    int y = game.smy;
                    int w = (int)Functions.abs(game.fmx - game.smx);
                    int h = (int)Functions.abs(game.fmy - game.smy);
                    if(x > game.fmx)
                    {
                        x = game.fmx;
                    }
                    if(y > game.fmy)
                    {
                        y = game.fmy;
                    }
                    //start---------------//26mar2021
                    if(Functions.abs(w)>10 || Functions.abs(h)>10)
                    {
                        Game.selectingtime = Game.WAITSELECTINGTIME;
                    }
                    //end-----------------//26mar2021
                    //21apr2021 added diffx stuff
                    int diffx = Game.CORNERX - Game.TMPCORNERX;
                    int diffy = Game.CORNERY - Game.TMPCORNERY;
                    RenderList.drawunfilledrect(game,diffx + x - 1,diffy + y - 1,w,h,RenderList.getrgb(24,170,24),0);
                    RenderList.drawunfilledrect(game,diffx + x + 1,diffy + y + 1,w,h,RenderList.getrgb(24,170,24),0);
                    RenderList.drawunfilledrect(game,diffx + x,diffy + y,w,h,RenderList.getrgb(32,255,32),0);
                    int mmx = (int)((float)(x - Game.RESOLUTIONX/2)/game.zoom) + Game.CORNERX + Game.RESOLUTIONX/2;
                    int mmy = (int)((float)(y - Game.RESOLUTIONY/2)/game.zoom) + Game.CORNERY + Game.RESOLUTIONY/2;
                    int mmw = (int)((float)w / game.zoom);
                    int mmh = (int)((float)h / game.zoom);
                    Unit.select(game,mmx,mmy,mmw,mmh);
                }
                //if(game.mlclick && !game.paused)//22mar2021
                if(game.mlclick && !game.paused && !Game.togglepause)//22mar2021
                {
                    //freeze selection until a command is chosen....
                    if(Unit.noneselected(game))
                    {
                        //Unit.selectone(game);
                        int mmx = (int)((float)(game.mx - Game.RESOLUTIONX/2)/game.zoom) + Game.CORNERX + Game.RESOLUTIONX/2;
                        int mmy = (int)((float)(game.my - Game.RESOLUTIONY/2)/game.zoom) + Game.CORNERY + Game.RESOLUTIONY/2;
                        Unit.select(game,mmx,mmy,-1,-1);
                    }
                    Unit.freezeselect(game);
                }
                //if(game.mrclick && !game.paused)//22mar2021
                if(game.mrclick && !game.paused && !Game.togglepause)//22mar2021
                {
                    Unit.issueorder(game);
                    //Unit.deselect(game);
                }
                if(Unit.CRPG>0)//25sep2021
                {
                        if(game.mlclick && !game.paused && !Game.togglepause)
                        {
                            Unit.issueorder(game);
                        }
                }
                if(!Game.togglepause)//22mar2021
                {
                    handlegroupselection(game);
                }
                selecttime = Math.Abs(utimer.ElapsedMilliseconds - selecttime);
                Game.CORNERX = Game.TMPCORNERX;//21apr2021
                Game.CORNERY = Game.TMPCORNERY;//21apr2021
            }
            else
            {
                if(game.demomode)
                {
                    RenderList.IGNOREZOOM = true;//18sep2021
                    if(Config.NOUPDATEINDEMOMODE==0)//18sep2021
                    {
                        Map.updatepos(ref game);
                        if((game.frame % 121)==0)
                        {
                            Map.correct(game);
                            Map.setonfire(1940,2580,true);
                        }
                        Unit.updateall(game);
                        Tech.updateall(game);//2sep2021
                        Bullet.updateall(game);
                        Blood.updateall(game);
                        Gibbet.updateall(game);//2apr2021
                        Emitter.UpdateAll(game);//22apr2022
                        Particle.UpdateAll(game);//22apr2022
                        //RenderList.IGNOREZOOM = true;//18sep2021
                        Unit.drawall(game);
                        Bullet.drawall(game);
                        Blood.drawall(game);
                        Gibbet.drawall(game);//2apr2021
                        Particle.DrawAll(game);//22apr2022
                    }
                    Game.editkeypressed = 0; //22mar2021
                    //RenderList.drawtext(game,1400,845,"Version"+Game.VERSION,RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);
                    //RenderList.drawtext(game,1400,860,Game.AUTHOR+" "+Game.YEAR,RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);
                    //RenderList.drawtext(game,1400,875,Game.MUSIC,RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);
                }
            }
            guimenus(game);
            if(game.gamestate==10000 || game.gamestate==10088)//bestiary or main menu//1mar2022
            {
                Game.DisplayQuote(game);
            }
            if(Replay.PLAYBACK)//2apr2021
            {
                if(Replay.CHECKSUMBROKEN!=-1)
                {
                    RenderList.drawtext(game,30,870,"err:"+Replay.CHECKSUMBROKEN,RenderList.getrgb(255,255,200),game.fonts[Resources.SMALLFONT].font,false);
                }
            }
            if(game.gamestate==Game.CAT_GAMESTATE_DEBRIEF || game.gamestate==Game.CAT_GAMESTATE_DEBRIEF2)
            {
                drawdebriefbk(game);
            }
            //if(game.gamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR==false)//18apr2021
            if(game.oldgamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR==false)//18apr2021
            {
                triggertime = utimer.ElapsedMilliseconds;
                if(!Game.togglepause)//22mar2021
                {
                    Trigger.updateall(game);
                }
                if(game.onscreen==false && Game.GAMEENDSTATE==0)
                {
                //    RenderList.drawtext(game,Game.RESOLUTIONX/2,3*Game.RESOLUTIONY/4,"Double Click To Find Units",RenderList.getrgb(200,200,180),game.fonts[Resources.FONT].font,true);
                }
                if(game.missions!=null) //&& game.skirmish==false)
                {
                    if(game.missionid>=0 && game.missionid<game.missions.Length)
                    {
                        if(game.missions[game.missionid].objectives!=null)
                        {
                            int j = 0;
                            for(int i=0;i<game.missions[game.missionid].objectives.Length;i++)
                            {
                                if(game.missions[game.missionid].objectives[i]!=null)
                                {
                                    RenderList.drawtext(game,40,40 + (j * game.fonts[Resources.SMALLFONT].ptsize * 2),game.missions[game.missionid].objectives[i],RenderList.getrgb(200,200,180),game.fonts[Resources.SMALLFONT].font,false);
                                    j++;
                                }
                            }
                            if(Game.MissionScore!=0)//(game.missions[game.missionid].showkills>0)//1mar2022
                            {
                                //RenderList.drawtext(game,40,40 + (j * game.fonts[Resources.SMALLFONT].ptsize * 2),"Kills:"+Game.killcount,RenderList.getrgb(200,200,180),game.fonts[Resources.SMALLFONT].font,false);//13mar2021
                                RenderList.drawtext(game,40,40 + (j * game.fonts[Resources.SMALLFONT].ptsize * 2),Translation.TranslateWord("Mission Score:",false)+":"+Translation.TranslateNumber(Game.MissionScore),RenderList.getrgb(200,200,180),game.fonts[Resources.SMALLFONT].font,false);//13mar2021
                            }
                        }
                    }
                }
                triggertime = Math.Abs(utimer.ElapsedMilliseconds - triggertime);
            }
            if(Game.GAMEENDSTATE!=0 && game.gamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR==false)
            {
                game.gameovertime--;
                Game.togglepause=false;//22mar2021
                if(Game.GAMEENDSTATE==Game.GAMEENDSTATE_VICTORY)
                {
                    if(game.victorymessage)
                    {
                        //RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,"Victory",RenderList.getrgb(200,200,180),game.fonts[Resources.FONT].font,true);
                    }
                    else
                    {
                        game.gameovertime=1;
                    }
                }
                else
                {
                    //RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,"Defeat",RenderList.getrgb(200,200,180),game.fonts[Resources.FONT].font,true);    
                }            
                if(game.gameovertime==1)
                {
                    Blood.clearall(game);//29oct2020
                    Bullet.clearall(game);//29oct2020
                    Gibbet.clearall(game);//2apr2021
                    Map.savepath(game.missionid);
                    //start-------------//12mar2021
                    //if(game.missionid>=0 && game.missionid < game.missions.Length && game.missions!=null && Game.GAMEENDSTATE==Game.GAMEENDSTATE_VICTORY && game.skirmish==false && game.playingtutorial==false)//4apr2021
                    if(game.missionid>=0 && game.missionid < game.missions.Length && game.missions!=null && Game.GAMEENDSTATE==Game.GAMEENDSTATE_VICTORY && game.skirmish==false && game.playingtutorial==false && Replay.PLAYBACK==false)//4apr2021
                    {
                        LocalStorage.setitem("mission"+game.missionid,"Complete");
                        Unit.SaveScore(game,game.missionid);//17sep2021
                    }
                    //end---------------//12mar2021
                    if(Game.GAMEENDSTATE==Game.GAMEENDSTATE_DEFEAT || game.nextmissionid==-1 || game.skirmish==true || game.playingtutorial==true)
                    {
                        game.gamestate = Game.CAT_GAMESTATE_MENU;
                        game.skirmish = false;
                        if(Game.GAMEENDSTATE==Game.GAMEENDSTATE_DEFEAT && game.failedmissionid!=-1)
                        {
                            Game.PLAYERFACTION = Unit.HUMAN;
                            Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                            game.gamestate = Game.CAT_GAMESTATE_GAME;
                            if(game.missionid>=0 && game.missionid < game.missions.Length && game.missions!=null && Config.DODEBRIEF==true)
                            {
                                if(game.missions[game.missionid].debrief==1)
                                {
                                    game.gamestate = Game.CAT_GAMESTATE_DEBRIEF;
                                    Game.MissionScore+=Trigger.VARIABLE[Trigger.TYPE_POINTS];//1mar2022
                                    Game.TopScore = 0;//1mar2022
                                    try//1mar2022
                                    {
                                        Int32.TryParse(LocalStorage.getitem("topscore_"+game.missionid),out Game.TopScore);
                                    }
                                    catch(Exception e)
                                    {
                                        Console.WriteLine(e.Message);
                                    }
                                    if(Game.MissionScore>Game.TopScore)//1mar2022
                                    {
                                        Game.TopScore = Game.MissionScore;//1mar2022
                                        LocalStorage.setitem("topscore_"+game.missionid,""+Game.TopScore);
                                    }
                                    //start-------------//28Feb2021
                                    Game.PLAYERFACTION = game.missions[game.missionid].playerfaction;
                                    Game.SKIRMISHENEMYFACTION = game.missions[game.missionid].skirmishenemyfaction;
                                    //end---------------//28Feb2021
                                }
                            }
                            game.map = new Map();
                            Program.setupmission(game,game.failedmissionid,0);
                        }
                        else
                        {
                            game.gamestate = Game.CAT_GAMESTATE_DEBRIEF2;
                            Game.MissionScore+=Trigger.VARIABLE[Trigger.TYPE_POINTS];//1mar2022
                            try//1mar2022
                            {
                                Int32.TryParse(LocalStorage.getitem("topscore_"+game.missionid),out Game.TopScore);
                            }
                            catch(Exception e)
                            {
                                Console.WriteLine(e.Message);
                            }
                                    
                            if(Game.MissionScore>Game.TopScore)//1mar2022
                            {
                                Game.TopScore = Game.MissionScore;//1mar2022
                                LocalStorage.setitem("topscore_"+game.missionid,""+Game.TopScore);
                            }
                            cleardeaths(game);
                            //this next bit is for the final mission - if we win it....then we should go to the outro.....
                            if(game.nextmissionid==-1 && game.skirmish==false && game.playingtutorial==false && Game.GAMEENDSTATE!=Game.GAMEENDSTATE_DEFEAT)//28feb2022
                            {
                                game.gamestate = Game.CAT_GAMESTATE_OUTRO;
                                Game.outroframe = 0;
                                Game.outrodelay = 10;
                            }
                            if(game.nextmissionid==-1 && game.skirmish==false && game.playingtutorial==false && Game.GAMEENDSTATE==Game.GAMEENDSTATE_DEFEAT && Game.EXITPRESSED==0)//28feb2022
                            {
                                game.gamestate = Game.CAT_GAMESTATE_OUTROBAD;
                                Game.outroframe = 0;
                                Game.outrodelay = 10;
                            }
                        }
                    }
                    else
                    {
                        Game.PLAYERFACTION = Unit.HUMAN;
                        Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                        game.gamestate = Game.CAT_GAMESTATE_GAME;
                        if(game.missionid>=0 && game.missionid < game.missions.Length && game.missions!=null && Config.DODEBRIEF==true)
                        {
                            if(game.missions[game.missionid].debrief==1)
                            {
                                game.gamestate = Game.CAT_GAMESTATE_DEBRIEF;
                                Game.MissionScore+=Trigger.VARIABLE[Trigger.TYPE_POINTS];//1mar2022
                                try//1mar2022
                                {
                                    Int32.TryParse(LocalStorage.getitem("topscore_"+game.missionid),out Game.TopScore);
                                }
                                catch(Exception e)
                                {
                                    Console.WriteLine(e.Message);
                                }
                                                                
                                if(Game.MissionScore>Game.TopScore)//1mar2022
                                {
                                    Game.TopScore = Game.MissionScore;//1mar2022
                                    LocalStorage.setitem("topscore_"+game.missionid,""+Game.TopScore);
                                }
                                //start-------------//28Feb2021
                                Game.PLAYERFACTION = game.missions[game.missionid].playerfaction;
                                Game.SKIRMISHENEMYFACTION = game.missions[game.missionid].skirmishenemyfaction;
                                //end---------------//28Feb2021
                            }
                        }
                        game.map = new Map();
                        Program.setupmission(game,game.nextmissionid,0);
                    }
                }
            }
            utimer.Reset();
            if(bmenutime > Config.maxbmenutime || game.frame % 300 == 0)
            {
                Config.maxbmenutime = bmenutime;
            }
            if(umusictime > Config.maxumusictime || game.frame % 300 == 0)
            {
                Config.maxumusictime = umusictime;
            }
            if(mapupdatepostime > Config.maxmapupdatepostime || game.frame % 300 == 0)
            {
                Config.maxmapupdatepostime = mapupdatepostime;
            }
            if(mapcorrecttime > Config.maxmapcorrecttime || game.frame % 300 == 0)
            {
                Config.maxmapcorrecttime = mapcorrecttime;
            }
            if(unitupdatetime > Config.maxunitupdatetime || game.frame % 300 == 0)
            {
                Config.maxunitupdatetime = unitupdatetime;
            }
            if(bullettime > Config.maxbullettime || game.frame % 300 == 0)
            {
                Config.maxbullettime = bullettime;
            }
            if(bloodtime > Config.maxbloodtime || game.frame % 300 == 0)
            {
                Config.maxbloodtime = bloodtime;
            }
            if(selecttime > Config.maxselecttime || game.frame % 300 == 0)
            {
                Config.maxselecttime = selecttime;
            }
            if(triggertime > Config.maxtriggertime || game.frame % 300 == 0)
            {
                Config.maxtriggertime = triggertime;
            }
            if(drawtime > Config.maxdrawtime || game.frame % 300 == 0)
            {
                Config.maxdrawtime = drawtime;
            }
        }

///////////////////Method Definition///////////////
        static void updateaudio(Game game)
        {
            //manages the audio playing
            for(int i=0;i<game.audios.Length;i++)
            {
                if(Game.audioon)
                {
                    if(game.audios[i].ismusic)
                    {
                        if(Map.musicplaying!=-1)
                        {
                            //Audios.playmusic(game.audios[Map.musictrack[Map.musicplaying]],1,true);
                            break;
                        }
                    }
                }
                else
                {
                    Audios.pauseaudio(game.audios[i]);
                }
            }
        }

///////////////////Method Definition///////////////
        static void toggleaudio(Game game,int x,int y)
        {
            //manages toggling audio on or off
            if(game.mlclick)
            {
                if(game.mx>=x - 40 && game.mx<=x + 40)
                {
                    if(game.my>=y - 25 && game.my<=y + 25)
                    {
                        game.mlclick = false;
                        game.mldown = false;
                        Game.audioon = !Game.audioon;
                        updateaudio(game);
                        //Audios.playsound(game.audios[Resources.CAT_AUDIO_CLICK],1f);
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        static void getmaxmission(Game game)
        {
            //get the value of the max mission in terms of locked campaign maps
            //currently we ignore this mostly.
            string folder = "";
            try
            {
                folder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"/"+Game.NETTITLE;
                if(!Directory.Exists(folder))
                {
                    Directory.CreateDirectory(folder);
                }
                string[] savegame = System.IO.File.ReadAllLines(folder+"/"+"savegame.txt");
                if(savegame.Length>0)
                {
                    Int32.TryParse(savegame[0],out Game.maxmission);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            if(Config.KOG2) //12mar2021
            {
                Game.maxmission = 36;
            }
            if(Game.maxmission > Game.overridemaxmission)//13sep2021
            {
                Game.maxmission = Game.overridemaxmission;//13sep2021
            }
        }

///////////////////Method Definition///////////////
        static void game(IntPtr window,IntPtr renderer)
        {
            //contains core game loop
            //perform initialisation of loading resource calls
            //and then enters core game loop
            Game game = new Game(renderer);
            game.takepicture = false;
            game.window = window;
            game.screen = SDL.SDL_GetWindowSurface(window);
            Stopwatch gametimer = new Stopwatch();
            SDL.SDL_Event e;
            SDL.SDL_MouseMotionEvent m;
            m.x = 0;
            m.y = 0;
            bool quit = false;
            Map.menumusic = -1;
            Map.menumusicplaying = -1;
            resourceload(game);
            getmaxmission(game);
            Network.reporterror(true);//15mar2021
            updateaudio(game);
            gametimer.Start();
            if(!Config.FREEDEMO)//26apr2021
            {
                Config.freedemo = 0;
            }
            if(Config.freedemo>0)//26apr2021
            {
                Game.VERSIONSTR = "0001";
            }
            Config.FASTFRAMECHECK++;//14sep2021
            if(Config.FASTFRAMECHECK>1)//14sep2021
            {
                Config.FASTFRAMECHECK = 2;//14sep2021
            }
            if(Config.FASTFRAMECHECK<1)//14sep2021
            {
                Config.FASTFRAMECHECK = 1;//14sep2021
            }
            switch(Config.FASTFRAMECHECK)//14sep2021
            {
                case 1:
                Unit.ORDERTIME = 300;
                break;
                case 2:
                Unit.ORDERTIME = 100;
                break;
            }
            //26mar2021 commented out the if statement and surrounds//calling network command each time now....
            //string playedonce = LocalStorage.getitem("start"); //19mar2021
            //if(playedonce!="1") //19mar2021 (and inside)
            //{
                //Network.url = "https://www.mattiesgames.com/metrics/launch.php?game=grumthorr";//15mar2021//30mar2021
                Network.url = "https://www.mattiesgames.com/metrics/launch.php?game=grumthorr&uid="+Config.uid+"&version="+Game.VERSIONSTR;//30mar2021//14apr2021 added version string....
                Network.httpget(Network.url);//15mar2021
            //    LocalStorage.setitem("start","1");
            //    LocalStorage.finalise();
            //}
            resetgame(game);
            long maxutime = 0;
            long maxrtime = 0;
            //while(!quit)//15mar2021
            //start---------------//26mar2021
            if(Game.restartgamestate!=-1)
            {
                game.gamestate = Game.restartgamestate;
                if(game.gamestate!=Game.CAT_GAMESTATE_GAME)//7apr2021
                {
                    game.map = new Map();//7apr2021
                    Program.setupbackdrop(game);//7apr2021
                    game.demomode = true;//7apr2021
                }                    
            }
            //end-----------------//26mar2021
            //start----------//5apr2021
            if(Game.EDITOR)
            {
                try
                {
                    Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=kog2mission&event=editor&value=1&uid="+Config.uid;//30mar2021
                    Network.httpget(Network.url);
                }
                catch(Exception ffe)
                {
                    string message = ffe.Message;
                }
            }
            //end-----------//5apr2021
            bool usedelta = false;//18sep2021
            if(Config.USEDELTATIME>0)//18sep2021
            {
                usedelta = true;//18sep2021
            }
            Config.delta = 100;//18sep2021
            Stopwatch pausetimer = new Stopwatch();//28feb2022
            bool opause = Game.togglepause;//28feb2022
            while(quit==false || RenderList.threadrunning==true)//15mar2021
            {
                //start-------//28feb2022
                if(opause!=Game.togglepause)
                {
                    if(Game.togglepause)
                    {
                        pausetimer.Reset();
                        pausetimer.Start();
                        Trigger.VARIABLE[Trigger.TYPE_PAUSETIMER] = 0;
                    }
                    else
                    {
                        if(game.gamestate==Game.CAT_GAMESTATE_GAME || game.gamestate==Game.CAT_GAMESTATE_REPLAY)
                        {
                            Trigger.VARIABLE[Trigger.TYPE_PAUSETIMER] = Convert.ToInt32(pausetimer.ElapsedMilliseconds);
                        }
                        pausetimer.Stop();
                    }
                }
                opause = Game.togglepause;
                //end--------//28feb2022
                //start--------//18sep2021
                if(Config.UNLOCKFRAMERATE>0)
                {
                    Config.FRAMETIME = 1000 / (uint)Config.UNLOCKFRAMERATE;
                }
                if(usedelta && Game.FRAMERATE>0)// && deltafps>0)
                {
                    if(Config.UNLOCKFRAMERATE>0)
                    {
                        Config.delta = (100 * Config.UNLOCKFRAMERATE) / Game.FRAMERATE;
                        if(Config.delta < 100)
                        {
                            Config.delta = 100;
                        }
                        if(Config.delta > 500)
                        {
                            Config.delta = 500;
                        }
                    }
                    else
                    {
                        Config.delta = 100;
                    }
                }
                else
                {
                    Config.delta = 100;
                }
                //end-----//18sep2021
                if(Game.EDITOR)//22mar2021
                {
                    Game.togglepause = false;
                }
                //start-------------//28Feb2021
                StreamResources.streamloadhelper(game);
                //if(game.gamestate==Game.CAT_GAMESTATE_GAME) //2apr2021
                if(game.gamestate==Game.CAT_GAMESTATE_GAME || game.gamestate==Game.CAT_GAMESTATE_REPLAY)//2apr2021
                {
                    StreamResources.TOLERANCE = StreamResources.LONGTOLERANCE;
                }
                else
                {
                    StreamResources.TOLERANCE = StreamResources.SHORTTOLERANCE;
                    Game.togglepause = false;//22mar2021
                }
                //end---------------//28Feb2021
                //start------------//29may2021
                if(game.oldgamestate==Game.CAT_GAMESTATE_GAME || game.oldgamestate==Game.CAT_GAMESTATE_REPLAY)//29may2021
                {
                    if(Config.THREADEDPATHING)//29may2021
                    {
                        MapThread.init();//29may2021
                    }
                }
                //end--------------//29may2021
                if(!Game.togglepause)//12apr2021
                {
                    game.frame++;
                }
                game.getmouse();
                Game.formation = 0;//2apr2021
                if(game.mldown) //14apr2021
                {
                    Game.HORIZONTALFORMATION = 0;
                    Game.VERTICALFORMATION = 0;
                }
                int k = -1;
                while(SDL.SDL_PollEvent(out e) != 0)
                {
                    switch(e.type)
                    {
                        case SDL.SDL_EventType.SDL_QUIT:
                            quit = true;
                            break;
                        case SDL.SDL_EventType.SDL_KEYDOWN:
                            switch(e.key.keysym.sym)
                            {
                                case SDL.SDL_Keycode.SDLK_BACKSPACE:
                                if(Game.EDITMODE==Game.EDITMODE_ENTERTEXT && Game.EDITOR==true)
                                {
                                    if(Game.edittriggerstring.Length>0 && (game.frame % 20 < 10))
                                    {
                                        Game.edittriggerstring = Game.edittriggerstring.Substring(0,Game.edittriggerstring.Length-1);
                                    }
                                }
                                break;
                                //start--------------------//2apr2021
                                case SDL.SDL_Keycode.SDLK_ESCAPE:
                                    if(Replay.PLAYBACK && Replay.FRAME>0)
                                    {
                                        Replay.FRAME = Game.replay[0].mx.Length + 100; //cheap and nasty way of getting out of it.....
                                    }
                                break;
                                //end----------------------//2apr2021
                                case SDL.SDL_Keycode.SDLK_LSHIFT:
                                    Game.editshiftheld = true;
                                break;
                                case SDL.SDL_Keycode.SDLK_RSHIFT:
                                    Game.editshiftheld = true;
                                break;
                                case SDL.SDL_Keycode.SDLK_LCTRL:
                                    Game.leftcontrolkey = 1;
                                break;
                                case SDL.SDL_Keycode.SDLK_0:
                                    k = 0;
                                break;
                                case SDL.SDL_Keycode.SDLK_1:
                                    k = 1;
                                break;
                                case SDL.SDL_Keycode.SDLK_2:
                                    k = 2;
                                break;
                                case SDL.SDL_Keycode.SDLK_3:
                                    k = 3;
                                break;
                                case SDL.SDL_Keycode.SDLK_4:
                                    k = 4;
                                break;
                                case SDL.SDL_Keycode.SDLK_5:
                                    k = 5;
                                break;
                                case SDL.SDL_Keycode.SDLK_6:
                                    k = 6;
                                break;
                                case SDL.SDL_Keycode.SDLK_7:
                                    k = 7;
                                break;
                                case SDL.SDL_Keycode.SDLK_8:
                                    k = 8;
                                break;
                                case SDL.SDL_Keycode.SDLK_9:
                                    k = 9;
                                break;
                            }
                            if(k!=-1 && Game.leftcontrolkey>0)
                            {
                                Game.numberkeys[k]=1;
                            }
                        break;
                        case SDL.SDL_EventType.SDL_KEYUP:
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_PRINTSCREEN)
                            {
                                game.takepicture = true;
                            }
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_F5)//22apr2022
                            {
                                    Emitter.pimages = null;
                                    Emitter.Reset(game);
                                    Particle.Reset();
                            }
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_TAB)
                            {
                                //6mar2022
                                if(Game.EDITOR)
                                {
                                    Game.EDITOR = false;//6mar2022
                                    Game.editkeypressed = 0;//6mar2022
                                    //22apr2022 altered this....whole section....
                                    //Game.PLAYERFACTION = 6;
                                    //Game.SKIRMISHENEMYFACTION = 5;
                                    bool first = false;
                                    bool second = false;
                                    for(int u=0;u<game.units.Length;u++)
                                    {
                                        if(game.units[u].hp>0 && game.units[u].faction!=Unit.NULLFACTION)
                                        {
                                            if(!first)
                                            {
                                                first = true;
                                                Game.PLAYERFACTION = game.units[u].faction;
                                            }
                                            if(!second && first)
                                            {
                                                if(game.units[u].faction!=Game.PLAYERFACTION)
                                                {
                                                    Game.SKIRMISHENEMYFACTION = game.units[u].faction;
                                                    second = true;
                                                }
                                                
                                            }
                                        }
                                    }
                                }
                                //
                                //if(RenderList.RENDERMODE==RenderList.RENDERMODE_POOL)
                                //{
//                                    RenderList.RENDERMODE=RenderList.RENDERMODE_NONPOOL;
                                //}
                                //else
                                //{
//                                    RenderList.RENDERMODE=RenderList.RENDERMODE_POOL;
                                //}
                            }
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_LSHIFT)
                            {
                                Game.editshiftheld = false;
                            }
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_RSHIFT)
                            {
                                Game.editshiftheld = false;
                            }
                            if(e.key.keysym.sym==SDL.SDL_Keycode.SDLK_BACKQUOTE)
                            {
                                //Config.DEBUG = !Config.DEBUG;
                            }
                            if(Game.EDITOR)
                            {
                                if(Game.EDITMODE!=Game.EDITMODE_ENTERTEXT)
                                {
                                    switch(e.key.keysym.sym)
                                    {
                                        case SDL.SDL_Keycode.SDLK_b:
                                        Game.backupkeypressed++;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_h:
                                        if(Config.USEHEIGHTS>0)
                                        {
                                            Game.EDITMODE = Game.EDITMODE_HEIGHT;
                                        }
                                        break;
                                        case SDL.SDL_Keycode.SDLK_w:
                                        Game.EDITMODE = Game.EDITMODE_WALL;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_r:
                                        Game.EDITMODE = Game.EDITMODE_ROCK;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_t:
                                        Game.EDITMODE = Game.EDITMODE_TREE;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_u:
                                        Game.EDITMODE = Game.EDITMODE_UNIT;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_x:
                                        Game.EDITMODE = Game.EDITMODE_TRIGGER;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_o:
                                        Map.OPENMAP = true;
                                        Map.savemap(game);
                                        Map.OPENMAP = false;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_c:
                                        Map.opencampaign(game);
                                        break;
                                    }
                                }
                                else
                                {
                                    switch(e.key.keysym.sym)
                                    {
                                        case SDL.SDL_Keycode.SDLK_RETURN:
                                        Game.edittriggerstring+="|";
                                        break;
                                        case SDL.SDL_Keycode.SDLK_ESCAPE:
                                        Game.EDITMODE = Game.EDITMODE_TRIGGER;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_BACKSPACE:
                                        if(Game.edittriggerstring.Length>0)
                                        {
                                            Game.edittriggerstring = Game.edittriggerstring.Substring(0,Game.edittriggerstring.Length-1);
                                        }
                                        break;
                                    }
                                    if(e.key.keysym.sym!= SDL.SDL_Keycode.SDLK_RETURN && e.key.keysym.sym!= SDL.SDL_Keycode.SDLK_BACKSPACE)
                                    {
                                        try
                                        {
                                            string mychar = (string)SDL.SDL_GetKeyName(e.key.keysym.sym);
                                            if(mychar.Length==1)
                                            {
                                                mychar = mychar.ToLower();
                                                if(Game.editshiftheld)
                                                {
                                                    mychar = mychar.ToUpper();
                                                    if(mychar=="1")
                                                    {
                                                        mychar = "!";
                                                    }
                                                    if(mychar=="2")
                                                    {
                                                        mychar = "@";
                                                    }
                                                    if(mychar=="3")
                                                    {
                                                        mychar = "#";
                                                    }
                                                    if(mychar=="4")
                                                    {
                                                        mychar = "$";
                                                    }
                                                    if(mychar=="5")
                                                    {
                                                        mychar = "%";
                                                    }
                                                    if(mychar=="6")
                                                    {
                                                        mychar = "^";
                                                    }
                                                    if(mychar=="7")
                                                    {
                                                        mychar = "&";
                                                    }
                                                    if(mychar=="8")
                                                    {
                                                        mychar = "*";
                                                    }
                                                    if(mychar=="9")
                                                    {
                                                        mychar = "(";
                                                    }
                                                    if(mychar=="0")

                                                    {
                                                        mychar = ")";
                                                    }
                                                    if(mychar=="-")
                                                    {
                                                        mychar = "_";
                                                    }
                                                    if(mychar=="=")
                                                    {
                                                        mychar = "+";
                                                    }
                                                    if(mychar=="\\")
                                                    {
                                                        mychar = "|";
                                                    }
                                                    if(mychar=="/")
                                                    {
                                                        mychar = "?";
                                                    }
                                                    if(mychar==";")
                                                    {
                                                        mychar = ":";
                                                    }
                                                    if(mychar=="[")
                                                    {
                                                        mychar = "{";
                                                    }
                                                    if(mychar=="]")
                                                    {
                                                        mychar = "}";    
                                                    }
                                                    if(mychar==",")
                                                    {
                                                        mychar = "<";
                                                    }
                                                    if(mychar==".")
                                                    {
                                                        mychar = ">";
                                                    }
                                                }
                                                Game.edittriggerstring+=mychar;    
                                            }
                                            if(mychar.ToUpper()=="SPACE")
                                            {
                                                Game.edittriggerstring+=" ";
                                            }
                                        }
                                        catch(Exception f)
                                        {
                                            string message = f.Message;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                if(!Replay.PLAYBACK)//2apr2021
                                {
                                    switch(e.key.keysym.sym)
                                    {
                                        case SDL.SDL_Keycode.SDLK_LCTRL:
                                        Game.leftcontrolkey = 0;
                                        break;
                                        //start-----------------//22mar2021
                                        case SDL.SDL_Keycode.SDLK_PAUSE:
                                            if(game.gamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR==false)
                                            {
                                                Game.togglepause = !Game.togglepause;
                                            }
                                        break;
                                        //end-------------------//22mar2021
                                        case SDL.SDL_Keycode.SDLK_e:
                                            Game.editkeypressed++;
                                        break;
                                        /* //9mar2021
                                        case SDL.SDL_Keycode.SDLK_r:
                                            Game.recordkeypressed++;
                                            if(Game.recordkeypressed>9)
                                            {
                                                //Config.RECORD = !Config.RECORD;
                                                Game.recordkeypressed = 0;
                                            }
                                        break;
                                        *
/ //9mar2021
                                        //start-------------//9mar2021
                                        case SDL.SDL_Keycode.SDLK_o: //OPEN FORMATION
                                            Unit.Formation(game,Gui.ACTION_OPEN);
                                            Game.formation = Gui.ACTION_OPEN;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_c: //CLOSE FORMATION
                                            Unit.Formation(game,Gui.ACTION_CLOSE);
                                            Game.formation = Gui.ACTION_CLOSE;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_r: // RALLY FORMATION
                                            Unit.Formation(game,Gui.ACTION_RALLY);
                                            Game.formation = Gui.ACTION_RALLY;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_v: // VERTICAL LINE FORMATION
                                            Unit.Formation(game,Gui.ACTION_LINEV);
                                            Game.formation = Gui.ACTION_LINEV;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_h: // HORIZONTAL LINE FORMATION
                                            Unit.Formation(game,Gui.ACTION_LINEH);
                                            Game.formation = Gui.ACTION_LINEH;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_d: // DEFEND FORMATION
                                            Unit.Formation(game,Gui.ACTION_DEFEND);
                                            Game.formation = Gui.ACTION_DEFEND;//2apr2021
                                        break;
                                        case SDL.SDL_Keycode.SDLK_a: // ENGAGE FORMATION
                                            Unit.Formation(game,Gui.ACTION_ENGAGE);
                                            Game.formation = Gui.ACTION_ENGAGE;//2apr2021
                                        break;
                                        //end---------------//9mar2021
                                        case SDL.SDL_Keycode.SDLK_0:
                                        k = 0;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_1:
                                        k = 1;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_2:
                                        k = 2;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_3:
                                        k = 3;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_4:
                                        k = 4;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_5:
                                        k = 5;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_6:
                                        k = 6;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_7:
                                        k = 7;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_8:
                                        k = 8;
                                        break;
                                        case SDL.SDL_Keycode.SDLK_9:
                                        k = 9;
                                        break;
                                    }
                                    if(k!=-1 && Game.leftcontrolkey==0)
                                    {
                                        Game.numberkeys[k]++;
                                        if(game.frame - Game.numberkeysframe[k]<=15)
                                        {
                                            Game.numberkeys[k]++;
                                        }
                                        Game.numberkeysframe[k] = game.frame;
                                    }
                                }//2apr2021
                            }
                            break;
                        case SDL.SDL_EventType.SDL_MOUSEWHEEL:
                            game.mwheel = e.wheel.y;
                        break;
                    }
                }
                long utime = gametimer.ElapsedMilliseconds;
                game.oldgamestate = game.gamestate;
                if(Config.ALLOWREPLAY )//2apr2021
                {
                    if(Replay.PLAYBACK)
                    {
                        //playback begins on frame 2
                        Replay.PlayReplay(game,Replay.FRAME); //sets mouse and other values....
                        Replay.FRAME++;
                    }
                    if(Replay.RECORD)
                    {
                        //recording begins on frame 2
                        Replay.RecordReplay(game); //mouse and running speeds etc will be set by now....as well as seeds....
                    }
                }
                if(RenderList.transitionmode<RenderList.HALFTRANSIT)//18apr2021
                {
                    update(game);
                }
                //start-----//18apr2021
                if(RenderList.transitionmode==RenderList.HALFTRANSIT)
                {
                    //Functions.saveseed(Functions.seed);
                    //if((Functions.Rand(0,100) % 10)<7)
                    //{
                    //    Gui.ALTMODE = !Gui.ALTMODE;
                    //}
                    //Functions.restoreseed();
                }
                //end-------//18apr2021
                if(Config.freedemo>0)//26apr2021
                {
                    Config.freedemo--;
                    if(Config.freedemo==60*10)
                    {
                        game.gamestate = 10000 + 888;
                    }
                    if(Config.freedemo<=1)
                    {
                        quit = true;
                        Game.restart = false;
                    }
                    RenderList.drawtext(game,800,850,"Demo Time Remaining:"+Functions.ClockTime(Config.freedemo / 60),RenderList.getrgb(220,220,180),game.fonts[Resources.FONT].font,true);
                }
            
                game.newgamestate = game.gamestate;
                //start-------------//12mar2021
                if(game.gamestate!=game.oldgamestate)
                {
                    if(game.gamestate==Game.CAT_GAMESTATE_GAME)//1mar2022
                    {
                        Game.MissionScore = 0;//1mar2022
                    }
                    Game.quoteindex = Functions.rand(0,100);//1mar2022
                    if(Game.quoteindex<0)//1mar2022
                    {
                        Game.quoteindex*=-1;//1mar2022
                    }
                    //if(RenderList.transitionmode<0 && Game.FULLSCREEN>0){RenderList.transitionmode = RenderList.STARTTRANSITION;}//18apr2021//19apr2021
                    if(RenderList.transitionmode<0){RenderList.transitionmode = RenderList.STARTTRANSITION;}//18apr2021//19apr2021
                    if(Game.EDITED>0) //7apr2021
                    {//7apr2021
                        Game.restart = true;//7apr2021
                        Game.EDITED = -1;
                    }//7apr2021
                    if(Game.chosenmissionindex!=-1)
                    {
                        Game.previousmissionindex = Game.chosenmissionindex;
                    }
                    Game.chosenmissionindex = -1;
                    Unit.MAXINDEX = 0;//26mar2021
                    Bullet.MAXINDEX = 0;//27mar2021
                    //moved elsewhere....//18apr2021//maybenot?
                    //Functions.saveseed(Functions.seed);//2apr2021
                    //if((Functions.Rand(0,100) % 10)<7) //24mar2021
                    //{
                    //    Gui.ALTMODE = !Gui.ALTMODE; //24mar2021
                    //}
                    //Functions.restoreseed();//2apr2021
                    //start--------------//2apr2021
                    if(Config.ALLOWREPLAY)
                    {
                        if(game.gamestate==Game.CAT_GAMESTATE_GAME && Replay.PLAYBACK==false)
                        {
                            //this occurs on frame 1
                            Replay.Init(game);
                            Replay.StartRecordReplay(game,0);
                        }
                        if(game.oldgamestate==Game.CAT_GAMESTATE_GAME)
                        {
                            Replay.EndRecord(game);
                        }
                        if(game.gamestate==Game.CAT_GAMESTATE_REPLAY)
                        {
                            //this occurs on frame 1
                            Replay.PrepareToPlay(game);
                            //Trigger.updateall(game); //to keep in line with the standard path taken through the game code.//18apr2021 commented out....
                        }
                    }
                    else
                    {
                        Replay.RECORD = false;
                        Replay.PLAYBACK = false;
                    }
                    //end----------------//2apr2021
                }
                utime-=gametimer.ElapsedMilliseconds;
                long rtime = gametimer.ElapsedMilliseconds;
                long sumr = 0;
                long sumu = 0;
                for(int i=0;i<Config.totrtime.Length;i++)
                {
                    sumr+=Config.totrtime[i];
                    sumu+=Config.totutime[i];
                }
                Config.sumu = sumu;
                Config.sumr = sumr;
                Config.RUNNINGSPEED = ((sumu + sumr)*100)/10000;
                Config.runningspeed = Config.RUNNINGSPEED;//redundancy//2apr2021
                if(Config.DEBUG)
                {
                    if(Config.NOMETRICS)
                    {
                        //RenderList.drawtext(game,800,25,"NOMETRICS",RenderList.getrgb(50,100,255),game.fonts[Resources.FONT].font,true);
                    }
                    RenderList.drawtext(game,800,50,"Utime:"+Math.Abs(maxutime)+" Rtime:"+Math.Abs(maxrtime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    if(sumu+sumr > 9000)
                    {
                        RenderList.drawtext(game,800,100,"WARNING:"+((sumu+sumr)*100/10000)+"%",RenderList.getrgb(255,32,32),game.fonts[Resources.FONT].font,true);
                    }
                    else
                    {
                        RenderList.drawtext(game,800,100,((sumu+sumr)*100/10000)+"%",RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    }
                    if(RenderList.RENDERMODE==RenderList.RENDERMODE_POOL)
                    {
                        RenderList.drawtext(game,800,75,"POOL Tot U:"+Math.Abs(sumu)+" Tot R:"+Math.Abs(sumr),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    }
                    else
                    {
                        RenderList.drawtext(game,800,75,"NON POOL Tot U:"+Math.Abs(sumu)+" Tot R:"+Math.Abs(sumr),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    }
                    //RenderList.drawtext(game,800,100,"bmenutime:"+Math.Abs(Config.maxbmenutime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,125,"bullettime:"+Math.Abs(Config.maxbullettime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    RenderList.drawtext(game,800,150,"drawtime:"+Math.Abs(Config.maxdrawtime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,175,"correcttime:"+Math.Abs(Config.maxmapcorrecttime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,200,"mappostime:"+Math.Abs(Config.maxmapupdatepostime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,225,"selecttime:"+Math.Abs(Config.maxselecttime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,250,"triggertime:"+Math.Abs(Config.maxtriggertime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,275,"unitupdatetime:"+Math.Abs(Config.maxunitupdatetime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,300,"musictime:"+Math.Abs(Config.maxumusictime),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,75,"animatetime:"+Math.Abs(Config.maxanimate),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,100,"updatetime:"+Math.Abs(Config.maxupdate),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,125,"attacktime:"+Math.Abs(Config.maxatt),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //this is where the optimisation can be found....
                    //RenderList.drawtext(game,800,325,"walktime:"+Math.Abs(Config.maxwalk),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    RenderList.drawtext(game,800,350,"MAXINDEX:"+Unit.MAXINDEX,RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,400,"precalcused:"+Math.Abs(Config.precalcused),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,425,"seekpathused:"+Math.Abs(Config.seekpathused),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,450,"seekpathsuccess:"+Math.Abs(Config.seekpathsuccess),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,475,"seekpathfailed:"+Math.Abs(Config.seekpathfailed),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                    //RenderList.drawtext(game,800,500,"maperrors:"+Math.Abs(Config.maxmaperrors),RenderList.getrgb(180,180,180),game.fonts[Resources.FONT].font,true);
                }
                //if(Game.transitionframe!=Game.TRANSITIONTIME)
                //{
                    if(Game.restart)//13apr2021
                    {
                        RenderList.drawrect(game,0,0,Game.RESOLUTIONX,Game.RESOLUTIONY,RenderList.getrgb(1,1,1),0);
                        RenderList.drawtext(game,Game.RESOLUTIONX/2,Game.RESOLUTIONY/2,Translation.TranslateWord("Please Wait",false),RenderList.getrgb(180,180,180),game.fonts[Resources.LARGEFONT].font,true);
                    }
                    render(game,window);
                //}
                if(game.takepicture || (game.frame >1 && (game.frame % 120)==0 && Config.RECORD==true && Config.totrtime[(game.frame - 1) % 600]<20))
                {    
                    if(Config.RECORD)
                    {
                        if(RenderList.recordframe>60*60)
                        {
                            Config.RECORD = false;
                            Game.recordkeypressed = 0;
                        }
                    }
                    bool taken = false;
                    SDL.SDL_Rect rect = new SDL.SDL_Rect();
                    rect.x = 0;
                    rect.y = 0;
                    rect.w = game.SW;
                    rect.h = game.SH;
                    IntPtr surface = SDL.SDL_CreateRGBSurfaceWithFormat(SDL.SDL_RLEACCEL,game.SW,game.SH,32,SDL.SDL_PIXELFORMAT_ARGB8888);        
                    try
                    {
                        //WARNING - NOT SURE IF I'M DOING THIS QUITE CORRECTLY. FOR MEMORY SAFETY.
                        unsafe
                        {
                            SDL.SDL_Surface * sur = (SDL.SDL_Surface *)surface;
                            SDL.SDL_RenderReadPixels(game.renderer,ref rect,SDL.SDL_PIXELFORMAT_ARGB8888,sur->pixels,sur->pitch);
                            //free the * sur reference
                        }
                        taken = RenderList.CaptureThread(surface);
                    }
                    catch(Exception ggg)
                    {
                        string msg = ggg.Message;
                    }
                    if(!taken)
                    {
                        try
                        {
                            SDL.SDL_FreeSurface(surface);
                        }
                        catch(Exception ggg)
                        {
                            string msg = ggg.Message;
                        }    
                    }                    
                    game.takepicture = false;
                }
                rtime-=gametimer.ElapsedMilliseconds;
                utime = Math.Abs(utime);
                rtime = Math.Abs(rtime);
                Config.totrtime[game.frame % 600]=rtime;
                Config.totutime[game.frame % 600]=utime;
                if(utime>maxutime || game.frame % 300== 0)
                {
                    maxutime = utime;
                }
                if(rtime > maxrtime || game.frame % 300 == 0)
                {
                    maxrtime = rtime;
                }
                if(game.gamestate<0)
                {
                    quit = true;
                }
                //while(gametimer.ElapsedMilliseconds<14)//26mar2021
                while(gametimer.ElapsedMilliseconds<Config.FRAMETIME-1 && gametimer.ElapsedMilliseconds>=0)//26mar2021
                {
                    //if(Game.NODELAY){SDL.SDL_Delay(1);}//26mar2021
                    SDL.SDL_Delay(Config.FRAMETIME - Convert.ToUInt32(gametimer.ElapsedMilliseconds));//26mar2021
                }
                Game.FRAMERATE = Convert.ToInt32(1000.0 / gametimer.ElapsedMilliseconds);
                gametimer.Reset();
                gametimer.Start();
                //26mar2021 uncommented this block out
                //if(game.frame % (60*60)==0 && game.frame > 0)//15mar2021//15sep2021
                if(game.frame % (60*60)==0 && game.frame > 0 && Game.togglepause==false)//15mar2021//15sep2021
                {//15mar2021
                    //Network.url = "https://www.mattiesgames.com/metrics/timespent.php?game=grumthorr";//15mar2021//30mar2021
                    Network.url = "https://www.mattiesgames.com/metrics/timespent.php?game=grumthorr&uid="+Config.uid;//30mar2021
                    Network.httpget(Network.url);//15mar2021
                }//15mar2021
                //start--------------//13mar2021
                //if(Game.restart)//15mar2021
                if(Game.restart==true && RenderList.threadrunning==false)//15mar2021
                {
                    //if(game.gamestate!=Game.CAT_GAMESTATE_GAME)//7apr2021
                    //{
                        quit = true;
                    //}
                    //Game.restart = false; //13mar2021 - bugger.
                }
                //end----------------//13mar2021
            }
            MapThread.quit = true;//29may2021
            gametimer.Stop();
            game.quit();
            //Network.url = "https://www.mattiesgames.com/metrics/metric.php?game="+Game.NETTITLE+"&event=maxmission&value="+Game.maxmission;//15mar2021
            //Network.httpget(Network.url);//15mar2021
            Game.restartgamestate = game.gamestate; //26mar2021
            //start---------------//28mar2021
            if(Game.restart==false)
            {
                string langlang = LocalStorage.getitem("language");
                if(langlang=="")
                {
                    langlang = "english";
                    if(Config.autodetectlang!="")//30mar2021
                    {
                        langlang = Config.autodetectlang;
                    }
                }
                int gtime = (game.frame / (60*60));
                //Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=grumthorr&event="+langlang+"&value="+gtime;//15mar2021//30mar2021
                Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=grumthorr&event="+langlang+"&value="+gtime+"&uid="+Config.uid;//30mar2021
                Network.httpget(Network.url);
            }
            //end-----------------//28mar2021
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Tech //2sep2021
    {
        public static bool TECHUNITSELECTED = false;
        public static int TECHUNITIDSELECTED = -1;
        public static int COMPLETEDTIME = 60 * 5; //time to show on screen the 'completed' message for....
        public static int COMPLETEDID = -1;
        //
        public static int ADDSUBTRACT = 0;
        public static int TARGETUID = -1;
        //
        public string name;
        public string techclass;//23sep2021
        public string displayname;
        public string[] description;
        public string tooltip;
        public int guilinkid;
        public int id;
        public int faction;
        //
        public int researchtime; //number of seconds to count down from
        public int timeleft; //initialised to -1
        public int researched; //reset at beginning of mission.
        public int completedtime;//
        public int researching;
        public int unlimited;//23sep2021
        //
        public int goldcost;//23sep2021
        public int purchased;//23sep2021
        public int purchaseguilink;//23sep2021
        public int temporary;//23sep2021
        public int temporarytime;//23sep2021
        public int TEMPORARYTIME = 90;//23sep2021
        public int attackaction;//23sep2021
        public int guiactionid;//23sep2021
        public int selectedtopurchase;//23sep2021
        public int manacost;//23sep2021
    
        public int img; //icon image
        public int imgframe; //frame in image if multiple cells...
        public string imgfile; //image file
        public int saleimg;//saleimage//23sep2021
        public string saleimgfile;//image file//23sep2021
        public int saleimgframe;//23sep2021
    
        public int scw; //cell width//23sep2021
        public int sch; //cell height//23sep2021
        public int snw; //number wide//23sep2021
        public int snh; //number high//23sep2021
    
        public int cw; //cell width
        public int ch; //cell height
        public int nw; //number wide
        public int nh; //number high
        //
        public string effectname; //pipe separated list of items....
        public int effectint;// if value is a buff of sorts....
        //
        public static string ENABLEUNIT = "EU_";

        public static string BUFFMOVE = "BM_";
        public static string BUFFATT = "BA_";
        public static string BUFFDEF = "BD_";
        public static string BUFFHP = "BH_";
        public static string BUFFABILITY = "BZ_";
        //
        public int[] unittemplatesenabled;
        public int[] unittemplatesmove;
        public int[] unittemplatesatt;
        public int[] unittemplatesdef;
        public int[] unittemplateshp;
        public string[] unittemplatesability;
        //
        //example effect name string:
        //effectname = EU_Hero Skeleton
        //would enable the Hero Skeleton to be built.
        //effectname = BA_Hero Skeleton|BD_Hero Skeleton
        //effectint = 1
        //would buff Hero Skeletons' Att and Def by +1 point permanently.
        
        public static string MV = "MV";
        public static string BA = "BA";
        public static string BD = "BD";
        public static string BH = "BH";
        public static string BZ = "BZ";
        
        ///////////////////Method Definition///////////////
        public static int PercentComplete(Game game,int id)
        {
            if(!Config.USETECH)
            {
                return 100;
            }
            if(game.techs[id].timeleft<0)
            {
                return 0;
            }
            if(game.techs[id].timeleft==0)
            {
                return 100;
            }
            if(game.techs[id].researchtime<=0)
            {
                return 100;
            }
            return ((game.techs[id].researchtime - game.techs[id].timeleft) * 100) / game.techs[id].researchtime;
        }
        
        ///////////////////Method Definition///////////////
        public static void StartResearch(Game game,int techid,int faction)
        {
            if(!Config.USETECH)
            {
                return;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                if(faction==game.techs[i].faction)
                {
                    game.techs[i].researching = 0;
                }
            }
            game.techs[techid].researching = 1;
            if(game.techs[techid].timeleft<0)
            {
                game.techs[techid].timeleft = game.techs[techid].researchtime;
            }
        }
        ///////////////////Method Definition///////////////
        public static int AddUnitUpgradeBuff(Game game,int templateid,string type)
        {
            if(!Config.USETECH)
            {
                return 0;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                if(game.techs[i].researched>0)
                {
                    if(game.techs[i].unittemplatesmove!=null && type==Tech.MV)
                    {
                        for(int j=0;j<game.techs[i].unittemplatesmove.Length;j++)
                        {
                            if(game.techs[i].unittemplatesmove[j]==templateid)
                            {
                                return game.techs[i].effectint;
                            }
                        }
                    }
                    if(game.techs[i].unittemplatesatt!=null && type==Tech.BA)
                    {
                        for(int j=0;j<game.techs[i].unittemplatesatt.Length;j++)
                        {
                            if(game.techs[i].unittemplatesatt[j]==templateid)
                            {
                                return game.techs[i].effectint;
                            }
                        }
                    }
                    if(game.techs[i].unittemplatesdef!=null && type==Tech.BD)
                    {
                        for(int j=0;j<game.techs[i].unittemplatesdef.Length;j++)
                        {
                            if(game.techs[i].unittemplatesdef[j]==templateid)
                            {
                                return game.techs[i].effectint;
                            }
                        }
                    }
                    if(game.techs[i].unittemplateshp!=null && type==Tech.BH)
                    {
                        for(int j=0;j<game.techs[i].unittemplateshp.Length;j++)
                        {
                            if(game.techs[i].unittemplateshp[j]==templateid)
                            {
                                return game.techs[i].effectint;
                            }
                        }
                    }
                    if(game.techs[i].unittemplatesability!=null && type==Tech.BZ && TARGETUID!=-1 && ADDSUBTRACT!=0)
                    {
                        for(int j=0;j<game.techs[i].unittemplatesability.Length-2;j+=2)
                        {
                            if(game.techs[i].unittemplatesability[j]==game.templates[templateid].name)
                            {
                                AlterUnitAbility(game,game.techs[i].unittemplatesability[j + 1],TARGETUID,ADDSUBTRACT);
                                return 0;
                            }
                        }
                    }
                }
            }
            return 0;
        }
        
        ///////////////////Method Definition///////////////
        public static void AlterUnitAbility(Game game,string ability,int id,int value)
        {
            //add to this list as time goes on....as more abilities come to light.....
            bool redomagic = false;
            switch(ability)
            {
                case "accuracy"://28feb2022
                game.units[id].accuracy+=value;
                break;
                case "needlos"://15sep2021
                game.units[id].needlos+=value;
                break;
                case "range":
                game.units[id].firerange+=value;
                break;
                case "damage2":
                game.units[id].damage2+=value;
                break;
                case "splash":
                game.units[id].splash+=value;
                break;
                case "range2":
                game.units[id].firerange2+=value;
                break;
                case "prefermobiletargets"://18sep2021
                game.units[id].prefermobiletargets+=value;
                break;
                case "spellcaster":
                game.units[id].spellcaster+=value;
                break;
                case "notabuffer": //15apr2021
                game.units[id].notabuffer+=value;
                break;
                case "extragibbet"://18sep2021
                game.units[id].extragibbet+=value;
                break;
                case "firespell":
                game.units[id].firespell+=value;
                break;
                case "powerspell":
                game.units[id].powerspell+=value;
                break;
                case "infectchanceonhit"://22apr2022
                game.units[id].infectchanceonhit+=value;
                break;
                case "infectchanceonkill"://22apr2022
                game.units[id].infectchanceonkill+=value;
                break;
                case "healer":
                game.units[id].healer+=value;
                break;
                case "zombiemaster":
                game.units[id].zombiemaster+=value;
                break;
                case "banishment": //12mar2021
                game.units[id].banish+=value;
                break;
                case "timid":
                game.units[id].timid+=value;
                break;
                case "hitandrun":
                game.units[id].hitandrun+=value;
                break;
                case "buildpenalty": //20mar2021
                game.units[id].buildpenalty+=value;
                break;//20mar2021
                case "brave":
                game.units[id].brave+=value;
                break;
                //start-----------//01apr2021
                case "spellability":
                game.units[id].spellability+=value;
                break;
                case "ping"://16sep2021
                game.units[id].ping+=value;
                break;
                case "spelldefense": //magic resistance....
                game.units[id].spelldefense+=value;
                break;
                //start--------------//4may2021
                case "canfly":
                game.units[id].canfly+=value;
                break;
                case "canflyandwalk":
                game.units[id].canflyandwalk+=value;
                break;
                case "canattackair":
                game.units[id].canattackair+=value;
                break;
                //end----------------//4may2021
                //start--------------//3may2021
                case "magicrelease": //for getting out of transports
                game.units[id].magicrelease +=value;
                redomagic = true;
                if(game.units[id].magicrelease>0)
                {
                    game.units[id].magicrelease = Unit.MAGICRELEASE;
                }
                else
                {
                    game.units[id].magicrelease = 0;
                }
                break;
                case "magictransform": //for transforming into a different unit
                redomagic = true;
                game.units[id].magictransform +=value;
                if(game.units[id].magictransform>0)
                {
                    game.units[id].magictransform = Unit.MAGICTRANSFORM;
                }
                else
                {
                    game.units[id].magictransform = 0;
                }
                break;
                case "magicsummoner":
                redomagic = true;
                game.units[id].magiczombiemaster+=value;
                if(game.units[id].magiczombiemaster>0)
                {
                    game.units[id].magiczombiemaster = Unit.MAGICZOMBIEMASTER;
                }
                else
                {
                    game.units[id].magiczombiemaster = 0;
                }
                break;
                case "magiczombiemaster"://redundant version alias
                redomagic = true;
                game.units[id].magiczombiemaster+=value;
                if(game.units[id].magiczombiemaster>0)
                {
                    game.units[id].magiczombiemaster = Unit.MAGICZOMBIEMASTER;
                }
                else
                {
                    game.units[id].magiczombiemaster = 0;
                }
                break;
                case "magicleader":
                game.units[id].magicleader+=value;
                redomagic = true;
                if(game.units[id].magicleader>0)
                {
                    game.units[id].magicleader = Unit.MAGICLEADER;
                }
                else
                {
                    game.units[id].magicleader = 0;
                }
                break;
                //end----------------//9apr2021
                case "magicfrenzy":
                game.units[id].magicfrenzy+=value;
                redomagic = true;
                if(game.units[id].magicfrenzy>0)
                {
                    game.units[id].magicfrenzy = Unit.MAGICFRENZY;
                }
                else
                {
                    game.units[id].magicfrenzy = 0;
                }
                break;
                case "magicdoom":
                game.units[id].magicdoom+=value;
                redomagic = true;
                if(game.units[id].magicdoom>0)
                {
                    game.units[id].magicdoom = Unit.MAGICDOOM;
                }
                else
                {
                    game.units[id].magicdoom = 0;
                }
                break;
                case "magicdefense":
                game.units[id].magicdef+=value;
                redomagic = true;
                if(game.units[id].magicdef>0)
                {
                    game.units[id].magicdef = Unit.MAGICDEF;
                }
                else
                {
                    game.units[id].magicdef = 0;
                }
                break;
                case "magicdef": //redundancy
                game.units[id].magicdef+=value;
                redomagic = true;
                if(game.units[id].magicdef>0)
                {
                    game.units[id].magicdef = Unit.MAGICDEF;
                }
                else
                {
                    game.units[id].magicdef = 0;
                }
                break;
                //end-------------//01apr2021
                //start---------------//28mar2021
                case "magicweb":
                game.units[id].magicweb+=value;
                redomagic = true;
                if(game.units[id].magicweb>0)
                {
                    game.units[id].magicweb = Unit.MAGICWEB;
                }
                else
                {
                    game.units[id].magicweb = 0;
                }
                break;
                case "magicgas":
                redomagic = true;
                game.units[id].magicgas+=value;
                if(game.units[id].magicgas>0)
                {
                    game.units[id].magicgas = Unit.MAGICGAS;
                }
                else
                {
                    game.units[id].magicgas = 0;
                }
                break;
                case "magichaste":
                redomagic = true;
                game.units[id].magichaste+=value;
                if(game.units[id].magichaste>0)
                {
                    game.units[id].magichaste = Unit.MAGICHASTE;
                }
                else
                {
                    game.units[id].magichaste = 0;
                }
                break;
                case "magicfear":
                redomagic = true;
                game.units[id].magicfear+=value;
                if(game.units[id].magicfear>0)
                {
                    game.units[id].magicfear = Unit.MAGICFEAR;
                }
                else
                {
                    game.units[id].magicfear = 0;
                }
                break;
                case "magicshield":
                redomagic = true;
                game.units[id].magicshield+=value;
                if(game.units[id].magicshield>0)
                {
                    game.units[id].magicshield = Unit.MAGICSHIELD;
                }
                else
                {
                    game.units[id].magicshield = 0;
                }
                break;
                case "magicstorm":
                redomagic = true;
                game.units[id].magicstorm+=value;
                if(game.units[id].magicstorm>0)
                {
                    game.units[id].magicstorm = Unit.MAGICSTORM;
                }
                else
                {
                    game.units[id].magicstorm = 0;
                }
                break;
                case "magicsword":
                redomagic = true;
                game.units[id].magicsword += value;
                if(game.units[id].magicsword>0)
                {
                    game.units[id].magicsword = Unit.MAGICSWORD;
                }
                else
                {
                    game.units[id].magicsword = 0;
                }
                break;
                case "magicstealth":
                redomagic = true;
                game.units[id].magicstealth += value;
                if(game.units[id].magicstealth>0)
                {
                    game.units[id].magicstealth = Unit.MAGICSTEALTH;
                }
                else
                {
                    game.units[id].magicstealth = 0;
                }
                break;
                case "magicplant":
                redomagic = true;
                game.units[id].magicplant += value;
                if(game.units[id].magicplant>0)
                {
                    game.units[id].magicplant = Unit.MAGICPLANT;
                }
                else
                {
                    game.units[id].magicplant = 0;
                }
                break;
                case "magicwind":
                redomagic = true;
                game.units[id].magicwind += value;
                if(game.units[id].magicwind>0)
                {
                    game.units[id].magicwind = Unit.MAGICWIND;
                }
                else
                {
                    game.units[id].magicwind = 0;
                }
                break;
                //end-----------------//28mar2021
                case "highfirerate": //25Feb2021
                game.units[id].highfirerate += value;
                break;
                //start-------------//7mar2021
                case "mob":
                game.units[id].mob += value;
                break;
                case "hatred":
                game.units[id].hatred += value;
                break;
                case "craftsman":
                game.units[id].craftsman += value;
                break;
                case "planar":
                game.units[id].planar += value;
                break;
                case "slow":
                game.units[id].slow += value;
                break;
                case "woodsman":
                game.units[id].woodsman += value;
                break;
                case "stupid":
                game.units[id].stupid += value;
                break;
                case "frenzy":
                game.units[id].frenzy += value;
                break;
                //end---------------//7mar2021
                case "shocktroops":
                game.units[id].shock += value;
                break;
                case "shock": //2sep2021
                game.units[id].shock += value;
                break;//2sep2021
                case "stealth":
                game.units[id].stealth += value;
                break;
                case "damagex":
                game.units[id].damagex += value;
                break;
                case "fearsome":
                game.units[id].fearsome += value;
                break;
                case "leader":
                game.units[id].leader += value;
                break;
                case "bounddemon"://12jul2021
                game.units[id].bounddemon += value;
                break;
                case "bossmonster":
                game.units[id].bossmonster += value;
                break;
                case "flammable":
                game.units[id].flammable += value;
                break;
                case "regeneration":
                game.units[id].regeneration += value;
                break;
                case "zombie":
                game.units[id].zombie += value;
                break;
                case "evilfire":
                game.units[id].firespell -= value;
                break;
                case "sacrificial":
                game.units[id].sacrificial += value;
                break;
                case "cansacrifice":
                game.units[id].cansacrifice += value;
                break;
                case "animosity":
                game.units[id].animosity += value;
                break;
            }
            if(redomagic)
            {
                game.units[id].magicarray = new int[17];
                int m = 0;
                if(game.units[id].magicrelease>0)//3may2021
                {
                    game.units[id].magicarray[m] = game.units[id].magicrelease;
                    m++;
                }
                if(game.units[id].magictransform>0)//3may2021
                {
                    game.units[id].magicarray[m] = game.units[id].magictransform;
                    m++;
                }
                //start--------------//9apr2021
                if(game.units[id].magicleader>0)//01apr2021
                {
                    game.units[id].magicarray[m] = game.units[id].magicleader;
                    m++;
                }
                if(game.units[id].magiczombiemaster>0)//01apr2021
                {
                    game.units[id].magicarray[m] = game.units[id].magiczombiemaster;
                    m++;
                }
                //end----------------//9apr2021
                if(game.units[id].magicdoom>0)//01apr2021
                {
                    game.units[id].magicarray[m] = game.units[id].magicdoom;
                    m++;
                }
                if(game.units[id].magicdef>0)//01apr2021
                {
                    game.units[id].magicarray[m] = game.units[id].magicdef;
                    m++;
                }
                if(game.units[id].magicfrenzy>0)//01apr2021
                {
                    game.units[id].magicarray[m] = game.units[id].magicfrenzy;
                    m++;
                }
                if(game.units[id].magicweb>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicweb;
                    m++;
                }
                
                if(game.units[id].magicfear>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicfear;
                    m++;
                }
                if(game.units[id].magicgas>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicgas;
                    m++;
                }
                if(game.units[id].magichaste>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magichaste;
                    m++;
                }
                if(game.units[id].magicplant>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicplant;
                    m++;
                }
                if(game.units[id].magicshield>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicshield;
                    m++;
                }
                if(game.units[id].magicstealth>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicstealth;
                    m++;
                }
                if(game.units[id].magicstorm>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicstorm;
                    m++;
                }
                if(game.units[id].magicsword>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicsword;
                    m++;
                }
                if(game.units[id].magicwind>0)
                {
                    game.units[id].magicarray[m] = game.units[id].magicwind;
                    m++;
                }
            }
        }
        
        ///////////////////Method Definition///////////////
        public static bool IsUnitEnabled(Game game,int templateid)
        {
            if(!Config.USETECH)
            {
                return true;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                if(game.techs[i].researched>0)
                {
                    if(game.techs[i].unittemplatesenabled!=null)
                    {
                        for(int j=0;j<game.techs[i].unittemplatesenabled.Length;j++)
                        {
                            if(game.techs[i].unittemplatesenabled[j]==templateid)
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
        ///////////////////Method Definition///////////////
        public static void parseeffect(Game game,int id)
        {
            string effect = game.techs[id].effectname;
            string[] effects = effect.Split("|");
            if(effects!=null)
            {
                for(int i=0;i<effects.Length;i++)
                {
                    string[] etype = effects[i].Split("_");
                    if(etype!=null)
                    {
                        if(etype.Length==2)
                        {
                            switch(etype[0])
                            {
                                case "EU":
                                Array.Resize(ref game.techs[id].unittemplatesenabled,game.techs[id].unittemplatesenabled.Length + 1);
                                game.techs[id].unittemplatesenabled[game.techs[id].unittemplatesenabled.Length - 1] = Unit.findtemplatebyname(game,etype[1]);
                                break;
                                case "BM":
                                Array.Resize(ref game.techs[id].unittemplatesmove,game.techs[id].unittemplatesmove.Length + 1);
                                game.techs[id].unittemplatesmove[game.techs[id].unittemplatesmove.Length - 1] = Unit.findtemplatebyname(game,etype[1]);
                                break;
                                case "BA":
                                Array.Resize(ref game.techs[id].unittemplatesatt,game.techs[id].unittemplatesatt.Length + 1);
                                game.techs[id].unittemplatesatt[game.techs[id].unittemplatesatt.Length - 1] = Unit.findtemplatebyname(game,etype[1]);
                                break;
                                case "BD":
                                Array.Resize(ref game.techs[id].unittemplatesdef,game.techs[id].unittemplatesdef.Length + 1);
                                game.techs[id].unittemplatesdef[game.techs[id].unittemplatesdef.Length - 1] = Unit.findtemplatebyname(game,etype[1]);
                                break;
                                case "BH":
                                Array.Resize(ref game.techs[id].unittemplateshp,game.techs[id].unittemplateshp.Length + 1);
                                game.techs[id].unittemplateshp[game.techs[id].unittemplateshp.Length - 1] = Unit.findtemplatebyname(game,etype[1]);
                                break;
                            }
                        }
                        if(etype.Length==3)
                        {
                            switch(etype[0])
                            {
                                case "BZ":
                                Array.Resize(ref game.techs[id].unittemplatesability,game.techs[id].unittemplatesability.Length + 2);
                                game.techs[id].unittemplatesability[game.techs[id].unittemplatesability.Length - 2] = etype[1];
                                game.techs[id].unittemplatesability[game.techs[id].unittemplatesability.Length - 1] = etype[2];
                                break;
                            }
                        }
                    }
                }
            }
            
        }
        
        ///////////////////Method Definition///////////////
        public Tech()
        {
                name = "";
                displayname = "";
                techclass = "";//23sep2021
                purchaseguilink = -1;//23sep2021
                guiactionid = -1;//23sep2021
                description = new string[3];
                description[0] = "";
                description[1] = "";
                description[2] = "";
                unittemplatesenabled = new int[0];
                unittemplatesatt = new int[0];
                unittemplatesdef = new int[0];
                unittemplateshp = new int[0];
                unittemplatesmove = new int[0];
                unittemplatesability = new string[0];
                researching = 0;
                tooltip = "";
                guilinkid = -1;
                researchtime = 0;
                completedtime = -1;
                timeleft = -1;
                researched = 0;
                img = -1;
                imgframe = 0;
                imgfile = "";
                cw = 0;
                ch = 0;
                nw = 1;
                nh = 1;
                effectname = "";
                effectint = 0;
                id = -1;
        }
        
        ///////////////////Method Definition///////////////
        public void reset(Game game,int id,bool missionstart)
        {
            if(!missionstart)
            {
                game.techs[id].name = "";
                game.techs[id].displayname = "";
                game.techs[id].techclass = "";//23sep2021
                game.techs[id].purchaseguilink =-1;//23sep2021
                game.techs[id].guiactionid = -1;//23sep2021
                game.techs[id].description = new string[3];
                game.techs[id].description[0] = "";
                game.techs[id].description[1] = "";
                game.techs[id].description[2] = "";
                game.techs[id].tooltip = "";
                game.techs[id].guilinkid = -1;
                game.techs[id].researchtime = 0;
                game.techs[id].timeleft = -1;
                game.techs[id].researched = 0;
                game.techs[id].completedtime = -1;
                game.techs[id].img = -1;
                game.techs[id].imgframe = 0;
                game.techs[id].imgfile = "";
                game.techs[id].cw = 0;
                game.techs[id].ch = 0;
                game.techs[id].nw = 1;
                game.techs[id].nh = 1;
                game.techs[id].effectname = "";
                game.techs[id].effectint = 0;
                game.techs[id].id = id;
                game.techs[id].unittemplatesenabled = new int[0];
                game.techs[id].unittemplatesatt = new int[0];
                game.techs[id].unittemplatesdef = new int[0];
                game.techs[id].unittemplateshp = new int[0];
                game.techs[id].unittemplatesmove = new int[0];
                game.techs[id].unittemplatesability = new string[0];
                game.techs[id].researching = 0;
            }
            else
            {
                TECHUNITSELECTED = false;
                TECHUNITIDSELECTED = -1;
                TARGETUID = -1;
                ADDSUBTRACT = 0;
                game.techs[id].timeleft = -1;
                game.techs[id].researched = 0;
                game.techs[id].completedtime = -1;
                game.techs[id].researching = 0;
            }
        }
        
        public static void updateall(Game game)
        {
            if(!Config.USETECH)
            {
                return;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                game.techs[i].update(game);
            }
            if((game.frame % 179)==0)
            {
                //every 3 seconds....the AI will try and learn a new tech....
                //if it is not already researching one.....
                for(int i=0;i<game.techs.Length;i++)
                {
                    if(game.techs[i].faction!=Game.PLAYERFACTION)
                    {
                        if(game.techs[i].timeleft<0)
                        {
                            //not researched...and not the player faction, nor currently researching....
                            //therefore.....
                            //check that we have the necessary unit in the game to research it....
                            for(int u=0;u<Unit.MAXINDEX;u++)
                            {
                                //if(game.units[u].hp>0 && game.units[u].faction==game.techs[i].faction && game.units[u].techguilinkid==game.techs[i].guilinkid)//26feb2022
                                for(int tt=0;tt<game.units[u].techguilinkid.Length;tt++)//26feb2022
                                {
                                    if(game.units[u].hp>0 && game.units[u].faction==game.techs[i].faction && game.units[u].techguilinkid[tt]==game.techs[i].guilinkid)//26feb2022
                                    {
                                        Tech.StartResearch(game,i,game.techs[i].faction);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        
        public static void unpurchase(Game game)//24sep2021
        {
            if(!Config.USETECH)
            {
                return;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                game.techs[i].purchased = 0;
            }
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].command.IndexOf("attackaction")>=0)
                {
                    game.gui[i].action = Gui.ACTION_NONE;
                }
            }
        }
        
        public static void resetall(Game game)
        {
            if(!Config.USETECH)
            {
                return;
            }
            for(int i=0;i<game.techs.Length;i++)
            {
                game.techs[i].reset(game,i,true);
            }
        }
        
        ///////////////////Method Definition///////////////
        public void update(Game game)
        {
            //start-----------//23sep2021
            if(goldcost>0 && purchased<=0)
            {
                timeleft = -1;
                completedtime = -1;
                researched = -1;
                researching = 0;
                return;
            }
            if(temporary>0 && attackaction>0)
            {
                //player is using this tech to perform an attack.....
                //therefore
                if(temporarytime>0)
                {
                    temporarytime--;
                    researched = 1;
                    completedtime = COMPLETEDTIME;
                    timeleft = 0;
                    researching = 0;
                    //pick a firetargeti value......
                    Unit.SelectNearestTarget(game,Unit.GetPlayer(game));//24sep2021
                }
                else
                {
                    timeleft = -1;
                    completedtime = -1;
                    researched = -1;
                    researching = 0;
                }
                return;
            }
            //end-------------//23sep2021
            if(timeleft==0)
            {
                researched = 1;
                completedtime = COMPLETEDTIME;
            }
            if(timeleft>0 && researching>0)
            {
                timeleft--;
            }
            if(completedtime>0)
            {
                completedtime--;
                COMPLETEDID = id;
            }
            else
            {
                COMPLETEDID = -1;
            }
        }
        //start----------23sep2021
    public static int GetTechIdFromAction(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        if(game.techs==null)
        {
            return -1;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                return i;
            }
        }
        return -1;
    }
    //
    public static int ChooseTechForEmptySlot(Game game)
    {
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].purchased>0 && game.techs[i].attackaction>0)
            {
                bool found = false;
                for(int g=0;g<game.gui.Length;g++)
                {
                    if(game.gui[g].action==game.techs[i].guiactionid && game.gui[g].command.IndexOf("attackaction")>=0)
                    {
                        //don't overwrite existing if filling an empty slot....
                        found = true;
                        break;
                    }
                }
                if(found)
                {
                    continue;
                }
                return game.techs[i].guiactionid;
            }
        }
        return Gui.ACTION_NONE;
    }

    //
    public static int GoldCost(Game game,int id)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        return game.techs[id].goldcost;
    }

    public static int GoldCostGui(Game game,int action)
    {
        if(!Config.USETECH)
        {
            return 0;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            //Console.WriteLine("Costs:"+game.techs[i].displayname+" "+game.techs[i].goldcost+ " actionid:"+action+" tech action:"+game.techs[i].guiactionid);
            if(action==game.techs[i].guiactionid)
            {
                return game.techs[i].goldcost;
            }
        }
        return 0;
    }
    
    public static int SelectFromGuiToPurchase(Game game,int gid)
    {
        if(!Config.USETECH)
        {
            return 0;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].purchaseguilink==gid)
            {
                return SelectToPurchase(game,i);
            }
        }
        return 0;
    }
    
    public static int SelectToPurchase(Game game, int id)
    {
        if(!Config.USETECH)
        {
            return 0;
        }
        if(id<0 || id>=game.techs.Length)
        {
            return 0;
        }
        if(game.techs[id].purchased>0)
        {
            return 0;
        }
        if(game.techs[id].goldcost<=0)
        {
            return 0;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].goldcost>0)
            {
                game.techs[i].selectedtopurchase = 0;
            }
        }
        game.techs[id].selectedtopurchase = 1;
        if(game.techs[id].unlimited>0)
        {
            game.techs[id].selectedtopurchase = -1;
        }
        return game.techs[id].selectedtopurchase;
    }
    
    public static int PurchaseGuiSelected(Game game)
    {
        int limit = 0;
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].selectedtopurchase!=0)
            {
                Tech.Purchase(game, i);
                limit = game.techs[i].selectedtopurchase;
            }
        }
        //Console.WriteLine("limit:"+limit);
        return limit;
    }
    
    public static void Purchase(Game game,int id)
    {
        if(!Config.USETECH)
        {
            return;
        }
        if(game.units==null)
        {
            return;
        }
        if(game.techs[id].purchased>0)
        {
            return;
        }
        for(int j=0;j<game.units.Length;j++)
        {
            if(game.units[j].faction==Game.PLAYERFACTION && game.units[j].hp>0 && game.units[j].gold>=game.techs[id].goldcost)
            {
                game.units[j].gold-=game.techs[id].goldcost;
                if(game.techs[id].name=="healthpotion")
                {
                    game.units[j].healthpotions++;
                    break;
                }
                if(game.techs[id].name=="manapotion")
                {
                    game.units[j].manapotions++;
                    break;
                }
                if(game.techs[id].name=="bothpotion")
                {
                    game.units[j].bothpotions++;
                    break;
                }
                
                game.techs[id].purchased=1;
                game.techs[id].researched = -1;
                game.techs[id].completedtime = -1;
                game.techs[id].timeleft = -1;
                game.techs[id].researching = 0;
                break;
            }
        }
    }

    public static void DrinkPotion(Game game,int pid,string type)
    {
        if(type=="health")
        {
            if(game.units[pid].healthpotions>0)
            {
                game.units[pid].healthpotions--;
                game.units[pid].hp+=PotionStrength(game,"healthpotion");
                if(game.units[pid].hp>game.units[pid].basehp)
                {
                    game.units[pid].hp = game.units[pid].basehp;
                }
            }
        }
        if(type=="mana")
        {
            if(game.units[pid].manapotions>0)
            {
                game.units[pid].manapotions--;
                game.units[pid].mana+=PotionStrength(game,"manapotion");
                if(game.units[pid].mana>game.units[pid].basemana)
                {
                    game.units[pid].mana = game.units[pid].basemana;
                }
            }
        }
        if(type=="both")
        {
            if(game.units[pid].bothpotions>0)
            {
                game.units[pid].bothpotions--;
                game.units[pid].hp+=PotionStrength(game,"bothpotion");
                if(game.units[pid].hp>game.units[pid].basehp)
                {
                    game.units[pid].hp = game.units[pid].basehp;
                }
                game.units[pid].mana+=PotionStrength(game,"bothpotion");
                if(game.units[pid].mana>game.units[pid].basemana)
                {
                    game.units[pid].mana = game.units[pid].basemana;
                }
            }
        }
    }
    
    public static int PotionStrength(Game game,string type)
    {
        if(!Config.USETECH)
        {
            return 0;
        }
        if(game.techs==null)
        {
            return 0;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].name==type)
            {
                return game.techs[i].effectint;
            }
        }
        return 0;
    }
    
    public static int GetImage(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        if(game.techs==null)
        {
            return -1;
        }
        
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                return game.techs[i].img;
            }
        }
        return -1;
    }
    //
    public static int GetImageIndex(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        if(game.techs==null)
        {
            return -1;
        }
        
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                return game.techs[i].imgframe;
            }
        }
        return -1;
    }
    
    public static int GetSaleImage(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        if(game.techs==null)
        {
            return -1;
        }
        
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                return game.techs[i].saleimg;
            }
        }
        
        return -1;
    }
    
    public static int GetSaleImageIndex(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return -1;
        }
        if(game.techs==null)
        {
            return -1;
        }
        
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                return game.techs[i].saleimgframe;
            }
        }
        
        return -1;
    }
    
    public static string[] GetDescription(Game game,int guiactionid)
    {
        string[] desc = new string[10];
        for(int i=0;i<10;i++)
        {
            desc[i] = "";
        }
        if(!Config.USETECH)
        {
            return desc;
        }
        if(game.techs==null)
        {
            return desc;
        }
        
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                for(int k=0;k<game.techs[i].description.Length;k++)
                {
                    desc[k] = game.techs[i].description[k];
                }
            }
        }
        return desc;
    }
    
    public static bool IsActionPurchased(Game game,int guiactionid)
    {
        if(!Config.USETECH)
        {
            return false;
        }
        if(game.techs==null)
        {
            return false;
        }
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==guiactionid)
            {
                if(game.techs[i].purchased>0)
                {
                    return true;
                }
            }
        }
        return false;
    }
    
    public static void ActivateAttack(Game game,int id)
    {
        if(!Config.USETECH)
        {
            return;
        }
        if(game.techs==null)
        {
            return;
        }
        int pid = Unit.GetPlayer(game);
        if(pid==-1)
        {
            return;
        }
        //Console.WriteLine("Attack Button Pressed");
        for(int i=0;i<game.techs.Length;i++)
        {
            if(game.techs[i].guiactionid==id)
            {
                if(game.techs[i].attackaction>0)
                {
                    if(game.units[pid].mana>=game.techs[i].manacost)
                    {
                        game.units[pid].mana-=game.techs[i].manacost;
                    }
                    else
                    {
                        return;
                    }
                    if(game.techs[i].temporary>0)
                    {
                        game.techs[i].temporarytime = game.techs[i].TEMPORARYTIME;
                    }
                    //the player will activate this option.....
                    if(game.units[pid].animmode!=Unit.ANIMMODE_ATTACK && game.units[pid].animmode!=Unit.ANIMMODE_ATTACK2 && game.units[pid].animmode!=Unit.ANIMMODE_ATTACK3)
                    {
                        game.units[pid].firetargeti = -1; //reset the player's attack choice....
                        game.units[pid].orderframe = 0;
                        game.techs[i].update(game);
                    }
                }
            }
        }
    }
    
    public static void RemoveItemFromStore(Game game,int g)
    {
        if(!Config.USETECH)
        {
            return;
        }
        if(game.techs==null)
        {
            return;
        }
        if(game.gui==null)
        {
            return;
        }
        if(g<0 || g>game.gui.Length)
        {
            return;
        }
        game.gui[g].action = Gui.ACTION_NONE;
    }
    
    public static void ChooseItemForStore(Game game,int g,string name,int mincost,int maxcost)
    {
        if(!Config.USETECH)
        {
            return;
        }
        if(game.techs==null)
        {
            return;
        }
        if(game.gui==null)
        {
            return;
        }
        if(g<0 || g>=game.gui.Length)
        {
            return;
        }
        if(game.gui[g].command.IndexOf("buydescription")>=0)
        {
            return;
        }
        int count = 0;
        int index = 0;
        //Console.WriteLine("Choose Item For Store:"+name);
        for(int i=0;i<game.techs.Length;i++)
        {
            if(mincost!=-1)
            {
                if(game.techs[i].goldcost<mincost || game.techs[i].goldcost>maxcost)
                {
                    continue;
                }
            }
            if(game.techs[i].name==name)
            {
                game.gui[g].action = game.techs[i].guiactionid;
                break;
            }
            if(game.techs[i].techclass==name)
            {
                count++;
            }
        }
        //Console.WriteLine("Item Count:"+count);
        if(count>0)
        {
            index = Functions.rand(0,1000);
            if(index<0)
            {
                index*=-1;
            }
            index%=count;
            index++;
            //Console.WriteLine("Item Index:"+index);
            for(int i=0;i<game.techs.Length;i++)
            {
                if(mincost!=-1)
                {
                    if(game.techs[i].goldcost<mincost || game.techs[i].goldcost>maxcost)
                    {
                        continue;
                    }
                }
                if(game.techs[i].techclass==name)
                {
                    index--;
                    if(index<=0)
                    {
                        game.gui[g].action = game.techs[i].guiactionid;
                        break;
                    }
                }
            }
            
        }
        //Console.WriteLine("Gui Item Action Buy ID:"+game.gui[g].action);
    }
    
    //end----23sep2021
    }
    
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Units //21apr2021
    {
        public Unit[] unit;
        
        public Units(Game game)
        {
            unit = new Unit[Unit.MAXUNITS];
            for(int i=0;i<unit.Length;i++)
            {
                unit[i] = new Unit(game);
                unit[i].reset(game,i);
                //blank canvas.....
            }
        }
        
    }
    
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Unit
    {
        public static bool COPYUNIT = false;//21apr2021
        public static int SPELLCHECK = 5;
        public static int GUARDRANGE = 150;
        public static int MAXWALKHEIGHTDIFF = 16;
        public static int CONTROLRATE = 5;
        public static int MAXUNITS = 200 * Config.FACTOR;
        public static int MAXINDEX = 0; //26mar2021
        public static int MAXDEPTH = 20;
        public static int MAXPATHFIND = 50;
        public static int PRECALCLIMIT = 10;
        public static int RETREATDEATH = 60 * 10;
        public static int PATHSTEP = 1;
        public static int MAXBUFFATT = 20;
        public static int MAXDEADTIME = 60;
        public int[] checkedgrid;
        public static int[] circles = null;//2jun2021
        public static int circlesmax = 0;//2jun2021
        //
        public static int DIRN_DOWN = 0;
        public static int DIRN_DOWNLEFT = 1;
        public static int DIRN_LEFT = 2;
        public static int DIRN_UPLEFT = 3;
        public static int DIRN_UP = 4;
        public static int DIRN_UPRIGHT = 5;
        public static int DIRN_RIGHT = 6;
        public static int DIRN_DOWNRIGHT = 7;
        public int dirn;
        public int odirn;
        public int displaydirn; //29may2021
        public static int DIRNDELAY = 10;
        public int dirntime;
        public int timesincelastpath;
        public int framesleft;//9sep2021
        public bool mirrorleftright;
        public float scale;//25sep2021
        public string controlmode;//24sep2021
        public static int CRPG = 0;//25sep2021
        public int offy;
        public int isdead;
        public int offx;//20apr2021
        public int[] offxa;//20apr2021
        public int[] offya;//20apr2021
        public bool autocalcedoffsets;//20apr2021
        //
        public string name;
        public string displayname; //13mar2021
        public string charactername;//10sep2021
        public int displaycharactername;//10sep2021
        //
        public static int HUMAN = 1;
        public static int UNDEAD = 2;
        public static int DEMON = 3;
        public static int REBELHUMAN = 5;
        public static int NULLFACTION = 99;
        public static int UNDEADWALKRATE = 1;
        public static int ANIMOSITY = 101; //7mar2021
        //start-----//3may2021
        //transporting units
        public int transportcapacity;
        public int transportsize;
        public int[] transportarray;
        public int transportedbyid;
        //end------//3may2021
        public int faction;
        public int team;
        public int id;
        public int templateid;
        public int deaths;
        public int kills;
        public int dieonce;//13sep2021
        public int creates;
        public int prevdeaths;
        public int prevcreates;
        public int prevkills;
        public int dispdeaths;
        public int dispkills;
        public int dispcreates;
        public int groupid;
        public int aiselectframe;//17apr2021
        public int basemana;//23sep2021
        public int mana;//23sep2021
        public int manarate;//23sep2021
        public int healthpotions;//23sep2021
        public int manapotions;//23sep2021
        public int bothpotions;//23sep2021
        public int gold;//23sep2021
        public int canpickup;//23sep2021
        public int guiattackdisplaylimit;//23sep2021
    
        //
        public int cat; //sprite atlas resource
        public int cathires;//sprite atlas resource double resolution....//9apr2021
        public int dropshadow;//25sep2021
        public string catfile;
        public string cathiresfile;//9arp2021
        public int framesperdirn;//
        public int nodirn;
        public int cw;
        public int ch;
        public static int AI_DEFAULT = 0;
        public static int AI_ASSAULT = 1;
        public static int AI_EXTRAASSAULT = 2;
        public static int RALLYCHANCE = 100; //out of 1000 - checked once per second while off screen.....
        public static int RALLYORDERCHANCE = 50; //9mar2021
        public int ai;
        //
        public bool infog;
        public bool retreat;
        public int retreatframe;
        public int livecount; //9mar2021
        public int olivecount; //9mar2021
        public int livecountframe;//9mar2021
        public int selectioncount; //22mar2021
        //
        //game stats
        public string[] description;
        public int basehp;
        public int hp;
        public int timedead;
        public int armour;
        public int damage;
        public int walkspeed;
        public int firetargeti;
        public int firerange;
        public int needlos;//15sep2021
        public int firerange2;
        public int damage2;
        public int splash; //2sep2021
        public int levelxp;
        public int xpvalue;
        public int xp;
        public int spellcaster;
        public int accuracy;//28feb2022
        public int prefermobiletargets;//18sep2021
        public int notabuffer; //15apr2021
        public int dustcloud;
        public int firespell;
        public int extragibbet;//18sep2021
        public int powerspell;
        public int healer;
        public int zombiemaster;
        public int banish; //12mar2021
        public int timid;
        public int hitandrun;
        public int brave;
        public int points;//17sep2021
        public int misfire; //28mar2021
        public int buildpenalty; //20mar2021
        public int spelldefense; //01apr2021
        public int spellability; //01apr2021
        public int ping; //16sep2021
        public int redping;//17sep2021
        //start----//22apr2022
        //zombieficator guns....
        public int infectchanceonkill;
        public int infectchanceonhit;
        public string infectinto;
        public int infected;
        //end-----///22apr2022
        
        
        //start-------//3may2021
        public int magictransform;
        public string transforminto;
        public string transformrequires;
        public static int MAGICTRANSFORM = 3025;
        public static int MAGICRELEASE = 3026;
        public int magicrelease;
        //end---------//3may2021
        //start---------------//28mar2021
        public int magicfear;
        public int magicgas;
        public int magichaste;
        public int magicplant;
        public int magicshield;
        public int magicstealth;
        public int magicstorm;
        public int magicsword;
        public int magicwind;
        public int magicweb;
        public int magicdef;//01apr2021
        public int magicdoom;//01apr2021
        public int magicfrenzy;//01apr2021
        public int magiczombiemaster;//9apr2021
        public int magicleader;//9apr2021
        public int[] magicarray;
        public static int MAGICFEAR = 3010;
        public static int MAGICGAS = 3011;
        public static int MAGICHASTE = 3012;
        public static int MAGICPLANT = 3013;
        public static int MAGICSHIELD = 3014;
        public static int MAGICSTEALTH = 3015;
        public static int MAGICSTORM = 3016;
        public static int MAGICSWORD = 3017;
        public static int MAGICWIND = 3018;
        public static int MAGICWEB = 3019;//29mar2021
        public static int MAGICDEF = 3020;//01apr2021
        public static int MAGICDOOM = 3021;//01apr2021
        public static int MAGICFRENZY = 3022;//01apr2021
        public static int MAGICZOMBIEMASTER = 3023;//9apr2021
        public static int MAGICLEADER = 3024;//9apr2021
        public bool casting;
        //end-----------------//28mar2021
        //start-------------//7mar2021
        public int mob;
        public int hatred;
        public int craftsman;
        public int planar;
        public int dieonplace;//21feb2022
        public string deathanim;//21feb2022
        public int slow;
        public int woodsman;
        public int stupid;
        public int frenzy;
        //end---------------//7mar2021
        public int shock;
        public bool shocked;
        public int stealth;
        public int damagex;
        public int fearsome;
        public int leader;
        public int bounddemon; //12jul2021
        public int highfirerate; //25Feb2021
        //public int fearful;
        public int bossmonster;
        public int flammable;
        public int ecat;
        public int fcat;
        public string ecatfile;
        public string fcatfile;
        public int controlpoint;
        public int controller;
        public int regeneration;
        public int zombie;
        public int sacrificial;
        public int cansacrifice;
        public int animosity;
        public int firebullet;
        public string spawner;
        public int spawnertemplateid = -1;//26feb2022
        public string spawnerconstraint; //9sep2021
        public string displayspawner; //13mar2021
        public int spawnertime;
        public int spawnercount;
        //
        //
        public bool buffed; //21mar2021
        public bool cursed; //21mar2021
        public int defendx; //9mar2021
        public int defendy; //9mar2021
        public int formationx;//14apr2021
        public int formationy;//14apr2021
        public int x;
        public int y;
        public int height;
        
        //flight stuff
        public int flightlevel;//4may2021
        public int canfly;//4may2021
        public int canflyandwalk;//4may2021
        public int canattackair;//4may2021
        //end of flight stuff
        
        public int tx;
        public int ty;
        public static int ORDERTIME = 300;
        public int orderframe;
        public int tmptx;
        public int tmpty;
        public int tmptframe;
        public int tmptattempts;
        public float angle;
        //
        public static int ANIMMODE_IDLE = 0;
        public static int ANIMMODE_WALK = 1;
        public static int ANIMMODE_ATTACK = 2;
        //
        public static int ANIMMODE_ATTACK2 = 3;
        public static int ANIMMODE_ATTACK3 = 4;
        public static int ANIMMODE_CAST = 3;
        public static int ANIMMODE_SPECIAL = 3;
        public static int ANIMMODE_SPECIAL2 = 4;
        public static int ANIMMODE_DEAD = 99; //25Feb2021
        public static int ANIMMODE_IDLE2 = 100; //28Feb2021
        public static int ANIMMODE_FLY = 10;//4may2021
        public static int ANIMMODE_FLYATTACK = 11;//4may2021
        //
        public int oanimmode;
        public int animmode;
        public int animrest;
        public int animframe;
        public int animspeed;
        public int animtime;//29sep2021
        //
        public int animmodeidleframestart;
        public int animmodeidleframeend;
        public int animmodeidle2framestart; //28Feb2021
        public int animmodeidle2frameend; //28Feb2021
        public int animmodewalkframestart;
        public int animmodewalkframeend;
        public int animmodeattframestart;
        public int animmodeattframeend;
        public int animmodeatt2framestart;
        public int animmodeatt2frameend;
        public int animmodeatt3framestart;
        public int animmodeatt3frameend;
        public int animmodedeadframestart; //25Feb2021
        public int animmodedeadframeend;    //25Feb2021
        public int animmodeflyframestart;//4may2021
        public int animmodeflyframeend;//4may2021
        public int animmodeflyattackframestart;//4may2021
        public int animmodeflyattackframeend;//4may2021
        
        //
        public bool drawn;
        //
        public static int SELECTIONSTART = 1;
        public static int SELECTIONFROZEN = 2;
        public static int SELECTIONENEMY = -1;
        public static int SELECTIONNONE = 0;
        public int selected;
        public int selectedframe;
        /////////////////////////////
        //Audio
        public bool onscreen;
        public bool ronscreen; //replay onscreen value - 25apr2021
        public int[] impactfx;
        public int[] attackfx;
        public int[] deathfx; //28jul2021
        public int[] targetfx;
        public int[] magicfx;
        public int[] ackfx;
        public int[] selectfx;
        /////////////////////////////
        //Tech
        //start----------------//2sep2021
        public int[] techguilinkid;
        //26feb2022 I'm thinking techguilinkid should be an array in order to allow units to have more than one
        //tech item assigned to them....otherwise it is a bit silly allowing only a single tech button per unit
        public int unresearchedbydefault;
        //end------------------//2sep2021

        
///////////////////Method Definition///////////////
        public static void SelectNearestTarget(Game game,int id)//24sep2021
        {
            if(id<0 || id>=game.units.Length)//25sep2021
            {
                return;
            }
            int target = -1;
            int mindist = 9999;
            int dist = 0;
            int[] searched = new int[Map.MAXX * Map.MAXY];
            //Console.WriteLine("Selecting Nearest");
            for(int c=1;c<10;c++)
            {
                if(c > 1 + (game.units[id].firerange / Map.GRIDW))
                {
                    continue;
                }
                for(int cx=game.units[id].x / Map.GRIDW - c;cx<=game.units[id].x / Map.GRIDW + c;cx++)
                {
                    for(int cy=game.units[id].y / Map.GRIDH - c;cy<=game.units[id].y / Map.GRIDH + c ;cy++)
                    {
                        if(cx>=0 && cx<Map.MAXX && cy>=0 && cy<Map.MAXY)
                        {
                            if(searched[cx + cy * Map.MAXX]==1)
                            {
                                continue;
                            }
                            searched[cx + cy * Map.MAXX] = 1;
                        }
                        else
                        {
                            continue;
                        }
                        target = Map.cellunit(cx * Map.GRIDW,cy * Map.GRIDH);
                        if(target!=-1)
                        {
                            if(game.units[target].hp>0 && game.units[target].faction!=game.units[id].faction && game.units[target].faction!=Unit.NULLFACTION)
                            {
                                dist = (int)(Functions.abs(cx - game.units[id].x / Map.MAXX) + Functions.abs(cy - game.units[id].y / Map.MAXY));
                                if(dist < mindist )
                                {
                                    if(game.units[id].needlos>0)//15sep2021
                                    {
                                        if(los(game,id,target))
                                        {
                                            mindist = dist;
                                            game.units[id].firetargeti = target;
                                            //Console.WriteLine("Selecting Nearest:"+game.units[target].dname());
                                        }
                                    }
                                    else//15sep2021
                                    {
                                        mindist = dist;
                                        game.units[id].firetargeti = target;
                                        //Console.WriteLine("Selecting Nearest:"+game.units[target].dname());
                                    }
                                }
                            }
                        }
                    }
                }
                if(game.units[id].firetargeti!=-1)
                {
                    break;
                }
            }
        }
        
///////////////////Method Definition///////////////        
        public static int PlayerGold(Game game)//23sep2021
        {
            if(game.units==null)
            {
                return 0;
            }
            int gold = 0;
            for(int i=0;i<game.units.Length;i++)
            {
                if(game.units[i].faction==Game.PLAYERFACTION && game.units[i].hp>0)
                {
                    if(game.units[i].gold>0)
                    {
                        gold+=game.units[i].gold;
                    }
                }
            }
            return gold;
        }

///////////////////Method Definition///////////////        
        public static int GetPlayer(Game game)//23sep2021
        {
            if(game==null)
            {
                return -1;
            }
            if(game.units==null)
            {
                return -1;
            }
            for(int i=0;i<game.units.Length;i++)
            {
                if(game.units[i].faction==Game.PLAYERFACTION && game.units[i].hp>0)
                {
                    return i;
                }
            }
            return -1;
        }
        
///////////////////Method Definition///////////////        
        public static void SaveScore(Game game,int mid)//17sep2021
        {
            int count = 0;
            for(int i=0;i<game.units.Length;i++)
            {
                if(game.templates[game.units[i].templateid].walkspeed>0 && game.units[i].hp>0 && game.units[i].faction==Game.PLAYERFACTION)
                {
                    count+=game.units[i].points;
                }
            }
            LocalStorage.setitem("missionscore"+mid,""+count);

            Game.scoredirty = true;//18sep2021
        }
        
///////////////////Method Definition///////////////
        public static bool SpawnerCanBuild(Game game,string constraint,int tid)//9sep2021
        {
            if(Trigger.VARIABLE[Trigger.TYPE_POINTS]<game.templates[tid].points)//23feb2022
            {
                if(game.templates[tid].faction==Game.PLAYERFACTION)//25apr2022
                {
                    return false;
                }
            }
            if(constraint=="*")
            {
                return true;
            }
            string[] constraints = constraint.Split("|");
            if(constraints==null)
            {
                return false;
            }
            if(constraints.Length==0)
            {
                return false;
            }
            for(int i=0;i<constraints.Length;i++)
            {
                if(constraints[i]==game.templates[tid].name)
                {
                    return true;
                }
            }
            return false;
        }
        
///////////////////Method Definition///////////////
        public static bool TransportingUnits(Game game,int i)//3may2021
        {
            if(game.units[i].transportarray==null)
            {
                return false;
            }
            if(game.units[i].transportcapacity>0)
            {
                for(int k=0;k<game.units[i].transportarray.Length;k++)
                {
                    if(game.units[i].transportarray[k]!=-1)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

///////////////////Method Definition///////////////
        public static void GetInTransport(Game game,int i,int j)//3may2021
        {
            //i = transport
            //j = non transport
            if(game.units[i].transportarray==null)
            {
                return;
            }
            if(game.units[i].hp<=0 || game.units[j].hp<=0)
            {
                return;
            }
            if(game.units[i].transportcapacity<=0)
            {
                return;
            }
            if(game.units[j].canfly>0)//4may2021
            {
                return;
            }
            if(game.units[j].flightlevel!=-1)//4may2021
            {
                return;
            }
            //if our distance is further than 2 grid squares then disallow as well
            //if(Functions.abs(game.units[i].x - game.units[j].x)>Map.GRIDW * 2 || Functions.abs(game.units[i].y - game.units[j].y)>Map.GRIDH *2)//3mar2022
            if(Functions.abs(game.units[i].x - game.units[j].x)>Map.GRIDW * 3 || Functions.abs(game.units[i].y - game.units[j].y)>Map.GRIDH *3)//3mar2022//additional grid distances...
            {
                return;
            }
            int numinside = 0;
            for(int k=0;k<game.units[i].transportarray.Length;k++)
            {
                int nid = game.units[i].transportarray[k];
                if(nid!=-1)
                {
                    numinside+=game.units[nid].transportsize;
                }
            }
            if(numinside>=game.units[i].transportcapacity)
            {
                return;
            }
            for(int k=0;k<game.units[i].transportarray.Length;k++)
            {
                int nid = game.units[i].transportarray[k];
                if(nid==-1)
                {
                    if(Map.removeunit(j,game.units[j].x,game.units[j].y))
                    {
                        game.units[i].transportarray[k] = j;
                        game.units[j].transportedbyid = i;
                        break;
                    }
                }
            }
        }
        
///////////////////Method Definition///////////////
        public static void DeployUnits(Game game,int i)//3may2021
        {
            //i is the transporter unit
            //we might take more than one frame....especially if it is crowded around us....
            //
            if(game.units[i].transportarray==null)
            {
                return;
            }
            if(game.units[i].transportcapacity>0)
            {
                for(int k=0;k<game.units[i].transportarray.Length;k++)
                {
                    if(game.units[i].transportarray[k]!=-1)
                    {
                        int nid = game.units[i].transportarray[k];
                        if(game.units[nid].hp>0)
                        {
                            if(game.units[nid].transportedbyid==i)
                            {
                                //try and drop us out of the transport......
                                bool foundspot = false;
                                for(int x=game.units[i].x - Map.GRIDW * 2;x<=game.units[i].x + Map.GRIDW * 2;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * 2;y<=game.units[i].y + Map.GRIDH * 2;y+=Map.GRIDH)
                                    {
                                        if(Map.cellunit(x,y)==Map.VACANT)
                                        {
                                            foundspot = true;
                                            if(Map.insertunit(nid,x,y))
                                            {
                                                game.units[nid].x = x;
                                                game.units[nid].y = y;
                                                game.units[nid].tx = x;
                                                game.units[nid].ty = y;
                                                game.units[nid].tmptx = x;
                                                game.units[nid].tmpty = y;
                                                game.units[nid].firetargeti = -1;
                                                game.units[nid].transportedbyid = -1;
                                                game.units[i].transportarray[k] = -1;
                                            }
                                            break;
                                        }
                                    }
                                    if(foundspot)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }                
                }
            }
        }

///////////////////Method Definition///////////////
        public static void CorrectTransport(Game game,int i)//3may2021
        {
            if(game.units[i].transportcapacity>0)
            {
                //go through any units inside.....and check they're alive.....
                if(game.units[i].transportarray==null)
                {
                    return;
                }
                for(int k=0;k<game.units[i].transportarray.Length;k++)
                {
                    int nid = game.units[i].transportarray[k];
                    if(nid!=-1)
                    {
                        if(game.units[nid].hp<=0)
                        {
                            game.units[nid].transportedbyid = -1;
                            game.units[i].transportarray[k] = -1;
                        }
                    }
                }            
            }
            else
            {
                //if have a transport....
                if(game.units[i].transportedbyid!=-1)
                {
                    //if it is dead?
                    int nid = game.units[i].transportedbyid;
                    if(game.units[nid].transportcapacity<=0)
                    {
                        //cannot be? we cannot be inside a non transport
                        //if this occurs we've really messed up.....
                        return;
                    }
                    if(game.units[nid].hp<=0)
                    {
                        //our transport is dead.....therefore.....
                        //deploy us........
                        Unit.DeployUnits(game,nid);
                        return;
                    }
                    //if we are not in its list?
                    bool found = false;
                    for(int k=0;k<game.units[nid].transportarray.Length;k++)
                    {
                        int jid = game.units[nid].transportarray[k];
                        if(jid==i)
                        {
                            found = true;
                        }
                    }
                    if(found==false)
                    {
                        //error we are not in their list.....
                        //?? we've messed up here too
                        //set our hitpoints to zero......
                        //and remove us from the map if we can....
                        game.units[i].hp = 0;
                        Map.removeunit(i,game.units[i].x,game.units[i].y);
                    }
                }
            }
        }
        
///////////////////Method Definition///////////////
        public static bool CanTransform(Game game,int i) //3may2021
        {
            bool okay = true;
            string req = game.units[i].transformrequires;
            string[] reqarray = req.Split("|");
            if(req!="")
            {
                //various requirements not yet determined....
                //pipe separated list of requirements of format:
                //type|qty|type|qty|type|qty
                //which all have to be met to return a true value for the method
            }
            return okay;
        }
        
///////////////////Method Definition///////////////
        public string dname() //13mar2021
        {
            //used for displaying the appropriate unit name in the game
            //which is either the displayname, or the actual name or a blank
            if(charactername!=null)//10sep2021
            {
                if(charactername!="")//10sep2021
                {
                    return charactername;//10sep2021
                }
            }
            if(displayname==null)
            {
                return name;
            }
            if(displayname=="")
            {
                return name;
            }
            if(name==null)
            {
                return "";
            }
            return displayname;
        }
        //start-------------//10mar2021

        public static void WriteOffsets(Game game,string file)
        {
            Config.AUTOCALCOFFSETS = false;
            try
            {
                string txt = "";
                for(int i=0;i<game.templates.Length;i++)
                {
                    if(game.templates[i].autocalcedoffsets==true)
                    {
                        txt+="image="+game.templates[i].catfile+","+game.templates[i].offx+","+game.templates[i].offy+Environment.NewLine;
                    }
                }
                System.IO.File.WriteAllText(file,txt);    
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
        
///////////////////Method Definition///////////////
        public unsafe static void AutoCalcOffsets(Game game,int i)//20apr2021
        {
            if(i>=0 && i<game.templates.Length)
            {
                //calculate the offset x and y positions for the creature......we already put in the text file...but this is more accurate....
                //we only do one of these per frame since it could take some time.....if we did them all at once....
                //we might have to use pointers...again.......
                int pixelcount = 0;
                int fully = 0;
                int offx = 0;
                int offy = 0;
                int sumx = 0;
                int sumy = 0;
                if(game.templates[i].cat!=-1 && game.templates[i].hp>0 && game.templates[i].walkspeed>0)
                {
                    if(game.images[game.templates[i].cat].texture!=IntPtr.Zero)
                    {
                        try
                        {
                            int w = game.images[game.templates[i].cat].cwx;
                            int h = game.images[game.templates[i].cat].chy;
                            IntPtr surface = SDL_image.IMG_Load(game.images[game.templates[i].cat].file);
                            game.templates[i].autocalcedoffsets=true;
                            SDL.SDL_Surface * sur = (SDL.SDL_Surface *)surface;
                            int frame = 0;
                            while(frame < game.images[game.templates[i].cat].cwn * game.images[game.templates[i].cat].chn)
                            {
                                int pointer = 0;
                                int cellx = frame % game.images[game.templates[i].cat].cwn;
                                int celly = (frame - cellx) / game.images[game.templates[i].cat].cwn;
                                int sx = cellx * game.images[game.templates[i].cat].cwx;
                                int sy = celly * game.images[game.templates[i].cat].chy;
                                pointer = 4 * (sy*sur->pitch + sx);
                                for(int y=0;y<h;y++)
                                {
                                    for(int x=0;x<w;x++)
                                    {
                                        byte alphapixel = Marshal.ReadByte(sur->pixels,pointer + x * 4);
                                        byte lastpixel = Marshal.ReadByte(sur->pixels,pointer + x * 4 + 3);
                                        if(alphapixel>0 && lastpixel>0)
                                        {
                                            pixelcount++;
                                            sumx+=x;
                                            sumy+=y;
                                            fully=y;
                                        }
                                    }
                                    pointer+=sur->pitch;
                                }
                                
                                if(pixelcount>0)
                                {
                                    offx = (w/2) - (sumx/pixelcount);
                                    offy = - (h / 2) + 3 * (h - fully) / 2 + (h - fully) / 2 + (fully - sumy/pixelcount)/2;
                                    game.templates[i].offxa[frame] = offx;
                                    game.templates[i].offya[frame] = offy;
                                    game.templates[i].offx+=offx;
                                    game.templates[i].offy+=offy;
                                    //game.templates[i].autocalcedoffsets = true;
                                    //Console.WriteLine("Offx:"+offx+" offy:"+offy+" file:"+game.templates[i].catfile+" frame:"+frame);
                                    sumx = 0;
                                    sumy = 0;
                                    pixelcount = 0;
                                    offx = 0;
                                    offy = 0;
                                    fully = 0;
                                }
                                frame++;
                            }
                            if(frame>0)
                            {
                                game.templates[i].offx/=frame;
                                game.templates[i].offy/=frame;
                            }
                            SDL.SDL_FreeSurface(surface);
                        }
                        catch(Exception e)
                        {
                            string msg = e.Message;
                            Console.WriteLine(e.Message);
                        }
                    }
                }
            }
        }
        
///////////////////Method Definition///////////////
        public int percentagespawn(Game game)
        {
            //used for showing the build progress at construction buildings
            //(game.frame+id)%(framecheck*spawnertime)==0)
            int framecheck = 60;
            if(Config.RUNNINGSPEED>90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED>110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            int curframe = game.frame + id;
            int fulltime = framecheck * spawnertime;
            if(fulltime==0)
            {
                return 0;
            }
            int startframe = (curframe - (curframe % fulltime));
            //int framesleft = fulltime - (curframe % fulltime);//9sep2021
            int pct = (100 * (fulltime - framesleft)) / fulltime;
            if(pct>100)
            {
                pct = 100;
            }
            if(pct<0)
            {
                pct = 0;
            }
            return pct;
        }

///////////////////Method Definition///////////////
        public static int CalculateSpawnerTime(Game game,int tid)
        {
            //calculate the time to spawn this unit
            //kind of like a points cost for units in time
            int minvalue = 3;
            int maxvalue = 45;
            int value = minvalue;
            int firerate = game.templates[tid].highfirerate+1;
            if(firerate>2)
            {
                firerate = 2;
            }
            if(firerate<2)
            {
                firerate = 1;
            }
            int tmpvalue = minvalue + game.templates[tid].basehp * (1 + game.templates[tid].armour / 2 + (game.templates[tid].damage / 3 + game.templates[tid].damage2 / 3) * (firerate)) / 60;
            //start-----------------//20mar2021
            tmpvalue += game.templates[tid].firebullet * 3; //20mar2021 - add 3 seconds to missile troops....
            tmpvalue += game.templates[tid].brave * 2; //20mar2021 - add 2 seconds to brave troops...
            tmpvalue -= Functions.sign(game.templates[tid].stupid) * 2; //deduct 2 seconds from stupid troops
            tmpvalue -= Functions.sign(game.templates[tid].timid) * 3; //deduct 3 seconds from timid troops
            tmpvalue += Functions.sign(game.templates[tid].shock) * 2; //add 2 seconds to shock troops
            tmpvalue += Functions.sign(game.templates[tid].damagex) * 2; //add 2 seconds to damagex troops
            tmpvalue -= Functions.sign(game.templates[tid].hitandrun) * 2; //deduct 2 seconds from skirmishers
            tmpvalue += Functions.sign(game.templates[tid].craftsman) * 2; //add 3 seconds to craftsman
            tmpvalue += Functions.sign(game.templates[tid].frenzy) * 2;//add 2 seconds to frenzy
            tmpvalue += Functions.sign(game.templates[tid].regeneration) * 3; //add 3 seconds for regeneration
            tmpvalue += Functions.sign(game.templates[tid].fearsome) * 2; //add 2 seconds to fearsome
            tmpvalue += Functions.sign(game.templates[tid].woodsman) * 2; //add 2 seconds for woodsman
            tmpvalue += Functions.sign(game.templates[tid].banish) * 4; //add 4 seconds for banishment....
            tmpvalue += Functions.sign(game.templates[tid].splash) * 6; //add 6 seconds for splash damage//2sep2021
            tmpvalue += game.templates[tid].buildpenalty;//special factor to adjust for some troops.....
            //
            if(tmpvalue < minvalue)
            {
                tmpvalue = minvalue;
            }
            //end-------------------//20mar2021
            if(tmpvalue > value)
            {
                value = tmpvalue;
            }
            if(value > maxvalue)
            {
                value = maxvalue;
            }
            return value;
        }
        //end---------------//10mar2021
        //start-------------//9mar2021

///////////////////Method Definition///////////////
        public static void SpellCast(Game game,int spellid,int sfaction)//28mar2021
        {
            //find our spellcasters......
            bool soundplayed = false;
            Functions.saveseed(Functions.seed);
            for(int i=0;i<=Unit.MAXINDEX;i++)
            {
                if(game.units[i].hp>0 && game.units[i].faction==sfaction && game.units[i].spellcaster>0 && ((game.units[i].selected!=Unit.SELECTIONNONE && sfaction==Game.PLAYERFACTION && Game.SPELLCASTERSELECTED==i) || (sfaction!=Game.PLAYERFACTION && game.units[i].casting==true)))
                {
                    //this is one of our casters.
                    game.units[i].casting = false;
                    if(!soundplayed)
                    {
                        game.units[i].playmagicsound(game,i);
                        soundplayed = true;
                    }
                    int spell = spellid;// - Gui.ACTION_SPELL_START;
                    //a value from 0 to 8
                    //as there are 9 different spells in the game (maximum)
                    //of varying level....
                    /*
                    spells are: (in no particular order)
                    magicfear
                    magicgas
                    magichaste
                    magicplant
                    magicshield
                    magicstealth
                    magicstorm
                    magicsword
                    magicwind
                    *
/
                    for(int m=0;m<game.units[i].magicarray.Length;m++)
                    {
                        if(spell==game.units[i].magicarray[m])
                        {
                            //cancel the spell - one use only.....
                            game.units[i].magicarray[m] = -1 * game.units[i].magicarray[m];
                            //start------//3may2021
                            if(spell==Unit.MAGICRELEASE)
                            {
                                //for units being transported.....
                                if(Unit.TransportingUnits(game,i))
                                {
                                    //deploy units outside the transport.......
                                    Unit.DeployUnits(game,i);    
                                }
                                else
                                {
                                    game.units[i].magicarray[m] = -1 * game.units[i].magicarray[m];
                                }
                            }
                            if(spell==Unit.MAGICTRANSFORM)
                            {
                                if(!Unit.CanTransform(game,i))
                                {
                                    game.units[i].magicarray[m] = -1 * game.units[i].magicarray[m]; //don't cast spell....and hence don't grey it out......
                                    continue;
                                }
                                int nid = i;
                                int oldhpfrac = (100 * game.units[i].hp) / game.units[i].basehp;
                                if(oldhpfrac>100)
                                {
                                    oldhpfrac = 100;
                                }
                                int oldx = game.units[i].x;
                                int oldy = game.units[i].y;
                                int ztmp = -1;
                                for(int tid=0;tid<game.templates.Length;tid++)
                                {
                                    if(game.templates[tid].name==game.units[i].transforminto)
                                    {
                                        ztmp = tid;
                                        break;
                                    }
                                }
                                if(ztmp!=-1)
                                {
                                    //assume all requirements are met to transform if here.....
                                    game.units[i].hp = 0;
                                    Map.removeunit(i,game.units[i].x,game.units[i].y);
                                    game.units[i].createunitatxy(game,i,game.templates[ztmp],oldx,oldy);
                                    game.units[i].hp = (game.units[i].basehp * oldhpfrac) / 100;
                                    if(game.units[i].hp<1)
                                    {
                                        game.units[i].hp = 1;
                                    }
                                    game.units[i].x = oldx;
                                    game.units[i].y = oldy;
                                }
                            }
                            //end--------//3may2021
                            //start------//01apr2021
                            if(spell==Unit.MAGICDEF)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0)
                                            {
                                                game.units[nid].spelldefense++;
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[i].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            //start--------------//9apr2021
                            if(spell==Unit.MAGICLEADER)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0)
                                            {
                                                game.units[nid].leader+=2;
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[i].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICZOMBIEMASTER)
                            {
                                int nid = Map.cellunit(game.units[i].x,game.units[i].y); //ie ourselves....
                                if(nid!=-1)
                                {
                                    if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].zombiemaster>0)
                                    {
                                        game.units[nid].zombiemaster+=5;
                                        if(game.units[nid].zombiemaster>10)
                                        {
                                            game.units[nid].zombiemaster=10;
                                        }
                                    }
                                }
                            }
                            //end----------------//9apr2021
                            if(spell==Unit.MAGICDOOM)
                            {
                                //hmm....what is this spell? some kind of 'inverse healing maybe?' for the undead? and chaos?
                                
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].spelldefense>0)//01apr2021
                                            {
                                                continue;
                                            }
                                            if(game.units[nid].hp>0 && game.units[nid].walkspeed>0)
                                            {
                                                if(Functions.rand(0,1000)<750)
                                                {
                                                    game.units[nid].hp-=game.units[i].spellcaster;
                                                    if(game.units[nid].onscreen)
                                                    {
                                                        Functions.saveseed();//25apr2021
                                                        if(Functions.rand(0,100)<25)
                                                        {
                                                            game.units[nid].playvictimhitsound(game,nid);
                                                        }
                                                        Functions.restoreseed();//25apr2021
                                                    }
                                                    Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[i].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.REDSPELL);
                                                    if(game.units[nid].hp<=0)//20mar2021
                                                    {
                                                        game.killed(game,nid);
                                                        game.templates[game.units[i].templateid].kills++;
                                                    }                        
                                                    game.units[i].hp+=game.units[i].spellcaster;
                                                    if(game.units[i].hp>game.units[i].basehp)
                                                    {
                                                        game.units[i].hp = game.units[i].basehp;
                                                    }
                                                    
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICFRENZY)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].damage>0)
                                            {
                                                game.units[nid].frenzy+=3;
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[i].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            //end--------//01apr2021
                            if(spell==Unit.MAGICFEAR)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].walkspeed>0)
                                            {
                                                if(game.units[nid].spelldefense>0)//01apr2021
                                                {
                                                    continue;
                                                }
                                                if(Functions.rand(0,1000)<500)
                                                {
                                                    game.units[nid].timid = 1;
                                                    game.units[nid].retreat = true;
                                                    game.units[nid].retreatframe = game.frame + Unit.RETREATDEATH;
                                                    game.units[nid].orderframe = Unit.ORDERTIME;
                                                    game.units[nid].firetargeti = -1;
                                                    Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.REDSPELL);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICGAS)
                            {
                                int fires = 0;
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 5;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 5;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 5;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 5;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].spelldefense>0)//01apr2021
                                            {
                                                continue;
                                            }
                                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0)
                                            {
                                                Map.setonfire(x,y,false);
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[i].offy,x,y,Bullet.FIRESPELL);
                                                fires++;
                                            }
                                        }
                                        if(fires>game.units[i].spellcaster*3)
                                        {
                                            break;
                                        }
                                    }
                                    if(fires>game.units[i].spellcaster*3)
                                    {
                                        break;
                                    }
                                }
                            }
                            if(spell==Unit.MAGICWEB)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].spelldefense>0)
                                            {
                                                continue;
                                            }
                                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].walkspeed>0)
                                            {
                                                game.units[nid].walkspeed--; //maximum walk speed....
                                                //if(game.units[nid].walkspeed<1)
                                                //{
                                                //    game.units[nid].walkspeed=1;
                                                //}
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.REDSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICHASTE)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].walkspeed>0)
                                            {
                                                game.units[nid].walkspeed++; //maximum walk speed....
                                                if(game.units[nid].walkspeed>3)
                                                {
                                                    game.units[nid].walkspeed=3;
                                                }
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICPLANT)//24apr2021
                            //if(spell==Unit.MAGICPLANT && Replay.IsPlaying()==false)//24apr2021
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 4;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 4;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 4;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 4;y+=Map.GRIDH)
                                    {
                                        //plant trees......
                                        if(Map.cellunit(x,y)!=Map.VACANT)//24apr2021
                                        {
                                            continue;//24apr2021
                                        }
                                        if(((x-game.units[i].x)*(x-game.units[i].x)+(y-game.units[i].y)*(y-game.units[i].y))<(Map.GRIDW*Map.GRIDW*8*8))
                                        {
                                            if(Functions.rand(0,1000)<200)
                                            {
                                                Map.planttree(x,y);
                                            }
                                        }
                                        else
                                        {
                                            if(((x-game.units[i].x)*(x-game.units[i].x)+(y-game.units[i].y)*(y-game.units[i].y))<(Map.GRIDW*Map.GRIDW*10*10))
                                            {
                                                if(Functions.rand(0,1000)<100)
                                                {
                                                    Map.planttree(x,y);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICSHIELD)
                            {
                                //add +2 to all friendly units within spellcaster * 3 grid squares to their DEF values....
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0)
                                            {
                                                if(game.units[nid].armour<4)
                                                {
                                                    game.units[nid].armour++;
                                                }
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICSTEALTH)
                            {
                                //set ourselves to stealthy.....
                                if(Trigger.VARIABLE[Trigger.TYPE_AIRSTRIKE]<=0)
                                {
                                    Trigger.VARIABLE[Trigger.TYPE_AIRSTRIKE] = game.units[i].spellcaster;
                                    //Console.WriteLine("Artillery called in:"+game.units[i].spellcaster);
                                }
                            }
                            if(spell==Unit.MAGICSTORM)//23feb2022 altered for sci fi game...
                            {
                                //simply decimates the enemy...eg 1/10th of all enemy units are destroyed......
                                //and does so after a countdown.....
                                if(Trigger.VARIABLE[Trigger.TYPE_ARTILLERY]<=0)
                                {
                                    Trigger.VARIABLE[Trigger.TYPE_ARTILLERY] = game.units[i].spellcaster;
                                    //Console.WriteLine("Artillery called in:"+game.units[i].spellcaster);
                                }
                                
                                //int storms = game.units[i].spellcaster * 5;
                                /*
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 5;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 5;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 5;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 5;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].spelldefense>0)//01apr2021
                                            {
                                                continue;
                                            }
                                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].walkspeed>0)
                                            {
                                                if(Functions.rand(0,1000)<250)
                                                {
                                                    //do damage.....
                                                    storms--;
                                                    game.units[nid].hp-=game.units[i].spellcaster * 5;
                                                    if(game.units[nid].onscreen)
                                                    {
                                                        Functions.saveseed();//25apr2021
                                                        if(Functions.rand(0,100)<25)
                                                        {
                                                            game.units[nid].playvictimhitsound(game,nid);
                                                        }
                                                        Functions.restoreseed();//25apr2021
                                                    }
                                                    //if(game.units[firetargeti].hp<=0) //20mar2021
                                                    Functions.saveseed();//11apr2021
                                                    int qqq = Functions.rand(0,1000);
                                                    if(storms==game.units[i].spellcaster*5 - 1 || qqq<200)//11apr2021 qqq
                                                    {
                                                        Functions.restoreseed();//11apr2021
                                                        Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.LIGHTNINGSPELL);
                                                    }
                                                    else
                                                    {
                                                        Functions.restoreseed();//11apr2021
                                                    }
                                                    Map.setonfire(x,y,false);
                                                    if(game.units[nid].hp<=0)//20mar2021
                                                    {
                                                        game.killed(game,nid);
                                                        game.templates[game.units[i].templateid].kills++;
                                                    }                        
                                                    
                                                }
                                            }
                                        }
                                        if(storms<=0)
                                        {
                                            break;
                                        }
                                    }
                                    if(storms<=0)
                                    {
                                        break;
                                    }
                                }
                                *
/
                            }
                            if(spell==Unit.MAGICSWORD)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(game.units[i].notabuffer>0 && nid!=i)//15apr2021
                                        {
                                            continue;
                                        }
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].damage>0)
                                            {
                                                if(game.units[nid].damage<10)
                                                {
                                                    game.units[nid].damage++;
                                                }
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GREENSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                            if(spell==Unit.MAGICWIND)
                            {
                                for(int x=game.units[i].x - Map.GRIDW * game.units[i].spellcaster * 3;x<=game.units[i].x + Map.GRIDW * game.units[i].spellcaster * 3;x+=Map.GRIDW)
                                {
                                    for(int y=game.units[i].y - Map.GRIDH * game.units[i].spellcaster * 3;y<=game.units[i].y + Map.GRIDH * game.units[i].spellcaster * 3;y+=Map.GRIDH)
                                    {
                                        int nid = Map.cellunit(x,y);
                                        if(nid!=-1)
                                        {
                                            if(game.units[nid].spelldefense>0)//01apr2021
                                            {
                                                continue;
                                            }
                                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].walkspeed>0 && game.units[nid].firebullet>0)
                                            {
                                                game.units[nid].misfire++;
                                                Bullet.createbullet(game,game.units[i].x,game.units[i].y+game.units[nid].offy,game.units[nid].x,game.units[nid].y+game.units[nid].offy,Bullet.GOODSPELL);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            Functions.restoreseed();
        }
///////////////////Method Definition///////////////
        public static void Formation(Game game,int formation)
        {
            //apply a formation to the selected units
            //formation comes from Gui....
            int centrex = -1;
            int centrey = -1;
            int count = 0;
            int sumx = 0;
            int sumy = 0;
            int diffx = 0;
            int diffy = 0;
            int index = 0;
            int leadercount = 0;
            int paniccount = 0;
            int timidcount = 0;
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            Game.HORIZONTALFORMATION = 0; //14apr2021
            Game.VERTICALFORMATION = 0; //14apr2021
            bool isai = false;//17apr2021
            if(formation<0)//17apr2021
            {
                formation*=-1;
                isai = true;
            }
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0 && game.units[i].walkspeed>0 && ((game.units[i].faction==Game.PLAYERFACTION && game.units[i].selected!=Unit.SELECTIONNONE) || (game.units[i].faction!=Game.PLAYERFACTION && isai==true && game.units[i].aiselectframe==game.frame)))
                {
                    count++;
                    sumx+=game.units[i].x;
                    sumy+=game.units[i].y;
                    centrex=sumx/count;
                    centrey=sumy/count;
                    if(game.units[i].retreat)
                    {
                        paniccount++;
                    }
                    if(game.units[i].leader>0)
                    {
                        leadercount++;
                    }
                    if(game.units[i].timid>0)
                    {
                        timidcount++;
                    }
                }
            }
            if(centrex==-1)
            {
                return;
            }
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            Functions.saveseed(Functions.seed);
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0 && game.units[i].walkspeed>0 && game.units[i].faction==Game.PLAYERFACTION && game.units[i].selected!=Unit.SELECTIONNONE)
                {
                    index++;
                    diffx = game.units[i].x - centrex;
                    diffy = game.units[i].y - centrey;
                    if(formation!=Gui.ACTION_RALLY)
                    {
                        game.units[i].defendx = -1;
                        game.units[i].defendy = -1;
                        game.units[i].orderframe = Unit.ORDERTIME;
                        game.units[i].firetargeti = -1;
                        game.units[i].tmptattempts = 0;
                        Game.ordergivenframe = game.frame;
                    }
                    if(formation==Gui.ACTION_CLOSE)
                    {
                        game.units[i].tx = game.units[i].x - diffx / 2;
                        game.units[i].ty = game.units[i].y - diffy / 2;
                    }
                    if(formation==Gui.ACTION_DEFEND)
                    {
                        game.units[i].defendx = game.units[i].x;
                        game.units[i].defendy = game.units[i].y;
                    }
                    if(formation==Gui.ACTION_ENGAGE)
                    {
                        game.units[i].defendx = -1;
                        game.units[i].defendy = -1;
                    }
                    if(formation==Gui.ACTION_LINEH)
                    {
                        game.units[i].tx = centrex + (index - count/2) * Map.GRIDW;
                        game.units[i].ty = centrey;
                        Game.HORIZONTALFORMATION++; //14apr2021
                        game.units[i].formationx = game.units[i].tx - centrex;//14apr2021
                        game.units[i].formationy = game.units[i].ty - centrey;//14apr2021
                    }
                    if(formation==Gui.ACTION_LINEV)
                    {
                        Game.VERTICALFORMATION++; //14apr2021
                        game.units[i].tx = centrex;
                        game.units[i].ty = centrey + (index - count/2) * Map.GRIDH;
                        game.units[i].formationx = game.units[i].tx - centrex;//14apr2021
                        game.units[i].formationy = game.units[i].ty - centrey;//14apr2021
                    }
                    if(formation==Gui.ACTION_RALLY)
                    {
                        int dieroll = Functions.rand(0,100) - paniccount * 3 - timidcount + leadercount * 25;
                        if(dieroll > RALLYORDERCHANCE)
                        {
                            game.units[i].retreat = false;
                            game.units[i].retreatframe = 0;
                            game.units[i].timid = 0;
                        }
                    }
                    if(formation==Gui.ACTION_OPEN)
                    {
                        game.units[i].tx = game.units[i].x + diffx;
                        game.units[i].ty = game.units[i].y + diffy;
                    }
                }
            }
            Functions.restoreseed();
        }
        //end---------------//9mar2021

///////////////////Method Definition///////////////
        public static int gettemplate(Game game,int index,int step,int depth)
        {
            //used for the bestiary going forwards and backwards through the list
            depth++;
            int its = 0;
            if(depth>game.templates.Length + 2)
            {
                return 0;
            }
            index+=step;
            if(index>=game.templates.Length)
            {
                index = 0;
            }
            if(index<0)
            {
                index = game.templates.Length - 1;
            }
            if(step>0)
            {
                while(game.templates[index].faction==Unit.NULLFACTION)
                {
                    index++;
                    index%=game.templates.Length;
                    its++;
                    if(its>10000)
                    {
                        break;
                    }
                }
            }
            if(step<0)
            {
                while(game.templates[index].faction==Unit.NULLFACTION)
                {
                    index--;
                    if(index<0)
                    {
                        index = game.templates.Length - 1;
                    }
                    index%=game.templates.Length;
                    its++;
                    if(its>10000)
                    {
                        break;
                    }
                }
            }
            return index;
        }

///////////////////Method Definition///////////////
        public static int findtemplatebyname(Game game,string name) //2sep2021
        {
            for(int i=0;i<game.templates.Length;i++)
            {
                if(name==game.templates[i].name)
                {
                    return i;
                }
            }
            return -1;
        }
        
///////////////////Method Definition///////////////
        public static string[] gettemplatetext(Game game, int uid)
        {
            //used for displaying the informational text about a creature/unit
            string[] uline = new string[4];
            int j = 0;
            for(int i=0;i<4;i++)
            {
                uline[i] = "";
            }
            //13mar2021 lots of translation stuff goes in here.....
            if(game.templates[uid].stealth>0)
            {
                uline[j] = Translation.TranslateWord("stealth",false);//"Stealth";
            }
            if(game.templates[uid].infectchanceonhit>0 || game.templates[uid].infectchanceonkill>0)//22apr2022
            {
                uline[j]+=" "+Translation.TranslateWord("infector",false);
            }
            if(game.templates[uid].healer>0)
            {
                uline[j]+= " "+Translation.TranslateWord("heal",false);//" Heal";
            }
            if(game.templates[uid].regeneration>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("regeneration",false);//Regeneration";
            }
            if(game.templates[uid].firespell>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("firespell",false);//Flames";
            }
            if(game.templates[uid].zombiemaster>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("zombiemaster",false);//
            }
            if(game.templates[uid].banish>0) //12mar2021
            {
                uline[j]+=" "+ Translation.TranslateWord("banishment",false);//
            }
            if(game.templates[uid].damagex>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("damagex",false);//
            }
            if(game.templates[uid].retreat)
            {
                uline[j]+=" "+Translation.TranslateWord("panic",false);//" PANIC!";
            }
            if(game.templates[uid].timid>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("timid",false);//
            }
            if(game.templates[uid].hitandrun>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("hitandrun",false);//
            }
            //if(game.templates[uid].brave>0)//7mar2021
            if(game.templates[uid].brave>0 && game.templates[uid].mob<=0 && game.templates[uid].hatred<=0)//7mar2021
            {
                uline[j]+=" "+ Translation.TranslateWord("brave",false);//
            }
            //start-------------//7mar2021
            if(game.templates[uid].mob>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("mob",false);//
            }
            if(game.templates[uid].hatred>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("hatred",false);//
            }
            if(game.templates[uid].craftsman>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("craftsman",false);//
            }
            if(game.templates[uid].planar>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("planar",false);//
            }
            if(game.templates[uid].animosity>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("animosity",false);//
            }
            if(game.templates[uid].slow>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("slow",false);//
            }
            if(game.templates[uid].woodsman>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("woodsman",false);//
            }
            if(game.templates[uid].stupid>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("stupid",false);//
            }
            if(game.templates[uid].frenzy>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("frenzy",false);//
            }
            //end---------------//7mar2021
            //start-----------//25Feb2021
            if(game.templates[uid].highfirerate>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("highfirerate",false);//
            }
            //end-------------//25Feb2021
            if(game.templates[uid].shock>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("shocktroops",false);//
            }
            if(game.templates[uid].fearsome>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("fearsome",false);//
            }
            if(game.templates[uid].leader>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("leader",false);//
            }
            //start---------------//12jul2021
            if(game.templates[uid].bounddemon>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("bounddemon",false);//
            }
            //end-----------------//12jul2021
            if(game.templates[uid].firerange2>0)
            {
                uline[j]+=" "+ Translation.TranslateWord("damage2",false);//
                j++;
                uline[j]+=" "+ Translation.TranslateWord("secondary damage",false)+" "+game.templates[uid].damage2;
            }
            if(game.templates[uid].splash>0) //2sep2021
            {
                uline[j]+=" "+ Translation.TranslateWord("splash",false);
            }
            for(int i=0;i<4;i++)
            {
                uline[i] = uline[i].Trim();
            }
            return uline;
        }

///////////////////Method Definition///////////////
        public static string[] getunittext(Game game,int uid)
        {
            //used for displaying informational text about a game unit or creature
            string[] uline = new string[4];
            for(int i=0;i<4;i++)
            {
                uline[i] = "";
            }
            uline[0] = game.units[uid].dname();//13mar2021
            //13mar2021 lots of translation stuff going on here...
            int j = 1;
            string bhp = ""+game.units[uid].basehp;
            if(game.units[uid].basehp>5000)
            {
                bhp = " "+ Translation.TranslateWord("NA",true);//;
            }
            uline[j] = Translation.TranslateWord("basehp",true)+":"+bhp+" "+Translation.TranslateWord("walkspeed",true)+":"+game.units[uid].walkspeed;
            j++;
            //uline[j] = Translation.TranslateWord("damage",true)+":"+game.units[uid].damage + " " + Translation.TranslateWord("armour",true)+":"+game.units[uid].armour;//28feb2022
            uline[j] = Translation.TranslateWord("damage",true)+":"+game.units[uid].damage + " " + Translation.TranslateWord("armour",true)+":"+game.units[uid].armour + " " + Translation.TranslateWord("accuracy",true)+":"+game.units[uid].accuracy;//28feb2022
            if(game.units[uid].armour>10000)
            {
                uline[j] = "";//"Att:(NA) Def:(NA)";
            }
            j++;
            if(game.units[uid].stealth>0)
            {
                uline[j] = Translation.TranslateWord("stealth",true);//"Stealth";
            }
            if(game.units[uid].infectchanceonhit>0 || game.units[uid].infectchanceonkill>0)//22apr2022
            {
                uline[j]+=" "+Translation.TranslateWord("infector",true);//zombieficator
            }
            if(game.units[uid].healer>0)
            {
                uline[j]+=" "+Translation.TranslateWord("heal",true);//Heal";
            }
            if(game.units[uid].regeneration>0)
            {
                uline[j]+=" "+Translation.TranslateWord("regeneration",true);//" Regen.";
            }
            if(game.units[uid].firespell>0)
            {
                uline[j]+=" "+Translation.TranslateWord("firespell",true);//" Flames";
            }
            if(game.units[uid].zombiemaster>0)
            {
                uline[j]+=" "+Translation.TranslateWord("zombiemaster",true);//" Summoner";
            }
            if(game.units[uid].banish>0) //12mar2021
            {
                uline[j]+=" "+Translation.TranslateWord("banishment",true);//" Banishment";
            }
            if(game.units[uid].damagex>0)
            {
                uline[j]+=" "+Translation.TranslateWord("damagex",true);//" Ignore Def";
            }
            if(game.units[uid].retreat)
            {
                uline[j]+=" "+Translation.TranslateWord("panic",true);//" PANIC!";
            }
            if(game.units[uid].timid>0)
            {
                uline[j]+=" "+Translation.TranslateWord("timid",true);//" Timid";
            }
            if(game.units[uid].hitandrun>0)
            {
                uline[j]+=" "+Translation.TranslateWord("hitandrun",true);//;
            }
            //if(game.units[uid].brave>0)//7mar2021
            if(game.units[uid].brave>0 && game.units[uid].mob<=0 && game.units[uid].hatred<=0)//7mar2021
            {
                uline[j]+=" "+Translation.TranslateWord("brave",true);//" Brave";
            }
            //start-------------//7mar2021
            if(game.units[uid].mob>0)
            {
                uline[j]+=" "+Translation.TranslateWord("mob",true);//" Mob";
            }
            if(game.units[uid].hatred>0)
            {
                uline[j]+=" "+Translation.TranslateWord("hatred",true);//" Hatred";
            }
            if(game.units[uid].craftsman>0)
            {
                uline[j]+=" "+Translation.TranslateWord("craftsman",true);//" Craftsman";
            }
            if(game.units[uid].planar>0)
            {
                uline[j]+=" "+Translation.TranslateWord("planar",true);//" Planar";
            }
            if(game.units[uid].animosity>0)
            {
                uline[j]+=" "+Translation.TranslateWord("animosity",true);//" Animosity";
            }
            if(game.units[uid].slow>0)
            {
                uline[j]+=" "+Translation.TranslateWord("slow",true);//" Shambling";
            }
            if(game.units[uid].woodsman>0)
            {
                uline[j]+=" "+Translation.TranslateWord("woodsman",true);//" Woodsman";
            }
            if(game.units[uid].stupid>0)
            {
                uline[j]+=" "+Translation.TranslateWord("stupid",true);//" Stupid";
            }
            if(game.units[uid].frenzy>0)
            {
                uline[j]+=" "+Translation.TranslateWord("frenzy",true);//" Frenzy";
            }
            //end---------------//7mar2021
            //start-----------//25Feb2021
            if(game.units[uid].highfirerate>1) //NOTE special > 1....it changes from 0 to 1 and 1 to 2 in the actionattack method.
            {
                uline[j]+=" "+Translation.TranslateWord("highfirerate",true);//" Fast Shot";
            }
            //end-------------//25Feb2021
            if(game.units[uid].shock>0)
            {
                uline[j]+=" "+Translation.TranslateWord("shocktroops",true);//" Shock";
            }
            if(game.units[uid].fearsome>0)
            {
                uline[j]+=" "+Translation.TranslateWord("fearsome",true);//" Fearsome";
            }
            if(game.units[uid].leader>0)
            {
                uline[j]+=" "+Translation.TranslateWord("leader",true);//" Leader";
            }
            //start---------------//12jul2021
            if(game.units[uid].bounddemon>0)
            {
                uline[j]+=" "+Translation.TranslateWord("bounddemon",true);//Bound Demon
            }
            //end-----------------//12jul2021
            if(game.units[uid].firerange2>0)
            {
                uline[j]+=" "+Translation.TranslateWord("damage2",true);//" Multi Att";
            }
            if(game.units[uid].splash>0)//2sep2021
            {
                uline[j]+= " " + Translation.TranslateWord("splash",true);//Splash Damage
            }
            for(int i=0;i<4;i++)
            {
                uline[i] = uline[i].Trim();
            }
            return uline;
        }

///////////////////Method Definition///////////////
        public void checkxp(Game game)
        {
            //not used
            //if(xp>=levelxp && levelxp>0)
            //{
//                //level up......
                //xp = 0;
            //}
        }

///////////////////Method Definition///////////////
        public void playattacksound(Game game, int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play the sound when a unit makes an attack, melee or ranged
            int count = 0;
            for(int a=0;a<game.units[i].attackfx.Length;a++)
            {
                if(game.units[i].attackfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].attackfx.Length;a++)
                {
                    if(game.units[i].attackfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].attackfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void playselectsound(Game game, int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when a unit is selected
            int count = 0;
            for(int a=0;a<game.units[i].selectfx.Length;a++)
            {
                if(game.units[i].selectfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].selectfx.Length;a++)
                {
                    if(game.units[i].selectfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].selectfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void playtargetchosensound(Game game, int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when a unit finds a target to attack
            int count = 0;
            for(int a=0;a<game.units[i].targetfx.Length;a++)
            {
                if(game.units[i].targetfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].targetfx.Length;a++)
                {
                    if(game.units[i].targetfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].targetfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void playmagicsound(Game game,int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when a unit casts a magic spell
            int count = 0;
            for(int a=0;a<game.units[i].magicfx.Length;a++)
            {
                if(game.units[i].magicfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].magicfx.Length;a++)
                {
                    if(game.units[i].magicfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].magicfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void playacknowledgesound(Game game,int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when a unit is given an order
            int count = 0;
            for(int a=0;a<game.units[i].ackfx.Length;a++)
            {
                if(game.units[i].ackfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].ackfx.Length;a++)
                {
                    if(game.units[i].ackfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].ackfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void playdeathsound(Game game,int i) //28jul2021
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when a unit is given an order
            int count = 0;
            for(int a=0;a<game.units[i].deathfx.Length;a++)
            {
                if(game.units[i].deathfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].deathfx.Length;a++)
                {
                    if(game.units[i].deathfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].deathfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

        ///////////////////Method Definition///////////////
        public void playvictimhitsound(Game game,int i)
        {
            if(game.demomode)//17sep2021
            {
                return;
            }
            //play this sound when the unit is struck by something
            int count = 0;
            for(int a=0;a<game.units[i].impactfx.Length;a++)
            {
                if(game.units[i].impactfx[a]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                count = 1 + (Functions.rand(0,1000)%count);
                for(int a=0;a<game.units[i].impactfx.Length;a++)
                {
                    if(game.units[i].impactfx[a]!=-1)
                    {
                        count--;
                        if(count<=0)
                        {
                            Audios.playsound(game.audios[game.units[i].impactfx[a]],Game.FXVOLUME);
                            break;
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void shocktarget(Game game,int tid)
        {
            //used when a shock trooper hits another unit, to determine if they flee etc
            if(game.units[tid].shocked && fearsome<=0)
            {
                return;
            }
            //27mar2021 units without 'brave' are slightly braver against shock and fear than they were before....
            //start---------------//27mar2021
            int countfriend = Map.countfactionneighbours(game,game.units[tid].x,game.units[tid].y,game.units[tid].faction);
            int tmpbrave = 0;
            if(countfriend>=3)
            {
                //in other words if we have at least two buddies next to us....we're a little braver....
                //it also lessens the ability of single shock troops from terrorising whole armies....
                //yep this next line is the one you want for the Steam giveaway.....'tmpbrave = 1;'
                tmpbrave = 1;
            }
            //end-----------------//27mar2021
            //if(game.units[tid].brave>0)//27mar2021
            if(game.units[tid].brave>0 || tmpbrave>0)//27mar2021
            {
                if(Functions.rand(0,1000)<850)
                {
                    return;
                }
            }
            game.units[tid].shocked = true;
            if(Functions.rand(0,1000)<500)
            {
                game.units[tid].timid=1;
            }
            if(Functions.rand(0,1000)<500)
            {
                game.units[tid].firetargeti = -1;
            }
            if(Functions.rand(0,1000)<100)
            {
                game.units[tid].retreat = true;
                game.units[tid].retreatframe = game.frame + (60 * 20);
                //game.units[tid].tx = game.units[tid].x + (int)(Functions.rand(-500,500));
                //game.units[tid].ty = game.units[tid].y + (int)(Functions.rand(-500,500));
                //game.units[tid].tmptx = game.units[tid].tx;
                //game.units[tid].tmpty = game.units[tid].ty;
                //game.units[tid].orderframe = Unit.ORDERTIME;
            }
        }

///////////////////Method Definition///////////////
        public void actionattack(Game game)
        {
            //base attack method that handles the whole process of
            //attacking other units
            //basic attack
            //
            //
            //
            int framecheck = 60;
            if(Config.RUNNINGSPEED>90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED>110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            if(hp <= 0)
            {
                return;
            }
            //start-----------//25Feb2021
            if(highfirerate>0)
            {
                if(highfirerate>2)
                {
                    highfirerate = 2;
                }
            }
            else
            {
                highfirerate = 1;
            }
            //end-------------//25Feb2021
            if(faction==Unit.NULLFACTION && walkspeed>0)
            {
            }
            if(faction==Unit.NULLFACTION && spawnercount<=0)
            {
                return;
            }
            bool closerange = false;
            int griddist = firerange / Map.GRIDW;
            int griddist2 = firerange2 / Map.GRIDW;
            if(griddist2==0)
            {
                griddist2 = griddist;
            }
            if(firerange2>firerange)
            {
                griddist = firerange2 / Map.GRIDW;
            }
            int myx = x / Map.GRIDW;
            int myy = y / Map.GRIDH;
            int enemyx = 0;
            int enemyy = 0;
            int ztmp = -1;
            //if(spawnercount>0 && (game.frame+id)%(framecheck*spawnertime)==0)//9sep2021
            if(framesleft>0)//9sep2021
            {
                framesleft--;
            }
            if(spawnercount>0 && framesleft==0)//9sep2021
            {
                //if(orderframe>0)
                //{
                    //return;
                //}
                framesleft = spawnertime * framecheck;//9sep2021
                for(int j=0;j<game.templates.Length;j++)
                {
                    if(game.templates[j].name==spawner)
                    {
                        ztmp = j;
                        break;
                    }
                }
                if(ztmp!=-1)
                {
                    for(int dd=1;dd<4;dd++)
                    {
                        for(int ex=myx - dd;ex<=myx+dd;ex++)
                        {
                            for(int ey=myy - dd;ey<=myy + dd;ey++)
                            {
                                int eid = Map.cellunit(ex*Map.GRIDW,ey*Map.GRIDH);
                                if(eid==Map.VACANT)
                                {
                                    //nothing in the cell......
                                    if(faction==Game.PLAYERFACTION)//23feb2022
                                    {
                                        if(Trigger.VARIABLE[Trigger.TYPE_POINTS]>=game.templates[ztmp].points)
                                        {
                                            Trigger.VARIABLE[Trigger.TYPE_POINTS]-=game.templates[ztmp].points;
                                        }
                                        else
                                        {
                                            return;
                                        }
                                    }
                                    for(int k=0;k<game.units.Length;k++)
                                    {
                                        if(game.units[k].hp<=0)
                                        {
                                            game.units[k].createunitatxy(game,k,game.templates[ztmp],ex * Map.GRIDW,ey * Map.GRIDH);
                                            game.units[k].ai = Unit.AI_ASSAULT;
                                            spawnercount--;
                                            if(k>Unit.MAXINDEX)
                                            {
                                                Unit.MAXINDEX = k;//11apr2021
                                            }
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return;
            }
            //start-------------//12mar2021
            if(banish>0 && (game.frame + id)%(framecheck * 10)==1 && firetargeti!=-1)
            {
                if(orderframe>0)
                {
                    return;
                }
                int rr1 = 4;
                bool banished = false;
                //Functions.saveseed();//11apr2021
                for(int ex=myx - rr1;ex<=myx+rr1;ex++)
                {
                    for(int ey=myy - rr1;ey<=myy + rr1;ey++)
                    {
                        int eid1 = Map.cellunit(ex*Map.GRIDW,ey*Map.GRIDH);
                        if(eid1!=-1)
                        {
                            if(game.units[eid1].zombie>0 && game.units[eid1].hp>0 && game.units[eid1].faction!=faction)
                            {    
                                //this unit killed it.....
                                //d100 check to see if we banish it.....
                                if(Functions.rand(0,100+game.units[eid1].zombie*10)<banish)
                                {
                                    game.units[eid1].hp=0;
                                    if(levelxp>0)
                                    {
                //                        xp+=game.units[eid1].xpvalue;
                //                        checkxp(game);
                                    }
                                    //do death effect.....
                                    game.killed(game,eid1);
                                    game.templates[templateid].kills++;
                                    banished = true;
                                    if(animmode != ANIMMODE_ATTACK)
                                    {    
                                        animmode = ANIMMODE_ATTACK;
                                        animframe = animmodeattframestart;
                                    }
                                }
                            }
                        }
                    }
                }
                //Functions.restoreseed();//11apr2021
                //Functions.saveseed();//11apr2021
                Functions.saveseed();//25apr2021
                if(Functions.rand(0,100)<30 && onscreen==true && banished==true)
                {
                    playmagicsound(game,id);
                }
                //Functions.restoreseed();//11apr2021
                Functions.restoreseed();//25apr2021
            }
            //end---------------//12mar2021
            //
            /*Explaining framecheck and game.frame + id mod....
            ///in a second there are 60 frames.
            //if we take the game.frame and divide it by 60 at any point it will return a remainder of between 0 and 59.
            //if...if we take the game.frame and add the index or the id of the array element to it, and then do so we will also get a value between 0 and 59.
            //Basically - the size of our framecheck determines the value is being between 0 and framecheck-1
            //By putting the id into 'game.frame + id' into our mod check...then we ensure that
            //we only check certain units every nth frame...
            *
/
            if(zombiemaster>0 && ((game.frame + id)%(framecheck*10)==0) && firetargeti!=-1)
            {
                if(orderframe>0)
                {
                    return;
                }
                int maxzombie = 0;
                for(int j=0;j<game.templates.Length;j++)
                {
                    if(game.templates[j].zombie<=zombiemaster && game.templates[j].zombie>0 && game.templates[j].faction==faction)
                    {
                        //game.units[i].createunitatxy(game,i,game.templates[j],game.missions[mission].units[i].x,game.missions[mission].units[i].y);
                        if(game.templates[j].zombie > maxzombie)
                        {
                            ztmp = j;
                            maxzombie = game.templates[j].zombie;
                        //break;
                        }
                    }
                }
                if(ztmp!=-1)
                {
                    int rr = 1;
                    //if(game.skirmish)
                    //{
                        rr = 4;
                    //}
                    int mzombiemaster = zombiemaster;//9apr2021
                    if(mzombiemaster>4)//9apr2021
                    {
                        mzombiemaster = 4;//9apr2021
                    }
                    for(int ex=myx - rr*mzombiemaster*2/maxzombie;ex<=myx+rr*mzombiemaster*2/maxzombie;ex++)
                    {
                        for(int ey=myy - rr*mzombiemaster*2/maxzombie;ey<=myy + rr*mzombiemaster*2/maxzombie;ey++)
                        {
                            int eid = Map.cellunit(ex*Map.GRIDW,ey*Map.GRIDH);
                            if(eid==-1)
                            {
                                //nothing in the cell......
                                //must have bones in skirmish mode.....
                                //if(game.skirmish==true)
                                //{
                                    if(!Map.dobonesexist(ex * Map.GRIDW, ey*Map.GRIDH))
                                    {
                                        continue;
                                    }
                                //}
                                for(int k=0;k<game.units.Length;k++)
                                {
                                    if(game.units[k].hp<=0)
                                    {
                                        game.units[k].createunitatxy(game,k,game.templates[ztmp],ex * Map.GRIDW,ey * Map.GRIDH);
                                        Map.removebones(ex * Map.GRIDW, ey * Map.GRIDH);
                                        Blood.makeblood(game,game.units[k].x,game.units[k].y+game.units[k].offy,1);
                                        if(k>Unit.MAXINDEX) //11apr2021
                                        {
                                            Unit.MAXINDEX = k;
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    //Functions.saveseed();//11apr2021
                    Functions.saveseed();//25apr2021
                    if(Functions.rand(0,100)<30 && onscreen==true)
                    {
                        playmagicsound(game,id);
                    }
                    Functions.restoreseed();//25apr2021
                    //Functions.restoreseed();//11apr2021
                }
                return;
            }
            //start------------//19mar2021
            if(spellcaster>0)
            {
                if(orderframe>0)
                {
                    return;
                }
                //start---------------//28mar2021
                if((game.frame + id + 30)%framecheck*SPELLCHECK==0 && Game.SPELLSACTIVE==true)
                {
                    if(faction!=Game.PLAYERFACTION)
                    {
                        //if(onscreen) //replace with ronscreen from replay......25apr2021
                        if((onscreen==true && Replay.IsPlaying()==false) || (ronscreen==true && Replay.IsPlaying()==true)) //replace with ronscreen from replay......25apr2021
                        {
                            //we're an ai unit on screen......about to cast a magic spell.....
                            if(firetargeti!=-1)
                            {
                                //and we have a target....
                                //Functions.saveseed();//11apr2021
                                int magicspell = (int)Functions.abs(Functions.rand(0,1000)) % 9;
                                if(magicarray[magicspell]>0)
                                {
                                    //yep we've got a spell ready....
                                    if(casting==false)
                                    {
                                        //////
                                        orderframe = Unit.ORDERTIME;
                                        casting = true;
                                        Unit.SpellCast(game,magicarray[magicspell],faction);
                                        casting = false;
                                    }
                                }
                                //Functions.restoreseed();//11apr2021
                            }
                        }
                    }
                }
                //end-----------------//28mar2021
                if((game.frame + id)%framecheck*SPELLCHECK==0 && notabuffer==0) //once per six seconds....
                {
                    //pick a random location within firerange units.....
                    //Functions.saveseed();//11apr2021
                    int rndx = (int)Functions.rand(x - firerange,x + firerange);
                    int rndy = (int)Functions.rand(y - firerange,y + firerange);
                    int rndid = Map.cellunit(rndx,rndy);
                    bool rbuffed = false;
                    if(rndid!=-1)
                    {
                        int ddx = 0;
                        int ddy = 0;
                        if(game.units[rndid].faction!=faction && rndid!=id && game.units[rndid].hp>0 && game.units[rndid].armour>0 && game.units[rndid].walkspeed>0) //curse an enemy
                        {
                            //we should buff it....if it is performing animmode==ANIMMODE_ATTACK
                            if(game.units[rndid].animmode==ANIMMODE_ATTACK && game.units[rndid].armour>0)
                            {
                                game.units[rndid].armour-=spellcaster;
                                game.units[rndid].cursed = true; //21mar2021
                                if(game.units[rndid].armour<0)
                                {
                                    game.units[rndid].armour=0;
                                }
                                rbuffed = true;
                                //fire a green ball of flame at the friendly unit.....
                                Bullet.createbullet(game,x,y+offy,game.units[rndid].x,game.units[rndid].y+game.units[rndid].offy,Bullet.REDSPELL);
                                if(animmode != ANIMMODE_ATTACK)
                                {
                                    animmode = ANIMMODE_ATTACK;
                                    animframe = animmodeattframestart;
                                }
                            }
                            ddx = Functions.sign(rndx - x);
                            ddy = Functions.sign(rndy - y);
                            odirn = dirn;
                            if(dirntime>0)
                            {
                                dirntime--;
                            }
                            if(dirntime<=0)
                            {
                                dirntime = Unit.DIRNDELAY;
                                if(ddx==0)
                                {
                                    if(ddy>0)
                                    {
                                        dirn = DIRN_DOWN;
                                    }
                                    else
                                    {
                                        dirn = DIRN_UP;
                                    }
                                }
                                if(ddy==0)
                                {
                                    if(ddx>0)
                                    {
                                        dirn = DIRN_RIGHT;
                                    }
                                    else
                                    {
                                        dirn = DIRN_LEFT;
                                    }
                                }
                                if(ddx!=0 && ddy!=0)
                                {
                                    if(ddx==-1 && ddy==-1)
                                    {
                                        dirn = DIRN_UPLEFT;
                                    }
                                    if(ddx==-1 && ddy==1)
                                    {
                                        dirn = DIRN_DOWNLEFT;
                                    }
                                    if(ddx==1 && ddy==-1)
                                    {
                                        dirn = DIRN_UPRIGHT;
                                    }
                                    if(ddx==1 && ddy==1)
                                    {
                                        dirn = DIRN_DOWNRIGHT;
                                    }
                                }
                            }
                        
                        }
                        if(game.units[rndid].faction==faction && rndid!=id && game.units[rndid].hp>0 && game.units[rndid].damage>0 && game.units[rndid].walkspeed>0) //buff a friend.....
                        {
                            //unit is alive and part of our faction.....
                            //therefore.....
                            //we should buff it....if it is performing animmode==ANIMMODE_ATTACK
                            if(game.units[rndid].animmode==ANIMMODE_ATTACK && game.units[rndid].damage<MAXBUFFATT)
                            {
                                game.units[rndid].damage+=spellcaster;
                                game.units[rndid].buffed = true;//21mar2021
                                rbuffed = true;
                                //fire a green ball of flame at the friendly unit.....
                                Bullet.createbullet(game,x,y+offy,game.units[rndid].x,game.units[rndid].y+game.units[rndid].offy,Bullet.GREENSPELL);
                                if(animmode != ANIMMODE_ATTACK)
                                {
                                    animmode = ANIMMODE_ATTACK;
                                    animframe = animmodeattframestart;
                                }
                            }
                            ddx = Functions.sign(rndx - x);
                            ddy = Functions.sign(rndy - y);
                            odirn = dirn;
                            if(dirntime>0)
                            {
                                dirntime--;
                            }
                            if(dirntime<=0)
                            {
                                dirntime = Unit.DIRNDELAY;
                                if(ddx==0)
                                {
                                    if(ddy>0)
                                    {
                                        dirn = DIRN_DOWN;
                                    }
                                    else
                                    {
                                        dirn = DIRN_UP;
                                    }
                                }
                                if(ddy==0)
                                {
                                    if(ddx>0)
                                    {
                                        dirn = DIRN_RIGHT;
                                    }
                                    else
                                    {
                                        dirn = DIRN_LEFT;
                                    }
                                }
                                if(ddx!=0 && ddy!=0)
                                {
                                    if(ddx==-1 && ddy==-1)
                                    {
                                        dirn = DIRN_UPLEFT;
                                    }
                                    if(ddx==-1 && ddy==1)
                                    {
                                        dirn = DIRN_DOWNLEFT;
                                    }
                                    if(ddx==1 && ddy==-1)
                                    {
                                        dirn = DIRN_UPRIGHT;
                                    }
                                    if(ddx==1 && ddy==1)
                                    {
                                        dirn = DIRN_DOWNRIGHT;
                                    }
                                }
                            }
                        }
                    }
                    //Functions.restoreseed();//11apr2021
                    if(rbuffed)
                    {
                        return;
                    }
                }
            }
            //end--------------//19mar2021
            if(healer>0)
            {
                if(orderframe>0)
                {
                    return;
                }
                bool bounddemonhelped = false; //12jul2021
                if((game.frame + id)%framecheck==0)
                {
                    //bool madeeffect = false;
                    for(int ex=myx - healer*2;ex<=myx+healer*2;ex++)
                    {
                        for(int ey=myy - healer*2;ey<=myy + healer*2;ey++)
                        {
                            int eid = Map.cellunit(ex*Map.GRIDW,ey*Map.GRIDH);
                            if(eid!=-1)
                            {
                                //start-------------------------//12jul2021
                                if(game.units[eid].faction==faction && eid!=id && game.units[eid].bounddemon<game.templates[game.units[eid].templateid].bounddemon && game.units[eid].bounddemon>1 && game.units[eid].hp>0 && bounddemonhelped == false)
                                {
                                    game.units[eid].bounddemon+=1;
                                    //magic users with healing can prevent bound demons from turning against everyone.....the more you have the better.....
                                    bounddemonhelped = true;
                                }
                                //end---------------------------//12jul2021
                                if(game.units[eid].faction==faction && eid!=id && game.units[eid].hp<game.units[eid].basehp && game.units[eid].hp>0)
                                {
                                    //ie friend in adjacent or near adjacent square
                                    //with less than full health.....
                                    game.units[eid].hp+=healer;
                                    if(game.units[eid].infected>0)//22apr2022
                                    {
                                        game.units[eid].infected = 0;
                                    }
                                    //Blood.makeblood(game,game.units[eid].x,game.units[eid].y,1);
                                    //if(!madeeffect)
                                    //{
                                        //Blood.makeblood(game,x,y,1);
                                    //    madeeffect = true;
                                    //}
                                    if(game.units[eid].hp>game.units[eid].basehp)
                                    {
                                        game.units[eid].hp=game.units[eid].basehp;
                                    }
                                    if(animmode != ANIMMODE_ATTACK)
                                    {
                                        animmode = ANIMMODE_ATTACK;
                                        animframe = animmodeattframestart;
                                    }
                                    int ddx = Functions.sign(ex - myx);
                                    int ddy = Functions.sign(ey - myy);
                                    odirn = dirn;
                                    if(dirntime>0)
                                    {
                                        dirntime--;
                                    }
                                    if(dirntime<=0)
                                    {
                                        dirntime = Unit.DIRNDELAY;
                                        if(ddx==0)
                                        {
                                            if(ddy>0)
                                            {
                                                dirn = DIRN_DOWN;
                                            }
                                            else
                                            {
                                                dirn = DIRN_UP;
                                            }
                                        }
                                        if(ddy==0)
                                        {
                                            if(ddx>0)
                                            {
                                                dirn = DIRN_RIGHT;
                                            }
                                            else
                                            {
                                                dirn = DIRN_LEFT;
                                            }
                                        }
                                        if(ddx!=0 && ddy!=0)
                                        {
                                            if(ddx==-1 && ddy==-1)
                                            {
                                                dirn = DIRN_UPLEFT;
                                            }
                                            if(ddx==-1 && ddy==1)
                                            {
                                                dirn = DIRN_DOWNLEFT;
                                            }
                                            if(ddx==1 && ddy==-1)
                                            {
                                                dirn = DIRN_UPRIGHT;
                                            }
                                            if(ddx==1 && ddy==1)
                                            {
                                                dirn = DIRN_DOWNRIGHT;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(firebullet==0){return;}
            }
            if(firetargeti!=-1)
            {
                //current target
                if(game.units[firetargeti].hp > 0)
                {
                    //check if we are in range.......
                    enemyx = game.units[firetargeti].x / Map.GRIDW;
                    enemyy = game.units[firetargeti].y / Map.GRIDH;
                    if(Functions.abs(myx - enemyx)<= griddist && Functions.abs(myy - enemyy)<= griddist)
                    {
                        //we can attack
                        if(Functions.abs(myx - enemyx)<= griddist && Functions.abs(myy - enemyy)<= griddist2)
                        {
                            closerange = true;
                        }
                        if(closerange)
                        {
                            if(animmode != ANIMMODE_ATTACK)
                            {
                                animmode = ANIMMODE_ATTACK;
                                animframe = animmodeattframestart;
                            }
                        }
                        else
                        {
                            if(animmode != ANIMMODE_ATTACK2)
                            {
                                animmode = ANIMMODE_ATTACK2;
                                animframe = animmodeatt2framestart;
                            }    
                        }
                        int ddx = Functions.sign(enemyx - myx);
                        int ddy = Functions.sign(enemyy - myy);
                        odirn = dirn;
                        if(dirntime>0)
                        {
                            dirntime--;
                        }
                        if(dirntime<=0)
                        {
                            dirntime = Unit.DIRNDELAY;
                            if(ddx==0)
                            {
                                if(ddy>0)
                                {
                                    dirn = DIRN_DOWN;
                                }
                                else
                                {
                                    dirn = DIRN_UP;
                                }
                            }
                            if(ddy==0)
                            {
                                if(ddx>0)
                                {
                                    dirn = DIRN_RIGHT;
                                }
                                else
                                {
                                    dirn = DIRN_LEFT;
                                }
                            }
                            if(ddx!=0 && ddy!=0)
                            {
                                if(ddx==-1 && ddy==-1)
                                {
                                    dirn = DIRN_UPLEFT;
                                }
                                if(ddx==-1 && ddy==1)
                                {
                                    dirn = DIRN_DOWNLEFT;
                                }
                                if(ddx==1 && ddy==-1)
                                {
                                    dirn = DIRN_UPRIGHT;
                                }
                                if(ddx==1 && ddy==1)
                                {
                                    dirn = DIRN_DOWNRIGHT;
                                }
                            }
                        }
                        //if((game.frame + id) % framecheck==0) //25Feb2021
                        if((game.frame + id) % (framecheck/highfirerate)==0)//25Feb2021
                        {
                            //once per second attack.....
                            //Console.WriteLine("attacking -have at you!");
                            int actualdamage = damage - game.units[firetargeti].armour;
                            int infectroll = -1;
                            //start----------//5apr2021
                            //Functions.saveseed();//11apr2021
                            if(banish>0 && game.units[firetargeti].zombie>0)
                            {
                                if(Functions.rand(0,100+game.units[firetargeti].zombie*10)<banish)
                                {
                                    actualdamage = actualdamage * 4; //+300% damage when a successful banish attack against a zombie creature (summoned)
                                }
                            }
                            if(banish>0 && game.units[firetargeti].planar>0)
                            {
                                if(Functions.rand(0,100)<banish)
                                {
                                    actualdamage = actualdamage * 7; //+600% damage when a successful banish attack against a zombie creature (summoned)
                                }
                            }
                            //Functions.restoreseed();//11apr2021
                            //end------------//5apr2021
                            //start-------------//7mar2021
                            if(frenzy>0)
                            {
                                frenzy--;
                                actualdamage+=damage;
                            }
                            //end---------------//7mar2021
                            if(!closerange && damage2>0)
                            {
                                actualdamage = damage2 - game.units[firetargeti].armour;
                            }
                            //if(damagex>0)//7mar2021
                            if(damagex>0 && game.units[firetargeti].craftsman<=0)//7mar2021
                            {
                                actualdamage+=game.units[firetargeti].armour; //ignores enemy armour.....
                            }
                            if(firespell>0 || game.units[firetargeti].flammable>0)
                            {
                                Map.setonfire(game.units[firetargeti].x,game.units[firetargeti].y,false);
                            }
                            int extradamage = 0;
                            if(powerspell>0)
                            {
                                if((game.frame + id) % (framecheck*powerspell)==0)
                                {
                                    extradamage = powerspell;
                                    actualdamage += extradamage;
                                }
                            }
                            if(shock>0)
                            {
                                //Functions.saveseed();//11apr2021
                                shocktarget(game,firetargeti);
                                //Functions.restoreseed();//11apr2021
                            }
                            //start-------------//7mar2021
                            if(game.units[firetargeti].woodsman>0)
                            {
                                if(Map.nearobstacle(game.units[firetargeti].x,game.units[firetargeti].y))
                                {
                                    actualdamage/=2;
                                }
                            }
                            //end---------------//7mar2021
                            //start-------------//24feb2022
                            if(Config.useseasons>0 && Config.Season==Config.WINTER && firebullet>0)//missile weapons are less effective in Winter...
                            {
                                if(Functions.rand(0,100)<25)
                                {
                                    actualdamage/=2;
                                }
                            }
                            //end---------------//24feb2022
                            if(firebullet==1 || closerange==false)
                            {
                                if(extradamage!=0)
                                {
                                    Bullet.createbullet(game,x,y+offy,game.units[firetargeti].x,game.units[firetargeti].y+game.units[firetargeti].offy,powerspell);
                                }
                                else
                                {
                                    Bullet.createbullet(game,x,y+offy,game.units[firetargeti].x,game.units[firetargeti].y+game.units[firetargeti].offy,firespell);
                                }
                                //if the target is near woods or other obstacles....then....
                                if(Map.nearobstacle(game.units[firetargeti].x,game.units[firetargeti].y) || misfire>0)
                                {
                                    actualdamage/=2;
                                }
                            }
                            //Functions.saveseed();//11apr2021
                            if(actualdamage<1)
                            {
                                if(Functions.rand(0,100)<50) //20mar2021
                                {
                                    actualdamage = 0; //20mar2021
                                }
                                else
                                {
                                    actualdamage = 1;
                                }
                            }
                            if(splash>0 && actualdamage>0)//2sep2021
                            {
                                int splashdamage = actualdamage / 2;
                                if(splashdamage<=0)
                                {
                                    splashdamage = 1;
                                }
                                for(int splashx = game.units[firetargeti].x - Map.GRIDW*splash;splashx<=game.units[firetargeti].x + Map.GRIDW*splash;splashx+=Map.GRIDW)
                                {
                                    for(int splashy = game.units[firetargeti].y - Map.GRIDH*splash;splashy<=game.units[firetargeti].y + Map.GRIDH*splash;splashy+=Map.GRIDH)
                                    {
                                        if(Map.cellunit(splashx,splashy)!=Map.VACANT)
                                        {
                                            int splashi = Map.cellunit(splashx,splashy);
                                            if(splashi!=firetargeti)
                                            {
                                                game.units[splashi].hp-=splashdamage;
                                                infectroll = Functions.rand(0,100);//22apr2022
                                                if(infectroll<infectchanceonhit)//22apr2022
                                                {
                                                    Unit.Infect(game,splashi,infectinto);
                                                }
                                                if(game.units[splashi].hp<=0)
                                                {
                                                    game.templates[templateid].kills++;
                                                    game.killed(game,splashi);
                                                    if(extragibbet>0)//18sep2021
                                                    {
                                                        Gibbet.makegibbets(game,splashi);//18sep2021
                                                    }
                                                    if(infectroll<infectchanceonkill)//22apr2022
                                                    {
                                                        Unit.Infect(game,splashi,infectinto);
                                                    }
                                                
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if(accuracy!=100)//28feb2022
                            {
                                if(Functions.rand(0,100)>accuracy)//28feb2022
                                {
                                    actualdamage = 0;//28feb2022
                                    if(accuracy!=0){accuracy++;xp++;}//1mar2022//do better over time....experience growth of units....every miss is a learning experience....
                                }
                                else
                                {
                                    Game.MissionScore+=actualdamage;//1mar2022
                                }
                            }
                            if(actualdamage!=0)//28feb2022
                            {
                                game.units[firetargeti].hp-=actualdamage;
                                infectroll = Functions.rand(0,100);//22apr2022
                                if(infectroll<infectchanceonhit)//22apr2022
                                {
                                    Unit.Infect(game,firetargeti,infectinto);
                                }
                                if(onscreen)
                                {
                                    Functions.saveseed();//25apr2021
                                    if(Functions.rand(0,100)<25)
                                    {
                                        playattacksound(game,id);
                                    }
                                    if(Functions.rand(0,100)<25)
                                    {
                                        playvictimhitsound(game,firetargeti);
                                    }
                                    Functions.restoreseed();//25apr2021
                                }
                            }//28feb2022
                            //Functions.restoreseed();//11apr2021
                            //if(game.units[firetargeti].hp<=0) //20mar2021
                            if(game.units[firetargeti].hp<=0 && actualdamage>0)//20mar2021
                            {
                                //this unit killed it.....
                                if(levelxp>0)
                                {
                                    //xp+=game.units[firetargeti].xpvalue;
                                    //checkxp(game);
                                }
                                //do death effect.....
                                game.killed(game,firetargeti);
                                game.templates[templateid].kills++;
                                if(extragibbet>0)//18sep2021
                                {
                                    Gibbet.makegibbets(game,firetargeti);//18sep2021
                                }
                                if(infectroll<infectchanceonkill)//22apr2022
                                {
                                    Unit.Infect(game,firetargeti,infectinto);
                                }
                                firetargeti = -1;
                            }
                            if(controlmode=="crpg")//24sep2021
                            {
                                firetargeti = -1;//deselect target after we've hit them....
                                
                            }
                            if(hitandrun>0)
                            {
                                //Functions.saveseed();//11apr2021
                                if(Functions.rand(0,1000)<150)
                                {
                                    //start-------//15mar2021
                                    if(firetargeti!=-1)
                                    {
                                        tmptattempts = 0;
                                        tx = x + (Game.RESOLUTIONX / 3) * (int)Functions.sign(x - game.units[firetargeti].x);
                                        ty = y + (Game.RESOLUTIONY / 3) * (int)Functions.sign(y - game.units[firetargeti].y);
                                        tmptx = tx;
                                        tmpty = ty;
                                    }
                                    //end---------//15mar2021
                                    firetargeti = -1;
                                    orderframe = 180;//15mar2021
                                    //retreat = true;//15mar2021
                                    //retreatframe = game.frame + Unit.RETREATDEATH;//15mar2021
                                }
                                //Functions.restoreseed();//11apr2021
                            }
                        }
                    }
                    else
                    {
                        //we should move towards the target
                        tx = game.units[firetargeti].x;
                        ty = game.units[firetargeti].y;
                        tmptattempts = 0;
                        if(retreat)
                        {
                            tx = x + Game.RESOLUTIONX * (int)Functions.sign(x - game.units[firetargeti].x);
                            ty = y + Game.RESOLUTIONY * (int)Functions.sign(y - game.units[firetargeti].y);
                        }
                        if(faction!=Game.PLAYERFACTION && orderframe<=0)
                        {
                            firetargeti = -1;
                        }
                    }
                }
                else
                {
                    firetargeti = -1;
                }
            }
            else
            {
                //no current target
                //find one.....
                if(orderframe>0)
                {
                    return;
                }
                if(faction!=Game.PLAYERFACTION && game.playingtutorial==true)
                {
                    return;
                }
                if(controlmode=="crpg")//24sep2021
                {
                    return;
                }
                //start-----------------------//4may2021
                if(flightlevel!=-1)
                {
                    //flying units cannot attack unless they have an anim mode for flying attacks....
                    //unless they have an animmodeflyattackframestart!=0
                    if(animmodeflyattackframestart==0 && animmodeflyattackframeend==0)
                    {
                        return;
                    }
                }
                //end-------------------------//4may2021
                //start-------------//7mar2021
                if(stupid>0)
                {
                    //Functions.saveseed();//11apr2021
                    if(stupid>=100)
                    {
                        stupid=99;
                    }
                    //if(Functions.rand(0,100)<stupid)//27mar2021
                    int qqq0 = Functions.rand(0,100);//11apr2021
                    if(qqq0<stupid || ((game.frame + id) % 101)<stupid)//27mar2021
                    {
                        return;
                    }
                }
                //end---------------//7mar2021
                int aidist = 12;
                //if(ai>=AI_ASSAULT && faction!=Game.PLAYERFACTION && game.playerready==true)//18sep2021
                if(ai>=AI_ASSAULT && (faction!=Game.PLAYERFACTION || Config.AUTOPLAY>0) && game.playerready==true)//18sep2021
                {
                    aidist = 45 * ai;
                }
                //if(game.skirmish==true && ai>0 && faction!=Game.PLAYERFACTION)//27mar2021//18sep2021
                if(game.skirmish==true && ai>0 && (faction!=Game.PLAYERFACTION || Config.AUTOPLAY>0))//27mar2021//18sep2021
                {
                    aidist = Map.MAXX + Map.MAXY + 10; //27mar2021
                }
                int rangeblock = 1 + ((game.frame + id) % aidist);
                if(rangeblock>aidist)
                {
                    rangeblock = aidist;
                }
                //start-------------//7mar2021
                if(slow>0)
                {
                    rangeblock/=2;
                }
                //end---------------//7mar2021
                if(rangeblock<1)
                {
                    rangeblock = 1;
                }
                //up to 12 squares away......
                if(stealth>0)
                {
                    if (rangeblock>4)
                    {
                        rangeblock = 1 + (rangeblock % 4);
                    }
                }
                int target = -1;
                int mindist = 9999;
                int dist = 0;
                int fl = (game.frame + id) % Map.FLIGHTLEVELS;//4may2021
                for(int cx=myx - rangeblock;cx<=myx + rangeblock;cx++)
                {
                    int cyy = myy - rangeblock;
                    target = Map.cellunit(cx * Map.GRIDW,cyy * Map.GRIDH);
                    if(target!=-1)
                    {
                        if(game.units[target].x / Map.GRIDW == cx && game.units[target].y / Map.GRIDH == cyy)
                        {
                            if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                            {
                                dist = (int)(Functions.abs(cx - myx) + Functions.abs(cyy - myy));
                                if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                {
                                    //75% more likely to choose a mobile target....
                                    dist*=3;
                                    dist/=4;
                                    //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                    //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                    dist*=(10 - game.units[target].walkspeed);
                                    dist/=10;
                                }
                                if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                {
                                    if(needlos>0)//15sep2021
                                    {
                                        if(los(game,id,target))
                                        {
                                            mindist = dist;
                                            firetargeti = target;
                                        }
                                    }
                                    else//15sep2021
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                        }
                        target = -1;
                    }
                    //start---------------------//4may2021
                    if(canattackair>0)
                    {
                        cyy = myy - rangeblock;
                        target = Map.cellflyer(cx * Map.GRIDW,cyy * Map.GRIDH,fl);
                        if(target!=-1)
                        {
                            if(game.units[target].x / Map.GRIDW == cx && game.units[target].y / Map.GRIDH == cyy)
                            {
                                if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                                {
                                    dist = (int)(Functions.abs(cx - myx) + Functions.abs(cyy - myy));
                                    if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                    {
                                        //75% more likely to choose a mobile target....
                                        dist*=3;
                                        dist/=4;
                                        //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                        //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                        dist*=(10 - game.units[target].walkspeed);
                                        dist/=10;
                                    }
                                    if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                            target = -1;
                        }
                        cyy = myy + rangeblock;
                        target = Map.cellflyer(cx * Map.GRIDW,cyy * Map.GRIDH,fl);
                        if(target!=-1)
                        {
                            if(game.units[target].x / Map.GRIDW == cx && game.units[target].y / Map.GRIDH == cyy)
                            {
                                if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                                {
                                    dist = (int)(Functions.abs(cx - myx) + Functions.abs(cyy - myy));
                                    if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                    {
                                        //75% more likely to choose a mobile target....
                                        dist*=3;
                                        dist/=4;
                                        //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                        //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                        dist*=(10 - game.units[target].walkspeed);
                                        dist/=10;
                                    }
                                    if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                            target = -1;
                        }
                    }
                    //end-----------------------//4may2021
                    cyy = myy + rangeblock;
                    target = Map.cellunit(cx * Map.GRIDW,cyy * Map.GRIDH);
                    if(target!=-1)
                    {
                        if(game.units[target].x / Map.GRIDW == cx && game.units[target].y / Map.GRIDH == cyy)
                        {
                            if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                            {
                                dist = (int)(Functions.abs(cx - myx) + Functions.abs(cyy - myy));
                                if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                {
                                    //75% more likely to choose a mobile target....
                                    dist*=3;
                                    dist/=4;
                                    //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                    //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                    dist*=(10 - game.units[target].walkspeed);
                                    dist/=10;
                                }
                                if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                {
                                    if(needlos>0)//15sep2021
                                    {
                                        if(los(game,id,target))
                                        {
                                            mindist = dist;
                                            firetargeti = target;
                                        }
                                    }
                                    else//15sep2021
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                        }
                    }
                    target = -1;
                }
                for(int cy=myy - rangeblock;cy<=myy + rangeblock;cy++)
                {
                    int cxx = myx - rangeblock;
                    target = Map.cellunit(cxx * Map.GRIDW,cy * Map.GRIDH);
                    if(target!=-1)
                    {
                        if(game.units[target].x / Map.GRIDW == cxx && game.units[target].y / Map.GRIDH == cy)
                        {
                            if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                            {
                                dist = (int)(Functions.abs(cxx - myx) + Functions.abs(cy - myy));
                                if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                {
                                    //75% more likely to choose a mobile target....
                                    dist*=3;
                                    dist/=4;
                                    //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                    //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                    dist*=(10 - game.units[target].walkspeed);
                                    dist/=10;
                                }
                                if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                {
                                    if(needlos>0)//15sep2021
                                    {
                                        if(los(game,id,target))
                                        {
                                            mindist = dist;
                                            firetargeti = target;
                                        }
                                    }
                                    else//15sep2021
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                        }
                        target = -1;                        
                    }
                    //start-----------------------//4may2021
                    if(canattackair>0)
                    {
                        cxx = myx - rangeblock;
                        target = Map.cellflyer(cxx * Map.GRIDW,cy * Map.GRIDH,fl);
                        if(target!=-1)
                        {
                            if(game.units[target].x / Map.GRIDW == cxx && game.units[target].y / Map.GRIDH == cy)
                            {
                                if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                                {
                                    dist = (int)(Functions.abs(cxx - myx) + Functions.abs(cy - myy));
                                    if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                    {
                                        //75% more likely to choose a mobile target....
                                        dist*=3;
                                        dist/=4;
                                        //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                        //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                        dist*=(10 - game.units[target].walkspeed);
                                        dist/=10;
                                    }
                                    if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }                        
                        }
                        target = -1;
                        cxx = myx + rangeblock;
                        target = Map.cellflyer(cxx * Map.GRIDW,cy * Map.GRIDH,fl);
                        if(target!=-1)
                        {
                            if(game.units[target].x / Map.GRIDW == cxx && game.units[target].y / Map.GRIDH == cy)
                            {
                                if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                                {
                                    dist = (int)(Functions.abs(cxx - myx) + Functions.abs(cy - myy));
                                    if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                    {
                                        //75% more likely to choose a mobile target....
                                        dist*=3;
                                        dist/=4;
                                        //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                        //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                        dist*=(10 - game.units[target].walkspeed);
                                        dist/=10;
                                    }
                                    if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }                        
                        }
                        target = -1;
                    }
                    //end-------------------------//4may2021
                    cxx = myx + rangeblock;
                    target = Map.cellunit(cxx * Map.GRIDW,cy * Map.GRIDH);
                    if(target!=-1)
                    {
                        if(game.units[target].x / Map.GRIDW == cxx && game.units[target].y / Map.GRIDH == cy)
                        {
                            if(game.units[target].hp>0 && game.units[target].faction!=faction && game.units[target].faction!=Unit.NULLFACTION)
                            {
                                dist = (int)(Functions.abs(cxx - myx) + Functions.abs(cy - myy));
                                if(game.units[target].walkspeed>0 && prefermobiletargets>0)//18sep2021
                                {
                                    //75% more likely to choose a mobile target....
                                    dist*=3;
                                    dist/=4;
                                    //and they get a 10% higher rating for every point of 'extra speed' they have.....
                                    //noting that walkspeed is only between 1 and 3 and never as high as 10.
                                    dist*=(10 - game.units[target].walkspeed);
                                    dist/=10;
                                }
                                if(dist < mindist && dist < (rangeblock + 2) * Map.GRIDW)
                                {
                                    if(needlos>0)//15sep2021
                                    {
                                        if(los(game,id,target))
                                        {
                                            mindist = dist;
                                            firetargeti = target;
                                        }
                                    }
                                    else//15sep2021
                                    {
                                        mindist = dist;
                                        firetargeti = target;
                                    }
                                }
                            }
                        }                        
                    }
                    target = -1;
                }
                if(firetargeti!=-1)
                {
                    if(game.units[firetargeti].stealth>0)
                    {
                        //stealthy units are harder to target...unless they are themselves attacking......
                        if(game.units[firetargeti].animmode<=ANIMMODE_WALK)
                        {
                            //cannot be targeted.....
                            //unless they are within 2 grid squares....
                            if(Functions.abs(x-game.units[firetargeti].x)>=Map.GRIDW*3 || Functions.abs(y - game.units[firetargeti].y)>=Map.GRIDH*3)
                            {
                                firetargeti = -1;
                                orderframe = 1;
                                tx = x;
                                ty = y;
                                tmptx = x;
                                tmpty = y;
                            }
                        }
                    }
                    if(transportcapacity>0 && faction!=Game.PLAYERFACTION && (game.frame + id) % 60==6)//24apr2022
                    {
                        if(Functions.abs(tx-x)<300 && Functions.abs(ty-y)<300)
                        {
                            //Unit.DeployUnits(game,id);
                        }
                    }
                }
                else//24apr2022
                {
                    if(faction!=Game.PLAYERFACTION && (game.frame + id) % 60==5)
                    {
                        if(transportsize>0 && transportsize<99)
                        {
                            //look around us for an APC
                            for(int xx=x-Map.GRIDW*3;xx<=x+Map.GRIDW*3;xx+=Map.GRIDW)
                            {
                                for(int yy=y-Map.GRIDH*3;yy<=y+Map.GRIDH*3;yy+=Map.GRIDH)
                                {
                                    int nid = Map.cellunit(xx,yy);
                                    if(nid!=Map.VACANT)
                                    {
                                        if(game.units[nid].faction==faction)
                                        {
                                            if(game.units[nid].hp>0 && game.units[nid].transportcapacity>0 && transportsize<game.units[nid].transportcapacity)
                                            {
                                                //try to hop in....
                                                //Unit.GetInTransport(game,nid,id);//3may2021
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if(faction!=Game.PLAYERFACTION && firetargeti!=-1)
                {
                    orderframe = 60;
                }
                if(firetargeti!=-1 && rangeblock>=4 && onscreen==true)
                {
                    //Functions.saveseed();//11apr2021
                    Functions.saveseed();//25apr2021
                    if(Functions.rand(0,100)<20 && faction==Game.PLAYERFACTION)
                    {
                        playtargetchosensound(game,id);
                    }
                    if(Functions.rand(0,100)<5 && faction!=Game.PLAYERFACTION)
                    {
                        playtargetchosensound(game,id);
                    }
                    Functions.restoreseed();//25apr2021
                    //Functions.restoreseed();//11apr2021
                }
            }
        }

///////////////////Method Definition///////////////
        public static bool los(Game game,int id,int target)
        {
            int sx = game.units[id].x / Map.GRIDW;
            int sy = game.units[id].y / Map.GRIDH;
            int fx = game.units[target].x / Map.GRIDW;
            int fy = game.units[target].y / Map.GRIDH;
            if(sx>=0 && sx<Map.MAXX && sy>=0 && sy<Map.MAXY && fx>=0 && fx<Map.MAXX && fy>=0 && fy<Map.MAXY)
            {
                if(Map.losmap[sx,sy,fx,fy]==1)
                {
                    return true;
                }
                if(Map.losmap[sx,sy,fx,fy]==2)
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
            int vecdx = fx - sx;
            int vecdy = fy - sy;
            int lvecdx = vecdx;
            int lvecdy = vecdy;
            if(lvecdx<0)
            {
                lvecdx*=-1;
            }
            if(lvecdy<0)
            {
                lvecdy*=-1;
            }
            int length = lvecdx + lvecdy;
            if(length<=4)
            {
                return true;
            }
            for(int i=0;i<length - 1;i++)
            {
                int x = sx + (vecdx * i) / length;
                int y = sy + (vecdy * i) / length;
                if(!Map.passable(x * Map.GRIDW,y * Map.GRIDH))
                {
                    Map.losmap[sx,sy,fx,fy] = 2;
                    return false;
                }
                if(x==fx && y==fy)
                {
                    break;
                }
            }
            Map.losmap[sx,sy,fx,fy] = 1;
            return true;
        }
        
///////////////////Method Definition///////////////
        public static void debugtemplate(Unit unit)
        {
            //debug only
            unit.faction = HUMAN;
            unit.team = 0;
            //unit.cat = Resources.CAT_KNIGHT;
            unit.framesperdirn = 8;
            unit.basehp = 1;
            unit.hp = 1;
            unit.animmodeidleframestart = 0;
            unit.animmodeidleframeend = 0;
            unit.animmodewalkframeend = 7;
            unit.animmodewalkframestart = 0;
            unit.walkspeed = 2;
            unit.animspeed = 6;
        }

///////////////////Method Definition///////////////
        public Unit(Game game)
        {
            if(circles==null)//2jun2021
            {
                circles = new int[MAXUNITS];//2jun2021
                for(int i=0;i<MAXUNITS;i++)//2jun2021
                {
                    circles[i] = -1; //2jun2021
                }
            }
            infectchanceonhit = 0;//22apr2022
            infectchanceonkill = 0;//22apr2022
            infectinto = "";
            infected = 0;//22apr2022
            deathanim = "";//21feb2022
            dieonplace = 0;//21feb2022
            isdead = 0;//30sep2021
            scale = 1;
            prefermobiletargets=0;//18sep2021
            charactername = "";//10sep2021
            ping = 0;//17sep2021
            redping = -1;//17sep2021
            displaycharactername = 0;//10sep2021
            gold = -1;//23sep2021
            canpickup = 0;//23sep2021
            guiattackdisplaylimit = 0;//23sep2021
        
            //start-----------//4may2021
            canfly = 0;
            canflyandwalk = 0;
            flightlevel = -1;
            canattackair = 0;
            //end------------//4may2021
            //
            aiselectframe = 0;//21apr2021
            casting = false; //28mar2021
            misfire = 0;//28mar2021
            magicarray = new int[17];//28mar2021
            timedead = MAXDEADTIME;//25mar2021
            cursed = false; //21mar2021
            buffed = false; //21mar2021
            defendx = -1; //9mar2021
            defendy = -1; //9mar2021
            checkedgrid = new int[4];
            shocked = false;
            groupid = -1;
            controller = -1;
            controlpoint = 0;
            retreat = false;
            onscreen = false;
            mirrorleftright = true;
            controlmode = "";//24sep2021
            firetargeti = -1;
            cat = -1;
            cathires = -1;//9apr2021
            dropshadow=0;//25sep2021
            spawnertime = 10;
            spawner = "";
            spawnertemplateid = -1;//26feb2022
            spawnerconstraint = "*";//9sep2021
            transforminto = "";//3may2021
            transformrequires = "";//3may2021
            displayspawner = "";//13mar2021
            accuracy = 100;//28feb2022
            transportsize = 1;//3may2021
            transportcapacity = 0;//3may2021
            transportarray = new int[0];//3may2021
            transportedbyid = -1;//4may2021
            impactfx = new int[5];
            attackfx = new int[5];//24feb2022 changed from 3 to 5
            targetfx = new int[5];//24feb2022 changed from 3 to 5
            magicfx = new int[5];//24feb2022 changed from 3 to 5
            ackfx = new int[5];
            deathfx = new int[5]; //28jul2021
            selectfx = new int[5];
            offxa = new int[100];
            offya = new int[100];
            techguilinkid = new int[0];//26feb2022
            for(int i=0;i<impactfx.Length;i++)
            {
                impactfx[i] = -1;
            }
            for(int i=0;i<attackfx.Length;i++)
            {
                attackfx[i] = -1;
            }
            for(int i=0;i<targetfx.Length;i++)
            {
                targetfx[i] = -1;
            }
            for(int i=0;i<magicfx.Length;i++)
            {
                magicfx[i] = -1;
            }
            for(int i=0;i<ackfx.Length;i++)
            {
                ackfx[i] = -1;
            }
            for(int i=0;i<selectfx.Length;i++)
            {
                selectfx[i] = -1;
            }
            for(int i=0;i<deathfx.Length;i++)//28jul2021
            {
                deathfx[i] = -1;
            }
            
        }

///////////////////Method Definition///////////////
        public static int countselected(Game game)
        {
            //as title
            int count = 0;
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0)
                {
                    if(game.units[i].selected==Unit.SELECTIONFROZEN)
                    {
                        count++;
                    }
                }
            }
            return count;
        }

///////////////////Method Definition///////////////
        public static void issueorder(Game game,int gx, int gy)
        {
            //issue a move or attack order
            bool ordered = false;
            int j = -1;
            int scount = countselected(game);
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0)
                {
                    if(game.units[i].selected==Unit.SELECTIONFROZEN)
                    {
                        game.units[i].tx = gx;
                        game.units[i].ty = gy;
                        if(Game.HORIZONTALFORMATION>0 || Game.VERTICALFORMATION>0)//14apr2021
                        {
                            game.units[i].tx+=game.units[i].formationx;
                            game.units[i].ty+=game.units[i].formationy;
                        }
                        else
                        {
                            game.units[i].formationx = 0;
                            game.units[i].formationy = 0;
                        }
                        game.units[i].orderframe = Unit.ORDERTIME;
                        game.units[i].firetargeti = -1;
                        game.units[i].tmptattempts = 0;
                        game.units[i].defendx = -1; //12mar2021
                        game.units[i].defendy = -1; //12mar2021
                        Game.ordergivenframe = game.frame;
                        ordered = true;
                        j = i;
                        //12mar2021 - added a radius of 1 grid square around it....
                        int nid = Map.cellunit(game.units[i].tx,game.units[i].ty);
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx - Map.GRIDW,game.units[i].ty);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty - Map.GRIDH);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty + Map.GRIDH);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        //start--------//24mar2021
                        //if(Game.mouseoverunitid!=-1)//4sep2021
                        //start--------//22feb2022
                        bool donot = false;
                        for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                        {                                        
                            int fid = (Map.cellflyer(game.units[i].tx,game.units[i].ty,fl));
                            if(fid!=-1)
                            {
                                if(game.units[fid].faction==game.units[i].faction)
                                {
                                    if(game.units[fid].faction==game.units[i].faction && game.units[fid].hp>0 && game.units[fid].transportcapacity>0 && game.units[i].transportsize<game.units[fid].transportcapacity)//3may2021
                                    {
                                        Unit.GetInTransport(game,fid,i);//3may2021
                                        donot = true;
                                    }
                                }
                            }
                        }
                        //end----------//22feb2022
                        
                        if(nid!=-1 && donot==false)//4sep2021
                        {
                            //nid = Game.mouseoverunitid;//4sep2021
                            //check if we should get in the transport...if it is a transport....
                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].transportcapacity>0 && game.units[i].transportsize<game.units[nid].transportcapacity)//3may2021
                            {
                                Unit.GetInTransport(game,nid,i);//3may2021
                            }
                        }
                        //end----------//24mar2021
                        if(nid!=-1 && !Game.EDITOR)
                        {
                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].faction!=Unit.NULLFACTION)
                            {
                                game.units[i].firetargeti = nid;
                                game.units[i].orderframe = 0;
                                Game.clickerrow = 1;//15apr2021
                            }
                        }
                        //if(scount > 1 && Game.VERTICALFORMATION==0 && Game.HORIZONTALFORMATION==0)//14apr2021//15sep2021
                        if(scount > 1 && Game.VERTICALFORMATION==0 && Game.HORIZONTALFORMATION==0 && Config.CLUMP==0)//14apr2021//15sep2021
                        {
                            game.units[i].tx = gx + (int)Functions.rand(-Map.GRIDW*4,Map.GRIDW*4);
                            game.units[i].ty = gy + (int)Functions.rand(-Map.GRIDH*4,Map.GRIDH*4);
                        }
                    }
                }
            }
            if(ordered)
            {
                game.units[j].playacknowledgesound(game,j);
            }
        }

///////////////////Method Definition///////////////
        public static void issueorder(Game game)
        {
            //issue a move or attack order
            bool ordered = false;
            int j = -1;
            int scount = countselected(game);
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0)
                {
                    if(game.units[i].selected==Unit.SELECTIONFROZEN)
                    {
                        //zoom stuff
                        game.units[i].tx = Game.CORNERX + (Game.RESOLUTIONX/2) + (int)(((float)(game.mx) - (float)Game.RESOLUTIONX/2)/game.zoom);
                        game.units[i].ty = Game.CORNERY + (Game.RESOLUTIONY/2) + (int)(((float)(game.my) - (float)Game.RESOLUTIONY/2)/game.zoom);
                        game.units[i].orderframe = Unit.ORDERTIME;
                        game.units[i].firetargeti = -1;
                        game.units[i].tmptattempts = 0;
                        game.units[i].defendx = -1; //12mar2021
                        game.units[i].defendy = -1; //12mar2021
                        if(Game.HORIZONTALFORMATION>0 || Game.VERTICALFORMATION>0)//14apr2021
                        {
                            game.units[i].tx+=game.units[i].formationx;
                            game.units[i].ty+=game.units[i].formationy;
                        }
                        else
                        {
                            game.units[i].formationx = 0;
                            game.units[i].formationy = 0;
                        }
                        
                        ordered = true;
                        Game.ordergivenframe = game.frame;
                        j = i;
                        int nid = Map.cellunit(game.units[i].tx,game.units[i].ty);
                        //12mar2021 added these 1 grid cell checker...
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx - Map.GRIDW,game.units[i].ty);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty - Map.GRIDH);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        if(nid==-1)
                        {
                            nid = Map.cellunit(game.units[i].tx + Map.GRIDW,game.units[i].ty + Map.GRIDH);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==game.units[i].faction)
                                {
                                    nid = -1;
                                }
                            }
                        }
                        //start--------//22feb2022
                        bool donot = false;
                        for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                        {                                        
                            int fid = (Map.cellflyer(game.units[i].tx,game.units[i].ty,fl));
                            if(fid!=-1)
                            {
                                if(game.units[fid].faction==game.units[i].faction)
                                {
                                    if(game.units[fid].faction==game.units[i].faction && game.units[fid].hp>0 && game.units[fid].transportcapacity>0 && game.units[i].transportsize<game.units[fid].transportcapacity)//3may2021
                                    {
                                        Unit.GetInTransport(game,fid,i);//3may2021
                                        donot = true;
                                    }
                                }
                            }
                        }
                        //end----------//22feb2022
                        
                        //start--------//24mar2021
                        //if(Game.mouseoverunitid!=-1)//4sep2021
                        if(nid!=-1 && donot == false)//4sep2021
                        {
                            //nid = Game.mouseoverunitid;//4sep2021
                            //check if we should get in the transport...if it is a transport....
                            if(game.units[nid].faction==game.units[i].faction && game.units[nid].hp>0 && game.units[nid].transportcapacity>0 && game.units[i].transportsize<game.units[nid].transportcapacity)//3may2021
                            {
                                Unit.GetInTransport(game,nid,i);//3may2021
                            }
                        }
                        //end----------//24mar2021
                        if(nid!=-1 && !Game.EDITOR)
                        {
                            if(game.units[nid].faction!=game.units[i].faction && game.units[nid].hp>0 && game.units[nid].faction!=Unit.NULLFACTION)
                            {
                                game.units[i].firetargeti = nid;
                                game.units[i].orderframe = 0;
                                Game.clickerrow = 1;//15apr2021
                            }
                        }
                        //if(scount > 1)
                        //if(scount > 1 && Game.VERTICALFORMATION==0 && Game.HORIZONTALFORMATION==0)//14apr2021//15sep2021
                        if(scount > 1 && Game.VERTICALFORMATION==0 && Game.HORIZONTALFORMATION==0 && Config.CLUMP==0)//14apr2021//15sep2021
                        {
                            game.units[i].tx+= (int)Functions.rand(-Map.GRIDW*4,Map.GRIDW*4);
                            game.units[i].ty+= (int)Functions.rand(-Map.GRIDH*4,Map.GRIDH*4);
                        }
                    }
                }
            }
            if(ordered)
            {
                game.units[j].playacknowledgesound(game,j);
            }
        }

///////////////////Method Definition///////////////
        public static void deselect(Game game)
        {
            //deselect all units
            if(game.frame - game.minimapframe>5)
            {
                //for(int i=0;i<game.units.Length;i++)//26mar2021
                for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
                {
                    if(game.units[i].selected!=Unit.SELECTIONNONE)
                    {
                        game.units[i].selected=Unit.SELECTIONNONE;
                    }            
                }
            }
        }

///////////////////Method Definition///////////////
        public static void selectone(Game game)
        {
            //select a single unit
            if(game.frame - game.minimapframe <= 5)
            {
                return;
            }
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0 && (game.units[i].faction==Game.PLAYERFACTION || Game.EDITOR==true))
                {
                    //if(game.units[i].faction==PLAYERFACTION)
                    //{
                    //zoom stuff
                    int mmx = (int)((float)(game.mx - Game.RESOLUTIONX/2)/game.zoom) + Game.CORNERX + Game.RESOLUTIONX/2;
                    int mmy = (int)((float)(game.my - Game.RESOLUTIONY/2)/game.zoom) + Game.CORNERY + Game.RESOLUTIONY/2;
                    if(mmx < game.units[i].x + (game.units[i].cw/2)/game.zoom && mmx > game.units[i].x - (game.units[i].cw/2)/game.zoom)
                    {
                        if(mmy < game.units[i].y + (game.units[i].ch/2)/game.zoom + (game.units[i].offy)/game.zoom && mmy > game.units[i].y - (game.units[i].ch/2 + game.units[i].offy)/game.zoom)
                        {
                            if(game.frame - game.units[i].selectedframe < 15)
                            {
                                //select all of the same type.....
                                //for(int j=0;j<game.units.Length;j++)//26mar2021
                                for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                                {
                                    game.units[j].selected = Unit.SELECTIONNONE;
                                    if(game.units[j].hp>0 && game.units[j].name==game.units[i].name)
                                    {
                                        game.units[j].selected = Unit.SELECTIONSTART;
                                    }
                                }
                            }
                            game.units[i].selected = Unit.SELECTIONSTART;
                            game.units[i].selectedframe = game.frame;
                            //Game.selectingtime = Game.WAITSELECTINGTIME;//26mar2021
                            return;
                        }
                    }
                    //}
                }
            }
        }

///////////////////Method Definition///////////////
        public static bool noneselected(Game game)
        {
            //check if no units are selected
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0)
                {
                    if(game.units[i].selected!=Unit.SELECTIONNONE)
                    {
                        return false;
                    }
                }
            }
            return true;
        }

///////////////////Method Definition///////////////
        public static void freezeselect(Game game)
        {
            //take units that have been drag selected and
            //mark them as properly selected
            bool selected = false;
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].hp>0)
                {
                    if(game.units[i].selected==Unit.SELECTIONSTART)
                    {
                        game.units[i].selected=Unit.SELECTIONFROZEN;
                        if(!selected)
                        {
                            selected = true;
                            game.units[i].playselectsound(game,i);
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void select(Game game,int x, int y, int w, int h)
        {
            //select the units at this location
            //zoom stuff
            bool anyselected = false;
            bool selectsingle = false;
            int ww = 0;
            int hh = 0;
            if(w==-1 && h==-1)
            {
                w = 40 ;//* (int)game.zoom;
                h = 40 ;//* (int)game.zoom;
                selectsingle = true;
                ww = w;
                hh = h;
            }
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].transportedbyid!=-1)//4may2021 //bugfix
                {
                    continue;
                }
                if(game.units[i].hp>0 && (game.units[i].faction==Game.PLAYERFACTION || Game.EDITOR==true))
                {
                    //if(game.units[i].faction==PLAYERFACTION)
                    //{
                    //if(x + Game.CORNERX<game.units[i].x    && x + Game.CORNERX + w > game.units[i].x)
                    //if(x - ww <game.units[i].x    && x + w > game.units[i].x)//26mar2021
                    if((x - ww <game.units[i].x    && x + w > game.units[i].x) || (i == Game.mouseoverunitid && selectsingle==true))//26mar2021
                    {
                        //if(y + Game.CORNERY < game.units[i].y + game.units[i].offy && y + Game.CORNERY + h > game.units[i].y + game.units[i].offy)
                        //if(y - hh < game.units[i].y + game.units[i].offy/game.zoom && y + h > game.units[i].y + game.units[i].offy/game.zoom)//26mar2021
                        if((y - hh < game.units[i].y + game.units[i].offy/game.zoom && y + h > game.units[i].y + game.units[i].offy/game.zoom) || (i == Game.mouseoverunitid && selectsingle==true))//26mar2021
                        {
                            anyselected = true;
                            if(selectsingle)
                            {
                                if(game.frame - game.units[i].selectedframe < 15)
                                {
                                    //select all of the same type.....
                                    //for(int j=0;j<game.units.Length;j++)//26mar2021
                                    for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                                    {
                                        game.units[j].selected = Unit.SELECTIONNONE;
                                        if(game.units[j].hp>0 && game.units[j].name==game.units[i].name)
                                        {
                                            game.units[j].selected = Unit.SELECTIONSTART;
                                        }
                                    }
                                }
                                else
                                {
                                    //28mar2021 check
                                    for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                                    {
                                        game.units[j].selected = Unit.SELECTIONNONE;
                                    }
                                }
                            }
                            game.units[i].selected = Unit.SELECTIONSTART;
                            game.units[i].selectedframe = game.frame;
                            //Game.selectingtime = Game.WAITSELECTINGTIME;//26mar2021
                            if(selectsingle)
                            {
                                break;
                            }
                        }
                    }
                    //}
                }
            }
            //start-------------//9mar2021
            //this block prevents units from being deselected when an icon in the gui is clicked upon
            //eg - if you are clicking the selection icons you don't want everything to become unselected
            //because you've left clicked somewhere on the screen!
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].action>=Gui.ACTION_FORMATIONSTART && game.gui[i].action<=Gui.ACTION_FORMATIONEND && game.gui[i].mouseover==true)
                {
                    return; //looks okay
                }
                //start-------------//10mar2021
                if(game.gui[i].triggerlink==Gui.LINK_SPAWNER_ICON && game.gui[i].mouseover==true && (Game.SPAWNERSELECTED==true || Game.NONSPAWNERSELECTED==true))//11mar2021
                {
                    return; //looks okay
                }
                //end---------------//10mar2021
                //start-------------//2sep2021
                if(game.gui[i].triggerlink==Gui.LINK_TECH_ICON && game.gui[i].mouseover==true && (Game.SPAWNERSELECTED==true || Game.NONSPAWNERSELECTED==true || Tech.TECHUNITSELECTED == true))//11mar2021
                {
                    return; //looks okay
                }
                //end---------------//2sep2021
                //start-----------------//22mar2021
                if(Game.showingselectedicons==true && game.gui[i].triggerlink==Gui.LINK_SELECTED_ICONS && game.gui[i].mouseover==true)
                {
                    return;//looks okay
                }
                //end-------------------//22mar2021
                //start---------------//28mar2021
                if(Game.SPELLCASTERSELECTED!=-1 && game.gui[i].action>=Gui.ACTION_SPELL_START && game.gui[i].action<=Gui.ACTION_SPELL_END && game.gui[i].mouseover==true)
                {
                    return;//looks okay
                }
                //end-----------------//28mar2021
            }
            //end---------------//9mar2021
            if(!anyselected)
            {
                Unit.deselect(game);
                //and check if any enemy are selected......
                //for(int i=0;i<game.units.Length;i++)//26mar2021
                for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
                {
                    if(game.units[i].hp>0 && (game.units[i].faction!=Game.PLAYERFACTION))
                    {
                        if(x - ww <game.units[i].x    && x + w > game.units[i].x)
                        {
                            if(y - hh < game.units[i].y + game.units[i].offy/game.zoom && y + h > game.units[i].y + game.units[i].offy/game.zoom)
                            {
                                game.units[i].selected = Unit.SELECTIONENEMY;
                                break;
                            }
                        }
                        //}
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void deselectall(Game game)
        {
            //as title
            if(game.frame - game.minimapframe > 5)
            {
                //for(int i=0;i<game.units.Length;i++)//26mar2021
                for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
                {
                    game.units[i].selected = Unit.SELECTIONNONE;
                }
            }
        }

///////////////////Method Definition///////////////
        public void draw(Game game)
        {
            //draw the unit - individual unit draw
            float alpha = 1f;//2apr2021
            if(stealth>0)
            {
                alpha = 0.7f + 0.25f * (float)Math.Sin((float)game.frame/20);
            }
            int tmpanimframe = animframe;
            onscreen = true;
            if(faction==NULLFACTION || nodirn==1) //scenery...special scenery...
            {
                if(walkspeed<=0)
                {
                    dirn = 0;
                    animmode = ANIMMODE_IDLE;
                }
            }
            if(hp <= 0)
            {
                if(animmode!=ANIMMODE_DEAD)//13sep2021
                {
                    return;
                }
            }
            //start-----------------//21mar2021
            //circles are offset too wrongly.....
            //if(Config.USEICONCIRCLES==true && Config.USEFEETCIRCLES==true)//20apr2021
            //2jun2021 removed whole next section and moved it elsewhere...where circlesmax is used....
            /*
            if(Config.USEFEETCIRCLES && game.templates[templateid].walkspeed>0)//20apr2021
            {
                //offx added 20apr2021
                if(selected!=Unit.SELECTIONNONE)
                {
                    if(Game.iconcircles!=-1)
                    {
                        float cc = 0.8f;
                        int cw0 = cw;
                        int ch0 = ch;
                        if(cw0<70)
                        {
                            cw0 = 70;
                        }
                        if(ch0<85)
                        {
                            ch0 = 85;
                        }
                        if(faction==Game.PLAYERFACTION)
                        {
                            //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,0,0,false,1f,Game.iconcircles);    
                            //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,0,1,false,0.25f,Game.iconcircles);    
                            RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX,height + y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,0,0,false,1f,Game.iconcircles);    
                            RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX,height + y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,0,1,false,0.25f,Game.iconcircles);    
                        }
                        else
                        {
                            //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,1,0,false,1f,Game.iconcircles);    
                            //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,1,1,false,0.25f,Game.iconcircles);    
                            RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX,height + y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,1,0,false,1f,Game.iconcircles);    
                            RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX,height + y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,1,1,false,0.25f,Game.iconcircles);    
                        }
                    }
                }
            }
            *
/
            //start-------------//24mar2021
            //if(game.mx > x-Game.CORNERX - cw/2 && game.mx < x - Game.CORNERX + cw/2 && game.my > y - Game.CORNERX + offy - ch/2 && game.my < y - Game.CORNERY + offy + ch/2)//26mar2021
            if(game.mx > x-Game.CORNERX - cw/4 && game.mx < x - Game.CORNERX + cw/4 && game.my > y - Game.CORNERY + offy - ch/4 && game.my < y - Game.CORNERY + offy + ch/4 && game.zoom==1)//26mar2021
            {
                //24apr2021 addressed potential mouseoverunitid being corrupt
                if(hp>0)//24apr2021
                {
                    Game.mouseoverunitid = id;
                }
            }
            //end---------------//24mar2021
            //end-------------------//21mar2021
            if(cat==-1) //show coloured rectangles if there are no graphics yet...
            {
                byte tr = 32;
                byte tg = 200;
                byte tb = 32;
                if(faction!=Game.PLAYERFACTION)
                {
                    tr = 200;
                    tg = 32;
                }
                RenderList.drawrect(game,x - Game.CORNERX - cw/2,height + y - Game.CORNERY - ch/2+offy,cw,ch,RenderList.getrgb(tr,tg,tb),0);
                //RenderList.drawtext(game,x - Game.CORNERX - cw/2,height + y - Game.CORNERY - ch+offy,name,RenderList.getrgb(200,200,180),game.fonts[Resources.SMALLFONT].font,true);//13mar2021
                RenderList.drawtext(game,x - Game.CORNERX - cw/2,height + y - Game.CORNERY - ch+offy,dname(),RenderList.getrgb(200,200,180),game.fonts[Resources.SMALLFONT].font,true);//13mar2021
            }
            else
            {
                if(mirrorleftright && (dirn==DIRN_DOWNRIGHT || dirn==DIRN_RIGHT || dirn==DIRN_UPRIGHT))
                {
                    int tmpdirn = dirn;
                    if(dirn==DIRN_DOWNRIGHT)
                    {
                        tmpdirn = DIRN_DOWNLEFT;
                    }
                    if(dirn==DIRN_RIGHT)
                    {
                        tmpdirn = DIRN_LEFT;
                    }
                    if(dirn==DIRN_UPRIGHT)
                    {
                        tmpdirn = DIRN_UPLEFT;
                    }
                    //2apr2021 added alpha
                    //9apr2021 cathires
                    //20apr2021 added offx
                    if(dropshadow>0)//25sep2021
                    {
                        RenderList.drawrect(game,offx + x - Game.CORNERX + (int)(scale * cw/2) - cw/14,height + y - Game.CORNERY + offy + (int)(scale * ch * 8) / 10,(int)(scale * cw/7),(int)(scale * ch/10),RenderList.getrgb(10,10,10),0);
                    }
                    if(cathires!=-1)
                    {
                        //25sep2021 added scale
                        RenderList.drawimage(game,game.images[cathires].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.5f * scale,0.5f * scale,tmpdirn * framesperdirn + tmpanimframe,0,false,alpha,cathires);    
                        //start----------//28feb2022
                        if(faction==6 && basehp<20 && Config.highseas!=0)
                        {
                            //if(Game.highseas_lo!=-1)
                            //{
                                //RenderList.drawimage(game,game.images[Game.highseas_lo].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.5f * scale,0.5f * scale,tmpdirn,0,false,alpha,Game.highseas_lo);    
                            //}
                            if(Game.highseas_hi!=-1 && tmpdirn==0)
                            {
                                RenderList.drawimage(game,game.images[Game.highseas_hi].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.75f * scale,0.75f * scale,tmpdirn,0,false,alpha,Game.highseas_hi);    
                            }
                        }
                        //end------------//28feb2022
                    }
                    else
                    {
                        //25sep2021 added scale
                        RenderList.drawimage(game,game.images[cat].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-1f * scale,1f * scale,tmpdirn * framesperdirn + tmpanimframe,0,false,alpha,cat);    
                        //start----------//28feb2022
                        if(faction==6 && basehp<20 && Config.highseas!=0)
                        {
                            if(Game.highseas_lo!=-1 && tmpdirn==0)
                            {
                                RenderList.drawimage(game,game.images[Game.highseas_lo].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.75f * scale,0.75f * scale,tmpdirn,0,false,alpha,Game.highseas_lo);    
                            }
                            //if(Game.highseas_hi!=-1)
                            //{
                            //    RenderList.drawimage(game,game.images[Game.highseas_hi].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.5f * scale,0.5f * scale,tmpdirn,0,false,alpha,Game.highseas_hi);    
                            //}
                        }
                        //end------------//28feb2022
                    }
                    
                }
                else
                {
                    if(controlpoint==1)
                    {
                        //20apr2021 added offx
                        if(controller==Game.PLAYERFACTION)
                        {
                            //25sep2012 added scale
                            RenderList.drawimage(game,game.images[fcat].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f * scale,1f * scale,dirn * framesperdirn + tmpanimframe,0,false,1f,fcat);    
                        }
                        if(controller==Game.SKIRMISHENEMYFACTION)
                        {
                            //25sep2012 added scale
                            RenderList.drawimage(game,game.images[ecat].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f * scale,1f * scale,dirn * framesperdirn + tmpanimframe,0,false,1f,ecat);    
                        }
                        if(controller!=Game.PLAYERFACTION && controller!=Game.SKIRMISHENEMYFACTION)
                        {
                            //9apr2021 hires stuff
                            //20apr2021 added offx
                            if(cathires!=-1)
                            {
                                //25sep2012 added scale
                                RenderList.drawimage(game,game.images[cathires].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,0.5f * scale,0.5f * scale,dirn * framesperdirn + tmpanimframe,0,false,1f,cathires);    
                            }
                            else
                            {
                                //25sep2012 added scale
                                RenderList.drawimage(game,game.images[cat].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY+offy,0,1f * scale,1f * scale,dirn * framesperdirn + tmpanimframe,0,false,1f,cat);    
                            }
                            
                        }
                    }
                    else
                    {
                        //2apr2021 added alpha
                        //9apr2021 added hires
                        //20apr2021 added offx
                        if(nodirn>0)
                        {
                            dirn = 0;
                        }
                        if(cathires!=-1)
                        {
                            //25sep2012 added scale
                            RenderList.drawimage(game,game.images[cathires].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY+offy,0,0.5f * scale,0.5f * scale,dirn * framesperdirn + tmpanimframe,0,false,alpha,cathires);    
                            //start----------//28feb2022
                            if(faction==6 && basehp<20 && Config.highseas!=0)
                            {
                                //if(Game.highseas_lo!=-1)
                                //{
                                    //RenderList.drawimage(game,game.images[Game.highseas_lo].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.5f * scale,0.5f * scale,dirn,0,false,alpha,Game.highseas_lo);    
                                //}
                                if(Game.highseas_hi!=-1 && dirn==0)
                                {
                                    RenderList.drawimage(game,game.images[Game.highseas_hi].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.75f * scale,0.75f * scale,dirn,0,false,alpha,Game.highseas_hi);    
                                }
                            }
                            //end------------//28feb2022
                        }
                        else
                        {
                            //25sep2012 added scale
                            RenderList.drawimage(game,game.images[cat].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY+offy,0,1f * scale,1f * scale,dirn * framesperdirn + tmpanimframe,0,false,alpha,cat);    
                            //start----------//28feb2022
                            if(faction==6 && basehp<20 && Config.highseas!=0)
                            {
                                if(Game.highseas_lo!=-1 && dirn==0)
                                {
                                    RenderList.drawimage(game,game.images[Game.highseas_lo].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.75f * scale,0.75f * scale,dirn,0,false,alpha,Game.highseas_lo);    
                                }
                                //if(Game.highseas_hi!=-1)
                                //{
                                //    RenderList.drawimage(game,game.images[Game.highseas_hi].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,-0.5f * scale,0.5f * scale,dirn,0,false,alpha,Game.highseas_hi);    
                                //}
                            }
                            //end------------//28feb2022
                        }
                    }
                }
            }
            if(Unit.CRPG>0)//25sep2021
            {
                if(faction==Game.SKIRMISHENEMYFACTION && hp>0)
                {
                    drawhealthbar(game);
                }
            }
            //25sep2021 removed this again....
            
            //2jun2021 altered this section and moved it elsewhere....
            //if(selected!=Unit.SELECTIONNONE || (bossmonster>0 && game.skirmish==false))
            //{
                //if(game.templates[templateid].walkspeed<=0 || selected==Unit.SELECTIONNONE) //2jun2021 - this is to account for the fact that SOME of these won't be drawn in the other section....
                //{
                //    drawhealthbar(game);
                //}
            //}
            //if(retreat)//15mar2021
            //20apr2021 added offx
            if(retreat==true && Game.whiteflag!=-1)//15mar2021
            {
                RenderList.drawimage(game,game.images[Game.whiteflag].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f,1f,tmpanimframe % 3,0,false,1f,Game.whiteflag);    
            }
            if((defendx!=-1 || defendy!=-1) && Game.shield!=-1)//15mar2021
            {
                RenderList.drawimage(game,game.images[Game.shield].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f,1f,0,0,false,1f,Game.shield);    
            }
            if(buffed && Game.iconplus!=-1) //21mar2021
            {
                RenderList.drawimage(game,game.images[Game.iconplus].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f,1f,0,0,false,1f,Game.iconplus);    
            }
            if((cursed==true || misfire!=0) && Game.iconminus!=-1)
            {
                RenderList.drawimage(game,game.images[Game.iconminus].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY+offy,0,1f,1f,0,0,false,1f,Game.iconminus);    
            }
            //start-----------------//21mar2021
            //20apr2021 added offx
            if(Config.USEICONCIRCLES)
            {
                if(Game.iconcircles!=-1 && Game.groupselected==groupid)
                {
                    if(groupid>=0 && groupid<=9)
                    {
                        //25sep2012 added scale
                        RenderList.drawimage(game,game.images[Game.iconcircles].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY + offy,0,0.5f * scale,0.5f * scale,2 + groupid,0,false,1f,Game.iconcircles);    
                    }
                }
                if(Config.USECOVERFLAG)
                {
                    if(Game.iconcircles!=-1 && game.gamestate==Game.CAT_GAMESTATE_GAME)
                    {
                        if(Map.nearobstacle(x,y))
                        {
                            //coverindicator
                            RenderList.drawimage(game,game.images[Game.iconcircles].texture,offx + x-Game.CORNERX,height + y-Game.CORNERY + offy,0,0.5f,0.5f,12,0,false,1f,Game.iconcircles);    
                        }
                    }
                }
            }
            //end-------------------//21mar2021
            //20apr2021 added offx
            if(Game.EDITOR)
            {
                //RenderList.drawtext(game,x - Game.CORNERX,height + y - Game.CORNERY + offy,name+","+(x/Map.GRIDW)+","+(y/Map.GRIDH),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//13mar2021
                RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy,dname()+","+Translation.TranslateNumber(x/Map.GRIDW)+","+Translation.TranslateNumber(y/Map.GRIDH),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//13mar2021
            }
            else//10sep2021
            {
                if(displaycharactername>0)
                {
                    RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy - ch/2,dname(),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//13mar2021                    
                }
            }
            //if(spawner!="" && spawnercount>0) //11mar2021//13mar2021
            //start--------------//13mar2021
            if(displayspawner=="")
            {
                displayspawner = spawner;
            }
            //end----------------//13mar2021
            if(spawnertemplateid!=-1 && faction==Game.PLAYERFACTION)//26feb2022//25apr2022 added playerfaction
            {
                if(Trigger.VARIABLE[Trigger.TYPE_POINTS]<game.templates[spawnertemplateid].points)//26feb2022
                {
                    //this is an attempt to stop the movement of the progress bar despite having no army points to build any units...or this unit....
                    spawnercount = 0;
                }
            }
            if(displayspawner!="" && spawnercount>0) //11mar2021//13mar2021
            {
                //todo 13mar2021
                //RenderList.drawtext(game,x - Game.CORNERX,height + y - Game.CORNERY + offy,spawner,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//13mar2021
                //RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy,displayspawner,RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//13mar2021//24apr2021
                RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy,displayspawner + " " +Translation.TranslateNumber(spawnercount),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//24apr2021
                RenderList.drawunfilledrect(game,offx + x - Game.CORNERX - 1 - 50,height + y - Game.CORNERY + offy - game.fonts[Resources.FONT].ptsize * 2 - 1,100,4,RenderList.getrgb(180,180,200),0);
                RenderList.drawrect(game,offx + x - Game.CORNERX - 50,height + y - Game.CORNERY + offy - game.fonts[Resources.FONT].ptsize * 2,percentagespawn(game),2,RenderList.getrgb(32,255,255),0);
            }
            //start-----------//12jul2021
            if(bounddemon>1)
            {
                RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy," " +Translation.TranslateNumber(bounddemon),RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,true);//24apr2021
            }
            if(bounddemon==1)
            {
                RenderList.drawtext(game,x - Game.CORNERX + offx,height + y - Game.CORNERY + offy,Translation.TranslateWord("!",false) ,RenderList.getrgb(255,155,100),game.fonts[Resources.FONT].font,true);//24apr2021
            }
            //end-------------//12jul2021
            drawn = true;
        }

///////////////////Method Definition///////////////
        public void drawhealthbar(Game game)
        {
            //draw the unit's health bar
            int pct = ((10 * hp) / basehp) - 1;
            if (pct<0)
            {
                pct = 0;
            }
            if(pct>5)
            {
                pct = 5;
            }
            //20apr2021 added offx
            RenderList.drawanimimage(game,game.images[Game.healthbar].texture,offx + x - Game.CORNERX,height + y - Game.CORNERY - ch/2 + offy,0,1f,1f,pct,0,false,1f,Game.healthbar);
            //also show xp //1mar2022
            if(faction==6)
            {
                if(xp>5)
                {
                    RenderList.drawrect(game,-5 + offx + x - Game.CORNERX,height + y - Game.CORNERY - ch/2 + offy + 3,2,2,RenderList.getrgb(255,225,64),0);
                }
                if(xp>10)
                {
                    RenderList.drawrect(game,- 5 + offx + x - Game.CORNERX + 5,height + y - Game.CORNERY - ch/2 + offy + 3,2,2,RenderList.getrgb(255,225,64),0);
                    
                }
                if(xp>15)
                {
                    RenderList.drawrect(game,- 5 + offx + x - Game.CORNERX + 10,height + y - Game.CORNERY - ch/2 + offy + 3,2,2,RenderList.getrgb(255,225,64),0);
                }
            }
            if(infected>0)//24apr2022
            {
                RenderList.drawrect(game,- 5 + offx + x - Game.CORNERX + 15,height + y - Game.CORNERY - ch/2 + offy + 3,2,2,RenderList.getrgb(64,235,64),0);
            }
            //int pct = (cw * hp) / basehp;
            /*
            RenderList.drawrect(game,x - Game.CORNERX - cw/2,y - Game.CORNERY - ch/2+offy,cw,3,RenderList.getrgb(255,32,32),0);
            if(bossmonster>0 && game.skirmish==false)
            {
                RenderList.drawrect(game,x - Game.CORNERX - cw/2,y - Game.CORNERY - ch/2+offy,pct,3,RenderList.getrgb(255,255,32),0);
            }
            else
            {
                RenderList.drawrect(game,x - Game.CORNERX - cw/2,y - Game.CORNERY - ch/2+offy,pct,3,RenderList.getrgb(32,255,32),0);
            }
            *
/
            /*
            for(int i=pct;i<cw;i+=4)
            {
                RenderList.drawrect(game,x - Game.CORNERX - cw/2+i,y - Game.CORNERY - ch/2+offy,3,3,RenderList.getrgb(255,32,32),0);
            }
            for(int i=0;i<pct;i+=4)
            {
                if(bossmonster>0 && game.skirmish==false)
                {
                    RenderList.drawrect(game,x - Game.CORNERX - cw/2+i,y - Game.CORNERY - ch/2+offy,3,3,RenderList.getrgb(255,255,32),0);
                }
                else
                {
                    RenderList.drawrect(game,x - Game.CORNERX - cw/2+i,y - Game.CORNERY - ch/2+offy,3,3,RenderList.getrgb(32,255,32),0);
                }
            }
            *
/
        }

///////////////////Method Definition///////////////
        public void managecontrolpoint(Game game)
        {
            //manage a control point - a type of infinite spawner
            //that is controlled by whoever is closest
            if(Game.EDITOR)
            {
                return;
            }
            int framecheck = 60;
            if(Config.RUNNINGSPEED > 90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED > 110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            int gx = x / Map.GRIDW;
            int gy = y / Map.GRIDH;
            int gdist = firerange / Map.GRIDW;
            int countfriends = 0;
            int countenemies = 0;
            bool emptyslot = false;
            int[] countfaction = new int[Game.MAXFACTIONS]; //26oct2020
            int highest = 0;
            int highestfaction = 0;
            if((game.frame + id) % framecheck==11)
            {
                //every second update the control points......
                for(int xx=gx-gdist;xx<=gx+gdist;xx++)
                {
                    for(int yy=gy-gdist;yy<=gy+gdist;yy++)
                    {
                        if(xx>=0 && yy>=0 && xx<Map.MAXX && yy<Map.MAXY)
                        {
                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                            if(nid!=-1)
                            {
                                if(game.units[nid].faction==Game.PLAYERFACTION)
                                {
                                    countfriends++;
                                }
                                if(game.units[nid].faction==Game.SKIRMISHENEMYFACTION)
                                {
                                    countenemies++;
                                }
                                if(game.units[nid].faction>=0 && game.units[nid].faction<Game.MAXFACTIONS)//26oct2020
                                {
                                    countfaction[game.units[nid].faction]++;
                                    if(countfaction[game.units[nid].faction]>highest)
                                    {
                                        highest = countfaction[game.units[nid].faction];
                                        highestfaction = game.units[nid].faction;
                                    }
                                }
                            }
                        }
                    }
                }
                if(countfriends>countenemies)
                {
                    controller = Game.PLAYERFACTION;
                }
                if(countfriends<countenemies)
                {
                    controller = Game.SKIRMISHENEMYFACTION;
                }
                if(highest>0) //26oct2020
                {
                    controller = highestfaction;
                }
            }
            if((game.frame + id)%(framecheck * Unit.CONTROLRATE)==29 && (controller==Game.PLAYERFACTION || controller==Game.SKIRMISHENEMYFACTION || highest>0))
            {
                //spawn a new unit....chosen how?
                for(int gdist2=1;gdist2<=gdist;gdist2++)
                {
                    for(int xx=gx-gdist2;xx<=gx+gdist2;xx++)
                    {
                        for(int yy=gy-gdist2;yy<=gy+gdist2;yy++)
                        {
                            if(xx>=0 && yy>=0 && xx<Map.MAXX && yy<Map.MAXY)
                            {
                                int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                if(nid==-1)
                                {
                                        emptyslot = true;
                                        controllerspawn(game,xx,yy);
                                        break;
                                }
                            }
                        }
                        if(emptyslot)
                        {
                            break;
                        }
                    }
                    if(emptyslot)
                    {
                        break;
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public void controllerspawn(Game game, int xx, int yy)
        {
            //spawn units from the controller
            //how to pick a unit?
            //randomly chosen?
            int count = 0;
            int index = 0;
            for(int j=0;j<game.templates.Length;j++)
            {
                if(game.templates[j].faction==controller && game.templates[j].walkspeed>0 && game.templates[j].bossmonster==0)
                {
                    count++;
                }
            }
            if(count>0)
            {
                index = 1 + ((int)Functions.rand(0,10000) % count);
                for(int j=0;j<game.templates.Length;j++)
                {
                    if(game.templates[j].faction==controller && game.templates[j].walkspeed>0 && game.templates[j].bossmonster==0)
                    {
                        index--;
                        if(index<=0)
                        {
                            for(int k=0;k<game.units.Length;k++)
                            {
                                if(game.units[k].hp<=0)
                                {
                                    game.units[k].createunitatxy(game,k,game.templates[j],xx * Map.GRIDW,yy * Map.GRIDH);
                                    Blood.makeblood(game,game.units[k].x,game.units[k].y+game.units[k].offy,Blood.BLOODSPAWNER+faction);
                                    if(k>Unit.MAXINDEX)//11apr2021
                                    {
                                        Unit.MAXINDEX = k;
                                    }
                                    break;
                                }
                            }
                            break;
                        }
                    }
                }
            }
        }
///////////////////Method Definition///////////////
        public void fademagic(Game game)//28mar2021
        {
            //if armour, damage, misfire, etc are in play....
            //then gradually reduce them back to their standard levels....
            int framecheck = 60;
            if(Config.RUNNINGSPEED>90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED>110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            int plusorminus = 0;
            if(Config.USETECH) //2sep2021
            {
                walkspeed-=Tech.AddUnitUpgradeBuff(game,templateid,Tech.MV);
                damage-=Tech.AddUnitUpgradeBuff(game,templateid,Tech.BA);
                armour-=Tech.AddUnitUpgradeBuff(game,templateid,Tech.BD);
                Tech.TARGETUID = id;
                Tech.ADDSUBTRACT = -1;
                Tech.AddUnitUpgradeBuff(game,templateid,Tech.BZ);
            }
            plusorminus-=Functions.sign(game.templates[templateid].walkspeed-walkspeed);
            plusorminus-=Functions.sign(game.templates[templateid].damage-damage);
            plusorminus-=Functions.sign(game.templates[templateid].armour-armour);
            plusorminus-=Functions.sign(game.templates[templateid].spelldefense-spelldefense);//01apr2021
            plusorminus-=Functions.sign(game.templates[templateid].frenzy-frenzy);//01apr2021
            plusorminus-=Functions.sign(game.templates[templateid].leader-leader);//09apr2021
            plusorminus-=Functions.sign(game.templates[templateid].zombiemaster-zombiemaster);//09apr2021
            if(misfire>0)
            {
                plusorminus--;
            }
            if(plusorminus>0)
            {
                buffed = true;
                cursed = false;
            }
            if(plusorminus<0)
            {
                cursed = true;
                buffed = false;
            }
            if(plusorminus==0)
            {
                cursed = false;
                buffed = false;
            }
            if(((game.frame + id)%(framecheck*20))==0)
            {
                //every 6 seconds......
                bool anydiff = false;
                if(misfire>0)
                {
                    //plusorminus--;
                    misfire--;
                    anydiff = true;
                    cursed = true;
                }
                if(game.templates[templateid].frenzy!=frenzy)//01apr2021
                {
                    anydiff = true;
                    frenzy+=Functions.sign(game.templates[templateid].frenzy-frenzy);
                }
                if(game.templates[templateid].spelldefense!=spelldefense)//01apr2021
                {
                    anydiff = true;
                    spelldefense+=Functions.sign(game.templates[templateid].spelldefense-spelldefense);
                }
                if(game.templates[templateid].walkspeed!=walkspeed)
                {
                    anydiff = true;
                    walkspeed+=Functions.sign(game.templates[templateid].walkspeed-walkspeed);
                    
                }
                if(game.templates[templateid].damage!=damage)
                {
                    anydiff = true;
                    damage+=Functions.sign(game.templates[templateid].damage-damage);
                    
                }
                if(game.templates[templateid].armour!=armour)
                {
                    anydiff = true;
                    armour+=Functions.sign(game.templates[templateid].armour-armour);
                    
                }
                //start--------------//9apr2021
                if(game.templates[templateid].leader!=leader)
                {
                    anydiff = true;
                    leader+=Functions.sign(game.templates[templateid].leader-leader);
                    
                }
                if(game.templates[templateid].zombiemaster!=zombiemaster)
                {
                    anydiff = true;
                    zombiemaster+=Functions.sign(game.templates[templateid].zombiemaster-zombiemaster);
                    
                }
                //end----------------//9apr2021
                if(!anydiff)
                {
                    cursed = false;
                    buffed = false;
                }
            }
            if(Config.USETECH) //2sep2021
            {
                walkspeed+=Tech.AddUnitUpgradeBuff(game,templateid,Tech.MV);
                damage+=Tech.AddUnitUpgradeBuff(game,templateid,Tech.BA);
                armour+=Tech.AddUnitUpgradeBuff(game,templateid,Tech.BD);
                Tech.TARGETUID = id;
                Tech.ADDSUBTRACT = 1;
                Tech.AddUnitUpgradeBuff(game,templateid,Tech.BZ);
            }
        }
        
///////////////////Method Definition///////////////
        public void update(Game game)
        {
            //core unit update method
            //correction for offx/offy
            if(game.templates[templateid].autocalcedoffsets==true && autocalcedoffsets==false)//20apr2021
            {
                offx = game.templates[templateid].offx;
                offy = game.templates[templateid].offy;
                autocalcedoffsets = true;
            }
            if(game.frame - game.gamestartframe<10)//2apr2021
            {
                return;
            }
            int framecheck = 60;
            if(hp>0)
            {
                timedead = 0;//25mar2021
                height = Map.getheight(x,y);
                game.templates[templateid].livecount++;//9mar2021
                if(faction==Game.PLAYERFACTION && selected!=SELECTIONNONE && walkspeed>0)//22mar2021
                {
                    game.templates[templateid].selectioncount++;
                }
            }
            else
            {
                timedead++; //25mar2021
                if(faction==Game.PLAYERFACTION)//17sep2021
                {
                    if(points>0) //space squad uses this....
                    {
                        if(redping<0)
                        {
                            redping=120;
                        }
                    }
                }
            }
            fademagic(game);
            if(firetargeti!=-1)//22mar2021
            {
                //this fixes a bug where because units replace so fast, sometimes
                //a creature dies, then the pool reuses it but the other creatures
                //still have it as their firetargeti which causes them to
                //chase after their own guys.....occasionally.
                if(game.units[firetargeti].faction==faction)
                {
                    firetargeti = -1;
                }
            }
            if(faction==Game.PLAYERFACTION)//24sep2021
            {
                if(controlmode=="crpg")//24sep2021
                {
                    Unit.CRPG = 1;//25sep2021
                    Game.CORNERX = x - Game.RESOLUTIONX/2;
                    Game.CORNERY = y - Game.RESOLUTIONY/2;
                    
                    if(Game.CORNERX<0)
                    {
                        Game.CORNERX = 0;
                    }
                    if(Game.CORNERY<0)
                    {
                        Game.CORNERY = 0;
                    }
                    if(Game.CORNERX>Map.MAXX * Map.GRIDW - Game.RESOLUTIONX)
                    {
                        Game.CORNERX = Map.MAXX * Map.GRIDW - Game.RESOLUTIONX;
                    }
                    if(Game.CORNERY>Map.MAXY * Map.GRIDH - Game.RESOLUTIONY)
                    {
                        Game.CORNERY = Map.MAXY * Map.GRIDH - Game.RESOLUTIONY;
                    }
                    if(selected==Unit.SELECTIONNONE){selected = Unit.SELECTIONSTART;selectedframe = game.frame;}
                }
            }
            if(groupid>=0 && groupid<=9 && selected!=SELECTIONNONE)//21mar2021
            {
                Game.groupselected = groupid;
            }
            if(Config.RUNNINGSPEED>90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED>110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            if(controlpoint==1)
            {
                managecontrolpoint(game);
                return;
            }
            //start-------------//7mar2021
            int enemyfaction = Game.PLAYERFACTION;
            if(faction==Game.PLAYERFACTION)
            {
                enemyfaction = Game.SKIRMISHENEMYFACTION;
            }
            if(mob>0)
            {
                int countfriend = Map.countfactionneighbours(game,x,y,faction);
                int countenemy = Map.countfactionneighbours(game,x,y,enemyfaction);
                if(countfriend>countenemy)
                {
                    brave = 1;
                }
                else
                {
                    brave = 0;
                }
            }
            if(basemana>0)//23sep2021
            {
                if(mana<basemana)
                {
                    if(manarate>0)
                    {
                        if(game.frame % framecheck == 0)
                        {
                            mana++;
                        }
                    }
                }
            }
            if(hatred>0)
            {
                if(hatred==enemyfaction)
                {
                    brave = 1;
                }
            }
            if(planar>0 && Game.EDITOR==false && hp>0)
            {
                //if(animmode==ANIMMODE_IDLE)
                //{
                    if((game.frame+id) % 60==0)//11apr2021 added +id
                    {
                        //Functions.saveseed();//11apr2021
                        if(Functions.rand(0,100)<planar)
                        {
                            hp--;
                        }
                        //Functions.restoreseed();//11apr2021
                    }                
                //}
            }
            if(misfire>0 && Game.whirlwind!=-1)//28mar2021
            {
                int ggxx = x / Map.GRIDW;
                int ggyy = y / Map.GRIDH;
                if((ggxx + ggyy)%Blood.WHIRLWINDGRID==0)
                {
                    Blood.makeblood(game,x,y,Blood.WHIRLWINDSPELL);
                }
            }
            if(animosity>0 && Game.EDITOR==false && hp>0)
            {
                if(animmode==ANIMMODE_IDLE)
                {
                    if((game.frame + id) % 60==0)//11apr2021 added +id
                    {
                        if(id%animosity==0)
                        {
                            //not sure about this one yet....
                            //Functions.saveseed();//11apr2021
                            if(Functions.rand(0,100)<10)
                            {
                                animosity = 0;
                                faction = Unit.ANIMOSITY;
                            }
                            //Functions.restoreseed();//11apr2021
                        }
                    }
                }
            }
            //end---------------//7mar2021
            //if(fearsome > 0 || leader > 0)//12jul2021
            if(fearsome > 0 || leader > 0 || bounddemon > 0) //12jul2021
            {
                retreat = false;
                retreatframe = game.frame + Unit.RETREATDEATH;
                timid = 0;
            }
            //start---------------//12jul2021
            if(bounddemon > 1)
            {
                if((game.frame + id) % framecheck==0) //28jul21 - brought into line from being '60'.
                {
                    bounddemon--;
                }
                if(bounddemon==1)
                {
                    //alter the faction to a faction not in the game, but not neutral....
                    faction = (Game.PLAYERFACTION + Game.SKIRMISHENEMYFACTION); //should be good enough....to do the job...
                    selected = Unit.SELECTIONNONE; //13jul2021 bug fix potentially.
                }
            }
            //end-----------------//12jul2021
            if(brave > 0 && retreat==true)
            {
                if((game.frame + id) % 60 == 0)//11apr2021
                {
                    //Functions.saveseed();//11apr2021
                    if(Functions.rand(0,1000)<Unit.RALLYCHANCE)
                    {
                        retreat = false;
                        retreatframe = game.frame + Unit.RETREATDEATH;
                        timid = 0;
                    }
                    //Functions.restoreseed();//11apr2021
                }
            }
            if(hitandrun > 0 && retreat==true)
            {
                if((game.frame+id) % framecheck == 0)
                {
                    int qqq1 = Functions.rand(0,1000);
                    int qqq2 = Functions.rand(0,1000);
                    int qqq3 = Functions.rand(0,1000);
                    if(qqq1<Unit.RALLYCHANCE || qqq2<Unit.RALLYCHANCE || qqq3<Unit.RALLYCHANCE)
                    {
                        //three chances to rally if a hit and run unit.....
                        retreat = false;
                        retreatframe = 0;
                    }
                    
                }
            }
            //start---------------//28mar2021
            if((game.frame + id)%(framecheck*15)==1)
            {
                for(int m=0;m<magicarray.Length;m++)
                {
                    if(magicarray[m]<0)
                    {
                        magicarray[m]*=-1;
                        break;
                    }
                }
            }
            //end-----------------//28mar2021
            //start---------------//2sep2021
            //if(selected!=SELECTIONNONE && faction==Game.PLAYERFACTION && techguilinkid>0)//26feb2022
            if(selected!=SELECTIONNONE && faction==Game.PLAYERFACTION && techguilinkid.Length>0)//26feb2022
            {
                Tech.TECHUNITSELECTED = true;
                Tech.TECHUNITIDSELECTED = id;
            }
            //end-----------------//2sep2021
            //start-------------//10mar2021
            if(selected!=SELECTIONNONE && faction==Game.PLAYERFACTION && spawner!="")
            {
                Game.SPAWNERSELECTED = true;
            }
            if(selected!=SELECTIONNONE && spawner=="") //11mar2021
            {
                Game.NONSPAWNERSELECTED = true; //11mar2021
            }
            //start-------------//11mar2021
            if(spawner!="" && faction!=Game.PLAYERFACTION)
            {
                if(((game.frame + id) % (framecheck*10))==2)//9sep2021
                if(((game.frame + id) % (framecheck*10))==2 && framesleft<=0)//9sep2021
                {
                    //AI spawners randomly choose a new thing to spawn.....
                    int randomspawncount = 0;
                    int randomspawnindex = 0;
                    int ttid = -1;
                    int maxkill = 0;
                    int maxkill2 = 0;
                    int ktid = -1;
                    Game.ai_direction++;//17apr2021
                    if((Game.ai_direction % 10)<5)//17apr2021 - altered AI to make it a bit more weird.......unpredictable but still following a logical course of action.
                    {
                        maxkill = 999999;
                        maxkill2 = 0;
                        for(int tid=0;tid<game.templates.Length;tid++)
                        {
                            if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                            {
                                continue;
                            }
                            if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                            {
                                randomspawncount++;
                                if(game.templates[tid].kills < maxkill)
                                {
                                    maxkill = game.templates[tid].kills;
                                    ktid = tid;
                                }
                            }
                        }
                        //get the second highest value....not the first highest value...
                        //Functions.saveseed();//11apr2021
                        if(Functions.rand(0,100)<25)
                        {
                            for(int tid=0;tid<game.templates.Length;tid++)
                            {
                                if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                                {
                                    continue;
                                }
                                if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                                {
                                    if(game.templates[tid].kills > maxkill2)// && game.templates[tid].kills < maxkill)
                                    {
                                        maxkill2 = game.templates[tid].kills;
                                        ktid = tid;
                                    }
                                }
                            }
                        }
                        //Functions.restoreseed();//11apr2021
                        if(randomspawncount>0)
                        {
                            Functions.saveseed();//11apr2021
                            int qqq4 = Functions.rand(0,100);//11apr2021
                            if(ktid==-1 || (qqq4 < 10 && ktid!=-1))
                            {
                                Functions.restoreseed();//11apr2021
                                randomspawnindex = 1 + (Functions.rand(0,1000) % randomspawncount);
                                for(int tid=0;tid<game.templates.Length;tid++)
                                {
                                    if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                                    {
                                        continue;
                                    }
                                    if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                                    {
                                        randomspawnindex--;
                                        if(randomspawnindex<=0)
                                        {
                                            ttid = tid;
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                ttid = ktid;
                                Functions.restoreseed();//11apr2021
                            }
                            if(ttid!=-1)
                            {
                                spawner = game.templates[ttid].name;
                                spawnertemplateid = ttid; //26feb2022
                                displayspawner = game.templates[ttid].dname(); //13mar2021
                                spawnertime = Unit.CalculateSpawnerTime(game,ttid);
                                framesleft = framecheck * spawnertime;//9sep2021
                                if(spawnercount<10)
                                {
                                    //spawnercount++;//12mar2021
                                    spawnercount+=3;//12mar2021 //to guarantee it keeps on producing and doesn't slow down with time.....
                                }
                                if(spawnercount<=0)
                                {
                                    spawnercount=1;
                                }
                            }
                            //Functions.restoreseed();//11apr2021
                        }
                    }
                    else
                    {
                        for(int tid=0;tid<game.templates.Length;tid++)
                        {
                            if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                            {
                                continue;
                            }
                            if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                            {
                                randomspawncount++;
                                if(game.templates[tid].kills > maxkill)
                                {
                                    maxkill = game.templates[tid].kills;
                                    ktid = tid;
                                }
                            }
                        }
                        //get the second highest value....not the first highest value...
                        //Functions.saveseed();//11apr2021
                        if(Functions.rand(0,100)<25)
                        {
                            for(int tid=0;tid<game.templates.Length;tid++)
                            {
                                if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                                {
                                    continue;
                                }
                                if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                                {
                                    if(game.templates[tid].kills > maxkill2 && game.templates[tid].kills < maxkill)
                                    {
                                        maxkill2 = game.templates[tid].kills;
                                        ktid = tid;
                                    }
                                }
                            }
                        }
                        //Functions.restoreseed();//11apr2021
                        if(randomspawncount>0)
                        {
                            Functions.saveseed();//11apr2021
                            int qqq4 = Functions.rand(0,100);//11apr2021
                            if(ktid==-1 || (qqq4 < 10 && ktid!=-1))
                            {
                                Functions.restoreseed();//11apr2021
                                randomspawnindex = 1 + (Functions.rand(0,1000) % randomspawncount);
                                for(int tid=0;tid<game.templates.Length;tid++)
                                {
                                    if(!Unit.SpawnerCanBuild(game,spawnerconstraint,tid))//9sep2021
                                    {
                                        continue;
                                    }
                                    if(faction==game.templates[tid].faction && game.templates[tid].walkspeed>0 && game.templates[tid].bossmonster<=0 && game.templates[tid].leader<=0 && game.templates[tid].planar<=0)
                                    {
                                        randomspawnindex--;
                                        if(randomspawnindex<=0)
                                        {
                                            ttid = tid;
                                            break;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                ttid = ktid;
                                Functions.restoreseed();//11apr2021
                            }
                            if(ttid!=-1)
                            {
                                spawner = game.templates[ttid].name;
                                spawnertemplateid = ttid;//26feb2022
                                displayspawner = game.templates[ttid].dname(); //13mar2021
                                spawnertime = Unit.CalculateSpawnerTime(game,ttid);
                                framesleft = framecheck * spawnertime;//9sep2021
                                if(spawnercount<10)
                                {
                                    //spawnercount++;//12mar2021
                                    spawnercount+=3;//12mar2021 //to guarantee it keeps on producing and doesn't slow down with time.....
                                }
                                if(spawnercount<=0)
                                {
                                    spawnercount=1;
                                }
                            }
                            //Functions.restoreseed();//11apr2021
                        }
                    }
                }
            }
            //end---------------//11mar2021
            //end---------------//10mar2021
            if(selected!=SELECTIONNONE && faction!=Game.PLAYERFACTION && (game.frame + id) % 15==3)
            {
                //correct this if necessary
                //for(int i=0;i<game.units.Length;i++) //26mar2021
                for(int i=0;i<=MAXINDEX;i++) //26mar2021
                {
                    if(game.units[i].selected!=SELECTIONNONE && faction==Game.PLAYERFACTION)
                    {
                        selected=SELECTIONNONE;
                        break;
                    }
                }
            }
            if(Replay.IsPlaying())//25apr2021
            {
                if(retreat==true && game.frame > retreatframe && ronscreen==false)
                {
                    if(hp>0)
                    {
                        game.killed(game,id);
                    }
                    hp=0;
                }
            }
            else//25apr2021
            {
                if(retreat==true && game.frame > retreatframe && onscreen==false)
                {
                    if(hp>0)
                    {
                        game.killed(game,id);
                    }
                    hp=0;
                }
            }
            if(Replay.IsPlaying())//25apr2021
            {
                if(retreat==true && game.frame <= retreatframe && ronscreen==false)
                {
                    //rallying chance?
                    if((game.frame + id) % framecheck == 0)
                    {
                        //Functions.saveseed();//11apr2021
                        Functions.saveseed();//25apr2021
                        if(Functions.rand(0,1000)<Unit.RALLYCHANCE)
                        {
                            retreat = false;
                            retreatframe = 0;
                        }
                        Functions.restoreseed();//25apr2021
                        //Functions.restoreseed();//11apr2021
                    }
                }
                
            }
            else
            {
                if(retreat==true && game.frame <= retreatframe && onscreen==false)
                {
                    //rallying chance?
                    if((game.frame + id) % framecheck == 0)
                    {
                        //Functions.saveseed();//11apr2021
                        Functions.saveseed();//25apr2021
                        if(Functions.rand(0,1000)<Unit.RALLYCHANCE)
                        {
                            retreat = false;
                            retreatframe = 0;
                        }
                        Functions.restoreseed();//25apr2021
                        //Functions.restoreseed();//11apr2021
                    }
                }
            }
            if(Replay.IsPlaying())//25apr2021
            {
                if(retreatframe>0 && ronscreen==true)
                {
                    retreatframe++;
                }
            }
            else
            {
                if(retreatframe>0 && onscreen==true)
                {
                    retreatframe++;
                }
            }
            //start-------------//4may2021
            if(hp<=0 && flightlevel!=-1)
            {
                int nid = Map.cellflyer(x,y,flightlevel);
                if(nid==id)
                {
                    Map.removeflyer(id,x,y,flightlevel);
                }
                return;
            }
            //end---------------//4may2021
            if(hp <= 0)
            {
                int nid = Map.cellunit(x,y);
                if(nid==id)
                {
                    if(animmode!=ANIMMODE_DEAD)//13sep2021 (just the if block)
                    {
                        Map.removeunit(id,x,y);
                    }
                }
                return;
            }
            //flying 4may2021
            //
            if(flightlevel!=-1)//4may2021
            {
                if(x > Game.CORNERX - Map.GRIDW*2 && x < Game.CORNERX + Game.RESOLUTIONX + Map.GRIDW*2 && y > Game.CORNERY - Map.GRIDH * 2 && y < Game.CORNERY + Game.RESOLUTIONY + Map.GRIDH * 2)
                {
                    Array.Resize(ref Map.flightlist,Map.flightlist.Length + 1);
                    Map.flightlist[Map.flightlist.Length - 1] = id;
                }    
            }
            //end flying
            
            if(timid>0)
            {
                if((game.frame + id) % (2 * framecheck)==0)
                {
                    //Functions.saveseed();//11apr2021
                    int dieroll = Functions.rand(0,100);
                    int pcthp = hp * 100 / basehp;
                    if(dieroll>pcthp)
                    {
                        retreat = true;
                        retreatframe = game.frame + Unit.RETREATDEATH;
                    }
                    //Functions.restoreseed();//11apr2021
                }
            }
            if(faction==Game.PLAYERFACTION)
            {
                infog = false;
            }
            else
            {
                if(Game.EDITOR)
                {
                    infog = false;
                }            
            }
            //start-------------//9mar2021
            if(defendx!=-1 && defendy!=-1)
            {
                if(((game.frame+id) % 180)==11)
                {
                    tx = defendx;
                    ty = defendy;
                    tmptx = tx;//12mar2021
                    tmpty = ty;//12mar2021
                    if(Functions.abs(x - tx)>Unit.GUARDRANGE && Functions.abs(y - ty)>Unit.GUARDRANGE)//12mar2021
                    {
                        firetargeti = -1;//12mar2021
                        orderframe = Unit.ORDERTIME; //12mar2021
                        tmptattempts = 0; //12mar2021
                    }
                }
            }
            //end---------------//9mar2021
            if(tmptframe>0)
            {
                tmptframe--;
            }
            else
            {
                tmptx = tx;
                tmpty = ty;
                if(game.gamestate==Game.CAT_GAMESTATE_GAME && ((game.frame + id)%30)==19){quickpathfind(x,y,tx,ty);}//28apr2021
            }
            //26oct2020
            //if(faction==Game.SKIRMISHENEMYFACTION && game.skirmish==true)
            if(faction!=Game.PLAYERFACTION && game.skirmish==true && faction!=Unit.NULLFACTION)
            {
                //Functions.saveseed();//11apr2021
                int cpoint = ((int)Functions.rand(0,10000) % 1000);
                if(firetargeti==-1)
                {
                    if(orderframe<=0)
                    {
                        if((game.frame + id)%framecheck==13)
                        {
                            //for(int i=0;i<game.units.Length;i++)//26mar2021
                            for(int i=0;i<=MAXINDEX;i++)//26mar2021
                            {
                                if(game.units[i].controlpoint==1 && cpoint < 250)
                                {
                                    //26oct2020
                                    //if(game.units[i].controller!=Game.SKIRMISHENEMYFACTION)
                                    if(game.units[i].controller==Game.PLAYERFACTION || game.units[i].controller!=faction)    
                                    {
                                        tx = game.units[i].x;
                                        ty = game.units[i].y;
                                        orderframe = Unit.ORDERTIME;
                                        firetargeti    = -1;
                                        tmptattempts = 0;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                //Functions.restoreseed();//11apr2021
            }
            if(orderframe>0)
            {
                orderframe--;
            }
            if(hp<basehp && regeneration>0 && ((game.frame+id) % framecheck)==0)
            {
                hp+=regeneration;
                if(hp>basehp)
                {
                    hp = basehp;
                }
            }
            //if(Map.isonfire(x,y))//4may2021
            if(Map.isonfire(x,y) && flightlevel==-1)//4may2021
            {
                if((game.frame + id) % framecheck==0 && firespell==0)
                {
                    //take damage....
                    if(hp>0)//25Feb2021
                    {
                        hp--;
                        if(hp<=0)
                        {
                            game.killed(game,id);
                        }
                    }//25Feb2021
                }
            }
            drawn = false;
            if(game.demomode)
            {
                if((game.frame + id) % (framecheck*20)==0)
                {
                        tx = x + 500 * (int)Functions.sign(1600 - x);
                        ty = y;
                        orderframe = Unit.ORDERTIME;
                        firetargeti = -1;
                        tmptattempts = 0;
                }
            }
        }

        
        
///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            //method that handles updating all units in game during gameplay
            Game.groupselected = -1;//21mar2021
            Game.anyselected = false;//16apr2021
            bool friendlyselected = false;//20apr2021
            int enemyselected = -1;//20apr2021
            Stopwatch utimer = new Stopwatch();
            utimer.Start();
            long atime = 0;
            long utime = 0;
            long atttime = 0;
            long wtime = 0;
            long ttime = 0;
            Game.SPAWNERSELECTED = false; //10mar2021
            Game.NONSPAWNERSELECTED = false;//11mar2021
            Tech.TECHUNITSELECTED = false;//2sep2021
            Tech.TECHUNITIDSELECTED = -1;//2sep2021
            //start-------------//9mar2021
            Map.flightlist = new int[0];//4may2021
            Unit.circlesmax = 0;//2jun2021
            for(int i=0;i<game.templates.Length;i++)
            {
                if(game.templates[i].livecount!=game.templates[i].olivecount)
                {
                    game.templates[i].livecountframe = 45;
                }
                else
                {
                    if(game.templates[i].livecountframe>0)
                    {
                        game.templates[i].livecountframe--;
                    }
                }
                game.templates[i].olivecount = game.templates[i].livecount;
                game.templates[i].livecount = 0;
                game.templates[i].selectioncount = 0;//22mar2021
            }
            //end---------------//9mar2021
            //start---------------//26mar2021
            if(game.units[MAXINDEX].hp<=0 && game.units[MAXINDEX].timedead>MAXDEADTIME && MAXINDEX>0)
            {
                MAXINDEX--;
            }
            //end-----------------//26mar2021
            Game.checksum = 0;//2apr2021
            for(int i=0;i<game.units.Length;i++)
            {
                //start---------------//26mar2021
                if((game.units[i].hp>0 || game.units[i].timedead<MAXDEADTIME) && i>MAXINDEX)
                {
                    MAXINDEX = i;
                }
                if(game.units[i].selected!=Unit.SELECTIONNONE && game.units[i].hp>0 && game.units[i].walkspeed>0 && game.units[i].faction==Game.PLAYERFACTION)//16apr2021
                {
                    Game.anyselected = true;
                    friendlyselected = true;//20apr2021
                }
                if(game.units[i].selected!=Unit.SELECTIONNONE && game.units[i].faction!=Game.PLAYERFACTION)
                {
                    enemyselected = i;
                }
                Game.checksum+=game.units[i].hp+game.units[i].x+game.units[i].y;//2apr2021
                if(game.units[i].hp<=0) //24apr2021
                {
                    game.units[i].selected = Unit.SELECTIONNONE;
                }
                //end-----------------//26mar2021
                Unit.CorrectTransport(game,i);//3may2021///in case stuff goes wrong..it shouldn't though......
                if(game.units[i].transportedbyid!=-1)//3may2021
                {
                    game.units[i].onscreen = false;
                    game.units[i].ronscreen = false;
                    continue;
                    //we don't want to update units that are inside transports...they should do nothing.....
                    //until they are out of the transport.....
                }
                //start-------------//2jun2021
                //if(game.templates[game.units[i].templateid].walkspeed>0 && game.units[i].selected!=Unit.SELECTIONNONE && game.units[i].hp>0)//3mar2022
                if(game.units[i].selected!=Unit.SELECTIONNONE && game.units[i].hp>0)//3mar2022
                {
                    Unit.circles[Unit.circlesmax] = i;
                    Unit.circlesmax++;
                    if(Unit.circlesmax>=MAXUNITS) //should never be needed
                    {
                        Unit.circlesmax=MAXUNITS - 1;
                    }
                }
                //end---------------//2jun2021
                //start-------------//2sep2021
                if(Config.USETECH)
                {
                    game.units[i].walkspeed+=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.MV);
                    game.units[i].damage+=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BA);
                    game.units[i].armour+=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BD);
                    Tech.TARGETUID = i;
                    Tech.ADDSUBTRACT = 1;
                    Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BZ);
                }
                //end---------------//2sep2021
                ttime = utimer.ElapsedMilliseconds;
                game.units[i].animate(game);//includes flying as of 4may2021
                atime+= Math.Abs(utimer.ElapsedMilliseconds - ttime);
                ttime = utimer.ElapsedMilliseconds;
                game.units[i].update(game);
                utime+= Math.Abs(utimer.ElapsedMilliseconds - ttime);
                if(!Game.EDITOR)
                {
                    ttime = utimer.ElapsedMilliseconds;
                    game.units[i].actionattack(game);
                    atttime+= Math.Abs(utimer.ElapsedMilliseconds - ttime);
                }
                ttime = utimer.ElapsedMilliseconds;
                int tmpwalkspeed = game.units[i].walkspeed; //24feb2022
                if(Config.useseasons>0 && Config.Season==Config.WINTER)//Winter//24feb2022
                {
                    if(game.units[i].canfly<=0 && game.units[i].canflyandwalk<=0)
                    {
                        if(game.units[i].walkspeed>2)//there's a maximum speed you can move at in the Winter...
                        {
                            game.units[i].walkspeed = 2;
                        }
                    }
                }
                game.units[i].walk(game,game.units[i].tmptx - game.units[i].x,game.units[i].tmpty - game.units[i].y);
                if(Config.USEDELTATIME>0)//18sep2021
                {
                    if(Config.delta > 150)
                    {
                        int ndelta = (Config.delta - (Config.delta % 100)) / 100;
                        for(int nd=0;nd<ndelta;nd++)
                        {
                            game.units[i].walk(game,game.units[i].tmptx - game.units[i].x,game.units[i].tmpty - game.units[i].y);
                        }
                    }
                }
                game.units[i].walkspeed = tmpwalkspeed;//24feb2022
                wtime+= Math.Abs(utimer.ElapsedMilliseconds - ttime);
                game.units[i].onscreen = false;
                game.units[i].ronscreen = false;//25apr2021
                //start-------------//2sep2021
                if(Config.USETECH)
                {
                    game.units[i].walkspeed-=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.MV);
                    game.units[i].damage-=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BA);
                    game.units[i].armour-=Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BD);
                    Tech.TARGETUID = i;
                    Tech.ADDSUBTRACT = -1;
                    Tech.AddUnitUpgradeBuff(game,game.units[i].templateid,Tech.BZ);
                }
                //end---------------//2sep2021
            }
            for(int i=0;i<game.units.Length;i++)//30sep2021
            {
                if(game.units[i].isdead>0)
                {
                    game.units[i].isdead=2;
                    game.units[i].hp=0;
                    game.killed(game, i);
                    if(game.units[i].infectinto!="" && game.units[i].infected>0)//22apr2022

                    {
                        Unit.Infect(game,i,game.units[i].infectinto);
                    }
                }
            }
        
            if(enemyselected!=-1 && friendlyselected==true)//20apr2021
            {
                game.units[enemyselected].selected=Unit.SELECTIONNONE;
            }
            utimer.Reset();
            if(atime > Config.maxanimate || game.frame % 300==0)
            {
                Config.maxanimate = atime;
            }
            if(utime > Config.maxupdate || game.frame % 300 == 0)
            {
                Config.maxupdate = utime;
            }
            if(atttime > Config.maxatt || game.frame % 300 == 0)
            {
                Config.maxatt = atttime;
            }
            if(wtime > Config.maxwalk || game.frame % 300 == 0)
            {
                Config.maxwalk = wtime;
            }
        }

///////////////////Method Definition///////////////
        public static void drawall(Game game)
        {
            //draw all units on the screen currently
            //draw in sorted order......down the screen from low y to high y
            
            //4mar2022 - using overlayimage if it exists instead of these.....
            if(game.missions[game.missionid].overlayimage!=-1 && Config.options_overlay!=0)//4mar2022
            {
                if(Config.Season==Config.WINTER && Config.useseasons>0 && game.missions[game.missionid].overlaysnow!=-1)
                {
                    RenderList.drawimage(game,game.images[game.missions[game.missionid].overlaysnow].texture,-Game.CORNERX+Map.MAXX*Map.GRIDW/2,-Game.CORNERY+Map.MAXY*Map.GRIDH/2,0,(float)Map.MAXX*(float)Map.GRIDW/(float)game.images[game.missions[game.missionid].overlaysnow].cwx,(float)Map.MAXY*(float)Map.GRIDH/(float)game.images[game.missions[game.missionid].overlaysnow].chy,0,0,false,1,game.missions[game.missionid].overlaysnow);    
                }
                else
                {
                    RenderList.drawimage(game,game.images[game.missions[game.missionid].overlayimage].texture,-Game.CORNERX+Map.MAXX*Map.GRIDW/2,-Game.CORNERY+Map.MAXY*Map.GRIDH/2,0,(float)Map.MAXX*(float)Map.GRIDW/(float)game.images[game.missions[game.missionid].overlayimage].cwx,(float)Map.MAXY*(float)Map.GRIDH/(float)game.images[game.missions[game.missionid].overlayimage].chy,0,0,false,1,game.missions[game.missionid].overlayimage);    
                }
            }
            else
            {
            
            if(Map.issnow)
            {
                RenderList.drawrect(game,0,0,Game.RESOLUTIONX,Game.RESOLUTIONY,RenderList.getrgb(182,191,180),0);
            }
            if(Map.isdesert)
            {
                RenderList.drawrect(game,0,0,Game.RESOLUTIONX,Game.RESOLUTIONY,RenderList.getrgb(109,96,37),0);
            }
            if(Map.isrgbbk) //1nov2020
            {
                RenderList.drawrect(game,0,0,Game.RESOLUTIONX,Game.RESOLUTIONY,RenderList.getrgb(Map.isrgbbk_r,Map.isrgbbk_g,Map.isrgbbk_b),0);
            }
            if(Map.isdesert==false && Map.issnow==false && Map.isrgbbk==false)
            {
                RenderList.drawrect(game,0,0,Game.RESOLUTIONX,Game.RESOLUTIONY,RenderList.getrgb(103,105,63),0);
            }
            for(int y=Game.CORNERY/Map.GRIDH - 2;y<(Game.CORNERY+Game.RESOLUTIONY)/Map.GRIDH + 2;y++)
            {
                for(int x=Game.CORNERX/Map.GRIDW - 2;x<(Game.CORNERX+Game.RESOLUTIONX)/Map.GRIDW + 2;x++)
                {
                    if(Map.TileFog(game,x,y)==0)//15sep2021
                    {
                        Map.draw(game,x*Map.GRIDW,y*Map.GRIDH,0); //the ground contents...if any.....
                    }
                }
            }
            //start---------------//21feb2022
            //if(game.missions[game.missionid].overlayimage!=-1)//28feb2022
            //4mar2022 commented out
            //if(game.missions[game.missionid].overlayimage!=-1 && Config.options_overlay!=0)//28feb2022
            //{
            //    RenderList.drawimage(game,game.images[game.missions[game.missionid].overlayimage].texture,-Game.CORNERX+Map.MAXX*Map.GRIDW/2,-Game.CORNERY+Map.MAXY*Map.GRIDH/2,0,1,1,0,0,false,1,game.missions[game.missionid].overlayimage);    
            //}
            //end-----------------//21feb2022
            //start---------------------------//18sep2021
            for(int y=Game.CORNERY/Map.GRIDH - 2;y<(Game.CORNERY+Game.RESOLUTIONY)/Map.GRIDH + 2;y++)
            {
                for(int x=Game.CORNERX/Map.GRIDW - 2;x<(Game.CORNERX+Game.RESOLUTIONX)/Map.GRIDW + 2;x++)
                {
                    if(Map.TileFog(game,x,y)==0)//15sep2021
                    {
                        Map.draw(game,x*Map.GRIDW,y*Map.GRIDH,Map.DECOR); //the ground contents...if any.....
                    }
                }
            }
            }//4mar2022
            //end-----------------------------//18sep2021
            //start------------//25apr2021
            if(Replay.IsPlaying())
            {
                    Game.TMPCORNERX = Game.CORNERX;
                    Game.TMPCORNERY = Game.CORNERY;
                    Game.CORNERX = Game.RCORNERX;
                    Game.CORNERY = Game.RCORNERY;
                    for(int y=Game.CORNERY/Map.GRIDH - 2;y<(Game.CORNERY+Game.RESOLUTIONY)/Map.GRIDH + 4;y++)
                    {
                        for(int x=Game.CORNERX/Map.GRIDW - 2;x<(Game.CORNERX+Game.RESOLUTIONX)/Map.GRIDW + 2;x++)
                        {
                            int id = Map.cellunit(x*Map.GRIDW,y*Map.GRIDH);
                            if(id!=-1)
                            {
                                //if the unit is drawn then onscreen would have been true....
                                //so we need to set ronscreen to true as well.....
                                game.units[id].ronscreen = true;
                            }
                        }
                    }            
                    Game.CORNERX = Game.TMPCORNERX;
                    Game.CORNERY = Game.TMPCORNERY;
            }
            //end--------------//25apr2021
            //start------------------------//2jun2021
            for(int i=0;i<Unit.circlesmax;i++)
            {
                //draw unit circles....
                int id = Unit.circles[i];
                if(id!=-1)
                {
                    if(game.units[id].x < Game.CORNERX - Map.GRIDW * 2 || game.units[id].x > Game.CORNERX + Game.RESOLUTIONX + Map.GRIDW * 2 || game.units[id].y < Game.CORNERY - Map.GRIDH * 2 || game.units[id].y > Game.CORNERY + Game.RESOLUTIONY + Map.GRIDH * 2)
                    {
                        continue;
                    }
                    if(game.units[id].walkspeed<=0)
                    {
                        continue;
                    }
                    if(Config.USEFEETCIRCLES)
                    {
                        {
                            if(Game.iconcircles!=-1)
                            {
                                float cc = 0.8f;
                                int cw0 = game.units[id].cw;
                                int ch0 = game.units[id].ch;
                                if(cw0<70)
                                {
                                    cw0 = 70;
                                }
                                if(ch0<85)
                                {
                                    ch0 = 85;
                                }
                                if(game.units[id].faction==Game.PLAYERFACTION)
                                {
                                    //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,0,0,false,1f,Game.iconcircles);    
                                    //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,0,1,false,0.25f,Game.iconcircles);    
                                    RenderList.drawimage(game,game.images[Game.iconcircles].texture,game.units[id].x-Game.CORNERX,game.units[id].height + game.units[id].y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,0,0,false,1f,Game.iconcircles);    
                                    RenderList.drawimage(game,game.images[Game.iconcircles].texture,game.units[id].x-Game.CORNERX,game.units[id].height + game.units[id].y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,0,1,false,0.25f,Game.iconcircles);    
                                }
                                else
                                {
                                    //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,1,0,false,1f,Game.iconcircles);    
                                    //RenderList.drawimage(game,game.images[Game.iconcircles].texture,x-Game.CORNERX + offx,height + y-Game.CORNERY + offy,0,cc * cw / game.images[Game.iconcircles].cwx,cc * ch / game.images[Game.iconcircles].chy,1,1,false,0.25f,Game.iconcircles);    
                                    RenderList.drawimage(game,game.images[Game.iconcircles].texture,game.units[id].x-Game.CORNERX,game.units[id].height + game.units[id].y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,1,0,false,1f,Game.iconcircles);    
                                    RenderList.drawimage(game,game.images[Game.iconcircles].texture,game.units[id].x-Game.CORNERX,game.units[id].height + game.units[id].y-Game.CORNERY,0,cc * cw0 / game.images[Game.iconcircles].cwx,cc * ch0 / game.images[Game.iconcircles].chy,1,1,false,0.25f,Game.iconcircles);    
                                }
                            }
                
                        }
                    }
                }
            }
            //end--------------------------//2jun2021
            for(int y=Game.CORNERY/Map.GRIDH - 2;y<(Game.CORNERY+Game.RESOLUTIONY)/Map.GRIDH + 4;y++)
            {
                for(int x=Game.CORNERX/Map.GRIDW - 2;x<(Game.CORNERX+Game.RESOLUTIONX)/Map.GRIDW + 2;x++)
                {
                    if(Map.TileFog(game,x,y)==0)//15sep2021
                    {
                        Map.draw(game,x*Map.GRIDW,y*Map.GRIDH,1); //the ground contents...if any.....
                    }
                    else//15sep2021
                    {
                            continue;
                    }
                    int id = Map.cellunit(x*Map.GRIDW,y*Map.GRIDH);
                    if(id!=-1)
                    {
                        //start-----------------//20mar2021
                        //game.units[id].draw(game);    
                        //some overdraw but that is fine.....
                        int savedirn = game.units[id].dirn; //29may2021
                        if(Config.SLOWROTATE)//29may2021
                        {
                            game.units[id].dirn = game.units[id].displaydirn;//29may2021
                        }
                        int lid = Map.cellunit((x-1)*Map.GRIDW,y*Map.GRIDH);
                        int rid = Map.cellunit((x+1)*Map.GRIDW,y*Map.GRIDH);
                        if(lid!=-1)// && rid==-1)
                        {
                            //left of us is occupied and right of us is not....
                            if(game.units[lid].y > game.units[id].y)
                            {
                                game.units[id].draw(game);    
                                game.units[lid].draw(game);    
                            }
                            else
                            {
                                game.units[id].draw(game);    
                            }
                        }
                        else
                        {
                            game.units[id].draw(game);    
                        }
                        game.units[id].dirn = savedirn; //29may2021
                        /*
                        if(lid==-1 && rid!=-1)
                        {
                            //left of us is empty and right of us is not
                            if(game.units[rid].y <= game.units[id].y)
                            {
                                //draw nothing....
                            }
                            else
                            {
                                game.units[id].draw(game);    
                            }
                        }
                        if(lid!=-1 && rid!=-1)
                        {
                            //neither left nor right are empty....
                            if(game.units[lid].y > game.units[id].y)
                            {
                                game.units[id].draw(game);    
                                game.units[lid].draw(game);    
                            }
                            else
                            {
                                //this will be slightly incorrect.....
                                //if(game.units[rid].y <= game.units[id].y)
                                //{
                                    
                                //}
                                //else
                                //{
                                    game.units[id].draw(game);        //some overdraw will occur.....
                                //}
                            }
                        }
                        *
/
                        //end-------------------//20mar2021
                        
                    }
                }
            }
            if(Config.ALLOWFLYING)//4may2021
            {
                for(int f=0;f<Map.flightlist.Length;f++)
                {
                    int nid = Map.flightlist[f];
                    if(nid!=-1)
                    {
                        if(Config.TILEFOG>0)//15sep2021
                        {
                            if(!Map.TileVisible(game.units[nid].x,game.units[nid].y))
                            {
                                continue;
                            }
                        }
                        int savedirn = game.units[nid].dirn;//29may2021
                        if(Config.SLOWROTATE)//29may2021
                        {
                            game.units[nid].dirn = game.units[nid].displaydirn;//29may2021
                        }
                        game.units[nid].draw(game);//
                        game.units[nid].dirn = savedirn; //29may2021
                    }
                }
            }
            //start------------------------//2jun2021
            
            for(int i=0;i<Unit.circlesmax;i++)
            {
                int id = Unit.circles[i];
                if(id!=-1)
                {
                    if(game.units[id].x < Game.CORNERX - Map.GRIDW * 2 || game.units[id].x > Game.CORNERX + Game.RESOLUTIONX + Map.GRIDW * 2 || game.units[id].y < Game.CORNERY - Map.GRIDH * 2 || game.units[id].y > Game.CORNERY + Game.RESOLUTIONY + Map.GRIDH * 2)
                    {
                        continue;
                    }
                    game.units[id].drawhealthbar(game);
                }
                Unit.circles[i] = -1; //reset afterwards.....
            }
            //end--------------------------//2jun2021
            if(!Game.EDITOR)
            {
                Map.fogdraw(game);
            }
        }

///////////////////Method Definition///////////////
        public void reset(Game game,int i)
        {        
            //initialisation
            if(circles==null)//2jun2021
            {
                circles = new int[MAXUNITS];//2jun2021
                for(int j=0;j<MAXUNITS;j++)//2jun2021
                {
                    circles[j] = -1; //2jun2021
                }
            }
            techguilinkid = new int[0];//26feb2022
            deathanim = "";//21feb2022
            dieonplace = 0;//21feb2022
            scale = 1;//25sep2021
            isdead = 0;//30sep2021
            prefermobiletargets=0;//18sep2021
            charactername = "";//10sep2021
            infectchanceonhit = 0;//22apr2022
            infectchanceonkill = 0;//22apr2022
            infectinto = "";//22apr2022
            infected = 0;//22apr2022
            ping = 0;//17sep2021
            redping = -1;//17sep2021
            displaycharactername = 0;//10sep2021
            casting = false;//28mar2021
            cursed = false; //21mar2021
            buffed = false; //21mar2021
            flightlevel = -1;//4may2021
            gold = -1;//23sep2021
            canpickup = 0;//23sep2021
            guiattackdisplaylimit = 0;//23sep2021
            misfire = 0;//28mar2021
            timedead = MAXDEADTIME; //25mar2021
            retreatframe = 0;
            retreat = false;
            defendx = -1; //9mar2021
            defendy = -1; //9mar2021
            id = i;
            selected = Unit.SELECTIONNONE;
            drawn = false;
            dirn = (Functions.rand(0,100) % 8);
            firetargeti = -1;
            groupid = -1;
            transforminto = "";//3may2021
            transformrequires = "";//3may2021
            transportcapacity = 0;//3may2021
            transportsize = 1;//3may2021
            transportedbyid = -1;//4may2021
            controlmode = "";//24sep2021
            x = 0;
            y = 0;
            tx = x;
            ty = y;
            tmptx = -1;
            tmpty = -1;
            xp = 0;
            tmptframe = 0;
            angle = 0;
            oanimmode = -1;
            animmode = ANIMMODE_IDLE;
            animrest = 0;
            animframe = animmodeidleframestart;
            spawner = "";
            spawnertemplateid = -1;//26feb2022
            spawnerconstraint = "*";//9sep2021
            displayspawner = "";
            accuracy = 100;//28feb2022
            //magicarray = new int[9];
            //almost always followed by createunitatxy which
            //populates all the template values
            //and hence we don't need to initialise them here.
        }

///////////////////Method Definition///////////////
        public static void Infect(Game game,int i,string infectinto)//22apr2022
        {
            if(game.units[i].name==infectinto)
            {
                return; //zombies can't return as zombies!
            }
            if(game.units[i].walkspeed<=0)
            {
                return; //structures cannot become zombies...duhh!
            }
            if(game.units[i].hp<=0 && game.units[i].infected>0)
            {
                //Console.WriteLine("zombieficator!!!");
                //Console.WriteLine("infectinto:"+infectinto);
                //unit has died, and was infected.....
                //therefore transform them into a zombie....
                //check that their position on the map is empty...
                if(Map.cellunit(game.units[i].x,game.units[i].y)==Map.VACANT)
                {
                    //Console.WriteLine("cell is empty");
                    for(int tid=0;tid<=game.templates.Length;tid++)
                    {
                        if(game.templates[tid].name==infectinto)
                        {
                            game.units[i].createunitatxy(game,i,game.templates[tid],game.units[i].x,game.units[i].y);
                            if(game.units[i].name=="zombie")
                            {
                                //Console.WriteLine("ZOMBIES!!!");
                            }
                            break;
                        }
                    }
                }
            }
            game.units[i].infected = 1;
            game.units[i].infectinto = infectinto;
        }
        
///////////////////Method Definition///////////////
        public bool createunitatxy(Game game,int id,Unit template,int x, int y)
        {
            //create a unit at this position from a specific template
            if(Map.cellunit(x,y)==Map.VACANT && Map.passable(x,y)==true)
            {
                reset(game,id);
                Unit.copyunitstats(template,ref game.units[id]);
                game.units[id].x = x;
                game.units[id].y = y;
                game.units[id].tx = x;
                game.units[id].ty = y;
                game.units[id].tmptx = x;
                game.units[id].tmpty = y;
                game.units[id].infected = 0;
                game.units[id].dieonce = -1;//13sep2021
                game.units[id].animmode = Unit.ANIMMODE_IDLE;
                if(game.units[id].dieonplace>0)//22feb2022
                {
                    game.units[id].animframe = game.units[id].animmodeidleframestart;
                    game.units[id].animtime = game.units[id].animspeed;
                }
                if(Map.insertunit(id,x,y))
                {
                    game.templates[template.id].creates++;
                }
                if(id>Unit.MAXINDEX)//11apr2021
                {
                    Unit.MAXINDEX = id;
                }
                //start---------------//2sep2021
                if(Config.USETECH)
                {
                    game.units[id].hp+=Tech.AddUnitUpgradeBuff(game,template.id,Tech.BH);
                    game.units[id].basehp+=Tech.AddUnitUpgradeBuff(game,template.id,Tech.BH);
                }
                //end-----------------//2sep2021
                //start---------------//14sep2021
                if(game.units[id].canfly>0)
                {
                    if(Map.cellflyer(game.units[id].x,game.units[id].y,Map.FLIGHTLEVELS - 1)==-1)
                    {
                        Map.removeunit(id,game.units[id].x,game.units[id].y);
                        game.units[id].flightlevel = Map.insertflyer(id,game.units[id].x,game.units[id].y);
                        game.units[id].animmode = ANIMMODE_FLY;
                        game.units[id].retreat = false;
                        game.units[id].retreatframe = 0;
                        game.units[id].tmptattempts = 0;
                        game.units[id].tmptframe = 0;
                        if(game.units[id].flightlevel==-1)
                        {
                            game.units[id].hp = 0; //bugger - we don't really want this to happen though....so we will prevent it through other means....
                        }
                    }
                }
                //end-----------------//14sep2021
                return true;
            }
            return false;
        }

///////////////////Method Definition///////////////
        public void walk(Game game,int dx,int dy)
        {
            //walk or move the unit about the map handling collisions
            if(hp <= 0)
            {
                return;
            }
            if(Functions.abs(tmptx-x)<=walkspeed+2)
            {
                tmptx = x;
                dx = 0;
            }
            if(Functions.abs(tmpty-y)<=walkspeed+2)
            {
                tmpty = y;
                dy = 0;
            }
            if(dx==0 && dy==0)
            {
                if(animmode==ANIMMODE_WALK)
                {
                    animmode = ANIMMODE_IDLE;
                }
                //tmptattempts = 0;
                return;
            }
            int ddx = Functions.sign(dx);
            int ddy = Functions.sign(dy);
            odirn = dirn;
            if(dirntime>0)
            {
                dirntime--;
            }
            if(dirntime<=0)
            {
                dirntime = Unit.DIRNDELAY;
                if(ddx==0 && ddy==-1)
                {
                    //up
                    dirn = DIRN_UP;
                }
                if(ddx==1 && ddy==-1)
                {
                    //upright
                    dirn = DIRN_UPRIGHT;
                }
                if(ddx==1 && ddy==0)
                {
                    //right
                    dirn = DIRN_RIGHT;
                }
                if(ddx==1 && ddy==1)
                {
                    //downright
                    dirn = DIRN_DOWNRIGHT;
                }
                if(ddx==0 && ddy==1)
                {
                    //down
                    dirn = DIRN_DOWN;
                }
                if(ddx==-1 && ddy==1)
                {
                    //downleft
                    dirn = DIRN_DOWNLEFT;
                }
                if(ddx==-1 && ddy==0)
                {
                    //left
                    dirn = DIRN_LEFT;
                }
                if(ddx==-1 && ddy==-1)
                {
                    //upleft
                    dirn = DIRN_UPLEFT;
                }
            }
            if(animrest>0)
            {
                animrest--;
            }
            if(animrest>0 || animmode>ANIMMODE_WALK)
            {
                if(animmode!=ANIMMODE_FLY) //2sep2021
                {
                    return;
                }
            }
            if(faction==Unit.UNDEAD) //?huh?26oct2020
            {
                if(game.frame % Unit.UNDEADWALKRATE!=0)
                {
                    return;
                }
            }
            //check if there is another unit here......
            //we really should do this with a maparray rather than cycling through everything.....
            int nx = x + ddx*walkspeed;
            int ny = y + ddy*walkspeed;
            //int nnx = x + ddx * (walkspeed + Map.GRIDW);//21apr2021
            //int nny = y + ddy * (walkspeed + Map.GRIDH);//21apr2021
            int nid = Map.cellunit(nx,ny);
            //start-----------------------//4may2021
            //flying
            if(Config.ALLOWFLYING)
            {
                if(flightlevel!=-1)
                {
                    animmode = ANIMMODE_FLY;
                    if(Map.cellflyer(nx,ny,Map.FLIGHTLEVELS - 1)==-1)
                    {
                        bool movedgrid = false;//2sep2021
                        if(nx/Map.GRIDW!=x/Map.GRIDW || ny/Map.GRIDH!=y/Map.GRIDH)//2sep2021
                        {
                            movedgrid = true;
                            Map.removeflyer(id,x,y,flightlevel);
                        }
                        x+=ddx*walkspeed;
                        y+=ddy*walkspeed;
                        if(movedgrid)//2sep2021
                        {
                            flightlevel = Map.insertflyer(id,x,y);
                        }
                        if(flightlevel==-1)
                        {
                            hp = 0; //bugger - we don't really want this to happen though....so we will prevent it through other means....
                            return;
                        }
                    }
                    if(canflyandwalk>0)
                    {
                        //should we return to ground?
                        if(Map.passable(nx,ny) && nid==Map.VACANT)
                        {
                            Map.removeflyer(id,x,y,flightlevel);
                            flightlevel = -1;
                            //good! we've returned to Earth...
                            animmode = ANIMMODE_WALK;
                            //will insert into map cell in a moment....
                        }
                    }
                    if(flightlevel!=-1)//3mar2022
                    {
                        return ;//3mar2022
                    }
                }
                else
                {
                    //we are not flying currently.....
                    //but....should we try to?
                    if(canflyandwalk>0)
                    {
                        if(!Map.passable(nx,ny))
                        {
                            if(Map.cellflyer(nx,ny,Map.FLIGHTLEVELS - 1)==-1)
                            {
                                Map.removeunit(id,x,y);
                                x+=ddx*walkspeed;
                                y+=ddy*walkspeed;
                                flightlevel = Map.insertflyer(id,x,y);
                                animmode = ANIMMODE_FLY;
                                retreat = false;
                                //retreatframe = 0;//2sep2021
                                tmptattempts = 0;
                                tmptframe = 0;
                                if(flightlevel==-1)
                                {
                                    hp = 0; //bugger - we don't really want this to happen though....so we will prevent it through other means....
                                }
                            }
                            if(flightlevel!=-1)
                            {
                                return; //we are off the ground....
                            }
                        }
                    }
                    else
                    {
                        if(canfly>0) //in case we are a flying unit at the beginning of our game...and we for some reason have started on the ground......
                        {
                            if(Map.cellflyer(nx,ny,Map.FLIGHTLEVELS - 1)==-1)
                            {
                                Map.removeunit(id,x,y);
                                x+=ddx*walkspeed;
                                y+=ddy*walkspeed;
                                flightlevel = Map.insertflyer(id,x,y);
                                animmode = ANIMMODE_FLY;
                                retreat = false;
                                retreatframe = 0;
                                tmptattempts = 0;
                                tmptframe = 0;
                                if(flightlevel==-1)
                                {
                                    hp = 0; //bugger - we don't really want this to happen though....so we will prevent it through other means....
                                }
                            }
                            if(flightlevel!=-1)
                            {
                                return; //we are off the ground....
                            }
                        }
                    }
                }
            }
            //end-------------------------//4may2021
            if((nid==id || nid==Map.VACANT) && Map.passable(nx,ny) && Map.heightdiff2(height,x,y)<Unit.MAXWALKHEIGHTDIFF)//21apr2021
            //if((nid==id || nid==Map.VACANT) && Map.passable(nx,ny) && Map.passable(nnx,nny) && Map.heightdiff2(height,x,y)<Unit.MAXWALKHEIGHTDIFF)//21apr2021
            {
                Map.removeunit(id,x,y);
                int ogx = x / Map.GRIDW;
                int ogy = y / Map.GRIDH;
                x+=ddx*walkspeed;
                y+=ddy*walkspeed;
                animmode = ANIMMODE_WALK;
                Map.insertunit(id,x,y);
                int ngx = x / Map.GRIDW;
                int ngy = y / Map.GRIDH;
                //if(ogx!=ngx || ogy!=ngy)
                //{
                    //square must have been vacant.....
                    //we should do a pathing check
                    if(game.frame % Unit.MAXUNITS==id)
                    {
                        if(checkedgrid[0]!=x || checkedgrid[1]!=y || checkedgrid[2]!=tx || checkedgrid[3]!=ty)
                        {
                            Unit.PATHSTEP = 2;
                            //this sets tmptx and tmpty
                            Functions.saveseed();//11apr2021
                            pathfind(game,x,y,tx,ty,id);
                            Functions.restoreseed();//11apr2021
                            checkedgrid[0] = x;
                            checkedgrid[1] = y;
                            checkedgrid[2] = tx;
                            checkedgrid[3] = ty;
                            Unit.PATHSTEP = 1;
                            tmptframe = 0; //we're not actually blocked...we're just making our life easier...
                            tmptattempts--;
                        }
                    }
                //}
                if(dustcloud>0)
                {
                    //Blood.makeblood(game,x,y,Blood.DUSTCLOUD);
                }
            }
            else
            {
                //try and walk around the obstacle......
                //tx = x + Functions.rand(-100,100);
                //ty = y + Functions.rand(-100,100);
                //animmode = ANIMMODE_IDLE;
                //tmptframe = 120;
                //tmptx = x + Functions.rand(-100,100);
                //tmpty = y + Functions.rand(-100,100);
                //NEED TO OPTIMISE PATH FINDING.
                animmode = ANIMMODE_WALK;
                if((game.frame + id) % 10==0)
                {
                    bool freesquare = checkfreeadjacent(game,id);
                    //if we are surrounded - eg such as when all enemies are around us, then no point checking to path find.....
                    if(freesquare)
                    {
                        Functions.saveseed();//11apr2021
                        pathfind(game,x,y,tx,ty,id); // only path find a short way to where we are going....
                        Functions.restoreseed();//11apr2021
                        //animmode = ANIMMODE_WALK;
                        if(tmptattempts > MAXPATHFIND)
                        {
                            tx = x;
                            ty = y;
                            tmptx = x;
                            tmpty = y;
                            tmptattempts = 0;
                        }
                        if(tmptattempts>4 && Functions.abs(tx-x)<4 && Functions.abs(ty-y)<4)
                        {
                            tx = x;
                            ty = y;
                            tmptx = x;
                            tmpty = y;
                            tmptattempts = 0;
                        }
                    }
                }
                if(nid!=id && nid!=Map.VACANT)
                {
                    //start---------//23sep2021
                    //currently only gold can be picked up...
                    if(game.units[nid].canpickup>0)
                    {
                        if(faction==Game.PLAYERFACTION)
                        {
                            gold+=game.units[nid].gold;
                            game.units[nid].gold = 0;
                            game.units[nid].hp=0;
                            Map.removeunit(nid, game.units[nid].x, game.units[nid].y);
                            //play sound?
                            return;
                        }
                    }
                    //end-----------//23sep2021
                    if(game.units[nid].faction!=faction && game.units[nid].faction!=Unit.NULLFACTION)
                    {
                        //we've bumped into an enemy......
                        if(orderframe<=0)
                        {
                            firetargeti = nid;
                        }
                        //if we are a shock unit
                        if(shock>0 || fearsome>0)
                        {
                            //Functions.saveseed();//11apr2021
                            shocktarget(game,nid);
                            //Functions.restoreseed();//11apr2021
                        }
                    }
                    if(game.units[nid].faction==faction)
                    {
                        if(leader > 0)
                        {
                            game.units[nid].timid = 0;
                            game.units[nid].retreat = false;
                            game.units[nid].retreatframe = game.frame + Unit.RETREATDEATH;
                        }
                    }
                    if(timid==1 && game.units[nid].timid==0 && game.units[nid].faction==faction)
                    {
                        //Functions.saveseed();//11apr2021
                        if(Functions.rand(0,1000)<200)
                        {
                            game.units[nid].timid = 1;
                        }
                        //Functions.restoreseed();//11apr2021
                    }
                    if(game.units[nid].faction==faction && retreat==true)
                    {
                        if(game.units[nid].timid==0)
                        {
                            game.units[nid].timid=1;
                        }
                        if(game.units[nid].retreat==false)
                        {
                            //Functions.saveseed();//11apr2021
                            if(Functions.rand(0,1000)<200)
                            {
                                game.units[nid].retreat = true;
                                game.units[nid].retreatframe = game.frame + Unit.RETREATDEATH;
                            }
                            //Functions.restoreseed();//11apr2021
                            //start---------------//27mar2021
                            //there should be a chance for us ourselves to rally if we collide with a friend who is not
                            //panicking....
                            //commented out currently until ready to test happily as I need a break from this...
                            //if(game.units[nid].retreat==false)
                            //{
                            //    //so if we didn't spread panic ourselves....
                            //    //then there's a chance we might rally...
                            //    if(Functions.rand(0,1000)<200)
                            //    {
                            //        retreat = false;
                            //        retreatframe = 0;
                            //    }
                            //    //and if we're not fleeing now...there's a chance we might no longer be timid too..
                            //    if(game.templates[templateid].timid<=0 && retreat==false)
                            //    {
                            //        timid = 0;
                            //    }
                            //}
                            //end-----------------//27mar2021
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public bool checkfreeadjacent(Game game, int id)
        {
            //check that the position moving to is empty
            int gx = game.units[id].x / Map.GRIDW;
            int gy = game.units[id].y / Map.GRIDH;
            if(gx>=0 && gy>=0 && gx<Map.MAXX && gy<Map.MAXY)
            {
                if(Map.cellunit((gx*Map.GRIDW),((gy + 1)*Map.GRIDH))==Map.VACANT && Map.passable((gx * Map.GRIDW),(gy + 1) * Map.GRIDH)==true && Map.heightdiff2(game.units[id].height,(gx)*Map.GRIDW,(gy + 1)*Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
                {
                    return true;
                }
                if(Map.cellunit((gx*Map.GRIDW),((gy - 1)*Map.GRIDH))==Map.VACANT && Map.passable(gx * Map.GRIDW,(gy - 1) * Map.GRIDH)==true && Map.heightdiff2(game.units[id].height,(gx)*Map.GRIDW,(gy - 1)*Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
                {
                    return true;
                }
                if(Map.cellunit(((gx - 1)*Map.GRIDW),((gy)*Map.GRIDH))==Map.VACANT && Map.passable((gx - 1) * Map.GRIDW,(gy) * Map.GRIDH)==true && Map.heightdiff2(game.units[id].height,(gx - 1)*Map.GRIDW,(gy)*Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
                {
                    return true;
                }
                if(Map.cellunit(((gx + 1)*Map.GRIDW),((gy)*Map.GRIDH))==Map.VACANT && Map.passable((gx + 1) * Map.GRIDW,(gy) * Map.GRIDH)==true && Map.heightdiff2(game.units[id].height,(gx + 1)*Map.GRIDW,(gy)*Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
                {
                    return true;
                }
            }
            return false;
        }

///////////////////Method Definition///////////////
        public static int seekpath(int sx,int sy,int fx,int fy,int dirn,int depth,int id)
        {
            //path finding
            //optimise
            if(depth==0)
            {
                Map.resetpathmap();
            }
            if(depth > MAXDEPTH)
            {
                return -1;
            }
            if(sx==fx && sy==fy)
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" met target.");
                return depth;
            }
            if(!Map.ignoreunits)
            {
                int nid = Map.cellunit(sx * Map.GRIDW,sy * Map.GRIDH);
                if(nid!=Map.VACANT && nid!=id)
                {
                    //Console.WriteLine("Cell Not VACANT:"+nid);
                    return -1;
                }
            }
            //okay.....
            if(!Map.passable(sx * Map.GRIDW,sy * Map.GRIDH))
            {
                //Console.WriteLine("Not Passable");
                return -1;
            }
            int pi = sx + sy * Map.MAXX;
            if(pi<0 || pi>=Map.pathmap.Length)
            {
                //Console.WriteLine("OUTSIDE BOUNDS");
                return -1;
            }
            if(depth==0)
            {
                Map.pathmap[pi] = Map.PATHINIT;
            }
            if(Map.pathmap[pi]==0)
            {
                //we haven't tested this square yet
                Map.pathmap[pi] = depth;
            }
            else
            {
                //we've already tested this square....
                if(depth < Map.pathmap[pi] || depth==0 || Map.pathmap[pi]==0)
                {
                    Map.pathmap[pi] = depth;
                }
                else
                {
                    return -1;
                }
            }
            int leftdir = -1;
            int rightdir = -1;
            int updir = -1;
            int downdir = -1;
            int mindepth = Map.PATHINIT;
            int direction = -1;
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx - 1) * Map.GRIDW,(sy) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                leftdir = seekpath(sx - 1,sy,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx + 1) * Map.GRIDW,(sy) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                rightdir = seekpath(sx + 1,sy,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx) * Map.GRIDW,(sy - 1) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                updir = seekpath(sx,sy - 1,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx) * Map.GRIDW,(sy + 1) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                downdir = seekpath(sx,sy + 1,fx,fy,0,depth + 1,id);
            }
            if(leftdir!=-1 && leftdir<mindepth)
            {
                mindepth = leftdir;
                direction = DIRN_LEFT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" LEFT.");
            }
            if(rightdir!=-1 && rightdir<mindepth)
            {
                mindepth = rightdir;
                direction = DIRN_RIGHT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" RIGHT.");
            }
            if(updir!=-1 && updir<mindepth)
            {
                mindepth = updir;
                direction = DIRN_UP;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" UP.");
            }
            if(downdir!=-1 && downdir<mindepth)
            {
                mindepth = downdir;
                direction = DIRN_DOWN;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" DOWN.");
            }
            if(depth==0)
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" GO:"+direction);
                return direction;
            }
            else
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" MINDEPTH:"+mindepth);
                return mindepth;
            }
        }
/*

///////////////////Method Definition///////////////
        public static int seekpath(int sx,int sy,int fx,int fy,int dirn,int depth,int id)
        {
            //optimise
            if(depth==0)
            {
                Map.resetpathmap();
            }
            if(depth > MAXDEPTH)
            {
                return -1;
            }
            if(sx==fx && sy==fy)
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" met target.");
                return depth;
            }
            if(!Map.ignoreunits)
            {
                int nid = Map.cellunit(sx * Map.GRIDW,sy * Map.GRIDH);
                if(nid!=Map.VACANT && nid!=id)
                {
                    //Console.WriteLine("Cell Not VACANT:"+nid);
                    return -1;
                }
            }
            //okay.....
            if(!Map.passable(sx * Map.GRIDW,sy * Map.GRIDH))
            {
                //Console.WriteLine("Not Passable");
                return -1;
            }
            int pi = sx + sy * Map.MAXX;
            if(pi<0 || pi>=Map.pathmap.Length)
            {
                //Console.WriteLine("OUTSIDE BOUNDS");
                return -1;
            }
            if(depth==0)
            {
                Map.pathmap[pi] = 0;
            }
            if(Map.pathmap[pi]==Map.PATHINIT)
            {
                //we haven't tested this square yet
                Map.pathmap[pi] = depth;
            }
            else
            {
                //we've already tested this square....
                if(depth < Map.pathmap[pi] || depth==0)
                {
                    Map.pathmap[pi] = depth;
                }
                else
                {
                    return -1;
                }
            }
            int leftdir = -1;
            int rightdir = -1;
            int updir = -1;
            int downdir = -1;
            int mindepth = Map.PATHINIT;
            int direction = -1;
            leftdir = seekpath(sx - 1,sy,fx,fy,0,depth + 1,id);
            rightdir = seekpath(sx + 1,sy,fx,fy,0,depth + 1,id);
            updir = seekpath(sx,sy - 1,fx,fy,0,depth + 1,id);
            downdir = seekpath(sx,sy + 1,fx,fy,0,depth + 1,id);
            if(leftdir!=-1 && leftdir<mindepth)
            {
                mindepth = leftdir;
                direction = DIRN_LEFT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" LEFT.");
            }
            if(rightdir!=-1 && rightdir<mindepth)
            {
                mindepth = rightdir;
                direction = DIRN_RIGHT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" RIGHT.");
            }
            if(updir!=-1 && updir<mindepth)
            {
                mindepth = updir;
                direction = DIRN_UP;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" UP.");
            }
            if(downdir!=-1 && downdir<mindepth)
            {
                mindepth = downdir;
                direction = DIRN_DOWN;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" DOWN.");
            }
            if(depth==0)
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" GO:"+direction);
                return direction;
            }
            else
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" MINDEPTH:"+mindepth);
                return mindepth;
            }
        }
        *
/
///////////////////Method Definition///////////////
        public bool quickpathfind(int sx,int sy,int fx, int fy)//28apr2021
        {
            sx/=Map.GRIDW;
            sy/=Map.GRIDH;
            fx/=Map.GRIDW;
            fy/=Map.GRIDH;
            if(sx<0 || sy<0 || fy<0 || fx<0 || sx>=Map.MAXX || sy>=Map.MAXY || fx>=Map.MAXX || fy>=Map.MAXY)
            {
                return false;
            }
            int godirn = Map.precalcedpaths[sx,sy,fx,fy];
            if(godirn!=Map.NOTCHECKED && godirn!=-1)
            {
                switch(godirn)
                {
                    case 0:
                    tmptx = x;
                    tmpty = y + Unit.PATHSTEP * Map.GRIDH;
                    break;
                    case 2:
                    tmptx = x - Unit.PATHSTEP * Map.GRIDW;
                    tmpty = y;
                    break;
                    case 6:
                    tmptx = x + Unit.PATHSTEP * Map.GRIDW;
                    tmpty = y;
                    break;
                    case 4:
                    tmptx = x;
                    tmpty = y - Unit.PATHSTEP * Map.GRIDH;
                    break;
                }
                return true;
            }
            return false;
        }
        
///////////////////Method Definition///////////////
        public void pathfind(Game game, int x, int y, int tx, int ty,int id)
        {
            //more path finding
            //uses a modified Djikstra algorithm.
            //NEED TO OPTIMISE
            int ttx = tx;
            int tty = ty;
            int oMAXDEPTH = Unit.MAXDEPTH;
            if(selected==Unit.SELECTIONFROZEN && game.frame < Game.ordergivenframe + Game.EXTRAPATHINGTIME && game.frame < timesincelastpath + Game.EXTRAPATHINGTIME)
            {
            //    Unit.MAXDEPTH*=2;//attempt to improve efficiency when lots of units are selected....24apr2022(hence commented this out)
            }
            timesincelastpath = game.frame;
            if(Functions.abs(tx-x)>Unit.MAXDEPTH)
            {
                ttx = x + Functions.sign(tx - x) * (Unit.MAXDEPTH/2) * Map.GRIDW;
            }
            else
            {
                ttx = x + Functions.rand(-4,4) * Map.GRIDW;
            }
            if(Functions.abs(ty-y)>Unit.MAXDEPTH)
            {
                tty = y + Functions.sign(ty - y) * (Unit.MAXDEPTH/2) * Map.GRIDH;
            }
            else
            {
                tty = y + Functions.rand(-4,4) * Map.GRIDH;
            }
            if(Functions.abs(tx-x)+Functions.abs(ty-y)<oMAXDEPTH/2)
            {
                Unit.MAXDEPTH = oMAXDEPTH / 2;
            }
            if(Functions.abs(tx-x)+Functions.abs(ty-y)<oMAXDEPTH/3)
            {
                Unit.MAXDEPTH = oMAXDEPTH / 3;
            }
            ttx = tx;
            tty = ty;
            int sx = 0;
            int sy = 0;
            int fx = 0;
            int fy = 0;
            int godirn = -1;
            float dist = Functions.abs(ttx-x)/Map.GRIDW + Functions.abs(tty-y)/Map.GRIDH;
            if(tmptattempts<Unit.PRECALCLIMIT)
            {
                sx = x / Map.GRIDW;
                sy = y / Map.GRIDH;
                fx = tx / Map.GRIDW;
                fy = ty / Map.GRIDH;
                if(sx>=0 && fx>=0 && sy>=0 && fy>=0 && sx<Map.MAXX && sy<Map.MAXY && fx<Map.MAXX && fy<Map.MAXY)
                {
                    godirn = Map.precalcedpaths[sx,sy,fx,fy];
                    if(godirn==Map.NOTCHECKED)
                    {
                        godirn = -1;
                    }
                    else
                    {
                        Config.precalcused++;
                        if(godirn!=-1)
                        {
                            Config.seekpathsuccess++;
                        }
                    }
                }
            }
            if(dist < Unit.MAXDEPTH && godirn==-1) //no point checking our pathfinding routine if we are too far away....
            //or rather only check if we can actually reach with our current maxdepth.....otherwise pointless.
            {
                godirn = seekpath(x / Map.GRIDW,y / Map.GRIDH,ttx / Map.GRIDW,tty / Map.GRIDH,0,0,id);
                Config.seekpathused++;
                if(godirn==-1)
                {
                    sx = x / Map.GRIDW;
                    sy = y / Map.GRIDH;
                    fx = tx / Map.GRIDW;
                    fy = ty / Map.GRIDH;
                    Config.seekpathfailed++;
                    if(sx>=0 && fx>=0 && sy>=0 && fy>=0 && sx<Map.MAXX && sy<Map.MAXY && fx<Map.MAXX && fy<Map.MAXY)
                    {
                        godirn = Map.precalcedpaths[sx,sy,fx,fy];
                        if(godirn==Map.NOTCHECKED)
                        {
                            godirn = -1;
                        }
                        else
                        {
                            Config.precalcused++;
                        }
                    }
                }
                else
                {
                    Config.seekpathsuccess++;
                    sx = x / Map.GRIDW;
                    sy = y / Map.GRIDH;
                    fx = tx / Map.GRIDW;
                    fy = ty / Map.GRIDH;
                    if(sx>=0 && fx>=0 && sy>=0 && fy>=0 && sx<Map.MAXX && sy<Map.MAXY && fx<Map.MAXX && fy<Map.MAXY)
                    {
                        if(Map.precalcedpaths[sx,sy,fx,fy]==Map.NOTCHECKED)
                        {
                            Map.precalcedpaths[sx,sy,fx,fy] = godirn;
                        }
                    }
                }
            }
            Unit.MAXDEPTH = oMAXDEPTH;
            tmptframe = 15;
            tmptattempts++;
            switch(godirn)
            {
                case 0:
                tmptx = x;
                //tmpty = y + 8 * Map.GRIDH;
                tmpty = y + Unit.PATHSTEP * Map.GRIDH;
                //Console.WriteLine("Go Down");
                break;
                case 1:
                tmptx = x - 5 * Map.GRIDW;
                tmpty = y + 5 * Map.GRIDH;
                break;
                case 7:
                tmptx = x + 5 * Map.GRIDW;
                tmpty = y + 5 * Map.GRIDH;
                break;
                //tmptx = x - 8 * Map.GRIDW;
                case 2:
                tmptx = x - Unit.PATHSTEP * Map.GRIDW;
                tmpty = y;
                //Console.WriteLine("Go Left");
                break;
                case 6:
                //tmptx = x + 8 * Map.GRIDW;
                tmptx = x + Unit.PATHSTEP * Map.GRIDW;
                tmpty = y;
                //Console.WriteLine("Go Right");
                break;
                case 4:
                tmptx = x;
                //tmpty = y - 8 * Map.GRIDH;
                tmpty = y - Unit.PATHSTEP * Map.GRIDH;
                //Console.WriteLine("Go Up");
                break;
                case 3:
                tmptx = x - 5 * Map.GRIDW;
                tmpty = y - 5 * Map.GRIDH;
                break;
                case 5:
                tmptx = x + 5 * Map.GRIDW;
                tmpty = y - 5 * Map.GRIDH;
                break;
                case -1:
                    tmptx = x + Functions.rand(-100,100);
                    tmpty = y + Functions.rand(-100,100);
                    if(tmptattempts==Unit.MAXPATHFIND/2 || tmptattempts==3*Unit.MAXPATHFIND/4 || (tmptattempts % 10)==0)
                    {
                        tx+=Functions.rand(-100,100);
                        ty+=Functions.rand(-100,100);
                        tmptx = tx;
                        tmpty = ty;
                    }
                break;
            }
        }

///////////////////Method Definition///////////////
        public void animate(Game game)
        {
            //animation method
            //handles all animation of units
            int oframe = animframe;
            if(animspeed<=0)
            {
                return;
            }
            //Functions.saveseed();//11apr2021
            animtime--;//29sep2021
            if(animmode==ANIMMODE_WALK)
            {
                //if(Game.frame % animspeed==0)//29sep2021
                if(animtime<=0)//29sep2021
                {
                    animframe++;    
                }
            }
            else
            {
                //if(Game.frame % (animspeed*2)==0)//29sep2021
                if(animtime<=0)//29sep2021
                {
                    animframe++;    
                }
            }
            if(animtime<=0)//29sep2021
            {
                animtime = animspeed;//29sep2021
            }
            //start------------//29may2021
            if((game.frame % animspeed==0))
            {
                int diffdirn = displaydirn - dirn;
                if(Functions.abs(diffdirn)<4)
                {
                    if(dirn<displaydirn)
                    {
                        displaydirn--;
                        if(displaydirn<0)
                        {
                            displaydirn+=8;
                        }
                    }
                    else
                    {
                        if(displaydirn!=dirn)
                        {
                        displaydirn++;
                        }
                    }
                    displaydirn%=8;
                }
                else
                {
                    if(dirn<displaydirn)
                    {
                        displaydirn++;
                    }
                    else
                    {
                        if(dirn!=displaydirn)
                        {
                            displaydirn--;
                            if(displaydirn<0)
                            {
                                displaydirn+=8;
                            }
                        }
                    }
                    displaydirn%=8;
                }
            }
            //end--------------//29may2021
            if(animmode==ANIMMODE_ATTACK || animmode==ANIMMODE_ATTACK2 || animmode==ANIMMODE_ATTACK3)
            {
                if(animmode!=oanimmode)
                {
                    if(animmode==ANIMMODE_ATTACK)
                    {
                        animframe = animmodeattframestart;
                    }
                    if(animmode==ANIMMODE_ATTACK2)
                    {
                        animframe = animmodeatt2framestart;
                    }
                    if(animmode==ANIMMODE_ATTACK3)
                    {
                        animframe = animmodeatt3framestart;
                    }
                }
                else
                {
                    if(animmode==ANIMMODE_ATTACK)
                    {
                        if(animframe>animmodeattframeend)
                        {
                            //start----------//21feb2022
                            if(dieonplace>0 && Game.EDITOR == false)
                            {
                                hp = 0;
                            }
                            //end------------//21feb2022

                            //change back to idle....
                            animmode = ANIMMODE_IDLE;
                            animframe = animmodeidleframestart;
                            animrest = 30; // half a second....
                        }
                    }
                    if(animmode==ANIMMODE_ATTACK2)
                    {
                        if(animframe>animmodeatt2frameend)
                        {
                            //start----------//21feb2022
                            if(dieonplace>0 && Game.EDITOR == false)
                            {
                                hp = 0;
                            }
                            //end------------//21feb2022
                            //change back to idle....
                            animmode = ANIMMODE_IDLE;
                            animframe = animmodeidleframestart;
                            animrest = 30; // half a second....
                        }
                    }
                    if(animmode==ANIMMODE_ATTACK3)
                    {
                        if(animframe>animmodeatt3frameend)
                        {
                            //change back to idle....
                            animmode = ANIMMODE_IDLE;
                            animframe = animmodeidleframestart;
                            animrest = 30; // half a second....
                            //start----------//21feb2022
                            if(dieonplace>0 && Game.EDITOR == false)
                            {
                                hp = 0;
                            }
                            //end------------//21feb2022
                        }
                    }
                }
            }
            //start-----------//4may2021
            if(animmode==ANIMMODE_FLYATTACK)
            {
                if(animmode!=oanimmode)
                {
                    if(animmode==ANIMMODE_FLYATTACK)
                    {
                        animframe = animmodeflyattackframestart;
                    }
                }
                else
                {
                    if(animmode==ANIMMODE_FLYATTACK)
                    {
                        if(animframe>animmodeflyattackframeend)
                        {
                            //change back to idle....
                            animmode = ANIMMODE_FLY;
                            animframe = animmodeflyframestart;
                            animrest = 30; // half a second....
                            //start----------//21feb2022
                            if(dieonplace>0 && Game.EDITOR == false)
                            {
                                hp = 0;
                            }
                            //end------------//21feb2022
                        }
                    }
                }
            }                
            //end------------//4may2021
            //start-------------//28Feb2021
            if(animmode==ANIMMODE_IDLE2)
            {
                if(animframe>animmodeidle2frameend)
                {
                    animframe = animmodeidleframestart;
                    animmode = ANIMMODE_IDLE;
                    //start----------//21feb2022
                    if(dieonplace>0 && Game.EDITOR == false)
                    {
                        hp = 0;
                    }
                    //end------------//21feb2022
                }
                if(animframe<animmodeidle2framestart)
                {
                    animframe = animmodeidle2framestart;
                }
                if((game.frame + id) % (60 * 5)==0)
                {
                    if(Functions.rand(0,100)<10)
                    {
                        dirn = Functions.rand(0,100) % 8;
                    }
                }
            }
            //end---------------//28Feb2021
            if(animmode==ANIMMODE_IDLE)
            {
                if(animframe>animmodeidleframeend)
                {
                    animframe = animmodeidleframestart;
                    //start----------//21feb2022
                    if(dieonplace>0 && Game.EDITOR == false)
                    {
                        hp = 0;
                    }
                    //end------------//21feb2022
                }
                if(animframe<animmodeidleframestart)
                {
                    animframe = animmodeidleframestart;
                }
                if((game.frame + id) % (60 * 5)==0)
                {
                    //start-------------//28Feb2021
                    if(Functions.rand(0,100)<30)
                    {
                        if(animmodeidle2framestart!=0 || animmodeidle2frameend!=0)
                        {
                            animframe = animmodeidle2framestart;
                            animmode = ANIMMODE_IDLE2;
                        }
                    }
                    //end---------------//28Feb2021
                    if(Functions.rand(0,100)<10)
                    {
                        dirn = Functions.rand(0,100) % 8;
                    }
                }
            }
            //start-------------//4may2021
            if(animmode==ANIMMODE_FLY)
            {
                if(animframe>animmodeflyframeend)
                {
                    animframe = animmodeflyframestart;
                    //start----------//21feb2022
                    if(dieonplace>0 && Game.EDITOR == false)
                    {
                        hp = 0;
                    }
                    //end------------//21feb2022
                    
                }
                if(animframe<animmodeflyframestart)
                {
                    animframe = animmodeflyframestart;
                }
            }
            //end---------------//4may2021
            if(animmode==ANIMMODE_WALK)
            {
                if(animmode!=oanimmode || animframe>animmodewalkframeend)
                {
                    animframe = animmodewalkframestart;
                    //start----------//21feb2022
                    if(dieonplace>0 && Game.EDITOR == false)
                    {
                        hp = 0;
                    }
                    //end------------//21feb2022
                    
                }
            }
            //Functions.restoreseed();//11apr2021
            //start-----------//25Feb2021
            if(animmode==ANIMMODE_DEAD)
            {
                if(animmode!=oanimmode)
                {
                    animframe = animmodedeadframestart;
                }
                if(animframe>animmodedeadframeend)
                {
                    animframe = animmodedeadframeend;
                    if(hp<=0 && dieonce<=(animmodedeadframeend - animmodedeadframestart))//13sep2021 added dieonce
                    {
                        if(dieonce==animmodedeadframeend - animmodedeadframestart){game.killed(game,id);}//13sep2021 around die once block.
                        dieonce++;//13sep2021
                    }
                    //start----------//21feb2022
                    if(dieonplace>0 && Game.EDITOR == false)
                    {
                        hp = 0;
                    }
                    //end------------//21feb2022
                    
                }
            }
            //end-------------//25Feb2021
            if(animmode!=oanimmode)
            {
                oanimmode = animmode;
            }
        }

///////////////////Method Definition///////////////
        public static void copyunitstats(Unit input,ref Unit output)
        {
            //copy a unit template from the base template
            //to the in game unit
            //typically used when creating new units
            //start-----------------//21mar2021
            if(Unit.COPYUNIT)
            {
                output.x = input.x;
                output.y = input.y;
                output.tx = input.tx;
                output.ty = input.ty;
                output.tmptx = input.tmptx;
                output.tmpty = input.tmpty;
                output.dirn = input.dirn;
                output.odirn = input.odirn;
                output.dirntime = input.dirntime;
                output.retreat = input.retreat;
                output.retreatframe = input.retreatframe;
                output.infog = input.infog;
                output.buffed = input.buffed;
                output.cursed = input.cursed;
                output.defendx = input.defendx;
                output.defendy = input.defendy;
                output.formationx = input.formationx;
                output.formationy = input.formationy;
                output.height = input.height;
                output.orderframe = input.orderframe;
                output.tmptframe = input.tmptframe;
                output.tmptattempts = input.tmptattempts;
                output.angle = input.angle;
                output.oanimmode = input.oanimmode;
                output.animmode = input.animmode;
                output.animrest = input.animrest;
                output.animframe = input.animframe;
                output.animspeed = input.animspeed;
                output.drawn = input.drawn;
                output.selected = input.selected;
                output.selectedframe = input.selectedframe;
                output.onscreen = input.onscreen;
                output.ronscreen = input.ronscreen;//25apr2021
                output.transportedbyid = input.transportedbyid; //4may2021
                output.bounddemon = input.bounddemon; //12jul2021
            }
            output.scale = input.scale;//25sep2021
            //end---------------------//21apr2021
            output.transportsize = input.transportsize;//3may2021
            output.transportcapacity = input.transportcapacity;//3may2021
            if(output.transportcapacity>0)//3may2021
            {
                output.transportarray = new int[output.transportcapacity];//3may2021
                for(int t=0;t<output.transportcapacity;t++) //4sep2021
                {
                    output.transportarray[t] = -1;//4sep2021
                }
            }
            else
            {
                output.transportarray = new int[0];//3may2021
            }
            if(Unit.COPYUNIT)//3may2021
            {
                if(input.transportarray!=null && output.transportarray!=null)
                {
                    if(output.transportarray.Length>0 && input.transportarray.Length>0)
                    {
                        for(int k=0;k<input.transportarray.Length;k++)
                        {
                            output.transportarray[k] = input.transportarray[k];
                        }
                    }
                }
            }
            output.accuracy = input.accuracy;//28feb2022
            output.basehp = input.basehp;
            output.basemana = input.basemana;//23sep2021
            output.mana = input.mana;//23sep2021
            output.manarate = input.manarate;//23sep2021
            output.healthpotions = input.healthpotions;//23sep2021
            output.manapotions = input.manapotions;//23sep2021
            output.bothpotions = input.bothpotions;//23sep2021
            output.unresearchedbydefault = input.unresearchedbydefault;//2sep2021
            output.gold = input.gold;//23sep2021
            output.canpickup = input.canpickup;//23sep2021
            //output.techguilinkid = input.techguilinkid;//2sep2021//26feb2022
            output.techguilinkid = new int[input.techguilinkid.Length];//26feb2022
            for(int t=0;t<output.techguilinkid.Length;t++)//26feb2022
            {
                output.techguilinkid[t] = input.techguilinkid[t];
            }
            
            output.hp = input.hp;
            output.misfire = 0;//28mar2021
            output.displayname = input.displayname; //13mar2021
            output.charactername = input.charactername;//10sep2021 //technically shouldn't be here because character name is set per mission not per unit in the unit file...
            output.displaycharactername = input.displaycharactername;//10sep2021
            output.damage = input.damage;
            output.damage2 = input.damage2;
            output.splash = input.splash;//2sep2021
            output.firerange2 = input.firerange2;
            output.needlos = input.needlos;//15sep2021
            output.bounddemon = input.bounddemon; //12jul2021
            output.armour = input.armour;
            output.firerange = input.firerange;
            output.firebullet = input.firebullet;
            output.healer = input.healer;
            output.infectchanceonhit = input.infectchanceonhit;//22apr2022
            output.infectchanceonkill = input.infectchanceonkill;//22apr2022
            output.infected = input.infected;//22apr2022
            output.infectinto = input.infectinto;//22apr2022
            output.spellcaster = input.spellcaster;
            output.prefermobiletargets = input.prefermobiletargets;//18sep2021
            output.notabuffer = input.notabuffer; //15apr2021
            output.firespell = input.firespell;
            output.extragibbet = input.extragibbet;//18sep2021
            output.powerspell = input.powerspell;
            output.points = input.points; //17sep2021
            output.zombiemaster = input.zombiemaster;
            output.banish = input.banish; //12mar2021
            output.dustcloud = input.dustcloud;
            output.timid = input.timid;
            output.mirrorleftright = input.mirrorleftright;//24sep2021
            output.controlmode = input.controlmode;//24sep2021
            output.guiattackdisplaylimit = input.guiattackdisplaylimit; //23sep2021
            output.hitandrun = input.hitandrun;
            output.brave = input.brave;
            //start-----//3may2021
            output.transforminto = input.transforminto;
            output.transformrequires = input.transformrequires;
            output.magictransform = input.magictransform;
            output.magicrelease = input.magicrelease;
            //end-------//3may2021
            //start---------------//01apr2021
            output.spellability = input.spellability;
            output.ping = input.ping;//16sep2021
            output.redping = input.redping;//17sep2021
            output.spelldefense = input.spelldefense;
            output.magicdef = input.magicdef;
            output.magicdoom = input.magicdoom;
            output.magicfrenzy = input.magicfrenzy;
            //end-----------------//01apr2021
            //start--------------//9apr2021
            output.magicleader = input.magicleader;
            output.magiczombiemaster = input.magiczombiemaster;
            //end----------------//9apr2021
            //start---------------//28mar2021
            output.magicgas = input.magicgas;
            output.magicweb = input.magicweb;
            output.magichaste = input.magichaste;
            output.magicfear = input.magicfear;
            output.magicplant = input.magicplant;
            output.magicsword = input.magicsword;
            output.magicstorm = input.magicstorm;
            output.magicwind = input.magicwind;
            output.magicstealth = input.magicstealth;
            output.magicshield = input.magicshield;
            output.magicarray = new int[17];
            int m = 0;
            if(output.magicrelease>0)//3may2021
            {
                output.magicarray[m] = output.magicrelease;
                m++;
            }
            if(output.magictransform>0)//3may2021
            {
                output.magicarray[m] = output.magictransform;
                m++;
            }
            //start--------------//9apr2021
            if(output.magicleader>0)//01apr2021
            {
                output.magicarray[m] = output.magicleader;
                m++;
            }
            if(output.magiczombiemaster>0)//01apr2021
            {
                output.magicarray[m] = output.magiczombiemaster;
                m++;
            }
            //end----------------//9apr2021
            if(output.magicdoom>0)//01apr2021
            {
                output.magicarray[m] = output.magicdoom;
                m++;
            }
            if(output.magicdef>0)//01apr2021
            {
                output.magicarray[m] = output.magicdef;
                m++;
            }
            if(output.magicfrenzy>0)//01apr2021
            {
                output.magicarray[m] = output.magicfrenzy;
                m++;
            }
            if(output.magicweb>0)
            {
                output.magicarray[m] = output.magicweb;
                m++;
            }
            
            if(output.magicfear>0)
            {
                output.magicarray[m] = output.magicfear;
                m++;
            }
            if(output.magicgas>0)
            {
                output.magicarray[m] = output.magicgas;
                m++;
            }
            if(output.magichaste>0)
            {
                output.magicarray[m] = output.magichaste;
                m++;
            }
            if(output.magicplant>0)
            {
                output.magicarray[m] = output.magicplant;
                m++;
            }
            if(output.magicshield>0)
            {
                output.magicarray[m] = output.magicshield;
                m++;
            }
            if(output.magicstealth>0)
            {
                output.magicarray[m] = output.magicstealth;
                m++;
            }
            if(output.magicstorm>0)
            {
                output.magicarray[m] = output.magicstorm;
                m++;
            }
            if(output.magicsword>0)
            {
                output.magicarray[m] = output.magicsword;
                m++;
            }
            if(output.magicwind>0)
            {
                output.magicarray[m] = output.magicwind;
                m++;
            }
            //start-----//21apr2021
            if(Unit.COPYUNIT)
            {
                for(int m2=0;m2<output.magicarray.Length;m2++)
                {
                    output.magicarray[m2] = input.magicarray[m2];
                }
            }
            //end-------//21apr2021
            //end-----------------//28mar2021
            output.buildpenalty = input.buildpenalty;//20mar2021
            //start-------------//7mar2021
            output.mob = input.mob;
            output.hatred = input.hatred;
            output.craftsman = input.craftsman;
            output.planar = input.planar;
            output.dieonplace = input.dieonplace;//21feb2022
            output.deathanim = input.deathanim;//21feb2022
            output.slow = input.slow;
            output.canpickup = input.canpickup;//23sep2021
            output.woodsman = input.woodsman;
            output.stupid = input.stupid;
            output.frenzy = input.frenzy;
            //end---------------//7mar2021
            output.highfirerate = input.highfirerate; //25Feb2021
            output.shock = input.shock;
            output.stealth = input.stealth;
            output.damagex = input.damagex;
            output.fearsome = input.fearsome;
            output.leader = input.leader;
            output.spawner = input.spawner;
            output.spawnertemplateid = input.spawnertemplateid;//26feb2022
            output.framesleft = input.framesleft;//9sep2021
            output.spawnerconstraint = input.spawnerconstraint;//9sep2021
            output.spawnertime = input.spawnertime;
            output.spawnercount = input.spawnercount;
            output.ai = input.ai;
            output.bossmonster = input.bossmonster;
            output.flammable = input.flammable;
            output.ecat = input.ecat;
            output.fcat = input.fcat;
            output.ecatfile = input.ecatfile;
            output.fcatfile = input.fcatfile;
            output.controlpoint = input.controlpoint;
            output.regeneration = input.regeneration;
            output.zombie = input.zombie;
            output.sacrificial = input.sacrificial;
            output.cansacrifice = input.cansacrifice;
            output.levelxp = input.levelxp;
            output.xpvalue = input.xpvalue;
            output.name = input.name;
            output.faction = input.faction;
            output.cat = input.cat;
            output.cathiresfile = input.cathiresfile; //9apr2021
            output.cathires = input.cathires;//9apr2021
            output.damage = input.damage;
            output.armour = input.armour;
            output.gold = input.gold;//23sep2021
            output.canpickup = input.canpickup;//23sep2021
            output.walkspeed = input.walkspeed;
            output.animspeed = input.animspeed;
            output.offy = input.offy;
            output.offx = input.offx; //20apr2021
            output.framesperdirn = input.framesperdirn;
            output.nodirn = input.nodirn;
            output.animmodedeadframestart = input.animmodedeadframestart; //25Feb2021
            output.animmodedeadframeend = input.animmodedeadframeend; //25Feb2021
            output.animmodeidleframestart = input.animmodeidleframestart;
            output.animmodeidleframeend = input.animmodeidleframeend;
            output.animmodeidle2framestart = input.animmodeidle2framestart; //28Feb2021
            output.animmodeidle2frameend = input.animmodeidle2frameend; //28Feb2021
            output.animmodewalkframestart = input.animmodewalkframestart;
            output.animmodewalkframeend = input.animmodewalkframeend;
            output.animmodeattframestart = input.animmodeattframestart;
            output.animmodeattframeend = input.animmodeattframeend;
            output.animmodeatt2framestart = input.animmodeatt2framestart;
            output.animmodeatt2frameend = input.animmodeatt2frameend;
            output.animmodeatt3framestart = input.animmodeatt3framestart;
            output.animmodeatt3frameend = input.animmodeatt3frameend;
            //start--------------//4may2021
            output.canattackair = input.canattackair;
            output.canfly = input.canfly;
            output.canflyandwalk = input.canflyandwalk;
            output.animmodeflyattackframeend = input.animmodeflyattackframeend;
            output.animmodeflyattackframestart = input.animmodeflyattackframestart;
            output.animmodeflyframeend = input.animmodeflyframeend;
            output.animmodeflyframestart = input.animmodeflyframestart;
            output.flightlevel = input.flightlevel;
            //end----------------//4may2021
            output.cw = input.cw;
            output.ch = input.ch;
            output.templateid = input.id;
            if(Unit.COPYUNIT)//21apr2021
            {
                output.templateid = input.templateid;
            }
            for(int i=0;i<input.impactfx.Length;i++)
            {
                output.impactfx[i] = input.impactfx[i];
            }
            for(int i=0;i<input.attackfx.Length;i++)
            {
                output.attackfx[i] = input.attackfx[i];
            }
            for(int i=0;i<input.targetfx.Length;i++)
            {
                output.targetfx[i] = input.targetfx[i];
            }
            for(int i=0;i<input.magicfx.Length;i++)
            {
                output.magicfx[i] = input.magicfx[i];
            }
            for(int i=0;i<input.ackfx.Length;i++)
            {
                output.ackfx[i] = input.ackfx[i];
            }
            for(int i=0;i<input.selectfx.Length;i++)
            {
                output.selectfx[i] = input.selectfx[i];
            }
            for(int i=0;i<input.deathfx.Length;i++) //28jul2021
            {
                output.deathfx[i] = input.deathfx[i];
            }
            //start----------//24feb2022
            if(Config.Night>0 & Config.useseasons>0 && COPYUNIT==false)
            {
                if(output.firerange>100)
                {
                    output.firerange = (output.firerange * 4) / 5;
                }
                if(output.firerange2>100)
                {
                    output.firerange2 = (output.firerange2 * 4) / 5;
                }
            }
            //end-----------//24feb2022
                
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////

    class MapThread //29may2021
    {
        public static bool running = false;
        public static bool quit = false;
        public static int MAXDEPTH = 500;
        public static int sx = 0;
        public static int sy = 0;
        public static int fx = 0;
        public static int fy = 0;
        public static int osx = 0;
        public static int osy = 0;
        public static int ofx = 0;
        public static int ofy = 0;
        public static int[] pathmap = new int[Map.MAXX*Map.MAXY];
        public static int[] checks = new int[Map.MAXX*Map.MAXY];
        public static int[] checkf = new int[Map.MAXX*Map.MAXY];
        public static int i = 0;
        public static int s = 0;
        public static int f = 0;
        public static bool complete = false;
        ///////////////////Method Definition///////////////
        public static void resetpathmap()
        {
            //not used
            //for(int i=0;i<pathmap.Length;i++)
            //{
            //    pathmap[i] = Map.PATHINIT;
            //}
            //pathmap = new int[MAXX*MAXY];
            Array.Clear(pathmap,0,pathmap.Length);
        }
        
        ///////////////////Method Definition///////////////
        public static void init()
        {
            //call this as soon as the game battle mode is entered and we've started playing....
            if(running)
            {
                return;
            }
            if(Game.EDITOR)
            {
                return;
            }
            if(complete)
            {
                return;
            }
            running = true;
            sx = 0;
            sy = 0;
            fx = 0;
            fy = 0;
            Array.Clear(checks,0,checks.Length);
            Array.Clear(checkf,0,checkf.Length);
            Array.Clear(pathmap,0,pathmap.Length);
            Thread thread = new Thread(new ThreadStart(ThreadFunction));
            thread.Start();        
        }
///////////////////Method Definition///////////////
        public static void ThreadFunction()
        {
            while(!quit)
            {
                //continually process the Map to read/write pathfinding information...
                //should be safe to do so continuously as long as the Map.precalc array exists....
                osx = sx;
                osy = sy;
                ofx = fx;
                ofy = fy;
                i++;
                i%=2;
                if(i==0)
                {
                    //every second iteration check between two 'unitmap' positions instead that have not yet been checked between....
                    for(int j=0;j<Map.unitmap.Length;j++)
                    {
                        if(Map.unitmap[j]!=Map.VACANT && checks[j]==0)
                        {
                            sx = j % Map.MAXX;
                            sy = (j - sx) / Map.MAXX;
                            s++;
                            s%=Unit.MAXUNITS;
                            break;
                        }
                    }
                    for(int j=Map.unitmap.Length - 1;j>=0;j--)
                    {
                        if(Map.unitmap[j]!=Map.VACANT && checkf[j]==0)
                        {
                            fx = j % Map.MAXX;
                            fy = (j - sx) / Map.MAXX;
                            f++;
                            f%=Unit.MAXUNITS;
                            break;
                        }
                    }
                    checks[sx + sy * Map.MAXX] = 1;
                    checkf[fx + fy * Map.MAXX] = 1;
                    if(s==0)
                    {
                        Array.Clear(checks,0,checks.Length);
                    }
                    if(f==0)
                    {
                        Array.Clear(checkf,0,checkf.Length);
                    }
                }
                if(Map.precalcedpaths!=null)
                {
                    //do our pathfinding calculation....
                    if(Map.precalcedpaths[sx,sy,fx,fy]==Map.NOTCHECKED)
                    {
                        Map.precalcedpaths[sx,sy,fx,fy] = seekpath2(sx,sy,fx,fy,0,0,0);
                    }
                }
                if(sx>=Map.MAXX && sy>=Map.MAXY && fx>=Map.MAXX && fy>=Map.MAXY)
                {
                    quit = true;
                    complete = true;
                    //also quit IF the game is exited......
                }
                if(Game.EDITOR)
                {
                    quit = true;
                }
                sx = osx;
                sy = osy;
                fx = ofx;
                fy = ofy;
                fx++;
                fx%=Map.MAXX;
                if(fx==0)
                {
                    fy++;
                    fy%=Map.MAXY;
                    if(fy==0)
                    {
                        sx++;
                        sx%=Map.MAXX;
                        if(sx==0)
                        {
                            sy++;
                            sy%=Map.MAXY;
                            if(sy==0)
                            {
                                quit=true;
                            }
                        }
                    }
                }
            }
            running = false;
        }
        
///////////////////Method Definition///////////////        
        public static int seekpath2(int sx,int sy,int fx,int fy,int dirn,int depth,int id)
        {
            //path finding
            //optimise
            if(depth==0)
            {
                MapThread.resetpathmap();
            }
            if(depth > MAXDEPTH)
            {
                return -1;
            }
            if(sx==fx && sy==fy)
            {
                return depth;
            }
            if(!Map.passable(sx * Map.GRIDW,sy * Map.GRIDH))
            {
                return -1;
            }
            int pi = sx + sy * Map.MAXX;
            if(pi<0 || pi>=MapThread.pathmap.Length)
            {
                return -1;
            }
            if(depth==0)
            {
                MapThread.pathmap[pi] = Map.PATHINIT;
            }
            if(MapThread.pathmap[pi]==0)
            {
                //we haven't tested this square yet
                MapThread.pathmap[pi] = depth;
            }
            else
            {
                //we've already tested this square....
                if(depth < MapThread.pathmap[pi] || depth==0 || MapThread.pathmap[pi]==0)
                {
                    MapThread.pathmap[pi] = depth;
                }
                else
                {
                    return -1;
                }
            }
            int leftdir = -1;
            int rightdir = -1;
            int updir = -1;
            int downdir = -1;
            int mindepth = Map.PATHINIT;
            int direction = -1;
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx - 1) * Map.GRIDW,(sy) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                leftdir = seekpath2(sx - 1,sy,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx + 1) * Map.GRIDW,(sy) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                rightdir = seekpath2(sx + 1,sy,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx) * Map.GRIDW,(sy - 1) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                updir = seekpath2(sx,sy - 1,fx,fy,0,depth + 1,id);
            }
            if(Map.heightdiff(sx * Map.GRIDW,sy * Map.GRIDH,(sx) * Map.GRIDW,(sy + 1) * Map.GRIDH)<Unit.MAXWALKHEIGHTDIFF)
            {
                downdir = seekpath2(sx,sy + 1,fx,fy,0,depth + 1,id);
            }
            if(leftdir!=-1 && leftdir<mindepth)
            {
                mindepth = leftdir;
                direction = Unit.DIRN_LEFT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" LEFT.");
            }
            if(rightdir!=-1 && rightdir<mindepth)
            {
                mindepth = rightdir;
                direction = Unit.DIRN_RIGHT;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" RIGHT.");
            }
            if(updir!=-1 && updir<mindepth)
            {
                mindepth = updir;
                direction = Unit.DIRN_UP;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" UP.");
            }
            if(downdir!=-1 && downdir<mindepth)
            {
                mindepth = downdir;
                direction = Unit.DIRN_DOWN;
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" DOWN.");
            }
            if(depth==0)
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" GO:"+direction);
                return direction;
            }
            else
            {
                //Console.WriteLine("sx:"+sx+" sy:"+sy+" fx:"+fx+" fy:"+fy+" depth:"+depth+" MINDEPTH:"+mindepth);
                return mindepth;
            }
        }
    }
    
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Map
    {
        public static int indoor;//23sep2021
        public static bool MINIMAPMODE = false;//18sep2021
        public static int DECOR = 9999;//18sep2021
        public static int levelseed = 0; //2apr2021
        public static int levelseed2 = 0;//2apr2021
        public static bool issnow = false;
        public static bool isdesert = false;
        public static bool isrgbbk = false;
        public static int isrgbbk_r = 0;
        public static int isrgbbk_g = 0;
        public static int isrgbbk_b = 0;
        public static int FADEOUT = 10;
        public static int MAXMUSIC=3;
        public static int[] musictrack;
        public static string[] musictrackfile;//25mar2021
        public static int[] musicduration;
        public static int musicplaying;
        public static int musicstartframe;
        public static int menumusic;
        public static int menumusicplaying;
        public static string menumusicfile = ""; //25mar2021
        public static bool OPENMAP = false;
        public static int[] deadcell = new int[10];    
        public static int VACANT = -1;
        public static int PATHINIT = 99999;
        public static int NOTCHECKED = -2;
        public static int MAXX = 100;
        public static int MAXY = 100;
        public static int GRIDW = 32;
        public static int GRIDH = 32;
        public static int DEFAULTGRIDW = 32;//10sep2021
        public static int DEFAULTGRIDH = 32;//10sep2021
        public static int[] unitmap; //id to unit in cell
        public static int[] tilefog; //15sep2021
        public static int[] unitcollisionmap;
        public static int[] flightmap;//4may2021 //id to unit in cell...for flyers....MAXX*MAXY*10 (10 should be sufficient)(3 dimensional array as 1 dimensional array)
        public static int[] flightlist;//4may2021
        public static int FLIGHTLEVELS = 10;//4may2021
        public static int FLIGHTLAYER = 999;//4may2021
        public static int[] pathmap;
        public static int[,,,] precalcedpaths;
        public static int[,,,] losmap;//15sep2021
        public static int precalcframestart;
        public static int precalcframestart2;
        public static bool ignoreunits;
        //
        public static int[] heightmap;
        public static int[] tileimage;
        public static int[] treeimage;
        public static int[] rockimage;
        public static int[] wallimage;
        public static int FIRETIME = 60 * 10;
        public static int[] firecell;
        public static int firecat;
        public static int fireframes;
        public static int tilecat;
        public static int treecat;
        public static int treeframes;
        public static int missiontreeframes;//28mar2021
        public static int treeoffsety;
        public static int rockcat;
        public static int rockframes;
        public static int rockoffsety;
        public static int wallcat;
        public static int wallframes;
        public static int walloffsety;
        public static int tileframes;
        //start--------------//2mar2021
        public static int[] decorimage;
        public static int decorcat;
        public static int decorframes;
        public static int odecorframes; //15mar2021
        public static int decoroffsety;
        //end----------------//2mar2021
        public static int[] treepositions;
        public static int FOGMAXX = 24;
        public static int FOGMAXY = 24;
        public static int FOGW = 160;
        public static int FOGH = 160;
        public static float FOGSCALE = 1f;//18sep2021
        public static float FOGADD = -0.25f;
        public static bool[] fog;
        public static float[] fogalpha;
        //
        public static string pathfile = "";
        public static bool threadrunning = false;

        public static int TILELIGHTRADIUS = 8;//15sep2021
        public static int MAXTILEFOG = 300;//15sep2021

///////////////////Method Definition///////////////
        public static bool TileVisible(int x,int y)
        {
            if(Config.TILEFOG==0)
            {
                return true;
            }
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0 || gx>=MAXX || gy>=MAXY)
            {
                return true;
            }
            if(tilefog[gx + gy * MAXX]<=0)
            {
                return false;
            }
            return true;
        }
///////////////////Method Definition///////////////
        public static int TileFog(Game game,int x,int y)//15sep2021
        {
            if(Config.TILEFOG==0)
            {
                return 0;
            }
            if(x<0 || y<0 || x>=MAXX || y>=MAXY)
            {
                return 0;
            }
            //update tilefog.....
            if(tilefog[x + y * MAXX]>0)
            {
                tilefog[x + y * MAXX]--;
                int jx = x + (game.frame % (TILELIGHTRADIUS*2)) - TILELIGHTRADIUS;
                int jy = y + ((game.frame - (game.frame % (TILELIGHTRADIUS*2)))/(TILELIGHTRADIUS*2)) - TILELIGHTRADIUS;
                if(Map.cellunit(jx,jy)!=-1)
                {
                    int jid = Map.cellunit(jx,jy);
                    if(game.units[jid].hp>0 && game.units[jid].faction==Game.PLAYERFACTION)
                    {
                        tilefog[x + y * MAXX] = MAXTILEFOG;
                    }
                }
                return 0;
            }
            for(int ix=x-TILELIGHTRADIUS;ix<=x+TILELIGHTRADIUS;ix++)
            {
                if(ix<0 || ix>=MAXX)
                {
                    continue;
                }
                for(int iy=y-TILELIGHTRADIUS;iy<=y+TILELIGHTRADIUS;iy++)
                {
                    if(iy<0 || iy>=MAXY)
                    {
                        continue;
                    }
                    
                    if(Map.cellunit(ix * GRIDW,iy * GRIDH)!=-1)
                    {
                        int id = Map.cellunit(ix * GRIDW,iy * GRIDH);
                        if(game.units[id].hp>0 && game.units[id].faction==Game.PLAYERFACTION)
                        {
                            tilefog[x + y * MAXX]=MAXTILEFOG;
                            return 0;
                        }
                    }
                }
            }
            return 1;
        }
        
///////////////////Method Definition///////////////
        public static void init() //13mar2021
        {
            //map initialisation used at startup and restartup
            musictrack = null;
            musicduration = null;
            musicplaying = 0;
            musicstartframe = 0;
            menumusic = 0;
            menumusicplaying = 0;
            OPENMAP = false;
            deadcell = new int[10];    
            unitmap = null; //id to unit in cell
            tilefog = null; //15sep2021
            flightmap = null;//id to unit in cell //4may2021
            flightlist = null;//4may2021
            unitcollisionmap = null;
            pathmap = null;
            precalcedpaths = null;
            losmap = null;//15sep2021
            heightmap = null;
            tileimage = null;
            treeimage = null;
            rockimage = null;
            wallimage = null;
            firecell = null;
            firecat = 0;
            fireframes = 0;
            tilecat = 0;
            treecat = 0;
            treeframes = 0;
            treeoffsety = 0;
            rockcat = 0;
            rockframes = 0;
            rockoffsety = 0;
            wallcat = 0;
            wallframes = 0;
            walloffsety = 0;
            tileframes = 0;
            GRIDW = 32;//10sep2021
            GRIDH = 32;//10sep2021
            //DEFAULTGRIDH = 32;//10sep2021
            //DEFAULTGRIDW = 32;//10sep2021
            //start--------------//2mar2021
            decorimage = null;
            decorcat = 0;
            decorframes = 0;
            decoroffsety = 0;
            //end----------------//2mar2021
            treepositions = null;
            fog = null;
            fogalpha = null;
            //
            pathfile = "";
        }

///////////////////Method Definition///////////////
        public static void loadpath(int mission)
        {
            //not used
            if(!Config.USEPATHFILE)
            {
                return;
            }
            try
            {
                string file = Config.custommapfolder + "\\path"+mission+".txt";
                string[] data = System.IO.File.ReadAllLines(file);
                for(int i=0;i<data.Length;i++)
                {
                    string[] dataline = data[i].Split(",");
                    if(dataline.Length==5)
                    {
                        int x0 = 0;
                        int y0 = 0;
                        int x1 = 0;
                        int y1 = 0;
                        int dd = Map.NOTCHECKED;
                        Int32.TryParse(dataline[0],out x0);
                        Int32.TryParse(dataline[1],out y0);
                        Int32.TryParse(dataline[2],out x1);
                        Int32.TryParse(dataline[3],out y1);
                        Int32.TryParse(dataline[4],out dd);
                        if(dd!=Map.NOTCHECKED)
                        {
                            precalcedpaths[x0,y0,x1,y1] = dd;
                        }
                    }
                }
            }
            catch(Exception e)
            {
                string msg = e.Message;
            }
        }
        //

///////////////////Method Definition///////////////
        public static void savepath(int mission)
        {
            //not used
            if(!Config.USEPATHFILE)
            {
                return;
            }
            if(threadrunning)
            {
                return;
            }
            threadrunning = true;
            pathfile = Config.custommapfolder + "\\path"+mission+".txt";
            Thread thread = new Thread(new ThreadStart(ThreadFunction));
            thread.Start();    
        }
        //

///////////////////Method Definition///////////////
        private static void ThreadFunction()
        {
            //not used
            string txt = "";
            for(int x0=0;x0<MAXX;x0++)
            {
                for(int y0=0;y0<MAXY;y0++)
                {
                    for(int x1=0;x1<MAXX;x1++)
                    {
                        for(int y1=0;y1<MAXY;y1++)
                        {
                            if(precalcedpaths[x0,y0,x1,y1]!=Map.NOTCHECKED && precalcedpaths[x0,y0,x1,y1]!=-1)
                            {
                                txt+=x0+","+y0+","+x1+","+y1+","+precalcedpaths[x0,y0,x1,y1]+Environment.NewLine;
                                precalcedpaths[x0,y0,x1,y1] = Map.NOTCHECKED;
                            }
                        }
                    }
                }
            }
            try
            {
                System.IO.File.WriteAllText(pathfile,txt);
                //Console.WriteLine("Map Saved To:"+file);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            threadrunning = false;
        }

///////////////////Method Definition///////////////
        public static void opencampaign(Game game)
        {
            //open the user campaign file
            try
            {
                System.Diagnostics.Process.Start("notepad.exe",Config.usercampaignfile);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

///////////////////Method Definition///////////////
        public static void savemap(Game game)
        {
            //save the user custom map to a temporary file
            string file = Config.custommapfolder + "\\"+Config.custommapprefix+game.frame+".txt";
            string txt = "";
            txt+="///////////////////////////////////////////////"+Environment.NewLine;
            txt+="//////KOG2 Level Editor Map 2021///////////////"+Environment.NewLine;
            txt+="///////////////////////////////////////////////"+Environment.NewLine;
            txt+="//change the mission name from custom map to something useful."+Environment.NewLine;
            txt+="mission=custom map"+Environment.NewLine;
            txt+="///////////////////"+Environment.NewLine;
            txt+="//Some editing by hand in the text file will likely be required to make this game ready."+Environment.NewLine;
            txt+="//If you haven't already, check the editor manual for details (English Only currently)"+Environment.NewLine;
            txt+="//But to make this level playable you have to copy the contents of this file onto the end of the relevant campaign00.txt file or usercampaign.txt file"+Environment.NewLine;
            txt+="///////////////////"+Environment.NewLine;
            txt+="//Description of Mission Here"+Environment.NewLine;
            txt+="description=Description Line 1"+Environment.NewLine;
            txt+="description=Description Line 2"+Environment.NewLine;
            txt+="description=Description Line 3(maximum)"+Environment.NewLine;
            txt+="//"+Environment.NewLine+"//"+Environment.NewLine+"//"+Environment.NewLine;
            txt+="//Leave this as default unless you know what it means. (it refers to the index position in the array of the mission, the first mission is index 0)."+Environment.NewLine;
            txt+="nextmissionid="+game.nextmissionid+Environment.NewLine;
            txt+="failedmissionid="+game.failedmissionid+Environment.NewLine;
            txt+="objective=[some objective here]"+Environment.NewLine;
            txt+="//add triggers by hand"+Environment.NewLine;
            txt+="Modify the corner position by hand."+Environment.NewLine;
            txt+="corner="+Game.CORNERX+","+Game.CORNERY+Environment.NewLine;
            txt+="///////////////////"+Environment.NewLine;
            txt+="//These features are special - use if you know what you are doing. Not set in editor.//"+Environment.NewLine;
            txt+="//lockcorner=0"+Environment.NewLine;
            txt+="//demo=0"+Environment.NewLine;
            txt+="//debrief=0"+Environment.NewLine;
            txt+="//nextmissionname=blank"+Environment.NewLine;
            txt+="//failedmissionname=blank"+Environment.NewLine;
            txt+="//fogoff=0"+Environment.NewLine;
            txt+="//neutralfog=0"+Environment.NewLine;
            txt+="//seed=123456"+Environment.NewLine;
            txt+="//unlocked=0"+Environment.NewLine;
            txt+="///////////////////"+Environment.NewLine;
            if(game.skirmish)
            {
                txt+="//this will mean the level will not be treated as a campaign level."+Environment.NewLine;
                txt+="skirmish=1"+Environment.NewLine;
            }
            else
            {
                txt+="skirmish=0"+Environment.NewLine;
            }
            txt+="//Triggers are here"+Environment.NewLine;
            txt+="//any trigger=3 or trigger=4 (chatter) triggers will need translating to other languages."+Environment.NewLine;
            for(int i=0;i<game.triggers.Length;i++)
            {
                if(game.triggers[i].type==0)
                {
                    continue;
                }
                txt+="trigger="+game.triggers[i].type+","+game.triggers[i].n+","+game.triggers[i].comparator+","+game.triggers[i].unitname.Replace(",","^")+","+game.triggers[i].x+","+game.triggers[i].y+","+game.triggers[i].fx+","+game.triggers[i].fy+Environment.NewLine;
            }
            txt+="Remember to Change This Next Line Accordingly"+Environment.NewLine;
            txt+="//Set ai=1 for an aggressive ai, otherwise leave as 0."+Environment.NewLine;
            txt+="ai=0"+Environment.NewLine;
            txt+="Trees, Rocks and Walls are here:"+Environment.NewLine;
            int count = 0;
            int index = 0;
            for(int i=0;i<Map.treeimage.Length;i++)
            {
                if(Map.treeimage[i]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                txt+="trees=";
                for(int i=0;i<Map.treeimage.Length;i++)
                {
                    if(Map.treeimage[i]!=-1)
                    {
                        index++;
                        if(index<count)
                        {
                            txt+=""+i+",";
                        }
                        else
                        {
                            txt+=""+i;
                        }
                    }
                }
            }
            txt+=Environment.NewLine;
            count=0;
            index=0;
            for(int i=0;i<Map.rockimage.Length;i++)
            {
                if(Map.rockimage[i]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                txt+="rocks=";
                for(int i=0;i<Map.rockimage.Length;i++)
                {
                    if(Map.rockimage[i]!=-1)
                    {
                        index++;
                        if(index<count)
                        {
                            txt+=""+i+",";
                        }
                        else
                        {
                            txt+=""+i;
                        }
                    }
                }
            }
            txt+=Environment.NewLine;
            count=0;
            index=0;
            for(int i=0;i<Map.wallimage.Length;i++)
            {
                if(Map.wallimage[i]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                txt+="walls=";
                for(int i=0;i<Map.wallimage.Length;i++)
                {
                    if(Map.wallimage[i]!=-1)
                    {
                        index++;
                        if(index<count)
                        {
                            txt+=""+i+",";
                        }
                        else
                        {
                            txt+=""+i;
                        }
                    }
                }
            }
            txt+=Environment.NewLine;
            //start--------------//2mar2021
            count=0; //7mar2021 bugfix
            index=0; //7mar2021 bugfix
            for(int i=0;i<Map.decorimage.Length;i++)
            {
                if(Map.decorimage[i]!=-1)
                {
                    count++;
                }
            }
            if(count>0)
            {
                txt+="decor=";
                for(int i=0;i<Map.decorimage.Length;i++)
                {
                    if(Map.decorimage[i]!=-1)
                    {
                        index++;
                        if(index<count)
                        {
                            txt+=""+i+",";
                        }
                        else
                        {
                            txt+=""+i;
                        }
                    }
                }
            }
            txt+=Environment.NewLine;
            //end----------------//2mar2021
            //start-----------------//21mar2021
            //faction set here
            txt+="Factions Are Here (change them if they're wrong as they auto-detected):"+Environment.NewLine;
            int pfaction=-1;
            int efaction=-1;
            for(int i=0;i<game.units.Length;i++)
            {
                if(game.units[i].hp>0 && game.units[i].faction<Unit.NULLFACTION)
                {
                    if(pfaction==-1)
                    {
                        pfaction = game.units[i].faction;
                    }
                    if(pfaction!=-1 && game.units[i].faction!=pfaction)
                    {
                        if(efaction==-1)
                        {
                            efaction = game.units[i].faction;
                        }
                    }
                }
            }
            //start-----------------//22mar2021
            if(Game.EDITORPFACTION!=0)
            {
                pfaction = Game.EDITORPFACTION;
            }
            if(Game.EDITOREFACTION!=0)
            {
                efaction = Game.EDITOREFACTION;
            }
            //end-------------------//22mar2021
            if(pfaction!=-1)
            {
                txt+="playerfaction=" + pfaction + Environment.NewLine;
            }
            if(efaction!=-1)
            {
                txt+="enemyfaction=" + efaction + Environment.NewLine;
            }
            //end-------------------//21mar2021
            txt+="Units Are Here:"+Environment.NewLine;
            txt+="//You can specify a random x or y position by entering 'random' into the x or y coordinate"+Environment.NewLine;
            for(int i=0;i<game.units.Length;i++)
            {
                if(game.units[i].hp>0)
                {
                    txt+="unit="+game.units[i].name+","+game.units[i].x+","+game.units[i].y+Environment.NewLine;
                }
            }
            txt+="///////////////////////////////////////////////"+Environment.NewLine;
            txt+="End of Mission"+Environment.NewLine;
            txt+="///////////////////////////////////////////////"+Environment.NewLine;
            try
            {
                System.IO.File.WriteAllText(file,txt);
                Console.WriteLine("Map Saved To:"+file);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.Message);
            }
            if(OPENMAP)
            {
                try
                {
                    System.Diagnostics.Process.Start(@Environment.GetFolderPath(Environment.SpecialFolder.Windows)+"\\notepad.exe",file);
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                }
            }
            OPENMAP = false;
        }

///////////////////Method Definition///////////////
        public static void marktreepos(Game game)
        {
            //mark trees on the minimap
            int count = 0;
            for(int i=0;i<treeimage.Length;i++)
            {
                if(treeimage[i]!=-1)
                {
                    count++;
                }
            }
            for(int i=0;i<rockimage.Length;i++)
            {
                if(rockimage[i]!=-1)
                {
                    count++;
                }
            }
            for(int i=0;i<wallimage.Length;i++)
            {
                if(wallimage[i]!=-1)
                {
                    count++;
                }
            }
            treepositions = new int[count];
            count = 0;
            for(int i=0;i<treeimage.Length;i++)
            {
                if(treeimage[i]!=-1)
                {
                    treepositions[count] = i;
                    count++;
                }
            }
            for(int i=0;i<rockimage.Length;i++)
            {
                if(rockimage[i]!=-1)
                {
                    treepositions[count] = i;
                    count++;
                }
            }
            for(int i=0;i<wallimage.Length;i++)
            {
                if(wallimage[i]!=-1)
                {
                    treepositions[count] = i;
                    count++;
                }
            }
        }

///////////////////Method Definition///////////////
        public static void correct(Game game)
        {
            //correct the map array
            //so far I have never found an error with the map
            //but this should clean up any errors if and when they occur
            //2sep2021 removed due to testing flight mode.....should not reintroduce
            int errors = 0;
            for(int i=0;i<unitmap.Length;i++)
            {
                if(Config.DEBUG)
                {
                    if(unitmap[i]!=VACANT)
                    {
                        int nid = unitmap[i];
                        if(nid>=0 && nid<game.units.Length)
                        {
                            int x = i % MAXX;
                            int y = (i - x) / MAXX;
                            int gx = game.units[nid].x / GRIDW;
                            int gy = game.units[nid].y / GRIDH;
                            if(gx!=x || gy!=y)
                            {
                                errors++;
                            }
                        }
                        else
                        {
                            errors++;
                        }
                    }
                }
                unitmap[i] = VACANT;
            }
            for(int i=0;i<flightmap.Length;i++)//21feb2022
            {
                flightmap[i] = VACANT;//21feb2022
            }
            for(int i=0;i<game.units.Length;i++)
            {
                //if(game.units[i].hp>0)//17sep2021
                if(game.units[i].hp>0 && game.units[i].flightlevel==-1)//17sep2021//22feb2022
                if(game.units[i].hp>0 && game.units[i].flightlevel==-1 && game.units[i].transportedbyid==-1)//17sep2021//22feb2022
                {
                    int gx = game.units[i].x / GRIDW;
                    int gy = game.units[i].y / GRIDH;
                    if(gx>=0 && gx<MAXX)
                    {
                        if(gy>=0 && gy<MAXY)
                        {
                            unitmap[gx + gy * MAXX] = i;
                        }
                    }
                }
                if(game.units[i].hp>0 && game.units[i].flightlevel!=-1)
                {
                    int gx = game.units[i].x / GRIDW;
                    int gy = game.units[i].y / GRIDH;
                    if(gx>=0 && gx<MAXX)
                    {
                        if(gy>=0 && gy<MAXY)
                        {
                            flightmap[gx + gy * MAXX + game.units[i].flightlevel * MAXX * MAXY] = i;
                        }
                    }
                }
            }
            if(errors>Config.maxmaperrors)
            {
                Config.maxmaperrors = errors;
            }
        }

///////////////////Method Definition///////////////
        public static void updatemusic(Game game)
        {
            //handle music control
            if(game.gamestate==Game.CAT_GAMESTATE_GAME)
            {
                if(menumusicplaying!=-1)
                {
                    SDL_mixer.Mix_PauseMusic();
                    menumusicplaying = -1;
                }
                bool startnewmusic = false;
                if(musicplaying==-1)
                {
                    startnewmusic = true;
                }
                else
                {
                    int v = 0;
                    if(game.frame > musicstartframe + 60 * musicduration[musicplaying])
                    {
                        startnewmusic = true;
                    }
                    if(game.frame/Map.FADEOUT < (musicstartframe/Map.FADEOUT) + Game.MUSICVOLUME)
                    {
                        v = (game.frame - musicstartframe)/Map.FADEOUT;
                        if(v<=0)
                        {
                            v = 1;
                        }
                        if(v>Game.MUSICVOLUME)
                        {
                            v = Game.MUSICVOLUME;
                        }
                    }
                    if((game.frame/Map.FADEOUT) > (musicstartframe + 60 * (musicduration[musicplaying] - 5))/Map.FADEOUT)
                    {
                        v = Game.MUSICVOLUME - (game.frame - (musicstartframe + 60 * (musicduration[musicplaying] - 5)))/Map.FADEOUT;
                        if(v<=0)
                        {
                            v = 1;
                        }
                        if(v>Game.MUSICVOLUME)
                        {
                            v = Game.MUSICVOLUME;
                        }
                    }
                    if(v!=0){SDL_mixer.Mix_VolumeMusic(v);}
                }
                if(startnewmusic)
                {
                    int nmusic = (int)(Functions.rand(0,1000) % musictrack.Length);
                    if(nmusic==musicplaying)
                    {
                        nmusic++;
                        nmusic%=musictrack.Length;
                    }
                    if(musictrack[nmusic]!=-1)
                    {
                        if(musicplaying!=-1)
                        {
                            SDL_mixer.Mix_PauseMusic();
                        }
                        musicplaying = nmusic;
                        Audios.playmusic(game.audios[musictrack[musicplaying]],Game.MUSICVOLUME,true);
                        musicstartframe = game.frame;
                    }
                }
            }
            else
            {
                if(musicplaying!=-1)
                {
                    SDL_mixer.Mix_PauseMusic();
                    Map.musicplaying = -1;
                    Map.musicstartframe = -1;
                }
                if(menumusicplaying==-1)
                {
                    if(menumusic!=-1)
                    {
                        menumusicplaying = 0;
                        Audios.playmusic(game.audios[menumusic],Game.MUSICVOLUME,true);
                    }
                }
                else
                {
                }
            }
        }

///////////////////Method Definition///////////////
        public Map()
        {
            //initialise the map object
                //for(int i=0;i<deadcell.Length;i++)
                //{
                //    deadcell[i] = -1;
                //}
                decorframes = 0;//15mar2021
                if(musictrack==null)
                {
                    musictrack = new int[MAXMUSIC];
                    musicduration = new int[MAXMUSIC];
                    musicplaying = -1;
                    musicstartframe = -1;
                    for(int i=0;i<MAXMUSIC;i++)
                    {
                        musictrack[i] = -1;
                        musicduration[i] = -1;
                    }
                }
                //
                flightmap = new int[MAXX*MAXY*FLIGHTLEVELS];//4may2021
                flightlist = new int[0];//4may2021
                unitmap = new int[MAXX*MAXY];
                tilefog = new int[MAXX*MAXY];//15sep2021
                pathmap = new int[MAXX*MAXY];
                heightmap = new int[MAXX*MAXY];
                if(losmap==null)//15sep2021
                {
                    losmap = new int[MAXX,MAXY,MAXX,MAXY];//15sep2021
                }
                if(precalcedpaths==null)
                {
                    precalcedpaths = new int[MAXX,MAXY,MAXX,MAXY];
                }
                ignoreunits = false;
                if(Map.MINIMAPMODE==false)//18sep2021
                {
                    if(!threadrunning)
                    {
                        for(int i1=0;i1<MAXX;i1++)
                        {
                            for(int i2=0;i2<MAXY;i2++)
                            {
                                for(int i3=0;i3<MAXX;i3++)
                                {
                                    for(int i4=0;i4<MAXY;i4++)
                                    {
                                        precalcedpaths[i1,i2,i3,i4] = Map.NOTCHECKED;
                                    }
                                }
                            }
                        }
                    }
                }//18sep2021
                precalcframestart = 0;
                precalcframestart2 = 0;
                firecell = new int[MAXX*MAXY];
                fog = new bool[FOGMAXX*FOGMAXY];
                fogalpha = new float[FOGMAXX*FOGMAXY];
                for(int i=0;i<fog.Length;i++)
                {
                    fog[i] = true;
                    fogalpha[i] = 1f;
                }
                if(tileimage==null)
                {
                    tileimage = new int[MAXX*MAXY];
                    for(int i=0;i<tileimage.Length;i++)
                    {
                        tileimage[i] = -1;
                        firecell[i] = -1;
                    }
                }
                if(treeimage==null)
                {
                    treeimage = new int[MAXX*MAXY];
                    rockimage = new int[MAXX*MAXY];
                    wallimage = new int[MAXX*MAXY];
                    decorimage = new int[MAXX*MAXY]; //2mar2021
                    for(int i=0;i<treeimage.Length;i++)
                    {
                        treeimage[i] = -1;
                        rockimage[i] = -1;
                        wallimage[i] = -1;
                        decorimage[i] = -1; //2mar2021
                    }
                }
                for(int i=0;i<unitmap.Length;i++)
                {
                    unitmap[i] = -1;
                    tilefog[i] = 0;//15sep2021
                }
                for(int i=0;i<flightmap.Length;i++)//4may2021
                {
                    flightmap[i] = -1;//4may2021
                }
                //
                unitcollisionmap = new int[MAXX*MAXY];
                for(int i=0;i<unitcollisionmap.Length;i++)
                {
                    unitcollisionmap[i] = -1;
                }
                for(int i=0;i<pathmap.Length;i++)
                {
                    pathmap[i] = -1;
                }
        }

///////////////////Method Definition///////////////
        public static void drawfires(Game game,int x, int y,int w, int h)
        {
            //draw flaming ground pieces
            int ww = 3;
            for(int fx=x-w;fx<=x+w;fx+=ww)
            {
                int fy = y + Functions.rand(-4,4);
                int hh = h + Functions.rand(-3*h/4,0);
                int r = 255;
                int g = 255;
                int b = 255;
                for(int l=0;l<hh;l++)
                {
                    g+= Functions.rand(-32,0);    
                    b+= Functions.rand(-96,0);
                    if(g<0)
                    {
                        g = 0;
                    }
                    if(b<0)
                    {
                        b = 0;
                    }
                    int xx = fx + Functions.rand(-w/4,w/4);
                    int yy = fy - l;// + Functions.rand(-8,8);
                    if(Functions.rand(0,1000+l*200)<500)
                    {
                        if(l<4)
                        {
                            RenderList.drawrect(game,xx,yy,5,5,RenderList.getrgb(r,g,b),0);
                        }
                        else
                        {
                            RenderList.drawrect(game,xx,yy,3,3,RenderList.getrgb(r,g,b),0);
                        }
                    }
                }
            }
        }
        //start--------------//2mar2021

///////////////////Method Definition///////////////
        public static void adddecor()
        {
            //not used
            for(int i=0;i<decorimage.Length;i++)
            {
                //if(treeimage[i]==-1 && rockimage[i]==-1 && wallimage[i]==-1)
                //{
                    if(Functions.rand(0,1000)<5 && decorframes>0)
                    {
                        decorimage[i] = Functions.rand(0,1000) % decorframes;
                        if(decorimage[i]<-1) //15mar2021 bugfix
                        {
                            decorimage[i] = -1;
                        }
                    }
                //}
            }
            if(Map.odecorframes>0) //15mar2021
            {
                Map.decorframes = Map.odecorframes;
            }
        }
        //end----------------//2mar2021

///////////////////Method Definition///////////////
        public static void generate(Game game)
        {
            //not used
            int q = 0;
            flightmap = new int[MAXX*MAXY*FLIGHTLEVELS];//4may2021
            for(int f=0;f<flightmap.Length;f++) //2sep2021
            {
                flightmap[f] = -1;
            }
            flightlist = new int[0];//4may2021
            unitmap = new int[MAXX*MAXY];
            tilefog = new int[MAXX*MAXY];
            pathmap = new int[MAXX*MAXY];
            tileimage = new int[MAXX*MAXY];
            firecell = new int[MAXX*MAXY];
            for(int i=0;i<tileimage.Length;i++)
            {
                tileimage[i] = Functions.rand(0,1000) % tileframes;
                if(Functions.rand(0,100)<80)
                {
                    tileimage[i] = 0;
                }
//                tileimage[i] = (((i % MAXX) % 8) + 8 * (((i - (i % MAXX))/MAXX) % 6)) % tileframes ;
                
            }
            for(int xx=0;xx<MAXX;xx++)
            {
                for(int yy=0;yy<MAXY;yy++)
                {
                    if(Functions.rand(0,1000)<25 || (game.skirmish==true && Functions.rand(0,1000)<150))
                    {
                        addbones(xx * GRIDW, yy * GRIDH);
                    }
                }
            }
            treeimage = new int[MAXX*MAXY];
            rockimage = new int[MAXX*MAXY];
            wallimage = new int[MAXX*MAXY];
            decorimage = new int[MAXX*MAXY]; //2mar2021
            for(int i=0;i<treeimage.Length;i++)
            {
                treeimage[i] = -1;
                firecell[i] = -1;
                rockimage[i] = -1;
                wallimage[i] = -1;
                decorimage[i] = -1; //2mar2021
            }
            int walls = (int)Functions.rand(-10,40);
            if(walls>0)
            {
                for(int wall=0;wall<walls;wall++)
                {
                    int wallx = (int)Functions.rand(10,90);
                    int wally = (int)Functions.rand(10,90);
                    int walldx = (int)Functions.rand(-1,1);
                    int walldy = (int)Functions.rand(-1,1);
                    if(walldx!=0)
                    {
                        walldy=0;
                    }
                    if(walldx==0 && walldy==0)
                    {
                        walldx=1;
                    }
                    int walll = (int)Functions.rand(3,8);
                    for(int l=0;l<walll;l++)
                    {
                        int wx = wallx + walldx * l;
                        int wy = wally + walldy * l;
                        if(wx>=0 && wy>=0 && wx<Map.MAXX && wy<Map.MAXY)
                        {
                            wallimage[wx + wy * Map.MAXX] = 0;
                        }
                    }
                }
            }
            for(int i=0;i<treeimage.Length;i++)
            {
                if(Functions.rand(0,100)<8)
                {
                    treeimage[i] = Functions.rand(0,1000) % treeframes;
                }
                if(Functions.rand(0,100)>80)
                {
                    treeimage[i] = -1;
                }
                if(treeimage[i]!=-1)
                {
                    q = Functions.rand(-150,30);
                    for(int j=0;j<q;j++)
                    {
                        int x = i % MAXX;
                        int y = (i - x) / MAXX;
                        int nx = x + Functions.rand(-4,4);
                        int ny = y + Functions.rand(-4,4);
                        int k = nx + ny * MAXX;
                        if(k>=0 && k<treeimage.Length)
                        {
                            treeimage[k] = Functions.rand(0,1000) % treeframes;
                        }
                    }
                }
                if(i % 5==1 || i % 5 == 3)
                {
                    if(Functions.rand(0,100)<50)
                    {
                        treeimage[i] = -1;
                    }
                }
                if(treeimage[i]!=-1)
                {
                    if(Functions.rand(0,100)<7)
                    {
                        rockimage[i] = Functions.rand(0,1000) % rockframes;
                    }
                }
            }
            q = Functions.rand(10,100);
            for(int j=0;j<q;j++)
            {
                int x = Functions.rand(0,MAXX);
                int y = Functions.rand(0,MAXY);
                int w = Functions.rand(4,12);
                int h = Functions.rand(4,12);
                for(int xx=x;xx<=x+w;xx++)
                {
                    for(int yy=y;yy<=y+h;yy++)
                    {
                        int i = xx + yy * MAXX;
                        if(i>=0 && i<treeimage.Length)
                        {
                            treeimage[i] = -1;
                        }
                    }
                }
            }
            //start--------------//2mar2021
            for(int i=0;i<treeimage.Length;i++)
            {
                if(treeimage[i]==-1 && rockimage[i]==-1 && wallimage[i]==-1)
                {
                    if(Functions.rand(0,100)<5 && decorframes>0)
                    {
                        decorimage[i] = Functions.rand(0,1000) % decorframes;
                    }
                }
            }
            //end----------------//2mar2021
            int treex = -1;
            int treey = -1;
            for(int i=0;i<unitmap.Length;i++)
            {
                unitmap[i] = -1;
                tilefog[i] = 0;//15sep2021
                treex = i % MAXX;
                treey = (i - treex) / MAXX;
                if(treex % 3<2 && treey % 3<2)
                {
                    treeimage[i] = -1;
                }
                if(treex % 2==1 && treey % 2==1)
                {
                    treeimage[i] = -1;
                }
            }
            if(game.playingtutorial)
            {
                for(int i=0;i<unitmap.Length;i++)
                {
                    treex = i % MAXX;
                    treey = (i - treex) / MAXX;
                    if(treex % 10<7 || treey % 10<7)
                    {
                        treeimage[i] = -1;
                    }
                }
            }
            //
            unitcollisionmap = new int[MAXX*MAXY];
            for(int i=0;i<unitcollisionmap.Length;i++)
            {
                unitcollisionmap[i] = -1;
            }
            for(int i=0;i<pathmap.Length;i++)
            {
                pathmap[i] = -1;
            }
        }        

///////////////////Method Definition///////////////
        public static bool isonfire(int x,int y)
        {
            //checks whether the ground here is burning
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return false;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return false;
            }
            if(firecell[i]>0)
            {
                return true;
            }
            return false;
        }

///////////////////Method Definition///////////////
        public static void spreadfire(int x,int y,int time)
        {
            //attempt to spread a fire around the map that is burning
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return ;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return;
            }
            if(firecell[i]<=0)
            {
                firecell[i] = time;
            }
        }

///////////////////Method Definition///////////////
        public static void setonfire(int x, int y,bool permanent)
        {
            //set the ground on fire here
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return;
            }
            firecell[i] = Map.FIRETIME;
            if(permanent)
            {
                firecell[i] = Map.FIRETIME * 100000;
            }
        }

///////////////////Method Definition///////////////
        public static void pushmap(int x,int y,int dirn)
        {
            //not used
            pushmapdepth(x / GRIDW,y / GRIDH,4 * dirn,0);
            int radius = 20;
            x/=GRIDW;
            y/=GRIDH;
            for(int gx = x - radius;gx<=x + radius;gx++)
            {
                for(int gy = y - radius;gy<= y + radius;gy++)
                {
                    if((gx-x)*(gx-x)+(gy-y)*(gy-y)>radius*radius)
                    {
                        continue;
                    }
                    float hh = (float)dirn;
                    float factor = (float)((gx-x)*(gx-x)+(gy-y)*(gy-y))/(float)(radius*radius);
                    hh *= (1f-factor);
                    if(Functions.sign(hh)!=Functions.sign(dirn))
                    {
                        continue;
                    }
                    pushmapdepth(gx,gy,(int)hh,0);
                }
            }
        }

///////////////////Method Definition///////////////
        public static void pushmapdepth(int gx, int gy,int dirn,int depth)
        {
            //not used
            if(depth > 2)
            {
                return;
            }
            if(gx<0 || gy<0 || gx>=MAXX || gy>=MAXY)
            {
                return;
            }
            heightmap[gx + gy * MAXX]+=dirn;
        }

///////////////////Method Definition///////////////
        public static int heightdiff2(int curh,int nx,int ny)
        {
            //not used
            int gsx = nx / GRIDW;
            int gsy = ny / GRIDH;
            if(gsx<0 || gsy<0 || gsx>=MAXX || gsy>=MAXY)
            {
                return 0;
            }
            int si = gsx + gsy * MAXX;
            if(si<0 || si >= heightmap.Length)
            {
                return 0;
            }
            return (int)Functions.abs(heightmap[si] - curh);
        }

///////////////////Method Definition///////////////
        public static int getheight(int x,int y)
        {
            //not used
            int gsx = x / GRIDW;
            int gsy = y / GRIDH;
            if(gsx<0 || gsy<0 || gsx>=MAXX || gsy>=MAXY)
            {
                return 0;
            }
            int si = gsx + gsy * MAXX;
            if(si<0 || si >= heightmap.Length)
            {
                return 0;
            }
            return heightmap[si];
        }

///////////////////Method Definition///////////////
        public static int heightdiff(int sx,int sy, int fx, int fy)
        {
            //not used
            //an absolute value.....
            int gsx = sx / GRIDW;
            int gsy = sy / GRIDH;
            int gfx = fx / GRIDW;
            int gfy = fy / GRIDH;
            if(gsx<0 || gsy<0 || gsx>=MAXX || gsy>=MAXY || gfx<0 || gfy<0 || gfx>=MAXX || gfy>=MAXY)
            {
                return 0;
            }
            int si = gsx + gsy * MAXX;
            int fi = gfx + gfy * MAXX;
            if(si<0 || fi<0 || si >= heightmap.Length || fi>=heightmap.Length)
            {
                return 0;
            }
            return (int)Functions.abs(heightmap[si] - heightmap[fi]);
        }

///////////////////Method Definition///////////////
        public static bool passable(int x,int y)
        {
            //determine if the position on the map is walkable
            int gx = x / GRIDW;//21apr2021
            int gy = y / GRIDH; //21apr2021
            if(gx<0 || gy<0 || gx >= MAXX || gy>= MAXY)
            {
                return false;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return false;
            }
            if(treeimage[i]!=-1)
            {
                return false;
            }
            if(i>0) //21apr2021
            {
                if(treeimage[i-1]!=-1)
                {
                    return false;
                }
            }
            if((i % MAXX) < MAXX - 1) //21apr2021
            {
                if(treeimage[i+1]!=-1)
                {
                    return false;
                }
            }
            if(rockimage[i]!=-1)
            {
                return false;
            }
            if(wallimage[i]!=-1)
            {
                return false;
            }
            if(gx>0)
            {
                if(wallimage[i-1]!=-1)
                {
                    return false;
                }
            }
            if(gx<MAXX-1)
            {
                if(wallimage[i+1]!=-1)
                {
                    return false;
                }
            }
            //until we start putting obstacles in....
            return true;
        }

///////////////////Method Definition///////////////
        public static bool nearobstacle(int x,int y)
        {
            //determine if the position on the map is near an obstacle
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return false;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return false;
            }
            for(int gxx=gx-2;gxx<=gx+2;gxx++)
            {
                for(int gyy=gy-2;gyy<=gy+2;gyy++)
                {
                    if(gxx>=0 && gyy>=0 && gxx<Map.MAXX && gyy<Map.MAXY)
                    {
                        i = gxx + gyy * MAXX;
                        if(treeimage[i]!=-1)
                        {
                            return true;
                        }
                        if(rockimage[i]!=-1)
                        {
                            return true;                            
                        }
                        if(wallimage[i]!=-1)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

///////////////////Method Definition///////////////
        public static void planttree(int x,int y)//28mar2021
        {
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return;
            }
            if(cellunit(x,y)!=-1)
            {
                return;
            }
            int tmptreeframes = treeframes;
            if(missiontreeframes!=treeframes && missiontreeframes>0)
            {
                tmptreeframes = missiontreeframes;
            }
            if(tmptreeframes<=0)
            {
                return;
            }
            treeimage[i] = (int)Functions.abs(Functions.rand(0,1000)) % tmptreeframes;
            Array.Resize(ref Game.newtrees,Game.newtrees.Length + 1);//24apr2021
            Game.newtrees[Game.newtrees.Length -1] = i + 1;//treeimage[i] + 1;//24apr2021 //1 based index not 0 based index
        }
        
///////////////////Method Definition///////////////
        public static bool isfogged(int x,int y)
        {
            //check if the region is covered in fog
            int fogx = (int)((float)x / (float)Map.FOGW);
            int fogy = (int)((float)y / (float)Map.FOGH);
            int f = fogx + fogy * Map.FOGMAXX;
            if(f>=0 && f<Map.fog.Length)
            {
                return Map.fog[f];
            }
            return true;
        }

///////////////////Method Definition///////////////
        public static void fogclear(Game game,int id)
        {
            //clear fog from the map here
            //if(game.units[id].faction==Game.PLAYERFACTION) //26Feb2021
            if(game.units[id].faction==Game.PLAYERFACTION || (Game.neutralfog==1 && game.units[id].faction==Unit.NULLFACTION) || Game.neutralfog==-1) //26Feb2021
            {
                int fogx = (int)((float)game.units[id].x / (float)Map.FOGW);
                int fogy = (int)((float)game.units[id].y / (float)Map.FOGH);
                for(int xx=fogx-1;xx<=fogx+2;xx++)
                {
                    for(int yy=fogy-1;yy<=fogy+2;yy++)
                    {
                        int f = xx + yy * Map.FOGMAXX;        
                        if(f>=0 && f<Map.fog.Length)
                        {
                            Map.fog[f] = false;
                            Map.fogalpha[f]+= Map.FOGADD;
                            if(Map.fogalpha[f]<-10)
                            {
                                Map.fogalpha[f]=-10;
                            }
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void fogdraw(Game game)
        {
            //draw fog on the map
            if(Game.fogoff==1) //26Feb2021
            {//26Feb2021
                return;//26Feb2021
            }//26Feb2021
            for(int i=0;i<Map.fog.Length;i++)
            {
                int fogx = ((i % Map.FOGMAXX) * Map.FOGW) - Game.CORNERX;
                int fogy = Map.FOGH * (((i - (i % Map.FOGMAXX)) / Map.FOGMAXX)) - Game.CORNERY;
                if(Map.fogalpha[i]<-10)
                {
                    Map.fogalpha[i] = -10f;
                }
                Map.fogalpha[i]+= 10f / (float)(60 * 10);
                if(Map.fogalpha[i]>1)
                {
                    Map.fogalpha[i] = 1;
                }
                float alpha = Map.fogalpha[i];
                if(alpha<0)
                {
                    alpha = 0;
                }
                if(alpha>1)
                {
                    alpha = 1;
                }
                //if(fogx>-150 && fogy>-150 && fogx<Game.RESOLUTIONX+150 && fogy<Game.RESOLUTIONY+150)//28feb2022
                if(fogx>-150 && fogy>-150 && fogx<Game.RESOLUTIONX+150 && fogy<Game.RESOLUTIONY+150 && Config.options_fog>0)//28feb2022
                {
                    if(alpha==1)
                    {
                        //RenderList.drawimage(game,game.images[Resources.FOG].texture,fogx,fogy,0,1.1f,1.1f,0,0,false,alpha,Resources.FOG);    //18sep2021
                        RenderList.drawimage(game,game.images[Resources.FOG].texture,fogx,fogy,0,Map.FOGSCALE*1.1f,Map.FOGSCALE*1.1f,0,0,false,alpha,Resources.FOG);    
                    }
                    else
                    {
                        if(alpha>0)
                        {
                            //RenderList.drawimage(game,game.images[Resources.FOG].texture,fogx,fogy,0,1,1,0,0,false,alpha,Resources.FOG);    //18sep2021
                            RenderList.drawimage(game,game.images[Resources.FOG].texture,fogx,fogy,0,Map.FOGSCALE,Map.FOGSCALE,0,0,false,alpha,Resources.FOG);    
                        }
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void drawminimap(Game game,int sx,int sy, int fx,int fy)
        {
            //not used
            for(int y=0;y<MAXY;y++)
            {
                for(int x=0;x<MAXX;x++)
                {
                    int i = x + y * MAXX;
                    int screenx = sx + (fx - sx) * x / MAXX;
                    int screeny = sy + (fy - sy) * y / MAXY;
                    float scalex = 1.1f*(float)(fx - sx) / (float)(MAXX * GRIDW);
                    float scaley = 1.1f*(float)(fy - sy) / (float)(MAXY * GRIDH);
                    if(i>=0 && i<tileimage.Length)
                    {
                        if(tileimage[i]!=-1)
                        {
                            RenderList.drawimage(game,game.images[tilecat].texture,screenx,screeny,0,scalex,scaley,tileimage[i],0,false,1f,tilecat);    
                        }
                        if(rockimage[i]!=-1)
                        {
                            RenderList.drawimage(game,game.images[rockcat].texture,screenx,screeny+(int)((float)Map.rockoffsety*scaley),0,scalex,scaley,rockimage[i],0,false,1f,rockcat);    
                        }
                        if(wallimage[i]!=-1)
                        {
                            RenderList.drawimage(game,game.images[wallcat].texture,screenx,screeny+(int)((float)Map.walloffsety*scaley),0,scalex,scaley,wallimage[i],0,false,1f,wallcat);    
                        }
                        if(treeimage[i]!=-1)
                        {
                            RenderList.drawimage(game,game.images[treecat].texture,screenx,screeny+(int)((float)Map.treeoffsety*scaley),0,scalex,scaley,treeimage[i],0,false,1f,treecat);    
                        }        
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void draw(Game game,int x,int y,int layer)
        {
            //4may2021 added flyers.......
            //main map drawing routine
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return ;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=tileimage.Length)
            {
                return;
            }
            //26oct2020 start
            int tmptilecat = tilecat;
            int tmptreecat = treecat;
            int tmprockcat = rockcat;
            int tmpwallcat = wallcat;
            int tmpdecorcat = decorcat; //2mar2021
            int tmptreeoffsety = treeoffsety;
            int tmprockoffsety = rockoffsety;
            int tmpwalloffsety = walloffsety;
            int tmpdecoroffsety = decoroffsety; //2mar2021
            issnow = false;
            isdesert = false;
            isrgbbk = false; //1nov2020
            //if(game.missions!=null) //&& game.skirmish==false)//22mar2021
            //if(game.missions!=null && Game.EDITOR==false) //22mar2021
            if(game.missions!=null && (Game.EDITOR==false || (Game.EDITOR==true && game.demomode==false))) //14apr2021
            {
                if(game.missionid>=0 && game.missionid<game.missions.Length)
                {
                    if(game.missions[game.missionid].demo==0 || Game.EDITOR==false)//19apr2021
                    {
                        if(game.missions[game.missionid].tilecat!=-1)
                        {
                            tmptilecat = game.missions[game.missionid].tilecat;
                            issnow = game.missions[game.missionid].issnow;
                            isdesert = game.missions[game.missionid].isdesert;
                        }
                        if(game.missions[game.missionid].treecat!=-1)
                        {
                            tmptreecat = game.missions[game.missionid].treecat;
                            tmptreeoffsety = game.missions[game.missionid].treeoffsety;
                        }
                        if(game.missions[game.missionid].wallcat!=-1)
                        {
                            tmpwallcat = game.missions[game.missionid].wallcat;
                            tmpwalloffsety = game.missions[game.missionid].walloffsety;
                        }
                        if(game.missions[game.missionid].rockcat!=-1)
                        {
                            tmprockcat = game.missions[game.missionid].rockcat;
                            tmprockoffsety = game.missions[game.missionid].rockoffsety;
                        }
                        //start--------------//2mar2021
                        if(game.missions[game.missionid].decorcat!=-1)
                        {
                            tmpdecorcat = game.missions[game.missionid].decorcat;
                            tmpdecoroffsety = game.missions[game.missionid].decoroffsety;
                        }
                        //end----------------//2mar2021
                        if(game.missions[game.missionid].overridergbbk)//1nov2020
                        {
                            isrgbbk_r = game.missions[game.missionid].overridergbbk_r;
                            isrgbbk_g = game.missions[game.missionid].overridergbbk_g;
                            isrgbbk_b = game.missions[game.missionid].overridergbbk_b;
                            isrgbbk = true;//14apr2021
                        }
                    }//19apr2021
                }
            }
            //26oct2020 end
            //start------------//18sep2021
            if(layer==Map.DECOR)//decor
            {
                if(decorimage[i]!=-1)
                {
                    RenderList.drawimage(game,game.images[tmpdecorcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY + tmpdecoroffsety,0,1f,1f,decorimage[i],0,false,1f,tmpdecorcat);    
                }
            }
            //end--------------//18sep2021
            if(layer==0)
            {
                if(i < tileimage.Length - MAXX)
                {
                    if(heightmap[i]<heightmap[i + MAXX])
                    {
                        //eventually use an image.....
                        //for now use a grey rect.....
                        RenderList.drawrect(game,x - Game.CORNERX - 1,heightmap[i] + y - Game.CORNERY + GRIDH/2 - 1,GRIDW + 2,2 + (int)Functions.abs(heightmap[i] - heightmap[i + MAXX]),RenderList.getrgb(32,32,32),0);
                    }
                }
                if(tileimage[i]!=-1)
                {
                    //26oct2020
                    //RenderList.drawimage(game,game.images[tilecat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY,0,1f,1f,tileimage[i],0,false,1f,tilecat);    
                    RenderList.drawimage(game,game.images[tmptilecat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY,0,1f,1f,tileimage[i],0,false,1f,tmptilecat);    
                }
                //start--------------//2mar2021
                //18sep2021 moved this to elsewhere.....
                //if(decorimage[i]!=-1)
                //{
                //    RenderList.drawimage(game,game.images[tmpdecorcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY + tmpdecoroffsety,0,1f,1f,decorimage[i],0,false,1f,tmpdecorcat);    
                //}
                //18sep2021 moved above elsewhere
                //end----------------//2mar2021
                if(Game.EDITOR)
                {
                    if(TriggerHelper.iflocation[3]!=-1)
                    {
                        if(gx>=TriggerHelper.iflocation[0] && gy>=TriggerHelper.iflocation[1] && gx<=TriggerHelper.iflocation[2] && gy<=TriggerHelper.iflocation[3])
                        {
                            RenderList.drawunfilledrect(game,gx * Map.GRIDW - Game.CORNERX,heightmap[i] + gy * Map.GRIDH - Game.CORNERY,Map.GRIDW,Map.GRIDH,RenderList.getrgb(32,255,255),0);
                        }
                    }
                    if(TriggerHelper.atlocation[3]!=-1)
                    {
                        if(gx>=TriggerHelper.atlocation[0] && gy>=TriggerHelper.atlocation[1] && gx<=TriggerHelper.atlocation[2] && gy<=TriggerHelper.atlocation[3])
                        {
                            RenderList.drawunfilledrect(game,gx * Map.GRIDW - Game.CORNERX,heightmap[i] + gy * Map.GRIDH - Game.CORNERY,Map.GRIDW,Map.GRIDH,RenderList.getrgb(32,255,32),0);
                        }
                    }
                    if(TriggerHelper.constructorindex>=8)
                    {
                        if(TriggerHelper.field8index==9)
                        {
                            if(TriggerHelper.atlocation[0]!=-1 && TriggerHelper.atlocation[1]!=-1)
                            {
                                if(gx==TriggerHelper.atlocation[0] && gy==TriggerHelper.atlocation[1])
                                {
                                    RenderList.drawrect(game,gx * Map.GRIDW - Game.CORNERX,heightmap[i] + gy * Map.GRIDH - Game.CORNERY,Map.GRIDW,Map.GRIDH,RenderList.getrgb(32,255,32),0);
                                }
                            }                        
                        }
                    }
                }
                if(rockimage[i]!=-1)
                {
                    //26oct2020
                    //RenderList.drawimage(game,game.images[rockcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+Map.rockoffsety,0,1f,1f,rockimage[i],0,false,1f,rockcat);    
                    RenderList.drawimage(game,game.images[tmprockcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+tmprockoffsety,0,1f,1f,rockimage[i],0,false,1f,tmprockcat);    
                }
                //start-----------//15sep2021
                if(Game.shadowleft!=-1 && Game.shadowright!=-1 && Map.indoor>0)//24sep2021
                {
                    if(wallimage[i]==-1)
                    {
                        if(i<wallimage.Length - MAXX)
                        {
                            if(wallimage[i + 1]!=-1)
                            {
                                RenderList.drawimage(game,game.images[Game.shadowright].texture,Game.shadowoffx + x-Game.CORNERX,heightmap[i] + y-Game.CORNERY,0,1f,1f,0,0,false,1f,Game.shadowright);    
                            }
                        }
                        if(i>0)
                        {
                            if(wallimage[i - 1]!=-1)
                            {
                                RenderList.drawimage(game,game.images[Game.shadowleft].texture,x-Game.CORNERX-Game.shadowoffx,heightmap[i] + y-Game.CORNERY,0,1f,1f,0,0,false,1f,Game.shadowleft);    
                            }
                        }
                    }
                }
                //end----------//15sep2021
                if(firecell[i]>0)
                {
                    //RenderList.drawimage(game,game.images[firecat].texture,x-Game.CORNERX,y-Game.CORNERY,0,1.5f,1.5f,((game.frame + i) / 4) % fireframes,0,false,1f,firecat);    
                    if(Config.OPTIMISEFIRES>0 && wallimage[i]!=-1)//15sep2021
                    {
                        //do nothing
                    }
                    else//15sep2021
                    {
                        Map.drawfires(game,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY,Map.GRIDW/2,Map.GRIDH/2);
                    }
                    if(!game.paused && !game.demomode)
                    {
                        firecell[i]--;
                        bool spread = false;
                        if((game.frame % 60)==0 && firecell[i]>0 && game.demomode==false && firecell[i]<=Map.FIRETIME)
                        {    
                            for(int gxx=gx-1;gxx<=gx+1;gxx++)
                            {
                                for(int gyy=gy-1;gyy<=gy+1;gyy++)
                                {
                                    if(gxx>=0 && gyy>=0 && gxx<MAXX && gyy<MAXY)
                                    {
                                        if(firecell[gxx + gyy * MAXX]<=0)
                                        {
                                            if(Functions.rand(0,100)<10)
                                            {
                                                Map.spreadfire(gxx * GRIDW,gyy * GRIDH,3 * firecell[i] / 4);
                                                spread = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                                if(spread)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if(layer==1)
            {
                if(wallimage[i]!=-1)
                {
                    //26oct2020
                    //RenderList.drawimage(game,game.images[wallcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+Map.walloffsety,0,1f,1f,wallimage[i],0,false,1f,wallcat);    
                    RenderList.drawimage(game,game.images[tmpwallcat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+tmpwalloffsety,0,1f,1f,wallimage[i],0,false,1f,tmpwallcat);    
                }
                if(treeimage[i]!=-1)
                {
                    //26oct2020
                    //RenderList.drawimage(game,game.images[treecat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+Map.treeoffsety,0,1f,1f,treeimage[i],0,false,1f,treecat);    
                    RenderList.drawimage(game,game.images[tmptreecat].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+tmptreeoffsety,0,1f,1f,treeimage[i],0,false,1f,tmptreecat);    
                }
                //start------------------//15sep2021
                if(Game.shadowup!=-1 && Map.indoor>0)//24sep2021
                {
                    if(wallimage[i]!=-1)
                    {
                        if(i<wallimage.Length - MAXX)
                        {
                            if(wallimage[i+MAXX]==-1)
                            {
                                //above us is a wall, below is ground.....
                                RenderList.drawimage(game,game.images[Game.shadowup].texture,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+Game.shadowoffy,0,1f,1f,0,0,false,1f,Game.shadowup);    
                            }
                            //if(wallimage[i + 1]==-1)
                            //{
//                                RenderList.drawimage(game,game.images[Game.shadowright].texture+Game.shadowoffx,x-Game.CORNERX,heightmap[i] + y-Game.CORNERY+Game.shadowoffy,0,1f,1f,0,0,false,1f,Game.shadowright);    
                            //}
                        }
                        //if(i>0)
                        //{
                            //if(wallimage[i - 1]==-1)
                            //{
//                                RenderList.drawimage(game,game.images[Game.shadowleft].texture,x-Game.CORNERX-Game.shadowoffx,heightmap[i] + y-Game.CORNERY+Game.shadowoffy,0,1f,1f,0,0,false,1f,Game.shadowleft);    
                            //}
                        //}
                    }
                }
                //end--------------------//15sep2021
            }
        }

///////////////////Method Definition///////////////
        public static void precalc(Game game)
        {
            if(Config.BLOCKPRECALC)//11apr2021
            {
                return;
            }
            Map.precalcframestart++;
            //there are 100 cells by 100 cells....
            //and we need to check for each one 100 cells by 100 cells.....
            //that will take a long time......
            //it is in fact....10,000 x 10,000
            //however we can reduce this considerably.....
            //what we can do is look only around regions that
            //are "near" our player units as a starting point...
            //that reduces to approximately 100-200 checks....versus how any positions?
            //well...we can only check positions that are near opposing units
            //so a lot of the map will go unchecked...which is fine...
            //do it for one unit at a time.....
            //against one other unit at a time.....
            //so in reality...it is perhaps 200 checks versus 200 checks...
            //now if we do 1 check per frame then that will surely take a long time....
            //at worst it will take 40,000 frames which at 60pfs is about 700 seconds...or 10 minutes
            //but if we change it to do like this:
            //1 unit per frame versus the first unit in position more than MAXDEPTH away from us
            //which has not already had a checked position.....
            //then it might work.....
            int i = ((Map.precalcframestart - Map.precalcframestart % Unit.MAXUNITS) / Unit.MAXUNITS) % Unit.MAXUNITS;
            if(Map.precalcframestart % Unit.MAXUNITS!=0)
            {
                if(Config.sumu>1000)
                {
                    return;
                }
            }
            Game.TMPCORNERX = Game.CORNERX;//2may2021
            Game.TMPCORNERY = Game.CORNERY;//2may2021'
            if(Replay.IsPlaying())//2may2021
            {
                Game.CORNERX = Game.RCORNERX;//2may2021
                Game.CORNERY = Game.RCORNERY;//2may2021
            }
            if(game.units[i].hp>0)
            {
                int sx = 0;
                int sy = 0;
                int fx = 0;
                int fy = 0;
                if(Config.sumu<Config.UTIMELOW)
                {
                    sx = game.units[i].x / Map.GRIDW;
                    sy = game.units[i].y / Map.GRIDH;
                    int x0 = Game.CORNERX / Map.GRIDW;
                    int y0 = Game.CORNERY / Map.GRIDH;
                    int x1 = (Game.CORNERX + Game.RESOLUTIONX) / Map.GRIDW;
                    int y1 = (Game.CORNERY + Game.RESOLUTIONY) / Map.GRIDH;
                    int xd = x1 - x0;
                    int yd = y1 - y0;
                    Map.precalcframestart2++;
                    fx = x0 + ((Map.precalcframestart2 % xd*yd) % xd);
                    fy = y0 + ((Map.precalcframestart2 % xd*yd) - ((Map.precalcframestart2 % xd*yd) % xd))/xd;
                    if(sx>=0 && sy>=0 && fx>=0 && fy>=0 && sx<Map.MAXX && sy<Map.MAXY && fx<Map.MAXX && fy<Map.MAXY)
                    {
                        if(Map.precalcedpaths[sx,sy,fx,fy]==Map.NOTCHECKED)
                        {
                            //set parameters
                            Map.ignoreunits = true;
                            int oMAXDEPTH = Unit.MAXDEPTH;
                            Unit.MAXDEPTH = 2 * oMAXDEPTH;//(Map.MAXX + Map.MAXY);
                            Map.precalcedpaths[sx,sy,fx,fy] = Unit.seekpath(sx,sy,fx,fy,0,0,0);
                            //restore parameters
                            Unit.MAXDEPTH = oMAXDEPTH;
                            Map.ignoreunits = false;
                        }                            
                    }
                }
                for(int j=0;j<Unit.MAXUNITS;j++)
                {
                    if(i!=j)
                    {
                        if(game.units[j].hp>0)
                        {
                            int dist = (int)(Functions.abs(game.units[i].x-game.units[j].x)+Functions.abs(game.units[i].y - game.units[j].y));
                            if(dist > Unit.MAXDEPTH*Map.GRIDW)
                            {
                                sx = game.units[i].x / Map.GRIDW;
                                sy = game.units[i].y / Map.GRIDH;
                                fx = game.units[j].x / Map.GRIDW;
                                fy = game.units[j].y / Map.GRIDH;
                                if(sx>=0 && sy>=0 && fx>=0 && fy>=0 && sx<Map.MAXX && sy<Map.MAXY && fx<Map.MAXX && fy<Map.MAXY)
                                {
                                    if(Map.precalcedpaths[sx,sy,fx,fy]==Map.NOTCHECKED)
                                    {
                                        //set parameters
                                        Map.ignoreunits = true;
                                        int oMAXDEPTH = Unit.MAXDEPTH;
                                        Unit.MAXDEPTH = 2 * dist / Map.GRIDW;//(Map.MAXX + Map.MAXY);
                                        Map.precalcedpaths[sx,sy,fx,fy] = Unit.seekpath(sx,sy,fx,fy,0,0,0);
                                        //restore parameters
                                        Unit.MAXDEPTH = oMAXDEPTH;
                                        Map.ignoreunits = false;
                                        break;
                                    }                            
                                }
                            }
                        }
                    }
                }
            }
            Game.CORNERX = Game.TMPCORNERX;//2may2021
            Game.CORNERY = Game.TMPCORNERY;//2may2021
            
        }

///////////////////Method Definition///////////////
        public static void updatepos(ref Game game)
        {
            bool onscreen = false;
            game.onscreen = false;
            //Stopwatch utimer = new Stopwatch();
            //utimer.Start();
            //long time = utimer.ElapsedMilliseconds;
            if(Config.RUNNINGSPEED<90)
            {
                precalc(game);
            }
            //time = Math.Abs(utimer.ElapsedMilliseconds - time);
            //if(time > Config.maxmapupdatepostime)
            //{
            //    Config.maxmapupdatepostime = time;
            //}
            //utimer.Reset();
            for(int i=0;i<Map.fog.Length;i++)
            {
                Map.fog[i] = true;
                if(Game.EDITOR)
                {
                    Map.fog[i] = false;
                    Map.fogalpha[i] = 0f;
                }
            }
            //for(int i=0;i<game.units.Length;i++)//26mar2021
            for(int i=0;i<=Unit.MAXINDEX;i++)//26mar2021
            {
                if(game.units[i].faction==Game.PLAYERFACTION && game.units[i].hp>0)
                {
                    if(game.units[i].x>Game.CORNERX && game.units[i].y>Game.CORNERY && game.units[i].x<Game.CORNERX+Game.RESOLUTIONX && game.units[i].y<Game.CORNERY+Game.RESOLUTIONY)
                    {
                        onscreen = true;
                        game.onscreen = true;
                        //break;
                    }
                }
                Map.fogclear(game,i);
            }
            if(game.mlclick && !game.demomode && !Game.EDITOR)
            {
                if(game.frame < game.mlclickframe + 15)
                {
                    if(!onscreen)
                    {
                        //double clicked and nothing on screen.....
                        int count = 0;
                        int min = 0;
                        int corx = 0;
                        int cory = 0;
                        for(int x=0;x<Map.MAXX*Map.GRIDW;x+=Game.RESOLUTIONX/4)
                        {
                            for(int y=0;y<Map.MAXY*Map.GRIDH;y+=Game.RESOLUTIONY/4)
                            {
                                count = 0;
                                int sx = x / Map.GRIDW;
                                int sy = y / Map.GRIDH;
                                int fx = (x + Game.RESOLUTIONX) / Map.GRIDW;
                                int fy = (y + Game.RESOLUTIONY) / Map.GRIDH;
                                for(int xx=sx;xx<fx;xx++)
                                {
                                    for(int yy=sy;yy<fy;yy++)
                                    {
                                        if(Map.cellunit(xx*Map.GRIDW,yy*Map.GRIDH)!=-1)
                                        {
                                            if(game.units[Map.cellunit(xx*Map.GRIDW,yy*Map.GRIDH)].faction==Game.PLAYERFACTION)
                                            {
                                                count++;
                                                if(count>min)
                                                {
                                                    min = count;
                                                    corx = x;
                                                    cory = y;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        Game.CORNERX = corx;
                        Game.CORNERY = cory;
                    }
                }
                game.mlclickframe = game.frame;
            }
            //if(!game.paused && !game.demomode)//1mar2021
            if(!game.paused && !game.demomode && Game.LOCKCORNER==0)//1mar2021
            {
                //21apr2012 changed mx to rmx etc
                if(game.rmx<Game.CORNEREDGEDIST)
                {
                    Game.CORNERX-=(int)(Game.CORNERSPEED/game.zoom);
                }
                if(game.rmy<Game.CORNEREDGEDIST)
                {
                    Game.CORNERY-=(int)(Game.CORNERSPEED/game.zoom);
                }
                if(game.rmx>Game.RESOLUTIONX-Game.CORNEREDGEDIST)
                {
                    Game.CORNERX+=(int)(Game.CORNERSPEED/game.zoom);
                }
                if(game.rmy>Game.RESOLUTIONY-Game.CORNEREDGEDIST)
                {
                    Game.CORNERY+=(int)(Game.CORNERSPEED/game.zoom);
                }
            }
            if(Game.CORNERX<0)
            {
                Game.CORNERX = 0;
            }
            if(Game.CORNERY<0)
            {
                Game.CORNERY = 0;
            }
            if(Game.CORNERX > Map.MAXX*Map.GRIDW - Game.RESOLUTIONX)
            {
                Game.CORNERX = Map.MAXX*Map.GRIDW - Game.RESOLUTIONX;
            }
            if(Game.CORNERY > Map.MAXY*Map.GRIDH - Game.RESOLUTIONY)
            {
                Game.CORNERY = Map.MAXY*Map.GRIDH - Game.RESOLUTIONY;
            }
        }

///////////////////Method Definition///////////////
        public static bool dobonesexist(int x,int y)
        {
            //check if dead men's bones exist on the map to be raised as skeletons or other summoned creatures
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            int i = -1;
            if(gx>=0 && gy>=0 && gx<MAXX && gy<MAXY)
            {
                i = gx + gy * MAXX;
                for(int j=0;j<deadcell.Length;j++)
                {
                    if(tileimage[i]==deadcell[j] && deadcell[j]!=-1)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

///////////////////Method Definition///////////////
        public static void removebones(int x, int y)
        {
            //remove bones is used when we summon creatures, so that they raise from the grave effectively...a resource of sorts
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            int i = -1;
            if(gx>=0 && gy>=0 && gx<MAXX && gy<MAXY)
            {
                i = gx + gy * MAXX;
                tileimage[i] = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void addbones(int x, int y)
        {
            //add bones to the ground when a unit dies
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            int i = -1;
            if(gx>=0 && gy>=0 && gx<MAXX && gy<MAXY)
            {
                i = gx + gy * MAXX;
                int count = 0;
                for(int j=0;j<deadcell.Length;j++)
                {
                    if(deadcell[j]!=-1)
                    {
                        count++;
                    }
                }
                if(count>0)
                {
                    count = 1 + ((int)Functions.rand(0,1000) % count);
                    for(int j=0;j<deadcell.Length;j++)
                    {
                        if(deadcell[j]!=-1)
                        {
                            count--;
                            if(count<=0)
                            {
                                tileimage[i] = deadcell[j];
                                return;
                            }
                        }
                    }                    
                }
            }
        }

///////////////////Method Definition///////////////
        public static bool removeunit(int id,int x,int y)
        {
            //remove a unit from the map array
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return false;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return false;
            }
            if(unitmap[i]!=id)
            {
                return false;
            }
            unitmap[i] = -1;
            return true;
        }

///////////////////Method Definition///////////////
        public static bool insertunit(int id,int x, int y)
        {
            //insert a unit into the map array
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return false;
            }
            int i = gx + gy * MAXX;
            if(i<0 || i>=unitmap.Length)
            {
                return false;
            }
            if(unitmap[i]!=-1)
            {
                return false;
            }
            unitmap[i] = id;
            return true;
        }
        //start-------------//7mar2021

///////////////////Method Definition///////////////
        public static bool removeflyer(int id,int x,int y,int flightlevel)//4may2021
        {
            //remove a unit from the map array
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return false;
            }
            if(flightlevel<0 || flightlevel>=FLIGHTLEVELS)
            {
                return false;
            }
            int i = (flightlevel * MAXX * MAXY) + (gy * MAXX) + (gx);//gx + gy * MAXX;
            if(i<0 || i>=flightmap.Length)
            {
                return false;
            }
            if(flightmap[i]!=id)
            {
                return false;
            }
            flightmap[i] = -1;
            return true;
        }

///////////////////Method Definition///////////////
        public static int insertflyer(int id,int x, int y)//4may2021
        {
            //insert a unit into the map array
            int flightlevel = -1;
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return -1;
            }
            for(int f=0;f<FLIGHTLEVELS;f++)
            {
                int i = gx + gy * MAXX + f * MAXX * MAXY;
                if(i<0 || i>=flightmap.Length)
                {
                    return -1;
                }
                if(flightmap[i]!=-1)
                {
                    continue;
                }
                flightmap[i] = id;
                flightlevel = f;
                break;
            }
            return flightlevel;
        }
        
///////////////////Method Definition///////////////
        public static int cellflyer(int x,int y,int flightlevel)//4may2021
        {
            //indicate the unit id at the xy position in question
            //return -1 if no unit there
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return -1;
            }
            if(flightlevel<0 || flightlevel>=FLIGHTLEVELS)
            {
                return -1;
            }
            int i = gx + gy * MAXX + flightlevel * MAXX * MAXY;
            if(i<0)
            {
                return -1;
            }
            if(i>=flightmap.Length)
            {
                return -1;
            }
            return flightmap[i];
        }
        
        
///////////////////Method Definition///////////////
        public static int countfactionneighbours(Game game,int x,int y,int faction)
        {
            //return the number of units of a specific faction adjacent to this grid cell
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            int count = 0;
            if(gx<0 || gy<0)
            {
                return -1;
            }
            int i = gx + gy * MAXX;
            if(i<0)
            {
                return -1;
            }
            if(i>=unitmap.Length)
            {
                return -1;
            }
            for(int gxx=gx-1;gxx<=gx+1;gxx++)
            {
                for(int gyy=gy-1;gyy<=gy+1;gyy++)
                {
                    int nid = cellunit(gxx * GRIDW,gyy * GRIDH);
                    if(nid!=-1)
                    {
                        if(game.units[nid].faction==faction)
                        {
                            count++;
                        }
                    }
                }
            }
            return count;
        }
        //end---------------//7mar2021

///////////////////Method Definition///////////////
        public static int cellunit(int x, int y)
        {
            //indicate the unit id at the xy position in question
            //return -1 if no unit there
            int gx = x / GRIDW;
            int gy = y / GRIDH;
            if(gx<0 || gy<0)
            {
                return -1;
            }
            int i = gx + gy * MAXX;
            if(i<0)
            {
                return -1;
            }
            if(i>=unitmap.Length)
            {
                return -1;
            }
            return unitmap[i];
        }

///////////////////Method Definition///////////////
        public static void resetpathmap()
        {
            //not used
            //for(int i=0;i<pathmap.Length;i++)
            //{
            //    pathmap[i] = Map.PATHINIT;
            //}
            //pathmap = new int[MAXX*MAXY];
            Array.Clear(pathmap,0,pathmap.Length);
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Gui
    {
        public static int TYPE_BUTTON = 1;
        public static int TYPE_PANEL = 2;
        public static int TYPE_LABEL = 3;
        public static int TYPE_IMAGE = 4;
        public static int TYPE_CODED = 5;
        public static int TYPE_MINIMAP = 6;
        public int type;
        public int missionindex;
        public string missionname;
        public int topindexzero; //24Feb2021
        public int gamestate;
        //public static string currentscreen;
        public string screenname;
        public int id;
        public int tmpimage;//30apr2021
        public int image;
        public int[] altimage;
        public int altimageindex;//11apr2021
        public string imagefile;
        public string[] altimagefile;
        public float scale;
        public int x;
        public int y;
        public int w;
        public int h;
        public bool mouseover;
        public int font;
        public int fontsize;
        public string fontfile;
        public string title;
        public string tooltip;
        //public string ID;
        //for buttons
        public string nextscreenname;
        public int nextgamestate;
        public int horizontal;//11mar2021
        public int vertical;//11mar2021
        /////////////////////////////////
        //Game Actions
        //
        public static int BACK = -1;
        public static int ACTION_NONE = -2;//23sep2021
        public static int ACTION_CHOOSEHUMAN = 1;
        public static int ACTION_CHOOSEUNDEAD = 2;
        public static int ACTION_CHOOSENEWMAP = 4;
        public static int ACTION_NEWGAME = 5;
        public static int ACTION_LARGEMINIMAP = 6;
        public static int ACTION_MINIMAPSCANLINE = 7;//16sep2021
        public static int ACTION_MISSION = 10;
        public static int ACTION_EDITOR = 123;
        public static int ACTION_EXTERNAL = 124;
        public static int ACTION_PLAY = 20;//26mar2021
        public string command;
        public static int LINK_SELECTION_TEXT = 4;
        public static int LINK_UNIT_DETAIL = 88;
        public static int LINK_PLAYER_ICONS = 3001; //9mar2021
        public static int LINK_ENEMY_ICONS = 3002; //9mar2021
        public static int LINK_SPAWNER_ICON = 3003; //10mar2021
        public static int LINK_SELECTED_ICONS = 3004;//22mar2021
        public static int LINK_TECH_ICON = 3005;//2sep2021
        //start---------------//28mar2021
        public static int ACTION_SPELL_ICONS = 3010;
        public static int ACTION_SPELL_START = 3010;
        public static int ACTION_SPELL_END = 3026;
        public bool spellactive;//12apr2021
        //end-----------------//28mar2021
        public static int ACTION_NEXT = 89;
        public static int ACTION_PREV = 87;
        public static int ACTION_CONTINUE = 1234;
        //start-------------//9mar2021
        public static int ACTION_FORMATIONSTART = 2001;
        public static int ACTION_LINEH = 2001;
        public static int ACTION_LINEV = 2002;
        public static int ACTION_OPEN = 2003;
        public static int ACTION_CLOSE = 2004;
        public static int ACTION_RALLY = 2005;
        public static int ACTION_DEFEND = 2006;
        public static int ACTION_ENGAGE = 2007;
        public static int ACTION_FORMATIONEND = 2007;
        //end---------------//9mar2021
        public static int ACTION_LANGUAGESET = 5050; //13mar2021
        public static int ACTION_REPLAY = 7777;//2apr2021
        public int action;
        public int mission;
        public static int GUILINK_VICTORY = 2;
        public static int GUILINK_DEFEAT = 3;
        public int triggerlink;
        public int triggervariable; //31dec2021
        public int triggerop;//31dec2021
        public int triggernum;//31dec2021
        public string link;
        public int index;
        public int hidden;
        public int uindex;
        public bool backgroundrect;
        public int[] backgroundrectcoords;
        public byte[] backgroundrectcolor;
        public static bool ALTMODE = false;

///////////////////Method Definition///////////////
        public Gui(Game game)
        {
            link = "";
            command = "";
            hidden = 0;
            triggerlink = 0;
            missionname = "";
            backgroundrect = false;
            backgroundrectcoords = new int[4];
            backgroundrectcolor = new byte[3];
            missionindex = -1;
            topindexzero = 0;//24Feb2021
            horizontal = 6;//11mar2021
            vertical = 0;//11mar2021
            //added these to initialise them....20sep2021
            title = "";
            screenname = "";
            imagefile = "";
            tooltip = "";
            fontfile = "";
            triggervariable = -1;//31dec2021
        }

///////////////////Method Definition///////////////
        public void reset(Game game,int i)
        {
            id = i;
            horizontal = 6;//11mar2021
            vertical = 0;//11mar2021
            mouseover = false;
            image = -1;
            tmpimage = -1;//30apr2021
            //altimage = -1;
            font = Resources.FONT;
            scale = 1f;
            altimage = new int[5];
            altimagefile = new string[5];
            altimageindex = -1;
            triggervariable = -1;//31dec2021
            for(int k=0;k<5;k++)
            {
                altimage[k] = -1;
                altimagefile[k] = "";
            }
        }

///////////////////Method Definition///////////////
        public static void matchcampaign(Game game) //28Feb2021
        {
            //if a mission is specified by name in the gui, then match it to an index number
            if(game.gui==null || game.missions==null)
            {
                return;
            }
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].missionname!="")
                {
                    for(int j=0;j<game.missions.Length;j++)
                    {
                        if(game.missions[j].name==game.gui[i].missionname)
                        {
                            game.gui[i].missionindex = j;
                            game.gui[i].topindexzero = 1;
                            break;
                        }
                    }
                    if(game.gui[i].missionindex>-1)
                    {
                        break;
                    }
                }
            }
        }
///////////////////Method Definition///////////////
        public static void updatealtimages(Game game)//30apr2021
        {
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].gamestate==game.gamestate)
                {
                    if(game.gui[i].tmpimage!=-1)
                    {
                        int k = 0;
                        for(int j=0;j<game.gui[i].altimage.Length;j++)
                        {
                            if(game.gui[i].altimage[j]!=-1)
                            {
                                k++;
                            }
                            if(game.gui[i].altimage[j]==-1)
                            {
                                break;
                            }
                        }
                        int m = ((int)Functions.abs(Functions.rand(0,1000))) % (k+1);
                        if(m==0)
                        {
                            game.gui[i].image = game.gui[i].tmpimage;
                        }
                        else
                        {
                            game.gui[i].image = game.gui[i].altimage[m - 1];
                        }
                    }
                }
            }
        }
        
///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            //update all gui stuff handling mouse interactions
            if(Functions.sign(game.mwheel)<0)
            {
                Game.topmissionindex++;
                if(Game.topmissionindex>game.missions.Length-8)
                {
                    Game.topmissionindex=game.missions.Length-8;
                }
            }
            if(Functions.sign(game.mwheel)>0)
            {
                Game.topmissionindex--;
            }
            if(Game.topmissionindex<0)
            {
                Game.topmissionindex=0;
            }
            if(game.gamestate!=Game.CAT_GAMESTATE_GAME)
            {
                game.mwheel = 0;
            }
            bool scannedunits = false;
                    //start-----------//23sep2021
        int pid = Unit.GetPlayer(game);
        int displaylimit = 0;
        int hhh = 0;
        if(pid!=-1)
        {
            displaylimit = game.units[pid].guiattackdisplaylimit;
        }
        if(displaylimit>0)
        {
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].gamestate==game.gamestate)
                {
                    if(game.gui[i].command.IndexOf("attackaction")>=0)
                    {
                        game.gui[i].hidden = 1;
                        game.gui[i].x-=game.gui[i].horizontal;
                        game.gui[i].horizontal = 0;
                    }
                }
            }
            for(int d=0;d<displaylimit;d++)
            {
                int maxgoldcost = 0;
                int targetguiid = -1;
                for(int i=0;i<game.gui.Length;i++)
                {
                    if(game.gui[i].gamestate==game.gamestate)
                    {
                        if(game.gui[i].hidden>0)
                        {
                            if(game.gui[i].command.IndexOf("attackaction")>=0)
                            {
                                int techid = Tech.GetTechIdFromAction(game, game.gui[i].action);
                                if(techid!=-1)
                                {
                                    if(Tech.GoldCost(game, techid)>maxgoldcost && Tech.IsActionPurchased(game, game.gui[i].action))
                                    {
                                        maxgoldcost = Tech.GoldCost(game, techid);
                                        targetguiid = i;
                                    }
                                }
                                if(game.gui[i].action==Gui.ACTION_NONE)
                                {
                                    game.gui[i].action = Tech.ChooseTechForEmptySlot(game);
                                }
                            }
                        }
                    }
                }
                if(targetguiid!=-1)
                {
                    game.gui[targetguiid].hidden = 0;
                    game.gui[targetguiid].horizontal = hhh * (game.gui[targetguiid].w + game.gui[targetguiid].w / 8);
                    game.gui[targetguiid].x+=game.gui[targetguiid].horizontal;
                    game.gui[targetguiid].image = Tech.GetImage(game,game.gui[targetguiid].action);
                    game.gui[targetguiid].index = Tech.GetImageIndex(game,game.gui[targetguiid].action);
                    hhh++;
                }
            }
        }
        //end-------------//23sep2021

            //start-----------//26apr2021
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].gamestate!=game.oldgamestate)
                {
                    if(game.gui[i].link=="toggleon")
                    {
                        game.gui[i].link="toggleoff";
                    }
                }
            }
            //end-------------//26apr2021
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].nextgamestate==Game.CAT_GAMESTATE_REPLAY && (Config.ALLOWREPLAY==false || Config.NOREPLAY>0))//2apr2021
                {
                    continue;
                }
                //start-------------//28mar2021
                if((game.frame % 60)==22 && game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END && game.gamestate==game.gui[i].gamestate && Game.SPELLSACTIVE==true && scannedunits==false)
                {
                    scannedunits = true;
                    bool foundu = false;
                    bool onlymagicusers = true;
                    Game.SPELLCASTERLEVEL = 99;
                    //for(int u=0;u<game.units.Length;u++)//26mar2021
                    for(int u=0;u<=Unit.MAXINDEX;u++)//26mar2021
                    {
                        //if(game.units[u].faction==Game.PLAYERFACTION && game.units[u].hp>0 && game.units[u].walkspeed>0 && game.units[u].selected!=Unit.SELECTIONNONE)//23feb2022
                        if(game.units[u].faction==Game.PLAYERFACTION && game.units[u].hp>0 && game.units[u].selected!=Unit.SELECTIONNONE)//23feb2022
                        {
                            foundu = true;
                            if(game.units[u].spellcaster<=0)
                            {
                                onlymagicusers = false;
                            }
                            else
                            {
                                //if(game.units[u].spellcaster<Game.SPELLCASTERLEVEL) //get minimum level of spell casters chosen....
                                //{
                                    //Game.SPELLCASTERLEVEL = game.units[u].spellcaster * 3;
                                    //if(Game.SPELLCASTERLEVEL>9)
                                    //{
                                    Game.SPELLCASTERLEVEL = ACTION_SPELL_END - ACTION_SPELL_START;
                                    Game.SPELLCASTERSELECTED = u;
                                    //}
                                //}
                            }
                            break;
                        }
                    }
                    if(foundu==true && Game.EDITOR==false && onlymagicusers==true)
                    {
                        //game.gui[i].hidden = 0;
                        
                    }
                    else
                    {
                        //game.gui[i].hidden = 1;
                        Game.SPELLCASTERSELECTED = -1;
                    }
                }
                //end-----------------//28mar2021
                game.gui[i].mouseover = false;
                if(game.gui[i].gamestate == game.gamestate)
                {
                    if(game.mx > game.gui[i].x && game.mx < game.gui[i].x + game.gui[i].w && game.my > game.gui[i].y && game.my < game.gui[i].y + game.gui[i].h)
                    {
                        game.gui[i].mouseover = true;
                        if(game.gui[i].triggerlink==LINK_SPAWNER_ICON && Game.SPAWNERSELECTED==false)
                        {
                            game.gui[i].mouseover = false;
                        }
                        //start------------------//2sep2021
                        if(game.gui[i].triggerlink==LINK_TECH_ICON && Tech.TECHUNITSELECTED==false)
                        {
                            game.gui[i].mouseover = false;
                        }
                        //end--------------------//2sep2021
                        if(game.gui[i].action>=ACTION_FORMATIONSTART && game.gui[i].action<=ACTION_FORMATIONEND && (Game.NONSPAWNERSELECTED==false || Game.SPAWNERSELECTED==true))
                        {
                            game.gui[i].mouseover = false;
                        }
                        if(game.gui[i].triggerlink==LINK_SELECTED_ICONS) //22mar2021
                        {
                            game.gui[i].mouseover = false;
                        }
                        if(game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END && (Game.SPELLCASTERSELECTED==-1 || game.gui[i].spellactive==false))//28mar2021
                        {
                            game.gui[i].mouseover = false;
                            game.gui[i].spellactive = false;//12apr2021
                        }
                        //if(Game.EDITOR && game.gui[i].action==Gui.BACK)//25apr2021
                        if(Game.EDITOR && game.gui[i].action==Gui.BACK && game.gui[i].link!="toggleoff")//25apr2021
                        {
                            Game.EDITMODE=Game.EDITMODE_TRIGGER;
                        }
                        //start------------//20apr2021
                        if(game.gui[i].link=="toggleoff")
                        {
                            game.gui[i].mouseover = false;
                        }
                        //end--------------//20apr2021
                        if(game.gui[i].hidden>0)//23sep2021//24sep2021
                        {
                            game.gui[i].mouseover = false;//23sep2021//24sep2021
                        }
                    }
                    //start--------------------//2apr2021
                    //if(game.exitmx > game.gui[i].x && game.exitmx < game.gui[i].x + game.gui[i].w && game.exitmy > game.gui[i].y && game.exitmy < game.gui[i].y + game.gui[i].h)
                    //{
                    //    if(game.gamestate==Game.CAT_GAMESTATE_GAME && Replay.PLAYBACK==true && game.gui[i].action==Gui.BACK && Game.EDITOR==false)
                    //    {
                    //        game.gui[i].mouseover = true;
                    //    }
                    //}
                    //end----------------------//2apr2021
                    if(game.gui[i].type==TYPE_CODED)
                    {
                        if(game.gui[i].action==ACTION_LARGEMINIMAP)
                        {
                            Map.drawminimap(game,game.gui[i].x,game.gui[i].y,game.gui[i].x + game.gui[i].w,game.gui[i].y + game.gui[i].h);
                        }
                    }
                    if(game.gui[i].missionindex>=0)
                    {
                        if(game.missions!=null)
                        {
                            //int mi = game.gui[i].missionindex + Game.topmissionindex; //24Feb2021
                            //topindexzero is equal to '1' when we are supposed to ignore topmissionindex, and zero otherwise.
                            int mi = game.gui[i].missionindex + (Game.topmissionindex * (1 - game.gui[i].topindexzero)); //24Feb2021
                            if(mi<game.missions.Length) //17mar2021
                            {
                                //game.gui[i].title = game.missions[mi].name;//21mar2021
                                game.gui[i].title = Translation.TranslateWord(game.missions[mi].name,false);//21mar2021
                                //start-------------//12mar2021
                                if(LocalStorage.getitem("mission"+mi)!="")
                                {
                                    game.gui[i].title+="("+Translation.TranslateWord("Complete",false)+")";
                                }
                                //end---------------//12mar2021
                                //if(mi>Game.maxmission && game.missions[mi].custom==false)//28Feb2021
                                if(mi>Game.maxmission && game.missions[mi].custom==false && game.missions[mi].alwaysunlocked==0)//28Feb2021
                                {
                                    game.gui[i].title = Translation.TranslateWord("LOCKED",false);
                                }
                                if(game.gui[i].title!=Translation.TranslateWord("LOCKED",false) && game.mlclick==true && game.gui[i].mouseover==true)
                                {
                                    Game.ochosenmissionindex = Game.chosenmissionindex; //17sep2021
                                    Game.chosenmissionindex = mi;
                                    Game.TopScore = 0;//1mar2022
                                    try//1mar2022
                                    {
                                        Int32.TryParse(LocalStorage.getitem("topscore_"+mi),out Game.TopScore);
                                    }
                                    catch(Exception e)
                                    {
                                        Console.WriteLine(e.Message);
                                    }
                                }
                            }
                            else //22mar2021
                            {
                                game.gui[i].title = "";
                                Game.topmissionindex--;
                                if(Game.topmissionindex<0)
                                {
                                    Game.topmissionindex = 0;
                                }
                            }
                        }
                    }
                    //start--------------------//2apr2021
                    //bool exitclick = false;//2apr2021
                    //if(game.gamestate==Game.CAT_GAMESTATE_GAME && Replay.PLAYBACK==true && game.gui[i].action==Gui.BACK && Game.EDITOR==false)//2apr2021
                    //{    
                    //    if(game.exitclick)
                    //    {
                    //        exitclick = true;
                    //    }                    
                    //}
                    if(Replay.PLAYBACK)
                    {
                        if(game.gui[i].action==Gui.BACK)
                        {
                            continue;
                        }
                    }
                    //end----------------------//2apr2021
                    if(game.gui[i].type==TYPE_BUTTON && game.gui[i].mouseover==true && game.mlclick==true)//2apr2021
                    //if(game.gui[i].type==TYPE_BUTTON && game.gui[i].mouseover==true && ((game.mlclick==true && exitclick==false) || (exitclick==true && game.mlclick==false)))//2apr2021
                    {
                        //start-------------------//20apr2021
                        if(game.gui[i].command.IndexOf("toggle")>=0)
                        {
                            for(int tog=0;tog<game.gui.Length;tog++)
                            {
                                if(game.gui[tog].triggerlink!=game.gui[i].triggerlink || game.gui[tog].gamestate!=game.gui[i].gamestate)
                                {
                                    continue;
                                }
                                if(game.gui[tog].link=="toggleon" || game.gui[tog].link=="toggleoff")
                                {
                                    if(game.gui[tog].link=="toggleon")
                                    {
                                        game.gui[tog].link="toggleoff";
                                    }
                                    else
                                    {
                                        game.gui[tog].link="toggleon";
                                    }
                                }
                            }
                        }
                        if(game.gui[i].command.IndexOf("pause")>=0)
                        {
                            Game.togglepause = !Game.togglepause;
                        }
                        //end---------------------//20apr2021
                        //start---------------//23sep2021
                        if(game.gui[i].command.IndexOf("attackaction")>=0)
                        {
                            //a tech button is pressed that perform an attack action....
                            if(game.gui[i].action==ACTION_NONE)//25sep2021
                            {
                                //default attack mode........
                                Unit.SelectNearestTarget(game,Unit.GetPlayer(game));//24sep2021//25sep2021
                            }
                            else//25sep2021
                            {
                                Tech.ActivateAttack(game,game.gui[i].action);
                            }
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                            continue;
                        }
                        pid = Unit.GetPlayer(game);
                        if(pid!=-1)
                        {
                            if(game.gui[i].command.IndexOf("drinkhealthpotion")>=0)
                            {
                                Tech.DrinkPotion(game, pid, "health");
                                game.gui[i].mouseover = false;
                                game.mlclick = false;
                                continue;
                            }
                            if(game.gui[i].command.IndexOf("drinkmanapotion")>=0)
                            {
                                Tech.DrinkPotion(game, pid, "mana");
                                game.gui[i].mouseover = false;
                                game.mlclick = false;
                                continue;
                            }
                            if(game.gui[i].command.IndexOf("drinkbothpotion")>=0)
                            {
                                Tech.DrinkPotion(game, pid, "both");
                                game.gui[i].mouseover = false;
                                game.mlclick = false;
                                continue;
                            }
                        }
                        if(game.gui[i].command.IndexOf("buyitem")>=0)
                        {
                            //can't use triggerlink, can't use link, have to use action.....
                            //and then we have to jump out of this.....
                            //
                            Tech.SelectFromGuiToPurchase(game, game.gui[i].action); //tells the gui this item is to be selected.....
                            for(int j=0;j<game.gui.Length;j++)//24sep2021
                            {
                                if(game.gui[j].triggerlink==game.gui[i].triggerlink && (game.gui[j].command.IndexOf("buydescription")>=0 || game.gui[j].command.IndexOf("buycost")>=0))//25sep2021
                                {
                                    game.gui[j].action = game.gui[i].action;
                                    if(game.gui[j].command.IndexOf("buycost")>=0)
                                    {
                                        game.gui[i].title = ""+Tech.GoldCostGui(game,game.gui[i].action);
                                    }
                                }
                            }
                            //
                            //
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                        }
                        if(game.gui[i].command.IndexOf("buybutton")>=0)
                        {
                            if(Tech.PurchaseGuiSelected(game)>0)
                            {
                                Tech.RemoveItemFromStore(game, i);
                            }
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                        }
                        if(game.gui[i].command.IndexOf("buycost")>=0)
                        {
                            game.gui[i].title = ""+Tech.GoldCostGui(game,game.gui[i].action);
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                        }
                        if(game.gui[i].command.IndexOf("buy")>=0)//finally stop processing all 'buy' related buttons....put at end of buy block
                        {
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                            continue;
                        }
                        //end-----------------//23sep2021
                        //start---------------//26mar2021
                        if(game.gui[i].action==ACTION_PLAY && Game.chosenmissionindex==-1)
                        {
                            game.gui[i].mouseover = false;//27mar2021 bugfix?
                            game.mlclick = false;//27mar2021 bugfix?
                            continue;
                        }
                        //start--------//12apr2021
                        if(game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END)
                        {
                            if(game.gui[i].spellactive==false)
                            {
                                game.gui[i].mouseover = false;//27mar2021 bugfix?
                                game.mlclick = false;//27mar2021 bugfix?
                                continue;
                            }
                        }
                        //end----------//12apr2021
                        if(Functions.abs(game.fmx - game.smx)>10 || Functions.abs(game.fmy - game.smy)>10) //don't want to accidentally push buttons when sliding the mouse around....TEST THIS BEFORE RELEASE
                        {
                            //potentially put minimap frame check in here
                            game.gui[i].mouseover = false;//27mar2021 bugfix?
                            game.mlclick = false;//27mar2021 bugfix?
                            
                            continue;
                        }
                        //bug fix with this....27mar2021...
                        //bug fix involved setting 'selectingtime' only when the mouse was in a drag box mode.....
                        if(Game.selectingtime>0 && (game.gamestate!=game.gui[i].nextgamestate || game.gui[i].action==Gui.BACK))
                        {
                            game.gui[i].mouseover = false;//27mar2021 bugfix?
                            game.mlclick = false;//27mar2021 bugfix?
                            game.minimapframe = game.frame - 1000;//27mar2021
                            Unit.deselect(game);//27mar2021
                            continue;
                        }
                        //end-----------------//26mar2021
                        //check what the action should be.....
                        //if(game.gui[i].triggerlink != LINK_SPAWNER_ICON)//2sep2021
                        if(game.gui[i].triggerlink != LINK_SPAWNER_ICON && game.gui[i].triggerlink != LINK_TECH_ICON)//2sep2021
                        {
                            game.mlclick = false;
                        }
                        //start---------------//31dec2021
                        if(game.gui[i].triggervariable>-1 && game.gui[i].triggervariable<Trigger.VARIABLE.Length)
                        {
                            int variable = game.gui[i].triggervariable;
                            int op = game.gui[i].triggerop;
                            int num = game.gui[i].triggernum;
                            switch(op)
                            {
                                case 0://increment
                                    Trigger.VARIABLE[variable]+=num;
                                break;
                                case 1://decrement
                                    Trigger.VARIABLE[variable]-=num;
                                break;
                                case 2://multiply
                                    Trigger.VARIABLE[variable]*=num;
                                break;
                                case 3://integer divide
                                    if(num!=0)
                                    {
                                        Trigger.VARIABLE[variable]/=num;
                                    }
                                break;
                            }
                            //Console.WriteLine("Trigger Variable Value:"+Trigger.VARIABLE[variable]+ " for variable:"+variable);
                            game.gui[i].hidden = 1;
                            game.gui[i].mouseover = false;
                            game.mlclick = false;
                        }
                        //end-----------------//31dec2021
                        if(game.gui[i].action!=ACTION_EXTERNAL)//8mar2022
                        {
                            Audios.playsound(game.audios[Resources.CLICK],Game.FXVOLUME);
                        }
                        if(game.gui[i].nextgamestate!=0)
                        {
                        //{
                            //screen to show
                            if(game.gamestate!=game.gui[i].nextgamestate && game.gamestate!=Game.CAT_GAMESTATE_GAME && game.gamestate!=Game.CAT_GAMESTATE_REPLAY)
                            {
                                //24feb2022 added Night changer.......
                                int oNight = Config.Night;
                                if(game.gui[i].nextgamestate==10000)
                                {
                                    if(Functions.rand(0,100)<50 )
                                    {
                                        Config.Night = 1;
                                    }
                                    else
                                    {
                                        Config.Night = 0;
                                    }
                                }
                                if(game.gui[i].nextgamestate==10088)
                                {
                                    Config.Night = 0;
                                }
                                if(Config.Night!=oNight)
                                {
                                    //non gui images anyway.....
                                    Resources.FreeAllImages(game);
                                }
                                //24feb2022
                                //Gui.ALTMODE=!Gui.ALTMODE;//18apr2021
                                //start---------------------//20apr2021
                                for(int tog=0;tog<game.gui.Length;tog++)
                                {
                                    if(game.gui[tog].gamestate!=game.gui[i].gamestate)
                                    {
                                        continue;
                                    }
                                    if(game.gui[tog].link=="toggleon" || game.gui[tog].link=="toggleoff")
                                    {
                                        game.gui[tog].link = "toggleoff";
                                    }
                                }
                                //end-----------------------//20apr2021
                            }
                            if(game.gamestate!=Game.CAT_GAMESTATE_GAME)//11apr2021
                            {
                                game.gamestate = game.gui[i].nextgamestate;
                            }
                            //start----------//5apr2021
                            
                            for(int g=0;g<game.gui.Length;g++)
                            {
                                if(game.gui[g].gamestate==game.gamestate && game.gui[g].triggerlink == Gui.LINK_UNIT_DETAIL && game.gamestate!=Game.CAT_GAMESTATE_GAME && Config.bestiarychk==false)
                                {
                                    Config.bestiarychk = true;
                                    try
                                    {
                                        Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=kog2mission&event=bestiary&value=1&uid="+Config.uid;//30mar2021
                                        Network.httpget(Network.url);
                                    }
                                    catch(Exception e)
                                    {
                                        string message = e.Message;
                                    }
                                    break;
                                }
                            }
                            
                            //end-----------//5apr2021
                        //}
                        //else
                        //{
                            //something game specific...
                            if(game.gui[i].action==Gui.BACK)
                            {
                                //start---------------------//20apr2021
                                for(int tog=0;tog<game.gui.Length;tog++)
                                {
                                    if(game.gui[tog].gamestate!=game.gui[i].gamestate)
                                    {
                                        continue;
                                    }
                                    if(game.gui[tog].link=="toggleon" || game.gui[tog].link=="toggleoff")
                                    {
                                        game.gui[tog].link = "toggleoff";
                                    }
                                }
                                //end-----------------------//20apr2021
                                if(Game.EDITOR)
                                {
                                    Map.savemap(game);
                                    //game.gamestate=-1; //quit
                                    game.map = new Map();
                                    Program.setupbackdrop(game);
                                    game.demomode = true;
                                    Game.PLAYERFACTION = Unit.HUMAN;
                                    Game.EDITOR = false;
                                    Game.editkeypressed = 0;
                                    //Game.restart = true;//7apr2021
                                    Game.EDITED = 1;//7apr2021
                                    game.gamestate = 0;
                                    return;
                                }
                                else
                                {
                                    //if(Replay.PLAYBACK && Replay.FRAME>0)//2apr2021
                                    //{
                                    //    if(game.exitclick)
                                    //    {
                                    //        Replay.FRAME = Game.replay[0].mx.Length + 100; //cheap and nasty way of getting out of it.....
                                    //    }
                                    //}
                                    //else//2apr2021
                                    //{
                                        if(game.gamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR==false)
                                        {
                                            Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                                            Game.EXITPRESSED = 1;//1mar2022
                                            if(game.gameovertime==0){game.gameovertime = 180;}
                                            Replay.EndRecord(game);
                                        }
                                        else
                                        {
                                            Blood.clearall(game); //29oct2020
                                            Bullet.clearall(game); //29oct2020
                                            Gibbet.clearall(game);//2apr2021
                                            game.map = new Map();
                                            Program.setupbackdrop(game);
                                            game.demomode = true;
                                            Game.PLAYERFACTION = Unit.HUMAN;
                                        }
                                        
                                    //}
                                }
                            }
                        }
                        if(game.gui[i].action!=0)
                        {
                            switch(game.gui[i].action)
                            {
                                //start--------------//13mar2021
                                case 5050:
                                    //set the language to the link value
                                    if(game.gui[i].link!="")
                                    {
                                        Translation.SetLanguage(game.gui[i].link);
                                        Game.restart = true; //not tested // bugger lots of weird crashes......
                                    }
                                break;
                                //end----------------//13mar2021
                                case 87: //PREV CREATURE
                                for(int j=0;j<game.gui.Length;j++)
                                {
                                    if(game.gui[j].gamestate==game.gamestate && game.gui[j].triggerlink == Gui.LINK_UNIT_DETAIL)
                                    {
                                        game.gui[j].index = Unit.gettemplate(game,game.gui[j].index,-1,0);
                                        game.gui[j].uindex = 0;
                                    }
                                }
                                break;
                                case 89: //NEXT CREATURE
                                for(int j=0;j<game.gui.Length;j++)
                                {
                                    if(game.gui[j].gamestate==game.gamestate && game.gui[j].triggerlink == Gui.LINK_UNIT_DETAIL)
                                    {
                                        game.gui[j].index = Unit.gettemplate(game,game.gui[j].index,1,0);
                                        game.gui[j].uindex = 0;
                                    }
                                }
                                break;
                                case 124: //MAP EDITOR HELP
                                //8mar2022 commented this line out....
                                //if(Game.EDITOR)//8mar2022
                                if(Game.EDITOR || game.gamestate!=Game.CAT_GAMESTATE_GAME)//8mar2022
                                {
                                    try
                                    {
                                        System.Diagnostics.Process.Start(game.gui[i].command);
                                    }
                                    catch(Exception ee)
                                    {
                                        string msg = ee.Message;
                                    }
                                }
                                break;
                                case 1234: //ACTION_CONTINUE
                                if(game.gamestate==Game.CAT_GAMESTATE_DEBRIEF)
                                {
                                    game.gamestate = Game.CAT_GAMESTATE_GAME;
                                }
                                else//DEBRIEF2
                                {
                                    game.gamestate = Game.CAT_GAMESTATE_MENU;
                                }
                                break;
                                case 123: //MAP EDITOR
                                Program.resetgame(game);
                                game.gamestate = Game.CAT_GAMESTATE_GAME;
                                game.map = new Map();
                                Program.setupeditor(game);
                                Game.PLAYERFACTION = Unit.HUMAN;
                                Game.EDITOR = true;
                                //start----------//5apr2021
                                try
                                {
                                    Network.url = "https://www.mattiesgames.com/metrics/metric.php?game=kog2mission&event=editor&value=1&uid="+Config.uid;//30mar2021
                                    Network.httpget(Network.url);
                                }
                                catch(Exception e)
                                {
                                    string message = e.Message;
                                }
                                //end-----------//5apr2021
                                Game.EDITORPFACTION = 0;
                                Game.EDITOREFACTION = 0;
                                break;
                                case 1111: //was 5
                                Functions.saveseed(Functions.seed);
                                Program.resetgame(game);
                                break;
                                case 5: //was 1
                                Functions.saveseed(Functions.seed); //added from above
                                Program.resetgame(game); //added from above
                                Program.cleardeaths(game);
                                Game.PLAYERFACTION = Unit.HUMAN;
                                Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                                game.gamestate = Game.CAT_GAMESTATE_GAME;
                                game.map = new Map();
                                Functions.restoreseed();
                                Program.resetlevel(game);
                                Program.skirmishmission(game);
                                Map.adddecor();//2mar2021
                                Map.marktreepos(game);
                                break;
                                case 20:
                                if(Game.chosenmissionindex!=-1)
                                {
                                    Emitter.Reset(game);//22apr2022
                                    Particle.Reset();//22apr2022
                                    Map.levelseed = Functions.seed;//2apr2021
                                    Program.resetgame(game);//2apr2021
                                    Game.PLAYERFACTION = Unit.HUMAN;
                                    Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                                    game.gamestate = Game.CAT_GAMESTATE_GAME;
                                    Program.cleardeaths(game);
                                    game.map = new Map();
                                    Program.setupmission(game,Game.chosenmissionindex,2);
                                    Map.adddecor();//2mar2021
                                    Map.marktreepos(game);
                                    if(Config.dointro!=0)//1mar2022
                                    {
                                        game.gamestate = Game.CAT_GAMESTATE_INTRO;
                                    }
                                    Map.levelseed2 = Functions.seed;//2apr2021
                                    
                                }
                                break;
                                case 4:
                                Map.generate(game);
                                Functions.saveseed(Functions.seed);
                                Program.cleardeaths(game);
                                break;
                                case 2:
                                Game.PLAYERFACTION = Unit.UNDEAD;
                                Game.SKIRMISHENEMYFACTION = Unit.HUMAN;
                                game.gamestate = Game.CAT_GAMESTATE_GAME;
                                game.map = new Map();
                                Functions.restoreseed();
                                Program.resetlevel(game);
                                Program.cleardeaths(game);
                                Program.skirmishmission(game);
                                Map.adddecor();//2mar2021
                                Map.marktreepos(game);
                                break;
                                case 120: //fullscreen/windowed//17apr2021
                                    if(Game.FULLSCREEN>0)
                                    {
                                        Game.FULLSCREEN = 0;
                                        LocalStorage.setitem("fullscreen","0");
                                    }
                                    else
                                    {
                                        Game.FULLSCREEN = 1;
                                        LocalStorage.setitem("fullscreen","1");
                                    }
                                    Game.restart = true;
                                break;
                                case 121: //hi res/low res sprites//17apr2021
                                    if(Config.hires>0)
                                    {
                                        Config.hires = 0;
                                        LocalStorage.setitem("hires","0");
                                    }
                                    else
                                    {
                                        Config.hires = 1;
                                        LocalStorage.setitem("hires","1");
                                    }
                                    if(game.gui[i].command.IndexOf("norestart")==-1)//20apr2021
                                    {
                                        Game.restart = true;
                                    }
                                break;
                                case 14://28feb2022 options fog
                                    if(Config.options_fog>0)
                                    {
                                        Config.options_fog = 0;
                                        LocalStorage.setitem("options_fog","off");
                                    }
                                    else
                                    {
                                        Config.options_fog = 1;
                                        LocalStorage.setitem("options_fog","on");
                                    }
                                break;
                                case 15://28feb2022 options overlayimage
                                    if(Config.options_overlay>0)
                                    {
                                        Config.options_overlay = 0;
                                        LocalStorage.setitem("options_overlay","off");
                                    }
                                    else
                                    {
                                        Config.options_overlay = 1;
                                        LocalStorage.setitem("options_overlay","on");
                                    }
                                break;
                                case 12:
                                    if(Game.FXVOLUME>0)
                                    {
                                        Game.FXVOLUME = 0;
                                        LocalStorage.setitem("sfx","off"); //12mar2021
                                    }
                                    else
                                    {
                                        Game.FXVOLUME = Game.oFXVOLUME;
                                        LocalStorage.setitem("sfx","on"); //12mar2021
                                    }
                                break;
                                case 13:
                                    if(Game.MUSICVOLUME>0)
                                    {
                                        Game.MUSICVOLUME = 0;
                                        SDL_mixer.Mix_PauseMusic();
                                        Map.menumusicplaying = 0;
                                        LocalStorage.setitem("music","off");
                                    }
                                    else
                                    {
                                        Game.MUSICVOLUME = Game.oMUSICVOLUME;
                                        Map.menumusicplaying = -1;
                                        LocalStorage.setitem("music","on");
                                        //start---------//25apr2021
                                        if(game.gamestate==Game.CAT_GAMESTATE_GAME)
                                        {
                                            SDL_mixer.Mix_ResumeMusic();
                                        }
                                        //end-----------//25apr2021
                                    }
                                break;
                                case 10:
                                Map.levelseed = Functions.seed; //2apr2021
                                Game.PLAYERFACTION = Unit.HUMAN;
                                Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                                game.gamestate = Game.CAT_GAMESTATE_GAME;
                                game.map = new Map();
                                Program.cleardeaths(game);
                                Program.setupmission(game,game.gui[i].mission,0);
                                Map.adddecor();//2mar2021
                                Map.marktreepos(game);
                                Map.levelseed2 = Functions.seed; //2apr2021
                                break;
                                case 11:
                                Game.PLAYERFACTION = Unit.HUMAN;
                                Game.SKIRMISHENEMYFACTION = Unit.UNDEAD;
                                Program.cleardeaths(game);                            
                                game.gamestate = Game.CAT_GAMESTATE_GAME;
                                game.map = new Map();
                                //Program.setupmission(game,-999);
                                for(int t=0;t<game.missions.Length;t++)
                                {
                                    if(game.missions[t].istutorial==1)
                                    {
                                        Program.setupmission(game,t,999);
                                        Map.adddecor();//2mar2021
                                        Map.marktreepos(game);
                                        break;
                                    }
                                }
                                break;
                            }
                            //start-------------//28mar2021
                            if(Game.SPELLCASTERSELECTED!=-1)
                            {
                                if(game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END && Game.SPELLCASTERLEVEL!=99 && game.gui[i].spellactive==true)
                                {
                                    Unit.SpellCast(game,game.gui[i].action,Game.PLAYERFACTION);
                                }
                            }
                            //end---------------//28mar2021
                            //start-------------//9mar2021
                            //special set of ACTIONS......
                            if(game.frame % 60>55 && game.gui[i].action>=ACTION_FORMATIONSTART && game.gui[i].action<=ACTION_FORMATIONEND)
                            {
                                bool foundu = false;
                                //for(int u=0;u<game.units.Length;u++)//26mar2021
                                for(int u=0;u<=Unit.MAXINDEX;u++)//26mar2021
                                {
                                    if(game.units[u].faction==Game.PLAYERFACTION && game.units[u].hp>0 && game.units[u].walkspeed>0 && game.units[u].selected!=Unit.SELECTIONNONE)
                                    {
                                        foundu = true;
                                        break;
                                    }
                                }
                                if(foundu && Game.EDITOR==false)
                                {
                                    game.gui[i].hidden = 0;
                                }
                                else
                                {
                                    game.gui[i].hidden = 1;
                                    game.gui[i].mouseover = false;//24apr2021 to correct selection bug with spawners
                                }
                            }
                            //if(game.gui[i].hidden==0)//10mar2021
                            if(Game.NONSPAWNERSELECTED==true && Game.SPAWNERSELECTED==false)
                            {
                                if(game.gui[i].action==ACTION_LINEH)
                                {
                                    Unit.Formation(game,ACTION_LINEH);
                                }
                                if(game.gui[i].action==ACTION_LINEV)
                                {
                                    Unit.Formation(game,ACTION_LINEV);
                                }
                                if(game.gui[i].action==ACTION_OPEN)
                                {
                                    Unit.Formation(game,ACTION_OPEN);
                                }
                                if(game.gui[i].action==ACTION_CLOSE)
                                {
                                    Unit.Formation(game,ACTION_CLOSE);
                                }
                                if(game.gui[i].action==ACTION_RALLY)
                                {
                                    Unit.Formation(game,ACTION_RALLY);
                                }
                                if(game.gui[i].action==ACTION_DEFEND)
                                {
                                    Unit.Formation(game,ACTION_DEFEND);
                                }
                                if(game.gui[i].action==ACTION_ENGAGE)
                                {
                                    Unit.Formation(game,ACTION_ENGAGE);
                                }
                            }
                            //end---------------//9mar2021
                        }
                    }
                }
            }        
        }

///////////////////Method Definition///////////////
        public static void drawall(Game game)
        {
            int pid = -1;
            //draw all gui stuff
            //start-----//9sep2021
            int framecheck = 60;
            if(Config.RUNNINGSPEED>90)
            {
                framecheck = 80;
            }
            if(Config.RUNNINGSPEED>110)
            {
                framecheck = 90;
            }
            framecheck/=Config.FASTFRAMECHECK;//14sep2021
            //end-------//9sep2021
            int spellframe = 0;
            uint color = 0;
            int uid = -1;
            int toffy = 15;
            int toffx = 25;
            string[] uline = new string[4];
            string[] description = new string[0];
            int tcount = 0;
            int xcount = 0; //11mar2021
            int ycount = 0; //11mar2021
            int icount = 0; //11mar2021
            for(int i=0;i<game.gui.Length;i++)
            {
                if(game.gui[i].nextgamestate==Game.CAT_GAMESTATE_REPLAY && (Config.ALLOWREPLAY==false || Config.NOREPLAY>0))//2apr2021
                {
                    continue;
                }
                //start--------------------//2apr2021
                if(Replay.PLAYBACK)
                {
                    if(game.gui[i].action==Gui.BACK)
                    {
                        continue;
                    }
                }
                //end----------------------//2apr2021
                //start--------------------//2sep2021
                if(game.gui[i].triggerlink == LINK_TECH_ICON && Game.EDITOR == false && game.gui[i].gamestate==game.oldgamestate && Tech.TECHUNITSELECTED==true && Config.USETECH == true)
                {
                    game.gui[i].mouseover = false;
                    game.gui[i].hidden = 1;
                    if(Tech.TECHUNITIDSELECTED!=-1)
                    {
                        for(int tt=0;tt<game.units[Tech.TECHUNITIDSELECTED].techguilinkid.Length;tt++)//26feb2022
                        {    
                            if(game.units[Tech.TECHUNITIDSELECTED].techguilinkid[tt] == game.gui[i].index)
                            {
                                int techid = -1;
                                tcount = 0;
                                xcount = 0;
                                ycount = 0;
                                icount = 0;
                                for(int t=0;t<game.techs.Length;t++)
                                {
                                    if(game.techs[t].guilinkid==game.gui[i].index && game.techs[t].researched<=0)
                                    {
                                        //this is a tech we want to show the icon for to choose to research.....
                                        game.gui[i].hidden = 0;
                                        RenderList.drawimage(game,game.images[game.gui[i].image].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                                        if(game.mx > game.gui[i].x + xcount && game.mx < game.gui[i].x + game.gui[i].w + xcount && game.my > game.gui[i].y + ycount && game.my < game.gui[i].y + game.gui[i].h + ycount)
                                        {    
                                            RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + xcount + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].image);                            
                                            //game.gui[i].tooltip = game.templates[tid].name; //13mar2021
                                            game.gui[i].tooltip = game.techs[t].tooltip;
                                            RenderList.drawtext(game,game.gui[i].x+ 3 * game.gui[i].w / 4 + xcount,ycount + game.gui[i].y + game.gui[i].h / 2,game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                        
                                            game.gui[i].mouseover = true;
                                            //WARNING - updating in DRAWING SECTION!
                                            if(game.mlclick==true && Game.togglepause==false)
                                            {
                                                techid = t;
                                                if(icount>0)//15mar2021
                                                {
                                                    Audios.playsound(game.audios[Resources.CLICK],Game.FXVOLUME);//15mar2021
                                                }
                                            }
                                        }
                                        //draw the tech sprite
                                        RenderList.drawimage(game,game.images[game.techs[t].img].texture,game.gui[i].x + game.gui[i].w/2 + xcount,ycount + game.gui[i].y + game.gui[i].h/2,0,0.7f,0.7f,game.techs[t].imgframe,0,false,1f,game.techs[t].img);
                                        if(game.techs[t].timeleft>0)
                                        {
                                            RenderList.drawrect(game,game.gui[i].x + game.gui[i].w/4 + xcount,ycount + game.gui[i].y + game.gui[i].h,Tech.PercentComplete(game,t),2,RenderList.getrgb(32,255,255),0);
                                            RenderList.drawunfilledrect(game,game.gui[i].x + game.gui[i].w/4 + xcount,ycount + game.gui[i].y + game.gui[i].h,100,4,RenderList.getrgb(180,180,200),0);
                                        }
                                        //
                                        tcount+=game.gui[i].h;
                                        icount++;
                                        if(game.gui[i].horizontal>0)
                                        {
                                            xcount+=game.gui[i].w;
                                        }
                                        if(game.gui[i].vertical>0)
                                        {
                                            ycount+=game.gui[i].h;
                                        }
                                        if((icount >= game.gui[i].horizontal && game.gui[i].horizontal > 0) || (icount >= game.gui[i].vertical && game.gui[i].vertical > 0))
                                        {
                                            if(game.gui[i].horizontal>0)
                                            {
                                                xcount = 0;
                                                ycount += game.gui[i].h;
                                            }
                                            else
                                            {
                                                ycount = 0;
                                                xcount += game.gui[i].w;
                                            }
                                            icount = 0;
                                        }
                                    }
                                }
                                if(techid!=-1)
                                {
                                    //only allow 1 research at a time.....
                                    Tech.StartResearch(game,techid,Game.PLAYERFACTION);
                                }
                            }
                        }
                    }
                }
                //end----------------------//2sep2021
                //start-------------//10mar2021
                //if(game.gui[i].triggerlink == LINK_SPAWNER_ICON && Game.EDITOR==false && game.gui[i].gamestate==game.gamestate && Game.SPAWNERSELECTED==true && Game.NONSPAWNERSELECTED==false)//18apr2021
                if(game.gui[i].triggerlink == LINK_SPAWNER_ICON && Game.EDITOR==false && game.gui[i].gamestate==game.oldgamestate && Game.SPAWNERSELECTED==true && Game.NONSPAWNERSELECTED==false)//18apr2021
                {
                    game.gui[i].mouseover = false;
                    bool doneonce = false;
                    int ttid = -1;
                    game.gui[i].hidden = 1;
                    //for(int u=0;u<game.units.Length;u++)//26mar2021
                    icount = 0;//2sep2021
                    for(int u=0;u<=Unit.MAXINDEX;u++)//26mar2021
                    {
                        if(game.units[u].faction==Game.PLAYERFACTION && game.units[u].hp>0 && game.units[u].walkspeed==0 && game.units[u].selected!=Unit.SELECTIONNONE && game.units[u].spawner!="")

                        {
                            if(!doneonce)
                            {
                                color = RenderList.getrgb(240,240,240);
                                tcount = 0;
                                xcount = 0;
                                ycount = 0;
                                game.gui[i].hidden = 0;
                                for(int tid=0;tid<game.templates.Length;tid++)
                                {
                                    if(!Unit.SpawnerCanBuild(game,game.units[u].spawnerconstraint,tid))//9sep2021
                                    {
                                        continue;
                                    }
                                    if(game.templates[tid].faction==Game.PLAYERFACTION && (game.templates[tid].bossmonster<=0 && game.templates[tid].planar<=0 && game.templates[tid].leader<=0) && game.templates[tid].walkspeed>0)
                                    {
                                        if(game.templates[tid].unresearchedbydefault>0)//2sep2021
                                        {
                                            if(!Tech.IsUnitEnabled(game,tid)) //2sep2021
                                            {
                                                continue;
                                            }
                                        }
                                        //draw this gui icon
                                        RenderList.drawimage(game,game.images[game.gui[i].image].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                                        if(game.mx > game.gui[i].x + xcount && game.mx < game.gui[i].x + game.gui[i].w + xcount && game.my > game.gui[i].y + ycount && game.my < game.gui[i].y + game.gui[i].h + ycount)
                                        {    
                                            RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + xcount + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].image);                            
                                            //game.gui[i].tooltip = game.templates[tid].name; //13mar2021
                                            game.gui[i].tooltip = game.templates[tid].dname(); //13mar2021
                                            RenderList.drawtext(game,game.gui[i].x+ 3 * game.gui[i].w / 4 + xcount,ycount + game.gui[i].y + game.gui[i].h / 2,game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                        
                                            game.gui[i].mouseover = true;
                                            //WARNING - updating in DRAWING SECTION!
                                            //10mar2021 Warning - updating in DRAWING SECTION
                                            //if(game.mlclick==true)// && ttid==-1)//22mar2021
                                            if(game.mlclick==true && Game.togglepause==false)// && ttid==-1)//22mar2021
                                            {
                                                ttid = tid;
                                                if(icount>0)//15mar2021
                                                {
                                                    Audios.playsound(game.audios[Resources.CLICK],Game.FXVOLUME);//15mar2021
                                                }
                                            }
                                        }
                                        //draw the sprite idle frame start
                                        //9apr2021 hires stuff
                                        if(game.templates[tid].cathires!=-1)
                                        {
                                            //half scale, double resolution....
                                            RenderList.drawimage(game,game.images[game.templates[tid].cathires].texture,game.gui[i].x + game.gui[i].w/2 + xcount,ycount + game.gui[i].y + game.gui[i].h/2,0,0.35f,0.35f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cathires);
                                        }
                                        else
                                        {
                                            RenderList.drawimage(game,game.images[game.templates[tid].cat].texture,game.gui[i].x + game.gui[i].w/2 + xcount,ycount + game.gui[i].y + game.gui[i].h/2,0,0.7f,0.7f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cat);
                                        }
                                        //
                                        tcount+=game.gui[i].h;
                                        icount++;
                                        if(game.gui[i].horizontal>0)
                                        {
                                            xcount+=game.gui[i].w;
                                        }
                                        if(game.gui[i].vertical>0)
                                        {
                                            ycount+=game.gui[i].h;
                                        }
                                        if((icount >= game.gui[i].horizontal && game.gui[i].horizontal > 0) || (icount >= game.gui[i].vertical && game.gui[i].vertical > 0))
                                        {
                                            if(game.gui[i].horizontal>0)
                                            {
                                                xcount = 0;
                                                ycount += game.gui[i].h;
                                            }
                                            else
                                            {
                                                ycount = 0;
                                                xcount += game.gui[i].w;
                                            }
                                            icount = 0;
                                        }
                                    }
                                }    
                            }                            
                            doneonce = true;
                            if(ttid!=-1)
                            {
                                string ospawner = game.units[u].spawner;//9sep2021
                                game.units[u].spawner = game.templates[ttid].name;
                                game.units[u].spawnertemplateid = ttid;//26feb2022
                                game.units[u].displayspawner = game.templates[ttid].dname();//13mar2021
                                game.units[u].spawnertime = Unit.CalculateSpawnerTime(game,ttid);
                                if(game.units[u].framesleft==0 || ospawner!=game.units[u].spawner)//9sep2021
                                {
                                    game.units[u].framesleft = framecheck * game.units[u].spawnertime;//9sep2021
                                }
                                if(game.units[u].spawnercount<10)
                                {
                                    game.units[u].spawnercount++;
                                }
                                if(game.units[u].spawnercount<=0)
                                {
                                    game.units[u].spawnercount=1;
                                }
                            }
                        }
                    }
                    break;
                }
                //end---------------//10mar2021
            }
            Game.showingselectedicons = false;//22mar2021
            for(int i=0;i<game.gui.Length;i++)
            {
                //start--------------------//2apr2021
                if(Replay.PLAYBACK)
                {
                    if(game.gui[i].action==Gui.BACK)
                    {
                        continue;
                    }
                }
                //end----------------------//2apr2021
                if(game.gui[i].nextgamestate==Game.CAT_GAMESTATE_REPLAY && (Config.ALLOWREPLAY==false || Config.NOREPLAY>0))//2apr2021
                {
                    continue;
                }
                spellframe = 0; //0 or 1 1 = greyed out.....0 = coloured....
                if(game.gui[i].triggerlink == LINK_SPAWNER_ICON) //10mar2021
                {
                    continue;
                }
                if(game.gui[i].triggerlink == LINK_TECH_ICON)//2sep2021
                {
                    continue;
                }
                if(game.gui[i].action>=ACTION_FORMATIONSTART && game.gui[i].action<=ACTION_FORMATIONEND)
                {
                    if(Game.SPAWNERSELECTED==true || Game.NONSPAWNERSELECTED==false)
                    {
                        game.gui[i].mouseover = false;//24apr2021
                        continue;
                    }
                    if(Tech.TECHUNITSELECTED) //2sep2021
                    {
                        if(Tech.TECHUNITIDSELECTED!=-1)
                        {
                            if(game.units[Tech.TECHUNITIDSELECTED].walkspeed<=0)
                            {
                                game.gui[i].mouseover = false;
                                continue;
                            }
                        }
                    }
                }
                //start---------------//28mar2021
                if(game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END)
                {
                    if(Game.SPELLCASTERSELECTED==-1 || Game.EDITOR==true)
                    {
                        game.gui[i].mouseover = false;//4apr2021
                        game.gui[i].spellactive = false;//12apr2021
                        continue;
                    }
                    if(Game.SPELLCASTERSELECTED!=-1)
                    {
                        int u = Game.SPELLCASTERSELECTED;
                        game.gui[i].spellactive = false;//12apr2021
                        if(game.units[u].hp>0 && game.units[u].faction==Game.PLAYERFACTION && game.units[u].spellcaster>0 && game.units[u].selected!=Unit.SELECTIONNONE)
                        {
                            bool foundm = false;
                            for(int m=0;m<game.units[u].magicarray.Length;m++)
                            {
                                if(game.units[u].magicarray[m]==game.gui[i].action)
                                {
                                    foundm = true;
                                    spellframe = 0; //coloured
                                    game.gui[i].spellactive = true;//12apr2021
                                    //start-----//3may2021
                                    if(game.units[u].magicarray[m]==Unit.MAGICRELEASE)
                                    {
                                        //check units are inside
                                        if(!Unit.TransportingUnits(game,u))
                                        {
                                            foundm = true;
                                            spellframe = 1;
                                            game.gui[i].spellactive = true;
                                        }
                                    }
                                    if(game.units[u].magicarray[m]==Unit.MAGICTRANSFORM)
                                    {
                                        //check requirements....
                                        if(!Unit.CanTransform(game,u))
                                        {
                                            foundm = true;
                                            spellframe = 1; //greyed out
                                            game.gui[i].spellactive = true;//12apr2021
                                        }
                                    }
                                    //end-------//3may2021
                                    break;
                                }
                                if(game.units[u].magicarray[m]==-1 * game.gui[i].action)
                                {
                                    foundm = true;
                                    spellframe = 1; //greyed out
                                    game.gui[i].spellactive = true;//12apr2021
                                    break;
                                }
                            }
                            if(!foundm)
                            {
                                game.gui[i].mouseover = false;//4apr2021
                                game.gui[i].spellactive = false;//12apr2021
                                continue;
                                //spellframe = 1;//greyed out...
                            }
                        }
                        else
                        {
                            game.gui[i].mouseover = false;//4apr2021
                            game.gui[i].spellactive = false;//12apr2021
                            continue;
                        }
                    }
                }
                //end-----------------//28mar2021
                //start-----------------//22mar2021
                if(game.gui[i].triggerlink==LINK_SELECTED_ICONS)
                {
                    //if(game.gui[i].gamestate==game.gamestate && Game.EDITOR==false)//18apr2021
                    if(game.gui[i].gamestate==game.oldgamestate && Game.EDITOR==false)//18apr2021
                    {
                        tcount = 0;
                        xcount = 0; //11mar2021
                        ycount = 0; //11mar2021
                        icount = 0; //11mar2021
                        color = RenderList.getrgb(240,240,240);
                        for(int tid=0;tid<game.templates.Length;tid++)
                        {
                            if(game.templates[tid].faction==Game.PLAYERFACTION && game.gui[i].triggerlink==LINK_SELECTED_ICONS && game.templates[tid].selectioncount>0 && game.templates[tid].walkspeed>0)
                            {
                                //draw this gui icon
                                Game.showingselectedicons = true;
                                RenderList.drawimage(game,game.images[game.gui[i].image].texture,xcount + game.gui[i].x + game.gui[i].w/2,game.gui[i].y +ycount + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                                //draw the sprite idle frame start
                                //9apr2021 hires stuff
                                if(game.templates[tid].cathires!=-1)
                                {
                                    RenderList.drawimage(game,game.images[game.templates[tid].cathires].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,0.35f,0.35f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cathires);    
                                }
                                else
                                {
                                    RenderList.drawimage(game,game.images[game.templates[tid].cat].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,0.7f,0.7f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cat);
                                }
                                //draw text value with the number....
                                //RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx - 1,toffy + ycount + game.gui[i].y + game.gui[i].h / 2 - 1,""+game.templates[tid].livecount,RenderList.getrgb(12,12,12),game.fonts[game.gui[i].font].font,true);//13mar2021
                                RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx - 1,toffy + ycount + game.gui[i].y + game.gui[i].h / 2 - 1,""+Translation.TranslateNumber(game.templates[tid].selectioncount),color,game.fonts[game.gui[i].font].font,true);                        
                                //
                                //game.gui[i].tooltip = game.templates[tid].name + " - " + game.templates[tid].livecount;//13mar2021
                                game.gui[i].tooltip = game.templates[tid].dname() + " - " + Translation.TranslateNumber(game.templates[tid].selectioncount);//13mar2021
                                if((game.mx > game.gui[i].x + xcount && game.mx < game.gui[i].x + game.gui[i].w + xcount && game.my > game.gui[i].y + ycount && game.my < game.gui[i].y + ycount + game.gui[i].h))
                                {
                                    RenderList.drawimage(game,game.images[game.gui[i].image].texture,xcount + game.gui[i].x + game.gui[i].w/2,game.gui[i].y +ycount + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].image);//22mar2021
                                    if(game.gui[i].y > Game.RESOLUTIONY/2)
                                    {
                                        RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 4,ycount + game.gui[i].y + game.gui[i].h / 2 - + ((60 * game.gui[i].h) / 100),game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                            
                                    }
                                    else
                                    {
                                        RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 4,ycount + game.gui[i].y + game.gui[i].h / 2 + ((60 * game.gui[i].h) / 100),game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                        
                                    }
                                    game.gui[i].mouseover = true;//22mar2021
                                    //WARNING - updating in DRAWING SECTION!
                                    //10mar2021 Warning - updating in DRAWING SECTION
                                    //if(game.mlclick==true && Game.togglepause==false )//26mar2021 //22mar2021 (everything inside here)
                                    if(game.mlclick==true && Game.togglepause==false && Functions.abs(game.fmx - game.smx)<10 && Functions.abs(game.fmy - game.smy)<10 && Game.selectingtime <= Game.WAITSELECTINGTIME/3) //26mar2021
                                    {
                                        Audios.playsound(game.audios[Resources.CLICK],Game.FXVOLUME);//15mar2021
                                        //update selection to just be this sub group within the group.....
                                        //for(int u=0;u<game.units.Length;u++)//26mar2021
                                        for(int u=0;u<=Unit.MAXINDEX;u++)//26mar2021
                                        {
                                            if(game.units[u].selected!=Unit.SELECTIONNONE && game.units[u].templateid!=tid)
                                            {
                                                game.units[u].selected = Unit.SELECTIONNONE;
                                                game.mlclick = false;
                                            }
                                        }
                                    }
                                }
                                tcount+=game.gui[i].w;
                                icount++;
                                if(game.gui[i].horizontal>0)
                                {
                                    xcount+=game.gui[i].w;
                                }
                                if(game.gui[i].vertical>0)
                                {
                                    ycount+=game.gui[i].h;
                                }
                                if((icount >= game.gui[i].horizontal && game.gui[i].horizontal > 0) || (icount >= game.gui[i].vertical && game.gui[i].vertical > 0))
                                {
                                    if(game.gui[i].horizontal>0)
                                    {
                                        xcount = 0;
                                        ycount += game.gui[i].h;
                                    }
                                    else
                                    {
                                        ycount = 0;
                                        xcount += game.gui[i].w;
                                    }
                                    icount = 0;
                                }
                            }
                        }
                    }
                    continue;
                }
                //end-------------------//22mar2021
                //start-------------//9mar2021
                if(game.gui[i].triggerlink>=LINK_PLAYER_ICONS && game.gui[i].triggerlink<=LINK_ENEMY_ICONS)
                {
                    //if(game.gui[i].gamestate==game.gamestate && Game.EDITOR==false)//18apr2021
                    if(game.gui[i].gamestate==game.oldgamestate && Game.EDITOR==false)//18apr2021
                    {
                        tcount = 0;
                        xcount = 0; //11mar2021
                        ycount = 0; //11mar2021
                        icount = 0; //11mar2021
                        color = RenderList.getrgb(240,240,240);
                        for(int tid=0;tid<game.templates.Length;tid++)
                        {
                            if(((game.templates[tid].faction==Game.SKIRMISHENEMYFACTION && game.gui[i].triggerlink==LINK_ENEMY_ICONS) || (game.templates[tid].faction==Game.PLAYERFACTION && game.gui[i].triggerlink==LINK_PLAYER_ICONS)) && game.templates[tid].livecount>0 && game.templates[tid].walkspeed>0)
                            {
                                //draw this gui icon
                                RenderList.drawimage(game,game.images[game.gui[i].image].texture,xcount + game.gui[i].x + game.gui[i].w/2,game.gui[i].y +ycount + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                                //draw the sprite idle frame start
                                //9apr2021 cathires stuff
                                if(game.templates[tid].cathires!=-1)
                                {
                                    RenderList.drawimage(game,game.images[game.templates[tid].cathires].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,0.35f,0.35f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cathires);
                                }
                                else
                                {
                                    RenderList.drawimage(game,game.images[game.templates[tid].cat].texture,xcount + game.gui[i].x + game.gui[i].w/2,ycount + game.gui[i].y + game.gui[i].h/2,0,0.7f,0.7f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cat);
                                }
                                //draw text value with the number....
                                //RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx - 1,toffy + ycount + game.gui[i].y + game.gui[i].h / 2 - 1,""+game.templates[tid].livecount,RenderList.getrgb(12,12,12),game.fonts[game.gui[i].font].font,true);//13mar2021
                                RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx - 1,toffy + ycount + game.gui[i].y + game.gui[i].h / 2 - 1,""+Translation.TranslateNumber(game.templates[tid].livecount),RenderList.getrgb(12,12,12),game.fonts[game.gui[i].font].font,true);                        
                                if(game.templates[tid].livecountframe==0 || (game.templates[tid].livecountframe>0 && game.frame % 30<15))
                                {
                                    //RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx,ycount + toffy + game.gui[i].y + game.gui[i].h / 2,""+game.templates[tid].livecount,color,game.fonts[game.gui[i].font].font,true);//13mar2021
                                    RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 2 + toffx,ycount + toffy + game.gui[i].y + game.gui[i].h / 2,""+Translation.TranslateNumber(game.templates[tid].livecount),color,game.fonts[game.gui[i].font].font,true);//13mar2021
                                }
                                //
                                //game.gui[i].tooltip = game.templates[tid].name + " - " + game.templates[tid].livecount;//13mar2021
                                game.gui[i].tooltip = game.templates[tid].dname() + " - " + Translation.TranslateNumber(game.templates[tid].livecount);//13mar2021
                                if((game.mx > game.gui[i].x + xcount && game.mx < game.gui[i].x + game.gui[i].w + xcount && game.my > game.gui[i].y + ycount && game.my < game.gui[i].y + ycount + game.gui[i].h))
                                {    
                                    if(game.gui[i].y > Game.RESOLUTIONY/2)
                                    {
                                        RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 4,ycount + game.gui[i].y + game.gui[i].h / 2 - + ((60 * game.gui[i].h) / 100),game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                            
                                    }
                                    else
                                    {
                                        RenderList.drawtext(game,xcount + game.gui[i].x+game.gui[i].w / 4,ycount + game.gui[i].y + game.gui[i].h / 2 + ((60 * game.gui[i].h) / 100),game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                        
                                    }
                                }
                                tcount+=game.gui[i].w;
                                icount++;
                                if(game.gui[i].horizontal>0)
                                {
                                    xcount+=game.gui[i].w;
                                }
                                if(game.gui[i].vertical>0)
                                {
                                    ycount+=game.gui[i].h;
                                }
                                if((icount >= game.gui[i].horizontal && game.gui[i].horizontal > 0) || (icount >= game.gui[i].vertical && game.gui[i].vertical > 0))
                                {
                                    if(game.gui[i].horizontal>0)
                                    {
                                        xcount = 0;
                                        ycount += game.gui[i].h;
                                    }
                                    else
                                    {
                                        ycount = 0;
                                        xcount += game.gui[i].w;
                                    }
                                    icount = 0;
                                }
                            }
                        }
                    }
                    continue;
                }
                //end---------------//9mar2021
                if(game.gui[i].triggerlink==Gui.LINK_SELECTION_TEXT)
                {
                    //if(game.gamestate==game.gui[i].gamestate)//18apr2021
                    if(game.oldgamestate==game.gui[i].gamestate)//18apr2021
                    {
                        bool found = false;
                        string uname = "";
                        //for(int j=0;j<game.units.Length;j++)//26mar2021
                        for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                        {
                            if(game.units[j].hp>0 && game.units[j].selected!=Unit.SELECTIONNONE)
                            {
                                if(uname=="")
                                {
                                    uname = game.units[j].name;
                                }
                                found = true;
                                uid = j;
                                if(uname!=game.units[j].name)
                                {
                                    found = false;
                                    uid = -1;
                                    break;
                                }
                            }
                        }
                        //start------//15apr2021
                        if(Game.mouseoverunitid!=-1 && found==false && uid==-1)
                        {
                            int j = Game.mouseoverunitid;
                            if(game.units[j].hp>0)
                            {
                                uid = j;
                                found = true;
                            }
                        }
                        //end--------//15apr2021
                        if(found)
                        {
                            game.gui[i].hidden = 0;
                            if(Config.USETECH) //2sep2021
                            {
                                game.units[uid].walkspeed+=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.MV);
                                game.units[uid].damage+=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BA);
                                game.units[uid].armour+=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BD);
                                Tech.TARGETUID = uid;
                                Tech.ADDSUBTRACT = 1;
                                Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BZ);
                    
                            }
                            uline = Unit.getunittext(game,uid);
                            if(Config.USETECH) //2sep2021
                            {
                                game.units[uid].walkspeed-=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.MV);
                                game.units[uid].damage-=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BA);
                                game.units[uid].armour-=Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BD);
                                Tech.TARGETUID = uid;
                                Tech.ADDSUBTRACT = -1;
                                Tech.AddUnitUpgradeBuff(game,game.units[uid].templateid,Tech.BZ);
                            }
                        }
                        else
                        {
                            game.gui[i].hidden = 1;
                        }
                    }
                }
                //
                if(game.gui[i].hidden==1)
                {
                    if((game.gui[i].triggerlink==GUILINK_DEFEAT && Game.GAMEENDSTATE==Game.GAMEENDSTATE_DEFEAT) || (game.gui[i].triggerlink==GUILINK_VICTORY && Game.GAMEENDSTATE==Game.GAMEENDSTATE_VICTORY))
                    {
                        if(!game.victorymessage)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if(Game.EDITOR)
                        {
                            if(game.gui[i].triggerlink==1)
                            {
                                if(Game.EDITMODE == Game.EDITMODE_TRIGGER)
                                {
                                    if(TriggerHelper.field8index==3 || TriggerHelper.field8index==4)
                                    {
                                        if(TriggerHelper.constructorindex==15)
                                        {
                                            game.gui[i].index = TriggerHelper.field15;
                                        }
                                        else
                                        {
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
                else
                {
                    //if(game.gui[i].triggerlink>0 && game.gamestate!=game.gui[i].gamestate)//18apr2021
                    if(game.gui[i].triggerlink>0 && game.oldgamestate!=game.gui[i].gamestate)//18apr2021
                    {
                        if(game.gui[i].triggerlink!=Gui.LINK_UNIT_DETAIL)
                        {
                            game.gui[i].hidden=1;
                            if(game.gui[i].triggerlink>=100000 && game.gui[i].triggerlink<100100)//23feb2022
                            {
                                game.gui[i].hidden=0;
                            }
                        }
                    }
                }
                //if(game.gui[i].link=="description" && Game.chosenmissionindex==-1)//18sep2021
                if((game.gui[i].link=="description" || game.gui[i].link=="showonlyformission") && Game.chosenmissionindex==-1)//18sep2021
                {
                    continue;
                }
                if(game.gui[i].link=="description" && Game.chosenmissionindex!=-1)
                {
                    if(game.missions[Game.chosenmissionindex].description[0]=="")
                    {
                        continue;
                    }
                }
                //start---------------//26mar2021
                if(Game.chosenmissionindex==-1 && game.gui[i].action==ACTION_PLAY)
                {
                    continue;
                }
                if(game.gui[i].action==ACTION_PLAY && Game.chosenmissionindex!=-1)
                {
                    if(game.missions[Game.chosenmissionindex].description[0]=="")
                    {
                        continue;
                    }
                }
                //end-----------------//26mar2021
                //8mar2022 added in gamestate check//rearranged this a lot...
                if(game.gui[i].action==ACTION_EXTERNAL)
                {
                    if(game.gamestate==Game.CAT_GAMESTATE_GAME && Game.EDITOR == false)
                    {
                        continue;
                    }
                    //continue;//8mar2022
                }
                //start-------------//9mar2021
                //if(game.gui[i].action>=ACTION_FORMATIONSTART && game.gui[i].action<=ACTION_FORMATIONEND && (Game.EDITOR==true || Game.SPAWNERSELECTED==true) && Game.NONSPAWNERSELECTED==false)//2sep2021
                if(game.gui[i].action>=ACTION_FORMATIONSTART && game.gui[i].action<=ACTION_FORMATIONEND && (Game.EDITOR==true || Game.SPAWNERSELECTED==true || Tech.TECHUNITSELECTED==true) && Game.NONSPAWNERSELECTED==false)//2sep2021
                {
                    game.gui[i].mouseover = false;//24apr2021
                    continue;
                }
                //end---------------//9mar2021
                //start------------//17apr2021
                //if(game.gui[i].gamestate==game.gamestate)//18apr2021
                if(game.gui[i].gamestate==game.oldgamestate)//18apr2021
                {
                    //if(game.gui[i].link=="targeticon" || game.gui[i].link=="clicker")//3may2021
                    if(game.gui[i].link=="targeticon" || game.gui[i].link=="clicker" || game.gui[i].link=="transporticon")//3may2021
                    {
                        game.gui[i].x = game.mx;
                        game.gui[i].y = game.my;
                        game.gui[i].w = game.images[game.gui[i].image].cwx;
                        game.gui[i].h = game.images[game.gui[i].image].chy;
                        if(game.gui[i].link=="clicker")

                        {
                            game.gui[i].x = Game.clickerx - game.gui[i].w/2;
                            game.gui[i].y = Game.clickery - game.gui[i].h/2;
                            if(Game.clickerframe<0)
                            {
                                continue;
                            }
                            else
                            {
                                if(Game.clickerframe>=0)
                                {
                                    Game.clickerframe++;
                                    if(Game.clickerframe>game.images[game.gui[i].image].cwn - 1)
                                    {
                                        Game.clickerframe = -1;
                                        Game.clickerrow = 0;
                                        continue;
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            game.gui[i].index = Game.clickerframe + game.images[game.gui[i].image].cwn * Game.clickerrow;
                        }
                        if(game.gui[i].link=="targeticon")
                        {
                            if(Game.mouseoverunitid!=-1 && Game.anyselected==true)
                            {
                                int nid = Game.mouseoverunitid;
                                if(game.units[nid].faction==Game.SKIRMISHENEMYFACTION && game.units[nid].hp>0)
                                {
                                    //show us
                                    //20apr2021 added offx
                                    game.gui[i].x = game.units[nid].offx + game.units[nid].x - Game.CORNERX - game.gui[i].w/2;
                                    game.gui[i].y = game.units[nid].y - Game.CORNERY + game.units[nid].offy - game.gui[i].h/2;
                                    if(game.mlclick || game.mrclick)//24sep2021
                                    {
                                        Unit.SelectNearestTarget(game,Unit.GetPlayer(game));//24sep2021
                                    }
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }
                        }
                        if(game.gui[i].link=="transporticon")//3may2021 (and contents)
                        {
                            if(Game.mouseoverunitid!=-1 && Game.anyselected==true)
                            {
                                int nid = Game.mouseoverunitid;
                                if(game.units[nid].faction==Game.PLAYERFACTION && game.units[nid].hp>0 && game.units[nid].transportcapacity>0)
                                {
                                    game.gui[i].x = game.units[nid].offx + game.units[nid].x - Game.CORNERX - game.gui[i].w/2;
                                    game.gui[i].y = game.units[nid].y - Game.CORNERY + game.units[nid].offy - game.gui[i].h/2;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                continue;
                            }
                        }                                            
                    }
                }
                //end--------------//17apr2021
                
                //if(game.gui[i].gamestate == game.gamestate)//18apr2021
                if(game.gui[i].gamestate == game.oldgamestate)//18apr2021
                {
                    //these buttons belong to us......etc
                    //start-------------------//20apr2021
                    if(game.gui[i].link=="toggleoff")
                    {
                        continue;
                    }
                    if(game.gui[i].link=="indoor" && Map.indoor==0)//25sep2021
                    {
                        continue;
                    }
                    //end-----------------------//20apr2021
                    if(game.gui[i].backgroundrect)
                    {
                        color = RenderList.getrgb(game.gui[i].backgroundrectcolor[0],game.gui[i].backgroundrectcolor[1],game.gui[i].backgroundrectcolor[2]);
                    //start----------23sep2021                    
                        bool healthbar = false;//23sep2021
                        bool manabar = false;//23sep2021
                        if(game.gui[i].link=="health")
                        {
                            healthbar = true;
                        }
                        if(game.gui[i].link=="mana")
                        {
                            manabar = true;
                        }
                        if(manabar || healthbar)
                        {
                            int hh = 0;
                            int vv = 0;
                            int yy = 0;
                            int value = 0;
                            int vbase =0;
                            //
                            pid = Unit.GetPlayer(game);
                            if(pid!=-1)
                            {
                                if(manabar)
                                {
                                    value = game.units[pid].mana;
                                    vbase = game.units[pid].basemana;
                                    if(vbase<=0)
                                    {
                                        continue;
                                    }
                                    if(value>vbase)
                                    {
                                        value = vbase;
                                    }
                                }
                                else
                                {
                                    value = game.units[pid].hp;
                                    vbase = game.units[pid].basehp;
                                    if(vbase<=0)
                                    {
                                        continue;
                                    }
                                    if(value>vbase)
                                    {
                                        value = vbase;
                                    }
                                }
                                if(game.gui[i].horizontal>0)
                                {
                                    hh = (game.gui[i].backgroundrectcoords[2] * value) / vbase;
                                    RenderList.drawrect(game,game.gui[i].backgroundrectcoords[0],game.gui[i].backgroundrectcoords[1],hh,game.gui[i].backgroundrectcoords[3],color,0);//25sep2021
                                }
                                if(game.gui[i].vertical>0)
                                {
                                    vv = (game.gui[i].backgroundrectcoords[3] * value) / vbase;
                                    yy = game.gui[i].backgroundrectcoords[1] + game.gui[i].backgroundrectcoords[3] - vv;
                                    RenderList.drawrect(game,game.gui[i].backgroundrectcoords[0],yy,game.gui[i].backgroundrectcoords[2],vv,color,0);//25sep2021
                                }
                            }
                        }
                        else
                        {
                            RenderList.drawrect(game,game.gui[i].backgroundrectcoords[0],game.gui[i].backgroundrectcoords[1],game.gui[i].backgroundrectcoords[2],game.gui[i].backgroundrectcoords[3],color,0);
                        }
                        //    RenderList.drawrect(game,game.gui[i].backgroundrectcoords[0],game.gui[i].backgroundrectcoords[1],game.gui[i].backgroundrectcoords[2],game.gui[i].backgroundrectcoords[3],color,0);
                        //end----------23sep2021
                    }
                    if(game.gui[i].image!=-1 && (game.gui[i].altimage[0]<0 || Gui.ALTMODE==false))
                    {
                        if(game.gui[i].action>=ACTION_SPELL_START && game.gui[i].action<=ACTION_SPELL_END)//28mar2021
                        {
                            if(spellframe==0) //coloured
                            {
                                RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y+game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                                if(game.gui[i].mouseover && game.gui[i].type!=TYPE_IMAGE)
                                {
                                    RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].image);                            
                                }
                            }
                            else
                            {
                                //greyed....
                                RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y+game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index + 1,0,false,1f,game.gui[i].image);                                                            
                            }
                        }
                        else
                        {
                            RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y+game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].image);                            
                            if(game.gui[i].mouseover && game.gui[i].type!=TYPE_IMAGE)
                            {
                                RenderList.drawimage(game,game.images[game.gui[i].image].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].image);                            
                            }
                        }
                    }
                    if(game.gui[i].altimage[0]>=0 && Gui.ALTMODE==true)
                    {
                        //int rnd = game.gui[i].altimageindex;
                        if(game.gui[i].altimageindex==-1 || game.gamestate!=game.oldgamestate)
                        {
                            int rnd = (int)(Functions.abs(Functions.rand(0,10))) % 5;
                            while(game.gui[i].altimage[rnd]<0)
                            {
                                rnd++;
                                rnd%=5;
                            }
                            game.gui[i].altimageindex = rnd;
                        }
                        RenderList.drawimage(game,game.images[game.gui[i].altimage[game.gui[i].altimageindex]].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y+game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,0,false,1f,game.gui[i].altimage[game.gui[i].altimageindex]);
                        if(game.gui[i].mouseover && game.gui[i].type!=TYPE_IMAGE)
                        {
                            RenderList.drawimage(game,game.images[game.gui[i].altimage[game.gui[i].altimageindex]].texture,game.gui[i].x + game.gui[i].w/2,game.gui[i].y + game.gui[i].h/2,0,game.gui[i].scale,game.gui[i].scale,game.gui[i].index,1,false,0.25f,game.gui[i].altimage[game.gui[i].altimageindex]);
                        }
                    }
                    if(Game.EDITOR)
                    {
                        if(TriggerHelper.field8index==3 || TriggerHelper.field8index==4)
                        {
                            if(TriggerHelper.constructorindex==15)
                            {
                                string[] message = TriggerHelper.constructor[9].Split("|");
                                if(message.Length>0)
                                {
                                    for(int j=0;j<message.Length;j++)
                                    {
                                        message[j] = message[j].Replace("^",",");
                                        RenderList.drawtext(game,TriggerHelper.atlocation[0],TriggerHelper.atlocation[1] + j * (4+game.fonts[Resources.FONT].ptsize),message[j],RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);
                                    }
                                }
                            }
                        }
                    }
                    //start------------//28feb2022
                    if(game.gui[i].action==14)//fog
                    {
                        if(Config.options_fog==0)
                        {
                            game.gui[i].title = Translation.TranslateWord("Fog Off",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("Fog On",false);
                        }
                    }
                    if(game.gui[i].action==15)//overlay
                    {
                        if(Config.options_overlay==1)
                        {
                            game.gui[i].title = Translation.TranslateWord("Overlay On",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("Overlay Off",false);
                        }
                    }
                    //end--------------//28feb2022
                    //start------------//17apr2021
                    if(game.gui[i].action==120)
                    {
                        if(Game.FULLSCREEN==0)
                        {
                            game.gui[i].title = Translation.TranslateWord("Windowed",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("Full Screen",false);
                        }
                    }
                    if(game.gui[i].action==121)
                    {
                        if(Config.hires==0)
                        {
                            game.gui[i].title = Translation.TranslateWord("Low Quality",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("High Quality",false);
                        }
                    }
                    //end--------------//17apr2021
                    if(game.gui[i].action==12)
                    {
                        if(Game.FXVOLUME>0)
                        {
                            game.gui[i].title = Translation.TranslateWord("Sound On",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("Sound Off",false);
                        }
                    }
                    if(game.gui[i].action==13)
                    {
                        if(Game.MUSICVOLUME>0)
                        {
                            game.gui[i].title = Translation.TranslateWord("Music On",false);
                        }
                        else
                        {
                            game.gui[i].title = Translation.TranslateWord("Music Off",false);
                        }
                    }
                    color = RenderList.getrgb(255,255,200);
                    if(game.gui[i].missionindex!=-1)
                    {
                        //int mi = game.gui[i].missionindex + Game.topmissionindex; //24Feb2021
                        int mi = game.gui[i].missionindex + (Game.topmissionindex * (1 - game.gui[i].topindexzero)); //24Feb2021
                        if(mi==Game.chosenmissionindex)
                        {
                            //do nothing
                        }
                        else
                        {
                            color = RenderList.getrgb(128,128,100);
                        }
                    }
                    if(game.gui[i].triggerlink>=100000 && game.gui[i].triggerlink<100100)//23feb2022
                    {
                        //ties in to Trigger system.....
                        if(game.gui[i].triggerlink==100000 + Trigger.TYPE_TIMER)
                        {
                            game.gui[i].title = "" + Functions.ClockTime((Trigger.VARIABLE[game.gui[i].triggerlink - 100000])/1000);
                        }
                        else
                        {
                            game.gui[i].title = "" + Trigger.VARIABLE[game.gui[i].triggerlink - 100000];
                        }
                    }
                    if(Config.NonEnglishAllowed==false)//1mar2022
                    {
                        if(game.gui[i].action==ACTION_LANGUAGESET)
                        {
                            game.gui[i].hidden = 1;
                        }
                    }
                    if(game.gui[i].title!="")
                    {
                        RenderList.drawtext(game,game.gui[i].x+game.gui[i].w / 2 - 1,game.gui[i].y + game.gui[i].h / 2 - 1,game.gui[i].title,RenderList.getrgb(25,25,25),game.fonts[game.gui[i].font].font,true);                        
                        RenderList.drawtext(game,game.gui[i].x+game.gui[i].w / 2,game.gui[i].y + game.gui[i].h / 2,game.gui[i].title,color,game.fonts[game.gui[i].font].font,true);                        
                    }
                    //start---------------------//17sep2021
                    if(game.gui[i].link=="Total Score:")
                    {
                        color = RenderList.getrgb(255,255,200);
                        if(Game.scoredirty)
                        {
                            int maxtotalscore = 0;
                            int totalscore = 0;
                            if(game.missions!=null)
                            {
                                for(int ms=0;ms<game.missions.Length;ms++)
                                {
                                    if(game.missions[ms].demo<=0)
                                    {
                                        string totalscorestr = LocalStorage.getitem("missionscore"+ms);
                                        int mscore = 0;
                                        Int32.TryParse(totalscorestr,out mscore);
                                        totalscore+=mscore;
                                        for(int tid=0;tid<game.templates.Length;tid++)
                                        {
                                            if(game.templates[tid].faction==game.missions[ms].playerfaction && game.templates[tid].walkspeed>0)
                                            {
                                                for(int v=0;v<game.missions[ms].units.Length;v++)
                                                {
                                                    if(v>=Unit.MAXUNITS)
                                                    {
                                                        continue;
                                                    }
                                                    if(game.missions[ms].units[v].name==game.templates[tid].name)
                                                    {
                                                        maxtotalscore+=game.templates[tid].points;
                                                    }
                                                }
                                            }
                                        }        
                                    }                            
                                }
                            }
                            Game.totalscore = totalscore;
                            Game.maxtotalscore = maxtotalscore;
                            Game.scoredirty = false;
                        }
                        RenderList.drawtext(game,game.gui[i].x,game.gui[i].y,Translation.TranslateWord(game.gui[i].link,false)+" "+Game.totalscore+" out of "+Game.maxtotalscore,color,game.fonts[Resources.FONT].font,false);
                    }
                    if(game.gui[i].link=="Score:")
                    {
                        if(Game.chosenmissionindex!=-1)
                        {
                            color = RenderList.getrgb(255,255,200);
                            int missionscore = 0;
                            string missionscorestr = LocalStorage.getitem("missionscore"+Game.chosenmissionindex);
                            Int32.TryParse(missionscorestr,out missionscore);
                            int maxscore = 0;
                            for(int tid=0;tid<game.templates.Length;tid++)
                            {
                                if(game.templates[tid].faction==game.missions[Game.chosenmissionindex].playerfaction && game.templates[tid].walkspeed>0)
                                {
                                    for(int v=0;v<game.missions[Game.chosenmissionindex].units.Length;v++)
                                    {
                                        if(v>=Unit.MAXUNITS)
                                        {
                                            continue;
                                        }
                                        if(game.missions[Game.chosenmissionindex].units[v].name==game.templates[tid].name)
                                        {
                                            maxscore+=game.templates[tid].points;
                                        }
                                    }
                                }
                            }
                            RenderList.drawtext(game,game.gui[i].x,game.gui[i].y,Translation.TranslateWord(game.gui[i].link,false)+" "+missionscore+" out of "+maxscore,color,game.fonts[Resources.FONT].font,false);
                        }
                    }
                    //end-----------------------//17sep2021
                    //start---------------------//18sep2021
                    
                    if(game.gui[i].link=="chosenmissionflavourtext")
                    {
                        if(Game.chosenmissionindex!=-1)
                        {
                            color = RenderList.getrgb(255,255,200);
                            if(game.missions[Game.chosenmissionindex].flavourtext!="")
                            {
                                string[] flavourtext = game.missions[Game.chosenmissionindex].flavourtext.Split("|");
                                if(flavourtext!=null)
                                {
                                    for(int ft=0;ft<flavourtext.Length;ft++)
                                    {
                                        RenderList.drawtext(game,game.gui[i].x,game.gui[i].y + ft * 25,flavourtext[ft],color,game.fonts[Resources.FONT].font,false);
                                    }
                                }
                            }
                        }
                    }
                    //end-----------------------//18sep2021
                    //start---------------------//23sep2021
                    if(game.gui[i].link=="gold")
                    {
                        if(game.units!=null)
                        {
                            for(int u=0;u<game.units.Length;u++)
                            {
                                if(game.units[u].faction==Game.PLAYERFACTION && game.units[u].gold>-1 && game.units[u].hp>0)
                                {
                                    game.gui[i].title = "" + game.units[u].gold;
                                }
                            }
                        }
                    }
                    pid = Unit.GetPlayer(game);
                    if(pid!=-1)
                    {
                        if(game.gui[i].link=="healthpotion")
                        {
                            game.gui[i].title = "" + game.units[pid].healthpotions;
                        }
                        if(game.gui[i].link=="manapotion")
                        {
                            game.gui[i].title = "" + game.units[pid].manapotions;
                        }
                        if(game.gui[i].link=="bothpotion")
                        {
                            game.gui[i].title = "" + game.units[pid].bothpotions;
                        }
                    }
                //end-----------------------//23sep2021
                
                    if(game.gui[i].link=="description")
                    {
                        if(Game.chosenmissionindex!=-1)
                        {
                            color = RenderList.getrgb(255,255,200);
                            if(game.missions[Game.chosenmissionindex].description[0]!="")
                            {
                                RenderList.drawtext(game,game.gui[i].x+20,game.gui[i].y + 20 ,game.missions[Game.chosenmissionindex].description[0],color,game.fonts[Resources.FONT].font,false);
                            }
                            if(game.missions[Game.chosenmissionindex].description[1]!="")
                            {
                                RenderList.drawtext(game,game.gui[i].x+20,game.gui[i].y + 45 ,game.missions[Game.chosenmissionindex].description[1],color,game.fonts[Resources.FONT].font,false);
                            }
                            if(game.missions[Game.chosenmissionindex].description[2]!="")
                            {
                                RenderList.drawtext(game,game.gui[i].x+20,game.gui[i].y + 70 ,game.missions[Game.chosenmissionindex].description[2],color,game.fonts[Resources.FONT].font,false);
                            }
                            //start-------------//11mar2021
                            color = RenderList.getrgb(255,255,200);
                            int xxcount = -40;
                            int yycount = 40;
                            int ucount = 0;
                            for(int tid=0;tid<game.templates.Length;tid++)
                            {
                                ucount = 0;
                                if(game.templates[tid].faction==game.missions[Game.chosenmissionindex].playerfaction && game.templates[tid].walkspeed>0)
                                {
                                    for(int v=0;v<game.missions[Game.chosenmissionindex].units.Length;v++)
                                    {
                                        if(v>=Unit.MAXUNITS)
                                        {
                                            continue;
                                        }
                                        if(game.missions[Game.chosenmissionindex].units[v].name==game.templates[tid].name)
                                        {
                                            ucount++;
                                        }
                                    }
                                }
                                if(ucount>0)
                                {
                                    //draw the sprite idle frame start
                                    //9apr2021 cathires stuff
                                    //16sep2021 changed 50 + to 75 + on x coordinates
                                    if(game.templates[tid].cathires!=-1)
                                    {
                                        RenderList.drawimage(game,game.images[game.templates[tid].cathires].texture,75 + xxcount + game.gui[i].x,100 + yycount + game.gui[i].y,0,0.35f,0.35f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cathires);
                                    }
                                    else
                                    {
                                        RenderList.drawimage(game,game.images[game.templates[tid].cat].texture,75 + xxcount + game.gui[i].x,100 + yycount + game.gui[i].y,0,0.7f,0.7f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cat);
                                    }
                                    //RenderList.drawtext(game,game.gui[i].x+50 + xxcount,game.gui[i].y + 70 + yycount ,""+ucount,color,game.fonts[Resources.FONT].font,false);//13mar2021
                                    RenderList.drawtext(game,game.gui[i].x+75 + xxcount,game.gui[i].y + 70 + yycount ,""+Translation.TranslateNumber(ucount),color,game.fonts[Resources.FONT].font,false);//13mar2021
                                    xxcount+=70;
                                    if(xxcount > 370)
                                    {
                                        xxcount = -40;
                                        yycount+=70;
                                    }
                                }
                            }
                            if(xxcount == -40)
                            {
                                yycount-=70;
                            }
                            xxcount = -40;
                            yycount+=70;
                            ucount=0;
                            for(int tid=0;tid<game.templates.Length;tid++)
                            {
                                ucount = 0;
                                if(game.templates[tid].faction==game.missions[Game.chosenmissionindex].skirmishenemyfaction && game.templates[tid].walkspeed>0)
                                {
                                    for(int v=0;v<game.missions[Game.chosenmissionindex].units.Length;v++)
                                    {
                                        if(v>=Unit.MAXUNITS)
                                        {
                                            continue;
                                        }
                                        if(game.missions[Game.chosenmissionindex].units[v].name==game.templates[tid].name)
                                        {
                                            ucount++;
                                        }
                                    }
                                }
                                if(ucount>0)
                                {
                                    //draw the sprite idle frame start
                                    //9apr2021 cathires stuff
                                    //16sep2021 changed 50 + to 75 + on x coordinates
                                    if(game.templates[tid].cathires!=-1)
                                    {
                                        RenderList.drawimage(game,game.images[game.templates[tid].cathires].texture,75 + xxcount + game.gui[i].x,100 + yycount + game.gui[i].y,0,0.35f,0.35f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cathires);
                                    }
                                    else
                                    {
                                        RenderList.drawimage(game,game.images[game.templates[tid].cat].texture,75 + xxcount + game.gui[i].x,100 + yycount + game.gui[i].y,0,0.7f,0.7f,game.templates[tid].animmodeidleframestart,0,false,1f,game.templates[tid].cat);
                                    }
                                    //RenderList.drawtext(game,game.gui[i].x+50 + xxcount,game.gui[i].y + 70 + yycount ,""+ucount,color,game.fonts[Resources.FONT].font,false);//13mar2021
                                    RenderList.drawtext(game,game.gui[i].x+75 + xxcount,game.gui[i].y + 70 + yycount ,""+Translation.TranslateNumber(ucount),color,game.fonts[Resources.FONT].font,false);//13mar2021
                                    xxcount+=70;
                                    if(xxcount > 370)
                                    {
                                        xxcount = -40;
                                        yycount+=70;
                                    }
                                }
                            }
                            //start--------------//1mar2022
                            if(xxcount <= 370)
                            {
                                yycount+=70;
                                xxcount = -40;
                            }
                            RenderList.drawtext(game,game.gui[i].x+75 + xxcount,game.gui[i].y + 70 + yycount ,Translation.TranslateWord("Top Mission Score:",false)+""+Translation.TranslateNumber(Game.TopScore),color,game.fonts[Resources.FONT].font,false);//13mar2021
                            //end----------------//1mar2022
                            //end---------------//11mar2021
                        }
                    }
                    if(game.gui[i].tooltip!="" && game.gui[i].mouseover==true)
                    {
                        RenderList.drawtext(game,game.gui[i].x+game.gui[i].w / 4,game.gui[i].y + game.gui[i].h / 2 + ((20 * game.gui[i].h) / 100),game.gui[i].tooltip,RenderList.getrgb(182,182,182),game.fonts[Resources.SMALLFONT].font,false);                        
                    }
                    if(game.gui[i].triggerlink==LINK_SELECTION_TEXT)
                    {
                        if(uid!=-1)
                        {
                            int uframe = game.units[uid].animmodeidleframestart;
                            int uyoff = (game.gui[i].h / 2);
                            int uxoff = (game.gui[i].w / 4);
                            uframe += (game.frame / (game.units[uid].animspeed*2)) % (1 + game.units[uid].animmodeidleframeend - game.units[uid].animmodeidleframestart);
                            if(uframe > game.units[uid].animmodeidleframeend)
                            {
                                uframe = game.units[uid].animmodeidleframestart;
                            }
                            float ss = 0.8f * (70f/(float)game.units[uid].ch);
                            //9apr2021 cathires stuff
                            if(game.units[uid].cathires!=-1)
                            {
                                RenderList.drawimage(game,game.images[game.units[uid].cathires].texture,game.gui[i].x + uxoff,game.gui[i].y + uyoff,0,ss/2,ss/2,uframe,0,false,1f,game.units[uid].cathires);    
                            }
                            else
                            {
                                RenderList.drawimage(game,game.images[game.units[uid].cat].texture,game.gui[i].x + uxoff,game.gui[i].y + uyoff,0,ss,ss,uframe,0,false,1f,game.units[uid].cat);    
                            }
                            color = RenderList.getrgb(255,255,200);
                            if(game.units[uid].faction!=Game.PLAYERFACTION && game.units[uid].faction!=Unit.NULLFACTION)
                            {
                                color = RenderList.getrgb(255,160,160);
                            }
                            for(int j=0;j<4;j++)
                            {
                                if(uline[j]!="")
                                {
                                    //todo needs translation.....13mar2021
                                    RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.SMALLFONT].ptsize) * (j-2),uline[j],color,game.fonts[Resources.SMALLFONT].font,false);
                                }
                            }
                        }
                    }
                    //start---------------//23sep2021
                    if(game.gui[i].command.IndexOf("buycost")>=0)
                    {
                        game.gui[i].title = ""+Tech.GoldCostGui(game,game.gui[i].action);
                    }
                    if(game.gui[i].command.IndexOf("buydescription")>=0 && game.gui[i].action!=ACTION_NONE)
                    {
                        int factor = 5;
                        string[] txtdesc = Tech.GetDescription(game,game.gui[i].action);
                        for(int j=0;j<txtdesc.Length;j++)
                        {
                            if(txtdesc[j]!="")
                            {
                                //Gui.checksum++;
                                RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),game.gui[i].y + (factor + 4 + game.fonts[Resources.FONT].ptsize) * (j-1),txtdesc[j],color,game.fonts[Resources.FONT].font,false);
                            }
                        }
                    }
                    if(game.gui[i].command.IndexOf("buyimage")>=0)
                    {
                        if(game.gui[i].action==ACTION_NONE)
                        {
                            game.gui[i].image = -1;
                            game.gui[i].index = 0;
                        }
                        else
                        {
                            game.gui[i].image = Tech.GetSaleImage(game,game.gui[i].action);
                            game.gui[i].index = Tech.GetSaleImageIndex(game,game.gui[i].action);
                        }
                    }
                    //end-----------------//23sep2021
                    if(game.gui[i].triggerlink==Gui.LINK_UNIT_DETAIL)
                    {
                        if(game.gui[i].index!=-1)
                        {
                            uid = game.gui[i].index;
                            int uframe = game.templates[uid].animmodeidleframestart;
                            int udirn = game.gui[i].uindex;
                            int uyoff = (game.gui[i].h / 2) ;
                            int uxoff = (game.gui[i].w / 8);
                            uframe += (game.frame / (game.templates[uid].animspeed*2)) % (1 + game.templates[uid].animmodeidleframeend - game.templates[uid].animmodeidleframestart);
                            int ssx = 1;
                            if(uframe > game.templates[uid].animmodeidleframeend)
                            {
                                uframe = game.templates[uid].animmodeidleframestart;
                            }
                            game.gui[i].uindex = udirn;
                            //float ss = 2.0f * (70f/(float)game.templates[uid].ch);//22mar2021
                            float ss = 4.0f * (70f/(float)game.templates[uid].ch);//22mar2021
                            //RenderList.drawimage(game,game.images[game.templates[uid].cat].texture,game.gui[i].x + uxoff,game.gui[i].y + uyoff+game.templates[uid].offy,0,ss*ssx,ss,uframe+udirn*game.templates[uid].framesperdirn,0,false,1f,game.templates[uid].cat);    //22mar2021
                            //9apr2021 cathires stuff
                            //20apr2021 added offx
                            if(game.templates[uid].cathires!=-1)
                            {
                                RenderList.drawimage(game,game.images[game.templates[uid].cathires].texture,game.gui[i].x + uxoff + game.templates[uid].offx,game.gui[i].y + uyoff+game.templates[uid].offy + 50,0,ss*ssx/2,ss/2,uframe+udirn*game.templates[uid].framesperdirn,0,false,1f,game.templates[uid].cathires);    //22mar2021
                            }
                            else
                            {
                                RenderList.drawimage(game,game.images[game.templates[uid].cat].texture,game.gui[i].x + uxoff + game.templates[uid].offx ,game.gui[i].y + uyoff+game.templates[uid].offy + 50,0,ss*ssx,ss,uframe+udirn*game.templates[uid].framesperdirn,0,false,1f,game.templates[uid].cat);    //22mar2021
                            }
                            color = RenderList.getrgb(255,255,200);
                            if(game.templates[uid].faction!=Game.PLAYERFACTION && game.templates[uid].faction!=Unit.NULLFACTION)
                            {
                                //color = RenderList.getrgb(255,160,160);
                            }
                            int jj = 0;
                            //RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (jj-4),game.templates[uid].name,color,game.fonts[Resources.FONT].font,false); //13mar2021
                            RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (jj-4),game.templates[uid].dname(),color,game.fonts[Resources.FONT].font,false); //13mar2021
                            //string txt = "HP " + game.templates[uid].basehp+ " MV "+game.templates[uid].walkspeed + " ATT "+game.templates[uid].damage + " DEF "+game.templates[uid].armour;//13mar2021
                            //string txt = "HP " + Translation.TranslateNumber(game.templates[uid].basehp)+ " MV "+Translation.TranslateNumber(game.templates[uid].walkspeed) + " ATT "+Translation.TranslateNumber(game.templates[uid].damage) + " DEF "+Translation.TranslateNumber(game.templates[uid].armour);//13mar2021//28feb2022
                            string txt = "HP " + Translation.TranslateNumber(game.templates[uid].basehp)+ " MV "+Translation.TranslateNumber(game.templates[uid].walkspeed) + " ATT "+Translation.TranslateNumber(game.templates[uid].damage) + " DEF "+Translation.TranslateNumber(game.templates[uid].armour) + " ACC " + Translation.TranslateNumber(game.templates[uid].accuracy) +"%";//13mar2021//28feb2022
                            RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (jj-3),txt,color,game.fonts[Resources.FONT].font,false);
                            txt = Unit.gettemplatetext(game,uid)[0];
                            for(int j=0;j<game.templates[uid].description.Length;j++)
                            {
                                if(game.templates[uid].description[j]!="")
                                {
                                    RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (j-1),game.templates[uid].description[j],color,game.fonts[Resources.FONT].font,false);
                                }
                            }
                            color = RenderList.getrgb(200,200,150);
                            //16sep2021 modified to not show this on space squad
                            if(Config.NOSHOWABILITY==0)//16sep2021
                            {
                                RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (game.templates[uid].description.Length+1),txt,color,game.fonts[Resources.FONT].font,false);
                                if(Unit.gettemplatetext(game,uid)[1].Length>0)
                                {
                                    RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),uyoff + game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * (game.templates[uid].description.Length+2),Unit.gettemplatetext(game,uid)[1],color,game.fonts[Resources.FONT].font,false);
                                }
                            }
                        }
                        else
                        {
                            game.gui[i].index = Unit.gettemplate(game,0,1,0);
                            RenderList.drawtext(game,game.gui[i].x + ((2 * game.gui[i].w)/5),game.gui[i].y + (4 + game.fonts[Resources.FONT].ptsize) * 1,""+game.gui[i].index,color,game.fonts[Resources.FONT].font,false);
                        }
                    }
                    //start----------------//17sep2021
                    if(game.oldgamestate != Game.CAT_GAMESTATE_GAME && game.oldgamestate != Game.CAT_GAMESTATE_REPLAY)
                    {
                        if(game.gui[i].type==TYPE_MINIMAP)
                        {
                            if(Game.chosenmissionindex!=Game.ochosenmissionindex)
                            {
                                Game.ochosenmissionindex = Game.chosenmissionindex;
                                if(Game.chosenmissionindex!=-1)
                                {
                                    int ostate = game.gamestate;
                                    Map.levelseed = Functions.seed;//2apr2021
                                    Map.MINIMAPMODE = true;//18sep2021
                                    Program.resetgame(game);//2apr2021
                                    Program.cleardeaths(game);
                                    game.map = new Map();
                                    Program.setupmission(game,Game.chosenmissionindex,99);
                                    //Map.adddecor();//2mar2021
                                    //Map.marktreepos(game);
                                    Map.levelseed2 = Functions.seed;//2apr2021
                                    game.gamestate = ostate;
                                    Map.MINIMAPMODE = false;//18sep2021
                                }
                                
                            }
                            if(Map.treepositions==null)
                            {
                                continue;
                            }
                            if(game.units==null)
                            {
                                continue;
                            }
                            
                        }
                    }
                    //end------------------//17sep2021
                    if(game.gui[i].type==TYPE_MINIMAP)
                    {
                        for(int j=0;j<Map.treepositions.Length;j++)
                        {
                            int xx = Map.treepositions[j] % Map.MAXX;
                            int yy = (Map.treepositions[j] - xx) / Map.MAXX;
                            uint grey = RenderList.getrgb(50,50,40);
                            RenderList.drawrect(game,game.gui[i].x + (xx)* game.gui[i].w / Map.MAXX,game.gui[i].y + (yy) * game.gui[i].h / Map.MAXY,2,2,grey,0);
                        }
                        //for(int j=0;j<game.units.Length;j++)//26mar2021
                        for(int j=0;j<=Unit.MAXINDEX;j++)//26mar2021
                        {
                            if(game.units[j].hp>0)
                            {
                                uint friend = RenderList.getrgb(96,255,96);
                                uint enemy = RenderList.getrgb(255,96,96);
                                if(game.units[j].faction==Game.PLAYERFACTION)
                                {
                                    RenderList.drawrect(game,game.gui[i].x + (game.units[j].x / Map.GRIDW)* game.gui[i].w / Map.MAXX,game.gui[i].y + (game.units[j].y / Map.GRIDH) * game.gui[i].h / Map.MAXY,2,2,friend,0);
                                }
                                else
                                {
                                    if(Map.isfogged(game.units[j].x,game.units[j].y)==false)
                                    {
                                        RenderList.drawrect(game,game.gui[i].x + (game.units[j].x / Map.GRIDW)* game.gui[i].w / Map.MAXX,game.gui[i].y + (game.units[j].y / Map.GRIDH) * game.gui[i].h / Map.MAXY,2,2,enemy,0);
                                    }
                                }
                                //RenderList.drawunfilledrect(game,game.gui[i].x + (Game.CORNERX / Map.GRIDW) * game.gui[i].w / Map.MAXX,game.gui[i].y + (Game.CORNERY / Map.GRIDH) * game.gui[i].h / Map.MAXY,(Game.RESOLUTIONX / Map.GRIDW) * game.gui[i].w / Map.MAXX,(Game.RESOLUTIONY / Map.GRIDH) * game.gui[i].h / Map.MAXY,RenderList.getrgb(255,255,200),0);//16sep2021
                                if(game.units[j].ping>0)//16sep2021
                                {
                                    uint ping = RenderList.getrgb(96,255,255);
                                    int size = 1 + ((game.frame/10) % 6);
                                    RenderList.drawunfilledrect(game,game.gui[i].x + (game.units[j].x / Map.GRIDW)* game.gui[i].w / Map.MAXX - size,game.gui[i].y + (game.units[j].y / Map.GRIDH) * game.gui[i].h / Map.MAXY - size,2*size,2*size,ping,0);
                                }                                
                            }
                            else//17sep2021
                            {
                                if(game.units[j].redping>0)
                                {
                                    uint redping = RenderList.getrgb(255,96,64);
                                    int size = 1 + ((game.frame/10) % 6);
                                    RenderList.drawunfilledrect(game,game.gui[i].x + (game.units[j].x / Map.GRIDW)* game.gui[i].w / Map.MAXX - size,game.gui[i].y + (game.units[j].y / Map.GRIDH) * game.gui[i].h / Map.MAXY - size,2*size,2*size,redping,0);
                                    game.units[j].redping--;
                                }
                            }
                        }
                        RenderList.drawunfilledrect(game,game.gui[i].x + (Game.CORNERX / Map.GRIDW) * game.gui[i].w / Map.MAXX,game.gui[i].y + (Game.CORNERY / Map.GRIDH) * game.gui[i].h / Map.MAXY,(Game.RESOLUTIONX / Map.GRIDW) * game.gui[i].w / Map.MAXX,(Game.RESOLUTIONY / Map.GRIDH) * game.gui[i].h / Map.MAXY,RenderList.getrgb(255,255,200),0);//16sep2021
                        if(game.gui[i].action==ACTION_MINIMAPSCANLINE)
                        {
                            //special effects.......
                            uint scanline = RenderList.getrgb(160,160,192);
                            int scany = (game.frame/2) % (1 + game.gui[i].h);
                            RenderList.drawunfilledrect(game,game.gui[i].x,game.gui[i].y + scany,game.gui[i].w,2 ,scanline,0);//16sep2021
                        }
                        //if(game.gui[i].mouseover==true && game.mldown==true)//11mar2021
                        //if(game.gui[i].mouseover==true && game.mldown==true && Functions.abs(game.fmx - game.smx)<10 && Functions.abs(game.fmy - game.smy)<10)//11mar2021//28mar2021
                        //start---------------//28mar2021
                        bool specialmouseover = false;
                        if(game.smx > game.gui[i].x && game.smx < game.gui[i].x + game.gui[i].w && game.smy > game.gui[i].y && game.smy < game.gui[i].y + game.gui[i].h)
                        {
                            if(game.fmx > game.gui[i].x && game.fmx < game.gui[i].x + game.gui[i].w && game.fmy > game.gui[i].y && game.fmy < game.gui[i].y + game.gui[i].h)
                            {
                                specialmouseover = true;
                            }
                        }
                        //end-----------------//28mar2021
                        if(game.gui[i].mouseover==true && game.mldown==true && ((Functions.abs(game.fmx - game.smx)<10 && Functions.abs(game.fmy - game.smy)<10) || specialmouseover==true))//28mar2021
                        {
                            if(!Replay.IsPlaying())//21apr2021
                            {
                                Game.CORNERX = Map.GRIDW * (Map.MAXX * (game.mx - game.gui[i].x) / game.gui[i].w) - (Game.RESOLUTIONX / 2);
                                Game.CORNERY = Map.GRIDH * (Map.MAXY * (game.my - game.gui[i].y) / game.gui[i].h) - (Game.RESOLUTIONY / 2);
                            }
                        }
                        if(game.gui[i].mouseover)
                        {
                            game.minimapframe = game.frame;
                        }
                        if(game.gui[i].mouseover==true && game.mrclick==true && game.paused==false)
                        {
                            //issue an order....
                            Unit.issueorder(game,Map.GRIDW * (Map.MAXX * (game.mx - game.gui[i].x) / game.gui[i].w),Map.GRIDH * (Map.MAXY * (game.my - game.gui[i].y) / game.gui[i].h));
                        }
                    }
                }
            }
        }
    }
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Gibbet
    {
        public static int MAXGIBBET = 100 * Config.FACTOR * 10;
        public static int MAXINDEX = 0;
        public static float ACCELERATION = 0.25f;
        public static float GROUNDH = 65.0f;
        public static int GIBCOUNTER = 0;
        public static int GIBMOD = 8;
        public static float VX = 1.5f;
        public static float VY = 5f;
        public static float ELASTIC = -0.5f;
        public static float MINVY = 0.01f;
        public static int LIFE = 180;
        //
        public int img; //(array index into game.images[img]
        public int imgindex; //0-99 (sub position within the cell)
        public int subx;
        public int suby;
        public int subw;
        public int subh;
        public float vx;
        public float vy;
        public float x;
        public float y;
        public float h;
        public float yy;
        public int scrx;
        public int scry;
        public int life;
        public float angle;
        
        ///////////////////Method Definition///////////////
        public Gibbet()
        {
            img = -1;
            life = 0;
        }
        
        ///////////////////Method Definition///////////////
        public static void clearall(Game game)
        {
            for(int i=0;i<MAXGIBBET;i++)
            {
                game.gibbet[i].life = 0;
            }
            MAXINDEX = 0;
        }
        
        ///////////////////Method Definition///////////////
        public static void makegibbets(Game game,int unitid)
        {
            Functions.saveseed(Functions.seed);
            int index = 0;
            for(int i=0;i<MAXGIBBET;i++)
            {
                if(game.gibbet[i].life<=0)
                {
                    if(i>MAXINDEX)
                    {
                        MAXINDEX = i;
                    }
                    game.gibbet[i] = new Gibbet(game,game.units[unitid].cat,index,game.units[unitid].x,game.units[unitid].y,game.units[unitid].offy);
                }
                index++;
                if(index>=99)
                {
                    break;
                }
            }
            Functions.restoreseed();
        }
        
        ///////////////////Method Definition///////////////
        public Gibbet(Game game,int lpimg,int lpimgindex,int lpmapx,int lpmapy,int lpoffy)
        {
            img = lpimg;
            imgindex = lpimgindex;
            x = (float)lpmapx;
            y = (float)lpmapy;
            yy = 0;
            h = (float)lpoffy;
            angle = (float)Functions.rand(0,628)*0.01f;
            if(lpimg>=0 && lpimg<game.images.Length)
            {
                int wx = game.images[img].cwx / 10;
                int wy = game.images[img].chy / 10;
                int ix = imgindex % 10;
                int iy = (imgindex - ix) / 10;
                subx = wx * ix;
                suby = wy * iy;
                subw = wx;
                subh = wy;
                life = LIFE;
                vx = (float)Functions.rand(-100,100) * 0.01f * VX;
                vy = (float)Functions.rand(-100,25) * 0.01f * VY;
                x+=subx - wx/2;
                y+=suby - wy/2;
                yy+=suby;
            }
            else
            {
                img = -1;
                life = 0;
            }
        }
        
        ///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            for(int i=0;i<=MAXINDEX;i++)
            {
                if(game.gibbet[i].life>0)
                {
                    game.gibbet[i].life--;
                    game.gibbet[i].x+=game.gibbet[i].vx * (float)(Config.delta)/100f;//18sep2021
                    game.gibbet[i].y+=game.gibbet[i].vy * (float)(Config.delta)/100f;//18sep2021
                    game.gibbet[i].yy+=game.gibbet[i].vy * (float)(Config.delta)/100f;//18sep2021
                
                    game.gibbet[i].vy+=ACCELERATION;
                    game.gibbet[i].scrx = (int)game.gibbet[i].x - Game.CORNERX;
                    game.gibbet[i].scry = (int)game.gibbet[i].y - Game.CORNERY + (int)game.gibbet[i].h;
                    game.gibbet[i].angle+=(float)Functions.sign(game.gibbet[i].vx)*0.05f;
                    if(game.gibbet[i].yy>GROUNDH)
                    {
                        game.gibbet[i].vy *= ELASTIC;
                    }
                    if(Functions.abs(game.gibbet[i].vy)<MINVY)
                    {
                        game.gibbet[i].life = 0;
                    }
                    if(game.gibbet[i].scrx < -100 || game.gibbet[i].scry < -100 || game.gibbet[i].scrx > Game.RESOLUTIONX + 100 || game.gibbet[i].scry > Game.RESOLUTIONY + 100)
                    {
                        game.gibbet[i].life = 0;
                    }
                }
                
                if(game.gibbet[i].life<=0 && i==MAXINDEX)
                {
                    MAXINDEX--;
                    if(MAXINDEX<0)
                    {
                        MAXINDEX = 0;
                    }
                }
            }
        }
        
        ///////////////////Method Definition///////////////
        public void draw(Game game)
        {
            RenderList.drawsubimage(game,game.images[img].texture,scrx,scry,angle,0.7f,0.7f,0,0,false,1f,img,subx,suby,subw,subh);        
        }
        
        ///////////////////Method Definition///////////////
        public static void drawall(Game game)
        {
            for(int i=0;i<=MAXINDEX;i++)
            {
                if(game.gibbet[i].life>0 && game.gibbet[i].scrx>=-100 && game.gibbet[i].scry>=-100 && game.gibbet[i].scrx<Game.RESOLUTIONX+100 && game.gibbet[i].scry<Game.RESOLUTIONY+100)
                {
                    game.gibbet[i].draw(game);
                }
            }
        }
        
    }
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Blood
    {
        public static int BLOODSPAWNER = 1000;
        public static int MAXBLOOD = 800 * Config.FACTOR;
        public static int NUMBLOOD = 20;
        public static int bloodcount = 0;
        public static float ACCELERATION = -0.2f;
        public static int DUSTCLOUD = 100;
        public static int SPELL = 200;
        public static int FIRESPELL = 201;
        public static int DARKSPELL = 202;
        public static int GOODSPELL = 203;
        public static int GREENSPELL = 204;//15mar2021
        public static int REDSPELL = 205;//15mar2021
        public static int LIGHTNINGSPELL = 206;//28mar2021
        public static int WHIRLWINDSPELL = 207;//28mar2021
        public static int WHIRLWINDGRID = 5;//28mar2021
        public float cx;
        public float cy;
        public float x;
        public float y;
        public float h;
        public float vx;
        public float vy;
        public float vh;
        public int life;
        public int red;
        public int green;
        public int blue;
        public int sizex;
        public int sizey;
        public float angle;
        public int magic;//28mar2021
        public int ismagic;

///////////////////Method Definition///////////////
        public Blood(int sx,int sy)
        {
            x = (float)sx;
            y = (float)sy;
            cx = sx;
            cy = sy;
            life = 90;
            h = 1.8f;
            angle = (float) Functions.rand(0,400) / 60f;
            vh = 2f * (float)(Functions.rand(70,100)) / 100f;
            vx = -2f * (float)(Functions.rand(-50,50)) / 100f;
            vy = -2f * (float)(Functions.rand(-50,50)) / 100f;
            red = Functions.rand(192,255);
            green = Functions.rand(32,128);
            blue = Functions.rand(96,160);
            sizex = Functions.rand(1,5);
            sizey = Functions.rand(1,5);
            ismagic = 0;
        }

///////////////////Method Definition///////////////
        public Blood()
        {
            //all set to zero....
        }

///////////////////Method Definition///////////////
        public static void makeblood(Game game,int sx,int sy,int magic)
        {
            //make a blood or fiery or spell effect in game
            Functions.saveseed(Functions.seed);
            sy += Map.getheight(sx,sy);
            for(int j=0;j<Blood.NUMBLOOD;j++)
            {
                for(int i=0;i<game.blood.Length;i++)
                {
                    if(game.blood[i].life<=0)
                    {
                        game.blood[i].magic = magic;//28mar2021
                        game.blood[i].x = (float)sx;
                        game.blood[i].y = (float)sy;
                        game.blood[i].cx = (float)sx;
                        game.blood[i].cy = (float)sy;
                        game.blood[i].life = 120;
                        if(magic==LIGHTNINGSPELL)

                        {
                            game.blood[i].life = 2;
                        }
                        game.blood[i].h = 1.8f;
                        game.blood[i].vh = 3f * (float)(Functions.rand(70,100)) / 100f;
                        game.blood[i].vx = -1.5f * (float)(Functions.rand(-50,50)) / 100f;
                        game.blood[i].vy = -1.5f * (float)(Functions.rand(-50,50)) / 100f;
                        if(magic==WHIRLWINDSPELL)
                        {
                            game.blood[i].life = 2;
                            game.blood[i].vh = 0;
                            game.blood[i].vx = 0;
                            game.blood[i].vy = 0;
                        }
                        game.blood[i].red = Functions.rand(128,200);
                        game.blood[i].green = Functions.rand(16,96);
                        game.blood[i].blue = Functions.rand(32,128);
                        game.blood[i].sizex = Functions.rand(1,5);
                        game.blood[i].sizey = Functions.rand(1,5);    
                        game.blood[i].ismagic = magic;
                        if(magic>0 && magic<BLOODSPAWNER)
                        {
                            game.blood[i].red = Functions.rand(140,180);
                            game.blood[i].green = Functions.rand(100,140);
                            game.blood[i].blue = Functions.rand(80,120);
                            game.blood[i].h = 0.1f;
                        }
                        if(magic>=SPELL && magic<=SPELL+10)
                        {
                            game.blood[i].life = 30;
                            /*
                            game.blood[i].sizex/=2;
                            game.blood[i].sizey/=2;
                            if(game.blood[i].sizex<2)
                            {
                                game.blood[i].sizex = 2;
                            }
                            if(game.blood[i].sizey<2)
                            {
                                game.blood[i].sizey = 2;
                            }
                            *
/
                            game.blood[i].vh/=3;
                            game.blood[i].vx/=3;
                            game.blood[i].vy/=3;
                            game.blood[i].angle = (float) Functions.rand(0,400) / 60f;
                            if(magic==FIRESPELL)
                            {
                                game.blood[i].red = Functions.rand(180,250);
                                game.blood[i].green = Functions.rand(160,220);
                                game.blood[i].blue = Functions.rand(80,120);    
                                game.blood[i].sizex*=2;//16sep2021
                            }
                            if(magic==GOODSPELL)
                            {
                                game.blood[i].red = Functions.rand(30,80);
                                game.blood[i].green = Functions.rand(120,220);
                                game.blood[i].blue = Functions.rand(180,240);
                            }
                            if(magic==DARKSPELL)
                            {
                                game.blood[i].red = Functions.rand(180,250);
                                game.blood[i].green = Functions.rand(30,80);
                                game.blood[i].blue = Functions.rand(180,240);
                            }
                            //start-------//15mar2021
                            if(magic==GREENSPELL)
                            {
                                game.blood[i].red = Functions.rand(20,80);
                                game.blood[i].green = Functions.rand(180,250);
                                game.blood[i].blue = Functions.rand(80,160);    
                            }
                            if(magic==REDSPELL)
                            {
                                game.blood[i].red = Functions.rand(180,250);
                                game.blood[i].green = Functions.rand(30,80);
                                game.blood[i].blue = Functions.rand(30,80);
                            }
                            //end---------//15mar2021
                        }
                        if(magic>BLOODSPAWNER)
                        {
                            game.blood[i].h = 0.1f;
                            if(magic-BLOODSPAWNER==Game.PLAYERFACTION)
                            {
                                game.blood[i].red = Functions.rand(80,120);
                                game.blood[i].green = Functions.rand(180,240);
                                game.blood[i].blue = Functions.rand(80,120);
                            }
                            if(magic-BLOODSPAWNER==Game.SKIRMISHENEMYFACTION)
                            {
                                game.blood[i].green = Functions.rand(80,120);
                                game.blood[i].red = Functions.rand(180,240);
                                game.blood[i].blue = Functions.rand(180,240);
                            }
                        }
                        break;
                    }
                }
                if(magic==LIGHTNINGSPELL)//28mar2021
                {
                    break;
                }
                if(magic==WHIRLWINDSPELL)//28mar2021
                {
                    break;
                }
                if(magic>=FIRESPELL)//12apr2021
                {
                    if(Functions.rand(0,100)<33)
                    {
                        break;//12apr2021
                    }
                }
            }
            Functions.restoreseed();
        }

///////////////////Method Definition///////////////
        public static void clearall(Game game) //29oct2020
        {
            //remove all the fx from the visuals of the game
            for(int i=0;i<game.blood.Length;i++)
            {
                game.blood[i].life = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            //update all the visual fx
            bloodcount=0;
            for(int i=0;i<game.blood.Length;i++)
            {
                if(game.blood[i].life>0)
                {
                    bloodcount++;
                    game.blood[i].life--;
                    game.blood[i].x+=game.blood[i].vx * (float)(Config.delta)/100f;//18sep2021
                    game.blood[i].y+=game.blood[i].vy * (float)(Config.delta)/100f;//18sep2021
                    game.blood[i].h+=game.blood[i].vh * (float)(Config.delta)/100f;//18sep2021
                    game.blood[i].vh+=Blood.ACCELERATION;
                    if(game.blood[i].h<0)
                    {
                        game.blood[i].vh*=-0.5f;
                        game.blood[i].h=0;
                        game.blood[i].vx*=0.6f;
                        game.blood[i].vy*=0.6f;
                    }
                    //if(Functions.abs(game.blood[i].vx)<0.1f && Functions.abs(game.blood[i].vy)<0.1f)//28mar2021
                    if(Functions.abs(game.blood[i].vx)<0.1f && Functions.abs(game.blood[i].vy)<0.1f && game.blood[i].magic!=WHIRLWINDSPELL)//28mar2021
                    {
                        game.blood[i].life=0;
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void drawall(Game game)
        {
            //draw all the visual fx
            if(bloodcount>MAXBLOOD)
            {
                bloodcount=MAXBLOOD;
            }
            for(int i=0;i<bloodcount;i++)
            {
                if(game.blood[i].life>0)
                {
                    //23mar2021 check if on screen if not then don't draw
                    if(game.blood[i].x-Game.CORNERX>=-100 && game.blood[i].x-Game.CORNERX<Game.RESOLUTIONX+100 && game.blood[i].y - game.blood[i].h - Game.CORNERY>=-100 && game.blood[i].y - game.blood[i].h - Game.CORNERY<=Game.RESOLUTIONY+100)
                    {
                        if(game.blood[i].magic==LIGHTNINGSPELL && Game.lightning!=-1)

                        {
                            int frame = (int)Functions.abs(Functions.rand(0,1000)) % (game.images[Game.lightning].cwn * game.images[Game.lightning].chn);
                            RenderList.drawimage(game,game.images[Game.lightning].texture,(int)game.blood[i].x-Game.CORNERX,(int)(game.blood[i].y - game.blood[i].h)-Game.CORNERY - game.images[Game.lightning].chy/2,0,1f,1f,frame,1,false,1f,Game.lightning);    
                        }
                        else
                        {
                            if(game.blood[i].magic==WHIRLWINDSPELL && Game.whirlwind!=-1)
                            {
                                int frame = (int)Functions.abs((game.frame/10)) % (game.images[Game.whirlwind].cwn * game.images[Game.whirlwind].chn);
                                RenderList.drawimage(game,game.images[Game.whirlwind].texture,(int)game.blood[i].x-Game.CORNERX,(int)(game.blood[i].y - game.blood[i].h)-Game.CORNERY - game.images[Game.whirlwind].chy/2,0,0.5f,0.5f,frame,0,false,1f,Game.whirlwind);        
                            }
                            else
                            {
                                if(Game.spellball!=-1 && game.blood[i].magic>=FIRESPELL)//12apr2021
                                {
                                    int frame = 0;
                                    switch(game.blood[i].magic)
                                    {
                                        case 205:
                                        frame = Game.REDBALL;
                                        break;
                                        case 204:
                                        frame = Game.GREENBALL;
                                        break;
                                        case 203:
                                        frame = Game.BLUEBALL;
                                        break;
                                        case 201:
                                        frame = Game.ORANGEBALL;
                                        break;
                                        case 202:
                                        frame = Game.PURPLEBALL;
                                        break;
                                    }
                                    RenderList.drawimage(game,game.images[Game.spellball].texture,(int)game.blood[i].x-Game.CORNERX,(int)(game.blood[i].y - game.blood[i].h)-Game.CORNERY - game.images[Game.spellball].chy/2,game.blood[i].angle,0.7f+0.06f*(float)game.blood[i].sizex,0.7f+0.06f*(float)game.blood[i].sizex,frame,1,false,1f,Game.spellball);                                            
                                }
                                else
                                {
                                    RenderList.drawrect(game,(int)game.blood[i].x-Game.CORNERX,(int)(game.blood[i].y - game.blood[i].h) - Game.CORNERY,game.blood[i].sizex,game.blood[i].sizey,RenderList.getrgb(game.blood[i].red,game.blood[i].green,game.blood[i].blue),0);    
                                }
                            }
                        }
                    }
                }
            }
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Bullet
    {
        //for Archers
        public static int MAXBULLET = 200 * Config.FACTOR;
        public static int MAXINDEX = 0; //26mar2021
        public static float ACCELERATION = 0.05f;
        public float x;
        public float y;
        public float h; //height
        public int tx;
        public int ty;
        public float vx;
        public float vy;
        public float vh; //
        public int life;
        public static int nextfree = 0;
        public int flaming;
        public static int FIRESPELL = 201;
        public static int DARKSPELL = 202;
        public static int GOODSPELL = 203;
        //15mar2021 - added some more colours......
        public static int GREENSPELL = 204;
        public static int REDSPELL = 205;
        public static int LIGHTNINGSPELL = 206;//28mar2021
        public static int WHIRLWINDSPELL = 207;//28mar2021
        
///////////////////Method Definition///////////////
        public Bullet()
        {
            flaming = 0;
        }

///////////////////Method Definition///////////////
        public Bullet(int sx, int sy,int fx,int fy,int fiery)
        {
            flaming = fiery;
            x = sx;
            y = sy;
            h = 1.5f;
            float dist = 0.01f+(float)(Math.Sqrt((double)((sx-fx)*(sx-fx)+(sy-fy)*(sy-fy))));
            float dx = (float)(fx-sx)/dist;
            float dy = (float)(fy-sy)/dist;
            vx = 9f * dx;
            vy = 9f * dy;
            //vh = -5f;
            vh = -5f * (float)Functions.rand(80,200)/100f;
            life = 180;
            tx = fx;
            ty = fy;
        }

///////////////////Method Definition///////////////
        public static void createbullet(Game game,int sx,int sy, int fx, int fy,int fiery)
        {
            Functions.saveseed(Functions.seed);
            //create a bullet in the game
            if(nextfree<0 || nextfree>game.bullets.Length-1)//28mar2021
            {
                nextfree=0;
                Functions.restoreseed();
                return;
            }
            if(game.bullets[nextfree].life>0)
            {
                nextfree = -1;
                for(int i=0;i<MAXBULLET;i++)
                {
                    if(game.bullets[i].life<=0)
                    {
                        nextfree = i;
                        break;
                    }
                }
            }
            if(nextfree!=-1)
            {
                game.bullets[nextfree] = new Bullet(sx,sy,fx,fy,fiery);
            }
            Functions.restoreseed();
        }

///////////////////Method Definition///////////////
        public static void clearall(Game game) //ml29oct2020
        {
            //clear all bullets from the game
            for(int i=0;i<game.bullets.Length;i++)
            {
                game.bullets[i].life = 0;
            }
        }

///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            //update all bullets in the game
            //start---------------//26mar2021
            if(game.bullets[MAXINDEX].life<=0 && MAXINDEX>0)
            {
                MAXINDEX--;
            }
            //end-----------------//26mar2021
            for(int i=0;i<game.bullets.Length;i++)
            {
                game.bullets[i].update(game);
                if(game.bullets[i].life<=0)
                {
                    nextfree = i;
                }
                else //26mar2021
                {
                    if(i>MAXINDEX)
                    {
                        MAXINDEX = i;
                    }
                }
            }
        }

///////////////////Method Definition///////////////
        public static void drawall(Game game)
        {
            //draw all bullets in the game
            //for(int i=0;i<game.bullets.Length;i++)//26mar2021
            for(int i=0;i<=MAXINDEX;i++)    //26mar2021
            {
                game.bullets[i].draw(game);
            }
        }

///////////////////Method Definition///////////////
        public void update(Game game)
        {
            //update all bullets in the game
            if(life<=0)
            {
                return;
            }
            x+=vx * (float)(Config.delta)/100f;//18sep2021
            y+=vy * (float)(Config.delta)/100f;//18sep2021
            h+=vh * (float)(Config.delta)/100f;//18sep2021
            vh+=ACCELERATION;
            life--;
            if(h>=0)
            {
                life = 0;
            }
            if(Functions.abs(tx-x)<Map.GRIDW && Functions.abs(ty-y)<Map.GRIDH)
            {
                life = 0;
            }
            if(Functions.abs(flaming)>=Blood.FIRESPELL)
            {
                Blood.makeblood(game,(int)x,(int)y,(int)Functions.abs(flaming));
            }
        }

///////////////////Method Definition///////////////
        public void draw(Game game)
        {
            //draw all bullets in the game
            if(life<=0)
            {
                return;
            }
            int scrfx = (int)x - Game.CORNERX;
            int scrfy = (int)y - Game.CORNERY;
            int scrsx = (int)(x-vx) - Game.CORNERX;
            int scrsy = (int)(y-vy) - Game.CORNERY;
            int scrsh = (int)(h-vh);
            int scrfh = (int)h;
            if(flaming==0)
            {
                //23mar2021 only draw if on screen....
                if(scrsx>=-100 && scrsx<Game.RESOLUTIONX+100 && scrsy+scrfh>=-100 && scrsy+scrfh<=Game.RESOLUTIONY+100)
                {
                    //RenderList.drawline(game,scrsx,scrsy+scrfh,scrfx,scrfy + scrfh,RenderList.getrgb(12,12,12),0);//23mar2021
                    RenderList.drawline(game,scrsx,scrsy+scrsh,scrfx,scrfy + scrfh,RenderList.getrgb(12,12,12),0);//23mar2021
                }
            }
            else
            {
                //drawfireball(game,scrsx,scrsy,scrfx,scrfy);
            }
        }

///////////////////Method Definition///////////////
        public void drawfireball(Game game,int sx0,int sy0,int fx0,int fy0)
        {
            int sy = sy0;
            int fy = fy0;
            int sx = sx0;
            int fx = fx0;
            if(fy<sy)
            {
                fy = sy0;
                sy = fy0;
                fx = sx0;
                sx = fx0;
            }
            int hh = Functions.rand(2,4);
            int r = 255;
            int g = 255;
            int b = 255;
            for(int j=0;j<3;j++)
            {
                for(int l=0;l<hh;l++)
                {
                    if(flaming>0)
                    {
                        g+= Functions.rand(-32,0);    
                        b+= Functions.rand(-96,0);
                    }
                    else
                    {
                        r+= Functions.rand(-32,0);    
                        g+= Functions.rand(-96,0);
                    }
                    if(g<0)
                    {
                        g = 0;
                    }
                    if(b<0)
                    {
                        b = 0;
                    }
                    if(r<0)
                    {
                        r = 0;
                    }
                    int xadd = (l + 1) * (int)Functions.rand(- ((int)Functions.abs(fx-sx)+1),1 + (int)Functions.abs(fx-sx));
                    int yadd = (l + 1) * (int)Functions.rand(- ((int)Functions.abs(fy-sy)+1),1 + (int)Functions.abs(fy-sy));
                    if(Functions.abs(xadd)>4)
                    {
                        xadd = 4 * Functions.sign(xadd);
                    }
                    if(Functions.abs(yadd)>4)
                    {
                        yadd = 4 * Functions.sign(yadd);
                    }
                    if(Functions.rand(0,1000 + l * 200)<500)
                    {
                        if(flaming>1)
                        {
                            RenderList.drawrect(game,sx+xadd * 3,sy+yadd * 3,6 * 2,6 * 2,RenderList.getrgb(r,g,b),0);
                        }
                        RenderList.drawrect(game,sx+xadd,sy+yadd,6,6,RenderList.getrgb(r,g,b),0);
                    }
                }
            }
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class TriggerHelper
    {
        public static int TYPE_VICTORY = 1;
        public static int TYPE_IMMEDIATE_DEFEAT = 2;
        public static int TYPE_OR_DEFEAT = 18;
        public static int TYPE_IMMEDIATE_CHATTER = 3;
        public static int TYPE_CONDITIONAL_CHATTER = 4;
        //
        //
        public static int TYPE_NOCONDITION = 0;
        public static int TYPE_ACTIVATECHATTER = 5;
        public static int TYPE_DEATHCOUNT = 6;
        public static int TYPE_ACTIVATE = 10;
        //
        public static int TYPE_RETREAT = 7;
        public static int TYPE_FIRE = 8;
        public static int TYPE_SPAWNER = 9;
        public static int TYPE_HEALING = 11;
        public static int TYPE_MOVETO = 15;
        public static int TYPE_MAKEFRIEND = 12;
        public static int TYPE_MAKEENEMY = 13;
        public static int TYPE_MAKENEUTRAL = 14;
        public static int TYPE_SETAI = 17;
        public static int TYPE_CREATE = 20;//25mar2021
        public static int TYPE_REMOVE = 21;//25mar2021
        //
        public static int TYPE_LOOP = 16;
        public static string[] constructor = new string[17];
        public static int constructorindex = -1;
        public static string[] triggers = new string[40];
        public static int triggerindex = -1;
        public static int[] iflocation = new int[4];
        public static int[] atlocation = new int[4];
        public static int fieldindex = 0;
        public static int CONSTRUCTOR_IF = 0;
        public static int CONSTRUCTOR_N = 2;
        public static int CONSTRUCTOR_COMP = 1;
        public static int CONSTRUCTOR_UNIT = 3;
        public static int CONSTRUCTOR_X = 4;
        public static int CONSTRUCTOR_Y = 5;
        public static int CONSTRUCTOR_FX = 6;
        public static int CONSTRUCTOR_FY = 7;
        public static int CONSTRUCTOR_DO = 8;
        public static int CONSTRUCTOR_TO_UNIT = 9;
        public static int CONSTRUCTOR_AT_LOCATION = 10;
        public static int CONSTRUCTOR_REPEAT = 14;
        public static string CONSTRUCT_IFBRING = "-if bring";

        public static string CONSTRUCT_IFKILL = "-if kill";

        public static string CONSTRUCT_EXACTLY = "-exactly ";
        public static string CONSTRUCT_LESS = "-less than ";
        public static string CONSTRUCT_MORE = "-more than ";
        public static string CONSTRUCT_N = "-0 ";
        public static string CONSTRUCT_UNIT = "-unit ";
        public static string CONSTRUCT_TO = "-x,y,fx,fy ";
        public static string CONSTRUCT_THEN_DO = "-then do/say ";
        public static string CONSTRUCT_TO_UNIT = "-to unit/say ";
        public static string CONSTRUCT_AT_LOC = "-at location ";
        public static string CONSTRUCT_REPEAT = "-repeat ";

///////////////////Method Definition///////////////
        public static string CONSTRUCT_OK = "-Ok?(Left click to confirm right click to alter)";
        public static string[] field0 = {"-if bring","-if kill"};
        public static string[] field1 = {"-less than","-exactly","-more than"};
        public static int field2 = 0;
        public static int field1index = 0;
        public static int field3index = 0;
        public static int field9index = 0;
        public static int field8index = 0;
        public static int field14 = 0;
        public static int field15 = 0;
        public static string[] field8 = {"-victory ","-immediate defeat ","-'or' defeat ","-chatter ","-conditionalchatter ","-retreat ","-create fire ","-spawner alter ","-heal ","-move to ","-make friend ","-make enemy ","-make neutral ","-set ai ","-create ","-remove "};
        //in editor

///////////////////Method Definition///////////////
        public static void gettext(Game game)
        {
            //helper for the Trigger text
            constructorindex = 9;
            constructor[9] = Game.edittriggerstring;
            if(game.mlclick)
            {
                Game.EDITMODE = Game.EDITMODE_TRIGGER;
                constructor[10] = "x-300";
                constructor[11] = "y-780";
                atlocation[0] = 300;
                atlocation[1] = 780;
                constructor[12] = "fx-0";
                constructor[13] = "fy-0";
                constructor[14] = "0";
                constructorindex = 15;
                //constructorindex++;
                Game.edittriggerstring = "";
            }
            if(game.mrclick)
            {
                Game.EDITMODE = Game.EDITMODE_TRIGGER;
                constructor[constructorindex]="";
                Game.edittriggerstring = "";
                constructorindex--;
            }
        }

///////////////////Method Definition///////////////
        public static string constructorstring(Game game,bool leftclick, bool rightclick,int wheeldirn)
        {
            //return a string containing the 'programming language text' for the trigger
            //display only - in the game a list of numbers are mostly used
            string value = "";
            if(wheeldirn!=0)
            {
                switch(constructorindex)
                {
                    case 15:
                    field15+=wheeldirn;
                    //constructor[15]="-special:"+field15;//22mar2021
                    constructor[15]=Translation.TranslateWord("-special:",false)+field15;//22mar2021
                    string stxt = "";
                    if(field8index==3 || field8index==4)
                    {
                        //stxt = "-talk to:";//22mar2021
                        stxt = Translation.TranslateWord("-talk to:",false);//22mar2021
                    }
                    if(field8index==7)
                    {
                        //stxt = "-on(1)/off(-1):";//22mar2021
                        stxt = Translation.TranslateWord("-on(1)/off(-1):",false);//22mar2021
                    }
                    constructor[15] = stxt+field15;
                    break;
                    case 0: //if
                    fieldindex++;
                    fieldindex%=2;
                    //constructor[0] = field0[fieldindex];//22mar2021
                    constructor[0] = Translation.TranslateWord(field0[fieldindex],false);//22mar2021
                    break;
                    case 1: //comp
                    field1index+=(int)Functions.sign(wheeldirn);
                    if(field1index<0)
                    {
                        field1index=field1.Length - 1;
                    }
                    field1index%=field1.Length;
                    //constructor[1] = field1[field1index];//22mar2021
                    constructor[1] = Translation.TranslateWord(field1[field1index],false);//22mar2021
                    break;
                    case 2: //n
                    if(wheeldirn>0)
                    {
                        field2++;
                    }
                    else
                    {
                        field2--;
                    }
                    //constructor[2] = "-this many:"+field2;//22mar2021
                    constructor[2] = Translation.TranslateWord("-this many:",false)+field2;//22mar2021
                    break;
                    case 3: //unit
                    field3index+=wheeldirn;
                    if(field3index<0)
                    {
                        field3index = game.templates.Length - 1;
                    }
                    field3index%=game.templates.Length;
                    field3index=(int)Functions.abs(field3index);
                    field3index%=game.templates.Length;
                    //constructor[3] = "-"+game.templates[field3index].name+" to area:"; //22mar2021
                    constructor[3] = "-"+game.templates[field3index].dname()+Translation.TranslateWord(" to area:",false);//22mar2021
                    break;
                    case 8: //do
                    field8index+=wheeldirn;
                    if(field8index<0)
                    {
                        field8index = field8.Length - 1;
                    }
                    field8index%=field8.Length;
                    field8index=(int)Functions.abs(field8index);
                    if(field8index==4 && fieldindex==1)
                    {
                        field8index+=wheeldirn;
                        field8index%=field8.Length;
                        field8index=(int)Functions.abs(field8index);
                    }
                    field8index%=field8.Length;
                    constructor[8] = field8[field8index];//22mar2021
                    //constructor[8] = Translation.TranslateWord(field8[field8index],false);//22mar2021
                    break;
                    case 9: //to unit
                    field9index+=wheeldirn;
                    if(field9index<0)
                    {
                        field9index = game.templates.Length - 1;
                    }
                    field9index%=game.templates.Length;
                    field9index=(int)Functions.abs(field9index);
                    field9index%=game.templates.Length;
                    //constructor[9] = "-"+game.templates[field9index].name+" in area:";//22mar2021
                    constructor[9] = "-"+game.templates[field9index].dname()+Translation.TranslateWord(" in area:",false);//22mar2021
                    break;
                    case 14: //loop
                    field14+=wheeldirn;
                    //constructor[14] = "-repeat this often:"+field14;//22mar2021
                    constructor[14] = Translation.TranslateWord("-repeat this often:",false)+field14;//22mar2021
                    break;
                }
            }
            if(constructorindex<=3)
            {
                for(int l=0;l<4;l++)
                {
                    iflocation[l] = -1;
                }
            }
            if(constructorindex>=4 && constructorindex<=5)
            {
                constructor[4] = "-x" + Game.editgridx;
                constructor[5] = "-y" + Game.editgridy;
                iflocation[0] = Game.editgridx;
                iflocation[1] = Game.editgridy;
            }
            if(constructorindex>=6 && constructorindex<=7)
            {
                constructor[6] = "-fx" + Game.editgridx;
                constructor[7] = "-fy" + Game.editgridy;
                iflocation[2] = Game.editgridx;
                iflocation[3] = Game.editgridy;
            }
            if(constructorindex<=9)
            {
                for(int l=0;l<4;l++)
                {
                    atlocation[l] = -1;
                }
            }
            if(constructorindex>=10 && constructorindex<=11)
            {
                constructor[10] = "-x" + Game.editgridx;
                constructor[11] = "-y" + Game.editgridy;
                atlocation[0] = Game.editgridx;
                atlocation[1] = Game.editgridy;
            }
            if(constructorindex>=12 && constructorindex<=13)
            {
                constructor[12] = "-fx" + Game.editgridx;
                constructor[13] = "-fy" + Game.editgridy;
                atlocation[2] = Game.editgridx;
                atlocation[3] = Game.editgridy;
            }
            int oindex = constructorindex;
            if(leftclick)
            {
                if(constructorindex>=0)
                {
                    if(constructor[constructorindex]!="")
                    {
                        constructorindex++;
                        if(constructorindex==9)
                        {
                            if(field8index>=0 && field8index<=2)
                            {
                                //constructor[9] = "(none)";//22mar2021
                                constructor[9] = Translation.TranslateWord("(none)",false);//22mar2021
                                constructor[10] = "x-0";
                                constructor[11] = "y-0";
                                constructor[12] = "fx-100";
                                constructor[13] = "fy-100";
                                constructor[14] = "0";
                                constructor[15] = "0";
                                constructorindex = 16;
                            }
                        }
                        if(constructorindex==constructor.Length-1)
                        {
                            //constructor[constructorindex] = CONSTRUCT_OK;//22mar2021
                            constructor[constructorindex] = Translation.TranslateWord(CONSTRUCT_OK,false);//22mar2021
                        }
                    }
                }
                else
                {
                    constructorindex = 0;
                    //constructor[0] = field0[0];//22mar2021
                    constructor[0] = Translation.TranslateWord(field0[0],false);//22mar2021
                }
            }
            if(rightclick)
            {
                if(constructorindex>=0)
                {
                    constructor[constructorindex]="";
                }
                else
                {
                    //remove the last trigger....
                    if(triggerindex>=0)
                    {
                        for(int i=0;i<game.triggers.Length-1;i++)
                        {
                            if(game.triggers[i + 1].type==0)
                            {
                                Trigger.cleartrigger(game,i);
                                break;
                            }
                        }
                        triggers[triggerindex] = "";
                        triggerindex--;
                    }
                }
                constructorindex--;
                if(constructorindex>8)
                {
                    if(field8index>=0 && field8index<=2)
                    {
                        constructorindex=8;
                    }
                }
            }
            if(constructorindex==9 && oindex!=constructorindex)
            {
                if(field8index==3 || field8index==4)
                {
                    Game.EDITMODE=Game.EDITMODE_ENTERTEXT;
                }
            }
            if(constructorindex<0)
            {
                for(int i=0;i<constructor.Length;i++)
                {
                    constructor[i] = "";
                }
                constructorindex=-1;
                //return "{CLICK TO BEGIN}";//22mar2021
                return Translation.TranslateWord("{CLICK TO BEGIN}",false);//22mar2021
            }
            if(constructorindex>=constructor.Length)
            {
                //create conditional trigger.....
                parseconstructor(game);
                triggerindex++;
                triggerindex%=triggers.Length;
                for(int i=0;i<constructor.Length;i++)
                {
                    if(i<constructor.Length-1){triggers[triggerindex]+=constructor[i];}
                    if(i==8)//22mar2021
                    {
                        value+=Translation.TranslateWord(constructor[i],false); //22mar2021
                    }
                    else
                    {
                        value+=constructor[i];
                    }
                    constructor[i] = "";
                }
                constructorindex=-1;
                return value;
            }
            value = "";
            for(int i=0;i<constructor.Length;i++)
            {
                if(i==8)//22mar2021
                {
                    value+=Translation.TranslateWord(constructor[i],false);//22mar2021
                }
                else
                {
                    value+=constructor[i];
                }
            }
            if(constructorindex>=0 && constructorindex<constructor.Length)
            {
                if(constructor[constructorindex] == "" || constructorindex<constructor.Length-1)
                {
                    if(game.frame % 60<30)
                    {
                        //value+="{SCROLL TO SELECT}";    //22mar2021
                        value+=Translation.TranslateWord("{SCROLL TO SELECT}",false);    
                    }
                }
            }
            if(constructorindex<0)
            {
                if(game.frame % 60<30)
                {
                    //value+="{CLICK TO BEGIN}";//22mar2021
                    value+=Translation.TranslateWord("{CLICK TO BEGIN}",false);//22mar2021
                }
            }
            return value;
        }

///////////////////Method Definition///////////////
        public static void parseconstructor(Game game)
        {
            //convert the constructor string into the relevant trigger code
            int ctype = 0;
            int atype = 0;
            int cn = 0;
            int cc = 0;
            string cname = "";
            int[] cloc = {0,0,100,100};
            int[] anc = {0,0};
            string aname = "";
            int[] aloc = {0,0,100,100};
            int loops = 0;
            //if(constructor[CONSTRUCTOR_IF]==field0[0])//22mar2021
            if(constructor[CONSTRUCTOR_IF]==Translation.TranslateWord(field0[0],false))//22mar2021
            {
                ctype = 10; //or perhaps 5
            }
            else
            {
                ctype = 6;
            }
            cn = field2;
            cc = field1index-1;
            cname = game.templates[field3index].name;
            Int32.TryParse(constructor[4].Substring(2),out cloc[0]);    
            Int32.TryParse(constructor[5].Substring(2),out cloc[1]);    
            Int32.TryParse(constructor[6].Substring(3),out cloc[2]);    
            Int32.TryParse(constructor[7].Substring(3),out cloc[3]);    
            aname = game.templates[field9index].name;
            Int32.TryParse(constructor[10].Substring(2),out aloc[0]);    
            Int32.TryParse(constructor[11].Substring(2),out aloc[1]);    
            Int32.TryParse(constructor[12].Substring(3),out aloc[2]);    
            Int32.TryParse(constructor[13].Substring(3),out aloc[3]);    
            loops = field14;
            anc[0] = field15;
            switch(constructor[8])
            {
                case "-victory ":
                atype = 1;    
                for(int j=9;j<constructor.Length;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-immediate defeat ":
                atype = 2;
                for(int j=9;j<constructor.Length;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-'or' defeat ":
                atype = 18;
                for(int j=9;j<constructor.Length;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-chatter ":
                atype = 3;
                for(int j=10;j<15;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-conditionalchatter ":
                atype = 4;
                ctype = 5;
                for(int j=10;j<15;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-retreat ":
                atype = 7;
                for(int j=9;j<constructor.Length;j++)
                {
                    constructor[j] = "";
                }
                break;
                case "-create fire ":
                atype = 8;
                break;
                case "-spawner alter ":
                atype = 9;
                break;
                case "-heal ":
                atype = 11;
                break;
                case "-move to ":
                atype = 15;
                break;
                case "-make friend ":
                atype = 12;
                break;
                case "-make enemy ":
                atype = 13;
                break;
                case "-make neutral ":
                atype = 14;
                break;
                case "-set ai ":
                atype = 17;
                break;
                //start---------------//25mar2021
                case "-create ":
                atype = 20;
                break;
                case "-remove ":
                atype = 21;
                break;
                //end-----------------//25mar2021
            }
            conditionaltrigger(game,ctype,atype,cc, cn,cname,cloc,anc,aname,aloc,loops); //deliberately swapped cn and cc since got it wrong all the way through the next section
        }

///////////////////Method Definition///////////////
        public static void conditionaltrigger(Game game,int conditiontype,int actiontype,int conditionn, int conditioncomparator,string conditionunitname,int[] conditionlocation,int[] actionnc,string actionunitname,int[] actionlocation,int loops)
        {
            //specific type of trigger creation
            if(conditionlocation.Length!=4)
            {
                return;
            }
            if(actionnc.Length!=2)
            {
                return;
            }
            if(actionlocation.Length!=4)
            {
                return;
            }
            if(conditionunitname=="")
            {
                return;
            }
            if(actionunitname=="")
            {
                return;
            }
            if(loops<-1)
            {
                return;
            }
            int i = -1;
            for(int t=0;t<game.triggers.Length;t++)
            {
                if(game.triggers[t].type==0)
                {
                    i = t;
                    break;
                }
            }
            if(i==-1)
            {
                return;
            }
            conditionunitname.Replace(",","^");
            actionunitname.Replace(",","^");
            int initi = i;
            if(actiontype==3)
            {
                game.triggers[i] = new Trigger(game,3,actionnc[0],1,constructor[9].Replace(",","^"), 300, 780, 0, 0);
            }
            switch(conditiontype)
            {
                case 0: //no condition
                    game.triggers[i] = new Trigger(game,actiontype,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                break;
                case 5: //activate chatter only
                    switch(actiontype)
                    {
                        case 4: //conditional chatter only
                        game.triggers[i] = new Trigger(game,5,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,4,actionnc[0],1,constructor[9].Replace(",","^"), 300, 780, 0, 0);
                        break;
                    }
                break;
                case 6: //death count
                    switch(actiontype)
                    {
                        case 1://victory
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, actiontype, 0, 0, 0);
                        break;
                        case 2: //immediate defeat
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, actiontype, 0, 0, 0);
                        break;
                        case 18: //or defeat
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, actiontype, 0, 0, 0);
                        break;
                        case 7: //retreat
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, 7, 0, 0, 0);
                        break;
                        case 8: //fire
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,conditionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 9: //spawner
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 11: //healing
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 12: //make friend
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 13: //make enemy
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 14: //make neutral
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 15: //move to
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionlocation[1] * Map.GRIDW,actionlocation[0] * Map.GRIDH,actionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        break;
                        case 17: //setai
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        //start---------------//25mar2021
                        case 20: //create
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 21: //remove
                        game.triggers[i] = new Trigger(game,6,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        //end-----------------//25mar2021
                    }
                break;
                case 10: //activate
                    switch(actiontype)
                    {
                        case 1://victory
                        game.triggers[i] = new Trigger(game,1,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        break;
                        case 2: //immediate defeat
                        game.triggers[i] = new Trigger(game,2,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        break;
                        case 18: //or defeat
                        game.triggers[i] = new Trigger(game,18,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        break;
                        case 7: //retreat
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 8: //fire
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,conditionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 9: //spawner
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 11: //healing
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 12: //make friend
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 13: //make enemy
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 14: //make neutral
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,0,0,actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 15: //move to
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionlocation[1] * Map.GRIDW,actionlocation[0] * Map.GRIDH,actionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        break;
                        case 17: //setai
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        //start---------------//25mar2021
                        case 20: //create
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        case 21: //remove
                        game.triggers[i] = new Trigger(game,10,conditionn,conditioncomparator,conditionunitname, conditionlocation[0], conditionlocation[1], conditionlocation[2], conditionlocation[3]);
                        i++;
                        game.triggers[i] = new Trigger(game,actiontype,actionnc[0],actionnc[0],actionunitname, actionlocation[0], actionlocation[1], actionlocation[2], actionlocation[3]);
                        break;
                        //end-----------------//25mar2021
                    }
                break;
            }
            if(i>initi)
            {
                if(loops!=0)
                {
                    if(conditiontype==TYPE_ACTIVATE || conditiontype==TYPE_DEATHCOUNT)
                    {
                        i++;
                        game.triggers[i] = new Trigger(game,TYPE_LOOP,0,loops,conditionunitname, 0, 0, 0, 0);
                    }
                }
            }
        }
        //Trigger(Game game,int typ,int comp,int m,string name, int xx, int yy, int ww, int hh)

///////////////////Method Definition///////////////
        public TriggerHelper()
        {
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Trigger
    {
        public static int number;
        public static int MAXTRIGGER = 1000;
        public static int TYPE_VICTORY = 1;
        public static int TYPE_DEFEAT = 2;
        public static int TYPE_CHATTER = 3;
        public static int TYPE_INACTIVECHATTER = 4;
        public static int TYPE_ACTIVATECHATTER = 5;
        public static int TYPE_DEATHCOUNT = 6;
        public static int TYPE_RETREAT = 7;
        public static int TYPE_FIRE = 8;
        public static int TYPE_SPAWNER = 9;
        public static int DEFAULTSPAWNERCOUNT = 25;
        public static int TYPE_ACTIVATE = 10;
        public static int TYPE_HEALING = 11;
        public static int TYPE_MAKEFRIEND = 12;
        public static int TYPE_MAKEENEMY = 13;
        public static int TYPE_MAKENEUTRAL = 14;        
        public static int TYPE_MOVETO = 15;
        public static int TYPE_LOOP = 16;
        public static int TYPE_SETAI = 17;
        public static int TYPE_OR_DEFEAT = 18;
        public static int TYPE_SETCORNER = 19; //1mar2021
        //25mar2021 CREATION,REMOVAL and ANY FRIEND,ENEMY OR ALL Not Implemented Yet.
        public static int TYPE_CREATE = 20;//25mar2021
        public static int TYPE_REMOVE = 21;//25mar2021
        public static int TYPE_CHATTERBACKGROUNDIMAGE = 22;//10sep2021
        public static int TYPE_CHATTERAUDIO = 23;//10sep2021
        public static int TYPE_EXITTOMISSION = 24;//12sep2021
        public static int TYPE_SHOWBUTTON = 25;//23sep2021
        public static int TYPE_HIDEBUTTON = 26;//23sep2021
        public static int TYPE_ADDITEMTOSTORE = 27;//23sep2021
        public static int TYPE_RESETSTORE = 28;//23sep2021
    
        //start-----------------//27dec2021
        public static int TYPE_VARIABLE = 30;
        public static int TYPE_CHECKVARIABLE = 31;
        public static int TYPE_ARTILLERY = 99;//23feb2022
        public static int TYPE_TIMER = 98;//23feb2022
        public static int TYPE_POINTS = 97;//23feb2022
        public static int TYPE_AIRSTRIKE = 96;//23feb2022
        public static int TYPE_PAUSETIMER = 95;//28feb2022
        public static int[] VARIABLE = new int[100]; //100 integer variables available
        public static int ElapsedMilliSeconds;
        public static float tmpMilliSeconds;
        public static Stopwatch TTimer = new Stopwatch();
        
        
        
        /*
        
        //NEW 23FEB2022**TYPE_ARTILLERY...
        
        Type_Artillery does the following:
        if the variable goes to 1 with a trigger then an artillery strike is launched.
        The strength of the artillery is mission/trigger dependant...
        //Every nth enemy is struck on the map according to the value of .fx
        //doing .y damage to it.
        //if .fy is non zero then friendly units are also struck.....
        
        //sample trigger expression for artillery is the following:
        trigger=31,0,1,NA,99,15,8,20
        trigger=30,0,0,NA,99,1,1,0
        trigger=16,-1,0,NA,0,0,0,0
        
        //what that would do is the following:
        //Every 2 seconds check if the value of VARIABLE 99 is greater than 0
        //if it is then decrement it.
        //the 15,8,20 indicates do 15 points of damage, one very 8th enemy and every 20th friendly unit
        //the trigger=16,-1 is a loop trigger
        //clearly you can only have 1 artillery trigger per map......
        
        
        
        Usage Of Variable Trigger Type
        Include a TYPE_VARIABLE trigger after an ACTIVATE or a DEATHCOUNT trigger
        the x value is the index into the VARIABLE array from 0-99
        the y value is the operator, 0 = increment, 1 = decrement, 2 = multiply, 3 = integer divide
        the fx value is the amount to do by, eg to increment by 100 then fx would be 100, to divide by 3 then fx would be 3 and so forth
        the value is stored inside VARIABLE[x] and is retained throughout the mission
        
        Include a TYPE_CHECKVARIABLE as a trigger type similar to TYPE_ACTIVATE except:
        the x value is the index as above
        the other parameters are not used.
        The comparator and n value are used to determine if the trigger should fire,
        if it fires then the subsequent trigger in the list fires, as if it were an activate trigger.
        
        //
        The purpose of this trigger is to allow for combined triggers to take effect but not necessarily at once.
        For example you might want a trigger to fire after a unit has moved to a number of places on the map in no particular order and you would do so by
        incrementing a variable by 1 at each location moved to. Then you would use a check variable trigger to see if the variable had reached a certain value
        indicating all locations have been moved to, if so then you would fire that other trigger.
        
            
        *
/
        
        //end-------------------//27dec2021
    
    
        public int img;//10sep2021
        public int audio;//10sep2021
        //
        public static string TYPE_FRIEND = "*FRIEND";//25mar2021
        public static string TYPE_ENEMY = "*ENEMY";//25mar2021
        public static string TYPE_ANY = "*ANY";//25mar2021
        
        public int type;
        public static int EQUAL = 0;
        public static int LESSTHAN = -1;
        public static int MORETHAN = 1;
        public int comparator;
        public int n;
        public string unitname;
        public int x;
        public int y;
        public int fx;
        public int fy;
        public int timelimit;
        public int skipped;//22feb2022
        public bool completed;
        public int completetime;
        public bool failed;
        public bool repeat;

///////////////////Method Definition///////////////
        public Trigger()
        {
            completed = false;
            repeat = false;
            failed = false;
            completetime = 180;
        }

///////////////////Method Definition///////////////
        public static void cleartrigger(Game game,int i)
        {
            //initialise triggers
            game.triggers[i].type = 0;
            game.triggers[i].comparator = 0;
            game.triggers[i].n = 0;
            game.triggers[i].unitname = "";
            game.triggers[i].x = 0;
            game.triggers[i].y = 0;
            game.triggers[i].fx = 0;
            game.triggers[i].fy = 0;
            game.triggers[i].img = -1;//10sep2021
            game.triggers[i].audio = -1;//10sep2021
        }

///////////////////Method Definition///////////////
        public Trigger(Game game,int typ,int comp,int m,string name, int xx, int yy, int ww, int hh)
        {
            type = typ;
            if(type!=0)
            {
                number++;
            }
            n = m;
            comparator = comp;
            unitname = name;
            if(unitname!=null){unitname.Replace("^",",");}
            x = xx;
            y = yy;
            if(ww==-1)
            {
                ww = Map.MAXX;
            }
            if(hh==-1)
            {
                hh = Map.MAXY;
            }
            fx = ww;
            fy = hh;
            completetime = 60 * 10;
            img = -1;//10sep2021
            audio = -1;//10sep2021
            //game.triggers[nexttrigger].timelimit = time;
            //game.triggers[nexttrigger].repeat = rpt;
        }

///////////////////Method Definition///////////////
        public static void updateall(Game game)
        {
            //update the triggers in the game
            //for defeat ALL defeat triggers must be completed
            int dcount = 0;
            int vcount = 0;
            //for victory ALL victory triggers must be completed
            game.paused = false;
            for(int i=0;i<Trigger.number;i++)
            {
                if(game.triggers[i].type==TYPE_CHATTER)
                {
                    game.playerready = true;
                    if(game.triggers[i].completed==false)
                    {
                        game.playerready=false;
                    }
                }
            }
            for(int i=0;i<Trigger.number;i++)
            {
                if(game.triggers[i].type==0)
                {
                    continue;
                }
                if(game.triggers[i].type==TYPE_OR_DEFEAT || game.triggers[i].type==TYPE_DEFEAT)
                {
                    dcount++;
                }
                if(game.triggers[i].type==TYPE_VICTORY)
                {
                    vcount++;
                }
                if(game.triggers[i].type==TYPE_DEATHCOUNT || game.triggers[i].type==TYPE_ACTIVATE)
                {
                    if(game.triggers[i].y==0 && game.triggers[i].fy==0)
                    {
                        if(game.triggers[i].x==TYPE_DEFEAT || game.triggers[i].x==TYPE_OR_DEFEAT)
                        {
                            dcount++;
                        }
                        if(game.triggers[i].x==TYPE_VICTORY)
                        {
                            vcount++;
                        }
                    }
                }
                if(game.triggers[i].type==TYPE_INACTIVECHATTER)
                {
                    continue;
                }
                if(game.triggers[i].completed==false)
                {
                    if(game.triggers[i].type==TYPE_CHATTER)
                    {
                        //stay on screen until a click is pressed......
                        string[] message = game.triggers[i].unitname.Split("|");
                        if(message.Length>0)
                        {
                            for(int j=0;j<message.Length;j++)
                            {
                                RenderList.drawtext(game,game.triggers[i].x,game.triggers[i].y + j * (4+game.fonts[Resources.FONT].ptsize),message[j],RenderList.getrgb(255,255,200),game.fonts[Resources.FONT].font,false);
                            }
                        }
                        //game.triggers[i].completetime--;
                        int triggerlink = game.triggers[i].n;
                        int index = game.triggers[i].comparator;
                        if(game.mlclick==true || game.mrclick==true)
                        {
                            game.triggers[i].completed = true;
                        }
                        else
                        {
                            game.paused = true;
                        }
                        if(triggerlink>0)
                        {
                            for(int j=0;j<game.gui.Length;j++)
                            {
                                if(game.gui[j].triggerlink==triggerlink)
                                {
                                    game.gui[j].hidden = 0;
                                    game.gui[j].index = index;
                                    //if(game.triggers[i].completed)//22feb2022
                                    if(game.triggers[i].completed && game.gui[j].type!=Gui.TYPE_BUTTON)//22feb2022
                                    {
                                        game.gui[j].hidden = 1;
                                    }
                                    if(game.gui[j].type==Gui.TYPE_BUTTON)//22feb2022
                                    {
                                        game.paused = false;
                                        game.triggers[i].completed = true;
                                    }
                                }
                            }
                            //start-----------------//10sep2021
                            if(i<game.triggers.Length)
                            {
                                for(int aa=1;aa<=2;aa++)
                                {
                                    if(i + aa >= game.triggers.Length)
                                    {
                                        continue;
                                    }
                                    if(game.triggers[i + aa].type!=TYPE_CHATTERAUDIO && game.triggers[i + aa].type!=TYPE_CHATTERBACKGROUNDIMAGE)
                                    {
                                        break;
                                    }
                                    if(game.triggers[i + aa].type==TYPE_CHATTERAUDIO)
                                    {
                                        if(game.triggers[i + aa].audio==-1)
                                        {
                                            game.triggers[i + aa].audio = Resources.LoadAudio(game,game.triggers[i + aa].unitname,false);//
                                            if(game.triggers[i + aa].audio!=-1)
                                            {
                                                game.triggers[i + aa].x = Audios.playsound(game.audios[game.triggers[i + aa].audio],Game.FXVOLUME);
                                            }
                                            else
                                            {
                                                game.triggers[i + aa].x = -1;
                                            }
                                        }
                                        if(game.triggers[i].completed)
                                        {
                                            Audios.stopchannel(game.triggers[i + aa].x);
                                            Audios.freeaudio(game.audios[game.triggers[i+aa].audio]);
                                        }
                                    }
                                    if(game.triggers[i + aa].type==TYPE_CHATTERBACKGROUNDIMAGE)
                                    {
                                        if(game.triggers[i + aa].img==-1)
                                        {
                                            //(Game game,string file,IntPtr renderer,int w,int h) //note the slight change.....added w and h as can't work out how to do it otherwise....
                                            game.triggers[i + aa].img = Resources.LoadImage(game,game.triggers[i + aa].unitname,game.renderer,game.triggers[i + aa].fx,game.triggers[i + aa].fy);
                                        }
                                        for(int j=0;j<game.gui.Length;j++)
                                        {
                                            if(game.gui[j].triggerlink==game.triggers[i + aa].n)
                                            {
                                                game.gui[j].hidden = 0;
                                                game.gui[j].index = 0;
                                                game.gui[j].image = game.triggers[i + aa].img;
                                                game.gui[j].tmpimage = game.triggers[i + aa].img;
                                                game.gui[j].x = game.triggers[i + aa].x;
                                                game.gui[j].y = game.triggers[i + aa].y;
                                                game.gui[j].w = game.triggers[i + aa].fx;
                                                game.gui[j].h = game.triggers[i + aa].fy;
                                                if(game.triggers[i].completed)
                                                {
                                                    game.gui[j].hidden = 1;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            //end-------------------//10sep2021
                        }
                        return;
                    }
                    else
                    {
                        //check if this one is completed....
                        if(game.triggers[i].timelimit>0)
                        {
                            if(game.frame % 60==0)
                            {
                                game.triggers[i].timelimit--;
                            }
                        }
                        if((game.frame + i) % 120 != 0)    
                        {
                            game.triggers[i].skipped++;//22feb2022
                            if(game.triggers[i].skipped>120)//22feb2022
                            {
                                game.triggers[i].skipped = 0;//22feb2022
                            }
                            else
                            {
                                continue;
                            }
                        }
                        int count = 0;
                        if(game.triggers[i].type==TYPE_DEATHCOUNT)
                        {
                            for(int d=0;d<game.templates.Length;d++)
                            {
                                //not implemented yet...23mar2021
                                //if(game.templates[d].name==game.triggers[i].unitname)//25mar2021
                                if(game.templates[d].name==game.triggers[i].unitname || (game.triggers[i].unitname==TYPE_ANY)|| (game.triggers[i].unitname==TYPE_FRIEND && game.templates[d].faction==Game.PLAYERFACTION) || (game.triggers[i].unitname==TYPE_ENEMY && game.templates[d].faction!=Game.PLAYERFACTION && game.templates[d].faction!=Unit.NULLFACTION))//25mar2021
                                {
                                    count+=game.templates[d].deaths;
                                }
                            }                        
                        }
                        else
                        {
                            if(game.triggers[i].type==TYPE_CHECKVARIABLE)//27dec2021
                            {
                                int variable = game.triggers[i].x;
//                                Console.WriteLine("Trigger Variable Index:"+variable);
                                if(variable>=0 && variable<Trigger.VARIABLE.Length)
                                {
                                    count = Trigger.VARIABLE[variable];
                                }
                                if(count>0)
                                {
                                    //Console.WriteLine("Trigger Variable Greater Than Zero:"+count);
                                }
                                if(variable==TYPE_ARTILLERY)
                                {
                                    //Console.WriteLine("Artillery countdown:"+count);
                                }
                                //start--------------//23feb2022
                                if(count==1 && (variable==TYPE_ARTILLERY || variable==TYPE_AIRSTRIKE))
                                {
                                    //Console.WriteLine("Artillery firing");
                                    //game.triggers[i].completed = true;
                                    //int j = i + 1;
                                    //if(j<game.triggers.Length)
                                    //{
                                        //game.triggers[j].completed = true;
                                    //}
                                    //do artillery strike........
                                    //hitpoints damage = game.triggers[i].y
                                    //striking every fx'th enemy unit
                                    if(game.triggers[i].fx<1)
                                    {
                                        game.triggers[i].fx = 1;
                                    }
                                    RenderList.screenshake = 30;//23feb2022
                                    for(int u=0;u<game.units.Length;u++)
                                    {
                                        if(game.units[u].hp>0 && game.units[u].faction!=Game.PLAYERFACTION && game.units[u].faction!=Unit.NULLFACTION)
                                        {
                                            
                                            if((u + game.frame) % game.triggers[i].fx==0)
                                            {
                                        //        Console.WriteLine("enemy struck");
                                                game.units[u].hp-=game.triggers[i].y;
                                                if(game.units[u].hp<=0)
                                                {
                                                    game.killed(game,u);
                                                }
                                            }
                                        }
                                        if(game.units[u].hp>0 && game.units[u].faction==Game.PLAYERFACTION && game.triggers[i].fy>0)
                                        {
                                            if((u + game.frame) % game.triggers[i].fy==0)
                                            {
                                            //    Console.WriteLine("friends struck");
                                                game.units[u].hp-=game.triggers[i].y;
                                                if(game.units[u].hp<=0)
                                                {
                                                    game.killed(game,u);
                                                }
                                            }
                                        }
                                    }
                                    
                                }
                                //end----------------//23feb2022
                            }
                            else
                            {
                                
                                for(int xx=game.triggers[i].x;xx<=game.triggers[i].fx;xx++)
                                {
                                    for(int yy=game.triggers[i].y;yy<=game.triggers[i].fy;yy++)
                                    {
                                        int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                        if(nid!=-1)
                                        {
                                            //if(game.units[nid].name==game.triggers[i].unitname && game.units[nid].hp>0)//25mar2021
                                            if((game.units[nid].name==game.triggers[i].unitname || (game.triggers[i].unitname==TYPE_ANY) || (game.triggers[i].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[i].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                            {
                                                count++;
                                            }
                                        }
                                        //flying units.....
                                        for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                        {                                        
                                            int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                            if(fid!=-1)
                                            {
                                                nid = fid;
                                                if((game.units[nid].name==game.triggers[i].unitname || (game.triggers[i].unitname==TYPE_ANY) || (game.triggers[i].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[i].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                {
                                                    count++;
                                                    //Console.WriteLine("flyer found at:"+xx+", "+yy);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        switch(game.triggers[i].comparator)
                        {
                            case 0:
                            if(count==game.triggers[i].n)
                            {
                                game.triggers[i].completed = true;
                            }
                            break;
                            case -1:
                            if(count<game.triggers[i].n)
                            {
                                game.triggers[i].completed = true;
                            }
                            break;
                            case 1:
                            if(count>game.triggers[i].n)
                            {
                                game.triggers[i].completed = true;
                            }
                            break;
                        }
                        //if(game.triggers[i].completed==true && (game.triggers[i].type==TYPE_ACTIVATE || game.triggers[i].type==TYPE_DEATHCOUNT))//27dec2021
                        if(game.triggers[i].completed==true && (game.triggers[i].type==TYPE_ACTIVATE || game.triggers[i].type==TYPE_DEATHCOUNT || game.triggers[i].type==TYPE_CHECKVARIABLE))//27dec2021
                        {
                            int j = i + 1;
                            if(j<game.triggers.Length)
                            {
                                game.triggers[j].completed = false;//22feb2022
                                if(game.triggers[j].type==TYPE_SETAI)
                                {
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid!=-1)
                                            {
                                                //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                {
                                                    game.units[nid].ai = game.triggers[j].n; // ai
                                                    game.triggers[j].completed = true;        
                                                }
                                            }
                                            //flying units.....
                                            for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                            {                                        
                                                int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                if(fid!=-1)
                                                {
                                                    nid = fid;
                                                    //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                    if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                    {
                                                        game.units[nid].ai = game.triggers[j].n; // ai
                                                        game.triggers[j].completed = true;        
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                if(game.triggers[i].type==TYPE_ACTIVATE)
                                {
                                    if(game.triggers[j].type==TYPE_RETREAT)
                                    {
                                        for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                        {
                                            for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                            {
                                                int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                                if(nid!=-1)
                                                {
                                                    //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                    if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                    {
                                                        game.units[nid].retreat = true;
                                                        if(game.units[nid].retreatframe==0){game.units[nid].retreatframe = game.frame + Unit.RETREATDEATH;}
                                                    }
                                                }
                                                for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                                {                                        
                                                    int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                    if(fid!=-1)
                                                    {
                                                        nid = fid;
                                                        if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                        {
                                                            game.units[nid].retreat = true;
                                                            if(game.units[nid].retreatframe==0){game.units[nid].retreatframe = game.frame + Unit.RETREATDEATH;}
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                if(game.triggers[j].type==TYPE_MOVETO)
                                {
                                    int countunits = 0;
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid!=-1)
                                            {
                                                //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                {
                                                    countunits++;
                                                    int noffx = 0;
                                                    int noffy = 0;
                                                    if(countunits>1)
                                                    {
                                                        noffx = (int)Functions.rand(-Map.GRIDW*3,Map.GRIDW*3);
                                                        noffy = (int)Functions.rand(-Map.GRIDH*3,Map.GRIDH*3);
                                                    }
                                                    game.units[nid].tx = game.triggers[j].n + noffx; //x
                                                    game.units[nid].ty = game.triggers[j].comparator + noffy;
                                                    game.units[nid].tmptx = game.units[nid].tx;
                                                    game.units[nid].tmpty = game.units[nid].ty;
                                                    game.units[nid].tmptattempts = 0;
                                                    game.units[nid].firetargeti = -1;
                                                    game.units[nid].orderframe = Unit.ORDERTIME;
                                                    game.triggers[j].completed = true;        
                                                }
                                            }
                                            for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                            {                                        
                                                int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                if(fid!=-1)
                                                {
                                                    nid = fid;
                                                    if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                    {
                                                        countunits++;
                                                        int noffx = 0;
                                                        int noffy = 0;
                                                        if(countunits>1)
                                                        {
                                                            //noffx = (int)Functions.rand(-Map.GRIDW*3,Map.GRIDW*3);
                                                            //noffy = (int)Functions.rand(-Map.GRIDH*3,Map.GRIDH*3);
                                                        }
                                                        game.units[nid].tx = game.triggers[j].n + noffx; //x
                                                        game.units[nid].ty = game.triggers[j].comparator + noffy;
                                                        game.units[nid].tmptx = game.units[nid].tx;
                                                        game.units[nid].tmpty = game.units[nid].ty;
                                                        game.units[nid].tmptattempts = 0;
                                                        game.units[nid].firetargeti = -1;
                                                        game.units[nid].orderframe = Unit.ORDERTIME;
                                                        game.triggers[j].completed = true;    
                                                        //Console.WriteLine("Flyer given move order:"+game.units[nid].tmptx+","+game.units[nid].tmpty);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                //start---------------//23sep2021
                                if(game.triggers[j].type==TYPE_RESETSTORE)
                                {
                                    game.triggers[j].completed = true;
                                    for(int g=0;g<game.gui.Length;g++)
                                    {
                                        if(game.gui[g].command.IndexOf("buy")>=0 && game.gui[g].triggerlink==game.triggers[j].n)
                                        {
                                            //game.gui[g].action = Gui.ACTION_NONE;
                                        }
                                    }
                                }
                                if(game.triggers[j].type==TYPE_ADDITEMTOSTORE)
                                {
                                    game.triggers[j].completed = true;
                                    for(int g=0;g<game.gui.Length;g++)
                                    {
                                        if(game.gui[g].command.IndexOf("buy")>=0)
                                        {
                                            if(game.gui[g].command.IndexOf("buy")>=0 && game.gui[g].triggerlink==game.triggers[j].n)
                                            {
                                                //unitname = TechName or *TechClass, x = minimum cost or -1, y = maximum cost or -1
                                                Console.WriteLine("Choosing Item - "+game.triggers[j].unitname);
                                                Tech.ChooseItemForStore(game,g,game.triggers[j].unitname,game.triggers[j].x,game.triggers[j].y);
                                            }
                                        }
                                    }
                                }
                                if(game.triggers[j].type==TYPE_SHOWBUTTON)
                                {
                                    //eg do this:
                                    /*
                                     trigger=10,0,1,Hero,0,10,10,20
                                     trigger=25,-200,-200,na,0,0,100,100
                                     trigger=16,-1,-1,na,0,0,100,100
                                    
                                     and this will cause the gui button to show
                                     *
/
                                    game.triggers[j].completed = true;
                                    int triggerlink = game.triggers[j].n;
                                    for(int g=0;g<game.gui.Length;g++)
                                    {
                                        if(game.gui[g].triggerlink==triggerlink && game.gui[g].command.IndexOf("toggle")>=0)
                                        {
                                            if(game.gui[g].type==Gui.TYPE_BUTTON)
                                            {
                                                game.gui[g].hidden = 0;
                                            }
                                        }
                                    }
                                }
                                if(game.triggers[j].type==TYPE_HIDEBUTTON)
                                {
                                    //eg do this:
                                    /*
                                     trigger=10,0,1,Hero,0,10,10,20
                                     trigger=25,-200,-200,na,0,0,100,100
                                     trigger=16,-1,-1,na,0,0,100,100
                                    
                                     and this will cause the gui button to hide
                                     *
/
                                    game.triggers[j].completed = true;
                                    int triggerlink = game.triggers[j].n;
                                    for(int g=0;g<game.gui.Length;g++)
                                    {
                                        if(game.gui[g].triggerlink==triggerlink && game.gui[g].command.IndexOf("toggle")>=0)
                                        {
                                            if(game.gui[g].type==Gui.TYPE_BUTTON)
                                            {
                                                game.gui[g].hidden = 1;
                                            }
                                        }
                                    }
                                }
                                //end-----------------//23sep2021

                                //start---------------//12sep2021
                                if(game.triggers[j].type==TYPE_EXITTOMISSION)
                                {
                                    //load a new map.....
                                    game.triggers[j].completed = true;
                                    int missionindex = Mission.PickMission(game,game.triggers[j].unitname,game.triggers[j].n);
                                    if(missionindex!=-1)
                                    {
                                        Game.chosenmissionindex = missionindex;
                                        Program.resetgame(game);
                                        game.gamestate = Game.CAT_GAMESTATE_GAME;
                                        Program.cleardeaths(game);
                                        game.map = new Map();
                                        Program.setupmission(game,Game.chosenmissionindex,0);
                                        Map.adddecor();//2mar2021
                                        Map.marktreepos(game);
                                        Functions.seed = Map.levelseed2;
                                        return;
                                    }
                                }
                                //end-----------------//12sep2021
                                //start---------------//25mar2021
                                if(game.triggers[j].type==TYPE_CREATE)
                                {
                                    int countunits = 0;
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid==-1 && xx>=0 && yy>=0 && xx<Map.MAXX && yy<Map.MAXY) //note the nid==-1
                                            {
                                                for(int tmp=0;tmp<game.templates.Length;tmp++)
                                                {
                                                    if(game.templates[tmp].name==game.triggers[j].unitname)
                                                    {
                                                        for(int u=0;u<game.units.Length;u++)
                                                        {
                                                            //check that we don't exist
                                                            if(game.units[u].hp<=0 && game.units[u].timedead>Unit.MAXDEADTIME)
                                                            {
                                                                //create one here....
                                                                if(game.units[u].createunitatxy(game,u,game.templates[tmp],xx * Map.GRIDW,yy * Map.GRIDH))
                                                                {
                                                                    countunits++;
                                                                    game.triggers[j].completed = true;        
                                                                }
                                                                break;
                                                            }
                                                        }
                                                        break;                                                        
                                                    }
                                                }
                                            }
                                            if(countunits>=game.triggers[j].n && game.triggers[j].n>0)
                                            {
                                                break;
                                            }
                                        }
                                        if(countunits>=game.triggers[j].n && game.triggers[j].n>0)
                                        {
                                            break;
                                        }
                                    }
                                }                
                                if(game.triggers[j].type==TYPE_REMOVE)
                                {
                                    int countunits = 0;
                                    //Console.WriteLine("attempting to remove");
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid!=-1)
                                            {
                                                if(game.triggers[j].unitname == game.units[nid].name || (game.triggers[j].unitname == TYPE_ANY) || (game.triggers[j].unitname == TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname == TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION))
                                                {
                                                    game.units[nid].hp = 0;
                                                    Map.removeunit(nid,game.units[nid].x,game.units[nid].y);
                                                    game.triggers[j].completed = true;        
                                                    countunits++;
                                                    //Console.WriteLine("removed");
                                                
                                                }
                                            }
                                            for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                            {                                        
                                                int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                if(fid!=-1)
                                                {
                                                    nid = fid;
                                                    if(game.triggers[j].unitname == game.units[nid].name || (game.triggers[j].unitname == TYPE_ANY) || (game.triggers[j].unitname == TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname == TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION))
                                                    {
                                                        //upto    
                                                        game.units[nid].hp = 0;
                                                        //Map.removeunit(nid,game.units[nid].x,game.units[nid].y);
                                                        Map.removeflyer(nid,game.units[nid].x,game.units[nid].y,game.units[nid].flightlevel);
                                                        game.triggers[j].completed = true;        
                                                        countunits++;
                                                    }
                                                }
                                            }
                                            if(countunits>=game.triggers[j].n && game.triggers[j].n>0)
                                            {
                                                break;
                                            }
                                        }
                                        if(countunits>=game.triggers[j].n && game.triggers[j].n>0)
                                        {
                                            break;
                                        }
                                    }
                                }                
                                //end-----------------//25mar2021
                                if(game.triggers[j].type==TYPE_MAKEENEMY || game.triggers[j].type==TYPE_MAKEFRIEND || game.triggers[j].type==TYPE_MAKENEUTRAL)
                                {
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid!=-1)
                                            {
                                                //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                {
                                                    //temporarily halt hostilities between this and other
                                                    //units
                                                    game.units[nid].firetargeti = -1;
                                                    for(int k=0;k<game.units.Length;k++)
                                                    {
                                                        if(game.units[k].firetargeti==nid)
                                                        {
                                                            game.units[k].firetargeti = -1;
                                                        }
                                                    }
                                                    switch(game.triggers[j].type)
                                                    {
                                                        case 12: // friend
                                                        game.units[nid].faction = Game.PLAYERFACTION;
                                                        break;
                                                        case 13: //enemy
                                                        game.units[nid].faction = Game.SKIRMISHENEMYFACTION;//Unit.UNDEAD;
                                                        //26oct2020
                                                        //commented out until we have some other factions in the games
                                                        //
                                                        //if(game.triggers[j].comparator==game.triggers[j].n && game.triggers[j].comparator>0)
                                                        //{
                                                        //    game.units[nid].faction = game.triggers[j].comparator;
                                                        //}
                                                        break;
                                                        case 14: //neutral
                                                        game.units[nid].faction = Unit.NULLFACTION;
                                                        break;
                                                    }
                                                    game.triggers[j].completed = true;        
                                                }
                                            }
                                            for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                            {                                        
                                                int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                if(fid!=-1)
                                                {
                                                    nid = fid;
                                                    if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                    {
                                                        //temporarily halt hostilities between this and other
                                                        //units
                                                        game.units[nid].firetargeti = -1;
                                                        for(int k=0;k<game.units.Length;k++)
                                                        {
                                                            if(game.units[k].firetargeti==nid)
                                                            {
                                                                game.units[k].firetargeti = -1;
                                                            }
                                                        }
                                                        switch(game.triggers[j].type)
                                                        {
                                                            case 12: // friend
                                                            game.units[nid].faction = Game.PLAYERFACTION;
                                                            break;
                                                            case 13: //enemy
                                                            game.units[nid].faction = Game.SKIRMISHENEMYFACTION;//Unit.UNDEAD;
                                                            //26oct2020
                                                            //commented out until we have some other factions in the games
                                                            //
                                                            //if(game.triggers[j].comparator==game.triggers[j].n && game.triggers[j].comparator>0)
                                                            //{
                                                            //    game.units[nid].faction = game.triggers[j].comparator;
                                                            //}
                                                            break;
                                                            case 14: //neutral
                                                            game.units[nid].faction = Unit.NULLFACTION;
                                                            break;
                                                        }
                                                        game.triggers[j].completed = true;        
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                //start--------------//1mar2021
                                if(game.triggers[j].type==TYPE_SETCORNER)
                                {
                                    if(game.triggers[j].n<100 && game.triggers[j].comparator<100)
                                    {
                                        float nnn = (float)game.triggers[j].n;
                                        if(nnn<game.triggers[j].comparator)
                                        {
                                            nnn = (float)game.triggers[j].comparator;
                                        }
                                        if(nnn<0)
                                        {
                                            nnn = 0f;
                                        }
                                        if(nnn>100)
                                        {
                                            nnn = 100f;
                                        }
                                        nnn/=100.0f;
                                        if((game.frame % 4)==0)
                                        {
                                            game.triggers[j].n++;
                                            game.triggers[j].comparator++;
                                        }
                                        Game.CORNERX = game.triggers[j].x + (int)((game.triggers[j].fx - game.triggers[j].x) * nnn);
                                        Game.CORNERY = game.triggers[j].y + (int)((game.triggers[j].fy - game.triggers[j].y) * nnn);
                                    }
                                    else
                                    {
                                        game.triggers[j].completed = true;
                                    }
                                    //game.triggers[j].completed = true;
                                }
                                //end----------------//1mar2021
                                if(game.triggers[j].type==TYPE_HEALING)
                                {
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            int nid = Map.cellunit(xx * Map.GRIDW,yy * Map.GRIDH);
                                            if(nid!=-1)
                                            {
                                                //if(game.units[nid].name==game.triggers[j].unitname && game.units[nid].hp>0)//25mar2021
                                                if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                {
                                                    game.units[nid].hp = game.units[nid].basehp;
                                                    game.triggers[j].completed = true;
                                                }
                                            }
                                            for(int fl=0;fl<Map.FLIGHTLEVELS;fl++)//21feb2022
                                            {                                        
                                                int fid = (Map.cellflyer(xx * Map.GRIDW,yy * Map.GRIDH,fl));
                                                if(fid!=-1)
                                                {
                                                    nid = fid;
                                                    if((game.units[nid].name==game.triggers[j].unitname || (game.triggers[j].unitname==TYPE_ANY) || (game.triggers[j].unitname==TYPE_FRIEND && game.units[nid].faction==Game.PLAYERFACTION) || (game.triggers[j].unitname==TYPE_ENEMY && game.units[nid].faction!=Unit.NULLFACTION && game.units[nid].faction!=Game.PLAYERFACTION)) && game.units[nid].hp>0)//25mar2021
                                                    {
                                                        game.units[nid].hp = game.units[nid].basehp;
                                                        game.triggers[j].completed = true;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                //start-------------//27dec2021
                                if(game.triggers[j].type==TYPE_VARIABLE)
                                {
                                    int variable = game.triggers[j].x;
                                    if(variable<0 || variable>=Trigger.VARIABLE.Length)
                                    {
                                        game.triggers[j].completed = true;
                                        continue;
                                    }
                                    int op = game.triggers[j].y;
                                    int num = game.triggers[j].fx;
                                    switch(op)
                                    {
                                        case 0://increment
                                            Trigger.VARIABLE[variable]+=num;
                                            break;
                                        case 1://decrement
                                            Trigger.VARIABLE[variable]-=num;
                                            break;
                                        case 2://multiply
                                            Trigger.VARIABLE[variable]*=num;
                                            break;
                                        case 3://integer divide
                                            if(num==0)
                                            {
                                                game.triggers[j].completed = true;
                                                continue;
                                            }
                                            Trigger.VARIABLE[variable]/=num;
                                            break;
                                        case 4://time since last time in here //23feb2022
                                            if(tmpMilliSeconds==0)
                                            {
                                                tmpMilliSeconds = 1;
                                                TTimer.Start();
                                            }
                                            else
                                            {
                                                ElapsedMilliSeconds = Convert.ToInt32(TTimer.ElapsedMilliseconds);
                                                TTimer.Reset();
                                                TTimer.Start();
                                            }
                                            Trigger.VARIABLE[variable]+=num*Trigger.ElapsedMilliSeconds;
                                            Trigger.VARIABLE[variable]-=num*Trigger.VARIABLE[TYPE_PAUSETIMER];//28feb2022
                                            Trigger.VARIABLE[TYPE_PAUSETIMER] = 0;//28feb2022
                                        break;
                                    }
                                    game.triggers[j].completed = true;
                                }
                                //end---------------//27dec2021
                                if(game.triggers[j].type==TYPE_FIRE)
                                {
                                    for(int xx=game.triggers[j].x;xx<=game.triggers[j].fx;xx++)
                                    {
                                        for(int yy=game.triggers[j].y;yy<=game.triggers[j].fy;yy++)
                                        {
                                            if(Functions.rand(0,100)<20)
                                            {
                                                Map.setonfire(xx*Map.GRIDW,yy*Map.GRIDH,true); //permanent fire
                                            }
                                            game.triggers[j].completed = true;
                                        }
                                    }
                                }
                                if(game.triggers[j].type==TYPE_SPAWNER)
                                {
                                    //*ANY etc not implemented yet 25mar2021
                                    game.triggers[j].completed = true;
                                    if(game.triggers[j].comparator>0 || game.triggers[j].n>0)
                                    {
                                        //turn on spawner
                                        for(int k=0;k<game.units.Length;k++)
                                        {
                                            if(game.units[k].spawner==game.triggers[j].unitname && game.units[k].spawnertime>0 && game.units[k].x>game.triggers[j].x * Map.GRIDW && game.units[k].y>game.triggers[j].y * Map.GRIDH && game.units[k].x<game.triggers[j].fx * Map.GRIDW && game.units[k].y<game.triggers[j].fy * Map.GRIDH)
                                            {
                                                game.units[k].spawnercount = Trigger.DEFAULTSPAWNERCOUNT;
                                                game.units[k].spawnertime = 3;
                                            }
                                        }
                                    }
                                    if(game.triggers[j].comparator<0 || game.triggers[j].n<0)
                                    {
                                        //turn off spawner
                                        for(int k=0;k<game.units.Length;k++)
                                        {
                                            if(game.units[k].spawner==game.triggers[j].unitname && game.units[k].spawnertime>0 && game.units[k].x>game.triggers[j].x * Map.GRIDW && game.units[k].y>game.triggers[j].y * Map.GRIDH && game.units[k].x<game.triggers[j].fx * Map.GRIDW && game.units[k].y<game.triggers[j].fy * Map.GRIDH)
                                            {
                                                game.units[k].spawnercount = 0;
                                                game.units[k].spawnertime = 3;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if(game.triggers[i].completed==true && game.triggers[i].type==TYPE_DEATHCOUNT && game.triggers[i].x==TYPE_RETREAT && game.triggers[i].y==0 && game.triggers[i].fy==0)
                        {
                            //make enemy soldiers flee away from their fire target instead......
                            for(int j=0;j<game.units.Length;j++)
                            {
                                if(game.units[j].faction!=Game.PLAYERFACTION && game.units[j].hp>0)
                                {
                                    game.units[j].retreat = true;
                                    if(game.units[j].retreatframe==0){game.units[j].retreatframe = game.frame + Unit.RETREATDEATH;}
                                }
                            }
                        }
                        if(game.triggers[i].completed==true && game.triggers[i].type==TYPE_ACTIVATECHATTER)
                        {
                            //find the next group of inactive chatters before the next activate chatter and activate them.....
                            //and it has to be after this one...
                            //so the sequence of triggers is important.....
                            for(int j=0;j<game.triggers.Length;j++)
                            {
                                if(game.triggers[j].type==TYPE_INACTIVECHATTER && j==i+1)
                                {
                                    game.triggers[j].type=TYPE_CHATTER;
                                }
                                if(game.triggers[j].type==TYPE_ACTIVATECHATTER && j>i)
                                {
                                    break;
                                }
                            }
                        }
                        if(game.triggers[i].completed==true && game.triggers[i].type==TYPE_DEATHCOUNT && game.triggers[i].x==TYPE_ACTIVATECHATTER)
                        {
                            //find the next group of inactive chatters before the next activate chatter and activate them.....
                            //and it has to be after this one...
                            //so the sequence of triggers is important.....
                            for(int j=0;j<game.triggers.Length;j++)
                            {
                                if(game.triggers[j].type==TYPE_INACTIVECHATTER && j==i+1)
                                {
                                    game.triggers[j].type=TYPE_CHATTER;
                                }
                                if(game.triggers[j].type==TYPE_ACTIVATECHATTER && j>i)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
                else
                {
                }
                if(game.triggers[i].type==TYPE_LOOP)
                {
                    //check the previous two triggers...
                    if(game.triggers[i].n!=0) //-1 equals indefinite loops...otherwise n times.
                    {
                        if(i>=2)
                        {
                            if(game.triggers[i-2].type==TYPE_ACTIVATE || game.triggers[i-2].type==TYPE_DEATHCOUNT || game.triggers[i-2].type==TYPE_CHECKVARIABLE)
                            {
                                game.triggers[i-2].completed = false;
                                game.triggers[i-1].completed = false;
                                game.triggers[i].completed = false;
                                game.triggers[i].n--;
                            }
                        }
                    }
                }
            }
            bool anychatter = false;
            for(int i=0;i<game.triggers.Length;i++)
            {
                if(game.triggers[i].type==TYPE_CHATTER && game.triggers[i].completed==false)
                {
                    anychatter=true;
                    break;
                }
            }
            if(!anychatter && !game.paused)
            {
                if(vcount>0)
                {
                    for(int i=0;i<game.triggers.Length;i++)
                    {
                        if(game.triggers[i].type==TYPE_VICTORY && game.triggers[i].completed==true)
                        {
                            vcount--;
                        }
                        if((game.triggers[i].type==TYPE_DEATHCOUNT || game.triggers[i].type==TYPE_ACTIVATE) && game.triggers[i].completed==true && game.triggers[i].x==TYPE_VICTORY && game.triggers[i].y==0 && game.triggers[i].fy==0)
                        {
                            vcount--;
                        }
                    }
                    if(vcount<=0)
                    {
                        Game.GAMEENDSTATE = Game.GAMEENDSTATE_VICTORY;
                        if(game.gameovertime==0){game.gameovertime = 180;}
                    }
                }
                if(dcount>0)
                {
                    for(int i=0;i<game.triggers.Length;i++)
                    {
                        if(game.triggers[i].type==TYPE_OR_DEFEAT && game.triggers[i].completed==true)
                        {
                            dcount--;
                            //Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                        }
                        if((game.triggers[i].type==TYPE_DEATHCOUNT || game.triggers[i].type==TYPE_ACTIVATE) && game.triggers[i].completed==true && game.triggers[i].x==TYPE_OR_DEFEAT && game.triggers[i].y==0 && game.triggers[i].fy==0)
                        {
                            dcount--;
                            //Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                        }
                        if(game.triggers[i].type==TYPE_DEFEAT && game.triggers[i].completed==true)
                        {
                            dcount=0;
                            Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                        }
                        if((game.triggers[i].type==TYPE_DEATHCOUNT || game.triggers[i].type==TYPE_ACTIVATE) && game.triggers[i].completed==true && game.triggers[i].x==TYPE_DEFEAT && game.triggers[i].y==0 && game.triggers[i].fy==0)
                        {
                            dcount=0;
                            Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                        }
                    }
                    if(dcount<=0)
                    {
                        Game.GAMEENDSTATE = Game.GAMEENDSTATE_DEFEAT;
                        if(game.gameovertime==0){game.gameovertime = 180;}
                    }
                }
            }
        }        
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Mission
    {
        //public int id;
        public int floorpattern;//16sep2021
        public int debrief;
        public int skirmish;
        public bool custom;
        public int ai;
        public int showkills;
        public int campfirex;
        public int campfirey;
        public int demo;
        public int overlayimage;//21feb2022
        public int overlaysnow;//4mar2022
        public string flavourtext;//18sep2021
        //1nov2020
        public int gridw; //10sep2021
        public int gridh; //10sep2021
        public bool overridergbbk;//1nov2020
        public int overridergbbk_r;//1nov2020
        public int overridergbbk_g;//1nov2020
        public int overridergbbk_b;//1nov2020
        public string name;
        public int indoor;//23sep2021
        public int[] treeimage;
        public int[] rockimage;
        public int[] wallimage;
        public int[] decorimage;//2mar2021
        public Unit[] units;
        public int cornerx;
        public int cornery;
        public Trigger[] triggers;
        public int mapgen;    
        public int seed;
        public int nextmissionid;
        public int failedmissionid;
        public string nextmissionname; //1mar2021
        public string failedmissionname; //1mar2021
        public int istutorial;
        public string[] objectives;
        public string[] description;
        //26oct2020 begin
        public bool issnow;
        public bool isdesert;
        public int tilecat;
        public int treecat;
        public int treeframes;
        public int treeoffsety;
        public int rockcat;
        public int rockframes;
        public int rockoffsety;
        public int wallcat;
        public int wallframes;
        public int walloffsety;
        public int tileframes;
        //26oct2020 end
        //start--------------//2mar2021
        public int decorcat;
        public int decorframes;
        public int decoroffsety;
        //end----------------//2mar2021
        public int neutralfog; //26Feb2021
        public int fogoff; //26Feb2021
        public int playerfaction; //28Feb2021
        public int skirmishenemyfaction; //28Feb2021
        public int alwaysunlocked ;//28Feb2021
        public int lockcorner; //1mar2021

///////////////////Method Definition///////////////
        public static int PickMission(Game game,string name,int index)//12sep2021
        {
                if(name!="")
                {
                    for(int i=0;i<game.missions.Length;i++)
                    {
                        if(game.missions[i].name==name)
                        {
                            return i;
                        }
                    }
                }
                if(index!=-1)
                {
                    if(game.missions!=null)
                    {
                        if(index>=0 && index<game.missions.Length)
                        {
                            return index;
                        }
                    }
                }
                return -1;
        }
        
///////////////////Method Definition///////////////
        public Mission()
        {
            overlayimage = -1;//21feb2022
            overlaysnow = -1;//4mar2022
            flavourtext = "";
            lockcorner = 0; //1mar2021
            alwaysunlocked = 0;//28Feb2021
            nextmissionname = ""; //1mar2021
            failedmissionname = ""; //1mar2021
            //26oct2020 begin
            tilecat = -1;
            treecat = -1;
            rockcat = -1;
            wallcat = -1;
            decorcat = -1; //2mar2021
            isdesert = false;
            issnow = false;
            overridergbbk = false;
            //26oct2020 end
            debrief = 1;
            description = new string[3];
            description[0] = "";
            description[1] = "";
            description[2] = "";
            custom = false;
            campfirex = -1;
            campfirey = -1;
            demo = 0;
            istutorial = 0;
            ai = 0;
            failedmissionid = -1;
            triggers = new Trigger[Trigger.MAXTRIGGER];
            fogoff = 0; //26Feb2021
            neutralfog = 0; //26Feb2021
            playerfaction = Unit.HUMAN ;//28Feb2021 //default
            skirmishenemyfaction = Unit.UNDEAD ;//28Feb2021 //default
            //
            for(int i=0;i<triggers.Length;i++)
            {
                triggers[i] = new Trigger();
            }
            mapgen = 0;
            seed = Functions.seed;
        }

///////////////////Method Definition///////////////
        public void createtrigger(int typ,int m,int comp,string name,int xx,int yy,int ww,int hh)
        {
            //create a trigger from the mission file
            //and associate it with a mission
            int id = -1;
            for(int i=0;i<triggers.Length;i++)
            {
                if(triggers[i].type==0)
                {
                    id=i;
                    break;
                }
            }
            triggers[id].type = typ;
            triggers[id].n = m;
            triggers[id].comparator = comp;
            triggers[id].unitname = name;
            triggers[id].x = xx;
            triggers[id].y = yy;
            if(ww==-1)
            {
                ww = Map.MAXX;
            }
            if(hh==-1)
            {
                hh = Map.MAXY;
            }
            triggers[id].fx = ww;
            triggers[id].fy = hh;
        }
    }

///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class LocalStorage //12mar2021
    {
        public static string filename;
        public static string[] data;

///////////////////Method Definition///////////////
        //public static void ClearLog()
        //{
        //    setitem("Log"," ");
        //}
///////////////////Method Definition///////////////
        //public static void WriteLog(string value)
        //{
        //    setitem("Log",getitem("Log") + "|" + value);
        //}
///////////////////Method Definition///////////////
        public static string getitem(string name)
        {
            //return the value of a name=value pair
            //from the localstorage.txt file
            if(filename=="")
            {
                return "";
            }
            if(data==null)
            {
                return "";
            }
            for(int i=0;i<data.Length;i++)
            {
                if(data[i].IndexOf("=")>0)
                {
                    if(data[i].Substring(0,data[i].IndexOf("="))==name)
                    {
                        return Resources.readstring(data[i]);
                    }
                }
            }
            return "";
        }

///////////////////Method Definition///////////////
        public static void setitem(string name,string value)
        {
            //set a value of a name=value pair
            //in the localstorage.txt file
            bool found = false;
            if(filename=="")
            {
                return;
            }
            if(data==null)
            {
                return;
            }
            for(int i=0;i<data.Length;i++)
            {
                if(data[i].IndexOf("=")>0)
                {
                    if(data[i].Substring(0,data[i].IndexOf("="))==name)
                    {
                        found = true;
                        data[i] = name+"="+value;
                        break;
                    }
                }
            }
            if(!found)
            {
                Array.Resize<string>(ref data,data.Length + 1);
                data[data.Length - 1] = name+"="+value;        
            }
        }

///////////////////Method Definition///////////////
        public static void init()
        {
            //setup the localstorage.txt file for use
            filename = "";
            data = null;
            try
            {
                filename = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)+"\\"+Game.NETTITLE + "\\localstorage.txt";            
            }
            catch(Exception e)
            {
                Console.WriteLine("Local Storage Error:"+e.Message);
                filename = "";
            }
            if(filename!="")
            {
                try
                {
                    data = System.IO.File.ReadAllLines(filename);                    
                }
                catch(Exception e)
                {
                    Console.WriteLine("Local Storage Error:"+e.Message);
                    data = new string[0];
                }
            }
            //ClearLog();
        }

///////////////////Method Definition///////////////
        public static void finalise()
        {
            //save the localstorage.txt file to disk.
            //typically called once at exit of the game
            if(filename==null)
            {
                return;
            }        
            if(filename=="")
            {
                return;
            }
            string txt = "";
            if(data==null)
            {
                return;
            }
            for(int i=0;i<data.Length;i++)
            {
                txt+=data[i]+Environment.NewLine;
            }
            try
            {
                System.IO.File.WriteAllText(filename,txt);
            }
            catch(Exception e)
            {
                Console.WriteLine("Local Storage Error:"+e.Message);
            }
        }
    }

///////////////////Class Definition////////////////
    class Replay
    {
        public static bool RECORD = false;
        public static bool PLAYBACK = false;
        public static int FRAME = 0;
        public static int KEYFRAME = 300;
        public static int CHECKSUMBROKEN = -1;
        public static int MAXLENGTH = 60 * 60 * 10; //10 minutes ought to be long enough for any replay......//11apr2021 commented out//6may2021 commented back in...
        //
        public int[] seed;
        public int[] mx;
        public int[] my;
        public int[] smx;
        public int[] smy;
        public int[] fmx;
        public int[] fmy;
        public bool[] mlclick;
        public bool[] mrclick;
        public bool[] mldown;
        public bool[] mrdown;
        public long[] runningspeed;
        public long[] sumu;
        public int[] CORNERX;
        public int[] CORNERY;
        public int[] frame;
        public int[] leftcontrolkey;
        public int[,] numberkeys;
        public int[,] numberkeysframe;
        //public int[,] newtrees;//24apr2021
        public bool[] togglepause;
        public int[] formation;
        public int[] checksum;
        public Units[] units; //21apr2021
        public int[] mouseoverunitid;
        public int[] ai_direction;//23apr2021
        //
        
        public static void Init(Game game)//done
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            ClearReplay(game);
            FRAME = 0;
            CHECKSUMBROKEN = -1;
            RECORD = true;
            PLAYBACK = false;
            Game.replay = new Replay[1];
            Game.replay[0] = new Replay(0);
            Game.replay[0].seed = new int[1];
            Game.replay[0].mx = new int[1];
            Game.replay[0].my = new int[1];
            Game.replay[0].smx = new int[1];
            Game.replay[0].smy = new int[1];
            Game.replay[0].fmx = new int[1];
            Game.replay[0].fmy = new int[1];
            Game.replay[0].mlclick = new bool[1];
            Game.replay[0].mrclick = new bool[1];
            Game.replay[0].mldown = new bool[1];
            Game.replay[0].mrdown = new bool[1];
            Game.replay[0].runningspeed = new long[1];
            Game.replay[0].sumu = new long[1];
            Game.replay[0].CORNERX = new int[1];
            Game.replay[0].CORNERY = new int[1];
            Game.replay[0].frame = new int[1];
            Game.replay[0].leftcontrolkey = new int[1];
            Game.replay[0].numberkeys = new int[1,10];
            Game.replay[0].numberkeysframe = new int[1,10];
            //Game.replay[0].newtrees = new int[1,1000];//24apr2021 //way too big an array but we will see it affects performance...
            Game.replay[0].togglepause = new bool[1];
            Game.replay[0].formation = new int[1];
            Game.replay[0].checksum = new int[1];
            Game.replay[0].units = new Units[1];//21apr2021
            Game.replay[0].mouseoverunitid = new int[1];//21apr2021
            Game.replay[0].ai_direction = new int[1];//23apr2021
        }
    
        public static void PrepareToPlay(Game game)//done
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            FRAME = 0;
            RECORD = false;
            PLAYBACK = true;
            Functions.seed = Map.levelseed;
            Program.resetgame(game);
            game.gamestate = Game.CAT_GAMESTATE_GAME;
            Program.cleardeaths(game);
            game.map = new Map();
            Game.chosenmissionindex = Game.previousmissionindex;
            if(Game.chosenmissionindex!=-1)
            {
                Program.setupmission(game,Game.chosenmissionindex,2);
                Map.adddecor();//2mar2021
                Map.marktreepos(game);
                Functions.seed = Map.levelseed2;
            }
        }
        
        public static void EndPlayBack(Game game)//done
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            FRAME = 0;
            RECORD = false;
            PLAYBACK = false;
            ClearReplay();
        }
    
        public static void EndRecord(Game game)//done
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            FRAME = 0;
            RECORD = false;
            PLAYBACK = false;
        }
    
        public static void StartRecordReplay(Game game,int max)
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            Array.Resize<Replay>(ref Game.replay,1);
            Game.replay[0] = new Replay(0);
        }
        
        public static void ClearReplay(Game game)
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            Array.Resize<Replay>(ref Game.replay,1);
            Game.replay[0] = new Replay(0);
            Game.replay[0].seed = new int[1];
            Game.replay[0].mx = new int[1];
            Game.replay[0].my = new int[1];
            Game.replay[0].smx = new int[1];
            Game.replay[0].smy = new int[1];
            Game.replay[0].fmx = new int[1];
            Game.replay[0].fmy = new int[1];
            Game.replay[0].mlclick = new bool[1];
            Game.replay[0].mrclick = new bool[1];
            Game.replay[0].mldown = new bool[1];
            Game.replay[0].mrdown = new bool[1];
            Game.replay[0].runningspeed = new long[1];
            Game.replay[0].sumu = new long[1];
            Game.replay[0].CORNERX = new int[1];
            Game.replay[0].CORNERY = new int[1];
            Game.replay[0].frame = new int[1];
            Game.replay[0].leftcontrolkey = new int[1];
            Game.replay[0].numberkeys = new int[1,10];
            //Game.replay[0].newtrees = new int[1,1000];//24apr2021 //way too big an array but we will see it affects performance...
            Game.replay[0].numberkeysframe = new int[1,10];
            Game.replay[0].togglepause = new bool[1];
            Game.replay[0].formation = new int[1];
            Game.replay[0].checksum = new int[1];
            Game.replay[0].units = new Units[1];//21apr2021
            Game.replay[0].mouseoverunitid = new int[1];//21apr2021
            Game.replay[0].ai_direction = new int[1];//23apr2021
        }
    
        public static void ClearReplay()
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            Array.Resize<Replay>(ref Game.replay,1);
            Game.replay[0] = new Replay(0);
            Game.replay[0].seed = new int[1];
            Game.replay[0].mx = new int[1];
            Game.replay[0].my = new int[1];
            Game.replay[0].smx = new int[1];
            Game.replay[0].smy = new int[1];
            Game.replay[0].fmx = new int[1];
            Game.replay[0].fmy = new int[1];
            Game.replay[0].mlclick = new bool[1];
            Game.replay[0].mrclick = new bool[1];
            Game.replay[0].mldown = new bool[1];
            Game.replay[0].mrdown = new bool[1];
            Game.replay[0].runningspeed = new long[1];
            Game.replay[0].sumu = new long[1];
            Game.replay[0].CORNERX = new int[1];
            Game.replay[0].CORNERY = new int[1];
            Game.replay[0].frame = new int[1];
            Game.replay[0].leftcontrolkey = new int[1];
            Game.replay[0].numberkeys = new int[1,10];
            //Game.replay[0].newtrees = new int[1,1000];//24apr2021 //way too big an array but we will see it affects performance...
            Game.replay[0].numberkeysframe = new int[1,10];
            Game.replay[0].togglepause = new bool[1];
            Game.replay[0].formation = new int[1];
            Game.replay[0].checksum = new int[1];
            Game.replay[0].units = new Units[1];//21apr2021
            Game.replay[0].mouseoverunitid = new int[1];//21apr2021
            Game.replay[0].ai_direction = new int[1];//23apr2021
        }
    
        public static void RecordReplay(Game game)
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            if(Game.replay==null)
            {
                Game.replay = new Replay[1];
                Game.replay[0] = new Replay(0);
                ClearReplay();
            }
            if(Game.replay[0]==null)
            {
                Game.replay = new Replay[1];
                ClearReplay();
            }
            if(Game.replay[0].mx==null)
            {
                Game.replay[0].mx = new int[1];
            }
            if(Game.togglepause) //this should work.....
            {
                return;
            }
            int f = Game.replay[0].mx.Length;
            int g = f + 1;
            if(f>MAXLENGTH)//11apr2021//6may2021
            {
                EndRecord(game);
                return;
            }
            Array.Resize(ref Game.replay[0].seed,g);
            Array.Resize(ref Game.replay[0].mx,g);
            Array.Resize(ref Game.replay[0].my,g);
            Array.Resize(ref Game.replay[0].smx,g);
            Array.Resize(ref Game.replay[0].smy,g);
            Array.Resize(ref Game.replay[0].fmx,g);
            Array.Resize(ref Game.replay[0].fmy,g);
            Array.Resize(ref Game.replay[0].mldown,g);
            Array.Resize(ref Game.replay[0].mrdown,g);
            Array.Resize(ref Game.replay[0].mlclick,g);
            Array.Resize(ref Game.replay[0].mrclick,g);
            Array.Resize(ref Game.replay[0].runningspeed,g);
            Array.Resize(ref Game.replay[0].sumu,g);
            Array.Resize(ref Game.replay[0].CORNERX,g);
            Array.Resize(ref Game.replay[0].CORNERY,g);
            Array.Resize(ref Game.replay[0].frame,g);
            Array.Resize(ref Game.replay[0].togglepause,g);
            Array.Resize(ref Game.replay[0].formation,g);
            Array.Resize(ref Game.replay[0].leftcontrolkey,g);
            Array.Resize(ref Game.replay[0].checksum,g);
            Array.Resize<Units>(ref Game.replay[0].units,g);//21apr2021
            Array.Resize(ref Game.replay[0].mouseoverunitid,g);
            Array.Resize(ref Game.replay[0].ai_direction,g);//23apr2021
            //
            //
            //because resizing multidimensional arrays doesn't work simply enough....
            int[,] tmp0 = new int[g,10];
            int[,] tmp1 = new int[g,10];
            //int[,] tmp2 = new int[g,1000]; //24apr2021
            if(f==1)
            {
                Game.replay[0].numberkeys = new int[1,10];
                Game.replay[0].numberkeysframe = new int[1,10];
                //Game.replay[0].newtrees = new int[1,1000];//24apr2021 //way too big an array but we will see it affects performance...
            }
            for(int e=0;e<f;e++)
            {
                for(int j=0;j<10;j++)
                {
                    tmp0[e,j] = Game.replay[0].numberkeys[e,j];
                    tmp1[e,j] = Game.replay[0].numberkeysframe[e,j];
                }
                //for(int j=0;j<1000;j++)//24apr2021
                //{
                //    tmp2[e,j] = Game.replay[0].newtrees[e,j];
                //}
            }
            Game.replay[0].numberkeys = tmp0;
            Game.replay[0].numberkeysframe = tmp1;
            //Game.replay[0].newtrees = tmp2;//24apr2021
            //
            //
            Game.replay[0].seed[f] = Functions.seed;
            Game.replay[0].frame[f] = game.frame;
            Game.replay[0].togglepause[f] = Game.togglepause;
            Game.replay[0].mx[f] = game.mx;
            Game.replay[0].my[f] = game.my;
            Game.replay[0].smx[f] = game.smx;
            Game.replay[0].smy[f] = game.smy;
            Game.replay[0].fmx[f] = game.fmx;
            Game.replay[0].fmy[f] = game.fmy;
            Game.replay[0].mlclick[f] = game.mlclick;
            Game.replay[0].mrclick[f] = game.mrclick;
            Game.replay[0].mldown[f] = game.mldown;
            Game.replay[0].mrdown[f] = game.mrdown;
            Game.replay[0].runningspeed[f] = Config.runningspeed;
            Game.replay[0].sumu[f] = Config.sumu;
            Game.replay[0].CORNERX[f] = Game.CORNERX;
            Game.replay[0].CORNERY[f] = Game.CORNERY;
            Game.replay[0].leftcontrolkey[f] = Game.leftcontrolkey;
            Game.replay[0].formation[f] = Game.formation;
            Game.replay[0].checksum[f] = Game.checksum;
            Game.replay[0].mouseoverunitid[f] = Game.mouseoverunitid;
            Game.replay[0].ai_direction[f] = Game.ai_direction;//23apr2021
            for(int j=0;j<10;j++)
            {
                Game.replay[0].numberkeys[f,j] = Game.numberkeys[j];
                Game.replay[0].numberkeysframe[f,j] = Game.numberkeysframe[j];
            }
            //for(int j=0;j<Game.newtrees.Length;j++)//24apr2021
            //{
            //    if(j>999)
            //    {
            //        break;
            //    }
            //    Game.replay[0].newtrees[f,j] = Game.newtrees[j];
            //}
            //start----------//21apr2021
            if((f % KEYFRAME)==0)
            {
                Game.replay[0].units[f] = new Units(game);
                for(int u=0;u<game.units.Length;u++)
                {
                    Unit.COPYUNIT = true;
                    Unit.copyunitstats(game.units[u],ref Game.replay[0].units[f].unit[u]);
                    Unit.COPYUNIT = false;
                }
                Map.correct(game);//21apr2021
            }
            //end------------//21apr2021
        }

        public static bool IsPlaying()//21apr2021
        {
            return PLAYBACK;
        }
        
        public static void PlayReplay(Game game,int f)
        {
            if(Config.NOREPLAY>0)//15sep2021
            {
                return;
            }
            if(f>=0 && f<Game.replay[0].mx.Length)
            {
                Functions.seed = Game.replay[0].seed[f];
                Game.RCORNERX = Game.replay[0].CORNERX[f];//21apr2021
                Game.RCORNERY = Game.replay[0].CORNERY[f];//21apr2021
                game.mx = Game.replay[0].mx[f];
                game.my = Game.replay[0].my[f];
                game.smx = Game.replay[0].smx[f];
                game.smy = Game.replay[0].smy[f];
                game.fmx = Game.replay[0].fmx[f];
                game.fmy = Game.replay[0].fmy[f];
                game.mldown = Game.replay[0].mldown[f];
                game.mrdown = Game.replay[0].mrdown[f];
                game.mlclick = Game.replay[0].mlclick[f];
                game.mrclick = Game.replay[0].mrclick[f];
                Config.runningspeed = Game.replay[0].runningspeed[f];
                Config.RUNNINGSPEED = Config.runningspeed;
                Config.sumu = Game.replay[0].sumu[f];
                game.frame = Game.replay[0].frame[f];
                Game.mouseoverunitid = Game.replay[0].mouseoverunitid[f];//21apr2021
                Game.ai_direction = Game.replay[0].ai_direction[f];//21apr2021
                if(f < 30) //21apr2021
                {
                    Game.CORNERX = Game.RCORNERX;
                    Game.CORNERY = Game.RCORNERY;
                }
                Game.leftcontrolkey = Game.replay[0].leftcontrolkey[f];
                Game.togglepause = Game.replay[0].togglepause[f];
                for(int j=0;j<10;j++)
                {
                    Game.numberkeys[j] = Game.replay[0].numberkeys[f,j];
                    Game.numberkeysframe[j] = Game.replay[0].numberkeysframe[f,j];
                }
                //for(int j=0;j<1000;j++)//24apr2021
                //{
                //    if(Game.replay[0].newtrees[f,j]>0)
                //    {
                //        //planttree
                //        int treex = (Game.replay[0].newtrees[f,j] - 1) % Map.MAXX;
                //        int treey = (Game.replay[0].newtrees[f,j] - 1 - treex) / Map.MAXX;
                //        Map.planttree(treex * Map.GRIDW, treey * Map.GRIDH);
                //    }
                //}
                if(Game.replay[0].formation[f]!=0)
                {
                    Unit.Formation(game,Game.replay[0].formation[f]);
                }
                if((f % KEYFRAME)==0)//21apr2021
                {
                    if(Game.replay[0].units[f]!=null)
                    {
                        if(Game.replay[0].units[f].unit!=null)
                        {
                            if(Game.replay[0].units[f].unit.Length>0)
                            {
                                for(int u=0;u<game.units.Length;u++)
                                {
                                    Unit.COPYUNIT = true;
                                    Unit.copyunitstats(Game.replay[0].units[f].unit[u],ref game.units[u]);
                                    Unit.COPYUNIT = false;
                                }
                            }
                        }
                    }
                    Map.correct(game);//21apr2021
                }
                if(Game.checksum!=Game.replay[0].checksum[f] && f>2 && CHECKSUMBROKEN==-1)
                {
                    CHECKSUMBROKEN = f;
                }
                if(Game.checksum==Game.replay[0].checksum[f]) //21apr2021
                {
                    CHECKSUMBROKEN = -1;
                }
            }
            else
            {
                //exit to main menu.....
                //if the replay works we won't actually get here...instead we will get to the DEFEEAT or VICTORY screens,
                //with the same data.....that's how you'll know this didn't work....
                //Blood.clearall(game); //29oct2020
                //Bullet.clearall(game); //29oct2020
                //Gibbet.clearall(game);//2apr2021
                //game.map = new Map();
                //Program.setupbackdrop(game);
                //game.demomode = true;
                //Game.PLAYERFACTION = Unit.HUMAN;
                //game.gamestate = 0;
                //game.frame+=FRAME;
                ////////////////////////////////////////////////
                //Given the replay feature is broken and doesn't seem fixable
                //I may as well give the player a reward for watching it!
                Game.GAMEENDSTATE = Game.GAMEENDSTATE_VICTORY;
                if(game.gameovertime==0){game.gameovertime = 180;}
            }
        }
    
        public Replay(int max)
        {
        }
    }

///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////Class Definition////////////////
    class Translation //13mar2021
    {
        public static string[] foreignnumbers; //13mar2021
        public static int MAXNUM = 10001;
        public static string filename = "";
        public static bool languageready = false;
        public static string[] foreignwords; //13mar2021
        public static string[] defaultwords; //13mar2021
        public static string[] sortedforeignwords; //28mar2021
        public static string[] sorteddefaultwords; //28mar2021
        public static bool sorted = false;//28mar2021
        public static int sortmax = 0;//28mar2021
        
///////////////////Method Definition///////////////
        public static void init(string nfilename)
        {
            //initialise the translation class
            foreignnumbers = new string[MAXNUM];
            for(int i=0;i<MAXNUM;i++)
            {
                foreignnumbers[i] = "" + i;
            }
            if(nfilename!="")
            {
                try
                {
                    foreignnumbers = System.IO.File.ReadAllLines(nfilename);
                    if(foreignnumbers==null)
                    {
                        filename = "";
                        return;
                    }
                    if(foreignnumbers.Length!=MAXNUM)
                    {
                        filename = "";
                        return;
                    }
                    filename = nfilename;
                    languageready = true;
                }
                catch(Exception e)
                {
                    Console.WriteLine("Translation Error:"+e.Message);
                    //LocalStorage.WriteLog("Translation Error:"+e.Message);
                    filename = "";
                }
            }
        }

///////////////////Method Definition///////////////
        public static void SetLanguage(string code)
        {
            //set the language to be used by the game
            LocalStorage.setitem("language",code);
        }

///////////////////Method Definition///////////////
        public static string GetLanguage()
        {
            //get the language used by the game ui
            return LocalStorage.getitem("language");
        }

///////////////////Method Definition///////////////
        public static void CollectWords()
        {
            //get the word list ready for translations
            if(!languageready)
            {
                return;
            }
            if(Config.wordsfile=="")
            {
                return;
            }        
            try
            {
                string[] data = System.IO.File.ReadAllLines(Config.wordsfile);
                if(data.Length>0)
                {
                    defaultwords = new string[data.Length];
                    foreignwords = new string[data.Length];
                    for(int i=0;i<data.Length;i++)
                    {
                        if(data[i].IndexOf("=")>0)
                        {
                            defaultwords[i] = data[i].Substring(0,data[i].IndexOf("="));
                            foreignwords[i] = Resources.readstring(data[i]);
                        }
                    }                        
                    sort(); //28mar2021 //not implemented
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Error In Translation:"+e.Message);
                //LocalStorage.WriteLog("Error In Translation:"+e.Message);
            }
        }

        
        private static void sort() //28mar2021
        {
            sorteddefaultwords = new string[defaultwords.Length];
            sortedforeignwords = new string[foreignwords.Length];
            bool[] sortedlist = new bool[defaultwords.Length];
            sorted = false;
            string biggestword = "";
            for(int i=0;i<defaultwords.Length;i++)
            {
                sorteddefaultwords[i] = "";
                sortedforeignwords[i] = "";
                sortedlist[i] = false;
            }
            while(!sorted)
            {
                //find the biggestword that has not been sorted
                int j = -1;
                biggestword = "";
                for(int i=0;i<defaultwords.Length;i++)
                {
                    if(String.Compare(defaultwords[i],biggestword)>0 && sortedlist[i]==false && defaultwords[i]!="")
                    {
                        biggestword = defaultwords[i];
                        j = i;
                    }
                }
                //we now have the biggest unsorted word.....
                if(j!=-1)
                {
                    //find the highest index value of sorteddefaultwords.....
                    for(int k=sorteddefaultwords.Length-1;k>=0;k--)
                    {
                        if(sorteddefaultwords[k]=="" && sortedforeignwords[k]=="")
                        {
                            sorteddefaultwords[k] = defaultwords[j];
                            sortedforeignwords[k] = foreignwords[j];
                            sortedlist[j] = true;
                            break;
                        }
                    }
                }
                else
                {
                    sorted = true;
                }
                
            }
            if(sorted)
            {
                for(int i=0;i<defaultwords.Length;i++)
                {
                    defaultwords[i] = sorteddefaultwords[i];
                    foreignwords[i] = sortedforeignwords[i];
                }
            }
        }
        
///////////////////Method Definition///////////////
        public static string TranslateWord(string word,bool usesecond)
        {
            //translate a specific word into a value found in the word list for the current language
            if(!languageready)
            {
                return word; //17mar2021 // was ""
            }
            if(defaultwords==null || foreignwords==null)
            {
                return word; //17mar2021 // was ""
            }
            string value = "";
            bool found = false;
            if(sorted)//28mar2021 //binary search Order Log N is the search time.....
            {
                int min = 0;
                int max = defaultwords.Length - 1;
                int mid = (min + max) / 2;
                int omid = mid - 1;
                int atleasttwice = 0;
                int pmid = (min + max);
                while(value=="" && omid!=mid)
                {
                    omid = mid;
                    string txt = defaultwords[mid];
                    int cmp = String.Compare(defaultwords[mid],word);
                    if(cmp==0)
                    {
                        value = foreignwords[mid];
                        break;
                    }
                    if((pmid)%2!=0)
                    {
                        if(mid + 1 <= max)
                        {
                            if(String.Compare(defaultwords[mid + 1],word)==0)
                            {
                                value = foreignwords[mid + 1];
                                break;
                            }
                        }
                    }
                    pmid = min + max;
                    if(cmp>0)
                    {
                        max = mid;
                        mid = (min + max)/2;
                        
                    }
                    if(cmp<0)
                    {
                        min = mid;
                        mid = (min + max)/2;
                    }
                    
                    if(omid==mid)
                    {
                        atleasttwice++;
                        if(atleasttwice<2)
                        {
                            omid = mid - 1;
                        }
                    }
                    
                }
            }
            else
            {
                for(int i=0;i<defaultwords.Length;i++)
                {
                    if(defaultwords[i]==word)
                    {
                        value = foreignwords[i];
                        if(!usesecond)
                        {
                            break;
                        }
                        if(found)
                        {
                            break;
                        }
                        found = true;
                    }
                }
            }
            if(value=="")
            {
                value = word;
            }
            return value;
        }

///////////////////Method Definition///////////////
        public static string TranslateNumber(int n)
        {
            //in the event that some cultures use non Arabic numbers
            //this handles that
            if(!languageready)
            {
                return "" + n;
            }
            if(n<0 || n>=MAXNUM)
            {
                return "" + n;
            }
            if(n>=0 && n<foreignnumbers.Length)
            {
                return foreignnumbers[n];
            }
            else
            {
                return "" + n;
            }
        }

///////////////////Method Definition///////////////
        public static int CountNonAscii(string text)
        {
            //used in drawtext to make sure the scale of the text is right
            if(text==null)
            {
                return 1; //special case
            }
            int count = text.Length;
            char[] letters = text.ToCharArray();
            char[] ZERO = " ".ToCharArray();
            char[] ZZ = "~".ToCharArray();
            for(int i=0;i<letters.Length;i++)
            {
                if(char.ToUpper(letters[i])>=ZERO[0] && char.ToUpper(letters[i])<=ZZ[0])
                {
                    count--;
                }
            }
            if(count<=0)
            {
                return 1;
            }
            return count;
        }

///////////////////Method Definition///////////////
        public static bool AllAscii(string text) //16mar2021 //another fix for Chinese Text....
        {
            //used in drawtext ot make sure the scale of the text is right
            if(text==null)
            {
                return false;
            }
            int count = text.Length;
            if(count<=0)
            {
                return false;
            }
            char[] letters = text.ToCharArray();
            char[] ZERO = " ".ToCharArray();
            char[] ZZ = "~".ToCharArray();
            for(int i=0;i<letters.Length;i++)
            {
                if(char.ToUpper(letters[i])<ZERO[0] || char.ToUpper(letters[i])>ZZ[0])
                {
                    return false;
                }
            }
            return true;
        }
    }
    
    class Emitter
    {
        public static int maxemitters = 50;
        public static int ecount;
        public static Emitter[] emitters;
        
        public float x;
        public float y;
        //public float h;
        
        public float vx;
        public float vy;
        //public float vh;
        
        //public float ah;
        
        public float lifetime;
        
        
        
        public int frame;
        public int ptype;
        
        
        public static int[] pimages;    
        public static Particle[] pdefine;
        public static int[] spelldefine; //blocks of 9 - 3 for origin, 3 for travel, 3 for impact
        public static int TYPEOFFSET = -1;
        
        public static int FORCEBOLT = 1;
        public static int SPARKS = 2;
        public static int FLAMES = 3;
        public static int SMOKE = 4;
        public static int FIREBALL = 5;
        public static int HEALING = 6;
        
        public Emitter()
        {
            
        }
        
        public static void CreateEmitter(int type,float x,float y,float vx,float vy)
        {
            //type = SPELL NUMBER (index 0 to n)
            if(TYPEOFFSET<0 || TYPEOFFSET>8)
            {
                TYPEOFFSET = -1;
                return;
            }
            for(int i=0;i<emitters.Length;i++)
            {
                if(emitters[i].lifetime<=0)
                {
                    if(TYPEOFFSET + (type * 9)<Emitter.spelldefine.Length && TYPEOFFSET + (type * 9)>=0)
                    {
                        emitters[i].ptype = Emitter.spelldefine[TYPEOFFSET + (type * 9)];
                        if(emitters[i].ptype < 0 || emitters[i].ptype >= Emitter.pdefine.Length)
                        {
                            TYPEOFFSET = -1;
                            emitters[i].lifetime = 0;
                            emitters[i].ptype = -1;
                            break;
                        }
                    }
                    else
                    {
                        emitters[i].ptype = -1;
                        emitters[i].lifetime = 0;
                        TYPEOFFSET = -1;
                        break;
                    }
                    emitters[i].x = x;
                    emitters[i].y = y;
                    emitters[i].vx = vx;
                    emitters[i].vy = vy;
                    emitters[i].lifetime = 4;
                    TYPEOFFSET = 0;
                    emitters[i].frame = 0;
                    if(emitters[i].ptype!=-1)
                    {
                        if(Emitter.pdefine[emitters[i].ptype].elifetime>0)
                        {
                            emitters[i].lifetime = Emitter.pdefine[emitters[i].ptype].elifetime;
                        }
                    }
                    break;
                }
            }
        }
        
        public static void LoadPType(Game game)
        {
            string file = "media/txt/ptypes.txt";
            try
            {
                string[] data = System.IO.File.ReadAllLines(file);//13mar2021
                //string[] data = System.IO.File.ReadAllLines(file,System.Text.Encoding.UTF8);//13mar2021
                int count = 0;
                int scount = 0;
                for(int i=0;i<data.Length;i++)
                {
                    if(data[i].IndexOf("=")>0)
                    {
                        switch(data[i].Substring(0,data[i].IndexOf("=")))
                        {
                            case "ptype":
                            count++;
                            break;
                            case "sdefine":
                            scount++;
                            break;
                        }
                    }
                }
                if(scount>0)
                {
                    Emitter.spelldefine = new int[scount * 9];
                    for(int s=0;s<scount * 9;s++)
                    {
                        Emitter.spelldefine[s] = -1;
                    }
                    int sid = -9;
                    for(int i=0;i<data.Length;i++)
                    {
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "sdefine":
                                sid+=9;
                                Game.LoadingProgress(game);
                                break;
                                case "s_origin_0":
                                Emitter.spelldefine[sid] = Resources.readint(data[i]);
                                break;
                                case "s_origin_1":
                                Emitter.spelldefine[sid + 1] = Resources.readint(data[i]);
                                break;
                                case "s_origin_2":
                                Emitter.spelldefine[sid + 2] = Resources.readint(data[i]);
                                break;
                                case "s_move_0":
                                Emitter.spelldefine[sid + 3] = Resources.readint(data[i]);
                                break;
                                case "s_move_1":
                                Emitter.spelldefine[sid + 4] = Resources.readint(data[i]);
                                break;
                                case "s_move_2":
                                Emitter.spelldefine[sid + 5] = Resources.readint(data[i]);
                                break;
                                case "s_stop_0":
                                Emitter.spelldefine[sid + 6] = Resources.readint(data[i]);
                                break;
                                case "s_stop_1":
                                Emitter.spelldefine[sid + 7] = Resources.readint(data[i]);
                                break;
                                case "s_stop_2":
                                Emitter.spelldefine[sid + 8] = Resources.readint(data[i]);
                                break;
                            }
                        }
                    }
                }
                if(count>0)
                {
                    Emitter.pimages = new int[count];
                    Emitter.pdefine = new Particle[count];
                    int id = -1;
                    int cw = 0;
                    int ch = 0;
                    int nh = 0;
                    int nw = 0;
                    for(int i=0;i<data.Length;i++)
                    {
                        if(data[i].IndexOf("=")>0)
                        {
                            switch(data[i].Substring(0,data[i].IndexOf("=")))
                            {
                                case "cw":
                                cw = Resources.readint(data[i]);
                                break;
                                case "ch":
                                ch = Resources.readint(data[i]);
                                break;
                                case "nh":
                                nh = Resources.readint(data[i]);
                                break;
                                case "nw":
                                nw = Resources.readint(data[i]);
                                break;
                                case "ptype":
                                id++;
                                string pfile = Resources.readstring(data[i]);
                                Emitter.pimages[id] = Resources.LoadAnimImage(game,pfile,game.renderer,cw,ch,nw,nh);
                                Emitter.pdefine[id] = new Particle();
                                Emitter.pdefine[id].image = Emitter.pimages[id];
                                Game.LoadingProgress(game);
                                break;
                                //particle definition for this emitter......
                                case "frame":
                                Emitter.pdefine[id].frame = Resources.readint(data[i]);
                                break;
                                case "randomframe":
                                Emitter.pdefine[id].randomframe = Resources.readint(data[i]);
                                break;
                                case "framespeed":
                                Emitter.pdefine[id].framespeed = Resources.readint(data[i]);
                                break;
                                case "dalpha":
                                Emitter.pdefine[id].dalpha = Resources.readfloat(data[i]);
                                break;
                                case "dscale":
                                Emitter.pdefine[id].dscale = Resources.readfloat(data[i]);
                                break;
                                case "alpha":
                                Emitter.pdefine[id].alpha = Resources.readfloat(data[i]);
                                break;
                                case "scale":
                                Emitter.pdefine[id].scale = Resources.readfloat(data[i]);
                                break;
                                case "blend":
                                Emitter.pdefine[id].blend = Resources.readint(data[i]);
                                break;
                                case "lifetime":
                                Emitter.pdefine[id].lifetime = Resources.readfloat(data[i]);
                                break;
                                case "elifetime":
                                Emitter.pdefine[id].elifetime = Resources.readfloat(data[i]);
                                break;
                                case "radius":
                                Emitter.pdefine[id].radius = Resources.readfloat(data[i]);
                                break;
                                case "dradius":
                                Emitter.pdefine[id].dradius = Resources.readfloat(data[i]);
                                break;
                                //case "acceleration":
                                //Emitter.pdefine[id].ah = Resources.readfloat(data[i]);
                                //break;
                                case "emitcount":
                                Emitter.pdefine[id].emitcount = Resources.readint(data[i]);
                                break;
                                case "dvx":
                                Emitter.pdefine[id].dvx = Resources.readfloat(data[i]);
                                break;
                                case "dvy":
                                Emitter.pdefine[id].dvy = Resources.readfloat(data[i]);
                                break;
                                case "dvh":
                                Emitter.pdefine[id].dvh = Resources.readfloat(data[i]);
                                break;
                                case "dx":
                                Emitter.pdefine[id].dx = Resources.readfloat(data[i]);
                                break;
                                case "dy":
                                Emitter.pdefine[id].dy = Resources.readfloat(data[i]);
                                break;
                                case "dh":
                                Emitter.pdefine[id].dh = Resources.readfloat(data[i]);
                                break;
                            }
                            
                        }
                    }
                }
            }
            catch(Exception e)
            {
                Console.WriteLine("Error Reading Ptypes:"+e.Message);
            }
        }
        
        public static void Reset(Game game)
        {
            emitters = new Emitter[maxemitters];
            for(int i=0;i<emitters.Length;i++)
            {
                emitters[i] = new Emitter();
            }
            if(pimages==null)
            {
                LoadPType(game);
            }
        }
        
        public static void UpdateAll(Game game)
        {
            if(Game.togglepause)
            {
                return;
            }
            for(int i=0;i<emitters.Length;i++)
            {
                if(emitters[i].lifetime>0)
                {
                    if(i>ecount)
                    {
                        ecount = i;
                    }
                    emitters[i].frame++;
                    emitters[i].lifetime--;
                    if(emitters[i].lifetime<=0)
                    {
                        emitters[i].frame = 0;
                    }
                    //
                    emitters[i].x+=emitters[i].vx;
                    emitters[i].y+=emitters[i].vy;
                    //emitters[i].h+=emitters[i].vh;
                    //emitters[i].vh+=emitters[i].ah;
                    if(emitters[i].x - Game.CORNERX < 0 || emitters[i].y - Game.CORNERY < 0 || emitters[i].x - Game.CORNERX > Game.RESOLUTIONX || emitters[i].y - Game.CORNERY > Game.RESOLUTIONY)
                    {
                        emitters[i].lifetime = 0;
                    }
                    if(emitters[i].ptype==-1)
                    {
                        continue;
                    }
                    int emitcount = 0;
                    for(int j=0;j<Particle.particles.Length;j++)
                    {
                        if(Particle.particles[j].lifetime<=0)
                        {
                            Particle.particles[j].image = Emitter.pdefine[emitters[i].ptype].image;
                            Particle.particles[j].frame = Emitter.pdefine[emitters[i].ptype].frame;
                            Particle.particles[j].framespeed = Emitter.pdefine[emitters[i].ptype].framespeed;
                            Particle.particles[j].framedelay = Emitter.pdefine[emitters[i].ptype].framespeed;
                            if(Emitter.pdefine[emitters[i].ptype].randomframe>0)
                            {
                                Particle.particles[j].frame = (int)Functions.rand(0,game.images[Particle.particles[j].image].chn * game.images[Particle.particles[j].image].cwn);
                            }
                            if(Emitter.pdefine[emitters[i].ptype].radius==0)
                            {
                                Particle.particles[j].x = emitters[i].x + Emitter.pdefine[emitters[i].ptype].dx * (float)Functions.rand(-100,100)/100f;
                                Particle.particles[j].y = emitters[i].y + Emitter.pdefine[emitters[i].ptype].dy * (float)Functions.rand(-100,100)/100f;
                                Particle.particles[j].h = Emitter.pdefine[emitters[i].ptype].dh * (float)Functions.rand(-100,100)/100f;
                            }
                            else
                            {
                                double angle = (double)Functions.rand(-180,180)/30f;
                                Particle.particles[j].x = emitters[i].x + (Emitter.pdefine[emitters[i].ptype].radius + Emitter.pdefine[emitters[i].ptype].dradius * (float)emitters[i].frame) * (float)Math.Sin(angle);
                                Particle.particles[j].y = emitters[i].y + (Emitter.pdefine[emitters[i].ptype].radius + Emitter.pdefine[emitters[i].ptype].dradius * (float)emitters[i].frame) * (float)Math.Cos(angle) / 2f;
                                Particle.particles[j].h = Emitter.pdefine[emitters[i].ptype].dh;
                            }
                            Particle.particles[j].vx = Emitter.pdefine[emitters[i].ptype].dvx * (float)Functions.rand(-100,100)/100f;
                            Particle.particles[j].vy = Emitter.pdefine[emitters[i].ptype].dvy * (float)Functions.rand(-100,100)/100f;
                            Particle.particles[j].vh = Emitter.pdefine[emitters[i].ptype].dvh * (float)Functions.rand(-100,100)/100f;
                            Particle.particles[j].alpha = Emitter.pdefine[emitters[i].ptype].alpha;
                            Particle.particles[j].dalpha = Emitter.pdefine[emitters[i].ptype].dalpha;
                            Particle.particles[j].scale = Emitter.pdefine[emitters[i].ptype].scale;
                            Particle.particles[j].dscale = Emitter.pdefine[emitters[i].ptype].dscale;
                            Particle.particles[j].blend = Emitter.pdefine[emitters[i].ptype].blend;
                            Particle.particles[j].lifetime = Emitter.pdefine[emitters[i].ptype].lifetime;
                            emitcount++;
                            if(emitcount>Emitter.pdefine[emitters[i].ptype].emitcount)
                            {
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    
    class Particle
    {
        public int image;
        public int frame;
        public int framespeed;
        public int framedelay;
        public int randomframe;
        
        public static int maxparticles = 5000;
        public static Particle[] particles;
        public static int pcount = 0;
        
        public float x;
        public float y;
        public float h;
        
        public float vx;
        public float vy;
        public float vh;
        
        //public float ah;

        public float alpha;
        public float scale;
        public int blend;
        
        public float dalpha;
        public float dscale;
        public float radius;
        public float dradius;
        
        public float lifetime;
        public float elifetime;
        
        public int emitcount;
        public float dvx;
        public float dvy;
        public float dvh;
        public float dx;
        public float dy;
        public float dh;

        
        public Particle()
        {
            
        }
        public static void Reset()
        {
            particles = new Particle[maxparticles];
            for(int i=0;i<particles.Length;i++)
            {
                particles[i] = new Particle();
            }
        }
        
        public static void UpdateAll(Game game)
        {
            if(Game.togglepause)
            {
                return;
            }
            for(int i=0;i<particles.Length;i++)
            {
                if(particles[i].lifetime>0)
                {
                    if(i>pcount)
                    {
                        pcount = i;
                    }
                    particles[i].lifetime--;
                    particles[i].x+=particles[i].vx;
                    particles[i].y+=particles[i].vy;
                    particles[i].h+=particles[i].vh;
                    //particles[i].vh+=particles[i].ah;
                    
                    particles[i].alpha+=particles[i].dalpha;
                    particles[i].scale+=particles[i].dscale;
                    
                    if(particles[i].scale<0.001)
                    {
                        particles[i].lifetime = 0;
                    }
                    if(particles[i].x - Game.CORNERX < 0 || particles[i].x - Game.CORNERX > Game.RESOLUTIONX || particles[i].y - Game.CORNERY < 0 || particles[i].y - Game.CORNERY > Game.RESOLUTIONY)
                    {
                        particles[i].lifetime = 0;
                    }
                    if(particles[i].alpha>1)
                    {
                        particles[i].alpha = 1;
                    }
                    if(particles[i].alpha<0)
                    {
                        particles[i].lifetime = 0;
                    }
                    //12apr2022 corrected bit where it was buggering around with the particle effects wrongly....unfortunately....    
                    if(particles[i].framespeed>=0 && particles[i].image!=-1 && particles[i].image>=0 && particles[i].image<game.images.Length)//12apr2022) //framespeed = -1 to not animate....
                    {
                        particles[i].framedelay--;
                        if(particles[i].framedelay<=0)
                        {
                            particles[i].frame++;
                            particles[i].framedelay = particles[i].framespeed;
                            if(particles[i].frame > game.images[particles[i].image].chn * game.images[particles[i].image].cwn)
                            {
                                particles[i].frame = 0;
                            }
                        }
                    }
                    
                }
            }
        }
        
        public static void DrawAll(Game game)
        {
            for(int i=0;i<particles.Length;i++)
            {
                if(particles[i].lifetime>0)
                {
                    int scrx = (int)particles[i].x - Game.CORNERX;
                    int scry = (int)particles[i].y - Game.CORNERY + (int)particles[i].h;
                    
                    //12apr2022 corrected bit where it was buggering around with the particle effects wrongly....unfortunately....
                    if(particles[i].image!=-1 && particles[i].image>=0 && particles[i].image<game.images.Length)//12apr2022
                    {
                        RenderList.drawanimimage(game,game.images[particles[i].image].texture,scrx,scry,0f,particles[i].scale,particles[i].scale,particles[i].frame,particles[i].blend,false,particles[i].alpha,particles[i].image);
                    }
                    else
                    {
                        RenderList.drawrect(game,scrx,scry,4,4,RenderList.getrgb(255,255,255),0);
                    }
                }
            }
        }
        
    }
    
    
}


///////////////////////////////////////////////////
//////////////////End of Program///////////////////

///////////////////////////////////////////////////
///////////////////////////////////////////////////
///////////////////////////////////////////////////
//////////////////Basic Code Tutorial Notes////////
/*
In this short section of comments I hope to describe the language features that are used in this program to highlight the fairly simple nature
of the concepts needed to put this game together and games like it in c#.

I have broken it down into the following sections.
1. Basic language features
2. C# Library functions that are slightly more complex.
3. SDL2 notes regarding the use of the c# wrapper in this program.

///////////////////////////////////////////////////
1. Basic Language Features

KOG2 uses the following core language features that are available in almost any programming language you can write
code in for desktop or mobile today.

Datatypes:
Integer, String, Floating Point Numbers

Arrays including simple access by element index and the slightly extended feature of being able to resize an array at runtime.

Loops:
For loops and while loops. Primarily for iterating through the many arrays in the program regarding for loops.

Conditionals:
if statements and switch statements

String functions and String parsing functions:
Extracting parts of strings (IndexOf) and also converting string text file data into relevant number types*

Classes including properties and methods.
In a sense the game could just as easily have been written in a procedural language that only uses struct or type
objects with globally accessible functions instead of object specific methods.

Static variables and methods.
Where either global constants or global variables are required I've used static variables.
I have not used ENUMs for constants out of habit, personal preference and flexibility - my constants are not truly constant sometimes.

///////////////////////////////////////////////////
2. C# Library Functions

The main c# library functions used a number of times throughout this program include:

Threading - when writing files to disk a simple second thread is started in which the file is written and then exited.

Reading and Writing basic text files - all game data files other than graphics and sound are in raw text format and use c#'s most simple
method for reading and writing text files into and out of a string array.

Cultural Library for converting text format floating point numbers into their appropriate floating point data type. A bit of a gotcha moment
where on first release I had no idea that different users machines would read commas and full stops as entirely different meanings when reading decimal numbers from a text file.

If you were to port this game to another language then these are the areas of code that would likely need to change the most.

///////////////////////////////////////////////////
3. SDL2 Notes

The graphics and sound engine I have written is simple enough that for most of the game there are
very few calls to the SDL wrapper functions outside of a few key methods.

The majority of SDL2 Wrapper function calls occur in the render() method of the RenderList object and the audio methods.

It keeps the code quite simple by doing this.

However having an ability to read and understand what's going on in the SDL2 wrapper code files themselves will help
with any deeper modifications to the game that you may wish to make.

The window creation and initialisation routines is where many of the other raw calls to the SDL2 wrapper functions occur.


*
/