blob: 92f4f56a40fafad4a4bed80b4c4ee449ae604e17 [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);
87 // Keine Bewacher
88 plant->guards = ({});
89 // Ausserdem ist es nicht pflueckbar per Standardkommando (pickable nicht
90 // gesetzt)
91 // Und eintragen
92 plantMap[filename] = plant;
93
94 // Details erzeugen aus Adjektiven und IDs
95 string *name_adj = ob->QueryProp(P_NAME_ADJ);
96
MG Mud User88f12472016-06-24 23:31:02 +020097 // aktuelles Geschlecht zwischenspeichern, wird spaeter wiederhergestellt
Zesstrae55d6812019-11-27 21:19:00 +010098 int gender = Query(P_GENDER, F_VALUE);
99 Set(P_GENDER, ob->Query(P_GENDER, F_VALUE), F_VALUE);
100
MG Mud User88f12472016-06-24 23:31:02 +0200101 // erzeugt fuer jede moegliche Kombination aus Adjektiv im Akkusativ
102 // und ID des Krautes ein Detail.
Zesstrae55d6812019-11-27 21:19:00 +0100103 name_adj = map(name_adj, #'DeclAdj, WEN, 0);
104
105 // Geschlecht zuruecksetzen
106 Set(P_GENDER, gender, F_VALUE);
107
108 string *det=({});
109 foreach(string _id : plant->ids) {
110 foreach(string _adj : name_adj) {
MG Mud User88f12472016-06-24 23:31:02 +0200111 det += ({ _adj + _id });
112 }
113 }
Zesstrae55d6812019-11-27 21:19:00 +0100114
115 det += plant->ids;
116 // keine existierenden Details ueberschreiben
117 det -= m_indices(Query(P_DETAILS, F_VALUE) || ([]));
118 if (sizeof(det))
119 AddDetail(det, ob->Query(PLANT_ROOMDETAIL, F_VALUE));
120
121 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200122}
123
124// Prueft, ob die Pflanze zu "filename" in diesem Raum schon nachgewachsen
125// ist.
126protected int CheckPlant(string filename)
127{
Zesstrae55d6812019-11-27 21:19:00 +0100128 struct plantinfo plant = plantMap[filename];
129 // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
130 if (!structp(plant))
131 return 0;
132
MG Mud User88f12472016-06-24 23:31:02 +0200133 // Solange die Zeit arr[0] noch nicht erreicht ist, ist das Kraut nicht
134 // nachgewachsen, dann gibt es gar nix.
Zesstrae55d6812019-11-27 21:19:00 +0100135 return (time() > plant->regrow);
MG Mud User88f12472016-06-24 23:31:02 +0200136}
137
138// Moechte man AddPlant() nicht benutzen, weil man die Pflanze nicht einfach
139// pfluecken, sondern vielleicht abschneiden, oder ausgraben soll, so kann
140// man sich mittels GetPlant(filename) das Objekt erzeugen lassen. Gibt
141// GetPlant() 0 zurueck, ist die Pflanze noch nicht wieder weit genug
142// nachgewachsen.
143object GetPlant(string filename)
144{
Zesstrae55d6812019-11-27 21:19:00 +0100145 struct plantinfo plant = plantMap[filename];
146 // Wenn es keinen Eintrag gibt, gibt es offenbar keine Pflanze
147 if (!structp(plant))
148 return 0;
149
150 // regrow enthaelt den Zeitpunkt, wann das Kraut nachgewachsen ist,
151 // regeneration denjenigen, wann es vollstaendig regeneriert ist.
MG Mud User88f12472016-06-24 23:31:02 +0200152
153 // Vor dem Nachgewachsen-Zeitpunkt kann man gar nix ernten.
Zesstrae55d6812019-11-27 21:19:00 +0100154 if (time() < plant->regrow)
155 return 0; // noch nicht nachgewachsen
MG Mud User88f12472016-06-24 23:31:02 +0200156
157 // Restzeit bis zur vollstaendigen Regeneration.
Zesstrae55d6812019-11-27 21:19:00 +0100158 int regeneriert = plant->regeneration - time();
159
MG Mud User88f12472016-06-24 23:31:02 +0200160 // Wenn vollstaendig regeneriert, ist STD_WACHSTUM die neue Zeit bis zur
Zesstrae55d6812019-11-27 21:19:00 +0100161 // Regeneration. Wenn noch nicht vollstaendig regeneriert, Restzeit
MG Mud User88f12472016-06-24 23:31:02 +0200162 // verdoppeln und STD_WACHSTUM nochmal drauf addieren.
Zesstrae55d6812019-11-27 21:19:00 +0100163 if (regeneriert<=0)
164 regeneriert = STD_WACHSTUM;
165 else
166 regeneriert = (regeneriert*2)+STD_WACHSTUM;
167
168 // Zeitpunkt des Nachwachsen ist die halbe Regenerationszeit
169 plant->regrow = time() + (regeneriert/2);
170 // Zeitpunkt voelliger Regeneration
171 plant->regeneration = regeneriert + time();
172
MG Mud User88f12472016-06-24 23:31:02 +0200173 return clone_object(filename);
174}
175
176static int _pfluecken(string str)
177{
178 int res;
179
180 if (!mappingp(plantMap)) return 0;
181 _notify_fail("WAS moechtest Du pfluecken?\n");
182
183 // IDs und Adjektive zwischenspeichern
184 mixed ids = Query(P_IDS, F_VALUE);
185 mixed adj = Query(P_ADJECTIVES, F_VALUE);
186
Zesstrae55d6812019-11-27 21:19:00 +0100187 foreach(string key, struct plantinfo plant : plantMap)
MG Mud User88f12472016-06-24 23:31:02 +0200188 {
Zesstrae55d6812019-11-27 21:19:00 +0100189 if ( !structp(plant) || !plant->pickable )
MG Mud User88f12472016-06-24 23:31:02 +0200190 continue;
Zesstrae55d6812019-11-27 21:19:00 +0100191
MG Mud User88f12472016-06-24 23:31:02 +0200192 // IDs und Adjektive des Krautes kopieren
Zesstrae55d6812019-11-27 21:19:00 +0100193 Set(P_IDS, plant->ids, F_VALUE);
194 Set(P_ADJECTIVES, plant->adj, F_VALUE);
MG Mud User88f12472016-06-24 23:31:02 +0200195
196 // Syntaxpruefung wird dann mit id() gemacht.
Zesstrae55d6812019-11-27 21:19:00 +0100197 if (id(str))
MG Mud User88f12472016-06-24 23:31:02 +0200198 {
199 object ob;
200 object bewacher;
201 res=1;
202
203 // Liste der eingetragenen Bewacher-IDs durchlaufen und pruefen, ob
204 // mindestens einer davon anwesend ist.
Zesstrae55d6812019-11-27 21:19:00 +0100205 foreach( string npcId : plant->guards )
MG Mud User88f12472016-06-24 23:31:02 +0200206 {
207 bewacher = present(npcId, ME);
208 if (objectp(bewacher))
209 break;
210 }
Zesstrae55d6812019-11-27 21:19:00 +0100211
212 if ( !PL->QueryProp(P_FREE_HANDS) )
MG Mud User88f12472016-06-24 23:31:02 +0200213 {
214 tell_object(PL, BS("Du hast keine Hand frei, um etwas pfluecken "
215 "zu koennen."));
216 }
217 // Ist der Bewacher anwesend? Dann kann man das Kraut nicht pfluecken.
218 else if ( objectp(bewacher) )
219 {
220 tell_object(PL, BS(bewacher->Name(WER, 2)+" laesst Dich "
221 "leider nicht nah genug heran. Irgendwie musst Du Dich wohl "
222 "zunaechst um "+bewacher->QueryPronoun(WEN)+" kuemmern."));
223 }
224 // Wenn GetPlant() ein Objekt liefert, kann was gepflueckt werden.
Zesstrae55d6812019-11-27 21:19:00 +0100225 else if ( objectp(ob=GetPlant(key)) )
MG Mud User88f12472016-06-24 23:31:02 +0200226 {
227 if ( ob->move(PL, M_GET) == MOVE_OK )
228 {
229 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+
230 " und nimmst "+ob->QueryPronoun(WEN)+" an Dich."));
231 }
232 else
233 {
234 write(BS("Vorsichtig pflueckst Du "+ob->name(WEN, 1)+", kannst "+
235 ob->QueryPronoun(WEN)+" aber nicht nehmen."));
236 ob->move(environment(PL), M_GET);
237 }
238 }
239 // Wenn alles nicht, dann ist das Kraut noch nicht wieder da.
240 else
241 {
Zesstrae55d6812019-11-27 21:19:00 +0100242 write(BS(plant->name+" ist noch nicht reif genug "
MG Mud User88f12472016-06-24 23:31:02 +0200243 +"und muss erst noch etwas wachsen."));
244 break;
245 }
246 }
247 }
248 // IDs und Adjektive zuruecksetzen.
249 Set(P_IDS, ids, F_VALUE);
250 Set(P_ADJECTIVES, adj, F_VALUE);
251
252 return res;
253}
254