//	VIETCONG 1
//	COOP_VC script (with automatic global variables for synchronized objects)
//	Created by Ando
//	v3.1



//	NOTES:
// 1.1 - added global wariables system
// 1.2 - added variable for server (600) to detect server from object scripts
// 1.2 - new G-var system (object scripts counting g-vars to channel 601 )
// 1.4 - added mission objectives test
// 2.0 - successfully tested with L|DC-78
// 2.1 - added civilian option
// 2.1 - mission restart when civilian is killed by us an message apears who killed civilian
// 2.1 - "mission fail" restart with fast fade
// 2.1 - fade when mission restarts
// 2.2 - switch to next map when mission done
// 3.0 - TESTED WITH TEAM
// 3.1 - added sound for "mission FAILED"
// 3.1 - added sound for "mission DONE"

// IDEAS





#include <inc\sc_global.h>
#include <inc\sc_def.h>

#define FADE_TIME			0.8

#define		DONE_SOUND		6035	//snd 6035 music\slap25.ogg
#define		FAILED_SOUND	6057	//snd 6057 music\slap47.ogg
//________________________________
//global variable system for object synchro  !!!DONT CHANGE THOSE!!!
#define GVAR_SERVER			600 	//	server  ( dont add SC_MP_Gvar_SetSynchro for that) 0 - not server, 1 - server
#define GVAR_COUNT			601 	//  count of object variables ( dont add SC_MP_Gvar_SetSynchro for that)
#define GVAR_USE_start		602 		//start		Global variable
//________________________________

#define GVAR_GPHASE				500

#define GVAR_KILLED				501
#define GVAR_KILLER				502



//#define RECOVER_TIME	15.0f		// time to global recover
#define NORECOV_TIME	3.0f		// disable time of recoverplace after recovering someone there

#define REC_WPNAME_US	"VCSpawn_coop_%d"
#define REC_MAX			64


s_SC_Objective Objectives [10];
int objective_count=0;
int remaining_time=0;


dword gRecs = 0;
s_SC_MP_Recover gRec[REC_MAX];
float gRecTimer[REC_MAX];

float gNextRecover = 0.0f;

dword gEndRule;
dword gEndValue;
float gTime;

#define GPHASE_BEGIN			1
#define GPHASE_GAME				2
#define GPHASE_DONE				3
#define GPHASE_FAILED			4
#define GPHASE_BEFORE_RESTART	5
#define GPHASE_RESTARTING		6	

#define RESTART_TIMER		3	//time before actual restart
#define FAIL_TIMER			7	//time before actual restart

dword	gPhase = GPHASE_BEGIN;
float	gPhase_timer = 5.0f;
float	client_fade_timer;
dword	gPhase_send = 0;

BOOL gValidSide0 = FALSE;
BOOL    notincar = TRUE;
BOOL    fade_off = TRUE;
BOOL	sound_start=TRUE;

dword gRecoverTime =	0;
dword gRecoverLimit =	0;

float gAllNoAiRecover  = 0.0f;

BOOL SRV_CheckEndRule(float time){
	switch(gEndRule){
		case SC_MP_ENDRULE_TIME:			
			if (gValidSide0) gTime += time;
			SC_MP_EndRule_SetTimeLeft(gTime,gValidSide0);
			if (gTime>gEndValue){
				SC_MP_LoadNextMap();
				return TRUE;
			}
			break;
		default:
			SC_message("EndRule unsopported: %d",gEndRule);
			break;
	}// switch(gEndRule)
	return FALSE;
}// void SRV_CheckEndRule(float time)

void SRV_CheckUpdate(void){
	if (gPhase_send!=gPhase){
		gPhase_send = gPhase;
		SC_sgi(GVAR_GPHASE,gPhase);
		//SC_message("SRV_CheckUpdate %d",gPhase);
	}// if (gPhase_send!=gPhase)
}// void SRV_CheckUpdate(void)

