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 | |
| 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. |
| 25 | private mapping validfiles; |
| 26 | |
| 27 | public 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 | |
| 42 | void 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 | |
| 55 | string 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 | |
| 66 | private 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. |
| 75 | nomask 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. |
| 99 | varargs 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(); |
| 114 | string rooms = arr[1]; |
| 115 | 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 | { |
| 165 | str=DeclAdj(lowerstring(str), WEN, 0); |
| 166 | previous_object()->AddAdjective(str); |
| 167 | } |
| 168 | } // Ende Konfiguration eines VC-erzeugten Objekts |
| 169 | // Plant-ID wird fuer alle Objekte auf irgendwas gesetzt. |
| 170 | previous_object()->SetPlantId(legal ? props[INGREDIENT_ID] : -1); |
| 171 | } |
| 172 | // Keine Krautdaten bekannt... |
| 173 | else |
| 174 | { |
| 175 | funcall(sp, P_NAME, "Kraut"); |
| 176 | funcall(sp, P_GENDER, NEUTER); |
| 177 | funcall(sp, P_SHORT, "Ein Testkraut ("+capitalize(file)+")"); |
| 178 | funcall(sp, P_LONG, "Ein nicht naeher spezifiziertes Testkraut.\n"); |
| 179 | funcall(sp, PLANT_ROOMDETAIL, |
| 180 | "Ein nicht naeher spezifiziertes Testkraut (" |
| 181 | +capitalize(file)+").\n"); |
| 182 | previous_object()->AddId("kraut"); |
| 183 | previous_object()->SetPlantId(-1); |
| 184 | } |
| 185 | return file; |
| 186 | } |
| 187 | |
| 188 | int NoParaObjects() |
| 189 | { return 1; } |
| 190 | |
| 191 | // AN: Funktion erzeugt aus den vorliegenden Daten der Kraeuterliste ein |
| 192 | // physikalisch existierendes File in diesem Verzeichnis, zB wenn die Daten |
| 193 | // erweitert werden sollen. Die Kraeuterliste stellt nur generische Objekte |
| 194 | // zur Verfuegung, die keine Details haben. Wenn die Objekte ausgeschmueckt |
| 195 | // werden sollen, koennen diese auch als Datei hier liegen. |
| 196 | // Wird vom Plantmaster aus gerufen. Die Existenz von Klartext- |
| 197 | // Fehlermeldungen laesst darauf schliessen, dass diese Funktion dafuer |
| 198 | // vorgesehen war, vom Planttool aus gerufen zu werden. Dies wird dadurch |
| 199 | // bestaetigt, dass dort wie hier alle von Magiern benutzbaren Kommando- |
| 200 | // funktionen mit _ beginnen (_showplant(), _addroom() etc.), und die |
| 201 | // Kommandofunktion im Planttool generell in der Lage ist, alle _*() |
| 202 | // im Plantmaster zu rufen, sofern existent und fuer den Magier freigegeben. |
| 203 | // AN/TODO: ggf. sollte man hier noch pruefen, ob die VC-Blueprint des |
| 204 | // angeforderten Krautes gerade existiert, denn sonst wuerde das auf der |
| 205 | // Platte liegende, scheinbar (nicht) geladene Objekt nicht mit dem |
| 206 | // VC-Objekt uebereinstimmen. Evtl. reicht es aus, die Blueprint einfach |
| 207 | // zu zerstoeren und neuzuladen. |
| 208 | int _createfile(string filename) |
| 209 | { |
| 210 | int i; |
| 211 | string str, short, long, gender, *name, roomdetail; |
| 212 | string *ids; |
| 213 | string plantfile; |
| 214 | |
| 215 | /* if (object_name(previous_object())!=PLANTMASTER) { |
| 216 | write("Illegal usage of _createfile()!\n"); |
| 217 | return 1; |
| 218 | }*/ |
| 219 | // ^^^ Zook, ggf.spaeter wieder Kommentar entfernen. |
| 220 | |
| 221 | mixed arr; |
| 222 | if (!pointerp(arr=krautdaten[filename])) { |
| 223 | write("Unknown plant '"+filename+"'.\n"); |
| 224 | return 1; |
| 225 | } |
| 226 | if (file_size(PLANTDIR+filename+".c")>=0) { |
| 227 | write("error: file "+PLANTDIR+filename+".c already exists.\n"); |
| 228 | return 1; |
| 229 | } |
| 230 | mixed props = arr[0]; |
| 231 | |
| 232 | // Kurzbeschreibung erzeugen |
| 233 | SetProp(P_NAME, props[INGREDIENT_NAME]); |
| 234 | SetProp(P_NAME_ADJ, props[INGREDIENT_ADJ]); |
| 235 | SetProp(P_GENDER, props[INGREDIENT_GENDER]); |
| 236 | if (props[INGREDIENT_DEMON]==RAW) { |
| 237 | SetProp(P_ARTICLE, 0); |
| 238 | short=Name(WER); |
| 239 | SetProp(P_ARTICLE, 1); |
| 240 | } |
| 241 | else short=Name(WER,props[INGREDIENT_DEMON]); |
| 242 | ids = ({ lowerstring(props[INGREDIENT_NAME]) }); |
| 243 | // bei zusammengesetzten Namen, auch den hauptnamen akzeptieren |
| 244 | str=lowerstring(props[INGREDIENT_NAME]); |
| 245 | name=explode(str, "-"); |
| 246 | if (sizeof(name)>1) ids += ({ name[<1] }); |
| 247 | name=explode(str, " "); |
| 248 | if (sizeof(name)>1) ids += ({ name[<1] }); |
| 249 | for (i=sizeof(IDLIST)-1; i>=0; i--) { |
| 250 | if (strstr(str, IDLIST[i], 0)==-1) continue; |
| 251 | ids += ({ IDLIST[i] }); |
| 252 | break; |
| 253 | } |
| 254 | switch(props[INGREDIENT_GENDER]) { |
| 255 | case MALE: gender="MALE"; break; |
| 256 | case FEMALE: gender="FEMALE"; break; |
| 257 | case NEUTER: gender="NEUTER"; break; |
| 258 | default: gender=props[INGREDIENT_GENDER]; |
| 259 | } |
| 260 | long=" \""+implode(old_explode(props[INGREDIENT_LONG], "\n"), |
| 261 | "\\n\"\n +\"")+"\\n\""; |
| 262 | roomdetail=" \""+implode( |
| 263 | old_explode(props[INGREDIENT_ROOMDETAIL], "\n"), "\\n\"\n +\"")+ |
| 264 | "\\n\""; |
| 265 | plantfile= |
| 266 | "#pragma strong_types,rtt_checks\n\n" |
| 267 | "#include <properties.h>\n" |
| 268 | "#include <items/kraeuter/kraueter.h>\n" |
| 269 | "#include <items/kraeuter/kraeuterliste.h>\n\n" |
| 270 | "inherit STDPLANT;\n\n" |
| 271 | "protected void create()\n" |
| 272 | "{\n" |
| 273 | " ::create();\n"; |
| 274 | plantfile+=" customizeMe("+upperstring(filename)+");\n"; |
| 275 | plantfile+= |
| 276 | " SetProp(P_NAME, \""+props[INGREDIENT_NAME]+"\");\n" |
| 277 | " SetProp(P_NAME_ADJ, \""+(props[INGREDIENT_ADJ]||"")+"\");\n" |
| 278 | " SetProp(P_GENDER, "+gender+");\n" |
| 279 | " SetProp(P_LONG, \n"+ |
| 280 | long+");\n" |
| 281 | " SetProp(PLANT_ROOMDETAIL, \n"+ |
| 282 | roomdetail+");\n" |
| 283 | " SetProp(P_SHORT, \""+short+"\");\n"; |
| 284 | plantfile+=" AddId(({"; |
| 285 | for (i=sizeof(ids)-1; i>=0; i--) |
| 286 | plantfile+=" \""+ids[i]+"\","; |
| 287 | plantfile[<1]=' '; |
| 288 | plantfile+="}));\n"; |
| 289 | // Adjective vorher deklinieren |
| 290 | if (stringp(short=props[INGREDIENT_ADJ])) { |
| 291 | short=DeclAdj(lowerstring(short), WEN, 0)[0..<2]; |
| 292 | plantfile+=" AddAdjective(\""+short+"\");\n"; |
| 293 | } |
| 294 | plantfile+="}\n"; |
| 295 | write(plantfile); |
| 296 | //write_file(PLANTDIR+filename+".c", plantfile); |
| 297 | write("Filename: "+PLANTDIR+filename+".c\n"); |
| 298 | return 1; |
| 299 | } |
| 300 | |