/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Dystopia Mud improvements copyright (C) 2000, 2001 by Brian Graversen *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
AFFECT_DATA *affect_free;
/*
* Local functions.
*/
/* returns race number */
int race_lookup (const char *name)
{
int race;
for ( race = 0; race_table[race].name != NULL; race++)
{
if (LOWER(name[0]) == LOWER(race_table[race].name[0])
&& !str_prefix( name,race_table[race].name))
return race;
}
return 0;
}
/*
* Retrieve a character's trusted level for permission checking.
*/
int get_trust(CHAR_DATA * ch)
{
if (ch->trust != 0)
return ch->trust;
if (IS_NPC(ch) && ch->level >= LEVEL_HERO)
return LEVEL_HERO - 1;
else
return ch->level;
}
/*
* Retrieve a character's age.
*/
int get_age(CHAR_DATA * ch)
{
return 17 + (ch->played + (int) (current_time - ch->logon)) / 7200;
}
/*
* Retrieve character's current strength.
*/
int get_curr_str(CHAR_DATA * ch)
{
int max;
if (IS_NPC(ch))
return 13;
max = 25;
return URANGE(3, ch->pcdata->perm_str + ch->pcdata->mod_str, max);
}
/*
* Retrieve character's current intelligence.
*/
int get_curr_int(CHAR_DATA * ch)
{
int max;
if (IS_NPC(ch))
return 13;
max = 25;
return URANGE(3, ch->pcdata->perm_int + ch->pcdata->mod_int, max);
}
/*
* Retrieve character's current wisdom.
*/
int get_curr_wis(CHAR_DATA * ch)
{
int max = 25;
if (IS_NPC(ch))
return 13;
max = 25;
return URANGE(3, ch->pcdata->perm_wis + ch->pcdata->mod_wis, max);
}
/*
* Retrieve character's current dexterity.
*/
int get_curr_dex(CHAR_DATA * ch)
{
int max;
if (IS_NPC(ch))
return 13;
max = 25;
return URANGE(3, ch->pcdata->perm_dex + ch->pcdata->mod_dex, max);
}
/*
* Retrieve character's current constitution.
*/
int get_curr_con(CHAR_DATA * ch)
{
int max;
if (IS_NPC(ch))
return 13;
max = 25;
return URANGE(3, ch->pcdata->perm_con + ch->pcdata->mod_con, max);
}
/*
* Retrieve a character's carry capacity.
*/
int can_carry_n(CHAR_DATA * ch)
{
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return 100000;
return MAX_WEAR + 2 * get_curr_dex(ch) + 2000;
}
/*
* Retrieve a character's carry capacity.
*/
int can_carry_w(CHAR_DATA * ch)
{
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return 1000000;
// return str_app[get_curr_str(ch)].carry;
return 100000;
}
/*
* See if a string is one of the names of an object.
*/
bool is_name(char *str, char *namelist)
{
char name[MAX_INPUT_LENGTH], part[MAX_INPUT_LENGTH];
char *list, *string;
/* fix crash on NULL namelist */
if (namelist == NULL || namelist[0] == '\0')
return FALSE;
/* fixed to prevent is_name on "" returning TRUE */
if (str[0] == '\0')
return FALSE;
string = str;
/* we need ALL parts of string to match part of namelist */
for (;;) /* start parsing string */
{
str = one_argument(str, part);
if (part[0] == '\0')
return TRUE;
/* check to see if this is part of namelist */
list = namelist;
for (;;) /* start parsing namelist */
{
list = one_argument(list, name);
if (name[0] == '\0') /* this name was not found */
return FALSE;
if (!str_prefix(string, name))
return TRUE; /* full pattern match */
if (!str_prefix(part, name))
break;
}
}
}
bool is_full_name(const char *str, char *namelist)
{
char name[MAX_INPUT_LENGTH];
for (;;)
{
namelist = one_argument(namelist, name);
if (name[0] == '\0')
return FALSE;
if (!str_cmp(str, name))
return TRUE;
}
}
bool char_exists(bool backup, char *argument)
{
FILE *fp;
char buf[MAX_STRING_LENGTH];
bool found = FALSE;
fclose(fpReserve);
if (backup)
sprintf(buf, "%sbackup/%s", PLAYER_DIR, capitalize(argument));
else
sprintf(buf, "%s%s", PLAYER_DIR, capitalize(argument));
if ((fp = fopen(buf, "r")) != NULL)
{
found = TRUE;
fclose(fp);
}
fpReserve = fopen(NULL_FILE, "r");
return found;
}
/*
* Apply or remove an affect to a character.
*/
void affect_modify(CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd, OBJ_DATA * obj)
{
OBJ_DATA *wield;
int mod;
mod = paf->modifier;
if (fAdd)
{
SET_BIT(ch->affected_by, paf->bitvector);
}
else
{
REMOVE_BIT(ch->affected_by, paf->bitvector);
mod = 0 - mod;
}
if (IS_NPC(ch))
{
switch (paf->location)
{
default:
break;
case APPLY_NONE:
break;
case APPLY_MANA:
ch->max_mana += mod;
break;
case APPLY_HIT:
ch->max_hit += mod;
break;
case APPLY_MOVE:
ch->max_move += mod;
break;
case APPLY_AC:
ch->armor += mod;
break;
case APPLY_HITROLL:
ch->hitroll += mod;
break;
case APPLY_DAMROLL:
ch->damroll += mod;
break;
case APPLY_SAVING_PARA:
ch->saving_throw += mod;
break;
case APPLY_SAVING_ROD:
ch->saving_throw += mod;
break;
case APPLY_SAVING_PETRI:
ch->saving_throw += mod;
break;
case APPLY_SAVING_BREATH:
ch->saving_throw += mod;
break;
case APPLY_SAVING_SPELL:
ch->saving_throw += mod;
break;
case APPLY_POLY:
ch->polyaff += mod;
break;
}
return;
}
switch (paf->location)
{
default:
bug("Affect_modify: unknown location %d.", paf->location);
return;
case APPLY_NONE:
break;
case APPLY_STR:
ch->pcdata->mod_str += mod;
break;
case APPLY_DEX:
ch->pcdata->mod_dex += mod;
break;
case APPLY_INT:
ch->pcdata->mod_int += mod;
break;
case APPLY_WIS:
ch->pcdata->mod_wis += mod;
break;
case APPLY_CON:
ch->pcdata->mod_con += mod;
break;
case APPLY_SEX:
case APPLY_CLASS:
case APPLY_LEVEL:
case APPLY_AGE:
case APPLY_HEIGHT:
case APPLY_WEIGHT:
break;
case APPLY_MANA:
ch->max_mana += mod;
break;
case APPLY_HIT:
ch->max_hit += mod;
break;
case APPLY_MOVE:
ch->max_move += mod;
break;
case APPLY_GOLD:
break;
case APPLY_EXP:
break;
case APPLY_AC:
ch->armor += mod;
break;
case APPLY_HITROLL:
ch->hitroll += mod;
break;
case APPLY_DAMROLL:
ch->damroll += mod;
break;
case APPLY_SAVING_PARA:
ch->saving_throw += mod;
break;
case APPLY_SAVING_ROD:
ch->saving_throw += mod;
break;
case APPLY_SAVING_PETRI:
ch->saving_throw += mod;
break;
case APPLY_SAVING_BREATH:
ch->saving_throw += mod;
break;
case APPLY_SAVING_SPELL:
ch->saving_throw += mod;
break;
case APPLY_POLY:
ch->polyaff += mod;
break;
}
/*
* Check for weapon wielding.
* Guard against recursion (for weapons with affects).
*/
if ((wield = get_eq_char(ch, WEAR_WIELD)) != NULL && wield->item_type == ITEM_WEAPON && get_obj_weight(wield) > str_app[get_curr_str(ch)].wield)
{
static int depth;
if (depth == 0)
{
depth++;
act("You drop $p.", ch, wield, NULL, TO_CHAR);
act("$n drops $p.", ch, wield, NULL, TO_ROOM);
obj_from_char(wield);
obj_to_room(wield, ch->in_room);
depth--;
}
}
return;
}
/*
* Remove an exit from a room -Thoric
*/
void extract_exit(ROOM_INDEX_DATA * room, EXIT_DATA * pexit)
{
UNLINK(pexit, room->first_exit, room->last_exit, next, prev);
if (pexit->rexit)
pexit->rexit->rexit = NULL;
STRFREE(pexit->keyword);
STRFREE(pexit->description);
DISPOSE(pexit);
}
void affect_to_obj(OBJ_DATA * obj, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_new;
if (affect_free == NULL)
{
paf_new = alloc_perm(sizeof(*paf_new));
}
else
{
paf_new = affect_free;
affect_free = affect_free->next;
}
*paf_new = *paf;
paf_new->next = obj->affected;
obj->affected = paf_new;
return;
}
/*
* Give an affect to a char.
*/
void affect_to_char(CHAR_DATA * ch, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_new;
if (affect_free == NULL)
{
paf_new = alloc_perm(sizeof(*paf_new));
}
else
{
paf_new = affect_free;
affect_free = affect_free->next;
}
*paf_new = *paf;
paf_new->next = ch->affected;
ch->affected = paf_new;
affect_modify(ch, paf_new, TRUE, NULL);
return;
}
void alias_remove(CHAR_DATA * ch, ALIAS_DATA * ali)
{
if (IS_NPC(ch))
return;
if (ch->pcdata->alias == NULL)
{
bug("Alias_remove: no alias.", 0);
return;
}
if (ali == ch->pcdata->alias)
{
ch->pcdata->alias = ali->next;
}
else
{
ALIAS_DATA *prev;
for (prev = ch->pcdata->alias; prev; prev = prev->next)
{
if (prev->next == ali)
{
prev->next = ali->next;
break;
}
}
if (prev == NULL)
{
bug("Alias_remove: cannot find ali.", 0);
return;
}
}
ali->next = alias_free;
alias_free = ali;
return;
}
/*
* Remove an affect from a char.
*/
void affect_remove(CHAR_DATA * ch, AFFECT_DATA * paf)
{
if (ch->affected == NULL)
{
bug("Affect_remove: no affect.", 0);
return;
}
affect_modify(ch, paf, FALSE, NULL);
if (paf == ch->affected)
{
ch->affected = paf->next;
}
else
{
AFFECT_DATA *prev;
for (prev = ch->affected; prev != NULL; prev = prev->next)
{
if (prev->next == paf)
{
prev->next = paf->next;
break;
}
}
if (prev == NULL)
{
bug("Affect_remove: cannot find paf.", 0);
return;
}
}
paf->next = affect_free;
affect_free = paf;
return;
}
/*
* Strip all affects of a given sn.
*/
void affect_strip(CHAR_DATA * ch, int sn)
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
for (paf = ch->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
if (paf->type == sn)
affect_remove(ch, paf);
}
return;
}
/*
* Return true if a char is affected by a spell.
*/
bool is_affected(CHAR_DATA * ch, int sn)
{
AFFECT_DATA *paf;
for (paf = ch->affected; paf != NULL; paf = paf->next)
{
if (paf->type == sn)
return TRUE;
}
return FALSE;
}
/*
* Add or enhance an affect.
*/
void affect_join(CHAR_DATA * ch, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_old;
bool found;
found = FALSE;
for (paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next)
{
if (paf_old->type == paf->type)
{
paf->duration += paf_old->duration;
paf->modifier += paf_old->modifier;
affect_remove(ch, paf_old);
break;
}
}
affect_to_char(ch, paf);
return;
}
/*
* Move a char out of a room.
*/
void char_from_room(CHAR_DATA * ch)
{
OBJ_DATA *obj;
if (ch->in_room == NULL)
{
bug("Char_from_room: NULL.", 0);
return;
}
if ((obj = get_eq_char(ch, WEAR_WIELD)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room->light > 0)
--ch->in_room->light;
else if ((obj = get_eq_char(ch, WEAR_HOLD)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room->light > 0)
--ch->in_room->light;
if (!IS_NPC(ch) && IS_SET(ch->newbits, NEW_DARKNESS))
{
if (ch->in_room != NULL)
REMOVE_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
}
if (ch == ch->in_room->people)
{
ch->in_room->people = ch->next_in_room;
}
else
{
CHAR_DATA *prev;
for (prev = ch->in_room->people; prev; prev = prev->next_in_room)
{
if (prev->next_in_room == ch)
{
prev->next_in_room = ch->next_in_room;
break;
}
}
if (prev == NULL)
bug("Char_from_room: ch not found.", 0);
}
ch->in_room = NULL;
ch->next_in_room = NULL;
return;
}
/*
* Move a char into a room.
*/
void char_to_room(CHAR_DATA * ch, ROOM_INDEX_DATA * pRoomIndex)
{
OBJ_DATA *obj;
if (!pRoomIndex)
{
char buf[MAX_STRING_LENGTH];
sprintf(buf, "Char_to_room: %s -> NULL room! Putting char in limbo (%d)", ch->name, ROOM_VNUM_LIMBO);
bug(buf, 0);
/* This used to just return, but there was a problem with crashing
and I saw no reason not to just put the char in limbo. -Narn */
pRoomIndex = get_room_index(ROOM_VNUM_LIMBO);
}
ch->in_room = pRoomIndex;
ch->next_in_room = pRoomIndex->people;
pRoomIndex->people = ch;
if ((obj = get_eq_char(ch, WEAR_WIELD)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
++ch->in_room->light;
else if ((obj = get_eq_char(ch, WEAR_HOLD)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
++ch->in_room->light;
if (ch->loc_hp[6] > 0 && ch->in_room->blood < 1000)
ch->in_room->blood += 1;
if (!IS_NPC(ch) && IS_SET(ch->newbits, NEW_DARKNESS))
SET_BIT(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS);
return;
}
/*
* Give an obj to a char.
*/
void obj_to_char(OBJ_DATA * obj, CHAR_DATA * ch)
{
if (obj == NULL)
return;
obj->next_content = ch->carrying;
ch->carrying = obj;
obj->carried_by = ch;
obj->in_room = NULL;
obj->in_obj = NULL;
ch->carry_number += 1;
ch->carry_weight += get_obj_weight(obj);
/* Artifact stuff */
if (!IS_NPC(ch) && IS_SET(obj->quest, QUEST_ARTIFACT))
{
if (IS_SET(ch->extra, EXTRA_AFK) || IS_SET(ch->pcdata->tempflag, TEMP_ARTIFACT) || ch->level < 3 || getMight(ch) < 150)
{
bool flag = IS_SET(ch->pcdata->tempflag, TEMP_ARTIFACT);
act("You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
act("$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
if (flag)
SET_BIT(ch->pcdata->tempflag, TEMP_ARTIFACT); // got removed under obj_from_char()
}
else
{
SET_BIT(ch->pcdata->tempflag, TEMP_ARTIFACT);
}
}
return;
}
/*
* Take an obj from its character.
*/
void obj_from_char(OBJ_DATA * obj)
{
CHAR_DATA *ch;
if (obj == NULL)
return;
if ((ch = obj->carried_by) == NULL)
{
log_string("Obj_from_char: null ch.");
return;
}
if (obj->wear_loc != WEAR_NONE)
unequip_char(ch, obj);
if (ch->carrying == obj)
{
ch->carrying = obj->next_content;
}
else
{
OBJ_DATA *prev;
for (prev = ch->carrying; prev != NULL; prev = prev->next_content)
{
if (prev->next_content == obj)
{
prev->next_content = obj->next_content;
break;
}
}
if (prev == NULL)
log_string("Obj_from_char: obj not in list.");
}
obj->carried_by = NULL;
obj->next_content = NULL;
ch->carry_number -= 1;
ch->carry_weight -= get_obj_weight(obj);
/* Artifact stuff */
if (IS_SET(obj->quest, QUEST_ARTIFACT) && !IS_NPC(ch))
{
REMOVE_BIT(ch->pcdata->tempflag, TEMP_ARTIFACT);
}
return;
}
/*
* Find the ac value of an obj, including position effect.
*/
int apply_ac(OBJ_DATA * obj, int iWear)
{
if (obj->item_type != ITEM_ARMOR)
return 0;
switch (iWear)
{
case WEAR_BODY:
return 3 * obj->value[0];
case WEAR_HEAD:
return 2 * obj->value[0];
case WEAR_LEGS:
return 2 * obj->value[0];
case WEAR_FEET:
return obj->value[0];
case WEAR_HANDS:
return obj->value[0];
case WEAR_ARMS:
return obj->value[0];
case WEAR_SHIELD:
return obj->value[0];
case WEAR_FINGER_L:
return obj->value[0];
case WEAR_FINGER_R:
return obj->value[0];
case WEAR_NECK_1:
return obj->value[0];
case WEAR_NECK_2:
return obj->value[0];
case WEAR_ABOUT:
return 2 * obj->value[0];
case WEAR_WAIST:
return obj->value[0];
case WEAR_WRIST_L:
return obj->value[0];
case WEAR_WRIST_R:
return obj->value[0];
case WEAR_HOLD:
return obj->value[0];
case WEAR_FACE:
return obj->value[0];
case WEAR_SCABBARD_L:
return 0;
case WEAR_SCABBARD_R:
return 0;
}
return 0;
}
/*
* Find a piece of eq on a character.
*/
OBJ_DATA *get_eq_char(CHAR_DATA * ch, int iWear)
{
OBJ_DATA *obj;
for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
{
if (obj->wear_loc == iWear)
return obj;
}
return NULL;
}
/*
* Equip a char with an obj.
*/
void equip_char(CHAR_DATA * ch, OBJ_DATA * obj, int iWear)
{
AFFECT_DATA *paf;
int sn;
if (obj->item_type == ITEM_ARMOR)
sn = obj->value[3];
else
sn = obj->value[0] / 1000;
if ((sn == 7 || sn == 54) && !IS_GOOD(ch))
{
act("You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
act("$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
do_autosave(ch, "");
return;
}
if (sn == 139 && !IS_EVIL(ch))
{
act("You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
act("$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
do_autosave(ch, "");
return;
}
if (!IS_NPC(ch) && IS_OBJ_STAT(obj, ITEM_LOYAL))
{
if (obj->questowner != NULL && str_cmp(ch->pcdata->switchname, obj->questowner) && strlen(obj->questowner) > 1)
{
act("$p leaps from $n to the ground.", ch, obj, NULL, TO_ROOM);
act("$p leaps from you, and onto the ground.", ch, obj, NULL, TO_CHAR);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
return;
}
}
if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) || (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch)))
{
/*
* Thanks to Morgenes for the bug fix here!
*/
act("You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
act("$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
do_autosave(ch, "");
return;
}
/* zap mobiles if they try to wear relics */
if (IS_NPC(ch) && IS_SET(obj->quest, QUEST_RELIC))
{
act("You are zapped by $p and drop it.", ch, obj, NULL, TO_CHAR);
act("$n is zapped by $p and drops it.", ch, obj, NULL, TO_ROOM);
obj_from_char(obj);
obj_to_room(obj, ch->in_room);
do_autosave(ch, "");
return;
}
if (iWear == WEAR_SCABBARD_L || iWear == WEAR_SCABBARD_R)
{
obj->wear_loc = iWear;
return;
}
ch->armor -= apply_ac(obj, iWear);
obj->wear_loc = iWear;
for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next)
affect_modify(ch, paf, TRUE, obj);
for (paf = obj->affected; paf != NULL; paf = paf->next)
affect_modify(ch, paf, TRUE, obj);
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room != NULL)
++ch->in_room->light;
if (obj->wear_loc == WEAR_NONE)
{
return;
}
if (((obj->item_type == ITEM_ARMOR) && (obj->value[3] >= 1))
|| ((obj->item_type == ITEM_WEAPON) && (obj->value[0] >= 1000))
|| IS_SET(obj->quest, QUEST_ARTIFACT))
{
/* artifact bonus */
if (IS_SET(obj->quest, QUEST_ARTIFACT))
SET_BIT(ch->itemaffect, ITEMA_ARTIFACT);
if ((sn == 1) && (IS_AFFECTED(ch, AFF_BLIND)))
return;
else if ((sn == 2) && (IS_AFFECTED(ch, AFF_DETECT_INVIS)))
return;
else if ((sn == 3) && (IS_AFFECTED(ch, AFF_FLYING)))
return;
else if ((sn == 4) && (IS_AFFECTED(ch, AFF_INFRARED)))
return;
else if ((sn == 5) && (IS_AFFECTED(ch, AFF_INVISIBLE)))
return;
else if ((sn == 6) && (IS_AFFECTED(ch, AFF_PASS_DOOR)))
return;
else if ((sn == 7) && (IS_AFFECTED(ch, AFF_PROTECT)))
return;
else if ((sn == 8) && (IS_AFFECTED(ch, AFF_PROTECT_GOOD)))
return;
else if ((sn == 9) && (IS_AFFECTED(ch, AFF_SANCTUARY)))
return;
else if ((sn == 10) && (IS_AFFECTED(ch, AFF_DETECT_HIDDEN)))
return;
else if ((sn == 11) && (IS_AFFECTED(ch, AFF_SNEAK)))
return;
else if ((sn == 12) && (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD)))
return;
else if ((sn == 13) && (IS_ITEMAFF(ch, ITEMA_REGENERATE)))
return;
else if ((sn == 14) && (IS_ITEMAFF(ch, ITEMA_SPEED)))
return;
else if ((sn == 15) && (IS_ITEMAFF(ch, ITEMA_VORPAL)))
return;
else if ((sn == 16) && (IS_ITEMAFF(ch, ITEMA_RESISTANCE)))
return;
else if ((sn == 17) && (IS_ITEMAFF(ch, ITEMA_VISION)))
return;
else if ((sn == 18) && (IS_ITEMAFF(ch, ITEMA_STALKER)))
return;
else if ((sn == 19) && (IS_ITEMAFF(ch, ITEMA_VANISH)))
return;
if (sn == 1)
{
SET_BIT(ch->affected_by, AFF_BLIND);
send_to_char("You cannot see a thing!\n\r", ch);
act("$n seems to be blinded!", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 2)
{
SET_BIT(ch->affected_by, AFF_DETECT_INVIS);
send_to_char("Your eyes tingle.\n\r", ch);
act("$n's eyes flicker with light.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 3)
{
SET_BIT(ch->affected_by, AFF_FLYING);
send_to_char("Your feet rise off the ground.\n\r", ch);
act("$n's feet rise off the ground.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 4)
{
SET_BIT(ch->affected_by, AFF_INFRARED);
send_to_char("Your eyes glow red.\n\r", ch);
act("$n's eyes glow red.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 5)
{
SET_BIT(ch->affected_by, AFF_INVISIBLE);
send_to_char("You fade out of existance.\n\r", ch);
act("$n fades out of existance.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 6)
{
SET_BIT(ch->affected_by, AFF_PASS_DOOR);
send_to_char("You turn translucent.\n\r", ch);
act("$n turns translucent.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 7)
{
SET_BIT(ch->affected_by, AFF_PROTECT);
send_to_char("You are surrounded by a divine aura.\n\r", ch);
act("$n is surrounded by a divine aura.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 8)
{
SET_BIT(ch->affected_by, AFF_PROTECT_GOOD);
send_to_char("You are surrounded by an unholy aura.\n\r", ch);
act("$n is surrounded by an unholy aura.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 9)
{
SET_BIT(ch->affected_by, AFF_SANCTUARY);
send_to_char("You are surrounded by a white aura.\n\r", ch);
act("$n is surrounded by a white aura.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 10)
{
SET_BIT(ch->affected_by, AFF_DETECT_HIDDEN);
send_to_char("You awarenes improves.\n\r", ch);
act("$n eyes tingle.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 11)
{
SET_BIT(ch->affected_by, AFF_SNEAK);
send_to_char("Your footsteps stop making any sound.\n\r", ch);
act("$n's footsteps stop making any sound.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 12)
{
SET_BIT(ch->itemaffect, ITEMA_CHAOSSHIELD);
send_to_char("You are surrounded by a swirling shield of chaos.\n\r", ch);
act("$n is surrounded by a swirling shield of chaos.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 13)
{
send_to_char("You feel revived.\n\r", ch);
SET_BIT(ch->itemaffect, ITEMA_REGENERATE);
}
else if (sn == 14)
{
SET_BIT(ch->itemaffect, ITEMA_SPEED);
send_to_char("You start moving faster than the eye can follow.\n\r", ch);
act("$n starts moving faster than the eye can follow.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 15)
{
SET_BIT(ch->itemaffect, ITEMA_VORPAL);
}
else if (sn == 16)
{
SET_BIT(ch->itemaffect, ITEMA_RESISTANCE);
}
else if (sn == 17)
{
SET_BIT(ch->itemaffect, ITEMA_VISION);
send_to_char("Your eyes begin to glow bright white.\n\r", ch);
act("$n's eyes begin to glow bright white.", ch, NULL, NULL, TO_ROOM);
}
else if (sn == 18)
{
SET_BIT(ch->itemaffect, ITEMA_STALKER);
}
else if (sn == 19)
{
SET_BIT(ch->itemaffect, ITEMA_VANISH);
send_to_char("You blend into the shadows.\n\r", ch);
act("$n gradually fades into the shadows.", ch, NULL, NULL, TO_ROOM);
}
}
return;
}
/*
* Unequip a char with an obj.
*/
void unequip_char(CHAR_DATA * ch, OBJ_DATA * obj)
{
CHAR_DATA *chch;
OBJ_DATA *cObj;
AFFECT_DATA *paf;
int sn, sn2, i;
bool spell_remove = TRUE;
if (obj->wear_loc == WEAR_NONE)
{
bug("Unequip_char: already unequipped.", 0);
return;
}
if (obj->wear_loc == WEAR_SCABBARD_L || obj->wear_loc == WEAR_SCABBARD_R)
{
obj->wear_loc = -1;
return;
}
ch->armor += apply_ac(obj, obj->wear_loc);
obj->wear_loc = -1;
for (paf = obj->pIndexData->affected; paf != NULL; paf = paf->next)
affect_modify(ch, paf, FALSE, obj);
for (paf = obj->affected; paf != NULL; paf = paf->next)
affect_modify(ch, paf, FALSE, obj);
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room != NULL && ch->in_room->light > 0)
--ch->in_room->light;
if ((chch = get_char_world(ch, ch->name)) == NULL)
return;
if (chch->desc != ch->desc)
return;
if (!IS_NPC(ch) && (ch->desc != NULL && ch->desc->connected != CON_PLAYING))
return;
if (((obj->item_type == ITEM_ARMOR) && (obj->value[3] >= 1))
|| ((obj->item_type == ITEM_WEAPON) && (obj->value[0] >= 1000))
|| IS_SET(obj->quest, QUEST_ARTIFACT))
{
/* take the arti bonus */
if (IS_SET(obj->quest, QUEST_ARTIFACT))
REMOVE_BIT(ch->itemaffect, ITEMA_ARTIFACT);
if (obj->item_type == ITEM_ARMOR)
sn = obj->value[3];
else
sn = obj->value[0] / 1000;
/* checking for affects already on other pieces */
for (i = 0; i < MAX_WEAR; i++)
{
if ((cObj = get_eq_char(ch, i)) != NULL)
{
if (cObj == obj) continue;
if (cObj->item_type == ITEM_ARMOR)
sn2 = cObj->value[3];
else sn2 = cObj->value[0] / 1000;
if (sn == sn2) spell_remove = FALSE;
}
}
if (spell_remove)
{
if (IS_AFFECTED(ch, AFF_BLIND) && sn == 1)
{
REMOVE_BIT(ch->affected_by, AFF_BLIND);
send_to_char("You can see again.\n\r", ch);
act("$n seems to be able to see again.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_DETECT_INVIS) && sn == 2)
{
REMOVE_BIT(ch->affected_by, AFF_DETECT_INVIS);
send_to_char("Your eyes stop tingling.\n\r", ch);
act("$n's eyes stop flickering with light.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_FLYING) && sn == 3)
{
REMOVE_BIT(ch->affected_by, AFF_FLYING);
send_to_char("You slowly float to the ground.\n\r", ch);
act("$n slowly floats to the ground.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_INFRARED) && sn == 4)
{
REMOVE_BIT(ch->affected_by, AFF_INFRARED);
send_to_char("Your eyes stop glowing red.\n\r", ch);
act("$n's eyes stop glowing red.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_INVISIBLE) && sn == 5)
{
REMOVE_BIT(ch->affected_by, AFF_INVISIBLE);
send_to_char("You fade into existance.\n\r", ch);
act("$n fades into existance.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_PASS_DOOR) && sn == 6)
{
REMOVE_BIT(ch->affected_by, AFF_PASS_DOOR);
send_to_char("You feel solid again.\n\r", ch);
act("$n is no longer translucent.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_PROTECT) && sn == 7)
{
REMOVE_BIT(ch->affected_by, AFF_PROTECT);
send_to_char("The divine aura around you fades.\n\r", ch);
act("The divine aura around $n fades.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_PROTECT_GOOD) && sn == 8)
{
REMOVE_BIT(ch->affected_by, AFF_PROTECT_GOOD);
send_to_char("The unholy aura around you fades.\n\r", ch);
act("The unholy aura around $n fades.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_SANCTUARY) && sn == 9)
{
REMOVE_BIT(ch->affected_by, AFF_SANCTUARY);
send_to_char("The white aura around your body fades.\n\r", ch);
act("The white aura about $n's body fades.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_DETECT_HIDDEN) && sn == 10)
{
REMOVE_BIT(ch->affected_by, AFF_DETECT_HIDDEN);
send_to_char("You feel less aware of your surrondings.\n\r", ch);
act("$n eyes tingle.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_AFFECTED(ch, AFF_SNEAK) && sn == 11)
{
REMOVE_BIT(ch->affected_by, AFF_SNEAK);
send_to_char("You are no longer moving so quietly.\n\r", ch);
act("$n is no longer moving so quietly.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_ITEMAFF(ch, ITEMA_CHAOSSHIELD) && sn == 12)
{
REMOVE_BIT(ch->itemaffect, ITEMA_CHAOSSHIELD);
send_to_char("The swirling shield of chaos around you fades.\n\r", ch);
act("The swirling shield of chaos around $n fades.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_ITEMAFF(ch, ITEMA_REGENERATE) && sn == 13)
{
REMOVE_BIT(ch->itemaffect, ITEMA_REGENERATE);
}
else if (IS_ITEMAFF(ch, ITEMA_SPEED) && sn == 14)
{
REMOVE_BIT(ch->itemaffect, ITEMA_SPEED);
send_to_char("Your actions slow down to normal speed.\n\r", ch);
act("$n stops moving at supernatural speed.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_ITEMAFF(ch, ITEMA_VORPAL) && sn == 15)
{
REMOVE_BIT(ch->itemaffect, ITEMA_VORPAL);
}
else if (IS_ITEMAFF(ch, ITEMA_RESISTANCE) && sn == 16)
{
REMOVE_BIT(ch->itemaffect, ITEMA_RESISTANCE);
}
else if (IS_ITEMAFF(ch, ITEMA_VISION) && sn == 17)
{
REMOVE_BIT(ch->itemaffect, ITEMA_VISION);
send_to_char("Your eyes stop glowing bright white.\n\r", ch);
act("$n's eyes stop glowing bright white.", ch, NULL, NULL, TO_ROOM);
}
else if (IS_ITEMAFF(ch, ITEMA_STALKER) && sn == 18)
{
REMOVE_BIT(ch->itemaffect, ITEMA_STALKER);
}
else if (IS_ITEMAFF(ch, ITEMA_VANISH) && sn == 19)
{
REMOVE_BIT(ch->itemaffect, ITEMA_VANISH);
send_to_char("You emerge from the shadows.\n\r", ch);
act("$n gradually fades out of the shadows.", ch, NULL, NULL, TO_ROOM);
}
}
}
return;
}
/*
* Count occurrences of an obj in a list.
*/
int count_obj_list(OBJ_INDEX_DATA * pObjIndex, OBJ_DATA * list)
{
OBJ_DATA *obj;
int nMatch;
nMatch = 0;
for (obj = list; obj != NULL; obj = obj->next_content)
{
if (obj->pIndexData == pObjIndex)
nMatch++;
}
return nMatch;
}
/*
* Move an obj out of a room.
*/
void obj_from_room(OBJ_DATA * obj)
{
ROOM_INDEX_DATA *in_room;
if (obj == NULL)
return;
if ((in_room = obj->in_room) == NULL)
{
bug("obj_from_room: NULL.", 0);
return;
}
if (obj == in_room->contents)
{
in_room->contents = obj->next_content;
}
else
{
OBJ_DATA *prev;
for (prev = in_room->contents; prev; prev = prev->next_content)
{
if (prev->next_content == obj)
{
prev->next_content = obj->next_content;
break;
}
}
if (prev == NULL)
{
bug("Obj_from_room: obj not found.", 0);
return;
}
}
obj->in_room = NULL;
obj->next_content = NULL;
return;
}
/*
* Move an obj into a room.
*/
void obj_to_room(OBJ_DATA * obj, ROOM_INDEX_DATA * pRoomIndex)
{
if (obj == NULL)
return;
if (pRoomIndex == NULL)
return;
obj->next_content = pRoomIndex->contents;
pRoomIndex->contents = obj;
obj->in_room = pRoomIndex;
obj->carried_by = NULL;
obj->in_obj = NULL;
return;
}
/*
* Move an object into an object.
*/
void obj_to_obj(OBJ_DATA * obj, OBJ_DATA * obj_to)
{
if (obj == NULL)
return;
obj->next_content = obj_to->contains;
obj_to->contains = obj;
obj->in_obj = obj_to;
obj->in_room = NULL;
obj->carried_by = NULL;
for (; obj_to != NULL; obj_to = obj_to->in_obj)
{
if (obj_to->carried_by != NULL)
obj_to->carried_by->carry_weight += get_obj_weight(obj);
}
return;
}
/*
* Move an object out of an object.
*/
void obj_from_obj(OBJ_DATA * obj)
{
OBJ_DATA *obj_from;
if (obj == NULL)
return;
if ((obj_from = obj->in_obj) == NULL)
{
bug("Obj_from_obj: null obj_from.", 0);
return;
}
if (obj == obj_from->contains)
{
obj_from->contains = obj->next_content;
}
else
{
OBJ_DATA *prev;
for (prev = obj_from->contains; prev; prev = prev->next_content)
{
if (prev->next_content == obj)
{
prev->next_content = obj->next_content;
break;
}
}
if (prev == NULL)
{
bug("Obj_from_obj: obj not found.", 0);
return;
}
}
obj->next_content = NULL;
obj->in_obj = NULL;
for (; obj_from != NULL; obj_from = obj_from->in_obj)
{
if (obj_from->carried_by != NULL)
obj_from->carried_by->carry_weight -= get_obj_weight(obj);
}
return;
}
/*
* Extract an obj from the world.
*/
void extract_obj(OBJ_DATA * obj)
{
CHAR_DATA *ch;
OBJ_DATA *obj_content;
OBJ_DATA *obj_next;
if (obj == NULL)
return;
if (obj->item_type == ITEM_CORPSE_PC && obj->contains)
{
OBJ_DATA *t_obj, *next_obj;
for (t_obj = obj->contains; t_obj != NULL; t_obj = next_obj)
{
next_obj = t_obj->next_content;
obj_from_obj(t_obj);
if (obj->in_obj) /* in another object */
obj_to_obj(t_obj, obj->in_obj);
else if (obj->carried_by) /* carried */
obj_to_char(t_obj, obj->carried_by);
else if (obj->in_room == NULL) /* destroy it */
extract_obj(t_obj);
else /* to a room */
obj_to_room(t_obj, obj->in_room);
}
}
if (obj->in_room != NULL)
obj_from_room(obj);
else if (obj->carried_by != NULL)
obj_from_char(obj);
else if (obj->in_obj != NULL)
obj_from_obj(obj);
if ((ch = obj->chobj) != NULL && !IS_NPC(ch) && ch->pcdata->chobj == obj && IS_HEAD(ch, LOST_HEAD))
{
REMOVE_BIT(ch->loc_hp[0], LOST_HEAD);
REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
free_string(ch->morph);
ch->morph = str_dup("");
ch->hit = 1;
char_from_room(ch);
char_to_room(ch, get_room_index(ROOM_VNUM_ALTAR));
ch->pcdata->chobj = NULL;
obj->chobj = NULL;
send_to_char("You have been KILLED!!\n\r", ch);
do_look(ch, "auto");
ch->position = POS_RESTING;
}
else if ((ch = obj->chobj) != NULL && !IS_NPC(ch) && ch->pcdata->chobj == obj && (IS_EXTRA(ch, EXTRA_OSWITCH) || ch->pcdata->obj_vnum != 0))
{
if (ch->pcdata->obj_vnum != 0)
{
send_to_char("You have been destroyed!\n\r", ch);
ch->pcdata->chobj = NULL;
obj->chobj = NULL;
}
else
{
REMOVE_BIT(ch->extra, EXTRA_OSWITCH);
REMOVE_BIT(ch->affected_by, AFF_POLYMORPH);
free_string(ch->morph);
ch->morph = str_dup("");
char_from_room(ch);
char_to_room(ch, get_room_index(ROOM_VNUM_ALTAR));
ch->pcdata->chobj = NULL;
obj->chobj = NULL;
send_to_char("You return to your body.\n\r", ch);
}
}
else if (obj->chobj != NULL)
{
if (!IS_NPC(obj->chobj))
obj->chobj->pcdata->chobj = NULL;
obj->chobj = NULL;
bug("Extract_obj: obj %d chobj invalid.", obj->pIndexData->vnum);
}
for (obj_content = obj->contains; obj_content; obj_content = obj_next)
{
obj_next = obj_content->next_content;
if (obj->contains != NULL)
extract_obj(obj->contains);
}
if (object_list == obj)
{
object_list = obj->next;
}
else
{
OBJ_DATA *prev;
for (prev = object_list; prev != NULL; prev = prev->next)
{
if (prev->next == obj)
{
prev->next = obj->next;
break;
}
}
if (prev == NULL)
{
bug("Extract_obj: obj %d not found.", obj->pIndexData->vnum);
return;
}
}
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
for (paf = obj->affected; paf != NULL; paf = paf_next)
{
paf_next = paf->next;
paf->next = affect_free;
affect_free = paf;
}
}
{
EXTRA_DESCR_DATA *ed;
EXTRA_DESCR_DATA *ed_next;
for (ed = obj->extra_descr; ed != NULL; ed = ed_next)
{
ed_next = ed->next;
free_string(ed->description);
free_string(ed->keyword);
ed->next = extra_descr_free;
extra_descr_free = ed;
}
}
free_string(obj->name);
free_string(obj->description);
free_string(obj->short_descr);
if (obj->questmaker != NULL)
free_string(obj->questmaker);
if (obj->questowner != NULL)
free_string(obj->questowner);
--obj->pIndexData->count;
obj->next = obj_free;
obj_free = obj;
return;
}
/*
* Extract a char from the world.
*/
void extract_char(CHAR_DATA * ch, bool fPull)
{
CHAR_DATA *wch;
CHAR_DATA *familiar;
// CHAR_DATA *wizard;
OBJ_DATA *obj;
OBJ_DATA *obj_next;
if (ch == NULL)
return;
if (ch->in_room == NULL)
{
bug("Extract_char: NULL.", 0);
return;
}
if (fPull)
die_follower(ch);
stop_fighting(ch, TRUE);
for (obj = ch->carrying; obj != NULL; obj = obj_next)
{
obj_next = obj->next_content;
extract_obj(obj);
}
char_from_room(ch);
if (IS_NPC(ch))
--ch->pIndexData->count;
else if (ch->pcdata->chobj != NULL)
{
ch->pcdata->chobj->chobj = NULL;
ch->pcdata->chobj = NULL;
}
if (!fPull)
{
char_to_room(ch, get_room_index(ROOM_VNUM_ALTAR));
return;
}
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (wch->reply == ch)
wch->reply = NULL;
}
if (ch == char_list)
{
char_list = ch->next;
}
else
{
CHAR_DATA *prev;
for (prev = char_list; prev != NULL; prev = prev->next)
{
if (prev->next == ch)
{
prev->next = ch->next;
break;
}
}
if (prev == NULL)
{
bug("Extract_char: char not found.", 0);
return;
}
}
if (ch->desc)
ch->desc->character = NULL;
/*
if ((wizard = ch->wizard) != NULL)
{
if (!IS_NPC(wizard))
wizard->pcdata->familiar = NULL;
ch->wizard = NULL;
}
*/
if (!IS_NPC(ch))
{
if ((familiar = ch->pcdata->familiar) != NULL)
{
// familiar->wizard = NULL;
ch->pcdata->familiar = NULL;
if (IS_NPC(familiar))
{
act("$n slowly fades away to nothing.", familiar, NULL, NULL, TO_ROOM);
extract_char(familiar, TRUE);
}
}
if ((familiar = ch->pcdata->partner) != NULL)
ch->pcdata->partner = NULL;
if ((familiar = ch->pcdata->propose) != NULL)
ch->pcdata->propose = NULL;
for (familiar = char_list; familiar != NULL; familiar = familiar->next)
{
if (!IS_NPC(familiar) && familiar->pcdata->propose != NULL && familiar->pcdata->propose == ch)
familiar->pcdata->propose = NULL;
if (!IS_NPC(familiar) && familiar->pcdata->partner != NULL && familiar->pcdata->partner == ch)
familiar->pcdata->partner = NULL;
}
}
free_char(ch);
return;
}
/*
* Find a char in the room.
*/
CHAR_DATA *get_char_room(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *rch;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
if (!str_cmp(arg, "self") && (IS_NPC(ch) || ch->pcdata->chobj == NULL))
return ch;
for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
{
if (!IS_NPC(rch) && IS_HEAD(rch, LOST_HEAD))
continue;
else if (!IS_NPC(rch) && IS_EXTRA(rch, EXTRA_OSWITCH))
continue;
else if (!can_see(ch, rch) || (!is_name(arg, rch->name) && (IS_NPC(rch) || !is_name(arg, rch->pcdata->switchname)) && (IS_NPC(rch) || !is_name(arg, rch->morph))))
continue;
if (++count == number)
return rch;
}
return NULL;
}
/*
* Find a char in the world.
*/
CHAR_DATA *get_char_world(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *wch;
int number;
int count;
if ((wch = get_char_room(ch, argument)) != NULL)
return wch;
number = number_argument(argument, arg);
count = 0;
for (wch = char_list; wch != NULL; wch = wch->next)
{
if (!IS_NPC(wch) && IS_HEAD(wch, LOST_HEAD))
continue;
else if (!IS_NPC(wch) && IS_EXTRA(wch, EXTRA_OSWITCH))
continue;
if (wch->in_room == NULL)
continue; // wonder if this ever happens.
else if (!can_see(ch, wch) || (!is_name(arg, wch->name) && (IS_NPC(wch) || !is_name(arg, wch->pcdata->switchname)) && (IS_NPC(wch) || !is_name(arg, wch->morph))))
continue;
if (++count == number)
return wch;
}
return NULL;
}
/*
* Find a char in the same area
*/
CHAR_DATA *get_char_area( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *wch;
int number, count;
if (!ch->in_room) return NULL;
if ((wch = get_char_room(ch, argument)) != NULL)
return wch;
number = number_argument(argument, arg);
count = 0;
for (wch = char_list; wch; wch = wch->next)
{
if (!IS_NPC(wch) && IS_HEAD(wch, LOST_HEAD)) continue;
if (!IS_NPC(wch) && IS_EXTRA(wch, EXTRA_OSWITCH)) continue;
if (wch->in_room == NULL) continue; // wonder if this ever happens.
if (wch->in_room->area != ch->in_room->area) continue;
if (!can_see( ch, wch ) || (!is_name(arg, wch->name) &&
(IS_NPC(wch) || !is_name(arg, wch->pcdata->switchname)) &&
(IS_NPC(wch) || !is_name(arg, wch->morph)))) continue;
if (++count == number) return wch;
}
return NULL;
}
/*
* Find some object with a given index data.
* Used by area-reset 'P' command.
*/
OBJ_DATA *get_obj_type(OBJ_INDEX_DATA * pObjIndex)
{
OBJ_DATA *obj;
for (obj = object_list; obj != NULL; obj = obj->next)
{
if (obj->pIndexData == pObjIndex)
return obj;
}
return NULL;
}
/*
* Find an obj in a list.
*/
OBJ_DATA *get_obj_list(CHAR_DATA * ch, char *argument, OBJ_DATA * list)
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
for (obj = list; obj != NULL; obj = obj->next_content)
{
if (can_see_obj(ch, obj) && is_name(arg, obj->name))
{
if (++count == number)
return obj;
}
}
return NULL;
}
/*
* Find an object within the object you are in.
*/
OBJ_DATA *get_obj_in_obj(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
OBJ_DATA *obj2;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
if (IS_NPC(ch) || ch->pcdata->chobj == NULL || ch->pcdata->chobj->in_obj == NULL)
return NULL;
obj = ch->pcdata->chobj;
if (obj->in_obj->item_type != ITEM_CONTAINER && obj->in_obj->item_type != ITEM_CORPSE_NPC && obj->in_obj->item_type != ITEM_CORPSE_PC)
return NULL;
for (obj2 = obj->in_obj->contains; obj2 != NULL; obj2 = obj2->next_content)
{
if (obj != obj2 && is_name(arg, obj2->name))
{
if (++count == number)
return obj2;
}
}
return NULL;
}
/*
* Find an obj in player's inventory.
*/
OBJ_DATA *get_obj_carry(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
{
if (obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && is_name(arg, obj->name))
{
if (++count == number)
return obj;
}
}
return NULL;
}
/*
* Find an obj in player's equipment.
*/
OBJ_DATA *get_obj_wear(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
{
if (obj->wear_loc != WEAR_NONE && can_see_obj(ch, obj) && is_name(arg, obj->name))
{
if (++count == number)
return obj;
}
}
return NULL;
}
/*
* Find an obj in the room or in inventory.
*/
OBJ_DATA *get_obj_here(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
obj = get_obj_list(ch, argument, ch->in_room->contents);
if (obj != NULL)
return obj;
if ((obj = get_obj_carry(ch, argument)) != NULL)
return obj;
if ((obj = get_obj_wear(ch, argument)) != NULL)
return obj;
if ((obj = get_obj_in_obj(ch, argument)) != NULL)
return obj;
return NULL;
}
/*
* Find an obj in the room or in inventory.
*/
OBJ_DATA *get_obj_room(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
obj = get_obj_list(ch, argument, ch->in_room->contents);
if (obj != NULL)
return obj;
return NULL;
}
/*
* Find an obj in the world.
*/
OBJ_DATA *get_obj_world(CHAR_DATA * ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
OBJ_DATA *obj;
int number;
int count;
if ((obj = get_obj_here(ch, argument)) != NULL)
return obj;
number = number_argument(argument, arg);
count = 0;
for (obj = object_list; obj != NULL; obj = obj->next)
{
if (can_see_obj(ch, obj) && is_name(arg, obj->name))
{
if (++count == number)
return obj;
}
}
return NULL;
}
/*
* Return weight of an object, including weight of contents.
*/
int get_obj_weight(OBJ_DATA * obj)
{
int weight;
weight = obj->weight;
for (obj = obj->contains; obj != NULL; obj = obj->next_content)
weight += get_obj_weight(obj);
return weight;
}
/*
* True if room is dark.
*/
bool room_is_dark(ROOM_INDEX_DATA * pRoomIndex)
{
if (!pRoomIndex)
{
bug("Room_is_dark: No room", 0);
return TRUE;
}
if (pRoomIndex->light > 0)
return FALSE;
if (IS_SET(pRoomIndex->room_flags, ROOM_LIGHT))
return FALSE;
if (IS_SET(pRoomIndex->room_flags, ROOM_DARK))
return TRUE;
if (pRoomIndex->sector_type == SECT_INSIDE || pRoomIndex->sector_type == SECT_CITY)
return FALSE;
if (weather_info.sunlight == SUN_SET || weather_info.sunlight == SUN_DARK)
return TRUE;
return FALSE;
}
/*
* True if room is private.
*/
bool room_is_private(ROOM_INDEX_DATA * pRoomIndex)
{
CHAR_DATA *rch;
int count;
count = 0;
for (rch = pRoomIndex->people; rch != NULL; rch = rch->next_in_room)
if (!IS_NPC(rch))
count++;
if (IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE) && count >= 2)
return TRUE;
return FALSE;
}
/*
* True if char can see victim.
*/
bool can_see(CHAR_DATA * ch, CHAR_DATA * victim)
{
if (ch == victim)
return TRUE;
if (get_trust(ch) > 6)
return TRUE;
if (!IS_NPC(victim) && IS_SET(victim->act, PLR_WIZINVIS) && victim->level > 6)
return FALSE;
if (IS_ITEMAFF(ch, ITEMA_VISION))
return TRUE;
if (!IS_NPC(victim) && IS_SET(victim->act, PLR_WIZINVIS))
return FALSE;
if (!IS_NPC(victim) && IS_SET(victim->act, AFF_HIDE))
return FALSE;
if (!IS_NPC(victim) && IS_SET(victim->newbits, NEW_DARKNESS))
return FALSE;
if (ch->in_room != NULL)
{
if (IS_SET(ch->in_room->room_flags, ROOM_TOTAL_DARKNESS))
{
if (!IS_IMMORTAL(ch))
return FALSE;
else
return TRUE;
}
}
if (IS_EXTRA(ch, BLINDFOLDED))
return FALSE;
if (!IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
if (IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R))
return FALSE;
if (IS_AFFECTED(ch, AFF_BLIND) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT))
return FALSE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_AFFECTED(victim, AFF_INVISIBLE) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
if (IS_AFFECTED(victim, AFF_HIDE) && !IS_AFFECTED(ch, AFF_DETECT_HIDDEN))
return FALSE;
if (!IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD))
return TRUE;
if (!IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH))
return TRUE;
if (!IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) && ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
return TRUE;
if (!IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) && ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
return TRUE;
return TRUE;
}
/*
* True if char can see obj.
*/
bool can_see_obj(CHAR_DATA * ch, OBJ_DATA * obj)
{
CHAR_DATA *gch;
if ((gch = obj->carried_by) != NULL)
{
if (gch->desc != NULL)
{
if (gch->desc->connected != CON_PLAYING)
return FALSE;
}
}
/* for quests */
if (IS_OBJ_STAT(obj, ITEM_NOLOCATE))
{
if (IS_NPC(ch))
return FALSE;
if (ch->pcdata->playerid != obj->ownerid)
return FALSE;
}
if (!IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
if (IS_ITEMAFF(ch, ITEMA_VISION))
return TRUE;
if (IS_OBJ_STAT(obj, ITEM_GLOW))
return TRUE;
if ((IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) && obj->carried_by == NULL) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT) && !IS_AFFECTED(ch, AFF_SHADOWPLANE))
return FALSE;
if ((!IS_SET(obj->extra_flags, ITEM_SHADOWPLANE) && obj->carried_by == NULL) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT) && IS_AFFECTED(ch, AFF_SHADOWPLANE))
return FALSE;
if (obj->item_type == ITEM_POTION)
return TRUE;
if (IS_HEAD(ch, LOST_EYE_L) && IS_HEAD(ch, LOST_EYE_R))
return FALSE;
if (IS_EXTRA(ch, BLINDFOLDED))
return FALSE;
if (IS_AFFECTED(ch, AFF_BLIND) && !IS_AFFECTED(ch, AFF_SHADOWSIGHT))
return FALSE;
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
return TRUE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_SET(obj->extra_flags, ITEM_INVIS) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
if (!IS_NPC(ch) && IS_HEAD(ch, LOST_HEAD) && ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
return TRUE;
if (!IS_NPC(ch) && IS_EXTRA(ch, EXTRA_OSWITCH) && ch->in_room != NULL && ch->in_room->vnum == ROOM_VNUM_IN_OBJECT)
return TRUE;
return TRUE;
}
/*
* True if char can drop obj.
*/
bool can_drop_obj(CHAR_DATA * ch, OBJ_DATA * obj)
{
if (!IS_SET(obj->extra_flags, ITEM_NODROP))
return TRUE;
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return TRUE;
return FALSE;
}
/*
* Return ascii name of an item type.
*/
char *item_type_name(OBJ_DATA * obj)
{
switch (obj->item_type)
{
case ITEM_LIGHT:
return "light";
case ITEM_SCROLL:
return "scroll";
case ITEM_WAND:
return "wand";
case ITEM_STAFF:
return "staff";
case ITEM_WEAPON:
return "weapon";
case ITEM_TREASURE:
return "treasure";
case ITEM_GRENADE:
return "grenade";
case ITEM_ARMOR:
return "armor";
case ITEM_POTION:
return "potion";
case ITEM_FURNITURE:
return "furniture";
case ITEM_TRASH:
return "trash";
case ITEM_CONTAINER:
return "container";
case ITEM_DRINK_CON:
return "drink container";
case ITEM_KEY:
return "key";
case ITEM_FOOD:
return "food";
case ITEM_MONEY:
return "money";
case ITEM_BOAT:
return "boat";
case ITEM_CORPSE_NPC:
return "npc corpse";
case ITEM_CORPSE_PC:
return "pc corpse";
case ITEM_FOUNTAIN:
return "fountain";
case ITEM_PILL:
return "pill";
case ITEM_PORTAL:
return "portal";
case ITEM_HOLYSYMBOL:
return "holy symbol";
case ITEM_STAKE:
return "stake";
case ITEM_QUEST:
return "quest token";
case ITEM_HEAD:
return "head";
case ITEM_COOKINGPOT:
return "cooking pot";
case ITEM_FAITHTOKEN:
return "faith token";
}
bug("Item_type_name: unknown type %d.", obj->item_type);
return "(unknown)";
}
/*
* Return ascii name of an affect location.
*/
char *affect_loc_name(int location)
{
switch (location)
{
case APPLY_NONE:
return "none";
case APPLY_STR:
return "strength";
case APPLY_DEX:
return "dexterity";
case APPLY_INT:
return "intelligence";
case APPLY_WIS:
return "wisdom";
case APPLY_CON:
return "constitution";
case APPLY_SEX:
return "sex";
case APPLY_CLASS:
return "class";
case APPLY_LEVEL:
return "level";
case APPLY_AGE:
return "age";
case APPLY_MANA:
return "mana";
case APPLY_HIT:
return "hp";
case APPLY_MOVE:
return "moves";
case APPLY_GOLD:
return "gold";
case APPLY_EXP:
return "experience";
case APPLY_AC:
return "armor class";
case APPLY_HITROLL:
return "hit roll";
case APPLY_DAMROLL:
return "damage roll";
case APPLY_SAVING_PARA:
return "save vs paralysis";
case APPLY_SAVING_ROD:
return "save vs rod";
case APPLY_SAVING_PETRI:
return "save vs petrification";
case APPLY_SAVING_BREATH:
return "save vs breath";
case APPLY_SAVING_SPELL:
return "save vs spell";
case APPLY_POLY:
return "polymorph form";
}
bug("Affect_location_name: unknown location %d.", location);
return "(unknown)";
}
/*
* Return ascii name of an affect bit vector.
*/
char *affect_bit_name(int vector)
{
static char buf[512];
buf[0] = '\0';
if (vector & AFF_BLIND)
strcat(buf, " blind");
if (vector & AFF_INVISIBLE)
strcat(buf, " invisible");
if (vector & AFF_DETECT_EVIL)
strcat(buf, " detect_evil");
if (vector & AFF_DETECT_INVIS)
strcat(buf, " detect_invis");
if (vector & AFF_DETECT_MAGIC)
strcat(buf, " detect_magic");
if (vector & AFF_DETECT_HIDDEN)
strcat(buf, " detect_hidden");
if (vector & AFF_SHADOWPLANE)
strcat(buf, " shadowplane");
if (vector & AFF_SANCTUARY)
strcat(buf, " sanctuary");
if (vector & AFF_FAERIE_FIRE)
strcat(buf, " faerie_fire");
if (vector & AFF_INFRARED)
strcat(buf, " infrared");
if (vector & AFF_CURSE)
strcat(buf, " curse");
if (vector & AFF_FLAMING)
strcat(buf, " flaming");
if (vector & AFF_POISON)
strcat(buf, " poison");
if (vector & AFF_PROTECT)
strcat(buf, " protect");
if (vector & AFF_ETHEREAL)
strcat(buf, " ethereal");
if (vector & AFF_SNEAK)
strcat(buf, " sneak");
if (vector & AFF_HIDE)
strcat(buf, " hide");
if (vector & AFF_CHARM)
strcat(buf, " charm");
if (vector & AFF_FLYING)
strcat(buf, " flying");
if (vector & AFF_PASS_DOOR)
strcat(buf, " pass_door");
if (vector & AFF_POLYMORPH)
strcat(buf, " polymorph");
if (vector & AFF_SHADOWSIGHT)
strcat(buf, " shadowsight");
return (buf[0] != '\0') ? buf + 1 : "none";
}
/*
* Return ascii name of extra flags vector.
*/
char *extra_bit_name(int extra_flags)
{
static char buf[512];
buf[0] = '\0';
if (extra_flags & ITEM_GLOW)
strcat(buf, " glow");
if (extra_flags & ITEM_HUM)
strcat(buf, " hum");
if (extra_flags & ITEM_INVIS)
strcat(buf, " invis");
if (extra_flags & ITEM_MAGIC)
strcat(buf, " magic");
if (extra_flags & ITEM_NODROP)
strcat(buf, " nodrop");
if (extra_flags & ITEM_ANTI_GOOD)
strcat(buf, " anti-good");
if (extra_flags & ITEM_ANTI_EVIL)
strcat(buf, " anti-evil");
if (extra_flags & ITEM_ANTI_NEUTRAL)
strcat(buf, " anti-neutral");
if (extra_flags & ITEM_BLESS)
strcat(buf, " bless");
if (extra_flags & ITEM_NOREMOVE)
strcat(buf, " noremove");
if (extra_flags & ITEM_INVENTORY)
strcat(buf, " inventory");
if (extra_flags & ITEM_LOYAL)
strcat(buf, " loyal");
if (extra_flags & ITEM_SHADOWPLANE)
strcat(buf, " shadowplane");
if (extra_flags & ITEM_THROWN)
strcat(buf, " thrown");
if (extra_flags & ITEM_KEEP)
strcat(buf, " keep");
if (extra_flags & ITEM_VANISH)
strcat(buf, " vanish");
if (extra_flags & ITEM_NOCLAIM)
strcat(buf, " noclaim");
if (extra_flags & ITEM_NOLOCATE)
strcat(buf, " nolocate");
return (buf[0] != '\0') ? buf + 1 : "none";
}
OBJ_DATA *get_obj_world2(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
int vnum = 0;
if (argument[0] == '\0')
return NULL;
for (obj = object_list; obj != NULL; obj = obj->next)
{
if (!str_cmp(argument, obj->short_descr))
{
if ((vnum = obj->pIndexData->vnum) == 30037 || vnum == 30041)
continue;
return obj;
}
}
return NULL;
}