/* Panik (Praekampfzauber) */ int flee_spell(struct castorder * co, int strength) { fighter * fi = co->magician.fig; int level = co->level; const spell * sp = co->sp; battle *b = fi->side->battle; unit *mage = fi->unit; selist *fgs, *ql; int n, qi, panik = 0; message *msg; double power = co->force; int force; force = (int)get_force(power, strength); if (force<=0 || !count_enemies(b, fi, FIGHT_ROW, AVOID_ROW, SELECT_ADVANCE | SELECT_FIND)) { msg = msg_message("sp_flee_effect_0", "mage spell", mage, sp); message_all(b, msg); msg_release(msg); return 0; } fgs = select_fighters(b, fi->side, FS_ENEMY, select_afraid, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; force > 0 && ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); for (n = 0; force > 0 && n != df->alive; ++n) { if (df->person[n].flags & FL_PANICED) { /* bei SPL_SONG_OF_FEAR moeglich */ df->person[n].attack -= 1; --force; ++panik; } else if (!(df->person[n].flags & FL_COURAGE) || !(u_race(df->unit)->flags & RCF_UNDEAD)) { if (!is_magic_resistant(mage, df->unit, 0)) { df->person[n].flags |= FL_PANICED; ++panik; } --force; } } } selist_free(fgs); msg = msg_message("sp_flee_effect_1", "mage spell amount", mage, sp, panik); message_all(b, msg); msg_release(msg); return level; }
int sp_healing(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; unit *mage = fi->unit; int j = 0; int healhp = (int)power * 200; selist *fgs; message *msg; bool use_item = has_ao_healing(mage); /* bis zu 11 Personen pro Stufe (einen HP muessen sie ja noch * haben, sonst waeren sie tot) koennen geheilt werden */ if (use_item) { healhp *= 2; } /* gehe alle denen wir helfen der reihe nach durch, heile verwundete, * bis zu verteilende HP aufgebraucht sind */ fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_HELP); scramble_fighters(fgs); j += heal_fighters(fgs, &healhp, false); j += heal_fighters(fgs, &healhp, true); selist_free(fgs); if (j <= 0) { level = j; } if (use_item) { msg = msg_message("healing_effect_1", "mage amount item", mage, j, get_resourcetype(R_AMULET_OF_HEALING)); } else { msg = msg_message("healing_effect_0", "mage amount", mage, j); } message_all(b, msg); msg_release(msg); return level; }
/** Spells: chaosrow / song of confusion. * German Title: 'Gesang der Verwirrung' */ int sp_chaosrow(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; const spell * sp = co->sp; battle *b = fi->side->battle; unit *mage = fi->unit; selist *fgs, *ql; message *m; const char *mtype; int qi, k = 0; bool chaosrow = strcmp(sp->sname, "chaosrow") == 0; if (!count_enemies(b, fi, FIGHT_ROW, NUMROWS, SELECT_ADVANCE | SELECT_FIND)) { m = msg_message("spell_out_of_range", "mage spell", fi->unit, sp); message_all(b, m); msg_release(m); return 0; } power = chaosrow ? (power * 40) : get_force(power, 5); fgs = select_fighters(b, fi->side, FS_ENEMY, select_alive, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); int n = df->unit->number; if (df->alive == 0) continue; if (power <= 0.0) break; if (is_magic_resistant(mage, df->unit, 0)) continue; if (chance(power / n)) { int row = statusrow(df->status); df->side->size[row] -= df->alive; if (u_race(df->unit)->battle_flags & BF_NOBLOCK) { df->side->nonblockers[row] -= df->alive; } row = FIRST_ROW + (rng_int() % (NUMROWS - FIRST_ROW)); switch (row) { case FIGHT_ROW: df->status = ST_FIGHT; break; case BEHIND_ROW: df->status = ST_CHICKEN; break; case AVOID_ROW: df->status = ST_AVOID; break; case FLEE_ROW: df->status = ST_FLEE; break; default: assert(!"unknown combatrow"); } assert(statusrow(df->status) == row); df->side->size[row] += df->alive; if (u_race(df->unit)->battle_flags & BF_NOBLOCK) { df->side->nonblockers[row] += df->alive; } k += df->alive; } power = fmax(0, power - n); } selist_free(fgs); if (chaosrow) { mtype = (k > 0) ? "sp_chaosrow_effect_1" : "sp_chaosrow_effect_0"; } else { mtype = (k > 0) ? "sp_confusion_effect_1" : "sp_confusion_effect_0"; } m = msg_message(mtype, "mage", mage); message_all(b, m); msg_release(m); return level; }
/* Rosthauch */ int sp_combatrosthauch(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; selist *ql, *fgs; int force = lovar(power * 15); int qi, k = 0; if (!count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE | SELECT_FIND)) { message *msg = msg_message("rust_effect_0", "mage", fi->unit); message_all(b, msg); msg_release(msg); return 0; } fgs = select_fighters(b, fi->side, FS_ENEMY, select_armed, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; force>0 && ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); int w; for (w = 0; df->weapons[w].type != NULL; ++w) { weapon *wp = df->weapons; if (df->unit->items && force > 0) { item ** itp = i_find(&df->unit->items, wp->type->itype); if (*itp) { item *it = *itp; requirement *mat = wp->type->itype->construction->materials; int n = force; if (it->number < n) n = it->number; while (mat && mat->number > 0) { if (mat->rtype == get_resourcetype(R_IRON)) { int p; force -= n; k += n; i_change(itp, wp->type->itype, -n); for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].melee == wp) { df->person[p].melee = NULL; --n; } } for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].missile == wp) { df->person[p].missile = NULL; --n; } } break; } mat++; } } } } } selist_free(fgs); if (k == 0) { /* keine Waffen mehr da, die zerstoert werden koennten */ message *msg = msg_message("rust_effect_1", "mage", fi->unit); message_all(b, msg); msg_release(msg); fi->magic = 0; /* kaempft nichtmagisch weiter */ level = 0; } else { message *msg = msg_message("rust_effect_2", "mage", fi->unit); message_all(b, msg); msg_release(msg); } return level; }
int sp_undeadhero(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; unit *mage = fi->unit; region *r = b->region; selist *fgs, *ql; int qi, n, undead = 0; message *msg; int force = (int)get_force(power, 0); double c = 0.50 + 0.02 * power; /* Liste aus allen Kaempfern */ fgs = select_fighters(b, fi->side, FS_ENEMY | FS_HELP, select_hero, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql && force>0; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); unit *du = df->unit; int j = 0; /* Wieviele Untote koennen wir aus dieser Einheit wecken? */ for (n = df->alive + df->run.number; force>0 && n != du->number; n++) { if (chance(c)) { ++j; --force; } } if (j > 0) { item **ilist; unit *u = create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, unit_getname(du), du); /* new units gets some stats from old unit */ unit_setinfo(u, unit_getinfo(du)); unit_setstatus(u, du->status); setguard(u, false); for (ilist = &du->items; *ilist;) { item *itm = *ilist; int loot = itm->number * j / du->number; if (loot != itm->number) { int split = itm->number * j % du->number; if (split > 0 && (rng_int() % du->number) < split) { ++loot; } } i_change(&u->items, itm->type, loot); i_change(ilist, itm->type, -loot); if (*ilist == itm) { ilist = &itm->next; } } /* inherit stealth from magician */ if (mage->flags & UFL_ANON_FACTION) { u->flags |= UFL_ANON_FACTION; } /* transfer dead people to new unit, set hitpoints to those of old unit */ transfermen(du, u, j); u->hp = u->number * unit_max_hp(du); assert(j <= df->side->casualties); df->side->casualties -= j; df->side->dead -= j; /* counting total number of undead */ undead += j; } } selist_free(fgs); if (level > undead) { level = undead; } if (undead == 0) { msg = msg_message("summonundead_effect_0", "mage region", mage, mage->region); } else { msg = msg_message("summonundead_effect_1", "mage region amount", mage, mage->region, undead); } message_all(b, msg); msg_release(msg); return level; }
/* Rosthauch */ int sp_combatrosthauch(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; quicklist *ql, *fgs; int force = lovar(power * 15); int qi, k = 0; if (!count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE | SELECT_FIND)) { message *msg = msg_message("rust_effect_0", "mage", fi->unit); message_all(b, msg); msg_release(msg); return 0; } fgs = fighters(b, fi->side, FIGHT_ROW, BEHIND_ROW - 1, FS_ENEMY); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql; ql_advance(&ql, &qi, 1)) { fighter *df = (fighter *)ql_get(ql, qi); if (df->alive == 0) continue; if (force <= 0) break; /* da n _min(force, x), sollte force maximal auf 0 sinken */ assert(force >= 0); if (df->weapons) { int w; for (w = 0; df->weapons[w].type != NULL; ++w) { weapon *wp = df->weapons; int n = _min(force, wp->used); if (n) { requirement *mat = wp->type->itype->construction->materials; bool iron = false; while (mat && mat->number > 0) { if (mat->rtype == get_resourcetype(R_IRON)) { iron = true; break; } mat++; } if (iron) { int p; force -= n; wp->used -= n; k += n; i_change(&df->unit->items, wp->type->itype, -n); for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].missile == wp) { df->person[p].missile = NULL; --n; } } for (p = 0; n && p != df->unit->number; ++p) { if (df->person[p].melee == wp) { df->person[p].melee = NULL; --n; } } } } } } } ql_free(fgs); if (k == 0) { /* keine Waffen mehr da, die zerst�rt werden k�nnten */ message *msg = msg_message("rust_effect_1", "mage", fi->unit); message_all(b, msg); msg_release(msg); fi->magic = 0; /* k�mpft nichtmagisch weiter */ level = 0; } else { message *msg = msg_message("rust_effect_2", "mage", fi->unit); message_all(b, msg); msg_release(msg); } return level; }
int sp_flee(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; const spell * sp = co->sp; battle *b = fi->side->battle; unit *mage = fi->unit; quicklist *fgs, *ql; int force, n, qi; int panik = 0; message *msg; switch (sp->id) { case SPL_FLEE: force = (int)get_force(power, 4); break; case SPL_SONG_OF_FEAR: force = (int)get_force(power, 3); break; case SPL_AURA_OF_FEAR: force = (int)get_force(power, 5); break; default: force = (int)get_force(power, 10); } if (!count_enemies(b, fi, FIGHT_ROW, AVOID_ROW, SELECT_ADVANCE | SELECT_FIND)) { msg = msg_message("sp_flee_effect_0", "mage spell", mage, sp); message_all(b, msg); msg_release(msg); return 0; } fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql; ql_advance(&ql, &qi, 1)) { fighter *df = (fighter *)ql_get(ql, qi); for (n = 0; n != df->alive; ++n) { if (force < 0) break; if (df->person[n].flags & FL_PANICED) { /* bei SPL_SONG_OF_FEAR m�glich */ df->person[n].attack -= 1; --force; ++panik; } else if (!(df->person[n].flags & FL_COURAGE) || !(u_race(df->unit)->flags & RCF_UNDEAD)) { if (!is_magic_resistant(mage, df->unit, 0)) { df->person[n].flags |= FL_PANICED; ++panik; } --force; } } } ql_free(fgs); msg = msg_message("sp_flee_effect_1", "mage spell amount", mage, sp, panik); message_all(b, msg); msg_release(msg); return level; }
int sp_undeadhero(struct castorder * co) { fighter * fi = co->magician.fig; int level = co->level; double power = co->force; battle *b = fi->side->battle; unit *mage = fi->unit; region *r = b->region; quicklist *fgs, *ql; int qi, n, undead = 0; message *msg; int force = (int)get_force(power, 0); double c = 0.50 + 0.02 * power; /* Liste aus allen Kämpfern */ fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY | FS_HELP); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql; ql_advance(&ql, &qi, 1)) { fighter *df = (fighter *) ql_get(ql, qi); unit *du = df->unit; if (force <= 0) break; /* keine Monster */ if (!playerrace(u_race(du))) continue; if (df->alive + df->run.number < du->number) { int j = 0; /* Wieviele Untote können wir aus dieser Einheit wecken? */ for (n = df->alive + df->run.number; n != du->number; n++) { if (chance(c)) { ++j; if (--force <= 0) break; } } if (j > 0) { unit *u = create_unit(r, mage->faction, 0, new_race[RC_UNDEAD], 0, du->name, du); /* new units gets some stats from old unit */ if (du->display) { unit_setinfo(u, du->display); } else { unit_setinfo(u, NULL); } setstatus(u, du->status); setguard(u, GUARD_NONE); /* inherit stealth from magician */ if (fval(mage, UFL_ANON_FACTION)) { fset(u, UFL_ANON_FACTION); } /* transfer dead people to new unit, set hitpoints to those of old unit */ transfermen(du, u, j); u->hp = u->number * unit_max_hp(du); assert(j <= df->side->casualties); df->side->casualties -= j; df->side->dead -= j; /* counting total number of undead */ undead += j; } } } ql_free(fgs); level = _min(level, undead); if (undead == 0) { msg = msg_message("summonundead_effect_0", "mage region", mage, mage->region); } else { msg = msg_message("summonundead_effect_1", "mage region amount", mage, mage->region, undead); } message_all(b, msg); msg_release(msg); return level; }