Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/doc/beispiele/testobjekte/.readme b/doc/beispiele/testobjekte/.readme
new file mode 100644
index 0000000..56ff41f
--- /dev/null
+++ b/doc/beispiele/testobjekte/.readme
@@ -0,0 +1,13 @@
+
+Hier liegen Test-Objekte zu man-pages. Unterschieden wird momentan nur nach:
+- xxx_testobj -> das kann man laden und ggf clonen
+- xxx_testraum -> den kann man betreten
+
+Der Praefix deutet an, fuer welche Features (also man-pages) der Testcode geschrieben wurde. Die man-page selbst nennt diesen Dateinamen hier, insofern:
+* bitte mit Bedacht veraendern - pruefen, welche Funktionalitaet
+ beispielhaft gezeigt werden soll und das nicht loeschen
+* bitte Dateinamen nur veraendern, wenn ihr euch sicher seid, _alle_
+ darauf verweisenden man-pages ebenfalls geaendert zu haben
+
+Verantwortlich: Gloinson
+
diff --git a/doc/beispiele/testobjekte/attack_busy_sensitive_testobj.c b/doc/beispiele/testobjekte/attack_busy_sensitive_testobj.c
new file mode 100644
index 0000000..4225d88
--- /dev/null
+++ b/doc/beispiele/testobjekte/attack_busy_sensitive_testobj.c
@@ -0,0 +1,105 @@
+inherit "/std/thing";
+#include <properties.h>
+#include <new_skills.h>
+#include <sensitive.h>
+
+private action_puste(string str);
+private int counter;
+
+void create() {
+ if (!clonep(this_object())) return;
+ ::create();
+ counter = 2+random(4);
+
+ SetProp(P_NAME, "Pusteblume");
+ SetProp(P_SHORT, "Eine kleine Pustblume");
+ SetProp(P_LONG, break_string(
+ "Eine abgebluehte Pflanze, die jetzt wie ein kleiner, weisser Ball "
+ "aussieht. Die fiedrigen Samen fliegen bestimmt prima.", 78));
+ AddDetail("samen", "Er sieht sehr fein und leicht aus.\n");
+ SetProp(P_GENDER,FEMALE);
+ SetProp(P_MATERIAL, MAT_MISC_PLANT);
+ SetProp(P_NOBUY, 1);
+ SetProp(P_VALUE, random(10));
+
+ SetProp(P_INFO, "Starker Wind taete ihr nicht gut.\n");
+
+ AddId(({"blume", "pusteblume", "loewenzahn"}));
+ SetProp(P_COMBATCMDS,(["puste loewenzahn":
+ ([C_HEAL: 5])]));
+
+ SetProp(P_SENSITIVE,({({SENSITIVE_ATTACK, DT_AIR, 20}),
+ ({SENSITIVE_INVENTORY, DT_AIR, 20})}));
+
+ AddCmd("puste&@ID", #'action_puste, "Puste wen oder was (an)?");
+}
+
+private action_puste(string str) {
+ if(environment()!=this_player()) {
+ notify_fail("Dazu solltest du "+name(WEN,1)+" haben.\n");
+ return 0;
+ }
+ if (this_player()->QueryProp(P_ATTACK_BUSY)) {
+ write("Du hast dafuer momentan einfach nicht mehr die Puste.\n");
+ return 1;
+ }
+ this_player()->SetProp(P_ATTACK_BUSY, 1);
+
+ if(counter<0) {
+ write(break_string("Du pustest sinnlos auf "+name(WEN, 2)+".", 78));
+ say(break_string(this_player()->Name(WER)+
+ " pustet wie daemlich gegen "+name(WEN, 0)+".", 78));
+ return 1;
+ } else {
+ write(break_string(
+ "Du pustest "+name(WEN, 2)+" vorsichtig an, einige Samen "
+ "loesen sich und fliegen taumelnd in deinem Atem davon."+
+ (counter<0?" Es bleibt nur noch ein nutzloser Strunk.":""), 78));
+ say(break_string(
+ this_player()->Name(WER)+" pustet sachte gegen "+name(WEN, 0)+" und "
+ "du schaust verzueckt den davonfliegenden Samen nach.", 78));
+ }
+
+ object who = this_player()->QueryEnemy();
+
+ if(objectp(who)) {
+ if(!interactive(this_player())) {
+ who->ModifySkillAttribute(SA_SPEED, 80+random(10), 6);
+ this_player()->heal_self(5);
+ } else
+ who->ModifySkillAttribute(SA_SPEED, 90+random(10), 4);
+ }
+
+ counter--;
+ if(counter<0) {
+ call_out(#'remove, 10+random(60));
+ AddId("strunk");
+ SetProp(P_NAME, "Strunk");
+ SetProp(P_SHORT, "Der Strunk einer Pusteblume");
+ SetProp(P_LONG, "Ein haesslicher, leerer Strunk.\n");
+ SetProp(P_GENDER, MALE);
+ }
+ return 1;
+}
+
+private void notify_env_destroy() {
+ object ob = environment();
+ while(ob && !living(ob)) ob = environment(ob);
+ if(objectp(ob))
+ tell_object(ob, "Der Wind zerblaest "+name(WEN, 2)+".\n");
+ remove(1);
+}
+
+varargs void trigger_sensitive_attack() {
+ notify_env_destroy();
+}
+
+varargs void trigger_sensitive_inv() {
+ notify_env_destroy();
+}
+
+varargs int remove(int silent) {
+ if(!silent && living(environment()))
+ tell_object(environment(), "Du wirfst "+name(WEN, 2)+" weg.\n");
+ return ::remove(silent);
+}
\ No newline at end of file
diff --git a/doc/beispiele/testobjekte/command_me_testraum.c b/doc/beispiele/testobjekte/command_me_testraum.c
new file mode 100644
index 0000000..29086ce
--- /dev/null
+++ b/doc/beispiele/testobjekte/command_me_testraum.c
@@ -0,0 +1,33 @@
+#include <properties.h>
+inherit "/std/room";
+
+void create() {
+ ::create();
+ SetProp(P_LONG, "AddCmd-Testraum, Kommandos "
+ "\"kriech\" und \"schleiche&heran|herum\".");
+ AddCmd("schleiche&heran|herum", "action_schleichen");
+ AddExit("gilde", "/gilden/abenteurer");
+}
+
+void init() {
+ ::init();
+ add_action("action_kriechen", "kriech", 1);
+}
+
+static action_schleichen(string str) {
+ string tmp = this_player()->QueryProp(P_RACE);
+ if(tmp[<1]=='e') tmp=tmp[0..<2];
+ write(break_string("Du versuchst leise zu schleichen, dabei passiert "
+ "dir aber ein allzu "+
+ (tmp=="Mensch"?"menschliches":lower_case(tmp)+"isches")+
+ " Missgeschick. Verflucht!", 78));
+ this_player()->command_me("\\furze");
+ return 1;
+}
+
+static int action_kriechen(string str) {
+ write(break_string("Deine Knie tun zu sehr weh dafuer.", 78));
+ tell_room(this_object(), break_string(this_player()->Name(WER)+
+ " knackt mit den Knien.", 78));
+ return 1;
+}
\ No newline at end of file
diff --git a/doc/beispiele/testobjekte/modifyskillspell_test.c b/doc/beispiele/testobjekte/modifyskillspell_test.c
new file mode 100644
index 0000000..3c58342
--- /dev/null
+++ b/doc/beispiele/testobjekte/modifyskillspell_test.c
@@ -0,0 +1,103 @@
+// ModifySkill-Beispiel fuer einem Spell. Erlaeuterung auf man-Page
+// und im Objekt selbst
+inherit "/std/thing";
+#include <new_skills.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <break_string.h>
+
+static int skillset(string str);
+static int skillunset(string str);
+
+void create() {
+ if(!clonep(this_object())) {
+ set_next_reset(-1);
+ return;
+ }
+
+ ::create();
+ set_next_reset(7200);
+
+ SetProp(P_NAME, "Skillbeispiel");
+ SetProp(P_SHORT, "Eine Skillbeispiel");
+ SetProp(P_LONG, break_string(
+ "Mit \"skillset\" kann man sich den Skill (eigentlich Spell) "
+ "\"fnrx\" setzen.\n"+
+ "Durch \"skillunset\" wird der Skill geloescht.\n"
+ "Das zaehlt deshalb als Spell, weil er kleingeschrieben und "
+ "damit direkt vom Spieler (also dir) als Kommando via UseSpell() "
+ "ausfuehrbar ist.", 78, 0, BS_LEAVE_MY_LFS));
+ SetProp(P_GENDER, NEUTER);
+ AddId(({"beispiel", "skillbeispiel", "spellbeispiel",
+ "skill", "spell"}));
+
+ AddCmd("skillset", #'skillset);
+ AddCmd("skillunset", #'skillunset);
+}
+
+// Testfunktion, weil im Code dazu aufgefordert wird, das Objekt auch
+// mal zu wegzulegen. Spieler sollten nicht an sich herumfummeln.
+private static int _checkLearner(object pl) {
+ if(!IS_LEARNER(this_player())) {
+ notify_fail("Du bist kein Magier, deshalb geht das nicht.\n");
+ call_out(#'remove, 1);
+ return 0;
+ }
+ return 1;
+}
+
+static int skillset(string str) {
+ if(!_checkLearner(this_player()))
+ return 0;
+
+ if(this_player()->QuerySkill("fnrx")) {
+ notify_fail("Du kannst den Skill schon.\n");
+ return 0;
+ }
+
+ this_player()->ModifySkill("fnrx",
+ ([SI_CLOSURE: function int (object caster, string skill, mapping sinf) {
+ caster->LearnSkill("fnrx", 1);
+ tell_object(caster, "Peng! Dein Skillwert steigt auf "+
+ caster->QuerySkillAbility("fnrx")+".\n");
+ return 1;
+ },
+ SI_SKILLABILITY: 8432]), 100, "ANY");
+ tell_object(this_player(), break_string(
+ "Der Skill ist gesetzt. Tipp doch ein paar Mal \"fnrx\" und schau den "
+ "Code unter "+load_name(this_object())+" an, damit du siehst, dass der "
+ "Skill jetzt nur aus einem Eintrag in dir und einer ueber UseSpell() "
+ "gerufenen Funktion in diesem Objekt besteht. Der Skill ist kein "
+ "Kommando in einem anderen Objekt.\n\n"
+ "Wenn du dieses Objekt weglegst, funktioniert also alles weiter. "
+ "Zerstoerst du aber das Objekt (oder dich mit \"ende\", funktioniert "
+ "die Skillfunktion nicht mehr.\n"
+ "Schau dir auch xeval this_player()->QuerySkill(\"fnrx\") an.", 78, 0,
+ BS_LEAVE_MY_LFS));
+ return 1;
+}
+
+// Here be dragons!
+// Bitte benutzt die folgende Art von Manipulation der Skills nur dann,
+// wenn ihr genau wisst, was ihr tut. In anderen Worten: NICHT MACHEN!
+// Und wenn, dann NUR AM EIGENEN MAGIEROBJEKT, NICHT AN SPIELERN!
+static int skillunset(string str) {
+ if(!_checkLearner(this_player()))
+ return 0;
+
+ // per Query() das Mapping an der _query_*-Fun vorbei direkt holen
+ mapping skills = this_player()->Query(P_NEWSKILLS);
+ // ... und manipulieren (wirkt sich wegen Referenz direkt aus)
+ if(mappingp(skills) && mappingp(skills["ANY"]) &&
+ member(skills["ANY"], "fnrx")) {
+ efun::m_delete(skills["ANY"], "fnrx");
+ tell_object(this_player(), "Erledigt.\n");
+ } else
+ tell_object(this_player(), "Nichts zu erledigen.\n");
+
+ return 1;
+}
+
+void reset() {
+ remove();
+}
diff --git a/doc/beispiele/testobjekte/netdead_info_testraum.c b/doc/beispiele/testobjekte/netdead_info_testraum.c
new file mode 100644
index 0000000..b2d8a71
--- /dev/null
+++ b/doc/beispiele/testobjekte/netdead_info_testraum.c
@@ -0,0 +1,69 @@
+// Beispielraum fuer P_NETDEAD_INFO-Funktionalitaet
+#include <properties.h>
+#include <break_string.h>
+inherit "/std/room";
+
+string create_destiny(mixed val);
+int create_room(string dir);
+
+void create() {
+ ::create();
+
+ if (clonep(this_object())) {
+ // setze Informationen, die in einem Netztoten gespeichert werden sollen
+ Set(P_NETDEAD_INFO, random(5));
+ SetProp(P_INT_LONG, break_string(
+ "Wenn du hier einschlaefst, wird der Raum nach 30s zerstoert. Beim "
+ "Aufwachen wirst du an die Blueprint dieses Raums die Info "+
+ QueryProp(P_NETDEAD_INFO)+" uebergeben. Diese wird aus dieser Info "
+ "einen Raumpfad ermitteln, in den du bewegt wirst.", 78));
+ } else {
+ // Blueprint: hier kann man zu einem Cloneraum gehen
+ AddExit("cloneraum", #'create_room);
+ SetProp(P_INT_LONG, break_string(
+ "Zum Testen einfach den Ausgang 'cloneraum' benutzen. Es wird dann "
+ "ein Raum geclont, in den man bewegt wird. Wenn man dort einschlaeft, "
+ "wird der geclonte Raum nach circa 30s zerstoert.\n"
+ "Beim Aufwachen werden die im Spieler gespeicherten Informationen des "
+ "geclonten (und nunmehr zerstoerten) Raumes benutzt, um einen "
+ "alternativen Aufwachraum (Klerusgilde, Karategilde, Wald oder Port "
+ "Vain) zu bestimmen.\n"
+ "Andernfalls wuerde der Spieler in der Abenteurergilde erwachen.", 78,
+ 0, BS_LEAVE_MY_LFS));
+ }
+
+ // Set-Method, um die Informationen aus P_NETDEAD_INFO beim Aufwachen
+ // in der Blueprint auswerten zu koennen
+ Set(P_NETDEAD_INFO, #'create_destiny, F_SET_METHOD);
+ SetProp(P_LIGHT, 1);
+}
+
+// Raum entfernen, normalerweise so KEINE GUTE IDEE!
+void BecomesNetDead(object pl) {
+ call_out(#'remove, 30);
+}
+
+// erzeuge einen Cloneraum und bewege den Spieler dahin
+int create_room(string dir) {
+ object dest = clone_object(object_name(this_object()));
+ this_player()->move(dest, M_NOCHECK);
+ return 1;
+}
+
+// Set-Method fuer P_NETDEAD_INFO: gibt Pfad zurueck
+// benutze die Informationen aus dem jetzt aufwachenden Netztoten, um einen
+// alternativen Aufwachraum zu ermitteln, da der Einschlafraum zerstoert ist
+string create_destiny(mixed val) {
+ if (intp(val)) {
+ switch (val) {
+ case 0:
+ return "/d/ebene/room/PortVain/po_haf1";
+ case 1:
+ return "/gilden/klerus";
+ case 2:
+ return "/gilden/karate";
+ default:
+ }
+ return "/d/ebene/room/waldweg4";
+ }
+}