1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name script_player.cpp - The player ccl functions. */
12 //
13 // (c) Copyright 2001-2019 by Lutz Sammer, Jimmy Salmon and Andrettin
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 /*----------------------------------------------------------------------------
31 -- Includes
32 ----------------------------------------------------------------------------*/
33
34 #include "stratagus.h"
35
36 #include "player.h"
37
38 #include "actions.h"
39 #include "age.h"
40 #include "ai.h"
41 #include "character.h"
42 #include "civilization.h"
43 #include "commands.h"
44 #include "currency.h"
45 //Wyrmgus start
46 #include "editor.h"
47 #include "font.h"
48 #include "grand_strategy.h"
49 #include "item.h"
50 #include "luacallback.h"
51 //Wyrmgus end
52 #include "map/map.h"
53 #include "map/site.h"
54 #include "plane.h"
55 #include "province.h"
56 #include "quest.h"
57 #include "religion/deity.h"
58 #include "religion/deity_domain.h"
59 #include "religion/pantheon.h"
60 #include "religion/religion.h"
61 #include "script.h"
62 #include "time/calendar.h"
63 #include "ui/button_action.h"
64 #include "unit/unit.h"
65 #include "unit/unit_find.h"
66 #include "unit/unittype.h"
67 #include "video.h"
68 #include "upgrade/upgrade.h"
69 //Wyrmgus start
70 #include "ui/ui.h"
71 #include "util.h"
72 //Wyrmgus end
73
74 /*----------------------------------------------------------------------------
75 -- Variables
76 ----------------------------------------------------------------------------*/
77
78 /*----------------------------------------------------------------------------
79 -- Functions
80 ----------------------------------------------------------------------------*/
81
82 extern CUnit *CclGetUnitFromRef(lua_State *l);
83
84 /**
85 ** Get a player pointer
86 **
87 ** @param l Lua state.
88 **
89 ** @return The player pointer
90 */
CclGetPlayer(lua_State * l)91 static CPlayer *CclGetPlayer(lua_State *l)
92 {
93 return &Players[LuaToNumber(l, -1)];
94 }
95
96 /**
97 ** Parse the player configuration.
98 **
99 ** @param l Lua state.
100 */
CclPlayer(lua_State * l)101 static int CclPlayer(lua_State *l)
102 {
103 int i = LuaToNumber(l, 1);
104
105 CPlayer &player = Players[i];
106 player.Index = i;
107
108 if (NumPlayers <= i) {
109 NumPlayers = i + 1;
110 }
111
112 player.Load(l);
113 return 0;
114 }
115
Load(lua_State * l)116 void CPlayer::Load(lua_State *l)
117 {
118 const int args = lua_gettop(l);
119
120 this->Units.resize(0);
121 this->FreeWorkers.resize(0);
122 //Wyrmgus start
123 this->LevelUpUnits.resize(0);
124 //Wyrmgus end
125
126 // j = 0 represent player Index.
127 for (int j = 1; j < args; ++j) {
128 const char *value = LuaToString(l, j + 1);
129 ++j;
130
131 if (!strcmp(value, "name")) {
132 this->SetName(LuaToString(l, j + 1));
133 } else if (!strcmp(value, "type")) {
134 value = LuaToString(l, j + 1);
135 if (!strcmp(value, "neutral")) {
136 this->Type = PlayerNeutral;
137 } else if (!strcmp(value, "nobody")) {
138 this->Type = PlayerNobody;
139 } else if (!strcmp(value, "computer")) {
140 this->Type = PlayerComputer;
141 } else if (!strcmp(value, "person")) {
142 this->Type = PlayerPerson;
143 } else if (!strcmp(value, "rescue-passive")) {
144 this->Type = PlayerRescuePassive;
145 } else if (!strcmp(value, "rescue-active")) {
146 this->Type = PlayerRescueActive;
147 } else {
148 LuaError(l, "Unsupported tag: %s" _C_ value);
149 }
150 } else if (!strcmp(value, "race")) {
151 const char *civilization_ident = LuaToString(l, j + 1);
152 CCivilization *civilization = CCivilization::GetCivilization(civilization_ident);
153 if (civilization) {
154 this->Race = civilization->ID;
155 }
156 //Wyrmgus start
157 } else if (!strcmp(value, "faction")) {
158 this->Faction = LuaToNumber(l, j + 1);
159 } else if (!strcmp(value, "dynasty")) {
160 this->Dynasty = PlayerRaces.GetDynasty(LuaToString(l, j + 1));
161 } else if (!strcmp(value, "age")) {
162 this->Age = CAge::GetAge(LuaToString(l, j + 1));
163 } else if (!strcmp(value, "color")) {
164 int color_id = LuaToNumber(l, j + 1);
165 this->Color = PlayerColors[color_id][0];
166 this->UnitColors.Colors = PlayerColorsRGB[color_id];
167 //Wyrmgus end
168 } else if (!strcmp(value, "ai-name")) {
169 this->AiName = LuaToString(l, j + 1);
170 } else if (!strcmp(value, "team")) {
171 this->Team = LuaToNumber(l, j + 1);
172 } else if (!strcmp(value, "enemy")) {
173 value = LuaToString(l, j + 1);
174 for (int i = 0; i < PlayerMax && *value; ++i, ++value) {
175 if (*value == '-' || *value == '_' || *value == ' ') {
176 this->Enemy &= ~(1 << i);
177 } else {
178 this->Enemy |= (1 << i);
179 }
180 }
181 } else if (!strcmp(value, "allied")) {
182 value = LuaToString(l, j + 1);
183 for (int i = 0; i < PlayerMax && *value; ++i, ++value) {
184 if (*value == '-' || *value == '_' || *value == ' ') {
185 this->Allied &= ~(1 << i);
186 } else {
187 this->Allied |= (1 << i);
188 }
189 }
190 } else if (!strcmp(value, "shared-vision")) {
191 value = LuaToString(l, j + 1);
192 for (int i = 0; i < PlayerMax && *value; ++i, ++value) {
193 if (*value == '-' || *value == '_' || *value == ' ') {
194 this->SharedVision &= ~(1 << i);
195 } else {
196 this->SharedVision |= (1 << i);
197 }
198 }
199 } else if (!strcmp(value, "start")) {
200 CclGetPos(l, &this->StartPos.x, &this->StartPos.y, j + 1);
201 //Wyrmgus start
202 } else if (!strcmp(value, "start-map-layer")) {
203 this->StartMapLayer = LuaToNumber(l, j + 1);
204 } else if (!strcmp(value, "overlord")) {
205 int overlord_id = LuaToNumber(l, j + 1);
206 this->SetOverlord(&Players[overlord_id]);
207 //Wyrmgus end
208 } else if (!strcmp(value, "resources")) {
209 if (!lua_istable(l, j + 1)) {
210 LuaError(l, "incorrect argument");
211 }
212 const int subargs = lua_rawlen(l, j + 1);
213 for (int k = 0; k < subargs; ++k) {
214 value = LuaToString(l, j + 1, k + 1);
215 ++k;
216 const int resId = GetResourceIdByName(l, value);
217 this->Resources[resId] = LuaToNumber(l, j + 1, k + 1);
218 }
219 } else if (!strcmp(value, "stored-resources")) {
220 if (!lua_istable(l, j + 1)) {
221 LuaError(l, "incorrect argument");
222 }
223 const int subargs = lua_rawlen(l, j + 1);
224 for (int k = 0; k < subargs; ++k) {
225 value = LuaToString(l, j + 1, k + 1);
226 ++k;
227
228 const int resId = GetResourceIdByName(l, value);
229 this->StoredResources[resId] = LuaToNumber(l, j + 1, k + 1);
230 }
231 } else if (!strcmp(value, "max-resources")) {
232 if (!lua_istable(l, j + 1)) {
233 LuaError(l, "incorrect argument");
234 }
235 const int subargs = lua_rawlen(l, j + 1);
236 for (int k = 0; k < subargs; ++k) {
237 value = LuaToString(l, j + 1, k + 1);
238 ++k;
239 const int resId = GetResourceIdByName(l, value);
240 this->MaxResources[resId] = LuaToNumber(l, j + 1, k + 1);
241 }
242 } else if (!strcmp(value, "last-resources")) {
243 if (!lua_istable(l, j + 1)) {
244 LuaError(l, "incorrect argument");
245 }
246 const int subargs = lua_rawlen(l, j + 1);
247 for (int k = 0; k < subargs; ++k) {
248 value = LuaToString(l, j + 1, k + 1);
249 ++k;
250 const int resId = GetResourceIdByName(l, value);
251 this->LastResources[resId] = LuaToNumber(l, j + 1, k + 1);
252 }
253 } else if (!strcmp(value, "incomes")) {
254 if (!lua_istable(l, j + 1)) {
255 LuaError(l, "incorrect argument");
256 }
257 const int subargs = lua_rawlen(l, j + 1);
258 for (int k = 0; k < subargs; ++k) {
259 value = LuaToString(l, j + 1, k + 1);
260 ++k;
261
262 const int resId = GetResourceIdByName(l, value);
263 this->Incomes[resId] = LuaToNumber(l, j + 1, k + 1);
264 }
265 } else if (!strcmp(value, "revenue")) {
266 if (!lua_istable(l, j + 1)) {
267 LuaError(l, "incorrect argument");
268 }
269 const int subargs = lua_rawlen(l, j + 1);
270 for (int k = 0; k < subargs; ++k) {
271 value = LuaToString(l, j + 1, k + 1);
272 ++k;
273
274 const int resId = GetResourceIdByName(l, value);
275 this->Revenue[resId] = LuaToNumber(l, j + 1, k + 1);
276 }
277 //Wyrmgus start
278 } else if (!strcmp(value, "prices")) {
279 if (!lua_istable(l, j + 1)) {
280 LuaError(l, "incorrect argument");
281 }
282 const int subargs = lua_rawlen(l, j + 1);
283 for (int k = 0; k < subargs; ++k) {
284 value = LuaToString(l, j + 1, k + 1);
285 ++k;
286
287 const int resId = GetResourceIdByName(l, value);
288 this->Prices[resId] = LuaToNumber(l, j + 1, k + 1);
289 }
290 //Wyrmgus end
291 } else if (!strcmp(value, "ai-enabled")) {
292 this->AiEnabled = true;
293 --j;
294 } else if (!strcmp(value, "ai-disabled")) {
295 this->AiEnabled = false;
296 --j;
297 //Wyrmgus start
298 } else if (!strcmp(value, "revealed")) {
299 this->Revealed = true;
300 --j;
301 //Wyrmgus end
302 } else if (!strcmp(value, "supply")) {
303 this->Supply = LuaToNumber(l, j + 1);
304 } else if (!strcmp(value, "demand")) {
305 this->Demand = LuaToNumber(l, j + 1);
306 } else if (!strcmp(value, "trade-cost")) {
307 this->TradeCost = LuaToNumber(l, j + 1);
308 } else if (!strcmp(value, "unit-limit")) {
309 this->UnitLimit = LuaToNumber(l, j + 1);
310 } else if (!strcmp(value, "building-limit")) {
311 this->BuildingLimit = LuaToNumber(l, j + 1);
312 } else if (!strcmp(value, "total-unit-limit")) {
313 this->TotalUnitLimit = LuaToNumber(l, j + 1);
314 } else if (!strcmp(value, "score")) {
315 this->Score = LuaToNumber(l, j + 1);
316 } else if (!strcmp(value, "total-units")) {
317 this->TotalUnits = LuaToNumber(l, j + 1);
318 } else if (!strcmp(value, "total-buildings")) {
319 this->TotalBuildings = LuaToNumber(l, j + 1);
320 } else if (!strcmp(value, "total-razings")) {
321 this->TotalRazings = LuaToNumber(l, j + 1);
322 } else if (!strcmp(value, "total-kills")) {
323 this->TotalKills = LuaToNumber(l, j + 1);
324 //Wyrmgus start
325 } else if (!strcmp(value, "unit-type-kills")) {
326 if (!lua_istable(l, j + 1)) {
327 LuaError(l, "incorrect argument");
328 }
329 const int subargs = lua_rawlen(l, j + 1);
330 for (int k = 0; k < subargs; ++k) {
331 CUnitType *unit_type = UnitTypeByIdent(LuaToString(l, j + 1, k + 1));
332 ++k;
333 if (unit_type) {
334 this->UnitTypeKills[unit_type->Slot] = LuaToNumber(l, j + 1, k + 1);
335 }
336 }
337 } else if (!strcmp(value, "lost-town-hall-timer")) {
338 this->LostTownHallTimer = LuaToNumber(l, j + 1);
339 } else if (!strcmp(value, "hero-cooldown-timer")) {
340 this->HeroCooldownTimer = LuaToNumber(l, j + 1);
341 //Wyrmgus end
342 } else if (!strcmp(value, "total-resources")) {
343 if (!lua_istable(l, j + 1)) {
344 LuaError(l, "incorrect argument");
345 }
346 const int subargs = lua_rawlen(l, j + 1);
347 //Wyrmgus start
348 // if (subargs != MaxCosts) {
349 // LuaError(l, "Wrong number of total-resources: %d" _C_ subargs);
350 // }
351 if (subargs != MaxCosts) {
352 fprintf(stderr, "Wrong number of total-resources: %d.\n", subargs);
353 }
354 //Wyrmgus end
355 for (int k = 0; k < subargs; ++k) {
356 this->TotalResources[k] = LuaToNumber(l, j + 1, k + 1);
357 }
358 } else if (!strcmp(value, "speed-resource-harvest")) {
359 if (!lua_istable(l, j + 1)) {
360 LuaError(l, "incorrect argument");
361 }
362 const int subargs = lua_rawlen(l, j + 1);
363 //Wyrmgus start
364 // if (subargs != MaxCosts) {
365 // LuaError(l, "Wrong number of speed-resource-harvest: %d" _C_ subargs);
366 // }
367 if (subargs != MaxCosts) {
368 fprintf(stderr, "Wrong number of speed-resource-harvest: %d.\n", subargs);
369 }
370 //Wyrmgus end
371 for (int k = 0; k < subargs; ++k) {
372 this->SpeedResourcesHarvest[k] = LuaToNumber(l, j + 1, k + 1);
373 }
374 } else if (!strcmp(value, "speed-resource-return")) {
375 if (!lua_istable(l, j + 1)) {
376 LuaError(l, "incorrect argument");
377 }
378 const int subargs = lua_rawlen(l, j + 1);
379 //Wyrmgus start
380 // if (subargs != MaxCosts) {
381 // LuaError(l, "Wrong number of speed-resource-harvest: %d" _C_ subargs);
382 // }
383 if (subargs != MaxCosts) {
384 fprintf(stderr, "Wrong number of speed-resource-return: %d.\n", subargs);
385 }
386 //Wyrmgus end
387 for (int k = 0; k < subargs; ++k) {
388 this->SpeedResourcesReturn[k] = LuaToNumber(l, j + 1, k + 1);
389 }
390 } else if (!strcmp(value, "speed-build")) {
391 this->SpeedBuild = LuaToNumber(l, j + 1);
392 } else if (!strcmp(value, "speed-train")) {
393 this->SpeedTrain = LuaToNumber(l, j + 1);
394 } else if (!strcmp(value, "speed-upgrade")) {
395 this->SpeedUpgrade = LuaToNumber(l, j + 1);
396 } else if (!strcmp(value, "speed-research")) {
397 this->SpeedResearch = LuaToNumber(l, j + 1);
398 //Wyrmgus start
399 /*
400 } else if (!strcmp(value, "color")) {
401 if (!lua_istable(l, j + 1) || lua_rawlen(l, j + 1) != 3) {
402 LuaError(l, "incorrect argument");
403 }
404 const int r = LuaToNumber(l, j + 1, 1);
405 const int g = LuaToNumber(l, j + 1, 2);
406 const int b = LuaToNumber(l, j + 1, 3);
407 this->Color = Video.MapRGB(TheScreen->format, r, g, b);
408 */
409 //Wyrmgus end
410 //Wyrmgus start
411 } else if (!strcmp(value, "current-quests")) {
412 if (!lua_istable(l, j + 1)) {
413 LuaError(l, "incorrect argument");
414 }
415 const int subargs = lua_rawlen(l, j + 1);
416 for (int k = 0; k < subargs; ++k) {
417 CQuest *quest = GetQuest(LuaToString(l, j + 1, k + 1));
418 if (quest) {
419 this->CurrentQuests.push_back(quest);
420 }
421 }
422 } else if (!strcmp(value, "completed-quests")) {
423 if (!lua_istable(l, j + 1)) {
424 LuaError(l, "incorrect argument");
425 }
426 const int subargs = lua_rawlen(l, j + 1);
427 for (int k = 0; k < subargs; ++k) {
428 CQuest *quest = GetQuest(LuaToString(l, j + 1, k + 1));
429 if (quest) {
430 this->CompletedQuests.push_back(quest);
431 if (quest->Competitive) {
432 quest->CurrentCompleted = true;
433 }
434 }
435 }
436 } else if (!strcmp(value, "quest-objectives")) {
437 if (!lua_istable(l, j + 1)) {
438 LuaError(l, "incorrect argument");
439 }
440 const int subargs = lua_rawlen(l, j + 1);
441 for (int k = 0; k < subargs; ++k) {
442 lua_rawgeti(l, j + 1, k + 1);
443 CPlayerQuestObjective *objective = new CPlayerQuestObjective;
444 this->QuestObjectives.push_back(objective);
445 if (!lua_istable(l, -1)) {
446 LuaError(l, "incorrect argument (expected table for quest objectives)");
447 }
448 const int subsubargs = lua_rawlen(l, -1);
449 for (int n = 0; n < subsubargs; ++n) {
450 value = LuaToString(l, -1, n + 1);
451 ++n;
452 if (!strcmp(value, "quest")) {
453 objective->Quest = GetQuest(LuaToString(l, -1, n + 1));
454 if (!objective->Quest) {
455 LuaError(l, "Quest doesn't exist.");
456 }
457 } else if (!strcmp(value, "objective-type")) {
458 objective->ObjectiveType = GetQuestObjectiveTypeIdByName(LuaToString(l, -1, n + 1));
459 if (objective->ObjectiveType == -1) {
460 LuaError(l, "Objective type doesn't exist.");
461 }
462 } else if (!strcmp(value, "objective-string")) {
463 objective->ObjectiveString = LuaToString(l, -1, n + 1);
464 } else if (!strcmp(value, "quantity")) {
465 objective->Quantity = LuaToNumber(l, -1, n + 1);
466 } else if (!strcmp(value, "counter")) {
467 objective->Counter = LuaToNumber(l, -1, n + 1);
468 } else if (!strcmp(value, "resource")) {
469 int resource = GetResourceIdByName(LuaToString(l, -1, n + 1));
470 if (resource == -1) {
471 LuaError(l, "Resource doesn't exist.");
472 }
473 objective->Resource = resource;
474 } else if (!strcmp(value, "unit-class")) {
475 int unit_class = GetUnitTypeClassIndexByName(LuaToString(l, -1, n + 1));
476 if (unit_class == -1) {
477 LuaError(l, "Unit class doesn't exist.");
478 }
479 objective->UnitClass = unit_class;
480 } else if (!strcmp(value, "unit-type")) {
481 CUnitType *unit_type = UnitTypeByIdent(LuaToString(l, -1, n + 1));
482 if (!unit_type) {
483 LuaError(l, "Unit type doesn't exist.");
484 }
485 objective->UnitTypes.push_back(unit_type);
486 } else if (!strcmp(value, "upgrade")) {
487 CUpgrade *upgrade = CUpgrade::Get(LuaToString(l, -1, n + 1));
488 if (!upgrade) {
489 LuaError(l, "Upgrade doesn't exist.");
490 }
491 objective->Upgrade = upgrade;
492 } else if (!strcmp(value, "character")) {
493 CCharacter *character = CCharacter::GetCharacter(LuaToString(l, -1, n + 1));
494 if (!character) {
495 LuaError(l, "Character doesn't exist.");
496 }
497 objective->Character = character;
498 } else if (!strcmp(value, "unique")) {
499 CUniqueItem *unique = GetUniqueItem(LuaToString(l, -1, n + 1));
500 if (!unique) {
501 LuaError(l, "Unique doesn't exist.");
502 }
503 objective->Unique = unique;
504 } else if (!strcmp(value, "settlement")) {
505 CSite *site = CSite::GetSite(LuaToString(l, -1, n + 1));
506 if (!site) {
507 LuaError(l, "Site doesn't exist.");
508 }
509 objective->Settlement = site;
510 } else if (!strcmp(value, "faction")) {
511 CFaction *faction = PlayerRaces.GetFaction(LuaToString(l, -1, n + 1));
512 if (!faction) {
513 LuaError(l, "Faction doesn't exist.");
514 }
515 objective->Faction = faction;
516 } else {
517 LuaError(l, "Invalid quest objective property.");
518 }
519 }
520 lua_pop(l, 1);
521 }
522 } else if (!strcmp(value, "modifiers")) {
523 if (!lua_istable(l, j + 1)) {
524 LuaError(l, "incorrect argument");
525 }
526 const int subargs = lua_rawlen(l, j + 1);
527 for (int k = 0; k < subargs; ++k) {
528 CUpgrade *modifier_upgrade = CUpgrade::Get(LuaToString(l, j + 1, k + 1));
529 ++k;
530 int end_cycle = LuaToNumber(l, j + 1, k + 1);
531 if (modifier_upgrade) {
532 this->Modifiers.push_back(std::pair<CUpgrade *, int>(modifier_upgrade, end_cycle));
533 }
534 }
535 //Wyrmgus end
536 } else if (!strcmp(value, "autosell-resources")) {
537 if (!lua_istable(l, j + 1)) {
538 LuaError(l, "incorrect argument");
539 }
540 const int subargs = lua_rawlen(l, j + 1);
541 for (int k = 0; k < subargs; ++k) {
542 const int res = GetResourceIdByName(LuaToString(l, j + 1, k + 1));
543 if (res != -1) {
544 this->AutosellResources.push_back(res);
545 }
546 }
547 } else if (!strcmp(value, "timers")) {
548 if (!lua_istable(l, j + 1)) {
549 LuaError(l, "incorrect argument");
550 }
551 const int subargs = lua_rawlen(l, j + 1);
552 //Wyrmgus start
553 // if (subargs != UpgradeMax) {
554 // LuaError(l, "Wrong upgrade timer length: %d" _C_ subargs);
555 // }
556 //Wyrmgus end
557 for (int k = 0; k < subargs; ++k) {
558 //Wyrmgus start
559 // this->UpgradeTimers.Upgrades[k] = LuaToNumber(l, j + 1, k + 1);
560 CUpgrade *timer_upgrade = CUpgrade::Get(LuaToString(l, j + 1, k + 1));
561 ++k;
562 if (timer_upgrade) {
563 this->UpgradeTimers.Upgrades[timer_upgrade->ID] = LuaToNumber(l, j + 1, k + 1);
564 }
565 //Wyrmgus end
566 }
567 } else {
568 LuaError(l, "Unsupported tag: %s" _C_ value);
569 }
570 }
571 // Manage max
572 for (int i = 0; i < MaxCosts; ++i) {
573 if (this->MaxResources[i] != -1) {
574 this->SetResource(i, this->Resources[i] + this->StoredResources[i], STORE_BOTH);
575 }
576 }
577 }
578
579 /**
580 ** Change unit owner
581 **
582 ** @param l Lua state.
583 */
CclChangeUnitsOwner(lua_State * l)584 static int CclChangeUnitsOwner(lua_State *l)
585 {
586 LuaCheckArgs(l, 4);
587
588 Vec2i pos1;
589 Vec2i pos2;
590 CclGetPos(l, &pos1.x, &pos1.y, 1);
591 CclGetPos(l, &pos2.x, &pos2.y, 2);
592 const int oldp = LuaToNumber(l, 3);
593 const int newp = LuaToNumber(l, 4);
594 std::vector<CUnit *> table;
595
596 //Wyrmgus start
597 // Select(pos1, pos2, table, HasSamePlayerAs(Players[oldp]));
598 Select(pos1, pos2, table, 0, HasSamePlayerAs(Players[oldp]));
599 //Wyrmgus end
600 for (size_t i = 0; i != table.size(); ++i) {
601 table[i]->ChangeOwner(Players[newp]);
602 }
603 return 0;
604 }
605
606 /**
607 ** Get ThisPlayer.
608 **
609 ** @param l Lua state.
610 */
CclGetThisPlayer(lua_State * l)611 static int CclGetThisPlayer(lua_State *l)
612 {
613 LuaCheckArgs(l, 0);
614 if (ThisPlayer) {
615 lua_pushnumber(l, ThisPlayer - Players);
616 } else {
617 lua_pushnumber(l, 0);
618 }
619 return 1;
620 }
621
622 /**
623 ** Set ThisPlayer.
624 **
625 ** @param l Lua state.
626 */
CclSetThisPlayer(lua_State * l)627 static int CclSetThisPlayer(lua_State *l)
628 {
629 LuaCheckArgs(l, 1);
630 int plynr = LuaToNumber(l, 1);
631
632 ThisPlayer = &Players[plynr];
633
634 //Wyrmgus start
635 UI.Load();
636 //Wyrmgus end
637
638 lua_pushnumber(l, plynr);
639 return 1;
640 }
641
642 /**
643 ** Set MaxSelectable
644 **
645 ** @param l Lua state.
646 */
CclSetMaxSelectable(lua_State * l)647 static int CclSetMaxSelectable(lua_State *l)
648 {
649 LuaCheckArgs(l, 1);
650 MaxSelectable = LuaToNumber(l, 1);
651
652 lua_pushnumber(l, MaxSelectable);
653 return 1;
654 }
655
656 /**
657 ** Set player unit limit.
658 **
659 ** @param l Lua state.
660 */
CclSetAllPlayersUnitLimit(lua_State * l)661 static int CclSetAllPlayersUnitLimit(lua_State *l)
662 {
663 LuaCheckArgs(l, 1);
664 for (int i = 0; i < PlayerMax; ++i) {
665 Players[i].UnitLimit = LuaToNumber(l, 1);
666 }
667
668 lua_pushnumber(l, lua_tonumber(l, 1));
669 return 1;
670 }
671
672 /**
673 ** Set player unit limit.
674 **
675 ** @param l Lua state.
676 */
CclSetAllPlayersBuildingLimit(lua_State * l)677 static int CclSetAllPlayersBuildingLimit(lua_State *l)
678 {
679 LuaCheckArgs(l, 1);
680 for (int i = 0; i < PlayerMax; ++i) {
681 Players[i].BuildingLimit = LuaToNumber(l, 1);
682 }
683
684 lua_pushnumber(l, lua_tonumber(l, 1));
685 return 1;
686 }
687
688 /**
689 ** Set player unit limit.
690 **
691 ** @param l Lua state.
692 */
CclSetAllPlayersTotalUnitLimit(lua_State * l)693 static int CclSetAllPlayersTotalUnitLimit(lua_State *l)
694 {
695 LuaCheckArgs(l, 1);
696 for (int i = 0; i < PlayerMax; ++i) {
697 Players[i].TotalUnitLimit = LuaToNumber(l, 1);
698 }
699
700 lua_pushnumber(l, lua_tonumber(l, 1));
701 return 1;
702 }
703
704 /**
705 ** Change the diplomacy from player to another player.
706 **
707 ** @param l Lua state.
708 **
709 ** @return FIXME: should return old state.
710 */
CclSetDiplomacy(lua_State * l)711 static int CclSetDiplomacy(lua_State *l)
712 {
713 LuaCheckArgs(l, 3);
714 const int base = LuaToNumber(l, 1);
715 const int plynr = LuaToNumber(l, 3);
716 const char *state = LuaToString(l, 2);
717
718 if (!strcmp(state, "allied")) {
719 SendCommandDiplomacy(base, DiplomacyAllied, plynr);
720 } else if (!strcmp(state, "neutral")) {
721 SendCommandDiplomacy(base, DiplomacyNeutral, plynr);
722 } else if (!strcmp(state, "crazy")) {
723 SendCommandDiplomacy(base, DiplomacyCrazy, plynr);
724 } else if (!strcmp(state, "enemy")) {
725 SendCommandDiplomacy(base, DiplomacyEnemy, plynr);
726 //Wyrmgus start
727 } else if (!strcmp(state, "overlord")) {
728 SendCommandDiplomacy(base, DiplomacyOverlord, plynr);
729 } else if (!strcmp(state, "vassal")) {
730 SendCommandDiplomacy(base, DiplomacyVassal, plynr);
731 //Wyrmgus end
732 }
733 return 0;
734 }
735
736 /**
737 ** Change the diplomacy from ThisPlayer to another player.
738 **
739 ** @param l Lua state.
740 */
CclDiplomacy(lua_State * l)741 static int CclDiplomacy(lua_State *l)
742 {
743 lua_pushnumber(l, ThisPlayer->Index);
744 lua_insert(l, 1);
745 return CclSetDiplomacy(l);
746 }
747
748 /**
749 ** Change the shared vision from player to another player.
750 **
751 ** @param l Lua state.
752 **
753 ** @return FIXME: should return old state.
754 */
CclSetSharedVision(lua_State * l)755 static int CclSetSharedVision(lua_State *l)
756 {
757 LuaCheckArgs(l, 3);
758
759 const int base = LuaToNumber(l, 1);
760 const bool shared = LuaToBoolean(l, 2);
761 const int plynr = LuaToNumber(l, 3);
762
763 SendCommandSharedVision(base, shared, plynr);
764
765 return 0;
766 }
767
768 /**
769 ** Change the shared vision from ThisPlayer to another player.
770 **
771 ** @param l Lua state.
772 */
CclSharedVision(lua_State * l)773 static int CclSharedVision(lua_State *l)
774 {
775 lua_pushnumber(l, ThisPlayer->Index);
776 lua_insert(l, 1);
777 return CclSetSharedVision(l);
778 }
779
780 //Wyrmgus start
781 /**
782 ** Define a civilization.
783 **
784 ** @param l Lua state.
785 */
CclDefineCivilization(lua_State * l)786 static int CclDefineCivilization(lua_State *l)
787 {
788 LuaCheckArgs(l, 2);
789 if (!lua_istable(l, 2)) {
790 LuaError(l, "incorrect argument (expected table)");
791 }
792
793 std::string civilization_name = LuaToString(l, 1);
794 CCivilization *civilization = CCivilization::GetOrAddCivilization(civilization_name);
795 int civilization_id = civilization->ID;
796
797 // Parse the list:
798 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
799 const char *value = LuaToString(l, -2);
800 if (!strcmp(value, "Display")) {
801 PlayerRaces.Display[civilization_id] = LuaToString(l, -1);
802 } else if (!strcmp(value, "Description")) {
803 civilization->Description = LuaToString(l, -1);
804 } else if (!strcmp(value, "Quote")) {
805 civilization->Quote = LuaToString(l, -1);
806 } else if (!strcmp(value, "Background")) {
807 civilization->Background = LuaToString(l, -1);
808 } else if (!strcmp(value, "Adjective")) {
809 civilization->Adjective = LuaToString(l, -1);
810 } else if (!strcmp(value, "Visible")) {
811 PlayerRaces.Visible[civilization_id] = LuaToBoolean(l, -1);
812 } else if (!strcmp(value, "Playable")) {
813 PlayerRaces.Playable[civilization_id] = LuaToBoolean(l, -1);
814 } else if (!strcmp(value, "Species")) {
815 PlayerRaces.Species[civilization_id] = LuaToString(l, -1);
816 } else if (!strcmp(value, "ParentCivilization")) {
817 civilization->ParentCivilization = CCivilization::GetCivilization(LuaToString(l, -1));
818 } else if (!strcmp(value, "Language")) {
819 CLanguage *language = PlayerRaces.GetLanguage(LuaToString(l, -1));
820 if (language) {
821 civilization->Language = language;
822 language->UsedByCivilizationOrFaction = true;
823 } else {
824 LuaError(l, "Language not found.");
825 }
826 } else if (!strcmp(value, "Calendar")) {
827 CCalendar *calendar = CCalendar::GetCalendar(LuaToString(l, -1));
828 civilization->Calendar = calendar;
829 } else if (!strcmp(value, "Currency")) {
830 CCurrency *currency = CCurrency::GetCurrency(LuaToString(l, -1));
831 civilization->Currency = currency;
832 } else if (!strcmp(value, "DefaultColor")) {
833 PlayerRaces.DefaultColor[civilization_id] = LuaToString(l, -1);
834 } else if (!strcmp(value, "CivilizationUpgrade")) {
835 PlayerRaces.CivilizationUpgrades[civilization_id] = LuaToString(l, -1);
836 } else if (!strcmp(value, "DevelopsFrom")) {
837 if (!lua_istable(l, -1)) {
838 LuaError(l, "incorrect argument");
839 }
840
841 const int subargs = lua_rawlen(l, -1);
842 for (int j = 0; j < subargs; ++j) {
843 std::string originary_civilization_name = LuaToString(l, -1, j + 1);
844 CCivilization *originary_civilization = CCivilization::GetCivilization(originary_civilization_name);
845 if (originary_civilization) {
846 PlayerRaces.DevelopsFrom[civilization_id].push_back(originary_civilization->ID);
847 PlayerRaces.DevelopsTo[originary_civilization->ID].push_back(civilization_id);
848 }
849 }
850 } else if (!strcmp(value, "ButtonIcons")) {
851 if (!lua_istable(l, -1)) {
852 LuaError(l, "incorrect argument");
853 }
854 const int subargs = lua_rawlen(l, -1);
855 for (int j = 0; j < subargs; ++j) {
856 std::string button_action_name = LuaToString(l, -1, j + 1);
857 int button_action = GetButtonActionIdByName(button_action_name);
858 if (button_action != -1) {
859 ++j;
860 PlayerRaces.ButtonIcons[civilization_id][button_action].Name = LuaToString(l, -1, j + 1);
861 PlayerRaces.ButtonIcons[civilization_id][button_action].Icon = nullptr;
862 PlayerRaces.ButtonIcons[civilization_id][button_action].Load();
863 } else {
864 LuaError(l, "Button action \"%s\" doesn't exist." _C_ button_action_name.c_str());
865 }
866 }
867 } else if (!strcmp(value, "ForceTypeWeights")) {
868 if (!lua_istable(l, -1)) {
869 LuaError(l, "incorrect argument");
870 }
871
872 civilization->ForceTypeWeights.clear();
873
874 const int subargs = lua_rawlen(l, -1);
875 for (int j = 0; j < subargs; ++j) {
876 int force_type = GetForceTypeIdByName(LuaToString(l, -1, j + 1));
877 ++j;
878 civilization->ForceTypeWeights[force_type] = LuaToNumber(l, -1, j + 1);
879 }
880 } else if (!strcmp(value, "ForceTemplates")) {
881 const int args = lua_rawlen(l, -1);
882 for (int j = 0; j < args; ++j) {
883 lua_rawgeti(l, -1, j + 1);
884 CForceTemplate *force = new CForceTemplate;
885 if (!lua_istable(l, -1)) {
886 LuaError(l, "incorrect argument (expected table for force templates)");
887 }
888 const int subargs = lua_rawlen(l, -1);
889 for (int k = 0; k < subargs; ++k) {
890 value = LuaToString(l, -1, k + 1);
891 ++k;
892 if (!strcmp(value, "force-type")) {
893 force->ForceType = GetForceTypeIdByName(LuaToString(l, -1, k + 1));
894 if (force->ForceType == -1) {
895 LuaError(l, "Force type doesn't exist.");
896 }
897 civilization->ForceTemplates[force->ForceType].push_back(force);
898 } else if (!strcmp(value, "priority")) {
899 force->Priority = LuaToNumber(l, -1, k + 1);
900 } else if (!strcmp(value, "weight")) {
901 force->Weight = LuaToNumber(l, -1, k + 1);
902 } else if (!strcmp(value, "unit-class")) {
903 int unit_class = GetOrAddUnitTypeClassIndexByName(LuaToString(l, -1, k + 1));
904 ++k;
905 int unit_quantity = LuaToNumber(l, -1, k + 1);
906 force->Units.push_back(std::pair<int, int>(unit_class, unit_quantity));
907 } else {
908 printf("\n%s\n", civilization->Ident.c_str());
909 LuaError(l, "Unsupported tag: %s" _C_ value);
910 }
911 }
912 lua_pop(l, 1);
913 }
914 for (std::map<int, std::vector<CForceTemplate *>>::iterator iterator = civilization->ForceTemplates.begin(); iterator != civilization->ForceTemplates.end(); ++iterator) {
915 std::sort(iterator->second.begin(), iterator->second.end(), [](CForceTemplate *a, CForceTemplate *b) {
916 return a->Priority > b->Priority;
917 });
918 }
919 } else if (!strcmp(value, "AiBuildingTemplates")) {
920 const int args = lua_rawlen(l, -1);
921 for (int j = 0; j < args; ++j) {
922 lua_rawgeti(l, -1, j + 1);
923 CAiBuildingTemplate *building_template = new CAiBuildingTemplate;
924 if (!lua_istable(l, -1)) {
925 LuaError(l, "incorrect argument (expected table for force templates)");
926 }
927 const int subargs = lua_rawlen(l, -1);
928 for (int k = 0; k < subargs; ++k) {
929 value = LuaToString(l, -1, k + 1);
930 ++k;
931 if (!strcmp(value, "unit-class")) {
932 int unit_class = GetOrAddUnitTypeClassIndexByName(LuaToString(l, -1, k + 1));
933 building_template->UnitClass = unit_class;
934 civilization->AiBuildingTemplates.push_back(building_template);
935 } else if (!strcmp(value, "priority")) {
936 building_template->Priority = LuaToNumber(l, -1, k + 1);
937 } else if (!strcmp(value, "per-settlement")) {
938 building_template->PerSettlement = LuaToBoolean(l, -1, k + 1);
939 } else {
940 printf("\n%s\n", civilization->Ident.c_str());
941 LuaError(l, "Unsupported tag: %s" _C_ value);
942 }
943 }
944 lua_pop(l, 1);
945 }
946 std::sort(civilization->AiBuildingTemplates.begin(), civilization->AiBuildingTemplates.end(), [](CAiBuildingTemplate *a, CAiBuildingTemplate *b) {
947 return a->Priority > b->Priority;
948 });
949 } else if (!strcmp(value, "UIFillers")) {
950 if (!lua_istable(l, -1)) {
951 LuaError(l, "incorrect argument");
952 }
953
954 PlayerRaces.CivilizationUIFillers[civilization_id].clear();
955
956 const int subargs = lua_rawlen(l, -1);
957 for (int j = 0; j < subargs; ++j) {
958 CFiller filler = CFiller();
959 std::string filler_file = LuaToString(l, -1, j + 1);
960 if (filler_file.empty()) {
961 LuaError(l, "Filler graphic file is empty.");
962 }
963 filler.G = CGraphic::New(filler_file);
964 ++j;
965 filler.X = LuaToNumber(l, -1, j + 1);
966 ++j;
967 filler.Y = LuaToNumber(l, -1, j + 1);
968 PlayerRaces.CivilizationUIFillers[civilization_id].push_back(filler);
969 }
970 } else if (!strcmp(value, "UnitSounds")) {
971 if (!lua_istable(l, -1)) {
972 LuaError(l, "incorrect argument");
973 }
974 const int subargs = lua_rawlen(l, -1);
975 for (int k = 0; k < subargs; ++k) {
976 value = LuaToString(l, -1, k + 1);
977 ++k;
978
979 if (!strcmp(value, "selected")) {
980 civilization->UnitSounds.Selected.Name = LuaToString(l, -1, k + 1);
981 } else if (!strcmp(value, "acknowledge")) {
982 civilization->UnitSounds.Acknowledgement.Name = LuaToString(l, -1, k + 1);
983 } else if (!strcmp(value, "attack")) {
984 civilization->UnitSounds.Attack.Name = LuaToString(l, -1, k + 1);
985 } else if (!strcmp(value, "idle")) {
986 civilization->UnitSounds.Idle.Name = LuaToString(l, -1, k + 1);
987 } else if (!strcmp(value, "build")) {
988 civilization->UnitSounds.Build.Name = LuaToString(l, -1, k + 1);
989 } else if (!strcmp(value, "ready")) {
990 civilization->UnitSounds.Ready.Name = LuaToString(l, -1, k + 1);
991 } else if (!strcmp(value, "repair")) {
992 civilization->UnitSounds.Repair.Name = LuaToString(l, -1, k + 1);
993 } else if (!strcmp(value, "harvest")) {
994 const std::string name = LuaToString(l, -1, k + 1);
995 ++k;
996 const int resId = GetResourceIdByName(l, name.c_str());
997 civilization->UnitSounds.Harvest[resId].Name = LuaToString(l, -1, k + 1);
998 } else if (!strcmp(value, "help")) {
999 civilization->UnitSounds.Help.Name = LuaToString(l, -1, k + 1);
1000 } else if (!strcmp(value, "help-town")) {
1001 civilization->UnitSounds.HelpTown.Name = LuaToString(l, -1, k + 1);
1002 } else {
1003 LuaError(l, "Unsupported sound tag: %s" _C_ value);
1004 }
1005 }
1006 } else if (!strcmp(value, "PersonalNames")) {
1007 const int args = lua_rawlen(l, -1);
1008 for (int j = 0; j < args; ++j) {
1009 int gender_id = GetGenderIdByName(LuaToString(l, -1, j + 1));
1010 if (gender_id == -1) {
1011 gender_id = NoGender;
1012 } else {
1013 ++j;
1014 }
1015
1016 civilization->PersonalNames[gender_id].push_back(LuaToString(l, -1, j + 1));
1017 }
1018 } else if (!strcmp(value, "UnitClassNames")) {
1019 const int args = lua_rawlen(l, -1);
1020 for (int j = 0; j < args; ++j) {
1021 std::string class_name = LuaToString(l, -1, j + 1);
1022 if (class_name.empty()) {
1023 LuaError(l, "Class is given as a blank string.");
1024 }
1025 int class_id = GetOrAddUnitTypeClassIndexByName(class_name);
1026 ++j;
1027
1028 civilization->UnitClassNames[class_id].push_back(LuaToString(l, -1, j + 1));
1029 }
1030 } else if (!strcmp(value, "FamilyNames")) {
1031 const int args = lua_rawlen(l, -1);
1032 for (int j = 0; j < args; ++j) {
1033 civilization->FamilyNames.push_back(LuaToString(l, -1, j + 1));
1034 }
1035 } else if (!strcmp(value, "ProvinceNames")) {
1036 const int args = lua_rawlen(l, -1);
1037 for (int j = 0; j < args; ++j) {
1038 civilization->ProvinceNames.push_back(LuaToString(l, -1, j + 1));
1039 }
1040 } else if (!strcmp(value, "ShipNames")) {
1041 const int args = lua_rawlen(l, -1);
1042 for (int j = 0; j < args; ++j) {
1043 civilization->ShipNames.push_back(LuaToString(l, -1, j + 1));
1044 }
1045 } else if (!strcmp(value, "MinisterTitles")) {
1046 if (!lua_istable(l, -1)) {
1047 LuaError(l, "incorrect argument");
1048 }
1049 const int subargs = lua_rawlen(l, -1);
1050 for (int k = 0; k < subargs; ++k) {
1051 int title = GetCharacterTitleIdByName(LuaToString(l, -1, k + 1));
1052 ++k;
1053 int gender = GetGenderIdByName(LuaToString(l, -1, k + 1));
1054 ++k;
1055 int government_type = GetGovernmentTypeIdByName(LuaToString(l, -1, k + 1));
1056 ++k;
1057 int faction_tier = GetFactionTierIdByName(LuaToString(l, -1, k + 1));
1058 ++k;
1059 civilization->MinisterTitles[title][gender][government_type][faction_tier] = LuaToString(l, -1, k + 1);
1060 }
1061 } else if (!strcmp(value, "HistoricalUpgrades")) {
1062 if (!lua_istable(l, -1)) {
1063 LuaError(l, "incorrect argument");
1064 }
1065 const int subargs = lua_rawlen(l, -1);
1066 for (int j = 0; j < subargs; ++j) {
1067 CDate date;
1068 lua_rawgeti(l, -1, j + 1);
1069 CclGetDate(l, &date);
1070 lua_pop(l, 1);
1071 ++j;
1072
1073 std::string technology_ident = LuaToString(l, -1, j + 1);
1074 ++j;
1075
1076 bool has_upgrade = LuaToBoolean(l, -1, j + 1);
1077
1078 civilization->HistoricalUpgrades[technology_ident][date] = has_upgrade;
1079 }
1080 } else {
1081 LuaError(l, "Unsupported tag: %s" _C_ value);
1082 }
1083 }
1084
1085 if (civilization->ParentCivilization) {
1086 const CCivilization *parent_civilization = civilization->ParentCivilization;
1087 int parent_civilization_id = parent_civilization->ID;
1088
1089 if (PlayerRaces.CivilizationUpgrades[civilization_id].empty() && !PlayerRaces.CivilizationUpgrades[parent_civilization_id].empty()) { //if the civilization has no civilization upgrade, inherit that of its parent civilization
1090 PlayerRaces.CivilizationUpgrades[civilization_id] = PlayerRaces.CivilizationUpgrades[parent_civilization_id];
1091 }
1092
1093 //inherit button icons from the parent civilization, for button actions which none are specified
1094 for (std::map<int, IconConfig>::iterator iterator = PlayerRaces.ButtonIcons[parent_civilization_id].begin(); iterator != PlayerRaces.ButtonIcons[parent_civilization_id].end(); ++iterator) {
1095 if (PlayerRaces.ButtonIcons[civilization_id].find(iterator->first) == PlayerRaces.ButtonIcons[civilization_id].end()) {
1096 PlayerRaces.ButtonIcons[civilization_id][iterator->first] = iterator->second;
1097 }
1098 }
1099
1100 //inherit historical upgrades from the parent civilization, if no historical data is given for that upgrade for this civilization
1101 for (std::map<std::string, std::map<CDate, bool>>::const_iterator iterator = parent_civilization->HistoricalUpgrades.begin(); iterator != parent_civilization->HistoricalUpgrades.end(); ++iterator) {
1102 if (civilization->HistoricalUpgrades.find(iterator->first) == civilization->HistoricalUpgrades.end()) {
1103 civilization->HistoricalUpgrades[iterator->first] = iterator->second;
1104 }
1105 }
1106
1107 //unit sounds
1108 if (civilization->UnitSounds.Selected.Name.empty()) {
1109 civilization->UnitSounds.Selected = parent_civilization->UnitSounds.Selected;
1110 }
1111 if (civilization->UnitSounds.Acknowledgement.Name.empty()) {
1112 civilization->UnitSounds.Acknowledgement = parent_civilization->UnitSounds.Acknowledgement;
1113 }
1114 if (civilization->UnitSounds.Attack.Name.empty()) {
1115 civilization->UnitSounds.Attack = parent_civilization->UnitSounds.Attack;
1116 }
1117 if (civilization->UnitSounds.Idle.Name.empty()) {
1118 civilization->UnitSounds.Idle = parent_civilization->UnitSounds.Idle;
1119 }
1120 if (civilization->UnitSounds.Hit.Name.empty()) {
1121 civilization->UnitSounds.Hit = parent_civilization->UnitSounds.Hit;
1122 }
1123 if (civilization->UnitSounds.Miss.Name.empty()) {
1124 civilization->UnitSounds.Miss = parent_civilization->UnitSounds.Miss;
1125 }
1126 if (civilization->UnitSounds.FireMissile.Name.empty()) {
1127 civilization->UnitSounds.FireMissile = parent_civilization->UnitSounds.FireMissile;
1128 }
1129 if (civilization->UnitSounds.Step.Name.empty()) {
1130 civilization->UnitSounds.Step = parent_civilization->UnitSounds.Step;
1131 }
1132 if (civilization->UnitSounds.StepDirt.Name.empty()) {
1133 civilization->UnitSounds.StepDirt = parent_civilization->UnitSounds.StepDirt;
1134 }
1135 if (civilization->UnitSounds.StepGrass.Name.empty()) {
1136 civilization->UnitSounds.StepGrass = parent_civilization->UnitSounds.StepGrass;
1137 }
1138 if (civilization->UnitSounds.StepGravel.Name.empty()) {
1139 civilization->UnitSounds.StepGravel = parent_civilization->UnitSounds.StepGravel;
1140 }
1141 if (civilization->UnitSounds.StepMud.Name.empty()) {
1142 civilization->UnitSounds.StepMud = parent_civilization->UnitSounds.StepMud;
1143 }
1144 if (civilization->UnitSounds.StepStone.Name.empty()) {
1145 civilization->UnitSounds.StepStone = parent_civilization->UnitSounds.StepStone;
1146 }
1147 if (civilization->UnitSounds.Used.Name.empty()) {
1148 civilization->UnitSounds.Used = parent_civilization->UnitSounds.Used;
1149 }
1150 if (civilization->UnitSounds.Build.Name.empty()) {
1151 civilization->UnitSounds.Build = parent_civilization->UnitSounds.Build;
1152 }
1153 if (civilization->UnitSounds.Ready.Name.empty()) {
1154 civilization->UnitSounds.Ready = parent_civilization->UnitSounds.Ready;
1155 }
1156 if (civilization->UnitSounds.Repair.Name.empty()) {
1157 civilization->UnitSounds.Repair = parent_civilization->UnitSounds.Repair;
1158 }
1159 for (unsigned int j = 0; j < MaxCosts; ++j) {
1160 if (civilization->UnitSounds.Harvest[j].Name.empty()) {
1161 civilization->UnitSounds.Harvest[j] = parent_civilization->UnitSounds.Harvest[j];
1162 }
1163 }
1164 if (civilization->UnitSounds.Help.Name.empty()) {
1165 civilization->UnitSounds.Help = parent_civilization->UnitSounds.Help;
1166 }
1167 if (civilization->UnitSounds.HelpTown.Name.empty()) {
1168 civilization->UnitSounds.HelpTown = parent_civilization->UnitSounds.HelpTown;
1169 }
1170 }
1171
1172 if (PlayerRaces.ButtonIcons[civilization_id].find(ButtonMove) != PlayerRaces.ButtonIcons[civilization_id].end()) {
1173 std::string button_definition = "DefineButton({\n";
1174 button_definition += "\tPos = 1,\n";
1175 button_definition += "\tAction = \"move\",\n";
1176 button_definition += "\tPopup = \"popup-commands\",\n";
1177 button_definition += "\tKey = \"m\",\n";
1178 button_definition += "\tHint = _(\"~!Move\"),\n";
1179 button_definition += "\tForUnit = {\"" + PlayerRaces.Name[civilization_id] + "-group\"},\n";
1180 button_definition += "})";
1181 CclCommand(button_definition);
1182 }
1183
1184 if (PlayerRaces.ButtonIcons[civilization_id].find(ButtonStop) != PlayerRaces.ButtonIcons[civilization_id].end()) {
1185 std::string button_definition = "DefineButton({\n";
1186 button_definition += "\tPos = 2,\n";
1187 button_definition += "\tAction = \"stop\",\n";
1188 button_definition += "\tPopup = \"popup-commands\",\n";
1189 button_definition += "\tKey = \"s\",\n";
1190 button_definition += "\tHint = _(\"~!Stop\"),\n";
1191 button_definition += "\tForUnit = {\"" + PlayerRaces.Name[civilization_id] + "-group\"},\n";
1192 button_definition += "})";
1193 CclCommand(button_definition);
1194 }
1195
1196 if (PlayerRaces.ButtonIcons[civilization_id].find(ButtonAttack) != PlayerRaces.ButtonIcons[civilization_id].end()) {
1197 std::string button_definition = "DefineButton({\n";
1198 button_definition += "\tPos = 3,\n";
1199 button_definition += "\tAction = \"attack\",\n";
1200 button_definition += "\tPopup = \"popup-commands\",\n";
1201 button_definition += "\tKey = \"a\",\n";
1202 button_definition += "\tHint = _(\"~!Attack\"),\n";
1203 button_definition += "\tForUnit = {\"" + PlayerRaces.Name[civilization_id] + "-group\"},\n";
1204 button_definition += "})";
1205 CclCommand(button_definition);
1206 }
1207
1208 if (PlayerRaces.ButtonIcons[civilization_id].find(ButtonPatrol) != PlayerRaces.ButtonIcons[civilization_id].end()) {
1209 std::string button_definition = "DefineButton({\n";
1210 button_definition += "\tPos = 4,\n";
1211 button_definition += "\tAction = \"patrol\",\n";
1212 button_definition += "\tPopup = \"popup-commands\",\n";
1213 button_definition += "\tKey = \"p\",\n";
1214 button_definition += "\tHint = _(\"~!Patrol\"),\n";
1215 button_definition += "\tForUnit = {\"" + PlayerRaces.Name[civilization_id] + "-group\"},\n";
1216 button_definition += "})";
1217 CclCommand(button_definition);
1218 }
1219
1220 if (PlayerRaces.ButtonIcons[civilization_id].find(ButtonStandGround) != PlayerRaces.ButtonIcons[civilization_id].end()) {
1221 std::string button_definition = "DefineButton({\n";
1222 button_definition += "\tPos = 5,\n";
1223 button_definition += "\tAction = \"stand-ground\",\n";
1224 button_definition += "\tPopup = \"popup-commands\",\n";
1225 button_definition += "\tKey = \"t\",\n";
1226 button_definition += "\tHint = _(\"S~!tand Ground\"),\n";
1227 button_definition += "\tForUnit = {\"" + PlayerRaces.Name[civilization_id] + "-group\"},\n";
1228 button_definition += "})";
1229 CclCommand(button_definition);
1230 }
1231
1232 return 0;
1233 }
1234
1235 /**
1236 ** Define a word for a particular language.
1237 **
1238 ** @param l Lua state.
1239 */
CclDefineLanguageWord(lua_State * l)1240 static int CclDefineLanguageWord(lua_State *l)
1241 {
1242 LuaCheckArgs(l, 2);
1243 if (!lua_istable(l, 2)) {
1244 LuaError(l, "incorrect argument (expected table)");
1245 }
1246
1247 LanguageWord *word = new LanguageWord;
1248 word->Word = LuaToString(l, 1);
1249
1250 LanguageWord *replaces = nullptr;
1251
1252 // Parse the list:
1253 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
1254 const char *value = LuaToString(l, -2);
1255
1256 if (!strcmp(value, "Language")) {
1257 CLanguage *language = PlayerRaces.GetLanguage(LuaToString(l, -1));
1258
1259 if (language) {
1260 language->LanguageWords.push_back(word);
1261 word->Language = language;
1262
1263 for (size_t i = 0; i < language->Dialects.size(); ++i) { //copy the word over for dialects
1264 language->Dialects[i]->LanguageWords.push_back(word);
1265 }
1266 } else {
1267 LuaError(l, "Language not found.");
1268 }
1269 } else if (!strcmp(value, "Meanings")) {
1270 if (!lua_istable(l, -1)) {
1271 LuaError(l, "incorrect argument");
1272 }
1273 const int subargs = lua_rawlen(l, -1);
1274 for (int j = 0; j < subargs; ++j) {
1275 word->Meanings.push_back(LuaToString(l, -1, j + 1));
1276 }
1277 } else if (!strcmp(value, "Type")) {
1278 std::string word_type_name = LuaToString(l, -1);
1279 int word_type = GetWordTypeIdByName(word_type_name);
1280 if (word_type != -1) {
1281 word->Type = word_type;
1282 } else {
1283 LuaError(l, "Word type \"%s\" doesn't exist." _C_ word_type_name.c_str());
1284 }
1285 } else if (!strcmp(value, "DerivesFrom")) {
1286 if (!lua_istable(l, -1)) {
1287 LuaError(l, "incorrect argument");
1288 }
1289 int j = 0;
1290 CLanguage *derives_from_language = PlayerRaces.GetLanguage(LuaToString(l, -1, j + 1));
1291 ++j;
1292 int derives_from_word_type = GetWordTypeIdByName(LuaToString(l, -1, j + 1));
1293 ++j;
1294
1295 std::vector<std::string> word_meanings;
1296 lua_rawgeti(l, -1, j + 1);
1297 if (lua_istable(l, -1)) {
1298 const int subargs = lua_rawlen(l, -1);
1299 for (int k = 0; k < subargs; ++k) {
1300 word_meanings.push_back(LuaToString(l, -1, k + 1));
1301 }
1302
1303 ++j;
1304 }
1305 lua_pop(l, 1);
1306
1307 if (derives_from_language && derives_from_word_type != -1) {
1308 std::string derives_from_word = LuaToString(l, -1, j + 1);
1309 word->DerivesFrom = derives_from_language->GetWord(derives_from_word, derives_from_word_type, word_meanings);
1310
1311 if (word->DerivesFrom != nullptr) {
1312 word->DerivesFrom->DerivesTo.push_back(word);
1313 } else {
1314 LuaError(l, "Word \"%s\" is set to derive from \"%s\" (%s, %s), but the latter doesn't exist" _C_ word->Word.c_str() _C_ derives_from_word.c_str() _C_ derives_from_language->Ident.c_str() _C_ GetWordTypeNameById(derives_from_word_type).c_str());
1315 }
1316 } else {
1317 LuaError(l, "Word \"%s\"'s derives from is incorrectly set, as either the language or the word type set for the original word given is incorrect" _C_ word->Word.c_str());
1318 }
1319 } else if (!strcmp(value, "Replaces")) {
1320 if (!lua_istable(l, -1)) {
1321 LuaError(l, "incorrect argument");
1322 }
1323 int j = 0;
1324 CLanguage *replaces_language = PlayerRaces.GetLanguage(LuaToString(l, -1, j + 1));
1325 ++j;
1326 int replaces_word_type = GetWordTypeIdByName(LuaToString(l, -1, j + 1));
1327 ++j;
1328
1329 std::vector<std::string> word_meanings;
1330 lua_rawgeti(l, -1, j + 1);
1331 if (lua_istable(l, -1)) {
1332 const int subargs = lua_rawlen(l, -1);
1333 for (int k = 0; k < subargs; ++k) {
1334 word_meanings.push_back(LuaToString(l, -1, k + 1));
1335 }
1336
1337 ++j;
1338 }
1339 lua_pop(l, 1);
1340
1341 if (replaces_language && replaces_word_type != -1) {
1342 std::string replaces_word = LuaToString(l, -1, j + 1);
1343 replaces = replaces_language->GetWord(replaces_word, replaces_word_type, word_meanings);
1344
1345 if (replaces == nullptr) {
1346 LuaError(l, "Word \"%s\" is set to replace \"%s\" (%s, %s), but the latter doesn't exist" _C_ word->Word.c_str() _C_ replaces_word.c_str() _C_ replaces_language->Ident.c_str() _C_ GetWordTypeNameById(replaces_word_type).c_str());
1347 }
1348 } else {
1349 LuaError(l, "Word \"%s\"'s replace is incorrectly set, as either the language or the word type set for the original word given is incorrect" _C_ word->Word.c_str());
1350 }
1351 } else if (!strcmp(value, "CompoundElements")) {
1352 if (!lua_istable(l, -1)) {
1353 LuaError(l, "incorrect argument");
1354 }
1355 const int subargs = lua_rawlen(l, -1);
1356 for (int j = 0; j < subargs; ++j) {
1357 std::string affix_type_name = LuaToString(l, -1, j + 1);
1358 int affix_type = GetAffixTypeIdByName(affix_type_name);
1359 if (affix_type == -1) {
1360 LuaError(l, "Affix type \"%s\" doesn't exist." _C_ affix_type_name.c_str());
1361 }
1362 ++j;
1363
1364 CLanguage *affix_language = PlayerRaces.GetLanguage(LuaToString(l, -1, j + 1)); // should be the same language as that of the word, but needs to be specified since the word's language may not have been set yet
1365 ++j;
1366 int affix_word_type = GetWordTypeIdByName(LuaToString(l, -1, j + 1));
1367 ++j;
1368
1369 std::vector<std::string> word_meanings;
1370 lua_rawgeti(l, -1, j + 1);
1371 if (lua_istable(l, -1)) {
1372 const int subargs = lua_rawlen(l, -1);
1373 for (int k = 0; k < subargs; ++k) {
1374 word_meanings.push_back(LuaToString(l, -1, k + 1));
1375 }
1376
1377 ++j;
1378 }
1379 lua_pop(l, 1);
1380
1381 if (affix_language && affix_word_type != -1) {
1382 std::string affix_word = LuaToString(l, -1, j + 1);
1383 word->CompoundElements[affix_type] = affix_language->GetWord(affix_word, affix_word_type, word_meanings);
1384
1385 if (word->CompoundElements[affix_type] != nullptr) {
1386 word->CompoundElements[affix_type]->CompoundElementOf[affix_type].push_back(word);
1387 } else {
1388 LuaError(l, "Word \"%s\" is set to be a compound formed by \"%s\" (%s, %s), but the latter doesn't exist" _C_ word->Word.c_str() _C_ affix_word.c_str() _C_ affix_language->Ident.c_str() _C_ GetWordTypeNameById(affix_word_type).c_str());
1389 }
1390 } else {
1391 LuaError(l, "Word \"%s\"'s compound elements are incorrectly set, as either the language or the word type set for one of the element words given is incorrect" _C_ word->Word.c_str());
1392 }
1393 }
1394 } else if (!strcmp(value, "Gender")) {
1395 std::string grammatical_gender_name = LuaToString(l, -1);
1396 int grammatical_gender = GetGrammaticalGenderIdByName(grammatical_gender_name);
1397 if (grammatical_gender != -1) {
1398 word->Gender = grammatical_gender;
1399 } else {
1400 LuaError(l, "Grammatical gender \"%s\" doesn't exist." _C_ grammatical_gender_name.c_str());
1401 }
1402 } else if (!strcmp(value, "GrammaticalNumber")) {
1403 std::string grammatical_number_name = LuaToString(l, -1);
1404 int grammatical_number = GetGrammaticalNumberIdByName(grammatical_number_name);
1405 if (grammatical_number != -1) {
1406 word->GrammaticalNumber = grammatical_number;
1407 } else {
1408 LuaError(l, "Grammatical number \"%s\" doesn't exist." _C_ grammatical_number_name.c_str());
1409 }
1410 } else if (!strcmp(value, "Archaic")) {
1411 word->Archaic = LuaToBoolean(l, -1);
1412 } else if (!strcmp(value, "NumberCaseInflections")) {
1413 if (!lua_istable(l, -1)) {
1414 LuaError(l, "incorrect argument");
1415 }
1416 const int subargs = lua_rawlen(l, -1);
1417 for (int j = 0; j < subargs; ++j) {
1418 std::string grammatical_number_name = LuaToString(l, -1, j + 1);
1419 int grammatical_number = GetGrammaticalNumberIdByName(grammatical_number_name);
1420 if (grammatical_number == -1) {
1421 LuaError(l, "Grammatical number \"%s\" doesn't exist." _C_ grammatical_number_name.c_str());
1422 }
1423 ++j;
1424
1425 std::string grammatical_case_name = LuaToString(l, -1, j + 1);
1426 int grammatical_case = GetGrammaticalCaseIdByName(grammatical_case_name);
1427 if (grammatical_case == -1) {
1428 LuaError(l, "Grammatical case \"%s\" doesn't exist." _C_ grammatical_case_name.c_str());
1429 }
1430 ++j;
1431
1432 word->NumberCaseInflections[std::tuple<int, int>(grammatical_number, grammatical_case)] = LuaToString(l, -1, j + 1);
1433 }
1434 } else if (!strcmp(value, "NumberPersonTenseMoodInflections")) {
1435 if (!lua_istable(l, -1)) {
1436 LuaError(l, "incorrect argument");
1437 }
1438 const int subargs = lua_rawlen(l, -1);
1439 for (int j = 0; j < subargs; ++j) {
1440 std::string grammatical_number_name = LuaToString(l, -1, j + 1);
1441 int grammatical_number = GetGrammaticalNumberIdByName(grammatical_number_name);
1442 if (grammatical_number == -1) {
1443 LuaError(l, "Grammatical number \"%s\" doesn't exist." _C_ grammatical_number_name.c_str());
1444 }
1445 ++j;
1446
1447 std::string grammatical_person_name = LuaToString(l, -1, j + 1);
1448 int grammatical_person = GetGrammaticalPersonIdByName(grammatical_person_name);
1449 if (grammatical_person == -1) {
1450 LuaError(l, "Grammatical person \"%s\" doesn't exist." _C_ grammatical_person_name.c_str());
1451 }
1452 ++j;
1453
1454 std::string grammatical_tense_name = LuaToString(l, -1, j + 1);
1455 int grammatical_tense = GetGrammaticalTenseIdByName(grammatical_tense_name);
1456 if (grammatical_tense == -1) {
1457 LuaError(l, "Grammatical tense \"%s\" doesn't exist." _C_ grammatical_tense_name.c_str());
1458 }
1459 ++j;
1460
1461 std::string grammatical_mood_name = LuaToString(l, -1, j + 1);
1462 int grammatical_mood = GetGrammaticalMoodIdByName(grammatical_mood_name);
1463 if (grammatical_mood == -1) {
1464 LuaError(l, "Grammatical mood \"%s\" doesn't exist." _C_ grammatical_mood_name.c_str());
1465 }
1466 ++j;
1467
1468 word->NumberPersonTenseMoodInflections[std::tuple<int, int, int, int>(grammatical_number, grammatical_person, grammatical_tense, grammatical_mood)] = LuaToString(l, -1, j + 1);
1469 }
1470 } else if (!strcmp(value, "ComparisonDegreeCaseInflections")) {
1471 if (!lua_istable(l, -1)) {
1472 LuaError(l, "incorrect argument");
1473 }
1474 const int subargs = lua_rawlen(l, -1);
1475 for (int j = 0; j < subargs; ++j) {
1476 std::string comparison_degree_name = LuaToString(l, -1, j + 1);
1477 int comparison_degree = GetComparisonDegreeIdByName(comparison_degree_name);
1478 if (comparison_degree == -1) {
1479 LuaError(l, "Comparison degree \"%s\" doesn't exist." _C_ comparison_degree_name.c_str());
1480 }
1481 ++j;
1482
1483 int grammatical_case = GrammaticalCaseNoCase;
1484 if (GetGrammaticalCaseIdByName(LuaToString(l, -1, j + 1)) != -1) {
1485 std::string grammatical_case_name = LuaToString(l, -1, j + 1);
1486 grammatical_case = GetGrammaticalCaseIdByName(grammatical_case_name);
1487 if (grammatical_case == -1) {
1488 LuaError(l, "Grammatical case \"%s\" doesn't exist." _C_ grammatical_case_name.c_str());
1489 }
1490 ++j;
1491 }
1492
1493 word->ComparisonDegreeCaseInflections[comparison_degree][grammatical_case] = LuaToString(l, -1, j + 1);
1494 }
1495 } else if (!strcmp(value, "Participles")) {
1496 if (!lua_istable(l, -1)) {
1497 LuaError(l, "incorrect argument");
1498 }
1499 const int subargs = lua_rawlen(l, -1);
1500 for (int j = 0; j < subargs; ++j) {
1501 std::string grammatical_tense_name = LuaToString(l, -1, j + 1);
1502 int grammatical_tense = GetGrammaticalTenseIdByName(grammatical_tense_name);
1503 if (grammatical_tense == -1) {
1504 LuaError(l, "Grammatical tense \"%s\" doesn't exist." _C_ grammatical_tense_name.c_str());
1505 }
1506 ++j;
1507
1508 word->Participles[grammatical_tense] = LuaToString(l, -1, j + 1);
1509 }
1510 //noun-specific variables
1511 } else if (!strcmp(value, "Uncountable")) {
1512 word->Uncountable = LuaToBoolean(l, -1);
1513 //pronoun and article-specific variables
1514 } else if (!strcmp(value, "Nominative")) {
1515 word->Nominative = LuaToString(l, -1);
1516 } else if (!strcmp(value, "Accusative")) {
1517 word->Accusative = LuaToString(l, -1);
1518 } else if (!strcmp(value, "Dative")) {
1519 word->Dative = LuaToString(l, -1);
1520 } else if (!strcmp(value, "Genitive")) {
1521 word->Genitive = LuaToString(l, -1);
1522 //article-specific variables
1523 } else if (!strcmp(value, "ArticleType")) {
1524 std::string article_type_name = LuaToString(l, -1);
1525 int article_type = GetArticleTypeIdByName(article_type_name);
1526 if (article_type != -1) {
1527 word->ArticleType = article_type;
1528 } else {
1529 LuaError(l, "Article type \"%s\" doesn't exist." _C_ article_type_name.c_str());
1530 }
1531 //numeral-specific variables
1532 } else if (!strcmp(value, "Number")) {
1533 word->Number = LuaToNumber(l, -1);
1534 //type name variables
1535 } else if (!strcmp(value, "Mod")) {
1536 word->Mod = LuaToString(l, -1);
1537 } else if (!strcmp(value, "MapWord")) { //to keep backwards compatibility
1538 word->Mod = Map.Info.Filename;
1539 } else {
1540 LuaError(l, "Unsupported tag: %s" _C_ value);
1541 }
1542 }
1543
1544 if (!word->Language) {
1545 LuaError(l, "Word \"%s\" has not been assigned to any language" _C_ word->Word.c_str());
1546 }
1547
1548 if (word->Type == -1) {
1549 LuaError(l, "Word \"%s\" has no type" _C_ word->Word.c_str());
1550 }
1551
1552 if (replaces != nullptr) {
1553 word->Language->RemoveWord(replaces);
1554 }
1555
1556 return 0;
1557 }
1558
1559 /**
1560 ** Get a civilization's data.
1561 **
1562 ** @param l Lua state.
1563 */
CclGetCivilizationData(lua_State * l)1564 static int CclGetCivilizationData(lua_State *l)
1565 {
1566 if (lua_gettop(l) < 2) {
1567 LuaError(l, "incorrect argument");
1568 }
1569 std::string civilization_name = LuaToString(l, 1);
1570 CCivilization *civilization = CCivilization::GetCivilization(civilization_name);
1571 if (!civilization) {
1572 return 0;
1573 }
1574 int civilization_id = civilization->ID;
1575
1576 const char *data = LuaToString(l, 2);
1577
1578 if (!strcmp(data, "Display")) {
1579 lua_pushstring(l, PlayerRaces.Display[civilization_id].c_str());
1580 return 1;
1581 } else if (!strcmp(data, "Description")) {
1582 lua_pushstring(l, civilization->Description.c_str());
1583 return 1;
1584 } else if (!strcmp(data, "Quote")) {
1585 lua_pushstring(l, civilization->Quote.c_str());
1586 return 1;
1587 } else if (!strcmp(data, "Background")) {
1588 lua_pushstring(l, civilization->Background.c_str());
1589 return 1;
1590 } else if (!strcmp(data, "Adjective")) {
1591 if (!civilization->Adjective.empty()) {
1592 lua_pushstring(l, civilization->Adjective.c_str());
1593 } else {
1594 lua_pushstring(l, PlayerRaces.Display[civilization_id].c_str());
1595 }
1596 return 1;
1597 } else if (!strcmp(data, "Playable")) {
1598 lua_pushboolean(l, PlayerRaces.Playable[civilization_id]);
1599 return 1;
1600 } else if (!strcmp(data, "Species")) {
1601 lua_pushstring(l, PlayerRaces.Species[civilization_id].c_str());
1602 return 1;
1603 } else if (!strcmp(data, "ParentCivilization")) {
1604 if (civilization->ParentCivilization) {
1605 lua_pushstring(l, PlayerRaces.Name[civilization->ParentCivilization->ID].c_str());
1606 } else {
1607 lua_pushstring(l, "");
1608 }
1609 return 1;
1610 } else if (!strcmp(data, "Language")) {
1611 CLanguage *language = PlayerRaces.GetCivilizationLanguage(civilization_id);
1612 if (language) {
1613 lua_pushstring(l, language->Ident.c_str());
1614 } else {
1615 lua_pushstring(l, "");
1616 }
1617 return 1;
1618 } else if (!strcmp(data, "DefaultColor")) {
1619 lua_pushstring(l, PlayerRaces.DefaultColor[civilization_id].c_str());
1620 return 1;
1621 } else if (!strcmp(data, "CivilizationUpgrade")) {
1622 lua_pushstring(l, PlayerRaces.CivilizationUpgrades[civilization_id].c_str());
1623 return 1;
1624 } else if (!strcmp(data, "DevelopsFrom")) {
1625 lua_createtable(l, PlayerRaces.DevelopsFrom[civilization_id].size(), 0);
1626 for (size_t i = 1; i <= PlayerRaces.DevelopsFrom[civilization_id].size(); ++i)
1627 {
1628 lua_pushstring(l, PlayerRaces.Name[PlayerRaces.DevelopsFrom[civilization_id][i-1]].c_str());
1629 lua_rawseti(l, -2, i);
1630 }
1631 return 1;
1632 } else if (!strcmp(data, "DevelopsTo")) {
1633 lua_createtable(l, PlayerRaces.DevelopsTo[civilization_id].size(), 0);
1634 for (size_t i = 1; i <= PlayerRaces.DevelopsTo[civilization_id].size(); ++i)
1635 {
1636 lua_pushstring(l, PlayerRaces.Name[PlayerRaces.DevelopsTo[civilization_id][i-1]].c_str());
1637 lua_rawseti(l, -2, i);
1638 }
1639 return 1;
1640 } else if (!strcmp(data, "Factions")) {
1641 bool is_mod = false;
1642 if (lua_gettop(l) >= 3) {
1643 is_mod = true;
1644 }
1645
1646 std::string mod_file;
1647
1648 if (is_mod) {
1649 mod_file = LuaToString(l, 3);
1650 }
1651
1652 std::vector<std::string> factions;
1653 for (size_t i = 0; i < PlayerRaces.Factions.size(); ++i)
1654 {
1655 if (PlayerRaces.Factions[i]->Civilization != civilization) {
1656 continue;
1657 }
1658
1659 if (!is_mod || PlayerRaces.Factions[i]->Mod == mod_file) {
1660 factions.push_back(PlayerRaces.Factions[i]->Ident);
1661 }
1662 }
1663
1664 lua_createtable(l, factions.size(), 0);
1665 for (size_t i = 1; i <= factions.size(); ++i)
1666 {
1667 lua_pushstring(l, factions[i-1].c_str());
1668 lua_rawseti(l, -2, i);
1669 }
1670 return 1;
1671 } else if (!strcmp(data, "Quests")) {
1672 lua_createtable(l, civilization->Quests.size(), 0);
1673 for (size_t i = 1; i <= civilization->Quests.size(); ++i)
1674 {
1675 lua_pushstring(l, civilization->Quests[i-1]->Ident.c_str());
1676 lua_rawseti(l, -2, i);
1677 }
1678 return 1;
1679 } else if (!strcmp(data, "ShipNames")) {
1680 lua_createtable(l, civilization->ShipNames.size(), 0);
1681 for (size_t i = 1; i <= civilization->ShipNames.size(); ++i)
1682 {
1683 lua_pushstring(l, civilization->ShipNames[i-1].c_str());
1684 lua_rawseti(l, -2, i);
1685 }
1686 return 1;
1687 } else {
1688 LuaError(l, "Invalid field: %s" _C_ data);
1689 }
1690
1691 return 0;
1692 }
1693
1694 /**
1695 ** Get a civilization's unit type/upgrade of a certain class.
1696 **
1697 ** @param l Lua state.
1698 */
CclGetCivilizationClassUnitType(lua_State * l)1699 static int CclGetCivilizationClassUnitType(lua_State *l)
1700 {
1701 LuaCheckArgs(l, 2);
1702 std::string class_name = LuaToString(l, 1);
1703 int class_id = GetUnitTypeClassIndexByName(class_name);
1704 CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, 2));
1705 std::string unit_type_ident;
1706 if (civilization && class_id != -1) {
1707 int unit_type_id = PlayerRaces.GetCivilizationClassUnitType(civilization->ID, class_id);
1708 if (unit_type_id != -1) {
1709 unit_type_ident = UnitTypes[unit_type_id]->Ident;
1710 }
1711 }
1712
1713 if (unit_type_ident.empty()) { //if wasn't found, see if it is an upgrade class instead
1714 class_id = GetUpgradeClassIndexByName(class_name);
1715 if (civilization && class_id != -1) {
1716 int upgrade_id = PlayerRaces.GetCivilizationClassUpgrade(civilization->ID, class_id);
1717 if (upgrade_id != -1) {
1718 unit_type_ident = AllUpgrades[upgrade_id]->Ident;
1719 }
1720 }
1721 }
1722
1723 if (!unit_type_ident.empty()) {
1724 lua_pushstring(l, unit_type_ident.c_str());
1725 } else {
1726 lua_pushnil(l);
1727 }
1728
1729 return 1;
1730 }
1731
1732
1733 /**
1734 ** Get a faction's unit type/upgrade of a certain class.
1735 **
1736 ** @param l Lua state.
1737 */
CclGetFactionClassUnitType(lua_State * l)1738 static int CclGetFactionClassUnitType(lua_State *l)
1739 {
1740 std::string class_name = LuaToString(l, 1);
1741 int class_id = GetUnitTypeClassIndexByName(class_name);
1742 int faction_id = -1;
1743 CFaction *faction = nullptr;
1744 const int nargs = lua_gettop(l);
1745 if (nargs == 2) {
1746 faction = PlayerRaces.GetFaction(LuaToString(l, 2));
1747 if (faction) {
1748 faction_id = faction->ID;
1749 }
1750 } else if (nargs == 3) {
1751 //the civilization was the second argument, but it isn't needed anymore
1752 faction = PlayerRaces.GetFaction(LuaToString(l, 3));
1753 if (faction) {
1754 faction_id = faction->ID;
1755 }
1756 }
1757 std::string unit_type_ident;
1758 if (class_id != -1) {
1759 int unit_type_id = PlayerRaces.GetFactionClassUnitType(faction_id, class_id);
1760 if (unit_type_id != -1) {
1761 unit_type_ident = UnitTypes[unit_type_id]->Ident;
1762 }
1763 }
1764
1765 if (unit_type_ident.empty()) { //if wasn't found, see if it is an upgrade class instead
1766 class_id = GetUpgradeClassIndexByName(class_name);
1767 if (class_id != -1) {
1768 int upgrade_id = PlayerRaces.GetFactionClassUpgrade(faction_id, class_id);
1769 if (upgrade_id != -1) {
1770 unit_type_ident = AllUpgrades[upgrade_id]->Ident;
1771 }
1772 }
1773 }
1774
1775 if (!unit_type_ident.empty()) {
1776 lua_pushstring(l, unit_type_ident.c_str());
1777 } else {
1778 lua_pushnil(l);
1779 }
1780
1781 return 1;
1782 }
1783
1784 /**
1785 ** Define a faction.
1786 **
1787 ** @param l Lua state.
1788 */
CclDefineFaction(lua_State * l)1789 static int CclDefineFaction(lua_State *l)
1790 {
1791 LuaCheckArgs(l, 2);
1792 if (!lua_istable(l, 2)) {
1793 LuaError(l, "incorrect argument (expected table)");
1794 }
1795
1796 std::string faction_name = LuaToString(l, 1);
1797 std::string parent_faction;
1798
1799 CFaction *faction = PlayerRaces.GetFaction(faction_name);
1800 if (faction) { // redefinition
1801 if (faction->ParentFaction != -1) {
1802 parent_faction = PlayerRaces.Factions[faction->ParentFaction]->Ident;
1803 }
1804 } else {
1805 faction = new CFaction;
1806 faction->Ident = faction_name;
1807 faction->ID = PlayerRaces.Factions.size();
1808 PlayerRaces.Factions.push_back(faction);
1809 SetFactionStringToIndex(faction->Ident, faction->ID);
1810 }
1811
1812 // Parse the list:
1813 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
1814 const char *value = LuaToString(l, -2);
1815
1816 if (!strcmp(value, "Civilization")) {
1817 CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1));
1818 if (civilization) {
1819 faction->Civilization = civilization;
1820 }
1821 } else if (!strcmp(value, "Name")) {
1822 faction->Name = LuaToString(l, -1);
1823 } else if (!strcmp(value, "Description")) {
1824 faction->Description = LuaToString(l, -1);
1825 } else if (!strcmp(value, "Quote")) {
1826 faction->Quote = LuaToString(l, -1);
1827 } else if (!strcmp(value, "Background")) {
1828 faction->Background = LuaToString(l, -1);
1829 } else if (!strcmp(value, "Adjective")) {
1830 faction->Adjective = LuaToString(l, -1);
1831 } else if (!strcmp(value, "Type")) {
1832 std::string faction_type_name = LuaToString(l, -1);
1833 int faction_type = GetFactionTypeIdByName(faction_type_name);
1834 if (faction_type != -1) {
1835 faction->Type = faction_type;
1836 } else {
1837 LuaError(l, "Faction type \"%s\" doesn't exist." _C_ faction_type_name.c_str());
1838 }
1839 } else if (!strcmp(value, "Colors")) {
1840 if (!lua_istable(l, -1)) {
1841 LuaError(l, "incorrect argument");
1842 }
1843 faction->Colors.clear(); //remove previously defined colors
1844 const int subargs = lua_rawlen(l, -1);
1845 for (int k = 0; k < subargs; ++k) {
1846 std::string color_name = LuaToString(l, -1, k + 1);
1847 int color = GetPlayerColorIndexByName(color_name);
1848 if (color != -1) {
1849 faction->Colors.push_back(color);
1850 } else {
1851 LuaError(l, "Player color \"%s\" doesn't exist." _C_ color_name.c_str());
1852 }
1853 }
1854 } else if (!strcmp(value, "DefaultTier")) {
1855 std::string faction_tier_name = LuaToString(l, -1);
1856 int faction_tier = GetFactionTierIdByName(faction_tier_name);
1857 if (faction_tier != -1) {
1858 faction->DefaultTier = faction_tier;
1859 } else {
1860 LuaError(l, "Faction tier \"%s\" doesn't exist." _C_ faction_tier_name.c_str());
1861 }
1862 } else if (!strcmp(value, "DefaultGovernmentType")) {
1863 std::string government_type_name = LuaToString(l, -1);
1864 int government_type = GetGovernmentTypeIdByName(government_type_name);
1865 if (government_type != -1) {
1866 faction->DefaultGovernmentType = government_type;
1867 } else {
1868 LuaError(l, "Government type \"%s\" doesn't exist." _C_ government_type_name.c_str());
1869 }
1870 } else if (!strcmp(value, "DefaultAI")) {
1871 faction->DefaultAI = LuaToString(l, -1);
1872 } else if (!strcmp(value, "ParentFaction")) {
1873 parent_faction = LuaToString(l, -1);
1874 } else if (!strcmp(value, "Playable")) {
1875 faction->Playable = LuaToBoolean(l, -1);
1876 } else if (!strcmp(value, "DefiniteArticle")) {
1877 faction->DefiniteArticle = LuaToBoolean(l, -1);
1878 } else if (!strcmp(value, "Icon")) {
1879 faction->Icon.Name = LuaToString(l, -1);
1880 faction->Icon.Icon = nullptr;
1881 faction->Icon.Load();
1882 faction->Icon.Icon->Load();
1883 } else if (!strcmp(value, "Currency")) {
1884 CCurrency *currency = CCurrency::GetCurrency(LuaToString(l, -1));
1885 faction->Currency = currency;
1886 } else if (!strcmp(value, "DevelopsFrom")) {
1887 if (!lua_istable(l, -1)) {
1888 LuaError(l, "incorrect argument");
1889 }
1890 const int subargs = lua_rawlen(l, -1);
1891 for (int k = 0; k < subargs; ++k) {
1892 CFaction *second_faction = PlayerRaces.GetFaction(LuaToString(l, -1, k + 1));
1893 if (!second_faction) {
1894 LuaError(l, "Faction doesn't exist.");
1895 }
1896 faction->DevelopsFrom.push_back(second_faction);
1897 second_faction->DevelopsTo.push_back(faction);
1898 }
1899 } else if (!strcmp(value, "DevelopsTo")) {
1900 if (!lua_istable(l, -1)) {
1901 LuaError(l, "incorrect argument");
1902 }
1903 const int subargs = lua_rawlen(l, -1);
1904 for (int k = 0; k < subargs; ++k) {
1905 CFaction *second_faction = PlayerRaces.GetFaction(LuaToString(l, -1, k + 1));
1906 if (!second_faction) {
1907 LuaError(l, "Faction doesn't exist.");
1908 }
1909 faction->DevelopsTo.push_back(second_faction);
1910 second_faction->DevelopsFrom.push_back(faction);
1911 }
1912 } else if (!strcmp(value, "Titles")) {
1913 if (!lua_istable(l, -1)) {
1914 LuaError(l, "incorrect argument");
1915 }
1916 const int subargs = lua_rawlen(l, -1);
1917 for (int k = 0; k < subargs; ++k) {
1918 int government_type = GetGovernmentTypeIdByName(LuaToString(l, -1, k + 1));
1919 ++k;
1920 int faction_tier = GetFactionTierIdByName(LuaToString(l, -1, k + 1));
1921 ++k;
1922 faction->Titles[government_type][faction_tier] = LuaToString(l, -1, k + 1);
1923 }
1924 } else if (!strcmp(value, "MinisterTitles")) {
1925 if (!lua_istable(l, -1)) {
1926 LuaError(l, "incorrect argument");
1927 }
1928 const int subargs = lua_rawlen(l, -1);
1929 for (int k = 0; k < subargs; ++k) {
1930 int title = GetCharacterTitleIdByName(LuaToString(l, -1, k + 1));
1931 ++k;
1932 int gender = GetGenderIdByName(LuaToString(l, -1, k + 1));
1933 ++k;
1934 int government_type = GetGovernmentTypeIdByName(LuaToString(l, -1, k + 1));
1935 ++k;
1936 int faction_tier = GetFactionTierIdByName(LuaToString(l, -1, k + 1));
1937 ++k;
1938 faction->MinisterTitles[title][gender][government_type][faction_tier] = LuaToString(l, -1, k + 1);
1939 }
1940 } else if (!strcmp(value, "FactionUpgrade")) {
1941 faction->FactionUpgrade = LuaToString(l, -1);
1942 } else if (!strcmp(value, "ButtonIcons")) {
1943 if (!lua_istable(l, -1)) {
1944 LuaError(l, "incorrect argument");
1945 }
1946 const int subargs = lua_rawlen(l, -1);
1947 for (int j = 0; j < subargs; ++j) {
1948 std::string button_action_name = LuaToString(l, -1, j + 1);
1949 int button_action = GetButtonActionIdByName(button_action_name);
1950 if (button_action != -1) {
1951 ++j;
1952 faction->ButtonIcons[button_action].Name = LuaToString(l, -1, j + 1);
1953 faction->ButtonIcons[button_action].Icon = nullptr;
1954 faction->ButtonIcons[button_action].Load();
1955 } else {
1956 LuaError(l, "Button action \"%s\" doesn't exist." _C_ button_action_name.c_str());
1957 }
1958 }
1959 } else if (!strcmp(value, "ForceTypeWeights")) {
1960 if (!lua_istable(l, -1)) {
1961 LuaError(l, "incorrect argument");
1962 }
1963
1964 faction->ForceTypeWeights.clear();
1965
1966 const int subargs = lua_rawlen(l, -1);
1967 for (int j = 0; j < subargs; ++j) {
1968 int force_type = GetForceTypeIdByName(LuaToString(l, -1, j + 1));
1969 ++j;
1970 faction->ForceTypeWeights[force_type] = LuaToNumber(l, -1, j + 1);
1971 }
1972 } else if (!strcmp(value, "ForceTemplates")) {
1973 const int args = lua_rawlen(l, -1);
1974 for (int j = 0; j < args; ++j) {
1975 lua_rawgeti(l, -1, j + 1);
1976 CForceTemplate *force = new CForceTemplate;
1977 if (!lua_istable(l, -1)) {
1978 LuaError(l, "incorrect argument (expected table for force templates)");
1979 }
1980 const int subargs = lua_rawlen(l, -1);
1981 for (int k = 0; k < subargs; ++k) {
1982 value = LuaToString(l, -1, k + 1);
1983 ++k;
1984 if (!strcmp(value, "force-type")) {
1985 force->ForceType = GetForceTypeIdByName(LuaToString(l, -1, k + 1));
1986 if (force->ForceType == -1) {
1987 LuaError(l, "Force type doesn't exist.");
1988 }
1989 faction->ForceTemplates[force->ForceType].push_back(force);
1990 } else if (!strcmp(value, "priority")) {
1991 force->Priority = LuaToNumber(l, -1, k + 1);
1992 } else if (!strcmp(value, "weight")) {
1993 force->Weight = LuaToNumber(l, -1, k + 1);
1994 } else if (!strcmp(value, "unit-class")) {
1995 int unit_class = GetOrAddUnitTypeClassIndexByName(LuaToString(l, -1, k + 1));
1996 ++k;
1997 int unit_quantity = LuaToNumber(l, -1, k + 1);
1998 force->Units.push_back(std::pair<int, int>(unit_class, unit_quantity));
1999 } else {
2000 printf("\n%s\n", faction->Ident.c_str());
2001 LuaError(l, "Unsupported tag: %s" _C_ value);
2002 }
2003 }
2004 lua_pop(l, 1);
2005 }
2006 for (std::map<int, std::vector<CForceTemplate *>>::iterator iterator = faction->ForceTemplates.begin(); iterator != faction->ForceTemplates.end(); ++iterator) {
2007 std::sort(iterator->second.begin(), iterator->second.end(), [](CForceTemplate *a, CForceTemplate *b) {
2008 return a->Priority > b->Priority;
2009 });
2010 }
2011 } else if (!strcmp(value, "AiBuildingTemplates")) {
2012 const int args = lua_rawlen(l, -1);
2013 for (int j = 0; j < args; ++j) {
2014 lua_rawgeti(l, -1, j + 1);
2015 CAiBuildingTemplate *building_template = new CAiBuildingTemplate;
2016 if (!lua_istable(l, -1)) {
2017 LuaError(l, "incorrect argument (expected table for force templates)");
2018 }
2019 const int subargs = lua_rawlen(l, -1);
2020 for (int k = 0; k < subargs; ++k) {
2021 value = LuaToString(l, -1, k + 1);
2022 ++k;
2023 if (!strcmp(value, "unit-class")) {
2024 int unit_class = GetOrAddUnitTypeClassIndexByName(LuaToString(l, -1, k + 1));
2025 building_template->UnitClass = unit_class;
2026 faction->AiBuildingTemplates.push_back(building_template);
2027 } else if (!strcmp(value, "priority")) {
2028 building_template->Priority = LuaToNumber(l, -1, k + 1);
2029 } else if (!strcmp(value, "per-settlement")) {
2030 building_template->PerSettlement = LuaToBoolean(l, -1, k + 1);
2031 } else {
2032 printf("\n%s\n", faction->Ident.c_str());
2033 LuaError(l, "Unsupported tag: %s" _C_ value);
2034 }
2035 }
2036 lua_pop(l, 1);
2037 }
2038 std::sort(faction->AiBuildingTemplates.begin(), faction->AiBuildingTemplates.end(), [](CAiBuildingTemplate *a, CAiBuildingTemplate *b) {
2039 return a->Priority > b->Priority;
2040 });
2041 } else if (!strcmp(value, "UIFillers")) {
2042 if (!lua_istable(l, -1)) {
2043 LuaError(l, "incorrect argument");
2044 }
2045
2046 faction->UIFillers.clear();
2047
2048 const int subargs = lua_rawlen(l, -1);
2049 for (int j = 0; j < subargs; ++j) {
2050 CFiller filler = CFiller();
2051 std::string filler_file = LuaToString(l, -1, j + 1);
2052 if (filler_file.empty()) {
2053 LuaError(l, "Filler graphic file is empty.");
2054 }
2055 filler.G = CGraphic::New(filler_file);
2056 ++j;
2057 filler.X = LuaToNumber(l, -1, j + 1);
2058 ++j;
2059 filler.Y = LuaToNumber(l, -1, j + 1);
2060 faction->UIFillers.push_back(filler);
2061 }
2062 } else if (!strcmp(value, "Conditions")) {
2063 faction->Conditions = new LuaCallback(l, -1);
2064 } else if (!strcmp(value, "ProvinceNames")) {
2065 faction->ProvinceNames.clear();
2066 const int args = lua_rawlen(l, -1);
2067 for (int j = 0; j < args; ++j) {
2068 faction->ProvinceNames.push_back(LuaToString(l, -1, j + 1));
2069 }
2070 } else if (!strcmp(value, "ShipNames")) {
2071 faction->ShipNames.clear();
2072 const int args = lua_rawlen(l, -1);
2073 for (int j = 0; j < args; ++j) {
2074 faction->ShipNames.push_back(LuaToString(l, -1, j + 1));
2075 }
2076 } else if (!strcmp(value, "HistoricalUpgrades")) {
2077 if (!lua_istable(l, -1)) {
2078 LuaError(l, "incorrect argument");
2079 }
2080 const int subargs = lua_rawlen(l, -1);
2081 for (int j = 0; j < subargs; ++j) {
2082 CDate date;
2083 lua_rawgeti(l, -1, j + 1);
2084 CclGetDate(l, &date);
2085 lua_pop(l, 1);
2086 ++j;
2087
2088 std::string technology_ident = LuaToString(l, -1, j + 1);
2089 ++j;
2090
2091 bool has_upgrade = LuaToBoolean(l, -1, j + 1);
2092
2093 faction->HistoricalUpgrades[technology_ident][date] = has_upgrade;
2094 }
2095 } else if (!strcmp(value, "HistoricalTiers")) {
2096 if (!lua_istable(l, -1)) {
2097 LuaError(l, "incorrect argument");
2098 }
2099 const int subargs = lua_rawlen(l, -1);
2100 for (int j = 0; j < subargs; ++j) {
2101 int year = LuaToNumber(l, -1, j + 1);
2102 ++j;
2103 std::string faction_tier_name = LuaToString(l, -1, j + 1);
2104 int faction_tier = GetFactionTierIdByName(faction_tier_name);
2105 if (faction_tier == -1) {
2106 LuaError(l, "Faction tier \"%s\" doesn't exist." _C_ faction_tier_name.c_str());
2107 }
2108 faction->HistoricalTiers[year] = faction_tier;
2109 }
2110 } else if (!strcmp(value, "HistoricalGovernmentTypes")) {
2111 if (!lua_istable(l, -1)) {
2112 LuaError(l, "incorrect argument");
2113 }
2114 const int subargs = lua_rawlen(l, -1);
2115 for (int j = 0; j < subargs; ++j) {
2116 int year = LuaToNumber(l, -1, j + 1);
2117 ++j;
2118 std::string government_type_name = LuaToString(l, -1, j + 1);
2119 int government_type = GetGovernmentTypeIdByName(government_type_name);
2120 if (government_type == -1) {
2121 LuaError(l, "Government type \"%s\" doesn't exist." _C_ government_type_name.c_str());
2122 }
2123 faction->HistoricalGovernmentTypes[year] = government_type;
2124 }
2125 } else if (!strcmp(value, "HistoricalDiplomacyStates")) {
2126 if (!lua_istable(l, -1)) {
2127 LuaError(l, "incorrect argument");
2128 }
2129 const int subargs = lua_rawlen(l, -1);
2130 for (int j = 0; j < subargs; ++j) {
2131 CDate date;
2132 lua_rawgeti(l, -1, j + 1);
2133 CclGetDate(l, &date);
2134 lua_pop(l, 1);
2135 ++j;
2136
2137 std::string diplomacy_state_faction_ident = LuaToString(l, -1, j + 1);
2138 CFaction *diplomacy_state_faction = PlayerRaces.GetFaction(diplomacy_state_faction_ident);
2139 if (diplomacy_state_faction == nullptr) {
2140 LuaError(l, "Faction \"%s\" doesn't exist." _C_ diplomacy_state_faction_ident.c_str());
2141 }
2142 ++j;
2143
2144 std::string diplomacy_state_name = LuaToString(l, -1, j + 1);
2145 int diplomacy_state = GetDiplomacyStateIdByName(diplomacy_state_name);
2146 if (diplomacy_state == -1) {
2147 LuaError(l, "Diplomacy state \"%s\" doesn't exist." _C_ diplomacy_state_name.c_str());
2148 }
2149 faction->HistoricalDiplomacyStates[std::pair<CDate, CFaction *>(date, diplomacy_state_faction)] = diplomacy_state;
2150 }
2151 } else if (!strcmp(value, "HistoricalResources")) {
2152 if (!lua_istable(l, -1)) {
2153 LuaError(l, "incorrect argument");
2154 }
2155 const int subargs = lua_rawlen(l, -1);
2156 for (int j = 0; j < subargs; ++j) {
2157 CDate date;
2158 lua_rawgeti(l, -1, j + 1);
2159 CclGetDate(l, &date);
2160 lua_pop(l, 1);
2161 ++j;
2162
2163 std::string resource_ident = LuaToString(l, -1, j + 1);
2164 int resource = GetResourceIdByName(l, resource_ident.c_str());
2165 if (resource == -1) {
2166 LuaError(l, "Resource \"%s\" doesn't exist." _C_ resource_ident.c_str());
2167 }
2168 ++j;
2169
2170 faction->HistoricalResources[std::pair<CDate, int>(date, resource)] = LuaToNumber(l, -1, j + 1);
2171 }
2172 } else if (!strcmp(value, "HistoricalCapitals")) {
2173 if (!lua_istable(l, -1)) {
2174 LuaError(l, "incorrect argument");
2175 }
2176 const int subargs = lua_rawlen(l, -1);
2177 for (int j = 0; j < subargs; ++j) {
2178 CDate date;
2179 lua_rawgeti(l, -1, j + 1);
2180 CclGetDate(l, &date);
2181 lua_pop(l, 1);
2182 ++j;
2183
2184 std::string site_ident = LuaToString(l, -1, j + 1);
2185
2186 faction->HistoricalCapitals.push_back(std::pair<CDate, std::string>(date, site_ident));
2187 }
2188 } else if (!strcmp(value, "Mod")) {
2189 faction->Mod = LuaToString(l, -1);
2190 } else {
2191 LuaError(l, "Unsupported tag: %s" _C_ value);
2192 }
2193 }
2194
2195 if (faction->Type == FactionTypeTribe) {
2196 faction->DefiniteArticle = true;
2197 }
2198
2199 if (!parent_faction.empty()) { //process this here
2200 faction->ParentFaction = PlayerRaces.GetFactionIndexByName(parent_faction);
2201
2202 if (faction->ParentFaction == -1) { //if a parent faction was set but wasn't found, give an error
2203 LuaError(l, "Faction %s doesn't exist" _C_ parent_faction.c_str());
2204 }
2205
2206 if (faction->ParentFaction != -1 && faction->FactionUpgrade.empty()) { //if the faction has no faction upgrade, inherit that of its parent faction
2207 faction->FactionUpgrade = PlayerRaces.Factions[faction->ParentFaction]->FactionUpgrade;
2208 }
2209
2210 if (faction->ParentFaction != -1) { //inherit button icons from parent civilization, for button actions which none are specified
2211 for (std::map<int, IconConfig>::iterator iterator = PlayerRaces.Factions[faction->ParentFaction]->ButtonIcons.begin(); iterator != PlayerRaces.Factions[faction->ParentFaction]->ButtonIcons.end(); ++iterator) {
2212 if (faction->ButtonIcons.find(iterator->first) == faction->ButtonIcons.end()) {
2213 faction->ButtonIcons[iterator->first] = iterator->second;
2214 }
2215 }
2216
2217 for (std::map<std::string, std::map<CDate, bool>>::iterator iterator = PlayerRaces.Factions[faction->ParentFaction]->HistoricalUpgrades.begin(); iterator != PlayerRaces.Factions[faction->ParentFaction]->HistoricalUpgrades.end(); ++iterator) {
2218 if (faction->HistoricalUpgrades.find(iterator->first) == faction->HistoricalUpgrades.end()) {
2219 faction->HistoricalUpgrades[iterator->first] = iterator->second;
2220 }
2221 }
2222 }
2223 } else if (parent_faction.empty()) {
2224 faction->ParentFaction = -1; // to allow redefinitions to remove the parent faction setting
2225 }
2226
2227 return 0;
2228 }
2229
2230 /**
2231 ** Define a dynasty.
2232 **
2233 ** @param l Lua state.
2234 */
CclDefineDynasty(lua_State * l)2235 static int CclDefineDynasty(lua_State *l)
2236 {
2237 LuaCheckArgs(l, 2);
2238 if (!lua_istable(l, 2)) {
2239 LuaError(l, "incorrect argument (expected table)");
2240 }
2241
2242 std::string dynasty_ident = LuaToString(l, 1);
2243
2244 CDynasty *dynasty = PlayerRaces.GetDynasty(dynasty_ident);
2245 if (!dynasty) { // new definition
2246 dynasty = new CDynasty;
2247 dynasty->Ident = dynasty_ident;
2248 dynasty->ID = PlayerRaces.Dynasties.size();
2249 PlayerRaces.Dynasties.push_back(dynasty);
2250 DynastyStringToIndex[dynasty->Ident] = dynasty->ID;
2251 }
2252
2253 // Parse the list:
2254 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
2255 const char *value = LuaToString(l, -2);
2256
2257 if (!strcmp(value, "Civilization")) {
2258 CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1));
2259 if (civilization) {
2260 dynasty->Civilization = civilization->ID;
2261 }
2262 } else if (!strcmp(value, "Name")) {
2263 dynasty->Name = LuaToString(l, -1);
2264 } else if (!strcmp(value, "Description")) {
2265 dynasty->Description = LuaToString(l, -1);
2266 } else if (!strcmp(value, "Quote")) {
2267 dynasty->Quote = LuaToString(l, -1);
2268 } else if (!strcmp(value, "Background")) {
2269 dynasty->Background = LuaToString(l, -1);
2270 } else if (!strcmp(value, "Icon")) {
2271 dynasty->Icon.Name = LuaToString(l, -1);
2272 dynasty->Icon.Icon = nullptr;
2273 dynasty->Icon.Load();
2274 dynasty->Icon.Icon->Load();
2275 } else if (!strcmp(value, "Factions")) {
2276 if (!lua_istable(l, -1)) {
2277 LuaError(l, "incorrect argument");
2278 }
2279 const int subargs = lua_rawlen(l, -1);
2280 for (int k = 0; k < subargs; ++k) {
2281 CFaction *faction = PlayerRaces.GetFaction(LuaToString(l, -1, k + 1));
2282 if (!faction) {
2283 LuaError(l, "Faction doesn't exist.");
2284 }
2285 dynasty->Factions.push_back(faction);
2286 faction->Dynasties.push_back(dynasty);
2287 }
2288 } else if (!strcmp(value, "DynastyUpgrade")) {
2289 dynasty->DynastyUpgrade = CUpgrade::Get(LuaToString(l, -1));
2290 } else if (!strcmp(value, "Conditions")) {
2291 dynasty->Conditions = new LuaCallback(l, -1);
2292 } else {
2293 LuaError(l, "Unsupported tag: %s" _C_ value);
2294 }
2295 }
2296
2297 return 0;
2298 }
2299
2300 /**
2301 ** Define a religion.
2302 **
2303 ** @param l Lua state.
2304 */
CclDefineReligion(lua_State * l)2305 static int CclDefineReligion(lua_State *l)
2306 {
2307 LuaCheckArgs(l, 2);
2308 if (!lua_istable(l, 2)) {
2309 LuaError(l, "incorrect argument (expected table)");
2310 }
2311
2312 std::string religion_ident = LuaToString(l, 1);
2313 CReligion *religion = CReligion::GetOrAddReligion(religion_ident);
2314
2315 // Parse the list:
2316 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
2317 const char *value = LuaToString(l, -2);
2318
2319 if (!strcmp(value, "Name")) {
2320 religion->Name = LuaToString(l, -1);
2321 } else if (!strcmp(value, "Description")) {
2322 religion->Description = LuaToString(l, -1);
2323 } else if (!strcmp(value, "Background")) {
2324 religion->Background = LuaToString(l, -1);
2325 } else if (!strcmp(value, "Quote")) {
2326 religion->Quote = LuaToString(l, -1);
2327 } else if (!strcmp(value, "CulturalDeities")) {
2328 religion->CulturalDeities = LuaToBoolean(l, -1);
2329 } else if (!strcmp(value, "Domains")) {
2330 if (!lua_istable(l, -1)) {
2331 LuaError(l, "incorrect argument (expected table)");
2332 }
2333 const int subargs = lua_rawlen(l, -1);
2334 for (int j = 0; j < subargs; ++j) {
2335 CDeityDomain *deity_domain = CDeityDomain::GetDeityDomain(LuaToString(l, -1, j + 1));
2336 if (deity_domain) {
2337 religion->Domains.push_back(deity_domain);
2338 }
2339 }
2340 } else {
2341 LuaError(l, "Unsupported tag: %s" _C_ value);
2342 }
2343 }
2344
2345 return 0;
2346 }
2347
2348 /**
2349 ** Define a deity.
2350 **
2351 ** @param l Lua state.
2352 */
CclDefineDeity(lua_State * l)2353 static int CclDefineDeity(lua_State *l)
2354 {
2355 LuaCheckArgs(l, 2);
2356 if (!lua_istable(l, 2)) {
2357 LuaError(l, "incorrect argument (expected table)");
2358 }
2359
2360 std::string deity_ident = LuaToString(l, 1);
2361 CDeity *deity = CDeity::GetOrAddDeity(deity_ident);
2362
2363 // Parse the list:
2364 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
2365 const char *value = LuaToString(l, -2);
2366
2367 if (!strcmp(value, "Name")) {
2368 deity->Name = LuaToString(l, -1);
2369 } else if (!strcmp(value, "Pantheon")) {
2370 deity->Pantheon = CPantheon::GetPantheon(LuaToString(l, -1));
2371 } else if (!strcmp(value, "Gender")) {
2372 deity->Gender = GetGenderIdByName(LuaToString(l, -1));
2373 } else if (!strcmp(value, "Major")) {
2374 deity->Major = LuaToBoolean(l, -1);
2375 } else if (!strcmp(value, "Description")) {
2376 deity->Description = LuaToString(l, -1);
2377 } else if (!strcmp(value, "Background")) {
2378 deity->Background = LuaToString(l, -1);
2379 } else if (!strcmp(value, "Quote")) {
2380 deity->Quote = LuaToString(l, -1);
2381 } else if (!strcmp(value, "HomePlane")) {
2382 CPlane *plane = CPlane::GetPlane(LuaToString(l, -1));
2383 if (!plane) {
2384 LuaError(l, "Plane doesn't exist.");
2385 }
2386 deity->HomePlane = plane;
2387 } else if (!strcmp(value, "DeityUpgrade")) {
2388 CUpgrade *upgrade = CUpgrade::Get(LuaToString(l, -1));
2389 if (!upgrade) {
2390 LuaError(l, "Upgrade doesn't exist.");
2391 }
2392 deity->DeityUpgrade = upgrade;
2393 CDeity::DeitiesByUpgrade[upgrade] = deity;
2394 } else if (!strcmp(value, "CharacterUpgrade")) {
2395 CUpgrade *upgrade = CUpgrade::Get(LuaToString(l, -1));
2396 if (!upgrade) {
2397 LuaError(l, "Upgrade doesn't exist.");
2398 }
2399 deity->CharacterUpgrade = upgrade;
2400 } else if (!strcmp(value, "Icon")) {
2401 deity->Icon.Name = LuaToString(l, -1);
2402 deity->Icon.Icon = nullptr;
2403 deity->Icon.Load();
2404 deity->Icon.Icon->Load();
2405 } else if (!strcmp(value, "Civilizations")) {
2406 if (!lua_istable(l, -1)) {
2407 LuaError(l, "incorrect argument (expected table)");
2408 }
2409 const int subargs = lua_rawlen(l, -1);
2410 for (int j = 0; j < subargs; ++j) {
2411 CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1));
2412 if (civilization) {
2413 deity->Civilizations.push_back(civilization);
2414 civilization->Deities.push_back(deity);
2415 }
2416 }
2417 } else if (!strcmp(value, "Religions")) {
2418 if (!lua_istable(l, -1)) {
2419 LuaError(l, "incorrect argument (expected table)");
2420 }
2421 const int subargs = lua_rawlen(l, -1);
2422 for (int j = 0; j < subargs; ++j) {
2423 CReligion *religion = CReligion::GetReligion(LuaToString(l, -1, j + 1));
2424 if (religion) {
2425 deity->Religions.push_back(religion);
2426 }
2427 }
2428 } else if (!strcmp(value, "Domains")) {
2429 if (!lua_istable(l, -1)) {
2430 LuaError(l, "incorrect argument (expected table)");
2431 }
2432 const int subargs = lua_rawlen(l, -1);
2433 for (int j = 0; j < subargs; ++j) {
2434 CDeityDomain *deity_domain = CDeityDomain::GetDeityDomain(LuaToString(l, -1, j + 1));
2435 if (deity_domain) {
2436 deity->Domains.push_back(deity_domain);
2437 }
2438 }
2439 } else if (!strcmp(value, "HolyOrders")) {
2440 if (!lua_istable(l, -1)) {
2441 LuaError(l, "incorrect argument (expected table)");
2442 }
2443 const int subargs = lua_rawlen(l, -1);
2444 for (int j = 0; j < subargs; ++j) {
2445 CFaction *holy_order = PlayerRaces.GetFaction(LuaToString(l, -1, j + 1));
2446 if (!holy_order) {
2447 LuaError(l, "Holy order doesn't exist.");
2448 }
2449
2450 deity->HolyOrders.push_back(holy_order);
2451 holy_order->HolyOrderDeity = deity;
2452 }
2453 } else if (!strcmp(value, "Abilities")) {
2454 if (!lua_istable(l, -1)) {
2455 LuaError(l, "incorrect argument (expected table)");
2456 }
2457 const int subargs = lua_rawlen(l, -1);
2458 for (int j = 0; j < subargs; ++j) {
2459 CUpgrade *ability = CUpgrade::Get(LuaToString(l, -1, j + 1));
2460 if (!ability || !ability->Ability) {
2461 LuaError(l, "Ability doesn't exist.");
2462 }
2463
2464 if (std::find(deity->Abilities.begin(), deity->Abilities.end(), ability) == deity->Abilities.end()) {
2465 deity->Abilities.push_back(ability);
2466 }
2467 }
2468 } else if (!strcmp(value, "Feasts")) {
2469 if (!lua_istable(l, -1)) {
2470 LuaError(l, "incorrect argument (expected table)");
2471 }
2472 const int subargs = lua_rawlen(l, -1);
2473 for (int j = 0; j < subargs; ++j) {
2474 std::string feast = LuaToString(l, -1, j + 1);
2475
2476 deity->Feasts.push_back(feast);
2477 }
2478 } else if (!strcmp(value, "CulturalNames")) {
2479 if (!lua_istable(l, -1)) {
2480 LuaError(l, "incorrect argument (expected table)");
2481 }
2482 const int subargs = lua_rawlen(l, -1);
2483 for (int j = 0; j < subargs; ++j) {
2484 const CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, -1, j + 1));
2485 ++j;
2486 if (!civilization) {
2487 continue;
2488 }
2489
2490 std::string cultural_name = LuaToString(l, -1, j + 1);
2491 deity->CulturalNames[civilization] = cultural_name;
2492 }
2493 } else {
2494 LuaError(l, "Unsupported tag: %s" _C_ value);
2495 }
2496 }
2497
2498 if (deity->Major && deity->Domains.size() > MAJOR_DEITY_DOMAIN_MAX) {
2499 deity->Domains.resize(MAJOR_DEITY_DOMAIN_MAX);
2500 } else if (!deity->Major && deity->Domains.size() > MINOR_DEITY_DOMAIN_MAX) {
2501 deity->Domains.resize(MINOR_DEITY_DOMAIN_MAX);
2502 }
2503
2504 for (CDeityDomain *domain : deity->Domains) {
2505 for (CUpgrade *ability : domain->Abilities) {
2506 if (std::find(deity->Abilities.begin(), deity->Abilities.end(), ability) == deity->Abilities.end()) {
2507 deity->Abilities.push_back(ability);
2508 }
2509 }
2510 }
2511
2512 return 0;
2513 }
2514
2515 /**
2516 ** Define a language.
2517 **
2518 ** @param l Lua state.
2519 */
CclDefineLanguage(lua_State * l)2520 static int CclDefineLanguage(lua_State *l)
2521 {
2522 LuaCheckArgs(l, 2);
2523 if (!lua_istable(l, 2)) {
2524 LuaError(l, "incorrect argument (expected table)");
2525 }
2526
2527 std::string language_ident = LuaToString(l, 1);
2528 CLanguage *language = PlayerRaces.GetLanguage(language_ident);
2529 if (!language) {
2530 language = new CLanguage;
2531 PlayerRaces.Languages.push_back(language);
2532 LanguageIdentToPointer[language_ident] = language;
2533 }
2534
2535 language->Ident = language_ident;
2536
2537 // Parse the list:
2538 for (lua_pushnil(l); lua_next(l, 2); lua_pop(l, 1)) {
2539 const char *value = LuaToString(l, -2);
2540
2541 if (!strcmp(value, "Name")) {
2542 language->Name = LuaToString(l, -1);
2543 } else if (!strcmp(value, "Family")) {
2544 language->Family = LuaToString(l, -1);
2545 } else if (!strcmp(value, "DialectOf")) {
2546 CLanguage *parent_language = PlayerRaces.GetLanguage(LuaToString(l, -1));
2547 if (parent_language) {
2548 language->DialectOf = parent_language;
2549 parent_language->Dialects.push_back(language);
2550 } else {
2551 LuaError(l, "Language not found.");
2552 }
2553 } else if (!strcmp(value, "NounEndings")) {
2554 if (!lua_istable(l, -1)) {
2555 LuaError(l, "incorrect argument");
2556 }
2557 const int subargs = lua_rawlen(l, -1);
2558 for (int k = 0; k < subargs; ++k) {
2559 std::string grammatical_number_name = LuaToString(l, -1, k + 1);
2560 int grammatical_number = GetGrammaticalNumberIdByName(grammatical_number_name);
2561 if (grammatical_number == -1) {
2562 LuaError(l, "Grammatical number \"%s\" doesn't exist." _C_ grammatical_number_name.c_str());
2563 }
2564 ++k;
2565
2566 std::string grammatical_case_name = LuaToString(l, -1, k + 1);
2567 int grammatical_case = GetGrammaticalCaseIdByName(grammatical_case_name);
2568 if (grammatical_case == -1) {
2569 LuaError(l, "Grammatical case \"%s\" doesn't exist." _C_ grammatical_case_name.c_str());
2570 }
2571 ++k;
2572
2573 int word_junction_type = WordJunctionTypeNoWordJunction;
2574 if (GetWordJunctionTypeIdByName(LuaToString(l, -1, k + 1)) != -1) {
2575 std::string word_junction_type_name = LuaToString(l, -1, k + 1);
2576 int word_junction_type = GetWordJunctionTypeIdByName(word_junction_type_name);
2577 if (word_junction_type == -1) {
2578 LuaError(l, "Word junction type \"%s\" doesn't exist." _C_ word_junction_type_name.c_str());
2579 }
2580 ++k;
2581 }
2582
2583 language->NounEndings[grammatical_number][grammatical_case][word_junction_type] = LuaToString(l, -1, k + 1);
2584 }
2585 } else if (!strcmp(value, "AdjectiveEndings")) {
2586 if (!lua_istable(l, -1)) {
2587 LuaError(l, "incorrect argument");
2588 }
2589 const int subargs = lua_rawlen(l, -1);
2590 for (int k = 0; k < subargs; ++k) {
2591 std::string article_type_name = LuaToString(l, -1, k + 1);
2592 int article_type = GetArticleTypeIdByName(article_type_name);
2593 if (article_type == -1) {
2594 LuaError(l, "Article type \"%s\" doesn't exist." _C_ article_type_name.c_str());
2595 }
2596 ++k;
2597
2598 std::string grammatical_case_name = LuaToString(l, -1, k + 1);
2599 int grammatical_case = GetGrammaticalCaseIdByName(grammatical_case_name);
2600 if (grammatical_case == -1) {
2601 LuaError(l, "Grammatical case \"%s\" doesn't exist." _C_ grammatical_case_name.c_str());
2602 }
2603 ++k;
2604
2605 std::string grammatical_number_name = LuaToString(l, -1, k + 1);
2606 int grammatical_number = GetGrammaticalNumberIdByName(grammatical_number_name);
2607 if (grammatical_number == -1) {
2608 LuaError(l, "Grammatical number \"%s\" doesn't exist." _C_ grammatical_number_name.c_str());
2609 }
2610 ++k;
2611
2612 std::string grammatical_gender_name = LuaToString(l, -1, k + 1);
2613 int grammatical_gender = GetGrammaticalGenderIdByName(grammatical_gender_name);
2614 if (grammatical_gender == -1) {
2615 LuaError(l, "Grammatical gender \"%s\" doesn't exist." _C_ grammatical_gender_name.c_str());
2616 }
2617 ++k;
2618
2619 language->AdjectiveEndings[article_type][grammatical_case][grammatical_number][grammatical_gender] = LuaToString(l, -1, k + 1);
2620 }
2621 } else if (!strcmp(value, "NameTranslations")) {
2622 if (!lua_istable(l, -1)) {
2623 LuaError(l, "incorrect argument");
2624 }
2625 const int subargs = lua_rawlen(l, -1);
2626 for (int k = 0; k < subargs; ++k) {
2627 std::string translation_from = LuaToString(l, -1, k + 1); //name to be translated
2628 ++k;
2629 std::string translation_to = LuaToString(l, -1, k + 1); //name translation
2630 language->NameTranslations[translation_from].push_back(translation_to);
2631 }
2632 } else {
2633 LuaError(l, "Unsupported tag: %s" _C_ value);
2634 }
2635 }
2636
2637 return 0;
2638 }
2639 //Wyrmgus end
2640
2641 /**
2642 ** Get the civilizations.
2643 **
2644 ** @param l Lua state.
2645 */
CclGetCivilizations(lua_State * l)2646 static int CclGetCivilizations(lua_State *l)
2647 {
2648 const int nargs = lua_gettop(l);
2649 bool only_visible = false;
2650 if (nargs >= 1) {
2651 only_visible = LuaToBoolean(l, 1);
2652 }
2653
2654 std::vector<std::string> civilization_idents;
2655 for (int i = 0; i < MAX_RACES; ++i) {
2656 if (!PlayerRaces.Name[i].empty() && (!only_visible || PlayerRaces.Visible[i])) {
2657 civilization_idents.push_back(PlayerRaces.Name[i]);
2658 }
2659 }
2660
2661 lua_createtable(l, civilization_idents.size(), 0);
2662 for (unsigned int i = 1; i <= civilization_idents.size(); ++i)
2663 {
2664 lua_pushstring(l, civilization_idents[i - 1].c_str());
2665 lua_rawseti(l, -2, i);
2666 }
2667
2668 return 1;
2669 }
2670
2671 /**
2672 ** Get the factions.
2673 **
2674 ** @param l Lua state.
2675 */
CclGetFactions(lua_State * l)2676 static int CclGetFactions(lua_State *l)
2677 {
2678 CCivilization *civilization = nullptr;
2679 if (lua_gettop(l) >= 1) {
2680 civilization = CCivilization::GetCivilization(LuaToString(l, 1));
2681 }
2682
2683 int faction_type = -1;
2684 if (lua_gettop(l) >= 2) {
2685 faction_type = GetFactionTypeIdByName(LuaToString(l, 2));
2686 }
2687
2688 std::vector<std::string> factions;
2689 if (civilization != nullptr) {
2690 for (size_t i = 0; i < PlayerRaces.Factions.size(); ++i) {
2691 if (faction_type != -1 && PlayerRaces.Factions[i]->Type != faction_type) {
2692 continue;
2693 }
2694 if (PlayerRaces.Factions[i]->Civilization == civilization) {
2695 factions.push_back(PlayerRaces.Factions[i]->Ident);
2696 }
2697 }
2698 } else {
2699 for (size_t i = 0; i < PlayerRaces.Factions.size(); ++i) {
2700 if (faction_type != -1 && PlayerRaces.Factions[i]->Type != faction_type) {
2701 continue;
2702 }
2703 factions.push_back(PlayerRaces.Factions[i]->Ident);
2704 }
2705 }
2706
2707 lua_createtable(l, factions.size(), 0);
2708 for (size_t i = 1; i <= factions.size(); ++i)
2709 {
2710 lua_pushstring(l, factions[i-1].c_str());
2711 lua_rawseti(l, -2, i);
2712 }
2713
2714 return 1;
2715 }
2716
2717 /**
2718 ** Get the dynasties.
2719 **
2720 ** @param l Lua state.
2721 */
CclGetDynasties(lua_State * l)2722 static int CclGetDynasties(lua_State *l)
2723 {
2724 int civilization_id = -1;
2725 if (lua_gettop(l) >= 1) {
2726 CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, 1));
2727 if (civilization) {
2728 civilization_id = civilization->ID;
2729 }
2730 }
2731
2732 std::vector<std::string> dynasties;
2733 if (civilization_id != -1) {
2734 for (size_t i = 0; i < PlayerRaces.Dynasties.size(); ++i) {
2735 if (PlayerRaces.Dynasties[i]->Civilization == civilization_id) {
2736 dynasties.push_back(PlayerRaces.Dynasties[i]->Ident);
2737 }
2738 }
2739 } else {
2740 for (size_t i = 0; i < PlayerRaces.Dynasties.size(); ++i) {
2741 dynasties.push_back(PlayerRaces.Dynasties[i]->Ident);
2742 }
2743 }
2744
2745 lua_createtable(l, dynasties.size(), 0);
2746 for (size_t i = 1; i <= dynasties.size(); ++i)
2747 {
2748 lua_pushstring(l, dynasties[i-1].c_str());
2749 lua_rawseti(l, -2, i);
2750 }
2751
2752 return 1;
2753 }
2754
2755 /**
2756 ** Get the player colors.
2757 **
2758 ** @param l Lua state.
2759 */
CclGetPlayerColors(lua_State * l)2760 static int CclGetPlayerColors(lua_State *l)
2761 {
2762 std::vector<std::string> player_colors;
2763 for (int i = 0; i < PlayerColorMax; ++i)
2764 {
2765 if (!PlayerColorNames[i].empty()) {
2766 player_colors.push_back(PlayerColorNames[i]);
2767 }
2768 }
2769
2770 lua_createtable(l, player_colors.size(), 0);
2771 for (size_t i = 1; i <= player_colors.size(); ++i)
2772 {
2773 lua_pushstring(l, player_colors[i-1].c_str());
2774 lua_rawseti(l, -2, i);
2775 }
2776
2777 return 1;
2778 }
2779
2780 /**
2781 ** Get faction data.
2782 **
2783 ** @param l Lua state.
2784 */
CclGetFactionData(lua_State * l)2785 static int CclGetFactionData(lua_State *l)
2786 {
2787 LuaCheckArgs(l, 2);
2788 std::string faction_name = LuaToString(l, 1);
2789 CFaction *faction = PlayerRaces.GetFaction(faction_name);
2790 if (faction == nullptr) {
2791 LuaError(l, "Faction \"%s\" doesn't exist." _C_ faction_name.c_str());
2792 }
2793
2794 const char *data = LuaToString(l, 2);
2795
2796 if (!strcmp(data, "Name")) {
2797 lua_pushstring(l, faction->Name.c_str());
2798 return 1;
2799 } else if (!strcmp(data, "Description")) {
2800 lua_pushstring(l, faction->Description.c_str());
2801 return 1;
2802 } else if (!strcmp(data, "Quote")) {
2803 lua_pushstring(l, faction->Quote.c_str());
2804 return 1;
2805 } else if (!strcmp(data, "Background")) {
2806 lua_pushstring(l, faction->Background.c_str());
2807 return 1;
2808 } else if (!strcmp(data, "Adjective")) {
2809 if (!faction->Adjective.empty()) {
2810 lua_pushstring(l, faction->Adjective.c_str());
2811 } else {
2812 lua_pushstring(l, faction->Name.c_str());
2813 }
2814 return 1;
2815 } else if (!strcmp(data, "Type")) {
2816 lua_pushstring(l, GetFactionTypeNameById(faction->Type).c_str());
2817 return 1;
2818 } else if (!strcmp(data, "Civilization")) {
2819 if (faction->Civilization != nullptr) {
2820 lua_pushstring(l, PlayerRaces.Name[faction->Civilization->ID].c_str());
2821 } else {
2822 lua_pushstring(l, "");
2823 }
2824 return 1;
2825 } else if (!strcmp(data, "Color")) {
2826 if (faction->Colors.size() > 0) {
2827 lua_pushstring(l, PlayerColorNames[faction->Colors[0]].c_str());
2828 } else {
2829 lua_pushstring(l, "");
2830 }
2831 return 1;
2832 } else if (!strcmp(data, "Playable")) {
2833 lua_pushboolean(l, faction->Playable);
2834 return 1;
2835 } else if (!strcmp(data, "FactionUpgrade")) {
2836 lua_pushstring(l, faction->FactionUpgrade.c_str());
2837 return 1;
2838 } else if (!strcmp(data, "ParentFaction")) {
2839 if (faction->ParentFaction != -1) {
2840 lua_pushstring(l, PlayerRaces.Factions[faction->ParentFaction]->Ident.c_str());
2841 } else {
2842 lua_pushstring(l, "");
2843 }
2844 return 1;
2845 } else if (!strcmp(data, "DefaultAI")) {
2846 lua_pushstring(l, faction->DefaultAI.c_str());
2847 return 1;
2848 } else {
2849 LuaError(l, "Invalid field: %s" _C_ data);
2850 }
2851
2852 return 0;
2853 }
2854
2855 /**
2856 ** Get dynasty data.
2857 **
2858 ** @param l Lua state.
2859 */
CclGetDynastyData(lua_State * l)2860 static int CclGetDynastyData(lua_State *l)
2861 {
2862 LuaCheckArgs(l, 2);
2863 std::string dynasty_ident = LuaToString(l, 1);
2864 CDynasty *dynasty = PlayerRaces.GetDynasty(dynasty_ident);
2865 if (dynasty == nullptr) {
2866 LuaError(l, "Dynasty \"%s\" doesn't exist." _C_ dynasty_ident.c_str());
2867 }
2868
2869 const char *data = LuaToString(l, 2);
2870
2871 if (!strcmp(data, "Name")) {
2872 lua_pushstring(l, dynasty->Name.c_str());
2873 return 1;
2874 } else if (!strcmp(data, "Description")) {
2875 lua_pushstring(l, dynasty->Description.c_str());
2876 return 1;
2877 } else if (!strcmp(data, "Quote")) {
2878 lua_pushstring(l, dynasty->Quote.c_str());
2879 return 1;
2880 } else if (!strcmp(data, "Background")) {
2881 lua_pushstring(l, dynasty->Background.c_str());
2882 return 1;
2883 } else if (!strcmp(data, "Civilization")) {
2884 if (dynasty->Civilization != -1) {
2885 lua_pushstring(l, PlayerRaces.Name[dynasty->Civilization].c_str());
2886 } else {
2887 lua_pushstring(l, "");
2888 }
2889 return 1;
2890 } else if (!strcmp(data, "DynastyUpgrade")) {
2891 if (dynasty->DynastyUpgrade) {
2892 lua_pushstring(l, dynasty->DynastyUpgrade->Ident.c_str());
2893 } else {
2894 lua_pushstring(l, "");
2895 }
2896 return 1;
2897 } else if (!strcmp(data, "Factions")) {
2898 lua_createtable(l, dynasty->Factions.size(), 0);
2899 for (size_t i = 1; i <= dynasty->Factions.size(); ++i)
2900 {
2901 lua_pushstring(l, dynasty->Factions[i-1]->Ident.c_str());
2902 lua_rawseti(l, -2, i);
2903 }
2904 return 1;
2905 } else {
2906 LuaError(l, "Invalid field: %s" _C_ data);
2907 }
2908
2909 return 0;
2910 }
2911 //Wyrmgus end
2912
2913 /**
2914 ** Define player colors
2915 **
2916 ** @param l Lua state.
2917 */
CclDefinePlayerColors(lua_State * l)2918 static int CclDefinePlayerColors(lua_State *l)
2919 {
2920 LuaCheckArgs(l, 1);
2921 if (!lua_istable(l, 1)) {
2922 LuaError(l, "incorrect argument");
2923 }
2924
2925 const int args = lua_rawlen(l, 1);
2926 for (int i = 0; i < args; ++i) {
2927 PlayerColorNames[i / 2] = LuaToString(l, 1, i + 1);
2928 ++i;
2929 lua_rawgeti(l, 1, i + 1);
2930 if (!lua_istable(l, -1)) {
2931 LuaError(l, "incorrect argument");
2932 }
2933 const int numcolors = lua_rawlen(l, -1);
2934 if (numcolors != PlayerColorIndexCount) {
2935 LuaError(l, "You should use %d colors (See DefinePlayerColorIndex())" _C_ PlayerColorIndexCount);
2936 }
2937 for (int j = 0; j < numcolors; ++j) {
2938 lua_rawgeti(l, -1, j + 1);
2939 PlayerColorsRGB[i / 2][j].Parse(l);
2940 lua_pop(l, 1);
2941 }
2942 }
2943
2944 return 0;
2945 }
2946
2947 /**
2948 ** Make new player colors
2949 **
2950 ** @param l Lua state.
2951 */
CclNewPlayerColors(lua_State * l)2952 static int CclNewPlayerColors(lua_State *l)
2953 {
2954 LuaCheckArgs(l, 0);
2955 SetPlayersPalette();
2956
2957 return 0;
2958 }
2959
2960 /**
2961 ** Define player color indexes
2962 **
2963 ** @param l Lua state.
2964 */
CclDefinePlayerColorIndex(lua_State * l)2965 static int CclDefinePlayerColorIndex(lua_State *l)
2966 {
2967 LuaCheckArgs(l, 2);
2968 PlayerColorIndexStart = LuaToNumber(l, 1);
2969 PlayerColorIndexCount = LuaToNumber(l, 2);
2970
2971 //Wyrmgus start
2972 // for (int i = 0; i < PlayerMax; ++i) {
2973 for (int i = 0; i < PlayerColorMax; ++i) {
2974 //Wyrmgus end
2975 PlayerColorsRGB[i].clear();
2976 PlayerColorsRGB[i].resize(PlayerColorIndexCount);
2977 PlayerColors[i].clear();
2978 PlayerColors[i].resize(PlayerColorIndexCount, 0);
2979 }
2980 return 0;
2981 }
2982
2983 /**
2984 ** Define conversible player colors.
2985 **
2986 ** @param l Lua state.
2987 */
CclDefineConversiblePlayerColors(lua_State * l)2988 static int CclDefineConversiblePlayerColors(lua_State *l)
2989 {
2990 ConversiblePlayerColors.clear();
2991
2992 const unsigned int args = lua_gettop(l);
2993 for (unsigned int i = 0; i < args; ++i) {
2994 std::string player_color_name = LuaToString(l, i + 1);
2995 int player_color = GetPlayerColorIndexByName(player_color_name);
2996 if (player_color != -1) {
2997 ConversiblePlayerColors.push_back(player_color);
2998 } else {
2999 LuaError(l, "Player color \"%s\" doesn't exist." _C_ player_color_name.c_str());
3000 }
3001 }
3002
3003 return 0;
3004 }
3005
3006 // ----------------------------------------------------------------------------
3007
3008 /**
3009 ** Get player data.
3010 **
3011 ** @param l Lua state.
3012 */
CclGetPlayerData(lua_State * l)3013 static int CclGetPlayerData(lua_State *l)
3014 {
3015 if (lua_gettop(l) < 2) {
3016 LuaError(l, "incorrect argument");
3017 }
3018 lua_pushvalue(l, 1);
3019 const CPlayer *p = CclGetPlayer(l);
3020 lua_pop(l, 1);
3021 const char *data = LuaToString(l, 2);
3022
3023 if (!strcmp(data, "Name")) {
3024 lua_pushstring(l, p->Name.c_str());
3025 return 1;
3026 //Wyrmgus start
3027 } else if (!strcmp(data, "Faction")) {
3028 if (p->Race != -1 && p->Faction != -1) {
3029 lua_pushstring(l, PlayerRaces.Factions[p->Faction]->Ident.c_str());
3030 } else {
3031 lua_pushstring(l, "");
3032 }
3033 return 1;
3034 } else if (!strcmp(data, "Dynasty")) {
3035 if (p->Dynasty) {
3036 lua_pushstring(l, p->Dynasty->Ident.c_str());
3037 } else {
3038 lua_pushstring(l, "");
3039 }
3040 return 1;
3041 //Wyrmgus end
3042 } else if (!strcmp(data, "RaceName")) {
3043 lua_pushstring(l, PlayerRaces.Name[p->Race].c_str());
3044 return 1;
3045 //Wyrmgus start
3046 } else if (!strcmp(data, "Color")) {
3047 bool found_color = false;
3048 for (int i = 0; i < PlayerColorMax; ++i) {
3049 if (PlayerColors[i][0] == p->Color) {
3050 lua_pushstring(l, PlayerColorNames[i].c_str());
3051 found_color = true;
3052 break;
3053 }
3054 }
3055 if (!found_color) {
3056 LuaError(l, "Player %d has no color." _C_ p->Index);
3057 }
3058 return 1;
3059 //Wyrmgus end
3060 } else if (!strcmp(data, "Resources")) {
3061 LuaCheckArgs(l, 3);
3062
3063 const std::string res = LuaToString(l, 3);
3064 const int resId = GetResourceIdByName(l, res.c_str());
3065 lua_pushnumber(l, p->Resources[resId] + p->StoredResources[resId]);
3066 return 1;
3067 } else if (!strcmp(data, "StoredResources")) {
3068 LuaCheckArgs(l, 3);
3069
3070 const std::string res = LuaToString(l, 3);
3071 const int resId = GetResourceIdByName(l, res.c_str());
3072 lua_pushnumber(l, p->StoredResources[resId]);
3073 return 1;
3074 } else if (!strcmp(data, "MaxResources")) {
3075 LuaCheckArgs(l, 3);
3076
3077 const std::string res = LuaToString(l, 3);
3078 const int resId = GetResourceIdByName(l, res.c_str());
3079 lua_pushnumber(l, p->MaxResources[resId]);
3080 return 1;
3081 //Wyrmgus start
3082 } else if (!strcmp(data, "Prices")) {
3083 LuaCheckArgs(l, 3);
3084
3085 const std::string res = LuaToString(l, 3);
3086 const int resId = GetResourceIdByName(l, res.c_str());
3087 lua_pushnumber(l, p->GetResourcePrice(resId));
3088 return 1;
3089 } else if (!strcmp(data, "ResourceDemand")) {
3090 LuaCheckArgs(l, 3);
3091
3092 const std::string res = LuaToString(l, 3);
3093 const int resId = GetResourceIdByName(l, res.c_str());
3094 lua_pushnumber(l, p->ResourceDemand[resId]);
3095 return 1;
3096 } else if (!strcmp(data, "StoredResourceDemand")) {
3097 LuaCheckArgs(l, 3);
3098
3099 const std::string res = LuaToString(l, 3);
3100 const int resId = GetResourceIdByName(l, res.c_str());
3101 lua_pushnumber(l, p->StoredResourceDemand[resId]);
3102 return 1;
3103 } else if (!strcmp(data, "EffectiveResourceDemand")) {
3104 LuaCheckArgs(l, 3);
3105
3106 const std::string res = LuaToString(l, 3);
3107 const int resId = GetResourceIdByName(l, res.c_str());
3108 lua_pushnumber(l, p->GetEffectiveResourceDemand(resId));
3109 return 1;
3110 } else if (!strcmp(data, "EffectiveResourceSellPrice")) {
3111 LuaCheckArgs(l, 3);
3112
3113 const std::string res = LuaToString(l, 3);
3114 const int resId = GetResourceIdByName(l, res.c_str());
3115 lua_pushnumber(l, p->GetEffectiveResourceSellPrice(resId));
3116 return 1;
3117 } else if (!strcmp(data, "EffectiveResourceBuyPrice")) {
3118 LuaCheckArgs(l, 3);
3119
3120 const std::string res = LuaToString(l, 3);
3121 const int resId = GetResourceIdByName(l, res.c_str());
3122 lua_pushnumber(l, p->GetEffectiveResourceBuyPrice(resId));
3123 return 1;
3124 } else if (!strcmp(data, "TotalPriceDifferenceWith")) {
3125 LuaCheckArgs(l, 3);
3126
3127 int other_player = LuaToNumber(l, 3);;
3128
3129 lua_pushnumber(l, p->GetTotalPriceDifferenceWith(Players[other_player]));
3130 return 1;
3131 } else if (!strcmp(data, "TradePotentialWith")) {
3132 LuaCheckArgs(l, 3);
3133
3134 int other_player = LuaToNumber(l, 3);;
3135
3136 lua_pushnumber(l, p->GetTradePotentialWith(Players[other_player]));
3137 return 1;
3138 } else if (!strcmp(data, "HasHero")) {
3139 LuaCheckArgs(l, 3);
3140
3141 CCharacter *hero = CCharacter::GetCharacter(LuaToString(l, 3));
3142
3143 lua_pushboolean(l, p->HasHero(hero));
3144 return 1;
3145 //Wyrmgus end
3146 } else if (!strcmp(data, "UnitTypesCount")) {
3147 LuaCheckArgs(l, 3);
3148 CUnitType *type = CclGetUnitType(l);
3149 Assert(type);
3150 lua_pushnumber(l, p->GetUnitTypeCount(type));
3151 return 1;
3152 } else if (!strcmp(data, "UnitTypesUnderConstructionCount")) {
3153 LuaCheckArgs(l, 3);
3154 CUnitType *type = CclGetUnitType(l);
3155 Assert(type);
3156 lua_pushnumber(l, p->GetUnitTypeUnderConstructionCount(type));
3157 return 1;
3158 } else if (!strcmp(data, "UnitTypesAiActiveCount")) {
3159 LuaCheckArgs(l, 3);
3160 CUnitType *type = CclGetUnitType(l);
3161 Assert(type);
3162 lua_pushnumber(l, p->GetUnitTypeAiActiveCount(type));
3163 return 1;
3164 //Wyrmgus start
3165 } else if (!strcmp(data, "Heroes")) {
3166 lua_createtable(l, p->Heroes.size(), 0);
3167 for (size_t i = 1; i <= p->Heroes.size(); ++i)
3168 {
3169 lua_pushstring(l, p->Heroes[i-1]->Character->Ident.c_str());
3170 lua_rawseti(l, -2, i);
3171 }
3172 return 1;
3173 //Wyrmgus end
3174 } else if (!strcmp(data, "AiEnabled")) {
3175 lua_pushboolean(l, p->AiEnabled);
3176 return 1;
3177 } else if (!strcmp(data, "TotalNumUnits")) {
3178 lua_pushnumber(l, p->GetUnitCount());
3179 return 1;
3180 //Wyrmgus start
3181 } else if (!strcmp(data, "TotalNumUnitsConstructed")) {
3182 lua_pushnumber(l, p->GetUnitCount() - p->NumBuildingsUnderConstruction);
3183 return 1;
3184 //Wyrmgus end
3185 } else if (!strcmp(data, "NumBuildings")) {
3186 lua_pushnumber(l, p->NumBuildings);
3187 return 1;
3188 //Wyrmgus start
3189 } else if (!strcmp(data, "NumBuildingsUnderConstruction")) {
3190 lua_pushnumber(l, p->NumBuildingsUnderConstruction);
3191 return 1;
3192 } else if (!strcmp(data, "NumTownHalls")) {
3193 lua_pushnumber(l, p->NumTownHalls);
3194 return 1;
3195 } else if (!strcmp(data, "NumHeroes")) {
3196 lua_pushnumber(l, p->Heroes.size());
3197 return 1;
3198 } else if (!strcmp(data, "TradeCost")) {
3199 lua_pushnumber(l, p->TradeCost);
3200 return 1;
3201 //Wyrmgus end
3202 } else if (!strcmp(data, "Supply")) {
3203 lua_pushnumber(l, p->Supply);
3204 return 1;
3205 } else if (!strcmp(data, "Demand")) {
3206 lua_pushnumber(l, p->Demand);
3207 return 1;
3208 } else if (!strcmp(data, "UnitLimit")) {
3209 lua_pushnumber(l, p->UnitLimit);
3210 return 1;
3211 } else if (!strcmp(data, "BuildingLimit")) {
3212 lua_pushnumber(l, p->BuildingLimit);
3213 return 1;
3214 } else if (!strcmp(data, "TotalUnitLimit")) {
3215 lua_pushnumber(l, p->TotalUnitLimit);
3216 return 1;
3217 } else if (!strcmp(data, "Score")) {
3218 lua_pushnumber(l, p->Score);
3219 return 1;
3220 } else if (!strcmp(data, "TotalUnits")) {
3221 lua_pushnumber(l, p->TotalUnits);
3222 return 1;
3223 } else if (!strcmp(data, "TotalBuildings")) {
3224 lua_pushnumber(l, p->TotalBuildings);
3225 return 1;
3226 } else if (!strcmp(data, "TotalResources")) {
3227 LuaCheckArgs(l, 3);
3228
3229 const std::string res = LuaToString(l, 3);
3230 const int resId = GetResourceIdByName(l, res.c_str());
3231 lua_pushnumber(l, p->TotalResources[resId]);
3232 return 1;
3233 } else if (!strcmp(data, "TotalRazings")) {
3234 lua_pushnumber(l, p->TotalRazings);
3235 return 1;
3236 } else if (!strcmp(data, "TotalKills")) {
3237 lua_pushnumber(l, p->TotalKills);
3238 return 1;
3239 //Wyrmgus start
3240 } else if (!strcmp(data, "UnitTypeKills")) {
3241 LuaCheckArgs(l, 3);
3242 CUnitType *type = CclGetUnitType(l);
3243 Assert(type);
3244 lua_pushnumber(l, p->UnitTypeKills[type->Slot]);
3245 return 1;
3246 //Wyrmgus end
3247 } else if (!strcmp(data, "SpeedResourcesHarvest")) {
3248 LuaCheckArgs(l, 3);
3249
3250 const std::string res = LuaToString(l, 3);
3251 const int resId = GetResourceIdByName(l, res.c_str());
3252 lua_pushnumber(l, p->SpeedResourcesHarvest[resId]);
3253 return 1;
3254 } else if (!strcmp(data, "SpeedResourcesReturn")) {
3255 LuaCheckArgs(l, 3);
3256
3257 const std::string res = LuaToString(l, 3);
3258 const int resId = GetResourceIdByName(l, res.c_str());
3259 lua_pushnumber(l, p->SpeedResourcesReturn[resId]);
3260 return 1;
3261 } else if (!strcmp(data, "SpeedBuild")) {
3262 lua_pushnumber(l, p->SpeedBuild);
3263 return 1;
3264 } else if (!strcmp(data, "SpeedTrain")) {
3265 lua_pushnumber(l, p->SpeedTrain);
3266 return 1;
3267 } else if (!strcmp(data, "SpeedUpgrade")) {
3268 lua_pushnumber(l, p->SpeedUpgrade);
3269 return 1;
3270 } else if (!strcmp(data, "SpeedResearch")) {
3271 lua_pushnumber(l, p->SpeedResearch);
3272 return 1;
3273 } else if (!strcmp(data, "Allow")) {
3274 LuaCheckArgs(l, 3);
3275 const char *ident = LuaToString(l, 3);
3276 if (!strncmp(ident, "unit-", 5)) {
3277 int id = UnitTypeIdByIdent(ident);
3278 if (UnitIdAllowed(Players[p->Index], id) > 0) {
3279 lua_pushstring(l, "A");
3280 } else if (UnitIdAllowed(Players[p->Index], id) == 0) {
3281 lua_pushstring(l, "F");
3282 }
3283 } else if (!strncmp(ident, "upgrade-", 8)) {
3284 if (UpgradeIdentAllowed(Players[p->Index], ident) == 'A') {
3285 lua_pushstring(l, "A");
3286 } else if (UpgradeIdentAllowed(Players[p->Index], ident) == 'R') {
3287 lua_pushstring(l, "R");
3288 } else if (UpgradeIdentAllowed(Players[p->Index], ident) == 'F') {
3289 lua_pushstring(l, "F");
3290 }
3291 } else {
3292 DebugPrint(" wrong ident %s\n" _C_ ident);
3293 }
3294 return 1;
3295 //Wyrmgus start
3296 } else if (!strcmp(data, "HasContactWith")) {
3297 LuaCheckArgs(l, 3);
3298 int second_player = LuaToNumber(l, 3);
3299 lua_pushboolean(l, p->HasContactWith(Players[second_player]));
3300 return 1;
3301 } else if (!strcmp(data, "HasQuest")) {
3302 LuaCheckArgs(l, 3);
3303 CQuest *quest = GetQuest(LuaToString(l, 3));
3304 if (std::find(p->CurrentQuests.begin(), p->CurrentQuests.end(), quest) != p->CurrentQuests.end()) {
3305 lua_pushboolean(l, true);
3306 } else {
3307 lua_pushboolean(l, false);
3308 }
3309 return 1;
3310 } else if (!strcmp(data, "CompletedQuest")) {
3311 LuaCheckArgs(l, 3);
3312 CQuest *quest = GetQuest(LuaToString(l, 3));
3313 if (std::find(p->CompletedQuests.begin(), p->CompletedQuests.end(), quest) != p->CompletedQuests.end()) {
3314 lua_pushboolean(l, true);
3315 } else {
3316 lua_pushboolean(l, false);
3317 }
3318 return 1;
3319 } else if (!strcmp(data, "FactionTitle")) {
3320 lua_pushstring(l, p->GetFactionTitleName().c_str());
3321 return 1;
3322 } else if (!strcmp(data, "CharacterTitle")) {
3323 LuaCheckArgs(l, 4);
3324 std::string title_type_ident = LuaToString(l, 3);
3325 std::string gender_ident = LuaToString(l, 4);
3326 int title_type_id = GetCharacterTitleIdByName(title_type_ident);
3327 int gender_id = GetGenderIdByName(gender_ident);
3328
3329 lua_pushstring(l, p->GetCharacterTitleName(title_type_id, gender_id).c_str());
3330 return 1;
3331 } else if (!strcmp(data, "HasSettlement")) {
3332 LuaCheckArgs(l, 3);
3333 std::string site_ident = LuaToString(l, 3);
3334 CSite *site = CSite::GetSite(site_ident);
3335 lua_pushboolean(l, p->HasSettlement(site));
3336 return 1;
3337 } else if (!strcmp(data, "SettlementName")) {
3338 LuaCheckArgs(l, 3);
3339 std::string site_ident = LuaToString(l, 3);
3340 const CSite *site = CSite::GetSite(site_ident);
3341 if (site) {
3342 lua_pushstring(l, site->GetCulturalName(p->Race != -1 ? CCivilization::Civilizations[p->Race] : nullptr).c_str());
3343 } else {
3344 lua_pushstring(l, "");
3345 }
3346 return 1;
3347 //Wyrmgus end
3348 } else if (!strcmp(data, "Currency")) {
3349 const CCurrency *currency = p->GetCurrency();
3350 if (currency) {
3351 lua_pushstring(l, currency->Name.c_str());
3352 } else {
3353 lua_pushstring(l, "");
3354 }
3355 return 1;
3356 } else {
3357 LuaError(l, "Invalid field: %s" _C_ data);
3358 }
3359
3360 return 0;
3361 }
3362
3363 /**
3364 ** Set player data.
3365 **
3366 ** @param l Lua state.
3367 */
CclSetPlayerData(lua_State * l)3368 static int CclSetPlayerData(lua_State *l)
3369 {
3370 if (lua_gettop(l) < 3) {
3371 LuaError(l, "incorrect argument");
3372 }
3373 lua_pushvalue(l, 1);
3374 CPlayer *p = CclGetPlayer(l);
3375 lua_pop(l, 1);
3376 const char *data = LuaToString(l, 2);
3377
3378 //Wyrmgus start
3379 //if player is unused, return
3380 if (p->Type == PlayerNobody && Editor.Running == EditorNotRunning) {
3381 return 0;
3382 }
3383 //Wyrmgus end
3384
3385 if (!strcmp(data, "Name")) {
3386 p->SetName(LuaToString(l, 3));
3387 } else if (!strcmp(data, "RaceName")) {
3388 if (GameRunning) {
3389 p->SetFaction(nullptr);
3390 }
3391
3392 const char *civilization_ident = LuaToString(l, 3);
3393 CCivilization *civilization = CCivilization::GetCivilization(civilization_ident);
3394 if (civilization) {
3395 p->SetCivilization(civilization->ID);
3396 }
3397 //Wyrmgus start
3398 } else if (!strcmp(data, "Faction")) {
3399 std::string faction_name = LuaToString(l, 3);
3400 if (faction_name == "random") {
3401 p->SetRandomFaction();
3402 } else {
3403 p->SetFaction(PlayerRaces.GetFaction(faction_name));
3404 }
3405 } else if (!strcmp(data, "Dynasty")) {
3406 std::string dynasty_ident = LuaToString(l, 3);
3407 p->SetDynasty(PlayerRaces.GetDynasty(dynasty_ident));
3408 //Wyrmgus end
3409 } else if (!strcmp(data, "Resources")) {
3410 LuaCheckArgs(l, 4);
3411
3412 const std::string res = LuaToString(l, 3);
3413 const int resId = GetResourceIdByName(l, res.c_str());
3414 p->SetResource(resId, LuaToNumber(l, 4));
3415 } else if (!strcmp(data, "StoredResources")) {
3416 LuaCheckArgs(l, 4);
3417
3418 const std::string res = LuaToString(l, 3);
3419 const int resId = GetResourceIdByName(l, res.c_str());
3420 p->SetResource(resId, LuaToNumber(l, 4), STORE_BUILDING);
3421 // } else if (!strcmp(data, "UnitTypesCount")) {
3422 // } else if (!strcmp(data, "AiEnabled")) {
3423 // } else if (!strcmp(data, "TotalNumUnits")) {
3424 // } else if (!strcmp(data, "NumBuildings")) {
3425 // } else if (!strcmp(data, "Supply")) {
3426 // } else if (!strcmp(data, "Demand")) {
3427 } else if (!strcmp(data, "UnitLimit")) {
3428 p->UnitLimit = LuaToNumber(l, 3);
3429 } else if (!strcmp(data, "BuildingLimit")) {
3430 p->BuildingLimit = LuaToNumber(l, 3);
3431 } else if (!strcmp(data, "TotalUnitLimit")) {
3432 p->TotalUnitLimit = LuaToNumber(l, 3);
3433 } else if (!strcmp(data, "Score")) {
3434 p->Score = LuaToNumber(l, 3);
3435 } else if (!strcmp(data, "TotalUnits")) {
3436 p->TotalUnits = LuaToNumber(l, 3);
3437 } else if (!strcmp(data, "TotalBuildings")) {
3438 p->TotalBuildings = LuaToNumber(l, 3);
3439 } else if (!strcmp(data, "TotalResources")) {
3440 LuaCheckArgs(l, 4);
3441
3442 const std::string res = LuaToString(l, 3);
3443 const int resId = GetResourceIdByName(l, res.c_str());
3444 p->TotalResources[resId] = LuaToNumber(l, 4);
3445 } else if (!strcmp(data, "TotalRazings")) {
3446 p->TotalRazings = LuaToNumber(l, 3);
3447 } else if (!strcmp(data, "TotalKills")) {
3448 p->TotalKills = LuaToNumber(l, 3);
3449 } else if (!strcmp(data, "SpeedResourcesHarvest")) {
3450 LuaCheckArgs(l, 4);
3451
3452 const std::string res = LuaToString(l, 3);
3453 const int resId = GetResourceIdByName(l, res.c_str());
3454 p->SpeedResourcesHarvest[resId] = LuaToNumber(l, 4);
3455 } else if (!strcmp(data, "SpeedResourcesReturn")) {
3456 LuaCheckArgs(l, 4);
3457
3458 const std::string res = LuaToString(l, 3);
3459 const int resId = GetResourceIdByName(l, res.c_str());
3460 p->SpeedResourcesReturn[resId] = LuaToNumber(l, 4);
3461 } else if (!strcmp(data, "SpeedBuild")) {
3462 p->SpeedBuild = LuaToNumber(l, 3);
3463 } else if (!strcmp(data, "SpeedTrain")) {
3464 p->SpeedTrain = LuaToNumber(l, 3);
3465 } else if (!strcmp(data, "SpeedUpgrade")) {
3466 p->SpeedUpgrade = LuaToNumber(l, 3);
3467 } else if (!strcmp(data, "SpeedResearch")) {
3468 p->SpeedResearch = LuaToNumber(l, 3);
3469 } else if (!strcmp(data, "Allow")) {
3470 LuaCheckArgs(l, 4);
3471 const char *ident = LuaToString(l, 3);
3472 const std::string acquire = LuaToString(l, 4);
3473
3474 if (!strncmp(ident, "upgrade-", 8)) {
3475 if (acquire == "R" && UpgradeIdentAllowed(*p, ident) != 'R') {
3476 UpgradeAcquire(*p, CUpgrade::Get(ident));
3477 } else if (acquire == "F" || acquire == "A") {
3478 if (UpgradeIdentAllowed(*p, ident) == 'R') {
3479 UpgradeLost(*p, CUpgrade::Get(ident)->ID);
3480 }
3481 AllowUpgradeId(*p, UpgradeIdByIdent(ident), acquire[0]);
3482 }
3483 //Wyrmgus start
3484 } else if (!strncmp(ident, "unit-", 5)) {
3485 const int UnitMax = 65536; /// How many units supported
3486 int id = UnitTypeIdByIdent(ident);
3487 if (acquire == "A" || acquire == "R") {
3488 AllowUnitId(*p, id, UnitMax);
3489 } else if (acquire == "F") {
3490 AllowUnitId(*p, id, 0);
3491 }
3492 //Wyrmgus end
3493 } else {
3494 LuaError(l, " wrong ident %s\n" _C_ ident);
3495 }
3496 //Wyrmgus start
3497 } else if (!strcmp(data, "AiEnabled")) {
3498 p->AiEnabled = LuaToBoolean(l, 3);
3499 } else if (!strcmp(data, "Team")) {
3500 p->Team = LuaToNumber(l, 3);
3501 } else if (!strcmp(data, "AcceptQuest")) {
3502 CQuest *quest = GetQuest(LuaToString(l, 3));
3503 if (quest) {
3504 p->AcceptQuest(quest);
3505 }
3506 } else if (!strcmp(data, "CompleteQuest")) {
3507 CQuest *quest = GetQuest(LuaToString(l, 3));
3508 if (quest) {
3509 p->CompleteQuest(quest);
3510 }
3511 } else if (!strcmp(data, "FailQuest")) {
3512 CQuest *quest = GetQuest(LuaToString(l, 3));
3513 if (quest) {
3514 p->FailQuest(quest);
3515 }
3516 } else if (!strcmp(data, "AddModifier")) {
3517 LuaCheckArgs(l, 4);
3518 CUpgrade *modifier_upgrade = CUpgrade::Get(LuaToString(l, 3));
3519 int cycles = LuaToNumber(l, 4);
3520 if (modifier_upgrade) {
3521 p->AddModifier(modifier_upgrade, cycles);
3522 }
3523 //Wyrmgus end
3524 } else {
3525 LuaError(l, "Invalid field: %s" _C_ data);
3526 }
3527
3528 return 0;
3529 }
3530
3531 /**
3532 ** Set ai player algo.
3533 **
3534 ** @param l Lua state.
3535 */
CclSetAiType(lua_State * l)3536 static int CclSetAiType(lua_State *l)
3537 {
3538 CPlayer *p;
3539
3540 if (lua_gettop(l) < 2) {
3541 LuaError(l, "incorrect argument");
3542 }
3543 lua_pushvalue(l, 1);
3544 p = CclGetPlayer(l);
3545 lua_pop(l, 1);
3546
3547 p->AiName = LuaToString(l, 2);
3548
3549 return 0;
3550 }
3551
3552 //Wyrmgus start
3553 /**
3554 ** Init ai for player.
3555 **
3556 ** @param l Lua state.
3557 */
CclInitAi(lua_State * l)3558 static int CclInitAi(lua_State *l)
3559 {
3560 CPlayer *p;
3561
3562 if (lua_gettop(l) < 1) {
3563 LuaError(l, "incorrect argument");
3564 }
3565 lua_pushvalue(l, 1);
3566 p = CclGetPlayer(l);
3567 lua_pop(l, 1);
3568
3569 AiInit(*p);
3570
3571 return 0;
3572 }
3573
CclGetLanguages(lua_State * l)3574 static int CclGetLanguages(lua_State *l)
3575 {
3576 bool only_used = false;
3577 if (lua_gettop(l) >= 1) {
3578 only_used = LuaToBoolean(l, 1);
3579 }
3580
3581 std::vector<std::string> languages;
3582 for (size_t i = 0; i != PlayerRaces.Languages.size(); ++i) {
3583 if (!only_used || PlayerRaces.Languages[i]->UsedByCivilizationOrFaction) {
3584 languages.push_back(PlayerRaces.Languages[i]->Ident);
3585 }
3586 }
3587
3588 lua_createtable(l, languages.size(), 0);
3589 for (size_t i = 1; i <= languages.size(); ++i)
3590 {
3591 lua_pushstring(l, languages[i-1].c_str());
3592 lua_rawseti(l, -2, i);
3593 }
3594 return 1;
3595 }
3596
3597 /**
3598 ** Get language data.
3599 **
3600 ** @param l Lua state.
3601 */
CclGetLanguageData(lua_State * l)3602 static int CclGetLanguageData(lua_State *l)
3603 {
3604 if (lua_gettop(l) < 2) {
3605 LuaError(l, "incorrect argument");
3606 }
3607 std::string language_name = LuaToString(l, 1);
3608 const CLanguage *language = PlayerRaces.GetLanguage(language_name);
3609 if (!language) {
3610 LuaError(l, "Language \"%s\" doesn't exist." _C_ language_name.c_str());
3611 }
3612 const char *data = LuaToString(l, 2);
3613
3614 if (!strcmp(data, "Name")) {
3615 lua_pushstring(l, language->Name.c_str());
3616 return 1;
3617 } else if (!strcmp(data, "Family")) {
3618 lua_pushstring(l, language->Family.c_str());
3619 return 1;
3620 } else if (!strcmp(data, "Words")) {
3621 lua_createtable(l, language->LanguageWords.size(), 0);
3622 for (size_t i = 1; i <= language->LanguageWords.size(); ++i)
3623 {
3624 lua_pushstring(l, language->LanguageWords[i-1]->Word.c_str());
3625 lua_rawseti(l, -2, i);
3626 }
3627 return 1;
3628 } else {
3629 LuaError(l, "Invalid field: %s" _C_ data);
3630 }
3631
3632 return 0;
3633 }
3634
3635 /**
3636 ** Get language word data.
3637 **
3638 ** @param l Lua state.
3639 */
CclGetLanguageWordData(lua_State * l)3640 static int CclGetLanguageWordData(lua_State *l)
3641 {
3642 if (lua_gettop(l) < 3) {
3643 LuaError(l, "incorrect argument");
3644 }
3645 std::string language_name = LuaToString(l, 1);
3646 const CLanguage *language = PlayerRaces.GetLanguage(language_name);
3647 if (!language) {
3648 LuaError(l, "Language \"%s\" doesn't exist." _C_ language_name.c_str());
3649 }
3650
3651 std::string word_name = LuaToString(l, 2);
3652 std::vector<std::string> word_meanings;
3653 const LanguageWord *word = language->GetWord(word_name, -1, word_meanings);
3654 if (word == nullptr) {
3655 LuaError(l, "Word \"%s\" doesn't exist for the \"%s\" language." _C_ word_name.c_str() _C_ language_name.c_str());
3656 }
3657
3658 const char *data = LuaToString(l, 3);
3659
3660 if (!strcmp(data, "Type")) {
3661 if (word->Type != -1) {
3662 lua_pushstring(l, GetWordTypeNameById(word->Type).c_str());
3663 } else {
3664 lua_pushstring(l, "");
3665 }
3666 return 1;
3667 } else if (!strcmp(data, "Meaning")) {
3668 for (size_t i = 0; i < word->Meanings.size(); ++i) {
3669 lua_pushstring(l, word->Meanings[i].c_str());
3670 return 1;
3671 }
3672 lua_pushstring(l, "");
3673 return 1;
3674 } else if (!strcmp(data, "Gender")) {
3675 if (word->Gender != -1) {
3676 lua_pushstring(l, GetGrammaticalGenderNameById(word->Gender).c_str());
3677 } else {
3678 lua_pushstring(l, "");
3679 }
3680 return 1;
3681 } else {
3682 LuaError(l, "Invalid field: %s" _C_ data);
3683 }
3684
3685 return 0;
3686 }
3687
CclGetReligions(lua_State * l)3688 static int CclGetReligions(lua_State *l)
3689 {
3690 lua_createtable(l, CReligion::Religions.size(), 0);
3691 for (size_t i = 1; i <= CReligion::Religions.size(); ++i)
3692 {
3693 lua_pushstring(l, CReligion::Religions[i-1]->Ident.c_str());
3694 lua_rawseti(l, -2, i);
3695 }
3696 return 1;
3697 }
3698
CclGetDeityDomains(lua_State * l)3699 static int CclGetDeityDomains(lua_State *l)
3700 {
3701 lua_createtable(l, CDeityDomain::DeityDomains.size(), 0);
3702 for (size_t i = 1; i <= CDeityDomain::DeityDomains.size(); ++i)
3703 {
3704 lua_pushstring(l, CDeityDomain::DeityDomains[i-1]->Ident.c_str());
3705 lua_rawseti(l, -2, i);
3706 }
3707 return 1;
3708 }
3709
CclGetDeities(lua_State * l)3710 static int CclGetDeities(lua_State *l)
3711 {
3712 lua_createtable(l, CDeity::Deities.size(), 0);
3713 for (size_t i = 1; i <= CDeity::Deities.size(); ++i)
3714 {
3715 lua_pushstring(l, CDeity::Deities[i-1]->Ident.c_str());
3716 lua_rawseti(l, -2, i);
3717 }
3718 return 1;
3719 }
3720
3721 /**
3722 ** Get religion data.
3723 **
3724 ** @param l Lua state.
3725 */
CclGetReligionData(lua_State * l)3726 static int CclGetReligionData(lua_State *l)
3727 {
3728 if (lua_gettop(l) < 2) {
3729 LuaError(l, "incorrect argument");
3730 }
3731 std::string religion_ident = LuaToString(l, 1);
3732 const CReligion *religion = CReligion::GetReligion(religion_ident);
3733 if (!religion) {
3734 return 0;
3735 }
3736 const char *data = LuaToString(l, 2);
3737
3738 if (!strcmp(data, "Name")) {
3739 lua_pushstring(l, religion->Name.c_str());
3740 return 1;
3741 } else if (!strcmp(data, "Description")) {
3742 lua_pushstring(l, religion->Description.c_str());
3743 return 1;
3744 } else if (!strcmp(data, "Background")) {
3745 lua_pushstring(l, religion->Background.c_str());
3746 return 1;
3747 } else if (!strcmp(data, "Quote")) {
3748 lua_pushstring(l, religion->Quote.c_str());
3749 return 1;
3750 } else if (!strcmp(data, "CulturalDeities")) {
3751 lua_pushboolean(l, religion->CulturalDeities);
3752 return 1;
3753 } else {
3754 LuaError(l, "Invalid field: %s" _C_ data);
3755 }
3756
3757 return 0;
3758 }
3759
3760 /**
3761 ** Get deity domain data.
3762 **
3763 ** @param l Lua state.
3764 */
CclGetDeityDomainData(lua_State * l)3765 static int CclGetDeityDomainData(lua_State *l)
3766 {
3767 if (lua_gettop(l) < 2) {
3768 LuaError(l, "incorrect argument");
3769 }
3770 std::string deity_domain_ident = LuaToString(l, 1);
3771 const CDeityDomain *deity_domain = CDeityDomain::GetDeityDomain(deity_domain_ident);
3772 if (!deity_domain) {
3773 return 0;
3774 }
3775 const char *data = LuaToString(l, 2);
3776
3777 if (!strcmp(data, "Name")) {
3778 lua_pushstring(l, deity_domain->Name.c_str());
3779 return 1;
3780 } else if (!strcmp(data, "Abilities")) {
3781 lua_createtable(l, deity_domain->Abilities.size(), 0);
3782 for (size_t i = 1; i <= deity_domain->Abilities.size(); ++i)
3783 {
3784 lua_pushstring(l, deity_domain->Abilities[i-1]->Ident.c_str());
3785 lua_rawseti(l, -2, i);
3786 }
3787 return 1;
3788 } else {
3789 LuaError(l, "Invalid field: %s" _C_ data);
3790 }
3791
3792 return 0;
3793 }
3794
3795 /**
3796 ** Get deity data.
3797 **
3798 ** @param l Lua state.
3799 */
CclGetDeityData(lua_State * l)3800 static int CclGetDeityData(lua_State *l)
3801 {
3802 if (lua_gettop(l) < 2) {
3803 LuaError(l, "incorrect argument");
3804 }
3805 std::string deity_ident = LuaToString(l, 1);
3806 const CDeity *deity = CDeity::GetDeity(deity_ident);
3807 if (!deity) {
3808 return 0;
3809 }
3810 const char *data = LuaToString(l, 2);
3811
3812 if (!strcmp(data, "Name")) {
3813 lua_pushstring(l, deity->Name.c_str());
3814 return 1;
3815 } else if (!strcmp(data, "Pantheon")) {
3816 if (deity->Pantheon) {
3817 lua_pushstring(l, deity->Pantheon->Name.c_str());
3818 } else {
3819 lua_pushstring(l, "");
3820 }
3821 return 1;
3822 } else if (!strcmp(data, "Description")) {
3823 lua_pushstring(l, deity->Description.c_str());
3824 return 1;
3825 } else if (!strcmp(data, "Background")) {
3826 lua_pushstring(l, deity->Background.c_str());
3827 return 1;
3828 } else if (!strcmp(data, "Quote")) {
3829 lua_pushstring(l, deity->Quote.c_str());
3830 return 1;
3831 } else if (!strcmp(data, "Major")) {
3832 lua_pushboolean(l, deity->Major);
3833 return 1;
3834 } else if (!strcmp(data, "HomePlane")) {
3835 if (deity->HomePlane) {
3836 lua_pushstring(l, deity->HomePlane->Ident.c_str());
3837 } else {
3838 lua_pushstring(l, "");
3839 }
3840 return 1;
3841 } else if (!strcmp(data, "Icon")) {
3842 lua_pushstring(l, deity->Icon.Name.c_str());
3843 return 1;
3844 } else if (!strcmp(data, "Civilizations")) {
3845 lua_createtable(l, deity->Civilizations.size(), 0);
3846 for (size_t i = 1; i <= deity->Civilizations.size(); ++i)
3847 {
3848 lua_pushstring(l, PlayerRaces.Name[deity->Civilizations[i-1]->ID].c_str());
3849 lua_rawseti(l, -2, i);
3850 }
3851 return 1;
3852 } else if (!strcmp(data, "Religions")) {
3853 lua_createtable(l, deity->Religions.size(), 0);
3854 for (size_t i = 1; i <= deity->Religions.size(); ++i)
3855 {
3856 lua_pushstring(l, deity->Religions[i-1]->Ident.c_str());
3857 lua_rawseti(l, -2, i);
3858 }
3859 return 1;
3860 } else if (!strcmp(data, "Domains")) {
3861 lua_createtable(l, deity->Domains.size(), 0);
3862 for (size_t i = 1; i <= deity->Domains.size(); ++i)
3863 {
3864 lua_pushstring(l, deity->Domains[i-1]->Ident.c_str());
3865 lua_rawseti(l, -2, i);
3866 }
3867 return 1;
3868 } else if (!strcmp(data, "Abilities")) {
3869 lua_createtable(l, deity->Abilities.size(), 0);
3870 for (size_t i = 1; i <= deity->Abilities.size(); ++i)
3871 {
3872 lua_pushstring(l, deity->Abilities[i-1]->Ident.c_str());
3873 lua_rawseti(l, -2, i);
3874 }
3875 return 1;
3876 } else if (!strcmp(data, "CulturalName")) {
3877 if (lua_gettop(l) < 3) {
3878 LuaError(l, "incorrect argument");
3879 }
3880
3881 const CCivilization *civilization = CCivilization::GetCivilization(LuaToString(l, 3));
3882 lua_pushstring(l, deity->GetCulturalName(civilization).c_str());
3883
3884 return 1;
3885 } else if (!strcmp(data, "Gender")) {
3886 lua_pushstring(l, GetGenderNameById(deity->Gender).c_str());
3887 return 1;
3888 } else {
3889 LuaError(l, "Invalid field: %s" _C_ data);
3890 }
3891
3892 return 0;
3893 }
3894 //Wyrmgus end
3895
3896 // ----------------------------------------------------------------------------
3897
3898 /**
3899 ** Register CCL features for players.
3900 */
PlayerCclRegister()3901 void PlayerCclRegister()
3902 {
3903 lua_register(Lua, "Player", CclPlayer);
3904 lua_register(Lua, "ChangeUnitsOwner", CclChangeUnitsOwner);
3905 lua_register(Lua, "GetThisPlayer", CclGetThisPlayer);
3906 lua_register(Lua, "SetThisPlayer", CclSetThisPlayer);
3907
3908 lua_register(Lua, "SetMaxSelectable", CclSetMaxSelectable);
3909
3910 lua_register(Lua, "SetAllPlayersUnitLimit", CclSetAllPlayersUnitLimit);
3911 lua_register(Lua, "SetAllPlayersBuildingLimit", CclSetAllPlayersBuildingLimit);
3912 lua_register(Lua, "SetAllPlayersTotalUnitLimit", CclSetAllPlayersTotalUnitLimit);
3913
3914 lua_register(Lua, "SetDiplomacy", CclSetDiplomacy);
3915 lua_register(Lua, "Diplomacy", CclDiplomacy);
3916 lua_register(Lua, "SetSharedVision", CclSetSharedVision);
3917 lua_register(Lua, "SharedVision", CclSharedVision);
3918
3919 //Wyrmgus start
3920 lua_register(Lua, "DefineCivilization", CclDefineCivilization);
3921 lua_register(Lua, "DefineLanguageWord", CclDefineLanguageWord);
3922 lua_register(Lua, "GetCivilizationData", CclGetCivilizationData);
3923 lua_register(Lua, "GetCivilizationClassUnitType", CclGetCivilizationClassUnitType);
3924 lua_register(Lua, "GetFactionClassUnitType", CclGetFactionClassUnitType);
3925 lua_register(Lua, "DefineFaction", CclDefineFaction);
3926 lua_register(Lua, "DefineDynasty", CclDefineDynasty);
3927 lua_register(Lua, "DefineReligion", CclDefineReligion);
3928 lua_register(Lua, "DefineDeity", CclDefineDeity);
3929 lua_register(Lua, "DefineLanguage", CclDefineLanguage);
3930 lua_register(Lua, "GetCivilizations", CclGetCivilizations);
3931 lua_register(Lua, "GetFactions", CclGetFactions);
3932 lua_register(Lua, "GetDynasties", CclGetDynasties);
3933 lua_register(Lua, "GetPlayerColors", CclGetPlayerColors);
3934 lua_register(Lua, "GetFactionData", CclGetFactionData);
3935 lua_register(Lua, "GetDynastyData", CclGetDynastyData);
3936 //Wyrmgus end
3937 lua_register(Lua, "DefinePlayerColors", CclDefinePlayerColors);
3938 lua_register(Lua, "DefinePlayerColorIndex", CclDefinePlayerColorIndex);
3939
3940 lua_register(Lua, "NewColors", CclNewPlayerColors);
3941
3942 lua_register(Lua, "DefineConversiblePlayerColors", CclDefineConversiblePlayerColors);
3943
3944 // player member access functions
3945 lua_register(Lua, "GetPlayerData", CclGetPlayerData);
3946 lua_register(Lua, "SetPlayerData", CclSetPlayerData);
3947 lua_register(Lua, "SetAiType", CclSetAiType);
3948 //Wyrmgus start
3949 lua_register(Lua, "InitAi", CclInitAi);
3950 lua_register(Lua, "GetLanguages", CclGetLanguages);
3951 lua_register(Lua, "GetLanguageData", CclGetLanguageData);
3952 lua_register(Lua, "GetLanguageWordData", CclGetLanguageWordData);
3953
3954 lua_register(Lua, "GetReligions", CclGetReligions);
3955 lua_register(Lua, "GetDeityDomains", CclGetDeityDomains);
3956 lua_register(Lua, "GetDeities", CclGetDeities);
3957 lua_register(Lua, "GetReligionData", CclGetReligionData);
3958 lua_register(Lua, "GetDeityDomainData", CclGetDeityDomainData);
3959 lua_register(Lua, "GetDeityData", CclGetDeityData);
3960 //Wyrmgus end
3961 }
3962