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_map.cpp - The map ccl functions. */
12 //
13 // (c) Copyright 1999-2005 by Lutz Sammer and Jimmy Salmon
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
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #include "map.h"
39 #include "fov.h"
40 #include "fow.h"
41 #include "iolib.h"
42 #include "netconnect.h"
43 #include "network.h"
44 #include "script.h"
45 #include "tileset.h"
46 #include "translate.h"
47 #include "ui.h"
48 #include "unit.h"
49 #include "version.h"
50 #include "video.h"
51
52 /*----------------------------------------------------------------------------
53 -- Variables
54 ----------------------------------------------------------------------------*/
55
56 /*----------------------------------------------------------------------------
57 -- Functions
58 ----------------------------------------------------------------------------*/
59
60 /**
61 ** Parse a map.
62 **
63 ** @param l Lua state.
64 */
CclStratagusMap(lua_State * l)65 static int CclStratagusMap(lua_State *l)
66 {
67 int args = lua_gettop(l);
68 for (int j = 0; j < args; ++j) {
69 const char *value = LuaToString(l, j + 1);
70 ++j;
71
72 if (!strcmp(value, "version")) {
73 char buf[32];
74
75 const char *version = LuaToString(l, j + 1);
76 strncpy(buf, VERSION, sizeof(buf));
77 if (strcmp(buf, version)) {
78 fprintf(stderr, "Warning not saved with this version.\n");
79 }
80 } else if (!strcmp(value, "uid")) {
81 Map.Info.MapUID = LuaToNumber(l, j + 1);
82 } else if (!strcmp(value, "description")) {
83 Map.Info.Description = LuaToString(l, j + 1);
84 } else if (!strcmp(value, "the-map")) {
85 if (!lua_istable(l, j + 1)) {
86 LuaError(l, "incorrect argument");
87 }
88 int subargs = lua_rawlen(l, j + 1);
89 for (int k = 0; k < subargs; ++k) {
90 const char *value = LuaToString(l, j + 1, k + 1);
91 ++k;
92
93 if (!strcmp(value, "size")) {
94 lua_rawgeti(l, j + 1, k + 1);
95 CclGetPos(l, &Map.Info.MapWidth, &Map.Info.MapHeight);
96 lua_pop(l, 1);
97
98 delete[] Map.Fields;
99 Map.Fields = new CMapField[Map.Info.MapWidth * Map.Info.MapHeight];
100 // FIXME: this should be CreateMap or InitMap?
101 } else if (!strcmp(value, "fog-of-war")) {
102 Map.NoFogOfWar = false;
103 --k;
104 } else if (!strcmp(value, "no-fog-of-war")) {
105 Map.NoFogOfWar = true;
106 --k;
107 } else if (!strcmp(value, "filename")) {
108 Map.Info.Filename = LuaToString(l, j + 1, k + 1);
109 } else if (!strcmp(value, "map-fields")) {
110 lua_rawgeti(l, j + 1, k + 1);
111 if (!lua_istable(l, -1)) {
112 LuaError(l, "incorrect argument");
113 }
114 const int subsubargs = lua_rawlen(l, -1);
115 if (subsubargs != Map.Info.MapWidth * Map.Info.MapHeight) {
116 fprintf(stderr, "Wrong tile table length: %d\n", subsubargs);
117 }
118 for (int i = 0; i < subsubargs; ++i) {
119 lua_rawgeti(l, -1, i + 1);
120 if (!lua_istable(l, -1)) {
121 LuaError(l, "incorrect argument");
122 }
123 Map.Fields[i].parse(l);
124 lua_pop(l, 1);
125 }
126 lua_pop(l, 1);
127 } else {
128 LuaError(l, "Unsupported tag: %s" _C_ value);
129 }
130 }
131 } else {
132 LuaError(l, "Unsupported tag: %s" _C_ value);
133 }
134 }
135 return 0;
136 }
137
138 /**
139 ** Reveal the complete map.
140 **
141 ** @param l Lua state.
142 */
CclRevealMap(lua_State * l)143 static int CclRevealMap(lua_State *l)
144 {
145 LuaCheckArgs(l, 1);
146
147 int newMode;
148 const char *revealMode = LuaToString(l, 1);
149 if (!strcmp(revealMode, "hidden")) {
150 newMode = MapRevealModes::cHidden;
151 } else if (!strcmp(revealMode, "known")) {
152 newMode = MapRevealModes::cKnown;
153 } else if (!strcmp(revealMode, "explored")) {
154 newMode = MapRevealModes::cExplored;
155 } else {
156 PrintFunction();
157 fprintf(stdout, "Accessible reveal modes: \"hidden\", \"known\", \"explored\".\n");
158 return 1;
159 }
160
161 if (CclInConfigFile || !Map.Fields) {
162 FlagRevealMap = newMode;
163 } else if (!IsNetworkGame()) {
164 Map.Reveal(newMode);
165 } else {
166 NetworkSendExtendedCommand(ExtendedMessageRevealMapDB, int(newMode), 0, 0, 0, 0);
167 }
168 return 0;
169 }
170
171 /**
172 ** <b>Description</b>
173 **
174 ** Center the map.
175 **
176 ** @param l Lua state.
177 **
178 ** Example:
179 **
180 ** <div class="example"><code>-- Center the view at position x=11 and y=1.
181 ** <strong>CenterMap</strong>(11, 1)</code></div>
182 */
CclCenterMap(lua_State * l)183 static int CclCenterMap(lua_State *l)
184 {
185 LuaCheckArgs(l, 2);
186 const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2));
187
188 UI.SelectedViewport->Center(Map.TilePosToMapPixelPos_Center(pos));
189 return 0;
190 }
191
192 /**
193 ** <b>Description</b>
194 **
195 ** Define the starting viewpoint for a given player.
196 **
197 ** @param l Lua state.
198 **
199 ** Example:
200 **
201 ** <div class="example"><code>-- Start view for player 0.
202 ** <strong>SetStartView</strong>(0, 25, 12)
203 ** -- Start view for player 1.
204 ** <strong>SetStartView</strong>(1, 71, 38)</code></div>
205 */
CclSetStartView(lua_State * l)206 static int CclSetStartView(lua_State *l)
207 {
208 LuaCheckArgs(l, 3);
209
210 const int p = LuaToNumber(l, 1);
211 Players[p].StartPos.x = LuaToNumber(l, 2);
212 Players[p].StartPos.y = LuaToNumber(l, 3);
213
214 return 0;
215 }
216
217 /**
218 ** Show Map Location
219 **
220 ** @param l Lua state.
221 */
CclShowMapLocation(lua_State * l)222 static int CclShowMapLocation(lua_State *l)
223 {
224 // Put a unit on map, use its properties, except for
225 // what is listed below
226
227 LuaCheckArgs(l, 5);
228 const char *unitname = LuaToString(l, 5);
229 CUnitType *unitType = UnitTypeByIdent(unitname);
230 if (!unitType) {
231 DebugPrint("Unable to find UnitType '%s'" _C_ unitname);
232 return 0;
233 }
234 CUnit *target = MakeUnit(*unitType, ThisPlayer);
235 if (target != NULL) {
236 target->Variable[HP_INDEX].Value = 0;
237 target->tilePos.x = LuaToNumber(l, 1);
238 target->tilePos.y = LuaToNumber(l, 2);
239 target->TTL = GameCycle + LuaToNumber(l, 4);
240 target->CurrentSightRange = LuaToNumber(l, 3);
241 MapMarkUnitSight(*target);
242 } else {
243 DebugPrint("Unable to allocate Unit");
244 }
245 return 0;
246 }
247
248 /**
249 ** <b>Description</b>
250 **
251 ** Set fog of war on/off.
252 **
253 ** Example:
254 **
255 ** <div class="example"><code><strong>SetFogOfWar</strong>(true)</code></div>
256 **
257 ** @param l Lua state.
258 */
CclSetFogOfWar(lua_State * l)259 static int CclSetFogOfWar(lua_State *l)
260 {
261
262 LuaCheckArgs(l, 1);
263 Map.NoFogOfWar = !LuaToBoolean(l, 1);
264 if (!CclInConfigFile && Map.Fields) {
265 UpdateFogOfWarChange();
266 // FIXME: save setting in replay log
267 //CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, "fow off", -1);
268 }
269 return 0;
270 }
271
272 /**
273 ** <b>Description</b>
274 **
275 ** Get if the fog of war is enabled.
276 **
277 ** @param l Lua state.
278 **
279 ** Example:
280 **
281 ** <div class="example"><code><strong>GetFogOfWar</strong>()</code></div>
282 */
CclGetFogOfWar(lua_State * l)283 static int CclGetFogOfWar(lua_State *l)
284 {
285 LuaCheckArgs(l, 0);
286 lua_pushboolean(l, !Map.NoFogOfWar);
287 return 1;
288 }
289
290 /**
291 ** <b>Description</b>
292 **
293 ** Enable display of terrain in minimap.
294 **
295 ** @param l Lua state.
296 **
297 ** Example:
298 **
299 ** <div class="example"><code>-- Show the minimap terrain
300 ** <strong>SetMinimapTerrain</strong>(true)</code></div>
301 */
CclSetMinimapTerrain(lua_State * l)302 static int CclSetMinimapTerrain(lua_State *l)
303 {
304 LuaCheckArgs(l, 1);
305 UI.Minimap.WithTerrain = LuaToBoolean(l, 1);
306 return 0;
307 }
308
309 /**
310 ** Activate map grid (true|false)
311 **
312 ** @param l Lua state.
313 **
314 ** @return 0 for success, 1 for wrong type;
315 */
CclSetEnableMapGrid(lua_State * l)316 static int CclSetEnableMapGrid(lua_State *l)
317 {
318 LuaCheckArgs(l, 1);
319 CViewport::EnableGrid(LuaToBoolean(l, 1));
320 return 0;
321 }
322
323 /**
324 ** Check if map grid is enabled
325 */
CclGetIsMapGridEnabled(lua_State * l)326 static int CclGetIsMapGridEnabled(lua_State *l)
327 {
328 LuaCheckArgs(l, 0);
329 lua_pushboolean(l, CViewport::isGridEnabled());
330 return 1;
331 }
332
333 /**
334 ** Select unit's field of view algorithm - ShadowCasting or SimpleRadial
335 **
336 ** @param l Lua state.
337 **
338 ** @return 0 for success, 1 for wrong type;
339 */
CclSetFieldOfViewType(lua_State * l)340 static int CclSetFieldOfViewType(lua_State *l)
341 {
342 LuaCheckArgs(l, 1);
343
344 FieldOfViewTypes new_type;
345 const char *type_name = LuaToString(l, 1);
346 if (!strcmp(type_name, "shadow-casting")) {
347 new_type = FieldOfViewTypes::cShadowCasting;
348 /// Tiled types of FOW don't work with shadow casting
349 if (FogOfWar.GetType() != FogOfWarTypes::cEnhanced) {
350 FogOfWar.SetType(FogOfWarTypes::cEnhanced);
351 }
352 } else if (!strcmp(type_name, "simple-radial")) {
353 new_type = FieldOfViewTypes::cSimpleRadial;
354 } else {
355 PrintFunction();
356 fprintf(stdout, "Accessible Field of View types: \"shadow-casting\", \"simple-radial\".\n");
357 return 1;
358 }
359 if (!IsNetworkGame()) {
360 FieldOfView.SetType(new_type);
361 } else {
362 NetworkSendExtendedCommand(ExtendedMessageFieldOfViewDB, int(new_type), 0, 0, 0, 0);
363 }
364 return 0;
365 }
366
367 /**
368 ** Get unit's field of view type - ShadowCasting or SimpleRadial
369 */
CclGetFieldOfViewType(lua_State * l)370 static int CclGetFieldOfViewType(lua_State *l)
371 {
372 LuaCheckArgs(l, 0);
373 lua_pushinteger(l, int(FieldOfView.GetType()));
374 return 1;
375 }
376
377 /**
378 ** Set opaque for the tile's terrain.
379 **
380 ** @param l Lua state.
381 **
382 ** @return 0 for success, 1 for wrong tile's terrain;
383 */
CclSetOpaqueFor(lua_State * l)384 static int CclSetOpaqueFor(lua_State *l)
385 {
386 uint16_t new_flag = 0;
387 const int args = lua_gettop(l);
388 if (args < 1) {
389 LuaError(l, "argument missed");
390 return 1;
391 }
392 for (int arg = 0; arg < args; ++arg) {
393 const char *flag_name = LuaToString(l, arg + 1);
394 if (!strcmp(flag_name, "wall")) {
395 new_flag |= MapFieldWall;
396 } else if (!strcmp(flag_name, "rock")) {
397 new_flag |= MapFieldRocks;
398 } else if (!strcmp(flag_name, "forest")) {
399 new_flag |= MapFieldForest;
400 } else {
401 PrintFunction();
402 fprintf(stdout, "Opaque can only be set for \"wall\", \"rock\" or \"forest\". \n");
403 return 1;
404 }
405 }
406 if (!IsNetworkGame()) {
407 FieldOfView.SetOpaqueFields(FieldOfView.GetOpaqueFields() | new_flag);
408 } else {
409 NetworkSendExtendedCommand(ExtendedMessageMapFieldsOpacityDB, 0,
410 FieldOfView.GetOpaqueFields() | new_flag, 0, 0, 0);
411 }
412 return 0;
413 }
414 /**
415 ** Check opacity for the tile's terrain.
416 **
417 ** @param l Lua state.
418 **
419 */
CclGetIsOpaqueFor(lua_State * l)420 static int CclGetIsOpaqueFor(lua_State *l)
421 {
422 LuaCheckArgs(l, 1);
423
424 uint16_t flagToCheck = 0;
425 const char *flag_name = LuaToString(l, 1);
426 if (!strcmp(flag_name, "wall")) {
427 flagToCheck = MapFieldWall;
428 } else if (!strcmp(flag_name, "rock")) {
429 flagToCheck = MapFieldRocks;
430 } else if (!strcmp(flag_name, "forest")) {
431 flagToCheck = MapFieldForest;
432 } else {
433 PrintFunction();
434 fprintf(stdout, "Opaque can only be checked for \"wall\", \"rock\" or \"forest\". \n");
435 }
436
437 lua_pushboolean(l, FieldOfView.GetOpaqueFields() & flagToCheck);
438 return 1;
439 }
440
CclRemoveOpaqueFor(lua_State * l)441 static int CclRemoveOpaqueFor(lua_State *l)
442 {
443 unsigned short new_flag = 0;
444 const int args = lua_gettop(l);
445 if (args < 1) {
446 LuaError(l, "argument missed");
447 return 1;
448 }
449 for (int arg = 0; arg < args; ++arg) {
450 const char *flag_name = LuaToString(l, arg + 1);
451 if (!strcmp(flag_name, "wall")) {
452 new_flag |= MapFieldWall;
453 } else if (!strcmp(flag_name, "rock")) {
454 new_flag |= MapFieldRocks;
455 } else if (!strcmp(flag_name, "forest")) {
456 new_flag |= MapFieldForest;
457 } else {
458 PrintFunction();
459 fprintf(stdout, "Opaque can only be removed for \"wall\", \"rock\" or \"forest\". \n");
460 return 1;
461 }
462 }
463 if (!IsNetworkGame()) {
464 FieldOfView.SetOpaqueFields(FieldOfView.GetOpaqueFields() & ~new_flag);
465 } else {
466 NetworkSendExtendedCommand(ExtendedMessageMapFieldsOpacityDB, 0,
467 FieldOfView.GetOpaqueFields() & ~new_flag, 0, 0, 0);
468 }
469 return 0;
470 }
471
472
473 /**
474 ** Select which type of Fog of War to use
475 **
476 ** @param l Lua state.
477 **
478 ** @return 0 for success, 1 for wrong type;
479 */
CclSetFogOfWarType(lua_State * l)480 static int CclSetFogOfWarType(lua_State *l)
481 {
482 LuaCheckArgs(l, 1);
483
484 FogOfWarTypes new_type;
485 const std::string type_name {LuaToString(l, 1)};
486 if (type_name == "tiled" || type_name == "fast") {
487 new_type = type_name == "tiled" ? FogOfWarTypes::cTiled : FogOfWarTypes::cTiledLegacy;
488 /// Tiled types of FOW don't work with shadow casting
489 if (FieldOfView.GetType() == FieldOfViewTypes::cShadowCasting) {
490 if (!IsNetworkGame()) {
491 FieldOfView.SetType(FieldOfViewTypes::cSimpleRadial);
492 } else {
493 NetworkSendExtendedCommand(ExtendedMessageFieldOfViewDB,
494 int(FieldOfViewTypes::cSimpleRadial), 0, 0, 0, 0);
495 }
496 }
497 } else if (type_name == "enhanced") {
498 new_type = FogOfWarTypes::cEnhanced;
499 } else {
500 PrintFunction();
501 fprintf(stdout, "Accessible Fog of War types: \"tiled\", \"enhanced\" and \"fast\".\n");
502 return 1;
503 }
504 FogOfWar.SetType(new_type);
505 return 0;
506 }
507
508 /**
509 ** Get Fog of War type - legacy or enhanced
510 */
CclGetFogOfWarType(lua_State * l)511 static int CclGetFogOfWarType(lua_State *l)
512 {
513 LuaCheckArgs(l, 0);
514 lua_pushinteger(l, int(FogOfWar.GetType()));
515 return 1;
516 }
517
518 /**
519 ** Set opacity (alpha) for different levels of fog of war - explored, revealed, unseen
520 **
521 ** @param l Lua state.
522 **
523 ** @return 0 for success, 1 for wrong type;
524 */
CclSetFogOfWarOpacityLevels(lua_State * l)525 static int CclSetFogOfWarOpacityLevels(lua_State *l)
526 {
527 LuaCheckArgs(l, 3);
528 const int explored = LuaToNumber(l, 1);
529 if (explored <= 0 || explored > 255) {
530 PrintFunction();
531 fprintf(stderr, "Invalid value (%d) of opacity for Explored tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", explored);
532 return 1;
533 }
534 const int revealed = LuaToNumber(l, 2);
535 if (revealed <= explored || revealed > 255) {
536 PrintFunction();
537 fprintf(stderr, "Invalid value (%d) of opacity for Revealed tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", revealed);
538 return 1;
539 }
540 const int unseen = LuaToNumber(l, 3);
541 if (unseen < revealed || unseen > 255) {
542 PrintFunction();
543 fprintf(stderr, "Invalid value (%d) of opacity for Unseen tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", unseen);
544 return 1;
545 }
546
547 FogOfWar.SetOpacityLevels(explored, revealed, unseen);
548
549 return 0;
550 }
551
552 /**
553 ** Set parameters for FOW blurer (radiuses and number of iterations)
554 **
555 ** @param l Lua state.
556 **
557 ** @return 0 for success, 1 for wrong type;
558 */
CclSetFogOfWarBlur(lua_State * l)559 static int CclSetFogOfWarBlur(lua_State *l)
560 {
561 LuaCheckArgs(l, 3);
562
563 const float radiusSimple = LuaToFloat(l, 1);
564 if (radiusSimple <= 0 ) {
565 PrintFunction();
566 fprintf(stdout, "Radius should be a positive float number. Blur is disabled.\n");
567 }
568
569 const float radiusBilinear = LuaToFloat(l, 2);
570 if (radiusBilinear <= 0 ) {
571 PrintFunction();
572 fprintf(stdout, "Radius should be a positive float number. Blur is disabled.\n");
573 }
574
575 const int iterations = LuaToNumber(l, 3);
576 if (iterations <= 0 ) {
577 PrintFunction();
578 fprintf(stdout, "Number of box blur iterations should be greater than 0. Blur is disabled.\n");
579 }
580 FogOfWar.InitBlurer(radiusSimple, radiusBilinear, iterations);
581 return 0;
582 }
583
584 /**
585 ** Activate FOW bilinear upscaling type (true|false)
586 **
587 ** @param l Lua state.
588 **
589 ** @return 0 for success, 1 for wrong type;
590 */
CclSetFogOfWarBilinear(lua_State * l)591 static int CclSetFogOfWarBilinear(lua_State *l)
592 {
593 LuaCheckArgs(l, 1);
594 FogOfWar.EnableBilinearUpscale(LuaToBoolean(l, 1));
595 return 0;
596 }
597
598 /**
599 ** Check if FOW bilinear upscaling enabled
600 */
CclGetIsFogOfWarBilinear(lua_State * l)601 static int CclGetIsFogOfWarBilinear(lua_State *l)
602 {
603 LuaCheckArgs(l, 0);
604 lua_pushboolean(l, FogOfWar.IsBilinearUpscaleEnabled());
605 return 1;
606 }
607
608 /**
609 ** <b>Description</b>
610 **
611 ** Set forest regeneration speed.
612 **
613 ** @param l Lua state.
614 **
615 ** @return Old speed
616 **
617 ** Example:
618 **
619 ** <div class="example"><code>-- No regeneration.
620 ** <strong>SetForestRegeneration</strong>(0)
621 ** -- Slow regeneration every 50 seconds
622 ** <strong>SetForestRegeneration</strong>(50)
623 ** -- Extremely slow regeneration every 1h of game time
624 ** <strong>SetForestRegeneration</strong>(3600)</code></div>
625 */
CclSetForestRegeneration(lua_State * l)626 static int CclSetForestRegeneration(lua_State *l)
627 {
628 LuaCheckArgs(l, 1);
629 int i = LuaToNumber(l, 1);
630 int frequency = 1;
631 if (i < 0) {
632 LuaError(l, "Regeneration speed should be >= 0\n");
633 }
634 while (i / frequency > 255) {
635 frequency++;
636 }
637 i = i / frequency;
638 const int old = ForestRegeneration * ForestRegenerationFrequency;
639 ForestRegeneration = i;
640 ForestRegenerationFrequency = frequency;
641
642 lua_pushnumber(l, old);
643 return 1;
644 }
645
646 /**
647 ** <b>Description</b>
648 **
649 ** Set Fog color.
650 **
651 ** @param l Lua state.
652 **
653 ** Example:
654 **
655 ** <div class="example"><code>-- Red fog of war
656 ** <strong>SetFogOfWarColor</strong>(128,0,0)</code></div>
657 */
CclSetFogOfWarColor(lua_State * l)658 static int CclSetFogOfWarColor(lua_State *l)
659 {
660 LuaCheckArgs(l, 3);
661 int r = LuaToNumber(l, 1);
662 int g = LuaToNumber(l, 2);
663 int b = LuaToNumber(l, 3);
664
665 if ((r < 0 || r > 255) ||
666 (g < 0 || g > 255) ||
667 (b < 0 || b > 255)) {
668 LuaError(l, "Arguments must be in the range 0-255");
669 }
670
671 FogOfWar.SetFogColor(r, g, b);
672
673 return 0;
674 }
675
676 /**
677 ** Define Fog graphics
678 **
679 ** @param l Lua state.
680 */
CclSetFogOfWarGraphics(lua_State * l)681 static int CclSetFogOfWarGraphics(lua_State *l)
682 {
683 std::string FogGraphicFile;
684
685 LuaCheckArgs(l, 1);
686 FogGraphicFile = LuaToString(l, 1);
687 CFogOfWar::SetTiledFogGraphic(FogGraphicFile);
688
689 return 0;
690 }
691
692
693 /**
694 ** Set opacity (alpha) for different levels of fog of war - explored, revealed, unexplored for mini map
695 **
696 ** @param l Lua state.
697 **
698 ** @return 0 for success, 1 for wrong type;
699 */
CclSetMMFogOfWarOpacityLevels(lua_State * l)700 static int CclSetMMFogOfWarOpacityLevels(lua_State *l)
701 {
702 LuaCheckArgs(l, 3);
703 const int explored = LuaToNumber(l, 1);
704 if (explored <= 0 || explored > 255) {
705 PrintFunction();
706 fprintf(stderr, "Invalid value (%d) of opacity for Minimap's Explored tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", explored);
707 return 1;
708 }
709 const int revealed = LuaToNumber(l, 2);
710 if (revealed <= explored || revealed > 255) {
711 PrintFunction();
712 fprintf(stderr, "Invalid value (%d) of opacity for Minimap's Revealed tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", revealed);
713 return 1;
714 }
715 const int unseen = LuaToNumber(l, 3);
716 if (unseen < revealed || unseen > 255) {
717 PrintFunction();
718 fprintf(stderr, "Invalid value (%d) of opacity for Minimap's Unseen tiles. Acceptable range is [0 <= Explored <= Known <= Hidden <= 255].\n", unseen);
719 return 1;
720 }
721
722 UI.Minimap.SetFogOpacityLevels(explored, revealed, unseen);
723
724 return 0;
725 }
726
727 /**
728 ** <b>Description</b>
729 **
730 ** Define size in pixels (x,y) of a tile in this game
731 **
732 ** @param l Lua state.
733 **
734 ** Example:
735 **
736 ** <div class="example"><code><strong>SetTileSize</strong>(32,32)</code></div>
737 */
CclSetTileSize(lua_State * l)738 static int CclSetTileSize(lua_State *l)
739 {
740 LuaCheckArgs(l, 2);
741 PixelTileSize.x = LuaToNumber(l, 1);
742 PixelTileSize.y = LuaToNumber(l, 2);
743 return 0;
744 }
745
746 /**
747 ** Set a tile
748 **
749 ** @param tileIndex Tile number
750 ** @param pos coordinate
751 ** @param value Value of the tile
752 */
SetTile(unsigned int tileIndex,const Vec2i & pos,int value)753 void SetTile(unsigned int tileIndex, const Vec2i &pos, int value)
754 {
755 if (!Map.Info.IsPointOnMap(pos)) {
756 fprintf(stderr, "Invalid map coordonate : (%d, %d)\n", pos.x, pos.y);
757 return;
758 }
759 if (Map.Tileset->getTileCount() <= tileIndex) {
760 fprintf(stderr, "Invalid tile number: %u\n", tileIndex);
761 return;
762 }
763 if (value < 0 || value >= 256) {
764 fprintf(stderr, "Invalid tile number: %u\n", tileIndex);
765 return;
766 }
767
768 if (Map.Fields) {
769 CMapField &mf = *Map.Field(pos);
770
771 mf.setTileIndex(*Map.Tileset, tileIndex, value);
772 }
773 }
774
775 /**
776 ** Define the type of each player available for the map
777 **
778 ** @param l Lua state.
779 */
CclDefinePlayerTypes(lua_State * l)780 static int CclDefinePlayerTypes(lua_State *l)
781 {
782 int numplayers = lua_gettop(l); /* Number of players == number of arguments */
783 if (numplayers < 2) {
784 LuaError(l, "Not enough players");
785 }
786
787 for (int i = 0; i < numplayers && i < PlayerMax; ++i) {
788 if (lua_isnil(l, i + 1)) {
789 numplayers = i;
790 break;
791 }
792 const char *type = LuaToString(l, i + 1);
793 if (!strcmp(type, "neutral")) {
794 Map.Info.PlayerType[i] = PlayerNeutral;
795 } else if (!strcmp(type, "nobody")) {
796 Map.Info.PlayerType[i] = PlayerNobody;
797 } else if (!strcmp(type, "computer")) {
798 Map.Info.PlayerType[i] = PlayerComputer;
799 } else if (!strcmp(type, "person")) {
800 Map.Info.PlayerType[i] = PlayerPerson;
801 } else if (!strcmp(type, "rescue-passive")) {
802 Map.Info.PlayerType[i] = PlayerRescuePassive;
803 } else if (!strcmp(type, "rescue-active")) {
804 Map.Info.PlayerType[i] = PlayerRescueActive;
805 } else {
806 LuaError(l, "Unsupported tag: %s" _C_ type);
807 }
808 }
809 for (int i = numplayers; i < PlayerMax - 1; ++i) {
810 Map.Info.PlayerType[i] = PlayerNobody;
811 }
812 if (numplayers < PlayerMax) {
813 Map.Info.PlayerType[PlayerMax - 1] = PlayerNeutral;
814 }
815 return 0;
816 }
817
818 /**
819 ** Load the lua file which will define the tile models
820 **
821 ** @param l Lua state.
822 */
CclLoadTileModels(lua_State * l)823 static int CclLoadTileModels(lua_State *l)
824 {
825 if (lua_gettop(l) != 1) {
826 LuaError(l, "incorrect argument");
827 }
828 Map.TileModelsFileName = LuaToString(l, 1);
829 const std::string filename = LibraryFileName(Map.TileModelsFileName.c_str());
830 if (LuaLoadFile(filename) == -1) {
831 DebugPrint("Load failed: %s\n" _C_ filename.c_str());
832 }
833 return 0;
834 }
835
836 /**
837 ** Define tileset
838 **
839 ** @param l Lua state.
840 */
CclDefineTileset(lua_State * l)841 static int CclDefineTileset(lua_State *l)
842 {
843 Map.Tileset->parse(l);
844
845 // Load and prepare the tileset
846 PixelTileSize = Map.Tileset->getPixelTileSize();
847
848 ShowLoadProgress(_("Tileset '%s'"), Map.Tileset->ImageFile.c_str());
849 Map.TileGraphic = CGraphic::New(Map.Tileset->ImageFile, PixelTileSize.x, PixelTileSize.y);
850 Map.TileGraphic->Load();
851 return 0;
852 }
853 /**
854 ** Build tileset tables like humanWallTable or mixedLookupTable
855 **
856 ** Called after DefineTileset and only for tilesets that have wall,
857 ** trees and rocks. This function will be deleted when removing
858 ** support of walls and alike in the tileset.
859 */
CclBuildTilesetTables(lua_State * l)860 static int CclBuildTilesetTables(lua_State *l)
861 {
862 LuaCheckArgs(l, 0);
863
864 Map.Tileset->buildTable(l);
865 return 0;
866 }
867 /**
868 ** Set the flags like "water" for a tile of a tileset
869 **
870 ** @param l Lua state.
871 */
CclSetTileFlags(lua_State * l)872 static int CclSetTileFlags(lua_State *l)
873 {
874 if (lua_gettop(l) < 2) {
875 LuaError(l, "No flags defined");
876 }
877 const unsigned int tilenumber = LuaToNumber(l, 1);
878
879 if (tilenumber >= Map.Tileset->tiles.size()) {
880 LuaError(l, "Accessed a tile that's not defined");
881 }
882 int j = 0;
883 int flags = 0;
884
885 unsigned char newBase = Map.Tileset->parseTilesetTileFlags(l, &flags, &j);
886 Map.Tileset->tiles[tilenumber].flag = flags;
887 if (newBase) {
888 Map.Tileset->tiles[tilenumber].tileinfo.BaseTerrain = newBase;
889 }
890 return 0;
891 }
892
893 /**
894 ** Get the name of the terrain of the tile.
895 **
896 ** @param l Lua state.
897 **
898 ** @return The name of the terrain of the tile.
899 */
CclGetTileTerrainName(lua_State * l)900 static int CclGetTileTerrainName(lua_State *l)
901 {
902 LuaCheckArgs(l, 2);
903
904 const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2));
905
906 const CMapField &mf = *Map.Field(pos);
907 const CTileset &tileset = *Map.Tileset;
908 const int index = tileset.findTileIndexByTile(mf.getGraphicTile());
909 Assert(index != -1);
910 const int baseTerrainIdx = tileset.tiles[index].tileinfo.BaseTerrain;
911
912 lua_pushstring(l, tileset.getTerrainName(baseTerrainIdx).c_str());
913 return 1;
914 }
915
916 /**
917 ** Check if the tile's terrain has a particular flag.
918 **
919 ** @param l Lua state.
920 **
921 ** @return True if has the flag, false if not.
922 */
CclGetTileTerrainHasFlag(lua_State * l)923 static int CclGetTileTerrainHasFlag(lua_State *l)
924 {
925 LuaCheckArgs(l, 3);
926
927 const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2));
928
929 unsigned short flag = 0;
930 const char *flag_name = LuaToString(l, 3);
931 if (!strcmp(flag_name, "opaque")) {
932 flag = MapFieldOpaque;
933 } else if (!strcmp(flag_name, "water")) {
934 flag = MapFieldWaterAllowed;
935 } else if (!strcmp(flag_name, "land")) {
936 flag = MapFieldLandAllowed;
937 } else if (!strcmp(flag_name, "coast")) {
938 flag = MapFieldCoastAllowed;
939 } else if (!strcmp(flag_name, "no-building")) {
940 flag = MapFieldNoBuilding;
941 } else if (!strcmp(flag_name, "unpassable")) {
942 flag = MapFieldUnpassable;
943 } else if (!strcmp(flag_name, "wall")) {
944 flag = MapFieldWall;
945 } else if (!strcmp(flag_name, "rock")) {
946 flag = MapFieldRocks;
947 } else if (!strcmp(flag_name, "forest")) {
948 flag = MapFieldForest;
949 }
950
951 const CMapField &mf = *Map.Field(pos);
952
953 if (mf.getFlag() & flag) {
954 lua_pushboolean(l, 1);
955 } else {
956 lua_pushboolean(l, 0);
957 }
958
959 return 1;
960 }
961
962 /**
963 ** Enable walls enabled for single player games (for debug purposes)
964 **
965 ** @param l Lua state.
966 **
967 ** @return 0 for success, 1 for wrong type;
968 */
CclSetEnableWallsForSP(lua_State * l)969 static int CclSetEnableWallsForSP(lua_State *l)
970 {
971 LuaCheckArgs(l, 1);
972 EnableWallsInSinglePlayer = LuaToBoolean(l, 1);
973 return 0;
974 }
975
976 /**
977 ** Check if walls enabled for single player games (for debug purposes)
978 */
CclIsWallsEnabledForSP(lua_State * l)979 static int CclIsWallsEnabledForSP(lua_State *l)
980 {
981 LuaCheckArgs(l, 0);
982 lua_pushboolean(l, EnableWallsInSinglePlayer);
983 return 1;
984 }
985
986 /**
987 ** Check if network game was created on this PC
988 */
CclGetIsGameHoster(lua_State * l)989 static int CclGetIsGameHoster(lua_State *l)
990 {
991 LuaCheckArgs(l, 0);
992 lua_pushboolean(l, (ThisPlayer->Index == Hosts[0].PlyNr) ? true : false);
993 return 1;
994 }
995
996 /**
997 ** Register CCL features for map.
998 */
MapCclRegister()999 void MapCclRegister()
1000 {
1001 lua_register(Lua, "StratagusMap", CclStratagusMap);
1002 lua_register(Lua, "RevealMap", CclRevealMap);
1003 lua_register(Lua, "CenterMap", CclCenterMap);
1004 lua_register(Lua, "SetStartView", CclSetStartView);
1005 lua_register(Lua, "ShowMapLocation", CclShowMapLocation);
1006
1007 lua_register(Lua, "SetTileSize", CclSetTileSize);
1008
1009 lua_register(Lua, "SetFogOfWar", CclSetFogOfWar);
1010 lua_register(Lua, "GetFogOfWar", CclGetFogOfWar);
1011 lua_register(Lua, "SetMinimapTerrain", CclSetMinimapTerrain);
1012
1013 lua_register(Lua, "SetEnableMapGrid", CclSetEnableMapGrid);
1014 lua_register(Lua, "GetIsMapGridEnabled", CclGetIsMapGridEnabled);
1015
1016 lua_register(Lua, "SetFieldOfViewType", CclSetFieldOfViewType);
1017 lua_register(Lua, "GetFieldOfViewType", CclGetFieldOfViewType);
1018 lua_register(Lua, "SetOpaqueFor", CclSetOpaqueFor);
1019 lua_register(Lua, "RemoveOpaqueFor", CclRemoveOpaqueFor);
1020 lua_register(Lua, "GetIsOpaqueFor", CclGetIsOpaqueFor);
1021
1022 lua_register(Lua, "SetFogOfWarType", CclSetFogOfWarType);
1023 lua_register(Lua, "GetFogOfWarType", CclGetFogOfWarType);
1024
1025 lua_register(Lua, "SetFogOfWarOpacityLevels", CclSetFogOfWarOpacityLevels);
1026 lua_register(Lua, "SetFogOfWarBlur", CclSetFogOfWarBlur);
1027 lua_register(Lua, "SetFogOfWarBilinear", CclSetFogOfWarBilinear);
1028 lua_register(Lua, "GetIsFogOfWarBilinear", CclGetIsFogOfWarBilinear);
1029
1030 lua_register(Lua, "SetFogOfWarGraphics", CclSetFogOfWarGraphics);
1031 lua_register(Lua, "SetFogOfWarColor", CclSetFogOfWarColor);
1032
1033 lua_register(Lua, "SetMMFogOfWarOpacityLevels", CclSetMMFogOfWarOpacityLevels);
1034
1035 lua_register(Lua, "SetForestRegeneration", CclSetForestRegeneration);
1036
1037 lua_register(Lua, "LoadTileModels", CclLoadTileModels);
1038 lua_register(Lua, "DefinePlayerTypes", CclDefinePlayerTypes);
1039
1040 lua_register(Lua, "DefineTileset", CclDefineTileset);
1041 lua_register(Lua, "SetTileFlags", CclSetTileFlags);
1042 lua_register(Lua, "BuildTilesetTables", CclBuildTilesetTables);
1043
1044 lua_register(Lua, "GetTileTerrainName", CclGetTileTerrainName);
1045 lua_register(Lua, "GetTileTerrainHasFlag", CclGetTileTerrainHasFlag);
1046
1047 lua_register(Lua, "SetEnableWallsForSP", CclSetEnableWallsForSP);
1048 lua_register(Lua, "GetIsWallsEnabledForSP", CclIsWallsEnabledForSP);
1049
1050 lua_register(Lua, "GetIsGameHoster", CclGetIsGameHoster);
1051
1052 }
1053
1054 //@}
1055