1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2
3 /* heavily based on CobInstance.h */
4
5 #ifndef UNIT_SCRIPT_H
6 #define UNIT_SCRIPT_H
7
8 #include <string>
9 #include <vector>
10 #include <list>
11
12 #include "System/Object.h"
13 #include "Rendering/Models/3DModel.h"
14
15
16 class CUnit;
17 class CPlasmaRepulser;
18
19
20 class CUnitScript : public CObject
21 {
22 public:
23 enum AnimType {ANone = -1, ATurn = 0, ASpin = 1, AMove = 2};
24
25 struct IAnimListener {
~IAnimListenerIAnimListener26 virtual ~IAnimListener() {}
27 virtual void AnimFinished(AnimType type, int piece, int axis) = 0;
28 };
29
30 public:
31 static const int UNIT_VAR_COUNT = 8;
32 static const int TEAM_VAR_COUNT = 64;
33 static const int ALLY_VAR_COUNT = 64;
34 static const int GLOBAL_VAR_COUNT = 4096;
35
36 static const int UNIT_VAR_START = 1024;
37 static const int TEAM_VAR_START = 2048;
38 static const int ALLY_VAR_START = 3072;
39 static const int GLOBAL_VAR_START = 4096;
40
41 static const int UNIT_VAR_END = UNIT_VAR_START + UNIT_VAR_COUNT - 1;
42 static const int TEAM_VAR_END = TEAM_VAR_START + TEAM_VAR_COUNT - 1;
43 static const int ALLY_VAR_END = ALLY_VAR_START + ALLY_VAR_COUNT - 1;
44 static const int GLOBAL_VAR_END = GLOBAL_VAR_START + GLOBAL_VAR_COUNT - 1;
45
46 static void InitVars(int numTeams, int numAllyTeams);
47
48 public:
GetTeamVars(int team)49 static const int* GetTeamVars(int team) { return &teamVars[team][0]; }
GetAllyVars(int ally)50 static const int* GetAllyVars(int ally) { return &allyVars[ally][0]; }
GetGlobalVars()51 static const int* GetGlobalVars() { return globalVars; }
52
GetUnitVars()53 const int* GetUnitVars() const { return unitVars; }
54 protected:
55 static std::vector< std::vector<int> > teamVars;
56 static std::vector< std::vector<int> > allyVars;
57 static int globalVars[GLOBAL_VAR_COUNT];
58
59 int unitVars[UNIT_VAR_COUNT];
60
61 protected:
62 CUnit* unit;
63 bool yardOpen;
64 bool busy;
65
66 struct AnimInfo {
67 AnimType type;
68 int axis;
69 int piece;
70 float speed;
71 float dest; // means final position when turning or moving, final speed when spinning
72 float accel; // used for spinning, can be negative
73 bool done;
74 std::list<IAnimListener*> listeners;
75 };
76
77 std::list<AnimInfo*> anims[AMove + 1];
78
79 bool hasSetSFXOccupy;
80 bool hasRockUnit;
81 bool hasStartBuilding;
82
83 void UnblockAll(AnimInfo* anim);
84
85 bool MoveToward(float& cur, float dest, float speed);
86 bool TurnToward(float& cur, float dest, float speed);
87 bool DoSpin(float& cur, float dest, float& speed, float accel, int divisor);
88
89 std::list<AnimInfo*>::iterator FindAnim(AnimType anim, int piece, int axis);
90 void RemoveAnim(AnimType type, const std::list<AnimInfo*>::iterator& animInfoIt);
91 void AddAnim(AnimType type, int piece, int axis, float speed, float dest, float accel);
92
93 virtual void ShowScriptError(const std::string& msg) = 0;
94
95 public:
96 // subclass is responsible for populating this with script pieces
97 const std::vector<LocalModelPiece*>& pieces;
98
PieceExists(unsigned int scriptPieceNum)99 bool PieceExists(unsigned int scriptPieceNum) const {
100 // NOTE: there can be NULL pieces present from the remapping in CobInstance
101 return ((scriptPieceNum < pieces.size()) && (pieces[scriptPieceNum] != NULL));
102 }
103
GetScriptLocalModelPiece(unsigned int scriptPieceNum)104 LocalModelPiece* GetScriptLocalModelPiece(unsigned int scriptPieceNum) const {
105 assert(PieceExists(scriptPieceNum));
106 return pieces[scriptPieceNum];
107 }
108
109 int ScriptToModel(int scriptPieceNum) const;
110 int ModelToScript(int lmodelPieceNum) const;
111
112 #define SCRIPT_TO_LOCALPIECE_FUNC(x, y, z, w) \
113 x y(int scriptPieceNum) const { \
114 if (!PieceExists(scriptPieceNum)) \
115 return w; \
116 LocalModelPiece* p = GetScriptLocalModelPiece(scriptPieceNum); \
117 return (p->z()); \
118 }
119
120 SCRIPT_TO_LOCALPIECE_FUNC(float3, GetPiecePos, GetAbsolutePos, float3(0.0f,0.0f,0.0f))
SCRIPT_TO_LOCALPIECE_FUNC(CMatrix44f,GetPieceMatrix,GetModelSpaceMatrix,CMatrix44f ())121 SCRIPT_TO_LOCALPIECE_FUNC(CMatrix44f, GetPieceMatrix, GetModelSpaceMatrix, CMatrix44f())
122 SCRIPT_TO_LOCALPIECE_FUNC(float3, GetPieceDirection, GetDirection, float3(1.0f,1.0f,1.0f))
123
124 bool GetEmitDirPos(int scriptPieceNum, float3& pos, float3& dir) const {
125 if (!PieceExists(scriptPieceNum))
126 return true;
127
128 LocalModelPiece* p = GetScriptLocalModelPiece(scriptPieceNum);
129 return (p->GetEmitDirPos(pos, dir));
130 }
131
132 public:
133 CUnitScript(CUnit* unit, const std::vector<LocalModelPiece*>& pieces);
134 virtual ~CUnitScript();
135
IsBusy()136 bool IsBusy() const { return busy; }
137
GetUnit()138 CUnit* GetUnit() { return unit; }
GetUnit()139 const CUnit* GetUnit() const { return unit; }
140
141 bool Tick(int deltaTime);
142 void TickAnims(int deltaTime, AnimType type, std::list< std::list<AnimInfo*>::iterator >& doneAnims);
143
144 // animation, used by CCobThread
145 void Spin(int piece, int axis, float speed, float accel);
146 void StopSpin(int piece, int axis, float decel);
147 void Turn(int piece, int axis, float speed, float destination);
148 void Move(int piece, int axis, float speed, float destination);
149 void MoveNow(int piece, int axis, float destination);
150 void TurnNow(int piece, int axis, float destination);
151
152 bool AddAnimListener(AnimType type, int piece, int axis, IAnimListener* listener);
153
154 // misc, used by CCobThread and callouts for Lua unitscripts
155 void SetVisibility(int piece, bool visible);
156 void EmitSfx(int type, int piece);
157 void AttachUnit(int piece, int unit);
158 void DropUnit(int unit);
159 void Explode(int piece, int flags);
160 void Shatter(int piece, const float3& pos, const float3& speed);
161 void ShowFlare(int piece);
162 int GetUnitVal(int val, int p1, int p2, int p3, int p4);
163 void SetUnitVal(int val, int param);
164
IsInAnimation(AnimType type,int piece,int axis)165 bool IsInAnimation(AnimType type, int piece, int axis) {
166 return (FindAnim(type, piece, axis) != anims[type].end());
167 }
HaveAnimations()168 bool HaveAnimations() const {
169 return (!anims[ATurn].empty() || !anims[ASpin].empty() || !anims[AMove].empty());
170 }
171 inline bool HaveListeners() const;
172
173 // checks for callin existence
HasSetSFXOccupy()174 bool HasSetSFXOccupy () const { return hasSetSFXOccupy; }
HasRockUnit()175 bool HasRockUnit () const { return hasRockUnit; }
HasStartBuilding()176 bool HasStartBuilding() const { return hasStartBuilding; }
HasBlockShot(int weaponNum)177 virtual bool HasBlockShot (int weaponNum) const { return false; }
HasTargetWeight(int weaponNum)178 virtual bool HasTargetWeight(int weaponNum) const { return false; }
179
180 // callins, called throughout sim
181 virtual void RawCall(int functionId) = 0;
182 virtual void Create() = 0;
183 // Killed must cause unit->deathScriptFinished and unit->delayedWreckLevel to be set!
184 virtual void Killed() = 0;
185 virtual void WindChanged(float heading, float speed) = 0;
186 virtual void ExtractionRateChanged(float speed) = 0;
187 virtual void RockUnit(const float3& rockDir) = 0;
188 virtual void HitByWeapon(const float3& hitDir, int weaponDefId, float& inout_damage) = 0;
189 virtual void SetSFXOccupy(int curTerrainType) = 0;
190 // doubles as QueryLandingPadCount and QueryLandingPad
191 // in COB, the first one determines the number of arguments to the second one
192 // in Lua, we can just count the number of return values
193 virtual void QueryLandingPads(std::vector<int>& out_pieces) = 0;
194 virtual void BeginTransport(const CUnit* unit) = 0;
195 virtual int QueryTransport(const CUnit* unit) = 0; // returns piece
196 virtual void TransportPickup(const CUnit* unit) = 0;
197 virtual void TransportDrop(const CUnit* unit, const float3& pos) = 0;
198 virtual void StartBuilding(float heading, float pitch) = 0;
199 virtual int QueryNanoPiece() = 0; // returns piece
200 virtual int QueryBuildInfo() = 0; // returns piece
201
202 virtual void Destroy() = 0;
203 virtual void StartMoving(bool reversing) = 0;
204 virtual void StopMoving() = 0;
205 virtual void StartUnload() = 0;
206 virtual void EndTransport() = 0;
207 virtual void StartBuilding() = 0;
208 virtual void StopBuilding() = 0;
209 virtual void Falling() = 0;
210 virtual void Landed() = 0;
211 virtual void Activate() = 0;
212 virtual void Deactivate() = 0;
213 virtual void MoveRate(int curRate) = 0;
214 virtual void FireWeapon(int weaponNum) = 0;
215 virtual void EndBurst(int weaponNum) = 0;
216
217 // weapon callins
218 virtual int QueryWeapon(int weaponNum) = 0; // returns piece, former QueryPrimary
219 virtual void AimWeapon(int weaponNum, float heading, float pitch) = 0;
220 virtual void AimShieldWeapon(CPlasmaRepulser* weapon) = 0;
221 virtual int AimFromWeapon(int weaponNum) = 0; // returns piece, former AimFromPrimary
222 virtual void Shot(int weaponNum) = 0;
223 virtual bool BlockShot(int weaponNum, const CUnit* targetUnit, bool userTarget) = 0; // returns whether shot should be blocked
224 virtual float TargetWeight(int weaponNum, const CUnit* targetUnit) = 0; // returns target weight
225 };
226
HaveListeners()227 inline bool CUnitScript::HaveListeners() const {
228 for (int animType = ATurn; animType <= AMove; animType++) {
229 for (std::list<AnimInfo *>::const_iterator i = anims[animType].begin(); i != anims[animType].end(); ++i) {
230 if (!(*i)->listeners.empty()) {
231 return true;
232 }
233 }
234 }
235 return false;
236 }
237
238 #endif // UNIT_SCRIPT_H
239