1 // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4 #include "EnumStrings.h"
5 #include "Frame.h"
6 #include "Pi.h"
7 #include "Planet.h"
8 #include "Player.h"
9 #include "Ship.h"
10 #include "ShipAICmd.h"
11 #include "Space.h"
12 #include "SpaceStation.h"
13 #include "libs.h"
14 #include "lua/LuaConstants.h"
15 #include "lua/LuaEvent.h"
16 #include "perlin.h"
17 #include "ship/Propulsion.h"
18
19 // returns true if command is complete
AITimeStep(float timeStep)20 bool Ship::AITimeStep(float timeStep)
21 {
22 PROFILE_SCOPED()
23 // allow the launch thruster thing to happen
24 if (m_launchLockTimeout > 0.0) return false;
25
26 m_decelerating = false;
27 if (!m_curAICmd) {
28 if (this == Pi::player) return true;
29
30 // just in case the AI left it on
31 ClearThrusterState();
32 for (int i = 0; i < Guns::GUNMOUNT_MAX; i++)
33 SetGunState(i, 0);
34 return true;
35 }
36
37 if (m_curAICmd->TimeStepUpdate()) {
38 AIClearInstructions();
39 // ClearThrusterState(); // otherwise it does one timestep at 10k and gravity is fatal
40 LuaEvent::Queue("onAICompleted", this, EnumStrings::GetString("ShipAIError", AIMessage()));
41 return true;
42 } else
43 return false;
44 }
45
AIClearInstructions()46 void Ship::AIClearInstructions()
47 {
48 if (!m_curAICmd) return;
49
50 delete m_curAICmd; // rely on destructor to kill children
51 m_curAICmd = 0;
52 m_decelerating = false; // don't adjust unless AI is running
53 }
54
AIGetStatusText(char * str)55 void Ship::AIGetStatusText(char *str)
56 {
57 if (!m_curAICmd)
58 strcpy(str, "AI inactive");
59 else
60 m_curAICmd->GetStatusText(str);
61 }
62
AIKamikaze(Body * target)63 void Ship::AIKamikaze(Body *target)
64 {
65 AIClearInstructions();
66 m_curAICmd = new AICmdKamikaze(this, target);
67 }
68
AIKill(Ship * target)69 void Ship::AIKill(Ship *target)
70 {
71 AIClearInstructions();
72 SetFuelReserve((GetFuel() < 0.5) ? GetFuel() / 2 : 0.25);
73
74 m_curAICmd = new AICmdKill(this, target);
75 }
76
77 /*
78 void Ship::AIJourney(SystemBodyPath &dest)
79 {
80 AIClearInstructions();
81 // m_curAICmd = new AICmdJourney(this, dest);
82 }
83 */
84
AIFlyTo(Body * target)85 void Ship::AIFlyTo(Body *target)
86 {
87 AIClearInstructions();
88 SetFuelReserve((GetFuel() < 0.5) ? GetFuel() / 2 : 0.25);
89
90 if (target->IsType(ObjectType::SHIP)) { // test code
91 vector3d posoff(-1000.0, 0.0, 1000.0);
92 m_curAICmd = new AICmdFormation(this, static_cast<Ship *>(target), posoff);
93 } else
94 m_curAICmd = new AICmdFlyTo(this, target);
95 }
96
AIDock(SpaceStation * target)97 void Ship::AIDock(SpaceStation *target)
98 {
99 AIClearInstructions();
100 SetFuelReserve((GetFuel() < 0.5) ? GetFuel() / 2 : 0.25);
101
102 m_curAICmd = new AICmdDock(this, target);
103 }
104
AIOrbit(Body * target,double alt)105 void Ship::AIOrbit(Body *target, double alt)
106 {
107 AIClearInstructions();
108 SetFuelReserve((GetFuel() < 0.5) ? GetFuel() / 2 : 0.25);
109
110 m_curAICmd = new AICmdFlyAround(this, target, alt);
111 }
112
AIHoldPosition()113 void Ship::AIHoldPosition()
114 {
115 AIClearInstructions();
116 m_curAICmd = new AICmdHoldPosition(this);
117 }
118