MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | // MorgenGrauen MUDlib |
| 2 | // |
| 3 | // player/viewcmd.c -- player view command handling |
| 4 | // |
| 5 | // $Id: viewcmd.c 9548 2016-04-17 19:28:22Z Zesstra $ |
| 6 | |
| 7 | #pragma strong_types |
| 8 | #pragma save_types |
| 9 | #pragma range_check |
| 10 | #pragma no_clone |
| 11 | #pragma pedantic |
| 12 | |
| 13 | #define NEED_PROTOTYPES |
| 14 | #include "/sys/thing/properties.h" |
| 15 | #include "/sys/living/put_and_get.h" |
| 16 | #include "/sys/living/description.h" |
| 17 | |
| 18 | #include <container.h> |
| 19 | #include <player.h> |
| 20 | #include <properties.h> |
| 21 | #include <rooms.h> |
| 22 | #include <wizlevels.h> |
| 23 | #include <defines.h> |
| 24 | #include <moving.h> |
| 25 | #include <new_skills.h> |
| 26 | #include <ansi.h> |
| 27 | |
| 28 | #include <sys_debug.h> |
| 29 | |
| 30 | varargs mixed More(string str, int fflag, string returnto); |
| 31 | |
| 32 | void create() |
| 33 | { |
| 34 | Set(P_BRIEF, SAVE, F_MODE); |
| 35 | Set(P_BLIND, SAVE, F_MODE); |
| 36 | } |
| 37 | |
| 38 | int _toggle_brief() |
| 39 | { |
| 40 | int brief; |
| 41 | |
| 42 | if (query_verb()=="kurz") |
| 43 | brief=1; |
| 44 | else if (query_verb()=="ultrakurz") |
| 45 | brief=2; |
| 46 | else brief=0; |
| 47 | SetProp(P_BRIEF, brief); |
| 48 | write("Du bist nun im \""+ |
| 49 | (brief?(brief==1?"Kurz":"Ultrakurz"):"Lang")+"\"modus.\n"); |
| 50 | return 1; |
| 51 | } |
| 52 | |
| 53 | private int sortinv(mixed a, mixed b) { return a[0] > b[0]; } |
| 54 | |
| 55 | private string collectinv(mixed obj) |
| 56 | { |
| 57 | if(obj[0]=="") return 0; |
| 58 | return (obj[2] ? " " : "") |
| 59 | + obj[0] |
| 60 | + (obj[1] > 1 ? " ("+obj[1]+")" : ""); |
| 61 | } |
| 62 | |
| 63 | #define I_AUTOLOAD 1 |
| 64 | #define I_KEEP 4 |
| 65 | #define I_FORMATTED 16 |
| 66 | #define I_ARMOUR 64 |
| 67 | #define I_SORT 256 |
| 68 | #define I_WEAPON 1024 |
| 69 | #define I_FORCE_SORT 4096 |
| 70 | #define I_NO_TABLE 16384 |
| 71 | |
| 72 | private string getflags(string arg, int flags) |
| 73 | { |
| 74 | int no, i; |
| 75 | if(sizeof(arg) < 2) return 0; |
| 76 | no = (arg[0] == '-'); |
| 77 | |
| 78 | for(i = 1; i < sizeof(arg); i++) |
| 79 | { |
| 80 | switch(arg[i]) |
| 81 | { |
| 82 | case 'a': flags |= I_AUTOLOAD << no; break; |
| 83 | case 'b': flags |= I_KEEP << no; break; |
| 84 | case 'f': flags |= I_FORMATTED << no; break; |
| 85 | case 'r': flags |= I_ARMOUR << no; break; |
| 86 | case 's': flags |= I_SORT << no; break; |
| 87 | case 'w': flags |= I_WEAPON << no; break; |
| 88 | case 'v': flags |= (I_ARMOUR | I_WEAPON) << !no; break; |
| 89 | case '1': flags |= I_NO_TABLE; break; |
| 90 | // Die Option macht nur Aerger und kommentiert ist sie eh nicht. |
| 91 | // Wer das dringend braucht, soll Wargons Schiebepuzzle benutzen. |
| 92 | // |
| 93 | // Tiamak, 15.10.2000 |
| 94 | // case 'S': flags |= I_FORCE_SORT << no; break; |
| 95 | default : return arg[i..i]; // wird ausgegeben an Spieler als unbekannt. |
| 96 | } |
| 97 | } |
| 98 | return 0; |
| 99 | } |
| 100 | |
| 101 | static int _check_keep(object ob) |
| 102 | { |
| 103 | return (ob->QueryProp(P_KEEP_ON_SELL))==geteuid(ME); |
| 104 | } |
| 105 | |
| 106 | int _inventory(string str) |
| 107 | { |
| 108 | mixed *args, output; |
| 109 | int ansi, i, flags, minv; |
| 110 | mixed inventory, weapons, armours, misc; |
| 111 | string format; |
| 112 | |
| 113 | if(CannotSee()) return 1; |
| 114 | |
| 115 | if((str = _unparsed_args()) && str!="") |
| 116 | { |
| 117 | string error; |
| 118 | error = "Benutzung: i[nventar] [-/+1abfrsvw]\n"; |
| 119 | args = regexp(regexplode(str, "[-+][1abfrswv][1abfrswv]*"), |
| 120 | "[-+][1abfrswv][1abfrswv]*"); |
| 121 | if(!sizeof(args)) return (_notify_fail(error), 0); |
| 122 | if(sizeof(args = map(args, #'getflags/*'*/, &flags) - ({ 0 }))) |
| 123 | { |
| 124 | printf("%s: Unbekanntes Argument.\n"+error, implode(args, ", ")); |
| 125 | return 1; |
| 126 | } |
| 127 | } |
| 128 | // Fuer Spieler gehen nur sichtbare Objekte in den Algorithmus |
| 129 | if (IS_LEARNING(ME)) |
| 130 | inventory = all_inventory(ME); |
| 131 | else |
| 132 | inventory = filter_objects(all_inventory(ME), "short"); |
| 133 | |
| 134 | ansi = member(({"vt100", "ansi"}), QueryProp(P_TTY)) != -1; |
| 135 | minv = 1 | (flags & (I_FORMATTED | (I_FORMATTED << 1)) ? 2 : 0); |
| 136 | format = (flags & I_NO_TABLE) ? "=" : "#"; |
| 137 | |
| 138 | // if(flags & (I_FORCE_SORT | I_FORCE_SORT << 1)) |
| 139 | // { |
| 140 | // closure sf; |
| 141 | // sf = flags & I_FORCE_SORT ? #'> : #'<; |
| 142 | // s = sort_array(s, lambda(({'a, 'b}), |
| 143 | // ({#'funcall, sf, |
| 144 | // ({#'||,({#'call_other,'a,"short"}),""}), |
| 145 | // ({#'||,({#'call_other,'b,"short"}),""})}))); |
| 146 | // map_objects(s, "move", this_object()); |
| 147 | // s = all_inventory(ME); |
| 148 | // } |
| 149 | |
| 150 | if (flags & I_AUTOLOAD) |
| 151 | inventory = filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ); |
| 152 | else if (flags & (I_AUTOLOAD << 1)) |
| 153 | inventory -= filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ); |
| 154 | |
| 155 | if(flags & I_KEEP) |
| 156 | inventory = filter(inventory,#'_check_keep); |
| 157 | else if(flags & (I_KEEP << 1)) |
| 158 | inventory -= filter(inventory,#'_check_keep); |
| 159 | |
| 160 | armours = filter_objects(inventory, "QueryProp", P_ARMOUR_TYPE); |
| 161 | // Kleidung dazu addieren, vorher die erkannten Ruestungen abziehen, die |
| 162 | // muessen nicht nochmal durchiteriert werden. |
| 163 | armours += filter_objects(inventory-armours, "IsClothing"); |
| 164 | // Ruestungen werden hier nicht abgezogen, weil es Kram gibt, welche sowohl |
| 165 | // Ruestung als auch Waffe ist. |
| 166 | weapons = filter_objects(inventory, "QueryProp", P_WEAPON_TYPE); |
| 167 | misc = inventory - weapons - armours; // rest ;-) |
| 168 | |
| 169 | if(flags & I_WEAPON) |
| 170 | { |
| 171 | inventory = weapons; misc = ({}); |
| 172 | if(!(flags & (I_ARMOUR))) armours = ({}); |
| 173 | } |
| 174 | if(flags & I_ARMOUR) |
| 175 | { |
| 176 | inventory = armours; misc = ({}); |
| 177 | if(!(flags & I_WEAPON)) weapons = ({}); |
| 178 | } |
| 179 | if(flags & (I_WEAPON << 1)) { weapons = ({}); inventory = armours + misc; } |
| 180 | if(flags & (I_ARMOUR << 1)) { armours = ({}); inventory = weapons + misc; } |
| 181 | |
| 182 | output = ""; |
| 183 | if(flags & (I_FORMATTED | (I_FORMATTED << 1))) |
| 184 | { |
| 185 | inventory = make_invlist(this_player(), inventory, minv); |
| 186 | if(flags & (I_SORT | (I_SORT << 1))) |
| 187 | inventory = sort_array(inventory, #'sortinv/*'*/); |
| 188 | output += sprintf("%"+format+"-78s\n", |
| 189 | implode(map(inventory,#'collectinv/*'*/),"\n")); |
| 190 | } |
| 191 | else |
| 192 | { |
| 193 | if(weapons && sizeof(weapons)) |
| 194 | { |
| 195 | weapons = make_invlist(this_player(), weapons, minv); |
| 196 | if(flags & (I_SORT | (I_SORT << 1))) |
| 197 | weapons = sort_array(weapons, #'sortinv/*'*/); |
| 198 | output += (ansi?ANSI_BOLD:"") + "Waffen:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 199 | + sprintf("%"+format+"-78s\n", |
| 200 | implode(map(weapons, #'collectinv/*'*/), "\n")); |
| 201 | } |
| 202 | if(armours && sizeof(armours)) |
| 203 | { |
| 204 | armours = make_invlist(this_player(), armours, minv); |
| 205 | if(flags & (I_SORT | (I_SORT << 1))) |
| 206 | armours = sort_array(armours, #'sortinv/*'*/); |
| 207 | output += (ansi?ANSI_BOLD:"") |
| 208 | + "Kleidung & Ruestungen:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 209 | + sprintf("%"+format+"-78s\n", |
| 210 | implode(map(armours, #'collectinv/*'*/), "\n")); |
| 211 | } |
| 212 | if(misc && sizeof(misc)) |
| 213 | { |
| 214 | misc = make_invlist(this_player(), misc, minv); |
| 215 | if(flags & (I_SORT | (I_SORT << 1))) |
| 216 | misc = sort_array(misc, #'sortinv/*'*/); |
| 217 | output += (ansi?ANSI_BOLD:"") + "Verschiedenes:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 218 | + sprintf("%"+format+"-78s\n", |
| 219 | implode(map(misc, #'collectinv/*'*/), "\n")); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | // Spielerwunsch: 'inventar' sollte doch das Bezugsobjekt auf den Spieler |
| 224 | // aendern. |
| 225 | SetProp(P_REFERENCE_OBJECT, this_object()); |
| 226 | |
| 227 | if (output=="") |
| 228 | output += (ansi?ANSI_BOLD:"")+"Die Liste ist leer."+(ansi?ANSI_NORMAL:""); |
| 229 | More(output); |
| 230 | return 1; |
| 231 | } |
| 232 | |
| 233 | private nosave int exa_cnt; |
| 234 | private nosave int exa_time; |
| 235 | private nosave string *exa; |
| 236 | |
| 237 | varargs int _examine(string str, int mode) |
| 238 | { |
| 239 | object base, *objs, env; |
| 240 | string what, detail, parent, out, error; |
| 241 | int i, size, done; |
| 242 | |
| 243 | if(CannotSee()) return 1; |
| 244 | |
| 245 | _notify_fail("Was willst Du denn untersuchen?\n"); |
| 246 | if (!str) return 0; |
| 247 | |
| 248 | if (member(({"boden","decke","wand","waende"}),old_explode(str," ")[0]) == -1) { |
| 249 | exa_cnt -= (time() - exa_time)/2; |
| 250 | exa_time = time(); |
| 251 | exa_cnt++; |
| 252 | if (!exa) |
| 253 | exa = ({ str }); |
| 254 | else |
| 255 | exa += ({ str }); |
| 256 | if (exa_cnt > 10) { |
| 257 | log_file("ARCH/LOOK", |
| 258 | sprintf("%s: %s in %s\n%@O\n",dtime(time()),getuid(this_object()), |
| 259 | environment() ? object_name(environment()) : "???",exa), 150000); |
| 260 | exa_cnt = 0; |
| 261 | exa = ({}); |
| 262 | } |
| 263 | else if (exa_cnt < 0) { |
| 264 | exa_cnt = 0; |
| 265 | exa = ({}); |
| 266 | } |
| 267 | } |
| 268 | // do we look at an object in our environment ? |
| 269 | if (sscanf(str,"%s in raum", what) || sscanf(str,"%s im raum", what)) |
| 270 | base = environment(); |
| 271 | // is the object inside of me (inventory) |
| 272 | else if (sscanf(str,"%s in mir", what) || sscanf(str,"%s in dir", what)) |
| 273 | base = this_object(); |
| 274 | else { |
| 275 | what = str; |
| 276 | // get the last object we looked at |
| 277 | base = QueryProp(P_REFERENCE_OBJECT); |
| 278 | |
| 279 | // if a reference object exists, test for its existance in the room |
| 280 | // or in our inventory |
| 281 | if (objectp(base)) |
| 282 | { |
| 283 | if (base == environment() || base==this_object()) |
| 284 | { |
| 285 | // Umgebung oder Spieler selber sind als Bezugsobjekt immer in |
| 286 | // Ordnung, nichts machen. |
| 287 | } |
| 288 | // Das Referenzobjekt darf nicht unsichtbar sein. |
| 289 | else if (!base->short()) |
| 290 | base = 0; |
| 291 | else if(member(deep_inventory(environment()), base) != -1) |
| 292 | { |
| 293 | foreach(env : all_environment(base)) { |
| 294 | // Ist eine Umgebung Living oder intransparenter Container oder |
| 295 | // unsichtbar? |
| 296 | if (living(env) || !env->QueryProp(P_TRANSPARENT) |
| 297 | || !env->short()) |
| 298 | { |
| 299 | // in dem Fall ist ende, aber wenn das gefundene Env nicht |
| 300 | // dieses Living selber oder sein Env ist, wird das |
| 301 | // Referenzobjekt zusaetzlich genullt. |
| 302 | if (env != this_object() && env != environment()) |
| 303 | base = 0; |
| 304 | break; |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | else |
| 309 | base = 0; // nicht im Raum oder Inventory |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | // scan input if we want a specific object to look at |
| 314 | if(sscanf(what, "%s an %s", detail, parent) == 2 || |
| 315 | sscanf(what, "%s am %s", detail, parent) == 2 || |
| 316 | sscanf(what, "%s in %s", detail, parent) == 2 || |
| 317 | sscanf(what, "%s im %s", detail, parent) == 2) |
| 318 | { |
| 319 | // if an ref object exists get its inventory. (Oben wurde sichergestellt, |
| 320 | // dass das Referenzobjekt einsehbar ist) |
| 321 | if(base) |
| 322 | objs = base->locate_objects(parent, 1) || ({}); |
| 323 | else { |
| 324 | // else get our inv and env |
| 325 | objs = environment()->locate_objects(parent, 1) |
| 326 | + locate_objects(parent, 1); |
| 327 | } |
| 328 | objs = filter_objects(objs, "short"); // nur sichtbare... |
| 329 | if(sizeof(objs) > 1) |
| 330 | return (notify_fail("Es gibt mehr als eine(n) "+capitalize(parent)+".\n"), 0); |
| 331 | else |
| 332 | { |
| 333 | if (sizeof(objs)) |
| 334 | base = objs[0]; |
| 335 | else |
| 336 | return (notify_fail("Hier ist kein(e) "+capitalize(parent)+".\n"), 0); |
| 337 | } |
| 338 | objs = 0; |
| 339 | } |
| 340 | else detail = what; |
| 341 | |
| 342 | int base_was_env = 1; |
| 343 | do { |
| 344 | // if a base exists get its inventory, else get our inv and env |
| 345 | if (base) |
| 346 | { |
| 347 | if (base == this_object() || base == environment() || |
| 348 | (base->QueryProp(P_TRANSPARENT) && !living(base))) |
| 349 | { |
| 350 | // ich kann in base reingucken... |
| 351 | objs = base->locate_objects(detail, 1) || ({}); |
| 352 | } |
| 353 | else |
| 354 | { |
| 355 | // Referenzobjekt da, aber nicht reinguckbar. base aber nicht nullen, |
| 356 | // denn es ist ja noch gueltig fuer Detailsuchen an base... |
| 357 | objs = ({}); |
| 358 | } |
| 359 | } |
| 360 | else |
| 361 | { |
| 362 | objs = environment()->locate_objects(detail, 1) |
| 363 | + locate_objects(detail, 1); |
| 364 | base = environment(); |
| 365 | } |
| 366 | objs = filter_objects(objs, "short"); // nur sichtbare... |
| 367 | |
| 368 | if(!sizeof(objs)) |
| 369 | { |
| 370 | // wenn keine Objekte gefunden wurden, wird nach Details gesucht... |
| 371 | if((out = base->GetDetail(detail, QueryProp(P_REAL_RACE),SENSE_VIEW)) || |
| 372 | (out = base->GetDoorDesc(detail))) |
| 373 | { |
| 374 | SetProp(P_REFERENCE_OBJECT, base); |
| 375 | return (write(out), 1); |
| 376 | } |
| 377 | else |
| 378 | { |
| 379 | // wenn auch keine Details gefunden, dann schauen, ob Ende ist |
| 380 | // (base==env) oder wir evtl. noch im env suchen koennen. |
| 381 | if (base == environment()) |
| 382 | { |
| 383 | if (base_was_env) { |
| 384 | // in diesem Fall war das Env das Bezugsobjekt - daher wegwerfen. |
| 385 | SetProp(P_REFERENCE_OBJECT, 0); |
| 386 | _notify_fail("Sowas siehst Du da nicht!\n"); |
| 387 | } |
| 388 | else { |
| 389 | _notify_fail("Sowas siehst Du auch da nicht!\n"); |
| 390 | // in diesem Fall war nicht das Env das Bezugsobjekt - es soll |
| 391 | // behalten und nicht geloescht werden. |
| 392 | } |
| 393 | return 0; |
| 394 | } |
| 395 | else { |
| 396 | base_was_env=0; |
| 397 | write(break_string("Du findest an "+base->name(WEM) |
| 398 | +" kein \"" + capitalize(detail) + "\"." |
| 399 | " Dein Blick wendet sich der Umgebung zu.",78)); |
| 400 | base = 0; |
| 401 | } |
| 402 | } |
| 403 | } |
| 404 | else // Objekte gefunden! |
| 405 | done = 1; |
| 406 | } while(!done); |
| 407 | |
| 408 | // Es muss min. ein (sichtbares) Objekt geben, sonst waere man hier nicht |
| 409 | // hingekommen. |
| 410 | object ob = objs[0]; |
| 411 | SetProp(P_REFERENCE_OBJECT, ob); |
| 412 | tell_object(ME, ob->long(mode)); |
| 413 | return 1; |
| 414 | } |
| 415 | |
| 416 | varargs int _sense_exa(string str) |
| 417 | { |
| 418 | object base, *objs, env; |
| 419 | string what, detail, parent, out, error; |
| 420 | int sense; |
| 421 | |
| 422 | if(member(({"riech","rieche","schnupper","schnuppere"}),query_verb())!=-1) |
| 423 | { |
| 424 | _notify_fail("Du kannst nichts Besonderes riechen.\n"); |
| 425 | sense = SENSE_SMELL; |
| 426 | } |
| 427 | else if(member(({"lausche","lausch","hoer","hoere"}),query_verb())!=-1) |
| 428 | { |
| 429 | if(QueryProp(P_DEAF)) |
| 430 | return notify_fail("Du bist taub!\n"), 0; |
| 431 | |
| 432 | _notify_fail("Du kannst nichts Besonderes hoeren.\n"); |
| 433 | sense = SENSE_SOUND; |
| 434 | } |
| 435 | else if(member(({"taste","beruehre","beruehr"}),query_verb())!=-1) |
| 436 | { |
| 437 | sense = SENSE_TOUCH; |
| 438 | // ein "ab" ganz am Ende von str wird abgeschnitten, es soll sowohl "taste |
| 439 | // x ab" als auch "taste x" funktionieren. |
| 440 | if (str) { |
| 441 | _notify_fail("Sowas kannst Du hier nicht ertasten!\n"); |
| 442 | string *tmp = explode(str," "); |
| 443 | if (sizeof(tmp) > 1 && tmp[<1] == "ab") |
| 444 | str = implode(tmp[0..<2], " "); |
| 445 | } |
| 446 | else |
| 447 | _notify_fail("Was willst Du denn abtasten?\n"); |
| 448 | } |
| 449 | else if (member(({"lies","lese","les"}), query_verb()) > -1) |
| 450 | { |
| 451 | _notify_fail("Was willst Du lesen?\n"); |
| 452 | if ( !str ) // Kein SENSE_DEFAULT zulassen. |
| 453 | return 0; |
| 454 | if (this_object()->CannotSee()) { |
| 455 | notify_fail("Du kannst nichts sehen!\n"); |
| 456 | return 0; |
| 457 | } |
| 458 | sense = SENSE_READ; |
| 459 | } |
| 460 | |
| 461 | if (!str) { |
| 462 | if(!detail = |
| 463 | environment()->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),sense)) |
| 464 | return 0; |
| 465 | write(detail); |
| 466 | return 1; |
| 467 | } |
| 468 | else if(sscanf(str,"an %s",what)==1) |
| 469 | str=what; |
| 470 | |
| 471 | // do we look at an object in our environment ? |
| 472 | if (sscanf(str,"%s in raum", what) || sscanf(str,"%s im raum", what)) |
| 473 | base = environment(); |
| 474 | // is the object inside of me (inventory) |
| 475 | else if (sscanf(str,"%s in mir", what) || sscanf(str,"%s in dir", what)) |
| 476 | base = this_object(); |
| 477 | else { |
| 478 | what = str; |
| 479 | // get the last object we looked at |
| 480 | base = QueryProp(P_REFERENCE_OBJECT); |
| 481 | |
| 482 | // if a reference object exists, test for its existance in the room |
| 483 | // or in our inventory |
| 484 | if (objectp(base)) |
| 485 | { |
| 486 | if (base == environment() || base==this_object()) |
| 487 | { |
| 488 | // Umgebung oder Spieler selber sind als Bezugsobjekt immer in |
| 489 | // Ordnung, nichts machen. |
| 490 | } |
| 491 | // Das Referenzobjekt darf nicht unsichtbar sein. |
| 492 | else if (!base->short()) |
| 493 | base = 0; |
| 494 | else if(member(deep_inventory(environment()), base) != -1) |
| 495 | { |
| 496 | foreach(env : all_environment(base)) { |
| 497 | // Ist eine Umgebung Living oder intransparenter Container oder |
| 498 | // unsichtbar? |
| 499 | if (living(env) || !env->QueryProp(P_TRANSPARENT) |
| 500 | || !env->short()) |
| 501 | { |
| 502 | // in dem Fall ist ende, aber wenn das gefundene Env nicht |
| 503 | // dieses Living selber oder sein Env ist, wird das |
| 504 | // Referenzobjekt zusaetzlich genullt. |
| 505 | if (env != this_object() && env != environment()) |
| 506 | base = 0; |
| 507 | break; |
| 508 | } |
| 509 | } |
| 510 | } |
| 511 | else |
| 512 | base = 0; // nicht im Raum oder Inventory |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | // scan input if we want a specific object to look at |
| 517 | if(sscanf(what, "%s an %s", detail, parent) == 2 || |
| 518 | sscanf(what, "%s am %s", detail, parent) == 2 || |
| 519 | sscanf(what, "%s in %s", detail, parent) == 2 || |
| 520 | sscanf(what, "%s im %s", detail, parent) == 2) |
| 521 | { |
| 522 | // if an ref object exists get its inventory. (Oben wurde sichergestellt, |
| 523 | // dass das Referenzobjekt einsehbar ist) |
| 524 | |
| 525 | if(base) |
| 526 | objs = base->locate_objects(parent, 1) || ({}); |
| 527 | else |
| 528 | { |
| 529 | // else get our inv and env |
| 530 | objs = environment()->locate_objects(parent, 1) |
| 531 | + locate_objects(parent, 1); |
| 532 | } |
| 533 | objs = filter_objects(objs, "short"); // nur sichtbare... |
| 534 | if(sizeof(objs) > 1) |
| 535 | return (notify_fail("Es gibt mehr als eine(n) "+capitalize(parent)+".\n"), 0); |
| 536 | else |
| 537 | { |
| 538 | if(sizeof(objs)) |
| 539 | base = objs[0]; |
| 540 | else |
| 541 | return (notify_fail("Hier ist kein(e) "+capitalize(parent)+".\n"), 0); |
| 542 | } |
| 543 | objs = 0; |
| 544 | } |
| 545 | else detail = what; |
| 546 | |
| 547 | // wie auch immer haben wir jetzt ein Bezugsobjekt. |
| 548 | int maxtries=3; |
| 549 | do { |
| 550 | int base_was_env=1; |
| 551 | // als ersten werden in Frage kommende Objekte gesucht. Wenn base |
| 552 | // existiert (idR nur im ersten Durchlauf), wird dort gesucht, sonst in |
| 553 | // Env und Inv. |
| 554 | if (base) |
| 555 | { |
| 556 | if (base == this_object() || base == environment() || |
| 557 | (base->QueryProp(P_TRANSPARENT) && !living(base))) |
| 558 | { |
| 559 | // ich kann in base reingucken... |
| 560 | objs = base->locate_objects(detail, 1) || ({}); |
| 561 | } |
| 562 | else |
| 563 | { |
| 564 | // Referenzobjekt da, aber nicht reinguckbar. base aber nicht nullen, |
| 565 | // denn es ist ja noch gueltig fuer Detailsuchen an base... |
| 566 | objs = ({}); |
| 567 | } |
| 568 | } |
| 569 | else |
| 570 | { |
| 571 | objs = environment()->locate_objects(detail, 1) |
| 572 | + locate_objects(detail, 1); |
| 573 | base = environment(); |
| 574 | } |
| 575 | objs = filter_objects(objs, "short"); // nur sichtbare... |
| 576 | |
| 577 | if (sizeof(objs)) |
| 578 | { |
| 579 | // Objekte gefunden, mal schauen, ob die taugen (d.h. fuer den jew. Sinn |
| 580 | // Infos haben. Wenn nicht, muessen wir weitersuchen. |
| 581 | // Aber erstmal die Objekte durchlaufen. |
| 582 | foreach(object ob: objs) |
| 583 | { |
| 584 | if (sense == SENSE_READ) |
| 585 | { |
| 586 | // Extrawurst: P_READ_MSG auch noch abfragen. |
| 587 | out = ob->QueryProp(P_READ_MSG); |
| 588 | if (!stringp(out)) |
| 589 | out = ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),SENSE_READ); |
| 590 | } |
| 591 | else |
| 592 | out=ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),sense); |
| 593 | if (stringp(out)) |
| 594 | { |
| 595 | SetProp(P_REFERENCE_OBJECT, ob); |
| 596 | tell_object(ME, out); |
| 597 | return 1; |
| 598 | } |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | // Keine Objekte gefunden, die in Frage kommen. Nach Details suchen. |
| 603 | if(out = base->GetDetail(detail, QueryProp(P_REAL_RACE),sense)) |
| 604 | { |
| 605 | SetProp(P_REFERENCE_OBJECT, base); |
| 606 | return (write(out), 1); |
| 607 | } |
| 608 | else |
| 609 | { |
| 610 | // Auch keine Details gefunden... Wenn wir uns noch das Env angucken |
| 611 | // koennen (weil base != env), dann machen wir das, ansonsten ist |
| 612 | // jetzt hier leider Ende... |
| 613 | if(base == environment()) |
| 614 | { |
| 615 | if (base_was_env) |
| 616 | SetProp(P_REFERENCE_OBJECT, 0); |
| 617 | return 0; |
| 618 | } |
| 619 | else |
| 620 | { |
| 621 | // nochmal im naechsten Schleifendurchlauf ohne base probieren. |
| 622 | base = 0; |
| 623 | base_was_env = 0; |
| 624 | } |
| 625 | } |
| 626 | } while(--maxtries); |
| 627 | |
| 628 | // nach dieser Schleife sollte man nie ankommen... |
| 629 | raise_error(sprintf("_sense_exa(): zuviele Versuche, etwas zu finden.")); |
| 630 | |
| 631 | return 0; |
| 632 | } |
| 633 | |
| 634 | varargs int look_into(string str,int mode) |
| 635 | { |
| 636 | object *found_obs; |
| 637 | |
| 638 | if( CannotSee() ) return 1; |
| 639 | _notify_fail("Wo willst Du denn reinschauen ?\n"); |
| 640 | found_obs=find_obs(str,PUT_GET_NONE); |
| 641 | if (!found_obs) |
| 642 | { |
| 643 | if (environment() && |
| 644 | (environment()->GetDetail(str,QueryProp(P_REAL_RACE))|| |
| 645 | environment()->GetDoorDesc(str))) |
| 646 | _notify_fail("Da kannst Du so nicht reinsehen.\n"); |
| 647 | return 0; |
| 648 | } |
| 649 | return _examine(str, mode); |
| 650 | } |
| 651 | |
| 652 | /* Gebe die Umgebung des aktiven Spielers zurueck, lasse dabei */ |
| 653 | /* rekursiv geschachtelte Raeume zu. */ |
| 654 | /* Wenn allow_short 0 ist, so wird immer die long-descr benutzt */ |
| 655 | varargs string env_descr(int allow_short,int flags, int force_short ) |
| 656 | { |
| 657 | object env; |
| 658 | int brief; |
| 659 | |
| 660 | env = environment(ME); |
| 661 | |
| 662 | if(!env) |
| 663 | return "Du schwebst im Nichts ... Du siehst nichts, rein gar nichts ...\n"; |
| 664 | |
| 665 | if (!force_short && (!allow_short || !QueryProp(P_BRIEF))) |
| 666 | return env->int_long(ME,ME,flags); |
| 667 | |
| 668 | if (!flags && ((brief=QueryProp(P_BRIEF))>=2)) |
| 669 | return ""; |
| 670 | |
| 671 | return env->int_short(ME,ME); |
| 672 | } |
| 673 | |
| 674 | int _look(string str) |
| 675 | { |
| 676 | string s; |
| 677 | int flag; |
| 678 | |
| 679 | if(CannotSee()) return 1; |
| 680 | |
| 681 | if(!str) |
| 682 | { |
| 683 | SetProp(P_REFERENCE_OBJECT, 0); |
| 684 | write( env_descr() ); |
| 685 | return 1; |
| 686 | } |
| 687 | if(str=="-f" || str=="genau") |
| 688 | { |
| 689 | SetProp(P_REFERENCE_OBJECT, 0); |
| 690 | write( env_descr(0,2) ); |
| 691 | return 1; |
| 692 | } |
| 693 | if(str=="-k" || str=="kurz") |
| 694 | { |
| 695 | SetProp(P_REFERENCE_OBJECT, 0); |
| 696 | write( env_descr(1,2,1) ); |
| 697 | return 1; |
| 698 | } |
| 699 | if(str[0..2]=="-f "){ |
| 700 | flag=2; |
| 701 | str=str[3..]; |
| 702 | } |
| 703 | else if(str[0..5]=="genau "){ |
| 704 | flag=2; |
| 705 | str=str[6..]; |
| 706 | } |
| 707 | else flag = 0; |
| 708 | if (sscanf(str,"%s an",s)) str=s; |
| 709 | if (sscanf(str,"%s in mir",s)||sscanf(str,"%s in dir",s)) return _examine(str,flag); |
| 710 | if (sscanf(str,"in %s",s)) return look_into(s,flag); |
| 711 | return _examine(str,flag); |
| 712 | } |
| 713 | |
| 714 | int _equipment(string arg) |
| 715 | { |
| 716 | if (CannotSee()) return 1; |
| 717 | call_other("/std/player/invmaster/invmaster", "ShowInv", ME, arg); |
| 718 | return 1; |
| 719 | } |
| 720 | |
| 721 | static mixed _query_localcmds() |
| 722 | { |
| 723 | return |
| 724 | ({({"ausruestung", "_equipment",0,0}), |
| 725 | ({"i","_inventory",0,0}), |
| 726 | ({"inv","_inventory",0,0}), |
| 727 | ({"inventur","_inventory",0,0}), |
| 728 | ({"schau","_look",0,0}), |
| 729 | ({"schaue","_look",0,0}), |
| 730 | ({"unt","_examine",0,0}), |
| 731 | ({"untersuch","_examine",0,0}), |
| 732 | ({"betracht","_examine",0,0}), |
| 733 | ({"untersuche","_examine",0,0}), |
| 734 | ({"betrachte","_examine",0,0}), |
| 735 | ({"betr","_examine",0,0}), |
| 736 | ({"lausche","_sense_exa",0,0}), |
| 737 | ({"lausch","_sense_exa",0,0}), |
| 738 | ({"hoer","_sense_exa",0,0}), |
| 739 | ({"hoere","_sense_exa",0,0}), |
| 740 | ({"lies","_sense_exa",0,0}), |
| 741 | ({"lese","_sense_exa",0,0}), |
| 742 | ({"les","_sense_exa",0,0}), |
| 743 | ({"schnupper","_sense_exa",0,0}), |
| 744 | ({"schnuppere","_sense_exa",0,0}), |
| 745 | ({"riech","_sense_exa",0,0}), |
| 746 | ({"rieche","_sense_exa",0,0}), |
| 747 | ({"taste","_sense_exa",0,0}), |
| 748 | ({"beruehre","_sense_exa",0,0}), |
| 749 | ({"beruehr","_sense_exa",0,0}), |
| 750 | ({"kurz","_toggle_brief",0,0}), |
| 751 | ({"lang","_toggle_brief",0,0}), |
| 752 | ({"ultrakurz","_toggle_brief",0,0}) |
| 753 | }); |
| 754 | } |