1 /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
2 
3 
4 #include <set>
5 #include <string>
6 #include <vector>
7 #include <set>
8 #include <map>
9 #include <cctype>
10 
11 
12 #include "LuaUnitDefs.h"
13 
14 #include "LuaInclude.h"
15 
16 #include "LuaConfig.h"
17 #include "LuaDefs.h"
18 #include "LuaHandle.h"
19 #include "LuaUtils.h"
20 #include "Game/Game.h"
21 #include "Game/GameHelper.h"
22 #include "Sim/Misc/Team.h"
23 #include "Map/Ground.h"
24 #include "Map/MapDamage.h"
25 #include "Map/MapInfo.h"
26 #include "Rendering/IconHandler.h"
27 #include "Rendering/Models/IModelParser.h"
28 #include "Sim/Features/Feature.h"
29 #include "Sim/Features/FeatureHandler.h"
30 #include "Sim/Misc/CategoryHandler.h"
31 #include "Sim/Misc/CollisionVolume.h"
32 #include "Sim/Misc/LosHandler.h"
33 #include "Sim/Misc/QuadField.h"
34 #include "Sim/Misc/Wind.h"
35 #include "Sim/MoveTypes/MoveDefHandler.h"
36 #include "Sim/Units/Unit.h"
37 #include "Sim/Units/UnitDef.h"
38 #include "Sim/Units/UnitHandler.h"
39 #include "Sim/Units/UnitDefHandler.h"
40 #include "Sim/Units/UnitDefImage.h"
41 #include "Sim/Units/UnitTypes/Builder.h"
42 #include "Sim/Units/UnitTypes/Factory.h"
43 #include "Sim/Units/CommandAI/Command.h"
44 #include "Sim/Units/CommandAI/CommandAI.h"
45 #include "Sim/Units/CommandAI/FactoryCAI.h"
46 #include "Sim/Weapons/Weapon.h"
47 #include "Sim/Weapons/WeaponDefHandler.h"
48 #include "System/FileSystem/FileHandler.h"
49 #include "System/FileSystem/SimpleParser.h"
50 #include "System/FileSystem/FileSystem.h"
51 #include "System/Log/ILog.h"
52 #include "System/Util.h"
53 
54 
55 static ParamMap paramMap;
56 
57 static bool InitParamMap();
58 
59 // iteration routines
60 static int Next(lua_State* L);
61 static int Pairs(lua_State* L);
62 
63 // meta-table calls
64 static int UnitDefIndex(lua_State* L);
65 static int UnitDefNewIndex(lua_State* L);
66 static int UnitDefMetatable(lua_State* L);
67 
68 // special access functions
69 static int UnitDefToID(lua_State* L, const void* data);
70 static int WeaponDefToID(lua_State* L, const void* data);
71 static int CustomParamsTable(lua_State* L, const void* data);
72 static int BuildOptions(lua_State* L, const void* data);
73 static int SoundsTable(lua_State* L, const void* data);
74 static int WeaponsTable(lua_State* L, const void* data);
75 static int CategorySetFromBits(lua_State* L, const void* data);
76 static int CategorySetFromString(lua_State* L, const void* data);
77 
78 
79 /******************************************************************************/
80 /******************************************************************************/
81 
PushEntries(lua_State * L)82 bool LuaUnitDefs::PushEntries(lua_State* L)
83 {
84 	if (paramMap.empty()) {
85 	  InitParamMap();
86 	}
87 
88 	const map<string, int>& udMap = unitDefHandler->unitDefIDsByName;
89 	map<string, int>::const_iterator udIt;
90 	for (udIt = udMap.begin(); udIt != udMap.end(); ++udIt) {
91 	  const UnitDef* ud = unitDefHandler->GetUnitDefByID(udIt->second);
92 		if (ud == NULL) {
93 	  	continue;
94 		}
95 		lua_pushnumber(L, ud->id);
96 		lua_newtable(L); { // the proxy table
97 
98 			lua_newtable(L); { // the metatable
99 
100 				HSTR_PUSH(L, "__index");
101 				lua_pushlightuserdata(L, (void*)ud);
102 				lua_pushcclosure(L, UnitDefIndex, 1);
103 				lua_rawset(L, -3); // closure
104 
105 				HSTR_PUSH(L, "__newindex");
106 				lua_pushlightuserdata(L, (void*)ud);
107 				lua_pushcclosure(L, UnitDefNewIndex, 1);
108 				lua_rawset(L, -3);
109 
110 				HSTR_PUSH(L, "__metatable");
111 				lua_pushlightuserdata(L, (void*)ud);
112 				lua_pushcclosure(L, UnitDefMetatable, 1);
113 				lua_rawset(L, -3);
114 			}
115 
116 			lua_setmetatable(L, -2);
117 		}
118 
119 		HSTR_PUSH(L, "pairs");
120 		lua_pushcfunction(L, Pairs);
121 		lua_rawset(L, -3);
122 
123 		HSTR_PUSH(L, "next");
124 		lua_pushcfunction(L, Next);
125 		lua_rawset(L, -3);
126 
127 		lua_rawset(L, -3); // proxy table into UnitDefs
128 	}
129 
130 	return true;
131 }
132 
133 
IsDefaultParam(const string & word)134 bool LuaUnitDefs::IsDefaultParam(const string& word)
135 {
136 	if (paramMap.empty()) {
137 	  InitParamMap();
138 	}
139 	return (paramMap.find(word) != paramMap.end());
140 }
141 
142 
143 /******************************************************************************/
144 
UnitDefIndex(lua_State * L)145 static int UnitDefIndex(lua_State* L)
146 {
147 	// not a default value
148 	if (!lua_isstring(L, 2)) {
149 		lua_rawget(L, 1);
150 		return 1;
151 	}
152 
153 	const char* name = lua_tostring(L, 2);
154 	ParamMap::const_iterator it = paramMap.find(name);
155 
156 	// not a default value
157 	if (it == paramMap.end()) {
158 	  lua_rawget(L, 1);
159 	  return 1;
160 	}
161 
162 	const void* userData = lua_touserdata(L, lua_upvalueindex(1));
163 	const UnitDef* ud = static_cast<const UnitDef*>(userData);
164 	const DataElement& elem = it->second;
165 	const void* p = ((const char*)ud) + elem.offset;
166 	switch (elem.type) {
167 		case READONLY_TYPE: {
168 			lua_rawget(L, 1);
169 			return 1;
170 		}
171 		case INT_TYPE: {
172 			lua_pushnumber(L, *reinterpret_cast<const int*>(p));
173 			return 1;
174 		}
175 		case BOOL_TYPE: {
176 			lua_pushboolean(L, *reinterpret_cast<const bool*>(p));
177 			return 1;
178 		}
179 		case FLOAT_TYPE: {
180 			lua_pushnumber(L, *reinterpret_cast<const float*>(p));
181 			return 1;
182 		}
183 		case STRING_TYPE: {
184 			lua_pushsstring(L, *reinterpret_cast<const std::string*>(p));
185 			return 1;
186 		}
187 		case FUNCTION_TYPE: {
188 			return elem.func(L, p);
189 		}
190 		case ERROR_TYPE: {
191 			LOG_L(L_ERROR, "[%s] ERROR_TYPE for key \"%s\" in UnitDefs __index", __FUNCTION__, name);
192 			lua_pushnil(L);
193 			return 1;
194 		}
195 	}
196 
197 	return 0;
198 }
199 
200 
UnitDefNewIndex(lua_State * L)201 static int UnitDefNewIndex(lua_State* L)
202 {
203 	// not a default value, set it
204 	if (!lua_isstring(L, 2)) {
205 		lua_rawset(L, 1);
206 		return 0;
207 	}
208 
209 	const char* name = lua_tostring(L, 2);
210 	ParamMap::const_iterator it = paramMap.find(name);
211 
212 	// not a default value, set it
213 	if (it == paramMap.end()) {
214 		lua_rawset(L, 1);
215 		return 0;
216 	}
217 
218 	const void* userData = lua_touserdata(L, lua_upvalueindex(1));
219 	const UnitDef* ud = static_cast<const UnitDef*>(userData);
220 
221 	// write-protected
222 	if (!gs->editDefsEnabled) {
223 		luaL_error(L, "Attempt to write UnitDefs[%d].%s", ud->id, name);
224 		return 0;
225 	}
226 
227 	// Definition editing
228 	const DataElement& elem = it->second;
229 	const void* p = ((const char*)ud) + elem.offset;
230 
231 	switch (elem.type) {
232 		case FUNCTION_TYPE:
233 		case READONLY_TYPE: {
234 			luaL_error(L, "Can not write to %s", name);
235 			return 0;
236 		}
237 		case INT_TYPE: {
238 			*((int*)p) = lua_toint(L, -1);
239 			return 0;
240 		}
241 		case BOOL_TYPE: {
242 			*((bool*)p) = lua_toboolean(L, -1);
243 			return 0;
244 		}
245 		case FLOAT_TYPE: {
246 			*((float*)p) = lua_tofloat(L, -1);
247 			return 0;
248 		}
249 		case STRING_TYPE: {
250 			*((string*)p) = lua_tostring(L, -1);
251 			return 0;
252 		}
253 		case ERROR_TYPE: {
254 			LOG_L(L_ERROR, "[%s] ERROR_TYPE for key \"%s\" in UnitDefs __newindex", __FUNCTION__, name);
255 			lua_pushnil(L);
256 			return 1;
257 		}
258 	}
259 
260 	return 0;
261 }
262 
263 
UnitDefMetatable(lua_State * L)264 static int UnitDefMetatable(lua_State* L)
265 {
266 	lua_touserdata(L, lua_upvalueindex(1));
267 	// const void* userData = lua_touserdata(L, lua_upvalueindex(1));
268 	// const UnitDef* ud = (const UnitDef*)userData;
269 	return 0;
270 }
271 
272 
273 /******************************************************************************/
274 
Next(lua_State * L)275 static int Next(lua_State* L)
276 {
277 	return LuaUtils::Next(paramMap, L);
278 }
279 
280 
Pairs(lua_State * L)281 static int Pairs(lua_State* L)
282 {
283 	luaL_checktype(L, 1, LUA_TTABLE);
284 	lua_pushcfunction(L, Next);	// iterator
285 	lua_pushvalue(L, 1);        // state (table)
286 	lua_pushnil(L);             // initial value
287 	return 3;
288 }
289 
290 
291 /******************************************************************************/
292 /******************************************************************************/
293 
UnitDefToID(lua_State * L,const void * data)294 static int UnitDefToID(lua_State* L, const void* data)
295 {
296 	const UnitDef* ud = *((const UnitDef**)data);
297 	if (ud == NULL) {
298 		return 0;
299 	}
300 	lua_pushnumber(L, ud->id);
301 	return 1;
302 }
303 
304 
WeaponDefToID(lua_State * L,const void * data)305 static int WeaponDefToID(lua_State* L, const void* data)
306 {
307 	const WeaponDef* wd = *((const WeaponDef**)data);
308 	if (wd == NULL) {
309 		return 0;
310 	}
311 	lua_pushnumber(L, wd->id);
312 	return 1;
313 }
314 
315 
WeaponDefToName(lua_State * L,const void * data)316 static int WeaponDefToName(lua_State* L, const void* data)
317 {
318 	const WeaponDef* wd = *((const WeaponDef**)data);
319 	if (wd == NULL) {
320 		return 0;
321 	}
322 	lua_pushsstring(L, wd->name);
323 	return 1;
324 }
325 
326 
SafeIconType(lua_State * L,const void * data)327 static int SafeIconType(lua_State* L, const void* data)
328 {
329 	// the iconType is unsynced because LuaUI has SetUnitDefIcon()
330 	if (!CLuaHandle::GetHandleSynced(L)) {
331 		const icon::CIcon& iconType = *((const icon::CIcon*)data);
332 		lua_pushsstring(L, iconType->GetName());
333 		return 1;
334 	}
335 	return 0;
336 }
337 
338 
CustomParamsTable(lua_State * L,const void * data)339 static int CustomParamsTable(lua_State* L, const void* data)
340 {
341 	const map<string, string>& params = *((const map<string, string>*)data);
342 	lua_newtable(L);
343 	map<string, string>::const_iterator it;
344 	for (it = params.begin(); it != params.end(); ++it) {
345 		lua_pushsstring(L, it->first);
346 		lua_pushsstring(L, it->second);
347 		lua_rawset(L, -3);
348 	}
349 	return 1;
350 }
351 
352 
BuildOptions(lua_State * L,const void * data)353 static int BuildOptions(lua_State* L, const void* data)
354 {
355 	const map<int, string>& buildOptions = *((const map<int, string>*)data);
356 	const map<string, int>& unitMap = unitDefHandler->unitDefIDsByName;
357 
358 	lua_newtable(L);
359 	int count = 0;
360 	map<int, string>::const_iterator it;
361 	for (it = buildOptions.begin(); it != buildOptions.end(); ++it) {
362 		map<string, int>::const_iterator fit = unitMap.find(it->second);
363 		if (fit != unitMap.end()) {
364 			count++;
365 			lua_pushnumber(L, count);
366 			lua_pushnumber(L, fit->second); // UnitDef id
367 			lua_rawset(L, -3);
368 		}
369 	}
370 	return 1;
371 }
372 
373 
BuildCategorySet(lua_State * L,const vector<string> & cats)374 static inline int BuildCategorySet(lua_State* L, const vector<string>& cats)
375 {
376 	lua_newtable(L);
377 	const int count = (int)cats.size();
378 	for (int i = 0; i < count; i++) {
379 		lua_pushsstring(L, cats[i]);
380 		lua_pushboolean(L, true);
381 		lua_rawset(L, -3);
382 	}
383 	return 1;
384 }
385 
386 
CategorySetFromBits(lua_State * L,const void * data)387 static int CategorySetFromBits(lua_State* L, const void* data)
388 {
389 	const int bits = *((const int*)data);
390 	const vector<string> &cats =
391 		CCategoryHandler::Instance()->GetCategoryNames(bits);
392 	return BuildCategorySet(L, cats);
393 }
394 
395 
CategorySetFromString(lua_State * L,const void * data)396 static int CategorySetFromString(lua_State* L, const void* data)
397 {
398 	const string& str = *((const string*)data);
399 	const string lower = StringToLower(str);
400 	const vector<string> &cats = CSimpleParser::Tokenize(lower, 0);
401 	return BuildCategorySet(L, cats);
402 }
403 
404 
WeaponsTable(lua_State * L,const void * data)405 static int WeaponsTable(lua_State* L, const void* data)
406 {
407 	const vector<UnitDefWeapon>& weapons =
408 		*((const vector<UnitDefWeapon>*)data);
409 
410 	lua_newtable(L);
411 
412 	for (size_t i = 0; i < weapons.size(); i++) {
413 		const UnitDefWeapon& udw = weapons[i];
414 		const WeaponDef* weapon = udw.def;
415 		lua_pushnumber(L, i + LUA_WEAPON_BASE_INDEX);
416 		lua_newtable(L); {
417 			HSTR_PUSH_NUMBER(L, "weaponDef",   weapon->id);
418 			HSTR_PUSH_NUMBER(L, "slavedTo",    udw.slavedTo-1+LUA_WEAPON_BASE_INDEX);
419 			HSTR_PUSH_NUMBER(L, "fuelUsage",   udw.fuelUsage);
420 			HSTR_PUSH_NUMBER(L, "maxAngleDif", udw.maxMainDirAngleDif);
421 			HSTR_PUSH_NUMBER(L, "mainDirX",    udw.mainDir.x);
422 			HSTR_PUSH_NUMBER(L, "mainDirY",    udw.mainDir.y);
423 			HSTR_PUSH_NUMBER(L, "mainDirZ",    udw.mainDir.z);
424 
425 			HSTR_PUSH(L, "badTargets");
426 			CategorySetFromBits(L, &udw.badTargetCat);
427 			lua_rawset(L, -3);
428 
429 			HSTR_PUSH(L, "onlyTargets");
430 			CategorySetFromBits(L, &udw.onlyTargetCat);
431 			lua_rawset(L, -3);
432 		}
433 		lua_rawset(L, -3);
434 	}
435 
436 	return 1;
437 }
438 
439 
PushGuiSoundSet(lua_State * L,const string & name,const GuiSoundSet & soundSet)440 static void PushGuiSoundSet(lua_State* L, const string& name,
441                             const GuiSoundSet& soundSet)
442 {
443 	const int soundCount = (int)soundSet.sounds.size();
444 	lua_pushsstring(L, name);
445 	lua_newtable(L);
446 	for (int i = 0; i < soundCount; i++) {
447 		lua_pushnumber(L, i + 1);
448 		lua_newtable(L);
449 		const GuiSoundSet::Data& sound = soundSet.sounds[i];
450 		HSTR_PUSH_STRING(L, "name",   sound.name);
451 		HSTR_PUSH_NUMBER(L, "volume", sound.volume);
452 		if (!CLuaHandle::GetHandleSynced(L)) {
453 			HSTR_PUSH_NUMBER(L, "id", sound.id);
454 		}
455 		lua_rawset(L, -3);
456 	}
457 	lua_rawset(L, -3);
458 }
459 
460 
SoundsTable(lua_State * L,const void * data)461 static int SoundsTable(lua_State* L, const void* data) {
462 	const UnitDef::SoundStruct& sounds = *((const UnitDef::SoundStruct*) data);
463 
464 	lua_newtable(L);
465 	PushGuiSoundSet(L, "select",      sounds.select);
466 	PushGuiSoundSet(L, "ok",          sounds.ok);
467 	PushGuiSoundSet(L, "arrived",     sounds.arrived);
468 	PushGuiSoundSet(L, "build",       sounds.build);
469 	PushGuiSoundSet(L, "repair",      sounds.repair);
470 	PushGuiSoundSet(L, "working",     sounds.working);
471 	PushGuiSoundSet(L, "underattack", sounds.underattack);
472 	PushGuiSoundSet(L, "cant",        sounds.cant);
473 	PushGuiSoundSet(L, "activate",    sounds.activate);
474 	PushGuiSoundSet(L, "deactivate",  sounds.deactivate);
475 
476 	return 1;
477 }
478 
479 
480 
481 
MoveDefTable(lua_State * L,const void * data)482 static int MoveDefTable(lua_State* L, const void* data)
483 {
484 	const unsigned int mdType = *static_cast<const unsigned int*>(data);
485 	const MoveDef* md = NULL;
486 
487 	lua_newtable(L);
488 	if (mdType == -1U) {
489 		return 1;
490 	}
491 	if ((md = moveDefHandler->GetMoveDefByPathType(mdType)) == NULL) {
492 		return 1;
493 	}
494 
495 	HSTR_PUSH_NUMBER(L, "id", md->pathType);
496 
497 	switch (md->speedModClass) {
498 		case MoveDef::Tank:  { HSTR_PUSH_STRING(L, "family", "tank");  HSTR_PUSH_STRING(L, "type", "ground"); break; }
499 		case MoveDef::KBot:  { HSTR_PUSH_STRING(L, "family", "kbot");  HSTR_PUSH_STRING(L, "type", "ground"); break; }
500 		case MoveDef::Hover: { HSTR_PUSH_STRING(L, "family", "hover"); HSTR_PUSH_STRING(L, "type",  "hover"); break; }
501 		case MoveDef::Ship:  { HSTR_PUSH_STRING(L, "family", "ship");  HSTR_PUSH_STRING(L, "type",   "ship"); break; }
502 	}
503 
504 	HSTR_PUSH_NUMBER(L, "xsize",         md->xsize);
505 	HSTR_PUSH_NUMBER(L, "zsize",         md->zsize);
506 	HSTR_PUSH_NUMBER(L, "depth",         md->depth);
507 	HSTR_PUSH_NUMBER(L, "maxSlope",      md->maxSlope);
508 	HSTR_PUSH_NUMBER(L, "slopeMod",      md->slopeMod);
509 	HSTR_PUSH_NUMBER(L, "depthMod",      md->depthModParams[MoveDef::DEPTHMOD_LIN_COEFF]);
510 	HSTR_PUSH_NUMBER(L, "crushStrength", md->crushStrength);
511 
512 	HSTR_PUSH_BOOL(L, "heatMapping",     md->heatMapping);
513 	HSTR_PUSH_NUMBER(L, "heatMod",       md->heatMod);
514 	HSTR_PUSH_NUMBER(L, "heatProduced",  md->heatProduced);
515 
516 	HSTR_PUSH_STRING(L, "name", md->name);
517 
518 	return 1;
519 }
520 
521 
TotalEnergyOut(lua_State * L,const void * data)522 static int TotalEnergyOut(lua_State* L, const void* data)
523 {
524 	const UnitDef& ud = *static_cast<const UnitDef*>(data);
525 	const float basicEnergy = (ud.energyMake - ud.energyUpkeep);
526 	const float tidalEnergy = (ud.tidalGenerator * mapInfo->map.tidalStrength);
527 	float windEnergy = 0.0f;
528 	if (ud.windGenerator > 0.0f) {
529 		windEnergy = (0.25f * (wind.GetMinWind() + wind.GetMaxWind()));
530 	}
531 	lua_pushnumber(L, basicEnergy + tidalEnergy + windEnergy); // CUSTOM
532 	return 1;
533 }
534 
535 
536 
ModelTable(lua_State * L,const void * data)537 static int ModelTable(lua_State* L, const void* data) {
538 	const UnitDef* ud = static_cast<const UnitDef*>(data);
539 	const std::string modelFile = modelParser->FindModelPath(ud->modelName);
540 
541 	lua_newtable(L);
542 	HSTR_PUSH_STRING(L, "type", StringToLower(FileSystem::GetExtension(modelFile)));
543 	HSTR_PUSH_STRING(L, "path", modelFile);
544 	HSTR_PUSH_STRING(L, "name", ud->modelName);
545 	HSTR_PUSH(L, "textures");
546 
547 	lua_newtable(L);
548 	if (ud->model != NULL) {
549 		LuaPushNamedString(L, "tex1", ud->model->tex1);
550 		LuaPushNamedString(L, "tex2", ud->model->tex2);
551 	}
552 	lua_rawset(L, -3);
553 	return 1;
554 }
555 
556 
ColVolTable(lua_State * L,const void * data)557 static int ColVolTable(lua_State* L, const void* data) {
558 	auto cv = static_cast<const CollisionVolume*>(data);
559 	assert(cv != NULL);
560 
561 	lua_newtable(L);
562 	switch (cv->GetVolumeType()) {
563 		case CollisionVolume::COLVOL_TYPE_ELLIPSOID:
564 			HSTR_PUSH_STRING(L, "type", "ellipsoid");
565 			break;
566 		case CollisionVolume::COLVOL_TYPE_CYLINDER:
567 			HSTR_PUSH_STRING(L, "type", "cylinder");
568 			break;
569 		case CollisionVolume::COLVOL_TYPE_BOX:
570 			HSTR_PUSH_STRING(L, "type", "box");
571 			break;
572 	}
573 
574 	LuaPushNamedNumber(L, "scaleX", cv->GetScales().x);
575 	LuaPushNamedNumber(L, "scaleY", cv->GetScales().y);
576 	LuaPushNamedNumber(L, "scaleZ", cv->GetScales().z);
577 	LuaPushNamedNumber(L, "offsetX", cv->GetOffsets().x);
578 	LuaPushNamedNumber(L, "offsetY", cv->GetOffsets().y);
579 	LuaPushNamedNumber(L, "offsetZ", cv->GetOffsets().z);
580 	LuaPushNamedNumber(L, "boundingRadius", cv->GetBoundingRadius());
581 	LuaPushNamedBool(L, "defaultToSphere",    cv->DefaultToSphere());
582 	LuaPushNamedBool(L, "defaultToFootPrint", cv->DefaultToFootPrint());
583 	LuaPushNamedBool(L, "defaultToPieceTree", cv->DefaultToPieceTree());
584 	return 1;
585 }
586 
587 
588 #define TYPE_FUNC(FuncName, LuaType)                           \
589 	static int FuncName(lua_State* L, const void* data)        \
590 	{                                                          \
591 		const UnitDef* ud = static_cast<const UnitDef*>(data); \
592 		lua_push ## LuaType(L, ud->FuncName());                \
593 		return 1;                                              \
594 	}
595 
596 #define TYPE_MODEL_FUNC(name, param)                           \
597 	static int name(lua_State* L, const void* data)            \
598 	{                                                          \
599 		const UnitDef* ud = static_cast<const UnitDef*>(data); \
600 		const S3DModel* model = ud->LoadModel();               \
601 		lua_pushnumber(L, model->param);                       \
602 		return 1;                                              \
603 	}
604 
TYPE_FUNC(IsTransportUnit,boolean)605 TYPE_FUNC(IsTransportUnit, boolean)
606 TYPE_FUNC(IsImmobileUnit, boolean)
607 TYPE_FUNC(IsBuildingUnit, boolean)
608 TYPE_FUNC(IsBuilderUnit, boolean)
609 TYPE_FUNC(IsMobileBuilderUnit, boolean)
610 TYPE_FUNC(IsStaticBuilderUnit, boolean)
611 TYPE_FUNC(IsFactoryUnit, boolean)
612 TYPE_FUNC(IsExtractorUnit, boolean)
613 TYPE_FUNC(IsGroundUnit, boolean)
614 TYPE_FUNC(IsAirUnit, boolean)
615 TYPE_FUNC(IsStrafingAirUnit, boolean)
616 TYPE_FUNC(IsHoveringAirUnit, boolean)
617 TYPE_FUNC(IsFighterAirUnit, boolean)
618 TYPE_FUNC(IsBomberAirUnit, boolean)
619 
620 TYPE_MODEL_FUNC(ModelHeight, height)
621 TYPE_MODEL_FUNC(ModelRadius, radius)
622 TYPE_MODEL_FUNC(ModelMinx,   mins.x)
623 TYPE_MODEL_FUNC(ModelMidx,   relMidPos.x)
624 TYPE_MODEL_FUNC(ModelMaxx,   maxs.x)
625 TYPE_MODEL_FUNC(ModelMiny,   mins.y)
626 TYPE_MODEL_FUNC(ModelMidy,   relMidPos.y)
627 TYPE_MODEL_FUNC(ModelMaxy,   maxs.y)
628 TYPE_MODEL_FUNC(ModelMinz,   mins.z)
629 TYPE_MODEL_FUNC(ModelMidz,   relMidPos.z)
630 TYPE_MODEL_FUNC(ModelMaxz,   maxs.z)
631 
632 
633 
634 static int ReturnEmptyString(lua_State* L, const void* data) {
635 	LOG_L(L_WARNING, "[%s] %s - deprecated field!", __FUNCTION__, lua_tostring(L, 2));
636 	lua_pushstring(L, "");
637 	return 1;
638 }
639 
ReturnFalse(lua_State * L,const void * data)640 static int ReturnFalse(lua_State* L, const void* data) {
641 	LOG_L(L_WARNING, "[%s] %s - deprecated field!", __FUNCTION__, lua_tostring(L, 2));
642 	lua_pushboolean(L, false);
643 	return 1;
644 }
645 
ReturnMinusOne(lua_State * L,const void * data)646 static int ReturnMinusOne(lua_State* L, const void* data) {
647 	LOG_L(L_WARNING, "[%s] %s - deprecated field!", __FUNCTION__, lua_tostring(L, 2));
648 	lua_pushnumber(L, -1);
649 	return 1;
650 }
651 
ReturnNil(lua_State * L,const void * data)652 static int ReturnNil(lua_State* L, const void* data) {
653 	LOG_L(L_WARNING, "[%s] %s - deprecated field!", __FUNCTION__, lua_tostring(L, 2));
654 	lua_pushnil(L);
655 	return 1;
656 }
657 
658 /******************************************************************************/
659 /******************************************************************************/
660 
InitParamMap()661 static bool InitParamMap()
662 {
663 	paramMap["next"]  = DataElement(READONLY_TYPE);
664 	paramMap["pairs"] = DataElement(READONLY_TYPE);
665 
666 	// dummy UnitDef for address lookups
667 	const UnitDef& ud = *unitDefHandler->unitDefs[0];
668 	const char* start = ADDRESS(ud);
669 
670 /*
671 ADD_FLOAT("maxRange",       maxRange);       // CUSTOM
672 ADD_BOOL("hasShield",       hasShield);      // CUSTOM
673 ADD_BOOL("canParalyze",     canParalyze);    // CUSTOM
674 ADD_BOOL("canStockpile",    canStockpile);   // CUSTOM
675 ADD_BOOL("canAttackWater",  canAttackWater); // CUSTOM
676 */
677 // ADD_INT("buildOptionsCount", ud.buildOptions.size(")); // CUSTOM
678 
679 	ADD_FUNCTION("builder", ud, ReturnFalse); // DEPRECATED
680 	ADD_FUNCTION("floater", ud, ReturnFalse); // DEPRECATED
681 	ADD_FUNCTION("canDGun", ud, ReturnFalse); // DEPRECATED
682 	ADD_FUNCTION("canCrash", ud, ReturnFalse); // DEPRECATED
683 	ADD_FUNCTION("isCommander", ud, ReturnFalse); // DEPRECATED
684 	ADD_FUNCTION("moveData", ud.pathType, ReturnNil); // DEPRECATED
685 	ADD_FUNCTION("type", ud, ReturnEmptyString); // DEPRECATED
686 	ADD_FUNCTION("maxSlope", ud, ReturnMinusOne); // DEPRECATED
687 
688 	ADD_FUNCTION("totalEnergyOut", ud, TotalEnergyOut);
689 
690 	ADD_FUNCTION("modCategories",      ud.categoryString,  CategorySetFromString);
691 	ADD_FUNCTION("springCategories",   ud.category,        CategorySetFromBits);
692 	ADD_FUNCTION("noChaseCategories",  ud.noChaseCategory, CategorySetFromBits);
693 
694 	ADD_FUNCTION("customParams",       ud.customParams,       CustomParamsTable);
695 	ADD_FUNCTION("buildOptions",       ud.buildOptions,       BuildOptions);
696 	ADD_FUNCTION("decoyDef",           ud.decoyDef,           UnitDefToID);
697 	ADD_FUNCTION("weapons",            ud.weapons,            WeaponsTable);
698 	ADD_FUNCTION("sounds",             ud.sounds,             SoundsTable);
699 	ADD_FUNCTION("model",              ud,                    ModelTable);
700 	ADD_FUNCTION("moveDef",            ud.pathType,           MoveDefTable);
701 	ADD_FUNCTION("shieldWeaponDef",    ud.shieldWeaponDef,    WeaponDefToID);
702 	ADD_FUNCTION("stockpileWeaponDef", ud.stockpileWeaponDef, WeaponDefToID);
703 	ADD_FUNCTION("iconType",           ud.iconType,           SafeIconType);
704 	ADD_FUNCTION("collisionVolume",    ud.collisionVolume,    ColVolTable);
705 
706 	ADD_FUNCTION("isTransport", ud, IsTransportUnit);
707 	ADD_FUNCTION("isImmobile", ud, IsImmobileUnit);
708 	ADD_FUNCTION("isBuilding", ud, IsBuildingUnit);
709 	ADD_FUNCTION("isBuilder", ud, IsBuilderUnit);
710 	ADD_FUNCTION("isMobileBuilder", ud, IsMobileBuilderUnit);
711 	ADD_FUNCTION("isStaticBuilder", ud, IsStaticBuilderUnit);
712 	ADD_FUNCTION("isFactory", ud, IsFactoryUnit);
713 	ADD_FUNCTION("isExtractor", ud, IsExtractorUnit);
714 	ADD_FUNCTION("isGroundUnit", ud, IsGroundUnit);
715 	ADD_FUNCTION("isAirUnit", ud, IsAirUnit);
716 	ADD_FUNCTION("isStrafingAirUnit", ud, IsStrafingAirUnit);
717 	ADD_FUNCTION("isHoveringAirUnit", ud, IsHoveringAirUnit);
718 	ADD_FUNCTION("isFighterAirUnit", ud, IsFighterAirUnit);
719 	ADD_FUNCTION("isBomberAirUnit", ud, IsBomberAirUnit);
720 
721 	ADD_FUNCTION("height",  ud, ModelHeight);
722 	ADD_FUNCTION("radius",  ud, ModelRadius);
723 	ADD_FUNCTION("minx",    ud, ModelMinx);
724 	ADD_FUNCTION("midx",    ud, ModelMidx);
725 	ADD_FUNCTION("maxx",    ud, ModelMaxx);
726 	ADD_FUNCTION("miny",    ud, ModelMiny);
727 	ADD_FUNCTION("midy",    ud, ModelMidy);
728 	ADD_FUNCTION("maxy",    ud, ModelMaxy);
729 	ADD_FUNCTION("minz",    ud, ModelMinz);
730 	ADD_FUNCTION("midz",    ud, ModelMidz);
731 	ADD_FUNCTION("maxz",    ud, ModelMaxz);
732 
733 
734 
735 	ADD_INT("id", ud.id);
736 	ADD_INT("cobID", ud.cobID);
737 
738 	ADD_STRING("name",      ud.name);
739 	ADD_STRING("humanName", ud.humanName);
740 
741 	ADD_STRING("tooltip", ud.tooltip);
742 
743 	ADD_STRING("wreckName", ud.wreckName);
744 
745 	ADD_FUNCTION("deathExplosion", ud.deathExpWeaponDef, WeaponDefToName);
746 	ADD_FUNCTION("selfDExplosion", ud.selfdExpWeaponDef, WeaponDefToName);
747 
748 	ADD_STRING("buildpicname", ud.buildPicName);
749 
750 	ADD_INT("techLevel",   ud.techLevel);
751 	ADD_INT("maxThisUnit", ud.maxThisUnit);
752 
753 	ADD_FLOAT("metalUpkeep",    ud.metalUpkeep);
754 	ADD_FLOAT("energyUpkeep",   ud.energyUpkeep);
755 	ADD_FLOAT("metalMake",      ud.metalMake);
756 	ADD_FLOAT("makesMetal",     ud.makesMetal);
757 	ADD_FLOAT("energyMake",     ud.energyMake);
758 	ADD_FLOAT("metalCost",      ud.metal);
759 	ADD_FLOAT("energyCost",     ud.energy);
760 	ADD_FLOAT("buildTime",      ud.buildTime);
761 	ADD_FLOAT("extractsMetal",  ud.extractsMetal);
762 	ADD_FLOAT("extractRange",   ud.extractRange);
763 	ADD_FLOAT("windGenerator",  ud.windGenerator);
764 	ADD_FLOAT("tidalGenerator", ud.tidalGenerator);
765 	ADD_FLOAT("metalStorage",   ud.metalStorage);
766 	ADD_FLOAT("energyStorage",  ud.energyStorage);
767 
768 	ADD_DEPRECATED_LUADEF_KEY("extractSquare");
769 
770 	ADD_FLOAT("power", ud.power);
771 
772 	ADD_FLOAT("health",       ud.health);
773 	ADD_FLOAT("autoHeal",     ud.autoHeal);
774 	ADD_FLOAT("idleAutoHeal", ud.idleAutoHeal);
775 
776 	ADD_INT("idleTime", ud.idleTime);
777 
778 	ADD_BOOL("canSelfD", ud.canSelfD);
779 	ADD_INT("selfDCountdown", ud.selfDCountdown);
780 
781 	ADD_FLOAT("speed",    ud.speed);
782 	ADD_FLOAT("turnRate", ud.turnRate);
783 	ADD_BOOL("turnInPlace", ud.turnInPlace);
784 	ADD_FLOAT("turnInPlaceSpeedLimit", ud.turnInPlaceSpeedLimit);
785 
786 	ADD_BOOL("upright", ud.upright);
787 	ADD_BOOL("collide", ud.collide);
788 
789 	ADD_FLOAT("losHeight",     ud.losHeight);
790 	ADD_FLOAT("losRadius",     ud.losRadius);
791 	ADD_FLOAT("airLosRadius",  ud.airLosRadius);
792 
793 	ADD_INT("radarRadius",    ud.radarRadius);
794 	ADD_INT("sonarRadius",    ud.sonarRadius);
795 	ADD_INT("jammerRadius",   ud.jammerRadius);
796 	ADD_INT("sonarJamRadius", ud.sonarJamRadius);
797 	ADD_INT("seismicRadius",  ud.seismicRadius);
798 
799 	ADD_FLOAT("seismicSignature", ud.seismicSignature);
800 
801 	ADD_BOOL("stealth",      ud.stealth);
802 	ADD_BOOL("sonarStealth", ud.sonarStealth);
803 
804 	ADD_FLOAT("mass", ud.mass);
805 
806 	ADD_FLOAT("maxHeightDif",  ud.maxHeightDif);
807 	ADD_FLOAT("minWaterDepth", ud.minWaterDepth);
808 	ADD_FLOAT("maxWaterDepth", ud.maxWaterDepth);
809 	ADD_FLOAT("waterline",     ud.waterline);
810 
811 	ADD_INT("flankingBonusMode",   ud.flankingBonusMode);
812 	ADD_FLOAT("flankingBonusMax",  ud.flankingBonusMax);
813 	ADD_FLOAT("flankingBonusMin",  ud.flankingBonusMin);
814 	ADD_FLOAT("flankingBonusDirX", ud.flankingBonusDir.x);
815 	ADD_FLOAT("flankingBonusDirY", ud.flankingBonusDir.y);
816 	ADD_FLOAT("flankingBonusDirZ", ud.flankingBonusDir.z);
817 	ADD_FLOAT("flankingBonusMobilityAdd", ud.flankingBonusMobilityAdd);
818 
819 	ADD_INT("armorType",         ud.armorType);
820 	ADD_FLOAT("armoredMultiple", ud.armoredMultiple);
821 
822 	ADD_FLOAT("minCollisionSpeed", ud.minCollisionSpeed);
823 	ADD_FLOAT("slideTolerance",    ud.slideTolerance);
824 
825 	ADD_FLOAT("maxWeaponRange", ud.maxWeaponRange);
826 	ADD_FLOAT("maxCoverage", ud.maxCoverage);
827 
828 	ADD_BOOL( "buildRange3D",   ud.buildRange3D);
829 	ADD_FLOAT("buildDistance",  ud.buildDistance);
830 	ADD_FLOAT("buildSpeed",     ud.buildSpeed);
831 	ADD_FLOAT("repairSpeed",    ud.repairSpeed);
832 	ADD_FLOAT("maxRepairSpeed", ud.repairSpeed);
833 	ADD_FLOAT("reclaimSpeed",   ud.reclaimSpeed);
834 	ADD_FLOAT("resurrectSpeed", ud.resurrectSpeed);
835 	ADD_FLOAT("captureSpeed",   ud.captureSpeed);
836 	ADD_FLOAT("terraformSpeed", ud.terraformSpeed);
837 
838 	ADD_BOOL("canSubmerge",       ud.canSubmerge);
839 	ADD_BOOL("floatOnWater",      ud.floatOnWater);
840 	ADD_BOOL("canFly",            ud.canfly);
841 	ADD_BOOL("canMove",           ud.canmove);
842 	ADD_BOOL("onOffable",         ud.onoffable);
843 	ADD_BOOL("activateWhenBuilt", ud.activateWhenBuilt);
844 
845 	ADD_DEPRECATED_LUADEF_KEY("canHover");
846 
847 	ADD_BOOL("reclaimable", ud.reclaimable);
848 	ADD_BOOL("capturable",  ud.capturable);
849 	ADD_BOOL("repairable",  ud.repairable);
850 
851 	ADD_BOOL("canManualFire",         ud.canManualFire);
852 	ADD_BOOL("canCloak",              ud.canCloak);
853 	ADD_BOOL("canRestore",            ud.canRestore);
854 	ADD_BOOL("canRepair",             ud.canRepair);
855 	ADD_BOOL("canSelfRepair",         ud.canSelfRepair);
856 	ADD_BOOL("canReclaim",            ud.canReclaim);
857 	ADD_BOOL("canAttack",             ud.canAttack);
858 	ADD_BOOL("canPatrol",             ud.canPatrol);
859 	ADD_BOOL("canFight",              ud.canFight);
860 	ADD_BOOL("canGuard",              ud.canGuard);
861 	ADD_BOOL("canAssist",             ud.canAssist);
862 	ADD_BOOL("canBeAssisted",         ud.canBeAssisted);
863 	ADD_BOOL("canRepeat",             ud.canRepeat);
864 	ADD_BOOL("canCapture",            ud.canCapture);
865 	ADD_BOOL("canResurrect",          ud.canResurrect);
866 	ADD_BOOL("canLoopbackAttack",     ud.canLoopbackAttack);
867 	ADD_BOOL("canFireControl",        ud.canFireControl);
868 	ADD_INT( "fireState",             ud.fireState);
869 	ADD_INT( "moveState",             ud.moveState);
870 	ADD_BOOL("fullHealthFactory",     ud.fullHealthFactory);
871 	ADD_BOOL("factoryHeadingTakeoff", ud.factoryHeadingTakeoff);
872 
873 	//aircraft stuff
874 	ADD_DEPRECATED_LUADEF_KEY("drag");
875 	ADD_FLOAT("wingDrag",     ud.wingDrag);
876 	ADD_FLOAT("wingAngle",    ud.wingAngle);
877 	ADD_FLOAT("crashDrag",    ud.crashDrag);
878 	ADD_FLOAT("frontToSpeed", ud.frontToSpeed);
879 	ADD_FLOAT("speedToFront", ud.speedToFront);
880 	ADD_FLOAT("myGravity",    ud.myGravity);
881 	ADD_FLOAT("verticalSpeed",ud.verticalSpeed);
882 
883 	ADD_FLOAT("maxBank",      ud.maxBank);
884 	ADD_FLOAT("maxPitch",     ud.maxPitch);
885 	ADD_FLOAT("turnRadius",   ud.turnRadius);
886 	ADD_FLOAT("wantedHeight", ud.wantedHeight);
887 	ADD_BOOL("hoverAttack",   ud.hoverAttack);
888 	ADD_BOOL("airStrafe",     ud.airStrafe);
889 	ADD_BOOL("bankingAllowed",ud.bankingAllowed);
890 	ADD_BOOL("useSmoothMesh", ud.useSmoothMesh);
891 
892 	// < 0 means it can land,
893 	// >= 0 indicates how much the unit will move during hovering on the spot
894 	ADD_FLOAT("dlHoverFactor", ud.dlHoverFactor);
895 
896 //	bool DontLand (") { return dlHoverFactor >= 0.0f; }
897 
898 	ADD_FLOAT("maxAcc",      ud.maxAcc);
899 	ADD_FLOAT("maxDec",      ud.maxDec);
900 	ADD_FLOAT("maxAileron",  ud.maxAileron);
901 	ADD_FLOAT("maxElevator", ud.maxElevator);
902 	ADD_FLOAT("maxRudder",   ud.maxRudder);
903 
904 	ADD_FLOAT("maxFuel",    ud.maxFuel);
905 	ADD_FLOAT("refuelTime", ud.refuelTime);
906 
907 	ADD_FLOAT("minAirBasePower", ud.minAirBasePower);
908 
909 //	unsigned char* yardmapLevels[6];
910 //	unsigned char* yardmaps[4];			//Iterations of the Ymap for building rotation
911 
912 	ADD_INT("xsize", ud.xsize);
913 	ADD_INT("zsize", ud.zsize);
914 
915 	// transport stuff
916 	ADD_INT(  "transportCapacity",     ud.transportCapacity);
917 	ADD_INT(  "transportSize",         ud.transportSize);
918 	ADD_FLOAT("transportMass",         ud.transportMass);
919 	ADD_FLOAT("loadingRadius",         ud.loadingRadius);
920 	ADD_BOOL( "isAirBase",             ud.isAirBase);
921 	ADD_BOOL( "isFirePlatform",        ud.isFirePlatform);
922 	ADD_BOOL( "holdSteady",            ud.holdSteady);
923 	ADD_BOOL( "releaseHeld",           ud.releaseHeld);
924 	ADD_BOOL( "cantBeTransported",     ud.cantBeTransported);
925 	ADD_BOOL( "transportByEnemy",      ud.transportByEnemy);
926 	ADD_INT(  "transportUnloadMethod", ud.transportUnloadMethod);
927 	ADD_FLOAT("fallSpeed",             ud.fallSpeed);
928 	ADD_FLOAT("unitFallSpeed",         ud.unitFallSpeed);
929 
930 	ADD_BOOL( "startCloaked",     ud.startCloaked);
931 	ADD_FLOAT("cloakCost",        ud.cloakCost);
932 	ADD_FLOAT("cloakCostMoving",  ud.cloakCostMoving);
933 	ADD_FLOAT("decloakDistance",  ud.decloakDistance);
934 	ADD_BOOL( "decloakSpherical", ud.decloakSpherical);
935 	ADD_BOOL( "decloakOnFire",    ud.decloakOnFire);
936 	ADD_INT(  "cloakTimeout",     ud.cloakTimeout);
937 
938 	ADD_BOOL( "canKamikaze",    ud.canKamikaze);
939 	ADD_FLOAT("kamikazeDist",   ud.kamikazeDist);
940 	ADD_BOOL( "kamikazeUseLOS", ud.kamikazeUseLOS);
941 
942 	ADD_BOOL("targfac", ud.targfac);
943 
944 	ADD_BOOL("needGeo",   ud.needGeo);
945 	ADD_BOOL("isFeature", ud.isFeature);
946 
947 	ADD_BOOL("hideDamage",     ud.hideDamage);
948 	ADD_BOOL("showPlayerName", ud.showPlayerName);
949 
950 	ADD_INT("highTrajectoryType", ud.highTrajectoryType);
951 
952 	ADD_BOOL( "leaveTracks",   ud.decalDef.leaveTrackDecals);
953 	ADD_INT(  "trackType",     ud.decalDef.trackDecalType);
954 	ADD_FLOAT("trackWidth",    ud.decalDef.trackDecalWidth);
955 	ADD_FLOAT("trackOffset",   ud.decalDef.trackDecalOffset);
956 	ADD_FLOAT("trackStrength", ud.decalDef.trackDecalStrength);
957 	ADD_FLOAT("trackStretch",  ud.decalDef.trackDecalStretch);
958 
959 	ADD_BOOL( "canDropFlare",     ud.canDropFlare);
960 	ADD_FLOAT("flareReloadTime",  ud.flareReloadTime);
961 	ADD_FLOAT("flareEfficiency",  ud.flareEfficiency);
962 	ADD_FLOAT("flareDelay",       ud.flareDelay);
963 	ADD_FLOAT("flareDropVectorX", ud.flareDropVector.x);
964 	ADD_FLOAT("flareDropVectorY", ud.flareDropVector.y);
965 	ADD_FLOAT("flareDropVectorZ", ud.flareDropVector.z);
966 	ADD_INT(  "flareTime",        ud.flareTime);
967 	ADD_INT(  "flareSalvoSize",   ud.flareSalvoSize);
968 	ADD_INT(  "flareSalvoDelay",  ud.flareSalvoDelay);
969 
970 	ADD_BOOL("levelGround", ud.levelGround);
971 	ADD_BOOL("strafeToAttack", ud.strafeToAttack);
972 
973 	ADD_BOOL( "useBuildingGroundDecal",  ud.decalDef.useGroundDecal);
974 	ADD_INT(  "buildingDecalType",       ud.decalDef.groundDecalType);
975 	ADD_INT(  "buildingDecalSizeX",      ud.decalDef.groundDecalSizeX);
976 	ADD_INT(  "buildingDecalSizeY",      ud.decalDef.groundDecalSizeY);
977 	ADD_FLOAT("buildingDecalDecaySpeed", ud.decalDef.groundDecalDecaySpeed);
978 
979 	ADD_BOOL("showNanoFrame", ud.showNanoFrame);
980 	ADD_BOOL("showNanoSpray", ud.showNanoSpray);
981 	ADD_FLOAT("nanoColorR",   ud.nanoColor.x);
982 	ADD_FLOAT("nanoColorG",   ud.nanoColor.y);
983 	ADD_FLOAT("nanoColorB",   ud.nanoColor.z);
984 
985 	ADD_STRING("scriptName", ud.scriptName);
986 	ADD_STRING("scriptPath", ud.scriptName); //FIXME // backward compability
987 
988 	return true;
989 }
990 
991 
992 /******************************************************************************/
993 /******************************************************************************/
994