- make mindblast less crazy
This commit is contained in:
Enno Rehling 2008-03-29 22:06:20 +00:00
parent 3e475d63ad
commit 536b177387
6 changed files with 182 additions and 69 deletions

View File

@ -206,16 +206,29 @@ read_mage(attrib * a, FILE * F)
fscanf(F, "%d %d %d", &mtype, &mage->spellpoints, &mage->spchange); fscanf(F, "%d %d %d", &mtype, &mage->spellpoints, &mage->spchange);
mage->magietyp = (magic_t)mtype; mage->magietyp = (magic_t)mtype;
for (i=0;i!=MAXCOMBATSPELLS;++i) { for (i=0;i!=MAXCOMBATSPELLS;++i) {
spell * sp = NULL;
int level = 0;
if (global.data_version<SPELLNAME_VERSION) { if (global.data_version<SPELLNAME_VERSION) {
int spid; int spid;
fscanf (F, "%d %d", &spid, &mage->combatspells[i].level); fscanf (F, "%d %d", &spid, &level);
if (spid>=0) { if (spid>=0) {
mage->combatspells[i].sp = find_spellbyid(mage->magietyp, (spellid_t)spid); sp = find_spellbyid(mage->magietyp, (spellid_t)spid);
} }
} else { } else {
fscanf (F, "%s %d", spname, &mage->combatspells[i].level); fscanf (F, "%s %d", spname, &level);
if (strcmp("none", spname)!=0) { if (strcmp("none", spname)!=0) {
mage->combatspells[i].sp = find_spell(mage->magietyp, spname); sp = find_spell(mage->magietyp, spname);
}
}
if (sp && level>0) {
int slot = -1;
if (sp->sptyp & PRECOMBATSPELL) slot = 0;
else if (sp->sptyp & COMBATSPELL) slot = 1;
else if (sp->sptyp & POSTCOMBATSPELL) slot = 2;
if (slot>=0) {
mage->combatspells[slot].level = level;
mage->combatspells[slot].sp = sp;
} }
} }
} }
@ -524,50 +537,50 @@ get_combatspelllevel(const unit *u, int nr)
const spell* const spell*
get_combatspell(const unit *u, int nr) get_combatspell(const unit *u, int nr)
{ {
sc_mage *m; sc_mage *m;
assert(nr < MAXCOMBATSPELLS); assert(nr < MAXCOMBATSPELLS);
m = get_mage(u); m = get_mage(u);
if (m) { if (m) {
return m->combatspells[nr].sp; return m->combatspells[nr].sp;
} else if (u->race->precombatspell != NULL) { } else if (u->race->precombatspell != NULL) {
return u->race->precombatspell; return u->race->precombatspell;
} }
return NULL; return NULL;
} }
void void
set_combatspell(unit *u, spell *sp, struct order * ord, int level) set_combatspell(unit *u, spell *sp, struct order * ord, int level)
{ {
sc_mage *m = get_mage(u); sc_mage *m = get_mage(u);
int i = -1; int i = -1;
if (!m) return; if (!m) return;
/* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */
if (knowsspell(u->region, u, sp) == false){ if (knowsspell(u->region, u, sp) == false){
/* Fehler 'Spell not found' */ /* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC); cmistake(u, ord, 173, MSG_MAGIC);
return; return;
} }
if (!has_spell(u, sp)) { if (!has_spell(u, sp)) {
/* Diesen Zauber kennt die Einheit nicht */ /* Diesen Zauber kennt die Einheit nicht */
cmistake(u, ord, 169, MSG_MAGIC); cmistake(u, ord, 169, MSG_MAGIC);
return; return;
} }
if (!(sp->sptyp & ISCOMBATSPELL)) { if (!(sp->sptyp & ISCOMBATSPELL)) {
/* Diesen Kampfzauber gibt es nicht */ /* Diesen Kampfzauber gibt es nicht */
cmistake(u, ord, 171, MSG_MAGIC); cmistake(u, ord, 171, MSG_MAGIC);
return; return;
} }
if (sp->sptyp & PRECOMBATSPELL) i = 0; if (sp->sptyp & PRECOMBATSPELL) i = 0;
else if (sp->sptyp & COMBATSPELL) i = 1; else if (sp->sptyp & COMBATSPELL) i = 1;
else if (sp->sptyp & POSTCOMBATSPELL) i = 2; else if (sp->sptyp & POSTCOMBATSPELL) i = 2;
assert(i>=0); assert(i>=0);
m->combatspells[i].sp = sp; m->combatspells[i].sp = sp;
m->combatspells[i].level = level; m->combatspells[i].level = level;
return; return;
} }
void void
@ -580,7 +593,6 @@ unset_combatspell(unit *u, spell *sp)
m = get_mage(u); m = get_mage(u);
if (!m) return; if (!m) return;
/* Kampfzauber löschen */
if (!sp) { if (!sp) {
for (i=0;i<MAXCOMBATSPELLS;i++) { for (i=0;i<MAXCOMBATSPELLS;i++) {
m->combatspells[i].sp = NULL; m->combatspells[i].sp = NULL;

View File

@ -127,6 +127,7 @@ finalize_skillmod(attrib * a)
free(a->data.v); free(a->data.v);
} }
/** temporary skill modification (NOT SAVED!). */
attrib_type at_skillmod = { attrib_type at_skillmod = {
"skillmod", "skillmod",
init_skillmod, init_skillmod,

View File

@ -457,23 +457,32 @@ sp_speed(fighter * fi, int level, double power, spell * sp)
} }
static skill_t static skill_t
random_skill(unit *u) random_skill(unit *u, boolean weighted)
{ {
int n = 0; int n = 0;
skill * sv; skill * sv;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
if (sv->level>0) ++n; if (sv->level>0) {
if (weighted) n+= sv->level;
else ++n;
}
} }
if(n == 0) if (n == 0)
return NOSKILL; return NOSKILL;
n = rng_int()%n; n = rng_int()%n;
for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) {
if (sv->level>0) { if (sv->level>0) {
if (n-- == 0) return sv->id; if (weighted) {
if (n<sv->level) return sv->id;
n-=sv->level;
} else {
if (n == 0) return sv->id;
--n;
}
} }
} }
@ -481,22 +490,19 @@ random_skill(unit *u)
return NOSKILL; return NOSKILL;
} }
/** The mind blast spell for regular folks.
* This spell temporarily reduces the skill of the victims
*/
int int
sp_mindblast(fighter * fi, int level, double power, spell * sp) sp_mindblast_temp(fighter * fi, int level, double power, spell * sp)
{ {
battle *b = fi->side->battle; battle *b = fi->side->battle;
unit *mage = fi->unit; unit *mage = fi->unit;
troop dt; int k = 0, reset = 0, maxloss = (level+2)/3;
unit *du;
skill_t sk;
int killed = 0;
int force, enemies;
int k = 0;
message * m; message * m;
int force = lovar(power * 25);
int enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
force = lovar(power * 25);
enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
if (!enemies) { if (!enemies) {
m = msg_message("battle::out_of_range", "mage spell", fi->unit, sp); m = msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
message_all(b, m); message_all(b, m);
@ -504,26 +510,110 @@ sp_mindblast(fighter * fi, int level, double power, spell * sp)
return 0; return 0;
} }
while (force && enemies) { while (force>0 && enemies>0) {
dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); unit *du;
troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
assert(dt.fighter); assert(dt.fighter);
du = dt.fighter->unit; du = dt.fighter->unit;
if (humanoidrace(du->race) && !is_magic_resistant(mage, du, 0)) { if (fval(du, UFL_MARK)) {
sk = random_skill(du); /* not this one again */
if (sk != NOSKILL) { continue;
skill * sv = get_skill(du, sk); }
int n = 1 + rng_int() % 3;
/* Skill abziehen */ if (humanoidrace(du->race) && force>=du->number) {
reduce_skill(du, sv, n); if (!is_magic_resistant(mage, du, 0)) {
} else { skill_t sk = random_skill(du, true);
/* Keine Skills mehr, Einheit töten */ if (sk != NOSKILL) {
kill_troop(dt); int n = 1 + rng_int() % maxloss;
++killed; attrib * a = make_skillmod(sk, SMF_ALWAYS, NULL, 0.0, n);
} /* neat: you can add a whole lot of these to a unit, they stack */
--enemies; a_add(&du->attribs, a);
++k; }
k += du->number;
}
force -= du->number;
}
fset(du, UFL_MARK);
reset = 1;
enemies -= du->number;
}
if (reset) {
unit * u;
for (u=b->region->units;u;u=u->next) {
freset(u, UFL_MARK);
}
}
m = msg_message("sp_mindblast_temp_effect", "mage spell amount", mage, sp, k);
message_all(b, m);
msg_release(m);
return level;
}
/** A mind blast spell for monsters.
* This spell PERMANENTLY reduces the skill of the victims or kills them
* when they have no skills left. Not currently in use.
*/
int
sp_mindblast(fighter * fi, int level, double power, spell * sp)
{
battle *b = fi->side->battle;
unit *mage = fi->unit;
int killed = 0, k = 0, reset = 0;
message * m;
int force = lovar(power * 25);
int enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
if (!enemies) {
m = msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
message_all(b, m);
msg_release(m);
return 0;
}
while (enemies>0 && force>0) {
unit *du;
troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
assert(dt.fighter);
du = dt.fighter->unit;
if (fval(du, UFL_MARK)) {
/* not this one again */
continue;
}
if (humanoidrace(du->race) && force>=du->number) {
if (!is_magic_resistant(mage, du, 0)) {
skill_t sk = random_skill(du, false);
if (sk != NOSKILL) {
skill * sv = get_skill(du, sk);
int n = 1 + rng_int() % 3;
reduce_skill(du, sv, n);
k+=du->number;
} else {
/* unit has no skill. kill it. */
kill_troop(dt);
++killed;
}
}
force -= du->number;
} else {
/* only works against humanoids, don't try others. but do remove them
* from 'force' once or we may never terminate. */
fset(du, UFL_MARK);
reset = 1;
}
enemies -= du->number;
}
if (reset) {
unit * u;
for (u=b->region->units;u;u=u->next) {
freset(u, UFL_MARK);
} }
--force;
} }
m = msg_message("sp_mindblast_effect", "mage spell amount dead", mage, sp, k, killed); m = msg_message("sp_mindblast_effect", "mage spell amount dead", mage, sp, k, killed);

View File

@ -40,6 +40,7 @@ extern "C" {
extern int sp_hero(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_hero(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_frighten(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_frighten(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_mindblast(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_mindblast(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_mindblast_temp(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_speed(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_speed(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_wolfhowl(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_wolfhowl(struct fighter * fi, int level, double power, struct spell * sp);
extern int sp_dragonodem(struct fighter * fi, int level, double power, struct spell * sp); extern int sp_dragonodem(struct fighter * fi, int level, double power, struct spell * sp);

View File

@ -7907,7 +7907,7 @@ static spelldata spelldaten[] =
}, },
{ {
SPL_MINDBLAST, "mindblast", NULL, NULL, NULL, SPL_MINDBLAST, "mindblast", NULL, NULL, NULL,
M_TRAUM, (COMBATSPELL | SPELLLEVEL), 5, 11, M_TRAUM, (PRECOMBATSPELL | SPELLLEVEL), 5, 11,
{ {
{ "aura", 2, SPC_LEVEL }, { "aura", 2, SPC_LEVEL },
{ 0, 0, 0 }, { 0, 0, 0 },
@ -7915,7 +7915,7 @@ static spelldata spelldaten[] =
{ 0, 0, 0 }, { 0, 0, 0 },
{ 0, 0, 0 } { 0, 0, 0 }
}, },
(spell_f)sp_mindblast, NULL (spell_f)sp_mindblast_temp, NULL
}, },
{ {
SPL_ORKDREAM, "orkdream", NULL, NULL, SPL_ORKDREAM, "orkdream", NULL, NULL,

View File

@ -7598,6 +7598,15 @@
<text locale="de">"$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden getötet."</text> <text locale="de">"$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden getötet."</text>
</message> </message>
<message name="sp_mindblast_temp_effect" section="magic">
<type>
<arg name="mage" type="unit"/>
<arg name="spell" type="spell"/>
<arg name="amount" type="int"/>
</type>
<text locale="de">"$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren kurzzeitig ihr Gedächtnis."</text>
</message>
<message name="sp_shadowcall_effect" section="magic"> <message name="sp_shadowcall_effect" section="magic">
<type> <type>
<arg name="mage" type="unit"/> <arg name="mage" type="unit"/>