1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 #include "AIAICallback.h"
4 
5 #include "ExternalAI/Interface/SSkirmishAICallback.h"
6 #include "ExternalAI/Interface/AISCommands.h"
7 
8 // these are all copies from the engine, so we do not have to adjust
9 // to each minor change done there
10 #include "MoveData.h"
11 #include "UnitDef.h"
12 #include "WeaponDef.h"
13 #include "FeatureDef.h"
14 #include "Command.h"
15 #include "CommandQueue.h"
16 
17 #include <string>
18 #include <string.h>
19 #include <cassert>
20 
21 
fillWithNULL(void ** arr,int size)22 static inline void fillWithNULL(void** arr, int size) {
23 	for (int i=0; i < size; ++i) {
24 		arr[i] = NULL;
25 	}
26 }
fillWithMinusOne(int * arr,int size)27 static inline void fillWithMinusOne(int* arr, int size) {
28 	for (int i=0; i < size; ++i) {
29 		arr[i] = -1;
30 	}
31 }
32 
33 static int resIndMetal = -1;
34 static int resIndEnergy = -1;
getResourceId_Metal(const SSkirmishAICallback * sAICallback,int skirmishAIId)35 static inline int getResourceId_Metal(const SSkirmishAICallback* sAICallback, int skirmishAIId) {
36 
37 	if (resIndMetal == -1) {
38 		resIndMetal = sAICallback->getResourceByName(skirmishAIId, "Metal");
39 	}
40 
41 	return resIndMetal;
42 }
getResourceId_Energy(const SSkirmishAICallback * sAICallback,int skirmishAIId)43 static inline int getResourceId_Energy(const SSkirmishAICallback* sAICallback, int skirmishAIId) {
44 
45 	if (resIndEnergy == -1) {
46 		resIndEnergy = sAICallback->getResourceByName(skirmishAIId, "Energy");
47 	}
48 
49 	return resIndEnergy;
50 }
51 
copyShortToUCharArray(const short * src,unsigned char * const dst,const size_t size)52 static inline void copyShortToUCharArray(const short* src, unsigned char* const dst, const size_t size) {
53 
54 	int i;
55 	for (i = 0; i < size; ++i) {
56 		dst[i] = (unsigned char) src[i];
57 	}
58 }
copyIntToUShortArray(const int * src,unsigned short * const dst,const size_t size)59 static inline void copyIntToUShortArray(const int* src, unsigned short* const dst, const size_t size) {
60 
61 	int i;
62 	for (i = 0; i < size; ++i) {
63 		dst[i] = (unsigned short) src[i];
64 	}
65 }
66 
67 // FIXME: group ID's have no runtime bound
68 const int maxGroups = MAX_UNITS;
69 
70 // FIXME: these are far too generous, but we
71 // don't have easy access to the right values
72 // on the AI side (so better waste memory than
73 // risk SEGVs)
74 static const int numUnitDefs = MAX_UNITS; // unitDefHandler->numUnitDefs;
75 static const int numFeatDefs = MAX_UNITS; // featureHandler->numFeatureDefs;
76 static const int numWeapDefs = MAX_UNITS; // weaponDefHandler->numWeaponDefs;
77 
78 
79 size_t springLegacyAI::CAIAICallback::numClbInstances = 0;
80 float* springLegacyAI::CAIAICallback::heightMap = NULL;
81 float* springLegacyAI::CAIAICallback::cornersHeightMap = NULL;
82 float* springLegacyAI::CAIAICallback::slopeMap = NULL;
83 unsigned short* springLegacyAI::CAIAICallback::losMap = NULL;
84 unsigned short* springLegacyAI::CAIAICallback::radarMap = NULL;
85 unsigned short* springLegacyAI::CAIAICallback::jammerMap = NULL;
86 unsigned char* springLegacyAI::CAIAICallback::metalMap = NULL;
87 
88 
CAIAICallback()89 springLegacyAI::CAIAICallback::CAIAICallback()
90 	: IAICallback(), skirmishAIId(-1), sAICallback(NULL) {
91 	init();
92 }
93 
CAIAICallback(int skirmishAIId,const SSkirmishAICallback * sAICallback)94 springLegacyAI::CAIAICallback::CAIAICallback(int skirmishAIId, const SSkirmishAICallback* sAICallback)
95 	: IAICallback(), skirmishAIId(skirmishAIId), sAICallback(sAICallback) {
96 	init();
97 }
98 
~CAIAICallback()99 springLegacyAI::CAIAICallback::~CAIAICallback() {
100 
101 	numClbInstances--;
102 
103 	for (int i=0; i < numWeapDefs; ++i) {
104 		delete weaponDefs[i];
105 		weaponDefs[i] = NULL;
106 	}
107 	delete[] weaponDefs;
108 	weaponDefs = NULL;
109 	delete[] weaponDefFrames;
110 	weaponDefFrames = NULL;
111 
112 	for (int i=0; i < numUnitDefs; ++i) {
113 		delete unitDefs[i];
114 		unitDefs[i] = NULL;
115 	}
116 	delete[] unitDefs;
117 	unitDefs = NULL;
118 	delete[] unitDefFrames;
119 	unitDefFrames = NULL;
120 
121 	for (int i=0; i < numFeatDefs; ++i) {
122 		delete featureDefs[i];
123 		featureDefs[i] = NULL;
124 	}
125 	delete[] featureDefs;
126 	featureDefs = NULL;
127 	delete[] featureDefFrames;
128 	featureDefFrames = NULL;
129 
130 	for (int i=0; i < maxGroups; ++i) {
131 		delete groupPossibleCommands[i];
132 		groupPossibleCommands[i] = NULL;
133 	}
134 	delete[] groupPossibleCommands;
135 	groupPossibleCommands = NULL;
136 
137 	for (int i=0; i < MAX_UNITS; ++i) {
138 		delete unitPossibleCommands[i];
139 		unitPossibleCommands[i] = NULL;
140 	}
141 	delete[] unitPossibleCommands;
142 	unitPossibleCommands = NULL;
143 
144 	for (int i=0; i < MAX_UNITS; ++i) {
145 		delete unitCurrentCommandQueues[i];
146 		unitCurrentCommandQueues[i] = NULL;
147 	}
148 	delete[] unitCurrentCommandQueues;
149 	unitCurrentCommandQueues = NULL;
150 
151 	if (numClbInstances == 0) {
152 		delete[] heightMap; heightMap = NULL;
153 		delete[] cornersHeightMap; cornersHeightMap = NULL;
154 		delete[] slopeMap; slopeMap = NULL;
155 		delete[] losMap; losMap = NULL;
156 		delete[] radarMap; radarMap = NULL;
157 		delete[] jammerMap; jammerMap = NULL;
158 		delete[] metalMap; metalMap = NULL;
159 	}
160 }
161 
162 
init()163 void springLegacyAI::CAIAICallback::init() {
164 
165 	numClbInstances++;
166 
167 	weaponDefs      = new WeaponDef*[numWeapDefs];
168 	weaponDefFrames = new int[numWeapDefs];
169 	fillWithNULL((void**) weaponDefs, numWeapDefs);
170 	fillWithMinusOne(weaponDefFrames, numWeapDefs);
171 
172 	unitDefs      = new UnitDef*[numUnitDefs];
173 	unitDefFrames = new int[numUnitDefs];
174 	fillWithNULL((void**) unitDefs, numUnitDefs);
175 	fillWithMinusOne(unitDefFrames, numUnitDefs);
176 
177 	featureDefs      = new FeatureDef*[numFeatDefs];
178 	featureDefFrames = new int[numFeatDefs];
179 	fillWithNULL((void**) featureDefs, numFeatDefs);
180 	fillWithMinusOne(featureDefFrames, numFeatDefs);
181 
182 	groupPossibleCommands    = new std::vector<CommandDescription>*[maxGroups];
183 	unitPossibleCommands     = new std::vector<CommandDescription>*[MAX_UNITS];
184 	unitCurrentCommandQueues = new CCommandQueue*[MAX_UNITS];
185 	fillWithNULL((void**) groupPossibleCommands,    maxGroups);
186 	fillWithNULL((void**) unitPossibleCommands,     MAX_UNITS);
187 	fillWithNULL((void**) unitCurrentCommandQueues, MAX_UNITS);
188 }
189 
190 
PosInCamera(float3 pos,float radius)191 bool springLegacyAI::CAIAICallback::PosInCamera(float3 pos, float radius) {
192 
193 	float pos_param[3];
194 	pos.copyInto(pos_param);
195 
196 	return sAICallback->Map_isPosInCamera(skirmishAIId, pos_param, radius);
197 }
198 
GetCurrentFrame()199 int springLegacyAI::CAIAICallback::GetCurrentFrame() {
200 	return sAICallback->Game_getCurrentFrame(skirmishAIId);
201 }
202 
GetMySkirmishAIId()203 int springLegacyAI::CAIAICallback::GetMySkirmishAIId() {
204 	return skirmishAIId;
205 }
206 
GetMyTeam()207 int springLegacyAI::CAIAICallback::GetMyTeam() {
208 	return sAICallback->Game_getMyTeam(skirmishAIId);
209 }
210 
GetMyAllyTeam()211 int springLegacyAI::CAIAICallback::GetMyAllyTeam() {
212 	return sAICallback->Game_getMyAllyTeam(skirmishAIId);
213 }
214 
GetPlayerTeam(int player)215 int springLegacyAI::CAIAICallback::GetPlayerTeam(int player) {
216 	return sAICallback->Game_getPlayerTeam(skirmishAIId, player);
217 }
218 
GetTeams()219 int springLegacyAI::CAIAICallback::GetTeams() {
220 	return sAICallback->Game_getTeams(skirmishAIId);
221 }
222 
GetTeamSide(int otherTeamId)223 const char* springLegacyAI::CAIAICallback::GetTeamSide(int otherTeamId) {
224 	return sAICallback->Game_getTeamSide(skirmishAIId, otherTeamId);
225 }
226 
GetTeamAllyTeam(int otherTeamId)227 int springLegacyAI::CAIAICallback::GetTeamAllyTeam(int otherTeamId) {
228 	return sAICallback->Game_getTeamAllyTeam(skirmishAIId, otherTeamId);
229 }
230 
GetTeamMetalCurrent(int otherTeamId)231 float springLegacyAI::CAIAICallback::GetTeamMetalCurrent(int otherTeamId) {
232 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
233 	return sAICallback->Game_getTeamResourceCurrent(skirmishAIId, otherTeamId, m);
234 }
235 
GetTeamMetalIncome(int otherTeamId)236 float springLegacyAI::CAIAICallback::GetTeamMetalIncome(int otherTeamId) {
237 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
238 	return sAICallback->Game_getTeamResourceIncome(skirmishAIId, otherTeamId, m);
239 }
240 
GetTeamMetalUsage(int otherTeamId)241 float springLegacyAI::CAIAICallback::GetTeamMetalUsage(int otherTeamId) {
242 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
243 	return sAICallback->Game_getTeamResourceUsage(skirmishAIId, otherTeamId, m);
244 }
245 
GetTeamMetalStorage(int otherTeamId)246 float springLegacyAI::CAIAICallback::GetTeamMetalStorage(int otherTeamId) {
247 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
248 	return sAICallback->Game_getTeamResourceStorage(skirmishAIId, otherTeamId, m);
249 }
250 
GetTeamEnergyCurrent(int otherTeamId)251 float springLegacyAI::CAIAICallback::GetTeamEnergyCurrent(int otherTeamId) {
252 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
253 	return sAICallback->Game_getTeamResourceCurrent(skirmishAIId, otherTeamId, e);
254 }
255 
GetTeamEnergyIncome(int otherTeamId)256 float springLegacyAI::CAIAICallback::GetTeamEnergyIncome(int otherTeamId) {
257 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
258 	return sAICallback->Game_getTeamResourceIncome(skirmishAIId, otherTeamId, e);
259 }
260 
GetTeamEnergyUsage(int otherTeamId)261 float springLegacyAI::CAIAICallback::GetTeamEnergyUsage(int otherTeamId) {
262 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
263 	return sAICallback->Game_getTeamResourceUsage(skirmishAIId, otherTeamId, e);
264 }
265 
GetTeamEnergyStorage(int otherTeamId)266 float springLegacyAI::CAIAICallback::GetTeamEnergyStorage(int otherTeamId) {
267 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
268 	return sAICallback->Game_getTeamResourceStorage(skirmishAIId, otherTeamId, e);
269 }
270 
IsAllied(int firstAllyTeamId,int secondAllyTeamId)271 bool springLegacyAI::CAIAICallback::IsAllied(int firstAllyTeamId, int secondAllyTeamId) {
272 	return sAICallback->Game_isAllied(skirmishAIId, firstAllyTeamId, secondAllyTeamId);
273 }
274 
GetUnitGroup(int unitId)275 int springLegacyAI::CAIAICallback::GetUnitGroup(int unitId) {
276 	return sAICallback->Unit_getGroup(skirmishAIId, unitId);
277 }
278 
GetGroupCommands(int groupId)279 const std::vector<springLegacyAI::CommandDescription>* springLegacyAI::CAIAICallback::GetGroupCommands(int groupId) {
280 
281 	int numCmds = sAICallback->Group_getSupportedCommands(skirmishAIId, groupId);
282 
283 	std::vector<CommandDescription>* cmdDescVec = new std::vector<CommandDescription>();
284 	for (int c=0; c < numCmds; c++) {
285 		CommandDescription commandDescription;
286 		commandDescription.id = sAICallback->Group_SupportedCommand_getId(skirmishAIId, groupId, c);
287 		commandDescription.name = sAICallback->Group_SupportedCommand_getName(skirmishAIId, groupId, c);
288 		commandDescription.tooltip = sAICallback->Group_SupportedCommand_getToolTip(skirmishAIId, groupId, c);
289 		commandDescription.showUnique = sAICallback->Group_SupportedCommand_isShowUnique(skirmishAIId, groupId, c);
290 		commandDescription.disabled = sAICallback->Group_SupportedCommand_isDisabled(skirmishAIId, groupId, c);
291 
292 		int numParams = sAICallback->Group_SupportedCommand_getParams(skirmishAIId, groupId, c, NULL, 0);
293 		const char** params = (const char**) calloc(numParams, sizeof(char*));
294 		numParams = sAICallback->Group_SupportedCommand_getParams(skirmishAIId, groupId, c, params, numParams);
295 		for (int p=0; p < numParams; p++) {
296 			commandDescription.params.push_back(params[p]);
297 		}
298 		free(params);
299 		cmdDescVec->push_back(commandDescription);
300 	}
301 
302 	// to prevent memory wholes
303 	if (groupPossibleCommands[groupId] != NULL) {
304 		delete groupPossibleCommands[groupId];
305 	}
306 	groupPossibleCommands[groupId] = cmdDescVec;
307 
308 	return cmdDescVec;
309 }
310 
311 
GetUnitCommands(int unitId)312 const std::vector<springLegacyAI::CommandDescription>* springLegacyAI::CAIAICallback::GetUnitCommands(int unitId) {
313 
314 	int numCmds = sAICallback->Unit_getSupportedCommands(skirmishAIId, unitId);
315 
316 	std::vector<CommandDescription>* cmdDescVec = new std::vector<CommandDescription>();
317 	for (int c=0; c < numCmds; c++) {
318 		CommandDescription commandDescription;
319 		commandDescription.id = sAICallback->Unit_SupportedCommand_getId(skirmishAIId, unitId, c);
320 		commandDescription.name = sAICallback->Unit_SupportedCommand_getName(skirmishAIId, unitId, c);
321 		commandDescription.tooltip = sAICallback->Unit_SupportedCommand_getToolTip(skirmishAIId, unitId, c);
322 		commandDescription.showUnique = sAICallback->Unit_SupportedCommand_isShowUnique(skirmishAIId, unitId, c);
323 		commandDescription.disabled = sAICallback->Unit_SupportedCommand_isDisabled(skirmishAIId, unitId, c);
324 
325 		int numParams = sAICallback->Unit_SupportedCommand_getParams(skirmishAIId, unitId, c, NULL, 0);
326 		const char** params = (const char**) calloc(numParams, sizeof(char*));
327 		numParams = sAICallback->Unit_SupportedCommand_getParams(skirmishAIId, unitId, c, params, numParams);
328 		for (int p=0; p < numParams; p++) {
329 			commandDescription.params.push_back(params[p]);
330 		}
331 		free(params);
332 		cmdDescVec->push_back(commandDescription);
333 	}
334 
335 	// to prevent memory wholes
336 	if (unitPossibleCommands[unitId] != NULL) {
337 		delete unitPossibleCommands[unitId];
338 	}
339 	unitPossibleCommands[unitId] = cmdDescVec;
340 
341 	return cmdDescVec;
342 }
343 
GetCurrentUnitCommands(int unitId)344 const springLegacyAI::CCommandQueue* springLegacyAI::CAIAICallback::GetCurrentUnitCommands(int unitId) {
345 
346 	const int numCmds = sAICallback->Unit_getCurrentCommands(skirmishAIId, unitId);
347 	const int type = sAICallback->Unit_CurrentCommand_getType(skirmishAIId, unitId);
348 
349 	CCommandQueue* cc = new CCommandQueue();
350 	cc->queueType = (CCommandQueue::QueueType) type;
351 	for (int c=0; c < numCmds; c++) {
352 		const int cmd_id            = sAICallback->Unit_CurrentCommand_getId(skirmishAIId, unitId, c);
353 		const unsigned char cmd_opt = sAICallback->Unit_CurrentCommand_getOptions(skirmishAIId, unitId, c);
354 
355 		Command command(cmd_id, cmd_opt);
356 		command.tag     = sAICallback->Unit_CurrentCommand_getTag(skirmishAIId, unitId, c);
357 		command.timeOut = sAICallback->Unit_CurrentCommand_getTimeOut(skirmishAIId, unitId, c);
358 
359 		int numParams = sAICallback->Unit_CurrentCommand_getParams(skirmishAIId, unitId, c, NULL, 0);
360 		float* params = (float*) calloc(numParams, sizeof(float));
361 		numParams = sAICallback->Unit_CurrentCommand_getParams(skirmishAIId, unitId, c, params, numParams);
362 		for (int p=0; p < numParams; p++) {
363 			command.params.push_back(params[p]);
364 		}
365 		free(params);
366 
367 		cc->push_back(command);
368 	}
369 
370 	// to prevent memory wholes
371 	if (unitCurrentCommandQueues[unitId] != NULL) {
372 		delete unitCurrentCommandQueues[unitId];
373 	}
374 	unitCurrentCommandQueues[unitId] = cc;
375 
376 	return cc;
377 }
378 
GetMaxUnits()379 int springLegacyAI::CAIAICallback::GetMaxUnits() {
380 	return sAICallback->Unit_getMax(skirmishAIId);
381 }
382 
GetUnitAiHint(int unitId)383 int springLegacyAI::CAIAICallback::GetUnitAiHint(int unitId) {
384 	return sAICallback->Unit_getAiHint(skirmishAIId, unitId);
385 }
386 
GetUnitTeam(int unitId)387 int springLegacyAI::CAIAICallback::GetUnitTeam(int unitId) {
388 	return sAICallback->Unit_getTeam(skirmishAIId, unitId);
389 }
390 
GetUnitAllyTeam(int unitId)391 int springLegacyAI::CAIAICallback::GetUnitAllyTeam(int unitId) {
392 	return sAICallback->Unit_getAllyTeam(skirmishAIId, unitId);
393 }
394 
GetUnitHealth(int unitId)395 float springLegacyAI::CAIAICallback::GetUnitHealth(int unitId) {
396 	return sAICallback->Unit_getHealth(skirmishAIId, unitId);
397 }
398 
GetUnitMaxHealth(int unitId)399 float springLegacyAI::CAIAICallback::GetUnitMaxHealth(int unitId) {
400 	return sAICallback->Unit_getMaxHealth(skirmishAIId, unitId);
401 }
402 
GetUnitSpeed(int unitId)403 float springLegacyAI::CAIAICallback::GetUnitSpeed(int unitId) {
404 	return sAICallback->Unit_getSpeed(skirmishAIId, unitId);
405 }
406 
GetUnitPower(int unitId)407 float springLegacyAI::CAIAICallback::GetUnitPower(int unitId) {
408 	return sAICallback->Unit_getPower(skirmishAIId, unitId);
409 }
410 
GetUnitExperience(int unitId)411 float springLegacyAI::CAIAICallback::GetUnitExperience(int unitId) {
412 	return sAICallback->Unit_getExperience(skirmishAIId, unitId);
413 }
414 
GetUnitMaxRange(int unitId)415 float springLegacyAI::CAIAICallback::GetUnitMaxRange(int unitId) {
416 	return sAICallback->Unit_getMaxRange(skirmishAIId, unitId);
417 }
418 
IsUnitActivated(int unitId)419 bool springLegacyAI::CAIAICallback::IsUnitActivated(int unitId) {
420 	return sAICallback->Unit_isActivated(skirmishAIId, unitId);
421 }
422 
UnitBeingBuilt(int unitId)423 bool springLegacyAI::CAIAICallback::UnitBeingBuilt(int unitId) {
424 	return sAICallback->Unit_isBeingBuilt(skirmishAIId, unitId);
425 }
426 
GetUnitDef(int unitId)427 const springLegacyAI::UnitDef* springLegacyAI::CAIAICallback::GetUnitDef(int unitId) {
428 	int unitDefId = sAICallback->Unit_getDef(skirmishAIId, unitId);
429 	return this->GetUnitDefById(unitDefId);
430 }
431 
432 
433 
GetUnitPos(int unitId)434 float3 springLegacyAI::CAIAICallback::GetUnitPos(int unitId) {
435 
436 	float pos_cache[3];
437 	sAICallback->Unit_getPos(skirmishAIId, unitId, pos_cache);
438 	return pos_cache;
439 }
440 
GetUnitVel(int unitId)441 float3 springLegacyAI::CAIAICallback::GetUnitVel(int unitId) {
442 
443 	float pos_cache[3];
444 	sAICallback->Unit_getVel(skirmishAIId, unitId, pos_cache);
445 	return pos_cache;
446 }
447 
448 
449 
GetBuildingFacing(int unitId)450 int springLegacyAI::CAIAICallback::GetBuildingFacing(int unitId) {
451 	return sAICallback->Unit_getBuildingFacing(skirmishAIId, unitId);
452 }
453 
IsUnitCloaked(int unitId)454 bool springLegacyAI::CAIAICallback::IsUnitCloaked(int unitId) {
455 	return sAICallback->Unit_isCloaked(skirmishAIId, unitId);
456 }
457 
IsUnitParalyzed(int unitId)458 bool springLegacyAI::CAIAICallback::IsUnitParalyzed(int unitId) {
459 	return sAICallback->Unit_isParalyzed(skirmishAIId, unitId);
460 }
461 
IsUnitNeutral(int unitId)462 bool springLegacyAI::CAIAICallback::IsUnitNeutral(int unitId) {
463 	return sAICallback->Unit_isNeutral(skirmishAIId, unitId);
464 }
465 
GetUnitResourceInfo(int unitId,UnitResourceInfo * resourceInfo)466 bool springLegacyAI::CAIAICallback::GetUnitResourceInfo(int unitId, UnitResourceInfo* resourceInfo) {
467 
468 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
469 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
470 	resourceInfo->energyMake = sAICallback->Unit_getResourceMake(skirmishAIId, unitId, e);
471 	if (resourceInfo->energyMake < 0) { return false; }
472 	resourceInfo->energyUse = sAICallback->Unit_getResourceUse(skirmishAIId, unitId, e);
473 	resourceInfo->metalMake = sAICallback->Unit_getResourceMake(skirmishAIId, unitId, m);
474 	resourceInfo->metalUse = sAICallback->Unit_getResourceUse(skirmishAIId, unitId, m);
475 	return true;
476 }
477 
GetUnitDef(const char * unitName)478 const springLegacyAI::UnitDef* springLegacyAI::CAIAICallback::GetUnitDef(const char* unitName) {
479 	int unitDefId = sAICallback->getUnitDefByName(skirmishAIId, unitName);
480 	return this->GetUnitDefById(unitDefId);
481 }
482 
483 
GetUnitDefById(int unitDefId)484 const springLegacyAI::UnitDef* springLegacyAI::CAIAICallback::GetUnitDefById(int unitDefId) {
485 	//logT("entering: GetUnitDefById sAICallback");
486 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
487 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
488 
489 	if (unitDefId < 0) {
490 		return NULL;
491 	}
492 
493 	const bool doRecreate = (unitDefFrames[unitDefId] < 0);
494 
495 	if (doRecreate) {
496 //		int currentFrame = this->GetCurrentFrame();
497 		int currentFrame = 1;
498 
499 		float pos_cache[3];
500 
501 		UnitDef* unitDef = new UnitDef();
502 
503 		unitDef->name = sAICallback->UnitDef_getName(skirmishAIId, unitDefId);
504 		unitDef->humanName = sAICallback->UnitDef_getHumanName(skirmishAIId, unitDefId);
505 		unitDef->filename = sAICallback->UnitDef_getFileName(skirmishAIId, unitDefId);
506 		//unitDef->id = sAICallback->UnitDef_getId(skirmishAIId, unitDefId);
507 		unitDef->id = unitDefId;
508 		unitDef->aihint = sAICallback->UnitDef_getAiHint(skirmishAIId, unitDefId);
509 		unitDef->cobID = sAICallback->UnitDef_getCobId(skirmishAIId, unitDefId);
510 		unitDef->techLevel = sAICallback->UnitDef_getTechLevel(skirmishAIId, unitDefId);
511 		unitDef->gaia = sAICallback->UnitDef_getGaia(skirmishAIId, unitDefId);
512 		unitDef->metalUpkeep = sAICallback->UnitDef_getUpkeep(skirmishAIId, unitDefId, m);
513 		unitDef->energyUpkeep = sAICallback->UnitDef_getUpkeep(skirmishAIId, unitDefId, e);
514 		unitDef->metalMake = sAICallback->UnitDef_getResourceMake(skirmishAIId, unitDefId, m);
515 		unitDef->makesMetal = sAICallback->UnitDef_getMakesResource(skirmishAIId, unitDefId, m);
516 		unitDef->energyMake = sAICallback->UnitDef_getResourceMake(skirmishAIId, unitDefId, e);
517 		unitDef->metalCost = sAICallback->UnitDef_getCost(skirmishAIId, unitDefId, m);
518 		unitDef->energyCost = sAICallback->UnitDef_getCost(skirmishAIId, unitDefId, e);
519 		unitDef->buildTime = sAICallback->UnitDef_getBuildTime(skirmishAIId, unitDefId);
520 		unitDef->extractsMetal = sAICallback->UnitDef_getExtractsResource(skirmishAIId, unitDefId, m);
521 		unitDef->extractRange = sAICallback->UnitDef_getResourceExtractorRange(skirmishAIId, unitDefId, m);
522 		unitDef->windGenerator = sAICallback->UnitDef_getWindResourceGenerator(skirmishAIId, unitDefId, e);
523 		unitDef->tidalGenerator = sAICallback->UnitDef_getTidalResourceGenerator(skirmishAIId, unitDefId, e);
524 		unitDef->metalStorage = sAICallback->UnitDef_getStorage(skirmishAIId, unitDefId, m);
525 		unitDef->energyStorage = sAICallback->UnitDef_getStorage(skirmishAIId, unitDefId, e);
526 		unitDef->autoHeal = sAICallback->UnitDef_getAutoHeal(skirmishAIId, unitDefId);
527 		unitDef->idleAutoHeal = sAICallback->UnitDef_getIdleAutoHeal(skirmishAIId, unitDefId);
528 		unitDef->idleTime = sAICallback->UnitDef_getIdleTime(skirmishAIId, unitDefId);
529 		unitDef->power = sAICallback->UnitDef_getPower(skirmishAIId, unitDefId);
530 		unitDef->health = sAICallback->UnitDef_getHealth(skirmishAIId, unitDefId);
531 		unitDef->category = sAICallback->UnitDef_getCategory(skirmishAIId, unitDefId);
532 		unitDef->speed = sAICallback->UnitDef_getSpeed(skirmishAIId, unitDefId);
533 		unitDef->turnRate = sAICallback->UnitDef_getTurnRate(skirmishAIId, unitDefId);
534 		unitDef->turnInPlace = sAICallback->UnitDef_isTurnInPlace(skirmishAIId, unitDefId);
535 		unitDef->upright = sAICallback->UnitDef_isUpright(skirmishAIId, unitDefId);
536 		unitDef->collide = sAICallback->UnitDef_isCollide(skirmishAIId, unitDefId);
537 		unitDef->losRadius = sAICallback->UnitDef_getLosRadius(skirmishAIId, unitDefId);
538 		unitDef->airLosRadius = sAICallback->UnitDef_getAirLosRadius(skirmishAIId, unitDefId);
539 		unitDef->losHeight = sAICallback->UnitDef_getLosHeight(skirmishAIId, unitDefId);
540 		unitDef->radarRadius = sAICallback->UnitDef_getRadarRadius(skirmishAIId, unitDefId);
541 		unitDef->sonarRadius = sAICallback->UnitDef_getSonarRadius(skirmishAIId, unitDefId);
542 		unitDef->jammerRadius = sAICallback->UnitDef_getJammerRadius(skirmishAIId, unitDefId);
543 		unitDef->sonarJamRadius = sAICallback->UnitDef_getSonarJamRadius(skirmishAIId, unitDefId);
544 		unitDef->seismicRadius = sAICallback->UnitDef_getSeismicRadius(skirmishAIId, unitDefId);
545 		unitDef->seismicSignature = sAICallback->UnitDef_getSeismicSignature(skirmishAIId, unitDefId);
546 		unitDef->stealth = sAICallback->UnitDef_isStealth(skirmishAIId, unitDefId);
547 		unitDef->sonarStealth = sAICallback->UnitDef_isSonarStealth(skirmishAIId, unitDefId);
548 		unitDef->buildRange3D = sAICallback->UnitDef_isBuildRange3D(skirmishAIId, unitDefId);
549 		unitDef->buildDistance = sAICallback->UnitDef_getBuildDistance(skirmishAIId, unitDefId);
550 		unitDef->buildSpeed = sAICallback->UnitDef_getBuildSpeed(skirmishAIId, unitDefId);
551 		unitDef->reclaimSpeed = sAICallback->UnitDef_getReclaimSpeed(skirmishAIId, unitDefId);
552 		unitDef->repairSpeed = sAICallback->UnitDef_getRepairSpeed(skirmishAIId, unitDefId);
553 		unitDef->maxRepairSpeed = sAICallback->UnitDef_getMaxRepairSpeed(skirmishAIId, unitDefId);
554 		unitDef->resurrectSpeed = sAICallback->UnitDef_getResurrectSpeed(skirmishAIId, unitDefId);
555 		unitDef->captureSpeed = sAICallback->UnitDef_getCaptureSpeed(skirmishAIId, unitDefId);
556 		unitDef->terraformSpeed = sAICallback->UnitDef_getTerraformSpeed(skirmishAIId, unitDefId);
557 		unitDef->mass = sAICallback->UnitDef_getMass(skirmishAIId, unitDefId);
558 		unitDef->pushResistant = sAICallback->UnitDef_isPushResistant(skirmishAIId, unitDefId);
559 		unitDef->strafeToAttack = sAICallback->UnitDef_isStrafeToAttack(skirmishAIId, unitDefId);
560 		unitDef->minCollisionSpeed = sAICallback->UnitDef_getMinCollisionSpeed(skirmishAIId, unitDefId);
561 		unitDef->slideTolerance = sAICallback->UnitDef_getSlideTolerance(skirmishAIId, unitDefId);
562 		unitDef->maxSlope = sAICallback->UnitDef_getMaxSlope(skirmishAIId, unitDefId);
563 		unitDef->maxHeightDif = sAICallback->UnitDef_getMaxHeightDif(skirmishAIId, unitDefId);
564 		unitDef->minWaterDepth = sAICallback->UnitDef_getMinWaterDepth(skirmishAIId, unitDefId);
565 		unitDef->waterline = sAICallback->UnitDef_getWaterline(skirmishAIId, unitDefId);
566 		unitDef->maxWaterDepth = sAICallback->UnitDef_getMaxWaterDepth(skirmishAIId, unitDefId);
567 		unitDef->armoredMultiple = sAICallback->UnitDef_getArmoredMultiple(skirmishAIId, unitDefId);
568 		unitDef->armorType = sAICallback->UnitDef_getArmorType(skirmishAIId, unitDefId);
569 		unitDef->flankingBonusMode = sAICallback->UnitDef_FlankingBonus_getMode(skirmishAIId, unitDefId);
570 		sAICallback->UnitDef_FlankingBonus_getDir(skirmishAIId, unitDefId, pos_cache);
571 		unitDef->flankingBonusDir = pos_cache;
572 		unitDef->flankingBonusMax = sAICallback->UnitDef_FlankingBonus_getMax(skirmishAIId, unitDefId);
573 		unitDef->flankingBonusMin = sAICallback->UnitDef_FlankingBonus_getMin(skirmishAIId, unitDefId);
574 		unitDef->flankingBonusMobilityAdd = sAICallback->UnitDef_FlankingBonus_getMobilityAdd(skirmishAIId, unitDefId);
575 		unitDef->maxWeaponRange = sAICallback->UnitDef_getMaxWeaponRange(skirmishAIId, unitDefId);
576 		unitDef->type = sAICallback->UnitDef_getType(skirmishAIId, unitDefId);
577 		unitDef->tooltip = sAICallback->UnitDef_getTooltip(skirmishAIId, unitDefId);
578 		unitDef->wreckName = sAICallback->UnitDef_getWreckName(skirmishAIId, unitDefId);
579 		unitDef->deathExplosion = sAICallback->UnitDef_getDeathExplosion(skirmishAIId, unitDefId);
580 		unitDef->selfDExplosion = sAICallback->UnitDef_getSelfDExplosion(skirmishAIId, unitDefId);
581 		unitDef->categoryString = sAICallback->UnitDef_getCategoryString(skirmishAIId, unitDefId);
582 		unitDef->canSelfD = sAICallback->UnitDef_isAbleToSelfD(skirmishAIId, unitDefId);
583 		unitDef->selfDCountdown = sAICallback->UnitDef_getSelfDCountdown(skirmishAIId, unitDefId);
584 		unitDef->canSubmerge = sAICallback->UnitDef_isAbleToSubmerge(skirmishAIId, unitDefId);
585 		unitDef->canfly = sAICallback->UnitDef_isAbleToFly(skirmishAIId, unitDefId);
586 		unitDef->canmove = sAICallback->UnitDef_isAbleToMove(skirmishAIId, unitDefId);
587 		unitDef->canhover = sAICallback->UnitDef_isAbleToHover(skirmishAIId, unitDefId);
588 		unitDef->floater = sAICallback->UnitDef_isFloater(skirmishAIId, unitDefId);
589 		unitDef->builder = sAICallback->UnitDef_isBuilder(skirmishAIId, unitDefId);
590 		unitDef->activateWhenBuilt = sAICallback->UnitDef_isActivateWhenBuilt(skirmishAIId, unitDefId);
591 		unitDef->onoffable = sAICallback->UnitDef_isOnOffable(skirmishAIId, unitDefId);
592 		unitDef->fullHealthFactory = sAICallback->UnitDef_isFullHealthFactory(skirmishAIId, unitDefId);
593 		unitDef->factoryHeadingTakeoff = sAICallback->UnitDef_isFactoryHeadingTakeoff(skirmishAIId, unitDefId);
594 		unitDef->reclaimable = sAICallback->UnitDef_isReclaimable(skirmishAIId, unitDefId);
595 		unitDef->capturable = sAICallback->UnitDef_isCapturable(skirmishAIId, unitDefId);
596 		unitDef->canRestore = sAICallback->UnitDef_isAbleToRestore(skirmishAIId, unitDefId);
597 		unitDef->canRepair = sAICallback->UnitDef_isAbleToRepair(skirmishAIId, unitDefId);
598 		unitDef->canSelfRepair = sAICallback->UnitDef_isAbleToSelfRepair(skirmishAIId, unitDefId);
599 		unitDef->canReclaim = sAICallback->UnitDef_isAbleToReclaim(skirmishAIId, unitDefId);
600 		unitDef->canAttack = sAICallback->UnitDef_isAbleToAttack(skirmishAIId, unitDefId);
601 		unitDef->canPatrol = sAICallback->UnitDef_isAbleToPatrol(skirmishAIId, unitDefId);
602 		unitDef->canFight = sAICallback->UnitDef_isAbleToFight(skirmishAIId, unitDefId);
603 		unitDef->canGuard = sAICallback->UnitDef_isAbleToGuard(skirmishAIId, unitDefId);
604 		unitDef->canAssist = sAICallback->UnitDef_isAbleToAssist(skirmishAIId, unitDefId);
605 		unitDef->canBeAssisted = sAICallback->UnitDef_isAssistable(skirmishAIId, unitDefId);
606 		unitDef->canRepeat = sAICallback->UnitDef_isAbleToRepeat(skirmishAIId, unitDefId);
607 		unitDef->canFireControl = sAICallback->UnitDef_isAbleToFireControl(skirmishAIId, unitDefId);
608 		unitDef->fireState = sAICallback->UnitDef_getFireState(skirmishAIId, unitDefId);
609 		unitDef->moveState = sAICallback->UnitDef_getMoveState(skirmishAIId, unitDefId);
610 		unitDef->wingDrag = sAICallback->UnitDef_getWingDrag(skirmishAIId, unitDefId);
611 		unitDef->wingAngle = sAICallback->UnitDef_getWingAngle(skirmishAIId, unitDefId);
612 		unitDef->drag = sAICallback->UnitDef_getDrag(skirmishAIId, unitDefId);
613 		unitDef->frontToSpeed = sAICallback->UnitDef_getFrontToSpeed(skirmishAIId, unitDefId);
614 		unitDef->speedToFront = sAICallback->UnitDef_getSpeedToFront(skirmishAIId, unitDefId);
615 		unitDef->myGravity = sAICallback->UnitDef_getMyGravity(skirmishAIId, unitDefId);
616 		unitDef->maxBank = sAICallback->UnitDef_getMaxBank(skirmishAIId, unitDefId);
617 		unitDef->maxPitch = sAICallback->UnitDef_getMaxPitch(skirmishAIId, unitDefId);
618 		unitDef->turnRadius = sAICallback->UnitDef_getTurnRadius(skirmishAIId, unitDefId);
619 		unitDef->wantedHeight = sAICallback->UnitDef_getWantedHeight(skirmishAIId, unitDefId);
620 		unitDef->verticalSpeed = sAICallback->UnitDef_getVerticalSpeed(skirmishAIId, unitDefId);
621 		unitDef->canCrash = sAICallback->UnitDef_isAbleToCrash(skirmishAIId, unitDefId);
622 		unitDef->hoverAttack = sAICallback->UnitDef_isHoverAttack(skirmishAIId, unitDefId);
623 		unitDef->airStrafe = sAICallback->UnitDef_isAirStrafe(skirmishAIId, unitDefId);
624 		unitDef->dlHoverFactor = sAICallback->UnitDef_getDlHoverFactor(skirmishAIId, unitDefId);
625 		unitDef->maxAcc = sAICallback->UnitDef_getMaxAcceleration(skirmishAIId, unitDefId);
626 		unitDef->maxDec = sAICallback->UnitDef_getMaxDeceleration(skirmishAIId, unitDefId);
627 		unitDef->maxAileron = sAICallback->UnitDef_getMaxAileron(skirmishAIId, unitDefId);
628 		unitDef->maxElevator = sAICallback->UnitDef_getMaxElevator(skirmishAIId, unitDefId);
629 		unitDef->maxRudder = sAICallback->UnitDef_getMaxRudder(skirmishAIId, unitDefId);
630 		{
631 			static const size_t facings = 4;
632 			const int yardMap_size = sAICallback->UnitDef_getYardMap(skirmishAIId, unitDefId, 0, NULL, 0);
633 			short* tmpYardMap = new short[yardMap_size];
634 
635 			for (int ym = 0 ; ym < facings; ++ym) {
636 				sAICallback->UnitDef_getYardMap(skirmishAIId, unitDefId, ym, tmpYardMap, yardMap_size);
637 				unitDef->yardmaps[ym] = new unsigned char[yardMap_size]; // this will be deleted in the dtor
638 				for (int i = 0; i < yardMap_size; ++i) {
639 					unitDef->yardmaps[ym][i] = (const char) tmpYardMap[i];
640 				}
641 			}
642 
643 			delete[] tmpYardMap;
644 		}
645 		unitDef->xsize = sAICallback->UnitDef_getXSize(skirmishAIId, unitDefId);
646 		unitDef->zsize = sAICallback->UnitDef_getZSize(skirmishAIId, unitDefId);
647 		unitDef->buildangle = sAICallback->UnitDef_getBuildAngle(skirmishAIId, unitDefId);
648 		unitDef->loadingRadius = sAICallback->UnitDef_getLoadingRadius(skirmishAIId, unitDefId);
649 		unitDef->unloadSpread = sAICallback->UnitDef_getUnloadSpread(skirmishAIId, unitDefId);
650 		unitDef->transportCapacity = sAICallback->UnitDef_getTransportCapacity(skirmishAIId, unitDefId);
651 		unitDef->transportSize = sAICallback->UnitDef_getTransportSize(skirmishAIId, unitDefId);
652 		unitDef->minTransportSize = sAICallback->UnitDef_getMinTransportSize(skirmishAIId, unitDefId);
653 		unitDef->isAirBase = sAICallback->UnitDef_isAirBase(skirmishAIId, unitDefId);
654 		unitDef->transportMass = sAICallback->UnitDef_getTransportMass(skirmishAIId, unitDefId);
655 		unitDef->minTransportMass = sAICallback->UnitDef_getMinTransportMass(skirmishAIId, unitDefId);
656 		unitDef->holdSteady = sAICallback->UnitDef_isHoldSteady(skirmishAIId, unitDefId);
657 		unitDef->releaseHeld = sAICallback->UnitDef_isReleaseHeld(skirmishAIId, unitDefId);
658 		unitDef->cantBeTransported = sAICallback->UnitDef_isNotTransportable(skirmishAIId, unitDefId);
659 		unitDef->transportByEnemy = sAICallback->UnitDef_isTransportByEnemy(skirmishAIId, unitDefId);
660 		unitDef->transportUnloadMethod = sAICallback->UnitDef_getTransportUnloadMethod(skirmishAIId, unitDefId);
661 		unitDef->fallSpeed = sAICallback->UnitDef_getFallSpeed(skirmishAIId, unitDefId);
662 		unitDef->unitFallSpeed = sAICallback->UnitDef_getUnitFallSpeed(skirmishAIId, unitDefId);
663 		unitDef->canCloak = sAICallback->UnitDef_isAbleToCloak(skirmishAIId, unitDefId);
664 		unitDef->startCloaked = sAICallback->UnitDef_isStartCloaked(skirmishAIId, unitDefId);
665 		unitDef->cloakCost = sAICallback->UnitDef_getCloakCost(skirmishAIId, unitDefId);
666 		unitDef->cloakCostMoving = sAICallback->UnitDef_getCloakCostMoving(skirmishAIId, unitDefId);
667 		unitDef->decloakDistance = sAICallback->UnitDef_getDecloakDistance(skirmishAIId, unitDefId);
668 		unitDef->decloakSpherical = sAICallback->UnitDef_isDecloakSpherical(skirmishAIId, unitDefId);
669 		unitDef->decloakOnFire = sAICallback->UnitDef_isDecloakOnFire(skirmishAIId, unitDefId);
670 		unitDef->canKamikaze = sAICallback->UnitDef_isAbleToKamikaze(skirmishAIId, unitDefId);
671 		unitDef->kamikazeDist = sAICallback->UnitDef_getKamikazeDist(skirmishAIId, unitDefId);
672 		unitDef->targfac = sAICallback->UnitDef_isTargetingFacility(skirmishAIId, unitDefId);
673 		unitDef->canDGun = sAICallback->UnitDef_canManualFire(skirmishAIId, unitDefId);
674 		unitDef->needGeo = sAICallback->UnitDef_isNeedGeo(skirmishAIId, unitDefId);
675 		unitDef->isFeature = sAICallback->UnitDef_isFeature(skirmishAIId, unitDefId);
676 		unitDef->hideDamage = sAICallback->UnitDef_isHideDamage(skirmishAIId, unitDefId);
677 		unitDef->isCommander = sAICallback->UnitDef_isCommander(skirmishAIId, unitDefId);
678 		unitDef->showPlayerName = sAICallback->UnitDef_isShowPlayerName(skirmishAIId, unitDefId);
679 		unitDef->canResurrect = sAICallback->UnitDef_isAbleToResurrect(skirmishAIId, unitDefId);
680 		unitDef->canCapture = sAICallback->UnitDef_isAbleToCapture(skirmishAIId, unitDefId);
681 		unitDef->highTrajectoryType = sAICallback->UnitDef_getHighTrajectoryType(skirmishAIId, unitDefId);
682 		unitDef->noChaseCategory = sAICallback->UnitDef_getNoChaseCategory(skirmishAIId, unitDefId);
683 		unitDef->leaveTracks = sAICallback->UnitDef_isLeaveTracks(skirmishAIId, unitDefId);
684 		unitDef->trackWidth = sAICallback->UnitDef_getTrackWidth(skirmishAIId, unitDefId);
685 		unitDef->trackOffset = sAICallback->UnitDef_getTrackOffset(skirmishAIId, unitDefId);
686 		unitDef->trackStrength = sAICallback->UnitDef_getTrackStrength(skirmishAIId, unitDefId);
687 		unitDef->trackStretch = sAICallback->UnitDef_getTrackStretch(skirmishAIId, unitDefId);
688 		unitDef->trackType = sAICallback->UnitDef_getTrackType(skirmishAIId, unitDefId);
689 		unitDef->canDropFlare = sAICallback->UnitDef_isAbleToDropFlare(skirmishAIId, unitDefId);
690 		unitDef->flareReloadTime = sAICallback->UnitDef_getFlareReloadTime(skirmishAIId, unitDefId);
691 		unitDef->flareEfficiency = sAICallback->UnitDef_getFlareEfficiency(skirmishAIId, unitDefId);
692 		unitDef->flareDelay = sAICallback->UnitDef_getFlareDelay(skirmishAIId, unitDefId);
693 		sAICallback->UnitDef_getFlareDropVector(skirmishAIId, unitDefId, pos_cache);
694 		unitDef->flareDropVector = pos_cache;
695 		unitDef->flareTime = sAICallback->UnitDef_getFlareTime(skirmishAIId, unitDefId);
696 		unitDef->flareSalvoSize = sAICallback->UnitDef_getFlareSalvoSize(skirmishAIId, unitDefId);
697 		unitDef->flareSalvoDelay = sAICallback->UnitDef_getFlareSalvoDelay(skirmishAIId, unitDefId);
698 		unitDef->smoothAnim = false;
699 		unitDef->canLoopbackAttack = sAICallback->UnitDef_isAbleToLoopbackAttack(skirmishAIId, unitDefId);
700 		unitDef->levelGround = sAICallback->UnitDef_isLevelGround(skirmishAIId, unitDefId);
701 		unitDef->useBuildingGroundDecal = sAICallback->UnitDef_isUseBuildingGroundDecal(skirmishAIId, unitDefId);
702 		unitDef->buildingDecalType = sAICallback->UnitDef_getBuildingDecalType(skirmishAIId, unitDefId);
703 		unitDef->buildingDecalSizeX = sAICallback->UnitDef_getBuildingDecalSizeX(skirmishAIId, unitDefId);
704 		unitDef->buildingDecalSizeY = sAICallback->UnitDef_getBuildingDecalSizeY(skirmishAIId, unitDefId);
705 		unitDef->buildingDecalDecaySpeed = sAICallback->UnitDef_getBuildingDecalDecaySpeed(skirmishAIId, unitDefId);
706 		unitDef->isFirePlatform = sAICallback->UnitDef_isFirePlatform(skirmishAIId, unitDefId);
707 		unitDef->maxFuel = sAICallback->UnitDef_getMaxFuel(skirmishAIId, unitDefId);
708 		unitDef->refuelTime = sAICallback->UnitDef_getRefuelTime(skirmishAIId, unitDefId);
709 		unitDef->minAirBasePower = sAICallback->UnitDef_getMinAirBasePower(skirmishAIId, unitDefId);
710 		unitDef->maxThisUnit = sAICallback->UnitDef_getMaxThisUnit(skirmishAIId, unitDefId);
711 		//unitDef->decoyDef = sAICallback->UnitDef_getDecoyDefId(skirmishAIId, unitDefId);
712 		unitDef->shieldWeaponDef = this->GetWeaponDefById(sAICallback->UnitDef_getShieldDef(skirmishAIId, unitDefId));
713 		unitDef->stockpileWeaponDef = this->GetWeaponDefById(sAICallback->UnitDef_getStockpileDef(skirmishAIId, unitDefId));
714 
715 		{
716 			int numBuildOpts = sAICallback->UnitDef_getBuildOptions(skirmishAIId, unitDefId, NULL, 0);
717 			int* buildOpts = new int[numBuildOpts];
718 
719 			numBuildOpts = sAICallback->UnitDef_getBuildOptions(skirmishAIId, unitDefId, buildOpts, numBuildOpts);
720 
721 			for (int b=0; b < numBuildOpts; b++) {
722 				unitDef->buildOptions[b] = sAICallback->UnitDef_getName(skirmishAIId, buildOpts[b]);
723 			}
724 
725 			delete[] buildOpts;
726 		}
727 		{
728 			const int size = sAICallback->UnitDef_getCustomParams(skirmishAIId, unitDefId, NULL, NULL);
729 			const char** cKeys = (const char**) calloc(size, sizeof(char*));
730 			const char** cValues = (const char**) calloc(size, sizeof(char*));
731 			sAICallback->UnitDef_getCustomParams(skirmishAIId, unitDefId, cKeys, cValues);
732 			int i;
733 			for (i = 0; i < size; ++i) {
734 				unitDef->customParams[cKeys[i]] = cValues[i];
735 			}
736 			free(cKeys);
737 			free(cValues);
738 		}
739 
740 		if (sAICallback->UnitDef_isMoveDataAvailable(skirmishAIId, unitDefId)) {
741 			unitDef->movedata = new MoveData();
742 			unitDef->movedata->maxAcceleration = sAICallback->UnitDef_MoveData_getMaxAcceleration(skirmishAIId, unitDefId);
743 			unitDef->movedata->maxBreaking = sAICallback->UnitDef_MoveData_getMaxBreaking(skirmishAIId, unitDefId);
744 			unitDef->movedata->maxSpeed = sAICallback->UnitDef_MoveData_getMaxSpeed(skirmishAIId, unitDefId);
745 			unitDef->movedata->maxTurnRate = sAICallback->UnitDef_MoveData_getMaxTurnRate(skirmishAIId, unitDefId);
746 
747 			unitDef->movedata->xsize = sAICallback->UnitDef_MoveData_getXSize(skirmishAIId, unitDefId);
748 			unitDef->movedata->zsize = sAICallback->UnitDef_MoveData_getZSize(skirmishAIId, unitDefId);
749 			unitDef->movedata->depth = sAICallback->UnitDef_MoveData_getDepth(skirmishAIId, unitDefId);
750 			unitDef->movedata->maxSlope = sAICallback->UnitDef_MoveData_getMaxSlope(skirmishAIId, unitDefId);
751 			unitDef->movedata->slopeMod = sAICallback->UnitDef_MoveData_getSlopeMod(skirmishAIId, unitDefId);
752 			unitDef->movedata->depthMod = sAICallback->UnitDef_MoveData_getDepthMod(skirmishAIId, unitDefId);
753 			unitDef->movedata->pathType = sAICallback->UnitDef_MoveData_getPathType(skirmishAIId, unitDefId);
754 			unitDef->movedata->crushStrength = sAICallback->UnitDef_MoveData_getCrushStrength(skirmishAIId, unitDefId);
755 			unitDef->movedata->moveType = (enum MoveData::MoveType) sAICallback->UnitDef_MoveData_getMoveType(skirmishAIId, unitDefId);
756 			unitDef->movedata->moveFamily = (enum MoveData::MoveFamily) sAICallback->UnitDef_MoveData_getSpeedModClass(skirmishAIId, unitDefId);
757 			unitDef->movedata->terrainClass = (enum MoveData::TerrainClass) sAICallback->UnitDef_MoveData_getTerrainClass(skirmishAIId, unitDefId);
758 
759 			unitDef->movedata->followGround = sAICallback->UnitDef_MoveData_getFollowGround(skirmishAIId, unitDefId);
760 			unitDef->movedata->subMarine = sAICallback->UnitDef_MoveData_isSubMarine(skirmishAIId, unitDefId);
761 			unitDef->movedata->name = std::string(sAICallback->UnitDef_MoveData_getName(skirmishAIId, unitDefId));
762 		} else {
763 			unitDef->movedata = NULL;
764 		}
765 
766 		const int numWeapons = sAICallback->UnitDef_getWeaponMounts(skirmishAIId, unitDefId);
767 		for (int w = 0; w < numWeapons; ++w) {
768 			unitDef->weapons.push_back(UnitDef::UnitDefWeapon());
769 			unitDef->weapons[w].name = sAICallback->UnitDef_WeaponMount_getName(skirmishAIId, unitDefId, w);
770 			int weaponDefId = sAICallback->UnitDef_WeaponMount_getWeaponDef(skirmishAIId, unitDefId, w);
771 			unitDef->weapons[w].def = this->GetWeaponDefById(weaponDefId);
772 			unitDef->weapons[w].slavedTo = sAICallback->UnitDef_WeaponMount_getSlavedTo(skirmishAIId, unitDefId, w);
773 			sAICallback->UnitDef_WeaponMount_getMainDir(skirmishAIId, unitDefId, w, pos_cache);
774 			unitDef->weapons[w].mainDir = pos_cache;
775 			unitDef->weapons[w].maxAngleDif = sAICallback->UnitDef_WeaponMount_getMaxAngleDif(skirmishAIId, unitDefId, w);
776 			unitDef->weapons[w].fuelUsage = sAICallback->UnitDef_WeaponMount_getFuelUsage(skirmishAIId, unitDefId, w);
777 			unitDef->weapons[w].badTargetCat = sAICallback->UnitDef_WeaponMount_getBadTargetCategory(skirmishAIId, unitDefId, w);
778 			unitDef->weapons[w].onlyTargetCat = sAICallback->UnitDef_WeaponMount_getOnlyTargetCategory(skirmishAIId, unitDefId, w);
779 		}
780 
781 		if (unitDefs[unitDefId] != NULL) {
782 			delete unitDefs[unitDefId];
783 		}
784 		unitDefs[unitDefId] = unitDef;
785 		unitDefFrames[unitDefId] = currentFrame;
786 	}
787 
788 	return unitDefs[unitDefId];
789 }
790 
GetEnemyUnits(int * unitIds,int unitIds_max)791 int springLegacyAI::CAIAICallback::GetEnemyUnits(int* unitIds, int unitIds_max) {
792 	return sAICallback->getEnemyUnits(skirmishAIId, unitIds, unitIds_max);
793 }
794 
GetEnemyUnits(int * unitIds,const float3 & pos,float radius,int unitIds_max)795 int springLegacyAI::CAIAICallback::GetEnemyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) {
796 
797 	float pos_param[3];
798 	pos.copyInto(pos_param);
799 
800 	return sAICallback->getEnemyUnitsIn(skirmishAIId, pos_param, radius, unitIds, unitIds_max);
801 }
802 
GetEnemyUnitsInRadarAndLos(int * unitIds,int unitIds_max)803 int springLegacyAI::CAIAICallback::GetEnemyUnitsInRadarAndLos(int* unitIds, int unitIds_max) {
804 	return sAICallback->getEnemyUnitsInRadarAndLos(skirmishAIId, unitIds, unitIds_max);
805 }
806 
GetFriendlyUnits(int * unitIds,int unitIds_max)807 int springLegacyAI::CAIAICallback::GetFriendlyUnits(int* unitIds, int unitIds_max) {
808 	return sAICallback->getFriendlyUnits(skirmishAIId, unitIds, unitIds_max);
809 }
810 
GetFriendlyUnits(int * unitIds,const float3 & pos,float radius,int unitIds_max)811 int springLegacyAI::CAIAICallback::GetFriendlyUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) {
812 
813 	float pos_param[3];
814 	pos.copyInto(pos_param);
815 
816 	return sAICallback->getFriendlyUnitsIn(skirmishAIId, pos_param, radius, unitIds, unitIds_max);
817 }
818 
GetNeutralUnits(int * unitIds,int unitIds_max)819 int springLegacyAI::CAIAICallback::GetNeutralUnits(int* unitIds, int unitIds_max) {
820 	return sAICallback->getNeutralUnits(skirmishAIId, unitIds, unitIds_max);
821 }
822 
GetNeutralUnits(int * unitIds,const float3 & pos,float radius,int unitIds_max)823 int springLegacyAI::CAIAICallback::GetNeutralUnits(int* unitIds, const float3& pos, float radius, int unitIds_max) {
824 
825 	float pos_param[3];
826 	pos.copyInto(pos_param);
827 
828 	return sAICallback->getNeutralUnitsIn(skirmishAIId, pos_param, radius, unitIds, unitIds_max);
829 }
830 
GetMapWidth()831 int springLegacyAI::CAIAICallback::GetMapWidth() {
832 	return sAICallback->Map_getWidth(skirmishAIId);
833 }
834 
GetMapHeight()835 int springLegacyAI::CAIAICallback::GetMapHeight() {
836 	return sAICallback->Map_getHeight(skirmishAIId);
837 }
838 
GetHeightMap()839 const float* springLegacyAI::CAIAICallback::GetHeightMap() {
840 
841 	if (heightMap == NULL) {
842 		const int size = sAICallback->Map_getHeightMap(skirmishAIId, NULL, 0);
843 		heightMap = new float[size]; // NOTE: memory leak, but will be used till end of the game anyway
844 		sAICallback->Map_getHeightMap(skirmishAIId, heightMap, size);
845 	}
846 
847 	return heightMap;
848 }
849 
GetCornersHeightMap()850 const float* springLegacyAI::CAIAICallback::GetCornersHeightMap() {
851 
852 	if (cornersHeightMap == NULL) {
853 		const int size = sAICallback->Map_getCornersHeightMap(skirmishAIId, NULL, 0);
854 		cornersHeightMap = new float[size]; // NOTE: memory leak, but will be used till end of the game anyway
855 		sAICallback->Map_getCornersHeightMap(skirmishAIId, cornersHeightMap, size);
856 	}
857 
858 	return cornersHeightMap;
859 }
860 
GetMinHeight()861 float springLegacyAI::CAIAICallback::GetMinHeight() {
862 	return sAICallback->Map_getMinHeight(skirmishAIId);
863 }
864 
GetMaxHeight()865 float springLegacyAI::CAIAICallback::GetMaxHeight() {
866 	return sAICallback->Map_getMaxHeight(skirmishAIId);
867 }
868 
GetSlopeMap()869 const float* springLegacyAI::CAIAICallback::GetSlopeMap() {
870 
871 	if (slopeMap == NULL) {
872 		const int size = sAICallback->Map_getSlopeMap(skirmishAIId, NULL, 0);
873 		slopeMap = new float[size]; // NOTE: memory leak, but will be used till end of the game anyway
874 		sAICallback->Map_getSlopeMap(skirmishAIId, slopeMap, size);
875 	}
876 
877 	return slopeMap;
878 }
879 
GetLosMap()880 const unsigned short* springLegacyAI::CAIAICallback::GetLosMap() {
881 
882 	if (losMap == NULL) {
883 		const int size = sAICallback->Map_getLosMap(skirmishAIId, NULL, 0);
884 		int* tmpLosMap = new int[size];
885 		sAICallback->Map_getLosMap(skirmishAIId, tmpLosMap, size);
886 		losMap = new unsigned short[size]; // NOTE: memory leak, but will be used till end of the game anyway
887 		copyIntToUShortArray(tmpLosMap, losMap, size);
888 		delete[] tmpLosMap;
889 	}
890 
891 	return losMap;
892 }
893 
GetLosMapResolution()894 int springLegacyAI::CAIAICallback::GetLosMapResolution() {
895 
896 	int fullSize = GetMapWidth() * GetMapHeight();
897 	int losSize = sAICallback->Map_getLosMap(skirmishAIId, NULL, 0);
898 
899 	return fullSize / losSize;
900 }
901 
GetRadarMap()902 const unsigned short* springLegacyAI::CAIAICallback::GetRadarMap() {
903 
904 	if (radarMap == NULL) {
905 		const int size = sAICallback->Map_getRadarMap(skirmishAIId, NULL, 0);
906 		int* tmpRadarMap = new int[size];
907 		sAICallback->Map_getRadarMap(skirmishAIId, tmpRadarMap, size);
908 		radarMap = new unsigned short[size]; // NOTE: memory leak, but will be used till end of the game anyway
909 		copyIntToUShortArray(tmpRadarMap, radarMap, size);
910 		delete[] tmpRadarMap;
911 	}
912 
913 	return radarMap;
914 }
915 
GetJammerMap()916 const unsigned short* springLegacyAI::CAIAICallback::GetJammerMap() {
917 
918 	if (jammerMap == NULL) {
919 		const int size = sAICallback->Map_getJammerMap(skirmishAIId, NULL, 0);
920 		int* tmpJammerMap = new int[size];
921 		sAICallback->Map_getJammerMap(skirmishAIId, tmpJammerMap, size);
922 		jammerMap = new unsigned short[size]; // NOTE: memory leak, but will be used till end of the game anyway
923 		copyIntToUShortArray(tmpJammerMap, jammerMap, size);
924 		delete[] tmpJammerMap;
925 	}
926 
927 	return jammerMap;
928 }
929 
GetMetalMap()930 const unsigned char* springLegacyAI::CAIAICallback::GetMetalMap() {
931 
932 	static const int m = getResourceId_Metal(sAICallback, skirmishAIId);
933 
934 	if (metalMap == NULL) {
935 		const int size = sAICallback->Map_getResourceMapRaw(skirmishAIId, m, NULL, 0);
936 		short* tmpMetalMap = new short[size];
937 		sAICallback->Map_getResourceMapRaw(skirmishAIId, m, tmpMetalMap, size);
938 		metalMap = new unsigned char[size]; // NOTE: memory leak, but will be used till end of the game anyway
939 		copyShortToUCharArray(tmpMetalMap, metalMap, size);
940 		delete[] tmpMetalMap;
941 	}
942 
943 	return metalMap;
944 }
945 
GetMapHash()946 int springLegacyAI::CAIAICallback::GetMapHash() {
947 	return sAICallback->Map_getHash(skirmishAIId);
948 }
949 
GetMapName()950 const char* springLegacyAI::CAIAICallback::GetMapName() {
951 	return sAICallback->Map_getName(skirmishAIId);
952 }
953 
GetMapHumanName()954 const char* springLegacyAI::CAIAICallback::GetMapHumanName() {
955 	return sAICallback->Map_getHumanName(skirmishAIId);
956 }
957 
GetModHash()958 int springLegacyAI::CAIAICallback::GetModHash() {
959 	return sAICallback->Mod_getHash(skirmishAIId);
960 }
961 
GetModName()962 const char* springLegacyAI::CAIAICallback::GetModName() {
963 	return sAICallback->Mod_getFileName(skirmishAIId);
964 }
965 
GetModHumanName()966 const char* springLegacyAI::CAIAICallback::GetModHumanName() {
967 	return sAICallback->Mod_getHumanName(skirmishAIId);
968 }
969 
GetModShortName()970 const char* springLegacyAI::CAIAICallback::GetModShortName() {
971 	return sAICallback->Mod_getShortName(skirmishAIId);
972 }
973 
GetModVersion()974 const char* springLegacyAI::CAIAICallback::GetModVersion() {
975 	return sAICallback->Mod_getVersion(skirmishAIId);
976 }
977 
GetElevation(float x,float z)978 float springLegacyAI::CAIAICallback::GetElevation(float x, float z) {
979 	return sAICallback->Map_getElevationAt(skirmishAIId, x, z);
980 }
981 
982 
GetMaxMetal() const983 float springLegacyAI::CAIAICallback::GetMaxMetal() const {
984 	static const int m = getResourceId_Metal(sAICallback, skirmishAIId);
985 	return sAICallback->Map_getMaxResource(skirmishAIId, m);
986 }
GetExtractorRadius() const987 float springLegacyAI::CAIAICallback::GetExtractorRadius() const {
988 	static const int m = getResourceId_Metal(sAICallback, skirmishAIId);
989 	return sAICallback->Map_getExtractorRadius(skirmishAIId, m);
990 }
991 
GetMinWind() const992 float springLegacyAI::CAIAICallback::GetMinWind() const { return sAICallback->Map_getMinWind(skirmishAIId); }
GetMaxWind() const993 float springLegacyAI::CAIAICallback::GetMaxWind() const { return sAICallback->Map_getMaxWind(skirmishAIId); }
GetCurWind() const994 float springLegacyAI::CAIAICallback::GetCurWind() const { return sAICallback->Map_getCurWind(skirmishAIId); }
995 
GetTidalStrength() const996 float springLegacyAI::CAIAICallback::GetTidalStrength() const  { return sAICallback->Map_getTidalStrength(skirmishAIId); }
GetGravity() const997 float springLegacyAI::CAIAICallback::GetGravity() const { return sAICallback->Map_getGravity(skirmishAIId); }
998 
999 
CanBuildAt(const UnitDef * unitDef,float3 pos,int facing)1000 bool springLegacyAI::CAIAICallback::CanBuildAt(const UnitDef* unitDef, float3 pos, int facing) {
1001 
1002 	float pos_param[3];
1003 	pos.copyInto(pos_param);
1004 
1005 	return sAICallback->Map_isPossibleToBuildAt(skirmishAIId, unitDef->id, pos_param, facing);
1006 }
1007 
ClosestBuildSite(const UnitDef * unitDef,float3 pos,float searchRadius,int minDist,int facing)1008 float3 springLegacyAI::CAIAICallback::ClosestBuildSite(const UnitDef* unitDef, float3 pos, float searchRadius, int minDist, int facing) {
1009 
1010 	float pos_param[3];
1011 	pos.copyInto(pos_param);
1012 
1013 	float pos_cache[3];
1014 	sAICallback->Map_findClosestBuildSite(skirmishAIId, unitDef->id, pos_param, searchRadius, minDist, facing, pos_cache);
1015 	return pos_cache;
1016 }
1017 
1018 /*
1019 bool springLegacyAI::CAIAICallback::GetProperty(int id, int property, void* dst) {
1020 //	return sAICallback->getProperty(skirmishAIId, id, property, dst);
1021 	return false;
1022 }
1023 */
GetProperty(int unitId,int propertyId,void * data)1024 bool springLegacyAI::CAIAICallback::GetProperty(int unitId, int propertyId, void *data)
1025 {
1026 	switch (propertyId) {
1027 		case AIVAL_UNITDEF: {
1028 			return false;
1029 		}
1030 		case AIVAL_CURRENT_FUEL: {
1031 			(*(float*)data) = sAICallback->Unit_getCurrentFuel(skirmishAIId, unitId);
1032 			return (*(float*)data) != -1.0f;
1033 		}
1034 		case AIVAL_STOCKPILED: {
1035 			(*(int*)data) = sAICallback->Unit_getStockpile(skirmishAIId, unitId);
1036 			return (*(int*)data) != -1;
1037 		}
1038 		case AIVAL_STOCKPILE_QUED: {
1039 			(*(int*)data) = sAICallback->Unit_getStockpileQueued(skirmishAIId, unitId);
1040 			return (*(int*)data) != -1;
1041 		}
1042 		case AIVAL_UNIT_MAXSPEED: {
1043 			(*(float*) data) = sAICallback->Unit_getMaxSpeed(skirmishAIId, unitId);
1044 			return (*(float*)data) != -1.0f;
1045 		}
1046 		default:
1047 			return false;
1048 	}
1049 	return false;
1050 }
1051 
1052 /*
1053 bool springLegacyAI::CAIAICallback::GetValue(int valueId, void* dst) {
1054 //	return sAICallback->getValue(skirmishAIId, valueId, dst);
1055 	return false;
1056 }
1057 */
GetValue(int valueId,void * data)1058 bool springLegacyAI::CAIAICallback::GetValue(int valueId, void *data)
1059 {
1060 	switch (valueId) {
1061 		case AIVAL_NUMDAMAGETYPES:{
1062 			*((int*)data) = sAICallback->WeaponDef_getNumDamageTypes(skirmishAIId);
1063 			return true;
1064 		}case AIVAL_EXCEPTION_HANDLING:{
1065 			*(bool*)data = sAICallback->Game_isExceptionHandlingEnabled(skirmishAIId);
1066 			return true;
1067 		}case AIVAL_MAP_CHECKSUM:{
1068 			*(unsigned int*)data = sAICallback->Map_getChecksum(skirmishAIId);
1069 			return true;
1070 		}case AIVAL_DEBUG_MODE:{
1071 			*(bool*)data = sAICallback->Game_isDebugModeEnabled(skirmishAIId);
1072 			return true;
1073 		}case AIVAL_GAME_PAUSED:{
1074 			*(bool*)data = sAICallback->Game_isPaused(skirmishAIId);
1075 			return true;
1076 		}case AIVAL_GAME_SPEED_FACTOR:{
1077 			*(float*)data = sAICallback->Game_getSpeedFactor(skirmishAIId);
1078 			return true;
1079 		}case AIVAL_GUI_VIEW_RANGE:{
1080 			*(float*)data = sAICallback->Gui_getViewRange(skirmishAIId);
1081 			return true;
1082 		}case AIVAL_GUI_SCREENX:{
1083 			*(float*)data = sAICallback->Gui_getScreenX(skirmishAIId);
1084 			return true;
1085 		}case AIVAL_GUI_SCREENY:{
1086 			*(float*)data = sAICallback->Gui_getScreenY(skirmishAIId);
1087 			return true;
1088 		}case AIVAL_GUI_CAMERA_DIR:{
1089 			float pos_cache[3];
1090 			sAICallback->Gui_Camera_getDirection(skirmishAIId, pos_cache);
1091 			*(static_cast<float3*>(data)) = pos_cache;
1092 			return true;
1093 		}case AIVAL_GUI_CAMERA_POS:{
1094 			float pos_cache[3];
1095 			sAICallback->Gui_Camera_getPosition(skirmishAIId, pos_cache);
1096 			*(static_cast<float3*>(data)) = pos_cache;
1097 			return true;
1098 		}case AIVAL_LOCATE_FILE_R:{
1099 			//sAICallback->File_locateForReading(skirmishAIId, (char*) data);
1100 			static const size_t absPath_sizeMax = 2048;
1101 			char absPath[absPath_sizeMax];
1102 			bool located = sAICallback->DataDirs_locatePath(skirmishAIId, absPath, absPath_sizeMax, (const char*) data, false, false, false, false);
1103 			// NOTE We can not use STRCPY_T or STRNCPY here, as we do not know
1104 			//   the size of data. It might be below absPath_sizeMax,
1105 			//   and thus we would corrupt the stack.
1106 			STRCPY((char*)data, absPath);
1107 			return located;
1108 		}case AIVAL_LOCATE_FILE_W:{
1109 			//sAICallback->File_locateForWriting(skirmishAIId, (char*) data);
1110 			static const size_t absPath_sizeMax = 2048;
1111 			char absPath[absPath_sizeMax];
1112 			bool located = sAICallback->DataDirs_locatePath(skirmishAIId, absPath, absPath_sizeMax, (const char*) data, true, true, false, false);
1113 			// NOTE We can not use STRCPY_T or STRNCPY here, as we do not know
1114 			//   the size of data. It might be below absPath_sizeMax,
1115 			//   and thus we would corrupt the stack.
1116 			STRCPY((char*)data, absPath);
1117 			return located;
1118 		}
1119 		case AIVAL_UNIT_LIMIT: {
1120 			*(int*) data = sAICallback->Unit_getLimit(skirmishAIId);
1121 			return true;
1122 		}
1123 		case AIVAL_SCRIPT: {
1124 			*(const char**) data = sAICallback->Game_getSetupScript(skirmishAIId);
1125 			return true;
1126 		}
1127 		default:
1128 			return false;
1129 	}
1130 }
1131 
GetFileSize(const char * name)1132 int springLegacyAI::CAIAICallback::GetFileSize(const char* name) {
1133 	return sAICallback->File_getSize(skirmishAIId, name);
1134 }
1135 
GetSelectedUnits(int * unitIds,int unitIds_max)1136 int springLegacyAI::CAIAICallback::GetSelectedUnits(int* unitIds, int unitIds_max) {
1137 	return sAICallback->getSelectedUnits(skirmishAIId, unitIds, unitIds_max);
1138 }
1139 
GetMousePos()1140 float3 springLegacyAI::CAIAICallback::GetMousePos() {
1141 
1142 	float pos_cache[3];
1143 	sAICallback->Map_getMousePos(skirmishAIId, pos_cache);
1144 	return pos_cache;
1145 }
1146 
GetMapPoints(PointMarker * pm,int pm_sizeMax,bool includeAllies)1147 int springLegacyAI::CAIAICallback::GetMapPoints(PointMarker* pm, int pm_sizeMax, bool includeAllies) {
1148 
1149 	const int numPoints = sAICallback->Map_getPoints(skirmishAIId, includeAllies);
1150 	float pos_cache[3];
1151 	short color_cache[3];
1152 	for (int p=0; p < numPoints; ++p) {
1153 		sAICallback->Map_Point_getPosition(skirmishAIId, p, pos_cache);
1154 		pm[p].pos = pos_cache; // float[3] -> float3
1155 		sAICallback->Map_Point_getColor(skirmishAIId, p, color_cache);
1156 		unsigned char* color = (unsigned char*) calloc(3, sizeof(unsigned char));
1157 		color[0] = (unsigned char) color_cache[0];
1158 		color[1] = (unsigned char) color_cache[1];
1159 		color[2] = (unsigned char) color_cache[2];
1160 		pm[p].color = color;
1161 		pm[p].label = sAICallback->Map_Point_getLabel(skirmishAIId, p);
1162 	}
1163 
1164 	return numPoints;
1165 }
1166 
GetMapLines(LineMarker * lm,int lm_sizeMax,bool includeAllies)1167 int springLegacyAI::CAIAICallback::GetMapLines(LineMarker* lm, int lm_sizeMax, bool includeAllies) {
1168 
1169 	const int numLines = sAICallback->Map_getLines(skirmishAIId, includeAllies);
1170 	float pos_cache[3];
1171 	short color_cache[3];
1172 	for (int l=0; l < numLines; ++l) {
1173 		sAICallback->Map_Line_getFirstPosition(skirmishAIId, l, pos_cache);
1174 		lm[l].pos = pos_cache; // float[3] -> float3
1175 		sAICallback->Map_Line_getSecondPosition(skirmishAIId, l, pos_cache);
1176 		lm[l].pos2 = pos_cache; // float[3] -> float3
1177 		sAICallback->Map_Line_getColor(skirmishAIId, l, color_cache);
1178 		unsigned char* color = (unsigned char*) calloc(3, sizeof(unsigned char));
1179 		color[0] = (unsigned char) color_cache[0];
1180 		color[1] = (unsigned char) color_cache[1];
1181 		color[2] = (unsigned char) color_cache[2];
1182 		lm[l].color = color;
1183 	}
1184 
1185 	return numLines;
1186 }
1187 
GetMetal()1188 float springLegacyAI::CAIAICallback::GetMetal() {
1189 	int m = getResourceId_Metal(sAICallback, skirmishAIId);
1190 	return sAICallback->Economy_getCurrent(skirmishAIId, m);
1191 }
1192 
GetMetalIncome()1193 float springLegacyAI::CAIAICallback::GetMetalIncome() {
1194 	int m = getResourceId_Metal(sAICallback, skirmishAIId);
1195 	return sAICallback->Economy_getIncome(skirmishAIId, m);
1196 }
1197 
GetMetalUsage()1198 float springLegacyAI::CAIAICallback::GetMetalUsage() {
1199 	int m = getResourceId_Metal(sAICallback, skirmishAIId);
1200 	return sAICallback->Economy_getUsage(skirmishAIId, m);
1201 }
1202 
GetMetalStorage()1203 float springLegacyAI::CAIAICallback::GetMetalStorage() {
1204 	int m = getResourceId_Metal(sAICallback, skirmishAIId);
1205 	return sAICallback->Economy_getStorage(skirmishAIId, m);
1206 }
1207 
GetEnergy()1208 float springLegacyAI::CAIAICallback::GetEnergy() {
1209 	int e = getResourceId_Energy(sAICallback, skirmishAIId);
1210 	return sAICallback->Economy_getCurrent(skirmishAIId, e);
1211 }
1212 
GetEnergyIncome()1213 float springLegacyAI::CAIAICallback::GetEnergyIncome() {
1214 	int e = getResourceId_Energy(sAICallback, skirmishAIId);
1215 	return sAICallback->Economy_getIncome(skirmishAIId, e);
1216 }
1217 
GetEnergyUsage()1218 float springLegacyAI::CAIAICallback::GetEnergyUsage() {
1219 	int e = getResourceId_Energy(sAICallback, skirmishAIId);
1220 	return sAICallback->Economy_getUsage(skirmishAIId, e);
1221 }
1222 
GetEnergyStorage()1223 float springLegacyAI::CAIAICallback::GetEnergyStorage() {
1224 	int e = getResourceId_Energy(sAICallback, skirmishAIId);
1225 	return sAICallback->Economy_getStorage(skirmishAIId, e);
1226 }
1227 
GetFeatures(int * featureIds,int featureIds_max)1228 int springLegacyAI::CAIAICallback::GetFeatures(int* featureIds, int featureIds_max) {
1229 	return sAICallback->getFeatures(skirmishAIId, featureIds, featureIds_max);
1230 }
1231 
GetFeatures(int * featureIds,int featureIds_max,const float3 & pos,float radius)1232 int springLegacyAI::CAIAICallback::GetFeatures(int *featureIds, int featureIds_max, const float3& pos, float radius) {
1233 
1234 	float aiPos[3];
1235 	pos.copyInto(aiPos);
1236 	return sAICallback->getFeaturesIn(skirmishAIId, aiPos, radius, featureIds, featureIds_max);
1237 }
1238 
GetFeatureDef(int featureId)1239 const springLegacyAI::FeatureDef* springLegacyAI::CAIAICallback::GetFeatureDef(int featureId) {
1240 	int featureDefId = sAICallback->Feature_getDef(skirmishAIId, featureId);
1241 	return this->GetFeatureDefById(featureDefId);
1242 }
1243 
GetFeatureDefById(int featureDefId)1244 const springLegacyAI::FeatureDef* springLegacyAI::CAIAICallback::GetFeatureDefById(int featureDefId) {
1245 
1246 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
1247 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
1248 
1249 	if (featureDefId < 0) {
1250 		return NULL;
1251 	}
1252 
1253 	bool doRecreate = featureDefFrames[featureDefId] < 0;
1254 	if (doRecreate) {
1255 //		int currentFrame = this->GetCurrentFrame();
1256 		int currentFrame = 1;
1257 	FeatureDef* featureDef = new FeatureDef();
1258 featureDef->myName = sAICallback->FeatureDef_getName(skirmishAIId, featureDefId);
1259 featureDef->description = sAICallback->FeatureDef_getDescription(skirmishAIId, featureDefId);
1260 featureDef->filename = sAICallback->FeatureDef_getFileName(skirmishAIId, featureDefId);
1261 //featureDef->id = sAICallback->FeatureDef_getId(skirmishAIId, featureDefId);
1262 featureDef->id = featureDefId;
1263 featureDef->metal = sAICallback->FeatureDef_getContainedResource(skirmishAIId, featureDefId, m);
1264 featureDef->energy = sAICallback->FeatureDef_getContainedResource(skirmishAIId, featureDefId, e);
1265 featureDef->maxHealth = sAICallback->FeatureDef_getMaxHealth(skirmishAIId, featureDefId);
1266 featureDef->reclaimTime = sAICallback->FeatureDef_getReclaimTime(skirmishAIId, featureDefId);
1267 featureDef->mass = sAICallback->FeatureDef_getMass(skirmishAIId, featureDefId);
1268 featureDef->upright = sAICallback->FeatureDef_isUpright(skirmishAIId, featureDefId);
1269 featureDef->drawType = sAICallback->FeatureDef_getDrawType(skirmishAIId, featureDefId);
1270 featureDef->modelname = sAICallback->FeatureDef_getModelName(skirmishAIId, featureDefId);
1271 featureDef->resurrectable = sAICallback->FeatureDef_getResurrectable(skirmishAIId, featureDefId);
1272 featureDef->smokeTime = sAICallback->FeatureDef_getSmokeTime(skirmishAIId, featureDefId);
1273 featureDef->destructable = sAICallback->FeatureDef_isDestructable(skirmishAIId, featureDefId);
1274 featureDef->reclaimable = sAICallback->FeatureDef_isReclaimable(skirmishAIId, featureDefId);
1275 featureDef->blocking = sAICallback->FeatureDef_isBlocking(skirmishAIId, featureDefId);
1276 featureDef->burnable = sAICallback->FeatureDef_isBurnable(skirmishAIId, featureDefId);
1277 featureDef->floating = sAICallback->FeatureDef_isFloating(skirmishAIId, featureDefId);
1278 featureDef->noSelect = sAICallback->FeatureDef_isNoSelect(skirmishAIId, featureDefId);
1279 featureDef->geoThermal = sAICallback->FeatureDef_isGeoThermal(skirmishAIId, featureDefId);
1280 featureDef->deathFeature = sAICallback->FeatureDef_getDeathFeature(skirmishAIId, featureDefId);
1281 featureDef->xsize = sAICallback->FeatureDef_getXSize(skirmishAIId, featureDefId);
1282 featureDef->zsize = sAICallback->FeatureDef_getZSize(skirmishAIId, featureDefId);
1283 {
1284 	const int size = sAICallback->FeatureDef_getCustomParams(skirmishAIId, featureDefId, NULL, NULL);
1285 	featureDef->customParams = std::map<std::string,std::string>();
1286 	const char** cKeys = (const char**) calloc(size, sizeof(char*));
1287 	const char** cValues = (const char**) calloc(size, sizeof(char*));
1288 	sAICallback->FeatureDef_getCustomParams(skirmishAIId, featureDefId, cKeys, cValues);
1289 	int i;
1290 	for (i=0; i < size; ++i) {
1291 		featureDef->customParams[cKeys[i]] = cValues[i];
1292 	}
1293 	free(cKeys);
1294 	free(cValues);
1295 }
1296 	if (featureDefs[featureDefId] != NULL) {
1297 		delete featureDefs[featureDefId];
1298 	}
1299 		featureDefs[featureDefId] = featureDef;
1300 		featureDefFrames[featureDefId] = currentFrame;
1301 	}
1302 
1303 	return featureDefs[featureDefId];
1304 }
1305 
GetFeatureHealth(int featureId)1306 float springLegacyAI::CAIAICallback::GetFeatureHealth(int featureId) {
1307 	return sAICallback->Feature_getHealth(skirmishAIId, featureId);
1308 }
1309 
GetFeatureReclaimLeft(int featureId)1310 float springLegacyAI::CAIAICallback::GetFeatureReclaimLeft(int featureId) {
1311 	return sAICallback->Feature_getReclaimLeft(skirmishAIId, featureId);
1312 }
1313 
GetFeaturePos(int featureId)1314 float3 springLegacyAI::CAIAICallback::GetFeaturePos(int featureId) {
1315 
1316 	float pos_cache[3];
1317 	sAICallback->Feature_getPosition(skirmishAIId, featureId, pos_cache);
1318 	return pos_cache;
1319 }
1320 
GetNumUnitDefs()1321 int springLegacyAI::CAIAICallback::GetNumUnitDefs() {
1322 	return sAICallback->getUnitDefs(skirmishAIId, NULL, 0);
1323 }
1324 
GetUnitDefList(const UnitDef ** list)1325 void springLegacyAI::CAIAICallback::GetUnitDefList(const UnitDef** list) {
1326 
1327 	int size = sAICallback->getUnitDefs(skirmishAIId, NULL, 0);
1328 	int* unitDefIds = new int[size];
1329 
1330 	// get actual number of IDs
1331 	size = sAICallback->getUnitDefs(skirmishAIId, unitDefIds, size);
1332 
1333 	for (int i = 0; i < size; ++i) {
1334 		list[i] = this->GetUnitDefById(unitDefIds[i]);
1335 	}
1336 
1337 	delete[] unitDefIds;
1338 }
1339 
GetUnitDefHeight(int def)1340 float springLegacyAI::CAIAICallback::GetUnitDefHeight(int def) {
1341 	return sAICallback->UnitDef_getHeight(skirmishAIId, def);
1342 }
1343 
GetUnitDefRadius(int def)1344 float springLegacyAI::CAIAICallback::GetUnitDefRadius(int def) {
1345 	return sAICallback->UnitDef_getRadius(skirmishAIId, def);
1346 }
1347 
GetWeapon(const char * weaponName)1348 const springLegacyAI::WeaponDef* springLegacyAI::CAIAICallback::GetWeapon(const char* weaponName) {
1349 	int weaponDefId = sAICallback->getWeaponDefByName(skirmishAIId, weaponName);
1350 	return this->GetWeaponDefById(weaponDefId);
1351 }
1352 
GetWeaponDefById(int weaponDefId)1353 const springLegacyAI::WeaponDef* springLegacyAI::CAIAICallback::GetWeaponDefById(int weaponDefId) {
1354 
1355 	static int m = getResourceId_Metal(sAICallback, skirmishAIId);
1356 	static int e = getResourceId_Energy(sAICallback, skirmishAIId);
1357 
1358 //	logT("entering: GetWeaponDefById sAICallback");
1359 	if (weaponDefId < 0) {
1360 		return NULL;
1361 	}
1362 
1363 	bool doRecreate = weaponDefFrames[weaponDefId] < 0;
1364 	if (doRecreate) {
1365 //		int currentFrame = this->GetCurrentFrame();
1366 		int currentFrame = 1;
1367 //weaponDef->damages = sAICallback->WeaponDef_getDamages(skirmishAIId, weaponDefId);
1368 //{
1369 int numTypes = sAICallback->WeaponDef_Damage_getTypes(skirmishAIId, weaponDefId, NULL, 0);
1370 //	logT("GetWeaponDefById 1");
1371 //float* typeDamages = new float[numTypes];
1372 float* typeDamages = (float*) calloc(numTypes, sizeof(float));
1373 numTypes = sAICallback->WeaponDef_Damage_getTypes(skirmishAIId, weaponDefId, typeDamages, numTypes);
1374 //	logT("GetWeaponDefById 2");
1375 //for(int i=0; i < numTypes; ++i) {
1376 //	typeDamages[i] = sAICallback->WeaponDef_Damages_getType(skirmishAIId, weaponDefId, i);
1377 //}
1378 DamageArray da(numTypes, typeDamages);
1379 // DamageArray is copying the array internaly, so it does no harm freeing it here
1380 free(typeDamages);
1381 //	logT("GetWeaponDefById 3");
1382 //AIDamageArray tmpDa(numTypes, typeDamages);
1383 //AIDamageArray tmpDa;
1384 //weaponDef->damages = *(reinterpret_cast<DamageArray*>(&tmpDa));
1385 //tmpDa.numTypes = numTypes;
1386 //tmpDa.damages = typeDamages;
1387 //delete tmpDa;
1388 //da.SetTypes(numTypes, typeDamages);
1389 //delete [] typeDamages;
1390 da.paralyzeDamageTime = sAICallback->WeaponDef_Damage_getParalyzeDamageTime(skirmishAIId, weaponDefId);
1391 da.impulseFactor = sAICallback->WeaponDef_Damage_getImpulseFactor(skirmishAIId, weaponDefId);
1392 da.impulseBoost = sAICallback->WeaponDef_Damage_getImpulseBoost(skirmishAIId, weaponDefId);
1393 da.craterMult = sAICallback->WeaponDef_Damage_getCraterMult(skirmishAIId, weaponDefId);
1394 da.craterBoost = sAICallback->WeaponDef_Damage_getCraterBoost(skirmishAIId, weaponDefId);
1395 //	logT("GetWeaponDefById 4");
1396 //}
1397 
1398 	short color_cache[3];
1399 	WeaponDef* weaponDef = new WeaponDef(da);
1400 //	WeaponDef* weaponDef = new WeaponDef();
1401 //	logT("GetWeaponDefById 5");
1402 //	logI("GetWeaponDefById 5 defId: %d", weaponDefId);
1403 weaponDef->name = sAICallback->WeaponDef_getName(skirmishAIId, weaponDefId);
1404 weaponDef->type = sAICallback->WeaponDef_getType(skirmishAIId, weaponDefId);
1405 weaponDef->description = sAICallback->WeaponDef_getDescription(skirmishAIId, weaponDefId);
1406 weaponDef->filename = sAICallback->WeaponDef_getFileName(skirmishAIId, weaponDefId);
1407 weaponDef->cegTag = sAICallback->WeaponDef_getCegTag(skirmishAIId, weaponDefId);
1408 weaponDef->range = sAICallback->WeaponDef_getRange(skirmishAIId, weaponDefId);
1409 weaponDef->heightmod = sAICallback->WeaponDef_getHeightMod(skirmishAIId, weaponDefId);
1410 weaponDef->accuracy = sAICallback->WeaponDef_getAccuracy(skirmishAIId, weaponDefId);
1411 weaponDef->sprayAngle = sAICallback->WeaponDef_getSprayAngle(skirmishAIId, weaponDefId);
1412 weaponDef->movingAccuracy = sAICallback->WeaponDef_getMovingAccuracy(skirmishAIId, weaponDefId);
1413 weaponDef->targetMoveError = sAICallback->WeaponDef_getTargetMoveError(skirmishAIId, weaponDefId);
1414 weaponDef->leadLimit = sAICallback->WeaponDef_getLeadLimit(skirmishAIId, weaponDefId);
1415 weaponDef->leadBonus = sAICallback->WeaponDef_getLeadBonus(skirmishAIId, weaponDefId);
1416 weaponDef->predictBoost = sAICallback->WeaponDef_getPredictBoost(skirmishAIId, weaponDefId);
1417 weaponDef->areaOfEffect = sAICallback->WeaponDef_getAreaOfEffect(skirmishAIId, weaponDefId);
1418 weaponDef->noSelfDamage = sAICallback->WeaponDef_isNoSelfDamage(skirmishAIId, weaponDefId);
1419 weaponDef->fireStarter = sAICallback->WeaponDef_getFireStarter(skirmishAIId, weaponDefId);
1420 weaponDef->edgeEffectiveness = sAICallback->WeaponDef_getEdgeEffectiveness(skirmishAIId, weaponDefId);
1421 weaponDef->size = sAICallback->WeaponDef_getSize(skirmishAIId, weaponDefId);
1422 weaponDef->sizeGrowth = sAICallback->WeaponDef_getSizeGrowth(skirmishAIId, weaponDefId);
1423 weaponDef->collisionSize = sAICallback->WeaponDef_getCollisionSize(skirmishAIId, weaponDefId);
1424 weaponDef->salvosize = sAICallback->WeaponDef_getSalvoSize(skirmishAIId, weaponDefId);
1425 weaponDef->salvodelay = sAICallback->WeaponDef_getSalvoDelay(skirmishAIId, weaponDefId);
1426 weaponDef->reload = sAICallback->WeaponDef_getReload(skirmishAIId, weaponDefId);
1427 weaponDef->beamtime = sAICallback->WeaponDef_getBeamTime(skirmishAIId, weaponDefId);
1428 weaponDef->beamburst = sAICallback->WeaponDef_isBeamBurst(skirmishAIId, weaponDefId);
1429 weaponDef->waterBounce = sAICallback->WeaponDef_isWaterBounce(skirmishAIId, weaponDefId);
1430 weaponDef->groundBounce = sAICallback->WeaponDef_isGroundBounce(skirmishAIId, weaponDefId);
1431 weaponDef->bounceRebound = sAICallback->WeaponDef_getBounceRebound(skirmishAIId, weaponDefId);
1432 weaponDef->bounceSlip = sAICallback->WeaponDef_getBounceSlip(skirmishAIId, weaponDefId);
1433 weaponDef->numBounce = sAICallback->WeaponDef_getNumBounce(skirmishAIId, weaponDefId);
1434 weaponDef->maxAngle = sAICallback->WeaponDef_getMaxAngle(skirmishAIId, weaponDefId);
1435 weaponDef->uptime = sAICallback->WeaponDef_getUpTime(skirmishAIId, weaponDefId);
1436 weaponDef->flighttime = sAICallback->WeaponDef_getFlightTime(skirmishAIId, weaponDefId);
1437 weaponDef->metalcost = sAICallback->WeaponDef_getCost(skirmishAIId, weaponDefId, m);
1438 weaponDef->energycost = sAICallback->WeaponDef_getCost(skirmishAIId, weaponDefId, e);
1439 weaponDef->projectilespershot = sAICallback->WeaponDef_getProjectilesPerShot(skirmishAIId, weaponDefId);
1440 //weaponDef->id = sAICallback->WeaponDef_getId(skirmishAIId, weaponDefId);
1441 weaponDef->id = weaponDefId;
1442 //weaponDef->tdfId = sAICallback->WeaponDef_getTdfId(skirmishAIId, weaponDefId);
1443 weaponDef->tdfId = -1;
1444 weaponDef->turret = sAICallback->WeaponDef_isTurret(skirmishAIId, weaponDefId);
1445 weaponDef->onlyForward = sAICallback->WeaponDef_isOnlyForward(skirmishAIId, weaponDefId);
1446 weaponDef->fixedLauncher = sAICallback->WeaponDef_isFixedLauncher(skirmishAIId, weaponDefId);
1447 weaponDef->waterweapon = sAICallback->WeaponDef_isWaterWeapon(skirmishAIId, weaponDefId);
1448 weaponDef->fireSubmersed = sAICallback->WeaponDef_isFireSubmersed(skirmishAIId, weaponDefId);
1449 weaponDef->submissile = sAICallback->WeaponDef_isSubMissile(skirmishAIId, weaponDefId);
1450 weaponDef->tracks = sAICallback->WeaponDef_isTracks(skirmishAIId, weaponDefId);
1451 weaponDef->dropped = sAICallback->WeaponDef_isDropped(skirmishAIId, weaponDefId);
1452 weaponDef->paralyzer = sAICallback->WeaponDef_isParalyzer(skirmishAIId, weaponDefId);
1453 weaponDef->impactOnly = sAICallback->WeaponDef_isImpactOnly(skirmishAIId, weaponDefId);
1454 weaponDef->noAutoTarget = sAICallback->WeaponDef_isNoAutoTarget(skirmishAIId, weaponDefId);
1455 weaponDef->manualfire = sAICallback->WeaponDef_isManualFire(skirmishAIId, weaponDefId);
1456 weaponDef->interceptor = sAICallback->WeaponDef_getInterceptor(skirmishAIId, weaponDefId);
1457 weaponDef->targetable = sAICallback->WeaponDef_getTargetable(skirmishAIId, weaponDefId);
1458 weaponDef->stockpile = sAICallback->WeaponDef_isStockpileable(skirmishAIId, weaponDefId);
1459 weaponDef->coverageRange = sAICallback->WeaponDef_getCoverageRange(skirmishAIId, weaponDefId);
1460 weaponDef->stockpileTime = sAICallback->WeaponDef_getStockpileTime(skirmishAIId, weaponDefId);
1461 weaponDef->intensity = sAICallback->WeaponDef_getIntensity(skirmishAIId, weaponDefId);
1462 weaponDef->thickness = sAICallback->WeaponDef_getThickness(skirmishAIId, weaponDefId);
1463 weaponDef->laserflaresize = sAICallback->WeaponDef_getLaserFlareSize(skirmishAIId, weaponDefId);
1464 weaponDef->corethickness = sAICallback->WeaponDef_getCoreThickness(skirmishAIId, weaponDefId);
1465 weaponDef->duration = sAICallback->WeaponDef_getDuration(skirmishAIId, weaponDefId);
1466 weaponDef->lodDistance = sAICallback->WeaponDef_getLodDistance(skirmishAIId, weaponDefId);
1467 weaponDef->falloffRate = sAICallback->WeaponDef_getFalloffRate(skirmishAIId, weaponDefId);
1468 weaponDef->graphicsType = sAICallback->WeaponDef_getGraphicsType(skirmishAIId, weaponDefId);
1469 weaponDef->soundTrigger = sAICallback->WeaponDef_isSoundTrigger(skirmishAIId, weaponDefId);
1470 weaponDef->selfExplode = sAICallback->WeaponDef_isSelfExplode(skirmishAIId, weaponDefId);
1471 weaponDef->gravityAffected = sAICallback->WeaponDef_isGravityAffected(skirmishAIId, weaponDefId);
1472 weaponDef->highTrajectory = sAICallback->WeaponDef_getHighTrajectory(skirmishAIId, weaponDefId);
1473 weaponDef->myGravity = sAICallback->WeaponDef_getMyGravity(skirmishAIId, weaponDefId);
1474 weaponDef->noExplode = sAICallback->WeaponDef_isNoExplode(skirmishAIId, weaponDefId);
1475 weaponDef->startvelocity = sAICallback->WeaponDef_getStartVelocity(skirmishAIId, weaponDefId);
1476 weaponDef->weaponacceleration = sAICallback->WeaponDef_getWeaponAcceleration(skirmishAIId, weaponDefId);
1477 weaponDef->turnrate = sAICallback->WeaponDef_getTurnRate(skirmishAIId, weaponDefId);
1478 weaponDef->maxvelocity = sAICallback->WeaponDef_getMaxVelocity(skirmishAIId, weaponDefId);
1479 weaponDef->projectilespeed = sAICallback->WeaponDef_getProjectileSpeed(skirmishAIId, weaponDefId);
1480 weaponDef->explosionSpeed = sAICallback->WeaponDef_getExplosionSpeed(skirmishAIId, weaponDefId);
1481 weaponDef->onlyTargetCategory = sAICallback->WeaponDef_getOnlyTargetCategory(skirmishAIId, weaponDefId);
1482 weaponDef->wobble = sAICallback->WeaponDef_getWobble(skirmishAIId, weaponDefId);
1483 weaponDef->dance = sAICallback->WeaponDef_getDance(skirmishAIId, weaponDefId);
1484 weaponDef->trajectoryHeight = sAICallback->WeaponDef_getTrajectoryHeight(skirmishAIId, weaponDefId);
1485 weaponDef->largeBeamLaser = sAICallback->WeaponDef_isLargeBeamLaser(skirmishAIId, weaponDefId);
1486 weaponDef->isShield = sAICallback->WeaponDef_isShield(skirmishAIId, weaponDefId);
1487 weaponDef->shieldRepulser = sAICallback->WeaponDef_isShieldRepulser(skirmishAIId, weaponDefId);
1488 weaponDef->smartShield = sAICallback->WeaponDef_isSmartShield(skirmishAIId, weaponDefId);
1489 weaponDef->exteriorShield = sAICallback->WeaponDef_isExteriorShield(skirmishAIId, weaponDefId);
1490 weaponDef->visibleShield = sAICallback->WeaponDef_isVisibleShield(skirmishAIId, weaponDefId);
1491 weaponDef->visibleShieldRepulse = sAICallback->WeaponDef_isVisibleShieldRepulse(skirmishAIId, weaponDefId);
1492 weaponDef->visibleShieldHitFrames = sAICallback->WeaponDef_getVisibleShieldHitFrames(skirmishAIId, weaponDefId);
1493 weaponDef->shieldEnergyUse = sAICallback->WeaponDef_Shield_getResourceUse(skirmishAIId, weaponDefId, e);
1494 weaponDef->shieldRadius = sAICallback->WeaponDef_Shield_getRadius(skirmishAIId, weaponDefId);
1495 weaponDef->shieldForce = sAICallback->WeaponDef_Shield_getForce(skirmishAIId, weaponDefId);
1496 weaponDef->shieldMaxSpeed = sAICallback->WeaponDef_Shield_getMaxSpeed(skirmishAIId, weaponDefId);
1497 weaponDef->shieldPower = sAICallback->WeaponDef_Shield_getPower(skirmishAIId, weaponDefId);
1498 weaponDef->shieldPowerRegen = sAICallback->WeaponDef_Shield_getPowerRegen(skirmishAIId, weaponDefId);
1499 weaponDef->shieldPowerRegenEnergy = sAICallback->WeaponDef_Shield_getPowerRegenResource(skirmishAIId, weaponDefId, e);
1500 weaponDef->shieldStartingPower = sAICallback->WeaponDef_Shield_getStartingPower(skirmishAIId, weaponDefId);
1501 weaponDef->shieldRechargeDelay = sAICallback->WeaponDef_Shield_getRechargeDelay(skirmishAIId, weaponDefId);
1502 sAICallback->WeaponDef_Shield_getGoodColor(skirmishAIId, weaponDefId, color_cache);
1503 weaponDef->shieldGoodColor = float3((float)color_cache[0] / 256.0f, (float)color_cache[1] / 256.0f, (float)color_cache[2] / 256.0f);
1504 sAICallback->WeaponDef_Shield_getBadColor(skirmishAIId, weaponDefId, color_cache);
1505 weaponDef->shieldBadColor = float3((float)color_cache[0] / 256.0f, (float)color_cache[1] / 256.0f, (float)color_cache[2] / 256.0f);
1506 weaponDef->shieldAlpha = sAICallback->WeaponDef_Shield_getAlpha(skirmishAIId, weaponDefId) / 256.0f;
1507 weaponDef->shieldInterceptType = sAICallback->WeaponDef_Shield_getInterceptType(skirmishAIId, weaponDefId);
1508 weaponDef->interceptedByShieldType = sAICallback->WeaponDef_getInterceptedByShieldType(skirmishAIId, weaponDefId);
1509 weaponDef->avoidFriendly = sAICallback->WeaponDef_isAvoidFriendly(skirmishAIId, weaponDefId);
1510 weaponDef->avoidFeature = sAICallback->WeaponDef_isAvoidFeature(skirmishAIId, weaponDefId);
1511 weaponDef->avoidNeutral = sAICallback->WeaponDef_isAvoidNeutral(skirmishAIId, weaponDefId);
1512 weaponDef->targetBorder = sAICallback->WeaponDef_getTargetBorder(skirmishAIId, weaponDefId);
1513 weaponDef->cylinderTargetting = sAICallback->WeaponDef_getCylinderTargetting(skirmishAIId, weaponDefId);
1514 weaponDef->minIntensity = sAICallback->WeaponDef_getMinIntensity(skirmishAIId, weaponDefId);
1515 weaponDef->heightBoostFactor = sAICallback->WeaponDef_getHeightBoostFactor(skirmishAIId, weaponDefId);
1516 weaponDef->proximityPriority = sAICallback->WeaponDef_getProximityPriority(skirmishAIId, weaponDefId);
1517 weaponDef->collisionFlags = sAICallback->WeaponDef_getCollisionFlags(skirmishAIId, weaponDefId);
1518 weaponDef->sweepFire = sAICallback->WeaponDef_isSweepFire(skirmishAIId, weaponDefId);
1519 weaponDef->canAttackGround = sAICallback->WeaponDef_isAbleToAttackGround(skirmishAIId, weaponDefId);
1520 weaponDef->cameraShake = sAICallback->WeaponDef_getCameraShake(skirmishAIId, weaponDefId);
1521 weaponDef->dynDamageExp = sAICallback->WeaponDef_getDynDamageExp(skirmishAIId, weaponDefId);
1522 weaponDef->dynDamageMin = sAICallback->WeaponDef_getDynDamageMin(skirmishAIId, weaponDefId);
1523 weaponDef->dynDamageRange = sAICallback->WeaponDef_getDynDamageRange(skirmishAIId, weaponDefId);
1524 weaponDef->dynDamageInverted = sAICallback->WeaponDef_isDynDamageInverted(skirmishAIId, weaponDefId);
1525 {
1526 	const int size = sAICallback->WeaponDef_getCustomParams(skirmishAIId, weaponDefId, NULL, NULL);
1527 	weaponDef->customParams = std::map<std::string,std::string>();
1528 	const char** cKeys = (const char**) calloc(size, sizeof(char*));
1529 	const char** cValues = (const char**) calloc(size, sizeof(char*));
1530 	sAICallback->WeaponDef_getCustomParams(skirmishAIId, weaponDefId, cKeys, cValues);
1531 	int i;
1532 	for (i=0; i < size; ++i) {
1533 		weaponDef->customParams[cKeys[i]] = cValues[i];
1534 	}
1535 	free(cKeys);
1536 	free(cValues);
1537 }
1538 	if (weaponDefs[weaponDefId] != NULL) {
1539 		delete weaponDefs[weaponDefId];
1540 	}
1541 		weaponDefs[weaponDefId] = weaponDef;
1542 		weaponDefFrames[weaponDefId] = currentFrame;
1543 	}
1544 
1545 	return weaponDefs[weaponDefId];
1546 }
1547 
GetStartPos()1548 const float3* springLegacyAI::CAIAICallback::GetStartPos() {
1549 
1550 	float pos_cache[3];
1551 	sAICallback->Map_getStartPos(skirmishAIId, pos_cache);
1552 	startPos = pos_cache;
1553 
1554 	return &startPos;
1555 }
1556 
GetCategoryFlag(const char * categoryName)1557 unsigned int springLegacyAI::CAIAICallback::GetCategoryFlag(const char* categoryName) {
1558 	return sAICallback->Game_getCategoryFlag(skirmishAIId, categoryName);
1559 }
1560 
GetCategoriesFlag(const char * categoryNames)1561 unsigned int springLegacyAI::CAIAICallback::GetCategoriesFlag(const char* categoryNames) {
1562 	return sAICallback->Game_getCategoriesFlag(skirmishAIId, categoryNames);
1563 }
1564 
GetCategoryName(int categoryFlag,char * name,int name_sizeMax)1565 void springLegacyAI::CAIAICallback::GetCategoryName(int categoryFlag, char* name, int name_sizeMax) {
1566 	sAICallback->Game_getCategoryName(skirmishAIId, categoryFlag, name, name_sizeMax);
1567 }
1568 
1569 
1570 
1571 
1572 
1573 
1574 
SendTextMsg(const char * text,int zone)1575 void springLegacyAI::CAIAICallback::SendTextMsg(const char* text, int zone) {
1576 
1577 	SSendTextMessageCommand cmd = {text, zone};
1578 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SEND_TEXT_MESSAGE, &cmd);
1579 }
1580 
SetLastMsgPos(float3 pos)1581 void springLegacyAI::CAIAICallback::SetLastMsgPos(float3 pos) {
1582 
1583 	float pos_f3[3];
1584 	pos.copyInto(pos_f3);
1585 
1586 	SSetLastPosMessageCommand cmd = {pos_f3};
1587 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SET_LAST_POS_MESSAGE, &cmd);
1588 }
1589 
AddNotification(float3 pos,float3 color,float alpha)1590 void springLegacyAI::CAIAICallback::AddNotification(float3 pos, float3 color, float alpha) {
1591 
1592 	float pos_f3[3];
1593 	pos.copyInto(pos_f3);
1594 	short color_s3[3];
1595 	color_s3[0] = (short) color[0] * 256;
1596 	color_s3[1] = (short) color[1] * 256;
1597 	color_s3[2] = (short) color[2] * 256;
1598 	const short alpha_s = (short) alpha * 256;
1599 
1600 	SAddNotificationDrawerCommand cmd = {pos_f3, color_s3, alpha_s};
1601 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_ADD_NOTIFICATION, &cmd);
1602 }
1603 
SendResources(float mAmount,float eAmount,int receivingTeam)1604 bool springLegacyAI::CAIAICallback::SendResources(float mAmount, float eAmount, int receivingTeam) {
1605 
1606 	SSendResourcesCommand cmd = {static_cast<int>(mAmount), eAmount, receivingTeam};
1607 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SEND_RESOURCES, &cmd);
1608 	return cmd.ret_isExecuted;
1609 }
1610 
SendUnits(const std::vector<int> & unitIds,int receivingTeam)1611 int springLegacyAI::CAIAICallback::SendUnits(const std::vector<int>& unitIds, int receivingTeam) {
1612 
1613 	int* arr_unitIds = (int*) calloc(unitIds.size(), sizeof(int));
1614 	for (size_t i=0; i < unitIds.size(); ++i) {
1615 		arr_unitIds[i] = unitIds[i];
1616 	}
1617 	SSendUnitsCommand cmd = {arr_unitIds, static_cast<int>(unitIds.size()), receivingTeam};
1618 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SEND_UNITS, &cmd);
1619 	free(arr_unitIds);
1620 	return cmd.ret_sentUnits;
1621 }
1622 
CreateSharedMemArea(char * name,int size)1623 void* springLegacyAI::CAIAICallback::CreateSharedMemArea(char* name, int size) {
1624 
1625 	//SCreateSharedMemAreaCommand cmd = {name, size};
1626 	//sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SHARED_MEM_AREA_CREATE, &cmd);
1627 	//return cmd.ret_sharedMemArea;
1628 	static const bool deprecatedMethod = true;
1629 	assert(!deprecatedMethod);
1630 	return NULL;
1631 }
1632 
ReleasedSharedMemArea(char * name)1633 void springLegacyAI::CAIAICallback::ReleasedSharedMemArea(char* name) {
1634 
1635 	//SReleaseSharedMemAreaCommand cmd = {name};
1636 	//sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SHARED_MEM_AREA_RELEASE, &cmd);
1637 	static const bool deprecatedMethod = true;
1638 	assert(!deprecatedMethod);
1639 }
1640 
CreateGroup()1641 int springLegacyAI::CAIAICallback::CreateGroup() {
1642 
1643 	SCreateGroupCommand cmd = {};
1644 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_GROUP_CREATE, &cmd);
1645 	return cmd.ret_groupId;
1646 }
1647 
EraseGroup(int groupId)1648 void springLegacyAI::CAIAICallback::EraseGroup(int groupId) {
1649 
1650 	SEraseGroupCommand cmd = {groupId};
1651 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_GROUP_ERASE, &cmd);
1652 }
1653 
AddUnitToGroup(int unitId,int groupId)1654 bool springLegacyAI::CAIAICallback::AddUnitToGroup(int unitId, int groupId) {
1655 
1656 	SGroupAddUnitCommand cmd = {unitId, -1, 0, 0, groupId};
1657 	const int ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_UNIT_GROUP_ADD, &cmd);
1658 	return (ret == 0);
1659 }
1660 
RemoveUnitFromGroup(int unitId)1661 bool springLegacyAI::CAIAICallback::RemoveUnitFromGroup(int unitId) {
1662 
1663 	SGroupAddUnitCommand cmd = {unitId, -1, 0, 0};
1664 	const int ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_UNIT_GROUP_CLEAR, &cmd);
1665 	return (ret == 0);
1666 }
1667 
GiveGroupOrder(int groupId,springLegacyAI::Command * c)1668 int springLegacyAI::CAIAICallback::GiveGroupOrder(int groupId, springLegacyAI::Command* c) {
1669 	return this->Internal_GiveOrder(-1, groupId, c);
1670 }
1671 
GiveOrder(int unitId,springLegacyAI::Command * c)1672 int springLegacyAI::CAIAICallback::GiveOrder(int unitId, springLegacyAI::Command* c) {
1673 	return this->Internal_GiveOrder(unitId, -1, c);
1674 }
1675 
Internal_GiveOrder(int unitId,int groupId,springLegacyAI::Command * c)1676 int springLegacyAI::CAIAICallback::Internal_GiveOrder(int unitId, int groupId, springLegacyAI::Command* c) {
1677 
1678 	const int maxUnits = sAICallback->Unit_getMax(skirmishAIId);
1679 
1680 	int sCommandId;
1681 	void* sCommandData = mallocSUnitCommand(unitId, groupId, c, &sCommandId, maxUnits);
1682 
1683 	int ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, sCommandId, sCommandData);
1684 
1685 	freeSUnitCommand(sCommandData, sCommandId);
1686 
1687 	return ret;
1688 }
1689 
InitPath(float3 start,float3 end,int pathType,float goalRadius)1690 int springLegacyAI::CAIAICallback::InitPath(float3 start, float3 end, int pathType, float goalRadius) {
1691 
1692 	float start_f3[3];
1693 	float end_f3[3];
1694 
1695 	start.copyInto(start_f3);
1696 	end.copyInto(end_f3);
1697 
1698 	SInitPathCommand cmd = {start_f3, end_f3, pathType, goalRadius};
1699 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_PATH_INIT, &cmd);
1700 	return cmd.ret_pathId;
1701 }
1702 
GetNextWaypoint(int pathId)1703 float3 springLegacyAI::CAIAICallback::GetNextWaypoint(int pathId) {
1704 
1705 	float ret_posF3[3] = {0.0f, 0.0f, 0.0f};
1706 	SGetNextWaypointPathCommand cmd = {pathId, ret_posF3};
1707 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_PATH_GET_NEXT_WAYPOINT, &cmd);
1708 	return float3(cmd.ret_nextWaypoint_posF3_out);
1709 }
1710 
GetPathLength(float3 start,float3 end,int pathType,float goalRadius)1711 float springLegacyAI::CAIAICallback::GetPathLength(float3 start, float3 end, int pathType, float goalRadius) {
1712 
1713 	float start_f3[3];
1714 	float end_f3[3];
1715 
1716 	start.copyInto(start_f3);
1717 	end.copyInto(end_f3);
1718 
1719 	SGetApproximateLengthPathCommand cmd = {start_f3, end_f3, pathType, goalRadius};
1720 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_PATH_GET_APPROXIMATE_LENGTH, &cmd);
1721 	return cmd.ret_approximatePathLength;
1722 }
1723 
FreePath(int pathId)1724 void springLegacyAI::CAIAICallback::FreePath(int pathId) {
1725 
1726 	SFreePathCommand cmd = {pathId};
1727 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_PATH_FREE, &cmd);
1728 }
1729 
LineDrawerStartPath(const float3 & pos,const float * color)1730 void springLegacyAI::CAIAICallback::LineDrawerStartPath(const float3& pos, const float* color) {
1731 
1732 	float pos_f3[3];
1733 	pos.copyInto(pos_f3);
1734 	short color_s3[3];
1735 	color_s3[0] = (short) color[0] * 256;
1736 	color_s3[1] = (short) color[1] * 256;
1737 	color_s3[2] = (short) color[2] * 256;
1738 	const short alpha = (short) color[3] * 256;
1739 
1740 	SStartPathDrawerCommand cmd = {pos_f3, color_s3, alpha};
1741 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_START, &cmd);
1742 }
1743 
LineDrawerFinishPath()1744 void springLegacyAI::CAIAICallback::LineDrawerFinishPath() {
1745 
1746 	SFinishPathDrawerCommand cmd = {};
1747 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_FINISH, &cmd);
1748 }
1749 
LineDrawerDrawLine(const float3 & endPos,const float * color)1750 void springLegacyAI::CAIAICallback::LineDrawerDrawLine(const float3& endPos, const float* color) {
1751 
1752 	float endPos_f3[3];
1753 	endPos.copyInto(endPos_f3);
1754 	short color_s3[3];
1755 	color_s3[0] = (short) color[0] * 256;
1756 	color_s3[1] = (short) color[1] * 256;
1757 	color_s3[2] = (short) color[2] * 256;
1758 	const short alpha = (short) color[3] * 256;
1759 
1760 	SDrawLinePathDrawerCommand cmd = {endPos_f3, color_s3, alpha};
1761 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_DRAW_LINE, &cmd);
1762 }
1763 
LineDrawerDrawLineAndIcon(int cmdId,const float3 & endPos,const float * color)1764 void springLegacyAI::CAIAICallback::LineDrawerDrawLineAndIcon(int cmdId, const float3& endPos, const float* color) {
1765 
1766 	float endPos_f3[3];
1767 	endPos.copyInto(endPos_f3);
1768 	short color_s3[3];
1769 	color_s3[0] = (short) color[0] * 256;
1770 	color_s3[1] = (short) color[1] * 256;
1771 	color_s3[2] = (short) color[2] * 256;
1772 	const short alpha = (short) color[3] * 256;
1773 
1774 	SDrawLineAndIconPathDrawerCommand cmd = {cmdId, endPos_f3, color_s3, alpha};
1775 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_DRAW_LINE_AND_ICON, &cmd);
1776 }
1777 
LineDrawerDrawIconAtLastPos(int cmdId)1778 void springLegacyAI::CAIAICallback::LineDrawerDrawIconAtLastPos(int cmdId) {
1779 
1780 	SDrawIconAtLastPosPathDrawerCommand cmd = {cmdId};
1781 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_DRAW_ICON_AT_LAST_POS, &cmd);
1782 }
1783 
LineDrawerBreak(const float3 & endPos,const float * color)1784 void springLegacyAI::CAIAICallback::LineDrawerBreak(const float3& endPos, const float* color) {
1785 
1786 	float endPos_f3[3];
1787 	endPos.copyInto(endPos_f3);
1788 	short color_s3[3];
1789 	color_s3[0] = (short) color[0] * 256;
1790 	color_s3[1] = (short) color[1] * 256;
1791 	color_s3[2] = (short) color[2] * 256;
1792 	const short alpha = (short) color[3] * 256;
1793 
1794 	SBreakPathDrawerCommand cmd = {endPos_f3, color_s3, alpha};
1795 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_BREAK, &cmd);
1796 }
1797 
LineDrawerRestart()1798 void springLegacyAI::CAIAICallback::LineDrawerRestart() {
1799 
1800 	SRestartPathDrawerCommand cmd = {false};
1801 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_RESTART, &cmd);
1802 }
1803 
LineDrawerRestartSameColor()1804 void springLegacyAI::CAIAICallback::LineDrawerRestartSameColor() {
1805 
1806 	SRestartPathDrawerCommand cmd = {true};
1807 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_PATH_RESTART, &cmd);
1808 }
1809 
CreateSplineFigure(float3 pos1,float3 pos2,float3 pos3,float3 pos4,float width,int arrow,int lifeTime,int figureGroupId)1810 int springLegacyAI::CAIAICallback::CreateSplineFigure(float3 pos1, float3 pos2, float3 pos3, float3 pos4, float width, int arrow, int lifeTime, int figureGroupId) {
1811 
1812 	float pos1_f3[3];
1813 	pos1.copyInto(pos1_f3);
1814 	float pos2_f3[3];
1815 	pos2.copyInto(pos2_f3);
1816 	float pos3_f3[3];
1817 	pos3.copyInto(pos3_f3);
1818 	float pos4_f3[3];
1819 	pos4.copyInto(pos4_f3);
1820 
1821 	SCreateSplineFigureDrawerCommand cmd = {
1822 		pos1_f3,
1823 		pos2_f3,
1824 		pos3_f3,
1825 		pos4_f3,
1826 		width,
1827 		static_cast<bool>(arrow),
1828 		lifeTime,
1829 		figureGroupId
1830 	};
1831 
1832 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_FIGURE_CREATE_SPLINE, &cmd);
1833 	return cmd.ret_newFigureGroupId;
1834 }
1835 
CreateLineFigure(float3 pos1,float3 pos2,float width,int arrow,int lifeTime,int figureGroupId)1836 int springLegacyAI::CAIAICallback::CreateLineFigure(float3 pos1, float3 pos2, float width, int arrow, int lifeTime, int figureGroupId) {
1837 
1838 	float pos1_f3[3];
1839 	pos1.copyInto(pos1_f3);
1840 	float pos2_f3[3];
1841 	pos2.copyInto(pos2_f3);
1842 
1843 	SCreateLineFigureDrawerCommand cmd = {
1844 		pos1_f3,
1845 		pos2_f3,
1846 		width,
1847 		static_cast<bool>(arrow),
1848 		lifeTime,
1849 		figureGroupId
1850 	};
1851 
1852 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_FIGURE_CREATE_LINE, &cmd);
1853 	return cmd.ret_newFigureGroupId;
1854 }
1855 
SetFigureColor(int figureGroupId,float red,float green,float blue,float alpha)1856 void springLegacyAI::CAIAICallback::SetFigureColor(int figureGroupId, float red, float green, float blue, float alpha) {
1857 
1858 	short color_s3[3];
1859 	color_s3[0] = (short) red * 256;
1860 	color_s3[1] = (short) green * 256;
1861 	color_s3[2] = (short) blue * 256;
1862 	const short alpha_s = (short) alpha * 256;
1863 
1864 	SSetColorFigureDrawerCommand cmd = {figureGroupId, color_s3, alpha_s};
1865 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_FIGURE_SET_COLOR, &cmd);
1866 }
1867 
DeleteFigureGroup(int figureGroupId)1868 void springLegacyAI::CAIAICallback::DeleteFigureGroup(int figureGroupId) {
1869 
1870 	SDeleteFigureDrawerCommand cmd = {figureGroupId};
1871 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_FIGURE_DELETE, &cmd);
1872 }
1873 
DrawUnit(const char * name,float3 pos,float rotation,int lifeTime,int unitTeamId,bool transparent,bool drawBorder,int facing)1874 void springLegacyAI::CAIAICallback::DrawUnit(const char* name, float3 pos, float rotation, int lifeTime, int unitTeamId, bool transparent, bool drawBorder, int facing) {
1875 
1876 	float pos_f3[3];
1877 	pos.copyInto(pos_f3);
1878 	SDrawUnitDrawerCommand cmd = {
1879 		sAICallback->getUnitDefByName(skirmishAIId, name),
1880 		pos_f3,
1881 		rotation,
1882 		lifeTime,
1883 		unitTeamId,
1884 		transparent,
1885 		drawBorder,
1886 		facing
1887 	};
1888 
1889 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_DRAW_UNIT, &cmd);
1890 }
1891 
1892 
1893 
IsDebugDrawerEnabled() const1894 bool springLegacyAI::CAIAICallback::IsDebugDrawerEnabled() const {
1895 	return sAICallback->Debug_GraphDrawer_isEnabled(skirmishAIId);
1896 }
1897 
DebugDrawerAddGraphPoint(int lineId,float x,float y)1898 void springLegacyAI::CAIAICallback::DebugDrawerAddGraphPoint(int lineId, float x, float y) {
1899 	SAddPointLineGraphDrawerDebugCommand cmd = {lineId, x, y};
1900 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_LINE_ADD_POINT, &cmd);
1901 }
DebugDrawerDelGraphPoints(int lineId,int numPoints)1902 void springLegacyAI::CAIAICallback::DebugDrawerDelGraphPoints(int lineId, int numPoints) {
1903 	SDeletePointsLineGraphDrawerDebugCommand cmd = {lineId, numPoints};
1904 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_LINE_DELETE_POINTS, &cmd);
1905 }
1906 
DebugDrawerSetGraphPos(float x,float y)1907 void springLegacyAI::CAIAICallback::DebugDrawerSetGraphPos(float x, float y) {
1908 	SSetPositionGraphDrawerDebugCommand cmd = {x, y};
1909 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_SET_POS, &cmd);
1910 }
DebugDrawerSetGraphSize(float w,float h)1911 void springLegacyAI::CAIAICallback::DebugDrawerSetGraphSize(float w, float h) {
1912 	SSetSizeGraphDrawerDebugCommand cmd = {w, h};
1913 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_SET_SIZE, &cmd);
1914 }
DebugDrawerSetGraphLineColor(int lineId,const float3 & color)1915 void springLegacyAI::CAIAICallback::DebugDrawerSetGraphLineColor(int lineId, const float3& color) {
1916 
1917 	short color_s3[3];
1918 	color_s3[0] = (short) color[0] * 256;
1919 	color_s3[1] = (short) color[1] * 256;
1920 	color_s3[2] = (short) color[2] * 256;
1921 
1922 	SSetColorLineGraphDrawerDebugCommand cmd = {lineId, color_s3};
1923 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_LINE_SET_COLOR, &cmd);
1924 }
DebugDrawerSetGraphLineLabel(int lineId,const char * label)1925 void springLegacyAI::CAIAICallback::DebugDrawerSetGraphLineLabel(int lineId, const char* label) {
1926 	SSetLabelLineGraphDrawerDebugCommand cmd = {lineId, label};
1927 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_GRAPH_LINE_SET_LABEL, &cmd);
1928 }
1929 
DebugDrawerAddOverlayTexture(const float * texData,int w,int h)1930 int springLegacyAI::CAIAICallback::DebugDrawerAddOverlayTexture(const float* texData, int w, int h) {
1931 	SAddOverlayTextureDrawerDebugCommand cmd = {0, texData, w, h};
1932 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_ADD, &cmd);
1933 	return cmd.ret_overlayTextureId;
1934 }
DebugDrawerUpdateOverlayTexture(int overlayTextureId,const float * texData,int x,int y,int w,int h)1935 void springLegacyAI::CAIAICallback::DebugDrawerUpdateOverlayTexture(int overlayTextureId, const float* texData, int x, int y, int w, int h) {
1936 	SUpdateOverlayTextureDrawerDebugCommand cmd = {overlayTextureId, texData, x, y, w, h};
1937 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_UPDATE, &cmd);
1938 }
DebugDrawerDelOverlayTexture(int overlayTextureId)1939 void springLegacyAI::CAIAICallback::DebugDrawerDelOverlayTexture(int overlayTextureId) {
1940 	SDeleteOverlayTextureDrawerDebugCommand cmd = {overlayTextureId};
1941 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_DELETE, &cmd);
1942 }
DebugDrawerSetOverlayTexturePos(int overlayTextureId,float x,float y)1943 void springLegacyAI::CAIAICallback::DebugDrawerSetOverlayTexturePos(int overlayTextureId, float x, float y) {
1944 	SSetPositionOverlayTextureDrawerDebugCommand cmd = {overlayTextureId, x, y};
1945 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_SET_POS, &cmd);
1946 }
DebugDrawerSetOverlayTextureSize(int overlayTextureId,float w,float h)1947 void springLegacyAI::CAIAICallback::DebugDrawerSetOverlayTextureSize(int overlayTextureId, float w, float h) {
1948 	SSetSizeOverlayTextureDrawerDebugCommand cmd = {overlayTextureId, w, h};
1949 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_SET_SIZE, &cmd);
1950 }
DebugDrawerSetOverlayTextureLabel(int overlayTextureId,const char * texLabel)1951 void springLegacyAI::CAIAICallback::DebugDrawerSetOverlayTextureLabel(int overlayTextureId, const char* texLabel) {
1952 	SSetLabelOverlayTextureDrawerDebugCommand cmd = {overlayTextureId, texLabel};
1953 	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DEBUG_DRAWER_OVERLAYTEXTURE_SET_LABEL, &cmd);
1954 }
1955 
1956 
1957 
HandleCommand(int commandId,void * data)1958 int springLegacyAI::CAIAICallback::HandleCommand(int commandId, void* data) {
1959 	int ret = -99;
1960 
1961 	switch (commandId) {
1962 		case AIHCQuerySubVersionId: {
1963 //			SQuerySubVersionCommand cmd;
1964 //			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, cmdTopicId, &cmd);
1965 			ret = sAICallback->Game_getAiInterfaceVersion(skirmishAIId);
1966 			break;
1967 		}
1968 		case AIHCAddMapPointId: {
1969 			const AIHCAddMapPoint* myData = static_cast<AIHCAddMapPoint*>(data);
1970 			float pos[3];
1971 			myData->pos.copyInto(pos);
1972 			SAddPointDrawCommand cmd = {pos, myData->label};
1973 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_POINT_ADD, &cmd);
1974 			break;
1975 		}
1976 		case AIHCAddMapLineId: {
1977 			const AIHCAddMapLine* myData = static_cast<AIHCAddMapLine*>(data);
1978 			float posfrom[3];
1979 			myData->posfrom.copyInto(posfrom);
1980 			float posto[3];
1981 			myData->posto.copyInto(posto);
1982 			SAddLineDrawCommand cmd = {posfrom, posto};
1983 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_LINE_ADD, &cmd);
1984 			break;
1985 		}
1986 		case AIHCRemoveMapPointId: {
1987 			const AIHCRemoveMapPoint* myData = static_cast<AIHCRemoveMapPoint*>(data);
1988 			float pos[3];
1989 			myData->pos.copyInto(pos);
1990 			SRemovePointDrawCommand cmd = {pos};
1991 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_DRAWER_POINT_REMOVE, &cmd);
1992 			break;
1993 		}
1994 		case AIHCSendStartPosId: {
1995 			const AIHCSendStartPos* myData = static_cast<AIHCSendStartPos*>(data);
1996 			float pos[3];
1997 			myData->pos.copyInto(pos);
1998 			SSendStartPosCommand cmd = {myData->ready, pos};
1999 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_SEND_START_POS, &cmd);
2000 			break;
2001 		}
2002 
2003 		case AIHCTraceRayId: {
2004 			AIHCTraceRay* myData = static_cast<AIHCTraceRay*>(data);
2005 			float rayPos[3];
2006 			myData->rayPos.copyInto(rayPos);
2007 			float rayDir[3];
2008 			myData->rayDir.copyInto(rayDir);
2009 			STraceRayCommand cCmdData = {
2010 				rayPos,
2011 				rayDir,
2012 				myData->rayLen,
2013 				myData->srcUID,
2014 				myData->hitUID,
2015 				myData->flags
2016 			};
2017 
2018 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_TRACE_RAY, &cCmdData);
2019 
2020 			myData->rayLen = cCmdData.rayLen;
2021 			myData->hitUID = cCmdData.ret_hitUnitId;
2022 			break;
2023 		}
2024 
2025 		case AIHCFeatureTraceRayId: {
2026 			AIHCFeatureTraceRay* myData = static_cast<AIHCFeatureTraceRay*>(data);
2027 			float rayPos[3];
2028 			myData->rayPos.copyInto(rayPos);
2029 			float rayDir[3];
2030 			myData->rayDir.copyInto(rayDir);
2031 			SFeatureTraceRayCommand cCmdData = {
2032 				rayPos,
2033 				rayDir,
2034 				myData->rayLen,
2035 				myData->srcUID,
2036 				myData->hitFID,
2037 				myData->flags
2038 			};
2039 
2040 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_TRACE_RAY_FEATURE, &cCmdData);
2041 
2042 			myData->rayLen = cCmdData.rayLen;
2043 			myData->hitFID = cCmdData.ret_hitFeatureId;
2044 			break;
2045 		}
2046 
2047 		case AIHCPauseId: {
2048 			const AIHCPause* cppCmdData = static_cast<AIHCPause*>(data);
2049 			SPauseCommand cCmdData = {
2050 				cppCmdData->enable,
2051 				cppCmdData->reason
2052 			};
2053 			ret = sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_PAUSE, &cCmdData);
2054 			break;
2055 		}
2056 
2057 		case AIHCGetDataDirId: {
2058 			AIHCGetDataDir* cppCmdData = static_cast<AIHCGetDataDir*>(data);
2059 			cppCmdData->ret_path = sAICallback->DataDirs_allocatePath(
2060 					skirmishAIId,
2061 					cppCmdData->relPath,
2062 					cppCmdData->writeable,
2063 					cppCmdData->create,
2064 					cppCmdData->dir,
2065 					cppCmdData->common);
2066 			ret = (cppCmdData->ret_path == NULL) ? 0 : 1;
2067 			break;
2068 		}
2069 	}
2070 
2071 	return ret;
2072 }
2073 
ReadFile(const char * filename,void * buffer,int bufferLen)2074 bool springLegacyAI::CAIAICallback::ReadFile(const char* filename, void* buffer, int bufferLen) {
2075 
2076 //	SReadFileCommand cmd = {name, buffer, bufferLen};
2077 //	sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_READ_FILE, &cmd); return cmd.ret_isExecuted;
2078 	return sAICallback->File_getContent(skirmishAIId, filename, buffer, bufferLen);
2079 }
2080 
2081 
2082 #define AIAICALLBACK_CALL_LUA(HandleName, HANDLENAME)                                                                     \
2083 	const char* springLegacyAI::CAIAICallback::CallLua ## HandleName(const char* inData, int inSize, int* outSize) {      \
2084 		SCallLua ## HandleName ## Command cmd = {inData, inSize};                                                         \
2085 		sAICallback->Engine_handleCommand(skirmishAIId, COMMAND_TO_ID_ENGINE, -1, COMMAND_CALL_LUA_ ## HANDLENAME, &cmd); \
2086                                                                                                                           \
2087 		if (outSize != NULL) {                                                                                            \
2088 			if (cmd.ret_outData != NULL) {                                                                                \
2089 				*outSize = strlen(cmd.ret_outData);                                                                       \
2090 			} else {                                                                                                      \
2091 				*outSize = -1;                                                                                            \
2092 			}                                                                                                             \
2093 		}                                                                                                                 \
2094                                                                                                                           \
2095 		return cmd.ret_outData;                                                                                           \
2096 	}
2097 
AIAICALLBACK_CALL_LUA(Rules,RULES)2098 AIAICALLBACK_CALL_LUA(Rules, RULES)
2099 AIAICALLBACK_CALL_LUA(UI, UI)
2100 
2101 #undef AIAICALLBACK_CALL_LUA
2102 
2103 
2104 
2105 std::map<std::string, std::string> springLegacyAI::CAIAICallback::GetMyInfo()
2106 {
2107 	std::map<std::string, std::string> info;
2108 
2109 	const int info_size = sAICallback->SkirmishAI_Info_getSize(skirmishAIId);
2110 	for (int ii = 0; ii < info_size; ++ii) {
2111 		const char* key   = sAICallback->SkirmishAI_Info_getKey(skirmishAIId, ii);
2112 		const char* value = sAICallback->SkirmishAI_Info_getValue(skirmishAIId, ii);
2113 		if ((key != NULL) && (value != NULL)) {
2114 			info[key] = value;
2115 		}
2116 	}
2117 
2118 	return info;
2119 }
2120 
GetMyOptionValues()2121 std::map<std::string, std::string> springLegacyAI::CAIAICallback::GetMyOptionValues()
2122 {
2123 	std::map<std::string, std::string> optionVals;
2124 
2125 	const int optionVals_size = sAICallback->SkirmishAI_OptionValues_getSize(skirmishAIId);
2126 	for (int ovi = 0; ovi < optionVals_size; ++ovi) {
2127 		const char* key   = sAICallback->SkirmishAI_OptionValues_getKey(skirmishAIId, ovi);
2128 		const char* value = sAICallback->SkirmishAI_OptionValues_getValue(skirmishAIId, ovi);
2129 		if ((key != NULL) && (value != NULL)) {
2130 			optionVals[key] = value;
2131 		}
2132 	}
2133 
2134 	return optionVals;
2135 }
2136