
//	VIETCONG 1
//	SSA (Sharp Shooter Assault) script - compatible with synchronized objects
//	made by Ando
// v2.4

/*

	______________DESCRIPTION:
SSA (Sharp Shooter Assault)
Sharp Shooter Assault - fight with everybody. No teams, no rules.
Weapon cycles to a random weapon and every player have same weapon.



	______________TUTORIAL FOR EDITOR
ENDRULE:			Frags
RECOVERY POINT:		SSA or waypoint name "SSA_'nr'"  if none then using DM recovery points



*/

/*
//- text added to bottom left
//- 0.5 sec without weapon when change
//- bug with grenade fixed
//- no repeated random weapon choice
//- VC style time counter removed
//- removed invisible gun
//- cant drop weapon continuously
//- clean all 9 weapon slots
//- bug with random choice fixed
//- new weapon cant be one what was last 3 rounds
//- switch right weapon when picked wrong one from ground
//2.2
//- right weap after spawn
- custom recover point id = 28. Added to editor after batch 1.7 
- added fade for restart
- show player in different color (on/off option in script)
- show players count when "TAB" is pressed (on/off option in script)
- cleaned

- added gphase "GPHASE_MISSION_COMPLETED" (used when end condition reached) 
- added text "Mission completed"	//#2026: 	#tee   Mission completed
- added fade to "Mission completed"
- best player in dark red when mission completed
- one definition fix
*/


#include <inc\sc_global.h>
#include <inc\sc_def.h>

#define SHOW_PLAYER_COLOR			1
#define SHOW_PLAYERS_COUNT			1

#define FADE_TIME					0.8
#define RESTART_TIMER				3	//time before actual restart
#define BEGIN_TIMER					3	//

//________________________________Global Variables for MP objects___
//global variable system for object synchro
#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

//________________________________Global Variables__________________
#define GVAR_GPHASE			500		// important to use  game phase and channel 500 for synchronised objects 
#define GVAR_GPHASE_TIME	501		
#define GVAR_CUR_WEAP		502
#define GVAR_WINNER			503 	// winner handle

//________________________________Game phases_______________________
#define GPHASE_BEGIN				1	//objects are restarting
#define GPHASE_WAIT_PLAYERS			2	//wait players
#define GPHASE_START_GAME			3	//fade on and spawn
#define GPHASE_GAME					4	//game
#define GPHASE_MISSION_COMPLETED	5

//________________________________Recover___________________________
#define RECOVER_TIME		5.0f		// time to recover player after killed
#define NORECOV_TIME		3.0f		// disable time of recoverplace after recovering someone there
#define REC_WPNAME			"SSA_%d"		//
#define REC_MAX				64

//#define RECOVER_POINT_ID	28			//custom recower point id.
#ifndef SC_MP_RESPAWN_SSA
#define	SC_MP_RESPAWN_SSA	28	
#endif

#ifndef GVAR_MP_MISSIONTYPE_SSA	
#define	GVAR_MP_MISSIONTYPE_SSA	19
#endif
//__________________________________________________________________






#define ROUND_TIME		40		


#define LIST_COUNT					23		// count of weapons
int	WEAP_LIST[LIST_COUNT]		= {	1,		//M16
									2,		//Ak-47
									4,	// – M1 garand sniper rifle
									6,	// – PPS-41 submachinegun
									7,	// – Colt M1911 pistol
									8,	// – Tokarev pistol
									9,	// – Makarov pistol
									10,	// – Revolver .38
									11,	// – Remmington shotgun
									12,	// – Winchester sniper rifle
									14,	// – SVD Dragunov sniper rifle
									15,	// – SKS Simonov rifle
									17,	// – M60 machinegun
									18,	// – Degtarjev machinegun
									19,	// – USM3 submachinegun
									21,	// – Thompson submachinegun
									22,	// – S&W silenced pistol
									23,	// – PPS-43 submachinegun
									25,	// – M1 carabine
									26,	// – Mosin Nagant rifle
									28,	// – double barelled shotgun
									29,		//Knife
									59 };	//Grenade
	





#define RESTART_TIMER				5	//time before actual restart




dword gPhase =			GPHASE_BEGIN;
float gPhase_timer =	BEGIN_TIMER;




