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 mapfield.cpp - The map field. */
12 //
13 // (c) Copyright 2013 by Joris Dauphin
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 "tile.h"
39
40 #include "fov.h"
41 #include "iolib.h"
42 #include "map.h"
43 #include "player.h"
44 #include "script.h"
45 #include "tileset.h"
46 #include "unit.h"
47 #include "unit_manager.h"
48
CMapField()49 CMapField::CMapField() :
50 #ifdef DEBUG
51 tilesetTile(0),
52 #endif
53 tile(0),
54 Flags(0),
55 cost(0),
56 Value(0),
57 UnitCache()
58 {}
59
IsTerrainResourceOnMap(int resource) const60 bool CMapField::IsTerrainResourceOnMap(int resource) const
61 {
62 // TODO: Hard coded stuff.
63 if (resource == WoodCost) {
64 return this->ForestOnMap();
65 }
66 return false;
67 }
68
IsTerrainResourceOnMap() const69 bool CMapField::IsTerrainResourceOnMap() const
70 {
71 for (int i = 0; i != MaxCosts; ++i) {
72 if (IsTerrainResourceOnMap(i)) {
73 return true;
74 }
75 }
76 return false;
77 }
78
setTileIndex(const CTileset & tileset,unsigned int tileIndex,int value)79 void CMapField::setTileIndex(const CTileset &tileset, unsigned int tileIndex, int value)
80 {
81 const CTile &tile = tileset.tiles[tileIndex];
82 this->tile = tile.tile;
83 this->Value = value;
84 #if 0
85 this->Flags = tile.flag;
86 #else
87 this->Flags &= ~(MapFieldOpaque | MapFieldHuman | MapFieldLandAllowed | MapFieldCoastAllowed |
88 MapFieldWaterAllowed | MapFieldNoBuilding | MapFieldUnpassable |
89 MapFieldWall | MapFieldRocks | MapFieldForest);
90 this->Flags |= tile.flag;
91 #endif
92 this->cost = 1 << (tile.flag & MapFieldSpeedMask);
93 #ifdef DEBUG
94 this->tilesetTile = tileIndex;
95 #endif
96 }
97
Save(CFile & file) const98 void CMapField::Save(CFile &file) const
99 {
100 file.printf(" {%3d, %3d, %2d, %2d", tile, playerInfo.SeenTile, Value, cost);
101 for (int i = 0; i != PlayerMax; ++i) {
102 if (playerInfo.Visible[i] == 1) {
103 file.printf(", \"explored\", %d", i);
104 }
105 }
106 if (Flags & MapFieldOpaque) {
107 file.printf(", \"opaque\"");
108 }
109 if (Flags & MapFieldHuman) {
110 file.printf(", \"human\"");
111 }
112 if (Flags & MapFieldLandAllowed) {
113 file.printf(", \"land\"");
114 }
115 if (Flags & MapFieldCoastAllowed) {
116 file.printf(", \"coast\"");
117 }
118 if (Flags & MapFieldWaterAllowed) {
119 file.printf(", \"water\"");
120 }
121 if (Flags & MapFieldNoBuilding) {
122 file.printf(", \"mud\"");
123 }
124 if (Flags & MapFieldUnpassable) {
125 file.printf(", \"block\"");
126 }
127 if (Flags & MapFieldWall) {
128 file.printf(", \"wall\"");
129 }
130 if (Flags & MapFieldRocks) {
131 file.printf(", \"rock\"");
132 }
133 if (Flags & MapFieldForest) {
134 file.printf(", \"wood\"");
135 }
136 #if 1
137 // Not Required for save
138 // These are required for now, UnitType::FieldFlags is 0 until
139 // UpdateStats is called which is after the game is loaded
140 if (Flags & MapFieldLandUnit) {
141 file.printf(", \"ground\"");
142 }
143 if (Flags & MapFieldAirUnit) {
144 file.printf(", \"air\"");
145 }
146 if (Flags & MapFieldSeaUnit) {
147 file.printf(", \"sea\"");
148 }
149 if (Flags & MapFieldBuilding) {
150 file.printf(", \"building\"");
151 }
152 #endif
153 file.printf("}");
154 }
155
156
parse(lua_State * l)157 void CMapField::parse(lua_State *l)
158 {
159 if (!lua_istable(l, -1)) {
160 LuaError(l, "incorrect argument");
161 }
162 const int len = lua_rawlen(l, -1);
163 if (len < 4) {
164 LuaError(l, "incorrect argument");
165 }
166
167 this->tile = LuaToNumber(l, -1, 1);
168 this->playerInfo.SeenTile = LuaToNumber(l, -1, 2);
169 this->Value = LuaToNumber(l, -1, 3);
170 this->cost = LuaToNumber(l, -1, 4);
171
172 for (int j = 4; j < len; ++j) {
173 const char *value = LuaToString(l, -1, j + 1);
174
175 if (!strcmp(value, "explored")) {
176 ++j;
177 this->playerInfo.Visible[LuaToNumber(l, -1, j + 1)] = 1;
178 } else if (!strcmp(value, "opaque")) {
179 this->Flags |= MapFieldOpaque;
180 } else if (!strcmp(value, "human")) {
181 this->Flags |= MapFieldHuman;
182 } else if (!strcmp(value, "land")) {
183 this->Flags |= MapFieldLandAllowed;
184 } else if (!strcmp(value, "coast")) {
185 this->Flags |= MapFieldCoastAllowed;
186 } else if (!strcmp(value, "water")) {
187 this->Flags |= MapFieldWaterAllowed;
188 } else if (!strcmp(value, "mud")) {
189 this->Flags |= MapFieldNoBuilding;
190 } else if (!strcmp(value, "block")) {
191 this->Flags |= MapFieldUnpassable;
192 } else if (!strcmp(value, "wall")) {
193 this->Flags |= MapFieldWall;
194 } else if (!strcmp(value, "rock")) {
195 this->Flags |= MapFieldRocks;
196 } else if (!strcmp(value, "wood")) {
197 this->Flags |= MapFieldForest;
198 } else if (!strcmp(value, "ground")) {
199 this->Flags |= MapFieldLandUnit;
200 } else if (!strcmp(value, "air")) {
201 this->Flags |= MapFieldAirUnit;
202 } else if (!strcmp(value, "sea")) {
203 this->Flags |= MapFieldSeaUnit;
204 } else if (!strcmp(value, "building")) {
205 this->Flags |= MapFieldBuilding;
206 } else {
207 LuaError(l, "Unsupported tag: %s" _C_ value);
208 }
209 }
210 }
211
212 /**
213 ** Check if a field is opaque
214 ** We check not only MapFieldOpaque flag because some field types (f.e. forest/rock/wall)
215 ** may be set in the FieldOfView as opaque as well.
216 */
isOpaque() const217 bool CMapField::isOpaque() const
218 {
219 return (FieldOfView.GetType() == FieldOfViewTypes::cShadowCasting
220 && FieldOfView.GetOpaqueFields() & this->Flags);
221 }
222
223 /// Check if a field flags.
CheckMask(int mask) const224 bool CMapField::CheckMask(int mask) const
225 {
226 return (this->Flags & mask) != 0;
227 }
228
229 /// Returns true, if water on the map tile field
WaterOnMap() const230 bool CMapField::WaterOnMap() const
231 {
232 return CheckMask(MapFieldWaterAllowed);
233 }
234
235 /// Returns true, if coast on the map tile field
CoastOnMap() const236 bool CMapField::CoastOnMap() const
237 {
238 return CheckMask(MapFieldCoastAllowed);
239 }
240
241 /// Returns true, if water on the map tile field
ForestOnMap() const242 bool CMapField::ForestOnMap() const
243 {
244 return CheckMask(MapFieldForest);
245 }
246
247 /// Returns true, if coast on the map tile field
RockOnMap() const248 bool CMapField::RockOnMap() const
249 {
250 return CheckMask(MapFieldRocks);
251 }
252
253 /// Returns true if the field should not need mixing with the surroundings
isDecorative() const254 bool CMapField::isDecorative() const
255 {
256 return CheckMask(MapFieldDecorative);
257 }
258
isAWall() const259 bool CMapField::isAWall() const
260 {
261 return Flags & MapFieldWall;
262 }
isHuman() const263 bool CMapField::isHuman() const
264 {
265 return Flags & MapFieldHuman;
266 }
267
isAHumanWall() const268 bool CMapField::isAHumanWall() const
269 {
270 const unsigned int humanWallFlag = (MapFieldWall | MapFieldHuman);
271 return (Flags & humanWallFlag) == humanWallFlag;
272 }
isAOrcWall() const273 bool CMapField::isAOrcWall() const
274 {
275 const unsigned int humanWallFlag = (MapFieldWall | MapFieldHuman);
276 return (Flags & humanWallFlag) == MapFieldWall;
277 }
278
279 //
280 // CMapFieldPlayerInfo
281 //
282
TeamVisibilityState(const CPlayer & player) const283 unsigned char CMapFieldPlayerInfo::TeamVisibilityState(const CPlayer &player) const
284 {
285 if (this->IsVisible(player)) {
286 return 2;
287 }
288 unsigned char maxVision = 0;
289 if (this->IsExplored(player)) {
290 maxVision = 1;
291 }
292
293 for (const uint8_t p : player.GetSharedVision()) {
294 maxVision = std::max<uint8_t>(maxVision, this->Visible[p]);
295 if (maxVision >= 2) {
296 return 2;
297 }
298 }
299
300 if (maxVision == 1 && Map.NoFogOfWar) {
301 return 2;
302 }
303 return maxVision;
304 }
305
IsExplored(const CPlayer & player) const306 bool CMapFieldPlayerInfo::IsExplored(const CPlayer &player) const
307 {
308 return this->Visible[player.Index] != 0;
309 }
310
IsVisible(const CPlayer & player) const311 bool CMapFieldPlayerInfo::IsVisible(const CPlayer &player) const
312 {
313 const bool fogOfWar = !Map.NoFogOfWar;
314 return this->Visible[player.Index] >= 2 || (!fogOfWar && IsExplored(player));
315 }
316
IsTeamVisible(const CPlayer & player) const317 bool CMapFieldPlayerInfo::IsTeamVisible(const CPlayer &player) const
318 {
319 return this->TeamVisibilityState(player) == 2;
320 }
321
322 //@}
323