2001-12-10 01:13:39 +01:00
|
|
|
|
/* 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>
|
2003-07-29 11:48:03 +02:00
|
|
|
|
| (c) 1998 - 2003 | Henning Peters <faroul@beyond.kn-bremen.de>
|
2001-12-10 01:13:39 +01:00
|
|
|
|
| | 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 */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
#include "battle.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "build.h"
|
|
|
|
|
#include "building.h"
|
2001-04-16 16:34:19 +02:00
|
|
|
|
#include "faction.h"
|
|
|
|
|
#include "item.h"
|
|
|
|
|
#include "magic.h"
|
2004-04-20 00:52:36 +02:00
|
|
|
|
#include "message.h"
|
2001-04-16 16:34:19 +02:00
|
|
|
|
#include "region.h"
|
|
|
|
|
#include "unit.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
#include "movement.h"
|
|
|
|
|
#include "spell.h"
|
|
|
|
|
#include "race.h"
|
2001-12-10 01:13:39 +01:00
|
|
|
|
#include "skill.h"
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* util includes */
|
|
|
|
|
#include <rand.h>
|
2004-02-20 00:51:46 +01:00
|
|
|
|
#include <base36.h>
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* 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";
|
2001-02-18 20:07:31 +01:00
|
|
|
|
case 4:
|
|
|
|
|
/* verwundet 11-26 HP */
|
|
|
|
|
return "3d6+8";
|
2003-12-12 18:17:13 +01:00
|
|
|
|
case 5:
|
|
|
|
|
/* leichter Schaden */
|
|
|
|
|
return "2d4";
|
2001-01-25 10:37:55 +01:00
|
|
|
|
default:
|
|
|
|
|
/* schwer verwundet 14-34 HP */
|
|
|
|
|
return "4d6+10";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-09 23:20:40 +01:00
|
|
|
|
static double
|
|
|
|
|
get_force(double power, int formel)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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:
|
2001-02-18 20:07:31 +01:00
|
|
|
|
/* (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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_kampfzauber(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-04 21:24:03 +02:00
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
troop at, dt;
|
|
|
|
|
message * m;
|
|
|
|
|
/* Immer aus der ersten Reihe nehmen */
|
|
|
|
|
int minrow = FIGHT_ROW;
|
|
|
|
|
int maxrow = BEHIND_ROW-1;
|
|
|
|
|
int force, enemies;
|
|
|
|
|
int killed = 0;
|
|
|
|
|
const char *damage;
|
|
|
|
|
|
|
|
|
|
if (power <= 0) return 0;
|
|
|
|
|
at.fighter = fi;
|
|
|
|
|
at.index = 0;
|
|
|
|
|
|
|
|
|
|
switch(sp->id) {
|
|
|
|
|
/* lovar halbiert im Schnitt! */
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
|
|
|
|
|
spell_name(sp, default_locale));
|
|
|
|
|
|
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
|
|
|
|
if (enemies==0) {
|
|
|
|
|
m = msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
|
|
|
|
|
message_all(b, m);
|
|
|
|
|
msg_release(m);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (force>0 && killed < enemies) {
|
|
|
|
|
dt = select_enemy(b, fi, minrow, maxrow);
|
|
|
|
|
assert(dt.fighter);
|
|
|
|
|
--force;
|
|
|
|
|
killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m = msg_message("battle::combatspell", "mage spell dead",
|
|
|
|
|
fi->unit, sp, killed);
|
|
|
|
|
message_all(b, m);
|
|
|
|
|
msg_release(m);
|
|
|
|
|
|
|
|
|
|
return level;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Versteinern */
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_versteinern(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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));
|
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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 {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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;
|
2001-12-10 01:13:39 +01:00
|
|
|
|
++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];
|
2001-12-10 01:13:39 +01:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_stun(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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 {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_combatrosthauch(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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;
|
2004-05-22 02:01:00 +02:00
|
|
|
|
|
|
|
|
|
if (df->alive==0) continue;
|
|
|
|
|
if (force<=0) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
}
|
2001-12-10 01:13:39 +01:00
|
|
|
|
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) {
|
Zu Anfang des Kampfes wählt jeder Kämpfer aus seinem Arsenal zwei Waffen
aus: Seine beste Fernampfwaffe und seine beste Nahkampfwaffe.
Welches die beste Waffe ist, ist nicht immer einleuchtend, und an dieser
Stelle macht der Server eine Vereinfachung - er wählt die Waffe, bei der der
Angriffswert plus dem Verteidigungswert am größten ist.
** Wenn eine Einheit an der Reihe ist, wird geprüft:
1. Ist die Einheit ein Magier, so zaubert sie.
2. Ist die Einheit damit beschäftigt, eine Waffe nachzuladen, so tut sie das.
3. Steht die Einheit in einer der hinteren Reihen, attackiert sie, so
vorhanden, mit der Fernkampfwaffe.
4. Steht die Einheit in der vorderen Kampfreihe, so attackiert sie mit
derjenigen Waffe von beiden, in der ihr Talent am höchsten ist.
** Wird eine Einheit angegriffen, so gilt:
1. Handelt es sich um einen Angriff durch einen Nahkämpfer, so verteidigt
sie sich mit ihrer Nahkampfwaffe oder Waffenlosem Kampf.
2. Handelt es sich um eine Attacke durch einen Fernkämpfer, so verteidigt
sie sich mit dem halben Talent ihrer besten Waffe.
2002-10-04 23:25:16 +02:00
|
|
|
|
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) {
|
Zu Anfang des Kampfes wählt jeder Kämpfer aus seinem Arsenal zwei Waffen
aus: Seine beste Fernampfwaffe und seine beste Nahkampfwaffe.
Welches die beste Waffe ist, ist nicht immer einleuchtend, und an dieser
Stelle macht der Server eine Vereinfachung - er wählt die Waffe, bei der der
Angriffswert plus dem Verteidigungswert am größten ist.
** Wenn eine Einheit an der Reihe ist, wird geprüft:
1. Ist die Einheit ein Magier, so zaubert sie.
2. Ist die Einheit damit beschäftigt, eine Waffe nachzuladen, so tut sie das.
3. Steht die Einheit in einer der hinteren Reihen, attackiert sie, so
vorhanden, mit der Fernkampfwaffe.
4. Steht die Einheit in der vorderen Kampfreihe, so attackiert sie mit
derjenigen Waffe von beiden, in der ihr Talent am höchsten ist.
** Wird eine Einheit angegriffen, so gilt:
1. Handelt es sich um einen Angriff durch einen Nahkämpfer, so verteidigt
sie sich mit ihrer Nahkampfwaffe oder Waffenlosem Kampf.
2. Handelt es sich um eine Attacke durch einen Fernkämpfer, so verteidigt
sie sich mit dem halben Talent ihrer besten Waffe.
2002-10-04 23:25:16 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_sleep(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
force = lovar(power * 25);
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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 {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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;
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
cv_next(df);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return dt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_speed(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
2004-02-16 20:59:26 +01:00
|
|
|
|
skill * sv;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-16 20:59:26 +01:00
|
|
|
|
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
|
|
|
|
|
if (sv->level>0) ++n;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(n == 0)
|
|
|
|
|
return NOSKILL;
|
|
|
|
|
|
|
|
|
|
n = rand()%n;
|
|
|
|
|
|
2004-02-16 20:59:26 +01:00
|
|
|
|
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
|
|
|
|
|
if (sv->level>0) {
|
|
|
|
|
if (n-- == 0) return sv->id;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(0==1); /* Hier sollte er niemals ankommen. */
|
|
|
|
|
return NOSKILL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_mindblast(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-22 18:26:03 +02:00
|
|
|
|
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;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 18:26:03 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
|
|
|
|
force = lovar(power * 25);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 18:26:03 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
|
|
|
|
if (!enemies) {
|
|
|
|
|
scat(", aber niemand war in Reichweite.");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
scat(":");
|
|
|
|
|
battlerecord(b, buf);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 18:26:03 +02:00
|
|
|
|
do {
|
|
|
|
|
dt = select_enemy(b, fi, minrow, maxrow);
|
|
|
|
|
assert(dt.fighter);
|
|
|
|
|
du = dt.fighter->unit;
|
|
|
|
|
if (humanoidrace(du->race) && !is_magic_resistant(mage, du, 0)) {
|
|
|
|
|
sk = random_skill(du);
|
|
|
|
|
if (sk != NOSKILL) {
|
|
|
|
|
skill * sv = get_skill(du, sk);
|
|
|
|
|
int n = 1 + rand() % 3;
|
|
|
|
|
/* Skill abziehen */
|
|
|
|
|
reduce_skill(du, sv, n);
|
|
|
|
|
} else {
|
|
|
|
|
/* Keine Skills mehr, Einheit t<>ten */
|
|
|
|
|
rmtroop(dt);
|
|
|
|
|
++killed;
|
|
|
|
|
}
|
|
|
|
|
--enemies;
|
|
|
|
|
++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(".");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 18:26:03 +02:00
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return level;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_dragonodem(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
|
|
|
|
|
spell_name(sp, default_locale));
|
2001-02-18 20:07:31 +01:00
|
|
|
|
/* 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
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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);
|
|
|
|
|
|
|
|
|
|
at.fighter = fi;
|
|
|
|
|
at.index = 0;
|
|
|
|
|
|
|
|
|
|
do {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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;
|
2002-02-23 20:04:51 +01:00
|
|
|
|
}
|
|
|
|
|
|
2003-12-12 18:17:13 +01:00
|
|
|
|
/* Feuersturm: Betrifft sehr viele Gegner (in der Regel alle),
|
|
|
|
|
* macht nur vergleichsweise geringen Schaden */
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_immolation(fighter * fi, int level, double power, spell * sp)
|
2003-12-12 18:17:13 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
troop dt;
|
|
|
|
|
troop at;
|
|
|
|
|
int minrow = FIGHT_ROW;
|
|
|
|
|
int maxrow = AVOID_ROW;
|
|
|
|
|
int force, enemies;
|
|
|
|
|
int killed = 0;
|
|
|
|
|
const char *damage;
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
|
|
|
|
|
spell_name(sp, default_locale));
|
|
|
|
|
/* 2d4 HP */
|
|
|
|
|
damage = spell_damage(5);
|
|
|
|
|
/* Betrifft alle Gegner */
|
|
|
|
|
force = 99999;
|
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
2003-12-12 18:17:13 +01:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
--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;
|
|
|
|
|
}
|
|
|
|
|
|
2002-02-23 20:04:51 +01:00
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_drainodem(fighter * fi, int level, double power, spell * sp)
|
2002-02-23 20:04:51 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(fi->unit),
|
|
|
|
|
spell_name(sp, default_locale));
|
2002-02-23 20:04:51 +01:00
|
|
|
|
/* 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
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
2002-02-23 20:04:51 +01:00
|
|
|
|
|
|
|
|
|
if (!enemies) {
|
|
|
|
|
scat(", aber niemand war in Reichweite.");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
scat(":");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
|
|
|
|
|
at.fighter = fi;
|
|
|
|
|
at.index = 0;
|
|
|
|
|
|
|
|
|
|
do {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
dt = select_enemy(b, fi, minrow, maxrow);
|
2002-02-23 20:04:51 +01:00
|
|
|
|
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 */
|
|
|
|
|
|
2002-02-23 20:04:51 +01:00
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_shadowcall(fighter * fi, int level, double power, spell * sp)
|
2002-02-23 20:04:51 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
region *r = b->region;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
attrib *a;
|
2004-02-10 00:28:12 +01:00
|
|
|
|
int force = (int)(get_force(power, 3)/2);
|
2002-02-24 10:20:38 +01:00
|
|
|
|
const race *rc = NULL;
|
2002-02-23 20:04:51 +01:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2004-02-10 00:28:12 +01:00
|
|
|
|
u = createunit(r, mage->faction, force, rc);
|
2002-02-23 20:04:51 +01:00
|
|
|
|
u->status = ST_FIGHT;
|
|
|
|
|
|
|
|
|
|
set_string(&u->name, racename(mage->faction->locale, u, u->race));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
set_level(u, SK_WEAPONLESS, (int)(power/2));
|
|
|
|
|
set_level(u, SK_AUSDAUER, (int)(power/2));
|
2002-02-23 20:04:51 +01:00
|
|
|
|
u->hp = u->number * unit_max_hp(u);
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
if (fval(mage, UFL_PARTEITARNUNG))
|
|
|
|
|
fset(u, UFL_PARTEITARNUNG);
|
2002-02-23 20:04:51 +01:00
|
|
|
|
|
|
|
|
|
a = a_new(&at_unitdissolve);
|
|
|
|
|
a->data.ca[0] = 0;
|
|
|
|
|
a->data.ca[1] = 100;
|
|
|
|
|
a_add(&u->attribs, a);
|
|
|
|
|
|
2004-02-09 22:12:46 +01:00
|
|
|
|
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED));
|
2002-02-23 20:04:51 +01:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_wolfhowl(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
region *r = b->region;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
attrib *a;
|
2004-02-10 00:28:12 +01:00
|
|
|
|
int force = (int)(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;
|
|
|
|
|
|
2002-02-23 20:04:51 +01:00
|
|
|
|
set_string(&u->name, racename(mage->faction->locale, u, u->race));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
set_level(u, SK_WEAPONLESS, (int)(power/3));
|
|
|
|
|
set_level(u, SK_AUSDAUER, (int)(power/3));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
u->hp = u->number * unit_max_hp(u);
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
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);
|
|
|
|
|
|
2004-02-09 22:12:46 +01:00
|
|
|
|
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
|
2002-02-23 20:04:51 +01:00
|
|
|
|
racename(default_locale, u, u->race));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_shadowknights(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
unit *u;
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
region *r = b->region;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
attrib *a;
|
2004-02-10 00:28:12 +01:00
|
|
|
|
int force = (int)get_force(power, 3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-10 00:28:12 +01:00
|
|
|
|
unused(sp);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-10 00:28:12 +01:00
|
|
|
|
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);
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
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);
|
|
|
|
|
|
2004-02-09 22:12:46 +01:00
|
|
|
|
make_fighter(b, u, fi->side, fval(fi, FIG_ATTACKED));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s beschw<68>rt Trugbilder herauf", unitname(mage));
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_strong_wall(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
building *burg;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
int effect = (int)(power/4);
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
|
|
|
|
|
2004-02-09 23:20:40 +01:00
|
|
|
|
if (chance(power-effect)) ++effect;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-09 23:20:40 +01:00
|
|
|
|
create_curse(mage, &burg->attribs, strongwall_ct, power, 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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_chaosrow(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-21 11:37:49 +02:00
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
cvector *fgs;
|
|
|
|
|
void **fig;
|
|
|
|
|
int enemies;
|
|
|
|
|
int k = 0;
|
|
|
|
|
int minrow = FIGHT_ROW;
|
|
|
|
|
int maxrow = NUMROWS;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
switch (sp->id) {
|
|
|
|
|
case SPL_CHAOSROW:
|
|
|
|
|
sprintf(buf, "%s murmelt eine d<>ster klingende Formel", unitname(mage));
|
|
|
|
|
power *= 40;
|
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
case SPL_SONG_OF_CONFUSION:
|
|
|
|
|
sprintf(buf, "%s stimmt einen seltsamen Gesang an", unitname(mage));
|
|
|
|
|
power = get_force(power, 5);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
|
|
|
|
if (!enemies) {
|
|
|
|
|
scat(", aber niemand war in Reichweite.");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
scat(". ");
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
fgs = fighters(b, fi, minrow, maxrow, FS_ENEMY);
|
|
|
|
|
v_scramble(fgs->begin, fgs->end);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
for (fig = fgs->begin; fig != fgs->end; ++fig) {
|
|
|
|
|
fighter *df = *fig;
|
|
|
|
|
int n = df->unit->number;
|
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
if (df->alive==0) continue;
|
2004-05-21 11:37:49 +02:00
|
|
|
|
if (power<=0.0) break;
|
|
|
|
|
/* force sollte wegen des max(0,x) nicht unter 0 fallen k<>nnen */
|
|
|
|
|
|
|
|
|
|
if (is_magic_resistant(mage, df->unit, 0)) continue;
|
|
|
|
|
|
|
|
|
|
if (chance(power/n)) {
|
|
|
|
|
int row = statusrow(df->status);
|
|
|
|
|
df->side->size[row] -= df->alive;
|
|
|
|
|
if (df->unit->race->battle_flags & BF_NOBLOCK) {
|
|
|
|
|
df->side->nonblockers[row] -= df->alive;
|
|
|
|
|
}
|
|
|
|
|
row = FIRST_ROW + (rand()%(LAST_ROW-FIRST_ROW));
|
|
|
|
|
switch (row) {
|
|
|
|
|
case FIGHT_ROW:
|
|
|
|
|
df->status = ST_FIGHT;
|
|
|
|
|
break;
|
|
|
|
|
case BEHIND_ROW:
|
|
|
|
|
df->status = ST_CHICKEN;
|
|
|
|
|
break;
|
|
|
|
|
case AVOID_ROW:
|
|
|
|
|
df->status = ST_AVOID;
|
|
|
|
|
break;
|
|
|
|
|
case FLEE_ROW:
|
|
|
|
|
df->status = ST_FLEE;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(!"unknown combatrow");
|
|
|
|
|
}
|
|
|
|
|
assert(statusrow(df->status)==row);
|
|
|
|
|
df->side->size[row] += df->alive;
|
|
|
|
|
if (df->unit->race->battle_flags & BF_NOBLOCK) {
|
|
|
|
|
df->side->nonblockers[row] += df->alive;
|
|
|
|
|
}
|
|
|
|
|
k+=df->alive;
|
|
|
|
|
}
|
|
|
|
|
power = max(0, power-n);
|
|
|
|
|
}
|
|
|
|
|
cv_kill(fgs);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-21 11:37:49 +02:00
|
|
|
|
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;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Gesang der Furcht (Kampfzauber) */
|
|
|
|
|
/* Panik (Pr<50>kampfzauber) */
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_flee(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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:
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,4);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
case SPL_SONG_OF_FEAR:
|
|
|
|
|
sprintf(buf, "%s stimmt einen d<>steren Gesang an", unitname(mage));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,3);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
2002-02-23 20:04:51 +01:00
|
|
|
|
case SPL_AURA_OF_FEAR:
|
|
|
|
|
sprintf(buf, "%s ist von dunklen Schatten umgeben", unitname(mage));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,5);
|
2002-02-23 20:04:51 +01:00
|
|
|
|
break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
default:
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,10);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
2004-04-18 23:44:24 +02:00
|
|
|
|
if (!count_enemies(b, fi->side, 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;
|
2004-05-22 02:01:00 +02:00
|
|
|
|
for (n=0; n!=df->alive; ++n) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
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)
|
2001-12-10 01:13:39 +01:00
|
|
|
|
|| !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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_hero(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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:
|
2004-02-09 23:20:40 +01:00
|
|
|
|
df_bonus = (int)(power/5);
|
|
|
|
|
force = lovar(get_force(power, 4));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
df_bonus = 1;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)power;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_berserk(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
at_bonus = 1;
|
|
|
|
|
df_malus = 0;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)power;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_frighten(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power, 2);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, 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 {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_tiredsoldiers(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
int n = 0;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
int force = (int)(power * power * 4);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s", unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
2004-04-18 23:44:24 +02:00
|
|
|
|
if (!count_enemies(b, fi->side, FIGHT_ROW, BEHIND_ROW)) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
scat(", aber niemand war in Reichweite.");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (force) {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_windshield(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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:
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)get_force(power,4);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
at_malus = level/4;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2004-02-09 23:20:40 +01:00
|
|
|
|
force = (int)power;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
at_malus = 2;
|
|
|
|
|
}
|
2004-04-18 23:44:24 +02:00
|
|
|
|
enemies = count_enemies(b, fi->side, minrow, maxrow);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (!enemies) {
|
|
|
|
|
scat(", aber niemand war in Reichweite.");
|
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
do {
|
2002-04-07 02:44:01 +02:00
|
|
|
|
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));
|
|
|
|
|
|
2002-10-04 23:37:35 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_reeling_arrows(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
unit *mage = fi->unit;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
|
|
|
|
|
unused(power);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
b->reelarrow = true;
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_denyattack(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2001-03-04 19:41:27 +01:00
|
|
|
|
/* 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);
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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 */
|
2001-04-16 16:34:19 +02:00
|
|
|
|
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
|
|
|
|
{
|
2001-03-04 19:41:27 +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);
|
2001-03-04 19:41:27 +01:00
|
|
|
|
fi->run.region = fleeregion(mage);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2001-03-04 19:41:27 +01:00
|
|
|
|
fi->run.region = fleeregion(mage);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
2001-04-22 20:14:07 +02: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);
|
2001-03-04 19:41:27 +01:00
|
|
|
|
fi->run.hp = mage->hp;
|
|
|
|
|
fi->run.number = mage->number;
|
2001-04-22 20:14:07 +02:00
|
|
|
|
/* fighter leeren */
|
|
|
|
|
rmfighter(fi, mage->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2001-03-04 19:41:27 +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;
|
|
|
|
|
}
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_armorshield(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int effect;
|
|
|
|
|
int duration;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
duration = (int)(20*power*power);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
effect = level/4;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
duration = (int)(power*power);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
do_meffect(fi, SHIELD_ARMOR, effect, duration);
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_reduceshield(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int effect;
|
|
|
|
|
int duration;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
duration = (int)(50*power*power);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
effect = level*3;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
duration = (int)get_force(power,5);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
do_meffect(fi, SHIELD_REDUCE, effect, duration);
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_fumbleshield(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
int effect;
|
|
|
|
|
int duration;
|
|
|
|
|
unit *mage = fi->unit;
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
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;
|
|
|
|
|
|
2003-07-29 11:48:03 +02:00
|
|
|
|
cv_foreach(s, b->sides) {
|
2001-01-25 10:37:55 +01:00
|
|
|
|
if (helping(df->side, s)) {
|
|
|
|
|
healable += s->casualties;
|
|
|
|
|
}
|
2003-07-29 11:48:03 +02:00
|
|
|
|
} cv_next(s);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
return healable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* wiederbeleben */
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_reanimate(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
unit *mage = fi->unit;
|
2004-02-09 23:20:40 +01:00
|
|
|
|
int healable, j=0;
|
|
|
|
|
double c = 0.50;
|
|
|
|
|
double k = EFFECT_HEALING_SPELL * power;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
switch(sp->id) {
|
|
|
|
|
case SPL_REANIMATE:
|
|
|
|
|
sprintf(buf, "%s beginnt ein Ritual der Wiederbelebung",
|
|
|
|
|
unitname(mage));
|
2004-02-09 23:20:40 +01:00
|
|
|
|
c += 0.02 * power;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
sprintf(buf, "%s zaubert %s",
|
2002-05-01 21:08:32 +02:00
|
|
|
|
unitname(mage),
|
|
|
|
|
spell_name(sp, default_locale));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
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);
|
2004-02-09 23:20:40 +01:00
|
|
|
|
healable = (int)min(k, healable);
|
|
|
|
|
while (healable--) {
|
2004-05-29 20:57:18 +02:00
|
|
|
|
fighter * tf = select_corpse(b, fi);
|
|
|
|
|
if (tf!=NULL && tf->side->casualties > 0
|
|
|
|
|
&& old_race(tf->unit->race) != RC_DAEMON
|
|
|
|
|
&& (chance(c)))
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-29 20:57:18 +02:00
|
|
|
|
assert(tf->alive < tf->unit->number);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
/* 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
|
2004-05-29 20:57:18 +02:00
|
|
|
|
* oder weggelaufene ist t.fighter->hitpoints[tf->alive] */
|
|
|
|
|
tf->person[tf->alive].hp = 2;
|
|
|
|
|
++tf->alive;
|
|
|
|
|
++tf->side->size[SUM_ROW];
|
|
|
|
|
++tf->side->size[tf->unit->status + 1];
|
|
|
|
|
++tf->side->healed;
|
|
|
|
|
--tf->side->casualties;
|
|
|
|
|
assert(tf->side->casualties>=0);
|
|
|
|
|
--tf->side->dead;
|
|
|
|
|
assert(tf->side->dead>=0);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
++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
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_keeploot(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
|
|
|
|
battle *b = fi->side->battle;
|
|
|
|
|
|
2002-05-01 21:08:32 +02:00
|
|
|
|
sprintf(buf, "%s zaubert %s.", unitname(fi->unit),
|
|
|
|
|
spell_name(sp, default_locale));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
|
2004-02-09 23:20:40 +01:00
|
|
|
|
b->keeploot = (int)max(50, b->keeploot + 5*power);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
return level;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_healing(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-22 02:01:00 +02:00
|
|
|
|
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;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
sprintf(buf, "%s k<>mmert sich um die Verletzten", unitname(mage));
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
/* 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 */
|
|
|
|
|
power *= 200;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
if (get_item(mage, I_AMULET_OF_HEALING) > 0) {
|
|
|
|
|
scat(" und benutzt das ");
|
|
|
|
|
scat(locale_string(default_locale, resourcename(oldresourcetype[R_AMULET_OF_HEALING], 0)));
|
|
|
|
|
scat(", um die Heilzauber zu verst<73>rken");
|
|
|
|
|
power *= 2;
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
/* gehe alle denen wir helfen der reihe nach durch, heile verwundete,
|
|
|
|
|
* bis zu verteilende HP aufgebraucht sind */
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
fgs = fighters(b, fi, minrow, maxrow, FS_HELP);
|
|
|
|
|
v_scramble(fgs->begin, fgs->end);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-02-09 23:20:40 +01:00
|
|
|
|
healhp = (int)power;
|
2004-05-22 02:01:00 +02:00
|
|
|
|
for (fig = fgs->begin; fig != fgs->end; ++fig) {
|
|
|
|
|
fighter *df = *fig;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
if (healhp<=0) break;
|
|
|
|
|
|
|
|
|
|
/* wir heilen erstmal keine Monster */
|
|
|
|
|
if (!playerrace(df->unit->race))
|
|
|
|
|
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;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
if (healhp<=0) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
/* Untote kann man nicht heilen */
|
|
|
|
|
if (fval(df->unit->race, RCF_NOHEAL))
|
|
|
|
|
continue;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
hp = unit_max_hp(df->unit);
|
|
|
|
|
for (n = 0; n < df->unit->number; n++) {
|
|
|
|
|
if (healhp<=0) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
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);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
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);
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-22 02:01:00 +02:00
|
|
|
|
return level;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2004-02-09 23:20:40 +01:00
|
|
|
|
sp_undeadhero(fighter * fi, int level, double power, spell * sp)
|
2001-01-25 10:37:55 +01:00
|
|
|
|
{
|
2004-05-20 00:59:08 +02:00
|
|
|
|
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;
|
2004-05-20 09:34:02 +02:00
|
|
|
|
int n, undead = 0;
|
|
|
|
|
int force = (int)get_force(power,0);
|
2004-05-20 00:59:08 +02:00
|
|
|
|
double c = 0.50 + 0.02 * power;
|
|
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
|
|
2004-05-20 09:34:02 +02:00
|
|
|
|
if (force<=0) break;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-20 00:59:08 +02:00
|
|
|
|
/* keine Monster */
|
2004-05-20 09:34:02 +02:00
|
|
|
|
if (!playerrace(du->race)) continue;
|
2004-05-20 00:59:08 +02:00
|
|
|
|
|
|
|
|
|
if (df->alive + df->run.number < du->number) {
|
2004-05-20 09:34:02 +02:00
|
|
|
|
int j = 0;
|
2004-05-20 00:59:08 +02:00
|
|
|
|
|
|
|
|
|
/* Wieviele Untote k<>nnen wir aus dieser Einheit wecken? */
|
2004-05-21 12:56:07 +02:00
|
|
|
|
for (n = df->alive + df->run.number; n != du->number; n++) {
|
2004-05-20 00:59:08 +02:00
|
|
|
|
if (chance(c)) {
|
2004-05-20 09:34:02 +02:00
|
|
|
|
++j;
|
|
|
|
|
if (--force<=0) break;
|
2004-05-20 00:59:08 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (j > 0) {
|
2004-05-21 11:37:49 +02:00
|
|
|
|
unit * u = createunit(r, mage->faction, 0, new_race[RC_UNDEAD]);
|
|
|
|
|
|
|
|
|
|
/* new units gets some stats from old unit */
|
|
|
|
|
set_string(&u->name, du->name);
|
|
|
|
|
set_string(&u->display, du->display);
|
|
|
|
|
u->status = du->status;
|
|
|
|
|
setguard(u, GUARD_NONE);
|
|
|
|
|
|
|
|
|
|
/* inherit stealth from magician */
|
|
|
|
|
if (fval(mage, UFL_PARTEITARNUNG)) {
|
|
|
|
|
fset(u, UFL_PARTEITARNUNG);
|
2004-05-20 00:59:08 +02:00
|
|
|
|
}
|
2004-05-21 11:37:49 +02:00
|
|
|
|
|
|
|
|
|
/* transfer dead people to new unit, set hitpoints to those of old unit */
|
|
|
|
|
transfermen(du, u, j);
|
|
|
|
|
u->hp = u->number * unit_max_hp(du);
|
2004-05-21 12:56:07 +02:00
|
|
|
|
assert(j<=df->side->casualties);
|
2004-05-21 11:37:49 +02:00
|
|
|
|
df->side->casualties -= j;
|
|
|
|
|
df->side->dead -= j;
|
|
|
|
|
|
|
|
|
|
/* counting total number of undead */
|
|
|
|
|
undead += j;
|
2004-05-20 00:59:08 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cv_kill(fgs);
|
|
|
|
|
|
|
|
|
|
if (undead == 0) {
|
2004-05-21 11:37:49 +02:00
|
|
|
|
sprintf(buf, "%s kann keine Untoten rufen.", unitname(mage));
|
2004-05-20 00:59:08 +02:00
|
|
|
|
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);
|
|
|
|
|
}
|
2001-01-25 10:37:55 +01:00
|
|
|
|
|
2004-05-20 00:59:08 +02:00
|
|
|
|
battlerecord(b, buf);
|
|
|
|
|
return level;
|
2001-01-25 10:37:55 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------ */
|