BOOL    fade_off = TRUE;
BOOL 	weap_removed = TRUE;
dword 	gEndRule;
dword 	gEndValue;
dword 	gPlayersConnected = 0;
dword 	gRecs = 0;
float 	delay_timer;
float 	gRecTimer[REC_MAX];
float 	gTime;
float 	new_time;
float 	Prev_time;
float 	update_timer;
float	client_fade_timer = RESTART_TIMER;
float	complete_f_timer=0;
float 	CLN_gPhase_timer;
float	fade_off_timer;
int		cur_weap=0;
int		CLN_cur_weap=0;
int 	last_srv_weap_2=0;
int 	last_srv_weap_3=0;
int 	last_srv_weap_4=0;
int 	last_srv_weap_5=0;
int 	last_srv_weap=0;
int 	last_weap=-1;
int 	my_min;
int 	my_sec;
s_SC_MP_Recover 	gRec[REC_MAX];
s_SC_P_Create		get_weap_inf;
ushort 				*player_s; 




BOOL SRV_CheckEndRule(float time){
	int frags;
	dword win_pl;
	BOOL completed=FALSE;

	switch(gEndRule){
		case SC_MP_ENDRULE_TIME:
			if (gPlayersConnected>0) gTime += time;
				SC_MP_EndRule_SetTimeLeft(gTime,gPlayersConnected>0);
				if (gTime>gEndValue) completed=TRUE;
			break;
		case SC_MP_ENDRULE_FRAGS:
			win_pl = SC_MP_GetMaxFragsPl(&frags);
			if (win_pl){
				if (frags>=gEndValue)completed=TRUE;
			}
			break;
		case SC_MP_ENDRULE_POINTS:
			win_pl = SC_MP_GetMaxPointsPl(&frags);
			if (win_pl){
				if (frags>=gEndValue)completed=TRUE;
				
			}
			break;
		default:
			//SC_message("EndRule unsopported: %d",gEndRule);
			break;
	}// switch(gEndRule)
	if(completed){	
		if(gPhase!=GPHASE_MISSION_COMPLETED){
			if(win_pl){
				SC_sgi(GVAR_WINNER,SC_MP_GetHandleofPl(win_pl));
			}
			gPhase=GPHASE_MISSION_COMPLETED;
			SC_sgi(GVAR_GPHASE,gPhase);
			SC_MP_LoadNextMap();
			return TRUE;
		}
	}
	return FALSE;
}// void SRV_CheckEndRule(float time)





