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 "registrar.h"
29 #include "config.h"
30 #include "object.h"
31 #include "item.h"
32 #include "ai/waypoints.h"
33 
34 class Car: public Object {
35 public:
Car(const std::string & classname)36 	Car(const std::string &classname) : Object(classname), _alt_fire(1, false) {}
37 	virtual void calculate(const float dt);
38 	virtual void tick(const float dt);
39 	virtual void on_spawn();
clone() const40 	virtual Object * clone() const { return new Car(*this); }
41 
42 	void emit(const std::string &event, Object * emitter);
43 
serialize(mrt::Serializator & s) const44 	virtual void serialize(mrt::Serializator &s) const {
45 		Object::serialize(s);
46 		s.add(_alt_fire);
47 	}
deserialize(const mrt::Serializator & s)48 	virtual void deserialize(const mrt::Serializator &s) {
49 		Object::deserialize(s);
50 		s.get(_alt_fire);
51 	}
52 
53 
54 protected:
55 	Alarm _alt_fire;
56 private:
57 	virtual void get_impassability_penalty(const float impassability, float &base, float &base_value, float &penalty) const;
58 };
59 
on_spawn()60 void Car::on_spawn() {
61 	if (registered_name.compare(0, 7, "static-") == 0) {
62 		disown();
63 		disable_ai = true;
64 	}
65 	_variants.add("safe");
66 	play("hold", true);
67 }
68 
get_impassability_penalty(const float impassability,float & base,float & base_value,float & penalty) const69 void Car::get_impassability_penalty(const float impassability, float &base, float &base_value, float &penalty) const {
70 	if (impassability >= 0.2) {
71 		base = 0.2;
72 		base_value = 0.5;
73 		penalty = 0;
74 		return;
75 	}
76 }
77 
emit(const std::string & event,Object * emitter)78 void Car::emit(const std::string &event, Object * emitter) {
79 	if (event == "death") {
80 		spawn("corpse", "dead-" + animation, v2<float>(), v2<float>());
81 		_dead = true;
82 		detachVehicle();
83 		Object::emit(event, emitter);
84 		return;
85 	} else if (emitter != NULL && !_velocity.is0() && event == "collision" && animation == "harvester") {
86 		const std::string &classname = emitter->classname;
87 		if (!emitter->get_variants().has("player") && (classname == "trooper" || classname == "civilian" || classname == "kamikaze" || classname == "monster")) {
88 			//LOG_DEBUG(("bloody harvest"));
89 			emitter->emit("death", NULL);
90 			if (classname != "monster")
91 				heal(5);
92 		}
93 	} else if (event == "collision" && !_variants.has("safe")) {
94 		if (emitter != NULL && emitter->speed > 0) {
95 			if (emitter->registered_name == "machinegunner" && registered_name.compare(0, 7, "static-") == 0) {
96 				return;
97 			}
98 			Item * item = dynamic_cast<Item *>(emitter);
99 			//no items.
100 			if (item == NULL) {
101 				GET_CONFIG_VALUE("objects.car.damage", int, d, 5);
102 				emitter->add_damage(this, d);
103 				emitter->add_effect("stunned", 0.1f);
104 				emit("death", emitter);
105 			}
106 		}
107 	}
108 	Object::emit(event, emitter);
109 }
110 
calculate(const float dt)111 void Car::calculate(const float dt) {
112 	Object::calculate(dt);
113 	GET_CONFIG_VALUE("objects." + registered_name + ".rotation-time", float, rt, 0.05f);
114 	limit_rotation(dt, rt, true, false);
115 }
116 
tick(const float dt)117 void Car::tick(const float dt) {
118 	if (_alt_fire.tick(dt) && _state.alt_fire) {
119 		_alt_fire.reset();
120 		play_random_sound("klaxon", false);
121 	}
122 	Object::tick(dt);
123 	if (_velocity.is0() && get_state() != "hold") {
124 		cancel_all();
125 		play("hold", true);
126 	} else if (!_velocity.is0() && get_state() != "move") {
127 		cancel_all();
128 		play("move", true);
129 	}
130 }
131 
132 class AICar : public Car, public ai::Waypoints {
133 public:
AICar(const std::string & classname)134 	AICar(const std::string &classname) : Car(classname){}
135 	virtual void calculate(const float dt);
clone() const136 	virtual Object * clone() const {return new AICar(*this);}
137 	virtual void on_spawn();
138 
serialize(mrt::Serializator & s) const139 	virtual void serialize(mrt::Serializator &s) const {
140 		Car::serialize(s);
141 		ai::Waypoints::serialize(s);
142 	}
deserialize(const mrt::Serializator & s)143 	virtual void deserialize(const mrt::Serializator &s) {
144 		Car::deserialize(s);
145 		ai::Waypoints::deserialize(s);
146 	}
147 
148 private:
149 	virtual void onObstacle(const Object *o);
150 };
151 
on_spawn()152 void AICar::on_spawn() {
153 	Car::on_spawn();
154 	//obstacle_filter.insert("car");
155 	//obstacle_filter.insert("civilian");
156 	//obstacle_filter.insert("trooper");
157 	//obstacle_filter.insert("fighting-vehicle");
158 	_avoid_obstacles = true;
159 
160 	ai::Waypoints::on_spawn(this);
161 	_alt_fire.set(5);
162 	//GET_CONFIG_VALUE("objects.car.refreshing-path-interval", float, rpi, 1);
163 	//_refresh_waypoints.set(rpi);
164 
165 	disown();
166 }
167 
168 
onObstacle(const Object * o)169 void AICar::onObstacle(const Object *o) {
170 /*
171 	if ((idx % 21) == 1) { //approx once per 5 second
172 		play_random_sound("klaxon", false);
173 	}
174 */
175 	_state.alt_fire = true;
176 }
177 
calculate(const float dt)178 void AICar::calculate(const float dt) {
179 	ai::Waypoints::calculate(this, dt);
180 
181 	float rt;
182 	Config->get("objects." + registered_name + ".rotation-time", rt, 0.05f);
183 	limit_rotation(dt, rt, true, false);
184 	update_state_from_velocity();
185 }
186 
187 REGISTER_OBJECT("static-car", AICar, ("vehicle"));
188 REGISTER_OBJECT("car", AICar, ("car"));
189