int ScriptMain(s_SC_NET_info *info)
{
	s_SC_MP_EnumPlayers		enum_pl[64];
	s_SC_MP_SRV_settings	SRVset;
	s_SC_MP_Recover			*precov;
	s_SC_MP_hud				hudinfo;
	s_SC_P_getinfo			plinfo;
	s_SC_P_getinfo			my_plinfo;
	dword	i, j, sideA, sideB, num;
	BOOL	valid[2];
	BOOL	alldeath;
	char	txt[32],*itxt;
	ushort wtxt[128],wtxt2[64],*witxt,*my_witxt;
	float	sc_width,sc_height,val;

	//
	switch(info->message){
		case SC_NET_MES_SERVER_TICK:	
			if (SRV_CheckEndRule(info->elapsed_time)) break;
			for (j=0;j<4;j++)
			for (i=0;i<gRecs;i++)
				gRecTimer[i] -= info->elapsed_time;
			if (gRecoverTime<0xffff){
				gNextRecover -= info->elapsed_time;
				if (gNextRecover<0.0f) gNextRecover = (float)gRecoverTime;
			}// if (gRecoverTime<0xffff)
			if (gAllNoAiRecover>0.0f){
				gAllNoAiRecover -= info->elapsed_time;				
				if (gAllNoAiRecover<=0.0f)
					SC_MP_RecoverAllNoAiPlayers();			
				break;
			}// if (gAllNoAiRecover>0.0f)
			else{
				gAllNoAiRecover -= info->elapsed_time;
			}
			CLEAR(valid);			
			j = 64;
			alldeath = FALSE;
			if (SC_MP_EnumPlayers(enum_pl,&j,SC_MP_ENUMPLAYER_SIDE_ALL)){
				alldeath = TRUE;
				for (i=0;i<j;i++){
					if (enum_pl[i].status==SC_MP_P_STATUS_INGAME){
						if (enum_pl[i].side>1); //SC_message("coop script wrong side: %d",enum_pl[i].side);
						else{
							valid[enum_pl[i].side] = TRUE;
						}
					}
					if ((enum_pl[i].side==1)&&(enum_pl[i].status==SC_MP_P_STATUS_INGAME)) alldeath = FALSE;
				}// for (i)
				//SC_message("Enum, v[0]: %d   v[1]: %d  alldeath: %d",valid[0],valid[1],alldeath);	
			}// if (SC_MP_EnumPlayers(enum_pl,&j,SC_MP_ENUMPLAYER_SIDE_ALL))
			else SC_message("NoEnum");	
			if ((gPhase==GPHASE_GAME)&&(alldeath)&&(gPhase_timer<0.0f)){
				if (gRecoverLimit==0){
					// mission failed
					//SC_Log(2,"Set GPHASE_FAILED");
					gPhase = GPHASE_FAILED;
					gPhase_timer = 5.0f;
				}
				else {
					// recover unlimited
					//SC_message("recover unlimited");
					if ((gRecoverTime>=0xffff)&&(gAllNoAiRecover<-5.0f)){
						gAllNoAiRecover = 4.0f;					
					}
				}
			}// if ((alldeath)&&(gRecoverTime>=0xffff))
			else gAllNoAiRecover = 0.0f;
			gValidSide0 = valid[1];
			gPhase_timer -= info->elapsed_time;
			switch(gPhase){
				case GPHASE_BEGIN:
					if (notincar){
						notincar = FALSE;
					}
					if (gPhase_timer<0.0f)
					if ((valid[0])&&(valid[1])){
						gPhase_timer = 5.0f;
						gPhase = GPHASE_GAME;	
					}
					break;
				case GPHASE_GAME:
					if (gPhase_timer<0.0f)
					if (!valid[0]){
						gPhase = GPHASE_DONE;
						gPhase_timer = 5.0f;
					}// if (!valid[0])
					break;
				case GPHASE_DONE:
					if (gPhase_timer<0.0f){	//wait before restart
						SC_MP_LoadNextMap();
					}
					break;
				case GPHASE_FAILED:
					if (gPhase_timer<0.0f){//wait before restart
						gPhase_timer = RESTART_TIMER;
						gPhase = GPHASE_BEFORE_RESTART;
					}
					break;
				case GPHASE_BEFORE_RESTART:
					if (gPhase_timer<0.0f){	//wait before restart
						gPhase = GPHASE_RESTARTING;
					}
					break;
				case GPHASE_RESTARTING:
					CLEAR(gRecTimer);
					gNextRecover = 0.0f;
					gTime = 0;
					gPhase = GPHASE_BEGIN;
					gPhase_timer = 5.0f;
					gPhase_send = 0;
					gValidSide0 = FALSE;
					SC_MP_GetSRVsettings(&SRVset);
					gRecoverTime = SRVset.coop_respawn_time;
					gRecoverLimit = SRVset.coop_respawn_limit;
					gAllNoAiRecover  = 0.0f;
					SC_MP_SRV_ClearPlsStats();
					SC_MP_SRV_InitGameAfterInactive();
					SC_MP_RecoverAllAiPlayers();
					SC_MP_RecoverAllNoAiPlayers();	

					//SC_MP_RestartMission();					//restart // causing some truoble //using SC_NET_MES_LEVELINIT
						//_________Reinit AI
						num = 64;
						SC_MP_EnumPlayers(enum_pl, &num, SC_MP_ENUMPLAYER_SIDE_ALL);//SC_MP_ENUMPLAYER_SIDE_ALL is for US_AI and civilian_AI
						for (i = 0; i < num; i++){
							SC_P_ScriptMessage(enum_pl[i].id, SCM_MP_REINIT, 0);
						}
						//_____________________


					break;
			}// switch(gPhase)
			SRV_CheckUpdate();
			break;
		case SC_NET_MES_CLIENT_TICK:
			switch(SC_ggi(GVAR_GPHASE)){
			case GPHASE_BEGIN:
				if (fade_off == FALSE){
					SC_FadeTo(FALSE, FADE_TIME);
					fade_off=TRUE;
				}
				break;
			case GPHASE_GAME:
				break;
			case GPHASE_DONE:
				if (sound_start==TRUE){
					SC_SND_PlaySound2D(DONE_SOUND);
					sound_start=FALSE;
				}
				break;
			case GPHASE_FAILED:
				if (sound_start==TRUE){
					SC_SND_PlaySound2D(FAILED_SOUND);
					sound_start=FALSE;
				}
				break;
			case GPHASE_BEFORE_RESTART:
				client_fade_timer -= info->elapsed_time;
				if (client_fade_timer<FADE_TIME){	
					SC_FadeTo(TRUE, FADE_TIME);
					fade_off=FALSE;
					sound_start=TRUE;
					client_fade_timer=RESTART_TIMER;
				}
				break;
			case GPHASE_RESTARTING:
				break;
			}// switch(gPhase)
			//SC_message(char *txt,...);
			break;// SC_NET_MES_CLIENT_TICK
		case SC_NET_MES_LEVELPREINIT:
			client_fade_timer=RESTART_TIMER;
			SC_sgi(GVAR_MP_MISSIONTYPE,10);//10 is for custom coop_vc
			gEndRule = info->param1;
			gEndValue = info->param2;
			gTime = 0.0f;
			SC_MP_EnableBotsFromScene(TRUE);
			break;// SC_NET_MES_LEVELPREINIT
		case SC_NET_MES_LEVELINIT:
			//_____________________________________automatic custom global variables_________________
			for (i=GVAR_USE_start;i<GVAR_USE_start+SC_ggi(GVAR_COUNT)+1;i++){	//custom global variables
				SC_MP_Gvar_SetSynchro(i); 
			}
			//_______________________________________________________________________________________
			SC_MP_Gvar_SetSynchro(GVAR_KILLED);	
			SC_MP_Gvar_SetSynchro(GVAR_KILLER);	
			SC_MP_SRV_SetForceSide(1);
			SC_MP_SetItemsNoDisappear(TRUE);
			SC_MP_SRV_SetClassLimit(18,0);
			SC_MP_SRV_SetClassLimit(19,0);
			SC_MP_SRV_SetClassLimit(39,0);
			SC_MP_GetSRVsettings(&SRVset);
			for (i=0;i<6;i++){
				SC_MP_SRV_SetClassLimit(i+1,SRVset.atg_class_limit[i]);
				SC_MP_SRV_SetClassLimit(i+21,SRVset.atg_class_limit[i]);
			}// for (i)
			CLEAR(hudinfo);
			hudinfo.title = 1098;
			hudinfo.sort_by[0] = SC_HUD_MP_SORTBY_KILLS;
			hudinfo.sort_by[1] = SC_HUD_MP_SORTBY_DEATHS | SC_HUD_MP_SORT_DOWNUP;
			hudinfo.sort_by[2] = SC_HUD_MP_SORTBY_PINGS | SC_HUD_MP_SORT_DOWNUP;
			hudinfo.pl_mask = SC_HUD_MP_PL_MASK_KILLS | SC_HUD_MP_PL_MASK_DEATHS | SC_HUD_MP_PL_MASK_CLASS;
			hudinfo.use_sides = TRUE;
			hudinfo.side_name[0] = 1010;
			hudinfo.side_color[0] = 0x44008800;
			hudinfo.side_name[1] = 1011;
			hudinfo.side_color[1] = 0x44ff0000;
			hudinfo.disableUSside = TRUE;
			//hudinfo.disableVCside = TRUE;





			hudinfo.side_mask = SC_HUD_MP_SIDE_MASK_FRAGS;
			SC_MP_HUD_SetTabInfo(&hudinfo);
			SC_MP_AllowStPwD(TRUE);
			SC_MP_AllowFriendlyFireOFF(TRUE);
			SC_MP_SetItemsNoDisappear(FALSE);
			SC_MP_SetChooseValidSides(2);//This function will set the valid sides for the player to choose from. Use 0 for US only, 2 for VC, 3 for both.
			SC_sgi(GVAR_SERVER,0); 
			if (info->param2){
				if (info->param1){// it's server		
					//____________
					SC_sgi(GVAR_SERVER,1);//For object scripts 
					//____________
					SC_MP_Gvar_SetSynchro(GVAR_GPHASE);	
					SC_MP_GetSRVsettings(&SRVset);
					gRecoverTime = SRVset.coop_respawn_time;
					gRecoverLimit = SRVset.coop_respawn_limit;


					if (SC_MP_GetAmmoBoxesEnabled()){
						SC_MP_SRV_InitWeaponsRecovery(10000.0); // change to allow numbered weapons to be shown like in DM. time based 0.0f =never disapears.
					}else{
						SC_MP_SRV_InitWeaponsRecovery(-1.0);
					}


					gRecs = 0;
					for (i=0;i<REC_MAX;i++){		
						sprintf(txt,REC_WPNAME_US,i);			
						if (SC_NET_FillRecover(&gRec[gRecs],txt)) gRecs++;					
					}					
					#if _GE_VERSION_ >= 133
					    i = REC_MAX - gRecs;
						SC_MP_GetRecovers(100,&gRec[gRecs],&i);
						 gRecs += i;
					#endif
					if (gRecs==0) SC_message("no VC recover place defined!");
					CLEAR(gRecTimer);
				}// if (info->param1)
			}//if (info->param2)
			if (info->param1){
				//!!! ++ Reinit AI - NEW
				num = 64;
				SC_MP_EnumPlayers(enum_pl, &num, SC_MP_ENUMPLAYER_SIDE_ALL);
				for (i = 0; i < num; i++){
					SC_P_ScriptMessage(enum_pl[i].id, SCM_MP_REINIT, 0);
				}
				//-- Reinit AI - NEW
			}
			break;// SC_NET_MES_LEVELINIT
		case SC_NET_MES_RENDERHUD:
			switch(SC_ggi(GVAR_GPHASE)){
				case GPHASE_DONE:
					j = 1049;	//1049 - "Vietcong win."  #1081: 	#tee VIETCONG WIN.
					witxt = SC_Wtxt(j);
					SC_GetScreenRes(&sc_width,&sc_height);
					val= sc_width - SC_Fnt_GetWidthW(witxt,1); 
					SC_Fnt_WriteW(val * 0.5f,15,witxt,1,0xffffffff);//0x44008800//0xffffffff
					if(gPhase_timer > 0){
						remaining_time=gPhase_timer;
						swprintf(wtxt,SC_AnsiToUni("LOAD NEXT MISSION after: %d sec.", wtxt2),(int)(remaining_time));
					}
					else{
						swprintf(wtxt,SC_AnsiToUni("LOADING NEXT MISSION", wtxt2));
					}
					
					swprintf(wtxt,SC_AnsiToUni("LOAD NEXT MISSION after: %d sec.", wtxt2),(int)(remaining_time));
					val= sc_width - SC_Fnt_GetWidthW(wtxt,1); 
					SC_Fnt_WriteW(val * 0.5f,50,wtxt,1,0xffffffff);
					break;
				case GPHASE_FAILED:
					swprintf(wtxt,SC_AnsiToUni("%S killed by %S", wtxt2),SC_P_GetName(SC_MP_GetPlofHandle(SC_ggi(GVAR_KILLED))),SC_P_GetName(SC_MP_GetPlofHandle(SC_ggi(GVAR_KILLER))));
					//j = 1081;	//1049 - "Vietcong win."	#1095: 	#tee VIETCONG WIN. PILOT KILLED.	#1081: 	#tee VIETCONG WIN. #2025: #tee Mission failed  #7781: 	#tee Status: MISSION FAILED\n
					witxt = SC_Wtxt(2025);
					SC_GetScreenRes(&sc_width,&sc_height);
					val= sc_width - SC_Fnt_GetWidthW(witxt,1); 
					SC_Fnt_WriteW(val * 0.5f,25,witxt,1,0xffff0000);
					val= sc_width - SC_Fnt_GetWidthW(wtxt,1); 
					SC_Fnt_WriteW(val * 0.5f,50,wtxt,1,0xffff0000);
					
					//#2095: 	#tee Restart
					break;
				case GPHASE_BEFORE_RESTART:
					swprintf(wtxt,SC_AnsiToUni("MISSION RESTARTING", wtxt2));
					SC_GetScreenRes(&sc_width,&sc_height);
					val= sc_width - SC_Fnt_GetWidthW(wtxt,1); 
					SC_Fnt_WriteW(val * 0.5f,50,wtxt,1,0xffffffff);

					break;
				default:j = 0;break;
			}// switch(SC_ggi(GVAR_GPHASE))
			break;
		case SC_NET_MES_SERVER_RECOVER_TIME:
			if (info->param2){
					info->fval1 = 0.1f;
			}
			else{
				// killed
				SC_P_GetInfo(info->param1,&plinfo);			
				if (plinfo.side==1){					
					if (gRecoverLimit>0){
						if (gRecoverTime>=0xffff) info->fval1 = -1.0f;
						else
						if (gRecoverTime>0) info->fval1 = gNextRecover;
							else info->fval1 = 4.0f;						
					}
					else info->fval1 = -1.0f;	
				}
				else info->fval1 = -1.0f;
			}
			break;
//_______________________________________________________________RECOVER_PLACE____________________
		case SC_NET_MES_SERVER_RECOVER_PLACE:
			if (info->param1!=1){
				SC_message("No recover for VC");
				break;
			}
			precov = (s_SC_MP_Recover*)info->param2;
			i = SC_MP_SRV_GetBestDMrecov(gRec,gRecs,gRecTimer,NORECOV_TIME);
			gRecTimer[i] = NORECOV_TIME;
			*precov = gRec[i];			
			break;
//_______________________________________________________________KILL____________________
		case SC_NET_MES_SERVER_KILL:
			SC_P_GetInfo(info->param1,&my_plinfo);				
			if (my_plinfo.side==3){
				gPhase_timer = FAIL_TIMER;
				gPhase=GPHASE_FAILED;
				SC_sgi(GVAR_GPHASE,gPhase);
				if (info->param2){
                    SC_P_GetInfo(info->param2,&my_plinfo);  
					if (my_plinfo.side==1){// killer was VC
						SC_sgi(GVAR_KILLED,SC_MP_GetHandleofPl(info->param1));
						SC_sgi(GVAR_KILLER,SC_MP_GetHandleofPl(info->param2));
					}
				}
			}
			break;// SC_NET_MES_SERVER_KILL
//_______________________________________________________________RESTARTMAP____________________
		case SC_NET_MES_RESTARTMAP:
			gPhase_timer = RESTART_TIMER;
			gPhase = GPHASE_BEFORE_RESTART;
			break;// SC_NET_MES_RESTARTMAP
		case SC_NET_MES_RULESCHANGED:			
			gEndRule = info->param1;
			gEndValue = info->param2;
			gTime = 0.0f;
			break;		
	}// switch(info->message)
	return 1;
}// int ScriptMain(void)
