예제 #1
0
파일: combatspells.c 프로젝트: mideg/server
int sp_tiredsoldiers(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;
  int n = 0;
  int force = (int)(power * power * 4);
  message *m;

  if (!count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW,
      SELECT_ADVANCE | SELECT_FIND)) {
    message *m =
      msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
    message_all(b, m);
    msg_release(m);
    return 0;
  }

  while (force) {
    troop t = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
    fighter *df = t.fighter;

    if (!df)
      break;

    assert(!helping(fi->side, df->side));
    if (!(df->person[t.index].flags & FL_TIRED)) {
      if (!is_magic_resistant(mage, df->unit, 0)) {
        df->person[t.index].flags = df->person[t.index].flags | FL_TIRED;
        df->person[t.index].defence -= 2;
        ++n;
      }
    }
    --force;
  }

  m = msg_message("cast_tired_effect", "mage spell amount", fi->unit, sp, n);
  message_all(b, m);
  msg_release(m);
  return level;
}
예제 #2
0
int sp_windshield(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;
    int force, at_malus;
    int enemies;
    message *m;

    force = (int)get_force(power, 4);
    at_malus = level / 4;

    enemies = count_enemies(b, fi, BEHIND_ROW, BEHIND_ROW, SELECT_ADVANCE);
    if (!enemies) {
        m = msg_message("spell_out_of_range", "mage spell", fi->unit, sp);
        message_all(b, m);
        msg_release(m);
        return 0;
    }

    while (force && enemies) {
        troop dt = select_enemy(fi, BEHIND_ROW, BEHIND_ROW, SELECT_ADVANCE);
        fighter *df = dt.fighter;
        --enemies;

        if (!df)
            break;
        assert(!helping(fi->side, df->side));

        if (df->person[dt.index].missile) {
            /* this suxx... affects your melee weapon as well. */
            df->person[dt.index].attack -= at_malus;
            --force;
        }
    }

    m = msg_message("cast_storm_effect", "mage spell", fi->unit, sp);
    message_all(b, m);
    msg_release(m);
    return level;
}
예제 #3
0
/* Versteinern */
int sp_petrify(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;
    /* Wirkt auf erste und zweite Reihe */
    int force, enemies;
    int stoned = 0;
    message *m;

    force = lovar(get_force(power, 0));

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
    if (!enemies) {
        message *m =
            msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
        message_all(b, m);
        msg_release(m);
        return 0;
    }

    while (force && stoned < enemies) {
        troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
        unit *du = dt.fighter->unit;
        if (!is_magic_resistant(mage, du, 0)) {
            /* person ans ende hinter die lebenden schieben */
            remove_troop(dt);
            ++stoned;
        }
        --force;
    }

    m =
        msg_message("cast_petrify_effect", "mage spell amount", fi->unit, sp,
        stoned);
    message_all(b, m);
    msg_release(m);
    return level;
}
예제 #4
0
int sp_sleep(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    const spell * sp = co->sp;
    battle *b = fi->side->battle;
    unit *mage = fi->unit;
    unit *du;
    troop dt;
    int force, enemies;
    int k = 0;
    message *m;
    /* Immer aus der ersten Reihe nehmen */

    force = lovar(co->force * 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);
        msg_release(m);
        return 0;
    }
    while (force && enemies) {
        dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
        assert(dt.fighter);
        du = dt.fighter->unit;
        if (!is_magic_resistant(mage, du, 0)) {
            dt.fighter->person[dt.index].flags |= FL_SLEEPING;
            ++k;
            --enemies;
        }
        --force;
    }

    m = msg_message("cast_sleep_effect", "mage spell amount", fi->unit, sp, k);
    message_all(b, m);
    msg_release(m);
    return level;
}
예제 #5
0
/* Generischer Kampfzauber */
int damage_spell(struct castorder * co, int dmg, int strength)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    const spell * sp = co->sp;
    double power = co->force;
    battle *b = fi->side->battle;
    troop at, dt;
    message *m;
    /* Immer aus der ersten Reihe nehmen */
    int enemies, killed = 0;
    int force = lovar(get_force(power, strength));
    const char *damage = spell_damage(dmg);

    at.fighter = fi;
    at.index = 0;

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
    if (enemies == 0) {
        m = msg_message("spell_out_of_range", "mage spell", fi->unit, sp);
        message_all(b, m);
        msg_release(m);
        return 0;
    }

    while (force > 0 && killed < enemies) {
        dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
        assert(dt.fighter);
        --force;
        killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
    }

    m = msg_message("cast_combatspell", "mage spell dead",
        fi->unit, sp, killed);
    message_all(b, m);
    msg_release(m);

    return level;
}
예제 #6
0
/*! \brief Activate the special skill
 *
 * This function activates the special skill for a hero,
 * including targetting etc. if required.
 *
 * \param   attack_fighter_index Hero to process
 * \returns 1 if the skill was used, otherwise 0
 */
