/* ************************************************************************ * File: limits.c Part of CircleMUD * * Usage: limits & gain funcs for HMV, exp, hunger/thirst, idle time * * * * All rights reserved. See license.doc for complete information. * * * * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * ************************************************************************ */ #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <assert.h> #include <string.h> #include "structs.h" #include "awake.h" #include "utils.h" #include "spells.h" #include "comm.h" #include "db.h" #include "dblist.h" #include "handler.h" #include "interpreter.h" extern class objList ObjList; extern struct char_data *character_list; extern struct room_data *world; extern int check_spirit_sector(int room, int spirit); extern int is_allergic(struct char_data *ch, int type); extern int max_exp_gain; extern int max_exp_loss; extern int fixers_need_save; extern int modify_target(struct char_data *ch); extern int spell_resist(struct char_data *ch); extern int reverse_web(struct char_data *ch, int &skill, int &target); extern "C" pid_t getpid(void); extern const char *composition_names[]; extern void save_etext(struct char_data *ch); extern void write_spells(struct char_data *ch); extern void check_trace(struct char_data *ic); extern void end_quest(struct char_data *ch); extern void save_fixer_data(struct char_data *ch); /* When age < 15 return the value p0 */ /* When age in 15..29 calculate the line between p1 & p2 */ /* When age in 30..44 calculate the line between p2 & p3 */ /* When age in 45..59 calculate the line between p3 & p4 */ /* When age in 60..79 calculate the line between p4 & p5 */ /* When age >= 80 return the value p6 */ int graf(int age, int p0, int p1, int p2, int p3, int p4, int p5, int p6) { if (age < 15) return (p0); /* < 15 */ else if (age <= 29) return (int) (p1 + (((age - 15) * (p2 - p1)) / 15)); /* 15..29 */ else if (age <= 44) return (int) (p2 + (((age - 30) * (p3 - p2)) / 15)); /* 30..44 */ else if (age <= 59) return (int) (p3 + (((age - 45) * (p4 - p3)) / 15)); /* 45..59 */ else if (age <= 79) return (int) (p4 + (((age - 60) * (p5 - p4)) / 20)); /* 60..79 */ else return (p6); /* >= 80 */ } void mental_gain(struct char_data * ch) { int gain = 0; if (IS_PERSONA(ch) || IS_PROJECT(ch)) return; if (IS_IC(ch)) { GET_MENTAL(ch) = MIN(GET_MAX_MENTAL(ch), GET_MENTAL(ch) + 100); return; } if (IS_AFFECTED(ch, AFF_SLEEP)) { REMOVE_BIT(AFF_FLAGS(ch), AFF_SLEEP); return; } switch (GET_POS(ch)) { case POS_STUNNED: gain = 20; break; case POS_SLEEPING: gain = 25; break; case POS_RESTING: gain = 20; break; case POS_SITTING: gain = 15; break; case POS_FIGHTING: gain = 5; break; case POS_STANDING: gain = 10; break; } if (IS_NPC(ch)) gain *= 2; else if (GET_LEVEL(ch) < LVL_LEGEND) switch (GET_RACE(ch)) { case RACE_HUMAN: if (GET_AGE(ch) >= 60) gain -= (int)((GET_AGE(ch) - 58) / 2); break; case RACE_DWARF: if (GET_AGE(ch) >= 130) gain -= (int)((GET_AGE(ch) - 125) / 5); break; case RACE_ELF: if (GET_AGE(ch) >= 325) gain -= (int)((GET_AGE(ch) - 315) / 10); break; case RACE_ORK: if (GET_AGE(ch) >= 50) gain -= (int)((GET_AGE(ch) - 48) / 2); break; case RACE_TROLL: if (GET_AGE(ch) >= 54) gain -= (int)((GET_AGE(ch) - 52) / 2); break; } if ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0)) gain >>= 1; gain = MAX(1, gain); GET_MENTAL(ch) = MIN(GET_MAX_MENTAL(ch), GET_MENTAL(ch) + gain); } void physical_gain(struct char_data * ch) { int gain = 0; struct obj_data *bio; if (IS_IC(ch) || IS_PERSONA(ch) || IS_PROJECT(ch)) return; switch (GET_POS(ch)) { case POS_STUNNED: gain = 13; break; case POS_SLEEPING: gain = 15; break; case POS_RESTING: gain = 13; break; case POS_SITTING: gain = 10; break; case POS_FIGHTING: gain = 5; break; case POS_STANDING: gain = 7; break; } if ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0)) gain >>= 1; if (IS_NPC(ch)) gain *= 2; else { if (GET_LEVEL(ch) < LVL_LEGEND) switch (GET_RACE(ch)) { case RACE_HUMAN: if (GET_AGE(ch) >= 60) gain -= (int)((GET_AGE(ch) - 57) / 3); break; case RACE_DWARF: if (GET_AGE(ch) >= 130) gain -= (int)((GET_AGE(ch) - 124) / 6); break; case RACE_ELF: if (GET_AGE(ch) >= 325) gain -= (int)((GET_AGE(ch) - 313) / 12); break; case RACE_ORK: if (GET_AGE(ch) >= 50) gain -= (int)((GET_AGE(ch) - 47) / 3); break; case RACE_TROLL: if (GET_AGE(ch) >= 55) gain -= (int)((GET_AGE(ch) - 52) / 3); break; } gain = MAX(1, gain); for (bio = ch->bioware; bio; bio = bio->next_content) if (GET_OBJ_VAL(bio, 2) == 1) { switch (GET_OBJ_VAL(bio, 0)) { case 1: gain = (int)(gain * 10/9); break; case 2: gain = (int)(gain * 7/5); break; case 3: gain *= 2; break; } break; } } GET_PHYSICAL(ch) = MIN(GET_MAX_PHYSICAL(ch), GET_PHYSICAL(ch) + gain); } int move_gain(struct char_data * ch) { int gain; if (IS_NPC(ch)) { return (GET_BOD(ch) * 5); } else { gain = graf(age(ch).year, 16, 20, 24, 20, 16, 12, 10); switch (GET_POS(ch)) { case POS_SLEEPING: gain += (gain >> 1); /* Divide by 2 */ break; case POS_RESTING: gain += (gain >> 2); /* Divide by 4 */ break; case POS_SITTING: gain += (gain >> 3); /* Divide by 8 */ break; } } if (IS_AFFECTED(ch, AFF_POISON)) gain >>= 2; if ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0)) gain >>= 2; if (IS_IC(ch) || IS_PERSONA(ch)) gain = 0; return (gain); } void set_title(struct char_data * ch, char *title) { if (title == NULL) title = ""; if (strlen(title) > MAX_TITLE_LENGTH) title[MAX_TITLE_LENGTH] = '\0'; if (GET_TITLE(ch) != NULL) delete [] GET_TITLE(ch); GET_TITLE(ch) = str_dup(title); } void set_whotitle(struct char_data * ch, char *title) { if (title == NULL) title = "title"; if (strlen(title) > 5) title[5] = '\0'; if (GET_WHOTITLE(ch) != NULL) delete [] GET_WHOTITLE(ch); GET_WHOTITLE(ch) = str_dup(title); } void set_pretitle(struct char_data * ch, char *title) { if (title == NULL) title = ""; if (strlen(title) > MAX_TITLE_LENGTH) title[MAX_TITLE_LENGTH] = '\0'; if (GET_PRETITLE(ch) != NULL) delete [] GET_PRETITLE(ch); GET_PRETITLE(ch) = str_dup(title); } void check_autowiz(struct char_data * ch) { char buf[100]; extern int use_autowiz; extern int min_wizlist_lev; if (use_autowiz && GET_LEVEL(ch) >= LVL_LEGEND) { sprintf(buf, "nice ../bin/autowiz %d %s %d %s %d &", min_wizlist_lev, WIZLIST_FILE, LVL_LEGEND, IMMLIST_FILE, (int) getpid()); mudlog("Initiating autowiz.", NULL, LOG_SYSLOG, FALSE); system(buf); } } int gain_exp(struct char_data * ch, int gain) { int max_gain, old = (int)(GET_KARMA(ch) / 100); if (!IS_NPC(ch) && ((GET_LEVEL(ch) < 1 || GET_LEVEL(ch) >= LVL_LEGEND))) return 0; if (IS_NPC(ch)) { GET_KARMA(ch) += (int)(gain / 10); return (int)(gain / 10); } max_gain = (PLR_FLAGGED(ch, PLR_NEWBIE) ? 20 : GET_REP(ch) * 2); if (gain > 0) { gain = MIN(max_gain, gain); /* put a cap on the max gain per kill */ GET_KARMA(ch) += gain; GET_REP(ch) += (int)(GET_KARMA(ch) / 100) - old; } else if (gain < 0) { gain = MAX(-max_exp_loss, gain); /* Cap max exp lost per death */ GET_KARMA(ch) += gain; if (GET_KARMA(ch) < 0) GET_KARMA(ch) = 0; GET_REP(ch) += (int)(GET_KARMA(ch) / 100) - old; } return gain; } void gain_exp_regardless(struct char_data * ch, int gain) { int is_altered = FALSE; int old = (int)(GET_KARMA(ch) / 100); if (!IS_NPC(ch)) { GET_KARMA(ch) += gain; if (GET_KARMA(ch) < 0) GET_KARMA(ch) = 0; GET_REP(ch) += (int)(GET_KARMA(ch) / 100) - old; // while (!access_level(ch, LVL_OWNER)) { // send_to_char("You rise a level!\r\n", ch); // GET_LEVEL(ch) += 1; // advance_level(ch); // is_altered = TRUE; // } if (is_altered) { check_autowiz(ch); } } else { GET_KARMA(ch) += gain; if (GET_KARMA(ch) < 0) GET_KARMA(ch) = 0; } } // only the pcs should need to access this void gain_condition(struct char_data * ch, int condition, int value) { bool intoxicated; struct obj_data *bio; if (GET_COND(ch, condition) == -1) /* No change */ return; intoxicated = (GET_COND(ch, DRUNK) > 0); if (value == -1) for (bio = ch->bioware; bio; bio = bio->next_content) if (GET_OBJ_VAL(bio, 2) == 1) { switch (GET_OBJ_VAL(bio, 0)) { case 1: if (GET_OBJ_VAL(bio, 6)) value--; GET_OBJ_VAL(bio, 6) = !GET_OBJ_VAL(bio, 6); break; case 2: if (!(GET_OBJ_VAL(bio, 6) % 3)) value--; if ((++GET_OBJ_VAL(bio, 6)) > 9) GET_OBJ_VAL(bio, 6) = 0; break; case 3: value--; break; } } else if (GET_OBJ_VAL(bio, 2) == 5) value--; GET_COND(ch, condition) += value; GET_COND(ch, condition) = MAX(0, GET_COND(ch, condition)); GET_COND(ch, condition) = MIN(24, GET_COND(ch, condition)); if (GET_COND(ch, condition) || PLR_FLAGGED(ch, PLR_CUSTOMIZE) || PLR_FLAGGED(ch, PLR_WRITING) || PLR_FLAGGED(ch, PLR_MAILING)) return; switch (condition) { case FULL: send_to_char("You are hungry.\r\n", ch); return; case THIRST: send_to_char("You are thirsty.\r\n", ch); return; case DRUNK: if (intoxicated) send_to_char("You are now sober.\r\n", ch); return; default: break; } } void resist_petrify(struct char_data *ch) { extern const char *spell_wear_off_msg[]; struct affected_type *af; int resist = 0; for (af = ch->affected; af; af = af->next) if (af->type == SPELL_PETRIFY) { resist = GET_BOD(ch); break; } else if (af->type == SPELL_OVERSTIMULATION) { resist = GET_WIL(ch); break; } if (!resist || !af) return; if (success_test(resist + spell_resist(ch), af->modifier + modify_target(ch)) > 0) { send_to_char(ch, "%s\r\n", spell_wear_off_msg[af->type]); if (af->type == SPELL_PETRIFY) act("$n's skin returns to normal.", TRUE, ch, 0, 0, TO_ROOM); affect_remove(ch, af, 1); } } void resist_poison(struct char_data *ch) { extern const char *spell_wear_off_msg[]; struct affected_type *af; struct obj_data *obj; int resist = GET_BOD(ch), success, dam; for (af = ch->affected; af; af = af->next) if (af->type == SPELL_POISON) break; for (obj = ch->cyberware; obj; obj = obj->next_content) if (GET_OBJ_VAL(obj, 2) == 25) resist += GET_OBJ_VAL(obj, 0); obj = GET_EQ(ch, WEAR_PATCH); resist += (obj && GET_OBJ_VAL(obj, 0) == 0 ? GET_OBJ_VAL(obj, 1) : 0); success = resisted_test(resist, af->duration + modify_target(ch), af->duration, resist); dam = convert_damage(stage(-success, af->modifier)); if (!dam && af) { send_to_char(ch, "%s\r\n", spell_wear_off_msg[af->type]); affect_remove(ch, af, 1); } else damage(ch, ch, dam, SPELL_POISON, PHYSICAL); } void remove_patch(struct char_data *ch) { struct obj_data *patch = GET_EQ(ch, WEAR_PATCH); int stun; if (!patch) return; switch (GET_OBJ_VAL(patch, 0)) { case 0: if (AFF_FLAGGED(ch, AFF_POISON) && affected_by_spell(ch, SPELL_POISON) != 1) { REMOVE_BIT(AFF_FLAGS(ch), AFF_POISON); send_to_char("You feel the effects of the toxin dissipate.\r\n", ch); } break; case 1: act("The effects of $p wear off, leaving you exhausted!", FALSE, ch, patch, 0, TO_CHAR); GET_MENTAL(ch) = MAX(0, GET_MENTAL(ch) - (GET_OBJ_VAL(patch, 1) - 1) * 100); if (GET_TRADITION(ch) == TRAD_HERMETIC || GET_TRADITION(ch) == TRAD_SHAMANIC && success_test(GET_MAGIC(ch), GET_OBJ_VAL(patch, 1)) < 0) { send_to_char("You feel your magical ability decline.\r\n", ch); ch->real_abils.mag = MAX(0, ch->real_abils.mag - 100); affect_total(ch); } update_pos(ch); break; case 2: stun = resisted_test(GET_OBJ_VAL(patch, 1), GET_BOD(ch), GET_BOD(ch), GET_OBJ_VAL(patch, 1)); if (stun > 0) { act("You feel the drugs from $p take effect.", FALSE, ch, patch, 0, TO_CHAR); GET_MENTAL(ch) = MAX(0, GET_MENTAL(ch) - (stun * 100)); update_pos(ch); } else act("You resist the feeble effects of $p.", FALSE, ch, patch, 0, TO_CHAR); break; case 3: if (success_test(ch->real_abils.bod, GET_OBJ_VAL(patch, 1)) > 0) SET_BIT(AFF_FLAGS(ch), AFF_STABILIZE); break; } GET_EQ(ch, WEAR_PATCH) = NULL; patch->worn_by = NULL; patch->worn_on = -1; extract_obj(patch); } void check_idling(void) { extern int free_rent; extern void Crash_rentsave(struct char_data *, int); void perform_immort_invis(struct char_data *ch, int level); ACMD(do_return); ACMD(do_disconnect); struct char_data *ch, *next; for (ch = character_list; ch; ch = next) { next = ch->next; if (IS_NPC(ch) && ch->desc && ch->desc->original) { if (ch->desc->original->char_specials.timer > 10) { if (IS_PERSONA(ch)) do_disconnect(ch, "", 0, SCMD_MORTED); else do_return(ch, "", 0, 0); } } else if (!IS_NPC(ch)) { ch->char_specials.timer++; if (GET_LEVEL(ch) < LVL_LEGEND) { if (GET_WAS_IN(ch) == NOWHERE && ch->in_room != NOWHERE && ch->char_specials.timer > 15) { GET_WAS_IN(ch) = ch->in_room; if (FIGHTING(ch)) { stop_fighting(FIGHTING(ch)); stop_fighting(ch); } act("$n disappears into the void.", TRUE, ch, 0, 0, TO_ROOM); send_to_char("You have been idle, and are pulled into a void.\r\n", ch); char_from_room(ch); char_to_room(ch, 1); } else if (ch->char_specials.timer > 30) { if (ch->in_room != NOWHERE) char_from_room(ch); char_to_room(ch, 1); if (ch->desc) close_socket(ch->desc); ch->desc = NULL; if (GET_QUEST(ch)) end_quest(ch); if (free_rent) Crash_rentsave(ch, 0); else Crash_idlesave(ch); sprintf(buf, "%s force-rented and extracted (idle).", GET_NAME(ch)); mudlog(buf, ch, LOG_MISCLOG, TRUE); extract_char(ch); } } else if (!ch->desc && ch->char_specials.timer > 15) { sprintf(buf, "%s removed from game (no link).", GET_NAME(ch)); mudlog(buf, ch, LOG_MISCLOG, FALSE); Crash_rentsave(ch, 0); extract_char(ch); } else if (GET_LEVEL(ch) >= LVL_LEGEND && ch->char_specials.timer > 15 && GET_INVIS_LEV(ch) < 2 && IS_SET(PRF_FLAGS(ch), PRF_AUTOINVIS)) perform_immort_invis(ch, 2); } } } void check_bioware(struct char_data *ch) { if (!ch->desc || (ch->desc && ch->desc->connected)) return; struct obj_data *bio; int dam = 0; for (bio = ch->bioware; bio; bio = bio->next_content) if (GET_OBJ_VAL(bio, 2) == 0) break; if (bio && GET_OBJ_VAL(bio, 2) == 0) { if (GET_OBJ_VAL(bio, 5) < 1) { if (!success_test(GET_BOD(ch), 3 + modify_target(ch) + (int)(GET_OBJ_VAL(bio, 6) / 2))) { dam = convert_damage(stage(-success_test(GET_BOD(ch), 4 + modify_target(ch)), DEADLY)); send_to_char("Your blood seems to erupt.\r\n", ch); damage(ch, ch, dam, TYPE_BIOWARE, PHYSICAL); } GET_OBJ_VAL(bio, 5) = 12; GET_OBJ_VAL(bio, 6)++; } else GET_OBJ_VAL(bio, 5)--; } } void check_swimming(struct char_data *ch) { int target, skill, i, dam, test; if (IS_NPC(ch) || GET_LEVEL(ch) >= LVL_LEGEND) return; target = MAX(2, world[ch->in_room].rating); if (GET_POS(ch) < POS_RESTING) { target -= success_test(MAX(1, (int)(ch->real_abils.bod / 3)), target); dam = convert_damage(stage(target, 0)); if (dam > 0) { act("$n's unconscious body is mercilessly thrown about by the current.", FALSE, ch, 0, 0, TO_ROOM); damage(ch, ch, dam, TYPE_DROWN, FALSE); } return; } skill = SKILL_ATHLETICS; if (!GET_SKILL(ch, skill)) i = reverse_web(ch, skill, target); else i = GET_SKILL(ch, skill); i = resisted_test(i, target + modify_target(ch), target, i); if (i < 0) { test = success_test(GET_WIL(ch), modify_target(ch) - i); dam = convert_damage(stage(-test, SERIOUS)); if (dam > 0) { send_to_char(ch, "You struggle to prevent your lungs getting " "flooded with water.\r\n"); damage(ch, ch, dam, TYPE_DROWN, FALSE); } } else if (!i) { test = success_test(GET_WIL(ch), 3 + modify_target(ch)); dam = convert_damage(stage(-test, MODERATE)); if (dam > 0) { send_to_char(ch, "You struggle to prevent your lungs getting " "flooded with water.\r\n"); damage(ch, ch, dam, TYPE_DROWN, FALSE); } } else if (i < 3) { test = success_test(GET_WIL(ch), 5 - i + modify_target(ch)); dam = convert_damage(stage(-test, LIGHT)); if (dam > 0) { send_to_char(ch, "You struggle to prevent your lungs getting " "flooded with water.\r\n"); damage(ch, ch, dam, TYPE_DROWN, FALSE); } } } void cycle_allergy(struct char_data *ch) { int i; if (PLR_FLAGGED(ch, PLR_NEWBIE)) return; if (GET_SEVERITY(ch) < REACT_SEVERE) { if (GET_ALLERGY(ch) != ALLERGIC_SUNLIGHT) { for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i) && is_allergic(ch, GET_OBJ_RENT(GET_EQ(ch, i))) && (i == WEAR_WIELD || i == WEAR_HOLD ? !GET_EQ(ch, WEAR_HANDS) : TRUE)) { send_to_char(ch, "Your skin tingles from contact with %s.\r\n", composition_names[GET_OBJ_RENT(GET_EQ(ch, i))]); return; } } else if (IS_LIGHT(ch->in_room) && weather_info.sunlight >= SUN_RISE && OUTSIDE(ch) && weather_info.sky < SKY_RAINING) { send_to_char("The presence of sunlight makes your skin tingle.\r\n", ch); return; } return; } if (GET_ALLERGY(ch) != ALLERGIC_SUNLIGHT) { for (i = 0; i < NUM_WEARS; i++) if (GET_EQ(ch, i) && is_allergic(ch, GET_OBJ_RENT(GET_EQ(ch, i))) && (i == WEAR_WIELD || i == WEAR_HOLD ? !GET_EQ(ch, WEAR_HANDS) : TRUE)) { send_to_char(ch, "Prolonged contact with %s fills your mind with pain!\r\n", composition_names[GET_OBJ_RENT(GET_EQ(ch, i))]); damage(ch, ch, 1, TYPE_ALLERGY, PHYSICAL); return; } } else if (IS_LIGHT(ch->in_room) && weather_info.sunlight >= SUN_RISE && OUTSIDE(ch) && weather_info.sky < SKY_RAINING) { send_to_char("Prolonged contact with sunlight fills your mind with pain!\r\n", ch); damage(ch, ch, 1, TYPE_ALLERGY, PHYSICAL); return; } return; } void process_regeneration(int half_hour) { struct char_data *ch, *next_char; for (ch = character_list; ch; ch = next_char) { next_char = ch->next; if ((affected_by_spell(ch, SPELL_PETRIFY) == 1 || affected_by_spell(ch, SPELL_OVERSTIMULATION) == 1) && half_hour) resist_petrify(ch); if (affected_by_spell(ch, SPELL_POISON) == 1 && half_hour) resist_poison(ch); else if (AFF_FLAGGED(ch, AFF_POISON) && half_hour) damage(ch, ch, 1, SPELL_POISON, PHYSICAL); else if (GET_POS(ch) >= POS_STUNNED) { physical_gain(ch); mental_gain(ch); if (!IS_NPC(ch) && SECT(ch->in_room) == SECT_WATER_SWIM && half_hour) check_swimming(ch); if (GET_POS(ch) == POS_STUNNED) update_pos(ch); } else if (AFF_FLAGGED(ch, AFF_STABILIZE) && half_hour) REMOVE_BIT(AFF_FLAGS(ch), AFF_STABILIZE); else if (GET_POS(ch) <= POS_INCAP && half_hour) damage(ch, ch, 1, TYPE_SUFFERING, PHYSICAL); } } /* Update PCs, NPCs, and objects */ void point_update(void) { SPECIAL(fixer); struct char_data *i, *next_char; /* characters */ for (i = character_list; i; i = next_char) { next_char = i->next; if (!IS_NPC(i)) { Crash_crashsave(i); save_char(i, GET_LOADROOM(i)); if ( GET_TRADITION(i) != TRAD_MUNDANE ) write_spells(i); save_etext(i); REMOVE_BIT(PLR_FLAGS(i), PLR_CRASH); gain_condition(i, FULL, -1); gain_condition(i, DRUNK, -1); gain_condition(i, THIRST, -1); if (GET_LEVEL(i) >= LVL_LEGEND) { GET_NUYEN(i) = 0; GET_BANK(i) = 0; } if (i->bioware) check_bioware(i); // check to see if char just died, as check_bioware might kill if (!PLR_FLAGGED(i, PLR_JUST_DIED) && GET_ALLERGY(i) && GET_POS(i) > POS_SLEEPING && GET_LEVEL(i) < LVL_LEGEND) cycle_allergy(i); } else { if (GET_MOB_SPEC(i) && GET_MOB_SPEC(i) == fixer && fixers_need_save) save_fixer_data(i); GET_MOOD(i) = MAX(-5, MIN(4, GET_MOOD(i) + number(-1, 1))); } if (IS_NPC(i) || !PLR_FLAGGED(i, PLR_JUST_DIED)) { if (LAST_HEAL(i) > 0) LAST_HEAL(i)--; else if (LAST_HEAL(i) < 0) LAST_HEAL(i)++; if (GET_EQ(i, WEAR_PATCH)) remove_patch(i); } } // process the objects in the object list ObjList.UpdateCounters(); } void misc_update(void) { struct char_data *ch, *next_ch; struct obj_data *obj, *o = NULL; struct affected_type *af; int i; // first go through the objects...extract temp items on mortals ObjList.RemoveObjs(); // loop through all the characters for (ch = character_list; ch; ch = next_ch) { next_ch = ch->next; for (af = ch->affected; af; af = af->next) if ((af->type == SPELL_HEAL || af->type == SPELL_ANTIDOTE || af->type == SPELL_STABILIZE || af->type == SPELL_CURE_DISEASE) && !af->caster) { if (af->duration > 0) af->duration--; else affect_remove(ch, af, 0); } if (IS_NPC(ch) && !ch->desc && GET_MOB_VNUM(ch) >= 20 && GET_MOB_VNUM(ch) <= 22) { act("$n dissolves into the background and is no more.", TRUE, ch, 0, 0, TO_ROOM); for (i = 0; i < NUM_WEARS; i++) if (ch->equipment[i]) extract_obj(ch->equipment[i]); for (obj = ch->carrying; obj; obj = o) { o = obj->next_content; extract_obj(obj); } extract_char(ch); } else if (IS_NPC(ch) && !ch->desc && GET_MOB_VNUM(ch) >= 50 && GET_MOB_VNUM(ch) < 70) extract_char(ch); else if (IS_SPIRIT(ch) && GET_MOB_VNUM(ch) >= 25 && GET_MOB_VNUM(ch) <= 41) { if (GET_ACTIVE(ch) < 1) { act("$s service fulfilled, $n dissolves from existence.", TRUE, ch, 0, 0, TO_ROOM); act("Your pitiful life as a slave to a mortal is over." "Have a nice nonexistence!", FALSE, ch, 0, 0, TO_CHAR); extract_char(ch); } else if (!check_spirit_sector(ch->in_room, GET_MOB_VNUM(ch) - 24)) { act("Being away from its environment, $n suddenly ceases to " "physically exist.", TRUE, ch, 0, 0, TO_ROOM); act("You feel extremely homesick, and depart the depressing " "physical realm.", FALSE, ch, 0, 0, TO_CHAR); extract_char(ch); } } else if (IS_IC(ch)) { check_trace(ch); if (AFF_FLAGGED(ch, AFF_COUNTER_ATT)) REMOVE_BIT(AFF_FLAGS(ch), AFF_COUNTER_ATT); } } }