server/src/common/kernel/combatspells.c

1776 lines
39 KiB
C
Raw Normal View History

/* vi: set ts=2:
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea-pbem.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
This program may not be used, modified or distributed
without prior permission by the authors of Eressea.
*/
2001-01-25 10:37:55 +01:00
#include <config.h>
#include "eressea.h"
/* kernel includes */
#include "battle.h"
2001-01-25 10:37:55 +01:00
#include "build.h"
#include "building.h"
#include "faction.h"
#include "item.h"
#include "magic.h"
#include "region.h"
#include "unit.h"
2001-01-25 10:37:55 +01:00
#include "movement.h"
#include "spell.h"
#include "race.h"
#include "skill.h"
2001-01-25 10:37:55 +01:00
/* util includes */
#include <rand.h>
/* libc includes */
#include <assert.h>
#include <stdlib.h>
#define EFFECT_HEALING_SPELL 5
/* ------------------------------------------------------------------ */
/* Kampfzauberfunktionen */
/* COMBAT */
static const char *
spell_damage(int sp)
{
switch (sp) {
case 0:
/* meist t<>dlich 20-65 HP */
return "5d10+15";
case 1:
/* sehr variabel 4-48 HP */
return "4d12";
case 2:
/* leicht verwundet 4-18 HP */
return "2d8+2";
2001-02-11 23:13:07 +01:00
case 3:
/* fast immer t<>dlich 30-50 HP */
return "5d5+25";
case 4:
/* verwundet 11-26 HP */
return "3d6+8";
2001-01-25 10:37:55 +01:00
default:
/* schwer verwundet 14-34 HP */
return "4d6+10";
}
}
static int
get_force(int power, int formel)
{
switch (formel) {
case 0:
/* (4,8,12,16,20,24,28,32,36,40,44,..)*/
return (power * 4);
case 1:
/* (15,30,45,60,75,90,105,120,135,150,165,..) */
return (power*15);
case 2:
/* (40,80,120,160,200,240,280,320,360,400,440,..)*/
return (power*40);
case 3:
/* (2,8,18,32,50,72,98,128,162,200,242,..)*/
return (power*power*2);
case 4:
/* (4,16,36,64,100,144,196,256,324,400,484,..)*/
return (power*power*4);
case 5:
/* (10,40,90,160,250,360,490,640,810,1000,1210,1440,..)*/
return (power*power*10);
2001-02-11 23:19:55 +01:00
case 6:
/* (6,24,54,96,150,216,294,384,486,600,726,864)*/
2001-02-11 23:19:55 +01:00
return (power*power*6);
2001-01-25 10:37:55 +01:00
default:
return power;
}
}
/* Generischer Kampfzauber */
int
sp_kampfzauber(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
troop dt;
troop at;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int force, enemies;
int killed = 0;
const char *damage;
at.fighter = fi;
at.index = 0;
if (power <= 0) return 0;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
switch(sp->id) {
/* lovar halbiert im Schnitt! */
2001-01-25 10:37:55 +01:00
case SPL_FIREBALL:
damage = spell_damage(0);
force = lovar(get_force(power,0));
break;
case SPL_HAGEL:
damage = spell_damage(2);
force = lovar(get_force(power,4));
break;
case SPL_METEORRAIN:
damage = spell_damage(1);
force = lovar(get_force(power,1));
break;
default:
damage = spell_damage(10);
force = lovar(get_force(power,10));
}
enemies = count_enemies(b, fi->side, FS_ENEMY,
2001-01-25 10:37:55 +01:00
minrow, maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
do {
dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
assert(dt.fighter);
--force;
killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
} while (force && killed < enemies);
sprintf(buf, "%d Personen %s get<65>tet",
killed, killed == 1 ? "wurde" : "wurden");
scat(".");
battlerecord(b, buf);
return level;
}
/* Versteinern */
int
sp_versteinern(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
/* Wirkt auf erste und zweite Reihe */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW;
int force, enemies;
int stoned = 0;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
force = lovar(get_force(power,0));
enemies = count_enemies(b, fi->side, FS_ENEMY,
2001-01-25 10:37:55 +01:00
minrow, maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
do {
troop dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
fighter * df = dt.fighter;
unit * du = df->unit;
if (is_magic_resistant(mage, du, 0) == false) {
/* person ans ende hinter die lebenden schieben */
struct person p = dt.fighter->person[dt.index];
++dt.fighter->removed;
++dt.fighter->side->removed;
2001-01-25 10:37:55 +01:00
++stoned;
dt.fighter->person[dt.index] = dt.fighter->person[df->alive-df->removed];
dt.fighter->person[(df->alive - df->removed)] = p;
2001-01-25 10:37:55 +01:00
}
--force;
} while (force && stoned < enemies);
sprintf(buf, "%d Personen %s versteinert.",
stoned, stoned == 1 ? "wurde" : "wurden");
battlerecord(b, buf);
return level;
}
/* Benommenheit: eine Runde kein Angriff */
int
sp_stun(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
troop at;
/* Aus beiden Reihen nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW;
int force=0, enemies;
int stunned;
at.fighter = fi;
at.index = 0;
if (power <= 0) return 0;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
switch(sp->id) {
case SPL_SHOCKWAVE:
force = lovar(get_force(power,1));
break;
default:
assert(0);
}
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow);
2001-01-25 10:37:55 +01:00
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
stunned = 0;
do {
troop dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
fighter * df = dt.fighter;
unit * du = df->unit;
--force;
if (is_magic_resistant(mage, du, 0) == false) {
df->person[dt.index].flags |= FL_STUNNED;
++stunned;
}
} while (force && stunned < enemies);
sprintf(buf, "%d Krieger %s f<>r einen Moment benommen.",
stunned, stunned == 1 ? "ist" : "sind");
scat(".");
battlerecord(b, buf);
return level;
}
/* ------------------------------------------------------------- */
/* F<>r Spr<70>che 'get_scrambled_list_of_enemys_in_row', so da<64> man diese
* Liste nur noch einmal durchlaufen muss, um Fl<EFBFBD>chenzauberwirkungen
* abzuarbeiten */
/* Rosthauch */
int
sp_combatrosthauch(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
cvector *fgs;
void **fig;
int force, enemies;
int k = 0;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
static const char * msgt[] = {
"ruft ein f<>rchterliches Unwetter <20>ber seine Feinde, doch es gab niemanden mehr, den dies treffen konnte.",
"ruft ein f<>rchterliches Unwetter <20>ber seine Feinde, doch der magische Regen zeigt keinen Effekt.",
"ruft ein f<>rchterliches Unwetter <20>ber seine Feinde, Der magischen Regen l<>sst alles Eisen rosten."
};
unused(sp);
force = lovar(power * 15);
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow);
2001-01-25 10:37:55 +01:00
if (!enemies) {
battlemsg(b, fi->unit, msgt[0]);
return 0;
}
fgs = fighters(b, fi, minrow, maxrow, FS_ENEMY);
v_scramble(fgs->begin, fgs->end);
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
if (!force)
break;
/* da n min(force, x), sollte force maximal auf 0 sinken */
assert(force >= 0);
/* Eisenwaffen: I_SWORD, I_GREATSWORD, I_AXE, I_HALBERD (50%) */
if (df->weapons) {
int w;
for (w=0;df->weapons[w].type!=NULL;++w) {
weapon * wp = df->weapons;
int n = min(force, wp->used);
if (n) {
requirement * mat = wp->type->itype->construction->materials;
boolean iron = false;
while (mat && mat->number>0) {
if (mat->type==R_IRON) {
iron = true;
break;
}
mat++;
2001-01-25 10:37:55 +01:00
}
if (iron) {
int p;
force -=n;
wp->used -= n;
k +=n;
i_change(&df->unit->items, wp->type->itype, -n);
for (p=0;n && p!=df->unit->number;++p) {
if (df->person[p].missile==wp) {
df->person[p].missile = NULL;
2001-01-25 10:37:55 +01:00
--n;
}
}
for (p=0;n && p!=df->unit->number;++p) {
if (df->person[p].melee==wp) {
df->person[p].melee = NULL;
2001-01-25 10:37:55 +01:00
--n;
}
}
}
}
}
}
}
cv_kill(fgs);
if (k == 0) {
/* keine Waffen mehr da, die zerst<73>rt werden k<>nnten */
battlemsg(b, fi->unit, msgt[1]);
fi->magic = 0; /* k<>mpft nichtmagisch weiter */
level = 0;
} else {
battlemsg(b, fi->unit, msgt[2]);
}
return level;
}
int
sp_sleep(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
unit *du;
troop dt;
int force, enemies;
int k = 0;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
force = lovar(power * 25);
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow);
2001-01-25 10:37:55 +01:00
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
do {
dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
assert(dt.fighter);
du = dt.fighter->unit;
if (is_magic_resistant(mage, du, 0) == false) {
dt.fighter->person[dt.index].flags |= FL_SLEEPING;
++k;
--enemies;
}
--force;
} while (force && enemies);
sprintf(buf, "%d Krieger %s in Schlaf versetzt.",
k, k == 1 ? "wurde" : "wurden");
battlerecord(b, buf);
return level;
}
static troop
select_ally_in_row(fighter * af, int minrow, int maxrow)
{
side *as = af->side;
battle *b = as->battle;
troop dt = no_troop;
fighter *df;
int allies;
allies = countallies(as);
if (!allies)
return dt;
allies = rand() % allies;
cv_foreach(df, b->fighters) {
2001-01-25 10:37:55 +01:00
side *ds = df->side;
int dr = get_unitrow(df);
if (helping(as, ds) && dr >= minrow && dr <= maxrow) {
if (df->alive - df->removed > allies) {
dt.index = allies;
dt.fighter = df;
break;
}
allies -= df->alive;
}
}
cv_next(df);
2001-01-25 10:37:55 +01:00
return dt;
}
int
sp_speed(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
int force;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW;
int allies;
int targets = 0;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
scat(":");
battlerecord(b, buf);
force = lovar(power * power * 5);
allies = countallies(fi->side);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten best<73>nde
* die Gefahr eine Endlosschleife*/
allies *= 2;
do {
troop dt = select_ally_in_row(fi, minrow, maxrow);
fighter *df = dt.fighter;
--allies;
if (df) {
if (df->person[dt.index].speed == 1) {
df->person[dt.index].speed++;
targets++;
--force;
}
}
} while (force && allies);
sprintf(buf, "%d Krieger %s magisch beschleunigt.",
targets, targets == 1 ? "wurde" : "wurden");
battlerecord(b, buf);
return 1;
}
static skill_t
random_skill(unit *u)
{
int n = 0;
skill_t sk;
for(sk=0;sk<MAXSKILLS;sk++) {
if (get_level(u, sk)) n++;
2001-01-25 10:37:55 +01:00
}
if(n == 0)
return NOSKILL;
n = rand()%n;
for(sk=0;sk<MAXSKILLS;sk++) {
if (get_level(u, sk)) {
2001-01-25 10:37:55 +01:00
if(n == 0) return sk;
n--;
}
}
assert(0==1); /* Hier sollte er niemals ankommen. */
return NOSKILL;
}
int
sp_mindblast(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
troop dt;
unit *du;
skill_t sk;
int killed = 0;
int force, enemies;
int k = 0;
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
force = lovar(power * 25);
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow);
2001-01-25 10:37:55 +01:00
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
do {
dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
assert(dt.fighter);
du = dt.fighter->unit;
if (humanoidrace(du->race) && is_magic_resistant(mage, du, 0) == false) {
2001-01-25 10:37:55 +01:00
sk = random_skill(du);
if (sk != NOSKILL) {
/* Skill abziehen */
int n = 30+rand()%61;
skill * sv = get_skill(du, sk);
while (n>0) {
if (n>=30*du->number) {
2002-02-22 20:41:20 +01:00
reduce_skill(du, sv, 1);
n-=30;
} else {
2002-02-22 20:41:20 +01:00
if (rand()%(30*du->number)<n) reduce_skill(du, sv, 1);
n = 0;
}
}
2001-01-25 10:37:55 +01:00
--enemies;
} else {
troop t;
/* Keine Skills mehr, Einheit t<>ten */
t.fighter = dt.fighter;
t.index = 0;
while(dt.fighter->alive - dt.fighter->removed) {
rmtroop(t);
enemies--;
killed++;
}
}
k++;
}
--force;
} while (force && enemies);
sprintf(buf, "%d Krieger %s Erinnerungen",
k, k == 1 ? "verliert" : "verlieren");
if (killed > 0) {
scat(", ");
icat(killed);
scat(" Krieger ");
if (killed == 1) {
scat("wurde");
} else {
scat("wurden");
}
scat(" get<65>tet");
}
scat(".");
battlerecord(b, buf);
return level;
}
int
sp_dragonodem(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
troop dt;
troop at;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int force, enemies;
int killed = 0;
const char *damage;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
/* 11-26 HP */
damage = spell_damage(4);
2001-02-11 23:19:55 +01:00
/* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
force = lovar(get_force(level,6));
2001-01-25 10:37:55 +01:00
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow,
2001-01-25 10:37:55 +01:00
maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
at.fighter = fi;
at.index = 0;
do {
dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
assert(dt.fighter);
--force;
killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
} while (force && killed < enemies);
sprintf(buf, "%d Personen %s get<65>tet",
killed, killed == 1 ? "wurde" : "wurden");
scat(".");
battlerecord(b, buf);
return level;
}
int
sp_drainodem(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
troop dt;
troop at;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int force, enemies;
int drained = 0;
int killed = 0;
const char *damage;
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
spell_name(sp, default_locale));
/* 11-26 HP */
damage = spell_damage(4);
/* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
force = lovar(get_force(level,6));
2001-01-25 10:37:55 +01:00
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow,
maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
at.fighter = fi;
at.index = 0;
do {
dt = select_enemy(b, fi, minrow, maxrow);
assert(dt.fighter);
if (hits(at, dt, NULL)) {
drain_exp(dt.fighter->unit, 90);
drained++;
}
killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
--force;
} while (force && drained < enemies);
sprintf(buf, "%d Person%s wurde ihre Lebenskraft entzogen",
drained, drained == 1 ? " wurde" : "en wurden");
scat(".");
battlerecord(b, buf);
return level;
2001-01-25 10:37:55 +01:00
}
/* ------------------------------------------------------------- */
/* PRECOMBAT */
int
sp_shadowcall(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
region *r = b->region;
unit *mage = fi->unit;
attrib *a;
int force = get_force(power, 3)/2;
2002-02-24 10:20:38 +01:00
const race *rc = NULL;
int num;
unit *u;
unused(sp);
switch(rand()%3) {
case 0:
rc = new_race[RC_SHADOWBAT];
num = 5000+dice_rand("3d5000");
break;
case 1:
rc = new_race[RC_NIGHTMARE];
num = 500+dice_rand("3d500");
break;
case 2:
rc = new_race[RC_VAMPUNICORN];
num = 500+dice_rand("3d500");
break;
}
u = createunit(r, mage->faction, force, rc);
u->status = ST_FIGHT;
set_string(&u->name, racename(mage->faction->locale, u, u->race));
set_level(u, SK_WEAPONLESS, power/2);
set_level(u, SK_AUSDAUER, power/2);
u->hp = u->number * unit_max_hp(u);
if (fval(mage, UFL_PARTEITARNUNG))
fset(u, UFL_PARTEITARNUNG);
a = a_new(&at_unitdissolve);
a->data.ca[0] = 0;
a->data.ca[1] = 100;
a_add(&u->attribs, a);
make_fighter(b, u, true);
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
racename(default_locale, u, u->race));
battlerecord(b, buf);
return level;
}
2001-01-25 10:37:55 +01:00
int
sp_wolfhowl(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
region *r = b->region;
unit *mage = fi->unit;
attrib *a;
int force = get_force(power, 3)/2;
unit *u = createunit(r, mage->faction, force, new_race[RC_WOLF]);
2001-01-25 10:37:55 +01:00
unused(sp);
u->status = ST_FIGHT;
set_string(&u->name, racename(mage->faction->locale, u, u->race));
set_level(u, SK_WEAPONLESS, power/3);
set_level(u, SK_AUSDAUER, power/3);
2001-01-25 10:37:55 +01:00
u->hp = u->number * unit_max_hp(u);
if (fval(mage, UFL_PARTEITARNUNG))
fset(u, UFL_PARTEITARNUNG);
2001-01-25 10:37:55 +01:00
a = a_new(&at_unitdissolve);
a->data.ca[0] = 0;
a->data.ca[1] = 100;
a_add(&u->attribs, a);
make_fighter(b, u, true);
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
racename(default_locale, u, u->race));
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
return level;
}
int
sp_shadowknights(fighter * fi, int level, int power, spell * sp)
{
unit *u;
battle *b = fi->side->battle;
region *r = b->region;
unit *mage = fi->unit;
attrib *a;
int force;
unused(sp);
force = get_force(power, 3);
u = createunit(r, mage->faction, force, new_race[RC_SHADOWKNIGHT]);
2001-01-25 10:37:55 +01:00
u->status = ST_FIGHT;
set_string(&u->name, "Schattenritter");
u->hp = u->number * unit_max_hp(u);
if (fval(mage, UFL_PARTEITARNUNG))
fset(u, UFL_PARTEITARNUNG);
2001-01-25 10:37:55 +01:00
a = a_new(&at_unitdissolve);
a->data.ca[0] = 0;
a->data.ca[1] = 100;
a_add(&u->attribs, a);
make_fighter(b, u, true);
sprintf(buf, "%s beschw<68>rt Trugbilder herauf", unitname(mage));
battlerecord(b, buf);
return level;
}
int
sp_strong_wall(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
building *burg;
int effect;
static boolean init = false;
static const curse_type * strongwall_ct;
if (!init) { init = true; strongwall_ct = ct_find("strongwall"); }
2001-01-25 10:37:55 +01:00
unused(sp);
if (!mage->building) {
sprintf(buf, "%s zaubert nicht, denn dieser Zauber h<>tte hier keinen "
"Sinn.", unitname(mage));
battlerecord(b, buf);
return 0;
}
burg = mage->building;
effect = force/4;
if (rand()%4 < force%4)
effect++;
create_curse(mage, &burg->attribs, strongwall_ct, force, 1, effect, 0);
2001-01-25 10:37:55 +01:00
sprintf(buf, "%s Mauern ergl<67>hen in einem unheimlichen magischen Licht.",
buildingname(burg));
battlerecord(b, buf);
return level;
}
int
sp_chaosrow(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
cvector *fgs;
void **fig;
int n, enemies, row;
int chance;
int k = 0;
int minrow = FIGHT_ROW;
int maxrow = NUMROWS;
2001-01-25 10:37:55 +01:00
switch (sp->id) {
case SPL_CHAOSROW:
sprintf(buf, "%s murmelt eine d<>ster klingende Formel", unitname(mage));
force *= 40;
break;
case SPL_SONG_OF_CONFUSION:
sprintf(buf, "%s stimmt einen seltsamen Gesang an", unitname(mage));
force = get_force(force,5);
break;
}
enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow);
2001-01-25 10:37:55 +01:00
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(". ");
fgs = fighters(b, fi, minrow, maxrow, FS_ENEMY);
v_scramble(fgs->begin, fgs->end);
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
if (!force)
break;
/* force sollte wegen des max(0,x) nicht unter 0 fallen k<>nnen */
assert(force >= 0);
if (is_magic_resistant(mage, df->unit, 0))
continue;
n = df->unit->number;
chance = 100 * force/n;
if (chance < 1 + rand()%100) {
row = statusrow(df->status)+FIRST_ROW;
2001-01-25 10:37:55 +01:00
df->side->size[row] -= df->alive;
if (df->unit->race->battle_flags & BF_NOBLOCK) {
df->side->nonblockers[row] -= df->alive;
2001-01-25 10:37:55 +01:00
}
2003-04-24 22:54:14 +02:00
row = FIRST_ROW + (rand()%(LAST_ROW-FIRST_ROW));
switch (row) {
case FIGHT_ROW:
df->status = ST_FIGHT;
2002-03-10 08:35:30 +01:00
break;
case BEHIND_ROW:
df->status = ST_CHICKEN;
2002-03-10 08:35:30 +01:00
break;
case AVOID_ROW:
df->status = ST_AVOID;
2002-03-10 08:35:30 +01:00
break;
case FLEE_ROW:
df->status = ST_FLEE;
2002-03-10 08:35:30 +01:00
break;
default:
assert(!"unknown combatrow");
}
2001-01-25 10:37:55 +01:00
df->side->size[row] += df->alive;
if (df->unit->race->battle_flags & BF_NOBLOCK) {
2001-01-25 10:37:55 +01:00
df->side->nonblockers[row] += df->alive;
}
k++;
}
force = max(0, force-n);
}
cv_kill(fgs);
scat("Ein pl<70>tzlicher Tumult entsteht");
if (k > 0) {
scat(" und bringt die Kampfaufstellung durcheinander.");
}else{
scat(", der sich jedoch schnell wieder legt.");
}
battlerecord(b, buf);
return level;
}
/* Gesang der Furcht (Kampfzauber) */
/* Panik (Pr<50>kampfzauber) */
int
sp_flee(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
cvector *fgs;
void **fig;
int minrow = FIGHT_ROW;
int maxrow = AVOID_ROW;
int force, n;
int panik = 0;
switch(sp->id) {
case SPL_FLEE:
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
force = get_force(power,4);
break;
case SPL_SONG_OF_FEAR:
sprintf(buf, "%s stimmt einen d<>steren Gesang an", unitname(mage));
force = get_force(power,3);
break;
case SPL_AURA_OF_FEAR:
sprintf(buf, "%s ist von dunklen Schatten umgeben", unitname(mage));
force = get_force(power,5);
break;
2001-01-25 10:37:55 +01:00
default:
force = get_force(power,10);
}
if (!count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow)) {
2001-01-25 10:37:55 +01:00
scat(", aber es gab niemanden mehr, der beeinflusst werden konnte.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
fgs = fighters(b, fi, minrow, maxrow, FS_ENEMY);
v_scramble(fgs->begin, fgs->end);
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
for (n = 0; n < df->alive; n++) {
if (force < 0)
break;
if (df->person[n].flags & FL_PANICED) { /* bei SPL_SONG_OF_FEAR m<>glich */
df->person[n].attack -= 1;
--force;
++panik;
} else if (!(df->person[n].flags & FL_HERO)
|| !fval(df->unit->race, RCF_UNDEAD))
2001-01-25 10:37:55 +01:00
{
if (is_magic_resistant(mage, df->unit, 0) == false) {
df->person[n].flags |= FL_PANICED;
++panik;
}
--force;
}
}
}
cv_kill(fgs);
sprintf(buf, "%d Krieger %s von Furcht gepackt.", panik,
panik == 1 ? "wurde" : "wurden");
battlerecord(b, buf);
return level;
}
/* Heldenmut */
int
sp_hero(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int df_bonus = 0;
int force = 0;
int allies;
int targets = 0;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
switch(sp->id) {
case SPL_HERO:
df_bonus = power/5;
force = lovar(get_force(power,4));
break;
default:
df_bonus = 1;
force = power;
}
scat(":");
battlerecord(b, buf);
allies = countallies(fi->side);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten best<73>nde
* die Gefahr eine Endlosschleife*/
allies *= 2;
do {
troop dt = select_ally_in_row(fi, minrow, maxrow);
fighter *df = dt.fighter;
--allies;
if (df) {
if (!(df->person[dt.index].flags & FL_HERO)) {
df->person[dt.index].defence += df_bonus;
df->person[dt.index].flags = df->person[dt.index].flags | FL_HERO;
targets++;
--force;
}
}
} while (force && allies);
sprintf(buf, "%d Krieger %s moralisch gest<73>rkt",
targets, targets == 1 ? "wurde" : "wurden");
scat(".");
battlerecord(b, buf);
return level;
}
int
sp_berserk(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int at_bonus = 0;
int df_malus = 0;
int force = 0;
int allies = 0;
int targets = 0;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
switch(sp->id) {
case SPL_BERSERK:
case SPL_BLOODTHIRST:
at_bonus = max(1,level/3);
df_malus = 2;
force = get_force(power,2);
break;
default:
at_bonus = 1;
df_malus = 0;
force = power;
}
scat(":");
battlerecord(b, buf);
allies = countallies(fi->side);
/* maximal 2*allies Versuche ein Opfer zu finden, ansonsten best<73>nde
* die Gefahr eine Endlosschleife*/
allies *= 2;
do {
troop dt = select_ally_in_row(fi, minrow, maxrow);
fighter *df = dt.fighter;
--allies;
if (df) {
if (!(df->person[dt.index].flags & FL_HERO)) {
df->person[dt.index].attack += at_bonus;
df->person[dt.index].defence -= df_malus;
df->person[dt.index].flags = df->person[dt.index].flags | FL_HERO;
targets++;
--force;
}
}
} while (force && allies);
sprintf(buf, "%d Krieger %s in Blutrausch versetzt",
targets, targets == 1 ? "wurde" : "wurden");
scat(".");
battlerecord(b, buf);
return level;
}
int
sp_frighten(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
/* Immer aus der ersten Reihe nehmen */
int minrow = FIGHT_ROW;
int maxrow = BEHIND_ROW-1;
int at_malus = 0;
int df_malus = 0;
int force = 0;
int enemies = 0;
int targets = 0;
at_malus = max(1,level - 4);
df_malus = 2;
force = get_force(power, 2);
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
enemies = count_enemies(b, fi->side, FS_ENEMY,
2001-01-25 10:37:55 +01:00
minrow, maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
scat(":");
battlerecord(b, buf);
do {
troop dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
fighter *df = dt.fighter;
--enemies;
if (!df)
break;
assert(!helping(fi->side, df->side));
if (df->person[dt.index].flags & FL_HERO) {
df->person[dt.index].flags &= ~(FL_HERO);
}
if (is_magic_resistant(mage, df->unit, 0) == false) {
df->person[dt.index].attack -= at_malus;
df->person[dt.index].defence -= df_malus;
targets++;
}
--force;
} while (force && enemies);
sprintf(buf, "%d Krieger %s eingesch<63>chtert",
targets, targets == 1 ? "wurde" : "wurden");
scat(".");
battlerecord(b, buf);
return level;
}
int
sp_tiredsoldiers(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
int n = 0;
force = force * force * 4;
2001-01-25 10:37:55 +01:00
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
if (!count_enemies(b, fi->side, FS_ENEMY, FIGHT_ROW,
2001-01-25 10:37:55 +01:00
BEHIND_ROW)) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
while (force) {
troop t = select_enemy(b, fi, FIGHT_ROW, BEHIND_ROW);
2001-01-25 10:37:55 +01:00
fighter *df = t.fighter;
if (!df)
break;
assert(!helping(fi->side, df->side));
if (!(df->person[t.index].flags & FL_TIRED)) {
if (is_magic_resistant(mage, df->unit, 0) == false) {
df->person[t.index].flags = df->person[t.index].flags | FL_TIRED;
df->person[t.index].defence -= 2;
++n;
}
}
--force;
}
scat(": ");
if (n == 0) {
scat("Der Zauber konnte keinen Krieger erm<72>den.");
} else if (n == 1) {
scat("Ein Krieger schleppt sich m<>de in den Kampf.");
} else {
icat(n);
scat(" Krieger schleppen sich m<>de in den Kampf.");
}
battlerecord(b, buf);
return level;
}
int
sp_windshield(fighter * fi, int level, int power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
int force, at_malus;
int enemies;
/* Immer aus der hinteren Reihe nehmen */
int minrow = BEHIND_ROW;
int maxrow = BEHIND_ROW;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
switch(sp->id) {
case SPL_WINDSHIELD:
force = get_force(power,4);
at_malus = level/4;
break;
default:
force = power;
at_malus = 2;
}
enemies = count_enemies(b, fi->side, FS_ENEMY,
2001-01-25 10:37:55 +01:00
minrow, maxrow);
if (!enemies) {
scat(", aber niemand war in Reichweite.");
battlerecord(b, buf);
return 0;
}
do {
troop dt = select_enemy(b, fi, minrow, maxrow);
2001-01-25 10:37:55 +01:00
fighter *df = dt.fighter;
--enemies;
if (!df)
break;
assert(!helping(fi->side, df->side));
if (df->person[dt.index].missile) {
/* this suxx... affects your melee weapon as well. */
2001-01-25 10:37:55 +01:00
df->person[dt.index].attack -= at_malus;
--force;
}
} while (force && enemies);
scat(": ");
scat("Ein Sturm kommt auf und die Sch<63>tzen k<>nnen kaum noch zielen.");
battlerecord(b, buf);
return level;
}
int
sp_reeling_arrows(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
unused(force);
b->reelarrow = true;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
scat(": ");
scat("Ein Sturm kommt auf und die Sch<63>tzen k<>nnen kaum noch zielen.");
battlerecord(b, buf);
return level;
}
int
sp_denyattack(fighter * fi, int level, int power, spell * sp)
{
/* Magier weicht dem Kampf aus. Wenn er sich bewegen kann, zieht er in
* eine Nachbarregion, wobei ein NACH ber<EFBFBD>cksichtigt wird. Ansonsten
* bleibt er stehen und nimmt nicht weiter am Kampf teil. */
2001-01-25 10:37:55 +01:00
battle *b = fi->side->battle;
unit *mage = fi->unit;
region *r = b->region;
unused(power);
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
scat(": ");
/* Fliehende Einheiten verlassen auf jeden Fall Geb<65>ude und Schiffe. */
leave(r, mage);
/* und bewachen nicht */
setguard(mage, GUARD_NONE);
/* irgendwie den langen befehl sperren */
fset(fi, FIG_ATTACKED);
/* Hat der Magier ein NACH, wird die angegebene Richtung bevorzugt */
if (igetkeyword(mage->thisorder, mage->faction->locale) == K_MOVE
|| igetkeyword(mage->thisorder, mage->faction->locale) == K_ROUTE)
2001-01-25 10:37:55 +01:00
{
fi->run.region = movewhere(r, mage);
if (!fi->run.region) {
2001-01-25 10:37:55 +01:00
cmistake(mage, findorder(mage, mage->thisorder), 71, MSG_MOVE);
fi->run.region = fleeregion(mage);
2001-01-25 10:37:55 +01:00
}
} else {
fi->run.region = fleeregion(mage);
2001-01-25 10:37:55 +01:00
}
/* bewegung erst am Ende des Kampfes, zusammen mit den normalen
* Fl<EFBFBD>chtlingen */
/* travel(r, mage, fi->run.region, 1); */
2001-01-25 10:37:55 +01:00
/* wir tun so, als w<>re die Person geflohen */
fset(fi, FIG_NOLOOT);
fi->run.hp = mage->hp;
fi->run.number = mage->number;
/* fighter leeren */
rmfighter(fi, mage->number);
2001-01-25 10:37:55 +01:00
scat("Das Kampfget<65>mmel erstirbt und er kann unbehelligt "
"seines Weges ziehen.");
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
return level;
}
static void
2001-01-25 10:37:55 +01:00
do_meffect(fighter * af, int typ, int effect, int duration)
{
battle *b = af->side->battle;
meffect *meffect = calloc(1, sizeof(struct meffect));
cv_pushback(&b->meffects, meffect);
meffect->magician = af;
meffect->typ = typ;
meffect->effect = effect;
meffect->duration = duration;
}
int
sp_armorshield(fighter * fi, int level, int power, spell * sp)
{
int effect;
int duration;
unit *mage = fi->unit;
battle *b = fi->side->battle;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
/* gibt R<>stung +effect f<>r duration Treffer */
switch(sp->id) {
case SPL_ARMORSHIELD:
effect = level/3;
duration = 20*power*power;
break;
default:
effect = level/4;
duration = power*power;
}
do_meffect(fi, SHIELD_ARMOR, effect, duration);
return level;
}
int
sp_reduceshield(fighter * fi, int level, int power, spell * sp)
{
int effect;
int duration;
unit *mage = fi->unit;
battle *b = fi->side->battle;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
/* jeder Schaden wird um effect% reduziert bis der Schild duration
* Trefferpunkte aufgefangen hat */
switch(sp->id) {
case SPL_REDUCESHIELD:
effect = 50;
duration = 50*power*power;
break;
default:
effect = level*3;
duration = get_force(power,5);
}
do_meffect(fi, SHIELD_REDUCE, effect, duration);
return level;
}
int
sp_fumbleshield(fighter * fi, int level, int power, spell * sp)
{
int effect;
int duration;
unit *mage = fi->unit;
battle *b = fi->side->battle;
sprintf(buf, "%s zaubert %s", unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
/* der erste Zauber schl<68>gt mit 100% fehl */
switch(sp->id) {
case SPL_DRAIG_FUMBLESHIELD:
case SPL_GWYRRD_FUMBLESHIELD:
case SPL_CERRDOR_FUMBLESHIELD:
case SPL_TYBIED_FUMBLESHIELD:
duration = 100;
effect = max(1, 25-level);
break;
default:
duration = 100;
effect = 10;
}
do_meffect(fi, SHIELD_BLOCK, effect, duration);
return level;
}
/* ------------------------------------------------------------- */
/* POSTCOMBAT */
static int
count_healable(battle *b, fighter *df)
{
side *s;
int healable = 0;
cv_foreach(s, b->sides) {
2001-01-25 10:37:55 +01:00
if (helping(df->side, s)) {
healable += s->casualties;
}
} cv_next(s);
2001-01-25 10:37:55 +01:00
return healable;
}
/* wiederbeleben */
int
sp_reanimate(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
int healable, k, j=0;
double c;
switch(sp->id) {
case SPL_REANIMATE:
sprintf(buf, "%s beginnt ein Ritual der Wiederbelebung",
unitname(mage));
k = EFFECT_HEALING_SPELL*force;
c = 0.50 + 0.02 * force;
break;
default:
sprintf(buf, "%s zaubert %s",
unitname(mage),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
k = EFFECT_HEALING_SPELL*force;
c = 0.50;
}
if (get_item(mage, I_AMULET_OF_HEALING) > 0) {
scat(" und benutzt das ");
2001-05-20 10:41:11 +02:00
scat(locale_string(default_locale, resourcename(oldresourcetype[R_AMULET_OF_HEALING], 0)));
2001-01-25 10:37:55 +01:00
scat(", um den Zauber zu verst<73>rken");
k *= 2;
c += 0.10;
}
healable = count_healable(b, fi);
k = min(k, healable);
while (k--) {
troop t = select_corpse(b, fi);
if (t.fighter
&& t.fighter->side->casualties > 0
&& old_race(t.fighter->unit->race) != RC_DAEMON
2001-01-25 10:37:55 +01:00
&& (chance(c)))
{
assert(t.fighter->alive < t.fighter->unit->number);
/* t.fighter->person[].hp beginnt mit t.index = 0 zu z<>hlen,
* t.fighter->alive ist jedoch die Anzahl lebender in der Einheit,
* also sind die hp von t.fighter->alive
* t.fighter->hitpoints[t.fighter->alive-1] und der erste Tote
* oder weggelaufene ist t.fighter->hitpoints[t.fighter->alive] */
t.fighter->person[t.fighter->alive].hp = 2;
++t.fighter->alive;
++t.fighter->side->size[SUM_ROW];
++t.fighter->side->size[t.fighter->unit->status + 1];
++t.fighter->side->healed;
--t.fighter->side->casualties;
--healable;
++j;
}
}
if (j == 0) {
scat(", kann aber niemanden wiederbeleben.");
level = 0;
} else if (j == 1) {
scat(" und belebt einen Toten wieder.");
level = 1;
} else {
scat(" und belebt ");
icat(j);
scat(" Tote wieder.");
}
battlerecord(b, buf);
return level;
}
int
sp_keeploot(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
sprintf(buf, "%s zaubert %s.", unitname(fi->unit),
spell_name(sp, default_locale));
2001-01-25 10:37:55 +01:00
battlerecord(b, buf);
b->keeploot = max(50, b->keeploot + 5*force);
return level;
}
int
sp_healing(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
int minrow = FIGHT_ROW;
int maxrow = AVOID_ROW;
int healhp;
int hp, wound;
int n, j = 0;
cvector *fgs;
void **fig;
sprintf(buf, "%s k<>mmert sich um die Verletzten", unitname(mage));
/* bis zu 11 Personen pro Stufe (einen HP m<>ssen sie ja noch
* haben, sonst w<EFBFBD>ren sie tot) k<EFBFBD>nnen geheilt werden */
healhp = force * 200;
if (get_item(mage, I_AMULET_OF_HEALING) > 0) {
scat(" und benutzt das ");
2001-05-20 10:41:11 +02:00
scat(locale_string(default_locale, resourcename(oldresourcetype[R_AMULET_OF_HEALING], 0)));
2001-01-25 10:37:55 +01:00
scat(", um die Heilzauber zu verst<73>rken");
healhp *= 2;
}
/* gehe alle denen wir helfen der reihe nach durch, heile verwundete,
* bis zu verteilende HP aufgebraucht sind */
fgs = fighters(b, fi, minrow, maxrow, FS_HELP);
v_scramble(fgs->begin, fgs->end);
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
if (!healhp)
break;
/* wir heilen erstmal keine Monster */
if (!playerrace(df->unit->race))
2001-01-25 10:37:55 +01:00
continue;
hp = unit_max_hp(df->unit);
for (n = 0; n < df->unit->number; n++) {
if (!healhp)
break;
wound = hp - df->person[n].hp;
if ( wound > 0 && wound < hp) {
int heal = min(healhp, wound);
assert(heal>=0);
df->person[n].hp += heal;
healhp = max(0, healhp - heal);
j++;
}
}
}
/* haben wir noch HP <20>brig, so heilen wir nun auch Monster */
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
if (!healhp)
break;
/* Untote kann man nicht heilen */
if (fval(df->unit->race, RCF_NOHEAL))
2001-01-25 10:37:55 +01:00
continue;
hp = unit_max_hp(df->unit);
for (n = 0; n < df->unit->number; n++) {
if (!healhp)
break;
wound = hp - df->person[n].hp;
if ( wound > 0 && wound < hp) {
int heal = min(healhp, wound);
assert(heal>=0);
df->person[n].hp += heal;
healhp = max(0, healhp - heal);
j++;
}
}
}
cv_kill(fgs);
if (j == 0) {
scat(", doch niemand mu<6D>te magisch geheilt werden.");
level = 0;
} else if (j == 1) {
scat(" und heilt einen Verwundeten.");
level = 1;
} else {
scat(" und heilt ");
icat(j);
scat(" Verwundete.");
}
battlerecord(b, buf);
return level;
}
int
sp_undeadhero(fighter * fi, int level, int force, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
region *r = b->region;
int minrow = FIGHT_ROW;
int maxrow = AVOID_ROW;
cvector *fgs;
void **fig;
int k, n, j;
int undead = 0;
double c;
/* maximal Stufe*4 Personen*/
k = get_force(force,0);
c = 0.50 + 0.02 * force;
/* Liste aus allen K<>mpfern */
fgs = fighters(b, fi, minrow, maxrow, FS_ENEMY | FS_HELP );
v_scramble(fgs->begin, fgs->end);
for (fig = fgs->begin; fig != fgs->end; ++fig) {
fighter *df = *fig;
unit *du = df->unit;
if (!k)
break;
/* keine Monster */
if (!playerrace(du->race))
2001-01-25 10:37:55 +01:00
continue;
if (df->alive + df->run.number < du->number) {
2001-01-25 10:37:55 +01:00
j = 0;
/* Wieviele Untote k<>nnen wir aus dieser Einheit wecken? */
for (n = df->alive + df->run.number; n <= du->number; n++) {
2001-01-25 10:37:55 +01:00
if (!k) break;
if (chance(c)) {
undead++;
j++;
--df->side->casualties;
--k;
}
}
if (j > 0) {
int hp = unit_max_hp(du);
if (j == du->number) {
/* Einheit war vollst<73>ndig tot und konnte vollst<73>ndig zu
* Untoten gemacht werden */
int nr;
du->race = new_race[RC_UNDEAD];
2001-01-25 10:37:55 +01:00
setguard(du, GUARD_NONE);
2001-02-10 15:18:01 +01:00
u_setfaction(du,mage->faction);
if (fval(mage, UFL_PARTEITARNUNG))
fset(du, UFL_PARTEITARNUNG);
2001-01-25 10:37:55 +01:00
df->alive = du->number;
/* den Toten wieder volle Hitpoints geben */
for (nr = 0; nr != df->alive; ++nr) {
df->person[nr].hp = hp;
}
/* vereinfachtes loot */
change_money(mage, get_money(du));
set_money(du, 0);
} else {
unit *u;
u = createunit(r, mage->faction, 0, new_race[RC_UNDEAD]);
2001-01-25 10:37:55 +01:00
transfermen(du, u, j);
sprintf(buf, "%s", du->name);
set_string(&u->name, buf);
sprintf(buf, "%s", du->display);
set_string(&u->display, buf);
u->status = du->status;
setguard(u, GUARD_NONE);
if (fval(mage, UFL_PARTEITARNUNG))
fset(u, UFL_PARTEITARNUNG);
2001-01-25 10:37:55 +01:00
set_string(&u->lastorder, du->lastorder);
/* den Toten volle Hitpoints geben */
u->hp = u->number * unit_max_hp(u);
}
}
}
}
cv_kill(fgs);
if (undead == 0) {
sprintf(buf, "%s kann keinen Untoten rufen.", unitname(mage));
level = 0;
} else if (undead == 1) {
sprintf(buf, "%s erweckt einen Untoten.", unitname(mage));
level = 1;
} else {
sprintf(buf, "%s erweckt %d Untote.", unitname(mage), undead);
}
battlerecord(b, buf);
return level;
}
/* ------------------------------------------------------------------ */