/***************************************************************************
* 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. *
* *
* Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley *
* *
* 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 Zepp 1998 *
* _/_/_/_/ _/ _/ _/ Version #: 4.3 *
* _/ _/ _/_/_/ _/ _/ _/ *
* *
* http://ackmud.nuc.net/ *
* zenithar@ackmud.nuc.net *
* 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. *
***************************************************************************/
/***************************************************************************
* _/_/_/_/ _/ _/ _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
* _/ _/ _/ _/ _/ copyright Matt Goff (Kline) 2008 *
* _/_/ _/ _/ _/_/_/_/ _/_/_/_/ *
* _/ _/ _/ _/ _/ Support for this code is provided *
* _/ _/_/_/_/ _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
***************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "globals.h"
#ifndef DEC_ACT_COMM_H
#include "h/act_comm.h"
#endif
#ifndef DEC_ACT_INFO_H
#include "h/act_info.h"
#endif
#ifndef DEC_ACT_MOB_H
#include "h/act_mob.h"
#endif
#ifndef DEC_ACT_MOVE_H
#include "h/act_move.h"
#endif
#ifndef DEC_ACT_OBJ_H
#include "h/act_obj.h"
#endif
#ifndef DEC_ACT_WIZ_H
#include "h/act_wiz.h"
#endif
#ifndef DEC_COMM_H
#include "h/comm.h"
#endif
#ifndef DEC_DB_H
#include "h/db.h"
#endif
#ifndef DEC_FIGHT_H
#include "h/fight.h"
#endif
#ifndef DEC_HANDLER_H
#include "h/handler.h"
#endif
#ifndef DEC_MAGIC_H
#include "h/magic.h"
#endif
#ifndef DEC_MONEY_H
#include "h/money.h"
#endif
#ifndef DEC_MOUNT_H
#include "h/mount.h"
#endif
#ifndef DEC_SSM_H
#include "h/ssm.h"
#endif
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];
/*
* 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 ) && ch->act.test(ACT_AMBASSADOR) )
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 );
snprintf( buf + strlen(buf) , MSL, "%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) && ch->act.test(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) && ch->act.test(ACT_PET) )
return 0; */
return str_app[get_curr_str( ch )].carry;
}
/*
* 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 ) )
{
switch ( paf->location )
{
default:
return;
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;
}
return;
}
if( paf->type == skill_lookup( "Enraged" ) )
ch->act.reset(ACT_RAGED);
switch ( paf->location )
{
default:
bug( "Affect_modify: unknown location %d.", paf->location );
snprintf( buf, MSL, "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;
}
/* 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];
raf_new = new ROOM_AFFECT_DATA;
/* 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 );
snprintf( buf, MSL, "@@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];
snprintf( buf, MSL, "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 );
delete raf;
return;
}
/*
* Give an affect to a char.
*/
void affect_to_char( CHAR_DATA * ch, AFFECT_DATA * paf )
{
AFFECT_DATA *paf_new;
paf_new = new AFFECT_DATA;
/* 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_WOLF( ch ) )
ch->act.set(ACT_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];
snprintf( buf, MSL, "affect_remove: %s did not have aff %d to remove.", NAME(ch), 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];
extern bool merc_down;
if( !merc_down ) // Don't send out messages on shutdown cleanup; it creates errors. --Kline
{
snprintf( buf1, MSL, "%s", this_shield->wearoff_room );
snprintf( buf2, MSL, "%s", 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 );
delete this_shield;
}
}
UNLINK( paf, ch->first_affect, ch->last_affect, next, prev );
delete 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->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_old->location == paf->location ) && ( paf_old->bitvector == paf->bitvector ) )
{
paf->duration += paf_old->duration;
paf->modifier += paf_old->modifier;
affect_remove( ch, paf_old );
break;
}
}
affect_to_char( ch, paf );
return;
}
/*
* Find a piece of eq on a character.
*/
OBJ_DATA *get_light_char( CHAR_DATA * ch )
{
OBJ_DATA *obj;
for( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list )
{
if( ( obj->wear_loc != -1 ) && ( obj->item_type == ITEM_LIGHT ) && ( obj->value[2] != 0 ) )
return obj;
}
return NULL;
}
/*
* 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];
snprintf( buf, MSL, "char_from_room: %s in NULL room.", NAME(ch) );
monitor_chan( buf, MONITOR_ROOM );
bug( "Char_from_room: NULL.", 0 );
return;
}
if( !IS_NPC( ch ) )
ch->in_room->area->player_list.remove(ch);
if( ( obj = get_light_char( ch ) ) != NULL )
--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];
snprintf( buf, MSL, "char_to_room: Attempted to move %s to a NULL room.", NAME( ch ) );
monitor_chan( buf, MONITOR_ROOM );
bug( "Char_to_room: NULL.", 0 );
}
ch->in_room = pRoomIndex;
if( IS_NPC( ch ) )
TOPLINK( ch, ch->in_room->first_person, ch->in_room->last_person, next_in_room, prev_in_room );
else
LINK( ch, ch->in_room->first_person, ch->in_room->last_person, next_in_room, prev_in_room );
if( !IS_NPC( ch ) )
ch->in_room->area->player_list.push_back(ch);
if( ( obj = get_light_char( ch ) ) != NULL )
++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!!!\r\n",
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 ) )
{
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!!!\r\n",
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 ) )
{
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!!!\r\n",
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.\r\n", 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 )
{
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( IS_IMMORTAL(ch) )
valid_questor = TRUE;
else 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 );
if( AI_MOB( ch ) )
{
OBJ_DATA *armor = NULL;
OBJ_DATA *obj2 = NULL;
bool ident = TRUE;
if( ( obj->item_type == ITEM_ARMOR ) || ( obj->item_type == ITEM_LIGHT ) )
{
if( obj->item_type == ITEM_ARMOR )
{
/*
* Check this object against our equiped objects
*/
ident = FALSE;
for( obj2 = ch->first_carry; obj2 != NULL; obj2 = obj2->next_in_carry_list )
{
if( ( obj2 != obj )
&& ( obj2->wear_loc != WEAR_NONE )
&& ( ( obj2->item_type == ITEM_ARMOR )
|| ( obj2->item_type == ITEM_LIGHT ) )
&& ( can_wear_at( ch, obj, obj2->wear_loc ) ) && ( get_item_value( obj ) > get_item_value( obj2 ) ) )
{
ident = TRUE; /* identical wear_loc */
armor = obj;
break;
}
}
}
/*
* Found no match for locations, so get and wear.
*/
if( !ident )
{
armor = obj;
// break;
}
if( armor != NULL )
{
do_wear( ch, armor->name );
}
else
{
do_drop( ch, obj->name );
}
}
// else if light
//else if weapon
}
} // end if ai_mob
/*
* 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];
snprintf( buf, MSL, "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_HOLD_HAND_R:
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_HAND_L:
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 ) )
{
snprintf( log, MSL, "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_EXTRA_ANTI_EVIL ) && IS_EVIL( ch ) )
|| ( IS_OBJ_STAT( obj, ITEM_EXTRA_ANTI_GOOD ) && IS_GOOD( ch ) )
|| ( IS_OBJ_STAT( obj, ITEM_EXTRA_ANTI_NEUTRAL ) && IS_NEUTRAL( ch ) ) ) )
{
/*
* Thanks to Morgenes for the bug fix here!
*/
if( !IS_OBJ_STAT( obj, ITEM_EXTRA_NO_DROP ) )
{
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 );
}
else
{
act( "You feel $p slither out of your grasp, and back into your inventory!", ch, obj, NULL, TO_CHAR );
act( "$p slithers out of $n's hands and back into $s inventory!", ch, obj, NULL, TO_ROOM );
}
return;
}
ch->armor -= apply_ac( obj, iWear );
obj->wear_loc = iWear;
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!\r\n", 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.\r\n", ch );
}
if( IS_SET( obj->item_apply, ITEM_APPLY_DET_INV ) )
send_to_char( "You feel more aware of your surroundings.\r\n", 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.\r\n", ch );
}
if( IS_SET( obj->item_apply, ITEM_APPLY_SNEAK ) )
send_to_char( "You feel all sneaky!\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_HIDE ) )
send_to_char( "You feel almost hidden.\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_PROT ) )
send_to_char( "You feel more protected.\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_ENHANCED ) )
send_to_char( "You feel much meaner!\r\n", 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.\r\n", 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!\r\n", 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!\r\n", 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];
snprintf( buf, MSL, "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!\r\n", 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.\r\n", ch );
}
if( IS_SET( obj->item_apply, ITEM_APPLY_DET_INV ) )
send_to_char( "You feel less aware of your surroundings.\r\n", 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.\r\n", ch );
}
if( IS_SET( obj->item_apply, ITEM_APPLY_SNEAK ) )
send_to_char( "You feel less sneaky!\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_HIDE ) )
send_to_char( "You feel less hidden.\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_PROT ) )
send_to_char( "You feel less protected.\r\n", ch );
if( IS_SET( obj->item_apply, ITEM_APPLY_ENHANCED ) )
send_to_char( "You feel much wimpier!\r\n", 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.\r\n", 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!\r\n", 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!\r\n", 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];
snprintf( buf, MSL, "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 )
{
snprintf( buf, MSL, "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];
snprintf( buf, MSL, "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 )
{
std::list<CHAR_DATA *>::iterator li;
CHAR_DATA *wch;
OBJ_DATA *obj_content;
ROOM_INDEX_DATA *drop_room = NULL;
extern bool merc_down;
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 );
{
AFFECT_DATA *paf;
while( ( paf = obj->first_apply ) != NULL )
{
obj->first_apply = paf->next;
delete paf;
}
}
{
EXTRA_DESCR_DATA *ed;
while( ( ed = obj->first_exdesc ) != NULL )
{
obj->first_exdesc = ed->next;
delete ed;
}
}
if( !merc_down ) //Chars get cleaned before objs on shutdown; checking past this point creates errors. --Kline
{
for( li = char_list.begin(); li != char_list.end(); li++ )
{
wch = *li;
if( wch->hunt_obj != NULL && wch->hunt_obj == obj )
end_hunt( wch );
if( wch->sitting != NULL && wch->sitting == obj )
do_stand( wch, "" );
}
}
if( obj->item_type == ITEM_CORPSE_PC )
{
corpse_list.remove(obj);
save_corpses( );
}
if( obj->reset )
obj->reset->count--;
obj_list.remove(obj);
delete obj;
return;
}
/*
* Extract a char from the world.
*/
void extract_char( CHAR_DATA * ch, bool fPull )
{
CHAR_DATA *wch;
OBJ_DATA *this_object;
ROOM_INDEX_DATA *room;
ROOM_AFFECT_DATA *raf;
std::list<CHAR_DATA *>::iterator li;
if( ch->in_room == NULL )
{
char buf[MAX_STRING_LENGTH];
snprintf( buf, MSL, "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;
}
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 );
ch->was_in_room = ch->in_room;
char_from_room( ch );
if( !fPull )
{
if( AI_MOB(ch) )
{
char_to_room( ch, get_room_index( ROOM_VNUM_INT_HEAL ) );
}
else if( !IS_VAMP( ch ) )
{
char_to_room(ch,ch->was_in_room);
ch->act.set(ACT_GHOST);
ch->death_cnt = number_range(3,5);
send_to_char("Your spirit rises up from your fallen body!\r\n",ch);
act("$n's spirit rises up from $s fallen body!",ch,NULL,NULL,TO_ROOM);
}
else
{
char_to_room( ch, get_room_index( VAMPIRE_RECALL ) );
}
ch->was_in_room = NULL;
return;
}
ch->was_in_room = NULL;
if( ch->desc != NULL && ch->desc->original != NULL )
do_return( ch, "" );
for( li = char_list.begin(); li != char_list.end(); li++ )
{
AFFECT_DATA *paf;
wch = *li;
if( wch->master == ch )
wch->master = NULL;
if( wch->leader == ch )
wch->leader = NULL;
if( wch->fighting == ch )
wch->fighting = NULL;
if( wch->reply == ch )
wch->reply = NULL;
if( wch->hunting == ch || wch->hunt_for == ch )
{
end_hunt( wch );
/*
* Aeria put this in for searching
*/
if( IS_NPC( wch ) )
{
wch->searching = ch->name;
}
else
send_to_char("@@RYou seem to have lost your prey.@@N\r\n",wch);
}
if( wch->old_body == ch )
{
do_return(wch,"");
wch->old_body = NULL;
}
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;
}
for( short i = 0; i < MAX_KEY_HASH; i++ )
for( room = room_index_hash[i]; room; room = room->next )
for( raf = room->first_room_affect; raf; raf = raf->next )
if( raf->caster == ch )
raf->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 );
delete this_shield;
}
}
if( ch->act.test(ACT_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;
}
}
}
if( IS_NPC(ch) && ch->npcdata->ngroup != NULL )
{
NPC_GROUP_DATA *kill_group = NULL;
DL_LIST *kill_member = NULL;
for( kill_group = first_npc_group; kill_group; kill_group = kill_group->next )
{
if( kill_group->leader == ch )
{
UNLINK( kill_group, first_npc_group, last_npc_group, next, prev );
delete kill_group;
}
else
{
for( kill_member = kill_group->first_follower; kill_member; kill_member = kill_member->next )
{
if( ( CHAR_DATA * ) kill_member->this_one == ch )
{
UNLINK( kill_member, kill_group->first_follower, kill_group->last_follower, next, prev );
PUT_FREE( kill_member, dl_list_free );
}
}
}
}
}
if( IS_NPC(ch) && ch->npcdata->reset )
ch->npcdata->reset->count--;
if( ch->desc )
ch->desc->character = NULL;
char_list.remove(ch);
delete 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!\r\n", ch );
return NULL;
}
else if( ch->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\r\n", 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!\r\n", ch );
return NULL;
}
else if( ch->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\r\n", ch );
return NULL;
}
if( ch->fighting->fighting->fighting == NULL )
{
send_to_char( "Hmm, that's wierd..where did he go?\r\n", 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;
std::list<CHAR_DATA *>::iterator li;
int number;
int count;
if( ( wch = get_char_room( ch, argument ) ) != NULL )
return wch;
number = number_argument( argument, arg );
count = 0;
for( li = char_list.begin(); li != char_list.end(); li++ )
{
wch = *li;
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;
std::list<CHAR_DATA *>::iterator li;
int number;
int count;
if( ( ach = get_char_room( ch, argument ) ) != NULL )
return ach;
number = number_argument( argument, arg );
count = 0;
for( li = char_list.begin(); li != char_list.end(); li++ )
{
ach = *li;
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;
std::list<OBJ_DATA *>::iterator li;
for( li = obj_list.begin(); li != obj_list.end(); li++ )
{
obj = *li;
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;
std::list<OBJ_DATA *>::iterator li;
if( ( obj = get_obj_here( ch, argument ) ) != NULL )
return obj;
number = number_argument( argument, arg );
count = 0;
for( li = obj_list.begin(); li != obj_list.end(); li++ )
{
obj = *li;
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 )
{
snprintf( buf, MSL, "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 );
snprintf( buf, MSL, 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( pRoomIndex->room_flags.test(RFLAG_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( pRoomIndex->room_flags.test(RFLAG_PRIVATE) && count >= 2 )
return TRUE;
if( pRoomIndex->room_flags.test(RFLAG_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 ) && victim->act.test(ACT_WIZINVIS) && get_trust( ch ) < victim->invis )
/*
* && get_trust( ch ) < get_trust( victim ) )
*/
return FALSE;
if( !IS_NPC( ch ) && ch->act.test(ACT_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 ) && ch->act.test(ACT_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_OBJ_STAT(obj,ITEM_EXTRA_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_OBJ_STAT(obj,ITEM_EXTRA_NO_DROP) )
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_OBJ_STAT(obj,ITEM_EXTRA_NO_SAC) )
return FALSE;
else
return TRUE;
}
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];
snprintf( buf, MSL, "[NOTE]: %s\r\n", message );
for( d = first_desc; d; d = d->next )
if( ( d->connected == CON_PLAYING )
&& ( d->character->level >= lv ) && !IS_NPC( d->character ) && !d->character->deaf.test(CHANNEL_NOTIFY) )
send_to_char( buf, d->character );
return;
}
void auction( char *message )
{
DESCRIPTOR_DATA *d;
char buf[MAX_STRING_LENGTH];
snprintf( buf, MSL, "[AUCTION]: %s\r\n", message );
for( d = first_desc; d; d = d->next )
if( ( d->connected == CON_PLAYING ) && !IS_NPC( d->character ) && !d->character->deaf.test(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 ) && !d->character->deaf.test(CHANNEL_INFO) )
{
snprintf( buf, MSL, "%s[INFO]: %s%s\r\n",
color_string( d->character, "info" ), message, color_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];
snprintf( buf, MSL, "[LOG]: %s\r\n", 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 ) && ( !d->character->deaf.test(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;
}
/* 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;
mob->npc = FALSE;
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:
victim->npc = TRUE;
}
victim->desc = NULL;
extract_char( victim, TRUE );
return original;
}
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->stun_timer = 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];
snprintf( buf, MSL, "shield_remove: %s did not have a shield to remove.", NAME(ch) );
monitor_chan( buf, MONITOR_MOB );
bug( "Remove_shield: no shield.", 0 );
return;
}
UNLINK( shield, ch->first_shield, ch->last_shield, next, prev );
delete shield;
return;
}
bool check_charm_aff( CHAR_DATA *ch, short charm_aff )
{
OBJ_DATA *obj;
if( ch == NULL || charm_aff < 0 )
return false;
for( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list )
if( obj->wear_loc == WEAR_NONE && obj->item_type == ITEM_CHARM && obj->value[CHARM_AFF] == charm_aff )
return true;
return false;
}
short get_charm_bonus( CHAR_DATA *ch, short charm_aff )
{
OBJ_DATA *obj;
if( ch == NULL || charm_aff < 0 )
return 0;
for( obj = ch->first_carry; obj != NULL; obj = obj->next_in_carry_list )
if( obj->wear_loc == WEAR_NONE && obj->item_type == ITEM_CHARM && obj->value[CHARM_AFF] == charm_aff )
return obj->value[CHARM_BONUS];
return 0;
}