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