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