AwakeMUD-0.8.18B/
AwakeMUD-0.8.18B/doc/
AwakeMUD-0.8.18B/lib/
AwakeMUD-0.8.18B/lib/etc/
AwakeMUD-0.8.18B/lib/etc/pfiles/
AwakeMUD-0.8.18B/lib/misc/
AwakeMUD-0.8.18B/lib/text/
AwakeMUD-0.8.18B/lib/text/help/
AwakeMUD-0.8.18B/lib/text/wizhelp/
AwakeMUD-0.8.18B/lib/veh/
AwakeMUD-0.8.18B/lib/world/
AwakeMUD-0.8.18B/lib/world/mob/
AwakeMUD-0.8.18B/lib/world/mtx/
AwakeMUD-0.8.18B/lib/world/qst/
AwakeMUD-0.8.18B/lib/world/shp/
AwakeMUD-0.8.18B/lib/world/veh/
/* ************************************************************************
*   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 <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <assert.h>
#include <string.h>

#if defined(WIN32) && !defined(__CYGWIN__)
#include <process.h>
#else
#include <unistd.h>
#endif

#include "structs.h"
#include "awake.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "newdb.h"
#include "dblist.h"
#include "handler.h"
#include "interpreter.h"
#include "utils.h"
#include "constants.h"
#include "newshop.h"
#include "newmagic.h"
#include <sys/time.h>

extern class objList ObjList;
extern int modify_target(struct char_data *ch);
extern void end_quest(struct char_data *ch);
extern char *cleanup(char *dest, const char *src);
extern void damage_equip(struct char_data *ch, struct char_data *victim, int power, int type);

void mental_gain(struct char_data * ch)
{
  int gain = 0;

  if (IS_PROJECT(ch))
    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;

  if ((GET_COND(ch, FULL) == 0) || (GET_COND(ch, THIRST) == 0))
    gain >>= 1;

  if (GET_TRADITION(ch) == TRAD_ADEPT)
    gain *= GET_POWER(ch, ADEPT_HEALING) + 1;
  if (GET_BIOOVER(ch) > 0)
    gain /= GET_BIOOVER(ch);

  gain = MAX(1, gain);

  GET_MENTAL(ch) = MIN(GET_MAX_MENTAL(ch), GET_MENTAL(ch) + gain);
  update_pos(ch);
}

void physical_gain(struct char_data * ch)
{
  int gain = 0;
  struct obj_data *bio;

  if (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
  {
    gain = MAX(1, gain);
    for (bio = ch->bioware; bio; bio = bio->next_content)
      if (GET_OBJ_VAL(bio, 0) == BIO_SYMBIOTES) {
        switch (GET_OBJ_VAL(bio, 1)) {
        case 1:
          gain = (int)(gain * 10/9);
          break;
        case 2:
          gain = (int)(gain * 7/5);
          break;
        case 3:
          gain *= 2;
          break;
        }
        break;
      }
  }
  if (GET_TRADITION(ch) == TRAD_ADEPT)
    gain *= GET_POWER(ch, ADEPT_HEALING) + 1;
  if (GET_BIOOVER(ch) > 0)
    gain /= GET_BIOOVER(ch);
  GET_PHYSICAL(ch) = MIN(GET_MAX_PHYSICAL(ch), GET_PHYSICAL(ch) + gain);
  update_pos(ch);
}

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) > MAX_WHOTITLE_LENGTH)
    title[MAX_WHOTITLE_LENGTH] = '\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);
}

int gain_exp(struct char_data * ch, int gain, bool rep)
{
  if (IS_PROJECT(ch))
    ch = ch->desc->original;
  int max_gain, old = (int)(GET_KARMA(ch) / 100);
  if (!IS_NPC(ch) && ((GET_LEVEL(ch) < 1 || IS_SENATOR(ch))))
    return 0;

  if (IS_NPC(ch))
  {
    GET_KARMA(ch) += (int)(gain / 10);
    return (int)(gain / 10);
  }

  if ( GET_TKE(ch) >= 0 && GET_TKE(ch) < 100 )
  {
    max_gain = 20;
  } else if ( GET_TKE(ch) >= 100 && GET_TKE(ch) < 500 )
  {
    max_gain = 30;
  } else
  {
    max_gain = GET_TKE(ch)/4;
  }

  if (gain > 0)
  {
    gain = MIN(max_gain, gain); /* put a cap on the max gain per kill */

    GET_KARMA(ch) += gain;
    GET_TKE(ch) += (int)(GET_KARMA(ch) / 100) - old;
    if (rep)
      GET_REP(ch) += (int)(GET_KARMA(ch) / 100) - old;
    else
      GET_NOT(ch) += (int)(GET_KARMA(ch) / 100) - old;
  }

  return gain;
}

void gain_exp_regardless(struct char_data * ch, int gain)
{
  if (IS_PROJECT(ch))
    ch = ch->desc->original;
  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_TKE(ch) += (int)(GET_KARMA(ch) / 100) - old;
    GET_REP(ch) += (int)(GET_KARMA(ch) / 100) - old;
  } 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, 0) == BIO_SYMBIOTES)
      {
        switch (GET_OBJ_VAL(bio, 1)) {
        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, 0) == BIO_SUPRATHYROIDGLAND)
        value *= 2;
      else if (GET_OBJ_VAL(bio, 0) == BIO_DIGESTIVEEXPANSION)
        value = (int)((float)value / .8);
  GET_COND(ch, condition) += value;

  GET_COND(ch, condition) = MAX(0, GET_COND(ch, condition));
  if ( condition == DRUNK )
    GET_COND(ch, condition) = MIN(24, GET_COND(ch, condition));
  else
    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) || PLR_FLAGGED(ch, PLR_AUTH) || PLR_FLAGGED(ch, PLR_MATRIX))
    return;

  switch (condition)
  {
  case FULL:
    send_to_char("Your stomach growls.\r\n", ch);
    return;
  case THIRST:
    send_to_char("Your mouth is dry.\r\n", ch);
    return;
  case DRUNK:
    if (intoxicated)
      send_to_char("Your head seems to clear slightly...\r\n", ch);
    return;
  default:
    break;
  }
}

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 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) {
      magic_loss(ch, 100, TRUE);
      affect_total(ch);
    }
    update_pos(ch);
    break;
  case 2:
    stun = resisted_test(GET_OBJ_VAL(patch, 1), GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0),
                         GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), 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(GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), GET_OBJ_VAL(patch, 1)) > 0)
      AFF_FLAGS(ch).RemoveBit(AFF_STABILIZE);
    break;
  }
  GET_EQ(ch, WEAR_PATCH) = NULL;
  patch->worn_by = NULL;
  patch->worn_on = -1;
  extract_obj(patch);
}

