// _________ __ __ // / _____// |_____________ _/ |______ ____ __ __ ______ // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/ // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ | // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ > // \/ \/ \//_____/ \/ // ______________________ ______________________ // T H E W A R B E G I N S // Stratagus - A free fantasy real time strategy game engine // /**@name script_map.cpp - The map ccl functions. */ // // (c) Copyright 1999-2005 by Lutz Sammer and Jimmy Salmon // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; only version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. // //@{ /*---------------------------------------------------------------------------- -- Includes ----------------------------------------------------------------------------*/ #include "stratagus.h" #include "map.h" #include "iolib.h" #include "script.h" #include "tileset.h" #include "translate.h" #include "ui.h" #include "unit.h" #include "version.h" #include "video.h" /*---------------------------------------------------------------------------- -- Functions ----------------------------------------------------------------------------*/ /** ** Parse a map. ** ** @param l Lua state. */ static int CclStratagusMap(lua_State *l) { int args = lua_gettop(l); for (int j = 0; j < args; ++j) { const char *value = LuaToString(l, j + 1); ++j; if (!strcmp(value, "version")) { char buf[32]; const char *version = LuaToString(l, j + 1); strncpy(buf, VERSION, sizeof(buf)); if (strcmp(buf, version)) { fprintf(stderr, "Warning not saved with this version.\n"); } } else if (!strcmp(value, "uid")) { Map.Info.MapUID = LuaToNumber(l, j + 1); } else if (!strcmp(value, "description")) { Map.Info.Description = LuaToString(l, j + 1); } else if (!strcmp(value, "the-map")) { if (!lua_istable(l, j + 1)) { LuaError(l, "incorrect argument"); } int subargs = lua_rawlen(l, j + 1); for (int k = 0; k < subargs; ++k) { const char *value = LuaToString(l, j + 1, k + 1); ++k; if (!strcmp(value, "size")) { lua_rawgeti(l, j + 1, k + 1); CclGetPos(l, &Map.Info.MapWidth, &Map.Info.MapHeight); lua_pop(l, 1); delete[] Map.Fields; Map.Fields = new CMapField[Map.Info.MapWidth * Map.Info.MapHeight]; // FIXME: this should be CreateMap or InitMap? } else if (!strcmp(value, "fog-of-war")) { Map.NoFogOfWar = false; --k; } else if (!strcmp(value, "no-fog-of-war")) { Map.NoFogOfWar = true; --k; } else if (!strcmp(value, "filename")) { Map.Info.Filename = LuaToString(l, j + 1, k + 1); } else if (!strcmp(value, "map-fields")) { lua_rawgeti(l, j + 1, k + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } const int subsubargs = lua_rawlen(l, -1); if (subsubargs != Map.Info.MapWidth * Map.Info.MapHeight) { fprintf(stderr, "Wrong tile table length: %d\n", subsubargs); } for (int i = 0; i < subsubargs; ++i) { lua_rawgeti(l, -1, i + 1); if (!lua_istable(l, -1)) { LuaError(l, "incorrect argument"); } Map.Fields[i].parse(l); lua_pop(l, 1); } lua_pop(l, 1); } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } } else { LuaError(l, "Unsupported tag: %s" _C_ value); } } return 0; } /** ** Reveal the complete map. ** ** @param l Lua state. */ static int CclRevealMap(lua_State *l) { LuaCheckArgs(l, 0); if (CclInConfigFile || !Map.Fields) { FlagRevealMap = 1; } else { Map.Reveal(); } return 0; } /** ** Center the map. ** ** @param l Lua state. */ static int CclCenterMap(lua_State *l) { LuaCheckArgs(l, 2); const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2)); UI.SelectedViewport->Center(Map.TilePosToMapPixelPos_Center(pos)); return 0; } /** ** Define the starting viewpoint for a given player. ** ** @param l Lua state. */ static int CclSetStartView(lua_State *l) { LuaCheckArgs(l, 3); const int p = LuaToNumber(l, 1); Players[p].StartPos.x = LuaToNumber(l, 2); Players[p].StartPos.y = LuaToNumber(l, 3); return 0; } /** ** Show Map Location ** ** @param l Lua state. */ static int CclShowMapLocation(lua_State *l) { // Put a unit on map, use its properties, except for // what is listed below LuaCheckArgs(l, 4); const char *unitname = LuaToString(l, 5); CUnitType *unitType = UnitTypeByIdent(unitname); if (!unitType) { DebugPrint("Unable to find UnitType '%s'" _C_ unitname); return 0; } CUnit *target = MakeUnit(*unitType, ThisPlayer); if (target != NULL) { target->Variable[HP_INDEX].Value = 0; target->tilePos.x = LuaToNumber(l, 1); target->tilePos.y = LuaToNumber(l, 2); target->TTL = GameCycle + LuaToNumber(l, 4); target->CurrentSightRange = LuaToNumber(l, 3); MapMarkUnitSight(*target); } else { DebugPrint("Unable to allocate Unit"); } return 0; } /** ** Set fog of war on/off. ** ** @param l Lua state. */ static int CclSetFogOfWar(lua_State *l) { LuaCheckArgs(l, 1); Map.NoFogOfWar = !LuaToBoolean(l, 1); if (!CclInConfigFile && Map.Fields) { UpdateFogOfWarChange(); // FIXME: save setting in replay log //CommandLog("input", NoUnitP, FlushCommands, -1, -1, NoUnitP, "fow off", -1); } return 0; } static int CclGetFogOfWar(lua_State *l) { LuaCheckArgs(l, 0); lua_pushboolean(l, !Map.NoFogOfWar); return 1; } /** ** Enable display of terrain in minimap. ** ** @param l Lua state. */ static int CclSetMinimapTerrain(lua_State *l) { LuaCheckArgs(l, 1); UI.Minimap.WithTerrain = LuaToBoolean(l, 1); return 0; } /** ** Fog of war opacity. ** ** @param l Lua state. */ static int CclSetFogOfWarOpacity(lua_State *l) { LuaCheckArgs(l, 1); int i = LuaToNumber(l, 1); if (i < 0 || i > 255) { PrintFunction(); fprintf(stdout, "Opacity should be 0 - 256\n"); i = 100; } FogOfWarOpacity = i; if (!CclInConfigFile) { Map.Init(); } return 0; } /** ** Set forest regeneration speed. ** ** @param l Lua state. ** ** @return Old speed */ static int CclSetForestRegeneration(lua_State *l) { LuaCheckArgs(l, 1); int i = LuaToNumber(l, 1); if (i < 0 || i > 255) { PrintFunction(); fprintf(stdout, "Regeneration speed should be 0 - 255\n"); i = 100; } const int old = ForestRegeneration; ForestRegeneration = i; lua_pushnumber(l, old); return 1; } /** ** Set Fog color. ** ** @param l Lua state. */ static int CclSetFogOfWarColor(lua_State *l) { LuaCheckArgs(l, 3); int r = LuaToNumber(l, 1); int g = LuaToNumber(l, 2); int b = LuaToNumber(l, 3); if ((r < 0 || r > 255) || (g < 0 || g > 255) || (b < 0 || b > 255)) { LuaError(l, "Arguments must be in the range 0-255"); } FogOfWarColor.R = r; FogOfWarColor.G = g; FogOfWarColor.B = b; return 0; } /** ** Define Fog graphics ** ** @param l Lua state. */ static int CclSetFogOfWarGraphics(lua_State *l) { std::string FogGraphicFile; LuaCheckArgs(l, 1); FogGraphicFile = LuaToString(l, 1); if (CMap::FogGraphic) { CGraphic::Free(CMap::FogGraphic); } CMap::FogGraphic = CGraphic::New(FogGraphicFile, PixelTileSize.x, PixelTileSize.y); return 0; } /** ** Set a tile ** ** @param tileIndex Tile number ** @param pos coordinate ** @param value Value of the tile */ void SetTile(unsigned int tileIndex, const Vec2i &pos, int value) { if (!Map.Info.IsPointOnMap(pos)) { fprintf(stderr, "Invalid map coordonate : (%d, %d)\n", pos.x, pos.y); return; } if (Map.Tileset->getTileCount() <= tileIndex) { fprintf(stderr, "Invalid tile number: %d\n", tileIndex); return; } if (value < 0 || value >= 256) { fprintf(stderr, "Invalid tile number: %d\n", tileIndex); return; } if (Map.Fields) { CMapField &mf = *Map.Field(pos); mf.setTileIndex(*Map.Tileset, tileIndex, value); } } /** ** Define the type of each player available for the map ** ** @param l Lua state. */ static int CclDefinePlayerTypes(lua_State *l) { int numplayers = lua_gettop(l); /* Number of players == number of arguments */ if (numplayers < 2) { LuaError(l, "Not enough players"); } for (int i = 0; i < numplayers && i < PlayerMax; ++i) { if (lua_isnil(l, i + 1)) { numplayers = i; break; } const char *type = LuaToString(l, i + 1); if (!strcmp(type, "neutral")) { Map.Info.PlayerType[i] = PlayerNeutral; } else if (!strcmp(type, "nobody")) { Map.Info.PlayerType[i] = PlayerNobody; } else if (!strcmp(type, "computer")) { Map.Info.PlayerType[i] = PlayerComputer; } else if (!strcmp(type, "person")) { Map.Info.PlayerType[i] = PlayerPerson; } else if (!strcmp(type, "rescue-passive")) { Map.Info.PlayerType[i] = PlayerRescuePassive; } else if (!strcmp(type, "rescue-active")) { Map.Info.PlayerType[i] = PlayerRescueActive; } else { LuaError(l, "Unsupported tag: %s" _C_ type); } } for (int i = numplayers; i < PlayerMax - 1; ++i) { Map.Info.PlayerType[i] = PlayerNobody; } if (numplayers < PlayerMax) { Map.Info.PlayerType[PlayerMax - 1] = PlayerNeutral; } return 0; } /** ** Load the lua file which will define the tile models ** ** @param l Lua state. */ static int CclLoadTileModels(lua_State *l) { if (lua_gettop(l) != 1) { LuaError(l, "incorrect argument"); } Map.TileModelsFileName = LuaToString(l, 1); const std::string filename = LibraryFileName(Map.TileModelsFileName.c_str()); if (LuaLoadFile(filename) == -1) { DebugPrint("Load failed: %s\n" _C_ filename.c_str()); } return 0; } /** ** Define tileset ** ** @param l Lua state. */ static int CclDefineTileset(lua_State *l) { Map.Tileset->parse(l); // Load and prepare the tileset PixelTileSize = Map.Tileset->getPixelTileSize(); ShowLoadProgress(_("Tileset `%s'"), Map.Tileset->ImageFile.c_str()); Map.TileGraphic = CGraphic::New(Map.Tileset->ImageFile, PixelTileSize.x, PixelTileSize.y); Map.TileGraphic->Load(); return 0; } /** ** Build tileset tables like humanWallTable or mixedLookupTable ** ** Called after DefineTileset and only for tilesets that have wall, ** trees and rocks. This function will be deleted when removing ** support of walls and alike in the tileset. */ static int CclBuildTilesetTables(lua_State *l) { LuaCheckArgs(l, 0); Map.Tileset->buildTable(l); return 0; } /** ** Set the flags like "water" for a tile of a tileset ** ** @param l Lua state. */ static int CclSetTileFlags(lua_State *l) { if (lua_gettop(l) < 2) { LuaError(l, "No flags defined"); } const unsigned int tilenumber = LuaToNumber(l, 1); if (tilenumber >= Map.Tileset->tiles.size()) { LuaError(l, "Accessed a tile that's not defined"); } int j = 0; int flags = 0; ParseTilesetTileFlags(l, &flags, &j); Map.Tileset->tiles[tilenumber].flag = flags; return 0; } //Wyrmgus start /** ** Get the name of the terrain of the tile. ** ** @param l Lua state. ** ** @return The name of the terrain of the tile. */ static int CclGetTileTerrainName(lua_State *l) { LuaCheckArgs(l, 2); const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2)); const CMapField &mf = *Map.Field(pos); const CTileset &tileset = *Map.Tileset; const int index = tileset.findTileIndexByTile(mf.getGraphicTile()); Assert(index != -1); const int baseTerrainIdx = tileset.tiles[index].tileinfo.BaseTerrain; // const char *baseTerrainStr = tileset.getTerrainName(baseTerrainIdx).c_str(); lua_pushstring(l, tileset.getTerrainName(baseTerrainIdx).c_str()); return 1; } /** ** Check if the tile's terrain has a particular flag. ** ** @param l Lua state. ** ** @return True if has the flag, false if not. */ static int CclGetTileTerrainHasFlag(lua_State *l) { LuaCheckArgs(l, 3); const Vec2i pos(LuaToNumber(l, 1), LuaToNumber(l, 2)); unsigned short flag = 0; const char *flag_name = LuaToString(l, 3); if (!strcmp(flag_name, "water")) { flag = MapFieldWaterAllowed; } else if (!strcmp(flag_name, "land")) { flag = MapFieldLandAllowed; } else if (!strcmp(flag_name, "coast")) { flag = MapFieldCoastAllowed; } else if (!strcmp(flag_name, "no-building")) { flag = MapFieldNoBuilding; } else if (!strcmp(flag_name, "unpassable")) { flag = MapFieldUnpassable; } else if (!strcmp(flag_name, "wall")) { flag = MapFieldWall; } else if (!strcmp(flag_name, "rock")) { flag = MapFieldRocks; } else if (!strcmp(flag_name, "forest")) { flag = MapFieldForest; } const CMapField &mf = *Map.Field(pos); if (mf.getFlag() & flag) { lua_pushboolean(l, 1); } else { lua_pushboolean(l, 0); } return 1; } //Wyrmgus end /** ** Register CCL features for map. */ void MapCclRegister() { lua_register(Lua, "StratagusMap", CclStratagusMap); lua_register(Lua, "RevealMap", CclRevealMap); lua_register(Lua, "CenterMap", CclCenterMap); lua_register(Lua, "SetStartView", CclSetStartView); lua_register(Lua, "ShowMapLocation", CclShowMapLocation); lua_register(Lua, "SetFogOfWar", CclSetFogOfWar); lua_register(Lua, "GetFogOfWar", CclGetFogOfWar); lua_register(Lua, "SetMinimapTerrain", CclSetMinimapTerrain); lua_register(Lua, "SetFogOfWarGraphics", CclSetFogOfWarGraphics); lua_register(Lua, "SetFogOfWarOpacity", CclSetFogOfWarOpacity); lua_register(Lua, "SetFogOfWarColor", CclSetFogOfWarColor); lua_register(Lua, "SetForestRegeneration", CclSetForestRegeneration); lua_register(Lua, "LoadTileModels", CclLoadTileModels); lua_register(Lua, "DefinePlayerTypes", CclDefinePlayerTypes); lua_register(Lua, "DefineTileset", CclDefineTileset); lua_register(Lua, "SetTileFlags", CclSetTileFlags); lua_register(Lua, "BuildTilesetTables", CclBuildTilesetTables); //Wyrmgus start lua_register(Lua, "GetTileTerrainName", CclGetTileTerrainName); lua_register(Lua, "GetTileTerrainHasFlag", CclGetTileTerrainHasFlag); //Wyrmgus end } //@}