File: multi_observer.cpp

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (218 lines) | stat: -rw-r--r-- 7,625 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 * Copyright (C) Volition, Inc. 1999.  All rights reserved.
 *
 * All source code herein is the property of Volition, Inc. You may not sell 
 * or otherwise commercially exploit the source or things you created based on the 
 * source.
 *
*/




#include "network/multi_observer.h"
#include "network/multi.h"
#include "network/multiutil.h"
#include "ship/ship.h"
#include "object/object.h"
#include "observer/observer.h"
#include "hud/hudconfig.h"
#include "playerman/managepilot.h"
#include "mission/missionparse.h"
#include "playerman/player.h"
#include "io/timer.h"



// ---------------------------------------------------------------------------------------
// MULTI OBSERVER DEFINES/VARS
//


// ---------------------------------------------------------------------------------------
// MULTI OBSERVER FUNCTIONS
//

// create a _permanent_ observer player 
void multi_obs_create_player(int player_num,char *name,net_addr *addr,player *pl)
{	
	Assertion(name != nullptr, "A nullptr callsign was passed to multi_obs_create_player(). This is a code error, please report.");
	Assertion(addr != nullptr, "A nullptr net_addr was passed to multi_obs_create_player(). This is a code error, please report.");
	Assertion(pl != nullptr, "A nullptr player was passed to multi_obs_create_player(). This is a code error, please report.");

	// blast the player struct
	Net_players[player_num].init();
	
	// Net_players[player_num].flags |= (NETINFO_FLAG_CONNECTED | NETINFO_FLAG_OBSERVER);	
	// DOH!!! The lack of this caused many bugs. 
	Net_players[player_num].flags = (NETINFO_FLAG_DO_NETWORKING | NETINFO_FLAG_OBSERVER);
	// memcpy(&Net_players[player_num].p_info.addr, addr, sizeof(net_addr));	
	Net_players[player_num].m_player = pl;

	// 6/3/98 -- don't set observer to update high...let it be whatever player set it at.
	//Net_players[player_num].p_info.options.obj_update_level = OBJ_UPDATE_HIGH;

	// set up the net_player structure
	pl->reset();

	stuff_netplayer_info( &Net_players[player_num], addr, 0, pl );
	Net_players[player_num].last_heard_time = timer_get_fixed_seconds();
	Net_players[player_num].reliable_socket = PSNET_INVALID_SOCKET;
	Net_players[player_num].s_info.kick_timestamp = UI_TIMESTAMP::invalid();
	Net_players[player_num].s_info.voice_token_timestamp = UI_TIMESTAMP::invalid();
	Net_players[player_num].s_info.player_collision_timestamp = TIMESTAMP::immediate();
	Net_players[player_num].s_info.tracker_security_last = -1;
	Net_players[player_num].s_info.target_objnum = -1;
	Net_players[player_num].s_info.accum_buttons = 0;

	// reset the ping for this player
	multi_ping_reset(&Net_players[player_num].s_info.ping);

	// timestamp his last_full_update_time
	Net_players[player_num].s_info.last_full_update_time = UI_TIMESTAMP::immediate();
	Net_players[player_num].m_player->objnum = -1;	

	// nil his file xfer handle
	Net_players[player_num].s_info.xfer_handle = -1;

	// zero out his object update and control info sequencing data
	Net_players[player_num].client_cinfo_seq = 0;
	Net_players[player_num].client_server_seq = 0;		

	// nil his data rate timestamp stuff
	Net_players[player_num].s_info.rate_stamp = -1;
	Net_players[player_num].s_info.rate_bytes = 0;

	// nil packet buffer stuff
	Net_players[player_num].s_info.unreliable_buffer_size = 0;
	Net_players[player_num].s_info.reliable_buffer_size = 0;

	// callsign and short callsign
	strcpy_s(pl->callsign,name);
	pilot_set_short_callsign(pl,SHORT_CALLSIGN_PIXEL_W);
	pl->flags |= PLAYER_FLAGS_STRUCTURE_IN_USE;	

	Net_players[player_num].sv_bytes_sent = 0;	
	Net_players[player_num].sv_last_pl = -1;	
	Net_players[player_num].cl_bytes_recvd = 0;	
	Net_players[player_num].cl_last_pl = -1;
}

