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