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>
10 #include <boost/format.hpp>
14 #include "python-optional.h"
19 static int ivec2_to_dir(ivec2 v
)
23 return v
.y
== 0 ? EXIT_LEFT
: -1;
37 return v
.y
== 0 ? EXIT_RIGHT
: -1;
43 static Exit
pythonNewExit(std::string area
, int x
, int y
, double z
)
45 return Exit(area
, x
, y
, z
);
52 FlagManip::FlagManip(unsigned* flags
)
57 bool FlagManip::isNowalk() const
59 return (*flags
& TILE_NOWALK
) != 0;
62 bool FlagManip::isNowalkPlayer() const
64 return (*flags
& TILE_NOWALK_PLAYER
) != 0;
67 bool FlagManip::isNowalkNPC() const
69 return (*flags
& TILE_NOWALK_NPC
) != 0;
72 bool FlagManip::isNowalkExit() const
74 return (*flags
& TILE_NOWALK_EXIT
) != 0;
77 bool FlagManip::isNowalkAreaBound() const
79 return (*flags
& TILE_NOWALK_AREA_BOUND
) != 0;
82 void FlagManip::setNowalk(bool nowalk
)
84 *flags
&= ~TILE_NOWALK
;
85 *flags
|= TILE_NOWALK
* nowalk
;
88 void FlagManip::setNowalkPlayer(bool nowalk
)
90 *flags
&= ~TILE_NOWALK_PLAYER
;
91 *flags
|= TILE_NOWALK_PLAYER
* nowalk
;
94 void FlagManip::setNowalkNPC(bool nowalk
)
96 *flags
&= ~TILE_NOWALK_NPC
;
97 *flags
|= TILE_NOWALK_NPC
* nowalk
;
100 void FlagManip::setNowalkExit(bool nowalk
)
102 *flags
&= ~TILE_NOWALK_EXIT
;
103 *flags
|= TILE_NOWALK_EXIT
* nowalk
;
106 void FlagManip::setNowalkAreaBound(bool nowalk
)
108 *flags
&= ~TILE_NOWALK_AREA_BOUND
;
109 *flags
|= TILE_NOWALK_AREA_BOUND
* nowalk
;
117 Exit::Exit(const std::string area
, int x
, int y
, double z
)
118 : area(area
), coords(x
, y
, z
)
127 : parent(NULL
), flags(0x0)
131 FlagManip
TileBase::flagManip()
133 return FlagManip(&flags
);
136 bool TileBase::hasFlag(unsigned flag
) const
138 return flags
& flag
|| (parent
&& parent
->hasFlag(flag
));
141 TileType
* TileBase::getType() const
143 return (TileType
*)parent
;
146 void TileBase::setType(TileType
* type
)
151 void TileBase::runEnterScript(Entity
* triggeredBy
)
153 runScript(triggeredBy
, enterScript
);
155 parent
->runEnterScript(triggeredBy
);
158 void TileBase::runLeaveScript(Entity
* triggeredBy
)
160 runScript(triggeredBy
, leaveScript
);
162 parent
->runLeaveScript(triggeredBy
);
165 void TileBase::runUseScript(Entity
* triggeredBy
)
167 runScript(triggeredBy
, useScript
);
169 parent
->runUseScript(triggeredBy
);
172 void TileBase::runScript(Entity
* triggeredBy
, ScriptInst
& script
)
174 pythonSetGlobal("Entity", triggeredBy
);
175 pythonSetGlobal("Tile", this);
188 Tile::Tile(Area
* area
, int x
, int y
, int z
)
189 : TileBase(), area(area
), x(x
), y(y
), z(z
), entCnt(0)
191 memset(exits
, 0, sizeof(exits
));
192 memset(layermods
, 0, sizeof(layermods
));
195 Tile
* Tile::offset(int x
, int y
)
197 return area
->getTile(this->x
+ x
, this->y
+ y
, z
);
202 vicoord vi
= area
->phys2virt_vi(icoord(x
, y
, z
));
206 Exit
* Tile::getNormalExit() const
208 return exits
[EXIT_NORMAL
];
211 void Tile::setNormalExit(Exit exit
)
213 Exit
** norm
= &exits
[EXIT_NORMAL
];
216 *norm
= new Exit(exit
);
219 Exit
* Tile::exitAt(ivec2 dir
) const
221 int idx
= ivec2_to_dir(dir
);
222 return idx
== -1 ? NULL
: exits
[idx
];
225 boost::optional
<double> Tile::layermodAt(ivec2 dir
) const
227 int idx
= ivec2_to_dir(dir
);
228 return idx
== -1 ? boost::optional
<double>() : layermods
[idx
];
240 TileType::TileType(ImageRef
& img
)
246 bool TileType::needsRedraw() const
248 const int millis
= GameWindow::instance().time();
249 return anim
.needsRedraw(millis
);
259 TileSet::TileSet(int width
, int height
)
260 : width(width
), height(height
)
264 void TileSet::add(TileType
* type
)
266 types
.push_back(type
);
269 void TileSet::set(int idx
, TileType
* type
)
274 TileType
* TileSet::get(int x
, int y
)
276 size_t i
= idx(x
, y
);
277 if (i
> types
.size()) {
278 Log::err("TileSet", boost::str(boost::format(
279 "get(%d, %d): out of bounds") % x
% y
));
285 int TileSet::getWidth() const
290 int TileSet::getHeight() const
295 size_t TileSet::idx(int x
, int y
) const
297 return y
* width
+ x
;
306 using namespace boost::python
;
308 class_
<FlagManip
> ("FlagManipulator", no_init
)
309 .add_property("nowalk",
310 &FlagManip::isNowalk
, &FlagManip::setNowalk
)
311 .add_property("nowalk_player",
312 &FlagManip::isNowalkPlayer
, &FlagManip::setNowalkPlayer
)
313 .add_property("nowalk_npc",
314 &FlagManip::isNowalkNPC
, &FlagManip::setNowalkNPC
)
315 .add_property("nowalk_exit",
316 &FlagManip::isNowalkExit
, &FlagManip::setNowalkExit
)
317 .add_property("nowalk_area_bound",
318 &FlagManip::isNowalkAreaBound
,
319 &FlagManip::setNowalkAreaBound
)
321 class_
<TileBase
> ("TileBase", no_init
)
322 .add_property("flag", &TileBase::flagManip
)
323 .add_property("type",
325 static_cast<TileType
* (TileBase::*) () const>
326 (&TileBase::getType
),
327 return_value_policy
<reference_existing_object
>()),
329 .def_readwrite("on_enter", &TileBase::enterScript
)
330 .def_readwrite("on_leave", &TileBase::leaveScript
)
331 .def_readwrite("on_use", &TileBase::useScript
)
332 .def("run_enter_script", &TileBase::runEnterScript
)
333 .def("run_leave_script", &TileBase::runLeaveScript
)
334 .def("run_use_script", &TileBase::runUseScript
)
336 class_
<Tile
, bases
<TileBase
> > ("Tile", no_init
)
337 .def_readonly("area", &Tile::area
)
338 .def_readonly("x", &Tile::x
)
339 .def_readonly("y", &Tile::y
)
340 .add_property("z", &Tile::getZ
)
341 .add_property("exit",
343 static_cast<Exit
* (Tile::*) () const>
344 (&Tile::getNormalExit
),
345 return_value_policy
<reference_existing_object
>()),
346 &Tile::setNormalExit
)
347 .def_readonly("nentities", &Tile::entCnt
)
348 .def("offset", &Tile::offset
,
349 return_value_policy
<reference_existing_object
>())
351 class_
<TileType
, bases
<TileBase
> > ("TileType", no_init
)
353 class_
<TileSet
> ("TileSet", no_init
)
354 .add_property("width", &TileSet::getWidth
)
355 .add_property("height", &TileSet::getHeight
)
356 .def("at", &TileSet::get
,
357 return_value_policy
<reference_existing_object
>())
359 class_
<Exit
> ("Exit", no_init
)
360 .def_readwrite("area", &Exit::area
)
361 .def_readwrite("coords", &Exit::coords
)
363 pythonAddFunction("new_exit", pythonNewExit
);