// create an explicit observer object and assign it to the passed player
void multi_obs_create_observer(net_player *pl)
{
	int objnum;
	
	// create the basic observer object
	objnum = observer_create( &vmd_identity_matrix, &vmd_zero_vector);	
	Assert(objnum != -1);
	Objects[objnum].flags.set(Object::Object_Flags::Player_ship);	
	Objects[objnum].net_signature = 0;

	// put it a 1,1,1
	Objects[objnum].pos.xyz.x = 1.0f;
	Objects[objnum].pos.xyz.y = 1.0f;
	Objects[objnum].pos.xyz.z = 1.0f;

	// assign this object to the player
	pl->m_player->objnum = objnum;				
}

// create observer object locally, and additionally, setup some other information
// ( client-side equivalent of multi_obs_create_observer() )
void multi_obs_create_observer_client()
{
	int pobj_num;
	
	Assert(!(Net_player->flags & NETINFO_FLAG_OBS_PLAYER));					

	// make me an observer object
	multi_obs_create_observer(Net_player);	
					
	// set my object to be the observer object	
	Player_obj = &Objects[Net_player->m_player->objnum];
	
	// create the default player ship object and use that as my default virtual "ship", and make it "invisible"
	pobj_num = parse_create_object(Player_start_pobject);
	Assert(pobj_num != -1);

	obj_set_flags(&Objects[pobj_num], Objects[pobj_num].flags + Object::Object_Flags::Player_ship);
	Player_ship = &Ships[Objects[pobj_num].instance];

	// make ship hidden from sensors so that this observer cannot target it.  Observers really have two ships
	// one observer, and one "Player_ship".  Observer needs to ignore the Player_ship.
    Player_ship->flags.set(Ship::Ship_Flags::Hidden_from_sensors);
	strcpy_s(Player_ship->ship_name, XSTR("Observer Ship",688));
	Player_ai = &Ai_info[Ships[Objects[pobj_num].instance].ai_index];		

	// configure the hud to be in "observer" mode
	hud_config_as_observer(Player_ship,Player_ai);	
		
	// set some flags for myself
	Net_player->flags |= NETINFO_FLAG_OBSERVER;	
	
	// reset the control info structure
	memset(&Player->ci,0,sizeof(control_info));	
}

// create objects for all known observers in the game at level start
// call this before entering a mission
// this implies for the local player in the case of a client or for _all_ players in the case of a server
void multi_obs_level_init()
{
	int idx;	

	// unset the OBS_PLAYER flag here for all net players
	for(idx=0;idx<MAX_PLAYERS;idx++){
		Net_players[idx].flags &= ~(NETINFO_FLAG_OBS_PLAYER);
	}

	// if i'm a client and I'm an observer, create an object for myself
	if(!(Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){		
		// create my own observer object and setup other misc. data
		multi_obs_create_observer_client();
	}
	// otherwise create stuff for all (permanent) observers in the game
	else {
		for(idx=0;idx<MAX_PLAYERS;idx++){
			if(MULTI_CONNECTED(Net_players[idx]) && MULTI_OBSERVER(Net_players[idx])){
				// make an observer object for the guy
				multi_obs_create_observer(&Net_players[idx]);
			}
		}
	}
}

// if i'm an observer, zoom to near my targted object (if any)
void multi_obs_zoom_to_target()
{
	vec3d direct;		
	float dist;	
	
	// if i'm not an observer, do nothing
	if(!(Game_mode & GM_MULTIPLAYER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type != OBJ_OBSERVER)){		
		return;
	}

	// if I have no targeted object, do nothing
	if(Player_ai->target_objnum == -1){		
		return;
	}

	// get the normalized direction vector between the observer and the targeted object
	vm_vec_sub(&direct,&Objects[Player_ai->target_objnum].pos,&Player_obj->pos);
	dist = vm_vec_mag(&direct);
	vm_vec_normalize(&direct);	

	// orient the guy correctly
	vm_vec_ang_2_matrix(&Player_obj->orient,&direct,0.0f);

	// keep about 3 object radii away when moving
	dist -= (Objects[Player_ai->target_objnum].radius * 3.0f);

	// get the movement vector
	vm_vec_scale(&direct,dist);

	// move
	vm_vec_add2(&Player_obj->pos,&direct);
}