void check_idling(void)
{
  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)
        do_return(ch, "", 0, 0);
    } else if (!IS_NPC(ch)) {
      ch->char_specials.timer++;
      if (!(IS_SENATOR(ch) || IS_WORKING(ch)) || !ch->desc) {
        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);
          sprintf(buf, "%s force-rented and extracted (idle).",
                  GET_CHAR_NAME(ch));
          mudlog(buf, ch, LOG_CONNLOG, TRUE);
          extract_char(ch);
        }
      } else if (!ch->desc && ch->char_specials.timer > 15) {
        sprintf(buf, "%s removed from game (no link).", GET_CHAR_NAME(ch));
        mudlog(buf, ch, LOG_CONNLOG, TRUE);
        extract_char(ch);
      } else if (IS_SENATOR(ch) && ch->char_specials.timer > 15 &&
                 GET_INVIS_LEV(ch) < 2 &&
                 PRF_FLAGGED(ch, PRF_AUTOINVIS))
        perform_immort_invis(ch, 2);
    }
  }
}

void check_bioware(struct char_data *ch)
{
  if (!ch->desc || (ch->desc && ch->desc->connected) || PLR_FLAGGED(ch, PLR_NEWBIE))
    return;

  struct obj_data *bio;
  for (bio = ch->bioware; bio; bio = bio->next_content)
    if (GET_OBJ_VAL(bio, 0) == BIO_PLATELETFACTORY)
    {
      if (--GET_OBJ_VAL(bio, 5) < 1) {
        GET_OBJ_VAL(bio, 5) = 12;
        if (success_test(GET_REAL_BOD(ch), 3 + GET_OBJ_VAL(bio, 6)) < 1) {
          send_to_char("Your blood seems to erupt.\r\n", ch);
          act("$n collapses to the floor, twitching.", TRUE, ch, 0, 0, TO_ROOM);
          damage(ch, ch, 10, TYPE_BIOWARE, PHYSICAL);
        }
        GET_OBJ_VAL(bio, 6)++;
      }
      break;
    }
}

