Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NetPlayer.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: NetPlayer.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Network Player (Director) class
13 */
14 
15 #include "MemDebug.h"
16 #include "NetPlayer.h"
17 #include "NetGame.h"
18 #include "NetMsg.h"
19 #include "NetData.h"
20 #include "NetUtil.h"
21 #include "Ship.h"
22 #include "ShipDesign.h"
23 #include "Shield.h"
24 #include "Shot.h"
25 #include "Sim.h"
26 #include "SimEvent.h"
27 #include "System.h"
28 #include "Weapon.h"
29 #include "WeaponGroup.h"
30 #include "Element.h"
31 #include "HUDView.h"
32 #include "Explosion.h"
33 #include "Farcaster.h"
34 #include "RadioMessage.h"
35 #include "RadioTraffic.h"
36 
37 #include "NetHost.h"
38 #include "Game.h"
39 #include "Light.h"
40 
41 // +--------------------------------------------------------------------+
42 
44 {
45  if (ship) {
47 
48  Sim* sim = Sim::GetSim();
49  sim->DestroyShip(ship);
50  }
51 }
52 
53 // +--------------------------------------------------------------------+
54 
55 void
57 {
58  if (ship != s) {
59  if (ship) {
60  ship->EnableRepair(true);
61  Ignore(ship);
62  }
63 
64  ship = s;
65 
66  if (ship) {
67  Observe(ship);
68  ship->SetNetworkControl(this);
70 
71  iff = ship->GetIFF();
72 
73  // Turn off auto-repair. All repair data should
74  // come in over the network from the remote player:
75 
76  ship->EnableRepair(false);
77 
78  // Set all ship weapons back to manual fire control.
79  // All trigger events should come over the network,
80  // not from weapon auto aiming ai:
81 
83  while (++iter) {
84  WeaponGroup* group = iter.value();
85 
86  ListIter<Weapon> w_iter = group->GetWeapons();
87  while (++w_iter) {
88  Weapon* weapon = w_iter.value();
89 
91  }
92  }
93  }
94  }
95 }
96 
97 // +--------------------------------------------------------------------+
98 
99 const double BLEED = 0.5;
100 
101 bool
103 {
104  if (ship && obj_loc) {
105  loc_error = obj_loc->GetLocation() - ship->Location();
106  bleed_time = BLEED;
107 
108  ship->SetVelocity(obj_loc->GetVelocity());
109  Point o = obj_loc->GetOrientation();
110  ship->SetAbsoluteOrientation(o.x, o.y, o.z);
111  ship->SetThrottle(obj_loc->GetThrottle() ? 100 : 0);
112  ship->SetAugmenter(obj_loc->GetAugmenter());
113 
114  if (obj_loc->GetGearDown())
115  ship->LowerGear();
116  else
117  ship->RaiseGear();
118 
119  Shield* shield = ship->GetShield();
120  if (shield)
121  shield->SetPowerLevel(obj_loc->GetShield());
122 
123  return true;
124  }
125 
126  return false;
127 }
128 
129 bool
131 {
132  if (ship && obj_hyper) {
133  Sim* sim = Sim::GetSim();
134  SimRegion* rgn = sim->FindRegion(obj_hyper->GetRegion());
135  DWORD fc1_id = obj_hyper->GetFarcaster1();
136  DWORD fc2_id = obj_hyper->GetFarcaster2();
137  Ship* fc1 = 0;
138  Ship* fc2 = 0;
139  int trans = obj_hyper->GetTransitionType();
140 
141  if (ship->GetRegion() == rgn) {
142  ::Print("NetPlayer::DoObjHyper ship: '%s' rgn: '%s' trans: %d (IGNORED)\n\n",
143  ship->Name(), obj_hyper->GetRegion().data(), trans);
144 
145  return false;
146  }
147 
148  ::Print("NetPlayer::DoObjHyper ship: '%s' rgn: '%s' trans: %d\n\n",
149  ship->Name(), obj_hyper->GetRegion().data(), trans);
150 
151  // orbital transition?
152  if (trans == Ship::TRANSITION_DROP_ORBIT) {
155  }
156 
157  else if (trans == Ship::TRANSITION_MAKE_ORBIT) {
160  }
161 
162  else {
163  if (fc1_id)
164  fc1 = sim->FindShipByObjID(fc1_id);
165 
166  if (fc2_id)
167  fc2 = sim->FindShipByObjID(fc2_id);
168 
169  sim->CreateExplosion(ship->Location(), Point(0,0,0),
171 
172  sim->RequestHyperJump(ship, rgn, obj_hyper->GetLocation(), trans, fc1, fc2);
173 
174  ShipStats* stats = ShipStats::Find(ship->Name());
175  stats->AddEvent(SimEvent::QUANTUM_JUMP, rgn->Name());
176  }
177 
178  return true;
179  }
180 
181  return false;
182 }
183 
184 bool
186 {
187  if (ship && obj_target) {
188  DWORD tgtid = obj_target->GetTgtID();
189  int subid = obj_target->GetSubtarget();
190  SimObject* target = 0;
191  System* subtgt = 0;
192 
193  NetGame* net_game = NetGame::GetInstance();
194  if (net_game && tgtid) {
195  target = net_game->FindShipByObjID(tgtid);
196 
197  if (target) {
198  if (subid >= 0) {
199  Ship* tgt_ship = (Ship*) target;
200  subtgt = tgt_ship->Systems().at(subid);
201  }
202  }
203  else {
204  target = net_game->FindShotByObjID(tgtid);
205  }
206  }
207 
208  ship->SetTarget(target, subtgt, true); // from net = true (don't resend)
209 
210  return true;
211  }
212 
213  return false;
214 }
215 
216 bool
218 {
219  if (ship && obj_emcon) {
220  int emcon = obj_emcon->GetEMCON();
221  ship->SetEMCON(emcon, true); // from net = true (don't resend)
222 
223  return true;
224  }
225 
226  return false;
227 }
228 
229 bool
231 {
232  if (ship && trigger) {
233  int index = trigger->GetIndex();
234  int count = trigger->GetCount();
235  DWORD tgtid = trigger->GetTgtID();
236  int subid = trigger->GetSubtarget();
237  bool decoy = trigger->GetDecoy();
238  bool probe = trigger->GetProbe();
239 
240  Weapon* w = 0;
241 
242  if (decoy) w = ship->GetDecoy();
243  else if (probe) w = ship->GetProbeLauncher();
244  else w = ship->GetWeaponByIndex(index);
245 
246  if (w) {
247  SimObject* target = 0;
248  System* subtgt = 0;
249 
250  NetGame* net_game = NetGame::GetInstance();
251  if (net_game) {
252  target = net_game->FindShipByObjID(tgtid);
253 
254  if (target) {
255  if (subid >= 0) {
256  Ship* tgt_ship = (Ship*) target;
257  subtgt = tgt_ship->Systems().at(subid);
258  }
259  }
260  else {
261  target = net_game->FindShotByObjID(tgtid);
262  }
263 
264  // re-broadcast:
265  if (net_game->IsServer()) {
266  if (w->IsPrimary()) {
267  w->NetFirePrimary(target, subtgt, count);
268  net_game->SendData(trigger);
269  }
270  else {
271  DWORD wepid = NetGame::GetNextObjID(NetGame::SHOT);
272  Shot* shot = w->NetFireSecondary(target, subtgt, wepid);
273 
274  if (shot && shot->IsDrone()) {
275  if (probe)
276  ship->SetProbe((Drone*) shot);
277 
278  else if (decoy)
279  ship->AddActiveDecoy((Drone*) shot);
280  }
281 
282  NetWepRelease release;
283  release.SetObjID(objid);
284  release.SetTgtID(tgtid);
285  release.SetSubtarget(subid);
286  release.SetWepID(wepid);
287  release.SetIndex(index);
288  release.SetDecoy(decoy);
289  release.SetProbe(probe);
290 
291  net_game->SendData(&release);
292  }
293  }
294 
295  else {
296  if (w->IsPrimary()) {
297  w->NetFirePrimary(target, subtgt, count);
298  }
299  }
300 
301  return true;
302  }
303  }
304 
305  }
306  return false;
307 }
308 
309 bool
311 {
312  if (ship && release) {
313  int index = release->GetIndex();
314  DWORD tgtid = release->GetTgtID();
315  DWORD wepid = release->GetWepID();
316  int subid = release->GetSubtarget();
317  bool decoy = release->GetDecoy();
318  bool probe = release->GetProbe();
319 
320  Weapon* w = 0;
321 
322  if (decoy) w = ship->GetDecoy();
323  else if (probe) w = ship->GetProbeLauncher();
324  else w = ship->GetWeaponByIndex(index);
325 
326  if (w && !w->IsPrimary()) {
327  SimObject* target = 0;
328  System* subtgt = 0;
329 
330  NetGame* net_game = NetGame::GetInstance();
331  if (net_game) {
332  target = net_game->FindShipByObjID(tgtid);
333 
334  if (target) {
335  if (subid >= 0) {
336  Ship* tgt_ship = (Ship*) target;
337  subtgt = tgt_ship->Systems().at(subid);
338  }
339  }
340  else {
341  target = net_game->FindShotByObjID(tgtid);
342  }
343  }
344 
345  Shot* shot = w->NetFireSecondary(target, subtgt, wepid);
346 
347  if (shot && shot->IsDrone()) {
348  if (probe)
349  ship->SetProbe((Drone*) shot);
350 
351  else if (decoy)
352  ship->AddActiveDecoy((Drone*) shot);
353  }
354 
355  return true;
356  }
357  }
358 
359  return false;
360 }
361 
362 bool
364 {
365  if (ship && comm_msg) {
367  RadioMessage* radio_msg = comm_msg->GetRadioMessage();
368 
369  if (traffic && radio_msg) {
370  if (radio_msg->DestinationElem() || radio_msg->DestinationShip()) {
371  // radio traffic owns the sent message,
372  // so we must give it a cloned object that is
373  // safe to delete:
374  traffic->SendMessage(new(__FILE__,__LINE__) RadioMessage(*radio_msg));
375  return true;
376  }
377  }
378  }
379 
380  return false;
381 }
382 
383 // +--------------------------------------------------------------------+
384 
385 bool
387 {
388  if (ship && sys_damage) {
389  System* sys = ship->GetSystem(sys_damage->GetSystem());
391  sys_damage->GetDamage(),
392  sys_damage->GetDamageType());
393 
394  return true;
395  }
396 
397  return false;
398 }
399 
400 bool
402 {
403  if (ship && sys_status) {
404  System* sys = ship->GetSystem(sys_status->GetSystem());
405  ship->SetNetSystemStatus( sys,
406  sys_status->GetStatus(),
407  sys_status->GetPower(),
408  sys_status->GetReactor(),
409  sys_status->GetAvailability());
410 
411  return true;
412  }
413 
414  return false;
415 }
416 
417 // +--------------------------------------------------------------------+
418 
419 void
420 NetPlayer::ExecFrame(double seconds)
421 {
422  if (ship) {
423  // bleed off the location error:
424  if (loc_error.length() > 0 && bleed_time > 0) {
425  double fragment = min(seconds / BLEED, bleed_time);
426  ship->MoveTo(ship->Location() + loc_error * fragment);
427  bleed_time -= fragment;
428  }
429 
430  // update the ship location by dead reckoning:
431  ship->MoveTo(ship->Location() + ship->Velocity() * seconds);
432 
433  // let the FLCS run, so that the drive flares will work:
434  ship->ExecFLCSFrame();
435 
436  // now update the graphic rep and light sources:
437  if (ship->Rep()) {
438  ship->Rep()->MoveTo(ship->Location());
440  }
441 
442  if (ship->LightSrc()) {
443  ship->LightSrc()->MoveTo(ship->Location());
444  }
445  }
446 }
447 
448 // +--------------------------------------------------------------------+
449 
450 bool
452 {
453  if (obj == ship) {
454  ship = 0;
455  }
456 
457  return SimObserver::Update(obj);
458 }
459 
460 const char*
462 {
463  return "NetPlayer";
464 }