Пример #1
0
bool
has_dark_sight(struct creature * self)
{
    return (AFF_FLAGGED(self, AFF_INFRAVISION) ||
            PRF_FLAGGED(self, PRF_HOLYLIGHT) ||
            AFF3_FLAGGED(self, AFF3_SONIC_IMAGERY) ||
            AFF_FLAGGED(self, AFF_RETINA) ||
            CHECK_SKILL(self, SKILL_NIGHT_VISION));
}
Пример #2
0
bool
can_psidrain(struct creature *ch, struct creature *vict, int *out_dist, bool msg)
{
    const char *to_char = NULL;
    const char *to_vict = NULL;
    int dist;

    if (CHECK_SKILL(ch, SKILL_PSIDRAIN) < 30 || !IS_PSIONIC(ch)) {
        to_char = "You have no idea how.";
        goto failure;
    }

    if (ROOM_FLAGGED(ch->in_room, ROOM_NOPSIONICS) && GET_LEVEL(ch) < LVL_GOD) {
        to_char = "Psychic powers are useless here!";
        goto failure;
    }

    if (GET_LEVEL(vict) >= LVL_AMBASSADOR && GET_LEVEL(ch) < GET_LEVEL(vict)) {
        to_char = "You cannot locate them.";
        to_vict = "$n has just tried to psidrain you.";
        goto failure;
    }

    if (vict == ch) {
        to_char = "Ha ha... Funny!";
        goto failure;
    }

    if (is_fighting(ch) && vict->in_room != ch->in_room) {
        to_char = "You cannot focus outside the room during battle!";
        goto failure;
    }

    if (ch->in_room != vict->in_room &&
        ch->in_room->zone != vict->in_room->zone) {
        to_char = "$N is not in your zone.";
        goto failure;
    }

    if (ROOM_FLAGGED(vict->in_room, ROOM_NOPSIONICS)
        && GET_LEVEL(ch) < LVL_GOD) {
        to_char = "Psychic powers are useless where $E is!";
        goto failure;
    }

    if (!ok_to_attack(ch, vict, msg))
        return false;

    if (GET_MOVE(ch) < 20) {
        to_char = "You are too physically exhausted.";
        goto failure;
    }

    dist = find_distance(ch->in_room, vict->in_room);
    if (out_dist)
        *out_dist = dist;
    if (dist > ((GET_LEVEL(ch) / 6))) {
        to_char = "$N is out of your psychic range.";
        goto failure;
    }

    if (NULL_PSI(vict)) {
        to_char = "It is pointless to attempt this on $M.";
        goto failure;
    }

    return true;

failure:
    if (msg) {
        if (to_char)
            act(to_char, false, ch, NULL, vict, TO_CHAR);
        if (to_vict)
            act(to_vict, false, ch, NULL, vict, TO_VICT);
    }
    return false;
}
Пример #3
0
void
perform_psidrain(struct creature *ch, struct creature *vict)
{
    int find_distance(struct room_data *tmp, struct room_data *location);
    int dist, drain, prob, percent;

    if (!can_psidrain(ch, vict, &dist, true))
        return;


    if (AFF3_FLAGGED(vict, AFF3_PSISHIELD) && creature_distrusts(vict, ch)) {
        prob = CHECK_SKILL(ch, SKILL_PSIDRAIN) + GET_INT(ch);
        prob += skill_bonus(ch, SKILL_PSIDRAIN);

        percent = skill_bonus(vict, SPELL_PSISHIELD);
        percent += number(1, 120);

        if (mag_savingthrow(vict, GET_LEVEL(ch), SAVING_PSI))
            percent *= 2;

        if (GET_INT(vict) > GET_INT(ch))
            percent += (GET_INT(vict) - GET_INT(ch)) * 8;

        if (percent >= prob) {
            act("Your attack is deflected by $N's psishield!",
                false, ch, NULL, vict, TO_CHAR);
            act("$n's psychic attack is deflected by your psishield!",
                false, ch, NULL, vict, TO_VICT);
            act("$n staggers under an unseen force.",
                true, ch, NULL, vict, TO_NOTVICT);

            return;
        }
    }

    if (GET_MANA(vict) <= 0) {
        act("$E is completely drained of psychic energy.",
            true, ch, NULL, vict, TO_CHAR);
        return;
    }

    drain = dice(GET_LEVEL(ch), GET_INT(ch) + GET_REMORT_GEN(ch)) +
        CHECK_SKILL(ch, SKILL_PSIDRAIN);
    if (dist > 0)
        drain /= dist + 1;

    drain /= 4;

    drain = MAX(0, MIN(GET_MANA(vict), drain));

    prob = CHECK_SKILL(ch, SKILL_PSIDRAIN) + GET_INT(ch) +
        (AFF3_FLAGGED(vict, AFF3_PSISHIELD) ? -20 : 0);

    if (is_fighting(vict))
        prob += 15;

    if (dist > 0)
        prob -= dist * 3;

    act("$n strains against an unseen force.", false, ch, NULL, vict, TO_ROOM);

    //
    // failure
    //

    if (number(0, 121) > prob) {
        send_to_char(ch, "You are unable to create the drainage link!\r\n");
        WAIT_STATE(ch, 2 RL_SEC);

        if (IS_NPC(vict) && !is_fighting(vict)) {

            if (ch->in_room == vict->in_room) {
                add_combat(vict, ch, false);
                add_combat(ch, vict, true);
            } else {
                remember(vict, ch);
                if (NPC2_FLAGGED(vict, NPC2_HUNT))
                    start_hunting(vict, ch);
            }
        }
    }
    //
    // success
    //
    else {

        act("A torrent of psychic energy is ripped out of $N's mind!",
            false, ch, NULL, vict, TO_CHAR);
        if (ch->in_room != vict->in_room &&
            GET_LEVEL(vict) + number(0, CHECK_SKILL(vict, SKILL_PSIDRAIN)) >
            GET_LEVEL(ch))
            act("Your psychic energy is ripped from you from afar!",
                false, ch, NULL, vict, TO_VICT);
        else
            act("Your psychic energy is ripped from you by $n!",
                false, ch, NULL, vict, TO_VICT);
        GET_MANA(vict) -= drain;
        GET_MANA(ch) = MIN(GET_MAX_MANA(ch), GET_MANA(ch) + drain);
        GET_MOVE(ch) -= 20;
        WAIT_STATE(vict, 1 RL_SEC);
        WAIT_STATE(ch, 5 RL_SEC);
        gain_skill_prof(ch, SKILL_PSIDRAIN);

        if (IS_NPC(vict) && !(is_fighting(vict))) {
            if (ch->in_room == vict->in_room) {
                remember(vict, ch);
                if (NPC2_FLAGGED(vict, NPC2_HUNT))
                    start_hunting(vict, ch);
                add_combat(vict, ch, false);
                add_combat(ch, vict, true);
            }
        }
    }
}
Пример #4
0
/*
 * This function controls the change to maxmove, maxmana, and maxhp for
 * each char_class every time they gain a level.
 */