void check_swimming(struct char_data *ch)
{
  int target, skill, i, dam, test;

  if (IS_NPC(ch) || IS_SENATOR(ch))
    return;

  target = MAX(2, world[ch->in_room].rating);
  if (GET_POS(ch) < POS_RESTING)
  {
    target -= success_test(MAX(1, (int)(GET_REAL_BOD(ch) / 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;
  i = get_skill(ch, skill, target);
  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 process_regeneration(int half_hour)
{
  struct char_data *ch, *next_char;

  for (ch = character_list; ch; ch = next_char) {
    next_char = ch->next;
    if (GET_POS(ch) >= POS_STUNNED) {
      physical_gain(ch);
      mental_gain(ch);
      if (!IS_NPC(ch) && IS_WATER(ch->in_room) && half_hour)
        check_swimming(ch);
      if (GET_POS(ch) == POS_STUNNED)
        update_pos(ch);
      if (GET_PHYSICAL(ch) >= GET_MAX_PHYSICAL(ch)) {
        if (AFF_FLAGS(ch).IsSet(AFF_HEALED))
          AFF_FLAGS(ch).RemoveBit(AFF_HEALED);
        if (AFF_FLAGS(ch).IsSet(AFF_RESISTPAIN))
          AFF_FLAGS(ch).RemoveBit(AFF_RESISTPAIN);
      }
      if (GET_PHYSICAL(ch) > 0) {
        if (AFF_FLAGS(ch).IsSet(AFF_STABILIZE))
          AFF_FLAGS(ch).RemoveBit(AFF_STABILIZE);
      }
    }
    if (GET_POS(ch) == POS_MORTALLYW && !AFF_FLAGS(ch).IsSet(AFF_STABILIZE) && half_hour) {
      bool dam = TRUE;
      for (struct obj_data *obj = ch->bioware; obj; obj = obj->next_content)
        if (GET_OBJ_VAL(obj, 0) == BIO_METABOLICARRESTER)
          if (++GET_OBJ_VAL(obj, 3) == 5) {
            GET_OBJ_VAL(obj, 3) = 0;
            dam = TRUE;
          } else
            dam = FALSE;
      if (dam)
        damage(ch, ch, 1, TYPE_SUFFERING, PHYSICAL);
    }
  }
  /* blood stuff */
  for (int i = 0; i < top_of_world; i++) {
    if (half_hour && world[i].blood > 0)
      world[i].blood--;
    if (world[i].icesheet[0])
      if (!--world[i].icesheet[1])
        world[i].icesheet[0] = 0;
    if (world[i].background[0] && world[i].background[1] >= 14)
      world[i].background[0]--;
  }
}

/* Update PCs, NPCs, and objects */
void point_update(void)
{
  ACMD(do_use);
  struct char_data *i, *next_char;
  FILE *fl;
  struct veh_data *veh;
  long room, v;
  struct obj_data *obj;
  extern struct time_info_data time_info;
  /* characters */
  for (i = character_list; i; i = next_char) {
    next_char = i->next;
    if (!IS_NPC(i)) {
      i->char_specials.subscribe = NULL;
      playerDB.SaveChar(i, GET_LOADROOM(i));

      AFF_FLAGS(i).RemoveBit(AFF_DAMAGED);

      if (!GET_POWER(i, ADEPT_SUSTENANCE) || !(time_info.hours % 3)) {
        gain_condition(i, FULL, -1);
        gain_condition(i, THIRST, -1);
      }
      gain_condition(i, DRUNK, -1);
      if (GET_TEMP_ESSLOSS(i) > 0)
        GET_TEMP_ESSLOSS(i) = MAX(0, GET_TEMP_ESSLOSS(i) - 100);
      if (GET_MAG(i) > 0) {
        int force = 0, total = 0;
        for (int x = 0; x < NUM_WEARS; x++)
          if (GET_EQ(i, x) && GET_OBJ_TYPE(GET_EQ(i, x)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(i, x), 2) == GET_IDNUM(i) && GET_OBJ_VAL(GET_EQ(i, x), 4)) {
            force += GET_OBJ_VAL(GET_EQ(i, x), 1);
            total++;
          }
        if (force * 100 > GET_REAL_MAG(i) * 2 && success_test(GET_REAL_MAG(i) / 100, force / 2) < 1) {
          int num = number(1, total);
          struct obj_data *foci = NULL;
          for (int x = 0; x < NUM_WEARS && !foci; x++)
            if (GET_EQ(i, x) && GET_OBJ_TYPE(GET_EQ(i, x)) == ITEM_FOCUS && GET_OBJ_VAL(GET_EQ(i, x), 2) == GET_IDNUM(i) && GET_OBJ_VAL(GET_EQ(i, x), 4) && !--num)
              foci = GET_EQ(i, x);
          if (foci) {
            send_to_char(i, "You feel some of your magic becoming locked in %s.\r\n", GET_OBJ_NAME(foci));
            GET_OBJ_VAL(foci, 9) = GET_IDNUM(i);
            magic_loss(i, 100, FALSE);
          }
        }
      }
      if (HUNTING(i) && !AFF_FLAGGED(i, AFF_TRACKING) && ++HOURS_SINCE_TRACK(i) > 8)
        HUNTING(i) = NULL;
      if (i->bioware)
        check_bioware(i);
      for (int x = 0; x < NUM_DRUGS; x++) {
        int tsl = (time(0) - GET_DRUG_LASTFIX(i, x)) / SECS_PER_MUD_DAY;
        if (GET_DRUG_ADDICT(i, x) > 0) {
          GET_DRUG_ADDTIME(i, x)++;
          if (!(GET_DRUG_ADDTIME(i ,x) % 168)) {
            switch (number(0, 1)) {
            case 0:
              GET_MENTAL_LOSS(i)++;
              break;
            case 1:
              GET_PHYSICAL_LOSS(i)++;
              break;
            }
            send_to_char(i, "Your health suffers at the hand of your %s addiction.\r\n", drug_types[x].name);
          }
          if (!(GET_DRUG_ADDTIME(i ,x) % 720)) {
            if (GET_REAL_BOD(i) > 1)
              GET_REAL_BOD(i)--;
            else if (GET_PERM_BOD_LOSS(i) < racial_limits[(int)GET_RACE(i)][0][0])
              GET_PERM_BOD_LOSS(i)++;
            send_to_char(i, "Your health suffers at the hand of your %s addiction.\r\n", drug_types[x].name);
          }
          if (AFF_FLAGGED(i, AFF_WITHDRAWL)) {
            if (tsl > GET_DRUG_LASTWITH(i, x) + 1) {
              GET_DRUG_LASTWITH(i, x) += 2;
              GET_DRUG_EDGE(i, x)--;
              if (!GET_DRUG_EDGE(i ,x)) {
                AFF_FLAGS(i).RemoveBit(AFF_WITHDRAWL);
                GET_DRUG_ADDICT(i, x) = 0;
                continue;
              }
            }
            send_to_char(i, "Your body cries out for some %s.\r\n", drug_types[x].name);
          } else if (tsl >= drug_types[x].fix + 1 && !AFF_FLAGGED(i, AFF_WITHDRAWL_FORCE)) {
            send_to_char(i, "You begin to go into %s withdrawl.\r\n", drug_types[x].name);
            AFF_FLAGS(i).SetBit(AFF_WITHDRAWL_FORCE);
            affect_total(i);
          } else if (tsl >= drug_types[x].fix) {
            if (drug_types[x].mental_addiction ? success_test(GET_WIL(i), drug_types[x].mental_addiction + GET_DRUG_EDGE(i, x)) : 1 < 1 ||
                drug_types[x].physical_addiction ? success_test(GET_REAL_BOD(i), drug_types[x].physical_addiction + GET_DRUG_EDGE(i, x)) : 1 < 1) {
              if (AFF_FLAGGED(i, AFF_WITHDRAWL_FORCE)) {
                sprintf(buf, "Your lack of %s is causing you great pain and discomfort.\r\n", drug_types[x].name);
                if (tsl > GET_DRUG_LASTWITH(i, x)) {
                  GET_DRUG_LASTWITH(i ,x)++;
                  GET_DRUG_EDGE(i, x)--;
                  if (!GET_DRUG_EDGE(i ,x)) {
                    AFF_FLAGS(i).RemoveBit(AFF_WITHDRAWL_FORCE);
                    GET_DRUG_ADDICT(i, x) = 0;
                    continue;
                  }
                }
              } else
                sprintf(buf, "You crave some %s.\r\n", drug_types[x].name);
              for (struct obj_data *obj = i->carrying; obj; obj = obj->next_content) {
                if (GET_OBJ_TYPE(obj) == ITEM_DRUG && GET_OBJ_VAL(obj, 0) == x) {
                  do_use(i, obj->text.keywords, 0, 0);
                  if (GET_DRUG_DOSE(i) > GET_DRUG_TOLERANT(i, x))
                    sprintf(buf, "You satisfy your craving for %s.\r\n", drug_types[x].name);
                  else
                    sprintf(buf, "You attempt to satisfy your craving for %s.\r\n", drug_types[x].name);
                  break;
                }
              }
              send_to_char(i, buf);
            }
          }
        }
      }
    }
    if (IS_PROJECT(i)) {
      if (AFF_FLAGGED(i->desc->original, AFF_TRACKING) && HUNTING(i->desc->original) && !--HOURS_LEFT_TRACK(i->desc->original)) {
        act("The astral signature leads you to $N.", FALSE, i, 0, HUNTING(i->desc->original), TO_CHAR);
        char_from_room(i);
        char_to_room(i, HUNTING(i->desc->original)->in_room);
        act("$n enters the area.", TRUE, i, 0, 0, TO_ROOM);
        AFF_FLAGS(i->desc->original).RemoveBit(AFF_TRACKING);
        AFF_FLAGS(HUNTING(i->desc->original)).RemoveBit(AFF_TRACKED);
        HUNTING(i->desc->original) = NULL;
      }
      GET_ESS(i) -= 100;
      if (GET_ESS(i) <= 0) {
        send_to_char("As you feel the attachment to your physical body fade you quickly return.\r\n", i);
        PLR_FLAGS(i->desc->original).RemoveBit(PLR_PROJECT);
        i->desc->character = i->desc->original;
        i->desc->original = NULL;
        GET_PHYSICAL(i->desc->character) = -(GET_BOD(i->desc->character) - 1) * 100;
        act("$n collapses in a heap.", TRUE, i->desc->character, 0, 0, TO_ROOM);
        update_pos(i->desc->character);
        i->desc->character->desc = i->desc;
        i->desc = NULL;
        extract_char(i);
      } else if (GET_ESS(i) <= 100)
        send_to_char("You feel memories of your physical body slipping away.\r\n", i);
    }
    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);
    }
  }
  for (int shop_nr = 0; shop_nr < top_of_shopt; shop_nr++) {
    sprintf(buf, "order/%ld", shop_table[shop_nr].vnum);
    unlink(buf);
    if (shop_table[shop_nr].order) {
      if (!(fl = fopen(buf, "w")))
        return;
      int i = 0;
      fprintf(fl, "[ORDERS]\n");
      for (struct shop_order_data *order = shop_table[shop_nr].order; order; order = order->next, i++) {
        fprintf(fl, "\t[ORDER %d]\n", i);
        fprintf(fl, "\t\tItem:\t%ld\n"
                "\t\tPlayer:\t%ld\n"
                "\t\tTime:\t%d\n"
                "\t\tNumber:\t%d\n"
                "\t\tPrice:\t%d\n", order->item, order->player, order->timeavail, order->number, order->price);
      }
      fclose(fl);
    }
  }
  int num_veh = 0;
  for (veh = veh_list; veh; veh = veh->next)
    if ((veh->owner > 0 && (veh->damage < 10 || veh->in_veh || ROOM_FLAGGED(veh->in_room, ROOM_GARAGE))) && playerDB.DoesExist(veh->owner))
      num_veh++;

  if (!(fl = fopen("veh/vfile", "w"))) {
    mudlog("SYSERR: Can't Open Vehicle File For Write.", NULL, LOG_SYSLOG, FALSE);
    return;
  }
  fprintf(fl, "%d\n", num_veh);
  fclose(fl);
  for (veh = veh_list, v = 0; veh && v < num_veh; veh = veh->next) {
    if (veh->owner < 1 || (veh->damage >= 10 && !(veh->in_veh || ROOM_FLAGGED(veh->in_room, ROOM_GARAGE))))
      continue;
    if (!playerDB.DoesExist(veh->owner)) {
      veh->owner = 0;
      continue;
    }

    sprintf(buf, "veh/%07ld", v);
    v++;
    if (!(fl = fopen(buf, "w"))) {
      mudlog("SYSERR: Can't Open Vehicle File For Write.", NULL, LOG_SYSLOG, FALSE);
      return;
    }

    if (veh->sub)
      for (i = character_list; i; i = i->next)
        if (GET_IDNUM(i) == veh->owner) {
          veh->next_sub = i->char_specials.subscribe;
          i->char_specials.subscribe = veh;
          break;
        }
    room = veh->in_room;
    if (!ROOM_FLAGGED(room, ROOM_GARAGE))
      if (zone_table[world[veh->in_room].zone].juridiction)
        switch (number(0, 2)) {
        case 0:
          room = real_room(2751 + number(0, 2));
          break;
        case 1:
          room = real_room(2756 + number(0, 2));
          break;
        case 2:
          room = real_room(2762 + number(0, 2));
          break;
        }
      else
        room = real_room(22670 + number(0, 16));
    fprintf(fl, "[VEHICLE]\n");
    fprintf(fl, "\tVnum:\t%ld\n", veh_index[veh->veh_number].vnum);
    fprintf(fl, "\tOwner:\t%ld\n", veh->owner);
    fprintf(fl, "\tInRoom:\t%ld\n", GET_ROOM_VNUM(room));
    fprintf(fl, "\tSubscribed:\t%d\n", veh->sub);
    fprintf(fl, "\tDamage:\t%d\n", veh->damage);
    fprintf(fl, "\tSpare:\t%ld\n", veh->spare);
    fprintf(fl, "\tIdnum:\t%ld\n", veh->idnum);
    if (veh->in_veh)
      fprintf(fl, "\tInVeh:\t%ld\n", veh->in_veh->idnum);
    if (veh->restring)
      fprintf(fl, "\tVRestring:\t%s\n", veh->restring);
    if (veh->restring_long)
      fprintf(fl, "\tVRestringLong:$\n%s~\n", cleanup(buf2, veh->restring_long));
    fprintf(fl, "[CONTENTS]\n");
    int o = 0, level = 0;
    for (obj = veh->contents;obj;) {
      if (!IS_OBJ_STAT(obj, ITEM_NORENT)) {
        fprintf(fl, "\t[Object %d]\n", o);
        o++;
        fprintf(fl, "\t\tVnum:\t%ld\n", GET_OBJ_VNUM(obj));
        fprintf(fl, "\t\tInside:\t%d\n", level);
        if (GET_OBJ_TYPE(obj) == ITEM_PHONE)
          for (int x = 0; x < 4; x++)
            fprintf(fl, "\t\tValue %d:\t%d\n", x, GET_OBJ_VAL(obj, x));
        else if (GET_OBJ_TYPE(obj) != ITEM_WORN)
          for (int x = 0; x < 10; x++)
            fprintf(fl, "\t\tValue %d:\t%d\n", x, GET_OBJ_VAL(obj, x));
        fprintf(fl, "\t\tCondition:\t%d\n", GET_OBJ_CONDITION(obj));
        fprintf(fl, "\t\tCost:\t%d\n", GET_OBJ_COST(obj));
        fprintf(fl, "\t\tTimer:\t%d\n", GET_OBJ_TIMER(obj));
        fprintf(fl, "\t\tAttempt:\t%d\n", GET_OBJ_ATTEMPT(obj));
        fprintf(fl, "\t\tExtraFlags:\t%d\n", GET_OBJ_EXTRA(obj).ToString());
        fprintf(fl, "\t\tFront:\t%d\n", obj->vfront);
        if (obj->restring)
          fprintf(fl, "\t\tName:\t%s\n", obj->restring);
        if (obj->photo)
          fprintf(fl, "\t\tPhoto:$\n%s~\n", cleanup(buf2, obj->photo));
      }

      if (obj->contains && !IS_OBJ_STAT(obj, ITEM_NORENT) && GET_OBJ_TYPE(obj) != ITEM_PART) {
        obj = obj->contains;
        level++;
        continue;
      } else if (!obj->next_content && obj->in_obj)
        while (obj && !obj->next_content && level >= 0) {
          obj = obj->in_obj;
          level--;
        }

      if (obj)
        obj = obj->next_content;
    }


    fprintf(fl, "[MODIS]\n");
    for (int x = 0, v = 0; x < NUM_MODS - 1; x++)
      if (GET_MOD(veh, x)) {
        fprintf(fl, "\tMod%d:\t%ld\n", v, GET_OBJ_VNUM(GET_MOD(veh, x)));
        v++;
      }
    fprintf(fl, "[MOUNTS]\n");
    int m = 0;
    for (obj = veh->mount; obj; obj = obj->next_content, m++) {
      fprintf(fl, "\t[Mount %d]\n", m);
      fprintf(fl, "\t\tMountNum:\t%ld\n", GET_OBJ_VNUM(obj));
      fprintf(fl, "\t\tAmmo:\t%d\n", GET_OBJ_VAL(obj, 9));
      if (obj->contains) {
        fprintf(fl, "\t\tVnum:\t%ld\n", GET_OBJ_VNUM(obj->contains));
        fprintf(fl, "\t\tCondition:\t%d\n", GET_OBJ_CONDITION(obj->contains));
        if (obj->restring)
          fprintf(fl, "\t\tName:\t%s\n", obj->contains->restring);
        for (int x = 0; x < 10; x++)
          fprintf(fl, "\t\tValue %d:\t%d\n", x, GET_OBJ_VAL(obj->contains, x));

      }
    }
    fprintf(fl, "[GRIDGUIDE]\n");
    o = 0;
    for (struct grid_data *grid = veh->grid; grid; grid = grid->next) {
      fprintf(fl, "\t[GRID %d]\n", o++);
      fprintf(fl, "\t\tName:\t%s\n", grid->name);
      fprintf(fl, "\t\tRoom:\t%ld\n", grid->room);
    }
    fclose(fl);
  }
  if (!(fl = fopen("etc/consist", "w"))) {
    mudlog("SYSERR: Can't Open Consistentcy File For Write.", NULL, LOG_SYSLOG, FALSE);
    return;
  }
  for (int m = 0; m < 5; m++) {
    market[m] = MIN(5000, market[m] + number(-1, 2));
    if (market[m] < 50)
      market[m] = 50;
  }
  fprintf(fl, "[MARKET]\r\n");
  fprintf(fl, "\tBlue:\t%d\n", market[0]);
  fprintf(fl, "\tGreen:\t%d\n", market[1]);
  fprintf(fl, "\tOrange:\t%d\n", market[2]);
  fprintf(fl, "\tRed:\t%d\n", market[3]);
  fprintf(fl, "\tBlack:\t%d\n", market[4]);
  fclose(fl);
  // 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;
  int i, dam = 0, power = 0;

  // loop through all the characters
  for (ch = character_list; ch; ch = next_ch) {

    next_ch = ch->next;

    if (AFF_FLAGGED(ch, AFF_FEAR)) {
      if (!number(0, 2)) {
        extern ACMD(do_flee);
        do_flee(ch, "", 0, 0);
      } else {
        AFF_FLAGS(ch).RemoveBit(AFF_FEAR);
        send_to_char("You feel calmer.\r\n", ch);
      }
    }
    if (GET_TEMP_QUI_LOSS(ch) > 0) {
      GET_TEMP_QUI_LOSS(ch)--;
      affect_total(ch);
    }
    if (AFF_FLAGGED(ch, AFF_ACID) && !FIGHTING(ch))
      AFF_FLAGS(ch).RemoveBit(AFF_ACID);
    if (GET_SUSTAINED_NUM(ch) && !IS_ELEMENTAL(ch)) {
      struct sustain_data *next, *temp;
      for (struct sustain_data *sus = GET_SUSTAINED(ch); sus; sus = next) {
        next = sus->next;
        //        if (sus && sus->caster && spells[sus->spell].duration == PERMANENT) osanai
        if (sus->spell < 0 || sus->spell > SPELL_SHADOW) {
          sprintf(buf, "COWS GO MOO %s %d", GET_CHAR_NAME(ch), sus->spell);
          log(buf);
          continue;
        }
        if (sus)
          if (sus->caster)
            if (spells[sus->spell].duration == PERMANENT)
              if (++sus->time >= (sus->spell == SPELL_IGNITE ? sus->drain : (sus->spell == SPELL_TREAT ? sus->drain * 2.5 : sus->drain * 5))) {
                if (sus->spell == SPELL_IGNITE) {
                  send_to_char("Your body erupts in flames!\r\n", sus->other);
                  act("$n's body suddenly bursts into flames!\r\n", TRUE, sus->other, 0, 0, TO_ROOM);
                  sus->other->points.fire[0] = srdice();
                  sus->other->points.fire[1] = 0;
                } else {
                  strcpy(buf, spells[sus->spell].name);
                  send_to_char(ch, "The effects of %s become permanent.\r\n", buf);
                }
                GET_SUSTAINED_NUM(ch)--;
                if (next && sus->idnum == next->idnum)
                  next = next->next;
                if (sus->other)
                  for (struct sustain_data *vsus = GET_SUSTAINED(sus->other); vsus; vsus = vsus->next)
                    if (vsus->other == ch && vsus->idnum == sus->idnum && (sus->other == ch ? vsus != sus : 1)) {
                      REMOVE_FROM_LIST(vsus, GET_SUSTAINED(sus->other), next);
                      delete [] vsus;
                    }
                REMOVE_FROM_LIST(sus, GET_SUSTAINED(ch), next);
                delete [] sus;
              }
      }
    }
    if (affected_by_spell(ch, SPELL_CONFUSION) || affected_by_spell(ch, SPELL_CHAOS) || affected_by_power(ch, CONFUSION))
      if (number(1, 10) >= 5)
        switch(number(0, 10)) {
        case 0:
          send_to_char("Lovely weather today.\r\n", ch);
          break;
        case 1:
          send_to_char("Is that who I think it is? Nah, my mistake.\r\n", ch);
          break;
        case 2:
          send_to_char("Now where did I leave my car keys.\r\n", ch);
          break;
        case 3:
          send_to_char("Over There!\r\n", ch);
          break;
        case 4:
          send_to_char("x + 2dy divided by 3 is... no wait CARRY THE 1!\r\n", ch);
          break;
        case 5:
          send_to_char("A large troll carrying a panther assault cannon arrives from the north.\r\n", ch);
          break;
        case 6:
          if (ch->carrying)
            send_to_char(ch, "You complete the bonding ritual for %s.\r\n", GET_OBJ_NAME(ch->carrying));
          break;
        case 7:
          send_to_char("You don't have enough karma to do that!\r\n", ch);
          break;
        case 8:
          send_to_char("You could do it with a needle!\r\n", ch);
          break;
        case 9:
          send_to_char("Nothing seems to happen.\r\n", ch);
          break;
        }

    if (!IS_NPC(ch) && GET_DRUG_DOSE(ch) && --GET_DRUG_DURATION(ch) < 0) {
      if (!GET_DRUG_STAGE(ch)) {
        bool physical = TRUE;
        if (GET_DRUG_AFFECT(ch) == DRUG_HYPER || GET_DRUG_AFFECT(ch) == DRUG_BURN)
          physical = FALSE;
        if (drug_types[GET_DRUG_AFFECT(ch)].level > 0) {
          dam = drug_types[GET_DRUG_AFFECT(ch)].level + (GET_DRUG_DOSE(ch) > 1 ? 1 : 0);
          power = drug_types[GET_DRUG_AFFECT(ch)].power + (GET_DRUG_DOSE(ch) > 2 ? GET_DRUG_DOSE(ch) - 2 : 0);
          dam = convert_damage(stage(-success_test(GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), power), dam));
          damage(ch, ch, dam, TYPE_BIOWARE, physical);
        }
        GET_DRUG_STAGE(ch) = 1;
        GET_DRUG_LASTFIX(ch, GET_DRUG_AFFECT(ch)) = time(0);
        switch (GET_DRUG_AFFECT(ch)) {
        case DRUG_ACTH:
          sprintf(buf, "You feel a brief moment of vertigo.\r\n");
          extern void check_adrenaline(struct char_data *ch, int mode);
          check_adrenaline(ch, 1);
          GET_DRUG_AFFECT(ch) = GET_DRUG_DOSE(ch) = GET_DRUG_DURATION(ch) = 0;
          break;
        case DRUG_HYPER:
          sprintf(buf, "The world seems to swirl around you as your mind is bombarded with feedback.\r\n");
          GET_DRUG_DURATION(ch) = dam * 10;
          break;
        case DRUG_JAZZ:
          sprintf(buf, "The world slows down around you.\r\n");
          GET_DRUG_DURATION(ch) = 10 * srdice();
          break;
        case DRUG_KAMIKAZE:
          sprintf(buf, "Your body feels alive with energy and the desire to fight.\r\n");
          GET_DRUG_DURATION(ch) = 10 * srdice();
          break;
        case DRUG_PSYCHE:
          sprintf(buf, "Your feel your mind racing.\r\n");
          GET_DRUG_DURATION(ch) = MAX(1, 12 - GET_REAL_BOD(ch)) * 60;
          break;
        case DRUG_BLISS:
          sprintf(buf, "The world fades into bliss as your body becomes sluggish.\r\n");
          GET_DRUG_DURATION(ch) = MAX(1, 6 - GET_REAL_BOD(ch)) * 60;
          break;
        case DRUG_BURN:
          sprintf(buf, "You suddenly feel very intoxicated.\r\n");
          GET_DRUG_AFFECT(ch) = GET_DRUG_DOSE(ch) = GET_DRUG_DURATION(ch) = 0;
          GET_COND(ch, DRUNK) = 24;
          break;
        case DRUG_CRAM:
          sprintf(buf, "Your body feels alive with energy.\r\n");
          GET_DRUG_DURATION(ch) = MAX(1, 12 - GET_REAL_BOD(ch)) * 60;
          break;
        case DRUG_NITRO:
          sprintf(buf, "You lose sense of yourself as your entire body comes alive with energy.\r\n");
          GET_DRUG_DURATION(ch) = 10 * srdice();
          break;
        case DRUG_NOVACOKE:
          sprintf(buf, "You feel euphoric and alert.\r\n");
          GET_DRUG_DURATION(ch) = MAX(1, 10 - GET_REAL_BOD(ch)) * 60;
          break;
        case DRUG_ZEN:
          sprintf(buf, "You start to loose your sense of reality as your sight fills with hallucinations.\r\n");
          GET_DRUG_DURATION(ch) = 10 * srdice();
          break;
        }
        send_to_char(buf, ch);
      } else if (GET_DRUG_STAGE(ch) == 1) {
        int toxin = 0;
        for (struct obj_data *obj = ch->bioware; obj && !toxin; obj = obj->next_content)
          if (GET_OBJ_VAL(obj, 0) == BIO_TOXINEXTRACTOR)
            toxin = GET_OBJ_VAL(obj, 1);
        send_to_char(ch, "You begin to feel drained as the %s wears off.\r\n", drug_types[GET_DRUG_AFFECT(ch)].name);
        GET_DRUG_STAGE(ch) = 2;
        switch (GET_DRUG_AFFECT(ch)) {
        case DRUG_JAZZ:
          GET_DRUG_DURATION(ch) = 10 * srdice();
          damage(ch, ch, convert_damage(stage(-success_test(GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), 8 - toxin), LIGHT)), TYPE_BIOWARE, 0);
          break;
        case DRUG_KAMIKAZE:
          GET_DRUG_DURATION(ch) = 10 * srdice();
          damage(ch, ch, convert_damage(stage(-success_test(GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), 6 - toxin), MODERATE)), TYPE_BIOWARE, 0);
          break;
        case DRUG_CRAM:
          GET_DRUG_DURATION(ch) = MAX(1, 12 - GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0)) * 60;
          break;
        case DRUG_NITRO:
          damage(ch, ch, convert_damage(stage(-success_test(GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0), 8 - toxin), DEADLY)), TYPE_BIOWARE, 0);
          GET_DRUG_STAGE(ch) = GET_DRUG_DOSE(ch) = GET_DRUG_AFFECT(ch) = 0;
          break;
        case DRUG_NOVACOKE:
          GET_DRUG_DURATION(ch) = MAX(1, 10 - GET_REAL_BOD(ch) - (GET_BIOOVER(ch) > 0 ? GET_BIOOVER(ch) / 2 : 0)) * 60;
          break;
        default:
          GET_DRUG_STAGE(ch) = GET_DRUG_DOSE(ch) = GET_DRUG_AFFECT(ch) = 0;
          if (AFF_FLAGGED(ch, AFF_DETOX))
            AFF_FLAGS(ch).RemoveBit(AFF_DETOX);
        }
        if (drug_types[GET_DRUG_AFFECT(ch)].tolerance) {
          if (GET_DRUG_DOSES(ch, GET_DRUG_AFFECT(ch)) == 1 && success_test(GET_REAL_BOD(ch), drug_types[GET_DRUG_AFFECT(ch)].tolerance) < 1)
            GET_DRUG_TOLERANT(ch, GET_DRUG_AFFECT(ch))++;
          if ((!GET_DRUG_ADDICT(ch, GET_DRUG_AFFECT(ch)) && !(drug_types[GET_DRUG_AFFECT(ch)].edge_preadd % ++GET_DRUG_DOSES(ch, GET_DRUG_AFFECT(ch)))) ||
              (GET_DRUG_ADDICT(ch, GET_DRUG_AFFECT(ch)) && !(drug_types[GET_DRUG_AFFECT(ch)].edge_posadd % ++GET_DRUG_DOSES(ch, GET_DRUG_AFFECT(ch)))) &&
              success_test(GET_REAL_BOD(ch), drug_types[GET_DRUG_AFFECT(ch)].tolerance + GET_DRUG_EDGE(ch, GET_DRUG_AFFECT(ch))))
            GET_DRUG_TOLERANT(ch, GET_DRUG_AFFECT(ch))++;
        }
      } else if (GET_DRUG_STAGE(ch) == 2) {
        send_to_char(ch, "The after affects of the %s begin to wear off.\r\n", drug_types[GET_DRUG_AFFECT(ch)].name);
        GET_DRUG_STAGE(ch) = GET_DRUG_DOSE(ch) = GET_DRUG_AFFECT(ch) = 0;
        if (AFF_FLAGGED(ch, AFF_DETOX))
          AFF_FLAGS(ch).RemoveBit(AFF_DETOX);
      }
      affect_total(ch);
    }
    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)) {
      if (!check_spirit_sector(ch->in_room, GET_SPARE1(ch))) {
        act("Being away from its environment, $n suddenly ceases to exist.", TRUE, ch, 0, 0, TO_ROOM);
        end_spirit_existance(ch, FALSE);
      }
    }
    if (ch->points.fire[0] > 0) {
      if (world[ch->in_room].sector_type != SPIRIT_HEARTH && !ROOM_FLAGGED(ch->in_room, ROOM_INDOORS) && weather_info.sky >= SKY_RAINING)
        ch->points.fire[0] -= 3;
      else
        ch->points.fire[0]--;
      if (ch->points.fire[0] < 1) {
        act("The flames around $n die down.", FALSE, ch, 0, 0, TO_ROOM);
        act("The flames surrounding you die down.", FALSE, ch, 0, 0, TO_CHAR);
      } else {
        act("Flames continue to burn around $n!", FALSE, ch, 0, 0, TO_ROOM);
        act("^RYour body is surrounded in flames!", FALSE, ch, 0, 0, TO_CHAR);
      }
      damage_equip(ch, ch, 6 + ch->points.fire[1], TYPE_FIRE);
      int dam = convert_damage(stage(-success_test(GET_BOD(ch) + GET_POWER(ch, ADEPT_TEMPERATURE_TOLERANCE), 6 + ch->points.fire[1]++ - GET_IMPACT(ch)), MODERATE));
      ch->points.fire[1]++;
      damage(ch, ch, dam, TYPE_SUFFERING, PHYSICAL);
    }

  }
}

