2001-01-25 10:37:55 +01:00
|
|
|
|
/* vi: set ts=2:
|
|
|
|
|
*
|
2001-12-10 01:13:39 +01:00
|
|
|
|
*
|
2003-07-29 11:48:03 +02:00
|
|
|
|
* Eressea PB(E)M host Copyright (C) 1998-2003
|
2001-01-25 10:37:55 +01:00
|
|
|
|
* Christian Schlittchen (corwin@amber.kn-bremen.de)
|
|
|
|
|
* Katja Zedel (katze@felidae.kn-bremen.de)
|
|
|
|
|
* Henning Peters (faroul@beyond.kn-bremen.de)
|
|
|
|
|
* Enno Rehling (enno@eressea-pbem.de)
|
|
|
|
|
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
|
|
|
|
|
*
|
|
|
|
|
* This program may not be used, modified or distributed without
|
|
|
|
|
* prior permission by the authors of Eressea.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <eressea.h>
|
|
|
|
|
#include "weapons.h"
|
|
|
|
|
|
|
|
|
|
#include <unit.h>
|
|
|
|
|
#include <build.h>
|
|
|
|
|
#include <race.h>
|
|
|
|
|
#include <item.h>
|
|
|
|
|
#include <battle.h>
|
2002-04-23 21:00:23 +02:00
|
|
|
|
#include <pool.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* util includes */
|
2006-02-19 23:43:56 +01:00
|
|
|
|
#include <util/functions.h>
|
|
|
|
|
#include <util/rng.h>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
/* libc includes */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
|
|
enum {
|
2006-02-12 00:18:10 +01:00
|
|
|
|
WP_NONE,
|
|
|
|
|
WP_MAX
|
2001-01-25 10:37:55 +01:00
|
|
|
|
};
|
|
|
|
|
|
2002-04-27 16:46:27 +02:00
|
|
|
|
/* damage types */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-04-27 16:46:27 +02:00
|
|
|
|
#define CUT (1<<0)
|
|
|
|
|
#define PIERCE (1<<1)
|
|
|
|
|
#define BASH (1<<2)
|
|
|
|
|
#define ARMORPIERCING (1<<3)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
typedef struct weapondata {
|
2006-02-12 00:18:10 +01:00
|
|
|
|
double magres;
|
|
|
|
|
const char *damfoot;
|
|
|
|
|
const char *damhorse;
|
|
|
|
|
item_t item;
|
|
|
|
|
skill_t skill;
|
|
|
|
|
char attmod;
|
|
|
|
|
char defmod;
|
|
|
|
|
boolean rear;
|
|
|
|
|
boolean is_magic;
|
|
|
|
|
struct reload {
|
|
|
|
|
int type;
|
|
|
|
|
char time;
|
|
|
|
|
} reload;
|
|
|
|
|
char damage_type;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
} weapondata;
|
|
|
|
|
|
|
|
|
|
static weapondata weapontable[WP_MAX + 1] =
|
|
|
|
|
/* MagRes, Schaden/Fu<46>, Schaden/Pferd, Item, Skill, OffMod, DefMod,
|
2004-06-11 21:59:02 +02:00
|
|
|
|
* missile, is_magic */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
/* Unbewaffnet */
|
2006-02-11 17:11:16 +01:00
|
|
|
|
{0.00, "1d5+0", "1d6+0", MAX_ITEMS, SK_MELEE, 0, 0, false, false, { 0, 0}, BASH },
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* Dummy */
|
2006-02-11 17:11:16 +01:00
|
|
|
|
{0.00, "0d0+0", "0d0+0", MAX_ITEMS, SK_MELEE, 0, 0, false, false, { 0, 0}, 0 }
|
2001-01-25 10:37:55 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
weapon_type * oldweapontype[WP_MAX];
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
|
|
|
|
static boolean
|
2006-07-30 14:52:26 +02:00
|
|
|
|
attack_firesword(const troop * at, const struct weapon_type * wtype, int *casualties)
|
2001-12-10 01:13:39 +01:00
|
|
|
|
{
|
2006-07-30 14:52:26 +02:00
|
|
|
|
fighter *fi = at->fighter;
|
|
|
|
|
troop dt;
|
|
|
|
|
int killed = 0;
|
|
|
|
|
const char *damage = "2d8";
|
|
|
|
|
int force = 1+rng_int()%10;
|
|
|
|
|
int enemies = count_enemies(fi->side->battle, fi, 0, 1, SELECT_ADVANCE|SELECT_DISTANCE);
|
|
|
|
|
|
|
|
|
|
if (!enemies) {
|
|
|
|
|
if (casualties) *casualties = 0;
|
|
|
|
|
return true; /* if no enemy found, no use doing standarad attack */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fi->catmsg == -1) {
|
|
|
|
|
int i, k=0;
|
|
|
|
|
for (i=0;i<=at->index;++i) {
|
|
|
|
|
struct weapon * wp = fi->person[i].melee;
|
|
|
|
|
if (wp!=NULL && wp->type == wtype) ++k;
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "%d K<>mpfer aus %s benutz%s Flammenschwert%s:", k, unitname(fi->unit),
|
|
|
|
|
(k==1)?"t sein ":"en ihre",(k==1)?"":"er");
|
|
|
|
|
battlerecord(fi->side->battle, buf);
|
|
|
|
|
fi->catmsg = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
dt = select_enemy(fi, 0, 1, SELECT_ADVANCE|SELECT_DISTANCE);
|
|
|
|
|
assert(dt.fighter);
|
|
|
|
|
--force;
|
|
|
|
|
killed += terminate(dt, *at, AT_SPELL, damage, 1);
|
|
|
|
|
} while (force && killed < enemies);
|
|
|
|
|
if (casualties) *casualties = killed;
|
|
|
|
|
return true;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2002-04-23 21:00:23 +02:00
|
|
|
|
#define CATAPULT_ATTACKS 6
|
|
|
|
|
|
2001-12-10 01:13:39 +01:00
|
|
|
|
static boolean
|
2006-07-30 14:52:26 +02:00
|
|
|
|
attack_catapult(const troop * at, const struct weapon_type * wtype, int * casualties)
|
2001-12-10 01:13:39 +01:00
|
|
|
|
{
|
2006-07-30 14:52:26 +02:00
|
|
|
|
fighter *af = at->fighter;
|
|
|
|
|
unit *au = af->unit;
|
|
|
|
|
battle * b = af->side->battle;
|
|
|
|
|
troop dt;
|
|
|
|
|
int d = 0, enemies;
|
|
|
|
|
weapon * wp = af->person[at->index].missile;
|
2005-01-30 15:30:31 +01:00
|
|
|
|
static item_type * it_catapultammo = NULL;
|
|
|
|
|
if (it_catapultammo==NULL) {
|
|
|
|
|
it_catapultammo = it_find("catapultammo");
|
|
|
|
|
}
|
2002-04-23 21:00:23 +02:00
|
|
|
|
|
2006-07-30 14:52:26 +02:00
|
|
|
|
assert(wp->type==wtype);
|
|
|
|
|
assert(af->person[at->index].reload==0);
|
2002-04-23 21:00:23 +02:00
|
|
|
|
|
2005-01-30 15:30:31 +01:00
|
|
|
|
if (it_catapultammo!=NULL) {
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (get_pooled(au, it_catapultammo->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, 1) <= 0) {
|
2005-01-30 15:30:31 +01:00
|
|
|
|
/* No ammo. Use other weapon if available. */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2006-07-30 14:52:26 +02:00
|
|
|
|
enemies = count_enemies(b, af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
|
|
|
|
|
enemies = min(enemies, CATAPULT_ATTACKS);
|
|
|
|
|
if (enemies==0) {
|
|
|
|
|
return true; /* allow further attacks */
|
|
|
|
|
}
|
2002-04-23 21:00:23 +02:00
|
|
|
|
|
2006-07-30 14:52:26 +02:00
|
|
|
|
if (af->catmsg == -1) {
|
|
|
|
|
int i, k=0;
|
|
|
|
|
for (i=0;i<=at->index;++i) {
|
|
|
|
|
if (af->person[i].reload==0 && af->person[i].missile == wp) ++k;
|
|
|
|
|
}
|
|
|
|
|
sprintf(buf, "%d K<>mpfer aus %s feuer%s Katapult ab:", k, unitname(au), (k==1)?"t sein":"n ihr");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
af->catmsg = 0;
|
|
|
|
|
}
|
2002-04-23 21:00:23 +02:00
|
|
|
|
|
2005-01-30 15:30:31 +01:00
|
|
|
|
if (it_catapultammo!=NULL) {
|
2005-10-30 16:42:15 +01:00
|
|
|
|
use_pooled(au, it_catapultammo->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, 1);
|
2005-01-30 15:30:31 +01:00
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|
2006-07-30 14:52:26 +02:00
|
|
|
|
while (--enemies >= 0) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
/* Select defender */
|
2006-07-30 14:52:26 +02:00
|
|
|
|
dt = select_enemy(af, FIGHT_ROW, FIGHT_ROW, SELECT_ADVANCE);
|
2001-12-10 01:13:39 +01:00
|
|
|
|
if (!dt.fighter)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* If battle succeeds */
|
|
|
|
|
if (hits(*at, dt, wp)) {
|
|
|
|
|
d += terminate(dt, *at, AT_STANDARD, wp->type->damage[0], true);
|
|
|
|
|
#ifdef CATAPULT_STRUCTURAL_DAMAGE
|
2006-02-19 23:43:56 +01:00
|
|
|
|
if (dt.fighter->unit->building && rng_int()%100 < 5) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
damage_building(b, dt.fighter->unit->building, 1);
|
2006-02-19 23:43:56 +01:00
|
|
|
|
} else if (dt.fighter->unit->ship && rng_int()%100 < 5) {
|
2001-12-10 01:13:39 +01:00
|
|
|
|
dt.fighter->unit->ship->damage+=DAMAGE_SCALE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (casualties) *casualties = d;
|
2002-01-20 12:03:50 +01:00
|
|
|
|
return false; /* keine weitren attacken */
|
2001-12-10 01:13:39 +01:00
|
|
|
|
}
|
|
|
|
|
|
2001-01-25 10:37:55 +01:00
|
|
|
|
static void
|
|
|
|
|
init_oldweapons(void)
|
|
|
|
|
{
|
|
|
|
|
int w;
|
2006-02-11 17:11:16 +01:00
|
|
|
|
for (w=0;w!=WP_MAX && weapontable[w].item!=MAX_ITEMS;++w) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
const char * damage[2];
|
|
|
|
|
item_type * itype = olditemtype[weapontable[w].item];
|
|
|
|
|
int minskill = 1, wflags = WTF_NONE;
|
2005-07-31 21:22:14 +02:00
|
|
|
|
int m;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
weapon_mod * modifiers = NULL;
|
2006-07-30 14:52:26 +02:00
|
|
|
|
boolean (*no_special_attack)(const troop *, const struct weapon_type *, int *) = NULL;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
assert(itype!=NULL || !"item not initialized");
|
|
|
|
|
|
|
|
|
|
if (weapontable[w].rear) wflags |= WTF_MISSILE;
|
|
|
|
|
if (weapontable[w].is_magic) wflags |= WTF_MAGICAL;
|
|
|
|
|
if (weapontable[w].damage_type & CUT) wflags |= WTF_CUT;
|
|
|
|
|
if (weapontable[w].damage_type & PIERCE) wflags |= WTF_PIERCE;
|
|
|
|
|
if (weapontable[w].damage_type & BASH) wflags |= WTF_BLUNT;
|
2002-04-27 16:46:27 +02:00
|
|
|
|
if (weapontable[w].damage_type & ARMORPIERCING) wflags |= WTF_ARMORPIERCING;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
damage[0] = weapontable[w].damfoot;
|
|
|
|
|
damage[1] = weapontable[w].damhorse;
|
|
|
|
|
|
|
|
|
|
oldweapontype[w] = new_weapontype(itype, wflags, weapontable[w].magres, damage, weapontable[w].attmod, weapontable[w].defmod, weapontable[w].reload.time, weapontable[w].skill, minskill);
|
|
|
|
|
oldweapontype[w]->modifiers = modifiers;
|
2006-07-30 14:52:26 +02:00
|
|
|
|
oldweapontype[w]->attack = no_special_attack;
|
2005-07-31 21:22:14 +02:00
|
|
|
|
|
|
|
|
|
#ifdef SCORE_MODULE
|
|
|
|
|
if (itype->construction->materials==NULL) {
|
|
|
|
|
itype->score = 6000;
|
|
|
|
|
} else for (m=0;itype->construction->materials[m].number;++m) {
|
2005-10-29 13:17:21 +02:00
|
|
|
|
const resource_type * rtype = itype->construction->materials[m].rtype;
|
2005-07-31 21:22:14 +02:00
|
|
|
|
int score = rtype->itype?rtype->itype->score:5;
|
|
|
|
|
itype->score = 2*itype->construction->materials[m].number * score;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2005-10-29 18:28:10 +02:00
|
|
|
|
register_weapons(void)
|
|
|
|
|
{
|
2005-10-31 23:34:45 +01:00
|
|
|
|
register_function((pf_generic)attack_catapult, "attack_catapult");
|
|
|
|
|
register_function((pf_generic)attack_firesword, "attack_firesword");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2002-01-09 09:20:33 +01:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_weapons(void)
|
|
|
|
|
{
|
2005-10-31 23:34:45 +01:00
|
|
|
|
init_oldweapons();
|
2002-01-09 09:20:33 +01:00
|
|
|
|
}
|