int ScriptMain(s_SC_NET_info *info){
	char txt[32];
	dword i;
	int j,k;
	int max_point;
	s_SC_MP_Recover *precov;
	s_SC_MP_hud hudinfo;
	s_SC_MP_EnumPlayers enum_pl[64];
	s_SC_MP_SRV_settings SRVset;
	s_SC_HUD_MP_icon icon[3];
	dword icons;
	ushort wtxt[128],wtxt2[64],*witxt,*my_witxt;
	float	sc_width,sc_height,val;

	switch(info->message){
		case SC_NET_MES_SERVER_TICK:	
			//________________________________________________________________	
			//gPlayersConnected = 64;
			SC_MP_EnumPlayers(enum_pl,&gPlayersConnected,SC_MP_ENUMPLAYER_SIDE_ALL);

			gPhase_timer -= info->elapsed_time;
			//________________________________________________________________
			switch(gPhase){
			case GPHASE_BEGIN: //GPHASE_BEGIN is phase for object restart
				if (gPhase_timer <= 0.0f){
					SC_MP_SetInstantRecovery(TRUE);//
					gPhase_timer=0;
					gPhase=GPHASE_WAIT_PLAYERS;
					SC_sgi(GVAR_GPHASE,gPhase);
				}
				break;
			case GPHASE_WAIT_PLAYERS:
				if (gPlayersConnected >1){
					gPhase_timer = RESTART_TIMER;
					gPhase = GPHASE_START_GAME;
					SC_sgi(GVAR_GPHASE,gPhase);
				}
				break;
			case GPHASE_START_GAME:
				if (gPhase_timer <= 0.0f){
					SC_MP_SetInstantRecovery(FALSE);					
					gTime = 0;
					gPhase_timer=0; 
					gPhase=GPHASE_GAME;
					SC_sgi(GVAR_GPHASE,gPhase);
					SC_MP_SRV_ClearPlsStats();
					SC_MP_SRV_InitGameAfterInactive();
					SC_MP_RecoverAllNoAiPlayers();	
					update_timer=11;//11= force update
				}
				break;
			case GPHASE_GAME:

				if (gPhase_timer <= 0.0f){
					last_srv_weap_3 = last_srv_weap_2;
					last_srv_weap_2 = last_srv_weap;
					last_srv_weap = cur_weap;
					do{
						cur_weap = WEAP_LIST[(rand() % LIST_COUNT)];
					}while( (cur_weap == last_srv_weap)||(cur_weap == last_srv_weap_2) || (cur_weap == last_srv_weap_3));//||
					SC_sgi(GVAR_CUR_WEAP,cur_weap);
					gPhase_timer=ROUND_TIME;
				}
				
				update_timer+=info->elapsed_time;//update time for clients
				if(update_timer > 10){// will update after every 10 sec.
					SC_sgf(GVAR_GPHASE_TIME,gPhase_timer);//send new time update
					update_timer=0.0f;
				}		
				
				
				
				break;
			case GPHASE_MISSION_COMPLETED:	
				break;
			}


			//________________________________________________________________
			//gPlayersConnected = 64;
			//SC_MP_EnumPlayers(enum_pl,&gPlayersConnected,SC_MP_ENUMPLAYER_SIDE_ALL);
			if (SRV_CheckEndRule(info->elapsed_time)) break;
			for (i=0;i<gRecs;i++)
				gRecTimer[i] -= info->elapsed_time;
			break;
		case SC_NET_MES_CLIENT_TICK:
			switch(SC_ggi(GVAR_GPHASE)){
			case GPHASE_BEGIN:				//___________________________CLN______BEGIN
				break;
			case GPHASE_WAIT_PLAYERS:		//___________________________CLN______WAIT_PLAYERS
				witxt = SC_Wtxt(1076);//1076
				SC_GetScreenRes(&sc_width,&sc_height);
				val= sc_width - SC_Fnt_GetWidthW(witxt,1); 			
				SC_Fnt_WriteW(val * 0.5f,15,witxt,1,0xffffffff);
				break;
			case GPHASE_START_GAME: 		//___________________________CLN______START_GAME
				if (fade_off){
					client_fade_timer -= info->elapsed_time;
					if (client_fade_timer < (FADE_TIME + 0.1f)){	
						SC_FadeTo(TRUE, FADE_TIME);
						fade_off=FALSE;
						client_fade_timer=RESTART_TIMER;
						fade_off_timer=0;

						//reset objexts and states
						
						Prev_time=-1;
					}
				}
				swprintf(wtxt,SC_AnsiToUni("%s %S", wtxt2),SC_Wtxt(6030)," - SSA (Sharp Shooter Assault)");
				val= (sc_width*0.5) - (SC_Fnt_GetWidthW(wtxt,1)*0.5);			
				SC_Fnt_WriteW(val,15,wtxt,1,0xffffffff);
				break;
			case GPHASE_GAME:
				//FADE OFF
				if (!fade_off){
					fade_off_timer += info->elapsed_time;
					if (fade_off_timer >  0.2f){// looks better so because spawn is with short delay
						SC_FadeTo(FALSE, FADE_TIME);
						fade_off=TRUE;



					}
				}	

			
				//if (SC_ggi(GVAR_SERVER) != 1){//not server
				CLN_cur_weap = SC_ggi(GVAR_CUR_WEAP);
				CLN_gPhase_timer -= info->elapsed_time;
				// update time
				new_time = SC_ggf(GVAR_GPHASE_TIME);
				if (Prev_time != new_time){//update if new time for update
					CLN_gPhase_timer = new_time;
					Prev_time = new_time;
				}
				//}

				if (last_weap != CLN_cur_weap){// new weapon
					if(SC_P_IsReady(SC_PC_Get())){
						SC_P_ChangeWeapon(SC_PC_Get(), 0, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 1, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 2, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 3, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 4, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 5, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 6, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 7, 0);//cur_weap
						SC_P_ChangeWeapon(SC_PC_Get(), 8, 0);//cur_weap
						weap_removed=TRUE;
					}
					last_weap=CLN_cur_weap;
					delay_timer =0;
				}
				delay_timer+=info->elapsed_time;
				if (delay_timer > 0.6f){
					if (CLN_cur_weap != 0){
						if(SC_P_IsReady(SC_PC_Get())){
							if (SC_P_GetWeapons(SC_PC_Get(), &get_weap_inf)){
								if(get_weap_inf.weap_main1 != CLN_cur_weap ){
									if ((weap_removed==TRUE) && (get_weap_inf.weap_main1 == 0 ) ||  (weap_removed==FALSE)&& (get_weap_inf.weap_main1 != 0 )  || (get_weap_inf.weap_pistol != 0 )){
										SC_P_ChangeWeapon(SC_PC_Get(), 0, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 1, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 3, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 4, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 5, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 6, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 7, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 8, 0);//cur_weap
										SC_P_ChangeWeapon(SC_PC_Get(), 2, CLN_cur_weap);//cur_weap
										SC_P_SetSelWeapon(SC_PC_Get(), 2);//
										weap_removed=FALSE; // if droped after that then he dont get new weapon
									}
								}
							}
						}
					}
				}

				my_min = (int)((CLN_gPhase_timer+1)/60);	
				my_sec = (int)(CLN_gPhase_timer+1) - my_min;
				if (my_sec < 0){
					swprintf(wtxt,SC_AnsiToUni("", wtxt2));
				}else if (my_sec < 10){
					swprintf(wtxt,SC_AnsiToUni("%s:  %d:0%d", wtxt2),SC_Wtxt(8260), my_min, my_sec);
				}else{
					swprintf(wtxt,SC_AnsiToUni("%s:  %d:%d", wtxt2),SC_Wtxt(8260), my_min, my_sec);
				}
				SC_GetScreenRes(&sc_width,&sc_height);
				SC_Fnt_WriteW(50,(sc_height - 100),wtxt,1.1,0x85ffffff);
				break;
			case GPHASE_MISSION_COMPLETED:	
				if (fade_off){
					complete_f_timer -= info->elapsed_time;
					if (complete_f_timer < -6.0f){	
						SC_FadeTo(TRUE, FADE_TIME);
						fade_off=FALSE;
					}
				}			
				swprintf(wtxt,SC_AnsiToUni("%s", wtxt2),SC_Wtxt(2026));//#2026: 	#tee   Mission completed
				SC_GetScreenRes(&sc_width,&sc_height);
				val= (sc_width*0.5) - (SC_Fnt_GetWidthW(wtxt,1)*0.5);			
				SC_Fnt_WriteW(val,15,wtxt,1,0xffffffff);

				swprintf(wtxt,SC_AnsiToUni("Best player:  %S ", wtxt2), SC_P_GetName(SC_MP_GetPlofHandle(SC_ggi(GVAR_WINNER))));
				//SC_Fnt_WriteW((sc_width*0.5),35,wtxt,1.1,0x85ffffff);
				val= (sc_width*0.5) - (SC_Fnt_GetWidthW(wtxt,1)*0.5);	
				SC_Fnt_WriteW(val,35,wtxt,1,0xffffffff);
				break;
			}
			break;// SC_NET_MES_CLIENT_TICK
		case SC_NET_MES_LEVELPREINIT:
			client_fade_timer=RESTART_TIMER;

			SC_sgi(GVAR_MP_MISSIONTYPE,GVAR_MP_MISSIONTYPE_SSA);
			gEndRule = info->param1;
			gEndValue = info->param2;
			gTime = 0.0f;
			SC_MP_EnableBotsFromScene(FALSE);
			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_SRV_SetForceSide(0xffffffff);
			SC_MP_SetChooseValidSides(3);
			SC_HUD_DisableRadar(TRUE);			
			SC_MP_SRV_SetClassLimitsForDM();	
			CLEAR(hudinfo);
			hudinfo.title = 1050;
			hudinfo.sort_by[0] = SC_HUD_MP_SORTBY_FRAGS;			
			hudinfo.sort_by[1] = SC_HUD_MP_SORTBY_KILLS;
			hudinfo.sort_by[2] = SC_HUD_MP_SORTBY_DEATHS | SC_HUD_MP_SORT_DOWNUP;
			hudinfo.sort_by[3] = SC_HUD_MP_SORTBY_PINGS | SC_HUD_MP_SORT_DOWNUP;
			hudinfo.pl_mask = SC_HUD_MP_PL_MASK_FRAGS | SC_HUD_MP_PL_MASK_KILLS | SC_HUD_MP_PL_MASK_DEATHS;
			hudinfo.use_sides = 0;
			SC_MP_HUD_SetTabInfo(&hudinfo);
			SC_MP_AllowStPwD(FALSE);
			SC_MP_AllowFriendlyFireOFF(FALSE);
			SC_MP_SetItemsNoDisappear(FALSE);
			if (info->param2){
				if (info->param1){
					// it's server	
					//_______________________________________________________________________________________
					SC_sgi(GVAR_SERVER,1); 
					SC_MP_Gvar_SetSynchro(GVAR_GPHASE);
					SC_MP_Gvar_SetSynchro(GVAR_GPHASE_TIME);
					SC_MP_Gvar_SetSynchro(GVAR_CUR_WEAP);
					SC_MP_Gvar_SetSynchro(GVAR_WINNER);
					SC_sgi(GVAR_GPHASE,gPhase);
					//_______________________________________________________________________________________
					

					SC_MP_GetSRVsettings(&SRVset);
					SC_MP_SRV_InitWeaponsRecovery((float)SRVset.dm_weap_resp_time);
					gRecs = 0;
					for (i=0;i<REC_MAX;i++){		
						sprintf(txt,REC_WPNAME,i);			
						if (SC_NET_FillRecover(&gRec[gRecs],txt)) gRecs++;
					}					
#if _GE_VERSION_ >= 170
					i = REC_MAX - gRecs;
					SC_MP_GetRecovers(SC_MP_RESPAWN_SSA,&gRec[gRecs],&i);
					gRecs += i;
#endif
					if (gRecs==0){ 
						SC_message("no 'SSA' recover place added! Will use 'DM' recover place if exist.");
						i = REC_MAX - gRecs;
						SC_MP_GetRecovers(SC_MP_RESPAWN_DM,&gRec[gRecs],&i);
						gRecs += i;
					}

					CLEAR(gRecTimer);
				}// if (info->param1)
			}//if (info->param2)
			break;// SC_NET_MES_LEVELINIT
		case SC_NET_MES_RENDERHUD:
			if(SC_KeyPressed(0x0F)){//TAB pressed
				if(SHOW_PLAYER_COLOR){
					SC_MP_HUD_SelectPl(SC_PC_Get(),0x1100ffff);
				}
				if (SHOW_PLAYERS_COUNT){
					SC_MP_EnumPlayers(enum_pl,&j,SC_MP_ENUMPLAYER_SIDE_ALL);
					if (j==1) player_s = SC_Wtxt(350); else player_s = SC_Wtxt(7001);
					swprintf(wtxt,SC_AnsiToUni("%d  %s", wtxt2),j,player_s);
					SC_Fnt_WriteW(100,25,wtxt,1,0xffffffff);
				}
			}else if(SC_ggi(GVAR_GPHASE)==GPHASE_MISSION_COMPLETED){
				if (SC_MP_GetMaxFragsPl(&max_point)){
					if(max_point > 0){
						SC_MP_HUD_SelectPl(SC_MP_GetMaxFragsPl(&max_point),0x88440000);
					}
				}
			}
			break;
		case SC_NET_MES_SERVER_RECOVER_TIME:

			if (info->param2){
					info->fval1 = 0.1f;
			}
			else{// killed

				info->fval1 = RECOVER_TIME;
			}
			break;
		case SC_NET_MES_SERVER_RECOVER_PLACE:
			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;
		case SC_NET_MES_RESTARTMAP:
			//___________________________________________________________
			gPhase_timer = BEGIN_TIMER;
			gPhase = GPHASE_BEGIN;	
			SC_sgi(GVAR_GPHASE,gPhase);	
			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)

