Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/weapon/combat.c b/std/weapon/combat.c
new file mode 100644
index 0000000..cb10ff5
--- /dev/null
+++ b/std/weapon/combat.c
@@ -0,0 +1,819 @@
+// MorgenGrauen MUDlib
+//
+// weapon/combat.c -- combat part of the weapon standard object
+//
+// $Id: combat.c 9425 2016-01-02 18:19:40Z Zesstra $
+
+#include <sys_debug.h>
+
+#pragma strict_types
+#pragma save_types
+#pragma no_clone
+#pragma pedantic
+#pragma range_check
+
+#define NEED_PROTOTYPES
+
+#include <thing/properties.h>
+#include <thing/commands.h>
+#include <thing/description.h>
+#include <properties.h>
+#include <language.h>
+#include <combat.h>
+#include <attributes.h>
+#include <defines.h>
+#include <moving.h>
+#include <new_skills.h>
+
+// Globale Variablen
+ int ftime, flaw;
+private nosave int logged;
+private nosave closure defend_cl, hit_cl;
+
+void create()
+{
+ // Variablen initialisieren
+ logged=ftime=flaw=0;
+ defend_cl=0;
+ hit_cl=0;
+
+ // Einige Grundwerte setzen
+ SetProp(P_WEAPON_TYPE, WT_CLUB);
+ SetProp(P_DAM_TYPE, ({DT_BLUDGEON}));
+ SetProp(P_NR_HANDS, 2);
+ SetProp(P_PARRY,PARRY_NOT);
+ SetProp(P_AC,0);
+ Set(P_RESTRICTIONS,([]),F_VALUE);
+ Set(P_LAST_USE,time(),F_VALUE);
+
+ // Einige Properties sollten nicht von aussen gesetzt werden koennen
+ Set(P_PARRY, PROTECTED, F_MODE_AS);
+ Set(P_WIELDED, PROTECTED, F_MODE_AS);
+ Set(P_LAST_USE,PROTECTED, F_MODE_AS);
+
+ // Diese kann von aussen gesetzt werden (noch), aber bitte nur ueber die
+ // hier definierte Setmethode.
+ Set(P_DAMAGED, PROTECTED, F_MODE_AS);
+
+ // Eine Waffe benoetigt Kommandos, mit denen man sie zuecken
+ // und wegstecken kann
+ AddCmd( ({"zueck","zuecke","zieh","ziehe"}), "wield" );
+ AddCmd( ({"steck","stecke"}), "unwield" );
+}
+
+// aktuelles Lebewesen, was diese Waffe zur Zeit gezueckt hat.
+public object QueryUser()
+{
+ return QueryProp(P_WIELDED);
+}
+
+/*
+ * Ausgabe einer Meldung beim Zuecken geht nur an Spieler, nicht an NPC.
+ * Die Umgebung bekommt natuerlich immer eine Meldung.
+ */
+void doWieldMessage()
+{
+ string *str, s1;
+
+ if(QueryProp(P_WIELD_MSG)) // Ist eine WieldMsg gesetzt?
+ {
+ if(closurep(QueryProp(P_WIELD_MSG))) // Sogar als eigene Fkt.?
+ {
+ str = funcall(QueryProp(P_WIELD_MSG),this_player());
+
+ if(interactive(this_player()))
+ {
+ this_player()->ReceiveMsg(str[0],
+ MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_WIELD, 0,
+ this_player());
+ }
+
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ str[1],
+ MT_LOOK|MSG_BS_LEAVE_LFS,
+ MA_WIELD, 0, ({this_player()}), environment());
+ return;
+ }
+ else if(interactive(this_player()))
+ {
+ s1 = replace_personal(sprintf(QueryProp(P_WIELD_MSG)[0],"@WEN2"),
+ ({this_player(),this_object()}), 1);
+
+ this_player()->ReceiveMsg(s1,
+ MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_WIELD, 0,
+ this_player());
+ }
+
+ // Abwaertskompatibel: Das erste %s wird zu WEN1, das zweite zu WEN2
+ s1 = replace_personal(sprintf(QueryProp(P_WIELD_MSG)[1],"@WEN1","@WEN2"),
+ ({this_player(), this_object()}), 1);
+
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ s1,
+ MT_LOOK|MSG_BS_LEAVE_LFS,
+ MA_WIELD, 0, ({this_player()}), environment());
+ return;
+ }
+ /*
+ * Keine WieldMsg gesetzt, Ausgabe der Default-Meldungen.
+ */
+ else if(interactive(this_player()))
+ {
+ this_player()->ReceiveMsg(
+ "Du zueckst "+name(WEN,1)+".",
+ MT_NOTIFICATION, MA_WIELD, 0, this_player());
+ }
+
+ //s.o. ersetzt durch tell_room()
+ //say(break_string(this_player()->Name(WER)+" zueckt "
+ // +name(WEN,0)+".",78),({ this_player() }));
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ this_player()->Name(WER)+" zueckt "+name(WEN,0)+".",
+ MT_LOOK,
+ MA_WIELD, 0, ({this_player()}), environment());
+}
+
+/*
+ * Ausgabe einer Meldung beim Wegstecken geht nur an Spieler, nicht an NPC.
+ * Die Umgebung bekommt immer eine Meldung.
+ */
+void doUnwieldMessage(object wielded_by)
+{
+ string *str,s1;
+
+ if(!objectp(wielded_by)) // Hoops! Gar nicht gezueckt? Abbruch!
+ {
+ return;
+ }
+
+ if(QueryProp(P_UNWIELD_MSG)) // Hier gibt es eine UnwieldMsg.
+ {
+ if(closurep(QueryProp(P_UNWIELD_MSG))) // Sogar als Closure, wow :-)
+ {
+ str = funcall(QueryProp(P_UNWIELD_MSG),wielded_by);
+
+ if(interactive(wielded_by))
+ {
+ wielded_by->ReceiveMsg(str[0],
+ MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_UNWIELD, 0, wielded_by);
+ }
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ str[1],
+ MT_LOOK|MSG_BS_LEAVE_LFS,
+ MA_UNWIELD, 0, ({wielded_by}), environment());
+ return;
+ }
+
+ else if(interactive(wielded_by))
+ {
+ s1 = replace_personal(sprintf(QueryProp(P_UNWIELD_MSG)[0],"@WEN2"),
+ ({this_player(),this_object()}), 1);
+ wielded_by->ReceiveMsg(s1,
+ MT_NOTIFICATION|MSG_BS_LEAVE_LFS, MA_UNWIELD, 0, wielded_by);
+ }
+
+ s1 = replace_personal(sprintf(QueryProp(P_UNWIELD_MSG)[1],"@WEN1","@WEN2"),
+ ({wielded_by, this_object()}), 1);
+
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ s1,
+ MT_LOOK|MSG_BS_LEAVE_LFS,
+ MA_UNWIELD, 0, ({wielded_by}), environment());
+ return;
+ }
+ /*
+ * Keine UnwieldMsg, also Default-Meldungen ausgeben.
+ */
+ else if(interactive(wielded_by))
+ {
+ wielded_by->ReceiveMsg(
+ "Du steckst "+name(WEN,1)+" zurueck.",
+ MT_NOTIFICATION, MA_UNWIELD, 0, wielded_by);
+ }
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ send_room(environment(environment()),
+ wielded_by->Name(WER) +" steckt "+name(WEN,0)+" zurueck.",
+ MT_LOOK,
+ MA_UNWIELD, 0, ({wielded_by}), environment());
+}
+
+// Diese Funktion wird aufgerufen, wenn die Waffe wirklich gezueckt wird
+protected void InformWield(object pl, int silent)
+{
+ return;
+}
+
+// Diese Funktion wird aufgerufen, wenn die Waffe wirklich weggesteckt
+// wird
+protected void InformUnwield(object pl, int silent)
+{
+ return;
+}
+
+
+// wield_me soll knallen.
+varargs int wield_me(int silent)
+{
+ raise_error("wield_me() ist veraltet. Bitte nutze DoWield()\n");
+ return 1;
+}
+
+// Die Funktion, die das eigentliche Zuecken durchfuehrt.
+varargs int DoWield(int silent)
+{ int dex, parry;
+ closure cl;
+ mixed res;
+
+ // Man kann nur Waffen zuecken, die man auch im Inventory hat.
+ if (environment()!=PL)
+ {
+ _notify_fail( break_string(
+ "Du musst "+name(WEN,1)+" schon erst nehmen!",78) );
+ return 0;
+ }
+
+ // Eine gezueckte Waffe kann man natuerlich nicht nochmal zuecken
+ if (QueryProp(P_WIELDED))
+ {
+ notify_fail("Das hast Du schon gemacht!\n");
+ return 0;
+ }
+
+ // Waffen, die ein oder mehrere Attribut veraendern und gegen
+ // das gesetzte Limit verstossen, haben keine Wirkung bezueglich der
+ // Attribute.
+ if ( mappingp(res=QueryProp(P_M_ATTR_MOD)) && PL->TestLimitViolation(res) )
+ {
+ write(break_string(
+ "Irgendetwas an Deiner Ausruestung verhindert, dass Du Dich mit "+
+ name(WEM,1)+" so richtig wohl fuehlst.",78));
+ }
+
+ // Ueber P_RESTRICTIONS kann man einige Restriktionen definieren, ohne
+ // gleich auf eine WieldFunc zurueckgreifen zu muessen.
+ // Die Auswertung erfolgt ueber den RestrictionChecker
+ if ( (res=QueryProp(P_RESTRICTIONS)) && mappingp(res) &&
+ (res=(string)call_other("/std/restriction_checker","check_restrictions",
+ PL,res)) && stringp(res) )
+ {
+ notify_fail(res);
+ return 0;
+ }
+
+ parry=(int)QueryProp(P_PARRY);
+ dex=(int)PL->QueryAttribute(A_DEX);
+
+ // Testen, ob der Spieler die noetige Geschicklichkeit besitzt, um
+ // mit dieser (Parier)Waffe umgehen zu koennen
+ if ( ((parry<PARRY_ONLY) && ((dex+8)*10)<QueryProp(P_WC)) ||
+ ((parry>PARRY_NOT) && ((dex+5)*2 )<QueryProp(P_AC)) )
+ {
+ notify_fail(
+ "Du bist nicht geschickt genug, um mit dieser Waffe umzugehen.\n");
+ return 0;
+ }
+
+ // Eine Gezueckte Waffe muss natuerlich erst mal weggesteckt werden.
+ if ( (parry<PARRY_ONLY) && objectp(res=(object)PL->QueryProp(P_WEAPON)) )
+ {
+ if ( (res->DoUnwield(silent)) && !((object)PL->QueryProp(P_WEAPON)) )
+ {
+ // Wenn die alte Waffe weggesteckt werden konnte, nochmal
+ // versuchen zu zuecken
+ return DoWield(silent);
+ }
+ else
+ {
+ // Sonst Meldung ausgeben
+ notify_fail("Das geht nicht, solange Du noch eine andere "+
+ "Waffe gezueckt hast.\n");
+ return 0;
+ }
+ }
+ // Das gleiche gilt natuerlich fuer Parierwaffen
+ if ( (parry>PARRY_NOT) && objectp(res=(object)PL->QueryProp(P_PARRY_WEAPON)) )
+ {
+ if ( (res->DoUnwield(silent)) && !(PL->QueryProp(P_PARRY_WEAPON)) )
+ {
+ // Wenn die alte Parierwaffe weggesteckt werden konnte, nochmal
+ // versuchen zu zuecken
+ return DoWield(silent);
+ }
+ else
+ {
+ // Sonst Meldung ausgeben
+ notify_fail("Das geht nicht, solange Du noch eine andere "+
+ "Paierwaffe gezueckt hast.\n");
+ return 0;
+ }
+ }
+
+ // Ist eine WieldFunc gesetzt, wird diese aufgerufen.
+ if (objectp(res=QueryProp(P_WIELD_FUNC))
+ && !(res->WieldFunc(ME,silent,environment())))
+ {
+ // Eine Meldung sollte schon von der WieldFunc ausgegeben werden.
+ return 1;
+ }
+
+ // Die zulaessigen Hoechstwerte duerfen natuerlich nicht
+ // ueberschritten werden.
+ if ( (parry<PARRY_ONLY) && (QueryProp(P_WC)>MAX_WEAPON_CLASS) )
+ {
+ notify_fail(
+ "Ungueltige Waffenklasse, bitte Erzmagier verstaendigen.\n");
+ return 0;
+ }
+ if ( (parry>PARRY_NOT) && (QueryProp(P_AC)>MAX_PARRY_CLASS) )
+ {
+ notify_fail(
+ "Ungueltige Parierklasse, bitte Erzmagier verstaendigen.\n");
+ return 0;
+ }
+
+ // Testen, ob der Zuecker genug Haende frei hat.
+ if (!(PL->UseHands(ME,QueryProp(P_NR_HANDS))))
+ {
+ notify_fail("Du hast keine Hand mehr frei.\n");
+ return 0;
+ }
+
+ // Ok, jetzt ist alles klar, die (Parier)Waffe wird gezueckt
+ SetProp(P_WIELDED, PL);
+ SetProp(P_EQUIP_TIME,time());
+
+ cl=symbol_function("SetProp",PL);
+
+ if (parry<PARRY_ONLY)
+ {
+ // Dieses Objekt als Waffe setzen
+ funcall(cl,P_WEAPON, ME );
+ }
+ if (parry>PARRY_NOT)
+ {
+ // Dieses Objekt als Parierwaffe setzen
+ funcall(cl,P_PARRY_WEAPON, ME );
+ }
+
+ // Waffen koennen Attribute aendern/blockieren. Also muessen diese
+ // nach dem Zuecken aktualisiert werden
+ PL->register_modifier(ME);
+ PL->UpdateAttributes();
+
+ // P_TOTAL_AC/P_TOTAL_WC im Spieler aktualisieren. Da dort Attribute
+ // eingehen, kann das erst hier gemacht werden.
+ if (parry<PARRY_ONLY)
+ {
+ PL->QueryProp(P_TOTAL_WC);
+ }
+ if (parry>PARRY_NOT)
+ {
+ PL->QueryProp(P_TOTAL_AC);
+ }
+
+ // Zueck-Meldung ausgeben, wenn das silent-Flag nicht gesetzt ist
+ if (!silent)
+ {
+ doWieldMessage();
+ }
+
+ // Alle Waffen werden im awmaster registriert, sobald sie von einem
+ // Spieler gezueckt werden
+ if (!logged && query_once_interactive(PL))
+ {
+ call_other("/secure/awmaster","RegisterWeapon",ME);
+ logged=1;
+ }
+
+ // Inform-Funktion aufrufen
+ InformWield(PL,silent);
+
+ // Fertig mit dem Zuecken
+ return 1;
+}
+
+// Die Funktion, die das eigentliche Wegstecken durchfuehrt.
+varargs int DoUnwield(int silent)
+{ closure cl;
+ int parry;
+ mixed res;
+ object wielded_by;
+
+ // Waffen, die nicht gezueckt sind, kann man natuerlich nicht
+ // wegstecken
+ if (!objectp(wielded_by=QueryProp(P_WIELDED)))
+ {
+ return 0;
+ }
+
+ // Ist eine UnwieldFunc gesetzt, wird diese aufgerufen
+ if ( objectp(res=QueryProp(P_UNWIELD_FUNC)) &&
+ !(res->UnwieldFunc(ME,silent,wielded_by)) )
+ {
+ // Eine Meldung muss die UnwieldFunc schon selbst ausgeben.
+ return 1;
+ }
+
+ // Eine verfluchte Waffe kann man natuerlich nicht wegstecken - aber
+ // auch da gibts Ausnahmefaelle, wie z.B. den Tod eines Spielers
+ if ((res=QueryProp(P_CURSED)) && !(silent&M_NOCHECK))
+ {
+ if (stringp(res))
+ {
+ // Stand in P_CURSED ein String? Dann diesen ausgeben
+ tell_object(wielded_by,
+ (res[<1]=='\n' ? res : break_string(res,78)));
+ }
+ else
+ {
+ // Sonst eine Standard-Meldung ausgeben
+ tell_object(wielded_by, break_string(
+ "Du kannst "+name(WEN)+" nicht wegstecken.",78));
+ }
+ return 1;
+ }
+
+ // Ok, jetzt ist alles klar, die (Parier)Waffe wird weggesteckt
+ parry=QueryProp(P_PARRY);
+ cl=symbol_function("SetProp",wielded_by);
+
+ if (parry<PARRY_ONLY)
+ {
+ // Eintrag als Waffe im Spieler loeschen
+ funcall(cl,P_WEAPON, 0);
+ }
+ if (parry>PARRY_NOT)
+ {
+ // Eintrag als Parierwaffe im Spieler loeschen
+ funcall(cl,P_PARRY_WEAPON, 0);
+ }
+
+ // Im Spieler die Zeit setzen, zu der er zuletzt eine Waffe weggesteckt
+ // hat.
+ funcall(cl,P_UNWIELD_TIME,time());
+
+ // Meldung ausgeben, wenn silent-Flag nicht gesetzt ist
+ if (!silent)
+ {
+ doUnwieldMessage(wielded_by);
+ }
+
+ // Die Haende, die bisher von der Waffe benutzt wurden, freigeben
+ wielded_by->FreeHands(ME);
+ SetProp(P_WIELDED, 0);
+
+ // Waffen koennen Attribute aendern/blockieren. Also muessen diese
+ // nach dem Wegstecken aktualisiert werden
+ wielded_by->deregister_modifier(ME);
+ wielded_by->UpdateAttributes();
+
+ // P_TOTAL_AC/P_TOTAL_WC im Spieler aktualisieren. Da dort Attribute
+ // eingehen, kann das erst hier gemacht werden.
+ if (parry<PARRY_ONLY)
+ {
+ wielded_by->QueryProp(P_TOTAL_WC);
+ }
+ if (parry>PARRY_NOT)
+ {
+ wielded_by->QueryProp(P_TOTAL_AC);
+ }
+
+ // Inform-Funktion aufrufen
+ InformUnwield(wielded_by, silent);
+
+ // Fertig mit dem Wegstecken
+ return 1;
+}
+
+// Die Funktion, die das "zuecken"-Kommando auswertet
+varargs int wield(string str, int silent)
+{
+ if ( !stringp(str) ||
+ (query_verb()[0..3]=="zieh" && sscanf(str,"%s hervor",str)!=1) )
+ {
+ return 0;
+ }
+
+ if (!id(str))
+ {
+ _notify_fail("Du hast sowas nicht.\n");
+ return 0;
+ }
+
+ return DoWield(silent);
+}
+
+// Die Funktion, die das "wegstecken"-Kommando auswertet
+int unwield(string str)
+{ int parry;
+ string dummy;
+
+ // Erstmal die Eingabe auswerten. Ist dies wirklich ein Kommando
+ // zum Wegstecken?
+ if ( !stringp(str) || (sscanf(str,"%s weg", dummy)!=1 &&
+ sscanf(str,"%s ein", dummy)!=1 &&
+ sscanf(str,"%s zurueck", dummy)!=1 ) )
+ {
+ return 0;
+ }
+
+ str = dummy;
+ parry=QueryProp(P_PARRY);
+
+ // Ist wirklich diese Waffe gemeint?
+ if ( !stringp(str) || !id(str) ||
+ ((parry<PARRY_ONLY)&&((object)PL->QueryProp(P_WEAPON)!=ME)) ||
+ ((parry>PARRY_NOT)&&((object)PL->QueryProp(P_PARRY_WEAPON)!=ME)) )
+ {
+ return 0;
+ }
+
+ // Man kann nur Waffen wegstecken, die man auch bei sich hat
+ if (environment() != PL)
+ {
+ _notify_fail("Diese Waffe gehoert Dir nicht!\n");
+ return 0;
+ }
+
+ // Und natuerlich geht das auch nur, wenn die Waffe gezueckt ist.
+ if (!QueryProp(P_WIELDED))
+ {
+ _notify_fail("Diese Waffe hast Du gar nicht gezueckt ...\n");
+ return 0;
+ }
+
+ return DoUnwield();
+}
+
+// Die Funktion, die den Schaden berechnet, den die Waffe verursacht
+int QueryDamage(object enemy)
+{ int dam;
+ mixed hit_func;
+ object wielder;
+
+ // Nur gezueckte Waffen machen Schaden
+ if (!objectp(wielder=QueryProp(P_WIELDED)))
+ return 0;
+
+ // Den Basis-Schaden berechnen. Die Staerke des Benutzers wird
+ // hier beruecksichtigt.
+ dam = (2*QueryProp(P_WC)+10*((int)wielder->QueryAttribute(A_STR)))/3;
+
+ // Wie gut man getroffen hat, wird ueber ein random() simuliert
+ dam = random(1+dam);
+
+ // Ist eine HitFunc gesetzt, dann wird diese ausgewertet. Der
+ // Rueckgabe-Wert wird zum Schaden addiert
+ if (!hit_cl || !get_type_info(hit_cl,2))
+ {
+ if (objectp(hit_func=QueryProp(P_HIT_FUNC)))
+ {
+ hit_cl=symbol_function("HitFunc",hit_func);
+ }
+ }
+ if (hit_cl && get_type_info(hit_cl,2))
+ {
+ dam += funcall(hit_cl,enemy);
+ }
+
+ // Zeitpunkt der letzten Benutzung ausgeben
+ SetProp(P_LAST_USE,time());
+
+ // Berechneten Schaden zurueckgeben
+ return dam;
+}
+
+// Die Funktion, die bei Parierwaffen den Schutzwert berechnet.
+int QueryDefend(string* dam_type, mixed spell, object enemy)
+{ int prot;
+ mixed def_func;
+ object pl;
+
+ prot = 0;
+
+ // Ruestungen schuetzen nur gegen physikalischen Schaden
+ if (!spell || (mappingp(spell) && spell[SP_PHYSICAL_ATTACK]))
+ {
+ if (sizeof(filter(dam_type,PHYSICAL_DAMAGE_TYPES)))
+ {
+ prot = random(1+QueryProp(P_AC));
+ }
+ }
+
+ // Ist eine DefendFunc gesetzt, wird diese ausgewertet
+ if (!defend_cl || !get_type_info(defend_cl,2))
+ {
+ if (objectp(def_func=QueryProp(P_DEFEND_FUNC)))
+ {
+ defend_cl=symbol_function("DefendFunc",def_func);
+ }
+ }
+ //Bei Netztoten keine (zurueckschlagende) DefendFunc
+ if (defend_cl && get_type_info(defend_cl,2) &&
+ objectp(pl=QueryProp(P_WIELDED)) && (!query_once_interactive(pl) ||
+ interactive(pl)) )
+ {
+ // Der Rueckgabewert der DefendFunc wird zum Schutz addiert
+ prot += funcall(defend_cl, dam_type, spell, enemy);
+ }
+
+ // Zeitpunkt der letzten Benutzung ausgeben
+ SetProp(P_LAST_USE,time());
+
+ // Berechneten Schutz zurueckgeben
+ return prot;
+}
+
+// Die Anzahl der von einer Waffe benoetigten Haende darf natuerlich nicht
+// kleiner als 1 sein.
+int _set_nr_hands(int arg)
+{
+ if (!intp(arg) || (arg<1) )
+ return Query(P_NR_HANDS, F_VALUE);
+ return Set(P_NR_HANDS, arg, F_VALUE);
+}
+
+// Der Schadenstyp einer Waffe darf zwar als string angegeben werden, wird
+// intern aber immer als array gespeichert
+mixed _set_dam_type(mixed arg)
+{
+ if (pointerp(arg))
+ {
+ return Set(P_DAM_TYPE, arg, F_VALUE);
+ }
+ else if (stringp(arg))
+ {
+ return Set(P_DAM_TYPE, ({ arg }), F_VALUE);
+ }
+ return Query(P_DAM_TYPE, F_VALUE);
+}
+
+// Objekte, die die Beschaedigung einer Waffe durch direktes Setzen von
+// P_DAMAGED durchfuehren, werden im awmaster geloggt
+mixed _set_item_damaged(mixed arg)
+{
+ if (arg && !intp(arg))
+ {
+ return Query(P_DAMAGED, F_VALUE);
+ }
+
+ if (previous_object(1))
+ call_other("/secure/awmaster","RegisterDamager",
+ previous_object(1),QueryProp(P_DAMAGED),arg);
+
+ return Set(P_DAMAGED,arg,F_VALUE);
+}
+
+// Wird etwas an P_HIT_FUNC geaendert, muss die zugehoerige closure
+// erstmal geloescht werden.
+mixed _set_hit_func(mixed arg)
+{
+ hit_cl=0;
+ return Set(P_HIT_FUNC, arg, F_VALUE);
+}
+
+// Wird etwas an P_DEFEND_FUNC geaendert, muss die zugehoerige closure
+// erstmal geloescht werden.
+mixed _set_defend_func(mixed arg)
+{
+ defend_cl=0;
+ return Set(P_DEFEND_FUNC, arg, F_VALUE);
+}
+
+// Die maximale Waffenklasse einer Waffe berechnet sich natuerlich aus
+// der aktuellen Waffenklasse und der Beschaedigung. Eine Ausnahme bilden
+// hier Waffen, deren effektive Waffenklasse groesser ist als diese Summe
+int _query_max_wc()
+{ int a,b;
+
+ a=QueryProp(P_WC)+QueryProp(P_DAMAGED);
+ b=QueryProp(P_EFFECTIVE_WC);
+ if (b>a)
+ return b;
+ return a;
+}
+
+// Will man eine Waffe beschaedigen oder reparieren, so macht man das
+// am besten ueber die Funktion Damage(argument). Positive Argumente
+// bedeuten eine Beschaedigung, negative eine Reparatur. Der Rueckgabewert
+// ist die wirklich durchgefuehrte Aenderung des Beschaedigungswertes
+int Damage(int new_dam)
+{ int wc,old_dam;
+ object w;
+
+ // Uebergebenes Argument pruefen
+ if (!new_dam || !intp(new_dam))
+ {
+ return 0;
+ }
+
+ // Bei Waffen, die nicht ausschliesslich zur Parade eingesetzt werden,
+ // geht die Beschaedigung auf die Kampfkraft, sprich: P_WC
+ if (QueryProp(P_PARRY)<PARRY_ONLY)
+ {
+ if ((wc=QueryProp(P_WC))<=MIN_WEAPON_CLASS && new_dam>0)
+ {
+ // Sonst wuerde Beschaedigung zur Reparatur fuehren
+ return 0;
+ }
+
+ // Min-WC und Max-WC beachten
+ if ((wc-new_dam) < MIN_WEAPON_CLASS)
+ {
+ new_dam = wc-MIN_WEAPON_CLASS;
+ }
+ else if ((wc-new_dam) > MAX_WEAPON_CLASS)
+ {
+ new_dam = wc-MAX_WEAPON_CLASS;
+ }
+
+ // Nie mehr als 100% reparieren
+ if (((old_dam=QueryProp(P_DAMAGED))<-new_dam) && new_dam<0)
+ {
+ new_dam=-old_dam;
+ }
+
+ // Aenderungen an der Waffenklasse und der dem Beschaedigungswert
+ // durchfuehren
+ SetProp(P_WC,(wc-new_dam));
+ // Ausnahmeweise Set, um die loggende Setmethode zu umgehen.
+ // TODO: SetProp, sobald direktes Beschaedigen raus ist.
+ Set(P_DAMAGED, old_dam+new_dam, F_VALUE);
+
+ // P_TOTAL_WC im Traeger updaten, so vorhanden
+ if (objectp(w=QueryProp(P_WIELDED)))
+ w->QueryProp(P_TOTAL_WC);
+
+ // Rueckgabewert: Durchgefuehrte Aenderung an P_DAMAGE
+ return new_dam;
+ }
+
+ // Bei reinen Parierwaffen geht die Beschaedigung auf die
+ // Schutzwirkung, sprich: P_AC
+
+ if ((wc=QueryProp(P_AC))<=0 && new_dam>0)
+ {
+ // Sonst wuerde Beschaedigung zur Reparatur fuehren
+ return 0;
+ }
+
+ // Min-AC=0 und Max-AC beachten
+ if ((wc-new_dam) < MIN_PARRY_CLASS)
+ {
+ new_dam = wc-MIN_PARRY_CLASS;
+ }
+ else if ((wc-new_dam) > MAX_PARRY_CLASS)
+ {
+ new_dam = wc-MAX_PARRY_CLASS;
+ }
+
+ // Nie mehr als 100% reparieren
+ if (((old_dam=QueryProp(P_DAMAGED))<-new_dam) && new_dam<0)
+ {
+ new_dam=-old_dam;
+ }
+
+ // Aenderungen an der Ruestungsklasse und dem Beschaedigungswert
+ // durchfuehren
+ SetProp(P_AC,wc-new_dam);
+ // Ausnahmeweise Set, um die loggende Setmethode zu umgehen.
+ // TODO: SetProp, sobald direktes Beschaedigen raus ist.
+ Set(P_DAMAGED,old_dam+new_dam, F_VALUE);
+
+ // P_TOTAL_AC im Traeger updaten, so vorhanden
+ if (objectp(w=QueryProp(P_WIELDED)))
+ w->QueryProp(P_TOTAL_AC);
+
+ // Rueckgabewert: Durchgefuehrte Aenderung an P_DAMAGE
+ return new_dam;
+}
+
+// Wird die Waffe einer Belastung ausgesetzt (z.B. wenn man damit
+// zuschlaegt), dann wird TakeFlaw() aufgerufen.
+varargs void TakeFlaw(object enemy)
+{ int c;
+
+ // Flaw-Wert erhoehen
+ flaw++;
+
+ // Ist der Waffe eine Qualitaet gesetzt worden, so kann es zu einer
+ // allmaehlichen Beschaedigung der Waffe kommen
+ if ((c=QueryProp(P_QUALITY)) && !(flaw%c))
+ Damage(1);
+
+ // Zeitpunkt des ersten Aufrufes festhalten
+ if (!ftime)
+ ftime=time();
+}
+
+// Die Flaw-Daten koennen natuerlich auch abgerufen werden
+mixed *QueryFlaw()
+{
+ return({flaw,ftime,dtime(ftime)});
+}
+
diff --git a/std/weapon/description.c b/std/weapon/description.c
new file mode 100644
index 0000000..aad2938
--- /dev/null
+++ b/std/weapon/description.c
@@ -0,0 +1,108 @@
+// MorgenGrauen MUDlib
+//
+// weapon/description.c -- weapon description handling
+//
+// $Id: description.c 6475 2007-09-19 20:56:40Z Zesstra $
+
+#pragma strict_types
+#pragma save_types
+#pragma no_clone
+#pragma pedantic
+#pragma range_check
+
+//#define NEED_PROTOTYPES
+
+#include <thing/properties.h>
+#include <thing/description.h>
+#include <properties.h>
+#include <combat.h>
+#include <thing/material.h>
+
+inherit "/std/thing/description";
+
+void create()
+{
+ ::create();
+ SetProp(P_DAM_DESC,DFLT_DAM_DESC);
+}
+
+string dam_descr()
+{ string re;
+ mixed desc;
+ int max,dam,pos;
+
+ if (!QueryProp(P_NAME) || !QueryProp(P_DAMAGED) || !QueryProp(P_SHORT) ||
+ !(desc=QueryProp(P_DAM_DESC)) || (!stringp(desc) && !pointerp(desc)))
+ return "";
+ re = capitalize(name(WER,2))+" ";
+ max = QueryProp(P_WC)+(dam=QueryProp(P_DAMAGED));
+ // Bei reinen Parierwaffen den AC als max nehmen!
+ if (QueryProp(P_PARRY)==PARRY_ONLY)
+ {
+ max=QueryProp(P_AC)+dam;
+ }
+ if (stringp(desc))
+ return (dam>(max/2))?(re+desc+".\n"):"";
+ pos = (sizeof(desc)*dam/max);
+ // Sonst koennen Parierwaffen, die Schrott sind, buggen
+ if (pos==sizeof(desc)) pos--;
+ if (stringp(desc[pos]))
+ return (re+desc[pos]+".\n");
+ return "";
+}
+
+string short()
+{ string s;
+
+ if (!(s=QueryProp(P_SHORT)))
+ return 0;
+ return s + (QueryProp(P_WIELDED)?" (gezueckt).\n":".\n");
+}
+
+varargs string long()
+{
+ return (process_string(QueryProp(P_LONG)||"") + (dam_descr()||""));
+}
+
+mixed _query_size() {
+ mixed res, wt;
+ if (intp(res=Query(P_SIZE)) && (res>0))
+ return res;
+ wt=QueryProp(P_WEAPON_TYPE);
+ switch (wt) {
+ case WT_SWORD : return 100; // default: Langschwert
+ case WT_AXE : return 80;
+ case WT_CLUB : return 80;
+ case WT_SPEAR : return 180;
+ case WT_KNIFE : return 20;
+ case WT_WHIP : return 200;
+ case WT_STAFF : return 150;
+ }
+ return 10; // alles andere
+}
+
+mapping _query_material() {
+ mixed res,wt;
+
+ if (mappingp(res=Query(P_MATERIAL)))
+ return res;
+ wt=QueryProp(P_WEAPON_TYPE);
+ switch(wt) {
+ case WT_SWORD:
+ return ([MAT_MISC_METAL:100]);
+ case WT_KNIFE:
+ return ([MAT_MISC_METAL:80,MAT_MISC_WOOD:20]);
+ case WT_AXE:
+ return ([MAT_MISC_METAL:50,MAT_MISC_WOOD:50]);
+ case WT_SPEAR:
+ return ([MAT_MISC_METAL:20,MAT_MISC_WOOD:80]);
+ case WT_STAFF:
+ case WT_CLUB:
+ return ([MAT_MISC_WOOD:100]);
+ }
+ return ([MAT_MISC_METAL:100]);
+}
+
+// P_BALANCED_WEAPON und P_TECHNIQUE sind mangels umgesetztem Konzept durch
+// EM-Beschluss fuer obsolet erklaert worden. Zesstra. 26.06.2007
+
diff --git a/std/weapon/moving.c b/std/weapon/moving.c
new file mode 100644
index 0000000..ce81770
--- /dev/null
+++ b/std/weapon/moving.c
@@ -0,0 +1,36 @@
+// MorgenGrauen MUDlib
+//
+// weapon/moving.c -- Bewegen/Zerstoeren von Waffen
+//
+// $Id: moving.c 6312 2007-05-20 22:40:51Z Zesstra $
+
+#pragma strict_types
+#pragma save_types
+#pragma no_clone
+#pragma pedantic
+#pragma range_check
+
+inherit "/std/thing/moving";
+
+//#define NEED_PROTOTYPES 1
+
+#include <thing/properties.h>
+#include <properties.h>
+#include <moving.h>
+#include <defines.h>
+
+varargs int DoUnwield(int silent);
+
+varargs int move(mixed dest, int method)
+{
+ DoUnwield( method & (M_SILENT|M_NOCHECK));
+ if ((method & M_NOCHECK) || (!QueryProp(P_WIELDED)))
+ return ::move(dest, method );
+}
+
+varargs int remove(int silent )
+{
+ DoUnwield( silent );
+ if (!QueryProp(P_WIELDED))
+ return ::remove( silent );
+}