about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-07 20:23:33 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-07 20:23:33 +0000
commit1c45aa51f83401cf9a9fc20d6587f0a8f04655ac (patch)
tree0b2ddde496200adcae2a6a45cb3ed23c747bbb60 /src
parentae3229fa200776618a526d6981a1e55deb9c3c5b (diff)
downloadzcatch-1c45aa51f83401cf9a9fc20d6587f0a8f04655ac.tar.gz
zcatch-1c45aa51f83401cf9a9fc20d6587f0a8f04655ac.zip
added spectator
Diffstat (limited to 'src')
-rw-r--r--src/game/client/game_client.cpp94
-rw-r--r--src/game/game_protocol.h2
-rw-r--r--src/game/server/game_server.cpp52
-rw-r--r--src/game/server/srv_common.h4
4 files changed, 98 insertions, 54 deletions
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp
index a9ca9dd5..332a84d9 100644
--- a/src/game/client/game_client.cpp
+++ b/src/game/client/game_client.cpp
@@ -1790,6 +1790,41 @@ void render_game()
 {	
 	float width = 400*3.0f;
 	float height = 300*3.0f;
+	
+	bool spectate = false;
+		
+	// setup world view
+	obj_game *gameobj = 0;
+	{
+		// 1. fetch local player
+		// 2. set him to the center
+		int num = snap_num_items(SNAP_CURRENT);
+		for(int i = 0; i < num; i++)
+		{
+			SNAP_ITEM item;
+			const void *data = snap_get_item(SNAP_CURRENT, i, &item);
+			
+			if(item.type == OBJTYPE_PLAYER)
+			{
+				obj_player *player = (obj_player *)data;
+				if(player->local)
+				{
+					local_player = player;
+					local_player_pos = vec2(player->x, player->y);
+					
+					const void *p = snap_find_item(SNAP_PREV, item.type, item.id);
+					if(p)
+						local_player_pos = mix(vec2(((obj_player *)p)->x, ((obj_player *)p)->y), local_player_pos, client_intratick());
+				}
+			}
+			else if(item.type == OBJTYPE_GAME)
+				gameobj = (obj_game *)data;
+		}
+	}
+	
+	local_player_pos = mix(predicted_prev_player.pos, predicted_player.pos, client_intrapredtick());
+	if(local_player && local_player->team == -1)
+		spectate = true;
 		
 	animstate idlestate;
 	anim_eval(&data->animations[ANIM_BASE], 0, &idlestate);
@@ -1889,9 +1924,12 @@ void render_game()
 		int x, y;
 		inp_mouse_relative(&x, &y);
 		mouse_pos += vec2(x, y);
-		float l = length(mouse_pos);
-		if(l > 600.0f)
-			mouse_pos = normalize(mouse_pos)*600.0f;
+		if(!spectate)
+		{
+			float l = length(mouse_pos);
+			if(l > 600.0f)
+				mouse_pos = normalize(mouse_pos)*600.0f;
+		}
 	}
 	
 	// snap input
@@ -1946,37 +1984,6 @@ void render_game()
 
 		snap_input(&input, sizeof(input));
 	}
-
-	// setup world view
-	obj_game *gameobj = 0;
-	{
-		// 1. fetch local player
-		// 2. set him to the center
-		int num = snap_num_items(SNAP_CURRENT);
-		for(int i = 0; i < num; i++)
-		{
-			SNAP_ITEM item;
-			const void *data = snap_get_item(SNAP_CURRENT, i, &item);
-			
-			if(item.type == OBJTYPE_PLAYER)
-			{
-				obj_player *player = (obj_player *)data;
-				if(player->local)
-				{
-					local_player = player;
-					local_player_pos = vec2(player->x, player->y);
-
-					const void *p = snap_find_item(SNAP_PREV, item.type, item.id);
-					if(p)
-						local_player_pos = mix(vec2(((obj_player *)p)->x, ((obj_player *)p)->y), local_player_pos, client_intratick());
-				}
-			}
-			else if(item.type == OBJTYPE_GAME)
-				gameobj = (obj_game *)data;
-		}
-	}
-	
-	local_player_pos = mix(predicted_prev_player.pos, predicted_player.pos, client_intrapredtick());
 	
 	// everything updated, do events
 	if(must_process_events)
@@ -1997,7 +2004,10 @@ void render_game()
 	
 	// render the world
 	gfx_clear(0.65f,0.78f,0.9f);
-	render_world(local_player_pos.x+offx, local_player_pos.y+offy, 1.0f);
+	if(spectate)
+		render_world(mouse_pos.x, mouse_pos.y, 1.0f);
+	else
+		render_world(local_player_pos.x+offx, local_player_pos.y+offy, 1.0f);
 
 	// DEBUG TESTING
 	if(inp_key_pressed('F'))
@@ -2088,7 +2098,7 @@ void render_game()
 		//gfx_mapscreen(0,0,400*3,300*3);
 	}
 	
