Fix INT_MAX definition on some newer systems.
[Tsunagari.git] / src / tile.cpp
blobe98d19d6dea378e15ffe87898f656a1cad3551a9
1 /***************************************
2 ** Tsunagari Tile Engine **
3 ** tile.cpp **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <stdlib.h> // for exit(1) on fatal
29 #include "area.h"
30 #include "formatter.h"
31 #include "log.h"
32 #include "python.h"
33 #include "python-bindings-template.cpp"
34 #include "string.h"
35 #include "tile.h"
36 #include "world.h"
38 static int ivec2_to_dir(ivec2 v)
40 switch (v.x) {
41 case -1:
42 return v.y == 0 ? EXIT_LEFT : -1;
43 case 0:
44 switch (v.y) {
45 case -1:
46 return EXIT_UP;
47 case 0:
48 return EXIT_NORMAL;
49 case 1:
50 return EXIT_DOWN;
51 default:
52 return -1;
54 break;
55 case 1:
56 return v.y == 0 ? EXIT_RIGHT : -1;
57 default:
58 return -1;
62 static Exit pythonNewExit(std::string area, int x, int y, double z)
64 return Exit(area, x, y, z);
69 * FLAGMANIP
71 FlagManip::FlagManip(unsigned* flags)
72 : flags(flags)
76 bool FlagManip::isNowalk() const
78 return (*flags & TILE_NOWALK) != 0;
81 bool FlagManip::isNowalkPlayer() const
83 return (*flags & TILE_NOWALK_PLAYER) != 0;
86 bool FlagManip::isNowalkNPC() const
88 return (*flags & TILE_NOWALK_NPC) != 0;
91 bool FlagManip::isNowalkExit() const
93 return (*flags & TILE_NOWALK_EXIT) != 0;
96 bool FlagManip::isNowalkAreaBound() const
98 return (*flags & TILE_NOWALK_AREA_BOUND) != 0;
101 void FlagManip::setNowalk(bool nowalk)
103 *flags &= ~TILE_NOWALK;
104 *flags |= TILE_NOWALK * nowalk;
107 void FlagManip::setNowalkPlayer(bool nowalk)
109 *flags &= ~TILE_NOWALK_PLAYER;
110 *flags |= TILE_NOWALK_PLAYER * nowalk;
113 void FlagManip::setNowalkNPC(bool nowalk)
115 *flags &= ~TILE_NOWALK_NPC;
116 *flags |= TILE_NOWALK_NPC * nowalk;
119 void FlagManip::setNowalkExit(bool nowalk)
121 *flags &= ~TILE_NOWALK_EXIT;
122 *flags |= TILE_NOWALK_EXIT * nowalk;
125 void FlagManip::setNowalkAreaBound(bool nowalk)
127 *flags &= ~TILE_NOWALK_AREA_BOUND;
128 *flags |= TILE_NOWALK_AREA_BOUND * nowalk;
132 Exit::Exit()
136 Exit::Exit(const std::string area, int x, int y, double z)
137 : area(area), coords(x, y, z)
143 * TILEBASE
145 TileBase::TileBase()
146 : parent(NULL), flags(0x0)
150 FlagManip TileBase::flagManip()
152 return FlagManip(&flags);
155 bool TileBase::hasFlag(unsigned flag) const
157 return flags & flag || (parent && parent->hasFlag(flag));
160 TileType* TileBase::getType() const
162 return (TileType*)parent;
165 void TileBase::setType(TileType* type)
167 parent = type;
170 void TileBase::runEnterScript(Entity* triggeredBy)
172 if (enterScript)
173 runScript(triggeredBy, enterScript);
174 if (parent)
175 parent->runEnterScript(triggeredBy);
178 void TileBase::runLeaveScript(Entity* triggeredBy)
180 if (leaveScript)
181 runScript(triggeredBy, leaveScript);
182 if (parent)
183 parent->runLeaveScript(triggeredBy);
186 void TileBase::runUseScript(Entity* triggeredBy)
188 if (useScript)
189 runScript(triggeredBy, useScript);
190 if (parent)
191 parent->runUseScript(triggeredBy);
194 void TileBase::runScript(Entity* triggeredBy, ScriptRef& script)
196 pythonSetGlobal("Entity", triggeredBy);
197 pythonSetGlobal("Tile", this);
198 script->invoke();
203 * TILE
205 Tile::Tile()
206 : entCnt(0)
210 Tile::Tile(Area* area, int x, int y, int z)
211 : TileBase(), area(area), x(x), y(y), z(z), entCnt(0)
213 memset(exits, 0, sizeof(exits));
214 memset(layermods, 0, sizeof(layermods));
217 icoord Tile::moveDest(icoord here, ivec2 facing) const
219 icoord dest = here + icoord(facing.x, facing.y, 0);
221 double* layermod = layermodAt(facing);
222 if (layermod)
223 dest = area->virt2phys(vicoord(dest.x, dest.y, *layermod));
224 return dest;
227 Tile* Tile::offset(int x, int y) const
229 return area->getTile(this->x + x, this->y + y, z);
232 double Tile::getZ() const
234 vicoord vi = area->phys2virt_vi(icoord(x, y, z));
235 return vi.z;
238 Exit* Tile::getNormalExit() const
240 return exits[EXIT_NORMAL];
243 void Tile::setNormalExit(Exit exit)
245 Exit** norm = &exits[EXIT_NORMAL];
246 if (*norm)
247 delete *norm;
248 *norm = new Exit(exit);
251 Exit* Tile::exitAt(ivec2 dir) const
253 int idx = ivec2_to_dir(dir);
254 return idx == -1 ? NULL : exits[idx];
257 double* Tile::layermodAt(ivec2 dir) const
259 int idx = ivec2_to_dir(dir);
260 return idx == -1 ? NULL : layermods[idx];
265 * TILETYPE
267 TileType::TileType()
268 : TileBase()
272 TileType::TileType(ImageRef& img)
273 : TileBase()
275 anim = Animation(img);
278 bool TileType::needsRedraw() const
280 time_t now = World::instance()->time();
281 return anim.needsRedraw(now);
285 * TILESET
287 TileSet::TileSet()
291 TileSet::TileSet(int width, int height)
292 : width(width), height(height)
296 void TileSet::add(TileType* type)
298 types.push_back(type);
301 void TileSet::set(int idx, TileType* type)
303 types[idx] = type;
306 TileType* TileSet::get(int x, int y)
308 size_t i = idx(x, y);
309 if (i > types.size()) {
310 Log::err("TileSet",
311 Formatter("get(%, %): out of bounds") % x % y);
312 return NULL;
314 return types[i];
317 int TileSet::getWidth() const
319 return height;
322 int TileSet::getHeight() const
324 return width;
327 size_t TileSet::idx(int x, int y) const
329 return y * width + x;
334 * PYTHON
336 void exportTile()
338 using namespace boost::python;
340 class_<FlagManip> ("FlagManipulator", no_init)
341 .add_property("nowalk",
342 &FlagManip::isNowalk, &FlagManip::setNowalk)
343 .add_property("nowalk_player",
344 &FlagManip::isNowalkPlayer, &FlagManip::setNowalkPlayer)
345 .add_property("nowalk_npc",
346 &FlagManip::isNowalkNPC, &FlagManip::setNowalkNPC)
347 .add_property("nowalk_exit",
348 &FlagManip::isNowalkExit, &FlagManip::setNowalkExit)
349 .add_property("nowalk_area_bound",
350 &FlagManip::isNowalkAreaBound,
351 &FlagManip::setNowalkAreaBound)
353 class_<TileBase> ("TileBase", no_init)
354 .add_property("flag", &TileBase::flagManip)
355 .add_property("type",
356 make_function(
357 static_cast<TileType* (TileBase::*) () const>
358 (&TileBase::getType),
359 return_value_policy<reference_existing_object>()),
360 &TileBase::setType)
361 // .def_readwrite("on_enter", &TileBase::enterScript)
362 // .def_readwrite("on_leave", &TileBase::leaveScript)
363 // .def_readwrite("on_use", &TileBase::useScript)
364 .def("run_enter_script", &TileBase::runEnterScript)
365 .def("run_leave_script", &TileBase::runLeaveScript)
366 .def("run_use_script", &TileBase::runUseScript)
368 class_<Tile, bases<TileBase> > ("Tile", no_init)
369 .def_readonly("area", &Tile::area)
370 .def_readonly("x", &Tile::x)
371 .def_readonly("y", &Tile::y)
372 .add_property("z", &Tile::getZ)
373 .add_property("exit",
374 make_function(
375 static_cast<Exit* (Tile::*) () const>
376 (&Tile::getNormalExit),
377 return_value_policy<reference_existing_object>()),
378 &Tile::setNormalExit)
379 .def_readonly("nentities", &Tile::entCnt)
380 .def("offset", &Tile::offset,
381 return_value_policy<reference_existing_object>())
383 class_<TileType, bases<TileBase> > ("TileType", no_init)
385 class_<TileSet> ("TileSet", no_init)
386 .add_property("width", &TileSet::getWidth)
387 .add_property("height", &TileSet::getHeight)
388 .def("at", &TileSet::get,
389 return_value_policy<reference_existing_object>())
391 class_<Exit> ("Exit", no_init)
392 .def_readwrite("area", &Exit::area)
393 .def_readwrite("coords", &Exit::coords)
395 pythonAddFunction("new_exit", pythonNewExit);