2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Network/multi_observer.cpp $
16 * Revision 1.4 2002/06/09 04:41:23 relnev
17 * added copyright header
19 * Revision 1.3 2002/05/27 00:40:47 theoddone33
20 * Fix net_addr vs net_addr_t
22 * Revision 1.2 2002/05/07 03:16:47 theoddone33
23 * The Great Newline Fix
25 * Revision 1.1.1.1 2002/05/03 03:28:10 root
29 * 6 9/14/99 2:21p Dave
30 * Fixed observer mode joining and ingame stuff.
32 * 5 8/19/99 10:59a Dave
33 * Packet loss detection.
35 * 4 11/17/98 11:12a Dave
36 * Removed player identification by address. Now assign explicit id #'s.
38 * 3 11/05/98 5:55p Dave
39 * Big pass at reducing #includes
41 * 2 10/07/98 10:53a Dave
44 * 1 10/07/98 10:50a Dave
46 * 13 6/13/98 6:01p Hoffoss
47 * Externalized all new (or forgot to be added) strings to all the code.
49 * 12 6/04/98 11:04a Allender
50 * object update level stuff. Don't reset to high when becoming an
51 * observer of any type. default to low when guy is a dialup customer
53 * 11 5/22/98 9:49p Allender
54 * make observers Player_ship hidden from sensors so that he cannot target
57 * 10 5/19/98 11:36p Allender
58 * fixed very nasty mask problem with ingame joiner marking player objects
59 * incorrectly. Named ingame joiner ship and observer ship unique names
61 * 9 4/18/98 5:00p Dave
62 * Put in observer zoom key. Made mission sync screen more informative.
64 * 8 4/03/98 3:13p Dave
65 * More work on udp reliable transport. Fixed observer hud offset problem.
66 * Made observer join and ingame join work again. Put subnet broadcasting
69 * 7 3/30/98 6:27p Dave
70 * Put in a more official set of multiplayer options, including a system
71 * for distributing netplayer and netgame settings.
73 * 6 3/24/98 5:00p Dave
74 * Fixed several ui bugs. Put in pre and post voice stream playback sound
75 * fx. Put in error specific popups for clients getting dropped from games
76 * through actions other than their own.
78 * 5 3/23/98 5:42p Dave
79 * Put in automatic xfer of pilot pic files. Changed multi_xfer system so
80 * that it can support multiplayer sends/received between client and
81 * server simultaneously.
83 * 4 3/15/98 4:17p Dave
84 * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
85 * of network orientation matrices.
87 * 3 3/14/98 2:48p Dave
88 * Cleaned up observer joining code. Put in support for file xfers to
89 * ingame joiners (observers or not). Revamped and reinstalled pseudo
92 * 2 3/13/98 2:51p Dave
93 * Put in support for observers to join ingame.
95 * 1 3/12/98 5:44p Dave
100 #include "freespace.h"
102 #include "multiutil.h"
104 #include "observer.h"
105 #include "hudconfig.h"
106 #include "hudobserver.h"
107 #include "managepilot.h"
108 #include "multi_observer.h"
109 #include "missionparse.h"
112 // ---------------------------------------------------------------------------------------
113 // MULTI OBSERVER DEFINES/VARS
117 // ---------------------------------------------------------------------------------------
118 // MULTI OBSERVER FUNCTIONS
121 // create a _permanent_ observer player
122 int multi_obs_create_player(int player_num,char *name,net_addr_t *addr,player *pl)
124 // blast the player struct
125 memset(&Net_players[player_num],0,sizeof(net_player));
127 // Net_players[player_num].flags |= (NETINFO_FLAG_CONNECTED | NETINFO_FLAG_OBSERVER);
128 // DOH!!! The lack of this caused many bugs.
129 Net_players[player_num].flags = (NETINFO_FLAG_DO_NETWORKING | NETINFO_FLAG_OBSERVER);
130 // memcpy(&Net_players[player_num].p_info.addr, addr, sizeof(net_addr));
131 Net_players[player_num].player = pl;
133 // 6/3/98 -- don't set observer to update high...let it be whatever player set it at.
134 //Net_players[player_num].p_info.options.obj_update_level = OBJ_UPDATE_HIGH;
135 // set up the net_player structure
136 memset(pl, 0, sizeof(player));
137 stuff_netplayer_info( &Net_players[player_num], addr, 0, pl );
138 Net_players[player_num].last_heard_time = timer_get_fixed_seconds();
139 Net_players[player_num].reliable_socket = INVALID_SOCKET;
140 Net_players[player_num].s_info.kick_timestamp = -1;
141 Net_players[player_num].s_info.voice_token_timestamp = -1;
142 Net_players[player_num].s_info.tracker_security_last = -1;
143 Net_players[player_num].s_info.target_objnum = -1;
144 Net_players[player_num].s_info.accum_buttons = 0;
146 // reset the ping for this player
147 multi_ping_reset(&Net_players[player_num].s_info.ping);
149 // timestamp his last_full_update_time
150 Net_players[player_num].s_info.last_full_update_time = timestamp(0);
151 Net_players[player_num].player->objnum = -1;
153 // nil his file xfer handle
154 Net_players[player_num].s_info.xfer_handle = -1;
156 // zero out his object update and control info sequencing data
157 Net_players[player_num].client_cinfo_seq = 0;
158 Net_players[player_num].client_server_seq = 0;
160 // his kick timestamp
161 Net_players[player_num].s_info.kick_timestamp = -1;
163 // nil his data rate timestamp stuff
164 Net_players[player_num].s_info.rate_stamp = -1;
165 Net_players[player_num].s_info.rate_bytes = 0;
167 // nil packet buffer stuff
168 Net_players[player_num].s_info.unreliable_buffer_size = 0;
169 Net_players[player_num].s_info.reliable_buffer_size = 0;
171 // callsign and short callsign
172 strcpy(pl->callsign,name);
173 pilot_set_short_callsign(pl,SHORT_CALLSIGN_PIXEL_W);
174 pl->flags |= PLAYER_FLAGS_STRUCTURE_IN_USE;
176 Net_players[player_num].sv_bytes_sent = 0;
177 Net_players[player_num].sv_last_pl = -1;
178 Net_players[player_num].cl_bytes_recvd = 0;
179 Net_players[player_num].cl_last_pl = -1;
184 // create an explicit observer object and assign it to the passed player
185 void multi_obs_create_observer(net_player *pl)
189 // create the basic observer object
190 objnum = observer_create( &vmd_identity_matrix, &vmd_zero_vector);
191 Assert(objnum != -1);
192 Objects[objnum].flags |= OF_PLAYER_SHIP;
193 Objects[objnum].net_signature = 0;
196 Objects[objnum].pos.x = 1.0f;
197 Objects[objnum].pos.y = 1.0f;
198 Objects[objnum].pos.z = 1.0f;
200 // assign this object to the player
201 pl->player->objnum = objnum;
204 // create observer object locally, and additionally, setup some other information
205 // ( client-side equivalent of multi_obs_create_observer() )
206 void multi_obs_create_observer_client()
210 Assert(!(Net_player->flags & NETINFO_FLAG_OBS_PLAYER));
212 // make me an observer object
213 multi_obs_create_observer(Net_player);
215 // set my object to be the observer object
216 Player_obj = &Objects[Net_player->player->objnum];
218 // create the default player ship object and use that as my default virtual "ship", and make it "invisible"
219 pobj_num = parse_create_object(&Player_start_pobject);
220 Assert(pobj_num != -1);
221 obj_set_flags(&Objects[pobj_num],OF_PLAYER_SHIP);
222 Player_ship = &Ships[Objects[pobj_num].instance];
224 // make ship hidden from sensors so that this observer cannot target it. Observers really have two ships
225 // one observer, and one "Player_ship". Observer needs to ignore the Player_ship.
226 Player_ship->flags |= SF_HIDDEN_FROM_SENSORS;
227 strcpy(Player_ship->ship_name, XSTR("Observer Ship",688));
228 Player_ai = &Ai_info[Ships[Objects[pobj_num].instance].ai_index];
230 // configure the hud to be in "observer" mode
231 hud_config_as_observer(Player_ship,Player_ai);
233 // set some flags for myself
234 Net_player->flags |= NETINFO_FLAG_OBSERVER;
236 // reset the control info structure
237 memset(&Player->ci,0,sizeof(control_info));
240 // create objects for all known observers in the game at level start
241 // call this before entering a mission
242 // this implies for the local player in the case of a client or for _all_ players in the case of a server
243 void multi_obs_level_init()
247 // unset the OBS_PLAYER flag here for all net players
248 for(idx=0;idx<MAX_PLAYERS;idx++){
249 Net_players[idx].flags &= ~(NETINFO_FLAG_OBS_PLAYER);
252 // if i'm a client and I'm an observer, create an object for myself
253 if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
254 // create my own observer object and setup other misc. data
255 multi_obs_create_observer_client();
257 // otherwise create stuff for all (permanent) observers in the game
259 for(idx=0;idx<MAX_PLAYERS;idx++){
260 if(MULTI_CONNECTED(Net_players[idx]) && MULTI_OBSERVER(Net_players[idx])){
261 // make an observer object for the guy
262 multi_obs_create_observer(&Net_players[idx]);
268 // if i'm an observer, zoom to near my targted object (if any)
269 void multi_obs_zoom_to_target()
274 // if i'm not an observer, do nothing
275 if(!(Game_mode & GM_MULTIPLAYER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type != OBJ_OBSERVER)){
279 // if I have no targeted object, do nothing
280 if(Player_ai->target_objnum == -1){
284 // get the normalized direction vector between the observer and the targeted object
285 vm_vec_sub(&direct,&Objects[Player_ai->target_objnum].pos,&Player_obj->pos);
286 dist = vm_vec_mag(&direct);
287 vm_vec_normalize(&direct);
289 // orient the guy correctly
290 vm_vec_ang_2_matrix(&Player_obj->orient,&direct,0.0f);
292 // keep about 3 object radii away when moving
293 dist -= (Objects[Player_ai->target_objnum].radius * 3.0f);
295 // get the movement vector
296 vm_vec_scale(&direct,dist);
299 vm_vec_add2(&Player_obj->pos,&direct);