/* -*- LPC -*- */
/*
* $Locker: $
* $Id: con_sider.c,v 1.24 2003/07/11 00:53:21 pinkfish Exp $
*
*/
#define CREATOR "Ceres"
/*
Replacement consider command. This one takes weapons, skills, armour and hit
points into account whereas the old one only compared their overall fighting
skill
*/
#include <weapon.h>
#include <cmr.h>
#include <player.h>
inherit "/cmds/base";
int calc_danger(object ob);
string do_compare(int dif);
mixed cmd(object *obs) {
object ob;
int level, ok, dif, total, them;
string out;
if(previous_object()->check_dark((int)environment(previous_object())->
query_light()) < 0) {
add_failed_mess("It's too dark to consider anyone.\n");
return 0;
}
if(previous_object()->check_dark((int)environment(previous_object())->
query_light()) > 0) {
add_failed_mess("It's too bright to consider anyone.\n");
return 0;
}
if (sizeof(obs) > 1) {
obs -= ({ this_player() });
}
if (sizeof(obs) > 5) {
add_failed_mess("You can only consider five things at once.\n");
return 0;
}
if (this_player()->query_property("dead")) {
add_failed_mess( "You're dead. You could just about kill a "
"conversation.\n" );
return 0;
}
level = calc_danger(previous_object());
foreach (ob in obs) {
if (!living(ob)) {
continue;
}
if (ob == previous_object()) {
if (sizeof(obs) == 1) {
write("You are exactly equal to yourself, you had better go and "
"arm yourself with more spiky things and try to not arm "
"your reflection at the same time. No problems?\n");
ok++;
}
continue;
}
ok++;
them = calc_danger(ob);
total += them;
// percentage difference.
dif = ((level - them) * 100) / level;
if ( userp( ob ) && this_player()->query_player_killer() &&
!ob->query_player_killer() ) {
out = replace( do_compare( dif ), "$who$", (string)ob->the_short() +
" [not a killer]" );
} else {
out = replace( do_compare( dif ), "$who$", (string)ob->the_short() );
}
if (userp(ob)) {
tell_object(ob, this_player()->the_short(1) + " looks you up and down "
"carefully checking out your weapons and armour.\n");
} else {
ob->event_npc_consider(this_player());
}
write( out +"\n" );
}
if(!ok) {
add_failed_mess("You need to consider someone.\n");
return 0;
}
return 1;
}
string do_compare(int dif) {
string ret;
int level;
ret = "$C$$who$";
// Check and see if they are drunk first.
level = PLAYER_DRUNK_EFFECT->query_drunk_level(this_player());
if (level > 4) {
if (level > 7) {
return "%^BOLD%^%^GREEN%^Mate! They looked at you wrong, you "
"better sort them out before they get more cocky.%^RESET%^";
}
return "%^BOLD%^%^GREEN%^You reckon they would be an easy "
"target. Why bother with weapons?%^RESET%^";
}
if(dif > 320) {
ret = "%^BOLD%^GREEN%^"+ret+" is too weak to bother attacking";
} else {
switch(dif) {
case 161..320:
ret = "%^BOLD%^%^GREEN%^"+ret+" is someone you look down on";
break;
case 81..160:
ret = "%^GREEN%^"+ret+" would be an easy target";
break;
case 41..80:
ret = "%^GREEN%^"+ret+" is a lot weaker than you";
break;
case 21..40:
ret = "%^GREEN%^"+ret+" is weaker than you";
break;
case 11..20:
ret = "%^CYAN%^"+ret+" is slightly weaker than you";
break;
case -10..10:
ret = "%^CYAN%^"+ret+" is about equal with you";
break;
case -20..-11:
ret = "%^CYAN%^"+ret+" is slightly tougher than you";
break;
case -40..-21:
ret = "%^RED%^"+ret+" is tougher than you";
break;
case -80..-41:
ret = "%^RED%^"+ret+" is a lot tougher than you";
break;
case -160..-81:
ret = "%^RED%^"+ret+" looks pretty nasty";
break;
case -320..-161:
ret = "%^BOLD%^%^RED%^"+ret+" is into the don't-even-think-about-it "
"region";
break;
default:
ret = "%^BOLD%^%^RED%^You would have to be utterly insane to attack "
"$who$";
break;
}
}
return ret + ".%^RESET%^";
}
int calc_weapon_damage(object weapon) {
mixed *data;
int wdam, *damage, i;
data = (mixed *)weapon->query_attack_data();
if(sizeof(data)) {
wdam = 0;
for ( i = 0; i < sizeof( data ); i += W_ARRAY_SIZE ) {
if (member_array( data[ i + W_TYPE ], ({ "blunt", "unarmed",
"sharp", "pierce" }) ) == -1 )
continue;
damage = data[ i + W_DAMAGE ];
wdam += ( data[ i + W_CHANCE ] * ( damage[ F_FIXED ] +
( damage[ F_NUM ] * damage[ F_DIE ] ) / 2 ) ) / 100;
wdam += damage[ F_FIXED ] + damage[ F_NUM ] * damage[ F_DIE ];
}
}
return wdam;
}
int calc_value(mixed arr) {
if (intp(arr))
return arr;
if (!pointerp(arr))
return 0;
if (sizeof(arr) == 1)
return arr[F_FIXED];
if (sizeof(arr) == 2)
return arr[F_FIXED]+arr[F_NUM];
return arr[F_FIXED]+(arr[F_NUM] * arr[F_DIE]);
}
int calc_armour_protection(object armour) {
int ac, i;
mapping data;
mixed *stuff;
if(!armour->query_armour())
return 0;
data = armour->query_armour_class();
if(!sizeof(data))
return 0;
stuff = keys(data);
for(i=0; i<sizeof(stuff); i++)
ac += calc_value(data[stuff[i]][0]);
return ac;
}
// calculate how dangerous ob is. Factors used include: weapon damage, weapon
// skill, defensive skill, armour worn and hit points.
int calc_danger(object ob) {
object weapon;
object *weapons;
object armour;
object rider;
int wdam;
int wskill;
int dskill;
int ac;
int hp;
int trans;
if (ob->query_transport()) {
foreach (rider in ob->query_riders()) {
trans += calc_danger(rider);
}
}
// decide which weapon to use for the consider
weapons = ob->query_holding();
if(weapons && sizeof(weapons) > 0 && (weapons[0] != 0) && (weapons[0]->
query_weapon())) {
weapon = weapons[0];
dskill = ob->query_skill_bonus("fighting.combat.parry.melee");
} else if(weapons && sizeof(weapons) > 1 && (weapons[1] != 0) &&
(weapons[1]->query_weapon())) {
weapon = weapons[1];
dskill = ob->query_skill_bonus("fighting.combat.parry.melee");
} else {
weapon = ob;
dskill = ob->query_skill_bonus("fighting.combat.parry.melee");
}
// count parry *and* dodge skill because they might change tactics
// partway through any combat.
dskill += ob->query_skill_bonus("fighting.combat.dodging.melee");
wdam = calc_weapon_damage(weapon);
if(!sizeof(weapon->query_attack_data())) {
wskill += ob->query_skill_bonus("fighting.combat.melee.unarmed");
wskill += ob->query_skill_bonus("fighting.combat.special.unarmed") / 2;
} else {
wskill += ob->query_skill_bonus("fighting.combat.melee."+
(string)weapon->query_attack_data()[W_SKILL]);
wskill += ob->query_skill_bonus("fighting.combat.special.weapon") / 2;
}
wskill += ob->query_skill_bonus("fighting.combat.special.tactics");
wskill += ob->query_specific_gp("fighting");
hp = ob->query_hp();
if(ob->query_wearing())
foreach(armour in ob->query_wearing())
if(armour)
ac += calc_armour_protection(armour);
// weighting of the different statistics
wdam /= 3;
hp /= 3;
dskill /= 2;
ac /= 6;
return trans + wdam + wskill + dskill + ac + hp;
}
mixed* query_patterns() {
return ({ "<indirect:living:here>", (: cmd($1) :) });
} /* query_patterns() */