#include <iostream>
#include <windows.h>
#include <time.h>
#include "PROFILE.h"
#include "date.h"
#include "engine.h"
#include <shellapi.h>
#include <string>
#include <vector>
#pragma warning(disable: 4035)
#pragma warning(disable: 4786)

date currdate;
bool ShowStartMessage = false;
bool Created_Nod_Veh_Zone = false;
bool Created_GDI_Veh_Zone = false;
bool AllowKillBuilding = false;
int GDIFlagHolder = 0;
int NodFlagHolder = 0;
int GDIFlagAttached = 0;
int NodFlagAttached = 0;
int TotalCaptures = 5;
int GDICaps = 0;
int NodCaps = 0;
int MapID = 0;
int GDIFlagLoc = 1;
int NodFlagLoc = 1;
char CurrMap[30];
std::vector<std::string> SvSKillMsg;
int SvSKillMsgTotal = 0;

bool FirstGame = true;
bool ShowAnnouncement = true;
char FlagPreset[100], FlagBackPreset[100], GDIPedPreset[100], NodPedPreset[100];
int EnableCTF = getProfileInt("Settings","EnableCTFMode",1,"CTF_Settings.ini");
int WeaponForHolder = getProfileInt("Settings","AllowWeaponForHolder",1,"CTF_Settings.ini");
int DropWeapons = getProfileInt("Settings","AllowDropWeapons",1,"CTF_Settings.ini");
int SpoilsofWar = getProfileInt("Settings","AllowSpoilsofWar",1,"CTF_Settings.ini");
int EnableCapLimit = getProfileInt("Settings","AllowCapLimit",1,"CTF_Settings.ini");
int RegenForHolder = getProfileInt("Settings","AllowRegenForHolder",0,"CTF_Settings.ini");
float RegenAmount = getProfileFloat("Settings","RegenAmount",2.0f,"CTF_Settings.ini");
int stg1 = getProfileString("Settings","FlagPresetName","POW_Data_Disc",FlagPreset,100,"CTF_Settings.ini");
int stg2 = getProfileString("Settings","GDIPedPresetName","CtfPedestalGold",GDIPedPreset,100,"CTF_Settings.ini");
int stg3 = getProfileString("Settings","NodPedPresetName","CtfPedestalRed",NodPedPreset,100,"CTF_Settings.ini");
int stg4 = getProfileString("Settings","FlagBackPresetName","CtfFlag",FlagBackPreset,100,"CTF_Settings.ini");
int ShowPlayerKillMessage = getProfileInt("Settings","ShowKillMessages",1,"CTF_Settings.ini");
int IDDebug = getProfileInt("Settings","DebugIDMode",1,"CTF_Settings.ini");
int HaveWeather = getProfileInt("Settings","EnableWeather",1,"CTF_Settings.ini");



unsigned long GetPlayerData(GameObject *obj) {
	__asm {
	   mov edx, obj
	   mov eax, dword ptr[edx + 960h]
	};
} 
    
unsigned long GetName(unsigned long ptr_) { 
	__asm {
		mov edx, [ptr_]
		mov eax, dword ptr[edx + 758h]
	};
}

char *Read16BitString(unsigned long ptr){
	int size = 0;
	char chr;
	int x = 0;
	unsigned long offs;
	while (1){
 		offs = ptr + x;
 		x += 2;
 		chr = *reinterpret_cast<const char*>(offs);
 		size++;
 		if (chr == 0)
 			break;
	}
	char *temp = (char *)malloc(size + 1);
	for (int y = 0; y < size; y++){
 		temp[y] = *reinterpret_cast<const char*>(ptr + (y * 2));
	}
	return temp;
}

GameObject *SoldierGameObj(GameObject *obj) {
	_asm {
		mov ecx,obj
		mov eax,[ecx]
		call [eax+44]
	}
}

int Get_PID(GameObject *obj) {
	if (SoldierGameObj(obj) != 0) {
		_asm {
			mov eax, obj
			cmp eax, 0
			jz loc1
			mov eax, [eax + 0x960]
			loc1:
		}
	}
	else return 0;
}

/*GameObject *Get_Vehicle(GameObject *obj) {
	_asm {
		mov eax, obj
		mov eax, [eax+98Ch]
	}
}*/

void ConsoleCommand(char *msg) {
	typedef void (*ConsoleMsg)(char *);
	ConsoleMsg do_consolemsg;
	do_consolemsg = (ConsoleMsg)0x00428960;
	do_consolemsg(msg);
}

char *Translate_Preset(GameObject *obj) {
	const char *preset = Commands->Get_Preset_Name(obj);
	char *TransName = (char *)malloc(256);
	getProfileString("Translated_Preset",preset,preset,TransName,256,"CTF_Settings.ini");
	return TransName;
}

char *PlayerName(GameObject *obj) { 
	if (Get_PID(obj) != 0) return Read16BitString(GetName(GetPlayerData(obj)));
	else return "ERROR_NotPlayer";
}

