2 * $Logfile: /Freespace2/code/Network/multi_observer.cpp $
8 * Revision 1.2 2002/05/07 03:16:47 theoddone33
9 * The Great Newline Fix
11 * Revision 1.1.1.1 2002/05/03 03:28:10 root
15 * 6 9/14/99 2:21p Dave
16 * Fixed observer mode joining and ingame stuff.
18 * 5 8/19/99 10:59a Dave
19 * Packet loss detection.
21 * 4 11/17/98 11:12a Dave
22 * Removed player identification by address. Now assign explicit id #'s.
24 * 3 11/05/98 5:55p Dave
25 * Big pass at reducing #includes
27 * 2 10/07/98 10:53a Dave
30 * 1 10/07/98 10:50a Dave
32 * 13 6/13/98 6:01p Hoffoss
33 * Externalized all new (or forgot to be added) strings to all the code.
35 * 12 6/04/98 11:04a Allender
36 * object update level stuff. Don't reset to high when becoming an
37 * observer of any type. default to low when guy is a dialup customer
39 * 11 5/22/98 9:49p Allender
40 * make observers Player_ship hidden from sensors so that he cannot target
43 * 10 5/19/98 11:36p Allender
44 * fixed very nasty mask problem with ingame joiner marking player objects
45 * incorrectly. Named ingame joiner ship and observer ship unique names
47 * 9 4/18/98 5:00p Dave
48 * Put in observer zoom key. Made mission sync screen more informative.
50 * 8 4/03/98 3:13p Dave
51 * More work on udp reliable transport. Fixed observer hud offset problem.
52 * Made observer join and ingame join work again. Put subnet broadcasting
55 * 7 3/30/98 6:27p Dave
56 * Put in a more official set of multiplayer options, including a system
57 * for distributing netplayer and netgame settings.
59 * 6 3/24/98 5:00p Dave
60 * Fixed several ui bugs. Put in pre and post voice stream playback sound
61 * fx. Put in error specific popups for clients getting dropped from games
62 * through actions other than their own.
64 * 5 3/23/98 5:42p Dave
65 * Put in automatic xfer of pilot pic files. Changed multi_xfer system so
66 * that it can support multiplayer sends/received between client and
67 * server simultaneously.
69 * 4 3/15/98 4:17p Dave
70 * Fixed oberver hud problems. Put in handy netplayer macros. Reduced size
71 * of network orientation matrices.
73 * 3 3/14/98 2:48p Dave
74 * Cleaned up observer joining code. Put in support for file xfers to
75 * ingame joiners (observers or not). Revamped and reinstalled pseudo
78 * 2 3/13/98 2:51p Dave
79 * Put in support for observers to join ingame.
81 * 1 3/12/98 5:44p Dave
86 #include "freespace.h"
88 #include "multiutil.h"
91 #include "hudconfig.h"
92 #include "hudobserver.h"
93 #include "managepilot.h"
94 #include "multi_observer.h"
95 #include "missionparse.h"
98 // ---------------------------------------------------------------------------------------
99 // MULTI OBSERVER DEFINES/VARS
103 // ---------------------------------------------------------------------------------------
104 // MULTI OBSERVER FUNCTIONS
107 // create a _permanent_ observer player
108 int multi_obs_create_player(int player_num,char *name,net_addr *addr,player *pl)
110 // blast the player struct
111 memset(&Net_players[player_num],0,sizeof(net_player));
113 // Net_players[player_num].flags |= (NETINFO_FLAG_CONNECTED | NETINFO_FLAG_OBSERVER);
114 // DOH!!! The lack of this caused many bugs.
115 Net_players[player_num].flags = (NETINFO_FLAG_DO_NETWORKING | NETINFO_FLAG_OBSERVER);
116 // memcpy(&Net_players[player_num].p_info.addr, addr, sizeof(net_addr));
117 Net_players[player_num].player = pl;
119 // 6/3/98 -- don't set observer to update high...let it be whatever player set it at.
120 //Net_players[player_num].p_info.options.obj_update_level = OBJ_UPDATE_HIGH;
121 // set up the net_player structure
122 memset(pl, 0, sizeof(player));
123 stuff_netplayer_info( &Net_players[player_num], addr, 0, pl );
124 Net_players[player_num].last_heard_time = timer_get_fixed_seconds();
125 Net_players[player_num].reliable_socket = INVALID_SOCKET;
126 Net_players[player_num].s_info.kick_timestamp = -1;
127 Net_players[player_num].s_info.voice_token_timestamp = -1;
128 Net_players[player_num].s_info.tracker_security_last = -1;
129 Net_players[player_num].s_info.target_objnum = -1;
130 Net_players[player_num].s_info.accum_buttons = 0;
132 // reset the ping for this player
133 multi_ping_reset(&Net_players[player_num].s_info.ping);
135 // timestamp his last_full_update_time
136 Net_players[player_num].s_info.last_full_update_time = timestamp(0);
137 Net_players[player_num].player->objnum = -1;
139 // nil his file xfer handle
140 Net_players[player_num].s_info.xfer_handle = -1;
142 // zero out his object update and control info sequencing data
143 Net_players[player_num].client_cinfo_seq = 0;
144 Net_players[player_num].client_server_seq = 0;
146 // his kick timestamp
147 Net_players[player_num].s_info.kick_timestamp = -1;
149 // nil his data rate timestamp stuff
150 Net_players[player_num].s_info.rate_stamp = -1;
151 Net_players[player_num].s_info.rate_bytes = 0;
153 // nil packet buffer stuff
154 Net_players[player_num].s_info.unreliable_buffer_size = 0;
155 Net_players[player_num].s_info.reliable_buffer_size = 0;
157 // callsign and short callsign
158 strcpy(pl->callsign,name);
159 pilot_set_short_callsign(pl,SHORT_CALLSIGN_PIXEL_W);
160 pl->flags |= PLAYER_FLAGS_STRUCTURE_IN_USE;
162 Net_players[player_num].sv_bytes_sent = 0;
163 Net_players[player_num].sv_last_pl = -1;
164 Net_players[player_num].cl_bytes_recvd = 0;
165 Net_players[player_num].cl_last_pl = -1;
170 // create an explicit observer object and assign it to the passed player
171 void multi_obs_create_observer(net_player *pl)
175 // create the basic observer object
176 objnum = observer_create( &vmd_identity_matrix, &vmd_zero_vector);
177 Assert(objnum != -1);
178 Objects[objnum].flags |= OF_PLAYER_SHIP;
179 Objects[objnum].net_signature = 0;
182 Objects[objnum].pos.x = 1.0f;
183 Objects[objnum].pos.y = 1.0f;
184 Objects[objnum].pos.z = 1.0f;
186 // assign this object to the player
187 pl->player->objnum = objnum;
190 // create observer object locally, and additionally, setup some other information
191 // ( client-side equivalent of multi_obs_create_observer() )
192 void multi_obs_create_observer_client()
196 Assert(!(Net_player->flags & NETINFO_FLAG_OBS_PLAYER));
198 // make me an observer object
199 multi_obs_create_observer(Net_player);
201 // set my object to be the observer object
202 Player_obj = &Objects[Net_player->player->objnum];
204 // create the default player ship object and use that as my default virtual "ship", and make it "invisible"
205 pobj_num = parse_create_object(&Player_start_pobject);
206 Assert(pobj_num != -1);
207 obj_set_flags(&Objects[pobj_num],OF_PLAYER_SHIP);
208 Player_ship = &Ships[Objects[pobj_num].instance];
210 // make ship hidden from sensors so that this observer cannot target it. Observers really have two ships
211 // one observer, and one "Player_ship". Observer needs to ignore the Player_ship.
212 Player_ship->flags |= SF_HIDDEN_FROM_SENSORS;
213 strcpy(Player_ship->ship_name, XSTR("Observer Ship",688));
214 Player_ai = &Ai_info[Ships[Objects[pobj_num].instance].ai_index];
216 // configure the hud to be in "observer" mode
217 hud_config_as_observer(Player_ship,Player_ai);
219 // set some flags for myself
220 Net_player->flags |= NETINFO_FLAG_OBSERVER;
222 // reset the control info structure
223 memset(&Player->ci,0,sizeof(control_info));
226 // create objects for all known observers in the game at level start
227 // call this before entering a mission
228 // this implies for the local player in the case of a client or for _all_ players in the case of a server
229 void multi_obs_level_init()
233 // unset the OBS_PLAYER flag here for all net players
234 for(idx=0;idx<MAX_PLAYERS;idx++){
235 Net_players[idx].flags &= ~(NETINFO_FLAG_OBS_PLAYER);
238 // if i'm a client and I'm an observer, create an object for myself
239 if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
240 // create my own observer object and setup other misc. data
241 multi_obs_create_observer_client();
243 // otherwise create stuff for all (permanent) observers in the game
245 for(idx=0;idx<MAX_PLAYERS;idx++){
246 if(MULTI_CONNECTED(Net_players[idx]) && MULTI_OBSERVER(Net_players[idx])){
247 // make an observer object for the guy
248 multi_obs_create_observer(&Net_players[idx]);
254 // if i'm an observer, zoom to near my targted object (if any)
255 void multi_obs_zoom_to_target()
260 // if i'm not an observer, do nothing
261 if(!(Game_mode & GM_MULTIPLAYER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type != OBJ_OBSERVER)){
265 // if I have no targeted object, do nothing
266 if(Player_ai->target_objnum == -1){
270 // get the normalized direction vector between the observer and the targeted object
271 vm_vec_sub(&direct,&Objects[Player_ai->target_objnum].pos,&Player_obj->pos);
272 dist = vm_vec_mag(&direct);
273 vm_vec_normalize(&direct);
275 // orient the guy correctly
276 vm_vec_ang_2_matrix(&Player_obj->orient,&direct,0.0f);
278 // keep about 3 object radii away when moving
279 dist -= (Objects[Player_ai->target_objnum].radius * 3.0f);
281 // get the movement vector
282 vm_vec_scale(&direct,dist);
285 vm_vec_add2(&Player_obj->pos,&direct);