/*	Renegade Scripts.dll
	Misc. Scripts by WhiteDragon(MDB)
	Copyright 2007 Jonathan Wilson, WhiteDragon(MDB)

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/

#include "scripts.h"
#include "engine.h"
#include "mdb.h"
#include "mdbevf.h"

struct Scope {
	char *Weapon;
	int Num;
};

SimpleDynVecClass<Scope*> *Scopes;

int LookupScopeByWeapon(const char *Weap)
{
	if (!Weap)
	{
		return -2;
	}
	if (!Scopes)
	{
		return -2;
	}
	if (!Scopes->Length())
	{
		return -2;
	}
	int x = Scopes->Length();
	for (int i = 0; i < x; i++)
	{
		if (!_stricmp((*Scopes)[i]->Weapon,Weap))
		{
			return (*Scopes)[i]->Num;
		}
	}
	return -2;
}

char *LookupScopeByNumber(int Num)
{
	if (!Scopes)
	{
		return "none";
	}
	if (!Scopes->Length())
	{
		return "none";
	}
	int x = Scopes->Length();
	for (int i = 0; i < x; i++)
	{
		if ((*Scopes)[i]->Num == Num)
		{
			return (*Scopes)[i]->Weapon;
		}
	}
	return "none";
}

void LoadScopes()
{
	Scopes = new SimpleDynVecClass<Scope*>();
	int handle = Commands->Text_File_Open("weaponscope.cfg");
	if (!handle)
	{
		return;
	}
	char data[100];
	while (Commands->Text_File_Get_String(handle,data,99))
	{
		Scope *s = new Scope;
		char *a = strtok(data,"=");
		char *b = strtok(NULL,"=");
		s->Weapon = newstr(a);
		s->Num = atoi(b);
		Scopes->Add(s);
	}
	Commands->Text_File_Close(handle);
}

void FreeScopes()
{
	if (!Scopes)
	{
		return;
	}
	int x = Scopes->Length();
	for (int i = 0; i < x; i++)
	{
		delete[] (*Scopes)[i]->Weapon;
		delete (*Scopes)[i];
	}
	delete Scopes;
	Scopes = 0;
}


void MDB_Weapon_Scope::Created(GameObject *obj)
{
	int Temp = Get_Int_Parameter("Default_Scope");
	Set_Scope(obj,Temp);
	CurrScope = Temp;
	Commands->Start_Timer(obj,this,1.0f,1);
}

void MDB_Weapon_Scope::Timer_Expired(GameObject *obj,int number)
{
	int Temp = LookupScopeByWeapon(Get_Current_Weapon(obj));
	if (Temp == -2)
	{
		int Temp2 = Get_Int_Parameter("Default_Scope");
		if (CurrScope != Temp2)
		{
			Set_Scope(obj,Temp2);
			CurrScope = Temp2;
		}
	}
	else if (CurrScope != Temp)
	{
		Set_Scope(obj,Temp);
		CurrScope = Temp;
	}
	Commands->Start_Timer(obj,this,1.0f,1);
}

void MDB_Weapon_Scope::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,4,&CurrScope);
}

void MDB_Weapon_Scope_Global::Created(GameObject *obj)
{
	sprintf(Params,"%d",Get_Int_Parameter("Default_Scope"));
}

void MDB_Weapon_Scope_Global::ObjectCreateHook(GameObject *obj)
{
	if (Commands->Is_A_Star(obj))
	{
		Attach_Script_Once(obj,"MDB_Weapon_Scope",Params);
	}
}

void MDB_Change_Spawn_Char_Custom::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == Get_Int_Parameter("Message"))
	{
		Change_Spawn_Char(param,Get_Parameter("Character"));
	}
}

void MDB_Change_Spawn_Char_Timer::Created(GameObject *obj)
{
	Commands->Start_Timer(obj,this,Get_Float_Parameter("Time"),1);
}

void MDB_Change_Spawn_Char_Timer::Timer_Expired(GameObject *obj, int number)
{
	if (number == 1)
	{
		Change_Spawn_Char(Get_Int_Parameter("Team"),Get_Parameter("Character"));
	}
}

void MDB_ConYard::Created(GameObject *obj)
{
	if (created != 1337)
	{
		Time = Get_Float_Parameter("Interval");
		Amount = Get_Float_Parameter("Heal_Amount");
		Self = Get_Int_Parameter("Repair_Self");
		PMode = Get_Int_Parameter("Power_Mode");
		Commands->Start_Timer(obj,this,Time,1);
		created = 1337;
	}
}

void MDB_ConYard::Timer_Expired(GameObject *obj, int number)
{
	if (!Is_Base_Powered(Get_Object_Type(obj)) && PMode != 1)
	{
		if (!PMode)
		{
			Destroy_Script();
			return;
		}
		else if (PMode == 2)
		{
			Amount = (Amount*Get_Float_Parameter("Power_Amount"));
		}
		else if (PMode == 3)
		{
			Time = (Time*Get_Float_Parameter("Power_Amount"));
		}
		PMode = 1;
	}
	Repair_All_Buildings_By_Team(Get_Object_Type(obj),Self?0:Commands->Get_ID(obj),Amount);
	Commands->Start_Timer(obj,this,Time,1);
}

void MDB_ConYard::Killed(GameObject *obj,GameObject *shooter)
{
	Amount = 0.0f;
	Destroy_Script();
}

void MDB_ConYard::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,4,&PMode);
	Auto_Save_Variable(2,4,&created);
	Auto_Save_Variable(3,4,&Time);
	Auto_Save_Variable(4,4,&Amount);
	Auto_Save_Variable(5,1,&Self);
}

void MDB_Send_Custom_Enemy_Seen::Created(GameObject *obj)
{
	Commands->Enable_Hibernation(obj,false);
	Commands->Innate_Enable(obj);
	Commands->Enable_Enemy_Seen(obj,true);
}

void MDB_Send_Custom_Enemy_Seen::Enemy_Seen(GameObject *obj,GameObject *seen)
{
	GameObject *Temp = Commands->Find_Object(Get_Int_Parameter("ID"));
	if (!Temp)
	{
		Commands->Destroy_Object(obj);
	}
	else
	{
		Commands->Send_Custom_Event(seen,Temp,Get_Int_Parameter("Message"),0,0);
	}
}

void MDB_Water_Zone::Entered(GameObject *obj,GameObject *enter)
{
	if (!Is_Script_Attached(enter,"MDB_Water_Unit"))
	{
		Commands->Apply_Damage(enter,Get_Float_Parameter("Damage"),Get_Parameter("Warhead"),0);
	}
}

void MDB_Vehicle_Limit::Created(GameObject *obj)
{
	char Limit[20];
	sprintf(Limit,"vlimit %d",Get_Int_Parameter("Limit"));
	Console_Input(Limit);
}

void MDB_Mine_Limit::Created(GameObject *obj)
{
	char Limit[20];
	int Num = Get_Int_Parameter("Limit");
	if (Num > 127) Num = 127;
	sprintf(Limit,"mlimit %d",Num);
	Console_Input(Limit);
}

void MDB_Unit_Limit::Created(GameObject *obj)
{
	Team = Get_Object_Type(obj);
	int Count = Get_Object_Count(2,Commands->Get_Preset_Name(obj));
	StringID = 0;
	if (Count > Get_Int_Parameter("Limit"))
	{
		Commands->Destroy_Object(obj);
	}
	else
	{
		unsigned long ID = Get_Definition_ID(Commands->Get_Preset_Name(obj));
		PurchaseSettingsDefClass *p = 0;
		unsigned int i;
		for (i = 0; i < 5; i++)
		{
			p = Get_Purchase_Definition(i,PTTEAM(Team));
			if (!p)
			{
				continue;
			}
			for (unsigned int j = 0; j < 10; j++)
			{
				if (p->presetids[j] == ID)
				{
					Free = false;
					Position = j;
					Type = i;
					Cost = p->costs[j];
					StringID = p->stringids[j];
					if (Count == Get_Int_Parameter("Limit"))
					{
						if (p->stringids[j] != STRINGID_UNAVAIL)
						{
							UnitInfo *Info = 0;
							if (ExpVehFac[Team] && ExpVehFac[Team]->Loaded && Is_Vehicle(Owner()))
							{
								Info = ExpVehFac[Team]->Get_Unit_Info(Commands->Get_Preset_ID(Owner()));
							}	
							if (Info && p->stringids[j] == STRINGID_LIMIT && Info->DMode == DISABLED_EVF)
							{
								Info->DMode = DISABLED_BOTH;
							}
							else
							{
								if (!Get_Int_Parameter("Sidebar"))
								{
									p->costs[j] = 1000000;
								}
								if (Info)
								{
									Info->DMode = DISABLED_UNIT;
								}
								p->stringids[j] = 9724;
								Update_PT_Data();
							}
						}
					}
					return;
				}
			}
		}
		TeamPurchaseSettingsDefClass *t = Get_Team_Purchase_Definition(PTTEAM(Team));
		for (i = 0; i < 4; i++)
		{
			if (t->presetids[i] == ID)
			{
				Free = true;
				Position = i;
				StringID = t->presetids[i];
				if (Count == Get_Int_Parameter("Limit"))
				{
					t->presetids[i] = 0;
					Update_PT_Data();
				}
			}
		}
	}
}

void MDB_Unit_Limit::ReEnable()
{
	if (StringID)
	{
		if (!Free)
		{
			PurchaseSettingsDefClass *p = Get_Purchase_Definition(Type,PTTEAM(Team));
			if (!p)
			{
				return;
			}
			if (p->stringids[Position] != STRINGID_UNAVAIL)
			{
				if (ExpVehFac[Team] && ExpVehFac[Team]->Loaded && Is_Vehicle(Owner()))
				{
					UnitInfo *Info = ExpVehFac[Team]->Get_Unit_Info(Commands->Get_Preset_ID(Owner()));
					if (Info->DMode == DISABLED_UNIT)
					{
						if ((Info->VehType == VEHTYPE_GROUND && ExpVehFac[Team]->Is_Ground_Building) || (Info->VehType == VEHTYPE_FLYING && ExpVehFac[Team]->Is_Flying_Building) || (Info->VehType == VEHTYPE_NAVAL && ExpVehFac[Team]->Is_Naval_Building))
						{
							p->stringids[Position] = STRINGID_BUILDING;
						}
						else
						{
							if (!Get_Int_Parameter("Sidebar"))
							{
								p->costs[Position] = Info->Cost;
							}
							p->stringids[Position] = Info->StringID;
						}
						Update_PT_Data();
					}
					else if (Info->DMode == DISABLED_BOTH)
					{
						Info->DMode = DISABLED_EVF;
					}	
				}
				else
				{
					if (!Get_Int_Parameter("Sidebar"))
					{
						p->costs[Position] = Cost;
					}
					p->stringids[Position] = StringID;
					Update_PT_Data();
				}
			}
		}
		else
		{
			TeamPurchaseSettingsDefClass *t = Get_Team_Purchase_Definition(PTTEAM(Team));
			if (!t->presetids[Position])
			{
				t->presetids[Position] = StringID;
				Update_PT_Data();
			}
		}
	}
}

void MDB_Unit_Limit::Destroyed(GameObject *obj)
{
	ReEnable();
	StringID = 0;
}

void MDB_Unit_Limit::Detach(GameObject *obj)
{
	ReEnable();
}

void MDB_Unit_Limit::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,4,&Position);
	Auto_Save_Variable(2,4,&Type);
	Auto_Save_Variable(3,4,&Team);
	Auto_Save_Variable(4,4,&Cost);
	Auto_Save_Variable(5,4,&StringID);
	Auto_Save_Variable(6,1,&Free);
}

void MDB_Send_Custom_On_Key::Created(GameObject *obj)
{
	if (is_keyhook_set != 1337)
	{
		InstallHook(Get_Parameter("Key"),obj);
		is_keyhook_set = 1337;
	}
}

void MDB_Send_Custom_On_Key::KeyHook()
{
	Commands->Send_Custom_Event(Owner(),Commands->Find_Object(Get_Int_Parameter("ID")),Get_Int_Parameter("Message"),0,0);
	if (Get_Int_Parameter("Once"))
	{
		Destroy_Script();
	}
}

void MDB_Remote_Controlled_Vehicle::Created(GameObject *obj)
{
	Commands->Start_Timer(obj,this,1.0f,1);
	BotID = 0;
}

void MDB_Remote_Controlled_Vehicle::Timer_Expired(GameObject *obj,int number)
{
	GameObject *Own = Get_Vehicle_Owner(obj);
	if (Own)
	{
		Send_Message_Player(Own,255,255,255,"Verifying encryption protocol...");
		char msg[256];
		const char *c = Get_Translated_Preset_Name(obj);
		sprintf(msg,"Remote connection to %s established",c);
		delete[] c;
		Send_Message_Player(Own,255,255,255,msg);
		Vector3 Pos = Commands->Get_Position(Own);
		float Facing = Commands->Get_Facing(Own);
		Commands->Set_Position(Own,Commands->Get_Position(obj));
		Commands->Enable_Engine(obj,false);
		GameObject *Bot = Commands->Create_Object(Commands->Get_Preset_Name(Own),Pos);
		BotID = Commands->Get_ID(Bot);
		Soldier_Transition_Vehicle(Own);
		Commands->Set_Facing(Bot,Facing);
		Commands->Set_Health(Bot,Commands->Get_Health(Own));
		Commands->Set_Shield_Strength(Bot,Commands->Get_Shield_Strength(Own));
		char params[20];
		sprintf(params,"%d",Commands->Get_ID(Own));
		Commands->Attach_Script(Bot,"MDB_Remote_Controlled_Vehicle_Bot",params);
	}
}

void MDB_Remote_Controlled_Vehicle::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == CUSTOM_EVENT_VEHICLE_EXIT && BotID)
	{
		GameObject *Bot = Commands->Find_Object(BotID);
		Commands->Set_Model(Bot,"null");
		Commands->Attach_To_Object_Bone(sender,Bot,"Origin");
		Commands->Send_Custom_Event(obj,Bot,72386,0,0.5f);
		BotID = 0;
		Commands->Enable_Vehicle_Transitions(obj,false);
	}
}

void MDB_Remote_Controlled_Vehicle::Destroyed(GameObject *obj)
{
	GameObject *Bot = Commands->Find_Object(BotID);
	GameObject *Player = Get_Vehicle_Occupant(obj,0);
	Commands->Set_Model(Bot,"null");
	Commands->Attach_To_Object_Bone(Player,Bot,"Origin");
	Commands->Send_Custom_Event(obj,Bot,72386,0,0.5f);
	char msg[256];
	const char *c = Get_Translated_Preset_Name(obj);
	sprintf(msg,"Remote connection to %s lost",c);
	delete[] c;
	Send_Message_Player(Player,255,255,255,msg);
}

void MDB_Remote_Controlled_Vehicle::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,4,&BotID);
}

void MDB_Remote_Controlled_Vehicle_Bot::Created(GameObject *obj)
{
	ID = Get_Int_Parameter("ID");
}

void MDB_Remote_Controlled_Vehicle_Bot::Damaged(GameObject *obj,GameObject *damager,float damage)
{
	if (Commands->Get_Health(obj) > 0)
	{
		GameObject *Player = Commands->Find_Object(ID);
		if (!Player)
		{
			Commands->Destroy_Object(obj);
			return;
		}
		Commands->Set_Health(Player,Commands->Get_Health(obj));
		Commands->Set_Shield_Strength(Player,Commands->Get_Shield_Strength(obj));
	}
}

void MDB_Remote_Controlled_Vehicle_Bot::Killed(GameObject *obj,GameObject *shooter)
{
	GameObject *Player = Commands->Find_Object(ID);
	Soldier_Transition_Vehicle(Player);
	Commands->Apply_Damage(Player,99999.0f,"Death",shooter);
}

void MDB_Remote_Controlled_Vehicle_Bot::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == 72386)
	{
		Commands->Destroy_Object(obj);
	}
}

void MDB_Remote_Controlled_Vehicle_Bot::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,4,&ID);
	Auto_Save_Variable(2,4,&VehID);
}

void MDB_Sidebar_Key::Created(GameObject *obj)
{
	if (is_keyhook_set != 1337)
	{
		InstallHook(Get_Parameter("Key"),obj);
		is_keyhook_set = 1337;
		Enabled = Get_Int_Parameter("Start_Enabled");
	}
}

void MDB_Sidebar_Key::KeyHook()
{
	GameObject *obj = Owner();
	if (Enabled && !Get_Vehicle(obj))
	{
		if (!Get_Object_Type(obj))
		{
			Display_NOD_Sidebar(obj);
		}
		else
		{
			Display_GDI_Sidebar(obj);
		}
	}
}

void MDB_Sidebar_Key::Register_Auto_Save_Variables()
{
	Auto_Save_Variable(1,1,&Enabled);
}

void MDB_Sidebar_Key::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == Get_Int_Parameter("Disable_Custom"))
	{
		Enabled = false;
	}
	else if (message == Get_Int_Parameter("Enable_Custom"))
	{
		Enabled = true;
	}
}

void MDB_Set_Ammo_Granted_Weapon_On_Pickup::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == CUSTOM_EVENT_POWERUP)
	{
		const char *Weapon = Get_Powerup_Weapon_By_Obj(obj);
		int Ammo = Get_Int_Parameter("Ammo");
		int Clip_Ammo = Get_Int_Parameter("Clip_Ammo");
		if (Ammo != -2)
		{
			Set_Bullets(sender,Weapon,Ammo);
		}
		if (Clip_Ammo != -2)
		{
			Set_Clip_Bullets(sender,Weapon,Clip_Ammo);
		}
	}
}

void MDB_Set_Ammo_Current_Weapon_On_Pickup::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == CUSTOM_EVENT_POWERUP)
	{
		int Ammo = Get_Int_Parameter("Ammo");
		int Clip_Ammo = Get_Int_Parameter("Clip_Ammo");
		if (Ammo != -2)
		{
			Set_Current_Bullets(sender,Ammo);
		}
		if (Clip_Ammo != -2)
		{
			Set_Current_Clip_Bullets(sender,Clip_Ammo);
		}
	}
}

void MDB_Set_Ammo_On_Pickup::Custom(GameObject *obj, int message, int param, GameObject *sender)
{
	if (message == CUSTOM_EVENT_POWERUP)
	{
		const char *Weapon = Get_Parameter("Weapon");
		int Ammo = Get_Int_Parameter("Ammo");
		int Clip_Ammo = Get_Int_Parameter("Clip_Ammo");
		if (Ammo != -2)
		{
			Set_Bullets(sender,Weapon,Ammo);
		}
		if (Clip_Ammo != -2)
		{
			Set_Clip_Bullets(sender,Weapon,Clip_Ammo);
		}
	}
}

ScriptRegistrant<MDB_Weapon_Scope> MDB_Weapon_Scope_Registrant("MDB_Weapon_Scope","Default_Scope=-1:int");
ScriptRegistrant<MDB_Weapon_Scope_Global> MDB_Weapon_Scope_Global_Registrant("MDB_Weapon_Scope_Global","Default_Scope=-1:int");
ScriptRegistrant<MDB_Change_Spawn_Char_Custom> MDB_Change_Spawn_Char_Custom_Registrant("MDB_Change_Spawn_Char_Custom","Message=0:int,Character:string");
ScriptRegistrant<MDB_Change_Spawn_Char_Timer> MDB_Change_Spawn_Char_Timer_Registrant("MDB_Change_Spawn_Char_Timer","Time=0:float,Team=-1:int,Character:string");
ScriptRegistrant<MDB_ConYard> MDB_ConYard_Registrant("MDB_ConYard","Interval=5.0:float,Heal_Amount=5.0:float,Power_Mode=1:int,Power_Amount=0.0:float,Repair_Self=0:int");
ScriptRegistrant<MDB_Send_Custom_Enemy_Seen> MDB_Send_Custom_Enemy_Seen_Registrant("MDB_Send_Custom_Enemy_Seen","Message=0:int,ID=0:int");
ScriptRegistrant<MDB_Water_Zone> MDB_Water_Zone_Registrant("MDB_Water_Zone","Damage=0.0:float,Warhead=None:string");
ScriptRegistrant<MDB_Water_Unit> MDB_Water_Unit_Registrant("MDB_Water_Unit","");
ScriptRegistrant<MDB_Vehicle_Limit> MDB_Vehicle_Limit_Registrant("MDB_Vehicle_Limit","Limit=7:int");
ScriptRegistrant<MDB_Mine_Limit> MDB_Mine_Limit_Registrant("MDB_Mine_Limit","Limit=30:int");
ScriptRegistrant<MDB_Unit_Limit> MDB_Unit_Limit_Registrant("MDB_Unit_Limit","Limit=1:int,Sidebar=0:int");
ScriptRegistrant<MDB_Send_Custom_On_Key> MDB_Send_Custom_On_Key_Registrant("MDB_Send_Custom_On_Key","Key=Key:string,ID=0:int,Message=0:int,Once=1:int");
ScriptRegistrant<MDB_Remote_Controlled_Vehicle> MDB_Remote_Controlled_Vehicle_Registrant("MDB_Remote_Controlled_Vehicle","");
ScriptRegistrant<MDB_Remote_Controlled_Vehicle_Bot> MDB_Remote_Controlled_Vehicle_Bot_Registrant("MDB_Remote_Controlled_Vehicle_Bot","ID=0:int");
ScriptRegistrant<MDB_Sidebar_Key> MDB_Sidebar_Key_Registrant("MDB_Sidebar_Key","Key=Sidebar:string,Start_Enabled=0:int,Enable_Custom=0:int,Disable_Custom=0:int");
ScriptRegistrant<MDB_Set_Ammo_Granted_Weapon_On_Pickup> MDB_Set_Ammo_Granted_Weapon_On_Pickup_Registrant("MDB_Set_Ammo_Granted_Weapon_On_Pickup","Ammo=-2:int,Clip_Ammo=-2:int");
ScriptRegistrant<MDB_Set_Ammo_Current_Weapon_On_Pickup> MDB_Set_Ammo_Current_Weapon_On_Pickup_Registrant("MDB_Set_Ammo_Current_Weapon_On_Pickup","Weapon=WeaponName:string,Ammo=-2:int,Clip_Ammo=-2:int");
ScriptRegistrant<MDB_Set_Ammo_On_Pickup> MDB_Set_Ammo_On_Pickup_Registrant("MDB_Set_Ammo_On_Pickup","Ammo=-2:int,Clip_Ammo=-2:int");