int skill_use(size_t attack_fighter_index)
{
	int tgt, found_item, a, b, c, p, cts, tx, ty, next_target = 0, nn[NUM_FIGHTERS];
	size_t enemy_index;
	size_t fighter_index;
	std::unique_ptr<Raster> temp;
	tempa = Magic.status_adjust(attack_fighter_index);
	switch (pidx[attack_fighter_index])
	{
	case SENSAR:
		tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE);
		if (tgt == -1)
		{
			return 0;
		}
		enemy_index = (unsigned int)tgt;
		temp = std::unique_ptr<Raster>(new Raster(320, 240));
		blit(Combat.backart, temp.get(), 0, 0, 0, 0, 320, 240);
		Draw.color_scale(temp.get(), Combat.backart, 16, 31);
		b = fighter[attack_fighter_index].mhp / 20;
		strcpy(attack_string, _("Rage"));
		display_attack_string = 1;
		tempa.stats[eStat::Attack] = fighter[attack_fighter_index].stats[eStat::Attack];
		tempa.stats[eStat::Hit] = fighter[attack_fighter_index].stats[eStat::Hit];
		if (fighter[enemy_index].crit == 1)
		{
			tempa.stats[eStat::Attack] += b;
			tempa.stats[eStat::Hit] += b;
		}
		Combat.fight(attack_fighter_index, enemy_index, 1);
		if (fighter[enemy_index].IsDead())
		{
			for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++)
			{
				if (fighter[fighter_index].IsAlive())
				{
					nn[next_target] = fighter_index;
					next_target++;
				}
			}
			if (next_target > 0)
			{
				enemy_index = nn[kqrandom->random_range_exclusive(0, next_target)];
				Combat.fight(attack_fighter_index, enemy_index, 1);
			}
		}

		fighter[attack_fighter_index].hp -= (b * 2);
		Combat.AdjustHealth(attack_fighter_index, b * 2);
		display_attack_string = 0;
		blit(temp.get(), Combat.backart, 0, 0, 0, 0, 320, 240);
		Effects.display_amount(attack_fighter_index, FONT_DECIDE, 0);
		if (fighter[attack_fighter_index].IsAlive() && fighter[attack_fighter_index].hp <= 0)
		{
			Combat.fkill(attack_fighter_index);
			Effects.death_animation(attack_fighter_index, 0);
		}
		break;

	case SARINA:
		fighter[attack_fighter_index].ctmem = 1000;
		strcpy(attack_string, _("Sweep"));
		display_attack_string = 1;
		tempa.stats[eStat::Attack] = tempa.stats[eStat::Attack] * 75 / 100;
		fighter[attack_fighter_index].aframe = 6;
		Combat.UnsetDatafileImageCoords();
		Combat.battle_render(0, 0, 0);
		Draw.blit2screen(0, 0);
		kq_wait(150);
		Combat.multi_fight(attack_fighter_index);
		display_attack_string = 0;
		break;

	case CORIN:
		strcpy(attack_string, _("Elemental Infusion"));
		display_attack_string = 1;
		fighter[attack_fighter_index].aux = 2;
		if (combat_spell_menu(attack_fighter_index) == 1)
		{
			Effects.draw_castersprite(
				attack_fighter_index,
				eff[magic[fighter[attack_fighter_index].csmem].eff].kolor);
			Combat.UnsetDatafileImageCoords();
			play_effect(22, 128);
			Draw.convert_cframes(
				attack_fighter_index,
				eff[magic[fighter[attack_fighter_index].csmem].eff].kolor - 3,
				eff[magic[fighter[attack_fighter_index].csmem].eff].kolor + 3, 0);
			Combat.battle_render(0, 0, 0);
			fullblit(double_buffer, back);
			for (p = 0; p < 2; p++)
			{
				for (a = 0; a < 16; a++)
				{
					tx = fighter[attack_fighter_index].cx +
						(fighter[attack_fighter_index].cw / 2);
					ty = fighter[attack_fighter_index].cy +
						(fighter[attack_fighter_index].cl / 2);
					if (p == 0)
					{
						circlefill(
							double_buffer, tx, ty, a,
							eff[magic[fighter[attack_fighter_index].csmem].eff].kolor);
					}
					else
					{
						circlefill(
							double_buffer, tx, ty, 15 - a,
							eff[magic[fighter[attack_fighter_index].csmem].eff].kolor);
						Combat.draw_fighter(attack_fighter_index, 0);
					}
					Draw.blit2screen(0, 0);
					kq_wait(50);
					fullblit(back, double_buffer);
				}
			}
			Draw.revert_cframes(attack_fighter_index, 0);
			Combat.battle_render(0, 0, 0);
			Draw.blit2screen(0, 0);
			infusion(attack_fighter_index, fighter[attack_fighter_index].csmem);
			c = Magic.mp_needed(attack_fighter_index, fighter[attack_fighter_index].csmem);
			if (c < 1)
			{
				c = 1;
			}
			fighter[attack_fighter_index].mp -= c;
			Combat.SetEtherEffectActive(attack_fighter_index, false);
			fighter[attack_fighter_index].aux = 1;
		}
		else
		{
			fighter[attack_fighter_index].aux = 0;
			display_attack_string = 0;
			return 0;
		}
		display_attack_string = 0;
		fighter[attack_fighter_index].SetInfuse(magic[fighter[attack_fighter_index].csmem].elem);
		break;

	case AJATHAR:
		if (fighter[attack_fighter_index].unl > 0)
		{
			strcpy(attack_string, _("Dispel Undead"));
			display_attack_string = 1;
			fullblit(double_buffer, back);
			for (a = 0; a < 14/*MagicNumber*/; a++)
			{
				Draw.convert_cframes(PSIZE, 1 + a, 15, 1);
				for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++)
				{
					if (Effects.is_active(fighter_index))
					{
						Combat.draw_fighter(fighter_index, 0);
					}
				}
				Draw.blit2screen(0, 0);
				kq_wait(50);
				fullblit(back, double_buffer);
			}
			Draw.revert_cframes(PSIZE, 1);
			display_attack_string = 0;
			b = fighter[attack_fighter_index].lvl * 15;
			for (fighter_index = PSIZE; fighter_index < PSIZE + Combat.GetNumEnemies(); fighter_index++)
			{
				if (fighter[fighter_index].IsAlive() && fighter[fighter_index].mhp > 0)
				{
					if (fighter[fighter_index].unl == 99 || fighter[fighter_index].unl == 0)
					{
						cts = 0;
					}
					else
					{
						a = (fighter[attack_fighter_index].lvl + 5) - fighter[fighter_index].unl;
						if (a > 0)
						{
							cts = a * 8;
						}
						else
						{
							cts = 0;
						}
					}
					if (kqrandom->random_range_exclusive(0, 100) < cts)
					{
						if (b >= fighter[fighter_index].hp)
						{
							b -= fighter[fighter_index].hp;
							Combat.SetShowDeathEffectAnimation(fighter_index, true);
							Combat.fkill(fighter_index);
						}
					}
				}
			}
			Effects.death_animation(PSIZE, 1);
			Combat.UnsetDatafileImageCoords();
			Combat.battle_render(attack_fighter_index, attack_fighter_index, 0);
		}
		else
		{
			a = kqrandom->random_range_exclusive(0, 100);
			c = fighter[attack_fighter_index].lvl / 10 + 1;
			if (a < 25)
			{
				b = kqrandom->random_range_exclusive(0, 5 * c) + 1;
			}
			else
			{
				if (a < 90)
				{
					b = kqrandom->random_range_exclusive(0, 10 * c) + (20 * c);
				}
				else
				{
					b = kqrandom->random_range_exclusive(0, 25 * c) + (50 * c);
				}
			}
			strcpy(attack_string, _("Divine Cure"));
			display_attack_string = 1;
			Effects.draw_spellsprite(0, 1, 15, 1);
			display_attack_string = 0;
			for (fighter_index = 0; fighter_index < numchrs; fighter_index++)
			{
				if (!fighter[fighter_index].IsStone() && fighter[fighter_index].IsAlive())
				{
					int amount = Magic.do_shell_check(fighter_index, b);
					Combat.AdjustHealth(fighter_index, amount);
				}
			}
			Effects.display_amount(0, FONT_YELLOW, 1);
			for (fighter_index = 0; fighter_index < numchrs; fighter_index++)
			{
				if (!fighter[fighter_index].IsStone() && fighter[fighter_index].IsAlive())
				{
					Magic.adjust_hp(fighter_index, Combat.GetHealthAdjust(fighter_index));
				}
			}
		}
		break;

	case CASANDRA:
		fighter[attack_fighter_index].atrack[0] = fighter[attack_fighter_index].stats[eStat::Aura];
		fighter[attack_fighter_index].atrack[1] = fighter[attack_fighter_index].stats[eStat::Spirit];
		fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].stats[eStat::Aura] * 15 / 10;
		fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].stats[eStat::Spirit] * 15 / 10;
		fighter[attack_fighter_index].atrack[2] = fighter[attack_fighter_index].mrp;
		fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].mrp * 15 / 10;
		if (combat_spell_menu(attack_fighter_index) == 1)
		{
			Combat.SetEtherEffectActive(attack_fighter_index, false);
			fighter[attack_fighter_index].aux = 1;
			fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].atrack[0];
			fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].atrack[1];
			fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].atrack[2];
		}
		else
		{
			fighter[attack_fighter_index].stats[eStat::Aura] = fighter[attack_fighter_index].atrack[0];
			fighter[attack_fighter_index].stats[eStat::Spirit] = fighter[attack_fighter_index].atrack[1];
			fighter[attack_fighter_index].mrp = fighter[attack_fighter_index].atrack[2];
			return 0;
		}
		break;

	case TEMMIN:
		fighter[attack_fighter_index].aux = 1;
		fighter[attack_fighter_index].defend = 1;
		break;

	case AYLA:
		tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE);
		if (tgt == -1)
		{
			return 0;
		}
		enemy_index = (uint32_t)tgt;
		tx = fighter[attack_fighter_index].cx;
		ty = fighter[attack_fighter_index].cy;
		fighter[attack_fighter_index].cx = fighter[enemy_index].cx - 16;
		fighter[attack_fighter_index].cy = fighter[enemy_index].cy + fighter[enemy_index].cl - 40;
		fighter[attack_fighter_index].facing = 1;
		strcpy(attack_string, _("Steal"));
		display_attack_string = 1;
		Combat.battle_render(0, attack_fighter_index + 1, 0);
		Draw.blit2screen(0, 0);
		kq_wait(100);
		play_effect(SND_MENU, 128);
		kq_wait(500);
		display_attack_string = 0;
		Combat.battle_render(attack_fighter_index, attack_fighter_index, 0);
		found_item = 0;
