2 // nazghul - an old-school RPG engine
3 // Copyright (C) 2002, 2003 Gordon McNutt
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License as published by the Free
7 // Software Foundation; either version 2 of the License, or (at your option)
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 // You should have received a copy of the GNU General Public License along with
16 // this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
17 // Suite 330, Boston, MA 02111-1307 USA
20 // gmcnutt@users.sourceforge.net
35 /* This is the number of wilderness turns an unnamed vehicle will hang around
36 * before being garbage collected. Note that wilderness turns only pass when
37 * the player is actually walking around in the wilderness. Kamping, loitering
38 * and combat don't count. */
39 #define VEHICLE_DEF_TTL 256
43 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
50 VehicleType::VehicleType(const char *tag, const char *name, struct sprite *sprite,
51 struct terrain_map *_map,
58 int _tailwind_penalty,
59 int _headwind_penalty,
60 int _crosswind_penalty,
64 : ObjectType(tag, name, sprite, vehicle_layer)
69 is_vulnerable = _vulnerable;
70 kills_occupants = _killsOccupants;
71 must_turn = _mustTurn;
72 mv_desc = strdup(_mv_desc);
75 tailwind_penalty = _tailwind_penalty;
76 headwind_penalty = _headwind_penalty;
77 crosswind_penalty = _crosswind_penalty;
79 max_hp = _max_hp; // override base class default
80 speed = _speed; // override base class default
83 VehicleType::~ VehicleType()
89 class Object *VehicleType::createInstance()
91 class Vehicle *obj = new Vehicle(this);
96 int VehicleType::getWindPenalty(int facing)
98 int vdx, vdy, wdx, wdy, base_speed;
100 base_speed = getSpeed();
105 vdx = directionToDx(facing);
106 vdy = directionToDy(facing);
107 wdx = directionToDx(windGetDirection());
108 wdy = directionToDy(windGetDirection());
110 // take the vector dot product
111 int dotprod = (vdx * wdx + vdy * wdy);
114 return tailwind_penalty;
115 } else if (0 == dotprod) {
116 // tacking across the wind
117 return crosswind_penalty;
120 return headwind_penalty;
124 bool VehicleType::mustTurn()
129 bool VehicleType::isVulnerable()
131 return is_vulnerable;
134 bool VehicleType::killsOccupants()
136 return kills_occupants;
139 int VehicleType::getType()
141 return VEHICLE_TYPE_ID;
144 bool VehicleType::isType(int classID)
146 if (classID == VEHICLE_TYPE_ID)
148 return ObjectType::isType(classID);
151 class ArmsType *VehicleType::getOrdnance()
156 char *VehicleType::getMvDesc()
161 sound_t *VehicleType::get_movement_sound()
166 // ----------------------------------------------------------------------------
170 // ----------------------------------------------------------------------------
172 // ----------------------------------------------------------------------------
173 // The constructor used by VehicleType::createInstance()
174 // ----------------------------------------------------------------------------
175 Vehicle::Vehicle(VehicleType *type)
176 : Object(type), name(0)
179 hp = type->getMaxHp();
183 // ----------------------------------------------------------------------------
184 // The constructor used by kern_mk_vehicle()
185 // ----------------------------------------------------------------------------
186 Vehicle::Vehicle(VehicleType *type, int _facing, int _hp)
187 : Object(type), name(0)
200 int Vehicle::get_facing_to_fire_weapon(int dx, int dy)
209 bool Vehicle::fire_weapon(int dx, int dy, class Object *user)
211 class ArmsType *ordnance;
213 ordnance = getOrdnance();
217 int vdir = getFacing();
218 if (((vdir == NORTH || vdir == SOUTH) && dy) ||
219 ((vdir == EAST || vdir == WEST) && dx)) {
223 ordnance->fireInDirection(getPlace(), getX(), getY(), dx, dy, user);
227 bool Vehicle::turn(int dx, int dy, int *cost)
231 if (getFacing() == vector_to_facing(dx, dy))
234 if (!setFacing(vector_to_facing(dx, dy)))
237 *cost = getObjectType()->getSpeed();
241 int Vehicle::getMovementCostMultiplier()
243 return getObjectType()->getWindPenalty(getFacing());
246 void Vehicle::damage(int amount)
248 Object::damage(amount);
251 hp = min(hp, getObjectType()->getMaxHp());
257 struct formation *Vehicle::get_formation()
259 return getObjectType()->formation;
262 struct place *Vehicle::getPlace()
265 return occupant->getPlace();
266 return Object::getPlace();
271 if (occupant != NULL)
272 return occupant->getX();
273 return Object::getX();
278 if (occupant != NULL)
279 return occupant->getY();
280 return Object::getY();
283 bool Vehicle::mustTurn()
285 return getObjectType()->mustTurn();
288 bool Vehicle::isVulnerable()
290 return getObjectType()->isVulnerable();
293 void Vehicle::destroy()
297 if (occupant != NULL &&
298 getObjectType()->killsOccupants()) {
304 bool Vehicle::isType(int classID)
306 if (classID == VEHICLE_ID)
308 return Object::isType(classID);
311 int Vehicle::getType()
316 class VehicleType *Vehicle::getObjectType()
318 return (class VehicleType *) Object::getObjectType();
321 class ArmsType *Vehicle::getOrdnance()
323 return getObjectType()->getOrdnance();
326 char *Vehicle::getMvDesc()
328 return getObjectType()->getMvDesc();
331 sound_t *Vehicle::get_movement_sound()
333 return getObjectType()->get_movement_sound();
336 void Vehicle::save(struct save *save)
338 save->enter(save, "(let ((kveh (kern-mk-vehicle %s %d %d)))\n",
339 getObjectType()->getTag(), getFacing(), getHp());
341 save->write(save, "(kern-vehicle-set-name kveh \"%s\")\n", name);
343 if (getTTL() != -1) {
344 save->write(save, "(kern-obj-set-ttl kveh %d)\n", getTTL());
346 save->exit(save, "kveh) ;; vehicle \n");
349 struct mmode *Vehicle::getMovementMode()
351 return getObjectType()->mmode;
354 const char *Vehicle::getName()
358 return Object::getName();
361 void Vehicle::setName(char *val)
367 class Object *Vehicle::getOccupant()
372 void Vehicle::setOccupant(class Object *val)
377 obj_inc_ref(occupant);
378 Object::setTTL(this, -1);
379 } else if (occupant) {
380 obj_dec_ref(occupant);
383 /* Unnamed vehicles will expire after a while. */
385 Object::setTTL(this, VEHICLE_DEF_TTL);
390 bool Vehicle::isNamed()
395 void Vehicle::describe()
398 log_continue("%s", name);