blob: 24f519332af4f1f8139705535b03c1f265efb7d7 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001#define NEED_PROTOTYPES
2#include <thing/properties.h>
3#include <thing/language.h>
4#include <thing/description.h>
5#include <thing/commands.h>
6#undef NEED_PROTOTYPES
7#include <moving.h>
8#include <items/kraeuter/kraeuter.h>
9#include <defines.h>
10#include <living/combat.h> // Fuer P_FREE_HANDS
11
12// Standardwert von 2 h fuer vollstaendige Regeneration des Krautes.
13// Einfaches Nachwachsen ist typischerweise die Haelfte davon.
14#define STD_WACHSTUM 7200
15#define BS(x) break_string(x, 78)
16
17// Struktur (6 Eintraege pro Kraut):
18// ([ filename : ({ Zeit_bis_nachgewachsen, Zeit_bis_komplett_regeneriert,
19// Kraut-IDs, Kraut-Adjektive, Kraut->Name(WER,1),
20// ID_des_Bewacher-NPCs }) ])
21mapping plantMap = ([]);
22
23// kann benutzt werden um schnell und einfach eine Pflanze in einem Raum
24// hinzuzufuegen. Beispiel: AddPlant(BAERENKLAU);
25// Diese Funktion erzeugt automatisch ein AddCmd() fuer das Pfluecken und
26// (falls noch nicht vorhanden) Details fuer die Pflanze.
27// Rueckgabewerte:
28// 1 -> Erfolg; -1 -> filename ungueltig
29varargs int AddPlant(string filename, string|string* npcId)
30{
31 mixed arr;
32
33 // Dateiname nicht uebergeben? Dann tun wir erstmal gar nix.
34 if (!stringp(filename))
35 return -1;
36 object ob=load_object(filename);
37
38 // Wenn wir zu dem Kraut schon Daten haben (erkennbar an >2 Eintraegen),
39 // werfen wir einen Fehler, damit das beim Laden des Raumes schon
40 // erkannt wird.
41 if (pointerp(arr=plantMap[filename]) && sizeof(arr)>2)
42 raise_error("AddPlant(): "+filename+" already exists.\n");
43
44 // IDs und Adjektive parsen und den Datensatz zusammenstellen
45 string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
46 string *adj = ob->Query(P_ADJECTIVES, F_VALUE);
47
48 if (!pointerp(arr) || sizeof(arr)<2)
49 arr = ({0,0});
50 if ( !npcId )
51 npcId = ({});
52 else if (stringp(npcId))
53 npcId = ({npcId});
54 plantMap[filename]=({arr[0], arr[1], ids, adj, ob->Name(WER, 1), npcId });
55
56 // Details erzeugen aus Adjektiven und IDs
57 adj = ob->QueryProp(P_NAME_ADJ);
58
59 // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
60 int gender = Query(P_GENDER, F_VALUE);
61 Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
62
63 // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
64 // und ID des Krautes ein Detail.
65 adj = map(adj, #'DeclAdj, WEN, 0);
66
67 string *det=({});
68 foreach(string _id : ids) {
69 foreach(string _adj : adj) {
70 det += ({ _adj + _id });
71 }
72 }
73
74 det += ids;
75 // keine existierenden Details ueberschreiben
76 det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
77 if (sizeof(det))
78 AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
79
80 // Eine Befehlsfunktion brauchen wir natuerlich auch.
81 AddCmd(({"pflueck", "pfluecke", "ernte"}), "_pfluecken");
82
83 return 1;
84}
85
86// Wenn jemand per Hand das Plantdetail hinzufuegen moechte...
87// z.B. bei Verwendung von GetPlant() anstelle von AddPlant()
88void AddPlantDetail(string filename)
89{
90 // Pfad in Objektpointer wandeln
91 object ob=load_object(filename);
92
93 // Details erzeugen
94 string *det = ({});
95 string *ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
96 string *adj = ob->QueryProp(P_NAME_ADJ);
97 // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
98 int gender=Query(P_GENDER, F_VALUE);
99 Set(P_GENDER, ob->Query(P_GENDER, F_VALUE));
100 // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
101 // und ID des Krautes ein Detail.
102 adj = map(adj, #'DeclAdj, WEN, 0);
103 foreach(string _id : ids) {
104 foreach(string _adj : adj) {
105 det += ({ _adj + _id });
106 }
107 }
108 AddDetail(det+ids, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
109 // Geschlecht zuruecksetzen
110 Set(P_GENDER, gender, F_VALUE);
111}
112
113// Prueft, ob die Pflanze zu "filename" in diesem Raum schon nachgewachsen
114// ist.
115protected int CheckPlant(string filename)
116{
117 mixed arr=plantMap[filename];
118 if (!pointerp(arr) || sizeof(arr)<2) {
119 arr=plantMap[filename]=({ 0, 0 });
120 }
121 // Solange die Zeit arr[0] noch nicht erreicht ist, ist das Kraut nicht
122 // nachgewachsen, dann gibt es gar nix.
123 return (time()>arr[0]);
124}
125
126// Moechte man AddPlant() nicht benutzen, weil man die Pflanze nicht einfach
127// pfluecken, sondern vielleicht abschneiden, oder ausgraben soll, so kann
128// man sich mittels GetPlant(filename) das Objekt erzeugen lassen. Gibt
129// GetPlant() 0 zurueck, ist die Pflanze noch nicht wieder weit genug
130// nachgewachsen.
131object GetPlant(string filename)
132{
133 int *arr=plantMap[filename];
134 if (!pointerp(arr) || sizeof(arr)<2)
135 {
136 arr=plantMap[filename]=({ 0, 0 });
137 }
138 // arr[0] enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
139 int nachgewachsen = arr[0];
140 // arr[1] denjenigen, wann es vollstaendig regeneriert ist.
141 int regeneriert = arr[1];
142
143 // Vor dem Nachgewachsen-Zeitpunkt kann man gar nix ernten.
144 if (time()<nachgewachsen) return 0; // noch nicht nachgewachsen
145
146 // Restzeit bis zur vollstaendigen Regeneration.
147 regeneriert-=time();
148
149 // Wenn vollstaendig regeneriert, ist STD_WACHSTUM die neue Zeit bis zur
150 // Regeneration. Wenn noch nicht vollstaendig regenriert, Restzeit
151 // verdoppeln und STD_WACHSTUM nochmal drauf addieren.
152 regeneriert = (regeneriert<=0 ? STD_WACHSTUM
153 : (regeneriert*2)+STD_WACHSTUM);
154 // nachgewachsen ist die halbe Regenerationszeit
155 arr[0]=nachgewachsen=time()+(regeneriert/2);
156 // Zeit voelliger Regeneration
157 arr[1]=regeneriert+=time();
158
159 return clone_object(filename);
160}
161
162static int _pfluecken(string str)
163{
164 int res;
165
166 if (!mappingp(plantMap)) return 0;
167 _notify_fail("WAS moechtest Du pfluecken?\n");
168
169 // IDs und Adjektive zwischenspeichern
170 mixed ids = Query(P_IDS, F_VALUE);
171 mixed adj = Query(P_ADJECTIVES, F_VALUE);
172
173 foreach(string key, mixed krautinfo : plantMap)
174 {
175 if ( sizeof(krautinfo) != 6 )
176 continue;
177
178 // IDs und Adjektive des Krautes kopieren
179 Set(P_IDS, krautinfo[2], F_VALUE);
180 Set(P_ADJECTIVES, krautinfo[3], F_VALUE);
181
182 // Syntaxpruefung wird dann mit id() gemacht.
183 if (id(str))
184 {
185 object ob;
186 object bewacher;
187 res=1;
188
189 // Liste der eingetragenen Bewacher-IDs durchlaufen und pruefen, ob
190 // mindestens einer davon anwesend ist.
191 foreach( string npcId : krautinfo[5] )
192 {
193 bewacher = present(npcId, ME);
194 if (objectp(bewacher))
195 break;
196 }
197
198 if ( !PL->QueryProp(P_FREE_HANDS) )
199 {
200 tell_object(PL, BS("Du hast keine Hand frei, um etwas pfluecken "
201 "zu koennen."));
202 }
203 // Ist der Bewacher anwesend? Dann kann man das Kraut nicht pfluecken.
204 else if ( objectp(bewacher) )
205 {
206 tell_object(PL, BS(bewacher->Name(WER, 2)+" laesst Dich "
207 "leider nicht nah genug heran. Irgendwie musst Du Dich wohl "
208 "zunaechst um "+bewacher->QueryPronoun(WEN)+" kuemmern."));
209 }
210 // Wenn GetPlant() ein Objekt liefert, kann was gepflueckt werden.
211 else if ( objectp(ob=GetPlant(key)) )
212 {
213 if ( ob->move(PL, M_GET) == MOVE_OK )
214 {
215 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+
216 " und nimmst "+ob->QueryPronoun(WEN)+" an Dich."));
217 }
218 else
219 {
220 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+", kannst "+
221 ob->QueryPronoun(WEN)+" aber nicht nehmen."));
222 ob->move(environment(PL), M_GET);
223 }
224 }
225 // Wenn alles nicht, dann ist das Kraut noch nicht wieder da.
226 else
227 {
228 write(BS(krautinfo[4]+" ist noch nicht reif genug "
229 +"und muss erst noch etwas wachsen."));
230 break;
231 }
232 }
233 }
234 // IDs und Adjektive zuruecksetzen.
235 Set(P_IDS, ids, F_VALUE);
236 Set(P_ADJECTIVES, adj, F_VALUE);
237
238 return res;
239}
240