float gen_size(int race, bool height, int size, int sex)
{
  float mod;
  switch (size) {
  case 1:
    mod = 0.75;
    break;
  case 2:
    mod = 0.88;
    break;
  case 3:
  default:
    mod = 1;
    break;
  case 4:
    mod = 1.13;
    break;
  case 5:
    mod = 1.25;
    break;

  }
  switch (race) {
  case RACE_HUMAN:
    if (sex == SEX_MALE) {
      if (height)
        return number(160, 187) * mod;
      else
        return number(65, 77) * mod;
    } else {
      if (height)
        return number(145, 175) * mod;
      else
        return number(56, 69) * mod;
    }
    break;
  case RACE_DWARF:
    if (sex == SEX_MALE) {
      if (height)
        return number(115, 133) * mod;
      else
        return number(50, 62) * mod;
    } else {
      if (height)
        return number(80, 115) * mod;
      else
        return number(45, 56) * mod;
    }
    break;
  case RACE_ELF:
    if (sex == SEX_MALE) {
      if (height)
        return number(180, 205) * mod;
      else
        return number(70, 82) * mod;
    } else {
      if (height)
        return number(175, 195) * mod;
      else
        return number(60, 75) * mod;
    }
    break;
  case RACE_ORK:
    if (sex == SEX_MALE) {
      if (height)
        return number(185, 210) * mod;
      else
        return number(90, 105) * mod;
    } else {
      if (height)
        return number(178, 195) * mod;
      else
        return number(90, 105) * mod;
    }
    break;
  case RACE_TROLL:
    if (sex == SEX_MALE) {
      if (height)
        return number(270, 295) * mod;
      else
        return number(215, 245) * mod;

    } else {
      if (height)
        return number(255, 280) * mod;
      else
        return number(200, 230) * mod;
    }
    break;
  case RACE_CYCLOPS:
    if (sex == SEX_MALE) {
      if (height)
        return number(290, 340) * mod;
      else
        return number(240, 350) * mod;
    } else {
      if (height)
        return number(275, 320) * mod;
      else
        return number(220, 340) * mod;
    }
    break;
  case RACE_KOBOROKURU:
    if (sex == SEX_MALE) {
      if (height)
        return number(115, 133) * mod;
      else
        return number(50, 62) * mod;
    } else {
      if (height)
        return number(80, 112) * mod;
      else
        return number(45, 56) * mod;
    }
    break;
  case RACE_FOMORI:
    if (sex == SEX_MALE) {
      if (height)
        return number(270, 295) * mod;
      else
        return number(215, 245) * mod;
    } else {
      if (height)
        return number(255, 280) * mod;
      else
        return number(200, 230) * mod;
    }
    break;
  case RACE_MENEHUNE:
    if (sex == SEX_MALE) {
      if (height)
        return number(115, 133) * mod;
      else
        return number(50, 62) * mod;
    } else {
      if (height)
        return number(80, 112) * mod;
      else
        return number(45, 56) * mod;
    }
    break;
  case RACE_HOBGOBLIN:
    if (sex == SEX_MALE) {
      if (height)
        return number(185, 210) * mod;
      else
        return number(90, 105) * mod;
    } else {
      if (height)
        return number(178, 195) * mod;
      else
        return number(85, 95) * mod;
    }
    break;
  case RACE_GIANT:
    if (sex == SEX_MALE) {
      if (height)
        return number(300, 450) * mod;
      else
        return number(380, 477) * mod;
    } else {
      if (height)
        return number(296, 369) * mod;
      else
        return number(380, 430) * mod;
    }
    break;
  case RACE_GNOME:
    if (sex == SEX_MALE) {
      if (height)
        return number(85, 137) * mod;
      else
        return number(45, 59) * mod;
    } else {
      if (height)
        return number(75, 95) * mod;
      else
        return number(39, 52) * mod;
    }
    break;
  case RACE_ONI:
    if (sex == SEX_MALE) {
      if (height)
        return number(185, 215) * mod;
      else
        return number(90, 105) * mod;
    } else {
      if (height)
        return number(178, 195) * mod;
      else
        return number(80, 95) * mod;
    }
    break;
  case RACE_WAKYAMBI:
    if (sex == SEX_MALE) {
      if (height)
        return number(180, 205) * mod;
      else
        return number(70, 82) * mod;
    } else {
      if (height)
        return number(175, 195) * mod;
      else
        return number(60, 75) * mod;
    }
    break;
  case RACE_OGRE:
    if (sex == SEX_MALE) {
      if (height)
        return number(185, 235) * mod;
      else
        return number(90, 105) * mod;
    } else {
      if (height)
        return number(175, 195) * mod;
      else
        return number(85, 96) * mod;
    }
    break;
  case RACE_MINOTAUR:
    if (sex == SEX_MALE) {
      if (height)
        return number(200, 255) * mod;
      else
        return number(100, 145) * mod;
    } else {
      if (height)
        return number(145, 180) * mod;
      else
        return number(95, 120) * mod;
    }
    break;
  case RACE_SATYR:
    if (sex == SEX_MALE) {
      if (height)
        return number(180, 217) * mod;
      else
        return number(90, 105) * mod;
    } else {
      if (height)
        return number(175, 195) * mod;
      else
        return number(80, 95) * mod;
    }
    break;
  case RACE_NIGHTONE:
    if (sex == SEX_MALE) {
      if (height)
        return number(185, 227) * mod;
      else
        return number(90, 108) * mod;
    } else {
      if (height)
        return number(180, 188) * mod;
      else
        return number(80, 91) * mod;
    }
    break;
  case RACE_DRAGON:
    if (sex == SEX_MALE) {
      if (height)
        return number(300, 400) * mod;
      else
        return number(1900, 2100) * mod;
    } else {
      if (height)
        return number(400, 500) * mod;
      else
        return number(1950, 2300) * mod;
    }
    break;
  default:
    if (sex == SEX_MALE) {
      if (height)
        return number(160, 187) * mod;
      else
        return number(65, 77) * mod;
    } else {
      if (height)
        return number(145, 175) * mod;
      else
        return number(56, 69) * mod;
    }
  }
}