1 /*********************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011-2012 OmegaSDG **
5 *********************************/
7 #include <stdlib.h> // for exit(1) on fatal
9 #include <boost/foreach.hpp>
13 #include "python-optional.h"
18 static int ivec2_to_dir(ivec2 v
)
22 return v
.y
== 0 ? EXIT_LEFT
: -1;
36 return v
.y
== 0 ? EXIT_RIGHT
: -1;
42 static Exit
pythonNewExit(std::string area
, int x
, int y
, double z
)
44 return Exit(area
, x
, y
, z
);
51 FlagManip::FlagManip(unsigned* flags
)
56 bool FlagManip::isNowalk() const
58 return (*flags
& TILE_NOWALK
) != 0;
61 bool FlagManip::isNowalkPlayer() const
63 return (*flags
& TILE_NOWALK_PLAYER
) != 0;
66 bool FlagManip::isNowalkNPC() const
68 return (*flags
& TILE_NOWALK_NPC
) != 0;
71 void FlagManip::setNowalk(bool nowalk
)
73 *flags
= (*flags
& ~TILE_NOWALK
) | TILE_NOWALK
* nowalk
;
76 void FlagManip::setNowalkPlayer(bool nowalk
)
78 *flags
= (*flags
& ~TILE_NOWALK_PLAYER
) | TILE_NOWALK_PLAYER
* nowalk
;
81 void FlagManip::setNowalkNPC(bool nowalk
)
83 *flags
= (*flags
& ~TILE_NOWALK_NPC
) | TILE_NOWALK_NPC
* nowalk
;
91 Exit::Exit(const std::string area
, int x
, int y
, double z
)
92 : area(area
), coords(x
, y
, z
)
101 : parent(NULL
), flags(0x0)
105 bool TileBase::hasFlag(unsigned flag
) const
107 return flags
& flag
|| (parent
&& parent
->hasFlag(flag
));
110 FlagManip
TileBase::flagManip()
112 return FlagManip(&flags
);
115 TileType
* TileBase::getType() const
117 return (TileType
*)parent
;
120 void TileBase::setType(TileType
* type
)
125 void TileBase::onEnterScripts(Entity
* triggeredBy
)
127 runScripts(triggeredBy
, onEnter
);
129 parent
->onEnterScripts(triggeredBy
);
132 void TileBase::onLeaveScripts(Entity
* triggeredBy
)
134 runScripts(triggeredBy
, onLeave
);
136 parent
->onLeaveScripts(triggeredBy
);
139 void TileBase::onUseScripts(Entity
* triggeredBy
)
141 runScripts(triggeredBy
, onUse
);
143 parent
->onUseScripts(triggeredBy
);
146 void TileBase::runScripts(Entity
* triggeredBy
,
147 const std::vector
<std::string
>& events
)
149 BOOST_FOREACH(const std::string
& script
, events
) {
150 Resourcer
* rc
= Resourcer::instance();
151 pythonSetGlobal("Entity", triggeredBy
);
152 pythonSetGlobal("Tile", this);
153 rc
->runPythonScript(script
);
165 Tile::Tile(Area
* area
, int x
, int y
, int z
)
166 : TileBase(), area(area
), x(x
), y(y
), z(z
)
168 memset(exits
, 0, sizeof(exits
));
169 memset(layermods
, 0, sizeof(layermods
));
172 Tile
& Tile::offset(int x
, int y
)
174 return area
->getTile(this->x
+ x
, this->y
+ y
, z
);
179 vicoord vi
= area
->phys2virt_vi(icoord(x
, y
, z
));
183 Exit
* Tile::getNormalExit() const
185 return exits
[EXIT_NORMAL
];
188 void Tile::setNormalExit(Exit exit
)
190 Exit
** norm
= &exits
[EXIT_NORMAL
];
193 *norm
= new Exit(exit
);
196 Exit
* Tile::exitAt(ivec2 dir
) const
198 int idx
= ivec2_to_dir(dir
);
199 return idx
== -1 ? NULL
: exits
[idx
];
202 boost::optional
<double> Tile::layermodAt(ivec2 dir
) const
204 int idx
= ivec2_to_dir(dir
);
205 return idx
== -1 ? boost::optional
<double>() : layermods
[idx
];
217 TileType::TileType(ImageRef
& img
)
223 bool TileType::needsRedraw() const
225 const int millis
= GameWindow::instance().time();
226 return anim
.needsRedraw(millis
);
236 TileSet::TileSet(int width
, int height
)
237 : width(width
), height(height
)
241 void TileSet::add(TileType
* type
)
243 types
.push_back(type
);
246 void TileSet::set(int idx
, TileType
* type
)
251 TileType
& TileSet::get(int x
, int y
)
253 size_t i
= idx(x
, y
);
254 if (i
> types
.size()) {
255 Log::fatal("TileSet", "index " + itostr((int)i
) + " out of bounds");
261 int TileSet::getWidth() const
266 int TileSet::getHeight() const
271 TileType
& TileSet::pyGet(int x
, int y
)
273 size_t i
= idx(x
, y
);
274 if (i
> types
.size()) {
275 PyErr_SetString(PyExc_IndexError
,
276 "TileSet::at(): x, y index out of range");
277 boost::python::throw_error_already_set();
282 size_t TileSet::idx(int x
, int y
) const
284 return y
* width
+ x
;
293 using namespace boost::python
;
295 class_
<FlagManip
> ("FlagManipulator", no_init
)
296 .add_property("nowalk",
297 &FlagManip::isNowalk
, &FlagManip::setNowalk
)
298 .add_property("nowalk_player",
299 &FlagManip::isNowalkPlayer
, &FlagManip::setNowalkPlayer
)
300 .add_property("nowalk_npc",
301 &FlagManip::isNowalkNPC
, &FlagManip::setNowalkNPC
)
303 class_
<TileBase
> ("TileBase", no_init
)
304 .add_property("flag", &TileBase::flagManip
)
305 .add_property("type",
307 static_cast<TileType
* (TileBase::*) () const>
308 (&TileBase::getType
),
309 return_value_policy
<reference_existing_object
>()),
311 .def("run_enter_scripts", &TileBase::onEnterScripts
)
312 .def("run_leave_scripts", &TileBase::onLeaveScripts
)
313 .def("run_use_scripts", &TileBase::onUseScripts
)
315 class_
<Tile
, bases
<TileBase
> > ("Tile", no_init
)
316 .def_readonly("area", &Tile::area
)
317 .def_readonly("x", &Tile::x
)
318 .def_readonly("y", &Tile::y
)
319 .add_property("z", &Tile::getZ
)
320 .add_property("exit",
322 static_cast<Exit
* (Tile::*) () const>
323 (&Tile::getNormalExit
),
324 return_value_policy
<reference_existing_object
>()),
325 &Tile::setNormalExit
)
326 .def("offset", &Tile::offset
,
327 return_value_policy
<reference_existing_object
>())
329 class_
<TileType
, bases
<TileBase
> > ("TileType", no_init
)
331 class_
<TileSet
> ("TileSet", no_init
)
332 .add_property("width", &TileSet::getWidth
)
333 .add_property("height", &TileSet::getHeight
)
334 .def("at", &TileSet::pyGet
,
335 return_value_policy
<reference_existing_object
>())
337 class_
<Exit
> ("Exit", no_init
)
338 .def_readwrite("area", &Exit::area
)
339 .def_readwrite("coords", &Exit::coords
)
341 pythonAddFunction("new_exit", pythonNewExit
);