void
advance_level(struct creature *ch, int8_t keep_internal)
{
    int add_hp[2], add_mana[2], add_move[2], i, char_class;
    char *msg;

    add_hp[0] = add_hp[1] = constitution_hitpoint_bonus(GET_CON(ch));
    add_mana[0] = add_mana[1] = wisdom_mana_bonus(GET_WIS(ch));
    add_move[0] = add_move[1] = MAX(0, GET_CON(ch) - 15);

    for (i = 0; i < 2; i++) {

        if (i == 0)
            char_class = MIN(GET_CLASS(ch), NUM_CLASSES - 1);
        else
            char_class = MIN(GET_REMORT_CLASS(ch), NUM_CLASSES - 1);
        if (char_class < 0)
            continue;

        switch (char_class) {
        case CLASS_MAGIC_USER:
            add_hp[i] /= 5;
            add_hp[i] += number(3, 10);
            add_mana[i] += number(1, 11) + (GET_LEVEL(ch) / 3);
            add_move[i] += number(1, 3);
            break;
        case CLASS_CLERIC:
            add_hp[i] /= 2;
            add_hp[i] += number(5, 11);
            add_mana[i] += number(1, 10) + (GET_LEVEL(ch) / 5);
            add_move[i] += number(1, 4);
            break;
        case CLASS_BARD:
            add_hp[i] = add_hp[i] / 3;
            add_hp[i] += number(5, 10);
            add_mana[i] += number(1, 4) + (GET_LEVEL(ch) / 10);
            add_move[i] += number(10, 18);
            break;
        case CLASS_THIEF:
            add_hp[i] /= 3;
            add_hp[i] += number(4, 10);
            add_mana[i] = add_mana[i] * 3 / 10;
            add_move[i] += number(2, 6);
            break;
        case CLASS_MERCENARY:
            add_hp[i] += number(6, 14);
            add_mana[i] = add_mana[i] * 5 / 10;
            add_mana[i] += number(1, 5) + GET_LEVEL(ch) / 10;
            add_move[i] += number(3, 9);
            break;
        case CLASS_WARRIOR:
            add_hp[i] += number(10, 15);
            add_mana[i] = add_mana[i] * 4 / 10;
            add_mana[i] += number(1, 5);
            add_move[i] += number(5, 10);
            break;
        case CLASS_BARB:
            add_hp[i] += number(13, 18);
            add_mana[i] = add_mana[i] * 3 / 10;
            add_mana[i] += number(0, 3);
            add_move[i] += number(5, 10);
            break;
        case CLASS_KNIGHT:
            add_hp[i] += number(7, 13);
            add_mana[i] = add_mana[i] * 7 / 10;
            add_mana[i] += number(1, 4) + (GET_LEVEL(ch) / 15);
            add_move[i] += number(3, 8);
            break;
        case CLASS_RANGER:
            add_hp[i] += number(4, 11);
            add_mana[i] = add_mana[i] * 6 / 10;
            add_mana[i] += number(1, 6) + (GET_LEVEL(ch) / 8);
            add_move[i] += number(6, 14);
            break;
        case CLASS_PSIONIC:
            add_hp[i] /= 3;
            add_hp[i] += number(3, 8);
            add_mana[i] = add_mana[i] * 6 / 10;
            add_mana[i] += number(1, 7) + (GET_LEVEL(ch) / 5);
            add_move[i] += number(2, 6);
            break;
        case CLASS_PHYSIC:
            add_hp[i] /= 4;
            add_hp[i] += number(4, 9);
            add_mana[i] = add_mana[i] * 6 / 10;
            add_mana[i] += number(1, 6) + (GET_LEVEL(ch) / 3);
            add_move[i] += number(2, 10);
            break;
        case CLASS_CYBORG:
            add_hp[i] /= 2;
            add_hp[i] += number(6, 14);
            add_mana[i] = add_mana[i] * 3 / 10;
            add_mana[i] += number(1, 2) + (GET_LEVEL(ch) / 15);
            add_move[i] += number(5, 8);
            break;
        case CLASS_MONK:
            add_hp[i] /= 3;
            add_hp[i] += number(6, 12);
            add_mana[i] = add_mana[i] * 3 / 10;
            add_mana[i] += number(1, 2) + (GET_LEVEL(ch) / 22);
            add_move[i] += number(6, 9);
            break;
        default:
            add_hp[i] /= 2;
            add_hp[i] += number(5, 16);
            add_mana[i] = add_mana[i] * 5 / 10;
            add_mana[i] += number(1, 13) + (GET_LEVEL(ch) / 4);
            add_move[i] += number(7, 15);
            break;
        }
    }

    if (IS_RACE(ch, RACE_HALF_ORC) || IS_RACE(ch, RACE_ORC)) {
        add_move[0] *= 2;
        add_move[1] *= 2;
    }
    ch->points.max_hit += MAX(1, add_hp[0]);
    ch->points.max_move += MAX(1, add_move[0]);

    if (GET_LEVEL(ch) > 1)
        ch->points.max_mana += add_mana[0];

    GET_LIFE_POINTS(ch) += (GET_LEVEL(ch) * (GET_WIS(ch) + GET_CON(ch))) / 300;
    if (PLR_FLAGGED(ch, PLR_HARDCORE))
        GET_LIFE_POINTS(ch) += 1;

    if (IS_REMORT(ch) && GET_REMORT_GEN(ch)) {

        if (add_hp[0] < 0 || add_hp[1] < 0) {
            errlog("remort level (%s) add_hp: [0]=%d,[1]=%d",
                GET_NAME(ch), add_hp[0], add_hp[1]);
        }

        ch->points.max_hit += add_hp[1] / 4;
        ch->points.max_mana += add_mana[1] / 2;
        ch->points.max_move += add_move[1] / 4;

    }

    if (GET_LEVEL(ch) >= LVL_AMBASSADOR) {
        for (i = 0; i < 3; i++)
            GET_COND(ch, i) = -1;
        SET_BIT(PRF_FLAGS(ch), PRF_HOLYLIGHT);
        SET_BIT(PRF_FLAGS(ch), PRF_NOHASSLE);
    }
    if (GET_LEVEL(ch) == 10)
        SET_BIT(PRF2_FLAGS(ch), PRF2_NEWBIE_HELPER);

    // special section for improving read_scrolls and use_wands
    if (CHECK_SKILL(ch, SKILL_READ_SCROLLS) > 10)
        SET_SKILL(ch, SKILL_READ_SCROLLS, 
                  MIN(100, CHECK_SKILL(ch, SKILL_READ_SCROLLS) +
                      MIN(10, number(1, GET_INT(ch) / 2))));
    if (CHECK_SKILL(ch, SKILL_USE_WANDS) > 10)
        SET_SKILL(ch, SKILL_USE_WANDS,
                  MIN(100, CHECK_SKILL(ch, SKILL_USE_WANDS) +
                      MIN(10, number(1, GET_INT(ch) / 2))));

    crashsave(ch);
    int rid = -1;
    if (ch->in_room != NULL)
        rid = ch->in_room->number;
    msg = tmp_sprintf("%s advanced to level %d in room %d%s",
        GET_NAME(ch), GET_LEVEL(ch), rid, is_tester(ch) ? " <TESTER>" : "");
    if (keep_internal)
        slog("%s", msg);
    else
        mudlog(GET_INVIS_LVL(ch), BRF, true, "%s", msg);
}