1 /* Battle Tanks Game
2  * Copyright (C) 2006-2009 Battle Tanks team
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 /*
20  * Additional rights can be granted beyond the GNU General Public License
21  * on the terms provided in the Exception. If you modify this file,
22  * you may extend this exception to your version of the file,
23  * but you are not obligated to do so. If you do not wish to provide this
24  * exception without modification, you must delete this exception statement
25  * from your version and license this file solely under the GPL without exception.
26 */
27 
28 #include "object.h"
29 #include "registrar.h"
30 #include "config.h"
31 #include "destructable_object.h"
32 #include "mrt/random.h"
33 #include "ai/base.h"
34 #include "ai/targets.h"
35 #include "special_owners.h"
36 
37 class PillBox : public DestructableObject, protected ai::Base {
38 	Alarm _reaction, _fire;
39 	std::string _object;
40 public:
PillBox(const std::string & object)41 	PillBox(const std::string &object) :
42 		DestructableObject("pillbox"), _reaction(true), _fire(false), _object(object) {}
43 
clone() const44 	virtual Object * clone() const { return new PillBox(*this); }
45 
on_spawn()46 	virtual void on_spawn() {
47 		GET_CONFIG_VALUE("objects.pillbox.reaction-time", float, rt, 0.1);
48 		mrt::randomize(rt, rt / 2);
49 		_reaction.set(rt);
50 
51 		GET_CONFIG_VALUE("objects.pillbox.fire-rate", float, fr, 0.2);
52 		_fire.set(fr);
53 
54 		DestructableObject::on_spawn();
55 		ai::Base::on_spawn(this);
56 		ai::Base::multiplier = 5.0f;
57 	}
58 
serialize(mrt::Serializator & s) const59 	virtual void serialize(mrt::Serializator &s) const {
60 		DestructableObject::serialize(s);
61 		ai::Base::serialize(s);
62 		s.add(_reaction);
63 		s.add(_fire);
64 		s.add(_object);
65 	}
deserialize(const mrt::Serializator & s)66 	virtual void deserialize(const mrt::Serializator &s) {
67 		DestructableObject::deserialize(s);
68 		ai::Base::deserialize(s);
69 		s.get(_reaction);
70 		s.get(_fire);
71 		s.get(_object);
72 	}
73 
tick(const float dt)74 	virtual void tick(const float dt) {
75 		Object::tick(dt);
76 		if (!_broken && _state.fire) {
77 
78 			bool fire = false;
79 			if (_fire.tick(dt)) {
80 				_fire.reset();
81 				if (canFire()) {
82 					fire = true;
83 					spawn(_object, _object, v2<float>(), _direction);
84 				}
85 			}
86 
87 			int dirs = 16/* bullet->get_directions_number() */, d = _direction.get_direction(dirs);
88 			v2<float> dpos;
89 			dpos.fromDirection((d + dirs / 4) % dirs, dirs);
90 			dpos *= 16;
91 
92 			if (fire) {
93 				spawn(_object, _object, dpos, _direction);
94 				spawn(_object, _object, -dpos, _direction);
95 			}
96 		}
97 	}
98 
calculate(const float dt)99 	virtual void calculate(const float dt) {
100 		if (!_reaction.tick(dt))
101 			return;
102 
103 		float range = getWeaponRange(_object);
104 		//LOG_DEBUG(("range = %g", range));
105 
106 		_state.fire = false;
107 
108 		const Object * result = NULL;
109 		float dist = -1;
110 
111 		std::set<const Object *> objects;
112 		enumerate_objects(objects, range, &ai::Targets->troops );
113 		for(std::set<const Object *>::const_iterator i = objects.begin(); i != objects.end(); ++i) {
114 			const Object *target = *i;
115 			if (has_same_owner(target) || target->ai_disabled() || target->pierceable || target->impassability == 0 || target->hp <= 0)
116 				continue;
117 
118 			v2<float> dpos = get_relative_position(target);
119 			if (check_distance(get_center_position(), target->get_center_position(), get_z(), true)) {
120 				if (result == NULL || dpos.quick_length() < dist) {
121 					result = target;
122 					dist = dpos.quick_length();
123 				}
124 			}
125 		}
126 
127 		if (result != NULL) {
128 			_state.fire = true;
129 			_direction = get_relative_position(result);
130 			_direction.normalize();
131 			//set_direction(_direction.get_direction(get_directions_number()) - 1);
132 		}
133 	}
134 
onBreak()135 	virtual void onBreak() {
136 		Object *o = spawn("explosion", "cannon-explosion");
137 		o->set_z(get_z() + 1, true);
138 		for(int i = 0; i < 2; ++i) {
139 			o = spawn("machinegunner", "machinegunner", size / 2);
140 			o->copy_special_owners(this);
141 		}
142 	}
143 };
144 
145 REGISTER_OBJECT("pillbox", PillBox, ("machinegunner-bullet"));
146