1 #include "spring_api.h"
2 #include "AI/Wrappers/Cpp/src-generated/WrappResource.h"
3 #include "AI/Wrappers/Cpp/src-generated/WrappWeaponMount.h"
4 #include "ExternalAI/Interface/AISCommands.h" // for UNIT_COMMAND_BUILD_NO_FACING
5 #include <vector>
6
CSpringUnit(springai::OOAICallback * callback,springai::Unit * u,IGame * game)7 CSpringUnit::CSpringUnit(springai::OOAICallback* callback, springai::Unit* u, IGame* game)
8 : callback(callback), unit(u), dead(false), game(game) {
9 if(u == 0){
10 throw std::runtime_error("springai::unit must never be null when passed into the constructor of a CSpringUnit object! Bad bad coder");
11 }
12 def = u->GetDef();
13 if(def) {
14 buildoptions = def->GetBuildOptions();
15 } else {
16 game->SendToConsole("shard-runtime warning: UnitDef was NULL in CSpringUnit.");
17 }
18 }
19
~CSpringUnit()20 CSpringUnit::~CSpringUnit(){
21 delete unit;
22 unit = NULL;
23 callback = NULL;
24 //
25 delete def;
26 def = NULL;
27 for (int i = 0; i < buildoptions.size(); i += 1) {
28 delete buildoptions[i];
29 }
30 }
31
ID()32 int CSpringUnit::ID(){
33 if (unit==NULL) {
34 return -1;
35 }
36 return unit->GetUnitId();
37 }
38
Team()39 int CSpringUnit::Team(){
40 return unit->GetTeam();
41 }
42
Name()43 std::string CSpringUnit::Name(){
44 if (unit == NULL) {
45 return "";
46 }
47 springai::UnitDef* u = def;
48 if(u == NULL){
49 return "";
50 }
51 return u->GetName();
52 }
53
SetDead(bool dead)54 void CSpringUnit::SetDead(bool dead){
55 this->dead = dead;
56 }
57
IsAlive()58 bool CSpringUnit::IsAlive(){
59 return dead;
60 }
61
IsAlly(int allyTeamId)62 bool CSpringUnit::IsAlly(int allyTeamId) {
63 if (!unit) {
64 game->SendToConsole("shard-runtime warning: Unit was NULL in IsAlly");
65 return false;
66 }
67 return allyTeamId == unit->GetAllyTeam();
68 }
69
IsCloaked()70 bool CSpringUnit::IsCloaked(){
71 if (!unit) {
72 game->SendToConsole("shard-runtime warning: Unit was NULL in IsCloaked");
73 return false;
74 }
75 return this->unit->IsCloaked();
76 }
77
Forget()78 void CSpringUnit::Forget(){
79 return;
80 }
81
Forgotten()82 bool CSpringUnit::Forgotten(){
83 return false;
84 }
85
Type()86 IUnitType* CSpringUnit::Type(){
87 return 0;
88 }
89
90
CanMove()91 bool CSpringUnit::CanMove(){
92 if (def != NULL)
93 return def->IsAbleToMove();
94 game->SendToConsole("shard-runtime warning: UnitDef was NULL in CanMove");
95 return false;
96 }
97
CanDeploy()98 bool CSpringUnit::CanDeploy(){
99 return false;
100 }
101
CanBuild()102 bool CSpringUnit::CanBuild(){
103 if (def != NULL) {
104 return (buildoptions.size() > 0);
105 }
106 game->SendToConsole("shard-runtime warning: UnitDef was NULL in CanBuild");
107 return false;
108 }
109
110
CanAssistBuilding(IUnit * unit)111 bool CSpringUnit::CanAssistBuilding(IUnit* unit){
112 if (def != NULL)
113 return def->IsAbleToAssist();
114 game->SendToConsole("shard-runtime warning: UnitDef was NULL in CanAssistBuilding");
115 return false;
116 }
117
118
CanMoveWhenDeployed()119 bool CSpringUnit::CanMoveWhenDeployed(){
120 return false;
121 }
122
CanFireWhenDeployed()123 bool CSpringUnit::CanFireWhenDeployed(){
124 return false;
125 }
126
CanBuildWhenDeployed()127 bool CSpringUnit::CanBuildWhenDeployed(){
128 return false;
129 }
130
CanBuildWhenNotDeployed()131 bool CSpringUnit::CanBuildWhenNotDeployed(){
132 return false;
133 }
134
135
136
Wait(int timeout)137 void CSpringUnit::Wait(int timeout){
138 if (!unit) {
139 game->SendToConsole("shard-runtime warning: Unit was NULL in Wait");
140 return;
141 }
142
143 this->unit->Wait(timeout);
144 }
145
Stop()146 void CSpringUnit::Stop(){
147 if (!unit) {
148 game->SendToConsole("shard-runtime warning: Unit was NULL in Stop");
149 return;
150 }
151
152 this->unit->Stop();
153 }
154
Move(Position p)155 void CSpringUnit::Move(Position p){
156 if (!unit) {
157 game->SendToConsole("shard-runtime warning: Unit was NULL in Move");
158 return;
159 }
160
161 const springai::AIFloat3 pos(p.x, p.y, p.z);
162 try {
163 this->unit->MoveTo(pos);
164 } catch (springai::CallbackAIException& e) {
165 game->SendToConsole(std::string("shard-runtime warning: Failed in MoveTo. Reason: ") + std::string(e.what()));
166 }
167 }
168
MoveAndFire(Position p)169 void CSpringUnit::MoveAndFire(Position p){
170 if (!unit) {
171 game->SendToConsole("shard-runtime warning: Unit was NULL in MoveAndFire");
172 return;
173 }
174
175 const springai::AIFloat3 pos(p.x, p.y, p.z);
176 this->unit->Fight(pos);
177 }
178
Build(IUnitType * t)179 bool CSpringUnit::Build(IUnitType* t){
180 if(!unit) {
181 game->SendToConsole("shard-runtime warning: Unit was NULL in Build(IUnitType)");
182 return false;
183 }
184
185 Position p = this->GetPosition();
186 CSpringUnitType* type = static_cast<CSpringUnitType*>(t);
187 springai::UnitDef* ud = type->GetUnitDef();
188 if(ud){
189 if((!ud->IsAbleToMove())&&(ud->GetType() == std::string("factory"))){
190 return Build(t,p);
191 }else{
192 int ms = std::max(ud->GetXSize(),ud->GetZSize());
193 double dsp = 6;
194 double radius = 500;
195 if(ms < 4){
196 radius = 900;
197 dsp = 8;
198 } else if(ms > 8){
199 radius = 900;
200 dsp = 5;
201 } else if (ms > 15){
202 radius = 1800;
203 dsp=3;
204 }
205 if(ud->IsNeedGeo()){
206 radius = 3000;
207 }
208 p = game->Map()->FindClosestBuildSite(t,p,radius,dsp);
209 return Build(t,p);
210 }
211 } else{
212 return false;
213 }
214 }
215
Build(std::string typeName)216 bool CSpringUnit::Build(std::string typeName){
217 IUnitType* t = game->GetTypeByName(typeName);
218 if(t){
219 return Build(t);
220 }
221 return false;
222 }
223
Build(std::string typeName,Position p)224 bool CSpringUnit::Build(std::string typeName, Position p){
225 IUnitType* t = game->GetTypeByName(typeName);
226 return Build(t,p,UNIT_COMMAND_BUILD_NO_FACING);
227 }
228
Build(IUnitType * t,Position p)229 bool CSpringUnit::Build(IUnitType* t, Position p){
230 return Build(t,p,UNIT_COMMAND_BUILD_NO_FACING);
231 }
232
Build(std::string typeName,Position p,int facing)233 bool CSpringUnit::Build(std::string typeName, Position p, int facing){
234 IUnitType* t = game->GetTypeByName(typeName);
235 return Build(t,p,facing);
236 }
237
Build(IUnitType * t,Position p,int facing)238 bool CSpringUnit::Build(IUnitType* t, Position p, int facing){
239 if(!unit) {
240 game->SendToConsole("shard-runtime warning: Unit was NULL in Build(IUnitType, Position, int)");
241 return false;
242 }
243 if(t){
244 CSpringUnitType* st = static_cast<CSpringUnitType*>(t);
245 springai::UnitDef* ud = st->GetUnitDef();
246 const springai::AIFloat3 pos(p.x, p.y, p.z);
247
248 if(this->game->Map()->CanBuildHereFacing(t,p,facing)){
249 try {
250 this->unit->Build(ud, pos, facing, 0, 10000);
251 } catch(...){
252 return false;
253 }
254 return true;
255 } else {
256 return false;
257 }
258 } else {
259 return false;
260 }
261 }
262
Reclaim(IMapFeature * mapFeature)263 bool CSpringUnit::Reclaim(IMapFeature* mapFeature){
264 if(!unit) {
265 game->SendToConsole("shard-runtime warning: Unit was NULL in Reclaim(IMapFeature)");
266 return false;
267 }
268 springai::Feature* f = static_cast<CSpringMapFeature*>(mapFeature)->feature;
269 this->unit->ReclaimFeature(f);
270 return true;
271 }
272
AreaReclaim(Position p,double radius)273 bool CSpringUnit::AreaReclaim(Position p, double radius){
274 if(!unit) {
275 game->SendToConsole("shard-runtime warning: Unit was NULL in AreaReclaim");
276 return false;
277 }
278 const springai::AIFloat3 pos(p.x, p.y, p.z);
279 this->unit->ReclaimInArea(pos, radius);
280 return true;
281 }
282
Reclaim(IUnit * unit)283 bool CSpringUnit::Reclaim(IUnit* unit){
284 if(!unit) {
285 game->SendToConsole("shard-runtime warning: Unit was NULL in Reclaim");
286 return false;
287 }
288 springai::Unit* u = static_cast<CSpringUnit*>(unit)->unit;
289 this->unit->ReclaimUnit(u);
290 return true;
291 }
292
Attack(IUnit * unit)293 bool CSpringUnit::Attack(IUnit* unit){
294 if(!unit) {
295 game->SendToConsole("shard-runtime warning: Unit was NULL in Attack");
296 return false;
297 }
298 springai::Unit* u = static_cast<CSpringUnit*>(unit)->unit;
299 this->unit->Attack(u);
300 return true;
301 }
302
Repair(IUnit * unit)303 bool CSpringUnit::Repair(IUnit* unit){
304 if(!unit) {
305 game->SendToConsole("shard-runtime warning: Unit was NULL in Repair");
306 return false;
307 }
308 springai::Unit* u = static_cast<CSpringUnit*>(unit)->unit;
309 this->unit->Repair(u);
310 return true;
311 }
312 /*
313 [23:19:39] <[RoX]knorke> who/whatever wants to use the custom commands (morph,jump,...) must know the numbers
314 [23:20:14] <[RoX]knorke> http://code.google.com/p/conflictterra/source/browse/games/CT/LuaRules/Gadgets/unit_morph.lua
315 [23:20:20] <[RoX]knorke> local CMD_MORPH_STOP = 32210
316 [23:20:21] <[RoX]knorke> local CMD_MORPH = 31210
317 [23:20:47] <[RoX]knorke> http://code.google.com/p/conflictterra/source/browse/games/CT/LuaRules/Gadgets/Jumpjets_lua.lua
318 [23:20:55] <[RoX]knorke> local CMD_JUMP = 38521
319 */
MorphInto(IUnitType * t)320 bool CSpringUnit::MorphInto(IUnitType* t){
321 if(!unit) {
322 game->SendToConsole("shard-runtime warning: Unit was NULL in MorphInto");
323 return false;
324 }
325 std::vector<float> params_list;
326 unit->ExecuteCustomCommand(31210, params_list);
327 return true;
328 }
329
GetPosition()330 Position CSpringUnit::GetPosition(){
331 Position p;
332 if(!unit) {
333 game->SendToConsole("shard-runtime warning: Unit was NULL in GetPosition");
334 return p;
335 }
336 const springai::AIFloat3 pos = unit->GetPos();
337 p.x = pos.x;
338 p.y = pos.y;
339 p.z = pos.z;
340 return p;
341 }
342
343
IsBeingBuilt()344 bool CSpringUnit::IsBeingBuilt(){
345 if(!unit) {
346 game->SendToConsole("shard-runtime warning: Unit was NULL in IsBeingBuilt");
347 return false;
348 }
349 return unit->IsBeingBuilt();
350 }
351
GetHealth()352 float CSpringUnit::GetHealth(){
353 if(!unit) {
354 game->SendToConsole("shard-runtime warning: Unit was NULL in GetHealth");
355 return 0.0f;
356 }
357 return unit->GetHealth();
358 }
359
GetMaxHealth()360 float CSpringUnit::GetMaxHealth(){
361 if(!unit) {
362 game->SendToConsole("shard-runtime warning: Unit was NULL in GetMaxHealth");
363 return 0.0f;
364 }
365 return unit->GetMaxHealth();
366 }
367
WeaponCount()368 int CSpringUnit::WeaponCount(){
369 if (def != NULL) {
370 std::vector<springai::WeaponMount*> wm = def->GetWeaponMounts();
371 int n = wm.size();
372 for (int i = 0; i < wm.size(); i += 1) {
373 delete wm[i];
374 }
375 return n;
376 }
377 return 0;
378 }
379
MaxWeaponsRange()380 float CSpringUnit::MaxWeaponsRange(){
381 if(!unit) {
382 game->SendToConsole("shard-runtime warning: Unit was NULL in MaxWeaponsRange");
383 return 0.0f;
384 }
385 return unit->GetMaxRange();
386 }
387
CanBuild(IUnitType * t)388 bool CSpringUnit::CanBuild(IUnitType* t){
389 if(t == 0){
390 return false;
391 }
392 if(unit == 0){
393 game->SendToConsole("shard-runtime warning: Unit was NULL in CanBuild");
394 return false;
395 }
396 if(def == 0){
397 return false;
398 }
399 std::vector<springai::UnitDef*> options = buildoptions;
400 if(!options.empty()){
401 //
402 std::vector<springai::UnitDef*>::iterator i = options.begin();
403 for(;i != options.end();++i){
404 springai::UnitDef* u = *i;
405 if( u->GetName() == t->Name()){
406 return true;
407 }
408 }
409
410 }
411 return false;
412 }
413
GetResourceUsage(int idx)414 SResourceTransfer CSpringUnit::GetResourceUsage(int idx){
415 springai::Resource* r = springai::WrappResource::GetInstance(callback->GetSkirmishAIId(), idx);
416 SResourceTransfer rt;
417 rt.consumption = this->unit->GetResourceUse(r);
418 rt.generation = this->unit->GetResourceMake(r);
419 rt.rate = 1;
420 rt.resource = game->GetResource(idx);
421 rt.gameframe = game->Frame();
422 return rt;
423 }
424
425
ExecuteCustomCommand(int cmdId,std::vector<float> params_list,short options=0,int timeOut=INT_MAX)426 void CSpringUnit::ExecuteCustomCommand(int cmdId, std::vector<float> params_list, short options = 0, int timeOut = INT_MAX){
427 if (!unit) {
428 game->SendToConsole("shard-runtime warning: Unit was NULL in ExecuteCustomCommand");
429 return;
430 }
431 try {
432 this->unit->ExecuteCustomCommand(cmdId,params_list,options,timeOut);
433 } catch (springai::CallbackAIException& e) {
434 game->SendToConsole(std::string("shard-runtime warning: Failed to executeCustomCommand. Reason: ") + std::string(e.what()));
435 }
436 }
437