1 #ifndef __BTANKS_ANIMATED_OBJECT__
2 #define __BTANKS_ANIMATED_OBJECT__
3 
4 /* Battle Tanks Game
5  * Copyright (C) 2006-2009 Battle Tanks team
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  */
21 
22 /*
23  * Additional rights can be granted beyond the GNU General Public License
24  * on the terms provided in the Exception. If you modify this file,
25  * you may extend this exception to your version of the file,
26  * but you are not obligated to do so. If you do not wish to provide this
27  * exception without modification, you must delete this exception statement
28  * from your version and license this file solely under the GPL without exception.
29 */
30 
31 #include <string>
32 #include <map>
33 #include <set>
34 #include <queue>
35 
36 #include "export_btanks.h"
37 #include "base_object.h"
38 #include "alarm.h"
39 #include "math/v2.h"
40 #include "math/matrix.h"
41 #include "object_common.h"
42 
43 namespace sdlx {
44 	class Rect;
45 	class Surface;
46 	class CollisionMap;
47 }
48 
49 namespace clunk {
50 	class Object;
51 }
52 
53 class AnimationModel;
54 class Animation;
55 class Pose;
56 
57 class BTANKSAPI Object : public BaseObject {
58 public:
59 	const v2<float> get_relative_position(const Object *obj) const;
get_position()60 	inline const v2<float> get_position() const { return _parent == NULL? _position: _position + _parent->get_position(); }
61 
62 	template<typename T>
get_position(v2<T> & position)63 	inline void get_position(v2<T> &position) const {
64 		position = _position.convert<T>();
65 		if (_parent != NULL) {
66 			v2<T> ppos;
67 			_parent->get_position(ppos);
68 			position += ppos;
69 		}
70 	}
71 
get_center_position()72 	inline const v2<float> get_center_position() const { return get_position() + size / 2; }
73 	template<typename T>
get_center_position(v2<T> & position)74 	inline void get_center_position(v2<T> &position) const { get_position<T>(position); position += (size / 2).convert<T>(); }
75 
76 	const std::string registered_name;
77 
78 	std::string animation;
79 	float fadeout_time;
80 
81 	Object(const std::string &classname); //do not use parent - internal
82 	~Object();
83 
84 	void init(const std::string &animation); //do not use it, needed for resman
85 
86 	virtual Object * clone() const;
87 	Object * deep_clone() const;
88 
89 	bool playing_sound(const std::string &name) const;
90 	void play_sound(const std::string &name, const bool loop, const float gain = 1.0);
91 	void play_random_sound(const std::string &classname, const bool loop, const float gain = 1.0);
92 	void fadeout_sound(const std::string &name);
93 
get_direction()94 	inline const int get_direction() const { return _direction_idx; }
get_directions_number()95 	inline const int get_directions_number() const { return _directions_n; }
96 	virtual void set_direction(const int dir);
97 	void set_directions_number(const int dirs);
98 
99 	virtual void tick(const float dt);
100 	virtual void render(sdlx::Surface &surface, const int x, const int y);
101 	const bool collides(const Object *other, const int x, const int y, const bool hidden_by_other = false) const;
102 	const bool collides(const sdlx::CollisionMap *other, const int x, const int y, const bool hidden_by_other = false) const;
103 
104 	// animation:
105 	void play(const std::string &id, const bool repeat = false);
106 	void play_now(const std::string &id);
107 	void cancel();
108 	void cancel_repeatable();
109 	void cancel_all();
get_state()110 	inline const std::string& get_state() const {
111 		static const std::string empty;
112 		if (_events.empty())
113 			return empty;
114 		return _events.front().name;
115 	}
116 	const float get_state_progress() const;
117 	//effects
118 	void add_effect(const std::string &name, const float ttl = -1);
has_effect(const std::string & name)119 	inline const bool has_effect(const std::string &name) const {
120 		return _effects.find(name) != _effects.end();
121 	}
122 	const float get_effect_timer(const std::string &name) const;
123 	void remove_effect(const std::string &name);
124 
125 	virtual void add_damage(Object *from, const int hp, const bool emitDeath = true);
126 	void add_damage(Object *from, const bool emitDeath = true);
127 
128 	virtual void emit(const std::string &event, Object * emitter = NULL);
129 	virtual void serialize(mrt::Serializator &s) const;
130 	virtual void deserialize(const mrt::Serializator &s);
131 
132 	void serialize_all(mrt::Serializator &s) const;
133 
134 	virtual void on_spawn();
135 
rotating()136 	inline const bool rotating() const { return _direction_idx != _dst_direction; }
137 
138 	virtual void calculate(const float dt);
139 
140 	virtual const std::string getType() const;
141 	virtual const int getCount() const;
142 
143 	const Object *get(const std::string &name) const;
144 	const bool has(const std::string &name) const;
145 
146 	const float getWeaponRange(const std::string &weapon) const;
147 
148 	const int get_target_position(v2<float> &relative_position, const v2<float> &target, const std::string &weapon) const;
149 	const int get_target_position(v2<float> &relative_position, const v2<float> &target, const float range) const;
150 	const int get_target_position(v2<float> &relative_position, const std::set<std::string> &targets, const std::string &weapon) const;
151 	const int get_target_position(v2<float> &relative_position, const std::set<std::string> &targets, const float range) const;
152 
153 	void quantize_velocity();
154 
get_way()155 	inline const Way& get_way() const { return _way; }
156 	void set_way(const Way & way);
157 	const bool is_driven() const;
158 
159 	const std::string get_nearest_waypoint(const std::string &classname) const;
160 
161 	void set_zbox(const int z);
162 
163 	virtual const bool detachVehicle();
164 	virtual const bool attachVehicle(Object *vehicle);
165 
166 	const int get_children(const std::string &classname) const;
167 	void enumerate_objects(std::set<const Object *> &o_set, const float range, const std::set<std::string> *classfilter) const;
168 
169 	static const bool check_distance(const v2<float> &map1, const v2<float>& map2, const int z, const bool use_pierceable_fixes);
170 
171 	const bool ai_disabled() const;
172 	virtual const bool take(const BaseObject *obj, const std::string &type);
173 
174 	Object * spawn(const std::string &classname, const std::string &animation, const v2<float> &dpos = v2<float>(), const v2<float> &vel = v2<float>(), const int z = 0);
175 
invalidate()176 	void invalidate() { set_sync(true); }
177 
178 	//grouped object handling
179 	void pick(const std::string &name, Object *object); //picks up object and insert as group one, i.e. ctf-flag
180 	Object *drop(const std::string &name, const v2<float> &dpos = v2<float>()); //pops object and inserts into world again
181 
182 	Object *add(const std::string &name, const std::string &classname, const std::string &animation, const v2<float> &dpos, const GroupType type);
183 	Object *get(const std::string &name);
184 	void remove(const std::string &name);
185 	void group_emit(const std::string &name, const std::string &event);
186 
187 	const bool get_render_rect(sdlx::Rect &src) const;
188 
is_subobject()189 	bool is_subobject() const { return _parent != NULL; }
190 
get_slot()191 	inline const int get_slot() const { return _slot_id; }
192 	void set_slot(const int id);
193 
194 	void update_outline(const bool hidden);
195 
get_clunk_object()196 	inline clunk::Object * get_clunk_object() { return clunk_object; }
get_clunk_object()197 	inline clunk::Object * get_clunk_object() const { return clunk_object; }
set_clunk_object(clunk::Object * co)198 	inline void set_clunk_object(clunk::Object *co) { clunk_object = co; }
199 
200 protected:
201 
202 	//pathfinding
203 
204 	struct Point {
PointPoint205 		inline Point() : id(), parent(), g(0), h(0), dir(-1) {}
206 		v2<int> id, parent;
207 		int g, h, dir;
208 	};
209 
210 	struct PD {
211 		int f;
212 		v2<int> id;
PDPD213 		inline PD(const int f, const v2<int> &id) : f(f), id(id) {}
214 
215 		inline const bool operator<(const PD &other) const {
216 			return f > other.f;
217 		}
218 	};
219 
220 	typedef std::set<v2<int> > CloseList;
221 	typedef std::priority_queue<PD> OpenList;
222 	typedef std::map<const v2<int>, Point> PointMap;
223 
224 
225 	void find_path(const v2<int> target, const int step);
226 	const bool find_path_done(Way &way);
calculating_path()227 	inline const bool calculating_path() const { return !_open_list.empty(); }
228 
229 	void calculate_way_velocity();
230 
231 	const bool get_nearest(const std::set<std::string> &classnames, const float range, v2<float> &position, v2<float> &velocity, const bool check_shooting_range) const;
232 	const Object * get_nearest_object(const std::set<std::string> &classnames, const float range, const bool check_shooting_range) const;
233 
234 	void limit_rotation(const float dt, const float speed, const bool rotate_even_stopped, const bool allow_backward);
235 
236 	void check_surface() const;
237 
238 	virtual const bool skip_rendering() const;
239 
240 	const sdlx::Surface * get_surface() const;
241 	const Matrix<int> &get_impassability_matrix() const;
242 
get_animation_model()243 	inline const AnimationModel * get_animation_model() const { return _model; }
244 
245 	Object * _parent;
246 
247 private:
248 //pathfinding stuff
249 	void close(const v2<int>& vertex);
250 
251 	OpenList _open_list;
252 	PointMap _points;
253 	CloseList _close_list;
254 	v2<int> _end, _begin;
255 	int _step;
256 //end of pathfinding stuff
257 
258 	struct Event : public mrt::Serializable {
259 		std::string name;
260 		bool repeat;
261 		std::string sound;
262 		float gain;
263 		bool played;
264 		mutable const Pose * cached_pose;
265 
266 		Event();
267 		Event(const std::string name, const bool repeat, const std::string &sound, const float gain, const Pose * cached_pose = NULL);
268 		virtual void serialize(mrt::Serializator &s) const;
269 		virtual void deserialize(const mrt::Serializator &s);
270 	};
271 
272 	void check_animation() const;
273 	void get_subobjects(std::set<Object *> &objects);
274 	void group_tick(const float dt);
275 
276 	mutable const Animation *_animation;
277 	mutable const AnimationModel *_model;
278 
279 	mutable const sdlx::Surface *_surface;
280 
281 	sdlx::Surface *_fadeout_surface;
282 	int _fadeout_alpha;
283 	const sdlx::CollisionMap *_cmap;
284 
285 	typedef std::deque<Event> EventQueue;
286 	EventQueue _events;
287 
288 	typedef std::map<const std::string, float> EffectMap;
289 	EffectMap _effects;
290 
291 	int _tw, _th;
292 	int _direction_idx, _directions_n;
293 	float _pos;
294 
295 	//waypoints stuff
296 	Way _way;
297 	v2<float> _next_target, _next_target_rel;
298 
299 	//rotation stuff
300 	float _rotation_time;
301 	int _dst_direction;
302 
303 	//grouped objects stuff
304 	typedef std::map<const std::string, Object *> Group;
305 	Group _group;
306 
307 	int _slot_id;
308 
309 	void set_sync(const bool sync);
310 
311 	friend class IWorld;
312 	friend class ai::Buratino;
313 	friend class ai::Waypoints;
314 	friend class RotatingObject;
315 	using BaseObject::_position;
316 
317 
318 	clunk::Object *clunk_object;
319 };
320 
321 
322 
323 #endif
324 
325