Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/clothing/wear.c b/std/clothing/wear.c
new file mode 100644
index 0000000..dcde4bd
--- /dev/null
+++ b/std/clothing/wear.c
@@ -0,0 +1,594 @@
+// MorgenGrauen MUDlib
+//
+// clothing/wear.c -- Funktionen rund ums Anziehen/Tragen von Kleidung.
+//
+// $Id: combat.c 6243 2007-03-15 21:10:21Z Zesstra $
+
+#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 <living/clothing.h>
+#include <clothing.h>
+#include <living/combat.h>
+#include <language.h>
+#include <defines.h>
+#include <new_skills.h>
+#include <moving.h>
+
+// Globale Variablen
+nosave int flaw, ftime;
+
+void create()
+{
+ // Einige Properties sollten nicht von aussen gesetzt werden koennen
+ Set(P_WORN, PROTECTED, F_MODE);
+ Set(P_LAST_USE, PROTECTED, F_MODE_AS);
+ Set(P_RESTRICTIONS,([]),F_VALUE);
+
+ // Bekleidung benoetigt Kommandos, mit denen man sie an- und
+ // ausziehen kann
+ AddCmd( ({"zieh","ziehe"}),"ziehe" );
+ AddCmd( ({"trag","trage"}),"do_wear" );
+}
+
+// aktuelles Lebewesen, was diese Kleidung (oder auch Ruestung) zur Zeit
+// traegt.
+public object QueryUser()
+{
+ return QueryProp(P_WORN);
+}
+
+
+// Ausgabe von Meldungen ueber write() oder _notify_fail(), je nachdem, ob der
+// Spieler alles anzieht oder was bestimmtes.
+protected void msg(string str, mixed fl) {
+ if (!stringp(str)) {
+ return;
+ }
+ if (fl) {
+ write(str);
+ }
+ else {
+ _notify_fail(str);
+ }
+}
+
+/*
+ * Ausgabe einer Meldung beim Anziehen geht nur an Spieler, nicht an NPC.
+ * Die Umgebung bekommt immer eine Meldung.
+ */
+varargs void doWearMessage(int all) {
+ string *str,s1;
+ mixed wearmsg;
+
+ if(wearmsg=QueryProp(P_WEAR_MSG)) { // Ist eine WearMsg gesetzt?
+ if(closurep(wearmsg)) { // Evtl. gar als extra Fkt.?
+
+ str = funcall(wearmsg, PL);
+ if(interactive(PL)) {
+ // Im Falle, dass all gesetzt ist, wird als Indent der Name des
+ // angezogenen Objektes gesetzt. (trag alles)
+ write(break_string(str[0],78,
+ (all?(Name(WER)+": "):0), BS_LEAVE_MY_LFS));
+ }
+ //(Zesstra): say() ist hier bloed, weil es an das Env vom this_player()
+ //ausgibt, sofern der existiert. So koennen Spieler die meldung kriegen,
+ //obwohl die laengst woanders sind (z.B. Sequenzen)
+ //Daher nun Ausgabe an das Env vom Env (wenn das kein Raum sein sollte,
+ //was durchaus sein koennte, macht tell_room() nix).
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ tell_room(environment(environment()),
+ break_string(str[1], 78, 0, BS_LEAVE_MY_LFS),({PL}) );
+
+ return;
+ }
+ else if(interactive(PL)) {
+ s1 = replace_personal(sprintf(wearmsg[0],"@WEN2"), ({PL,ME}), 1);
+
+ write(break_string(s1,78,(all?(Name(WER)+": "):0), BS_LEAVE_MY_LFS));
+ }
+
+ s1 = replace_personal(sprintf(wearmsg[1],"@WER1","@WENU2"),
+ ({PL, ME}), 1);
+
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ tell_room(environment(environment()),
+ break_string(s1, 78, 0, BS_LEAVE_MY_LFS),({ PL }) );
+
+ return;
+ }
+ /*
+ * Keine WearMsg gesetzt. Ausgabe der Default-Meldungen.
+ */
+ else if(interactive(PL)) {
+ write(break_string("Du ziehst " + name(WEN,1) + " an.",78,
+ (all?(Name(WER)+": "):0)));
+ }
+ if ( objectp(environment()) && objectp(environment(environment())) )
+ tell_room(environment(environment()),break_string(PL->Name(WER)
+ + " zieht " + name(WEN,0) +" an.",78), ({PL}));
+}
+
+/*
+ * Ausgabe einer Meldung beim Ausziehen geht nur an Spieler, nicht an NPC.
+ * Die Umgebung bekommt natuerlich immer eine Meldung.
+ */
+void doUnwearMessage(object worn_by, int all)
+{
+ string *str,s1;
+ mixed msg;
+
+ if(!objectp(worn_by)) { // Na huch, gar nicht angezogen? Abbruch.
+ return;
+ }
+
+ if(msg=QueryProp(P_UNWEAR_MSG)) { // Ist eine UnwearMsg gesetzt?
+ if(closurep(msg)) { // Oho! Gar gleich als Fkt.?
+
+ str = funcall(msg, worn_by);
+ if(interactive(worn_by)) {
+ tell_object(worn_by,break_string(str[0], 78,
+ (all?(Name(WER)+": "):0),BS_LEAVE_MY_LFS));
+ }
+
+ //(Zesstra): say() ist hier bloed, weil es an das Env vom this_player()
+ //ausgibt, sofern der existiert. So koennen Spieler die meldung kriegen,
+ //obwohl die laengst woanders sind (z.B. Sequenzen)
+ //Daher nun Ausgabe an das Env vom worn_by (wenn das kein Raum sein sollte,
+ //macht tell_room() nix).
+ if ( objectp(environment(worn_by)) )
+ tell_room(environment(worn_by),
+ break_string(str[1],78, 0, BS_LEAVE_MY_LFS),({ worn_by }) );
+
+ return;
+ }
+ else if(interactive(worn_by)) {
+ s1 = replace_personal(sprintf(msg[0],"@WEN2"),
+ ({worn_by,ME}), 1);
+
+ tell_object(worn_by,break_string(s1,78,
+ (all?(Name(WER)+": "):0), BS_LEAVE_MY_LFS));
+ }
+
+ s1 = replace_personal(sprintf(msg[1],"@WER1","@WENU2"),
+ ({worn_by, ME }), 1);
+
+ if ( objectp(environment(worn_by)) )
+ tell_room(environment(environment()),
+ break_string(s1,78, 0, BS_LEAVE_MY_LFS),({ worn_by }) );
+ return;
+ }
+ /*
+ * Keine UnwearMsg gesetzt. Ausgabe der Default-Meldungen.
+ */
+ else if(interactive(worn_by)) {
+ tell_object(worn_by,break_string("Du ziehst " + name(WEN,1) + " aus.",78,
+ (all?(Name(WER)+": "):0)));
+ }
+ if ( objectp(environment(worn_by)) )
+ tell_room(environment(worn_by), break_string(worn_by->Name(WER)
+ + " zieht " + name(WEN,0) + " aus.",78), ({ worn_by }) );
+}
+
+// Diese Funktion wird aufgerufen, wenn die Ruestung wirklich angezogen
+// wird
+protected void InformWear(object pl, int silent, int all) {
+ return;
+}
+
+// Diese Funktion wird aufgerufen, wenn die Ruestung wirklich ausgezogen
+// wird
+protected void InformUnwear(object pl, int silent, int all) {
+ return;
+}
+
+// liefert Werte <0 zurueck, wenn der Spieler die Kleidung _nicht_
+// anziehen darf.
+// Hierbei steht -1 dafuer, dass der Aufrufer return 0 machen sollte,
+// <= -2 sollte zur einem return !all fuehren.
+protected int _check_wear_restrictions(int silent, int all) {
+ mixed type,res;
+ object *armours;
+
+ // Man kann nur Kram anziehen, die man bei sich traegt
+ if (environment()!=PL) {
+ msg(break_string("Du musst "+name(WEN,1)+" erst nehmen!",78,
+ (all?(Name(WER)+": "):0)), all);
+ return(-1);
+ }
+
+ // Eine getragene Ruestung kann man nicht nochmal anziehen
+ if (QueryProp(P_WORN)) {
+ msg(break_string("Du traegst "+name(WEN,1)+" bereits.",78,
+ (all?(Name(WER)+": "):0)), all);
+ return(-1);
+ }
+
+ // Diese Funktion versucht immer, TP anzuziehen (*args*). Es gibt aber viele
+ // Magier, die ohne TP oder mit dem falschen TP anziehen wollen. Daher mal
+ // pruefen und ggf. Fehler ausloesen.
+ if (!this_player())
+ raise_error("Kein this_player() existent beim Anziehen!\n");
+ else if (this_player() != environment())
+ raise_error("Meine Umgebung beim Anziehen ist nicht this_player()!\n");
+
+ // Ueber P_RESTRICTIONS kann man einige Restriktionen definieren, ohne
+ // gleich auf eine WearFunc zurueckgreifen zu muessen.
+ // Die Auswertung erfolgt ueber den RestrictionChecker
+ if ((res=QueryProp(P_RESTRICTIONS)) && mappingp(res) &&
+ (res=(string)"/std/restriction_checker"->check_restrictions(PL,res))
+ && stringp(res)) {
+ msg(break_string(res,78,(all?(Name(WER)+": "):0)),all);
+ return(-1);
+ }
+
+ // Ist eine WearFunc gesetzt, wird diese aufgerufen.
+ if (objectp(res=QueryProp(P_WEAR_FUNC)) &&
+ !(res->WearFunc(ME, silent, environment()))) {
+ // Eine Meldung muss von der WearFunc ausgegeben werden
+ return(-2);
+ }
+
+ // scheinbar darf man das hier anziehen. ;-)
+ return 0;
+}
+
+protected void _informwear(int silent, int all) {
+
+ // Eine Meldung ausgeben, wenn das silent-Flag nicht gesetzt ist
+ if (!silent) {
+ doWearMessage(all);
+ }
+
+ // Inform-Funktion aufrufen
+ InformWear(PL, silent, all);
+}
+
+// Die Funktion, die das eigentliche Anziehen durchfuehrt
+varargs int DoWear(int silent, int all) {
+ int nh;
+
+ // Bedingungen pruefen, _check_restrictions() gibt die notwendigen Meldungen
+ // an den Spieler aus.
+ int res = _check_wear_restrictions(silent, all);
+ if (res == -1)
+ return(0);
+ else if (res <= -2)
+ return(!all);
+
+ // Der Check auf freie Haende muss nach allen anderen Checks aus Kleidung
+ // und Ruestung erfolgen und ist im Prinzip identisch fuer beide. Daher wird
+ // der hier in dieser Funktion gemacht.
+ // Soll das Objekt Haende "benutzen"? Steht da auch wirklich ein
+ // Integer-Wert drin? ich mach da jetzt ein raise_error(), das soll
+ // schliesslich gefixt werden. Ausserdem spart es nen Workaround beim
+ // Ausziehen.
+ if (!intp(nh=QueryProp(P_NR_HANDS))) {
+ raise_error(sprintf("Invalid P_NR_HANDS in %O",object_name()));
+ }
+ // Wenn Haende benutzt werden sollen, muss natuerlich auch getestet
+ // werden, ob das ueberhaupt geht
+ if (nh>0) {
+ if (!(PL->UseHands(ME, nh))) {
+ // Schade, nicht genug Haende frei -> Meldung ausgeben
+ write(break_string("Du hast keine Hand mehr frei.",78,
+ (all?(Name(WER)+": "):0)));
+ return(!all);
+ }
+ }
+
+ // OK, die Ruestung kann angezogen werden.
+ // Behinderung beim Wechsel nur fuer Spieler
+ if (query_once_interactive(PL))
+ // Wenn das Ganze ,,wirklich'' eine Kleidung/Ruestung ist und kein SMS
+ // oder aehnliches...
+ if (!QueryProp(P_WEAPON_TYPE)) {
+ // Aktion noch setzen, Spieler hat ja was angezogen
+ PL->SetProp(P_LAST_WEAR_ACTION,({WA_WEAR,time()}));
+ // Im Kampf verliert der Spieler durch Kleidungswechsel eine Runde.
+ if (PL->InFight()) {
+ PL->SetProp(P_ATTACK_BUSY,1);
+ }
+ }
+ // Eintragen in P_CLOTHING/P_ARMOURS
+ PL->Wear(this_object());
+
+ PL->SetProp(P_EQUIP_TIME,time());
+ SetProp(P_WORN, PL);
+ SetProp(P_EQUIP_TIME,time());
+
+ // ggf. andere Objekte informieren etc.
+ _informwear(silent, all);
+
+ // Fertig mit dem Anziehen. Vorgang beenden bzw. mit anderen
+ // Ruestungen fortfahren
+ return !all;
+}
+
+
+// liefert 0 zureck, wenn die Kleidung/Ruestung ausgezogen werden kann
+// bei M_NOCHECK ist das Ausziehen immer erlaubt, allerdings wird
+// P_REMOVE_FUNC auch dann gerufen (wenn auch ignoriert).
+// <0 verbietet das Ausziehen
+protected int _check_unwear_restrictions(object worn_by, int silent,
+ int all)
+{
+ // Nicht getragene Ruestungen kann man auch nicht ausziehen
+ if (!objectp(worn_by)) {
+ return(-2);
+ }
+
+ // Ist eine RemoveFunc gesetzt, wird diese aufgerufen
+ // Im Falle von M_NOCHECK wird das Ergebnis allerdings ignoriert.
+ mixed res=QueryProp(P_REMOVE_FUNC);
+ if (objectp(res)
+ && !res->RemoveFunc(ME,silent,worn_by)
+ && !(silent & M_NOCHECK)
+ )
+ {
+ // Eine Meldung muss von der RemoveFunc ausgegeben werden
+ return(-2);
+ }
+
+ // generell hebt M_NOCHECK die Restriktionen auf - sonst kommt es zu
+ // massiven Inkonsistenzen beim Bewegen mit M_NOCHECK.
+ if (silent & M_NOCHECK)
+ return 1;
+
+ // Eine verfluchte Ruestung kann man natuerlich nicht ausziehen
+ res=QueryProp(P_CURSED);
+ if (res ) {
+ if (stringp(res)) {
+ // Stand in P_CURSED ein String? Dann diesen ausgeben
+ tell_object(worn_by,
+ (res[<1]=='\n' ? res : break_string(res,78,
+ (all?(Name(WER)+": "):0))));
+ }
+ else {
+ // Sonst eine Standard-Meldung ausgeben
+ tell_object(worn_by,break_string(
+ "Du kannst " + name(WEN) + " nicht ausziehen, " + QueryPronoun(WER)
+ + " ist verflucht worden.\n",78,(all?(Name(WER)+": "):0)));
+ }
+ return(-2);
+ }
+
+ // Ausziehen moeglich
+ return(1);
+}
+
+protected void _informunwear(object worn_by, int silent, int all) {
+
+ // Inform-Funktion aufrufen
+ InformUnwear(worn_by, silent, all);
+
+ // Meldung ausgeben, wenn das silent-Flag nicht gesetzt ist
+ if (!(silent&M_SILENT)) {
+ doUnwearMessage( worn_by, all );
+ }
+}
+
+// Die Funktion, die das eigentliche Ausziehen durchfuehrt
+// hier steht nur drin, was auf jeden Fall fuer Kleidungen und Ruestungen
+// gleich ist, damit man bei Ruestungen diese Funktion nicht ueberschreiben
+// muss.
+varargs int DoUnwear(int silent, int all) {
+ object worn_by;
+ int nh;
+
+ // Das Flag "silent" wird in der RemoveFunc() etwas anders behandelt
+ // als ueberall anders. Deshalb wird M_SILENT gesetzt, sofern "silent"
+ // _irgendeinen_ Wert ausser M_NOCHECK hatte.
+ if ( silent & ~M_NOCHECK )
+ silent |= M_SILENT;
+
+ // Standard-Notfiyfail setzen.
+ if (all)
+ notify_fail("Alles ausgezogen, was ging.\n");
+
+ // Hat das Objekt Haende "benutzt"? Steht da auch wirklich ein
+ // Integer-Wert drin? Wenn nicht, mach ich nen raise_error(), das duerfte
+ // eigentlich gar nicht passieren. Pruefung mal am Anfang machen, bevor
+ // irgendwas anderes (RemoveFunc()) passiert ist.
+ if (!intp(nh=QueryProp(P_NR_HANDS))) {
+ raise_error(sprintf("Invalid P_NR_HANDS in %O",object_name()));
+ }
+
+ worn_by=QueryProp(P_WORN);
+ // darf ausgezogen werden? Wenn nicht, Ende.
+ int res = _check_unwear_restrictions(worn_by,silent,all);
+ if (res < 0)
+ return(!all);
+
+ // OK, alles klar, die Ruestung wird ausgezogen
+ worn_by->Unwear(ME);
+
+ // Benutzte Haende wieder freigeben
+ if (nh>0) {
+ worn_by->FreeHands(ME);
+ }
+
+ worn_by->SetProp(P_EQUIP_TIME, time());
+ SetProp(P_WORN, 0);
+
+ // Flag noch setzen, Spieler hat ja was ausgezogen
+ // Aber nur wenns auch der Spieler selbst ist.
+ // und wenn das wirklich eine Ruestung und kein SMS o.ae. ist.
+ if (PL && PL==worn_by && !QueryProp(P_WEAPON_TYPE)) {
+ //Behinderung beim Wechsel nur fuer Spieler
+ if (query_once_interactive(PL)) {
+ PL->SetProp(P_LAST_WEAR_ACTION,({WA_UNWEAR,time()}));
+ if (PL->InFight()) {
+ PL->SetProp(P_ATTACK_BUSY,1);
+ }
+ }
+ }
+
+ // ok, nun noch andere Objekte informieren.
+ _informunwear(worn_by,silent,all);
+
+ // Fertig mit dem Anziehen. Vorgang beenden bzw. mit anderen
+ // Ruestungen fortfahren
+ return !all;
+}
+
+protected int _do_wear(string str, int silent, int all) {
+ int *last;
+
+ // Standard-Notfiy-Fail setzen.
+ if (all)
+ notify_fail("Alles angezogen, was ging.\n");
+
+ // Ist diese Ruestung ueberhaupt gemeint? Bei "trage alles" ist dies
+ // natuerlich immer der Fall
+ if (!str || (!all && !id(str))) {
+ return 0;
+ }
+
+ // Vielleicht darf der Spieler ja gar nix mehr anziehen.
+ if ((object)PL->InFight()) {
+ last=(int*)PL->QueryProp(P_LAST_WEAR_ACTION);
+ if (pointerp(last) && (last[0]==WA_UNWEAR) && ((time()-last[1])<2)) {
+ notify_fail("Du hast doch gerade erst etwas ausgezogen!\n"
+ "So schnell bist Du nicht!\n");
+ return 0;
+ }
+ }
+
+ // Auf zum eigentlichen Anziehen
+ return DoWear(silent, all);
+
+}
+
+// Funktion, die das "trage"/"ziehe * an"-Kommando auswertet
+varargs int do_wear(string str, int silent) {
+ int all;
+
+ // Hat der Spieler "trage alles" eingegeben?
+ all=(str=="alles" || str=="alle kleidung" || str=="alle bekleidung");
+
+ return(_do_wear(str,silent,all));
+}
+
+protected int _do_unwear(string str, int silent, int all) {
+ int * last;
+
+ // Ist diese Ruestung ueberhaupt gemeint? Und hat dieser Spieler sie
+ // auch wirklich an?
+ if (!stringp(str) || (!all && !id(str))) {
+ return 0;
+ }
+
+ if (!QueryProp(P_WORN)) {
+ if (all) {
+ notify_fail("Alles ausgezogen, was ging.\n");
+ return 0;
+ }
+ if (!Query(P_ARTICLE) || QueryProp(P_PLURAL)) {
+ notify_fail( break_string(
+ "Du traegst k"+name(WEN,0)+".",78) );
+ }
+ else {
+ notify_fail( break_string(
+ "Du traegst "+name(WEN,1)+" nicht.",78) );
+ }
+ return 0;
+ }
+
+ // Vielleicht darf der Spieler ja gar nichts mehr ausziehen.
+ if ((object)PL->InFight()) {
+ last=(int*)PL->QueryProp(P_LAST_WEAR_ACTION);
+ if (pointerp(last) && (last[0]==WA_WEAR) && ((time()-last[1])<2)) {
+ notify_fail("Du hast doch gerade erst etwas angezogen!\n"
+ "So schnell bist Du nicht!\n");
+ return 0;
+ }
+ }
+ // Auf zum eigentlichen Ausziehen
+ return DoUnwear(silent, all);
+}
+
+// Die Funktion, die das "ziehe * aus"-Kommando auswertet
+varargs int do_unwear(string str, int silent) {
+ int all;
+
+ all=(str=="alles" || str=="alle kleidung" || str=="alle bekleidung");
+
+ return(_do_unwear(str,silent,all));
+}
+
+// Funktion, die das "ziehe"-Kommando auswertet
+int ziehe(string str) {
+ string ob;
+
+ // Uebergebenes Argument pruefen
+ if (!stringp(str)) {
+ return 0;
+ }
+
+ // Ist ANziehen gemeint?
+ if (sscanf(str, "%s an", ob)==1) {
+ return do_wear(ob );
+ }
+
+ // Oder ist AUSziehen gemeint?
+ if (sscanf(str, "%s aus", ob)==1 ) {
+ return do_unwear(ob);
+ }
+
+ // Ok, es geht wohl weder ums an- noch ums ausziehen
+ return 0;
+}
+
+
+// Beschaedigen des Kleidungsstuecks
+
+// Direktes Beschaedigen der Kleidung durch Setzen der Prop gibts nicht. ;-)
+// Das geht aus Kompatibilitaetgruenden bei Ruestungen, aber nicht mehr bei
+// Kleidung. Punkt.
+static mixed _set_item_damaged(mixed arg) {
+ return(QueryProp(P_DAMAGED));
+}
+
+// Will man eine Kleidung 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) {
+ return 0;
+}
+
+// Wird die Kleidung einer Belastung ausgesetzt (bei Ruestungen z.B. bei einem
+// Angriff eines Gegners), dann wird TakeFlaw() aufgerufen. Bei Kleidungen
+// koennte man ja per P_SENSITIVE arbeiten oder ein Magier ruft bei Aktionen
+// TakeFlaw() auf.
+varargs void TakeFlaw(mixed dam_types,mapping einfos) {
+ int quality;
+
+ // Ist der Ruestung eine Qualitaet gesetzt worden, so kann es zu einer
+ // allmaehlichen Beschaedigung der Ruestung kommen. Im if() flaw gleich
+ // hochzaehlen.
+ if ((quality=QueryProp(P_QUALITY)) && !((++flaw) % quality)) {
+ 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)});
+}
+
+public status IsClothing() {return 1;}
+