/**************************************************************************
* File: handler.c Part of CircleMUD *
* Usage: internal funcs: moving and finding chars/objs *
* *
* 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include "structs.h"
#include "awake.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "handler.h"
#include "interpreter.h"
#include "spells.h"
#include "memory.h"
#include "dblist.h"
// memory object
extern class memoryClass *Mem;
extern class objList ObjList;
/* external vars */
extern char *MENU;
extern char *QMENU;
extern const char *spells[];
extern int top_of_world;
extern int top_of_zone_table;
extern struct char_data *character_list;
extern struct descriptor_data *descriptor_list;
extern struct room_data *world;
extern struct zone_data *zone_table;
/* external functions */
extern void stop_fighting(struct char_data * ch);
extern void remove_follower(struct char_data * ch);
extern void clearMemory(struct char_data * ch);
extern void Crash_rentsave(struct char_data *ch, int cost);
extern void print_object_location(int, struct obj_data *, struct char_data *, int);
extern int skill_web(struct char_data *, int);
extern int return_general(int skill_num);
extern int can_wield_both(struct char_data *, struct obj_data *, struct obj_data *);
extern int ability_cost(int abil, int level);
extern int max_ability(int i);
extern bool save_etext(struct char_data *ch);
extern bool write_spells(struct char_data *ch);
struct obj_data *find_obj(struct char_data *ch, char *name, int num);
char *fname(char *namelist)
{
static char holder[30];
register char *point;
for (point = holder; isalpha(*namelist); namelist++, point++)
*point = *namelist;
*point = '\0';
return (holder);
}
int isname(char *str, char *namelist)
{
if(*namelist == '\0')
return 0;
if (namelist[0] == '\0')
return 0;
register char *curname, *curstr;
curname = namelist;
for (;;) {
for (curstr = str;; curstr++, curname++) {
if ((!*curstr && !isalpha(*curname)) || is_abbrev(curstr, curname))
/* if (!*curstr && !isalpha(*curname))*/
return (1);
if (!*curname)
return (0);
if (!*curstr || *curname == ' ')
break;
if (LOWER(*curstr) != LOWER(*curname))
break;
}
/* skip to next name */
for (; isalpha(*curname); curname++);
if (!*curname)
return (0);
curname++; /* first char of new name */
}
}
void age_stat_affect(struct char_data *ch)
{
switch (GET_RACE(ch)) {
case RACE_HUMAN:
if (GET_AGE(ch) < 55)
return;
GET_STR(ch) -= (int)((GET_AGE(ch) - 49) / 6);
GET_QUI(ch) -= (int)((GET_AGE(ch) - 49) / 6);
GET_BOD(ch) -= (int)((GET_AGE(ch) - 49) / 6);
GET_CHA(ch) -= (int)((GET_AGE(ch) - 49) / 7);
GET_INT(ch) -= (int)((GET_AGE(ch) - 49) / 8);
GET_WIL(ch) -= (int)((GET_AGE(ch) - 49) / 8);
GET_REA(ch) -= (int)((GET_AGE(ch) - 49) / 7);
break;
case RACE_DWARF:
if (GET_AGE(ch) < 125)
return;
GET_STR(ch) -= (int)((GET_AGE(ch) - 115) / 15);
GET_QUI(ch) -= (int)((GET_AGE(ch) - 115) / 10);
GET_BOD(ch) -= (int)((GET_AGE(ch) - 115) / 20);
GET_CHA(ch) -= (int)((GET_AGE(ch) - 115) / 15);
GET_INT(ch) -= (int)((GET_AGE(ch) - 115) / 15);
GET_WIL(ch) -= (int)((GET_AGE(ch) - 115) / 20);
GET_REA(ch) -= (int)((GET_AGE(ch) - 115) / 12);
break;
case RACE_ELF:
if (GET_AGE(ch) < 300)
return;
GET_STR(ch) -= (int)((GET_AGE(ch) - 275) / 30);
GET_QUI(ch) -= (int)((GET_AGE(ch) - 275) / 50);
GET_BOD(ch) -= (int)((GET_AGE(ch) - 275) / 25);
GET_CHA(ch) -= (int)((GET_AGE(ch) - 275) / 50);
GET_INT(ch) -= (int)((GET_AGE(ch) - 275) / 50);
GET_WIL(ch) -= (int)((GET_AGE(ch) - 275) / 40);
GET_REA(ch) -= (int)((GET_AGE(ch) - 275) / 50);
break;
case RACE_ORK:
if (GET_AGE(ch) < 45)
return;
GET_STR(ch) -= (int)((GET_AGE(ch) - 38) / 9);
GET_QUI(ch) -= (int)((GET_AGE(ch) - 38) / 8);
GET_BOD(ch) -= (int)((GET_AGE(ch) - 38) / 10);
GET_CHA(ch) -= (int)((GET_AGE(ch) - 38) / 7);
GET_INT(ch) -= (int)((GET_AGE(ch) - 38) / 7);
GET_WIL(ch) -= (int)((GET_AGE(ch) - 38) / 8);
GET_REA(ch) -= (int)((GET_AGE(ch) - 38) / 7);
break;
case RACE_TROLL:
if (GET_AGE(ch) < 50)
return;
GET_STR(ch) -= (int)((GET_AGE(ch) - 42) / 10);
GET_QUI(ch) -= (int)((GET_AGE(ch) - 42) / 8);
GET_BOD(ch) -= (int)((GET_AGE(ch) - 42) / 15);
GET_CHA(ch) -= (int)((GET_AGE(ch) - 42) / 8);
GET_INT(ch) -= (int)((GET_AGE(ch) - 42) / 8);
GET_WIL(ch) -= (int)((GET_AGE(ch) - 42) / 9);
GET_REA(ch) -= (int)((GET_AGE(ch) - 42) / 8);
break;
}
}
void affect_modify(struct char_data * ch, byte loc, sbyte mod, long bitv, bool add)
{
int maxabil;
if (add) {
SET_BIT(AFF_FLAGS(ch), bitv);
} else {
REMOVE_BIT(AFF_FLAGS(ch), bitv);
mod = -mod;
}
maxabil = ((IS_NPC(ch) || (GET_LEVEL(ch) >= LVL_MANAGER)) ? 50 : 20);
switch (loc) {
case APPLY_NONE:
break;
case APPLY_STR:
GET_STR(ch) += mod;
break;
case APPLY_QUI:
GET_QUI(ch) += mod;
break;
case APPLY_INT:
GET_INT(ch) += mod;
break;
case APPLY_WIL:
GET_WIL(ch) += mod;
break;
case APPLY_BOD:
GET_BOD(ch) += mod;
break;
case APPLY_CHA:
GET_CHA(ch) += mod;
break;
case APPLY_MAG:
GET_MAG(ch) += (mod * 100);
break;
case APPLY_ESS:
GET_ESS(ch) += (mod * 100);
break;
case APPLY_REA:
GET_REA(ch) += mod;
break;
case APPLY_AGE:
ch->player.time.birth -= (mod * SECS_PER_MUD_YEAR);
break;
case APPLY_CHAR_WEIGHT:
GET_WEIGHT(ch) += mod;
break;
case APPLY_CHAR_HEIGHT:
GET_HEIGHT(ch) += mod;
break;
case APPLY_MENTAL:
GET_MAX_MENTAL(ch) += mod * 100;
break;
case APPLY_PHYSICAL:
GET_MAX_PHYSICAL(ch) += mod * 100;
break;
case APPLY_BALLISTIC:
GET_BALLISTIC(ch) += mod;
break;
case APPLY_IMPACT:
GET_IMPACT(ch) += mod;
break;
case APPLY_ASTRAL_POOL:
GET_ASTRAL(ch) += mod;
break;
case APPLY_COMBAT_POOL:
GET_COMBAT(ch) += mod;
break;
case APPLY_HACKING_POOL:
GET_HACKING(ch) += mod;
break;
case APPLY_MAGIC_POOL:
GET_MAGIC(ch) += mod; /* GET_MAGIC gets their magic pool, GET_MAG is for attribute*/
break;
case APPLY_INITIATIVE_DICE:
GET_INIT_DICE(ch) += mod;
break;
case APPLY_TARGET:
GET_TARGET_MOD(ch) += mod;
break;
default:
// sprintf(buf, "SYSLOG: Unknown apply adjust: %s/%d.", GET_NAME(ch), loc);
// log(buf);
break;
} /* switch */
}
void apply_focus_effect( struct char_data *ch, struct obj_data *object )
{
int i;
if (object->worn_by == NULL )
return;
if (GET_OBJ_TYPE(object) != ITEM_FOCUS)
return;
if (GET_OBJ_VAL(object, 9) != GET_IDNUM(ch))
return;
if (GET_OBJ_VAL(object, 5) == 0)
{
if ((GET_FOCI(ch) + 1) > GET_INT(ch))
return;
GET_OBJ_VAL(object, 5) = 1;
GET_FOCI(ch)++;
}
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
object->affected[i].location,
object->affected[i].modifier,
object->obj_flags.bitvector,
TRUE);
}
void remove_focus_effect( struct char_data *ch, struct obj_data *object )
{
int i;
if (GET_OBJ_TYPE(object) != ITEM_FOCUS)
return;
if (GET_OBJ_VAL(object, 9) != GET_IDNUM(ch))
return;
if (GET_OBJ_VAL(object, 5) == 0)
return;
GET_OBJ_VAL(object, 5) = 0;
GET_FOCI(ch)--;
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(ch,
object->affected[i].location,
object->affected[i].modifier,
object->obj_flags.bitvector,
FALSE);
}
/* This updates a character by subtracting everything he is affected by */
/* restoring original abilities, and then affecting all again */
void affect_total(struct char_data * ch)
{
struct obj_data *wielded = GET_EQ(ch, WEAR_WIELD);
struct obj_data *cyber, *obj = NULL, *one, *two;
struct affected_type *af;
spell_t *spell;
sh_int i, j, skill;
if (IS_IC(ch) || IS_PERSONA(ch) || IS_PROJECT(ch))
return;
/* effects of used equipment */
for (i = 0; i < (NUM_WEARS - 1); i++) {
if (GET_EQ(ch, i))
{
if (GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_FOCUS)
remove_focus_effect(ch, GET_EQ(ch, i));
else
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, GET_EQ(ch, i)->affected[j].location, GET_EQ(ch, i)->affected[j].modifier,
GET_EQ(ch, i)->obj_flags.bitvector, FALSE);
}
}
/* effects of foci in inventory *
for (obj = ch->carrying; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS)
remove_focus_effect(ch, obj);*/
/* effects of cyberware */
for (cyber = ch->cyberware; cyber; cyber = cyber->next_content) {
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, cyber->affected[j].location,
cyber->affected[j].modifier,
cyber->obj_flags.bitvector, FALSE);
}
/* effects of bioware */
for (cyber = ch->bioware; cyber; cyber = cyber->next_content) {
if (GET_OBJ_VAL(cyber, 2) != 4 || (GET_OBJ_VAL(cyber, 2) == 4 &&
GET_OBJ_VAL(cyber, 5) > 0))
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, cyber->affected[j].location,
cyber->affected[j].modifier,
cyber->obj_flags.bitvector, FALSE);
}
/* effects of spells */
for (af = ch->affected; af; af = af->next)
affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);
ch->aff_abils = ch->real_abils;
/* calculate reaction before you add eq, cyberware, etc so that things *
* such as wired reflexes work properly (as they only modify reaction *
* and not intelligence and quickness). -cjd */
ch->real_abils.rea = (ch->real_abils.intel + ch->real_abils.qui) >> 1;
GET_REA(ch) = (GET_INT(ch) + GET_QUI(ch)) >> 1;
if (PLR_FLAGGED(ch, PLR_NEWBIE) && GET_REP(ch) > 15) {
REMOVE_BIT(PLR_FLAGS(ch), PLR_NEWBIE);
for (cyber = ch->cyberware; cyber; cyber = cyber->next_content) {
if (IS_OBJ_STAT(cyber, ITEM_NODONATE))
REMOVE_BIT(GET_OBJ_EXTRA(cyber), ITEM_NODONATE);
if (IS_OBJ_STAT(cyber, ITEM_NOSELL))
REMOVE_BIT(GET_OBJ_EXTRA(cyber), ITEM_NOSELL);
}
}
/* set the dice pools before equip so that they can be affected */
/* combat pool is equal to quickness, wil, and int divided by 2 */
GET_COMBAT(ch) = 0;
GET_HACKING(ch) = 0;
GET_ASTRAL(ch) = 0;
GET_MAGIC(ch) = 0;
// reset initiative dice
GET_INIT_DICE(ch) = 0;
/* reset # of foci char has */
if (!IS_NPC(ch))
GET_FOCI(ch) = 0;
/* effects of foci in inventory *
for (obj = ch->carrying; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS)
apply_focus_effect(ch, obj);*/
/* effects of equipment */
for (i = 0; i < (NUM_WEARS - 1); i++)
if (GET_EQ(ch, i))
{
if (GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_FOCUS)
apply_focus_effect(ch, GET_EQ(ch,i));
else
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, GET_EQ(ch, i)->affected[j].location,
GET_EQ(ch, i)->affected[j].modifier,
GET_EQ(ch, i)->obj_flags.bitvector, TRUE);
}
/* effects of cyberware */
for (cyber = ch->cyberware; cyber; cyber = cyber->next_content) {
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, cyber->affected[j].location, cyber->affected[j].modifier,
cyber->obj_flags.bitvector, TRUE);
}
/* effects of bioware */
for (cyber = ch->bioware; cyber; cyber = cyber->next_content){
if (GET_OBJ_VAL(cyber, 2) != 4 || (GET_OBJ_VAL(cyber, 2) == 4 && GET_OBJ_VAL(cyber, 5) > 0))
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, cyber->affected[j].location,
cyber->affected[j].modifier,
cyber->obj_flags.bitvector, TRUE);
}
for (af = ch->affected; af; af = af->next)
affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
// take age into account
if (!IS_NPC(ch) && GET_LEVEL(ch) < LVL_LEGEND)
age_stat_affect(ch);
/* Make certain values are between 1..50, not < 0 and not > 50! */
i = ((IS_NPC(ch) || (GET_LEVEL(ch) >= LVL_MANAGER)) ? 50 : 15);
GET_QUI(ch) = MAX(1, MIN(GET_QUI(ch), i));
GET_CHA(ch) = MAX(1, MIN(GET_CHA(ch), i));
GET_INT(ch) = MAX(1, MIN(GET_INT(ch), i));
GET_WIL(ch) = MAX(1, MIN(GET_WIL(ch), i));
GET_BOD(ch) = MAX(1, MIN(GET_BOD(ch), i));
GET_STR(ch) = MAX(1, MIN(GET_STR(ch), i));
GET_MAG(ch) = MAX(0, MIN(GET_MAG(ch), i * 100));
GET_ESS(ch) = MAX(0, MIN(GET_ESS(ch), 600));
GET_REA(ch) = MAX(1, MIN(GET_REA(ch), i));
if ((IS_NPC(ch) || GET_TRADITION(ch) == TRAD_ADEPT) &&
GET_SKILL(ch, SKILL_REFLEXES) > 0)
GET_INIT_DICE(ch) += MIN(3, GET_SKILL(ch, SKILL_REFLEXES));
/* fix pools to take into account new attributes */
one = (GET_WIELDED(ch, 0) ? GET_EQ(ch, WEAR_WIELD) :
(struct obj_data *) NULL);
two = (GET_WIELDED(ch, 1) ? GET_EQ(ch, WEAR_HOLD) :
(struct obj_data *) NULL);
if (!one && !two)
skill = GET_SKILL(ch, SKILL_UNARMED_COMBAT);
else if (one) {
if (!GET_SKILL(ch, GET_OBJ_VAL(one, 4)))
skill = GET_SKILL(ch, return_general(GET_OBJ_VAL(one, 4)));
else skill = GET_SKILL(ch, GET_OBJ_VAL(one, 4));
} else if (two) {
if (!GET_SKILL(ch, GET_OBJ_VAL(two, 4)))
skill = GET_SKILL(ch, return_general(GET_OBJ_VAL(two, 4)));
else skill = GET_SKILL(ch, GET_OBJ_VAL(two, 4));
} else {
if (GET_SKILL(ch, GET_OBJ_VAL(one, 4)) <= GET_SKILL(ch, GET_OBJ_VAL(two, 4))) {
if (!GET_SKILL(ch, GET_OBJ_VAL(one, 4)))
skill = GET_SKILL(ch, return_general(GET_OBJ_VAL(one, 4)));
else skill = GET_SKILL(ch, GET_OBJ_VAL(one, 4));
} else {
if (!GET_SKILL(ch, GET_OBJ_VAL(two, 4)))
skill = GET_SKILL(ch, return_general(GET_OBJ_VAL(two, 4)));
else skill = GET_SKILL(ch, GET_OBJ_VAL(two, 4));
}
}
GET_COMBAT(ch) += (GET_QUI(ch) + GET_WIL(ch) + GET_INT(ch)) / 2;
if ((IS_NPC(ch) || GET_TRADITION(ch) == TRAD_ADEPT) &&
GET_SKILL(ch, SKILL_COMBAT_SENSE) > 0)
GET_COMBAT(ch) += MIN(3, GET_SKILL(ch, SKILL_COMBAT_SENSE));
GET_DEFENSE(ch) = MIN(GET_DEFENSE(ch), GET_COMBAT(ch));
GET_OFFENSE(ch) = GET_COMBAT(ch) - GET_DEFENSE(ch);
if (GET_OFFENSE(ch) > skill) {
GET_DEFENSE(ch) += GET_OFFENSE(ch) - skill;
GET_OFFENSE(ch) = skill;
}
if (GET_SKILL(ch, SKILL_COMPUTER) > 0)
GET_HACKING(ch) += GET_SKILL(ch, SKILL_COMPUTER) + GET_REA(ch);
if (!(!IS_NPC(ch) && GET_TRADITION(ch) != TRAD_SHAMANIC &&
GET_TRADITION(ch) != TRAD_HERMETIC))
GET_ASTRAL(ch) += (GET_MAG(ch) / 100) + GET_INT(ch) + GET_SKILL(ch, SKILL_SORCERY);
if (!(!IS_NPC(ch) && GET_TRADITION(ch) != TRAD_SHAMANIC &&
GET_TRADITION(ch) != TRAD_HERMETIC))
GET_MAGIC(ch) += GET_SKILL(ch, SKILL_SORCERY);
}
/* Insert an affect_type in a char_data structure
Automatically sets apropriate bits and apply's */
void affect_to_char(struct char_data *ch, struct affected_type *af)
{
struct affected_type *affected_alloc;
affected_alloc = new struct affected_type;
*affected_alloc = *af;
affected_alloc->next = ch->affected;
ch->affected = affected_alloc;
affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
affect_total(ch);
}
/*
* Remove an affected_type structure from a char (called when duration
* reaches zero). Pointer *af must never be NIL! Frees mem and calls
* affect_location_apply
*/
void affect_remove(struct char_data * ch, struct affected_type * af, int message)
{
struct char_data *tch = character_list;
struct affected_type *af2, *temp;
bool found = FALSE;
assert(ch->affected);
affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);
if (af->sustained_by < 0)
while (tch != NULL && (IS_NPC(tch) ? tch->nr : 0) != -af->sustained_by)
tch = tch->next;
else while (tch != NULL && (IS_NPC(tch) ? 0 : GET_IDNUM(tch)) != af->sustained_by)
tch = tch->next;
if (tch)
for (af2 = tch->affected; af2 && !found; af2 = af2->next)
if ((af2->type == af->type) && (af2->caster == TRUE) &&
(af2->sustained_by == (IS_NPC(ch) ? -ch->nr : GET_IDNUM(ch)))) {
if (af2->type < MAX_SPELLS) {
sprintf(buf, "You no longer sustain %s.\r\n", spells[af->type]);
if (message && af->type != SPELL_HEAL && af->type != SPELL_ANTIDOTE &&
af->type != SPELL_STABILIZE && af->type != SPELL_CURE_DISEASE)
send_to_char(buf, tch);
if (GET_SUSTAINED(tch) > 0)
GET_SUSTAINED(tch) -= 1;
}
REMOVE_FROM_LIST(af2, tch->affected, next);
if ( af != af2 )
delete af2;
found = TRUE;
}
if (af->type == SPELL_INFLUENCE && ch->master)
stop_follower(ch);
else if (af->type == SPELL_LIGHT && ch->in_room != NOWHERE)
world[ch->in_room].light--;
REMOVE_FROM_LIST(af, ch->affected, next);
delete af;
affect_total(ch);
}
/* Call affect_remove with every spell of spelltype "skill" */
void affect_from_char(struct char_data * ch, sh_int type)
{
struct affected_type *hjp;
for (hjp = ch->affected; hjp; hjp = hjp->next)
if (hjp->type == type)
affect_remove(ch, hjp, 1);
}
/*
* Return if a char is affected by a spell (SPELL_XXX), NULL indicates
* not affected
*/
int affected_by_spell(struct char_data * ch, sh_int type)
{
struct affected_type *hjp;
struct obj_data *obj;
int i;
for (hjp = ch->affected; hjp; hjp = hjp->next)
if ((hjp->type == type) && (hjp->caster == FALSE))
return 1;
for (obj = ch->carrying; obj; obj = obj->next_content)
if (GET_OBJ_TYPE(obj) == ITEM_FOCUS
&& GET_OBJ_VAL(obj, 0) == FOCI_LOCK
&& GET_OBJ_VAL(obj, 9) == (IS_NPC(ch) ? -1 : GET_IDNUM(ch))
&& GET_OBJ_VAL(obj, 8) == type)
return 2;
for (i = 0; i < NUM_WEARS; i++)
if ((obj = GET_EQ(ch, i)) && GET_OBJ_TYPE(obj) == ITEM_FOCUS &&
GET_OBJ_VAL(obj, 0) == FOCI_LOCK && GET_OBJ_VAL(obj, 8) == type &&
GET_OBJ_VAL(obj, 9) == (IS_NPC(ch) ? -1 : GET_IDNUM(ch)))
return 2;
return 0;
}
void affect_join(struct char_data * ch, struct affected_type * af,
bool add_dur, bool avg_dur, bool add_mod, bool avg_mod)
{
struct affected_type *hjp;
bool found = FALSE;
for (hjp = ch->affected; !found && hjp; hjp = hjp->next) {
if (hjp->type == af->type) {
if (add_dur)
af->duration += hjp->duration;
if (avg_dur)
af->duration >>= 1;
if (add_mod)
af->modifier += hjp->modifier;
if (avg_mod)
af->modifier >>= 1;
affect_remove(ch, hjp, 1);
affect_to_char(ch, af);
found = TRUE;
}
}
if (!found)
affect_to_char(ch, af);
}
/* move a player out of a room */
void char_from_room(struct char_data * ch)
{
struct char_data *temp;
if (ch == NULL || ch->in_room == NOWHERE) {
log("SYSLOG: NULL or NOWHERE in handler.c, char_from_room");
exit(1);
}
if (FIGHTING(ch) != NULL)
stop_fighting(ch);
if (GET_EQ(ch, WEAR_LIGHT) != NULL)
if (GET_OBJ_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT)
if (GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2)) /* Light is ON */
world[ch->in_room].light--;
if (affected_by_spell(ch, SPELL_LIGHT))
world[ch->in_room].light--;
REMOVE_FROM_LIST(ch, world[ch->in_room].people, next_in_room);
ch->in_room = NOWHERE;
ch->next_in_room = NULL;
}
/* place a character in a room */
void char_to_room(struct char_data * ch, int room)
{
if (!ch || room < 0 || room > top_of_world)
log("SYSLOG: Illegal value(s) passed to char_to_room");
else {
ch->next_in_room = world[room].people;
world[room].people = ch;
ch->in_room = room;
if (GET_EQ(ch, WEAR_LIGHT))
if (GET_OBJ_TYPE(GET_EQ(ch, WEAR_LIGHT)) == ITEM_LIGHT)
if (GET_OBJ_VAL(GET_EQ(ch, WEAR_LIGHT), 2)) /* Light ON */
world[room].light++;
if (affected_by_spell(ch, SPELL_LIGHT))
world[room].light++;
}
}
#define IS_INVIS(o) IS_OBJ_STAT(o, ITEM_INVISIBLE)
/* give an object to a char */
void obj_to_char(struct obj_data * object, struct char_data * ch)
{
struct obj_data *i = NULL, *op = NULL;
int j;
if (object && ch) {
for (i = ch->carrying; i; i = i->next_content) {
if (i->item_number == object->item_number &&
!strcmp(i->description, object->description) &&
IS_INVIS(i) == IS_INVIS(object))
break;
op = i;
}
if (i) {
object->next_content = i;
if (op)
op->next_content = object;
else ch->carrying = object;
} else {
object->next_content = ch->carrying;
ch->carrying = object;
}
object->carried_by = ch;
object->in_room = NOWHERE;
IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
IS_CARRYING_N(ch)++;
/* set flag for crash-save system */
if (!IS_NPC(ch))
SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
if (GET_OBJ_TYPE(object) == ITEM_FOCUS)
apply_focus_effect(ch, object);
} else
log("SYSLOG: NULL obj or char passed to obj_to_char");
}
void old_obj_to_char(struct obj_data * object, struct char_data * ch)
{
int j;
if (object && ch) {
object->next_content = ch->carrying;
ch->carrying = object;
object->carried_by = ch;
object->in_room = NOWHERE;
IS_CARRYING_W(ch) += GET_OBJ_WEIGHT(object);
IS_CARRYING_N(ch)++;
/* set flag for crash-save system */
if (!IS_NPC(ch))
SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
if (GET_OBJ_TYPE(object) == ITEM_FOCUS)
apply_focus_effect(ch, object);
} else
log("SYSLOG: NULL obj or char passed to obj_to_char");
}
void reduce_abilities(struct char_data *vict)
{
int i;
if (vict->real_abils.mag >= 0)
return;
for (i = number(SKILL_PERCEPTION, SKILL_RESISTANCE); vict->real_abils.mag < 0;
i = number(SKILL_PERCEPTION, SKILL_RESISTANCE)) {
if (GET_SKILL(vict, i) > 0) {
vict->real_abils.mag += ability_cost(i, GET_SKILL(vict, i));
SET_SKILL(vict, i, GET_SKILL(vict, i) - 1);
vict->real_abils.mag -= ability_cost(i, GET_SKILL(vict, i));
send_to_char(vict, "Your loss in magic makes you feel less "
"skilled in %s.\r\n", spells[i]);
}
// just in case...
if ((GET_SKILL(vict, SKILL_PERCEPTION) + GET_SKILL(vict, SKILL_COMBAT_SENSE) +
GET_SKILL(vict, SKILL_REFLEXES) + GET_SKILL(vict, SKILL_KILL_HANDS) +
GET_SKILL(vict, SKILL_RESISTANCE)) < 1) {
vict->real_abils.mag = MAX(0, vict->real_abils.mag);
return;
}
}
}
void obj_to_cyberware(struct obj_data * object, struct char_data * ch)
{
int temp;
if (object && ch) {
if (GET_OBJ_TYPE(object) != ITEM_CYBERWARE) {
log("Non-cyberware object type passed to obj_to_bioware.");
return;
}
object->next_content = ch->cyberware;
ch->cyberware = object;
object->carried_by = ch;
object->in_room = NOWHERE;
if (!IS_NPC(ch))
SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
ch->real_abils.ess -= GET_TOTEM(ch) == TOTEM_EAGLE ?
GET_OBJ_VAL(object, 1) << 1 :
GET_OBJ_VAL(object, 1);
if (GET_TRADITION(ch) == TRAD_ADEPT) {
ch->real_abils.mag -= GET_TOTEM(ch) == TOTEM_EAGLE ?
GET_OBJ_VAL(object, 1) << 1 :
GET_OBJ_VAL(object, 1);
if (ch->real_abils.mag < 0)
reduce_abilities(ch);
} else ch->real_abils.mag = (int)(ch->real_abils.ess / 100) * 100;
if (GET_OBJ_VAL(object, 4) != 1)
object->obj_flags.value[4] = 1;
for (temp = 0; temp < MAX_OBJ_AFFECT; temp++)
affect_modify(ch, object->affected[temp].location,
object->affected[temp].modifier,
object->obj_flags.bitvector, TRUE);
affect_total(ch);
} else log("SYSLOG: NULL obj or char passed to obj_to_cyberware");
}
void obj_to_bioware(struct obj_data * object, struct char_data * ch)
{
int temp;
if (object && ch) {
if (GET_OBJ_TYPE(object) != ITEM_BIOWARE) {
log("Non-bioware object type passed to obj_to_bioware.");
return;
}
object->next_content = ch->bioware;
ch->bioware = object;
object->carried_by = ch;
object->in_room = NOWHERE;
if (!IS_NPC(ch))
SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
GET_INDEX(ch) -= GET_OBJ_VAL(object, 1);
if (GET_OBJ_VAL(object, 4) != 1)
object->obj_flags.value[4] = 1;
if (GET_OBJ_VAL(object, 2) != 4 || GET_OBJ_VAL(object, 5) > 0)
for (temp = 0; temp < MAX_OBJ_AFFECT; temp++)
affect_modify(ch, object->affected[temp].location,
object->affected[temp].modifier,
object->obj_flags.bitvector, TRUE);
affect_total(ch);
} else log("SYSLOG: NULL obj or char passed to obj_to_bioware");
}
void obj_from_bioware(struct obj_data *bio)
{
struct obj_data *temp;
int i;
if (bio == NULL) {
log("SYSLOG: NULL object passed to obj_from_bioware");
return;
}
if (!IS_NPC(bio->carried_by))
SET_BIT(PLR_FLAGS(bio->carried_by), PLR_CRASH);
GET_INDEX(bio->carried_by) += GET_OBJ_VAL(bio, 1);
if (GET_OBJ_VAL(bio, 2) == 4 && GET_OBJ_VAL(bio, 5) < 1)
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(bio->carried_by, bio->affected[i].location,
bio->affected[i].modifier,
bio->obj_flags.bitvector, FALSE);
affect_total(bio->carried_by);
REMOVE_FROM_LIST(bio, bio->carried_by->bioware, next_content);
bio->carried_by = NULL;
bio->next_content = NULL;
}
/* take an object from a char */
void obj_from_char(struct obj_data * object)
{
struct obj_data *temp;
int i;
if (object == NULL) {
log("SYSLOG: NULL object passed to obj_from_char");
return;
}
REMOVE_FROM_LIST(object, object->carried_by->carrying, next_content);
/* set flag for crash-save system */
if (!IS_NPC(object->carried_by))
SET_BIT(PLR_FLAGS(object->carried_by), PLR_CRASH);
if (GET_OBJ_TYPE(object) == ITEM_FOCUS)
remove_focus_effect(object->carried_by, object);
IS_CARRYING_W(object->carried_by) -= GET_OBJ_WEIGHT(object);
IS_CARRYING_N(object->carried_by)--;
object->carried_by = NULL;
object->next_content = NULL;
}
/* Removes a piece of cyberware from the cyberware list */
void obj_from_cyberware(struct obj_data * cyber)
{
struct obj_data *temp;
int i;
if (cyber == NULL) {
log("SYSLOG: NULL object passed to obj_from_cyberware");
return;
}
/* set flag for crash-save system */
if (!IS_NPC(cyber->carried_by))
SET_BIT(PLR_FLAGS(cyber->carried_by), PLR_CRASH);
cyber->carried_by->real_abils.ess += GET_OBJ_VAL(cyber, 1);
if (GET_TRADITION(cyber->carried_by) == TRAD_ADEPT)
cyber->carried_by->real_abils.mag += GET_OBJ_VAL(cyber, 1);
else if (GET_TRADITION(cyber->carried_by) == TRAD_HERMETIC ||
GET_TRADITION(cyber->carried_by) == TRAD_SHAMANIC)
cyber->carried_by->real_abils.mag =
(int)(cyber->carried_by->real_abils.ess / 100) * 100;
for (i = 0; i < MAX_OBJ_AFFECT; i++)
affect_modify(cyber->carried_by, cyber->affected[i].location,
cyber->affected[i].modifier,
cyber->obj_flags.bitvector, FALSE);
affect_total(cyber->carried_by);
REMOVE_FROM_LIST(cyber, cyber->carried_by->cyberware, next_content);
cyber->carried_by = NULL;
cyber->next_content = NULL;
}
/* Return the effect of a piece of armor in position eq_pos */
int apply_ballistic(struct char_data * ch, int eq_pos)
{
assert(GET_EQ(ch, eq_pos));
if (!(GET_OBJ_TYPE(GET_EQ(ch, eq_pos)) == ITEM_ARMOR))
return 0;
return (GET_OBJ_VAL(GET_EQ(ch, eq_pos), 0));
}
int apply_impact(struct char_data * ch, int eq_pos)
{
assert(GET_EQ(ch, eq_pos));
if (!(GET_OBJ_TYPE(GET_EQ(ch, eq_pos)) == ITEM_ARMOR))
return 0;
return (GET_OBJ_VAL(GET_EQ(ch, eq_pos), 1));
}
void equip_char(struct char_data * ch, struct obj_data * obj, int pos)
{
int j, maxb = 0, maxi = 0;
int invalid_class(struct char_data *ch, struct obj_data *obj);
assert(pos >= 0 && pos < NUM_WEARS);
if (IS_NPC(ch) && pos == WEAR_WIELD) {
if (!GET_EQ(ch, WEAR_WIELD))
GET_WIELDED(ch, 0) = 1;
else if (!GET_EQ(ch, WEAR_HOLD) && can_wield_both(ch, GET_EQ(ch, WEAR_WIELD), obj)) {
pos = WEAR_HOLD;
GET_WIELDED(ch, 1) = 1;
} else {
sprintf(buf, "SYSLOG: trying to equip invalid or third weapon: %s, %s", GET_NAME(ch),
obj->short_description);
log(buf);
return;
}
} else if (GET_EQ(ch, pos)) {
sprintf(buf, "SYSLOG: Char is already equipped: %s, %s", GET_NAME(ch), obj->short_description);
log(buf);
return;
}
if (obj->carried_by) {
log("SYSLOG: EQUIP: Obj is carried_by when equip.");
return;
}
if (obj->in_room != NOWHERE) {
log("SYSLOG: EQUIP: Obj is in_room when equip.");
return;
}
if (invalid_class(ch, obj)) {
act("You are zapped by $p and instantly let go of it.", FALSE, ch, obj, 0, TO_CHAR);
act("$n is zapped by $p and instantly lets go of it.", FALSE, ch, obj, 0, TO_ROOM);
obj_to_char(obj, ch); /* changed to drop in inventory instead of
* ground */
return;
}
GET_EQ(ch, pos) = obj;
obj->worn_by = ch;
obj->worn_on = pos;
if (GET_OBJ_TYPE(obj) == ITEM_ARMOR) {
for (j = 0; j < NUM_WEARS - 1; j++)
if (GET_EQ(ch, j) && j != pos) {
if (apply_ballistic(ch, j) > maxb)
maxb = apply_ballistic(ch, j);
if (apply_impact(ch, j) > maxi)
maxi = apply_impact(ch, j);
}
if (apply_ballistic(ch, pos) > maxb)
GET_BALLISTIC(ch) += apply_ballistic(ch, pos) - maxb;
if (apply_impact(ch, pos) > maxi)
GET_IMPACT(ch) += apply_impact(ch, pos) - maxi;
}
if (ch->in_room != NOWHERE) {
if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT)
if (GET_OBJ_VAL(obj, 2)) /* if light is ON */
world[ch->in_room].light++;
}
// changed for autoequiping
//else
//log("SYSLOG: ch->in_room = NOWHERE when equipping char.");
// if (GET_OBJ_TYPE(obj) != ITEM_FOCUS)
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, obj->affected[j].location, obj->affected[j].modifier, obj->obj_flags.bitvector, TRUE);
affect_total(ch);
}
struct obj_data *unequip_char(struct char_data * ch, int pos)
{
int j, maxb = 0, maxi = 0;
struct obj_data *obj, *tempobj;
bool natural = TRUE;
if (pos < 0 || pos >= NUM_WEARS) {
sprintf(buf, "SYSERR: pos < 0 || pos >= NUM_WEARS, %s - %d", GET_NAME(ch), pos);
log(buf);
}
assert(pos >= 0 && pos < NUM_WEARS);
if (!GET_EQ(ch, pos)) {
sprintf(buf, "SYSERR: Trying to remove non-existent item from %s at %d", GET_NAME(ch), pos);
log(buf);
}
assert(GET_EQ(ch, pos));
obj = GET_EQ(ch, pos);
obj->worn_by = NULL;
obj->worn_on = -1;
if (GET_OBJ_TYPE(obj) == ITEM_ARMOR) {
for (j = 0; j < NUM_WEARS; j++)
if (GET_EQ(ch, j) && j != pos) {
if (apply_ballistic(ch, j) > maxb)
maxb = apply_ballistic(ch, j);
if (apply_impact(ch, j) > maxi)
maxi = apply_impact(ch, j);
}
if (apply_ballistic(ch, pos) > maxb)
GET_BALLISTIC(ch) -= apply_ballistic(ch, pos) - maxb;
if (apply_impact(ch, pos) > maxi)
GET_IMPACT(ch) -= apply_impact(ch, pos) - maxi;
}
if (ch->in_room != NOWHERE) {
if (pos == WEAR_LIGHT && GET_OBJ_TYPE(obj) == ITEM_LIGHT)
if (GET_OBJ_VAL(obj, 2)) /* if light is ON */
world[ch->in_room].light--;
}
if (pos == WEAR_HOLD || pos == WEAR_WIELD)
GET_WIELDED(ch, pos - WEAR_WIELD) = 0;
// these were removed because of the autoequip routines
//else
//log("SYSLOG: ch->in_room = NOWHERE when equipping char.");
GET_EQ(ch, pos) = NULL;
// if (GET_OBJ_TYPE(obj) != ITEM_FOCUS)
for (j = 0; j < MAX_OBJ_AFFECT; j++)
affect_modify(ch, obj->affected[j].location, obj->affected[j].modifier, obj->obj_flags.bitvector, FALSE);
/* Give natural vision back */
for ( tempobj = ch->cyberware; tempobj != NULL; tempobj = tempobj->next_content )
{
if ( !str_cmp(tempobj->short_description,"thermographic vision")
|| !str_cmp(tempobj->short_description,"low-light vision")
|| !str_cmp(tempobj->short_description,"flare compensation")
|| !str_cmp(tempobj->short_description,"optical magnification")
|| !str_cmp(tempobj->short_description,"electrical magnification") )
natural = FALSE;
}
if ( natural )
{
switch (GET_RACE(ch))
{
case RACE_ELF:
case RACE_ORK: SET_BIT(ch->char_specials.saved.affected_by, AFF_LOW_LIGHT);
break;
case RACE_TROLL:
case RACE_DWARF: SET_BIT(ch->char_specials.saved.affected_by, AFF_INFRAVISION);
break;
default: break;
}
}
affect_total(ch);
return (obj);
}
int get_number(char **name)
{
int i;
char *ppos;
char number[MAX_INPUT_LENGTH];
*number = '\0';
if ((ppos = strchr((const char *)*name, '.'))) {
*ppos++ = '\0';
strcpy(number, *name);
strcpy(*name, ppos);
for (i = 0; *(number + i); i++)
if (!isdigit(*(number + i)))
return 0;
return (atoi(number));
}
return 1;
}
/* Search a given list for an object number, and return a ptr to that obj */
struct obj_data *get_obj_in_list_num(int num, struct obj_data * list)
{
struct obj_data *i;
for (i = list; i; i = i->next_content)
if (GET_OBJ_RNUM(i) == num)
return i;
return NULL;
}
int from_ip_zone(int vnum)
{
int counter;
if (vnum == -1) // obj made using create_obj, like mail and corpses
return 0;
else if (vnum < 0 || vnum > (zone_table[top_of_zone_table].top))
return 1;
for (counter = 0; counter <= top_of_zone_table; counter++)
if (!(zone_table[counter].connected) && vnum >= (zone_table[counter].number * 100) &&
vnum <= zone_table[counter].top)
return 1;
return 0;
}
/* search the entire world for an object number, and return a pointer */
//struct obj_data *get_obj_num(int nr)
//{
// struct obj_data *i;
// for (i = object_list; i; i = i->next)
// if (GET_OBJ_RNUM(i) == nr)
// return i;
// return NULL;
//}
/* search a room for a char, and return a pointer if found.. */
struct char_data *get_char_room(char *name, int room)
{
struct char_data *i;
int j = 0, number;
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
strcpy(tmp, name);
if (!(number = get_number(&tmp)))
return NULL;
for (i = world[room].people; i && (j <= number); i = i->next_in_room)
if (isname(tmp, i->player.name))
if (++j == number)
return i;
return NULL;
}
/* search all over the world for a char num, and return a pointer if found */
struct char_data *get_char_num(int nr)
{
struct char_data *i;
for (i = character_list; i; i = i->next)
if (GET_MOB_RNUM(i) == nr)
return i;
return NULL;
}
/* put an object in a room */
void obj_to_room(struct obj_data * object, int room)
{
struct obj_data *i = NULL, *op = NULL;
if (!object || room < 0 || room > top_of_world)
log("SYSLOG: Illegal value(s) passed to obj_to_room");
else {
for (i = world[room].contents; i; i = i->next_content) {
if (i->item_number == object->item_number &&
!strcmp(i->description, object->description) &&
IS_INVIS(i) == IS_INVIS(object))
break;
op = i;
}
if (i) {
object->next_content = i;
if (op)
op->next_content = object;
else
world[room].contents = object;
} else {
object->next_content = world[room].contents;
world[room].contents = object;
}
object->in_room = room;
object->carried_by = NULL;
if (ROOM_FLAGGED(room, ROOM_HOUSE))
SET_BIT(ROOM_FLAGS(room), ROOM_HOUSE_CRASH);
}
}
/* Take an object from a room */
void obj_from_room(struct obj_data * object)
{
struct obj_data *temp;
if (!object || object->in_room == NOWHERE) {
log("SYSLOG: NULL object or obj not in a room passed to obj_from_room");
return;
}
REMOVE_FROM_LIST(object, world[object->in_room].contents, next_content);
if (ROOM_FLAGGED(object->in_room, ROOM_HOUSE))
SET_BIT(ROOM_FLAGS(object->in_room), ROOM_HOUSE_CRASH);
object->in_room = NOWHERE;
object->next_content = NULL;
}
/* put an object in an object (quaint) */
void obj_to_obj(struct obj_data * obj, struct obj_data * obj_to)
{
struct obj_data *tmp_obj;
struct obj_data *i = NULL, *op = NULL;
for (i = obj_to->contains; i; i = i->next_content) {
if (i->item_number == obj->item_number &&
!strcmp(i->description, obj->description) &&
IS_INVIS(i) == IS_INVIS(obj))
break;
op=i;
}
if (i) {
obj->next_content = i;
if (op)
op->next_content = obj;
else obj_to->contains = obj;
} else {
obj->next_content = obj_to->contains;
obj_to->contains = obj;
}
obj->in_obj = obj_to;
for (tmp_obj = obj->in_obj; tmp_obj->in_obj; tmp_obj = tmp_obj->in_obj)
GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
/* top level object. Subtract weight from inventory if necessary. */
GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
if (tmp_obj->carried_by)
IS_CARRYING_W(tmp_obj->carried_by) += GET_OBJ_WEIGHT(obj);
}
/* remove an object from an object */
void obj_from_obj(struct obj_data * obj)
{
struct obj_data *temp, *obj_from;
if (obj->in_obj == NULL) {
log("error (handler.c): trying to illegally extract obj from obj");
return;
}
obj_from = obj->in_obj;
REMOVE_FROM_LIST(obj, obj_from->contains, next_content);
/* Subtract weight from containers container */
for (temp = obj->in_obj; temp->in_obj; temp = temp->in_obj)
GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj);
/* Subtract weight from char that carries the object */
GET_OBJ_WEIGHT(temp) -= GET_OBJ_WEIGHT(obj);
if (temp->carried_by)
IS_CARRYING_W(temp->carried_by) -= GET_OBJ_WEIGHT(obj);
obj->in_obj = NULL;
obj->next_content = NULL;
}
/* Set all carried_by to point to new owner */
void object_list_new_owner(struct obj_data * list, struct char_data * ch)
{
if (list) {
object_list_new_owner(list->contains, ch);
object_list_new_owner(list->next_content, ch);
list->carried_by = ch;
}
}
/* Extract an object from the world */
void extract_obj(struct obj_data * obj)
{
bool set = FALSE;
if (obj->worn_by != NULL)
if (unequip_char(obj->worn_by, obj->worn_on) != obj)
log("SYSLOG: Inconsistent worn_by and worn_on pointers!!");
if (obj->in_room != NOWHERE) {
obj_from_room(obj);
set = TRUE;
}
if (obj->carried_by) {
obj_from_char(obj);
if (set)
log("SYSLOG: More than one list pointer set!");
set = TRUE;
}
if (obj->in_obj) {
obj_from_obj(obj);
if (set)
log("SYSLOG: More than one list pointer set!");
set = TRUE;
}
/* Get rid of the contents of the object, as well. */
while (obj->contains)
extract_obj(obj->contains);
if (!ObjList.Remove(obj)) {
sprintf(buf, "ObjList.Remove returned FALSE! (%d)", GET_OBJ_VNUM(obj));
log(buf);
}
if (GET_OBJ_RNUM(obj) >= 0)
(obj_index[GET_OBJ_RNUM(obj)].number)--;
Mem->DeleteObject(obj);
}
/* Extract a ch completely from the world, and leave his stuff behind */
void extract_char(struct char_data * ch)
{
struct char_data *k, *temp;
struct descriptor_data *t_desc;
struct obj_data *obj, *next;
int i, wield[2];
extern struct char_data *combat_list;
ACMD(do_return);
void die_follower(struct char_data * ch);
if (!IS_NPC(ch) && !ch->desc) {
for (t_desc = descriptor_list; t_desc; t_desc = t_desc->next)
if (t_desc->original == ch)
do_return(t_desc->character, "", 0, 0);
}
if (ch->in_room == NOWHERE) {
log("SYSLOG: NOWHERE extracting char. (handler.c, extract_char)");
exit(1);
}
if (ch->followers || ch->master)
die_follower(ch);
/* Forget snooping, if applicable */
if (ch->desc) {
if (ch->desc->snooping) {
ch->desc->snooping->snoop_by = NULL;
ch->desc->snooping = NULL;
}
if (ch->desc->snoop_by) {
SEND_TO_Q("Your victim is no longer among us.\r\n", ch->desc->snoop_by);
ch->desc->snoop_by->snooping = NULL;
ch->desc->snoop_by = NULL;
}
}
/* transfer objects to room, if any */
while (ch->carrying) {
obj = ch->carrying;
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
}
/* extract all cyberware from NPC's since it can't be reused */
if (IS_NPC(ch)) {
for (obj = ch->cyberware; obj; obj = next) {
next = obj->next_content;
obj_from_cyberware(obj);
extract_obj(obj);
}
for (obj = ch->bioware; obj; obj = next) {
next = obj->next_content;
obj_from_bioware(obj);
extract_obj(obj);
}
}
wield[0] = GET_WIELDED(ch, 0);
wield[1] = GET_WIELDED(ch, 1);
/* transfer equipment to room, if any */
for (i = 0; i < NUM_WEARS; i++)
if (GET_EQ(ch, i))
obj_to_room(unequip_char(ch, i), ch->in_room);
if (FIGHTING(ch))
stop_fighting(ch);
for (k = combat_list; k; k = temp) {
temp = k->next_fighting;
if (FIGHTING(k) == ch)
stop_fighting(k);
}
while (ch->affected)
affect_remove(ch, ch->affected, 0);
char_from_room(ch);
/* pull the char from the list */
REMOVE_FROM_LIST(ch, character_list, next);
if (ch->desc && ch->desc->original)
do_return(ch, "", 0, 0);
if (!IS_NPC(ch)) {
GET_WIELDED(ch, 0) = wield[0];
GET_WIELDED(ch, 1) = wield[1];
REMOVE_BIT(PLR_FLAGS(ch), PLR_MATRIX | PLR_PROJECT | PLR_SWITCHED |
PLR_WRITING | PLR_MAILING | PLR_EDITING |
PLR_SPELL_CREATE | PLR_CUSTOMIZE);
save_char(ch, GET_LOADROOM(ch));
save_etext(ch);
write_spells(ch);
Crash_delete_crashfile(ch);
if (ch->desc) {
if (STATE(ch->desc) == CON_QMENU)
SEND_TO_Q(QMENU, ch->desc);
else {
STATE(ch->desc) = CON_MENU;
SEND_TO_Q(MENU, ch->desc);
}
}
} else {
if (GET_MOB_RNUM(ch) > -1) /* if mobile */
mob_index[GET_MOB_RNUM(ch)].number--;
clearMemory(ch); /* Only NPC's can have memory */
Mem->DeleteCh(ch);
}
}
/* ***********************************************************************
Here follows high-level versions of some earlier routines, ie functions
which incorporate the actual player-data.
*********************************************************************** */
struct char_data *get_player_vis(struct char_data * ch, char *name, int inroom)
{
struct char_data *i;
for (i = character_list; i; i = i->next)
if (!IS_NPC(i) && (!inroom || i->in_room == ch->in_room) &&
!str_cmp(i->player.name, name) && CAN_SEE(ch, i) &&
!(isname("neuromancer", GET_NAME(i)) && GET_REAL_LEVEL(ch) < LVL_OWNER))
return i;
return NULL;
}
struct char_data *get_char_room_vis(struct char_data * ch, char *name)
{
struct char_data *i;
int j = 0, number;
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
/* JE 7/18/94 :-) :-) */
if (!str_cmp(name, "self") || !str_cmp(name, "me"))
return ch;
/* 0.<name> means PC with name */
strcpy(tmp, name);
if (!(number = get_number(&tmp)))
return get_player_vis(ch, tmp, 1);
for (i = world[ch->in_room].people; i && j <= number; i = i->next_in_room)
if (isname(tmp, i->player.name) && CAN_SEE(ch, i))
if (++j == number)
return i;
return NULL;
}
struct char_data *get_char_vis(struct char_data * ch, char *name)
{
struct char_data *i;
int j = 0, number;
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
/* check the room first */
if ((i = get_char_room_vis(ch, name)) != NULL)
return i;
strcpy(tmp, name);
if (!(number = get_number(&tmp)))
return get_player_vis(ch, tmp, 0);
for (i = character_list; i && (j <= number); i = i->next)
if (isname(tmp, i->player.name) && CAN_SEE(ch, i))
if (++j == number)
return i;
return NULL;
}
struct obj_data *get_obj_in_list_vis(struct char_data * ch, char *name, struct obj_data * list)
{
struct obj_data *i;
int j = 0, number;
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
strcpy(tmp, name);
if (!(number = get_number(&tmp)))
return NULL;
for (i = list; i && (j <= number); i = i->next_content)
if (isname(tmp, i->name))
if (CAN_SEE_OBJ(ch, i))
if (++j == number)
return i;
return NULL;
}
/* search the entire world for an object, and return a pointer */
struct obj_data *get_obj_vis(struct char_data * ch, char *name)
{
struct obj_data *i;
int j = 0, number;
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
/* scan items carried */
if ((i = get_obj_in_list_vis(ch, name, ch->carrying)))
return i;
/* scan room */
if ((i = get_obj_in_list_vis(ch, name, world[ch->in_room].contents)))
return i;
strcpy(tmp, name);
if (!(number = get_number(&tmp)))
return NULL;
// return find_obj(ch, tmp, number);
return ObjList.FindObj(ch, tmp, number);
return NULL;
}
struct obj_data *get_object_in_equip_vis(struct char_data * ch,
char *arg, struct obj_data * equipment[], int *j)
{
char tmpname[MAX_INPUT_LENGTH];
char *tmp = tmpname;
int i = 0, number;
strcpy(tmp, arg);
if (!(number = get_number(&tmp)))
return NULL;
for ((*j) = 0; (*j) < NUM_WEARS && i <= number; (*j)++)
if (equipment[(*j)])
if (CAN_SEE_OBJ(ch, equipment[(*j)]))
if (isname(tmp, equipment[(*j)]->name))
if (++i == number)
return (equipment[(*j)]);
return NULL;
}
int belongs_to(struct char_data *ch, struct obj_data *obj)
{
if (GET_OBJ_TYPE(obj) == ITEM_MONEY && GET_OBJ_VAL(obj, 1) == 1 &&
(IS_NPC(ch) ? GET_OBJ_VAL(obj, 3) == 0 : GET_OBJ_VAL(obj, 3) == 1) &&
GET_OBJ_VAL(obj, 4) == (IS_NPC(ch) ? ch->nr : GET_IDNUM(ch)))
return 1;
else return 0;
}
struct obj_data *get_first_credstick(struct char_data *ch, char *arg)
{
struct obj_data *obj;
int i;
for (obj = ch->carrying; obj; obj = obj->next_content)
if (belongs_to(ch, obj) && isname(arg, obj->name))
return obj;
for (i = 0; i < NUM_WEARS - 1; i++)
if (GET_EQ(ch, i) && belongs_to(ch, GET_EQ(ch, i)) && isname(arg, GET_EQ(ch, i)->name))
return GET_EQ(ch, i);
return NULL;
}
struct obj_data *create_credstick(struct char_data *ch, int amount)
{
struct obj_data *obj;
int num;
if (amount <= 0) {
log("SYSLOG: Try to create negative or 0 nuyen.");
return NULL;
} else if (!IS_NPC(ch)) {
log("SYSLOG: Creating a credstick for a PC corpse.");
return NULL;
}
if (amount < 2500)
num = 100; // plastic credstick
else if (amount < 10000)
num = 101; // steel credstick
else if (amount < 50000)
num = 102; // silver credstick
else if (amount < 150000)
num = 103; // titanium credstick
else if (amount < 500000)
num = 104; // platinum credstick
else num = 105; // emerald credstick
obj = read_object(num, VIRTUAL);
GET_OBJ_VAL(obj, 0) = amount;
GET_OBJ_VAL(obj, 3) = 0;
GET_OBJ_VAL(obj, 4) = ch->nr;
if (num < 102)
GET_OBJ_VAL(obj, 5) = (number(1, 9) * 100000) + (number(0, 9) * 10000) +
(number(0, 9) * 1000) + (number(0, 9) * 100) +
(number(0, 9) * 10) + number(0, 9);
return obj;
}
struct obj_data *create_nuyen(int amount)
{
struct obj_data *obj;
if (amount <= 0) {
log("SYSLOG: Try to create negative or 0 nuyen.");
return NULL;
}
obj = read_object(110, VIRTUAL);
GET_OBJ_VAL(obj, 0) = amount;
return obj;
}
int find_skill_num(char *name)
{
int index = 0, ok;
char *temp, *temp2;
char first[256], first2[256];
while (*spells[++index] != '\n') {
if (is_abbrev(name, spells[index]))
return index;
ok = 1;
temp = any_one_arg((char *)spells[index], first);
temp2 = any_one_arg(name, first2);
while (*first && *first2 && ok) {
if (!is_abbrev(first2, first))
ok = 0;
temp = any_one_arg(temp, first);
temp2 = any_one_arg(temp2, first2);
}
if (ok && !*first2)
return index;
}
return -1;
}
/* Generic Find, designed to find any object/character */
/* Calling : */
/* *arg is the sting containing the string to be searched for. */
/* This string doesn't have to be a single word, the routine */
/* extracts the next word itself. */
/* bitv.. All those bits that you want to "search through". */
/* Bit found will be result of the function */
/* *ch This is the person that is trying to "find" */
/* **tar_ch Will be NULL if no character was found, otherwise points */
/* **tar_obj Will be NULL if no object was found, otherwise points */
/* */
/* The routine returns a pointer to the next word in *arg (just like the */
/* one_argument routine). */
int generic_find(char *arg, int bitvector, struct char_data * ch,
struct char_data ** tar_ch, struct obj_data ** tar_obj)
{
int i, found;
char name[256];
one_argument(arg, name);
if (!*name)
return (0);
*tar_ch = NULL;
*tar_obj = NULL;
if (IS_SET(bitvector, FIND_CHAR_ROOM)) { /* Find person in room */
if ((*tar_ch = get_char_room_vis(ch, name))) {
return (FIND_CHAR_ROOM);
}
}
if (IS_SET(bitvector, FIND_CHAR_WORLD)) {
if ((*tar_ch = get_char_vis(ch, name))) {
return (FIND_CHAR_WORLD);
}
}
if (IS_SET(bitvector, FIND_OBJ_EQUIP)) {
if ((*tar_obj = get_object_in_equip_vis(ch, name, ch->equipment, &i)))
return (FIND_OBJ_EQUIP);
}
if (IS_SET(bitvector, FIND_OBJ_INV)) {
if ((*tar_obj = get_obj_in_list_vis(ch, name, ch->carrying))) {
return (FIND_OBJ_INV);
}
}
if (IS_SET(bitvector, FIND_OBJ_ROOM)) {
if ((*tar_obj = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))) {
return (FIND_OBJ_ROOM);
}
}
if (IS_SET(bitvector, FIND_OBJ_WORLD)) {
if ((*tar_obj = get_obj_vis(ch, name))) {
return (FIND_OBJ_WORLD);
}
}
return (0);
}
/* a function to scan for "all" or "all.x" */
int find_all_dots(char *arg)
{
if (!strcmp(arg, "all"))
return FIND_ALL;
else if (!strncmp(arg, "all.", 4)) {
strcpy(arg, arg + 4);
return FIND_ALLDOT;
} else
return FIND_INDIV;
}