Raal's Tome of Destruction

主にroguelikeのことを書くブログです

DCSS ver0.5 Elyvilonメモ

spell1.cc

static bool _can_pacify_monster(const monsters *mon, const int healed)
{
    if (you.religion != GOD_ELYVILON)
        return (false);

    if (healed < 1)
        return (false);

    // I was thinking of jellies when I wrote this, but maybe we shouldn't
    // exclude zombies and such... (jpeg)
    if (mons_intel(mon) <= I_PLANT) // no self-awareness
        return (false);

    const mon_holy_type holiness = mons_holiness(mon);

    if (holiness != MH_HOLY
        && holiness != MH_NATURAL
        && holiness != MH_UNDEAD
        && holiness != MH_DEMONIC)
    {
        return (false);
    }

    if (mons_is_stationary(mon)) // not able to leave the level
        return (false);

    if (mons_is_sleeping(mon)) // not aware of what is happening
        return (false);

    const int factor = (mons_intel(mon) <= I_ANIMAL)       ? 3 : // animals
                       (is_player_same_species(mon->type)) ? 2   // same species
                                                           : 1;  // other

    int divisor = 3;

    if (holiness == MH_HOLY)
        divisor--;
    else if (holiness == MH_UNDEAD)
        divisor++;
    else if (holiness == MH_DEMONIC)
        divisor += 2;

    const int random_factor = random2((you.skills[SK_INVOCATIONS] + 1) *
                                      healed / divisor);

#ifdef DEBUG_DIAGNOSTICS
    mprf(MSGCH_DIAGNOSTICS,
         "pacifying %s? max hp: %d, factor: %d, Inv: %d, healed: %d, rnd: %d",
         mon->name(DESC_PLAIN).c_str(), mon->max_hit_points, factor,
         you.skills[SK_INVOCATIONS], healed, random_factor);
#endif

    if (mon->max_hit_points < factor * random_factor)
        return (true);

    return (false);
}

// Returns: 1 -- success, 0 -- failure, -1 -- cancel
static int _healing_spell(int healed, bool divine_ability,
                          const coord_def& where, bool not_self,
                          targ_mode_type mode)
{
    ASSERT(healed >= 1);

    bolt beam;
    dist spd;

    if (where.origin())
    {
        spd.isValid = spell_direction(spd, beam, DIR_TARGET,
                                      mode != TARG_NUM_MODES ? mode :
                                      you.religion == GOD_ELYVILON ?
                                            TARG_ANY : TARG_FRIEND,
                                      LOS_RADIUS,
                                      false, true, true, "Heal whom?");
    }
    else
    {
        spd.target  = where;
        spd.isValid = in_bounds(spd.target);
    }

    if (!spd.isValid)
        return (-1);

    if (spd.target == you.pos())
    {
        if (not_self)
        {
            mpr("You can only heal others!");
            return (-1);
        }

        mpr("You are healed.");
        inc_hp(healed, false);
        return (1);
    }

    monsters* monster = monster_at(spd.target);
    if (!monster)
    {
        mpr("There isn't anything there!");
        // This isn't a cancel, to avoid leaking invisible monster
        // locations.
        return (0);
    }

    const bool can_pacify = _can_pacify_monster(monster, healed);
    const bool is_hostile = _mons_hostile(monster);

    // Don't divinely heal a monster you can't pacify.
    if (divine_ability
        && you.religion == GOD_ELYVILON
        && !can_pacify)
    {
        canned_msg(MSG_NOTHING_HAPPENS);
        return (0);
    }

    bool did_something = false;

    if (you.religion == GOD_ELYVILON
        && can_pacify && is_hostile)
    {
        did_something = true;

        const bool is_holy     = mons_is_holy(monster);
        const bool is_summoned = mons_is_summoned(monster);

        int pgain = 0;
        if (!is_holy && !is_summoned && you.piety < MAX_PIETY)
        {
            pgain = random2(1 + random2(monster->max_hit_points /
                            (2 + you.piety / 20)));
        }

        if (pgain > 0)
            simple_god_message(" approves of your offer of peace.");
        else
            simple_god_message(" supports your offer of peace.");

        if (is_holy)
            good_god_holy_attitude_change(monster);
        else
        {
            simple_monster_message(monster, " turns neutral.");
            mons_pacify(monster);

            // Give a small piety return.
            if (pgain > 0)
                gain_piety(pgain);
        }
    }

    if (heal_monster(monster, healed, false))
    {
        did_something = true;
        mprf("You heal %s.", monster->name(DESC_NOCAP_THE).c_str());

        if (monster->hit_points == monster->max_hit_points)
            simple_monster_message(monster, " is completely healed.");
        else
            print_wounds(monster);

        if (you.religion == GOD_ELYVILON && !is_hostile)
        {
            int pgain = 0;
            if (one_chance_in(8) && you.piety < MAX_PIETY)
                pgain = 1;

            if (pgain > 0)
            {
                simple_god_message(" approves of your healing of a fellow "
                                   "creature.");
            }
            else
            {
                simple_god_message(" appreciates your healing of a fellow "
                                   "creature.");
            }

            // Give a small piety return.
            if (pgain > 0)
                gain_piety(pgain);
        }
    }

    if (!did_something)
    {
        canned_msg(MSG_NOTHING_HAPPENS);
        return (0);
    }

    return (1);
}

// Returns: 1 -- success, 0 -- failure, -1 -- cancel
int cast_healing(int pow, bool divine_ability, const coord_def& where,
                 bool not_self, targ_mode_type mode)
{
    pow = std::min(50, pow);
    return (_healing_spell(pow + roll_dice(2, pow) - 2, divine_ability, where,
                           not_self, mode));
}

