//	VIETCONG 1
//	Mace_Trap_Random script v3.3 (Writen for custom objects - _mace_trap.bes and _mace_trap_tree.bes)
//	made by Ando

/*
	______________TRAP DESCRIPTION IN REALITY:
Mace Trap: Mace traps take various forms, and may consist of a spiked concrete ball, drum, box or log 
suspended in a tree on the end of a rope, or cable. When the trip wire is pulled, the mace swings down 
along the path striking anyone in its way.



    ______________TRAP BEHAVIOUR IN GAME:
If player collides with wire then trap is released and mace swings down. If player is on its way then he will be killed. 
Wire goes down also when hit by bullet, knife or explosion. Player can also reactivate that trap in game, when mace dont move anymore. 
After start/restart trap will appear randomly to some predefined position.


	______________TUTORIAL FOR EDITOR
-Place one _mace_trap.bes and _mace_trap_tree.bes object to map.
- move "_mace_trap" to exactly same position as is tree object
	 (copy "tree" transform x,y,z to "trap" transform x,y,x)
	 (now you will see how trap is located with tree)
- link trap to tree object (now trap will be with tree when you move/rotate tree)
- select tree and place it where you need
 for next tree:
- select trap and tree 
- copy 
- link trap to tree object
- select tree and place it where you need
( continue as long as you need but there cant be more than 20 "trees")
- when "trees" are in right position then you can delete trap objects.
- turn on sub object selector
- select and move "sign_place" dummy where you want a sign to appear.
- do it for every "tree"
- Place one "trap" object somewhere on map (where players cant see it)
- add script to trap object in level.c script

	


	_____________NOTES:
1.3 - new sync system
1.4 - Changed movement
1.5 - new killing system - with death count
1.6 - automatic Global variable system
2.0 - tested with 2x editor
3.0 - tested with team
3.1 - all 3.1 improvements was recomendations by Intruder and his testing team
3.1 - "move" sound is decreasing now faster 
3.1 - reset text distance appears now from 1.0m(was 0.5)
3.1 - dont kill player when mace rotation angle is smaller than 55 degrees (before was killing as long as it was moveing)
3.1 - added option for random places
3.1 - added trap sign
3.2 - added waypoint blocker (important for random places)
3.3 - changed restart 

	_____________CURRENT BUGS:
none


	______________IDEAS:
maybe its reasonable to add option only for engineer to set up that trap again (now its for all)




*/






#include <inc\sc_global.h>
#include <inc\sc_def.h>

//____________________________OBJECT PARAMETERS____________________________

//OBJECT STATES: 0 - trap up , 1 -  move , 2 -  down , 

#define DISARM_STRING			2806	//#2806: 	#tee to cut the wire.
#define RESET_STRING			7362	//#7362: 	#tee Enable
#define MOVE_SOUND				1932	//1869, 1933 
#define CUT_SOUND				1950	//
#define PL_HIT_SOUND			2344//264		// player hit sound

#define ROT_ANGLE				170.0f  //
#define SWING_TIME				1.5f	//trap movement time

#define tree_obj	"_mace_trap_tree#%d"		//tree object for trap places. objects must start with #0
								//will found count of objects automatically

#define	mov_sub_obj				"pendel"	//moving pendel object
#define	stat_sub_obj			"lanovis"	//static pendel object
#define	wire_sub_obj			"drat_1"	//
#define	dum_sub_obj				"Dummy_A"	//


#define	dum_trat_sub_obj		"Dummy_drat"	//dummy for waypoint blocker

#define	sign_sub_obj			"sign"		//sign sub object

#define	sign_place_sub_obj		"sign_place"	//sign place sub object on random tree object

//_________________________________________________________________________

#define GVAR_SERVER				600 	// don't edit	//0 - not server . 1 - server
#define GVAR_COUNT				601 	// don't edit   //Channel for G-var count
#define GVAR_GPHASE				500		// don't edit


void		*mov_sub_obj_id;
void		*stat_sub_obj_id;
void		*wire_sub_obj_id;
void		*dum_sub_obj_id;
void		*sign_sub_obj_id;
void		*cur_tree_id;

