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)); }
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; }
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); } } } }
/* * 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); }