- mapper kompiliert nicht (set_skill, learning)

- Neues Monster, entsteht noch nicht automatisch
- Fliegende Monster ignorieren Kampfreihen
This commit is contained in:
Christian Schlittchen 2002-02-23 19:04:51 +00:00
parent aad9405373
commit ae81e915b7
15 changed files with 307 additions and 43 deletions

View File

@ -946,8 +946,8 @@ remove_troop(troop dt)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
#if SKILLPOINTS #if SKILLPOINTS
static void void
drain_exp(unit *u, int n) drain_exp(const struct unit *u, int n)
{ {
skill_t sk = (skill_t)(rand() % MAXSKILLS); skill_t sk = (skill_t)(rand() % MAXSKILLS);
skill_t ssk; skill_t ssk;
@ -971,8 +971,8 @@ drain_exp(unit *u, int n)
/** reduces the target's exp by an equivalent of n points learning /** reduces the target's exp by an equivalent of n points learning
* 30 points = 1 week * 30 points = 1 week
*/ */
static void void
drain_exp(unit *u, int n) drain_exp(const struct unit *u, int n)
{ {
skill_t sk = (skill_t)(rand() % MAXSKILLS); skill_t sk = (skill_t)(rand() % MAXSKILLS);
skill_t ssk; skill_t ssk;
@ -1334,6 +1334,13 @@ select_enemy(fighter * af, int minrow, int maxrow)
void ** si; void ** si;
int enemies; int enemies;
if(af->unit->race->flags & RCF_FLY) {
/* flying races ignore min- and maxrow and can attack anyone fighting
* them */
minrow = FIGHT_ROW;
maxrow = BEHIND_ROW;
}
enemies = count_enemies(af->side, FS_ENEMY, minrow, maxrow); enemies = count_enemies(af->side, FS_ENEMY, minrow, maxrow);
if (!enemies) if (!enemies)

View File

@ -120,7 +120,6 @@ typedef struct weapon {
/*** fighter::flags ***/ /*** fighter::flags ***/
#define FIG_ATTACKED 1 #define FIG_ATTACKED 1
#define FIG_NOLOOT 2 #define FIG_NOLOOT 2
#define FIG_COMBATEXP 4
typedef unsigned char armor_t; typedef unsigned char armor_t;
enum { enum {
@ -237,5 +236,6 @@ extern boolean enemy (const struct side * a, const struct side * b);
extern struct troop select_corpse(struct battle * b, struct fighter * af); extern struct troop select_corpse(struct battle * b, struct fighter * af);
extern fighter * make_fighter(struct battle * b, struct unit * u, boolean attack); extern fighter * make_fighter(struct battle * b, struct unit * u, boolean attack);
void flee(const troop dt); void flee(const troop dt);
void drain_exp(const struct unit *u, int d);
#endif #endif

View File

@ -637,12 +637,116 @@ sp_dragonodem(fighter * fi, int level, int power, spell * sp)
scat("."); scat(".");
battlerecord(b, buf); battlerecord(b, buf);
return level; 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), sp->name);
/* 11-26 HP */
damage = spell_damage(4);
/* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
force = lovar(get_force(level,6));
enemies = count_enemies(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(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;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* PRECOMBAT */ /* 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;
race *rc;
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, FL_PARTEITARNUNG))
fset(u, FL_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;
}
int int
sp_wolfhowl(fighter * fi, int level, int power, spell * sp) sp_wolfhowl(fighter * fi, int level, int power, spell * sp)
{ {
@ -656,7 +760,7 @@ sp_wolfhowl(fighter * fi, int level, int power, spell * sp)
u->status = ST_FIGHT; u->status = ST_FIGHT;
set_string(&u->name, force == 1 ? "Wolf" : "Wölfe"); set_string(&u->name, racename(mage->faction->locale, u, u->race));
set_level(u, SK_WEAPONLESS, power/3); set_level(u, SK_WEAPONLESS, power/3);
set_level(u, SK_AUSDAUER, power/3); set_level(u, SK_AUSDAUER, power/3);
u->hp = u->number * unit_max_hp(u); u->hp = u->number * unit_max_hp(u);
@ -671,7 +775,7 @@ sp_wolfhowl(fighter * fi, int level, int power, spell * sp)
make_fighter(b, u, true); make_fighter(b, u, true);
sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force, sprintf(buf, "%s ruft %d %s zu Hilfe", unitname(mage), force,
force == 1 ? "Wolf" : "Wölfe"); racename(default_locale, u, u->race));
battlerecord(b, buf); battlerecord(b, buf);
return level; return level;
} }
@ -841,6 +945,10 @@ sp_flee(fighter * fi, int level, int power, spell * sp)
sprintf(buf, "%s stimmt einen düsteren Gesang an", unitname(mage)); sprintf(buf, "%s stimmt einen düsteren Gesang an", unitname(mage));
force = get_force(power,3); force = get_force(power,3);
break; break;
case SPL_AURA_OF_FEAR:
sprintf(buf, "%s ist von dunklen Schatten umgeben", unitname(mage));
force = get_force(power,5);
break;
default: default:
force = get_force(power,10); force = get_force(power,10);
} }

View File

@ -686,6 +686,10 @@ enum {
RC_TEMPLATE, /* 61 */ RC_TEMPLATE, /* 61 */
RC_CLONE, /* 62 */ RC_CLONE, /* 62 */
RC_SHADOWDRAGON,
RC_SHADOWBAT,
RC_NIGHTMARE,
RC_VAMPUNICORN,
MAXRACES, MAXRACES,
NORACE = (race_t) - 1 NORACE = (race_t) - 1

View File

@ -622,8 +622,9 @@ get_combatspelllevel(const unit *u, int nr)
{ {
sc_mage *m; sc_mage *m;
assert(nr < MAXCOMBATSPELLS);
m = get_mage(u); m = get_mage(u);
if (!m || !(nr < MAXCOMBATSPELLS)) { if (!m) {
return -1; return -1;
} }
@ -638,12 +639,15 @@ get_combatspell(const unit *u, int nr)
{ {
sc_mage *m; sc_mage *m;
assert(nr < MAXCOMBATSPELLS);
m = get_mage(u); m = get_mage(u);
if (!m || !(nr < MAXCOMBATSPELLS)) { if (m) {
return (spell *)NULL; return find_spellbyid(m->combatspell[nr]);
} else if(u->race->precombatspell != NO_SPELL) {
return find_spellbyid(u->race->precombatspell);
} }
return find_spellbyid(m->combatspell[nr]); return NULL;
} }
void void

View File

@ -72,6 +72,7 @@ rc_new(const char * zName)
rc->_name[2] = strdup(zBuffer); rc->_name[2] = strdup(zBuffer);
sprintf(zBuffer, "%s_x", zName); sprintf(zBuffer, "%s_x", zName);
rc->_name[3] = strdup(zBuffer); rc->_name[3] = strdup(zBuffer);
rc->precombatspell = NO_SPELL;
return rc; return rc;
} }
@ -169,7 +170,7 @@ static const char * oldracenames[MAXRACES] = {
"centaur", "centaur",
"skeleton", "skeleton lord", "zombie", "juju-zombie", "ghoul", "ghast", "museumghost", "gnome", "skeleton", "skeleton lord", "zombie", "juju-zombie", "ghoul", "ghast", "museumghost", "gnome",
"template", "template",
"clone" "clone", "shadowdragon", "shadowbat", "nightmare", "vampunicorn"
}; };
/* magres, {3 namen}, /* magres, {3 namen},
@ -660,6 +661,7 @@ tagbegin(struct xml_stack * stack)
if (xml_bvalue(tag, "resistcut")) rc->battle_flags |= BF_RES_CUT; if (xml_bvalue(tag, "resistcut")) rc->battle_flags |= BF_RES_CUT;
if (xml_bvalue(tag, "resistpierce")) rc->battle_flags |= BF_RES_PIERCE; if (xml_bvalue(tag, "resistpierce")) rc->battle_flags |= BF_RES_PIERCE;
state->race = rc; state->race = rc;
} else if (strcmp(tag->name, "ai")==0) { } else if (strcmp(tag->name, "ai")==0) {
race * rc = state->race; race * rc = state->race;
@ -698,6 +700,9 @@ tagbegin(struct xml_stack * stack)
} }
a->type = xml_ivalue(tag, "type"); a->type = xml_ivalue(tag, "type");
a->flags = xml_ivalue(tag, "flags"); a->flags = xml_ivalue(tag, "flags");
} else if (strcmp(tag->name, "precombatspell") == 0) {
race * rc = state->race;
rc->precombatspell = xml_ivalue(tag, "spell");
} else if (strcmp(tag->name, "function")==0) { } else if (strcmp(tag->name, "function")==0) {
race * rc = state->race; race * rc = state->race;
const char * name = xml_value(tag, "name"); const char * name = xml_value(tag, "name");

View File

@ -66,7 +66,8 @@ typedef struct race {
char df_default; /* Verteidigungsskill Unbewaffnet (default: -2)*/ char df_default; /* Verteidigungsskill Unbewaffnet (default: -2)*/
char at_bonus; /* Verändert den Angriffsskill (default: 0)*/ char at_bonus; /* Verändert den Angriffsskill (default: 0)*/
char df_bonus; /* Verändert den Verteidigungskill (default: 0)*/ char df_bonus; /* Verändert den Verteidigungskill (default: 0)*/
struct att attack[6]; spellid_t precombatspell;
struct att attack[10];
char bonus[MAXSKILLS]; char bonus[MAXSKILLS];
boolean __remove_me_nonplayer; boolean __remove_me_nonplayer;
int flags; int flags;

View File

@ -636,13 +636,16 @@ spskill(const struct locale * lang, const struct unit * u, skill_t sk, int *dh,
sbuf += sprintf(sbuf, " [%d]", get_skill(u, sk) / u->number); sbuf += sprintf(sbuf, " [%d]", get_skill(u, sk) / u->number);
} }
#else #else
if(effsk > 0 && u->faction->options & Pow(O_SHOWSKCHANGE)) { if(u->faction->options & Pow(O_SHOWSKCHANGE)) {
attrib *a; skill *skill = get_skill(u, sk);
for(a = a_find(u->attribs,&at_showskchange); a; a=a->nexttype) { int oldeff = skill->old + get_modifier(u, sk, skill->old, u->region);
if(a->data.sa[0] == sk) { int diff;
sbuf += sprintf(sbuf, " (%s%hd)", (a->data.sa[1]>0)?"+":"", a->data.sa[1]);
break; oldeff = max(0, oldeff);
} diff = effsk - oldeff;
if(diff != 0) {
sbuf += sprintf(sbuf, " (%s%hd)", (diff>0)?"+":"", diff);
} }
} }
#endif #endif

View File

@ -1474,7 +1474,7 @@ readgame(boolean backup)
assert(weeks>0 && weeks<=lvl+1); assert(weeks>0 && weeks<=lvl+1);
if (lvl) { if (lvl) {
skill * sv = add_skill(u, sk); skill * sv = add_skill(u, sk);
sv->level = (unsigned char)lvl; sv->level = sv->old = (unsigned char)lvl;
sv->weeks = (unsigned char)weeks; sv->weeks = (unsigned char)weeks;
} }
} }
@ -1484,7 +1484,7 @@ readgame(boolean backup)
int weeks = ri(F); int weeks = ri(F);
if (level) { if (level) {
skill * sv = add_skill(u, sk); skill * sv = add_skill(u, sk);
sv->level = (unsigned char)level; sv->level = sv->old = (unsigned char)level;
sv->weeks = (unsigned char)weeks; sv->weeks = (unsigned char)weeks;
} }
} }