s_SC_NOD_transform	trans;
s_SC_NOD_transform	trans_swing;
s_SC_NOD_transform	orig_trans_stat;
s_SC_NOD_transform	orig_trans_move;
s_SC_NOD_transform	orig_trans_wire;
s_SC_NOD_transform	cur_trans_trap;
s_SC_NOD_transform	orig_trans_master;
s_SC_NOD_transform	orig_trans_sign;

c_Vector3	vec2;
c_Vector3	head_pos;
c_Vector3	dum_pos;
s_sphere	sph2;

float		val = 0.0f;
float		timer = 0.0f;
float		cur_rot = 0.0f;
float		sound_h = 0.0f;


int			Temp =	0;	//global object status
int			Temp2 =	-1;	//local object status.  -1 = unknown ststus  (for start/restart)
int			Temp3 = 0;	//local movement status
int			r_dir = 1;	// rotation direction
int			my_gvar_count;
int			my_gvar;
int			my_gvar_tree;
int			tree_obj_count=0;
int			current_tree;

s_SC_P_getinfo	pl_info;

dword 		list[32];
dword 		player;
dword       Ai_block;
BOOL		is_block = FALSE;
BOOL		SRV_restart_done = FALSE;

int			i_items,j;


int ScriptMain(s_SC_OBJ_info *info){
	int i;
	char	txt[32];

	switch(info->event_type){
		case SC_OBJ_INFO_EVENT_INIT:
			tree_obj_count=0;
			
			for(i= 0; i < 20; i++){//count of objects
				sprintf(txt, tree_obj, i);
				if (SC_NOD_GetNoMessage_Entity(txt))tree_obj_count++;
			}

			stat_sub_obj_id = SC_NOD_GetNoMessage(info->master_nod, stat_sub_obj);
			mov_sub_obj_id = SC_NOD_GetNoMessage(info->master_nod, mov_sub_obj);
			wire_sub_obj_id  = SC_NOD_GetNoMessage(info->master_nod, wire_sub_obj);
			dum_sub_obj_id  = SC_NOD_GetNoMessage(info->master_nod, dum_sub_obj);
			sign_sub_obj_id  = SC_NOD_GetNoMessage(info->master_nod, sign_sub_obj);

			SC_NOD_GetTransform(info->master_nod,&orig_trans_master);

			SC_NOD_GetTransform(stat_sub_obj_id,&orig_trans_stat);
			SC_NOD_GetTransform(mov_sub_obj_id,&orig_trans_move);
			SC_NOD_GetTransform(wire_sub_obj_id,&orig_trans_wire);
			SC_NOD_GetTransform(sign_sub_obj_id,&orig_trans_sign);

			//creating global variable
			my_gvar_count = SC_ggi(GVAR_COUNT)+1;
			my_gvar = my_gvar_count+ 601;
			my_gvar_count++;
			my_gvar_tree = my_gvar_count+ 601;
			SC_sgi(GVAR_COUNT,my_gvar_count);//new count of custom global variables


			break;
		case SC_OBJ_INFO_EVENT_JUSTLOADED:
			break;
		case SC_OBJ_INFO_EVENT_RELEASE:
			SC_NOD_SetTransform(info->master_nod,&orig_trans_master);
			SC_NOD_SetTransform(stat_sub_obj_id,&orig_trans_stat); 
			SC_NOD_SetTransform(mov_sub_obj_id,&orig_trans_move); 
			SC_NOD_SetTransform(wire_sub_obj_id,&orig_trans_wire); 
			SC_NOD_SetTransform(sign_sub_obj_id,&orig_trans_sign);	
			Temp2 = -1;	//restores unknown state for light (important for restar tmap)
			if (is_block){// remove Ai blocker if exist
				SC_Ai_Blocker_Remove(Ai_block);
				is_block = FALSE;
			}
			break;
		case SC_OBJ_INFO_EVENT_HIT:  
			if(info->nod == wire_sub_obj_id){
				SC_sgi(my_gvar,1); //
			}
			break;
		case SC_OBJ_INFO_EVENT_DOTICK:
			if(SC_ggi(GVAR_GPHASE)==1){//reset after restartmap/gamedone
				if (SC_ggi(GVAR_SERVER) == 1){	// its server
					if (!SRV_restart_done){
						SC_sgi(my_gvar,0); // status on start/restart
						current_tree = rand() % tree_obj_count;// choosing current tree where will be trap
						SC_sgi(my_gvar_tree,current_tree); // status on start/restart
						if (is_block){// remove Ai blocker if exist
							SC_Ai_Blocker_Remove(Ai_block);
							is_block = FALSE;
						}
						SRV_restart_done=TRUE;
					}
				}
				Temp2 = -1;	//restores unknown state for trap
				return TRUE;
			}//

			if (Temp2 == -1){//first run after restart
				if (SC_ggi(GVAR_SERVER) == 1){	// its server
					SRV_restart_done=FALSE;	//for next restert , if needed
				}
			}
			Temp = SC_ggi(my_gvar);

			//______________use string__________
			if (Temp == Temp2){	//was strange collision bug without it
				switch(Temp){	//
				case 0:	// trap up
					val = SC_DOBJ_CameraLooksAt(wire_sub_obj_id,2);
					if (val<0.5f){
						SC_ACTIVE_Add(info->master_nod,2.0f*val,DISARM_STRING);
					}
					if (SC_NOD_GetCollision(info->master_nod, wire_sub_obj, TRUE)){
						SC_sgi(my_gvar,1); //___sync
						Temp = 1;
					}
					break;
				case 2:	// drap down
					val = SC_DOBJ_CameraLooksAt(info->master_nod,2);
					if (val<1.0f){
						SC_ACTIVE_Add(info->master_nod,2.0f*val,RESET_STRING);
					}
					break;
				}//switch(Temp)
			}
			//_____________CHANGE OBJECT STATUS________________
			if (Temp != Temp2){	//global status != Local status 
				switch(Temp){
				case 0:	// trap up
					//____move trap to random position
					sprintf(txt, tree_obj, SC_ggi(my_gvar_tree));// current tree name
					cur_tree_id = SC_NOD_GetNoMessage_Entity(txt);
					SC_NOD_GetTransform(cur_tree_id,&cur_trans_trap);// current tree transform
					SC_NOD_SetTransform(info->master_nod,&cur_trans_trap); //
					SC_NOD_GetTransform(SC_NOD_GetNoMessage(cur_tree_id, sign_place_sub_obj),&trans);
					SC_NOD_SetTransform(sign_sub_obj_id,&trans);
					//____AI blocker
					if (!is_block){//Ai blocker add if not exist
						SC_NOD_GetWorldPos(SC_NOD_GetNoMessage(info->master_nod, dum_trat_sub_obj), &vec2);
						sph2.pos = vec2;
						sph2.rad = 1.5f;
						Ai_block = SC_Ai_Blocker_Add(&sph2);
						is_block = TRUE;
					}
					//____
					SC_NOD_SetTransform(stat_sub_obj_id,&orig_trans_stat); //
					trans=orig_trans_move;
					trans.loc.z-=1000;
					SC_NOD_SetTransform(mov_sub_obj_id,&trans); //
					SC_NOD_SetTransform(wire_sub_obj_id,&orig_trans_wire); //
					Temp2=0;
					Temp3=0;
					break;
				case 1:	// drap move
					switch(Temp3){
					case 0:	//first move time
						SC_NOD_GetWorldPos(wire_sub_obj_id, &vec2);
						SC_SND_PlaySound3D(CUT_SOUND,&vec2);
						//SC_NOD_GetWorldPos(mov_sub_obj_id, &vec2);
						SC_SND_PlaySound3D(MOVE_SOUND,&vec2);

						trans=orig_trans_wire;
						trans.loc.z-=1000;
						SC_NOD_SetTransform(wire_sub_obj_id,&trans); //wire

						trans=orig_trans_stat;
						trans.loc.z-=1000;
						SC_NOD_SetTransform(stat_sub_obj_id,&trans); //static 
						
						trans_swing=orig_trans_move;
						timer = 0;
						r_dir=1;
						cur_rot=ROT_ANGLE;
						sound_h = 0.0f;
						
						Temp3=1;
						break;
					case 1:	//normal move
						if (cur_rot <= 0){//second movement is over
							Temp3=2;//movement over for client
							if (SC_ggi(GVAR_SERVER) == 1){
								SC_sgi(my_gvar,2); //trap down for server
							}
							return TRUE;
							//break;
						}
						timer+=info->time;
						if (timer >= SWING_TIME){// one swing time is over
							trans_swing.rot.y+=r_dir*(DEG_TO_RAD(cur_rot));
							r_dir=-r_dir;	//reverse movement direction
							timer=0;		//reset time for next swing
							cur_rot-=((0.11* cur_rot)+0.1);	//degrease angle for next swing
							sound_h+= 1.4f; //
							SC_NOD_GetWorldPos(mov_sub_obj_id, &vec2);
							vec2.z+=sound_h;
							SC_SND_PlaySound3D(MOVE_SOUND,&vec2);
						}
						trans=trans_swing;
						trans.rot.y+=r_dir*(DEG_TO_RAD(cur_rot)/2+(DEG_TO_RAD(cur_rot)/2 *sin((DEG_TO_RAD(180)*timer/SWING_TIME)- DEG_TO_RAD(90))));
						SC_NOD_SetTransform(mov_sub_obj_id,&trans); 

						//______________________killing player_________
						if (cur_rot > 55){
							SC_NOD_GetWorldPos(dum_sub_obj_id, &dum_pos);
							if (SC_ggi(GVAR_SERVER) == 1){// only server
								sph2.pos=dum_pos;
								sph2.rad=2;
								SC_GetPls(&sph2,list,&i_items);
								for (j=0;j<i_items;j++) {
									SC_P_GetHeadPos(list[j], &head_pos);
									if ((SC_2VectorsDist(&dum_pos, &head_pos)) < 0.85){
										SC_P_GetInfo(list[j], &pl_info);
										if((pl_info.cur_hp) > 1){ // player isnt dead
											vec2=head_pos;
											vec2.z+=sound_h;
											SC_SND_PlaySound3D(PL_HIT_SOUND,&vec2);
											SC_P_SetHp(list[j], 0.1f);
											SC_P_GetPos(list[j], &head_pos);
											head_pos.z+=0.1f;
											SC_P_SetPos(list[j], &head_pos);
										}
									}
								}
							}else {
								player =SC_PC_Get();
								SC_P_GetHeadPos(player, &head_pos);
								if ((SC_2VectorsDist(&dum_pos, &head_pos)) < 0.85){
									SC_P_GetInfo(player, &pl_info);
									if((pl_info.cur_hp) > 1){ // player isnt dead
										vec2=head_pos;
										vec2.z+=sound_h;
										SC_SND_PlaySound3D(PL_HIT_SOUND,&vec2);
										SC_P_SetHp(player, 0.1f);
										SC_P_GetPos(player, &head_pos);
										head_pos.z+=0.1f;
										SC_P_SetPos(player, &head_pos);
									}
								}
							}
						}
						//_____________________end of killing player________________________
						break;
					}//switch(Temp3){
					break;
				case 2:	// drap down
					//added here too because when player join after trap starts moving
					sprintf(txt, tree_obj, SC_ggi(my_gvar_tree));// current tree name
					SC_NOD_GetTransform(SC_NOD_GetNoMessage_Entity(txt),&cur_trans_trap);// current tree transform
					SC_NOD_SetTransform(info->master_nod,&cur_trans_trap); //
					//

					trans=orig_trans_stat;
					trans.loc.z-=1000;
					SC_NOD_SetTransform(stat_sub_obj_id,&trans); //
					
					trans=orig_trans_move;
					trans.rot.y+=(DEG_TO_RAD((ROT_ANGLE-80.0f)));//
					SC_NOD_SetTransform(mov_sub_obj_id,&trans); 
					trans=orig_trans_wire;
					trans.loc.z-=1000;
					SC_NOD_SetTransform(wire_sub_obj_id,&trans); //
					Temp2=2;
					break;
				}
			}
            break;
		case SC_OBJ_INFO_EVENT_USED:
			Temp = SC_ggi(my_gvar);
			switch(Temp){
			case 0:	// execute trap
					SC_sgi(my_gvar,1);
				break;
			case 2:	//reset trap
					SC_sgi(my_gvar,0);
				break;
			}
        break;
   }// switch(info->event_type)
   return FALSE;
}// int ScriptMain(s_OBJ_info *info)