#ifdef DEBUGMODE
		if (debugging > 2)
		{
			if (fighter[enemy_index].steal_item_rare > 0)
			{
				/* This steals a rare item from monster, if there is one */
				found_item = fighter[enemy_index].steal_item_rare;
				fighter[enemy_index].steal_item_rare = 0;
			}
			else if (fighter[enemy_index].steal_item_common > 0)
			{
				/* This steals a common item from a monster, if there is one */
				found_item = fighter[enemy_index].steal_item_common;
				fighter[enemy_index].steal_item_common = 0;
			}
			if (found_item > 0)
			{
				if (check_inventory(found_item, 1) != 0)
				{
					sprintf(strbuf, _("%s taken!"), items[found_item].name);
					Draw.message(strbuf, items[found_item].icon, 0, 0, 0);
				}
			}
			else
			{
				if (fighter[enemy_index].steal_item_common == 0 && fighter[enemy_index].steal_item_rare == 0)
				{
					Draw.message(_("Nothing to steal!"), 255, 0, 0, 0);
				}
				else
				{
					Draw.message(_("Couldn't steal!"), 255, 0, 0, 0);
				}
			}
		}
#else
		cts = party[pidx[attack_fighter_index]].lvl * 2 + 35;
		if (cts > 95)
		{
			cts = 95;
		}
		if (kqrandom->random_range_exclusive(0, 100) < cts)
		{
			if (fighter[enemy_index].steal_item_rare > 0 && (kqrandom->random_range_exclusive(0, 100) < 5))
			{
				/* This steals a rare item from monster, if there is one */
				found_item = fighter[enemy_index].steal_item_rare;
				fighter[enemy_index].steal_item_rare = 0;
			}
			else if (fighter[enemy_index].steal_item_common > 0 && (kqrandom->random_range_exclusive(0, 100) < 95))
			{
				/* This steals a common item from a monster, if there is one */
				found_item = fighter[enemy_index].steal_item_common;
				fighter[enemy_index].steal_item_common = 0;
			}
			if (found_item > 0)
			{
				if (check_inventory(found_item, 1) != 0)
				{
					sprintf(strbuf, _("%s taken!"), items[found_item].name);
					Draw.message(strbuf, items[found_item].icon, 0, 0, 0);
				}
			}
			else
			{
				if (fighter[enemy_index].steal_item_common == 0 && fighter[enemy_index].steal_item_rare == 0)
				{
					Draw.message(_("Nothing to steal!"), 255, 0, 0, 0);
				}
				else
				{
					Draw.message(_("Couldn't steal!"), 255, 0, 0, 0);
				}
			}
		}
		else
		{
			Draw.message(_("Couldn't steal!"), 255, 0, 0, 0);
		}