View File

@ -30,6 +30,7 @@ typedef struct skill {
unsigned char id; unsigned char id;
unsigned char level; unsigned char level;
unsigned char weeks; unsigned char weeks;
unsigned char old;
#endif #endif
} skill; } skill;

View File

@ -10370,6 +10370,48 @@ spell spelldaten[] =
(spell_f)sp_dragonodem, patzer (spell_f)sp_dragonodem, patzer
}, },
{ SPL_DRAINODEM, "Schattenodem",
"Entzieht Talentstufen und macht Schaden wie Großer Odem",
NULL,
NULL,
M_GRAU, (COMBATSPELL), 5, 12,
{
{R_AURA, 4, SPC_FIX},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}},
(spell_f)sp_dragonodem, patzer
},
{SPL_AURA_OF_FEAR, "Gesang der Furcht",
"Panik",
NULL,
NULL,
M_GRAU, (COMBATSPELL), 5, 12,
{
{R_AURA, 1, SPC_LEVEL},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}},
(spell_f)sp_flee, patzer
},
{SPL_SHADOWCALL, "Schattenruf",
"Ruft Schattenwesen.",
NULL,
NULL,
M_GRAU, (PRECOMBATSPELL), 5, 12,
{
{R_AURA, 2, SPC_LEVEL},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}},
(spell_f)sp_shadowcall, patzer
},
/* SPL_NOSPELL MUSS der letzte Spruch der Liste sein*/ /* SPL_NOSPELL MUSS der letzte Spruch der Liste sein*/
{SPL_NOSPELL, "Keiner", NULL, NULL, NULL, 0, 0, 0, 0, {SPL_NOSPELL, "Keiner", NULL, NULL, NULL, 0, 0, 0, 0,

View File

@ -197,6 +197,9 @@ enum {
SPL_BLOODSACRIFICE, SPL_BLOODSACRIFICE,
SPL_MALLORN, SPL_MALLORN,
SPL_CLONECOPY, SPL_CLONECOPY,
SPL_DRAINODEM, /* 174? */
SPL_AURA_OF_FEAR, /* 175? */
SPL_SHADOWCALL, /* 176? */
MAXALLSPELLS, MAXALLSPELLS,
NO_SPELL = (spellid_t) -1 NO_SPELL = (spellid_t) -1
}; };
@ -238,6 +241,7 @@ extern int sp_reduceshield(struct fighter * fi, int level, int power, struct spe
extern int sp_armorshield(struct fighter * fi, int level, int power, struct spell * sp); extern int sp_armorshield(struct fighter * fi, int level, int power, struct spell * sp);
extern int sp_stun(struct fighter * fi, int level, int power, struct spell * sp); extern int sp_stun(struct fighter * fi, int level, int power, struct spell * sp);
extern int sp_undeadhero(struct fighter * fi, int level, int power, struct spell * sp); extern int sp_undeadhero(struct fighter * fi, int level, int power, struct spell * sp);
extern int sp_shadowcall(struct fighter * fi, int level, int power, struct spell * sp);
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */

View File

@ -914,10 +914,6 @@ set_number(unit * u, int count)
#if !SKILLPOINTS #if !SKILLPOINTS
attrib_type at_showskchange = {
"showskchange", NULL, NULL, NULL, NULL, NULL, ATF_UNIQUE
};
boolean boolean
learn_skill(unit * u, skill_t sk, double chance) learn_skill(unit * u, skill_t sk, double chance)
{ {
@ -969,22 +965,6 @@ learn_skill(unit * u, skill_t sk, double chance)
} }
*/ */
/*
if(load == false) {
for(a = a_find(u->attribs, &at_showskchange);a;a = a->nexttype) {
if(a->data.sa[0] == id) {
a->data.sa[1] = (short)(a->data.sa[1] + (level-oldlevel));
break;
}
}
if(a == NULL) {
a = a_add(&u->attribs, a_new(&at_showskchange));
a->data.sa[0] = id;
a->data.sa[1] = (short)(level-oldlevel);
}
}
*/
skill * skill *
add_skill(unit * u, skill_t id) add_skill(unit * u, skill_t id)
{ {

View File

@ -2909,6 +2909,74 @@
<text locale="en">ent</text> <text locale="en">ent</text>
</string> </string>
<string name="shadowdragon">
<text locale="de">Schattendrache</text>
<text locale="en">shadow dragon</text>
</string>
<string name="shadowdragon_p">
<text locale="de">Schattendrachen</text>
<text locale="en">shadow dragons</text>
</string>
<string name="shadowdragon_d">
<text locale="de">Schattendrachen</text>
<text locale="en">shadow dragons</text>
</string>
<string name="shadowdragon_x">
<text locale="de">Schattendrachen</text>
<text locale="en">shadow dragon</text>
</string>
<string name="shadowbat">
<text locale="de">Todesflatter</text>
<text locale="en">darkbat</text>
</string>
<string name="shadowbat_p">
<text locale="de">Todesflattern</text>
<text locale="en">darkbats</text>
</string>
<string name="shadowbat_d">
<text locale="de">Todesflattern</text>
<text locale="en">darkbats</text>
</string>
<string name="shadowbat_x">
<text locale="de">Todesflatter</text>
<text locale="en">darkbat</text>
</string>
<string name="nightmare">
<text locale="de">Alptraum</text>
<text locale="en">nightmare</text>
</string>
<string name="nightmare_p">
<text locale="de">Alpträume</text>
<text locale="en">nightmares</text>
</string>
<string name="nightmare_d">
<text locale="de">Alpträumen</text>
<text locale="en">nightmares</text>
</string>
<string name="nightmare_x">
<text locale="de">Alptraum</text>
<text locale="en">nightmare</text>
</string>
<string name="vampunicorn">
<text locale="de">Nachteinhorn</text>
<text locale="en">vampiric unicorn</text>
</string>
<string name="vampunicorn_p">
<text locale="de">Nachteinhörner</text>
<text locale="en">vampiric unicorns</text>
</string>
<string name="vampunicorn_d">
<text locale="de">Nachteinhörnern</text>
<text locale="en">vampiric unicorns</text>
</string>
<string name="vampunicorn_x">
<text locale="de">Nachteinhorn</text>
<text locale="en">vampiric unicorn</text>
</string>
<string name="wyrm"> <string name="wyrm">
<text locale="de">Wyrm</text> <text locale="de">Wyrm</text>
<text locale="en">wyrm</text> <text locale="en">wyrm</text>

View File

@ -1263,4 +1263,41 @@
<familiar race="wolf"></familiar> <familiar race="wolf"></familiar>
<familiar race="demon"></familiar> <familiar race="demon"></familiar>
</race> </race>
<race name="shadowdragon" magres="0.950000" maxaura="1.000000" regaura="3.000000" recruitcost="2500000" maintenance="0" weight="1" speed="1.000000" hp="2700" ac="10" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="12" scarepeasants fly walk noteach getitem canguard>
<ai splitsize="1" killpeasants attackrandom learn></ai>
<function name="name" value="namedragon"></function>
<function name="move" value="movedragon"></function>
<function name="itemdrop" value="dragondrops"></function>
<skill name="sk_tactics" modifier="20"></skill>
<skill name="sk_perception" modifier="20"></skill>
<attack type="4" damage="5d30"></attack>
<attack type="4" damage="3d20"></attack>
<attack type="4" damage="3d20"></attack>
<attack type="4" damage="5d30"></attack>
<attack type="6" spell="174"></attack>
<attack type="6" spell="175"></attack>
<precombatspell spell="176"></precombatspell>
</race>
<race name="shadowbat" magres="0.800000" maxaura="0.000000" regaura="0.000000" recruitcost="500" maintenance="0" weight="5" speed="1.000000" hp="1" ac="4" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="3" scarepeasants fly walk noteach getitem>
<ai splitsize="5000" killpeasants></ai>
<attack type="4" damage="1d6"></attack>
<attack type="3" damage="1d1"></attack>
</race>
<race name="nightmare" magres="0.500000" maxaura="0.000000" regaura="0.000000" recruitcost="500" maintenance="0" weight="1" speed="1.000000" hp="80" ac="10" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="3" scarepeasants fly walk noteach getitem invinciblenonmagic>
<ai splitsize="500" killpeasants></ai>
<attack type="4" damage="1d4"></attack>
<attack type="4" damage="1d4"></attack>
<attack type="4" damage="1d4"></attack>
<attack type="3" damage="1d4"></attack>
<attack type="2" damage="1d10"></attack>
</race>
<race name="vampunicorn" magres="1.000000" maxaura="0.000000" regaura="0.000000" recruitcost="500" maintenance="0" weight="5" speed="1.000000" hp="30" ac="4" damage="2d4" unarmedattack="0" unarmeddefense="0" attackmodifier="3" defensemodifier="3" scarepeasants walk noteach getitem>
<ai splitsize="5000" killpeasants></ai>
<attack type="4" damage="2d10"></attack>
<attack type="3" damage="1d4"></attack>
<attack type="3" damage="1d4"></attack>
<attack type="3" damage="1d4"></attack>
<attack type="3" damage="1d4"></attack>
<attack type="2" damage="2d60"></attack>
</race>
</races> </races>