-	if(local_player)
+	if(local_player && !spectate)
 	{
 		gfx_texture_set(data->images[IMAGE_GAME].id);
 		gfx_quads_begin();
@@ -2336,7 +2346,7 @@ void render_game()
 	
 	// render score board
 	if(inp_key_pressed(KEY_TAB) || // user requested
-		(local_player && local_player->health == -1) || // player dead
+		(!spectate && (local_player && local_player->health == -1)) || // not spectating and is dead
 		(gameobj && gameobj->game_over) // game over
 		)
 	{
@@ -2372,6 +2382,16 @@ extern "C" void modc_render()
 		}
 		
 		render_game();
+		
+		// handle team switching
+		if(config.team != -10)
+		{
+			msg_pack_start(MSG_SETTEAM, MSGFLAG_VITAL);
+			msg_pack_int(config.team);
+			msg_pack_end();
+			client_send_msg();
+			config.team = -10;
+		}
 	}
 	else // if (client_state() != CLIENTSTATE_CONNECTING && client_state() != CLIENTSTATE_LOADING)
 	{
diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h
index 7172e8a5..56156e24 100644
--- a/src/game/game_protocol.h
+++ b/src/game/game_protocol.h
@@ -41,7 +41,7 @@ enum
 	MSG_CHAT,
 	MSG_SETNAME,
 	MSG_KILLMSG,
-	MSG_SWITCHTEAM,
+	MSG_SETTEAM,
 	MSG_JOIN,
 	MSG_QUIT,
 	MSG_EMOTICON,
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index d1620193..517b297b 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -75,7 +75,7 @@ entity::entity(int objtype)
 {
 	this->objtype = objtype;
 	pos = vec2(0,0);
-	flags = FLAG_ALIVE;
+	flags = FLAG_PHYSICS;
 	proximity_radius = 0;
 	
 	id = snap_new_id();
@@ -108,7 +108,7 @@ int game_world::find_entities(vec2 pos, float radius, entity **ents, int max)
 	int num = 0;
 	for(entity *ent = first_entity; ent; ent = ent->next_entity)
 	{
-		if(!(ent->flags&entity::FLAG_ALIVE))
+		if(!(ent->flags&entity::FLAG_PHYSICS))
 			continue;
 			
 		if(distance(ent->pos, pos) < radius+ent->proximity_radius)
@@ -130,7 +130,7 @@ int game_world::find_entities(vec2 pos, float radius, entity **ents, int max, co
 	{
 		for(entity *ent = first_entity_types[types[t]]; ent; ent = ent->next_type_entity)
 		{
-			if(!(ent->flags&entity::FLAG_ALIVE))
+			if(!(ent->flags&entity::FLAG_PHYSICS))
 				continue;
 			
 			if(distance(ent->pos, pos) < radius+ent->proximity_radius)
@@ -354,7 +354,7 @@ void player::init()
 	name[3] = 'b';
 	name[4] = 0;
 	client_id = -1;
-	team = 0;
+	team = -1; // -1 == spectator
 	extrapowerflags = 0;
 	ninjaactivationtick = 0;
 
@@ -404,6 +404,22 @@ void player::respawn()
 	spawning = true;
 }
 
+
+void player::set_team(int new_team)
+{
+	team = new_team;
+	die(client_id, -1);
+	score--;
+	
+	dbg_msg("game", "cid=%d team=%d", client_id, team);
+	
+	if(team == -1)
+		clear_flag(FLAG_PHYSICS);
+	else
+		set_flag(FLAG_PHYSICS);
+}
+
+
 bool try_spawntype(int t, vec2 *pos)
 {
 	// get spawn point
@@ -459,7 +475,7 @@ void player::try_respawn()
 	armor = 0;
 	jumped = 0;
 	dead = false;
-	set_flag(entity::FLAG_ALIVE);
+	set_flag(entity::FLAG_PHYSICS);
 	state = STATE_PLAYING;
 	
 	core.hook_state = HOOK_IDLE;
@@ -810,6 +826,13 @@ void player::tick()
 		}
 	}
 	
+	if(team == -1)
+	{
+		// spectator
+		return;
+	}
+	
+	
 	if(spawning)
 		try_respawn();
 
@@ -884,7 +907,7 @@ void player::die(int killer, int weapon)
 	// set dead state
 	dead = true;
 	die_tick = server_tick();
-	clear_flag(entity::FLAG_ALIVE);
+	clear_flag(FLAG_PHYSICS);
 	create_death(pos);
 }
 
@@ -1408,12 +1431,13 @@ void mods_client_enter(int client_id)
 
 	dbg_msg("game", "join player='%d:%s'", client_id, players[client_id].name);
 
-	if (gameobj->gametype == GAMETYPE_TDM)
-	{
-		// Check which team the player should be on
+	// Check which team the player should be on
+	if(gameobj->gametype == GAMETYPE_DM)
+		players[client_id].team = 0;
+	else
 		players[client_id].team = gameobj->getteam(client_id);
-	}
-	
+
+	//	
 	msg_pack_start(MSG_SETNAME, MSGFLAG_VITAL);
 	msg_pack_int(client_id);
 	msg_pack_string(players[client_id].name, 64);
@@ -1462,12 +1486,10 @@ void mods_message(int msg, int client_id)
 			team = -1;
 		send_chat(client_id, team, text);
 	}
-	else if (msg == MSG_SWITCHTEAM)
+	else if (msg == MSG_SETTEAM)
 	{
 		// Switch team on given client and kill/respawn him
-		players[client_id].team = !players[client_id].team;
-		players[client_id].die(client_id, -1);
-		players[client_id].score--;
+		players[client_id].set_team(msg_unpack_int());
 	}
 	else if (msg == MSG_CHANGENAME)
 	{
diff --git a/src/game/server/srv_common.h b/src/game/server/srv_common.h
index 103e4a01..8cef2cf8 100644
--- a/src/game/server/srv_common.h
+++ b/src/game/server/srv_common.h
@@ -49,7 +49,7 @@ public:
 	enum
 	{
 		FLAG_DESTROY=0x00000001,
-		FLAG_ALIVE=0x00000002,
+		FLAG_PHYSICS=0x00000002,
 	};
 	
 	entity(int objtype);
@@ -272,6 +272,8 @@ public:
 		
 	void try_respawn();
 	void respawn();
+	
+	void set_team(int team);
 
 	bool is_grounded();