inherit "/std/weapon_logic"; int *weapon_attack_out, *attack_out; //dk static object attackee; static object *attacker_list, *call_outed, protector; // weapon, //dk I allow 2-weapons combat, so equip.c defines held_ob[0] as the primary //weapon, if any, and held_ob[1] as the secondary weapon, if any. static int concentrate; static int att_level, dodging; #define DIV_NUM 6 #include "money.h" void set_weapon_attack_out(int mess, object *held_ob) { } int query_dodging() { return dodging; } int query_my_att_level() { return (int)this_object()->query_level(); } void set_concentrate(int i) { concentrate = i; } int query_concentrate() { return concentrate; } object set_protector(object ob) { return (protector = ob); } object query_protector() { return protector; } void actual_death(); void create() { attacker_list = ({ }); call_outed = ({ }); weapon_logic::create(); } void combat_commands() { add_action("do_protect", "protect"); } int do_death(object killed_by) { int i, xp, aln, tot; mapping damage_done; damage_done = (mapping)this_object()->query_damage_done(); if (!damage_done) damage_done = ([ ]); for (i=0;i<sizeof(attacker_list);i++) { attacker_list[i]->stop_fight(this_object()); tot += damage_done[attacker_list[i]]; } for (i=0;i<sizeof(call_outed);i++) call_outed[i]->stop_fight(this_object()); xp = (int)this_object()->query_xp(); if (!tot) tot = 1; aln = (int)this_object()->query_align(); for (i=0;i<sizeof(attacker_list);i++) { attacker_list[i]->adjust_xp(((xp * damage_done[attacker_list[i]]/tot) * att_level) / (DIV_NUM * ((int)attacker_list[i]->query_level()))); attacker_list[i]->adjust_align(aln); } if (killed_by) say(killed_by->query_cap_name()+" dealt the death blow to "+ this_object()->query_cap_name()+".\n"); else say(this_object()->query_cap_name()+" died horribly.\n"); if (environment()) event(environment(), "death", attacker_list, killed_by); actual_death(); return 0; } object make_corpse() { object corpse, money, *obs, ob; int i; corpse = clone_object("/obj/corpse"); corpse->set_owner(this_object()->short(0)); corpse->set_race_name(this_object()->query_race()); //? corpse->add_alias((string)this_object()->query_name()); //? corpse->add_alias((string *)this_object()->query_aliases()); //? corpse->add_plural((string *)this_object()->query_plurals()); corpse->start_decay(); corpse->add_adjective(this_object()->query_adjectives()); if (!this_object()->query_race_ob()) if (file_size("/std/races/"+this_object()->query_race()+".c") >= 0) corpse->set_race_ob("/std/races/"+this_object()->query_race()); else corpse->set_race_ob("/std/races/unknown"); else corpse->set_race_ob(this_object()->query_race_ob()); //dk Until we make an informed decision here, I'm going to have corpses //unhold, unwear and unwield everything. Otherwise, since some items have a //special effect on the room only if they're worn or held by a living //creature, creators would have to code each such item carefully to //distinguish the effects when worn or held by a corpse...we probly don't //want to do this, but even if we do, I don't want to deal with it right now. tell_room(environment(),this_object()->query_cap_name()+" drops everything, and "+ this_object()->query_possessive()+" armor eerily hops off "+this_object()->query_possessive()+ " body and falls to the floor.\n", this_object()); tell_object(this_object(),"You drop everything, and your armor eerily hops" " off your body and falls to the floor.\n"); for (i=0; i<2; i++) if (ob=(object)this_object()->query_held_ob(i)) { if (!ob->query_weapon()) ob->set_held(0); else ob->set_wielder(0); ob->set_drop(); ob->move(environment()); } weapon_attack_out = ({ }); obs = this_object()->query_armors(); for (i=0; i<sizeof(obs); i++) { ob = obs[i]; ob->set_wearer(0); ob->set_drop(); ob->move(environment()); } this_object()->equip_create(); obs = all_inventory(this_object()); for (i=0; i<sizeof(obs); i++) obs[i]->move(environment()); corpse->move(environment()); return corpse; } //? shouldnt need to call this... so make it static, just in case static void actual_death() { object ob, ob2; //dw if second_life returns false... do stupid things... if (!((int)this_object()->second_life())) { make_corpse()->move(environment()); //dw dest the ones that stick around... ob = first_inventory(this_object()); while(ob) { ob2 = next_inventory(ob); ob->dest_me(); ob = ob2; } this_object()->dest_me(); } } object query_attackee() { return attackee; } void attack() { int i, dam, his_att_lvl; string his_name; object *obs,ob,weapon; if (!attacker_list) attacker_list = ({ }); while (i<sizeof(attacker_list)) { if (!attacker_list[i]) //dw have they died unexpecedaly? attacker_list = delete(attacker_list,i,1); else //dw I will put all the ones not in the correct environ in a new list. if (environment(attacker_list[i]) != environment()) { write("You are hunting "+attacker_list[i]->short()+"\n"); /* this call out would be nice to get rid of... * Baldrick */ call_out("check_stop_fight",600,attacker_list[i]); if (!call_outed) call_outed = ({ attacker_list[i] }); else call_outed += ({ attacker_list[i] }); attacker_list = delete(attacker_list,i,1); } else i++; } //dw check the not correct environ list to see if any one has come back. i = 0; while (i<sizeof(call_outed)) if (!call_outed[i]) call_outed = delete(call_outed,i,1); else if (environment() == environment(call_outed[i])) { attacker_list += ({ call_outed[i] }); call_outed = delete(call_outed,i,1); } else i++; //dw not hitting anyone... do spell effects anyway... if (!sizeof(attacker_list)) { // this_object()->do_spell_effects(0); (dk: ducky moved this to hb) attackee = 0; return; } //dw choose a random person from the attacker list; they're in correct env. if (concentrate) attackee = attacker_list[0]; else attackee = attacker_list[random(sizeof(attacker_list))]; //dw Check to see if they are being protected. // Should we use a skill here? Hmm.... To slow probably, will make it // a fixed 80% chance for now. First check to make sure that the // protector isnt in the attacker list if (protector && member_array(protector, attacker_list) != -1) { tell_object(this_object(), protector->query_cap_name()+ " turns against you and starts fighting you.\n"); tell_object(protector, "You start fighting "+ this_object()->query_cap_name()+" and stop protecting "+ this_object()->query_objective()+".\n"); say(protector->query_cap_name()+" turns against "+ this_object()->query_cap_name()+" and starts attacking him.\n", ({ protector, this_object() })); } if ((ob = (object)attackee->query_protector()) && environment(ob) == environment(attackee) && random(100) >= 20) { tell_object(attackee, ob->query_cap_name()+ " valiantly protects you.\n"); tell_object(ob,"You valiantly protect "+attackee->query_cap_name()+".\n"); say(ob->query_cap_name()+" valiantly protects "+ attackee->query_cap_name()+".\n", ({ attackee, ob })); attackee = ob; } his_att_lvl = maxi(({ (int)attackee->query_level(), 1 }) ); his_name = (string)attackee->query_name(); //dk ducky removed the following line and uses "time effect" in hb instead: // if(!this_object()->do_spell_effects(attackee)) { attackee->attack_by(this_object()); //dw Ok, do the damage to the person we are attacking. This has already //dw been wombled to get the attackee to be the right person (ie being //dw protected). //dk the combat damage needs to be worked out here...not finished yet, // cause it needs the guild to define set_weapon_attack_out //dk so ducky removed this next line too // } /* * Ok, do the damage to the person we are attacking. This has already * been wombled to get the attackee to be the right person (ie being * protected). * * This didn't work at all so I changed it.... -Aragorn * Old code: * weapon = this_object()->query_held_ob(0); * if(weapon && !weapon->query_weapon()){ * weapon = this_object()->query_held_ob(1); * if (!weapon->query_weapon()) weapon =""; * } */ weapon = this_object()->query_held_ob(0); if(weapon && !weapon->query_weapon()) { weapon = this_object()->query_held_ob(1); if (weapon && !weapon->query_weapon()) weapon = 0; } if (weapon) dam = (int)weapon->weapon_attack(attackee,this_object()); else dam = weapon_attack(attackee,this_object()); /* } */ if (!attackee) { tell_object(this_object(),"You killed "+his_name+"\n"); say(this_object()->query_cap_name()+" killed "+his_name+"\n"); } if (!att_level) att_level = this_object()->query_level(); /* Added By Asmodean to stop the fatal error on 0 level players When the use the follow adjust_xp line. Division by 0 would always occur */ if (att_level == 0) att_level = 1; this_object()->adjust_xp(dam*his_att_lvl/att_level); event(environment(), "fight_in_progress", attackee); } void attack_by(object ob) { if (ob == this_object()) return ; if (!attacker_list) attacker_list = ({ }); if (!sizeof(attacker_list)) { att_level = (int)this_object()->query_level(); dodging = (int)this_object()->query_level(); } if (member_array(ob, attacker_list) == -1 && member_array(ob, call_outed) == -1) { attacker_list += ({ ob }); } set_heart_beat(1); } void attack_ob(object ob) { if (ob == this_object()) return; if (!attacker_list) attacker_list = ({ }); if (!sizeof(attacker_list)) { att_level = (int)this_object()->query_level(); dodging = (int)this_object()->query_level(); } if (member_array(ob, attacker_list) == -1 && member_array(ob, call_outed) == -1) { attacker_list += ({ ob }); } if (ob) ob->attack_by(this_object()); } void check_stop_fight(object ob) { int i; if ((i=member_array(ob,call_outed)) != -1) call_outed = delete(call_outed,i,1); } int stop_fight(object ob) { int i; if ((i=member_array(ob,call_outed)) != -1) { tell_object(this_object(),"You stop hunting "+call_outed[i]->short(0)+ ".\n"); call_outed = delete(call_outed, i, 1); } if ((i=member_array(ob,attacker_list)) != -1) attacker_list = delete(attacker_list,i,1); } mixed *query_attacker_list() { return attacker_list; } mixed *query_call_outed() { return call_outed; } //dw Sets up protection matrixes. int do_protect(string str) { object *obs, *ok; int i; if (!str) { notify_fail("Syntax: protect <objects>\n"); return 0; } obs = find_match(str, environment()); if (!sizeof(obs)) { notify_fail("Protect what?\n"); return 0; } //dk added member_array to this next line: if (member_array(this_object(), obs)) //dk I changed this next line from this_player() to this_object(): obs -= ({ this_object() }); ok = ({ }); for (i=0; i<sizeof(obs); i++) if (obs[i]->set_protector(this_object())) ok += ({ obs[i] }); if (!sizeof(ok)) { notify_fail(query_multiple_short(obs)+ (sizeof(obs)==1?" doesnt":" don't")+" want your protection.\n"); return 0; } if (sizeof(obs) != sizeof(ok)) write("You fail to protect "+query_multiple_short(obs - ok)+".\n"); write("You protect "+query_multiple_short(ok)+".\n"); say(this_object()->query_cap_name()+" protects "+query_multiple_short(ok)+ ".\n", ok); for (i=0; i<sizeof(ok); i++) tell_object(ok[i], this_object()->query_cap_name()+" protects "+ query_multiple_short(({ "you" }) + (ok - ok[i..i]))+".\n"); return 1; } mixed stats() { int i; object ob; mixed *ret; if (ob=this_object()->query_held_ob(0) && ob->query_weapon()) ret += ({ ({ "Weapon", ob->short() }) }) + (mixed)ob->weapon_stats(); if (ob=this_object()->query_held_ob(1) && ob->query_weapon()) ret += ({ ({ "Secondary weapon", ob->short() }) }); for (i=0; i<sizeof(attack_out); i+=7) ret += ({ ({ "If", attack_out[i], }), ({ "Rate", attack_out[i+1], }), ({ "Attack", attack_out[i+2], }), ({ "Tohit", attack_out[i+3], }), ({ "Number of damage dice", attack_out[i+4], }), ({ "Die size", attack_out[i+5], }), ({ "Addend", attack_out[i+6], }), }); return ret; }