1 
2 /* Battle Tanks Game
3  * Copyright (C) 2006-2009 Battle Tanks team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19 
20 /*
21  * Additional rights can be granted beyond the GNU General Public License
22  * on the terms provided in the Exception. If you modify this file,
23  * you may extend this exception to your version of the file,
24  * but you are not obligated to do so. If you do not wish to provide this
25  * exception without modification, you must delete this exception statement
26  * from your version and license this file solely under the GPL without exception.
27 */
28 
29 #define _USE_MATH_DEFINES
30 #include <math.h>
31 #include "object.h"
32 #include "registrar.h"
33 #include "resource_manager.h"
34 #include "alarm.h"
35 #include "config.h"
36 #include "trooper.h"
37 #include "game_monitor.h"
38 #include "rt_config.h"
39 #include <string.h>
40 
get_impassability_penalty(const float impassability,float & base,float & base_value,float & penalty) const41 void Trooper::get_impassability_penalty(const float impassability, float &base, float &base_value, float &penalty) const {
42 	if (impassability > 0.2f) {
43 		base_value = 0.2f;
44 		base = 0;
45 		penalty = 0;
46 	}
47 }
48 
tick(const float dt)49 void Trooper::tick(const float dt) {
50 	set_direction(_velocity.get_direction8() - 1);
51 	Object::tick(dt);
52 
53 	if (!_state.fire) {
54 		if (get_state() == "fire")
55 			cancel_all();
56 	}
57 
58 	if (_velocity.is0()) {
59 		const std::string state = get_state();
60 		if (state != "hold" && state != "fire" && state != "throw") {
61 			cancel_all();
62 			play("hold", true);
63 			if (has("helmet")) {
64 				Object *helmet = get("helmet");
65 				helmet->cancel_all();
66 				helmet->play("hold", true);
67 			}
68 		}
69 	} else {
70 		const std::string state = get_state();
71 		if (state == "hold" || state.empty()) {
72 			cancel_all();
73 			play("run", true);
74 			if (has("helmet")) {
75 				Object *helmet = get("helmet");
76 				helmet->cancel_all();
77 				helmet->play("run", true);
78 			}
79 		}
80 	}
81 
82 	if (!_object.empty() && _fire.tick(dt) && _state.fire && !_variants.has("nukeman")) {
83 		_fire.reset();
84 		if (disable_ai || validateFire(0)) {
85 			if (get_state() != "fire") {
86 				cancel_all();
87 				play("fire", true);
88 			}
89 			spawn(_object, _object, v2<float>(), _direction);
90 		}
91 	}
92 	if (_alt_fire.tick(dt) && _state.alt_fire) {
93 		_alt_fire.reset();
94 		if (_variants.has("nukeman")) {
95 			//MUGGAGAGAGAGAG!!!
96 			Object *o = spawn("nuke-explosion", "nuke-explosion");
97 			emit("death", o);
98 		} else if (!_variants.has("no-grenades")) {
99 			if (get_state() != "throw")
100 				play_now("throw");
101 			spawn("grenade", "grenade", v2<float>(), _direction);
102 		}
103 	}
104 }
105 
take(const BaseObject * obj,const std::string & type)106 const bool Trooper::take(const BaseObject *obj, const std::string &type) {
107 	if (obj->classname == "missiles" && type == "nuke" && _variants.has("player") && !_variants.has("nukeman")) {
108 		if (GameMonitor->getCampaign() != NULL || RTConfig->game_type == GameTypeCTF)
109 			return Object::take(obj, type);
110 
111 		_variants.add("nukeman");
112 		hp = max_hp = 999;
113 		init("nukeman");
114 		invalidate();
115 		return true;
116 	}
117 	return Object::take(obj, type);
118 }
119 
120 #include "world.h"
121 
on_spawn()122 void Trooper::on_spawn() {
123 	if (_variants.has("player")) {
124 		speed *= 1.75f;
125 		hp = max_hp *= 2;
126 	}
127 
128 	int sid = get_summoner();
129 	const Object *summoner = World->getObjectByID(sid);
130 	if (summoner != NULL) {
131 		const std::string &a = summoner->animation;
132 		static const char *colors[4] = {"red-", "green-", "yellow-", "blue-"};
133 		int i;
134 		for(i = 0; i < 4; ++i) {
135 			size_t l = strlen(colors[i]);
136 			if (a.size() > l && a.compare(0, l, colors[i]) == 0)
137 				break;
138 		}
139 		if (i < 4) {
140 			std::string animation = colors[i] + registered_name + "-helmet";
141 			//LOG_DEBUG(("helmet animation = %s", animation.c_str()));
142 			if (ResourceManager->hasAnimation(animation)) {
143 				add("helmet", "helmet", animation, v2<float>(), Centered);
144 			}
145 		}
146 	}
147 
148 	if (_variants.has("disembark")) {
149 		play_sound("disembark", false);
150 		//add helmet if parent player detected.
151 	}
152 	GET_CONFIG_VALUE("objects.trooper.grenade-rate", float, gr, 1.2f);
153 	_alt_fire.set(gr);
154 
155 	if (_object.empty()) {
156 		//nothing to do
157 	} else if (_object == "thrower-missile") {
158 		GET_CONFIG_VALUE("objects.thrower.fire-rate", float, fr, 3);
159 		_fire.set(fr);
160 	} else if (_object == "machinegunner-bullet") {
161 		GET_CONFIG_VALUE("objects.machinegunner.fire-rate", float, fr, 0.2);
162 		_fire.set(fr);
163 	} else throw_ex(("unsupported weapon %s", _object.c_str()));
164 
165 	play("hold", true);
166 	_pose = "run";
167 }
168 
can_attach(Object * vehicle) const169 bool Trooper::can_attach(Object *vehicle) const {
170 	if (registered_name == "machinegunner-player")
171 		return true;
172 
173 	if (!disable_ai)
174 		return false;
175 
176 	v2<float> rel = get_relative_position(vehicle);
177 	rel.normalize();
178 	v2<float> dir = vehicle->get_direction_vector();
179 	dir.normalize();
180 	float c = - rel.x * dir.x - rel.y * dir.y;
181 	//LOG_DEBUG(("cos = %g", c));
182 	if (c > 0.8660254037844386468) //sqrt(3) / 2
183 		return false;
184 
185 	return true;
186 }
187 
emit(const std::string & event,Object * emitter)188 void Trooper::emit(const std::string &event, Object * emitter) {
189 	if (event == "death") {
190 		spawn("corpse(human-death)", "dead-" + animation, v2<float>(), v2<float>());
191 	} else if (event == "collision" && emitter != NULL && emitter->classname == "vehicle" && !_variants.has("nukeman")) {
192 		if (can_attach(emitter) && attachVehicle(emitter))
193 			return;
194 	}
195 	Object::emit(event, emitter);
196 }
197 
validateFire(const int idx)198 const bool Trooper::validateFire(const int idx) {
199 	return true;
200 }
201 
clone() const202 Object* Trooper::clone() const  {
203 	return new Trooper(*this);
204 }
205