/**
* This is the health handler.
* Spits out health strings for livings and a bit fancier
* strings for the health command. Also deals with
* attacking checks and prints the monitor.
* @author Sandoz
*/
#include <player.h>
#define RED "%^RED%^"
#define CYAN "%^CYAN%^"
#define YELL "%^YELLOW%^"
#define RES "%^RESET%^"
#define NAME "$who$ "
private mapping monitor_queue;
private int flush_id;
private void flush_monitor_queue();
/** @ignore yes */
void create() {
monitor_queue = ([ ]);
} /* create() */
/** @ignore yes */
void dest_me() {
destruct(TO);
} /* dest_me() */
/**
* This method does all the checks required for any
* aggressive commands. If the attack argument is 0,
* then combat will not be initiated, if 1, then the
* targets will be attacked.
* @param things the things to test
* @param attack if this is 0, then combat will not be
* initiated, if 1, then the things that pass the checks
* will be attacked
*/
object *do_attack_checks( object *things, int attack ) {
object thing;
int dark;
if( !ENV( TP ) ) {
add_failed_mess("You are in limbo...\n" );
return 0;
}
if( TP->no_offense() ) {
add_failed_mess("You cannot attack anyone at the moment.\n" );
return 0;
}
things -= ({ TP });
if( !sizeof( things ) ) {
add_failed_mess("You cannot attack yourself!\n");
return 0;
}
dark = TP->check_dark( (int)ENV(TP)->query_light() );
if( dark > 1 ) {
add_failed_mess("It is way too bright to attack anyone.\n");
return 0;
}
if( dark < -1 ) {
add_failed_mess("It is way too dark to attack anyone.\n");
return 0;
}
foreach( thing in things ) {
if( thing->query_property( PASSED_OUT ) ) {
write("You cannot attack "+(string)thing->the_short()+" since "+
(string)thing->HE+" is passed out.\n");
things -= ({ thing });
continue;
}
if( !userp( thing ) ) {
if( userp( TP ) || !thing->query_property("no attack") ) {
switch( dark ) {
case -1:
if( !random( 2 ) ) {
write("You peer into the darkness, but fail to "
"find "+(string)thing->the_short()+".\n");
things -= ({ thing });
continue;
}
write("You just manage to make out "+
(string)thing->the_short()+".\n");
break;
case 1:
if( !random(2) ) {
write("You squint as hard as you can, but fail to "
"find "+(string)thing->the_short() +".\n");
things -= ({ thing });
continue;
}
write("You just manage to make out "+
(string)thing->the_short()+".\n");
default:
}
if( attack )
TP->attack_ob( thing );
}
continue;
}
if( !interactive( thing ) ) {
write( (string)thing->the_short() +" is net-dead.\n");
things -= ({ thing });
continue;
}
if( thing->query_property( "guest" ) ) {
write("You cannot attack "+(string)thing->the_short()+" since "+
(string)thing->HE+" is a guest.\n");
things -= ({ thing });
continue;
}
if( thing->query_auto_loading() ) {
write("Be sporting; "+(string)thing->the_short()+" doesn't have "+
(string)thing->HIS+" equipment yet.\n");
things -= ({ thing });
continue;
}
if( userp( TP ) && !TP->query_property( PKER ) ) {
write("You cannot summon the courage to attack "+
(string)thing->the_short() +".\n");
things -= ({ thing });
continue;
}
if( userp( TP ) && pk_check( TP, thing ) ) {
write("Something tells you that it would be wrong to attack "+
(string)thing->the_short() +".\n");
things -= ({ thing });
continue;
}
switch( dark ) {
case -1:
if( !random( 2 ) ) {
write("You peer into the darkness, but fail to "
"find "+(string)thing->the_short()+".\n");
things -= ({ thing });
continue;
}
write("You just manage to make out "+
(string)thing->the_short()+".\n");
break;
case 1:
if( !random( 2 ) ) {
write("You squint as hard as you can, but fail to "
"find "+(string)thing->the_short() +".\n");
things -= ({ thing });
continue;
}
write("You just manage to make out "+
(string)thing->the_short()+".\n");
default:
}
if( attack )
TP->attack_ob( thing );
}
return things;
} /* do_attack_checks() */
/**
* This method returns the health string of the creature.
* It is used in extra_look in living creatures and in the 'health' command.
* @param who the creature to get the health string for
* @param full whether or not to returns the full (coloured) health string
* @return the health string
*/
varargs string health_string( object who, int full ) {
int per, current;
string msg;
if( !objectp(who) )
return 0;
if( who->query_property( "dead" ) ) {
msg = "appears to be dead";
return ( full ? NAME+msg+"." : msg );
}
current = ( who->query_name() == "death" ? 1 : (int)who->query_hp() );
per = 100 * current / ( (int)who->query_max_hp() || 1 );
// DO NOT CHANGE THESE MESSAGES ON PAIN OF DEATH
// - SHAYDZ
switch( per ) {
case -100..10:
msg = "is in very bad shape";
return ( full ? RED+NAME+msg+"."+RES : msg );
case 11..30:
msg = "is in bad shape";
return ( full ? RED+NAME+msg+"."+RES : msg );
case 31..60:
msg = "is not in good shape";
return ( full ? YELL+NAME+msg+"."+RES : msg );
case 61..95:
msg = "is slightly hurt";
return ( full ? CYAN+NAME+msg+"."+RES : msg );
case 96..100:
msg = "is in good shape";
return ( full ? NAME+msg+"." : msg );
default:
msg = "is rather buggy and you should probably contact a creator";
return ( full ? NAME+msg+"." : msg );
}
} /* health_string() */
/**
* This method prints out the health and gp points during combat,
* if the player so desires. Moved to here from the combat effect.
* @param player the object recieving the monitor message
* @param charge non-zero to charge the player gp points for the message
* @see query_monitor
*/
void monitor_points( object player, int charge ) {
int hp, max;
string colour;
if( charge && player->adjust_gp( -1 ) < 0 )
return;
hp = player->query_hp();
max = player->query_max_hp();
switch( ( hp * 100 ) / max ) {
case 61..100:
colour = "%^GREEN%^";
break;
case 31..60:
colour = "%^YELLOW%^";
break;
default :
colour = "%^RED%^";
}
tell_object( player, colour + "Hp: " + hp + " (" + max + ") "
"Gp: "+(int)player->query_gp()+" ("+player->query_max_gp()+") "
"Xp: "+(int)player->query_xp()+"%^RESET%^\n");
} /* monitor_points() */
/**
* This method is used by combat to display the monitor after
* all heartbeats have finished.
* @param ob the object to print the monitor to
* @param charge non-zero to charge the player gp points for the message
*/
void register_monitor( object ob, int charge ) {
if( !userp(ob) )
return;
if( undefinedp( monitor_queue[ob] ) || charge )
monitor_queue[ob] = charge;
if( !flush_id )
flush_id = call_out( (: flush_monitor_queue :), 0 );
} /* register_monitor() */
/** @ignore yes */
private void flush_monitor_queue() {
flush_id = 0;
foreach( object ob, int charge in monitor_queue ) {
if( ob )
monitor_points( ob, charge );
}
monitor_queue = ([ ]);
} /* flush_monitor_queue() */