forked from github/server
- make mindblast less crazy
This commit is contained in:
parent
3e475d63ad
commit
536b177387
6 changed files with 182 additions and 69 deletions
|
@ -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;
|
||||
|
|
|
@ -127,6 +127,7 @@ finalize_skillmod(attrib * a)
|
|||
free(a->data.v);
|
||||
}
|
||||
|
||||
/** temporary skill modification (NOT SAVED!). */
|
||||
attrib_type at_skillmod = {
|
||||
"skillmod",
|
||||
init_skillmod,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"/>
|
||||
|
|
Loading…
Add table
Reference in a new issue