EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
BeyonceService.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: Zhur
24  Rewrite: Allan
25 */
26 
27 #include "eve-server.h"
28 
29 #include "PyBoundObject.h"
30 #include "PyServiceCD.h"
31 #include "StaticDataMgr.h"
32 #include "cache/ObjCacheService.h"
33 #include "planet/PlanetDB.h"
34 #include "system/SystemDB.h"
35 #include "planet/Moon.h"
36 #include "pos/Structure.h"
37 #include "ship/BeyonceService.h"
38 #include "station/StationDataMgr.h"
39 #include "system/BookmarkService.h"
40 #include "system/Container.h"
41 #include "system/DestinyManager.h"
42 #include "system/SystemBubble.h"
43 #include "system/SystemManager.h"
46 
48 : public PyBoundObject
49 {
50 public:
52 
54  : PyBoundObject(mgr),
55  m_dispatch(new Dispatcher(this))
56  {
58 
59  m_strBoundObjectName = "BeyonceBound";
60 
61  PyCallable_REG_CALL(BeyonceBound, CmdFollowBall); //*
62  PyCallable_REG_CALL(BeyonceBound, CmdOrbit); //*
63  PyCallable_REG_CALL(BeyonceBound, CmdAlignTo);
64  PyCallable_REG_CALL(BeyonceBound, CmdGotoDirection); //*
65  PyCallable_REG_CALL(BeyonceBound, CmdGotoBookmark);
66  PyCallable_REG_CALL(BeyonceBound, CmdSetSpeedFraction);
68  PyCallable_REG_CALL(BeyonceBound, CmdWarpToStuff);
70  PyCallable_REG_CALL(BeyonceBound, CmdStargateJump);
71  PyCallable_REG_CALL(BeyonceBound, UpdateStateRequest);
72  PyCallable_REG_CALL(BeyonceBound, CmdWarpToStuffAutopilot); //*
73  PyCallable_REG_CALL(BeyonceBound, CmdAbandonLoot);
74 
75  PyCallable_REG_CALL(BeyonceBound, CmdFleetRegroup);
76  PyCallable_REG_CALL(BeyonceBound, CmdFleetTagTarget);
77  PyCallable_REG_CALL(BeyonceBound, CmdBeaconJumpFleet);
78  PyCallable_REG_CALL(BeyonceBound, CmdBeaconJumpAlliance);
79  PyCallable_REG_CALL(BeyonceBound, CmdJumpThroughFleet);
80  PyCallable_REG_CALL(BeyonceBound, CmdJumpThroughAlliance);
81  PyCallable_REG_CALL(BeyonceBound, CmdJumpThroughCorporationStructure);
82 
83 
84  pClient->SetBeyonce(true);
85  if (pClient->IsLogin() and !pClient->IsSetStateSent())
86  pClient->SetBallPark();
87  }
88 
89  virtual ~BeyonceBound()
90  {
91  delete m_dispatch;
92  }
93 
94  virtual void Release() {
95  //I hate this statement
96  delete this;
97  }
98 
99  PyCallable_DECL_CALL(CmdFollowBall);
100  PyCallable_DECL_CALL(CmdOrbit);
101  PyCallable_DECL_CALL(CmdAlignTo);
102  PyCallable_DECL_CALL(CmdGotoDirection);
103  PyCallable_DECL_CALL(CmdGotoBookmark);
104  PyCallable_DECL_CALL(CmdSetSpeedFraction);
105  PyCallable_DECL_CALL(CmdStop);
106  PyCallable_DECL_CALL(CmdWarpToStuff);
107  PyCallable_DECL_CALL(CmdDock);
108  PyCallable_DECL_CALL(CmdStargateJump);
109  PyCallable_DECL_CALL(UpdateStateRequest);
110  PyCallable_DECL_CALL(CmdWarpToStuffAutopilot);
111  PyCallable_DECL_CALL(CmdAbandonLoot);
112 
113  PyCallable_DECL_CALL(CmdFleetRegroup);
114  PyCallable_DECL_CALL(CmdFleetTagTarget);
115  PyCallable_DECL_CALL(CmdJumpThroughFleet);
116  PyCallable_DECL_CALL(CmdBeaconJumpFleet);
117  PyCallable_DECL_CALL(CmdBeaconJumpAlliance);
118  PyCallable_DECL_CALL(CmdJumpThroughAlliance);
119  PyCallable_DECL_CALL(CmdJumpThroughCorporationStructure);
120 
121 protected:
122  Dispatcher *const m_dispatch;
123 
124 };
125 
127 
129 : PyService(mgr, "beyonce"),
130  m_dispatch(new Dispatcher(this))
131 {
132  _SetCallDispatcher(m_dispatch);
133 
134  PyCallable_REG_CALL(BeyonceService, GetFormations)
135 }
136 
138  delete m_dispatch;
139 }
140 
141 PyBoundObject* BeyonceService::CreateBoundObject(Client* pClient, const PyRep* bind_args)
142 {
143  return new BeyonceBound(m_manager, pClient);
144 }
145 
146 PyResult BeyonceService::Handle_GetFormations(PyCallArgs &call) {
147  // this is only called when player enters new system and calls to bind new beyonce
148  if (!call.client->IsSetStateSent())
149  call.client->CheckBallparkTimer();
150 
151  PyTuple* res = new PyTuple( 2 );
152  Beyonce_Formation f;
153  //Diamond formation
154  f.name = "Diamond";
155  f.pos1.x = 100;
156  f.pos2.y = 100;
157  f.pos3.x = -100;
158  f.pos4.y = -100;
159  res->SetItem( 0, f.Encode() );
160  //Arrow formation
161  f.name = "Arrow";
162  f.pos1.x = 100;
163  f.pos1.z = -50;
164  f.pos2.x = 50;
165  f.pos2.y = 0;
166  f.pos3.x = -100;
167  f.pos3.z = -50;
168  f.pos4.x = -50;
169  f.pos4.y = 0;
170  res->SetItem( 1, f.Encode() );
171  return res;
172 }
173 
174 PyResult BeyonceBound::Handle_CmdFollowBall(PyCallArgs &call) {
175  _log(AUTOPILOT__MESSAGE, "%s called Follow. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
176 
177  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
178  if (pDestiny == nullptr) {
179  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
180  return PyStatic.NewNone();
181  } else if (pDestiny->IsWarping()) {
182  call.client->SendNotifyMsg( "You can't do this while warping");
183  return PyStatic.NewNone();
184  } else if (pDestiny->IsFrozen()) {
185  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
186  return PyStatic.NewNone();
187  }
188  SystemManager* pSystem = call.client->SystemMgr();
189  if (pSystem == nullptr) {
190  codelog(CLIENT__ERROR, "%s: Client has no system manager!", call.client->GetName());
191  return PyStatic.NewNone();
192  }
193  Call_FollowBall args;
194  if (!args.Decode(&call.tuple)) {
195  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
196  return PyStatic.NewNone();
197  }
198 
199  SystemEntity* pSE = pSystem->GetSE(args.ballID);
200  if (pSE == nullptr) {
201  _log(CLIENT__ERROR, "%s: Unable to find entity %u to Follow/Approach.", call.client->GetName(), args.ballID);
202  return PyStatic.NewNone();
203  }
204 
205  call.client->SetInvul(false);
206  call.client->SetUndock(false);
207 
208  pDestiny->Follow(pSE, PyRep::IntegerValue(args.distance));
209 
210  return PyStatic.NewNone();
211 }
212 
213 PyResult BeyonceBound::Handle_CmdSetSpeedFraction(PyCallArgs &call) {
214  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
215  if (pDestiny == nullptr) {
216  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
217  return PyStatic.NewNone();
218  } else if (pDestiny->IsWarping()) {
219  call.client->SendNotifyMsg( "You can't do this while warping");
220  return PyStatic.NewNone();
221  } else if (pDestiny->IsFrozen()) {
222  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
223  return PyStatic.NewNone();
224  }
225 
226  Call_SingleRealArg arg;
227  if (!arg.Decode(&call.tuple)) {
228  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
229  return PyStatic.NewNone();
230  }
232  // client should not legally send anything < 0.1 (except on rare occasion a 0.0 instead of Stop.)
233  if ((arg.arg != 0) && (arg.arg < 0.1))
234  return PyStatic.NewNone();
235 
236  //sLog.Warning( "BeyonceBound", "Handle_CmdSetSpeedFraction %.2f", arg.arg );
237  if (!call.client->IsUndock()){
238  if (pDestiny->IsMoving()) {
239  pDestiny->SetSpeedFraction(arg.arg);
240  } else {
241  pDestiny->SetSpeedFraction(arg.arg, true);
242  }
243  }
244 
245  return PyStatic.NewNone();
246 }
247 
248 PyResult BeyonceBound::Handle_CmdAlignTo(PyCallArgs &call) {
249  _log(AUTOPILOT__MESSAGE, "%s called Align. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
250  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
251  if (pDestiny == nullptr) {
252  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
253  return PyStatic.NewNone();
254  } else if (pDestiny->IsWarping()) {
255  call.client->SendNotifyMsg( "You can't do this while warping");
256  return PyStatic.NewNone();
257  } else if (pDestiny->IsFrozen()) {
258  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
259  return PyStatic.NewNone();
260  }
261  SystemManager* pSystem = call.client->SystemMgr();
262  if (pSystem == nullptr) {
263  codelog(CLIENT__ERROR, "%s: Client has no system manager!", call.client->GetName());
264  return PyStatic.NewNone();
265  }
266 
267  CallAlignTo arg;
268  if (!arg.Decode(&call.tuple)) {
269  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
270  return PyStatic.NewNone();
271  }
272 
273  SystemEntity* pEntity = pSystem->GetSE(arg.entityID);
274  if (pEntity == nullptr) {
275  _log(CLIENT__ERROR, "%s: Unable to find entity %u to AlignTo.", call.client->GetName(), arg.entityID);
276  return PyStatic.NewNone();
277  }
278 
279  call.client->SetInvul(false);
280  call.client->SetUndock(false);
281 
282  pDestiny->AlignTo( pEntity );
283 
284  return PyStatic.NewNone();
285 }
286 
287 PyResult BeyonceBound::Handle_CmdGotoDirection(PyCallArgs &call) {
288  _log(AUTOPILOT__MESSAGE, "%s called GotoDirection. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
289  //call.client->SetAutoPilot(false);
290 
291  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
292  if (pDestiny == nullptr) {
293  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
294  return PyStatic.NewNone();
295  } else if (pDestiny->IsWarping()) {
296  call.client->SendNotifyMsg( "You can't do this while warping");
297  return PyStatic.NewNone();
298  } else if (pDestiny->IsFrozen()) {
299  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
300  return PyStatic.NewNone();
301  }
302 
303  Call_PointArg arg;
304  if (!arg.Decode(&call.tuple)) {
305  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
306  return PyStatic.NewNone();
307  }
308 
309  call.client->SetInvul(false);
310  call.client->SetUndock(false);
311 
312  const GPoint dir = GPoint(arg.x, arg.y, arg.z);
313  pDestiny->GotoDirection(dir);
314 
315  return PyStatic.NewNone();
316 }
317 
318 PyResult BeyonceBound::Handle_CmdGotoBookmark(PyCallArgs &call) {
319  _log(AUTOPILOT__MESSAGE, "%s called GotoBookmark. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
320  //call.client->SetAutoPilot(false);
321 
322  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
323  if (pDestiny == nullptr) {
324  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
325  return PyStatic.NewNone();
326  } else if (pDestiny->IsWarping()) {
327  call.client->SendNotifyMsg( "You can't do this while warping");
328  return PyStatic.NewNone();
329  } else if (pDestiny->IsFrozen()) {
330  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
331  return PyStatic.NewNone();
332  }
333 
334  Call_SingleIntegerArg arg;
335  if (!arg.Decode(&call.tuple)) {
336  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
337  return PyStatic.NewNone();
338  }
339 
340  double x(0.0), y(0.0), z(0.0);
341  uint16 typeID(0);
342  uint32 itemID(0), locationID(0);
343 
344  BookmarkService* pBMSvc = (BookmarkService*)(call.client->services().LookupService( "bookmark" ));
345 
346  if (pBMSvc == nullptr) {
347  sLog.Error( "BeyonceService::Handle_GotoBookmark()", "Attempt to access BookmarkService via (BookmarkService*)(call.client->services().LookupService(\"bookmark\")) returned NULL." );
348  return PyStatic.NewNone();
349  } else {
350  pBMSvc->LookupBookmark(arg.arg, itemID, typeID, locationID, x, y, z);
351 
352  if (typeID == 5) {
353  if (call.client->GetSystemID() != locationID) {
354  // this bm is for different system. make and send error here.
355  return PyStatic.NewNone();
356  }
357 
358  GPoint point(x, y, z);
359  pDestiny->GotoPoint(point);
360  } else {
361  // Bookmark type is of a static system entity, so search for it and obtain its coordinates:
362  SystemEntity* pSE = call.client->SystemMgr()->GetSE(itemID);
363  if (pSE == nullptr) {
364  sLog.Error( "BeyonceService::Handle_GotoBookmark()", "%s: unable to find location %d", call.client->GetName(), itemID );
365  return PyStatic.NewNone();
366  }
367 
368  pDestiny->GotoPoint( pSE->GetPosition() );
369  }
370  }
371 
372  call.client->SetInvul(false);
373  call.client->SetUndock(false);
374 
375  return PyStatic.NewNone();
376 }
377 
378 PyResult BeyonceBound::Handle_CmdOrbit(PyCallArgs &call) {
379  _log(AUTOPILOT__MESSAGE, "%s called Orbit. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
380  call.client->SetAutoPilot(false);
381 
382  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
383  if (pDestiny == nullptr) {
384  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
385  return PyStatic.NewNone();
386  } else if (pDestiny->IsWarping()) {
387  call.client->SendNotifyMsg( "You can't do this while warping");
388  return PyStatic.NewNone();
389  } else if (pDestiny->IsFrozen()) {
390  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
391  return PyStatic.NewNone();
392  }
393 
394  SystemManager* pSystem = call.client->SystemMgr();
395  if (pSystem == nullptr) {
396  codelog(CLIENT__ERROR, "%s: Client has no system manager!", call.client->GetName());
397  return PyStatic.NewNone();
398  }
399 
400  call.Dump(SERVICE__CALL_DUMP);
401  Call_Orbit args;
402  if (!args.Decode(&call.tuple)) {
403  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
404  return PyStatic.NewNone();
405  }
406 
407  double range =
408  args.range->IsInt()
409  ? args.range->AsInt()->value()
410  : args.range->AsFloat()->value();
411 
412  SystemEntity* pEntity = pSystem->GetSE(args.entityID);
413  if (pEntity == nullptr) {
414  _log(CLIENT__ERROR, "%s: Unable to find entity %u to Orbit.", call.client->GetName(), args.entityID);
415  return PyStatic.NewNone();
416  }
417 
418  call.client->SetInvul(false);
419  call.client->SetUndock(false);
420 
421  pDestiny->Orbit(pEntity, range);
422 
423  return PyStatic.NewNone();
424 }
425 
426 PyResult BeyonceBound::Handle_CmdWarpToStuff(PyCallArgs &call) {
427  _log(AUTOPILOT__MESSAGE, "%s called WarpToStuff. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
428  //call.client->SetAutoPilot(false);
429 
430  _log(SERVICE__CALL_DUMP, "BeyonceBound::Handle_CmdWarpToStuff() - size %u", call.tuple->size() );
431  call.Dump(SERVICE__CALL_DUMP);
432 
434  // >0 means ship cannot warp (warp stabs are neg values, warp scrams are pos values)
436  throw UserError ("WarpScrambled");
437 
438  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
439  if (pDestiny == nullptr) {
440  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
441  return PyStatic.NewNone();
442  }
443  if (pDestiny->IsWarping()){
444  call.client->SendNotifyMsg( "You are already warping");
445  return PyStatic.NewNone();
446  } else if (pDestiny->IsFrozen()) {
447  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
448  return PyStatic.NewNone();
449  }
450 
451  SystemManager* pSystem = call.client->SystemMgr();
452  if (pSystem == nullptr) {
453  codelog(CLIENT__ERROR, "%s: Client has no system manager!", call.client->GetName());
454  return PyStatic.NewNone();
455  }
456 
457  bool fleet(false);
458  if (call.byname.find("fleet") != call.byname.end())
459  if (!(call.byname.find("fleet")->second->IsNone()))
460  fleet = call.byname.find("fleet")->second->AsBool()->value();
461 
462  // get the warp-to distance specified by the client
463  int32 distance(0); //Was set to 5000; setting to 0 makes warp in to station and gate more realistic.
464  if (call.byname.find("minRange") != call.byname.end())
465  distance = PyRep::IntegerValueU32(call.byname.find("minRange")->second);
466 
467  GPoint warpToPoint(NULL_ORIGIN);
468  SystemEntity* pSE(nullptr);
469  double radius(0);
470  uint32 toID(0);
471  std::string stringArg = "";
472 
473  if ((call.tuple->GetItem(1)->IsString())
474  or (call.tuple->GetItem(1)->IsWString())) {
475  stringArg = PyRep::StringContent(call.tuple->GetItem(1));
476  } else {
477  toID = PyRep::IntegerValueU32(call.tuple->GetItem(1));
478  }
479 
480  std::string type = PyRep::StringContent(call.tuple->GetItem(0));
481  if (type == "item" ) {
482  pSE = pSystem->GetSE(toID);
483  if (pSE == nullptr) {
484  codelog(CLIENT__ERROR, "%s: unable to find item location %u in %s(%u)", call.client->GetName(), toID, pSystem->GetName(), pSystem->GetID());
485  return PyStatic.NewNone();
486  }
487  } else if (type == "bookmark" ) {
488  double x(0.0), y(0.0), z(0.0);
489  uint16 typeID(0);
490  uint32 locationID(0);
491  uint32 bookmarkID(PyRep::IntegerValueU32(call.tuple->GetItem(1)));
492 
493  BookmarkService* bkSrvc = (BookmarkService *)(call.client->services().LookupService( "bookmark" ));
494  if (bkSrvc == nullptr) {
495  sLog.Error( "BeyonceService::Handle_WarpToStuff()", "Attempt to access BookmarkService returned NULL." );
496  return PyStatic.NewNone();
497  }
498  bkSrvc->LookupBookmark(bookmarkID, toID, typeID, locationID, x, y, z);
499 
500  if ( typeID == 5 ) {
501  if (call.client->GetSystemID() != locationID) {
502  // this bm is for different system. make error here.
503  return PyStatic.NewNone();
504  }
505  warpToPoint.x = x;
506  warpToPoint.y = y;
507  warpToPoint.z = z;
508  } else {
509  // Bookmark type is of a static system entity, so search for it and obtain its coordinates:
510  pSE = pSystem->GetSE( toID );
511  if (pSE == nullptr) {
512  codelog(CLIENT__ERROR, "%s: unable to find bookmark location %u in %s(%u)", call.client->GetName(), toID, pSystem->GetName(), pSystem->GetID());
513  return PyStatic.NewNone();
514  }
515  }
516  } else if (type == "scan") {
517  uint32 anomID = pSystem->GetAnomMgr()->GetAnomalyID(stringArg);
518  pSE = pSystem->GetSE(anomID);
519  } else if (type == "launch") {
520  //warpToPoint = PlanetDB::GetLaunchPos(toID);
521  pSE = pSystem->GetSE(toID);
522  // launchpickup - launch, launchid
523  }
524  // the systems below are not implemented yet. hold on coding till systems are working and we know what needs to be done here
525  // more info can be found in client::menuSvc.py
526  else if (type == "epinstance") {
527  // epinstance, instanceid
528  //stringArg
529  call.client->SendErrorMsg("WarpToInstance is not implemented at this time.");
530  return PyStatic.NewNone();
531  } else if (type == "tutorial") {
532  // tutorial, none
533  call.client->SendErrorMsg("WarpToTutorial is not implemented at this time.");
534  return PyStatic.NewNone();
535  } else if (type == "char") {
536  // fleet warping
537  // [warptomember] char, charid, minrange
538  // [warpfleettomember] char, charid, minrange, fleet=1
539  call.client->SendErrorMsg("WarpToChar is not implemented at this time.");
540  return PyStatic.NewNone();
541  } else {
542  sLog.Error( "BeyonceService::Handle_WarpToStuff()", "Unexpected type value: '%s'.", type.c_str() );
543  return PyStatic.NewNone();
544  }
545 
546  /* formulas for warpin points for all objects
547  * x,y,z = object coords. r = object radius
548  *
549  * for objects <90kr
550  * dest = x,y,z + (vector - r)
551  *
552  * for objects >90kr
553  * (x + (r + 5000000) * cos(r), y + 1.3r -7500, z - (r + 5000000) * sin(r))
554  *
555  * for planets, its a bit different
556  * (x + d*sin(t), y + 0.5*r*sin(j), z - d*cos(t))
557  * where:
558  * j = rand(seed=planetID).rand(0,1) - 1.0/3.0
559  * d = r*(s+1) +1000000
560  * t = sin^-1(x/abs(x) * z / sqrt(x^2 + z^2) +j)
561  * s = 20*((1/40)*(10*log10(r/10^6)-39)^20) +0.5
562  * s = max(0.5, min(s, 10.5))
563  */
591  if (pSE != nullptr) {
592  radius = pSE->GetRadius();
593  // this will need adjustment for warping to bookmarks
594  warpToPoint = pSE->GetPosition();
595  if (pSE->IsPlanetSE()) {
596  srandom(toID); //this is the only place random() is used....other random functions use rand() as it's non-repeatable.
597  int rand = random();
598  double j = (((rand / RAND_MAX) - 1.0f) / 3.0f);
599  double s = 20 * std::pow(0.025f * (10 * std::log10(radius / 1000000) - 39), 20) + 0.5f;
600  s = EvE::max(0.5f, EvE::min(s, 10.5f));
601  double t = std::asin((warpToPoint.x / std::fabs(warpToPoint.x)) * (warpToPoint.z / std::sqrt(std::pow(warpToPoint.x, 2) + std::pow(warpToPoint.z, 2)))) + j;
602  uint32 d = radius * (s + 1) + 1000000;
603  warpToPoint.x += (d * std::sin(t));
604  warpToPoint.y += (0.5f * radius * std::sin(j));
605  warpToPoint.z -= (d * std::cos(t));
606  } else if (pSE->IsStationSE()) {
607  // this makes ship warp to station dock elevation (y), instead of warping to stations "center point" position (where icon is)
608  warpToPoint.y = stDataMgr.GetDockPosY(pSE->GetID());
609  } else if (pSE->IsCOSE()) {
610  distance += (radius / 2);
611  } else if (pSE->IsGateSE()) {
612  distance += (radius / 3); // fudge the distance a bit for gates... its' a lil close by default
613  } else if (pSE->IsMoonSE()) {
614  if (pSE->GetMoonSE()->HasTower()) {
615  // if moon has a tower, make warpin point 20km inside edge of tower's bubble.
616  warpToPoint = pSE->GetMoonSE()->GetMyTower()->GetPosition();
617  GVector vectorFromOrigin(call.client->GetShipSE()->GetPosition(), warpToPoint);
618  vectorFromOrigin.normalize(); //we now have a direction
619  GPoint stopPoint = (vectorFromOrigin * (BUBBLE_RADIUS_METERS - 20000)); // 20km inside bubble.
620  warpToPoint -= stopPoint;
621  distance = 0;
622  } else {
623  // hack for warping to moons
624  // this puts ship at Az: 0.785332, Ele: 0.615505, angle: 1.5708
625  warpToPoint -= (radius * 1.25f);
626  }
627  } else if (pSE->IsWormholeSE()) {
628  distance += 20000; // add 20k for wh
629  } else if (radius > 90000) {
630  // this doesnt work for moons
631  warpToPoint.x += ((radius + 500000) * std::cos(radius));
632  warpToPoint.y += ((radius * 1.3f) - 7500);
633  warpToPoint.z -= ((radius + 500000) * std::sin(radius));
634  }
635  if (radius < 90000) {
636  // this will include stations (max station radius 60km)
637  GVector vectorFromOrigin(call.client->GetShipSE()->GetPosition(), warpToPoint);
638  vectorFromOrigin.normalize(); //we now have a direction
639  GPoint stopPoint = (vectorFromOrigin * radius);
640  warpToPoint -= stopPoint;
641  }
642  }
643  if (warpToPoint.isZero()) {
644  // point is zero ....make error and return
645  codelog(CLIENT__ERROR, "%s: warpToPoint.isZero() = true. Cannot find location %u for '%s'", call.client->GetName(), toID, type.c_str());
646  call.client->SendErrorMsg("WarpTo: Item location not found.");
647  return PyStatic.NewNone();
648  }
649 
650  call.client->SetInvul(false);
651  call.client->SetUndock(false);
652 
653  distance += (call.client->GetShipSE()->GetRadius() * 2); // add ship diameter to distance
654  pDestiny->WarpTo(warpToPoint, distance);
655 
656  return PyStatic.NewNone();
657 }
658 
659 PyResult BeyonceBound::Handle_CmdWarpToStuffAutopilot(PyCallArgs &call) {
660  _log(AUTOPILOT__MESSAGE, "%s called WarpToStuffAutopilot. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
661  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
662  if (pDestiny == nullptr) {
663  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
664  return PyStatic.NewNone();
665  } else if (pDestiny->IsWarping()) {
666  call.client->SendNotifyMsg( "You can't do this while warping");
667  return PyStatic.NewNone();
668  } else if (pDestiny->IsFrozen()) {
669  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
670  return PyStatic.NewNone();
671  }
672  SystemManager* pSystem = call.client->SystemMgr();
673  if (pSystem == nullptr) {
674  codelog(CLIENT__ERROR, "%s: Client has no system manager!", call.client->GetName());
675  return PyStatic.NewNone();
676  }
677 
678  // sends targeted celestial itemID as arg.destID
679  CallWarpToStuffAutopilot arg;
680  if (!arg.Decode(&call.tuple)) {
681  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
682  return PyStatic.NewNone();
683  }
684 
685  SystemEntity* pSE = pSystem->GetSE(arg.destID);
686  if (pSE == nullptr) {
687  codelog(CLIENT__ERROR, "%s: unable to find destination Entity for ID %u", call.client->GetName(), arg.destID);
688  return PyStatic.NewNone();
689  }
690 
691  call.client->SetInvul(false);
692  call.client->SetUndock(false);
693  // AP shit here.....
694  call.client->SetAutoPilot(true);
695  call.client->UpdateSessionInt("solarsystemid", pSystem->GetID());
696  //call.client->UpdateSession();
697  //call.client->SendSessionChange();
698 
699  uint16 distance = sConfig.world.apWarptoDistance; //10km default
700  //Adding in ship and target object radius'
701  //distance += call.client->GetShipSE()->GetRadius() + pSE->GetRadius();
702  pDestiny->WarpTo(pSE->GetPosition(), distance, true, pSE);
703 
704  return PyStatic.NewNone();
705 }
706 
707 PyResult BeyonceBound::Handle_CmdStop(PyCallArgs &call) {
708  _log(AUTOPILOT__MESSAGE, "%s called Stop. AP: %s, Invul: %s", call.client->GetName(), \
709  (call.client->IsAutoPilot() ? "true" : "false"), call.client->IsInvul()?"true":"false");
710 
711  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
712  if (pDestiny == nullptr) {
713  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
714  return PyStatic.NewNone();
715  }
716  if (!pDestiny->IsMoving())
717  return PyStatic.NewNone();
718  if (pDestiny->IsWarping()) {
719  call.client->SendNotifyMsg( "You can't do this while warping");
720  return PyStatic.NewNone();
721  } else if (pDestiny->IsFrozen()) {
722  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
723  return PyStatic.NewNone();
724  }
725 
726  call.client->SetUndock(false);
727  call.client->SetAutoPilot(false);
728 
729  pDestiny->Stop();
730 
731  return PyStatic.NewNone();
732 }
733 
734 // CmdTurboDock (in client code)
735 PyResult BeyonceBound::Handle_CmdDock(PyCallArgs &call) {
736  _log(AUTOPILOT__MESSAGE, "%s called Dock. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
737  if (call.client->IsSessionChange()) {
738  call.client->SendNotifyMsg("Session Change currently active.");
739  return PyStatic.NewNone();
740  }
741  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
742  if (pDestiny == nullptr) {
743  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
744  return PyStatic.NewNone();
745  } else if (pDestiny->IsWarping()) {
746  call.client->SendNotifyMsg( "You can't do this while warping");
747  return PyStatic.NewNone();
748  } else if (pDestiny->IsFrozen()) {
749  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
750  return PyStatic.NewNone();
751  }
752  SystemManager* pSystem = call.client->SystemMgr();
753  if (pSystem == nullptr) {
754  codelog(CLIENT__ERROR, "%s: Client has no system manager.", call.client->GetName());
755  return PyStatic.NewNone();
756  }
757  Call_TwoIntegerArgs args; //sends stationID, shipID
758  if (!args.Decode(&call.tuple)) {
759  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
760  return PyStatic.NewNone();
761  }
762 
763  // this sets m_dockStationID for radius checks and other things
764  call.client->SetDockStationID( args.arg1 );
765 
766  /* return error msg from this call, if applicable, else nodeid and timestamp */
767  return pDestiny->AttemptDockOperation();
768 }
769 
770 PyResult BeyonceBound::Handle_CmdStargateJump(PyCallArgs &call) {
771 
772  /* jump system messages....
773 (67187, `{[location]system.name} Traffic Control: your jump-in clearance has expired.`)
774 (67191, `{[location]system.name} Traffic Control: you have been cleared for jump-in within {[timeinterval]expiration.writtenForm, from=second, to=second}.`)
775 (67210, `{[location]system.name} Traffic Control: you are at position {[numeric]pos} in queue for jump-in.`)
776 (258673, `{system} is currently loading. Bizzarre, seeing that you're there already... Please try again in a minute or two.`)
777 (258674, `The stargates in {system} are currently experiencing minor technical difficulties. Please try again in a moment.`)
778 (258675, `Jump Prohibited`)
779 (258676, `Officials have closed the stargates in {system} due to heavy congestion. Travelers are advised to enjoy the local scenery.`)
780 (258677, `{system} Traffic Control is currently experiencing heavy load and is unable to process your request. Please try again in a moment.`)
781 (258678, `{system} Traffic Control is currently offline and unable to process your jump request. Please try again in a moment.`)
782 (258679, `{system} Traffic Control is currently experiencing heavy load and is unable to process your request. You are #{[numeric]position} in queue for jump-in.`)
783 (258680, `Jump Prohibited`)
784 (258681, `Officials have closed the stargates in {system} due to heavy congestion. Travelers are advised to seek alternate routes.`)
785 (258683, `Your character is located within {system}, which is currently loading. Please try again in a moment.`)
786 (258685, `Your character is located within {system}, which is currently experiencing heavy load. Please try again in a moment.`)
787 (258687, `Your character is located within {system}, which has reached maximum capacity. You are #{[numeric]position} in queue for entrance. Please try again in a moment.`)
788 (258689, `Your character is located within {system}, which is currently stuck. Please select a different character or try later.`)
789 (258691, `The character is located within {system}, which is currently loading. Please try again in a moment.`)
790 (258693, `The character is located within {system}, which is currently experiencing heavy load. Please try again in a moment.`)
791 (258695, `The character is located within {system}, which is currently stuck. Please try again later.`)
792 (258699, `The item <b>{example}</b> was not found in the station <b>{[location]station.name}</b>. Please make sure all items are in the correct hangar before finalizing this contract.`)
793 (258701, `{system} Traffic Control is currently experiencing heavy load and was unable to process your request. Please try again in a moment.`)
794 (258704, `You cannot leave {system} yet because of instability in the space-time continuum. Please try again in a moment.`)
795 */
796 
797  _log(AUTOPILOT__MESSAGE, "%s called Jump. AP: %s", call.client->GetName(), (call.client->IsAutoPilot() ? "true" : "false"));
798  if (call.client->IsSessionChange()) {
799  call.client->SendNotifyMsg("Session Change currently active.");
800  return PyStatic.NewNone();
801  }
802  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
803  if (pDestiny == nullptr) {
804  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
805  return PyStatic.NewNone();
806  } else if (pDestiny->IsWarping()) {
807  call.client->SendNotifyMsg( "You can't do this while warping");
808  return PyStatic.NewNone();
809  } else if (pDestiny->IsFrozen()) {
810  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
811  return PyStatic.NewNone();
812  }
813 
814  Call_StargateJump args;
815  if (!args.Decode(&call.tuple)) {
816  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
817  return PyStatic.NewNone();
818  }
819 
821  call.client->StargateJump(args.fromStargateID, args.toStargateID);
822 
823  /* return error msg from this call, if applicable, else nodeid and timestamp */
824  // returns nodeID and timestamp
825  PyTuple* tuple = new PyTuple(2);
826  tuple->SetItem(0, new PyString(GetBindStr())); // node info here
827  tuple->SetItem(1, new PyLong(GetFileTimeNow()));
828  return tuple;
829 }
830 
831 PyResult BeyonceBound::Handle_CmdAbandonLoot(PyCallArgs &call) {
832  /* remotePark.CmdAbandonLoot(wrecks) <- this is pylist from 'abandonAllWrecks'
833  * remotePark.CmdAbandonLoot([wreckID]) <- single itemID in list
834  */
835  sLog.White( "BeyonceBound::Handle_CmdAbandonLoot()", "size= %u", call.tuple->size() );
836  call.Dump(SERVICE__CALL_DUMP);
837 
838  Call_SingleIntList arg;
839  if (!arg.Decode(&call.tuple)) {
840  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
841  return PyStatic.NewNone();
842  }
843 
845  SystemEntity* pSE(nullptr);
846  SystemManager* pSysMgr = call.client->SystemMgr();
847  for (auto cur : arg.ints) {
848  pSE = pSysMgr->GetSE(cur);
849  if (pSE == nullptr)
850  continue;
851  pSE->Abandon();
852  PyTuple* slimData = new PyTuple(2);
853  slimData->SetItem(0, new PyLong(pSE->GetID()));
854  slimData->SetItem(1, new PyObject( "foo.SlimItem", pSE->MakeSlimItem()));
855  PyTuple* itemData = new PyTuple(2);
856  itemData->SetItem(0, new PyString("OnSlimItemChange"));
857  itemData->SetItem(1, slimData);
858  pSE->SysBubble()->BubblecastDestinyUpdate(&itemData, "OnSlimItemChange" );
859  }
860 
861  return PyStatic.NewNone();
862 }
863 
864 PyResult BeyonceBound::Handle_UpdateStateRequest(PyCallArgs &call) {
865  codelog(CLIENT__ERROR, "%s: Client sent UpdateStateRequest. Previous call generated a bad return. Check Logs.", call.client->GetName());
866 
867  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
868  if (pDestiny == nullptr) {
869  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
870  return PyStatic.NewNone();
871  }
872  if (pDestiny->IsWarping()) {
873  call.client->SendNotifyMsg( "You can't do this while warping");
874  return PyStatic.NewNone();
875  }
876 
877  call.client->SetStateSent(false);
878  pDestiny->SendSetState();
879 
880  return PyStatic.NewNone();
881 }
882 
965 PyResult BeyonceBound::Handle_CmdJumpThroughFleet(PyCallArgs &call) {
966  // sm.StartService('sessionMgr').PerformSessionChange('jump', bp.CmdJumpThroughFleet, otherCharID, otherShipID, beaconID, solarsystemID)
967  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdJumpThroughFleet");
968  call.Dump(SHIP__WARNING);
969  return PyStatic.NewNone();
970 }
971 
972 PyResult BeyonceBound::Handle_CmdJumpThroughAlliance(PyCallArgs &call) {
973  //sm.StartService('sessionMgr').PerformSessionChange('jump', bp.CmdJumpThroughAlliance, otherShipID, beaconID, solarsystemID)
974  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdJumpThroughAlliance");
975  call.Dump(SHIP__WARNING);
976  return PyStatic.NewNone();
977 }
978 
979 PyResult BeyonceBound::Handle_CmdJumpThroughCorporationStructure(PyCallArgs &call) {
980  //sm.StartService('sessionMgr').PerformSessionChange('jump', bp.CmdJumpThroughCorporationStructure, itemID, remoteStructureID, remoteSystemID)
981  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdJumpThroughCorporationStructure");
982  call.Dump(SHIP__WARNING);
983 
984  _log(AUTOPILOT__MESSAGE, "%s called bridge jump.", call.client->GetName());
985  if (call.client->IsSessionChange()) {
986  call.client->SendNotifyMsg("Session Change currently active.");
987  return PyStatic.NewNone();
988  }
989 
990  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
991  if (pDestiny == nullptr) {
992  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
993  return PyStatic.NewNone();
994  } else if (pDestiny->IsWarping()) {
995  call.client->SendNotifyMsg( "You can't do this while warping");
996  return PyStatic.NewNone();
997  }
998 
999  Call_BridgeJumpAlliance args;
1000  if (!args.Decode(&call.tuple)) {
1001  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
1002  return PyStatic.NewNone();
1003  }
1004 
1005  InventoryItemRef beacon = sItemFactory.GetInventoryItemFromID(args.remoteStructureID);
1006 
1007  //Check for jump fuel and make sure there is enough fuel available
1008  InventoryItemRef bridge = sItemFactory.GetInventoryItemFromID(args.itemID);
1009  ShipItemRef ship = call.client->GetShip();
1010 
1011  std::vector<InventoryItemRef> fuelBayItems;
1012  std::vector<InventoryItemRef> requiredItems;
1014  uint32 fuelQuantity = 500; // Bridges use static fuel quantity
1015 
1016  bridge->GetMyInventory()->GetItemsByFlag(flagHangar, fuelBayItems);
1017  uint32 quantity = 0;
1018  for (auto cur : fuelBayItems) {
1019  if (cur->type().id() == fuelType) {
1020  quantity += cur->quantity();
1021  requiredItems.push_back(cur);
1022  if (quantity >= fuelQuantity) {
1023  break;
1024  }
1025  }
1026  }
1027  if (quantity < fuelQuantity) {
1028  ship->GetPilot()->SendNotifyMsg("This jump requires %u units of %s in the Jump Bridge fuel hold.", fuelQuantity, sItemFactory.GetType(fuelType)->name().c_str());
1029  return nullptr;
1030  }
1031 
1032  uint32 quantityLeft = fuelQuantity;
1033  for (auto cur : requiredItems) {
1034  if (cur->quantity() >= quantityLeft) {
1035  //If we have all the quantity we need in the current stack, decrement the amount we need and break
1036  cur->AlterQuantity(-quantityLeft, true);
1037  break;
1038  } else {
1039  //If the stack doesn't have the full amount, decrement the quantity from what we need and zero out the stack
1040  quantityLeft -= cur->quantity();
1041  // Delete item after we zero it's quantity
1042  cur->SetQuantity(0, true, true);
1043  }
1044  }
1045  GPoint position = beacon->position();
1046  position.MakeRandomPointOnSphere(2500.0);
1047  call.client->CynoJump(beacon);
1048 
1049  /* return error msg from this call, if applicable, else nodeid and timestamp */
1050  // returns nodeID and timestamp
1051  PyTuple* tuple = new PyTuple(2);
1052  tuple->SetItem(0, new PyString(GetBindStr())); // node info here
1053  tuple->SetItem(1, new PyLong(GetFileTimeNow()));
1054  return tuple;
1055 
1056  return PyStatic.NewNone();
1057 
1058 }
1059 
1060 PyResult BeyonceBound::Handle_CmdBeaconJumpFleet(PyCallArgs &call) {
1061  // sm.StartService('sessionMgr').PerformSessionChange('jump', bp.CmdBeaconJumpFleet, charid, beaconID, solarsystemID)
1062  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdBeaconJumpFleet");
1063  call.Dump(SHIP__WARNING);
1064 
1065  _log(AUTOPILOT__MESSAGE, "%s called beacon jump.", call.client->GetName());
1066  if (call.client->IsSessionChange()) {
1067  call.client->SendNotifyMsg("Session Change currently active.");
1068  return PyStatic.NewNone();
1069  }
1070 
1071  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
1072  if (pDestiny == nullptr) {
1073  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
1074  return PyStatic.NewNone();
1075  } else if (pDestiny->IsWarping()) {
1076  call.client->SendNotifyMsg( "You can't do this while warping");
1077  return PyStatic.NewNone();
1078  } else if (pDestiny->IsFrozen()) {
1079  call.client->SendNotifyMsg( "Your ship is frozen and cannot move");
1080  return PyStatic.NewNone();
1081  }
1082 
1083  Call_BeaconJumpFleet args;
1084  if (!args.Decode(&call.tuple)) {
1085  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
1086  return PyStatic.NewNone();
1087  }
1088 
1089  InventoryItemRef beacon = sItemFactory.GetInventoryItemFromID(args.beaconID);
1090 
1091  //Check for jump fuel and make sure there is enough fuel available
1092  ShipItemRef ship = call.client->GetShip();
1093 
1094  std::vector<InventoryItemRef> fuelBayItems;
1095  std::vector<InventoryItemRef> requiredItems;
1097  uint32 fuelBaseConsumption = uint32(ceil(ship->GetAttribute(AttrJumpDriveConsumptionAmount).get_float()));
1098  uint32 fuelQuantity;
1099 
1100  GPoint startPosition = SystemDB::GetSolarSystemPosition(call.client->GetSystemID());
1101  GPoint endPosition = SystemDB::GetSolarSystemPosition(beacon->locationID());
1102 
1103  GVector heading ( startPosition, endPosition );
1104  double jumpDistance = EvEMath::Units::MetersToLightYears(heading.length());
1105 
1106  int8 jumpFuelConservationLevel = call.client->GetChar()->GetSkillLevel(EvESkill::JumpFuelConservation);
1107  int8 jumpFreightersLevel = call.client->GetChar()->GetSkillLevel(EvESkill::JumpFreighters);
1108 
1109  if (ship->groupID() == EVEDB::invGroups::JumpFreighter) {
1110  fuelQuantity = uint32(ceil(jumpDistance * fuelBaseConsumption * (1 - 0.1 * jumpFuelConservationLevel) * (1 - 0.1 * jumpFreightersLevel)));
1111  } else {
1112  fuelQuantity = uint32(ceil(jumpDistance * fuelBaseConsumption * (1 - 0.1 * jumpFuelConservationLevel)));
1113  }
1114 
1115  ship->GetMyInventory()->GetItemsByFlag(flagFuelBay, fuelBayItems);
1116  uint32 quantity = 0;
1117  for (auto cur : fuelBayItems) {
1118  if (cur->type().id() == fuelType) {
1119  quantity += cur->quantity();
1120  requiredItems.push_back(cur);
1121  if (quantity >= fuelQuantity) {
1122  break;
1123  }
1124  }
1125  }
1126  if (quantity < fuelQuantity) {
1127  ship->GetPilot()->SendNotifyMsg("This jump requires you to have %u units of %s in your fuel bay.", fuelQuantity, sItemFactory.GetType(fuelType)->name().c_str());
1128  return nullptr;
1129  }
1130 
1131  for (auto cur : requiredItems) {
1132  if (cur->quantity() > fuelQuantity) {
1133  //If we have all the quantity we need in the current stack, decrement the amount we need and break
1134  cur->AlterQuantity(-fuelQuantity, true);
1135  break;
1136  } else {
1137  //If the stack doesn't have the full amount delete item
1138  cur->SetQuantity(0, true, true);
1139  }
1140  }
1141 
1142  call.client->CynoJump(beacon);
1143 
1144  /* return error msg from this call, if applicable, else nodeid and timestamp */
1145  // returns nodeID and timestamp
1146  PyTuple* tuple = new PyTuple(2);
1147  tuple->SetItem(0, new PyString(GetBindStr())); // node info here
1148  tuple->SetItem(1, new PyLong(GetFileTimeNow()));
1149  return tuple;
1150 
1151  return PyStatic.NewNone();
1152 }
1153 
1154 PyResult BeyonceBound::Handle_CmdBeaconJumpAlliance(PyCallArgs &call) {
1155  // sm.StartService('sessionMgr').PerformSessionChange('jump', bp.CmdBeaconJumpAlliance, beaconID, solarSystemID)
1156  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdBeaconJumpAlliance");
1157  call.Dump(SHIP__WARNING);
1158 
1159  _log(AUTOPILOT__MESSAGE, "%s called beacon jump.", call.client->GetName());
1160  if (call.client->IsSessionChange()) {
1161  call.client->SendNotifyMsg("Session Change currently active.");
1162  return PyStatic.NewNone();
1163  }
1164 
1165  DestinyManager* pDestiny = call.client->GetShipSE()->DestinyMgr();
1166  if (pDestiny == nullptr) {
1167  codelog(CLIENT__ERROR, "%s: Client has no destiny manager!", call.client->GetName());
1168  return PyStatic.NewNone();
1169  } else if (pDestiny->IsWarping()) {
1170  call.client->SendNotifyMsg( "You can't do this while warping");
1171  return PyStatic.NewNone();
1172  }
1173 
1174  Call_BeaconJumpAlliance args;
1175  if (!args.Decode(&call.tuple)) {
1176  codelog(SERVICE__ERROR, "%s: Failed to decode arguments.", GetName());
1177  return PyStatic.NewNone();
1178  }
1179 
1180  InventoryItemRef beacon = sItemFactory.GetInventoryItemFromID(args.beaconID);
1181 
1182  //Check for jump fuel and make sure there is enough fuel available
1183  ShipItemRef ship = call.client->GetShip();
1184 
1185  std::vector<InventoryItemRef> fuelBayItems;
1186  std::vector<InventoryItemRef> requiredItems;
1188  uint32 fuelBaseConsumption = uint32(ceil(ship->GetAttribute(AttrJumpDriveConsumptionAmount).get_float()));
1189  uint32 fuelQuantity;
1190 
1191  GPoint startPosition = SystemDB::GetSolarSystemPosition(call.client->GetSystemID());
1192  GPoint endPosition = SystemDB::GetSolarSystemPosition(beacon->locationID());
1193 
1194  GVector heading ( startPosition, endPosition );
1195  double jumpDistance = EvEMath::Units::MetersToLightYears(heading.length());
1196 
1197  int8 jumpFuelConservationLevel = call.client->GetChar()->GetSkillLevel(EvESkill::JumpFuelConservation);
1198  int8 jumpFreightersLevel = call.client->GetChar()->GetSkillLevel(EvESkill::JumpFreighters);
1199 
1200  if (ship->groupID() == EVEDB::invGroups::JumpFreighter) {
1201  fuelQuantity = uint32(ceil(jumpDistance * fuelBaseConsumption * (1 - 0.1 * jumpFuelConservationLevel) * (1 - 0.1 * jumpFreightersLevel)));
1202  } else {
1203  fuelQuantity = uint32(ceil(jumpDistance * fuelBaseConsumption * (1 - 0.1 * jumpFuelConservationLevel)));
1204  }
1205 
1206  ship->GetMyInventory()->GetItemsByFlag(flagFuelBay, fuelBayItems);
1207  uint32 quantity = 0;
1208  for (auto cur : fuelBayItems) {
1209  if (cur->type().id() == fuelType) {
1210  quantity += cur->quantity();
1211  requiredItems.push_back(cur);
1212  if (quantity >= fuelQuantity) {
1213  break;
1214  }
1215  }
1216  }
1217  if (quantity < fuelQuantity) {
1218  ship->GetPilot()->SendNotifyMsg("This jump requires you to have %u units of %s in your inventory.", fuelQuantity, sItemFactory.GetType(fuelType)->name().c_str());
1219  return nullptr;
1220  }
1221 
1222  uint32 quantityLeft = fuelQuantity;
1223  for (auto cur : requiredItems) {
1224  if (cur->quantity() >= quantityLeft) {
1225  //If we have all the quantity we need in the current stack, decrement the amount we need and break
1226  cur->AlterQuantity(-quantityLeft, true);
1227  break;
1228  } else {
1229  //If the stack doesn't have the full amount, decrement the quantity from what we need and zero out the stack
1230  quantityLeft -= cur->quantity();
1231  // Delete item after we zero it's quantity
1232  cur->SetQuantity(0, true, true);
1233  }
1234  }
1235  GPoint position = beacon->position();
1236  position.MakeRandomPointOnSphere(2500.0);
1237  call.client->CynoJump(beacon);
1238 
1239  /* return error msg from this call, if applicable, else nodeid and timestamp */
1240  // returns nodeID and timestamp
1241  PyTuple* tuple = new PyTuple(2);
1242  tuple->SetItem(0, new PyString(GetBindStr())); // node info here
1243  tuple->SetItem(1, new PyLong(GetFileTimeNow()));
1244  return tuple;
1245 
1246  return PyStatic.NewNone();
1247 
1248 }
1249 
1250 PyResult BeyonceBound::Handle_CmdFleetRegroup(PyCallArgs &call) {
1251  // not sure what this is supposed to do yet
1252  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdFleetRegroup");
1253  call.Dump(SHIP__WARNING);
1254  return nullptr;
1255 }
1256 
1257 PyResult BeyonceBound::Handle_CmdFleetTagTarget(PyCallArgs &call) {
1258  // bp.CmdFleetTagTarget(itemID, tag)
1259  _log(SHIP__WARNING, "BeyonceBound::Handle_CmdFleetTagTarget");
1260  call.Dump(SHIP__WARNING);
1261  return PyStatic.NewNone();
1262 }
bool IsLogin()
Definition: Client.h:235
Base Python wire object.
Definition: PyRep.h:66
#define sConfig
A macro for easier access to the singleton.
Dispatcher *const m_dispatch
bool IsSessionChange()
Definition: Client.h:241
void UpdateSessionInt(const char *sessionType, int value)
Definition: Client.cpp:1965
SystemEntity * GetSE(uint32 entityID) const
static std::string StringContent(PyRep *pRep)
Definition: PyRep.cpp:103
void SendErrorMsg(const char *fmt,...)
Definition: Client.cpp:2719
uint32 GetSystemID() const
Definition: Client.h:152
itemID[count] Create count or of the specified() x() y(z)-Jump to the specified position in space.Stopped." ) COMMAND( translocate
#define _log(type, fmt,...)
Definition: logsys.h:124
#define stDataMgr
Dispatcher *const m_dispatch
PyRep * GetItem(size_t index) const
Returns Python object.
Definition: PyRep.h:602
Python string.
Definition: PyRep.h:430
PyServiceMgr & services() const
Definition: Client.h:90
double GetRadius()
Definition: SystemEntity.h:208
virtual MoonSE * GetMoonSE()
Definition: SystemEntity.h:102
void SetAutoPilot(bool set=false)
Definition: Client.cpp:669
Dispatcher *const m_dispatch
std::map< std::string, PyRep * > byname
Definition: PyCallable.h:51
size_t size() const
Definition: PyRep.h:591
double min(double x, double y)
Definition: misc.h:95
PyService * LookupService(const std::string &name)
const GPoint & position() const
void GotoDirection(const GPoint &direction)
SystemBubble * SysBubble()
Definition: SystemEntity.h:195
bool IsString() const
Definition: PyRep.h:105
bool IsInvul()
Definition: Client.h:234
bool IsUndock()
Definition: Client.h:236
uint32 GetID() const
Definition: SystemManager.h:80
static uint32 IntegerValueU32(PyRep *pRep)
Definition: PyRep.cpp:134
std::string m_strBoundObjectName
Definition: PyBoundObject.h:54
virtual bool IsMoonSE()
Definition: SystemEntity.h:150
void SendNotifyMsg(const char *fmt,...)
Definition: Client.cpp:2776
virtual bool IsWormholeSE()
Definition: SystemEntity.h:155
CharacterRef GetChar() const
Definition: Client.h:164
Python tuple.
Definition: PyRep.h:567
GaFloat x
Definition: GaTypes.h:207
virtual bool IsPlanetSE()
Definition: SystemEntity.h:149
signed __int8 int8
Definition: eve-compat.h:45
const GPoint & GetPosition() const
Definition: SystemEntity.h:211
Client * pClient
virtual bool IsGateSE()
Definition: SystemEntity.h:148
PyCallable_Make_Dispatcher(BeyonceBound) BeyonceBound(PyServiceMgr *mgr
bool IsSetStateSent()
Definition: Client.h:240
bool LookupBookmark(uint32 bookmarkID, uint32 &itemID, uint16 &typeID, uint32 &locationID, double &x, double &y, double &z)
uint16 groupID() const
signed __int32 int32
Definition: eve-compat.h:49
void _SetCallDispatcher(CallDispatcher *d)
Definition: PyCallable.h:87
PyCallable_DECL_CALL(CmdFollowBall)
GaExpInl GaFloat normalize()
Definition: GaTypes.h:163
* args
uint32 GetItemsByFlag(EVEItemFlags flag, std::vector< InventoryItemRef > &items) const
Definition: Inventory.cpp:458
void CheckBallparkTimer()
Definition: Client.cpp:913
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
void SetUndock(bool undock=false)
Definition: Client.h:245
virtual PyDict * MakeSlimItem()
Definition: gpoint.h:33
StructureSE * GetMyTower()
Definition: Moon.h:45
virtual bool IsCOSE()
Definition: SystemEntity.h:164
DestinyManager * DestinyMgr()
Definition: SystemEntity.h:198
void SetInvul(bool invul=false)
Definition: Client.h:244
Python object.
Definition: PyRep.h:826
virtual bool IsStationSE()
Definition: SystemEntity.h:151
AnomalyMgr * GetAnomMgr()
double MetersToLightYears(double meters)
Definition: EvEMath.cpp:12
virtual ~BeyonceService()
#define codelog(type, fmt,...)
Definition: logsys.h:128
void SetItem(size_t index, PyRep *object)
Stores Python object.
Definition: PyRep.h:610
SystemManager * SystemMgr() const
Definition: Client.h:92
static const GPoint NULL_ORIGIN(0, 0, 0)
void AlignTo(SystemEntity *pSE)
uint32 get_uint32()
Definition: EvilNumber.cpp:173
std::string GetBindStr() const
uint32 GetAnomalyID(std::string &sigID)
Definition: AnomalyMgr.cpp:403
uint32 locationID() const
virtual ~BeyonceBound()
void SetSpeedFraction(float fraction=1.0f, bool startMovement=false)
uint32 GetID()
Definition: SystemEntity.h:207
PyServiceMgr *const m_manager
Definition: PyService.h:91
#define PyStatic
Definition: PyRep.h:1209
static GPoint GetSolarSystemPosition(uint32 systemID)
Definition: SystemDB.cpp:89
ShipItemRef GetShip() const
Definition: Client.h:167
const char * GetName() const
Definition: Client.h:94
void SetStateSent(bool set=false)
Definition: Client.h:249
void SetBallPark()
Definition: Client.cpp:887
Client *const client
Definition: PyCallable.h:49
Python object "ccp_exceptions.UserError".
Definition: PyExceptions.h:121
#define PyCallable_REG_CALL(c, m)
Definition: PyServiceCD.h:78
Definition: Client.h:66
void SetDockStationID(uint32 stationID)
Definition: Client.h:223
itemID[count] Create count or of the specified() x() entityID Translocate to the specified entity Immediately stops ship
unsigned __int32 uint32
Definition: eve-compat.h:50
bool IsAutoPilot()
Definition: Client.h:256
void Follow(SystemEntity *pSE, uint32 distance)
virtual PyBoundObject * CreateBoundObject(Client *pClient, const PyRep *bind_args)
Definition: PyService.cpp:169
bool HasTower()
Definition: Moon.h:46
void GotoPoint(const GPoint &point)
double GetFileTimeNow()
Definition: utils_time.cpp:84
void WarpTo(const GPoint &where, int32 distance=0, bool autoPilot=false, SystemEntity *pSE=nullptr)
const char * GetName() const
Definition: SystemManager.h:84
ShipSE * GetShipSE()
Definition: Client.h:168
int64 max(int64 x, int64 y=0)
Definition: misc.h:103
void StargateJump(uint32 fromGate, uint32 toGate)
Definition: Client.cpp:1410
virtual Client * GetPilot()
Definition: Ship.h:72
void Orbit(SystemEntity *pSE, uint32 distance=0)
EvilNumber GetAttribute(const uint16 attrID) const
typeID Spawn an NPC with the specified type text Search for items matching the specified query() type()() itemID() copy() materialLevel()() itemID(attributeID)-Retrieves attribute value." ) COMMAND( setattr
void Dump(LogType type) const
Definition: PyCallable.cpp:81
PyCallable_Make_InnerDispatcher(BeyonceService) BeyonceService
int8 GetSkillLevel(uint16 skillTypeID, bool zeroForNotInjected=true) const
Definition: Character.cpp:575
virtual void Release()
#define sItemFactory
Definition: ItemFactory.h:165
void BubblecastDestinyUpdate(std::vector< PyTuple * > &updates, const char *desc) const
float get_float()
Definition: EvilNumber.cpp:184
Definition: gpoint.h:70
static int64 IntegerValue(PyRep *pRep)
Definition: PyRep.cpp:118
void MakeRandomPointOnSphere(double radius)
Definition: gpoint.h:46
PyResult AttemptDockOperation()
void SetBeyonce(bool beyonce=false)
Definition: Client.h:246
Inventory * GetMyInventory()
Definition: InventoryItem.h:91
unsigned __int16 uint16
Definition: eve-compat.h:48
virtual void Abandon()
void CynoJump(InventoryItemRef beacon)
Definition: Client.cpp:1454
const char * GetName() const
Definition: PyBoundObject.h:44
Python long integer.
Definition: PyRep.h:261
PyTuple * tuple
Definition: PyCallable.h:50
bool IsWString() const
Definition: PyRep.h:106
static const float BUBBLE_RADIUS_METERS
Definition: BubbleManager.h:32