blob: a0ab9569b3747dffa880cb9ae99e57f3b2761fcb [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
Zesstrae55d6812019-11-27 21:19:00 +010012public int AddPlantDetail(string filename);
13
MG Mud User88f12472016-06-24 23:31:02 +020014// Standardwert von 2 h fuer vollstaendige Regeneration des Krautes.
15// Einfaches Nachwachsen ist typischerweise die Haelfte davon.
16#define STD_WACHSTUM 7200
17#define BS(x) break_string(x, 78)
18
Zesstrae55d6812019-11-27 21:19:00 +010019// Struktur (7 Eintraege pro Kraut):
20struct plantinfo {
21 int regrow; // Zeit_bis_nachgewachsen
22 int regeneration; // Zeit_bis_komplett_regeneriert
23 int pickable; // per Standardkommanod pflueckbar?
24 string *ids; // Kraut-IDs
25 string *adj; // Kraut-Adjektive
26 string name; // Kraut->Name(WER,1)
27 string *guards; // ID_des_Bewacher-NPCs
28};
29// ([ filename : struct plantinfo ])
MG Mud User88f12472016-06-24 23:31:02 +020030mapping plantMap = ([]);
31
32// kann benutzt werden um schnell und einfach eine Pflanze in einem Raum
33// hinzuzufuegen. Beispiel: AddPlant(BAERENKLAU);
34// Diese Funktion erzeugt automatisch ein AddCmd() fuer das Pfluecken und
35// (falls noch nicht vorhanden) Details fuer die Pflanze.
36// Rueckgabewerte:
37// 1 -> Erfolg; -1 -> filename ungueltig
38varargs int AddPlant(string filename, string|string* npcId)
39{
Zesstrae55d6812019-11-27 21:19:00 +010040 // Eintrag und Details etc. hinzufuegen, wenn nicht erfolgreich, auch mit -1
41 // beenden.
42 if (AddPlantDetail(filename) == -1)
MG Mud User88f12472016-06-24 23:31:02 +020043 return -1;
MG Mud User88f12472016-06-24 23:31:02 +020044
Zesstrae55d6812019-11-27 21:19:00 +010045 struct plantinfo plant = plantMap[filename];
MG Mud User88f12472016-06-24 23:31:02 +020046
Zesstrae55d6812019-11-27 21:19:00 +010047 // es ist pflueckbar
48 plant->pickable = 1;
49
50 // Bewacher noch eintragen
51 if (npcId)
52 {
53 if (stringp(npcId))
54 plant->guards = ({npcId});
55 else
56 plant->guards = npcId;
MG Mud User88f12472016-06-24 23:31:02 +020057 }
Zesstrae55d6812019-11-27 21:19:00 +010058 // Eine Befehlsfunktion brauchen wir dann natuerlich auch.
MG Mud User88f12472016-06-24 23:31:02 +020059 AddCmd(({"pflueck", "pfluecke", "ernte"}), "_pfluecken");
Zesstrae55d6812019-11-27 21:19:00 +010060
61 // erfolgreich fertig
62 return 1;
MG Mud User88f12472016-06-24 23:31:02 +020063}
64
65// Wenn jemand per Hand das Plantdetail hinzufuegen moechte...
66// z.B. bei Verwendung von GetPlant() anstelle von AddPlant()
Zesstrae55d6812019-11-27 21:19:00 +010067// Im Gegensatz zu AddPlant() fuegt es kein Kommando zum Pfluecken hinzu und
68// traegt keine Bewacher ein.
69// 1 -> Erfolg; -1 -> filename ungueltig
70public int AddPlantDetail(string filename)
MG Mud User88f12472016-06-24 23:31:02 +020071{
Zesstrae55d6812019-11-27 21:19:00 +010072 // Dateiname nicht uebergeben? Dann tun wir erstmal gar nix.
73 if (!stringp(filename))
74 return -1;
MG Mud User88f12472016-06-24 23:31:02 +020075 object ob=load_object(filename);
Zesstrae55d6812019-11-27 21:19:00 +010076
77 // Wenn wir zu dem Kraut schon Daten haben, werfen wir einen Fehler, damit
78 // das beim Laden des Raumes schon erkannt wird.
79 struct plantinfo plant = plantMap[filename];
80 if (structp(plant))
81 raise_error("AddPlant(): "+filename+" already exists.\n");
82
83 plant = (<plantinfo>);
84 // IDs und Adjektive parsen und den Datensatz zusammenstellen
85 plant->ids = ob->Query(P_IDS, F_VALUE)-({ "Ding" });
86 plant->adj = ob->Query(P_ADJECTIVES, F_VALUE);
Zesstra4f20c712020-01-12 11:04:55 +010087 plant->name = ob->Name(WER,1);
Zesstrae55d6812019-11-27 21:19:00 +010088 // Keine Bewacher
89 plant->guards = ({});
90 // Ausserdem ist es nicht pflueckbar per Standardkommando (pickable nicht
91 // gesetzt)
92 // Und eintragen
93 plantMap[filename] = plant;
94
95 // Details erzeugen aus Adjektiven und IDs
96 string *name_adj = ob->QueryProp(P_NAME_ADJ);
97
MG Mud User88f12472016-06-24 23:31:02 +020098 // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
Zesstrae55d6812019-11-27 21:19:00 +010099 int gender = Query(P_GENDER, F_VALUE);
100 Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
101
MG Mud User88f12472016-06-24 23:31:02 +0200102 // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
103 // und ID des Krautes ein Detail.
Zesstrae55d6812019-11-27 21:19:00 +0100104 name_adj = map(name_adj, #'DeclAdj, WEN, 0);
105
106 // Geschlecht zuruecksetzen
107 Set(P_GENDER, gender, F_VALUE);
108
109 string *det=({});
110 foreach(string _id : plant->ids) {
111 foreach(string _adj : name_adj) {
MG Mud User88f12472016-06-24 23:31:02 +0200112 det += ({ _adj + _id });
113 }
114 }
Zesstrae55d6812019-11-27 21:19:00 +0100115
116 det += plant->ids;
117 // keine existierenden Details ueberschreiben
118 det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
119 if (sizeof(det))
120 AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
121
122 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200123}
124
125// Prueft, ob die Pflanze zu "filename" in diesem Raum schon nachgewachsen
126// ist.
127protected int CheckPlant(string filename)
128{
Zesstrae55d6812019-11-27 21:19:00 +0100129 struct plantinfo plant = plantMap[filename];
130 // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
131 if (!structp(plant))
132 return 0;
133
MG Mud User88f12472016-06-24 23:31:02 +0200134 // Solange die Zeit arr[0] noch nicht erreicht ist, ist das Kraut nicht
135 // nachgewachsen, dann gibt es gar nix.
Zesstrae55d6812019-11-27 21:19:00 +0100136 return (time() > plant->regrow);
MG Mud User88f12472016-06-24 23:31:02 +0200137}
138
139// Moechte man AddPlant() nicht benutzen, weil man die Pflanze nicht einfach
140// pfluecken, sondern vielleicht abschneiden, oder ausgraben soll, so kann
141// man sich mittels GetPlant(filename) das Objekt erzeugen lassen. Gibt
142// GetPlant() 0 zurueck, ist die Pflanze noch nicht wieder weit genug
143// nachgewachsen.
144object GetPlant(string filename)
145{
Zesstrae55d6812019-11-27 21:19:00 +0100146 struct plantinfo plant = plantMap[filename];
147 // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
148 if (!structp(plant))
149 return 0;
150
151 // regrow enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
152 // regeneration denjenigen, wann es vollstaendig regeneriert ist.
MG Mud User88f12472016-06-24 23:31:02 +0200153
154 // Vor dem Nachgewachsen-Zeitpunkt kann man gar nix ernten.
Zesstrae55d6812019-11-27 21:19:00 +0100155 if (time() < plant->regrow)
156 return 0; // noch nicht nachgewachsen
MG Mud User88f12472016-06-24 23:31:02 +0200157
158 // Restzeit bis zur vollstaendigen Regeneration.
Zesstrae55d6812019-11-27 21:19:00 +0100159 int regeneriert = plant->regeneration - time();
160
MG Mud User88f12472016-06-24 23:31:02 +0200161 // Wenn vollstaendig regeneriert, ist STD_WACHSTUM die neue Zeit bis zur
Zesstrae55d6812019-11-27 21:19:00 +0100162 // Regeneration. Wenn noch nicht vollstaendig regeneriert, Restzeit
MG Mud User88f12472016-06-24 23:31:02 +0200163 // verdoppeln und STD_WACHSTUM nochmal drauf addieren.
Zesstrae55d6812019-11-27 21:19:00 +0100164 if (regeneriert<=0)
165 regeneriert = STD_WACHSTUM;
166 else
167 regeneriert = (regeneriert*2)+STD_WACHSTUM;
168
169 // Zeitpunkt des Nachwachsen ist die halbe Regenerationszeit
170 plant->regrow = time() + (regeneriert/2);
171 // Zeitpunkt voelliger Regeneration
172 plant->regeneration = regeneriert + time();
173
MG Mud User88f12472016-06-24 23:31:02 +0200174 return clone_object(filename);
175}
176
177static int _pfluecken(string str)
178{
179 int res;
180
181 if (!mappingp(plantMap)) return 0;
182 _notify_fail("WAS moechtest Du pfluecken?\n");
183
184 // IDs und Adjektive zwischenspeichern
185 mixed ids = Query(P_IDS, F_VALUE);
186 mixed adj = Query(P_ADJECTIVES, F_VALUE);
187
Zesstrae55d6812019-11-27 21:19:00 +0100188 foreach(string key, struct plantinfo plant : plantMap)
MG Mud User88f12472016-06-24 23:31:02 +0200189 {
Zesstrae55d6812019-11-27 21:19:00 +0100190 if ( !structp(plant) || !plant->pickable )
MG Mud User88f12472016-06-24 23:31:02 +0200191 continue;
Zesstrae55d6812019-11-27 21:19:00 +0100192
MG Mud User88f12472016-06-24 23:31:02 +0200193 // IDs und Adjektive des Krautes kopieren
Zesstrae55d6812019-11-27 21:19:00 +0100194 Set(P_IDS, plant->ids, F_VALUE);
195 Set(P_ADJECTIVES, plant->adj, F_VALUE);
MG Mud User88f12472016-06-24 23:31:02 +0200196
197 // Syntaxpruefung wird dann mit id() gemacht.
Zesstrae55d6812019-11-27 21:19:00 +0100198 if (id(str))
MG Mud User88f12472016-06-24 23:31:02 +0200199 {
200 object ob;
201 object bewacher;
202 res=1;
203
204 // Liste der eingetragenen Bewacher-IDs durchlaufen und pruefen, ob
205 // mindestens einer davon anwesend ist.
Zesstrae55d6812019-11-27 21:19:00 +0100206 foreach( string npcId : plant->guards )
MG Mud User88f12472016-06-24 23:31:02 +0200207 {
208 bewacher = present(npcId, ME);
209 if (objectp(bewacher))
210 break;
211 }
Zesstrae55d6812019-11-27 21:19:00 +0100212
213 if ( !PL->QueryProp(P_FREE_HANDS) )
MG Mud User88f12472016-06-24 23:31:02 +0200214 {
215 tell_object(PL, BS("Du hast keine Hand frei, um etwas pfluecken "
216 "zu koennen."));
217 }
218 // Ist der Bewacher anwesend? Dann kann man das Kraut nicht pfluecken.
219 else if ( objectp(bewacher) )
220 {
221 tell_object(PL, BS(bewacher->Name(WER, 2)+" laesst Dich "
222 "leider nicht nah genug heran. Irgendwie musst Du Dich wohl "
223 "zunaechst um "+bewacher->QueryPronoun(WEN)+" kuemmern."));
224 }
225 // Wenn GetPlant() ein Objekt liefert, kann was gepflueckt werden.
Zesstrae55d6812019-11-27 21:19:00 +0100226 else if ( objectp(ob=GetPlant(key)) )
MG Mud User88f12472016-06-24 23:31:02 +0200227 {
228 if ( ob->move(PL, M_GET) == MOVE_OK )
229 {
230 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+
231 " und nimmst "+ob->QueryPronoun(WEN)+" an Dich."));
232 }
233 else
234 {
235 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+", kannst "+
236 ob->QueryPronoun(WEN)+" aber nicht nehmen."));
237 ob->move(environment(PL), M_GET);
238 }
239 }
240 // Wenn alles nicht, dann ist das Kraut noch nicht wieder da.
241 else
242 {
Zesstrae55d6812019-11-27 21:19:00 +0100243 write(BS(plant->name+" ist noch nicht reif genug "
MG Mud User88f12472016-06-24 23:31:02 +0200244 +"und muss erst noch etwas wachsen."));
245 break;
246 }
247 }
248 }
249 // IDs und Adjektive zuruecksetzen.
250 Set(P_IDS, ids, F_VALUE);
251 Set(P_ADJECTIVES, adj, F_VALUE);
252
253 return res;
254}
255