Div. Fixes zum Pfluecken von Kraeutern
* Typfixes
* Datenstruktur als struct
* keine defekten Datenstrukturen in GetPlant() erzeugen:
Funktion hat Daten in der plantMap mit nur den Zeiten fuer
Regeneration angelegt, weil das Kraut mit AddPlantDetail
nicht hinzugefuegt wurde. Jetzt wird es hinzugefuegt, aber
ohne Kommando und Flag pickable und das Standardkommando
pflueckt es damit nicht
* Duplizierten Code in AddPlant und AddPlantDetail entfernt
Change-Id: I3ac5f9792d009171c70f4fac535557582f38085c
diff --git a/std/room/kraeuter.c b/std/room/kraeuter.c
index 24f5193..92f4f56 100644
--- a/std/room/kraeuter.c
+++ b/std/room/kraeuter.c
@@ -9,15 +9,24 @@
#include <defines.h>
#include <living/combat.h> // Fuer P_FREE_HANDS
+public int AddPlantDetail(string filename);
+
// Standardwert von 2 h fuer vollstaendige Regeneration des Krautes.
// Einfaches Nachwachsen ist typischerweise die Haelfte davon.
#define STD_WACHSTUM 7200
#define BS(x) break_string(x, 78)
-// Struktur (6 Eintraege pro Kraut):
-// ([ filename : ({ Zeit_bis_nachgewachsen, Zeit_bis_komplett_regeneriert,
-// Kraut-IDs, Kraut-Adjektive, Kraut->Name(WER,1),
-// ID_des_Bewacher-NPCs }) ])
+// Struktur (7 Eintraege pro Kraut):
+struct plantinfo {
+ int regrow; // Zeit_bis_nachgewachsen
+ int regeneration; // Zeit_bis_komplett_regeneriert
+ int pickable; // per Standardkommanod pflueckbar?
+ string *ids; // Kraut-IDs
+ string *adj; // Kraut-Adjektive
+ string name; // Kraut->Name(WER,1)
+ string *guards; // ID_des_Bewacher-NPCs
+};
+// ([ filename : struct plantinfo ])
mapping plantMap = ([]);
// kann benutzt werden um schnell und einfach eine Pflanze in einem Raum
@@ -28,99 +37,102 @@
// 1 -> Erfolg; -1 -> filename ungueltig
varargs int AddPlant(string filename, string|string* npcId)
{
- mixed arr;
-
- // Dateiname nicht uebergeben? Dann tun wir erstmal gar nix.
- if (!stringp(filename))
+ // Eintrag und Details etc. hinzufuegen, wenn nicht erfolgreich, auch mit -1
+ // beenden.
+ if (AddPlantDetail(filename) == -1)
return -1;
- object ob=load_object(filename);
-
- // Wenn wir zu dem Kraut schon Daten haben (erkennbar an >2 Eintraegen),
- // werfen wir einen Fehler, damit das beim Laden des Raumes schon
- // erkannt wird.
- if (pointerp(arr=plantMap[filename]) && sizeof(arr)>2)
- raise_error("AddPlant(): "+filename+" already exists.\n");
- // IDs und Adjektive parsen und den Datensatz zusammenstellen
- string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
- string *adj = ob->Query(P_ADJECTIVES, F_VALUE);
-
- if (!pointerp(arr) || sizeof(arr)<2)
- arr = ({0,0});
- if ( !npcId )
- npcId = ({});
- else if (stringp(npcId))
- npcId = ({npcId});
- plantMap[filename]=({arr[0], arr[1], ids, adj, ob->Name(WER, 1), npcId });
-
- // Details erzeugen aus Adjektiven und IDs
- adj = ob->QueryProp(P_NAME_ADJ);
-
- // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
- int gender = Query(P_GENDER, F_VALUE);
- Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
-
- // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
- // und ID des Krautes ein Detail.
- adj = map(adj, #'DeclAdj, WEN, 0);
+ struct plantinfo plant = plantMap[filename];
- string *det=({});
- foreach(string _id : ids) {
- foreach(string _adj : adj) {
- det += ({ _adj + _id });
- }
+ // es ist pflueckbar
+ plant->pickable = 1;
+
+ // Bewacher noch eintragen
+ if (npcId)
+ {
+ if (stringp(npcId))
+ plant->guards = ({npcId});
+ else
+ plant->guards = npcId;
}
-
- det += ids;
- // keine existierenden Details ueberschreiben
- det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
- if (sizeof(det))
- AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
-
- // Eine Befehlsfunktion brauchen wir natuerlich auch.
+ // Eine Befehlsfunktion brauchen wir dann natuerlich auch.
AddCmd(({"pflueck", "pfluecke", "ernte"}), "_pfluecken");
-
- return 1;
+
+ // erfolgreich fertig
+ return 1;
}
// Wenn jemand per Hand das Plantdetail hinzufuegen moechte...
// z.B. bei Verwendung von GetPlant() anstelle von AddPlant()
-void AddPlantDetail(string filename)
+// Im Gegensatz zu AddPlant() fuegt es kein Kommando zum Pfluecken hinzu und
+// traegt keine Bewacher ein.
+// 1 -> Erfolg; -1 -> filename ungueltig
+public int AddPlantDetail(string filename)
{
- // Pfad in Objektpointer wandeln
+ // Dateiname nicht uebergeben? Dann tun wir erstmal gar nix.
+ if (!stringp(filename))
+ return -1;
object ob=load_object(filename);
-
- // Details erzeugen
- string *det = ({});
- string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
- string *adj = ob->QueryProp(P_NAME_ADJ);
+
+ // Wenn wir zu dem Kraut schon Daten haben, werfen wir einen Fehler, damit
+ // das beim Laden des Raumes schon erkannt wird.
+ struct plantinfo plant = plantMap[filename];
+ if (structp(plant))
+ raise_error("AddPlant(): "+filename+" already exists.\n");
+
+ plant = (<plantinfo>);
+ // IDs und Adjektive parsen und den Datensatz zusammenstellen
+ plant->ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
+ plant->adj = ob->Query(P_ADJECTIVES, F_VALUE);
+ // Keine Bewacher
+ plant->guards = ({});
+ // Ausserdem ist es nicht pflueckbar per Standardkommando (pickable nicht
+ // gesetzt)
+ // Und eintragen
+ plantMap[filename] = plant;
+
+ // Details erzeugen aus Adjektiven und IDs
+ string *name_adj = ob->QueryProp(P_NAME_ADJ);
+
// aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
- int gender=Query(P_GENDER, F_VALUE);
- Set(P_GENDER, ob->Query(P_GENDER, F_VALUE));
+ int gender = Query(P_GENDER, F_VALUE);
+ Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
+
// erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
// und ID des Krautes ein Detail.
- adj = map(adj, #'DeclAdj, WEN, 0);
- foreach(string _id : ids) {
- foreach(string _adj : adj) {
+ name_adj = map(name_adj, #'DeclAdj, WEN, 0);
+
+ // Geschlecht zuruecksetzen
+ Set(P_GENDER, gender, F_VALUE);
+
+ string *det=({});
+ foreach(string _id : plant->ids) {
+ foreach(string _adj : name_adj) {
det += ({ _adj + _id });
}
}
- AddDetail(det+ids, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
- // Geschlecht zuruecksetzen
- Set(P_GENDER, gender, F_VALUE);
+
+ det += plant->ids;
+ // keine existierenden Details ueberschreiben
+ det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
+ if (sizeof(det))
+ AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
+
+ return 1;
}
// Prueft, ob die Pflanze zu "filename" in diesem Raum schon nachgewachsen
// ist.
protected int CheckPlant(string filename)
{
- mixed arr=plantMap[filename];
- if (!pointerp(arr) || sizeof(arr)<2) {
- arr=plantMap[filename]=({ 0, 0 });
- }
+ struct plantinfo plant = plantMap[filename];
+ // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
+ if (!structp(plant))
+ return 0;
+
// Solange die Zeit arr[0] noch nicht erreicht ist, ist das Kraut nicht
// nachgewachsen, dann gibt es gar nix.
- return (time()>arr[0]);
+ return (time() > plant->regrow);
}
// Moechte man AddPlant() nicht benutzen, weil man die Pflanze nicht einfach
@@ -130,32 +142,34 @@
// nachgewachsen.
object GetPlant(string filename)
{
- int *arr=plantMap[filename];
- if (!pointerp(arr) || sizeof(arr)<2)
- {
- arr=plantMap[filename]=({ 0, 0 });
- }
- // arr[0] enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
- int nachgewachsen = arr[0];
- // arr[1] denjenigen, wann es vollstaendig regeneriert ist.
- int regeneriert = arr[1];
+ struct plantinfo plant = plantMap[filename];
+ // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
+ if (!structp(plant))
+ return 0;
+
+ // regrow enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
+ // regeneration denjenigen, wann es vollstaendig regeneriert ist.
// Vor dem Nachgewachsen-Zeitpunkt kann man gar nix ernten.
- if (time()<nachgewachsen) return 0; // noch nicht nachgewachsen
+ if (time() < plant->regrow)
+ return 0; // noch nicht nachgewachsen
// Restzeit bis zur vollstaendigen Regeneration.
- regeneriert-=time();
-
+ int regeneriert = plant->regeneration - time();
+
// Wenn vollstaendig regeneriert, ist STD_WACHSTUM die neue Zeit bis zur
- // Regeneration. Wenn noch nicht vollstaendig regenriert, Restzeit
+ // Regeneration. Wenn noch nicht vollstaendig regeneriert, Restzeit
// verdoppeln und STD_WACHSTUM nochmal drauf addieren.
- regeneriert = (regeneriert<=0 ? STD_WACHSTUM
- : (regeneriert*2)+STD_WACHSTUM);
- // nachgewachsen ist die halbe Regenerationszeit
- arr[0]=nachgewachsen=time()+(regeneriert/2);
- // Zeit voelliger Regeneration
- arr[1]=regeneriert+=time();
-
+ if (regeneriert<=0)
+ regeneriert = STD_WACHSTUM;
+ else
+ regeneriert = (regeneriert*2)+STD_WACHSTUM;
+
+ // Zeitpunkt des Nachwachsen ist die halbe Regenerationszeit
+ plant->regrow = time() + (regeneriert/2);
+ // Zeitpunkt voelliger Regeneration
+ plant->regeneration = regeneriert + time();
+
return clone_object(filename);
}
@@ -170,17 +184,17 @@
mixed ids = Query(P_IDS, F_VALUE);
mixed adj = Query(P_ADJECTIVES, F_VALUE);
- foreach(string key, mixed krautinfo : plantMap)
+ foreach(string key, struct plantinfo plant : plantMap)
{
- if ( sizeof(krautinfo) != 6 )
+ if ( !structp(plant) || !plant->pickable )
continue;
-
+
// IDs und Adjektive des Krautes kopieren
- Set(P_IDS, krautinfo[2], F_VALUE);
- Set(P_ADJECTIVES, krautinfo[3], F_VALUE);
+ Set(P_IDS, plant->ids, F_VALUE);
+ Set(P_ADJECTIVES, plant->adj, F_VALUE);
// Syntaxpruefung wird dann mit id() gemacht.
- if (id(str))
+ if (id(str))
{
object ob;
object bewacher;
@@ -188,14 +202,14 @@
// Liste der eingetragenen Bewacher-IDs durchlaufen und pruefen, ob
// mindestens einer davon anwesend ist.
- foreach( string npcId : krautinfo[5] )
+ foreach( string npcId : plant->guards )
{
bewacher = present(npcId, ME);
if (objectp(bewacher))
break;
}
-
- if ( !PL->QueryProp(P_FREE_HANDS) )
+
+ if ( !PL->QueryProp(P_FREE_HANDS) )
{
tell_object(PL, BS("Du hast keine Hand frei, um etwas pfluecken "
"zu koennen."));
@@ -208,7 +222,7 @@
"zunaechst um "+bewacher->QueryPronoun(WEN)+" kuemmern."));
}
// Wenn GetPlant() ein Objekt liefert, kann was gepflueckt werden.
- else if ( objectp(ob=GetPlant(key)) )
+ else if ( objectp(ob=GetPlant(key)) )
{
if ( ob->move(PL, M_GET) == MOVE_OK )
{
@@ -225,7 +239,7 @@
// Wenn alles nicht, dann ist das Kraut noch nicht wieder da.
else
{
- write(BS(krautinfo[4]+" ist noch nicht reif genug "
+ write(BS(plant->name+" ist noch nicht reif genug "
+"und muss erst noch etwas wachsen."));
break;
}