#include "define.h"
#include "struct.h"
bool can_die ( char_data* );
void death_cry ( char_data* );
obj_data* make_corpse ( char_data*, content_array* );
void raw_kill ( char_data* );
void loot_corpse ( obj_data*, char_data*, char_data* );
void register_death ( char_data*, char_data*, char* );
/*
* HAS LIVE-SAVING?
*/
bool can_die( char_data* victim )
{
obj_data* obj;
room_data* room;
if( victim->species != NULL )
return TRUE;
if( ( room = Room( victim->array->where ) ) != NULL
&& is_set( &room->room_flags, RFLAG_ARENA ) ) {
send( *victim->array, "In a flash of light %s disappears.\r\n", victim );
victim->hit = 1;
update_pos( victim );
victim->From( );
victim->To( get_temple( victim ) );
dismount( victim );
victim->position = POS_RESTING;
return FALSE;
}
if( victim->shdata->level >= LEVEL_BUILDER ) {
fsend_seen( victim, "The body of %s slowly fades out of existence.",
victim );
fsend( *victim->array,
"A swirling mist appears and %s slowly reforms.", victim );
send( victim, "You find yourself alive again.\r\n" );
victim->hit = victim->max_hit;
update_max_move( victim );
update_pos( victim );
return FALSE;
}
for( int i = 0 ; ; i++ ) {
if( i >= victim->affected ) {
for( int j = 0; ; j++ ) {
if( j >= victim->wearing )
return TRUE;
obj = (obj_data*) victim->wearing[j];
if( is_set( obj->pIndexData->affect_flags, AFF_LIFE_SAVING ) )
break;
}
fsend( *victim->array,
"%s that %s was wearing starts to glow a deep purple!",
obj, victim );
fsend_seen( victim, "The body of %s slowly disappears!", victim );
obj->Extract( 1 );
break;
}
if( victim->affected[i]->type == AFF_LIFE_SAVING
&& number_range( 0, 100 ) > 60-2*victim->affected[i]->level ) {
send_seen( victim,
"%s disappears in an explosion of light and energy.\r\n", victim );
break;
}
}
victim->From( );
remove_affect( victim );
remove_leech( victim );
rejuvenate( victim );
victim->To( get_temple( victim ) );
dismount( victim );
victim->position = POS_RESTING;
send_seen( victim, "%s slowly materializes.\r\nFrom %s appearance\
%s obviously came close to death.\r\n",
victim, victim->His_Her( ), victim->He_She( ) );
send( victim, "You wake up confused and dazed, but seem alive despite\
your memories.\r\n" );
return FALSE;
}
bool die_forever( char_data* ch )
{
if( ch->Type( ) == MOB_DATA )
return TRUE;
return FALSE;
}
/*
* DEATH HANDLER
*/
void death( char_data* victim, char_data* ch, char* dt )
{
char tmp [ TWO_LINES ];
obj_data* corpse;
content_array* where = victim->array;
char_data* rch;
bool survive;
remove_bit( &victim->status, STAT_BERSERK );
if( ch == NULL )
for( int i = 0; i < *where; i++ )
if( ( rch = character( where->list[i] ) ) != NULL
&& includes( rch->aggressive, victim ) ) {
ch = rch;
break;
}
stop_fight( victim );
clear_queue( victim );
if( !can_die( victim ) )
return;
disburse_exp( victim );
register_death( victim, ch, dt );
clear_queue( victim );
death_cry( victim );
if( survive = !die_forever( victim ) )
raw_kill( victim );
corpse = make_corpse( victim, where );
loot_corpse( corpse, ch, victim );
if( survive )
return;
if( mob( victim ) != NULL ) {
victim->Extract( );
return;
}
sprintf( tmp, "%s's soul is taken by death.", victim->Name( ) );
info( tmp, LEVEL_BUILDER, tmp, IFLAG_DEATHS, 1, victim );
clear_screen( victim );
reset_screen( victim );
send( victim, "Death is surprisingly peaceful.\r\n" );
send( victim, "Good night.\r\n" );
purge( player( victim ) );
}
void raw_kill( char_data* victim )
{
affect_data affect;
victim->From( );
remove_affect( victim );
remove_leech( victim );
victim->position = POS_RESTING;
victim->hit = max( 1, victim->hit );
victim->mana = max( 1, victim->mana );
victim->move = max( 1, victim->move );
affect.type = AFF_DEATH;
affect.duration = 20;
affect.level = 10;
affect.leech = NULL;
add_affect( victim, &affect );
delete_list( victim->prepare );
update_maxes( victim );
victim->To( get_room_index( ROOM_DEATH, FALSE ) );
dismount( victim );
clear_enemies( victim );
write( player( victim ) );
}
void register_death( char_data* victim, char_data* ch, char* dt )
{
char tmp1 [ TWO_LINES ];
char tmp2 [ TWO_LINES ];
mprog_data* mprog;
int exp;
if( victim->species != NULL ) {
if( is_set( &victim->status, STAT_PET ) && victim->leader != NULL
&& victim->leader->pcdata != NULL ) {
sprintf( tmp1, "%s killed by %s at %s. (Pet)",
victim->Name( ), ch == NULL ? dt : ch->Name( ),
victim->array->where->Location( ) );
player_log( victim->leader, tmp1 );
}
for( mprog = victim->species->mprog; mprog != NULL;
mprog = mprog->next )
if( mprog->trigger == MPROG_TRIGGER_DEATH ) {
var_mob = victim;
var_ch = ch;
var_room = Room( victim->array->where );
execute( mprog );
}
return;
}
sprintf( tmp1, "%s killed by %s.", victim->Name( ),
ch == NULL ? dt : ch->Name( ) );
sprintf( tmp2, "%s killed by %s at %s.", victim->Name( ),
ch == NULL ? dt : ch->Name( ), victim->array->where->Location( ) );
info( tmp1, LEVEL_APPRENTICE, tmp2, IFLAG_DEATHS, 1, victim );
exp = death_exp( victim, ch );
add_exp( victim, -exp, "You lose %d exp for dying.\r\n" );
sprintf( tmp1, "Killed by %s at %s.",
ch == NULL ? dt : ch->real_name( ), victim->array->where->Location( ) );
player_log( victim, tmp1 );
if( ch != NULL && ch->pcdata != NULL ) {
sprintf( tmp1, "Pkilled %s at %s.",
victim->real_name( ), victim->array->where->Location( ) );
player_log( ch, tmp1 );
}
}
/*
* DEATH CRY
*/
void death_message( char_data* victim )
{
char tmp1 [ ONE_LINE ];
char tmp2 [ ONE_LINE ];
char_data* rch;
const char* name;
for( int i = 0; i < *victim->array; i++ ) {
if( ( rch = character( victim->array->list[i] ) ) == NULL
|| rch->link == NULL || rch == victim || !victim->Seen( rch ) )
continue;
name = victim->Name( rch );
send( rch, bold_red_v( rch ) );
if( victim->species != NULL
&& is_set( &victim->species->act_flags, ACT_MELT ) ) {
sprintf( tmp1, " +-- %%%ds --+\r\n", strlen( name )+11 );
sprintf( tmp2, tmp1, "" );
sprintf( tmp1, " %s SHATTERS!!\r\n", name );
}
else {
sprintf( tmp1, " +-- %%%ds --+\r\n", strlen( name )+10 );
sprintf( tmp2, tmp1, "" );
sprintf( tmp1, " %s is DEAD!!\r\n", name );
}
tmp1[6] = toupper( tmp1[6] );
send( rch, tmp2 );
send( rch, tmp1 );
send( rch, tmp2 );
send( rch, normal( rch ) );
}
send( victim, "You have been KILLED!!\r\n" );
}
void death_cry( char_data* ch )
{
room_data* room;
char* msg;
if( ( room = Room( ch->array->where ) ) == NULL )
return;
msg = ch->species ? "You hear something's death cry.\r\n"
: "You hear someone's death cry.\r\n";
for( int i = 0; i < room->exits; i++ )
send( room->exits[i]->to_room->contents, msg );
if( is_set( &ch->status, STAT_FAMILIAR ) && ch->leader != NULL )
send( ch->leader, "You sense your familiars death!\r\n" );
}
/*
* CORPSE ROUTINES
*/
const char* fragments_msg =
"The fragments from %s quickly melt, leaving %s %s.";
obj_data* make_corpse( char_data* ch, content_array* where )
{
obj_data* corpse;
obj_data* obj;
obj_clss_data* obj_clss;
thing_data* thing;
int i;
/* GHOSTS */
if( ch->species != NULL && is_set( &ch->species->act_flags, ACT_GHOST ) ) {
for( i = ch->wearing-1; i >= 0; i-- ) {
thing = ch->wearing[i]->From( ch->wearing[i]->number );
thing->To( &ch->contents );
}
send_publ( ch, &ch->contents, "fades out of existence", "dropping" );
for( i = ch->contents.size-1; i >= 0; i-- ) {
thing = ch->contents[i]->From( ch->contents[i]->number );
thing->To( where );
}
return NULL;
}
/*
if( ch->species != NULL && is_set( &ch->species->act_flags, ACT_MELT ) ) {
if( ( obj = ch->contents ) == NULL ) {
fsend_room( room, fragments_msg, ch, "nothing", "behind" );
}
else if( obj->next_content == NULL ) {
fsend_room( room, fragments_msg, ch, obj,
"lying on the ground" );
}
else {
fsend_room( room, fragments_msg, ch, "several items",
"on the ground" );
}
for( ; obj != NULL; obj = ch->contents ) {
obj = remove( obj, obj->number );
put_obj( obj, room );
}
return NULL;
}
*/
/* CREATE CORPSE */
if( ch->species != NULL ) {
if( ( obj_clss = get_obj_index( ch->species->corpse ) ) == NULL )
return NULL;
corpse = create( obj_clss );
if( obj_clss->item_type == ITEM_CORPSE )
corpse->value[1] = ch->species->vnum;
}
else {
corpse = create( get_obj_index( OBJ_CORPSE_PC ) );
corpse->value[1] = ch->pcdata->pfile->ident;
}
/* WEIGHT */
if( corpse->pIndexData->item_type == ITEM_CORPSE
&& corpse->pIndexData->weight == 0 )
corpse->weight = ch->Empty_Weight( );
/* NAME CORPSE */
if( !strncmp( corpse->pIndexData->singular, "corpse of", 9 ) ) {
char* tmp = static_string( );
if( ch->descr->name != empty_string ) {
sprintf( tmp, "corpse of %s", ch->descr->name );
corpse->singular = alloc_string( tmp, MEM_OBJECT );
sprintf( tmp, "%s corpses", ch->descr->name );
corpse->plural = alloc_string( tmp, MEM_OBJECT );
}
else {
sprintf( tmp, "corpse of %s", ch->Name( NULL ) );
corpse->singular = alloc_string( tmp, MEM_OBJECT );
sprintf( tmp, "%s corpses", seperate( ch->descr->singular, TRUE ) );
corpse->plural = alloc_string( tmp, MEM_OBJECT );
}
}
/* TRANSFER ITEMS TO CORPSE */
for( i = ch->wearing-1; i >= 0; i-- ) {
if( ch->species != NULL || number_range( 0,10 ) == 0 ) {
obj = (obj_data*) ch->wearing[i];
obj->From( obj->number );
obj->To( corpse );
}
}
for( i = ch->contents-1; i >= 0; i-- ) {
if( ( obj = object( ch->contents[i] ) ) != NULL
&& ( ch->species != NULL || number_range( 0,10 ) == 0 ) ) {
obj = (obj_data*) obj->From( obj->number );
obj->To( corpse );
}
}
corpse->To( where );
return corpse;
}
void loot_corpse( obj_data* corpse, char_data* ch, char_data* victim )
{
if( ch == NULL || ch->pcdata == NULL
|| victim->species == NULL || corpse == NULL )
return;
int level = level_setting( &ch->pcdata->pfile->settings,
SET_AUTOLOOT );
if( level == 0 )
return;
if( level == 1 ) {
send_priv( ch, &corpse->contents, "contains", corpse );
return;
}
/*
for( obj = corpse->contents; obj != NULL; obj = next ) {
next = obj->next_content;
if( obj->pIndexData->item_type == ITEM_MONEY ) {
for( i = 0; i < MAX_COIN; i++ )
if( obj->pIndexData->vnum == coin_vnum[i] )
amount += obj->number*coin_value[i];
}
else {
if( !is_set( ch->pcdata->pfile->flags, PLR_AUTO_LOOT ) )
continue;
}
obj->next_list = get;
get = obj;
obj->selected = obj->number;
}
get_obj( ch, get, corpse );
if( is_set( ch->pcdata->pfile->flags, PLR_AUTO_SPLIT ) )
split_money( ch, amount, FALSE );
*/
}
/*
* SLAY ROUTINE
*/
void do_slay( char_data* ch, char* argument )
{
char_data* victim;
if( ch->shdata->level < LEVEL_BUILDER ) {
send( ch, "To prevent abuse you are unable to use slay in\
mortal form.\r\n" );
return;
}
if( *argument == '\0' ) {
send( ch, "Slay whom?\r\n" );
return;
}
if( ( victim = one_character( ch, argument, "slay",
ch->array ) ) == NULL )
return;
if( ch == victim ) {
send( ch, "Suicide is a mortal sin.\r\n" );
return;
}
if( victim->species == NULL
&& ( get_trust( victim ) >= get_trust( ch )
|| !has_permission( ch, PERM_PLAYERS ) ) ) {
send( ch, "You failed.\r\n" );
return;
}
send( ch, "You slay %s in cold blood!\r\n", victim );
send( victim, "%s slays you in cold blood!\r\n", ch );
send( *ch->array, "%s slays %s in cold blood!\r\n", ch, victim );
make_corpse( victim, ch->array );
if( victim->species == NULL )
raw_kill( victim );
else
victim->Extract( );
}
/*
* EXTRACTION ROUTINES
*/
void dereference( char_data* wch, char_data* ch )
{
player_data* pc;
wizard_data* imm;
if( !wch->Is_Valid( ) )
return;
if( wch->cast != NULL && wch->cast->target == ch )
disrupt_spell( wch );
wch->seen_by -= ch;
wch->known_by -= ch;
if( wch->reply == ch ) {
if( is_set( &wch->status, STAT_REPLY_LOCK ) ) {
send( wch, "%s has quit - reply lock removed.\r\n", ch );
remove_bit( &wch->status, STAT_REPLY_LOCK );
}
wch->reply = NULL;
}
if( ( imm = wizard( wch ) ) != NULL
&& imm->player_edit == ch ) {
send( imm, "The player you were editing just quit.\r\n" );
imm->player_edit = NULL;
}
if( ( pc = player( wch ) ) != NULL
&& pc->familiar == ch )
pc->familiar = NULL;
}
void Char_Data :: Extract( )
{
affect_data* affect;
char_data* wch;
obj_array* array;
mob_data* npc;
player_data* pc;
wizard_data* imm;
int i;
/* REMOVE WORLD REFERENCES */
if( !Is_Valid( ) ) {
roach( "Extract Char: Extracting invalid character." );
return;
}
if( species != NULL ) {
if( link != NULL )
do_return( this, "" );
unregister_reset( this );
}
if( link != NULL ) {
link->character = NULL;
link->player = NULL;
link = NULL;
}
if( this->array != NULL )
From( );
clear_queue( this );
if( ( pc = player( this ) ) != NULL ) {
remove( request_app, pc );
remove( request_imm, pc );
}
/* CLEAR EVENTS */
stop_events( this );
unlink( &active );
active.time = -1;
/* EXTRACT OBJECTS */
if( ( pc = player( this ) ) != NULL ) {
array = &pc->save_list;
for( int i = 0; i < array->size; i++ )
if( array->list[i] != NULL )
array->list[i]->save = NULL;
clear( *array );
extract( pc->locker );
extract( pc->junked );
}
extract( contents );
extract( wearing );
/* REMOVE FOLLOWERS */
if( leader != NULL ) {
if( ( pc = player( leader ) ) != NULL
&& pc->familiar == this )
pc->familiar = NULL;
leader->followers -= this;
leader = NULL;
}
for( i = 0; i < followers; i++ ) {
wch = followers[i];
wch->leader = NULL;
if( wch->species != NULL && is_set( &wch->status, STAT_PET ) ) {
send_seen( wch,
"%s goes into limbo and awaits %s master's return.\r\n",
wch, wch->His_Her( ) );
wch->Extract( );
}
}
clear( followers );
/* REMOVE REFERENCES ON OTHER PLAYERS */
for( i = 0; i < player_list; i++ )
dereference( player_list[i], this );
for( i = 0; i < mob_list; i++ )
dereference( mob_list[i], this );
if( mount != NULL ) {
mount->rider = NULL;
mount = NULL;
}
if( rider != NULL ) {
rider->mount = NULL;
rider = NULL;
}
/*
* FREE MEMORY
*/
remove_leech( this );
for( i = 0; i < affected; i++ ) {
affect = affected[i];
if( affect->leech != NULL )
fsend( affect->leech, "Leech for %s on %s dissipated.",
aff_char_table[affect->type].name, descr->name );
remove_leech( affect );
}
clear( affected );
extract( enemy );
delete_list( prepare );
clear( cmd_queue );
clear( known_by );
clear( seen_by );
clear( seen_exits );
if( species == NULL || descr != species->descr )
delete descr;
if( ( pc = player( this ) ) != NULL ) {
delete_list( pc->alias );
delete_list( pc->tell );
delete_list( pc->gtell );
delete_list( pc->ctell );
delete_list( pc->whisper );
delete_list( pc->chat );
delete_list( pc->gossip );
delete_list( pc->say );
delete_list( pc->yell );
delete_list( pc->shout );
delete_list( pc->atalk );
delete_list( pc->to );
delete_list( pc->chant );
}
if( ( imm = wizard( this ) ) != NULL ) {
delete_list( imm->build_chan );
delete_list( imm->imm_talk );
delete_list( imm->god_talk );
delete_list( imm->avatar );
free_string( imm->bamfin, MEM_WIZARD );
free_string( imm->bamfout, MEM_WIZARD );
free_string( imm->level_title, MEM_WIZARD );
}
if( ( npc = mob( this ) ) != NULL ) {
if( npc->pTrainer != NULL )
npc->pTrainer->mob = NULL;
free_string( npc->pet_name, MEM_MOBS );
}
if( pcdata != NULL ) {
free_string( pcdata->title, MEM_PLAYER );
free_string( pcdata->buffer, MEM_PLAYER );
free_string( pcdata->tmp_short, MEM_PLAYER );
free_string( pcdata->tmp_keywords, MEM_PLAYER );
free_string( pcdata->prompt, MEM_PLAYER );
delete pcdata->recognize;
delete pcdata;
delete shdata;
}
pcdata = NULL;
shdata = NULL;
descr = NULL;
species = NULL;
position = POS_EXTRACTED;
pShop = NULL;
reset = NULL;
valid = -1;
extracted += this;
}