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