blob: c0c3a7f23521161c43d7342da3130118572d2f9a [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// (c) by Padreic (Padreic@mg.mud.de)
2
3#pragma no_inherit,no_clone,strong_types,rtt_checks
4
5#include <defines.h>
6#include <properties.h>
7#include <v_compiler.h>
8#include <items/kraeuter/kraeuter.h>
9#include <wizlevels.h>
10
11inherit "/std/virtual/v_compiler";
12inherit "/std/thing/language";
13inherit "/std/thing/description";
14
15// mit Hilfe dieses mappings kommt man sowohl an die ID und die Eigenschaften,
16// als auch an die Liste der Raeume in denen das Kraut mit dem filenamen room
17// gefunden werden kann.
18// ([ "key": ({ ({eigenschaften}), ([raeume]) }) ])
19private mapping krautdaten;
20
21// AN: enthaelt die Liste der gueltigen Kraeuter-Dateinamen ohne .c
22// am Ende. Ich vermute, dass es deswegen ein Mapping ist, damit in
23// Validate() einfach member() drauf gemacht werden kann und man nur 0/1
24// als Rueckgabewerte pruefen muss, statt -1 bei nem member() auf ein Array.
25private mapping validfiles;
26
27public void update(mapping data)
28{
29 if (previous_object() == find_object(PLANTMASTER))
30 {
31 krautdaten = data;
32 validfiles = mkmapping(m_indices(krautdaten));
33 }
34}
35
36// Wird benutzt, um kurze IDs von Kraeutern zu raten. Diese IDs werden
37// eingetragen, wenn der Krautname die ID als Teilstring enthaelt.
38#define IDLIST ({ "klee", "rebe", "hahnenfuss", "rettich", "kraut", "wurz",\
39 "moos", "enzian", "rautenwicke", "pilz", "nelke",\
40 "lichtnelke", "wicke", "zwiebel", "hanf", "kresse"})
41
42void create()
43{
44 seteuid(getuid());
45
46 v_compiler::create();
47 description::create();
48
49 SetProp(P_COMPILER_PATH, __DIR__);
50 SetProp(P_STD_OBJECT, PLANTITEM);
51
52 PLANTMASTER->UpdateVC();
53}
54
55string Validate(string file)
56{
57 if (!stringp(file)) return 0;
58 file = ::Validate(explode(file, "#")[0]);
59#if MUDNAME == "MorgenGrauen"
60 return (member(validfiles, file) ? file : 0);
61#else
62 return file;
63#endif
64}
65
66private nosave object simul_efun;
67
68// fuer SIMUL_EFUN_FILE
69#include <config.h>
70
71// AN: Funktion liefert das clonende Objekt als dessen Blueprint-Namen,
72// indem es den Caller-Stack durchlaeuft und nach einem Objekt sucht,
73// das weder der Master, noch ein Simul-Efun-Objekt, noch dieser VC selbst
74// ist. Der Name des gefundenen Objekts wird zurueckgegeben, oder 0.
75nomask private string get_cloner()
76{
77 int i;
78 object po;
79
80 if (!simul_efun)
81 {
82 if (!(simul_efun=find_object(SIMUL_EFUN_FILE)))
83 simul_efun=find_object(SPARE_SIMUL_EFUN_FILE);
84 }
85 // wenn sie jetzt nicht existiert - auch gut, dann gibt es halt keine
86 // sefuns.
87
88 for (i=0; po=previous_object(i); i++)
89 {
90 if (po==master() || po==simul_efun || po==ME || po==previous_object())
91 continue;
92 return BLUE_NAME(po);
93 }
94 return 0;
95}
96
97// Konfiguriert das erzeugte Objekt entsprechend der dafuer im Kraeutermaster
98// bekannten Daten. Vergibt auf die Plant-ID.
99varargs string CustomizeObject(string file)
100{
101 if (previous_object()->QueryPlantId()) return 0; // bereits initialisiert
102
103 if (stringp(file))
104 file=Validate(file);
105 else file=::CustomizeObject();
106 if (!file) return 0;
107
108 closure sp=symbol_function("SetProp", previous_object());
109 mixed arr=krautdaten[file];
110 if (pointerp(arr))
111 {
112 // Welches Objekt clont das File?
113 string cloner = get_cloner();
Zesstra0d1bd1d2019-11-23 10:19:15 +0100114 mapping rooms = arr[1];
MG Mud User88f12472016-06-24 23:31:02 +0200115 mixed props = arr[0];
116 // Wird das Kraut legal von einem eingetragenen Cloner erzeugt? Nur dann
117 // bekommt es eine gueltige Plant-ID.
118 int legal=member(rooms, get_cloner()) || cloner==PLANTMASTER;
119 if (!legal && this_interactive() && IS_ARCH(this_interactive()))
120 legal=1;
121
122 // Konfiguriert wird das Objekt dann, wenn es per VC erzeugt wird oder
123 // ein Clone einer per VC erzeugten BP ist - d.h. wenn es nicht aus
124 // einem real existierenden File auf der Platte existiert. Das ist dann
125 // der Fall, wenn der Loadname gleich dem Standardplantobjekt des VC
126 // ist.
127 if (load_name(previous_object())==PLANTITEM)
128 {
129 if ((props[INGREDIENT_NAME]=="Klee") ||
130 (props[INGREDIENT_NAME][<4..]=="klee")) {
131 funcall(sp, P_NAME, ({ props[INGREDIENT_NAME],
132 props[INGREDIENT_NAME]+"s",
133 props[INGREDIENT_NAME],
134 props[INGREDIENT_NAME]}));
135 }
136 else funcall(sp, P_NAME, props[INGREDIENT_NAME]);
137 funcall(sp, P_NAME_ADJ, props[INGREDIENT_ADJ]);
138 funcall(sp, P_GENDER, props[INGREDIENT_GENDER]);
139 funcall(sp, P_LONG, props[INGREDIENT_LONG]);
140 funcall(sp, PLANT_ROOMDETAIL, props[INGREDIENT_ROOMDETAIL]);
141 if (props[INGREDIENT_DEMON]==RAW) {
142 funcall(sp, P_ARTICLE, 0);
143 funcall(sp, P_SHORT, previous_object()->Name(WER));
144 funcall(sp, P_ARTICLE, 1);
145 }
146 else funcall(sp, P_SHORT,
147 previous_object()->Name(WER,props[INGREDIENT_DEMON]));
148 previous_object()->AddId(lowerstring(props[INGREDIENT_NAME]));
149 // bei zusammengesetzten Namen, auch den hauptnamen akzeptieren
150 string str=lowerstring(props[INGREDIENT_NAME]);
151 string *names=explode(str, "-");
152 if (sizeof(names)>1) previous_object()->AddId(names[<1]);
153 names=explode(str, " ");
154 if (sizeof(names)>1) previous_object()->AddId(names[<1]);
155 foreach(string id: IDLIST)
156 {
157 if (strstr(str, id)==-1) continue;
158 previous_object()->AddId(id);
159 break;
160 }
161 // Adjective vorher deklinieren
162 str=props[INGREDIENT_ADJ];
163 if (stringp(str))
164 {
Arathorn1c5b52c2020-07-27 23:49:54 +0200165 str = lowerstring(str);
166 string* adj = ({});
167 foreach(int casus : ({WER,WESSEN,WEM,WEN})) {
168 adj += ({ trim(previous_object()->DeclAdj(str, casus, 0)) });
169 }
170 previous_object()->AddAdjective(adj);
MG Mud User88f12472016-06-24 23:31:02 +0200171 }
172 } // Ende Konfiguration eines VC-erzeugten Objekts
173 // Plant-ID wird fuer alle Objekte auf irgendwas gesetzt.
174 previous_object()->SetPlantId(legal ? props[INGREDIENT_ID] : -1);
175 }
176 // Keine Krautdaten bekannt...
177 else
178 {
179 funcall(sp, P_NAME, "Kraut");
180 funcall(sp, P_GENDER, NEUTER);
181 funcall(sp, P_SHORT, "Ein Testkraut ("+capitalize(file)+")");
182 funcall(sp, P_LONG, "Ein nicht naeher spezifiziertes Testkraut.\n");
183 funcall(sp, PLANT_ROOMDETAIL,
184 "Ein nicht naeher spezifiziertes Testkraut ("
185 +capitalize(file)+").\n");
186 previous_object()->AddId("kraut");
187 previous_object()->SetPlantId(-1);
188 }
189 return file;
190}
191
192int NoParaObjects()
193{ return 1; }
194
195// AN: Funktion erzeugt aus den vorliegenden Daten der Kraeuterliste ein
196// physikalisch existierendes File in diesem Verzeichnis, zB wenn die Daten
197// erweitert werden sollen. Die Kraeuterliste stellt nur generische Objekte
198// zur Verfuegung, die keine Details haben. Wenn die Objekte ausgeschmueckt
199// werden sollen, koennen diese auch als Datei hier liegen.
200// Wird vom Plantmaster aus gerufen. Die Existenz von Klartext-
201// Fehlermeldungen laesst darauf schliessen, dass diese Funktion dafuer
202// vorgesehen war, vom Planttool aus gerufen zu werden. Dies wird dadurch
203// bestaetigt, dass dort wie hier alle von Magiern benutzbaren Kommando-
204// funktionen mit _ beginnen (_showplant(), _addroom() etc.), und die
205// Kommandofunktion im Planttool generell in der Lage ist, alle _*()
206// im Plantmaster zu rufen, sofern existent und fuer den Magier freigegeben.
207// AN/TODO: ggf. sollte man hier noch pruefen, ob die VC-Blueprint des
208// angeforderten Krautes gerade existiert, denn sonst wuerde das auf der
209// Platte liegende, scheinbar (nicht) geladene Objekt nicht mit dem
210// VC-Objekt uebereinstimmen. Evtl. reicht es aus, die Blueprint einfach
211// zu zerstoeren und neuzuladen.
212int _createfile(string filename)
213{
214 int i;
215 string str, short, long, gender, *name, roomdetail;
216 string *ids;
217 string plantfile;
218
219/* if (object_name(previous_object())!=PLANTMASTER) {
220 write("Illegal usage of _createfile()!\n");
221 return 1;
222 }*/
223// ^^^ Zook, ggf.spaeter wieder Kommentar entfernen.
224
225 mixed arr;
226 if (!pointerp(arr=krautdaten[filename])) {
227 write("Unknown plant '"+filename+"'.\n");
228 return 1;
229 }
230 if (file_size(PLANTDIR+filename+".c")>=0) {
231 write("error: file "+PLANTDIR+filename+".c already exists.\n");
232 return 1;
233 }
234 mixed props = arr[0];
235
236 // Kurzbeschreibung erzeugen
237 SetProp(P_NAME, props[INGREDIENT_NAME]);
238 SetProp(P_NAME_ADJ, props[INGREDIENT_ADJ]);
239 SetProp(P_GENDER, props[INGREDIENT_GENDER]);
240 if (props[INGREDIENT_DEMON]==RAW) {
241 SetProp(P_ARTICLE, 0);
242 short=Name(WER);
243 SetProp(P_ARTICLE, 1);
244 }
245 else short=Name(WER,props[INGREDIENT_DEMON]);
246 ids = ({ lowerstring(props[INGREDIENT_NAME]) });
247 // bei zusammengesetzten Namen, auch den hauptnamen akzeptieren
248 str=lowerstring(props[INGREDIENT_NAME]);
249 name=explode(str, "-");
250 if (sizeof(name)>1) ids += ({ name[<1] });
251 name=explode(str, " ");
252 if (sizeof(name)>1) ids += ({ name[<1] });
253 for (i=sizeof(IDLIST)-1; i>=0; i--) {
254 if (strstr(str, IDLIST[i], 0)==-1) continue;
255 ids += ({ IDLIST[i] });
256 break;
257 }
258 switch(props[INGREDIENT_GENDER]) {
259 case MALE: gender="MALE"; break;
260 case FEMALE: gender="FEMALE"; break;
261 case NEUTER: gender="NEUTER"; break;
262 default: gender=props[INGREDIENT_GENDER];
263 }
264 long=" \""+implode(old_explode(props[INGREDIENT_LONG], "\n"),
265 "\\n\"\n +\"")+"\\n\"";
266 roomdetail=" \""+implode(
267 old_explode(props[INGREDIENT_ROOMDETAIL], "\n"), "\\n\"\n +\"")+
268 "\\n\"";
269 plantfile=
270 "#pragma strong_types,rtt_checks\n\n"
271 "#include <properties.h>\n"
272 "#include <items/kraeuter/kraueter.h>\n"
273 "#include <items/kraeuter/kraeuterliste.h>\n\n"
274 "inherit STDPLANT;\n\n"
275 "protected void create()\n"
276 "{\n"
277 " ::create();\n";
278 plantfile+=" customizeMe("+upperstring(filename)+");\n";
279 plantfile+=
280 " SetProp(P_NAME, \""+props[INGREDIENT_NAME]+"\");\n"
281 " SetProp(P_NAME_ADJ, \""+(props[INGREDIENT_ADJ]||"")+"\");\n"
282 " SetProp(P_GENDER, "+gender+");\n"
283 " SetProp(P_LONG, \n"+
284 long+");\n"
285 " SetProp(PLANT_ROOMDETAIL, \n"+
286 roomdetail+");\n"
287 " SetProp(P_SHORT, \""+short+"\");\n";
288 plantfile+=" AddId(({";
289 for (i=sizeof(ids)-1; i>=0; i--)
290 plantfile+=" \""+ids[i]+"\",";
291 plantfile[<1]=' ';
292 plantfile+="}));\n";
293 // Adjective vorher deklinieren
294 if (stringp(short=props[INGREDIENT_ADJ])) {
295 short=DeclAdj(lowerstring(short), WEN, 0)[0..<2];
296 plantfile+=" AddAdjective(\""+short+"\");\n";
297 }
298 plantfile+="}\n";
299 write(plantfile);
300 //write_file(PLANTDIR+filename+".c", plantfile);
301 write("Filename: "+PLANTDIR+filename+".c\n");
302 return 1;
303}
304