1 /***************************************
2 ** Tsunagari Tile Engine **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
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
27 #include <stdlib.h> // for exit(1) on fatal
29 #include <boost/foreach.hpp>
30 #include <boost/format.hpp>
35 #include "python-bindings-template.cpp"
40 static int ivec2_to_dir(ivec2 v
)
44 return v
.y
== 0 ? EXIT_LEFT
: -1;
58 return v
.y
== 0 ? EXIT_RIGHT
: -1;
64 static Exit
pythonNewExit(std::string area
, int x
, int y
, double z
)
66 return Exit(area
, x
, y
, z
);
73 FlagManip::FlagManip(unsigned* 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
;
138 Exit::Exit(const std::string area
, int x
, int y
, double z
)
139 : area(area
), coords(x
, y
, z
)
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
)
172 void TileBase::runEnterScript(Entity
* triggeredBy
)
175 runScript(triggeredBy
, enterScript
);
177 parent
->runEnterScript(triggeredBy
);
180 void TileBase::runLeaveScript(Entity
* triggeredBy
)
183 runScript(triggeredBy
, leaveScript
);
185 parent
->runLeaveScript(triggeredBy
);
188 void TileBase::runUseScript(Entity
* triggeredBy
)
191 runScript(triggeredBy
, useScript
);
193 parent
->runUseScript(triggeredBy
);
196 void TileBase::runScript(Entity
* triggeredBy
, ScriptRef
& script
)
198 pythonSetGlobal("Entity", triggeredBy
);
199 pythonSetGlobal("Tile", this);
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
);
225 dest
= area
->virt2phys(vicoord(dest
.x
, dest
.y
, *layermod
));
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
));
240 Exit
* Tile::getNormalExit() const
242 return exits
[EXIT_NORMAL
];
245 void Tile::setNormalExit(Exit exit
)
247 Exit
** norm
= &exits
[EXIT_NORMAL
];
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
];
274 TileType::TileType(ImageRef
& img
)
277 anim
= Animation(img
);
280 bool TileType::needsRedraw() const
282 time_t now
= World::instance()->time();
283 return anim
.needsRedraw(now
);
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
)
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")
321 int TileSet::getWidth() const
326 int TileSet::getHeight() const
331 size_t TileSet::idx(int x
, int y
) const
333 return y
* width
+ x
;
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",
361 static_cast<TileType
* (TileBase::*) () const>
362 (&TileBase::getType
),
363 return_value_policy
<reference_existing_object
>()),
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",
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
);