]> icculus.org git repositories - taylor/freespace2.git/blob - src/network/multi_observer.cpp
added copyright header
[taylor/freespace2.git] / src / network / multi_observer.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
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
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Network/multi_observer.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * $Log$
16  * Revision 1.4  2002/06/09 04:41:23  relnev
17  * added copyright header
18  *
19  * Revision 1.3  2002/05/27 00:40:47  theoddone33
20  * Fix net_addr vs net_addr_t
21  *
22  * Revision 1.2  2002/05/07 03:16:47  theoddone33
23  * The Great Newline Fix
24  *
25  * Revision 1.1.1.1  2002/05/03 03:28:10  root
26  * Initial import.
27  *  
28  * 
29  * 6     9/14/99 2:21p Dave
30  * Fixed observer mode joining and ingame stuff.
31  * 
32  * 5     8/19/99 10:59a Dave
33  * Packet loss detection.
34  * 
35  * 4     11/17/98 11:12a Dave
36  * Removed player identification by address. Now assign explicit id #'s.
37  * 
38  * 3     11/05/98 5:55p Dave
39  * Big pass at reducing #includes
40  * 
41  * 2     10/07/98 10:53a Dave
42  * Initial checkin.
43  * 
44  * 1     10/07/98 10:50a Dave
45  * 
46  * 13    6/13/98 6:01p Hoffoss
47  * Externalized all new (or forgot to be added) strings to all the code.
48  * 
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
52  * 
53  * 11    5/22/98 9:49p Allender
54  * make observers Player_ship hidden from sensors so that he cannot target
55  * his "ship".
56  * 
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
60  * 
61  * 9     4/18/98 5:00p Dave
62  * Put in observer zoom key. Made mission sync screen more informative.
63  * 
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
67  * in for TCP.
68  * 
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.
72  * 
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.
77  * 
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.
82  * 
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.
86  * 
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
90  * lag/loss system.
91  * 
92  * 2     3/13/98 2:51p Dave
93  * Put in support for observers to join ingame.
94  * 
95  * 1     3/12/98 5:44p Dave
96  *  
97  * $NoKeywords: $
98  */
99
100 #include "freespace.h"
101 #include "multi.h"
102 #include "multiutil.h"
103 #include "object.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"
110 #include "timer.h"
111
112 // ---------------------------------------------------------------------------------------
113 // MULTI OBSERVER DEFINES/VARS
114 //
115
116
117 // ---------------------------------------------------------------------------------------
118 // MULTI OBSERVER FUNCTIONS
119 //
120
121 // create a _permanent_ observer player 
122 int multi_obs_create_player(int player_num,char *name,net_addr_t *addr,player *pl)
123 {       
124         // blast the player struct
125         memset(&Net_players[player_num],0,sizeof(net_player));
126         
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;
132         
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;
145
146         // reset the ping for this player
147         multi_ping_reset(&Net_players[player_num].s_info.ping);
148         
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;    
152
153         // nil his file xfer handle
154         Net_players[player_num].s_info.xfer_handle = -1;
155
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;          
159
160         // his kick timestamp
161         Net_players[player_num].s_info.kick_timestamp = -1;
162
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;
166
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;
170
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;     
175
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;
180         
181         return 1;
182 }
183
184 // create an explicit observer object and assign it to the passed player
185 void multi_obs_create_observer(net_player *pl)
186 {
187         int objnum;
188         
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;
194
195         // put it a 1,1,1
196         Objects[objnum].pos.x = 1.0f;
197         Objects[objnum].pos.y = 1.0f;
198         Objects[objnum].pos.z = 1.0f;
199
200         // assign this object to the player
201         pl->player->objnum = objnum;                            
202 }
203
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()
207 {
208         int pobj_num;
209         
210         Assert(!(Net_player->flags & NETINFO_FLAG_OBS_PLAYER));                                 
211
212         // make me an observer object
213         multi_obs_create_observer(Net_player);  
214                                         
215         // set my object to be the observer object      
216         Player_obj = &Objects[Net_player->player->objnum];
217         
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];
223
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];               
229
230         // configure the hud to be in "observer" mode
231         hud_config_as_observer(Player_ship,Player_ai);  
232                 
233         // set some flags for myself
234         Net_player->flags |= NETINFO_FLAG_OBSERVER;     
235         
236         // reset the control info structure
237         memset(&Player->ci,0,sizeof(control_info));     
238 }
239
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()
244 {
245         int idx;        
246
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);
250         }
251
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();
256         }
257         // otherwise create stuff for all (permanent) observers in the game
258         else {
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]);
263                         }
264                 }
265         }
266 }
267
268 // if i'm an observer, zoom to near my targted object (if any)
269 void multi_obs_zoom_to_target()
270 {
271         vector direct;          
272         float dist;     
273         
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)){                
276                 return;
277         }
278
279         // if I have no targeted object, do nothing
280         if(Player_ai->target_objnum == -1){             
281                 return;
282         }
283
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);      
288
289         // orient the guy correctly
290         vm_vec_ang_2_matrix(&Player_obj->orient,&direct,0.0f);
291
292         // keep about 3 object radii away when moving
293         dist -= (Objects[Player_ai->target_objnum].radius * 3.0f);
294
295         // get the movement vector
296         vm_vec_scale(&direct,dist);
297
298         // move
299         vm_vec_add2(&Player_obj->pos,&direct);
300 }
301         
302
303         
304