/***************************************************************************
* 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. *
* *
* _/ _/_/_/ _/ _/ _/ ACK! MUD is modified *
* _/_/ _/ _/ _/ _/ Merc2.0/2.1/2.2 code *
* _/ _/ _/ _/_/ _/ (c)Stephen Dooley 1994 *
* _/_/_/_/ _/ _/ _/ "This mud has not been *
* _/ _/ _/_/_/ _/ _/ _/ tested on animals." *
* *
* *
* 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 <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "merc.h"
extern OBJ_DATA * quest_object;
extern bool quest;
extern CHAR_DATA * quest_mob;
extern CHAR_DATA * quest_target;
extern COUNCIL_DATA super_councils[MAX_SUPER];
/*
* Local functions.
*/
void affect_modify args( ( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd ) );
/*
* Updated pointer referencing, curtesy of Spectrum, from Beyond the Veil
*
*/
struct obj_ref_type *obj_ref_list;
void obj_reference(struct obj_ref_type *ref)
{
if (ref->inuse)
{
bugf("Reused obj_reference!");
abort();
}
ref->inuse=TRUE;
ref->next=obj_ref_list;
obj_ref_list=ref;
}
void obj_unreference(OBJ_DATA **var)
{
struct obj_ref_type *p, *last;
for (p=obj_ref_list, last=NULL;
p && p->var!=var;
last=p,p=p->next)
;
if (!p)
{
bugf("obj_unreference: var not found");
return;
}
p->inuse=FALSE;
if (!last)
obj_ref_list=obj_ref_list->next;
else
last->next=p->next;
}
struct char_ref_type *char_ref_list;
void char_reference(struct char_ref_type *ref)
{
if (ref->inuse)
{
bugf("Reused char_reference!");
abort();
}
ref->inuse=TRUE;
ref->next=char_ref_list;
char_ref_list=ref;
}
void char_unreference(CHAR_DATA **var)
{
struct char_ref_type *p, *last;
for (p=char_ref_list, last=NULL;
p && p->var!=var;
last = p, p=p->next)
;
if (!p)
{
bugf("char_unreference: var not found");
return;
}
p->inuse=FALSE;
if (!last)
char_ref_list=char_ref_list->next;
else
last->next=p->next;
}
/*
* Retrieve a character's trusted level for permission checking.
*/
int get_trust( CHAR_DATA *ch )
{
if ( ch->desc != NULL && ch->desc->original != NULL )
ch = ch->desc->original;
if ( !IS_NPC(ch) && IS_SET( ch->pcdata->pflags, PFLAG_AMBAS ) )
return( LEVEL_HERO+1 );
if ( ch->trust != 0 )
return ch->trust;
if ( IS_NPC(ch) && ch->level >= LEVEL_HERO )
return LEVEL_HERO - 1;
else
return ch->level;
}
/*
* Replacement for retrieving a character's age
* Each tick = 1 mud hr. (spaced at 1 minute rl)
* 24 mud hrs = 1 mud day
* 20 mud days = 1 mud month
* 8 mud months = 1 mud year
* Therefore, 24*20*8 = 3840 ticks/mins.
* Returns a string with age info in for use by score, mst, etc
*/
void my_get_age( CHAR_DATA *ch, char *buf )
{
int days, years, months;
int base, ticks;
/* Base = time in seconds ch has been playing... */
base = ch->played + (int) (current_time - ch->logon );
ticks = base/60; /* 1 tick = 60 seconds */
days = ( ticks / 24 ) % 20;
months = ( ticks / 480 ) % 8;
years = 17 + ( ticks / 3840 );
sprintf( buf+strlen(buf), "%d years, %d months and %d days",
years, months, days );
return;
}
/* Simple function to return number of hours a character has played */
int my_get_hours(CHAR_DATA *ch )
{
int secs;
int hrs;
secs = ch->played + (int) (current_time - ch->logon );
hrs = ( secs / 3600 );
return hrs;
}
/*
* Retrieve a character's age.
*/
int get_age( CHAR_DATA *ch )
{
return 17 + ( ch->played + (int) (current_time - ch->logon) ) / 14400;
/* 12240 assumes 30 second hours, 24 hours a day, 20 day - Kahn */
}
/*
* Retrieve character's current strength.
*/
int get_curr_str( CHAR_DATA *ch )
{
int max;
if ( IS_NPC(ch) )
{
return (13+(ch->level/16));
}
max = ch->pcdata->max_str;
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 (15+number_fuzzy((ch->level/20)));
}
max = ch->pcdata->max_int;
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;
if ( IS_NPC(ch) )
{
return (15+number_fuzzy((ch->level/20)));
}
max = ch->pcdata->max_wis;
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 (16 + number_fuzzy( (ch->level / 25 ) ) );
}
max = ch->pcdata->max_dex;
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 ( 15 + number_fuzzy( (ch->level/12) ) );
}
max = ch->pcdata->max_con;
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 500;
/* if ( IS_NPC(ch) && IS_SET(ch->act, ACT_PET) )
return 0; */
return MAX_WEAR + 2 * get_curr_dex( ch ) / 2;
}
/*
* Retrieve a character's carry capacity.
*/
int can_carry_w( CHAR_DATA *ch )
{
if ( !IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL )
return 9999999;
/* if ( IS_NPC(ch) && IS_SET(ch->act, ACT_PET) )
return 0; */
return str_app[get_curr_str(ch)].carry;
}
/*
* See if a string is one of the names of an object.
*/
/*
* New is_name sent in by Alander.
*/
bool is_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;
}
}
/*
* Apply or remove an affect to a character.
*/
void affect_modify( CHAR_DATA *ch, AFFECT_DATA *paf, bool fAdd )
{
char buf[MAX_STRING_LENGTH];
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) )
return;
if ( paf->type == skill_lookup( "Enraged" ) )
REMOVE_BIT( ch->pcdata->pflags, PFLAG_RAGED );
switch ( paf->location )
{
default:
bug( "Affect_modify: unknown location %d.", paf->location );
sprintf( buf, "Affect_modify: called for %s - unknown location %d.",
ch->name, paf->location );
monitor_chan( buf, MONITOR_OBJ );
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: ch->sex += mod; break;
case APPLY_CLASS: break;
case APPLY_LEVEL: break;
case APPLY_AGE: break;
case APPLY_HEIGHT: break;
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;
}
/*
* Check for weapon wielding.
* Guard against recursion (for weapons with affects).
*/
if ( ( ch->is_quitting == FALSE )
&& ( ch->desc != NULL )
&& ( ch->desc->connected != CON_SETTING_STATS ) )
{
short i;
for ( i = 0; i < MAX_WEAR ; i++ )
{
if ( ( ( wield = get_eq_char( ch, i ) ) != NULL )
&& ( get_obj_weight(wield) > str_app[get_curr_str(ch)].wield ) )
{
static int depth;
if ( depth == 0 )
{
depth++;
act( "You stop using $p since it is too heavy.", ch, wield, NULL, TO_CHAR );
act( "$n stops using $p. since it is too heavy", ch, wield, NULL, TO_ROOM );
unequip_char( ch, wield );
/* obj_to_room( wield, ch->in_room ); */
depth--;
}
}
}
}
return;
}
void mark_to_room( int this_room_vnum, MARK_DATA * mark )
{
/* this assumes that the mark_data is good, and has
* been constructed properly. It will link it to the room
* and the main list. Caller must get the struct memory.
*
*/
MARK_LIST_MEMBER *mlist;
MARK_LIST_MEMBER *rlist;
ROOM_INDEX_DATA *this_room;
if ( ( this_room = get_room_index( this_room_vnum ) ) == NULL )
{
free_string( mark->author );
free_string( mark->message );
PUT_FREE( mark, mark_free );
return;
}
GET_FREE( mlist, mark_list_free);
GET_FREE( rlist, mark_list_free);
mlist->mark = mark;
rlist->mark = mark;
LINK( mlist, first_mark_list, last_mark_list, next, prev );
LINK( rlist, this_room->first_mark_list, this_room->last_mark_list, next, prev );
if ( !booting_up )
save_marks( );
return;
}
void mark_from_room( int this_room_vnum, MARK_DATA * mark )
{
MARK_LIST_MEMBER *mlist;
MARK_LIST_MEMBER *rlist;
ROOM_INDEX_DATA *this_room;
this_room = get_room_index( this_room_vnum );
for ( rlist = this_room->first_mark_list; rlist != NULL; rlist = rlist->next )
{
if ( rlist->mark == mark )
{
UNLINK( rlist, this_room->first_mark_list, this_room->last_mark_list, next, prev );
break;
}
}
for ( mlist = first_mark_list; mlist != NULL; mlist = mlist->next )
{
if ( mlist->mark == mark )
{
UNLINK( mlist, first_mark_list, last_mark_list, next, prev );
break;
}
}
free_string( mark->message );
free_string( mark->author );
PUT_FREE( mark, mark_free );
PUT_FREE( rlist, mark_list_free );
PUT_FREE( mlist, mark_list_free );
if ( !booting_up )
save_marks( );
return;
}
/* Give an affect to a room */
void affect_to_room( ROOM_INDEX_DATA *room, ROOM_AFFECT_DATA *raf )
{
ROOM_AFFECT_DATA *raf_new;
char buf[MAX_STRING_LENGTH];
GET_FREE(raf_new, raffect_free);
/* Ramias... Don't copy uninitialized fields: next, prev, is_free */
/*
*raf_new = *raf;
*/
raf_new->duration = raf->duration;
raf_new->level = raf->level;
raf_new->type = raf->type;
raf_new->bitvector = raf->bitvector;
raf_new->applies_spell = raf->applies_spell;
raf_new->modifier = raf->modifier;
raf_new->location = raf->location;
raf_new->caster = raf->caster;
LINK(raf_new, room->first_room_affect, room->last_room_affect,
next, prev);
SET_BIT( room->affected_by, raf->bitvector );
sprintf( buf, "@@e%s@@N has cast @@d%s@@N in @@Narea: @@r%s@@N, @@Nroom: @@r%d@@N.",
raf->caster->name, raffect_bit_name( raf->bitvector ) ,room->area->name, room->vnum );
monitor_chan( buf, MONITOR_GEN_MORT );
return;
}
/* Remove an affect from a room */
void r_affect_remove( ROOM_INDEX_DATA *room, ROOM_AFFECT_DATA *raf )
{
if ( room->first_room_affect == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "r_affect_remove: no affect to remove from room %d.",
room->vnum );
monitor_chan( buf, MONITOR_ROOM );
bug( "R_affect_remove: no affect for room: %d.", room->vnum );
return;
}
REMOVE_BIT( room->affected_by, raf->bitvector );
UNLINK(raf, room->first_room_affect, room->last_room_affect,
next, prev);
PUT_FREE(raf, raffect_free);
return;
}
/*
* Give an affect to a char.
*/
void affect_to_char( CHAR_DATA *ch, AFFECT_DATA *paf )
{
AFFECT_DATA *paf_new;
GET_FREE(paf_new, affect_free);
/* Ramias... Don't copy uninitialized fields: next, prev, is_free */
/*
*paf_new = *paf;
*/
paf_new->type = paf->type;
paf_new->duration = paf->duration;
paf_new->location = paf->location;
paf_new->modifier = paf->modifier;
paf_new->bitvector = paf->bitvector;
paf_new->caster = paf->caster;
paf_new->level = paf->level;
LINK(paf_new, ch->first_affect, ch->last_affect, next, prev);
affect_modify( ch, paf_new, TRUE );
if ( paf_new->type == skill_lookup( "Enraged" ) )
if ( !IS_NPC( ch ) && IS_WOLF( ch ) )
SET_BIT( ch->pcdata->pflags, PFLAG_RAGED );
return;
}
/*
* Remove an affect from a char.
*/
void affect_remove( CHAR_DATA *ch, AFFECT_DATA *paf )
{
short shield_type;
if ( ch->first_affect == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "affect_remove: %s did not have aff %d to remove.",
IS_NPC(ch) ? ch->short_descr : ch->name, paf->type );
monitor_chan( buf, MONITOR_MOB );
bug( "Affect_remove: no affect.", 0 );
return;
}
affect_modify( ch, paf, FALSE );
shield_type = SHIELD_NONE;
if ( paf->type == skill_lookup( "fireshield" ) )
shield_type = FLAME_SHIELD;
else if ( paf->type == skill_lookup( "iceshield" ) )
shield_type = ICE_SHIELD;
else if ( paf->type == skill_lookup( "shockshield" ) )
shield_type = SHOCK_SHIELD;
else if ( paf->type == skill_lookup( "shadowshield" ) )
shield_type = SHADOW_SHIELD;
else if ( paf->type == skill_lookup( "thoughtshield" ) )
shield_type = PSI_SHIELD;
if ( shield_type > SHIELD_NONE )
{
MAGIC_SHIELD * this_shield;
for ( this_shield = ch->first_shield; this_shield != NULL; this_shield = this_shield->next )
if ( this_shield->type == shield_type )
break;
if ( this_shield != NULL )
{
char buf1[MSL];
char buf2[MSL];
sprintf( buf1, this_shield->wearoff_room );
sprintf( buf2, this_shield->wearoff_self );
act( buf1, ch, NULL, NULL, TO_ROOM );
act( buf2, ch, NULL, NULL, TO_CHAR );
UNLINK( this_shield, ch->first_shield, ch->last_shield, next, prev );
free_string( this_shield->absorb_message_self );
free_string( this_shield->absorb_message_room );
free_string( this_shield->absorb_message_victim );
free_string( this_shield->name );
free_string( this_shield->wearoff_room );
free_string( this_shield->wearoff_self );
PUT_FREE( this_shield, shield_free );
}
}
UNLINK( paf, ch->first_affect, ch->last_affect, next, prev );
PUT_FREE(paf, affect_free);
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->first_affect; 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->first_affect; 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->first_affect; 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 )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "char_from_room: %s in NULL room.",
IS_NPC(ch) ? ch->short_descr : ch->name );
monitor_chan( buf, MONITOR_ROOM );
bug( "Char_from_room: NULL.", 0 );
return;
}
if ( !IS_NPC(ch) )
--ch->in_room->area->nplayer;
if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
&& obj->item_type == ITEM_LIGHT
&& obj->value[2] != 0
&& ch->in_room->light > 0 )
--ch->in_room->light;
UNLINK(ch, ch->in_room->first_person, ch->in_room->last_person,
next_in_room, prev_in_room);
ch->in_room = NULL;
ch->next_in_room = NULL;
ch->prev_in_room = NULL;
if ( ch->fighting != NULL )
if ( ch->fighting->in_room != ch->in_room )
{
ch->fighting = NULL;
ch->position = POS_STANDING;
}
return;
}
/*
* Move a char into a room.
*/
void char_to_room( CHAR_DATA *ch, ROOM_INDEX_DATA *pRoomIndex )
{
OBJ_DATA *obj;
ROOM_AFFECT_DATA *raf;
ROOM_AFFECT_DATA *raf_next;
AFFECT_DATA af;
if ( pRoomIndex == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "char_to_room: Attempted to move %s to a NULL room.",
NAME(ch) );
monitor_chan( buf, MONITOR_ROOM );
bug( "Char_to_room: NULL.", 0 );
return;
}
ch->in_room = pRoomIndex;
if ( IS_NPC(ch) )
TOPLINK(ch, pRoomIndex->first_person, pRoomIndex->last_person,
next_in_room, prev_in_room);
else
LINK(ch, pRoomIndex->first_person, pRoomIndex->last_person,
next_in_room, prev_in_room);
if ( !IS_NPC(ch) )
++ch->in_room->area->nplayer;
if ( ( obj = get_eq_char( ch, WEAR_LIGHT ) ) != NULL
&& obj->item_type == ITEM_LIGHT
&& obj->value[2] != 0 )
++ch->in_room->light;
if ( ch->fighting != NULL )
if ( ch->fighting->in_room != ch->in_room )
{
ch->fighting = NULL;
ch->position = POS_STANDING;
}
if ( IS_SET( ch->in_room->affected_by, ROOM_BV_FIRE_RUNE ) )
{
send_to_char( "@@NAs you step into the room, you fleetingly see a mystical @@eFire@@N Rune suspended in front of you, which then @@eEXPLODES@@N!!!\n\r", ch );
act( "@@NThe @@eFire@@N Rune explodes as $n enters the room!", ch, NULL, NULL, TO_ROOM );
for ( raf = ch->in_room->first_room_affect; raf != NULL; raf = raf_next )
{
raf_next = raf->next;
if ( raf->bitvector == ROOM_BV_FIRE_RUNE )
{
ch->hit -= raf->modifier;
r_affect_remove( ch->in_room, raf );
}
}
}
if ( IS_SET( ch->in_room->affected_by, ROOM_BV_SHOCK_RUNE )
&& ( ch->is_free == FALSE ) )
{
send_to_char( "@@NAs you step into the room, you fleetingly see a mystical @@lShock@@N Rune suspended in front of you, which then @@lZAPS@@N You!!!\n\r", ch );
act( "@@NThe @@lShock@@N Rune flashes as $n enters the room!", ch, NULL, NULL, TO_ROOM );
for ( raf = ch->in_room->first_room_affect; raf != NULL; raf = raf_next )
{
raf_next = raf->next;
if ( raf->bitvector == ROOM_BV_SHOCK_RUNE )
{
ch->hit -= raf->modifier;
r_affect_remove( ch->in_room, raf );
}
}
}
if ( IS_SET( ch->in_room->affected_by, ROOM_BV_POISON_RUNE )
&& ( ch->is_free == FALSE ) )
{
send_to_char( "@@NAs you step into the room, you fleetingly see a mystical @@dPoison@@N Rune suspended in front of you, which then @@dEXPLODES@@N!!!\n\r", ch );
act( "@@NThe @@dPoison@@N Rune explodes as $n enters the room!", ch, NULL, NULL, TO_ROOM );
for ( raf = ch->in_room->first_room_affect; raf != NULL; raf = raf_next )
{
short caster_level = 0;
raf_next = raf->next;
if ( raf->bitvector == ROOM_BV_POISON_RUNE )
{
if ( raf->caster == NULL )
{
caster_level = get_psuedo_level( ch );
}
else
{
caster_level = raf->caster->level;
}
if ( !saves_spell( caster_level, ch ) )
{
af.type = skill_lookup( "poison" );
af.duration = 12 + (caster_level/10);
af.location = APPLY_STR;
af.modifier = -2;
af.bitvector = AFF_POISON;
affect_join( ch, &af );
send_to_char( "You feel very sick.\n\r", ch );
act( "$n looks very sick.", ch, NULL, NULL, TO_ROOM );
}
r_affect_remove( ch->in_room, raf );
}
}
}
return;
}
/*
* Give an obj to a char.
*/
void obj_to_char( OBJ_DATA *obj, CHAR_DATA *ch )
{
extern OBJ_DATA * quest_object;
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
if ( ( !IS_NPC( ch ) )
&& ( obj == quest_object ) )
{
bool valid_questor = FALSE;
short average_level;
average_level = obj->value[3];
if ( ( average_level < 20 )
&& ( get_psuedo_level( ch ) < 45 ) )
{
valid_questor = TRUE;
}
else if ( ( average_level < 65 )
&& ( get_psuedo_level ( ch ) > 45 )
&& ( get_psuedo_level( ch ) < 95 ) )
{
valid_questor = TRUE;
}
else if ( ( get_psuedo_level ( ch ) > 90 )
&& ( average_level > 65 ) )
{
valid_questor = TRUE;
}
if ( valid_questor == FALSE )
{
act( "$n fumbles, trying to hold $p, and it falls to the ground.", ch, obj, NULL, TO_ROOM );
act( "You try to hold $p, but it seems to come alive, and slips from your grasp and falls to the ground.", ch, obj, NULL, TO_CHAR );
obj_to_room( obj, ch->in_room );
return;
}
}
LINK(obj, ch->first_carry, ch->last_carry, next_in_carry_list, prev_in_carry_list);
obj->carried_by = ch;
obj->in_room = NULL;
obj->in_obj = NULL;
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
ch->carry_number += get_obj_number( obj );
ch->carry_weight += get_obj_weight( obj );
}
/*
* Take an obj from its character.
*/
void obj_from_char( OBJ_DATA *obj )
{
CHAR_DATA *ch;
if ( ( ch = obj->carried_by ) == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "obj_from_char: NULL ch to remove %s from.",
obj->short_descr );
monitor_chan( buf, MONITOR_OBJ );
bug( "Obj_from_char: null ch.", 0 );
return;
}
if ( obj->wear_loc != WEAR_NONE )
unequip_char( ch, obj );
UNLINK(obj, ch->first_carry, ch->last_carry,
next_in_carry_list, prev_in_carry_list);
obj->carried_by = NULL;
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
obj->in_room = NULL;
obj->in_obj = NULL;
ch->carry_number -= get_obj_number( obj );
ch->carry_weight -= get_obj_weight( obj );
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];
}
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->first_carry; obj != NULL; obj = obj->next_in_carry_list )
{
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;
char log[MAX_STRING_LENGTH];
if ( ( !IS_NPC( ch ) && ch->desc->connected != CON_SETTING_STATS )
&& ( get_eq_char( ch, iWear ) != NULL ) )
{
sprintf( log, "equip_char: %s (room %d) cannot be equiped with %s, as wear slot (%d) not empty.",
NAME(ch), ch->in_room->vnum, obj->short_descr, iWear );
monitor_chan( log, MONITOR_OBJ );
bug( log, 0 );
return;
}
if ( ( !IS_NPC( ch ) && ch->desc->connected != CON_SETTING_STATS )
&& ( ( 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 );
return;
}
ch->armor -= apply_ac( obj, iWear );
obj->wear_loc = iWear;
/* Don't need this anymore!
for ( paf = obj->pIndexData->first_apply; paf != NULL; paf = paf->next )
affect_modify( ch, paf, TRUE );
-I think! */
for ( paf = obj->first_apply; paf != NULL; paf = paf->next )
affect_modify( ch, paf, TRUE );
/* spec: light bugfix */
if ( (IS_NPC(ch) || !ch->desc || ch->desc->connected != CON_SETTING_STATS)
&& obj->item_type == ITEM_LIGHT
&& obj->value[2] != 0
&& ch->in_room != NULL )
++ch->in_room->light;
/* Check to see if object has magical affects... */
if ( IS_SET( obj->item_apply, ITEM_APPLY_INFRA ) )
{
act( "$n's eyes glow brightly.", ch, NULL, NULL, TO_ROOM );
send_to_char( "Your eyes glow brightly!\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_INV ) )
{
act( "$n slowly fades out of existance.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You slowly fade out of existance.\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_DET_INV ) )
send_to_char( "You feel more aware of your surroundings.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_SANC ) )
{
act( "$n is surrounded by a white aura.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You are surrounded by a white aura.\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_SNEAK ) )
send_to_char( "You feel all sneaky!\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_HIDE ) )
send_to_char( "You feel almost hidden.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_PROT ) )
send_to_char( "You feel more protected.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_ENHANCED ) )
send_to_char( "You feel much meaner!\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_DET_MAG )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_HID )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_EVIL )
|| IS_SET( obj->item_apply, ITEM_APPLY_KNOW_ALIGN )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_POISON ) )
send_to_char( "Your eyes tingle slightly.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_PASS_DOOR ) )
{
act( "$n turns turns very pale.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You feel almost weightless!\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_FLY ) )
{
act( "$n gently floats into the air!", ch, NULL, NULL, TO_ROOM );
send_to_char( "You gently float upwards!\n\r", ch );
}
return;
}
/*
* Unequip a char with an obj.
*/
void unequip_char( CHAR_DATA *ch, OBJ_DATA *obj )
{
AFFECT_DATA *paf;
if ( obj->wear_loc == WEAR_NONE )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "unequip_char: %s is not wearing %s.",
NAME(ch), obj->short_descr );
monitor_chan( buf, MONITOR_OBJ );
bug( "Unequip_char: already unequipped.", 0 );
return;
}
ch->armor += apply_ac( obj, obj->wear_loc );
obj->wear_loc = -1;
/*
for ( paf = obj->pIndexData->first_apply; paf != NULL; paf = paf->next )
affect_modify( ch, paf, FALSE );
*/
for ( paf = obj->first_apply; paf != NULL; paf = paf->next )
affect_modify( ch, paf, FALSE );
if ( obj->item_type == ITEM_LIGHT
&& obj->value[2] != 0
&& ch->in_room != NULL
&& ch->in_room->light > 0 )
--ch->in_room->light;
/* Check to see if object has magical affects... */
if ( IS_SET( obj->item_apply, ITEM_APPLY_INFRA ) )
{
act( "$n's eyes become dim.", ch, NULL, NULL, TO_ROOM );
send_to_char( "Your eyes become dim!\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_INV ) )
{
act( "$n slowly fades back into existance.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You slowly fade into existance.\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_DET_INV ) )
send_to_char( "You feel less aware of your surroundings.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_SANC ) )
{
act( "The white aura around $n fades.", ch, NULL, NULL, TO_ROOM );
send_to_char( "The white aura around you fades.\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_SNEAK ) )
send_to_char( "You feel less sneaky!\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_HIDE ) )
send_to_char( "You feel less hidden.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_PROT ) )
send_to_char( "You feel less protected.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_ENHANCED ) )
send_to_char( "You feel much wimpier!\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_DET_MAG )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_HID )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_EVIL )
|| IS_SET( obj->item_apply, ITEM_APPLY_KNOW_ALIGN )
|| IS_SET( obj->item_apply, ITEM_APPLY_DET_POISON ) )
send_to_char( "Your feel less well-informed.\n\r", ch );
if ( IS_SET( obj->item_apply, ITEM_APPLY_PASS_DOOR ) )
{
act( "$n becomes solid again.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You feel more solid!\n\r", ch );
}
if ( IS_SET( obj->item_apply, ITEM_APPLY_FLY ) )
{
act( "$n gently floats to the ground!", ch, NULL, NULL, TO_ROOM );
send_to_char( "You gently float to the ground!\n\r", ch );
}
if ( ch->mana > ch->max_mana )
ch->mana = ch->max_mana;
if ( ch->hit > ch->max_hit )
ch->hit = ch->max_hit;
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_in_carry_list )
{
if ( obj->pIndexData == pObjIndex )
nMatch++;
}
return nMatch;
}
/*
* Count occurrences of an obj in a list.
*/
int count_obj_room( OBJ_INDEX_DATA *pObjIndex, OBJ_DATA *list )
{
OBJ_DATA *obj;
int nMatch;
nMatch = 0;
for ( obj = list; obj != NULL; obj = obj->next_in_room )
{
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 ( ( in_room = obj->in_room ) == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "obj_from_room: %s in NULL room.", obj->short_descr );
monitor_chan( buf, MONITOR_OBJ );
bug( "obj_from_room: NULL.", 0 );
/* attempt to recover by moving obj to another room */
if ( obj->carried_by != NULL )
obj_from_char( obj );
else
if ( obj->in_obj != NULL )
obj_from_obj( obj );
obj_to_room( obj, get_room_index( ROOM_VNUM_LIMBO ) );
if ( ( in_room = obj->in_room ) == NULL )
{
sprintf( buf, "obj_from_room, %s really screwed up, failed attempts to move to Limbo.", obj->short_descr );
monitor_chan( buf, MONITOR_OBJ );
return;
}
/* code to save everyone here Zen */
}
UNLINK(obj, in_room->first_content, in_room->last_content,
next_in_room, prev_in_room);
obj->in_room = NULL;
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
obj->carried_by = NULL;
obj->in_obj = NULL;
return;
}
/*
* Move an obj into a room.
*/
void obj_to_room( OBJ_DATA *obj, ROOM_INDEX_DATA *pRoomIndex )
{
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
TOPLINK(obj, pRoomIndex->first_content, pRoomIndex->last_content,
next_in_room, prev_in_room);
obj->in_room = pRoomIndex;
obj->carried_by = NULL;
obj->in_obj = NULL;
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
return;
}
/*
* Move an object into an object.
*/
void obj_to_obj( OBJ_DATA *obj, OBJ_DATA *obj_to )
{
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
TOPLINK(obj, obj_to->first_in_carry_list, obj_to->last_in_carry_list,
next_in_carry_list, prev_in_carry_list);
obj->in_obj = obj_to;
obj->in_room = NULL;
obj->carried_by = NULL;
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
for ( ; obj_to != NULL; obj_to = obj_to->in_obj )
if ( obj_to->carried_by != NULL )
{
/* obj_to->carried_by->carry_number += get_obj_number( obj ); */
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_from = obj->in_obj ) == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "obj_from_obj: %s not in another object.", obj->short_descr );
monitor_chan( buf, MONITOR_OBJ );
bug( "Obj_from_obj: null obj_from.", 0 );
return;
}
UNLINK(obj, obj_from->first_in_carry_list, obj_from->last_in_carry_list,
next_in_carry_list, prev_in_carry_list);
obj->next_in_carry_list = NULL;
obj->prev_in_carry_list = NULL;
obj->in_obj = NULL;
obj->next_in_room = NULL;
obj->prev_in_room = NULL;
obj->carried_by = NULL;
obj->in_room = NULL;
for ( ; obj_from != NULL; obj_from = obj_from->in_obj )
{
if ( obj_from->carried_by != NULL )
{
/* obj_from->carried_by->carry_number -= get_obj_number( obj ); */
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 *wch;
OBJ_DATA * obj_content;
struct obj_ref_type *ref;
ROOM_INDEX_DATA * drop_room = NULL;
for (ref=obj_ref_list; ref; ref=ref->next)
if (*ref->var==obj)
switch (ref->type)
{
case OBJ_NEXT:
*ref->var=obj->next;
break;
case OBJ_NEXTCONTENT:
*ref->var=obj->next_in_carry_list;
break;
case OBJ_NULL:
*ref->var=NULL;
break;
default:
bugf("Bad obj_ref_list type %d", ref->type);
break;
}
if ( ( obj == quest_object ) && quest )
{
if ( ( obj->in_obj != NULL )
&& ( ( obj->in_obj->item_type == ITEM_CORPSE_NPC )
|| ( obj->in_obj->item_type == ITEM_CORPSE_PC ) ) )
{
drop_room = obj->in_obj->in_room;
obj_from_obj( obj);
}
else
if ( obj->carried_by != NULL )
{
drop_room = obj->carried_by->in_room;
obj_from_char( obj );
}
else
if ( obj->in_room != NULL )
{
drop_room = obj->in_room;
obj_from_room( obj );
}
obj_to_room( obj, ( drop_room != NULL ? drop_room : get_room_index( ROOM_VNUM_TEMPLE) ) );
return;
}
if ( obj->carried_by != NULL )
obj_from_char( obj );
else if
( obj->in_room != NULL )
obj_from_room( obj );
else if ( obj->in_obj != NULL )
obj_from_obj( obj );
while ( ( obj_content = obj->last_in_carry_list ) != NULL )
extract_obj( obj_content );
UNLINK(obj, first_obj, last_obj, next, prev);
{
AFFECT_DATA *paf;
while ( (paf = obj->first_apply) != NULL )
{
obj->first_apply = paf->next;
PUT_FREE(paf, affect_free);
}
}
{
EXTRA_DESCR_DATA *ed;
while ( (ed = obj->first_exdesc) != NULL )
{
obj->first_exdesc = ed->next;
free_string( ed->description );
free_string( ed->keyword );
PUT_FREE(ed, exdesc_free);
}
}
for ( wch = first_char; wch; wch = wch->next )
{
MPROG_ACT_LIST *mpact;
if ( wch->hunt_obj == obj )
end_hunt(wch);
/* wch->hunt_obj = NULL;*/
if ( wch->sitting == obj )
do_stand( wch, "" );
for ( mpact = wch->first_mpact; mpact; mpact = mpact->next )
{
if ( mpact->obj == obj )
mpact->obj = NULL;
if ( mpact->vo == obj )
mpact->vo = NULL;
}
}
if ( obj->item_type == ITEM_CORPSE_PC )
{
CORPSE_DATA * this_corpse;
for ( this_corpse = first_corpse; this_corpse != NULL; this_corpse = this_corpse->next)
if ( this_corpse->this_corpse == obj )
break;
if ( this_corpse != NULL )
{
UNLINK( this_corpse, first_corpse, last_corpse, next, prev );
PUT_FREE( this_corpse, corpse_free );
}
save_corpses( );
}
free_string( obj->owner );
free_string( obj->name );
free_string( obj->description );
free_string( obj->short_descr );
--obj->pIndexData->count;
PUT_FREE(obj, obj_free);
return;
}
/*
* Extract a char from the world.
*/
void extract_char( CHAR_DATA *ch, bool fPull )
{
CHAR_DATA *wch;
OBJ_DATA * this_object;
extern CHAR_DATA *quest_mob;
extern CHAR_DATA * quest_target;
struct char_ref_type *ref;
/*
* Updated pointer referencing, curtesy of Spectrum, from Beyond the Veil
*
*/
if ( ch->in_room == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "extract_char: %s in NULL room., Moved to room 2", NAME(ch) );
monitor_chan( buf, MONITOR_MOB );
bug( "Extract_char: NULL.", 0 );
/* char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) ); */
return;
}
for (ref=char_ref_list; ref; ref=ref->next)
if (*ref->var==ch)
switch (ref->type)
{
case CHAR_NEXT:
*ref->var=ch->next;
break;
case CHAR_NEXTROOM:
*ref->var=ch->next_in_room;
break;
case CHAR_NULL:
*ref->var=NULL;
break;
default:
bugf("Bad char_ref_list type %d", ref->type);
break;
}
if ( ( ch == quest_mob )
|| ( ch == quest_target ) )
quest_cancel();
if ( fPull )
die_follower( ch );
stop_fighting( ch, TRUE );
ch->is_quitting = TRUE;
while ( ( this_object = ch->last_carry ) != NULL )
extract_obj( this_object );
char_from_room( ch );
if ( !fPull )
{
if ( IS_NPC( ch ) && IS_SET( ch->act, ACT_INTELLIGENT ) )
char_to_room( ch, get_room_index( ROOM_VNUM_INT_HEAL ) );
else if ( !IS_VAMP(ch) )
char_to_room( ch, get_room_index( ROOM_VNUM_MORIBUND ) );
else
char_to_room( ch, get_room_index( VAMPIRE_RECALL ) );
return;
}
if ( IS_NPC(ch) )
--ch->pIndexData->count;
if ( ch->desc != NULL && ch->desc->original != NULL )
do_return( ch, "" );
for ( wch = first_char; wch != NULL; wch = wch->next )
{
AFFECT_DATA *paf;
if ( wch->reply == ch )
wch->reply = NULL;
if ( wch->hunting == ch || wch->hunt_for == ch )
end_hunt(wch);
if ( !str_cmp( wch->target , ch->name ) )
{
free_string( wch->target );
wch->target=NULL; /* spec- fix the evil nasty duplicate frees */
}
if ( wch->riding == ch )
{
do_dismount( wch, "" );
wch->riding = NULL;
}
if ( wch->rider == ch )
wch->rider = NULL;
for ( paf = wch->first_affect; paf; paf = paf->next )
if ( paf->caster == ch )
paf->caster = NULL;
}
/* free up any shields */
if ( ch->first_shield != NULL )
{
MAGIC_SHIELD * this_shield;
MAGIC_SHIELD * this_shield_next;
for ( this_shield = ch->first_shield; this_shield != NULL; this_shield = this_shield_next )
{
this_shield_next = this_shield->next;
UNLINK( this_shield, ch->first_shield, ch->last_shield, next, prev );
free_string( this_shield->absorb_message_room );
free_string( this_shield->absorb_message_victim );
free_string( this_shield->absorb_message_self );
free_string( this_shield->name );
free_string( this_shield->wearoff_room );
free_string( this_shield->wearoff_self );
PUT_FREE( this_shield, shield_free );
}
}
if ( !IS_NPC( ch ) && IS_SET( ch->pcdata->pflags, PFLAG_SUPER_COUNCIL ) )
{
short this_council;
MEMBER_DATA * imember;
MEMBER_DATA * imember_next;
if ( IS_VAMP( ch ) )
this_council = SUPER_VAMP;
else
this_council = SUPER_NONE;
if ( this_council != SUPER_NONE && super_councils[this_council].council_time > 0 )
for( imember = super_councils[this_council].first_member; imember != NULL; imember = imember_next )
{
imember_next = imember->next;
if ( imember->this_member == ch )
{
UNLINK( imember, super_councils[this_council].first_member, super_councils[this_council].last_member, next, prev );
imember->this_member = NULL;
imember->next = NULL;
imember->prev = NULL;
PUT_FREE( imember, member_free );
continue;
}
}
}
UNLINK(ch, first_char, last_char, next, prev);
if ( ch->desc )
ch->desc->character = 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 ( arg[0] == '\0' )
return NULL;
if ( !str_cmp( arg, "self" ) )
return ch;
if ( !str_cmp( arg, "tank" ) )
{
if ( ch->fighting == NULL )
{
send_to_char( "You aren't fighting anyone!\n\r", ch );
return NULL;
}
else
if ( ch->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\n\r", ch );
return NULL;
}
else
{
return ch->fighting->fighting;
}
}
if ( !str_cmp( arg, "enemy" ) )
{
if ( ch->fighting == NULL )
{
send_to_char( "You aren't fighting anyone!\n\r", ch );
return NULL;
}
else
if ( ch->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\n\r", ch );
return NULL;
}
if ( ch->fighting->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\n\r", ch );
return NULL;
}
else
{
return ch->fighting->fighting->fighting;
}
}
for ( rch = ch->in_room->first_person; rch != NULL; rch = rch->next_in_room )
{
if ( !can_see( ch, rch ) || !is_name( arg, rch->name ) )
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 = first_char; wch != NULL ; wch = wch->next )
{
if ( !can_see( ch, wch ) || !is_name( arg, wch->name ) )
continue;
if ( ++count == number )
return wch;
}
return NULL;
}
CHAR_DATA *get_char_area( CHAR_DATA *ch, char *argument )
{
char arg[MAX_INPUT_LENGTH];
CHAR_DATA *ach;
int number;
int count;
if ( ( ach = get_char_room( ch, argument ) ) != NULL )
return ach;
number = number_argument( argument, arg );
count = 0;
for ( ach = first_char; ach != NULL ; ach = ach->next )
{
if ( ach->in_room->area != ch->in_room->area
|| !can_see( ch, ach ) || !is_name( arg, ach->name ) )
continue;
if ( ++count == number )
return ach;
}
return NULL;
}
/* Used mainly for Imtlset ---Flar */
CHAR_DATA *get_char( CHAR_DATA *ch )
{
if ( !ch->pcdata )
return ch->desc->original;
else
return ch;
}
/*
* 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 = first_obj; obj != NULL; obj = obj->next )
{
if ( obj->pIndexData == pObjIndex )
return obj;
}
return NULL;
}
/*
* Find an obj in a room.
*/
OBJ_DATA *get_obj_room( 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_in_room )
{
if ( can_see_obj( ch, obj ) && is_name( arg, obj->name ) )
{
if ( ++count == number )
return obj;
}
}
return NULL;
}
/*
* Find an obj in a room.
*/
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_in_carry_list )
{
if ( can_see_obj( ch, obj ) && is_name( arg, obj->name ) )
{
if ( ++count == number )
return obj;
}
}
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->first_carry; obj != NULL; obj = obj->next_in_carry_list )
{
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->first_carry; obj != NULL; obj = obj->next_in_carry_list )
{
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_room( ch, argument, ch->in_room->first_content );
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;
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 = first_obj; obj != NULL; obj = obj->next )
{
if ( can_see_obj( ch, obj ) && is_name( arg, obj->name ) )
{
if ( ++count == number )
return obj;
}
}
return NULL;
}
/*
* Create a 'money' obj.
*/
OBJ_DATA *create_money( int amount )
{
char buf[MAX_STRING_LENGTH];
OBJ_DATA *obj;
if ( amount <= 0 )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "create_money: %d provided as amount.", amount );
monitor_chan( buf, MONITOR_OBJ );
bug( "Create_money: zero or negative money %d.", amount );
amount = 1;
}
if ( amount == 1 )
{
obj = create_object( get_obj_index( OBJ_VNUM_MONEY_ONE ), 0 );
}
else
{
obj = create_object( get_obj_index( OBJ_VNUM_MONEY_SOME ), 0 );
sprintf( buf, obj->short_descr, amount );
free_string( obj->short_descr );
obj->short_descr = str_dup( buf );
obj->value[0] = amount;
}
return obj;
}
/*
* Return # of objects which an object counts as.
* Thanks to Tony Chamberlain for the correct recursive code here.
*/
int get_obj_number( OBJ_DATA *obj )
{
int number;
/* OBJ_DATA *vobj; */
number = 1; /*set to one since bag will count as 1 item*/
/* if ( obj->item_type == ITEM_CONTAINER )
{
for ( vobj = obj->first_in_carry_list; vobj != NULL; vobj = vobj->next_in_carry_list )
{
number = number - 1;
}
}
*/
/* containers should count as one item!
if ( obj->item_type == ITEM_CONTAINER )
for ( obj = obj->contains; obj != NULL; obj = obj->next_content )
number += get_obj_number( obj );
else
number = 1;
Zen */
return number;
}
/*
* Return weight of an object, including weight of contents.
*/
int get_obj_weight( OBJ_DATA *obj )
{
int weight;
if ( obj->item_type == ITEM_MONEY )
{
weight = obj->value[0] / 100000;
return weight;
}
weight = obj->weight;
for ( obj = obj->first_in_carry_list; obj != NULL; obj = obj->next_in_carry_list )
weight += get_obj_weight( obj );
return weight;
}
/*
* True if room is dark.
*/
bool room_is_dark( ROOM_INDEX_DATA *pRoomIndex )
{
if ( pRoomIndex->light > 0 )
return FALSE;
if ( IS_SET(pRoomIndex->room_flags, ROOM_DARK) )
return TRUE;
if ( IS_SET( pRoomIndex->affected_by, ROOM_BV_SHADE ) )
return TRUE;
if ( pRoomIndex->sector_type == SECT_INSIDE
|| pRoomIndex->sector_type == SECT_CITY )
return FALSE;
if ( weather_info.moon_phase == MOON_FULL
&& ( weather_info.moon_loc >= MOON_RISE
&& weather_info.moon_loc <= MOON_FALL ) )
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->first_person; rch != NULL; rch = rch->next_in_room )
count++;
if ( IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE) && count >= 2 )
return TRUE;
if ( IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) && count >= 1 )
return TRUE;
return FALSE;
}
/*
* True if char can see victim.
*/
bool can_see( CHAR_DATA *ch, CHAR_DATA *victim )
{
if ( IS_AFFECTED(ch, AFF_BLIND) )
return FALSE;
if ( ch == victim )
return TRUE;
if ( is_same_group( ch, victim ) )
return TRUE;
if ( victim->leader == ch )
return TRUE;
if ( !IS_NPC(ch) && !IS_NPC(victim)
&& !str_cmp(ch->name,"bash")
&& !str_cmp(victim->name,"vannevar")
)
return FALSE;
if ( !IS_NPC(ch) && !IS_NPC(victim)
&& !str_cmp(ch->name,"vannevar")
&& !str_cmp(victim->name,"bash")
)
return FALSE;
if ( !IS_NPC(victim)
&& IS_SET(victim->act, PLR_WIZINVIS)
&& get_trust( ch ) < victim->invis )
/* && get_trust( ch ) < get_trust( victim ) ) */
return FALSE;
if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT) )
return TRUE;
if ( ( room_is_dark( ch->in_room ) && !IS_AFFECTED(ch, AFF_INFRARED) )
&& ch->in_room == victim->in_room)
return FALSE;
if ( !IS_NPC( victim )
&& ( victim->stance == STANCE_AMBUSH ) )
return FALSE;
if ( ( IS_AFFECTED(victim, AFF_INVISIBLE) || item_has_apply( victim, ITEM_APPLY_INV ) )
&& (!IS_AFFECTED(ch, AFF_DETECT_INVIS) && !item_has_apply( ch, ITEM_APPLY_DET_INV)) )
return FALSE;
if ( IS_AFFECTED( victim, AFF_INVISIBLE )
&& ( IS_AFFECTED( ch, AFF_DETECT_INVIS ) || item_has_apply( ch, ITEM_APPLY_DET_INV) )
&& get_psuedo_level( victim ) - 10 > get_psuedo_level( ch ) )
return FALSE;
/* if ( ( IS_AFFECTED( victim, AFF_SNEAK ) || item_has_apply( victim, ITEM_APPLY_SNEAK ) )
&& ( number_percent() < 50 + ( 5 * ( get_psuedo_level( victim ) - get_psuedo_level( ch ) ) ) ) )
return FALSE; */
if ( ( IS_AFFECTED(victim, AFF_HIDE) || item_has_apply( victim, ITEM_APPLY_HIDE ) )
&& ( !IS_AFFECTED(ch, AFF_DETECT_HIDDEN) && !item_has_apply( ch, ITEM_APPLY_DET_HID) )
&& victim->fighting == NULL
&& ( IS_NPC(ch) ? !IS_NPC(victim) : IS_NPC(victim) ) )
return FALSE;
return TRUE;
}
/*
* True if char can see obj.
*/
bool can_see_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( !IS_NPC(ch) && IS_SET(ch->act, PLR_HOLYLIGHT) )
return TRUE;
/* if ( obj->item_type == ITEM_TRIGGER )
return TRUE; */
if ( obj->item_type == ITEM_POTION )
return TRUE;
if ( IS_AFFECTED( ch, AFF_BLIND ) )
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) ) && !item_has_apply( ch, ITEM_APPLY_INFRA) )
return FALSE;
if ( IS_SET(obj->extra_flags, ITEM_INVIS)
&& ( !IS_AFFECTED(ch, AFF_DETECT_INVIS) && !item_has_apply( ch, ITEM_APPLY_DET_INV)) )
return FALSE;
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;
}
bool can_sac_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
if ( IS_SET( obj->extra_flags, ITEM_NOSAC ) )
return FALSE;
else
return TRUE;
}
/*
* Return ascii name of an item type.
*/
char *item_type_name( OBJ_DATA *obj )
{
char log[MAX_STRING_LENGTH];
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_BEACON: return "beacon";
case ITEM_WEAPON: return "weapon";
case ITEM_TREASURE: return "treasure";
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_QUEST: return "quest";
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_BOARD: return "bulletin board";
case ITEM_CLUTCH: return "clutch";
case ITEM_TRIGGER: return "trigger";
case ITEM_STAKE: return "stake";
case ITEM_SOUL: return "soul";
case ITEM_PIECE: return "piece";
case ITEM_SPELL_MATRIX: return "spell matrix";
case ITEM_ENCHANTMENT: return "enchantment";
case ITEM_PORTAL: return "portal";
}
sprintf( log, "Item_type_name: Object: %d. Unknown Type: %d",
obj->pIndexData->vnum, obj->item_type );
monitor_chan( log, MONITOR_OBJ );
bug( log, 0 );
return "(unknown)";
}
/*
* Return ascii name of an affect location.
*/
char *affect_loc_name( int location )
{
char buf[MAX_STRING_LENGTH];
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_HEIGHT: return "height";
case APPLY_WEIGHT: return "weight";
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";
}
sprintf( buf, "affect_location_name: location %d unknown.", location );
monitor_chan( buf, MONITOR_OBJ );
bug( "Affect_location_name: unknown location %d.", location );
return "(unknown)";
}
char *raffect_bit_name( int vector )
{
static char rbuf[512];
rbuf[0] = '\0';
if ( vector & ROOM_BV_NONE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " NONE" );
if ( vector & ROOM_BV_SILENCE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " Silence" );
if ( vector & ROOM_BV_SAFE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " Safe" );
if ( vector & ROOM_BV_ENCAPS ) safe_strcat( MAX_STRING_LENGTH, rbuf, " Seal Room" );
if ( vector & ROOM_BV_SHADE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " Shade" );
if ( vector & ROOM_BV_HEAL_REGEN ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@mHealing Light@@N" );
if ( vector & ROOM_BV_HEAL_STEAL ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@dWither Shadow@@N" );
if ( vector & ROOM_BV_MANA_REGEN ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@eMana Flare@@N" );
if ( vector & ROOM_BV_MANA_STEAL ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@dMana Drain@@N" );
if ( vector & ROOM_BV_FIRE_RUNE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@eFire @@NRune" );
if ( vector & ROOM_BV_FIRE_TRAP ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@eFire @@NTrap" );
if ( vector & ROOM_BV_DAMAGE_TRAP ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@dDamage @@NTrap" );
if ( vector & ROOM_BV_SHOCK_RUNE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@lShock @@NRune" );
if ( vector & ROOM_BV_SHOCK_TRAP ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@lShock @@NTrap" );
if ( vector & ROOM_BV_HOLD ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@rCage@@N" );
if ( vector & ROOM_BV_POISON_RUNE ) safe_strcat( MAX_STRING_LENGTH, rbuf, " @@Poison@@N Rune" );
return ( rbuf[0] != '\0' ) ? rbuf+1 : "none";
}
/*
* 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 ) safe_strcat( MAX_STRING_LENGTH, buf, " blind" );
if ( vector & AFF_INVISIBLE ) safe_strcat( MAX_STRING_LENGTH, buf, " invisible" );
if ( vector & AFF_DETECT_EVIL ) safe_strcat( MAX_STRING_LENGTH, buf, " detect_evil" );
if ( vector & AFF_DETECT_INVIS ) safe_strcat( MAX_STRING_LENGTH, buf, " detect_invis" );
if ( vector & AFF_DETECT_MAGIC ) safe_strcat( MAX_STRING_LENGTH, buf, " detect_magic" );
if ( vector & AFF_DETECT_HIDDEN ) safe_strcat( MAX_STRING_LENGTH, buf, " detect_hidden" );
if ( vector & AFF_HOLD ) safe_strcat( MAX_STRING_LENGTH, buf, " hold" );
if ( vector & AFF_SANCTUARY ) safe_strcat( MAX_STRING_LENGTH, buf, " sanctuary" );
if ( vector & AFF_FAERIE_FIRE ) safe_strcat( MAX_STRING_LENGTH, buf, " faerie_fire" );
if ( vector & AFF_INFRARED ) safe_strcat( MAX_STRING_LENGTH, buf, " infrared" );
if ( vector & AFF_CURSE ) safe_strcat( MAX_STRING_LENGTH, buf, " curse" );
if ( vector & AFF_CLOAK_FLAMING ) safe_strcat( MAX_STRING_LENGTH, buf, " flaming" );
if ( vector & AFF_POISON ) safe_strcat( MAX_STRING_LENGTH, buf, " poison" );
if ( vector & AFF_PROTECT ) safe_strcat( MAX_STRING_LENGTH, buf, " protect" );
if ( vector & AFF_PARALYSIS ) safe_strcat( MAX_STRING_LENGTH, buf, " paralysis" );
if ( vector & AFF_SLEEP ) safe_strcat( MAX_STRING_LENGTH, buf, " sleep" );
if ( vector & AFF_SNEAK ) safe_strcat( MAX_STRING_LENGTH, buf, " sneak" );
if ( vector & AFF_HIDE ) safe_strcat( MAX_STRING_LENGTH, buf, " hide" );
if ( vector & AFF_CHARM ) safe_strcat( MAX_STRING_LENGTH, buf, " charm" );
if ( vector & AFF_FLYING ) safe_strcat( MAX_STRING_LENGTH, buf, " flying" );
if ( vector & AFF_PASS_DOOR ) safe_strcat( MAX_STRING_LENGTH, buf, " pass_door" );
if ( vector & AFF_CLOAK_REFLECTION ) safe_strcat( MAX_STRING_LENGTH, buf, " cloak:reflection" );
if ( vector & AFF_CLOAK_ABSORPTION ) safe_strcat( MAX_STRING_LENGTH, buf, " cloak:absorption" );
if ( vector & AFF_CLOAK_ADEPT ) safe_strcat( MAX_STRING_LENGTH, buf, " cloak:adept" );
if ( vector & AFF_CLOAK_REGEN ) safe_strcat( MAX_STRING_LENGTH, buf, " cloak:regeneration" );
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 ) safe_strcat( MAX_STRING_LENGTH, buf, " glow" );
if ( extra_flags & ITEM_HUM ) safe_strcat( MAX_STRING_LENGTH, buf, " hum" );
if ( extra_flags & ITEM_DARK ) safe_strcat( MAX_STRING_LENGTH, buf, " nodisarm" );
if ( extra_flags & ITEM_LOCK ) safe_strcat( MAX_STRING_LENGTH, buf, " lock" );
if ( extra_flags & ITEM_EVIL ) safe_strcat( MAX_STRING_LENGTH, buf, " evil" );
if ( extra_flags & ITEM_INVIS ) safe_strcat( MAX_STRING_LENGTH, buf, " invis" );
if ( extra_flags & ITEM_MAGIC ) safe_strcat( MAX_STRING_LENGTH, buf, " magic" );
if ( extra_flags & ITEM_NODROP ) safe_strcat( MAX_STRING_LENGTH, buf, " nodrop" );
if ( extra_flags & ITEM_BLESS ) safe_strcat( MAX_STRING_LENGTH, buf, " bless" );
if ( extra_flags & ITEM_ANTI_GOOD ) safe_strcat( MAX_STRING_LENGTH, buf, " anti-good" );
if ( extra_flags & ITEM_ANTI_EVIL ) safe_strcat( MAX_STRING_LENGTH, buf, " anti-evil" );
if ( extra_flags & ITEM_ANTI_NEUTRAL ) safe_strcat( MAX_STRING_LENGTH, buf, " anti-neutral" );
if ( extra_flags & ITEM_NOREMOVE ) safe_strcat( MAX_STRING_LENGTH, buf, " noremove" );
if ( extra_flags & ITEM_INVENTORY ) safe_strcat( MAX_STRING_LENGTH, buf, " inventory" );
if ( extra_flags & ITEM_NOLOOT ) safe_strcat( MAX_STRING_LENGTH, buf, " noloot" );
if ( extra_flags & ITEM_NOSAC ) safe_strcat( MAX_STRING_LENGTH, buf, " nosac" );
if ( extra_flags & ITEM_REMORT ) safe_strcat( MAX_STRING_LENGTH, buf, " remort" );
if ( extra_flags & ITEM_CLAN_EQ ) safe_strcat( MAX_STRING_LENGTH, buf, " claneq" );
if ( extra_flags & ITEM_NOSAVE ) safe_strcat( MAX_STRING_LENGTH, buf, " nosave" );
if ( extra_flags & ITEM_NO_AUCTION ) safe_strcat( MAX_STRING_LENGTH, buf, " no_auction" );
if ( extra_flags & ITEM_RARE ) safe_strcat( MAX_STRING_LENGTH, buf, " rare" );
if ( extra_flags & ITEM_VAMP ) safe_strcat( MAX_STRING_LENGTH, buf, " vamp" );
if ( extra_flags & ITEM_UNIQUE ) safe_strcat( MAX_STRING_LENGTH, buf, " unique" );
if ( extra_flags & ITEM_TRIG_DESTROY ) safe_strcat( MAX_STRING_LENGTH, buf, " trigger:destroy" );
if ( extra_flags & ITEM_LIFESTEALER ) safe_strcat( MAX_STRING_LENGTH, buf, " lifestealer" );
if ( extra_flags & ITEM_SILVER ) safe_strcat( MAX_STRING_LENGTH, buf, " silver" );
return ( buf[0] != '\0' ) ? buf+1 : "none";
}
/* Return the ASCII name of a character's race
* -- Stephen
*/
char *race_name( CHAR_DATA *ch )
{
if (IS_NPC( ch ) )
return( "NPC" );
if ( ch->race >= MAX_RACE || ch->race < 0 )
{
/* error reporting here one day... maybe */
return( "???" );
}
return( race_table[ch->race].race_title );
}
char *short_race_name( CHAR_DATA *ch )
{
static char buf[MAX_STRING_LENGTH];
if (IS_NPC( ch ) )
sprintf( buf, "NPC" );
else
if ( ch->race >= MAX_RACE || ch->race < 0 )
{
/* error reporting here one day... maybe */
sprintf( buf, "unknown!" );
}
else
sprintf( buf, "%s", race_table[ch->race].race_name );
return( buf );
}
bool can_use( CHAR_DATA *ch, OBJ_DATA *obj )
{
return( TRUE );
}
/*
* Return names of classes which can use an object
* -- Stephen
*/
char *who_can_use( OBJ_DATA *obj )
{
return( " all classes." );
}
void notify( char * message, int lv )
{
/* This function sends <message>
* to all players of level (lv) and above
* -- Stephen
*/
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];
sprintf( buf, "[NOTE]: %s\n\r", message );
for ( d = first_desc; d; d = d->next )
if ( ( d->connected == CON_PLAYING )
&& (d->character->level >=lv)
&& !IS_NPC(d->character)
&& !IS_SET( d->character->deaf, CHANNEL_NOTIFY ) )
send_to_char( buf, d->character );
return;
}
void auction( char * message )
{
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];
sprintf( buf, "[AUCTION]: %s\n\r", message );
for ( d = first_desc; d; d = d->next )
if ( ( d->connected == CON_PLAYING )
&& !IS_NPC(d->character)
&& !IS_SET( d->character->deaf, CHANNEL_AUCTION ) )
send_to_char( buf, d->character );
return;
}
void info( char * message, int lv )
{
/* This function sends <message>
* to all players of level (lv) and above
* Used mainly to send level gain, death info, etc to mortals.
* - Stephen
*/
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];
for ( d = first_desc; d; d = d->next )
if ( ( d->connected == CON_PLAYING )
&& (d->character->level >=lv)
&& !IS_NPC(d->character)
&& !IS_SET( d->character->deaf, CHANNEL_INFO ) )
{
sprintf( buf, "%s[INFO]: %s%s\n\r",
colour_string( d->character, "info" ), message,
colour_string( d->character, "normal" ) );
send_to_char( buf, d->character );
}
return;
}
void log_chan( const char *message, int lv )
{
/* Used to send messages to Immortals.
* Level is used to determine WHO gets the message... */
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];
sprintf( buf, "[LOG]: %s\n\r", message );
for ( d = first_desc; d; d = d->next )
if ( ( d->connected == CON_PLAYING )
&& ( get_trust( d->character ) == MAX_LEVEL )
&& ( !IS_NPC( d->character ) )
&& ( d->character->level >= lv )
&& ( !IS_SET( d->character->deaf, CHANNEL_LOG ) ) )
send_to_char( buf, d->character );
return;
}
bool item_has_apply( CHAR_DATA *ch, int bit )
{
/* Used to see if ch is HOLDING any object(s) with the specified
* ITEM_APPLY bit set.
* -S-
*/
OBJ_DATA *obj;
for ( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list )
if ( IS_SET( obj->item_apply, bit ) && obj->wear_loc != WEAR_NONE )
return TRUE;
return FALSE;
}
/* This is for immrotal authorized skills. Enables imms to set which skillks lower imms may use. handy for abuse control --Flar
*/
bool authorized( CHAR_DATA *ch, char *skllnm )
{
char buf [ MAX_STRING_LENGTH ];
if ( ( !IS_NPC( ch ) && str_infix( skllnm, ch->pcdata->immskll ) )
|| IS_NPC( ch ) )
{
sprintf( buf, "Sorry, you are not authorized to use %s.\n\r", skllnm );
send_to_char( buf, ch );
return FALSE;
}
return TRUE;
}
/* For new spells, etc, eg Polymorph. Transfer a PC to safe room, then
'switches' them into the given mob. The mob is placed into the
room 'victim' was in. */
CHAR_DATA *switch_char( CHAR_DATA *victim, int mvnum, int poly_level )
{
/* Levels of polymorphism :
0 : equivalent to switch
1 : pc with pcdata.
2 : pc with pcdata + objects
3 : pc with pcdata + objs, levels and exp, pract, gold
4 : as 3, but same stats(hp/mana/move)
*/
CHAR_DATA *mob;
ROOM_INDEX_DATA *location;
OBJ_DATA *eq;
int foo;
location = victim->in_room;
char_from_room( victim );
char_to_room( victim, get_room_index( ROOM_VNUM_BODIES ) );
mob = create_mobile( get_mob_index( mvnum) );
switch( poly_level )
{
case 4: /* Level 4 */
mob->hit = victim->hit;
mob->max_hit = victim->max_hit;
mob->mana = victim->mana;
mob->max_mana = victim->max_mana;
mob->max_move = victim->max_move;
mob->move = victim->move;
case 3: /* Level 3 */
mob->level = victim->level;
mob->gold = victim->gold;
mob->exp = victim->exp;
for ( foo = 0; foo < MAX_CLASS; foo++ )
mob->lvl[foo] = victim->lvl[foo];
mob->practice = victim->practice;
case 2: /* Level 2 */
while ( (eq = victim->first_carry) != NULL )
{
obj_from_char( eq );
obj_to_char( eq, mob );
}
case 1: /* Level 1 */
mob->pcdata = victim->pcdata;
REMOVE_BIT( mob->act, ACT_IS_NPC);
case 0: /* Level 0 */
mob->desc = victim->desc;
mob->desc->character = mob;
mob->desc->original = victim;
mob->switched = TRUE;
victim->desc = NULL;
victim->switched = TRUE;
break;
default:
bug( "Invalid poly_level %d encountered.", poly_level );
break;
}
mob->poly_level = poly_level;
mob->old_body = victim;
char_to_room( mob, location );
return (mob);
}
CHAR_DATA *unswitch_char( CHAR_DATA * victim)
{
/* Check poly_level, and copy back relevant stats, etc. */
CHAR_DATA *original;
ROOM_INDEX_DATA *location;
OBJ_DATA *eq;
int foo;
if (victim->switched==FALSE)
return victim;
location=victim->in_room;
original=victim->old_body;
char_from_room( original );
char_to_room( original, location );
original->switched=FALSE;
original->desc=victim->desc;
original->desc->character=original;
original->desc->original=NULL;
switch ( victim->poly_level )
{
case 4:
original->hit = victim->hit;
original->max_hit = victim->max_hit;
original->mana = victim->mana;
original->max_mana = victim->max_mana;
original->max_move = victim->max_move;
original->move = victim->move;
case 3:
original->level = victim->level;
original->exp = victim->exp;
original->gold = victim->gold;
for ( foo = 0; foo < MAX_CLASS; foo++ )
original->lvl[foo] = victim->lvl[foo];
case 2:
while ( (eq = victim->first_carry) != NULL )
{
obj_from_char( eq );
obj_to_char( eq, original );
}
case 1:
original->pcdata = victim->pcdata;
case 0:
SET_BIT( victim->act, ACT_IS_NPC );
}
victim->desc=NULL;
extract_char(victim,TRUE);
return original;
}
/* A Function to "center" text, and return a string with
* the required amount of white space either side of the
* original text. --Stephen
*/
char *center_text( char *text, int width )
{
/* This could do with a LOT of improvement sometime! */
/* Improvements done.. -- Altrag */
static char foo[MAX_STRING_LENGTH];
int len, diff;
/* Don't bother with strings too long.. */
if ( (len = my_strlen(text)) >= width )
return text;
diff = strlen(text)-len;
/* Add the spaces and terminate string */
memset(foo, ' ', width+diff);
foo[width+diff] = '\0';
/* Copy old string over */
memcpy(&foo[(width-len)/2], text, len+diff);
return foo;
}
void set_stun( CHAR_DATA * victim, int stunTime )
{
/* Sets the victim's wait_state and position
-Damane- 4/26/96 */
if( victim->position != POS_SLEEPING )
victim->position = POS_STUNNED;
victim->stunTimer = stunTime;
return;
}
bool is_shielded( CHAR_DATA * ch, short shield_type)
{
MAGIC_SHIELD * shield;
for ( shield = ch->first_shield; shield != NULL; shield = shield->next )
if ( shield->type == shield_type )
return TRUE;
return FALSE;
}
void remove_shield( CHAR_DATA * ch, MAGIC_SHIELD * shield )
{
if ( ch->first_shield == NULL )
{
char buf[MAX_STRING_LENGTH];
sprintf( buf, "shield_remove: %s did not have a shield to remove.",
IS_NPC(ch) ? ch->short_descr : ch->name );
monitor_chan( buf, MONITOR_MOB );
bug( "Remove_shield: no shield.", 0 );
return;
}
UNLINK(shield, ch->first_shield, ch->last_shield, next, prev);
PUT_FREE(shield, shield_free);
return;
}