// equip.c by Dank. Copyright 1993 by Dan Kindsvater on everything but
// function names borrowed from Discworld mudlib. Keep this header if you use
// any docs or code from this file.
inherit "/std/living/combat"; //this will go when combat.c is done.
//inherit "/std/armor_logic";
//inherit "weapon_logic";
private object *held_ob, *armors;
private int ac;
private string *armor_types;
private status *useless_hands, *cursed_hands, *amputated_hands, *free_hands;
private status hand;
string weapon;
// prototypes:
status remove_armor(object armor);
void do_equip(status mess);
object query_held_ob(int i) { return held_ob[i]; }
status set_held_ob(int i, object ob) { held_ob[i] = ob; return 1; }
object *query_armors()
{
int i;
object *aa;
aa = ({ });
for(i=0; i<sizeof(armors); i++)
if(armors[i]!=0 && objectp(armors[i]))
aa += ({ armors[i] });
armors = aa;
return armors;
}
/*
string query_pronoun() { return (string)this_object()->query_pronoun(); }
*/
create() {
combat::create();
// armor_logic::create();
held_ob = ({ 0, 0 });
armors = ({ });
ac = 0;
armor_types = ({ });
useless_hands = ({ 0, 0 });
cursed_hands = ({ 0, 0 });
amputated_hands = ({ 0, 0 });
free_hands = ({ 1, 1 });
hand = 0;
weapon = 0;
}
int query_ac() { return ac; }
status adjust_ac(int i) { ac += i; return 1; }
status add_ac(int i) { ac += i; return 1; }
void calc_free_hands() {
int i; object ob;
for (i=0; i<2; i++) {
ob = held_ob[i];
if ( (ob && ob->query_cursed() && (!ob->query_weapon() || !i))
|| (ob && ob->query_armor())
|| (ob && cursed_hands[i]) || useless_hands[i] )
free_hands[i] = 0;
else
free_hands[i] = 1;
}
if (ob && ob==held_ob[0] && mini(free_hands)==0) {
free_hands[0] = 0;
free_hands[1] = 0;
}
}
status set_amputated_hands(int i, status amputated) {
int j, k; string *str; object ob, guild_ob;
amputated_hands[i] = amputated;
useless_hands[i] = amputated;
if (amputated) {
str = ({ "right", "left" });
tell_room(environment(),this_object()->query_cap_name()+" loses "+this_object()->query_possessive()
+" "+str[j]+ " hand! "+this_object()->query_pronoun()+" drops everything from the "
"shock!\n", this_object());
tell_object(this_object(),"You lose your "+str[j]+" hand! You drop "
"everything from the shock!\n");
for (j=0; j<2; j++)
if (ob=held_ob[j]) {
held_ob[j] = 0;
if (!ob->query_weapon())
ob->set_held(0);
else
ob->set_wielder(0);
ob->set_drop();
ob->move(environment());
tell_room(environment(),this_object()->query_cap_name()+" drops "+this_object()->query_possessive()
+" "+ob->short(0)+".\n", this_object());
tell_object(this_object(),"You drop your "+ob->short(0)+".\n");
}
guild_ob = this_object()->query_guild_ob();
if (!guild_ob) guild_ob = "/std/guild";
weapon_attack_out = (int *)guild_ob->set_weapon_attack_out(0, held_ob);
if (j = member_array("gloves", armor_types)!=-1) {
ob = armors[j];
ob->set_wearer(0);
adjust_ac(-((int)ob->query_ac()));
ob->set_drop();
ob->move(environment());
tell_room(environment(),this_object()->query_cap_name()+" drops "+this_object()->query_possessive()
+" "+ob->short(0)+".\n", this_object());
tell_object(this_object(),"You drop your "+ob->short(0)+".\n");
armors = delete(armors,j,1);
armor_types = delete(armor_types,j,1);
}
}
calc_free_hands();
return 1;
}
status query_amputated_hands(status hand) { return amputated_hands[hand]; }
status set_useless_hands(int i, status useless) {
int j; string *str; object ob, guild_ob;
str = ({ "right", "left" });
useless_hands[i] = useless;
if (i == 1) {
tell_room(environment(),this_object()->query_cap_name()+" loses the use of "+
this_object()->query_possessive()+" "+str[j]+ " hand! "+this_object()->query_pronoun()+
" drops everything from the shock!\n", this_object());
tell_object(this_object(),"You lose the use of your "+str[j]+" hand! "
"You drop everything from the shock!\n");
for (j=0; j<2; j++)
if (ob=held_ob[j]) {
if (ob->query_armor())
remove_armor(ob);
if (!ob->move(environment())) { //MOVE_OK is 0 in move_failures.h
tell_room(environment(),this_object()->query_cap_name()+" drops "+
this_object()->query_possessive()+" "+ob->short(0)+".\n", this_object());
tell_object(this_object(),"You drop your "+ob->short(0)+".\n");
}
}
}
guild_ob = this_object()->query_guild_ob();
if (!guild_ob) guild_ob = "/std/guild";
weapon_attack_out = (int *)guild_ob->set_weapon_attack_out(0, held_ob);
calc_free_hands();
return 1;
}
status query_useless_hands(status hand) { return useless_hands[hand]; }
status set_cursed_hands(int i, status cursed) {
cursed_hands[i] = cursed;
calc_free_hands();
return 1;
}
status query_cursed_hands(status hand) { return cursed_hands[hand]; }
status set_hand(status i) { hand = i; return 1; }
status query_hand() { return hand; }
// called from dest_me() in /obj/armor.c
void dest_armor(object armor) {
int i;
if ((string)armor->query_type() == "shield") {
held_ob[1] = 0;
calc_free_hands();
}
i = member_array(armor, armors);
armors = delete(armors, i, 1);
armor_types = delete(armor_types, i, 1);
adjust_ac(-((int)armor->query_ac()));
}
void wear_remove_mess(object armor, string str1, string str2, string str3) {
tell_room(environment(), this_object()->query_cap_name()+" tries to "+str1+" "+
add_a(armor->short(0))+", but "+this_object()->query_pronoun()+" "+str2+".\n",
this_object());
tell_object(this_object(), "You try to "+str1+" "+add_a(armor->short(0))+
", but you "+str3+".\n");
}
// mess = 1 means we want a message that the object is unheld. Before
// unhold_ob() is called, set_held(0) or set_wielder(0) is called in the
// item to make sure the item will successfully be unheld or unwielded.
int unhold_ob(status mess, object ob) {
int i; object guild_ob;
if ((i = member_array(ob, held_ob))==-1) {
notify_fail("Bug! The object was not unheld or unwielded.\n");
return 0;
}
held_ob[i] = 0;
if (!ob->query_weapon()) {
ob->set_held(0);
if (mess = 1) {
tell_room(environment(), this_object()->query_cap_name()+" puts "+
this_object()->query_possessive()+" "+ob->short(0)+" away.\n", this_object());
tell_object(this_object(),"You put your "+ob->short(0)+" away.\n");
}
}
else {
ob->set_wielder(0);
guild_ob = this_object()->query_guild_ob();
if (!guild_ob) guild_ob = "/std/guild";
weapon_attack_out = (int *)guild_ob->set_weapon_attack_out(mess,
held_ob);
}
calc_free_hands();
if (held_ob[1-i] == ob) // ie if it's a twohanded item
return unhold_ob(mess, held_ob[1-i]);
}
// Before calling hold_ob() we make sure that any item in that hand, or in
// both hands if it's a twohanded item, has been unheld, and that this
// item will be successfully held.
status hold_ob(object ob, int hand) {
int i; object guild_ob; string curse;
curse = "";
held_ob[hand] = ob;
if (ob->query_cursed() || cursed_hands[hand] )
curse = " It sticks to your hand!\n";
if (ob->query_twohanded()) {
held_ob[1-hand] = ob;
if (cursed_hands[1-hand] || curse)
curse = "It sticks to your hands!\n";
}
if (ob->query_weapon()) {
ob->set_wielder(this_object());
guild_ob = this_object()->query_guild_ob();
if (!guild_ob) guild_ob = "/std/guild";
weapon_attack_out = (int *)guild_ob->set_weapon_attack_out(1, held_ob);
}
else {
ob->set_held(1);
tell_room(environment(), this_object()->query_cap_name()+" holds "+
this_object()->query_possessive()+" "+ob->short(0)+ ".\n"+curse, this_object());
tell_object(this_object(),"You hold your "+ob->short(0)+".\n"+curse);
}
calc_free_hands();
return 1;
}
status hold_wield(string str, int j)
{ // j is which hand
int i;
object *obs;
object ob, ob2;
string h;
obs = find_match(str, this_object());
if(!obs || !sizeof(obs))
ob = 0;
else
ob = obs[0];
if (j)
h = "hold";
else
{
weapon = str;
h = "wield";
j = 1;
}
if (j && (i=member_array("shield", armor_types))!=-1)
{
tell_object(this_object(),"You must 'remove shield' to put away your "
+(str=ob->short(0))+".\n");
tell_room(environment(), this_object()->query_cap_name()+" must 'remove shield' to put"
" away "+this_object()->query_possessive()+" "+str+".\n",this_object());
return 0;
}
if (!str || str == "hands" || str == "nothing")
str = "";
if (!held_ob[j] && str=="") {
tell_room(environment(), this_object()->query_cap_name()+" isn't "+h+"ing anything.\n",
this_object());
tell_object(this_object(),"You aren't "+h+"ing anything.\n");
return 0;
}
else if (held_ob[j])
if (cursed_hands[j]||(held_ob[j]->query_twohanded()&&cursed_hands[1-j])){
wear_remove_mess(held_ob[j], "put away", "can't get "+
this_object()->query_possessive()+" hand to let go",
"can't get your hand to let go");
return 0;
}
else if (!free_hands[j]) {
wear_remove_mess(held_ob[j], "put away", "can't! It's cursed!",
"can't! It's cursed!");
return 0;
}
if (str=="") {
unhold_ob(1, held_ob[j]);
return 1;
}
if (useless_hands[j]) {
tell_room(environment(), this_object()->query_cap_name()+" tries to "+h+" "+str+
", but "+this_object()->query_pronoun()+" has no useful "+h+"ing hand.\n",
this_object());
tell_object(this_object(),"You try to "+h+" "+str+", but "
"you have no useful "+h+"ing hand.\n");
return 0;
}
obs = find_match(str, this_object());
if (!sizeof(obs)) {
tell_room(environment(), this_object()->query_cap_name()+" tries to "+h+" "+str+
", but "+this_object()->query_pronoun()+" doesn't have that.\n", this_object());
tell_object(this_object(),"You try to "+h+" "+str+", but "
"you don't have that.\n");
return 0;
}
ob = 0; ob2 = 0;
for (i=0;i<sizeof(obs);i++)
{
if (obs[i]->set_held(obs[i]->query_held()) )
{
if (member_array(obs[i], held_ob)==-1)
{
if (!obs[i]->query_twohanded() || free_hands[1-j])
{
if (held_ob[j])
unhold_ob(0, held_ob[j]);
if (held_ob[1-j] && obs[i]->query_twohanded())
unhold_ob(0, held_ob[1-j]);
hold_ob(obs[i], j);
return 1;
}
else if (!ob2) {
ob = obs[i];
continue;
}
}
else if (!ob)
ob2 = obs[i];
}
}
if (ob)
{
if (ob == held_ob[j])
{
wear_remove_mess(ob, h, "is already "+h+"ing it", "are already "+
h+"ing it");
}
else
{
wear_remove_mess(ob, h, "must first release it from the other hand",
"must first release it from the other hand");
}
}
else if (ob2)
{
wear_remove_mess(ob2, h, "doesn't have both hands free, "
"and it take two hands to "+h+" it", "don't have both hands free, "
"and it take two hands to "+h+" it");
}
else if (obs[0]->query_armor())
{
wear_remove_mess(obs[0], h, "probably wants to 'wear' it instead",
"probably want to 'wear' it instead");
}
else {
tell_room(environment(), this_object()->query_cap_name()+" doesn't have to "+h+" "+
// Aragorn temp fix until some1 can code it properly...
// add_a(ob->short(0))+".\n",this_object());
//
str+".\n",this_object());
tell_object(this_object(), "It's not necessary for you to "+h+" "+
// add_a(ob->short(0))+".\n");
str+".\n");
}
return 1;
}
status hold(string str) { return hold_wield(str, 1); }
status wield(string str) { return hold_wield(str, 0); }
status wear_armor(object armor) {
int num, i; string type; object guild_ob;
if (member_array(armor, armors)!=-1) {
wear_remove_mess(armor, "wear", "is already wearing that",
"are already wearing that");
return 0;
}
type = armor->query_type();
if (i=member_array(type, armor_types)!=-1) {
num = 1;
if (type=="ring" && member_array(type, armor_types[i+1..-1])!=-1)
num = 2;
}
// the guild object can query the race object if it needs to
guild_ob = this_object()->query_guild_ob();
if(!guild_ob) guild_ob = "/std/guild";
if(guild_ob)
if (num > guild_ob->query_number_worn(type)) {
if (num == 1)
wear_remove_mess(armor, "wear", "isn't trained in wearing that",
"aren't trained in wearing that");
else
wear_remove_mess(armor, "wear", "can't wear any more of those",
"can't wear any more of those");
return 0;
}
if (type == "armor" && member_array("cloak", armor_types)!=-1) {
wear_remove_mess(armor, "wear", "forgot to remove a cloak first",
"forgot to remove your cloak first");
return 0;
}
if (type == "gloves" && mini(free_hands) == 0) {
wear_remove_mess(armor, "wear", "doesn't have both hands free",
"don't have both hands free");
return 0;
}
if (type == "shield")
if (free_hands[1] == 0) {
wear_remove_mess(armor, "wear", "doesn't have "+this_object()->query_possessive()+
" shield hand free", "don't have your shield hand free");
return 0;
}
// Well, finally...everything above this line means you don't wear the armor,
// everything below this line means you do.
else if (held_ob[1]) {
unhold_ob(0, held_ob[1]);
held_ob[1] = armor;
calc_free_hands();
}
if (type == "armor") {
tell_room(environment(),this_object()->query_cap_name()+" begins to wear"+
this_object()->query_possessive()+" body armor.\n", this_object());
tell_object(this_object(), "You begin to wear your body armor.\n");
call_out("armor_call_out", 2+2*random(3), "wearing", 0, armor, type);
}
else {
armor->set_wearer(this_object());
armors += ({ armor });
armor_types += ({ type });
adjust_ac((int)armor->query_ac());
}
return 1;
} // wear_armor()
void armor_call_out(string str, int i, object armor, string type) {
tell_room(environment(), this_object()->query_cap_name()+" is finally "
"finished "+str+" "+this_object()->query_possessive()+" body armor.\n",
this_object());
tell_object(this_object(), "You're finally finished "+str+" your body"
" armor.\n");
if (str == "wearing") {
armor->set_wearer(this_object());
armors += ({ armor });
armor_types += ({ type });
adjust_ac((int)armor->query_ac());
}
else {
armor->set_wearer(0);
armors = delete(armors,i,1);
armor_types = delete(armor_types,i,1);
adjust_ac(-((int)armor->query_ac()));
}
}
status remove_armor(object armor) {
int i; string type;
type = (string)armor->query_type();
if (member_array(armor, armors)==-1) {
wear_remove_mess(armor, "remove", "isn't wearing that",
"aren't wearing that");
return 0;
}
if (type == "armor" && member_array("cloak", armor_types)!=-1) {
wear_remove_mess(armor, "remove", "forgot to remove a cloak first",
"forgot to remove your cloak first");
return 0;
}
if (type == "gloves" && (mini(free_hands)==0)) {
wear_remove_mess(armor, "remove", "doesn't have both hands free",
"don't have both hands free");
return 0;
}
if (armor->query_cursed()) {
wear_remove_mess(armor, "remove", "can't! It's cursed",
"can't! It's cursed");
return 0;
}
if (type == "shield") {
wear_remove_mess(armor, "remove", "can't get "+this_object()->query_possessive()+
" hand to let go", "can't get your hand to let go");
return 0;
}
// Well, finally...everything above this line means you don't remove the
// armor, everything below this line means you do.
else {
held_ob[1] = 0;
calc_free_hands();
}
if (type == "armor") {
tell_room(environment(),this_object()->query_cap_name()+" begins to remove "+
this_object()->query_possessive()+" body armor.\n", this_object());
tell_object(this_object(), "You begin to remove your body armor.\n");
// body armor takes 1 to 4 rounds longer than other armor to wear.
call_out("armor_call_out", 2+2*random(3), "removing", i, armor, type);
}
else {
armor->set_wearer(0);
armors = delete(armors,i,1);
armor_types = delete(armor_types,i,1);
adjust_ac(-((int)armor->query_ac()));
}
return 1;
}
void wear(string str) {
int i; object *obs;
if (!str) {
notify_fail("Wear what? Use remove if you want to remove armor.\n");
return;
}
if (str == "all") {
do_equip(1);
return;
}
obs = find_match(str, this_object());
if (!sizeof(obs)) {
tell_room(environment(), this_object()->query_cap_name()+" tries to wear "+str+
", but "+this_object()->query_pronoun()+" doesn't have that.\n", this_object());
tell_object(this_object(),"You try to wear "+str+", but "
"you don't have that.\n");
return;
}
for (i=0; i<sizeof(obs); i++)
if (!obs[i]->query_armor())
wear_remove_mess(obs[i], "wear", "doesn't think it's a type of armor",
"don't think it's a type of armor");
else
wear_armor(obs[i]);
}
void remove(string str) {
int i; object *obs;
if (!str) {
notify_fail("Remove what?\n");
return;
}
obs = find_match(str, this_object());
if (!sizeof(obs)) {
tell_room(environment(), this_object()->query_cap_name()+" tries to remove "+str+
", but "+this_object()->query_pronoun()+" doesnt have that.\n", this_object());
tell_object(this_object(),"You try to remove "+str+", but "
"you don't have that.\n");
return;
}
for (i=0; i<sizeof(obs); i++)
if (member_array(obs[i], armors)==-1)
wear_remove_mess(obs[i], "remove", "isn't wearing it",
"aren't wearing it");
else
remove_armor(obs[i]);
}
int do_equip(status mess) {
int i, j, *attack;
string str;
object ob, ob2, guild_ob, *obs;
mixed *armor, *weapon;
armor = ({ });
weapon = ({0,-50});
guild_ob = this_object()->query_guild_ob();
if (!guild_ob) guild_ob = "/std/guild";
obs = all_inventory(this_object());
for (i=0; i<sizeof(obs); i++)
{
ob = obs[i];
if (ob->query_armor())
{
str = (string)ob->query_type();
j = member_array(str, armor);
ob2 = (object)ob->prev_wearer();
if( j==-1 || (
( (int)ob->query_ac() > armor[j-1]) ) &&
( objectp(ob2) && ob2==this_object() ) &&
( (int)guild_ob->query_number_worn(str) ) )
{
if (j == -1)
{
j = 2;
armor += ({ 0, 0, 0 });
}
armor[j-2] = ob;
armor[j-1] = (int)ob->query_ac();
armor[j] = str;
}
}
else
{
ob2 = (object)ob->prev_wielder();
if ( (ob->query_weapon() ) &&
( guild_ob->query_valid_melee_weapon(ob) ) &&
( attack=(int*)ob->query_attack_out() ) &&
( (ob2?(ob2==this_object()):1) ) &&
( !( (ob->query_twohanded()) && (!free_hands[1])) ) &&
( (j=attack[4]*(1+attack[5])/2+attack[6])) > weapon[1] )
{
weapon[0] = ob;
weapon[1] = j;
}
}
}
// printf("armors: %0\nweapon: %0\n",armor,weapon);
if (i = member_array("shield", armor)!=-1) {
if (held_ob[1]) {
tell_room(environment(),this_object()->query_cap_name()+" decides not to wear a " "shield since "+this_object()->query_possessive()+" shield hand is holding something"
" already.\n", this_object());
tell_object(this_object(),"You decide not to wear a shield since your"
" shield hand is holding something already.\n");
armor = delete(armor, i-2, 3);
}
else if (useless_hands[1]) {
wear_remove_mess(armor[i-2], "wear", "can't use "+this_object()->query_possessive()+
" shield hand", "can't use your shield hand");
armor = delete(armor, i-2, 3);
}
}
if (!sizeof(armor)) {
tell_room(environment(), this_object()->query_cap_name()+" has nothing to wear.\n",
this_object());
tell_object(this_object(),"You have nothing to wear.\n");
// return 1;
}
j = -1;
for (i=0; i<sizeof(armor); i+=3)
if (armor[i+2] != "cloak")
wear_armor(armor[i]);
else
j = i;
if (j != -1)
wear_armor(armor[j]);
if(weapon[0])
ob = weapon[0];
if (!ob) {
tell_room(environment(), this_object()->query_cap_name()+" has nothing to wield.\n",
this_object());
tell_object(this_object(),"You have nothing to wield.\n");
}
else if (!free_hands[0]){
tell_room(environment(), this_object()->query_cap_name()+" doesn't have a free weapon "
"hand.\n", this_object());
tell_object(this_object(),"You don't have a free weapon hand.\n");
}
else {
if (held_ob[0])
unhold_ob(0, held_ob[0]);
if (held_ob[1] && ob->query_twohanded())
unhold_ob(0, held_ob[1]);
hold_ob(ob, 0);
}
return 1;
}
mixed *stats() {
mixed *ret; string *str; int i, j;
ret = ({ });
i = query_hand();
str = ({ "right", "left" });
for (j=0; j<sizeof(armors); j++)
ret += ({ ({ "Wearing", armors[i]->short(0) }) });
return ({ ({ "Total armor protection", ac }),
/* ({ "Holding in "+str[i]+" hand:", held_ob[0]->short(0) }),
({ "Holding in "+str[1-i]+" hand:", held_ob[1]->short(0) }), */
}) + ret + combat::stats();
}
/* Add for new weapon_logic.c */
/* Look in /w/sojan/combat/excode.new for explanation. */
int shield_bonus()
{
return 0;
}