#endif
		fighter[attack_fighter_index].cx = tx;
		fighter[attack_fighter_index].cy = ty;
		display_attack_string = 0;
		fighter[attack_fighter_index].facing = 0;
		Combat.battle_render(attack_fighter_index, attack_fighter_index, 0);
		Draw.blit2screen(0, 0);
		break;

	case NOSLOM:
		tgt = select_enemy(attack_fighter_index, TGT_ENEMY_ONE);
		if (tgt == -1)
		{
			return 0;
		}
		enemy_index = (uint32_t)tgt;
		reveal(enemy_index);
		break;
	default:
		break;
	}
	return 1;
}
예제 #7
0
/** The mind blast spell for regular folks.
* This spell temporarily reduces the skill of the victims
*/
int sp_mindblast(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;
    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);

    if (!enemies) {
        m = msg_message("spell_out_of_range", "mage spell", fi->unit, sp);
        message_all(b, m);
        msg_release(m);
        return 0;
    }

    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 (du->flags & UFL_MARK) {
            /* not this one again */
            continue;
        }

        if (humanoidrace(u_race(du)) && 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, 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;
        }
        du->flags |= UFL_MARK;
        reset = 1;
        enemies -= du->number;
    }

    if (reset) {
        unit *u;
        for (u = b->region->units; u; u = u->next) {
            u->flags &= ~UFL_MARK;
        }
    }

    m = msg_message("sp_mindblast_temp_effect", "mage spell amount", mage, sp, k);
    message_all(b, m);
    msg_release(m);
    return level;
}
예제 #8
0
/** 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(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;
    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 (du->flags & UFL_MARK) {
            /* not this one again */
            continue;
        }

        if (humanoidrace(u_race(du)) && force >= du->number) {
            if (!is_magic_resistant(mage, du, 0)) {
                skill_t sk = random_skill(du, false);
                if (sk != NOSKILL) {
                    skill *sv = unit_skill(du, sk);
                    if (sv) {
                        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. */
            du->flags |= UFL_MARK;
            reset = 1;
        }
        enemies -= du->number;
    }

    if (reset) {
        unit *u;
        for (u = b->region->units; u; u = u->next) {
            u->flags &= ~UFL_MARK;
        }
    }

    m =
        msg_message("sp_mindblast_effect", "mage spell amount dead", mage, sp, k,
        killed);
    message_all(b, m);
    msg_release(m);
    return level;
}
예제 #9
0
/* Generischer Kampfzauber */
int sp_kampfzauber(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;
    troop at, dt;
    message *m;
    /* Immer aus der ersten Reihe nehmen */
    int force, enemies;
    int killed = 0;
    const char *damage;

    if (power <= 0)
        return 0;
    at.fighter = fi;
    at.index = 0;

    switch (sp->id) {
        /* lovar halbiert im Schnitt! */
    case SPL_FIREBALL:
        damage = spell_damage(0);
        force = lovar(get_force(power, 0));
        break;
    case SPL_HAGEL:
        damage = spell_damage(2);
        force = lovar(get_force(power, 4));
        break;
    case SPL_METEORRAIN:
        damage = spell_damage(1);
        force = lovar(get_force(power, 1));
        break;
    default:
        damage = spell_damage(10);
        force = lovar(get_force(power, 10));
    }

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
    if (enemies == 0) {
        message *m =
            msg_message("battle::out_of_range", "mage spell", fi->unit, sp);
        message_all(b, m);
        msg_release(m);
        return 0;
    }

    while (force > 0 && killed < enemies) {
        dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
        assert(dt.fighter);
        --force;
        killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
    }

    m = msg_message("battle::combatspell", "mage spell dead",
        fi->unit, sp, killed);
    message_all(b, m);
    msg_release(m);

    return level;
}