finish move to Python-handled imports
[Tsunagari.git] / src / tile.cpp
blob06d9a64a01788067ed859058ee5bedbaefc82843
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 <boost/foreach.hpp>
30 #include <boost/format.hpp>
32 #include "area.h"
33 #include "log.h"
34 #include "python.h"
35 #include "python-bindings-template.cpp"
36 #include "string.h"
37 #include "tile.h"
38 #include "world.h"
40 static int ivec2_to_dir(ivec2 v)
42 switch (v.x) {
43 case -1:
44 return v.y == 0 ? EXIT_LEFT : -1;
45 case 0:
46 switch (v.y) {
47 case -1:
48 return EXIT_UP;
49 case 0:
50 return EXIT_NORMAL;
51 case 1:
52 return EXIT_DOWN;
53 default:
54 return -1;
56 break;
57 case 1:
58 return v.y == 0 ? EXIT_RIGHT : -1;
59 default:
60 return -1;
64 static Exit pythonNewExit(std::string area, int x, int y, double z)
66 return Exit(area, x, y, z);
71 * FLAGMANIP
73 FlagManip::FlagManip(unsigned* flags)
74 : flags(flags)
78 bool FlagManip::isNowalk() const
80 return (*flags & TILE_NOWALK) != 0;
83 bool FlagManip::isNowalkPlayer() const
85 return (*flags & TILE_NOWALK_PLAYER) != 0;
88 bool FlagManip::isNowalkNPC() const
90 return (*flags & TILE_NOWALK_NPC) != 0;
93 bool FlagManip::isNowalkExit() const
95 return (*flags & TILE_NOWALK_EXIT) != 0;
98 bool FlagManip::isNowalkAreaBound() const
100 return (*flags & TILE_NOWALK_AREA_BOUND) != 0;
103 void FlagManip::setNowalk(bool nowalk)
105 *flags &= ~TILE_NOWALK;
106 *flags |= TILE_NOWALK * nowalk;
109 void FlagManip::setNowalkPlayer(bool nowalk)
111 *flags &= ~TILE_NOWALK_PLAYER;
112 *flags |= TILE_NOWALK_PLAYER * nowalk;
115 void FlagManip::setNowalkNPC(bool nowalk)
117 *flags &= ~TILE_NOWALK_NPC;
118 *flags |= TILE_NOWALK_NPC * nowalk;
121 void FlagManip::setNowalkExit(bool nowalk)
123 *flags &= ~TILE_NOWALK_EXIT;
124 *flags |= TILE_NOWALK_EXIT * nowalk;
127 void FlagManip::setNowalkAreaBound(bool nowalk)
129 *flags &= ~TILE_NOWALK_AREA_BOUND;
130 *flags |= TILE_NOWALK_AREA_BOUND * nowalk;
134 Exit::Exit()
138 Exit::Exit(const std::string area, int x, int y, double z)
139 : area(area), coords(x, y, z)
145 * TILEBASE
147 TileBase::TileBase()
148 : parent(NULL), flags(0x0)
152 FlagManip TileBase::flagManip()
154 return FlagManip(&flags);
157 bool TileBase::hasFlag(unsigned flag) const
159 return flags & flag || (parent && parent->hasFlag(flag));
162 TileType* TileBase::getType() const
164 return (TileType*)parent;
167 void TileBase::setType(TileType* type)
169 parent = type;
172 void TileBase::runEnterScript(Entity* triggeredBy)
174 if (enterScript)
175 runScript(triggeredBy, enterScript);
176 if (parent)
177 parent->runEnterScript(triggeredBy);
180 void TileBase::runLeaveScript(Entity* triggeredBy)
182 if (leaveScript)
183 runScript(triggeredBy, leaveScript);
184 if (parent)
185 parent->runLeaveScript(triggeredBy);
188 void TileBase::runUseScript(Entity* triggeredBy)
190 if (useScript)
191 runScript(triggeredBy, useScript);
192 if (parent)
193 parent->runUseScript(triggeredBy);
196 void TileBase::runScript(Entity* triggeredBy, ScriptRef& script)
198 pythonSetGlobal("Entity", triggeredBy);
199 pythonSetGlobal("Tile", this);
200 script->invoke();
205 * TILE
207 Tile::Tile()
208 : entCnt(0)
212 Tile::Tile(Area* area, int x, int y, int z)
213 : TileBase(), area(area), x(x), y(y), z(z), entCnt(0)
215 memset(exits, 0, sizeof(exits));
216 memset(layermods, 0, sizeof(layermods));
219 icoord Tile::moveDest(icoord here, ivec2 facing) const
221 icoord dest = here + icoord(facing.x, facing.y, 0);
223 double* layermod = layermodAt(facing);
224 if (layermod)
225 dest = area->virt2phys(vicoord(dest.x, dest.y, *layermod));
226 return dest;
229 Tile* Tile::offset(int x, int y) const
231 return area->getTile(this->x + x, this->y + y, z);
234 double Tile::getZ() const
236 vicoord vi = area->phys2virt_vi(icoord(x, y, z));
237 return vi.z;
240 Exit* Tile::getNormalExit() const
242 return exits[EXIT_NORMAL];
245 void Tile::setNormalExit(Exit exit)
247 Exit** norm = &exits[EXIT_NORMAL];
248 if (*norm)
249 delete *norm;
250 *norm = new Exit(exit);
253 Exit* Tile::exitAt(ivec2 dir) const
255 int idx = ivec2_to_dir(dir);
256 return idx == -1 ? NULL : exits[idx];
259 double* Tile::layermodAt(ivec2 dir) const
261 int idx = ivec2_to_dir(dir);
262 return idx == -1 ? NULL : layermods[idx];
267 * TILETYPE
269 TileType::TileType()
270 : TileBase()
274 TileType::TileType(ImageRef& img)
275 : TileBase()
277 anim = Animation(img);
280 bool TileType::needsRedraw() const
282 time_t now = World::instance()->time();
283 return anim.needsRedraw(now);
287 * TILESET
289 TileSet::TileSet()
293 TileSet::TileSet(int width, int height)
294 : width(width), height(height)
298 void TileSet::add(TileType* type)
300 types.push_back(type);
303 void TileSet::set(int idx, TileType* type)
305 types[idx] = type;
308 TileType* TileSet::get(int x, int y)
310 using namespace boost;
312 size_t i = idx(x, y);
313 if (i > types.size()) {
314 Log::err("TileSet", str(format("get(%d, %d): out of bounds")
315 % x % y));
316 return NULL;
318 return types[i];
321 int TileSet::getWidth() const
323 return height;
326 int TileSet::getHeight() const
328 return width;
331 size_t TileSet::idx(int x, int y) const
333 return y * width + x;
338 * PYTHON
340 void exportTile()
342 using namespace boost::python;
344 class_<FlagManip> ("FlagManipulator", no_init)
345 .add_property("nowalk",
346 &FlagManip::isNowalk, &FlagManip::setNowalk)
347 .add_property("nowalk_player",
348 &FlagManip::isNowalkPlayer, &FlagManip::setNowalkPlayer)
349 .add_property("nowalk_npc",
350 &FlagManip::isNowalkNPC, &FlagManip::setNowalkNPC)
351 .add_property("nowalk_exit",
352 &FlagManip::isNowalkExit, &FlagManip::setNowalkExit)
353 .add_property("nowalk_area_bound",
354 &FlagManip::isNowalkAreaBound,
355 &FlagManip::setNowalkAreaBound)
357 class_<TileBase> ("TileBase", no_init)
358 .add_property("flag", &TileBase::flagManip)
359 .add_property("type",
360 make_function(
361 static_cast<TileType* (TileBase::*) () const>
362 (&TileBase::getType),
363 return_value_policy<reference_existing_object>()),
364 &TileBase::setType)
365 // .def_readwrite("on_enter", &TileBase::enterScript)
366 // .def_readwrite("on_leave", &TileBase::leaveScript)
367 // .def_readwrite("on_use", &TileBase::useScript)
368 .def("run_enter_script", &TileBase::runEnterScript)
369 .def("run_leave_script", &TileBase::runLeaveScript)
370 .def("run_use_script", &TileBase::runUseScript)
372 class_<Tile, bases<TileBase> > ("Tile", no_init)
373 .def_readonly("area", &Tile::area)
374 .def_readonly("x", &Tile::x)
375 .def_readonly("y", &Tile::y)
376 .add_property("z", &Tile::getZ)
377 .add_property("exit",
378 make_function(
379 static_cast<Exit* (Tile::*) () const>
380 (&Tile::getNormalExit),
381 return_value_policy<reference_existing_object>()),
382 &Tile::setNormalExit)
383 .def_readonly("nentities", &Tile::entCnt)
384 .def("offset", &Tile::offset,
385 return_value_policy<reference_existing_object>())
387 class_<TileType, bases<TileBase> > ("TileType", no_init)
389 class_<TileSet> ("TileSet", no_init)
390 .add_property("width", &TileSet::getWidth)
391 .add_property("height", &TileSet::getHeight)
392 .def("at", &TileSet::get,
393 return_value_policy<reference_existing_object>())
395 class_<Exit> ("Exit", no_init)
396 .def_readwrite("area", &Exit::area)
397 .def_readwrite("coords", &Exit::coords)
399 pythonAddFunction("new_exit", pythonNewExit);