From 536b177387b091d1cde63ad3d1a1063af95ed52f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 29 Mar 2008 22:06:20 +0000 Subject: [PATCH] http://eressea.upb.de/mantis/view.php?id=1393 - make mindblast less crazy --- src/common/kernel/magic.c | 84 +++++++++-------- src/common/kernel/skill.c | 1 + src/common/spells/combatspells.c | 152 ++++++++++++++++++++++++------- src/common/spells/combatspells.h | 1 + src/common/spells/spells.c | 4 +- src/res/messages.xml | 9 ++ 6 files changed, 182 insertions(+), 69 deletions(-) diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index 885e80f70..c0c8221a7 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -206,16 +206,29 @@ read_mage(attrib * a, FILE * F) fscanf(F, "%d %d %d", &mtype, &mage->spellpoints, &mage->spchange); mage->magietyp = (magic_t)mtype; for (i=0;i!=MAXCOMBATSPELLS;++i) { + spell * sp = NULL; + int level = 0; if (global.data_versioncombatspells[i].level); + fscanf (F, "%d %d", &spid, &level); if (spid>=0) { - mage->combatspells[i].sp = find_spellbyid(mage->magietyp, (spellid_t)spid); + sp = find_spellbyid(mage->magietyp, (spellid_t)spid); } } else { - fscanf (F, "%s %d", spname, &mage->combatspells[i].level); + fscanf (F, "%s %d", spname, &level); + 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* get_combatspell(const unit *u, int nr) { - sc_mage *m; + sc_mage *m; - assert(nr < MAXCOMBATSPELLS); - m = get_mage(u); - if (m) { - return m->combatspells[nr].sp; - } else if (u->race->precombatspell != NULL) { - return u->race->precombatspell; - } + assert(nr < MAXCOMBATSPELLS); + m = get_mage(u); + if (m) { + return m->combatspells[nr].sp; + } else if (u->race->precombatspell != NULL) { + return u->race->precombatspell; + } - return NULL; + return NULL; } void 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; - if (!m) return; + if (!m) return; - /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ - if (knowsspell(u->region, u, sp) == false){ - /* Fehler 'Spell not found' */ - cmistake(u, ord, 173, MSG_MAGIC); - return; - } - if (!has_spell(u, sp)) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, ord, 169, MSG_MAGIC); - return; - } - if (!(sp->sptyp & ISCOMBATSPELL)) { - /* Diesen Kampfzauber gibt es nicht */ - cmistake(u, ord, 171, MSG_MAGIC); - return; - } + /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ + if (knowsspell(u->region, u, sp) == false){ + /* Fehler 'Spell not found' */ + cmistake(u, ord, 173, MSG_MAGIC); + return; + } + if (!has_spell(u, sp)) { + /* Diesen Zauber kennt die Einheit nicht */ + cmistake(u, ord, 169, MSG_MAGIC); + return; + } + if (!(sp->sptyp & ISCOMBATSPELL)) { + /* Diesen Kampfzauber gibt es nicht */ + cmistake(u, ord, 171, MSG_MAGIC); + return; + } - if (sp->sptyp & PRECOMBATSPELL) i = 0; + if (sp->sptyp & PRECOMBATSPELL) i = 0; else if (sp->sptyp & COMBATSPELL) i = 1; else if (sp->sptyp & POSTCOMBATSPELL) i = 2; assert(i>=0); - m->combatspells[i].sp = sp; - m->combatspells[i].level = level; - return; + m->combatspells[i].sp = sp; + m->combatspells[i].level = level; + return; } void @@ -580,7 +593,6 @@ unset_combatspell(unit *u, spell *sp) m = get_mage(u); if (!m) return; - /* Kampfzauber löschen */ if (!sp) { for (i=0;icombatspells[i].sp = NULL; diff --git a/src/common/kernel/skill.c b/src/common/kernel/skill.c index 969b959f8..10135f389 100644 --- a/src/common/kernel/skill.c +++ b/src/common/kernel/skill.c @@ -127,6 +127,7 @@ finalize_skillmod(attrib * a) free(a->data.v); } +/** temporary skill modification (NOT SAVED!). */ attrib_type at_skillmod = { "skillmod", init_skillmod, diff --git a/src/common/spells/combatspells.c b/src/common/spells/combatspells.c index dfda1bd6e..5fd07b276 100644 --- a/src/common/spells/combatspells.c +++ b/src/common/spells/combatspells.c @@ -457,23 +457,32 @@ sp_speed(fighter * fi, int level, double power, spell * sp) } static skill_t -random_skill(unit *u) +random_skill(unit *u, boolean weighted) { int n = 0; skill * 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; n = rng_int()%n; for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { if (sv->level>0) { - if (n-- == 0) return sv->id; + if (weighted) { + if (nlevel) return sv->id; + n-=sv->level; + } else { + if (n == 0) return sv->id; + --n; + } } } @@ -481,22 +490,19 @@ random_skill(unit *u) return NOSKILL; } +/** The mind blast spell for regular folks. +* This spell temporarily reduces the skill of the victims +*/ 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; unit *mage = fi->unit; - troop dt; - unit *du; - skill_t sk; - int killed = 0; - int force, enemies; - int k = 0; + int k = 0, reset = 0, maxloss = (level+2)/3; 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) { m = msg_message("battle::out_of_range", "mage spell", fi->unit, sp); message_all(b, m); @@ -504,26 +510,110 @@ sp_mindblast(fighter * fi, int level, double power, spell * sp) return 0; } - while (force && enemies) { - dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); + while (force>0 && enemies>0) { + unit *du; + troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE); + 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 + rng_int() % 3; - /* Skill abziehen */ - reduce_skill(du, sv, n); - } else { - /* Keine Skills mehr, Einheit töten */ - kill_troop(dt); - ++killed; - } - --enemies; - ++k; + 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, true); + if (sk != NOSKILL) { + int n = 1 + rng_int() % maxloss; + 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 */ + a_add(&du->attribs, a); + } + 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); diff --git a/src/common/spells/combatspells.h b/src/common/spells/combatspells.h index f8396b6d8..cfda537bb 100644 --- a/src/common/spells/combatspells.h +++ b/src/common/spells/combatspells.h @@ -40,6 +40,7 @@ extern "C" { 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_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_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); diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 14f340169..0893aa467 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -7907,7 +7907,7 @@ static spelldata spelldaten[] = }, { SPL_MINDBLAST, "mindblast", NULL, NULL, NULL, - M_TRAUM, (COMBATSPELL | SPELLLEVEL), 5, 11, + M_TRAUM, (PRECOMBATSPELL | SPELLLEVEL), 5, 11, { { "aura", 2, SPC_LEVEL }, { 0, 0, 0 }, @@ -7915,7 +7915,7 @@ static spelldata spelldaten[] = { 0, 0, 0 }, { 0, 0, 0 } }, - (spell_f)sp_mindblast, NULL + (spell_f)sp_mindblast_temp, NULL }, { SPL_ORKDREAM, "orkdream", NULL, NULL, diff --git a/src/res/messages.xml b/src/res/messages.xml index a84127edb..ca3136079 100644 --- a/src/res/messages.xml +++ b/src/res/messages.xml @@ -7598,6 +7598,15 @@ "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren Erinnerungen, $int($dead) wurden getötet." + + + + + + + "$unit($mage) zaubert $spell($spell). $int($amount) Krieger verloren kurzzeitig ihr Gedächtnis." + +