Example #1
0
int sp_frighten(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 at_malus = 0;
    int df_malus = 0;
    int force = 0;
    int enemies = 0;
    int targets = 0;
    message *m;

    at_malus = level - 4;
    if (at_malus < 1) at_malus = 1;
    df_malus = 2;
    force = (int)get_force(power, 2);

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, 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, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
        fighter *df = dt.fighter;
        --enemies;

        if (!df)
            break;

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

        if (df->person[dt.index].flags & FL_COURAGE) {
            df->person[dt.index].flags &= ~(FL_COURAGE);
        }
        if (!is_magic_resistant(mage, df->unit, 0)) {
            df->person[dt.index].attack -= at_malus;
            df->person[dt.index].defense -= df_malus;
            targets++;
        }
        --force;
    }

    m =
        msg_message("cast_frighten_effect", "mage spell amount", fi->unit, sp,
        targets);
    message_all(b, m);
    msg_release(m);
    return level;
}
Example #2
0
/* Feuersturm: Betrifft sehr viele Gegner (in der Regel alle),
 * macht nur vergleichsweise geringen Schaden */
int sp_immolation(struct castorder * co)
{
    fighter * fi = co->magician.fig;
    int level = co->level;
    const spell * sp = co->sp;
    battle *b = fi->side->battle;
    troop at;
    int force, qi, killed = 0;
    const char *damage;
    quicklist *fgs, *ql;
    message *m;

    /* 2d4 HP */
    damage = spell_damage(5);
    /* Betrifft alle Gegner */
    force = 99999;

    if (!count_enemies(b, fi, FIGHT_ROW, AVOID_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;
    }

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

    fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY);
    for (qi = 0, ql = fgs; ql; ql_advance(&ql, &qi, 1)) {
        fighter *df = (fighter *)ql_get(ql, qi);
        int n = df->alive - df->removed;
        troop dt;

        dt.fighter = df;
        while (n != 0) {
            dt.index = --n;
            killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
            if (--force == 0)
                break;
        }
        if (force == 0)
            break;
    }
    ql_free(fgs);

    m =
        msg_message("battle::combatspell", "mage spell killed", fi->unit, sp,
        killed);
    message_all(b, m);
    msg_release(m);
    return level;
}
Example #3
0
/* 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;
}
Example #4
0
/* Benommenheit: eine Runde kein Angriff */
int sp_stun(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;
    message *m;
    /* Aus beiden Reihen nehmen */
    int force = 0, enemies;
    int stunned;

    if (power <= 0)
        return 0;

    switch (sp->id) {
    case SPL_SHOCKWAVE:
        force = lovar(get_force(power, 1));
        break;
    default:
        assert(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;
    }

    stunned = 0;
    while (force && stunned < enemies) {
        troop dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW, SELECT_ADVANCE);
        fighter *df = dt.fighter;
        unit *du = df->unit;

        --force;
        if (!is_magic_resistant(mage, du, 0)) {
            df->person[dt.index].flags |= FL_STUNNED;
            ++stunned;
        }
    }

    m = msg_message("cast_stun_effect", "mage spell amount", fi->unit, sp, stunned);
    message_all(b, m);
    msg_release(m);
    return level;
}
Example #5
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;

    switch (sp->id) {
    case SPL_WINDSHIELD:
        force = (int)get_force(power, 4);
        at_malus = level / 4;
        break;

    default:
        force = (int)power;
        at_malus = 2;
    }
    enemies = count_enemies(b, fi, BEHIND_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) {
        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;
}
Example #6
0
int sp_dragonodem(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 dt;
    troop at;
    int force, enemies;
    const char *damage;

    /* 11-26 HP */
    damage = spell_damage(4);
    /* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
    force = lovar(get_force(power, 6));

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);

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

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

        while (force && 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;
}
Example #7
0
int sp_drainodem(fighter * fi, int level, double power, spell * sp)
{
    battle *b = fi->side->battle;
    troop dt;
    troop at;
    int force, enemies;
    int drained = 0;
    int killed = 0;
    const char *damage;
    message *m;

    /* 11-26 HP */
    damage = spell_damage(4);
    /* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */
    force = lovar(get_force(power, 6));

    enemies = count_enemies(b, fi, FIGHT_ROW, BEHIND_ROW - 1, 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;
    }

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

    while (force && drained < enemies) {
        dt = select_enemy(fi, FIGHT_ROW, BEHIND_ROW - 1, SELECT_ADVANCE);
        assert(dt.fighter);
        if (hits(at, dt, NULL)) {
            drain_exp(dt.fighter->unit, 90);
            ++drained;
            killed += terminate(dt, at, AT_COMBATSPELL, damage, false);
        }
        --force;
    }

    m =
        msg_message("cast_drainlife_effect", "mage spell amount", fi->unit, sp,
        drained);
    message_all(b, m);
    msg_release(m);
    return level;
}
Example #8
0
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;
}
Example #9
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;
}
Example #10
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;
}
Example #11
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;
}
Example #12
0
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;
}
Example #13
0
/** 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;
}
Example #14
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;
}
Example #15
0
/* 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;
}
Example #16
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;
}
Example #17
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;
}
Example #18
0
/* 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;
}