void remove_divine_vigour()
{
    mpr("Your divine vigour fades away.", MSGCH_DURATION);
    you.duration[DUR_DIVINE_VIGOUR] = 0;
    you.attribute[ATTR_DIVINE_VIGOUR] = 0;
    calc_hp();
    calc_mp();
}

bool cast_divine_vigour()
{
    bool success = false;

    if (!you.duration[DUR_DIVINE_VIGOUR])
    {
        mprf("%s grants you divine vigour.",
             god_name(you.religion).c_str());

        const int vigour_amt = 1 + (you.skills[SK_INVOCATIONS]/6);
        const int old_hp_max = you.hp_max;
        const int old_mp_max = you.max_magic_points;
        you.attribute[ATTR_DIVINE_VIGOUR] = vigour_amt;
        you.duration[DUR_DIVINE_VIGOUR]
            = 40 + (you.skills[SK_INVOCATIONS]*5)/2;
        calc_hp();
        inc_hp(you.hp_max - old_hp_max, false);
        calc_mp();
        inc_mp(you.max_magic_points - old_mp_max, false);

        success = true;
    }
    else
        canned_msg(MSG_NOTHING_HAPPENS);

    return (success);
}

abl-show.cc

    // Elyvilon
    { ABIL_ELYVILON_DESTROY_WEAPONS, "Destroy Weapons",
      0, 0, 0, 0, ABFLAG_NONE },
    { ABIL_ELYVILON_LESSER_HEALING_SELF, "Lesser Self-Healing",
      1, 0, 100, generic_cost::range(0, 1), ABFLAG_CONF_OK },
    { ABIL_ELYVILON_LESSER_HEALING_OTHERS, "Lesser Healing",
      1, 0, 100, 0, ABFLAG_CONF_OK },
    { ABIL_ELYVILON_PURIFICATION, "Purification", 2, 0, 150, 1,
      ABFLAG_CONF_OK },
    { ABIL_ELYVILON_GREATER_HEALING_SELF, "Greater Self-Healing",
      2, 0, 250, 2, ABFLAG_CONF_OK },
    { ABIL_ELYVILON_GREATER_HEALING_OTHERS, "Greater Healing",
      2, 0, 250, 2, ABFLAG_CONF_OK },
    { ABIL_ELYVILON_RESTORATION, "Restoration", 3, 0, 400, 3, ABFLAG_CONF_OK },
    { ABIL_ELYVILON_DIVINE_VIGOUR, "Divine Vigour", 0, 0, 600, 6,
      ABFLAG_CONF_OK },
    case ABIL_ELYVILON_LESSER_HEALING_SELF:
    case ABIL_ELYVILON_LESSER_HEALING_OTHERS:
    {
        const bool self = (abil.ability == ABIL_ELYVILON_LESSER_HEALING_SELF);

        if (cast_healing(3 + (you.skills[SK_INVOCATIONS] / 6), true,
                         self ? you.pos() : coord_def(0, 0), !self,
                         self ? TARG_NUM_MODES : TARG_HOSTILE) < 0)
        {
            return (false);
        }

        exercise(SK_INVOCATIONS, 1);
        break;
    }
    case ABIL_ELYVILON_PURIFICATION:
        purification();
        exercise(SK_INVOCATIONS, 2 + random2(3));
        break;

    case ABIL_ELYVILON_GREATER_HEALING_SELF:
    case ABIL_ELYVILON_GREATER_HEALING_OTHERS:
    {
        const bool self = (abil.ability == ABIL_ELYVILON_GREATER_HEALING_SELF);

        if (cast_healing(10 + (you.skills[SK_INVOCATIONS] / 3), true,
                         self ? you.pos() : coord_def(0, 0), !self,
                         self ? TARG_NUM_MODES : TARG_HOSTILE) < 0)
        {
            return (false);
        }

        exercise(SK_INVOCATIONS, 3 + random2(5));
        break;
    }
    case ABIL_ELYVILON_RESTORATION:
        restore_stat(STAT_ALL, 0, false);
        unrot_hp(100);

        exercise(SK_INVOCATIONS, 4 + random2(6));
        break;

    case ABIL_ELYVILON_DIVINE_VIGOUR:
        if (!cast_divine_vigour())
            return (false);

        exercise(SK_INVOCATIONS, 6 + random2(10));
        break;

player.cc

int get_real_hp(bool trans, bool rotted)
{
    int hitp;

    hitp  = (you.base_hp - 5000) + (you.base_hp2 - 5000);
    hitp += (you.experience_level * you.skills[SK_FIGHTING]) / 5;

    // Being berserk makes you resistant to damage. I don't know why.
    if (trans && you.duration[DUR_BERSERKER])
        hitp *= 2;

    if (trans)
    {
        // Some transformations give you extra hp.
        switch (you.attribute[ATTR_TRANSFORMATION])
        {
        case TRAN_STATUE:
            hitp *= 15;
            hitp /= 10;
            break;
        case TRAN_ICE_BEAST:
            hitp *= 12;
            hitp /= 10;
            break;
        case TRAN_DRAGON:
            hitp *= 16;
            hitp /= 10;
            break;
        }
    }

    if (rotted)
        hitp += player_rotted();

    // Frail and robust mutations, and divine vigour.
    hitp *= 10 + player_mutation_level(MUT_ROBUST)
               + you.attribute[ATTR_DIVINE_VIGOUR]
               - player_mutation_level(MUT_FRAIL);
    hitp /= 10;

    return (hitp);
}