- 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);
mage->magietyp = (magic_t)mtype;
for (i=0;i!=MAXCOMBATSPELLS;++i) {
spell * sp = NULL;
int level = 0;
if (global.data_version<SPELLNAME_VERSION) {
int spid;
fscanf (F, "%d %d", &spid, &mage->combatspells[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;i<MAXCOMBATSPELLS;i++) {
m->combatspells[i].sp = NULL;

View File

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

View File

@ -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 (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;
}
/** 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);

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_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);

View File

@ -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,

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>
</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">
<type>
<arg name="mage" type="unit"/>