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