GameObject *IsPlayerVehicle(GameObject *obj) {
	if (Get_Vehicle(obj) != 0) return Get_Vehicle(obj);
	else return obj;
}

GameObject *FindPlayer (const char *name) {
	std::string CallData = name;
	if (CallData.empty()) CallData = "Error";
	int Count = 0;
	float StartDistance = 0.1f;
	Vector3 Pos;
	Pos.X = 0.0f;
	Pos.Y = 0.0f;
	Pos.Z = 0.0f;
	GameObject *You = Commands->Create_Object("Invisible_Object",Pos);
	GameObject *Him = You;
	while (strcmp(CallData.c_str(),PlayerName(Him)) != 0) {
		Him = Commands->Find_Closest_Soldier(Commands->Get_Position(You),StartDistance,1000.0f,true);
		StartDistance = (Commands->Get_Distance(Commands->Get_Position(You),Commands->Get_Position(Him)) + 0.1f);
		Count++;
		if (StartDistance > 1000.0f) break;
		if (Count > 500) break;
		if (Him == 0) break;
	}
	return Him;
}

bool IsFemale (GameObject *obj) {
	if (strcmp(Commands->Get_Preset_Name(obj),"CnC_GDI_Engineer_2SF") == 0) return true;
	else if (strcmp(Commands->Get_Preset_Name(obj),"CnC_Sydney_PowerSuit") == 0) return true;
	else if (strcmp(Commands->Get_Preset_Name(obj),"CnC_Sydney") == 0) return true;
	else if (strcmp(Commands->Get_Preset_Name(obj),"CnC_Nod_Minigunner_3Boss") == 0) return true;
	else if (strcmp(Commands->Get_Preset_Name(obj),"CnC_Nod_Minigunner_3Boss_ALT2") == 0) return true;
	return false;
}



class M00_BUILDING_EXPLODE_NO_DAMAGE_DAK : public ScriptImpClass {
	void Created(GameObject *obj);
	void Damaged(GameObject *obj, GameObject *damager, float damage);
	void Destroyed(GameObject *obj);
};

class M00_Disable_Transition : public ScriptImpClass {
	void Created(GameObject *obj);
	void Damaged(GameObject *obj, GameObject *damager, float damage);
};

class M00_GrantPowerup_Created : public ScriptImpClass {
	void Created(GameObject *obj);
	void Killed(GameObject *obj, GameObject *shooter);
	void Timer_Expired(GameObject *obj,int number);
	void Destroyed(GameObject *obj);
	void Register_Auto_Save_Variables();
	bool IsDestroyed;
	std::string Dropper;
	bool IsAlive;
	int done;
};

class KAK_Backpack_Object : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
	GameObject *BackpackScript;
	Vector3 DeathPlace;
};

class KAK_CTF_Flag : public ScriptImpClass {
	void Custom(GameObject *obj, int message, int param, GameObject *sender);
};

class KAK_CTF_DropFlag : public ScriptImpClass {
	void Created(GameObject *obj);
	void Custom(GameObject *obj, int message, int param, GameObject *sender);
	void Timer_Expired(GameObject *obj, int number);
};

class KAK_Select_Flag : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
	void Custom(GameObject *obj, int message, int param, GameObject *sender);
};

class KAK_Limit_Announcement : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
};

class KAK_FlagHolder_Regen : public ScriptImpClass {
	void Created(GameObject *obj);
	void Damaged(GameObject *obj, GameObject *damager, float damage);
	void Killed(GameObject *obj, GameObject *shooter);
	void Timer_Expired(GameObject *obj, int number);
	void Custom(GameObject *obj, int message, int param, GameObject *sender);
	bool IsAlive;
};

class KAK_FlagHolder_Appear : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
	void Custom(GameObject *obj, int message, int param, GameObject *sender);
	void Killed(GameObject *obj, GameObject *shooter);
};

class KAK_Flag_Icon : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
	GameObject *Icon;
	int LastLoc;
	Vector3 IconPos;
};

class KAK_Capture_Animation : public ScriptImpClass {
	void Created(GameObject *obj);
	void Animation_Complete(GameObject *obj, const char *anim);
	void Timer_Expired(GameObject *obj, int number);
};

class KAK_Random_Weather : public ScriptImpClass {
	void Created(GameObject *obj);
	void Timer_Expired(GameObject *obj, int number);
	float Range, CurrentClouds, CurrentRain, CurrentLightning, CurrentSnow, CurrentAsh, CurrentWind, FogEnd;
	char MapName[256], WeatherType[256], IDNum[10];
};

class M00_PCT_Pokable_DAK : public ScriptImpClass {
   void Damaged(GameObject *obj, GameObject *damager, float damage);
   void Killed(GameObject *obj, GameObject *shooter);
   void Poked(GameObject *obj,GameObject * poker);
};
float Get_Character_Price(const char *Preset);