blob: 4dce80796d1a7a64651492ddc068a13b29e603b2 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// 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
Zesstra55f94fe2018-11-14 23:16:01 +010013//#include <player.h>
MG Mud User88f12472016-06-24 23:31:02 +020014#include <properties.h>
15#include <rooms.h>
16#include <wizlevels.h>
17#include <defines.h>
18#include <moving.h>
19#include <new_skills.h>
20#include <ansi.h>
Zesstra55f94fe2018-11-14 23:16:01 +010021#include <notify_fail.h>
MG Mud User88f12472016-06-24 23:31:02 +020022#include <sys_debug.h>
23
Zesstra55f94fe2018-11-14 23:16:01 +010024#define NEED_PROTOTYPES
25#include <container.h>
26#include <thing/properties.h>
27#include <living/put_and_get.h>
28#include <living/description.h>
29#include <living/put_and_get.h>
30#include <player/command.h>
31
MG Mud User88f12472016-06-24 23:31:02 +020032varargs mixed More(string str, int fflag, string returnto);
33
34void create()
35{
36 Set(P_BRIEF, SAVE, F_MODE);
37 Set(P_BLIND, SAVE, F_MODE);
38}
39
40int _toggle_brief()
41{
42 int brief;
43
44 if (query_verb()=="kurz")
45 brief=1;
46 else if (query_verb()=="ultrakurz")
47 brief=2;
48 else brief=0;
49 SetProp(P_BRIEF, brief);
50 write("Du bist nun im \""+
51 (brief?(brief==1?"Kurz":"Ultrakurz"):"Lang")+"\"modus.\n");
52 return 1;
53}
54
55private int sortinv(mixed a, mixed b) { return a[0] > b[0]; }
56
57private string collectinv(mixed obj)
58{
59 if(obj[0]=="") return 0;
60 return (obj[2] ? " " : "")
61 + obj[0]
62 + (obj[1] > 1 ? " ("+obj[1]+")" : "");
63}
64
65#define I_AUTOLOAD 1
66#define I_KEEP 4
67#define I_FORMATTED 16
68#define I_ARMOUR 64
69#define I_SORT 256
70#define I_WEAPON 1024
71#define I_FORCE_SORT 4096
72#define I_NO_TABLE 16384
73
74private string getflags(string arg, int flags)
75{
76 int no, i;
77 if(sizeof(arg) < 2) return 0;
78 no = (arg[0] == '-');
79
80 for(i = 1; i < sizeof(arg); i++)
81 {
82 switch(arg[i])
83 {
84 case 'a': flags |= I_AUTOLOAD << no; break;
85 case 'b': flags |= I_KEEP << no; break;
86 case 'f': flags |= I_FORMATTED << no; break;
87 case 'r': flags |= I_ARMOUR << no; break;
88 case 's': flags |= I_SORT << no; break;
89 case 'w': flags |= I_WEAPON << no; break;
90 case 'v': flags |= (I_ARMOUR | I_WEAPON) << !no; break;
91 case '1': flags |= I_NO_TABLE; break;
92 // Die Option macht nur Aerger und kommentiert ist sie eh nicht.
93 // Wer das dringend braucht, soll Wargons Schiebepuzzle benutzen.
94 //
95 // Tiamak, 15.10.2000
96 // case 'S': flags |= I_FORCE_SORT << no; break;
97 default : return arg[i..i]; // wird ausgegeben an Spieler als unbekannt.
98 }
99 }
100 return 0;
101}
102
103static int _check_keep(object ob)
104{
105 return (ob->QueryProp(P_KEEP_ON_SELL))==geteuid(ME);
106}
107
108int _inventory(string str)
109{
110 mixed *args, output;
111 int ansi, i, flags, minv;
112 mixed inventory, weapons, armours, misc;
113 string format;
114
115 if(CannotSee()) return 1;
116
117 if((str = _unparsed_args()) && str!="")
118 {
119 string error;
120 error = "Benutzung: i[nventar] [-/+1abfrsvw]\n";
121 args = regexp(regexplode(str, "[-+][1abfrswv][1abfrswv]*"),
122 "[-+][1abfrswv][1abfrswv]*");
123 if(!sizeof(args)) return (_notify_fail(error), 0);
124 if(sizeof(args = map(args, #'getflags/*'*/, &flags) - ({ 0 })))
125 {
126 printf("%s: Unbekanntes Argument.\n"+error, implode(args, ", "));
127 return 1;
128 }
129 }
130 // Fuer Spieler gehen nur sichtbare Objekte in den Algorithmus
131 if (IS_LEARNING(ME))
132 inventory = all_inventory(ME);
133 else
134 inventory = filter_objects(all_inventory(ME), "short");
135
136 ansi = member(({"vt100", "ansi"}), QueryProp(P_TTY)) != -1;
137 minv = 1 | (flags & (I_FORMATTED | (I_FORMATTED << 1)) ? 2 : 0);
138 format = (flags & I_NO_TABLE) ? "=" : "#";
139
140// if(flags & (I_FORCE_SORT | I_FORCE_SORT << 1))
141// {
142// closure sf;
143// sf = flags & I_FORCE_SORT ? #'> : #'<;
144// s = sort_array(s, lambda(({'a, 'b}),
145// ({#'funcall, sf,
146// ({#'||,({#'call_other,'a,"short"}),""}),
147// ({#'||,({#'call_other,'b,"short"}),""})})));
148// map_objects(s, "move", this_object());
149// s = all_inventory(ME);
150// }
151
152 if (flags & I_AUTOLOAD)
153 inventory = filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ);
154 else if (flags & (I_AUTOLOAD << 1))
155 inventory -= filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ);
156
157 if(flags & I_KEEP)
158 inventory = filter(inventory,#'_check_keep);
159 else if(flags & (I_KEEP << 1))
160 inventory -= filter(inventory,#'_check_keep);
161
162 armours = filter_objects(inventory, "QueryProp", P_ARMOUR_TYPE);
163 // Kleidung dazu addieren, vorher die erkannten Ruestungen abziehen, die
164 // muessen nicht nochmal durchiteriert werden.
165 armours += filter_objects(inventory-armours, "IsClothing");
166 // Ruestungen werden hier nicht abgezogen, weil es Kram gibt, welche sowohl
167 // Ruestung als auch Waffe ist.
168 weapons = filter_objects(inventory, "QueryProp", P_WEAPON_TYPE);
169 misc = inventory - weapons - armours; // rest ;-)
170
171 if(flags & I_WEAPON)
172 {
173 inventory = weapons; misc = ({});
174 if(!(flags & (I_ARMOUR))) armours = ({});
175 }
176 if(flags & I_ARMOUR)
177 {
178 inventory = armours; misc = ({});
179 if(!(flags & I_WEAPON)) weapons = ({});
180 }
181 if(flags & (I_WEAPON << 1)) { weapons = ({}); inventory = armours + misc; }
182 if(flags & (I_ARMOUR << 1)) { armours = ({}); inventory = weapons + misc; }
183
184 output = "";
185 if(flags & (I_FORMATTED | (I_FORMATTED << 1)))
186 {
187 inventory = make_invlist(this_player(), inventory, minv);
188 if(flags & (I_SORT | (I_SORT << 1)))
189 inventory = sort_array(inventory, #'sortinv/*'*/);
190 output += sprintf("%"+format+"-78s\n",
191 implode(map(inventory,#'collectinv/*'*/),"\n"));
192 }
193 else
194 {
195 if(weapons && sizeof(weapons))
196 {
197 weapons = make_invlist(this_player(), weapons, minv);
198 if(flags & (I_SORT | (I_SORT << 1)))
199 weapons = sort_array(weapons, #'sortinv/*'*/);
200 output += (ansi?ANSI_BOLD:"") + "Waffen:" + (ansi?ANSI_NORMAL:"")+"\n"
201 + sprintf("%"+format+"-78s\n",
202 implode(map(weapons, #'collectinv/*'*/), "\n"));
203 }
204 if(armours && sizeof(armours))
205 {
206 armours = make_invlist(this_player(), armours, minv);
207 if(flags & (I_SORT | (I_SORT << 1)))
208 armours = sort_array(armours, #'sortinv/*'*/);
209 output += (ansi?ANSI_BOLD:"")
210 + "Kleidung & Ruestungen:" + (ansi?ANSI_NORMAL:"")+"\n"
211 + sprintf("%"+format+"-78s\n",
212 implode(map(armours, #'collectinv/*'*/), "\n"));
213 }
214 if(misc && sizeof(misc))
215 {
216 misc = make_invlist(this_player(), misc, minv);
217 if(flags & (I_SORT | (I_SORT << 1)))
218 misc = sort_array(misc, #'sortinv/*'*/);
219 output += (ansi?ANSI_BOLD:"") + "Verschiedenes:" + (ansi?ANSI_NORMAL:"")+"\n"
220 + sprintf("%"+format+"-78s\n",
221 implode(map(misc, #'collectinv/*'*/), "\n"));
222 }
223 }
224
225 // Spielerwunsch: 'inventar' sollte doch das Bezugsobjekt auf den Spieler
226 // aendern.
227 SetProp(P_REFERENCE_OBJECT, this_object());
228
229 if (output=="")
230 output += (ansi?ANSI_BOLD:"")+"Die Liste ist leer."+(ansi?ANSI_NORMAL:"");
231 More(output);
232 return 1;
233}
234
Zesstra55f94fe2018-11-14 23:16:01 +0100235private int select_sense(string str)
MG Mud User88f12472016-06-24 23:31:02 +0200236{
Zesstra55f94fe2018-11-14 23:16:01 +0100237 int sense = -1;
MG Mud User88f12472016-06-24 23:31:02 +0200238 if(member(({"riech","rieche","schnupper","schnuppere"}),query_verb())!=-1)
239 {
240 _notify_fail("Du kannst nichts Besonderes riechen.\n");
241 sense = SENSE_SMELL;
242 }
243 else if(member(({"lausche","lausch","hoer","hoere"}),query_verb())!=-1)
244 {
245 if(QueryProp(P_DEAF))
Zesstra55f94fe2018-11-14 23:16:01 +0100246 {
247 notify_fail("Du bist taub!\n");
248 return -1;
249 }
MG Mud User88f12472016-06-24 23:31:02 +0200250 _notify_fail("Du kannst nichts Besonderes hoeren.\n");
251 sense = SENSE_SOUND;
252 }
253 else if(member(({"taste","beruehre","beruehr"}),query_verb())!=-1)
254 {
255 sense = SENSE_TOUCH;
256 // ein "ab" ganz am Ende von str wird abgeschnitten, es soll sowohl "taste
257 // x ab" als auch "taste x" funktionieren.
258 if (str) {
259 _notify_fail("Sowas kannst Du hier nicht ertasten!\n");
260 string *tmp = explode(str," ");
261 if (sizeof(tmp) > 1 && tmp[<1] == "ab")
262 str = implode(tmp[0..<2], " ");
263 }
264 else
265 _notify_fail("Was willst Du denn abtasten?\n");
266 }
267 else if (member(({"lies","lese","les"}), query_verb()) > -1)
268 {
269 _notify_fail("Was willst Du lesen?\n");
270 if ( !str ) // Kein SENSE_DEFAULT zulassen.
Zesstra55f94fe2018-11-14 23:16:01 +0100271 return -1;
272 if (CannotSee(1)) {
273 notify_fail("Du kannst nichts sehen!\n", NF_NL_MAX);
274 return -1;
MG Mud User88f12472016-06-24 23:31:02 +0200275 }
276 sense = SENSE_READ;
277 }
Zesstra55f94fe2018-11-14 23:16:01 +0100278 // else ist normales Sehen/untersuchen
279 else
280 {
281 if (CannotSee(1)) {
282 notify_fail("Du kannst nichts sehen!\n", NF_NL_MAX);
283 return -1;
284 }
285 _notify_fail("Was willst Du denn untersuchen?\n");
286 if (!str) return -1;
287 sense = SENSE_VIEW;
MG Mud User88f12472016-06-24 23:31:02 +0200288 }
Zesstra55f94fe2018-11-14 23:16:01 +0100289 // "rieche an ..." etc.: das an rausschneiden, wird nicht gebraucht.
290 if (sizeof(str))
291 {
292 if (sense!=SENSE_VIEW)
293 {
294 string what;
295 if (sscanf(str,"an %s",what)==1) str=what;
296 }
297 }
MG Mud User88f12472016-06-24 23:31:02 +0200298
Zesstra55f94fe2018-11-14 23:16:01 +0100299 return sense;
300}
301
302private object get_ref_object(string str, string what)
303{
304 object ref_object;
MG Mud User88f12472016-06-24 23:31:02 +0200305 // do we look at an object in our environment ?
306 if (sscanf(str,"%s in raum", what) || sscanf(str,"%s im raum", what))
Zesstra55f94fe2018-11-14 23:16:01 +0100307 ref_object = environment();
MG Mud User88f12472016-06-24 23:31:02 +0200308 // is the object inside of me (inventory)
309 else if (sscanf(str,"%s in mir", what) || sscanf(str,"%s in dir", what))
Zesstra55f94fe2018-11-14 23:16:01 +0100310 ref_object = this_object();
311 else
312 {
313 // ansonsten ist das argument komplett der suchstring und wir nehmen das
314 // Referenzobjekt (so existent).
MG Mud User88f12472016-06-24 23:31:02 +0200315 what = str;
316 // get the last object we looked at
Zesstra55f94fe2018-11-14 23:16:01 +0100317 ref_object = QueryProp(P_REFERENCE_OBJECT);
MG Mud User88f12472016-06-24 23:31:02 +0200318 // if a reference object exists, test for its existance in the room
319 // or in our inventory
Zesstra55f94fe2018-11-14 23:16:01 +0100320 if (objectp(ref_object))
MG Mud User88f12472016-06-24 23:31:02 +0200321 {
Zesstra55f94fe2018-11-14 23:16:01 +0100322 if (ref_object == environment() || ref_object==this_object())
MG Mud User88f12472016-06-24 23:31:02 +0200323 {
324 // Umgebung oder Spieler selber sind als Bezugsobjekt immer in
325 // Ordnung, nichts machen.
326 }
327 // Das Referenzobjekt darf nicht unsichtbar sein.
Zesstra55f94fe2018-11-14 23:16:01 +0100328 else if (!ref_object->short())
329 ref_object = 0;
330 // Nur wenn unser environment()
331 else if(member(deep_inventory(environment()), ref_object) != -1)
MG Mud User88f12472016-06-24 23:31:02 +0200332 {
Zesstra55f94fe2018-11-14 23:16:01 +0100333 foreach(object env : all_environment(ref_object)) {
MG Mud User88f12472016-06-24 23:31:02 +0200334 // Ist eine Umgebung Living oder intransparenter Container oder
335 // unsichtbar?
336 if (living(env) || !env->QueryProp(P_TRANSPARENT)
337 || !env->short())
338 {
339 // in dem Fall ist ende, aber wenn das gefundene Env nicht
340 // dieses Living selber oder sein Env ist, wird das
341 // Referenzobjekt zusaetzlich genullt.
342 if (env != this_object() && env != environment())
Zesstra55f94fe2018-11-14 23:16:01 +0100343 ref_object = 0;
MG Mud User88f12472016-06-24 23:31:02 +0200344 break;
345 }
346 }
347 }
348 else
Zesstra55f94fe2018-11-14 23:16:01 +0100349 ref_object = 0; // nicht im Raum oder Inventory
MG Mud User88f12472016-06-24 23:31:02 +0200350 }
351 }
Zesstra55f94fe2018-11-14 23:16:01 +0100352 return ref_object;
353}
MG Mud User88f12472016-06-24 23:31:02 +0200354
Zesstra55f94fe2018-11-14 23:16:01 +0100355private object find_base(object ref_object, string what, string detail,
356 string parent)
357{
358 object base;
359 // Suchen wir an/im/in/etc. einem bestimmten Objekt?
MG Mud User88f12472016-06-24 23:31:02 +0200360 if(sscanf(what, "%s an %s", detail, parent) == 2 ||
361 sscanf(what, "%s am %s", detail, parent) == 2 ||
362 sscanf(what, "%s in %s", detail, parent) == 2 ||
363 sscanf(what, "%s im %s", detail, parent) == 2)
364 {
Zesstra55f94fe2018-11-14 23:16:01 +0100365 object *objs;
366 // Wenn es ein Referenzobjekt gibt, wird das parent-Objekt in diesem
367 // gesucht. (Oben wurde sichergestellt, dass das Referenzobjekt einsehbar
368 // ist)
369 if(ref_object)
370 objs = ref_object->locate_objects(parent, 1) || ({});
371 // sonst im Environment oder in uns.
372 else {
MG Mud User88f12472016-06-24 23:31:02 +0200373 objs = environment()->locate_objects(parent, 1)
374 + locate_objects(parent, 1);
375 }
376 objs = filter_objects(objs, "short"); // nur sichtbare...
Zesstra55f94fe2018-11-14 23:16:01 +0100377 switch(sizeof(objs))
MG Mud User88f12472016-06-24 23:31:02 +0200378 {
Zesstra55f94fe2018-11-14 23:16:01 +0100379 case 0:
380 notify_fail("Hier ist kein(e) "+capitalize(parent)+".\n");
381 return 0;
382 case 1:
383 // Basisobjekt gefunden.
384 base = objs[0];
385 break;
386 default:
387 notify_fail("Es gibt mehr als eine(n) "+capitalize(parent)+".\n");
388 return 0;
MG Mud User88f12472016-06-24 23:31:02 +0200389 }
MG Mud User88f12472016-06-24 23:31:02 +0200390 }
Zesstra55f94fe2018-11-14 23:16:01 +0100391 // im anderen fall ist das komplette what das gesuchte detail, was wir am
392 // Referenzobjekt suchen (sofern vorhanden).
393 else
394 {
395 base = ref_object;
396 detail = what;
397 }
398 return base;
399}
MG Mud User88f12472016-06-24 23:31:02 +0200400
Zesstra55f94fe2018-11-14 23:16:01 +0100401private nosave int exa_cnt;
402private nosave int exa_time;
403private nosave string *exa;
404private void unt_script_dings(string str)
405{
406 // unt-script-sucher
407 if (!sizeof(str)) return;
408 if (member(({"boden","decke","wand","waende"}),old_explode(str," ")[0]) == -1) {
409 exa_cnt -= (time() - exa_time)/2;
410 exa_time = time();
411 exa_cnt++;
412 if (!exa)
413 exa = ({ str });
414 else
415 exa += ({ str });
416 if (exa_cnt > 10) {
417 log_file("ARCH/LOOK",
418 sprintf("%s: %s in %s\n%@O\n",dtime(time()),getuid(this_object()),
419 environment() ? object_name(environment()) : "???",exa), 150000);
420 exa_cnt = 0;
421 exa = ({});
422 }
423 else if (exa_cnt < 0) {
424 exa_cnt = 0;
425 exa = ({});
426 }
427 }
428}
429
430varargs int _examine(string str, int mode)
431{
432 // Sinn auswaehlen, der benutzt wird. Wenn -1, abbrechen (kein Sinn bzw.
433 // Sinn erlaubt ggf. kein leeren <str> fuer Defaulmeldung). Je nach Sinn
434 // wird auch <str>modifiziert.
435 int sense=select_sense(&str);
436 if (sense<0) return 0;
437
438 unt_script_dings(str);
439
440 // Wenn kein str, dann SENSE_DEFAULT vom Environment ausgeben. Bei
441 // SENSE_VIEW wurde das bereits bei den Aufrufern dieser Funktion gemacht.
442 if (sense!=SENSE_VIEW)
443 {
444 if (!str)
445 {
446 string detail = environment()->GetDetail(SENSE_DEFAULT,
447 QueryProp(P_REAL_RACE),sense);
448 if(!detail)
449 return 0;
450 write(detail);
451 return 1;
452 }
453 }
454
455 // Das Ref-Objekt finden, das kann dann auch in <what> angeben sein. In dem
456 // Fall wird <what> um die Angabe des Ref-Objekts gekuerzt.
457 string what;
458 object ref_object = get_ref_object(str, &what);
459
460 // Sodann ein Basisobjekt finden. Das Basisobjekt ist das, was bei einem
461 // "detail an parent" durch parent gekennzeichnet wird oder notfalls das
462 // Ref-Objekt von oben.
463 string detail, parent; // detail an parent
464 object base; // das fuer parent gefundene objekt
465 base = find_base(ref_object, what, &detail, &parent);
466
467 // Jetzt wird versucht, ein Objekt mit der ID "detail" in base (parent) oder
468 // ein Detail an base zu finden. Die Schleife laeuft ggf. zweimal. Wenn im
469 // ersten Durchlauf nichts gefunden wird, wird ggf. noch die Umgebung in
470 // einem zweiten Durchlauf anguckt.
471 int first_base_was_env = (!base || base==environment() ? 1 : 0);
MG Mud User88f12472016-06-24 23:31:02 +0200472 do {
Zesstra55f94fe2018-11-14 23:16:01 +0100473 object *objs;
474 // Wenn base existiert und wir reingucken koennen, ermitteln wir alle zu
475 // detail in Frage kommenanden Objekte in seinem Inventar
MG Mud User88f12472016-06-24 23:31:02 +0200476 if (base)
477 {
478 if (base == this_object() || base == environment() ||
479 (base->QueryProp(P_TRANSPARENT) && !living(base)))
480 {
481 // ich kann in base reingucken...
482 objs = base->locate_objects(detail, 1) || ({});
483 }
484 else
485 {
Zesstra55f94fe2018-11-14 23:16:01 +0100486 // Basisobjekt da, aber nicht reinguckbar, also keine Objekte
487 // gefunden. base aber nicht nullen, denn es ist ja noch gueltig fuer
488 // Detailsuchen an base...
MG Mud User88f12472016-06-24 23:31:02 +0200489 objs = ({});
490 }
491 }
Zesstra55f94fe2018-11-14 23:16:01 +0100492 // Wenn nicht, werden alle fuer detail in Frage kommenden Objekt in
493 // unserer Umgebung und in uns selber ermittelt.
MG Mud User88f12472016-06-24 23:31:02 +0200494 else
495 {
Zesstra55f94fe2018-11-14 23:16:01 +0100496 base = environment();
MG Mud User88f12472016-06-24 23:31:02 +0200497 objs = environment()->locate_objects(detail, 1)
498 + locate_objects(detail, 1);
MG Mud User88f12472016-06-24 23:31:02 +0200499 }
Zesstra55f94fe2018-11-14 23:16:01 +0100500 // Und in jedem Fall werden alle Objekt raussortiert, die unsichtbar sind.
501 // ;-)
MG Mud User88f12472016-06-24 23:31:02 +0200502 objs = filter_objects(objs, "short"); // nur sichtbare...
503
Zesstra55f94fe2018-11-14 23:16:01 +0100504 // Wenn es sichtbare gibt, werden die ggf. angeguckt.
MG Mud User88f12472016-06-24 23:31:02 +0200505 if (sizeof(objs))
506 {
507 // Objekte gefunden, mal schauen, ob die taugen (d.h. fuer den jew. Sinn
508 // Infos haben. Wenn nicht, muessen wir weitersuchen.
509 // Aber erstmal die Objekte durchlaufen.
510 foreach(object ob: objs)
511 {
Zesstra55f94fe2018-11-14 23:16:01 +0100512 string out;
513 if (sense == SENSE_VIEW)
514 {
515 out = ob->long(mode);
516 }
517 else if (sense == SENSE_READ)
MG Mud User88f12472016-06-24 23:31:02 +0200518 {
519 // Extrawurst: P_READ_MSG auch noch abfragen.
520 out = ob->QueryProp(P_READ_MSG);
521 if (!stringp(out))
522 out = ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),SENSE_READ);
523 }
524 else
525 out=ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),sense);
Zesstra55f94fe2018-11-14 23:16:01 +0100526 // Wenn was gefunden wurde, sind wir fertig.
MG Mud User88f12472016-06-24 23:31:02 +0200527 if (stringp(out))
528 {
529 SetProp(P_REFERENCE_OBJECT, ob);
530 tell_object(ME, out);
531 return 1;
532 }
533 }
534 }
Zesstra55f94fe2018-11-14 23:16:01 +0100535 // offenbar keine Objekte gefunden oder die hatten nix fuer unseren Sinn
536 // dabei. Also nach ordinaeren Details an base/parent suchen.
537 string out = base->GetDetail(detail, QueryProp(P_REAL_RACE), sense);
538 if (!out && sense==SENSE_VIEW)
539 out = base->GetDoorDesc(detail);
540 if (out)
MG Mud User88f12472016-06-24 23:31:02 +0200541 {
Zesstra55f94fe2018-11-14 23:16:01 +0100542 // Detail gefunden, base darf neues Referenzobjekt werden und nach
543 // Ausgabe sind wir fertig.
MG Mud User88f12472016-06-24 23:31:02 +0200544 SetProp(P_REFERENCE_OBJECT, base);
Zesstra55f94fe2018-11-14 23:16:01 +0100545 write(out);
546 return 1;
MG Mud User88f12472016-06-24 23:31:02 +0200547 }
548 else
549 {
Zesstra55f94fe2018-11-14 23:16:01 +0100550 // wenn auch keine Details gefunden, dann schauen, unser Env evtl.
551 // noch nen passendes Detail oder Objekt hat. Das ist aber natuerlich
552 // nur der Fall, wenn base nicht eh schon das Environment ist.
553 if (base != environment())
MG Mud User88f12472016-06-24 23:31:02 +0200554 {
Zesstra55f94fe2018-11-14 23:16:01 +0100555 // Wir schauen uns das Env noch an. Bei den anderen Sinnen kein neues
556 // notify_fail, weil sonst staendig Meldungen kommen, dass x nicht da
557 // ist, nur weil es keine Beschreibung fuer den Sinn hat.
558 if (sense==SENSE_VIEW)
559 write(break_string("Du findest an "+base->name(WEM)
560 +" kein \"" + capitalize(detail) + "\"."
561 " Dein Blick wendet sich der Umgebung zu.",78));
562 // in diesem Fall nullen wir base und lassen die Schleife noch
563 // einmal durchlaufen.
564 base = 0;
565 continue;
MG Mud User88f12472016-06-24 23:31:02 +0200566 }
Zesstra55f94fe2018-11-14 23:16:01 +0100567 // Leider ist nix mehr uebrig zum angucken und in jedem Fall Ende.
MG Mud User88f12472016-06-24 23:31:02 +0200568 else
569 {
Zesstra55f94fe2018-11-14 23:16:01 +0100570 // Wenn schon das erste angeguckte base das Environment war (dann
571 // ist diese Schleife uebrigens nur einmal gelaufen), gibt es eine
572 // leicht andere Meldung und das Bezugsobjekt muss weg.
573 // neue notify_fail gibt es nur fuer SENSE_VIEW (s.o.)
574 if (first_base_was_env) {
575 SetProp(P_REFERENCE_OBJECT, 0);
576 if (sense==SENSE_VIEW)
577 _notify_fail("Sowas siehst Du da nicht!\n");
578 }
579 else if (sense==SENSE_VIEW) {
580 _notify_fail("Sowas siehst Du auch da nicht!\n");
581 }
582 return 0;
MG Mud User88f12472016-06-24 23:31:02 +0200583 }
584 }
Zesstra55f94fe2018-11-14 23:16:01 +0100585 } while(1);
586 // Nie erreicht.
MG Mud User88f12472016-06-24 23:31:02 +0200587 return 0;
588}
589
Zesstra55f94fe2018-11-14 23:16:01 +0100590// Funktion fuer "schau in ..."
MG Mud User88f12472016-06-24 23:31:02 +0200591varargs int look_into(string str,int mode)
592{
593 object *found_obs;
594
595 if( CannotSee() ) return 1;
Zesstra55f94fe2018-11-14 23:16:01 +0100596 _notify_fail("Wo willst Du denn reinschauen?\n");
597 found_obs=find_objects(str, 0, 0);
598 if (!sizeof(found_obs))
MG Mud User88f12472016-06-24 23:31:02 +0200599 {
600 if (environment() &&
601 (environment()->GetDetail(str,QueryProp(P_REAL_RACE))||
602 environment()->GetDoorDesc(str)))
603 _notify_fail("Da kannst Du so nicht reinsehen.\n");
604 return 0;
605 }
Zesstra55f94fe2018-11-14 23:16:01 +0100606
MG Mud User88f12472016-06-24 23:31:02 +0200607 return _examine(str, mode);
608}
609
610/* Gebe die Umgebung des aktiven Spielers zurueck, lasse dabei */
611/* rekursiv geschachtelte Raeume zu. */
612/* Wenn allow_short 0 ist, so wird immer die long-descr benutzt */
613varargs string env_descr(int allow_short,int flags, int force_short )
614{
615 object env;
616 int brief;
617
618 env = environment(ME);
619
620 if(!env)
621 return "Du schwebst im Nichts ... Du siehst nichts, rein gar nichts ...\n";
622
623 if (!force_short && (!allow_short || !QueryProp(P_BRIEF)))
624 return env->int_long(ME,ME,flags);
625
626 if (!flags && ((brief=QueryProp(P_BRIEF))>=2))
627 return "";
628
629 return env->int_short(ME,ME);
630}
631
Zesstra55f94fe2018-11-14 23:16:01 +0100632// Kommandofunktion fuer schau.
633// Verzweigt ggf. in _examine() fuers normale Untersuchen.
MG Mud User88f12472016-06-24 23:31:02 +0200634int _look(string str)
635{
636 string s;
637 int flag;
638
639 if(CannotSee()) return 1;
640
Zesstra55f94fe2018-11-14 23:16:01 +0100641 // nur schau mit ggf. Flags entsorgt das Ref-Objekt und schaut die
642 // Raumbeschreibung an.
MG Mud User88f12472016-06-24 23:31:02 +0200643 if(!str)
644 {
645 SetProp(P_REFERENCE_OBJECT, 0);
646 write( env_descr() );
647 return 1;
648 }
649 if(str=="-f" || str=="genau")
650 {
651 SetProp(P_REFERENCE_OBJECT, 0);
652 write( env_descr(0,2) );
653 return 1;
654 }
655 if(str=="-k" || str=="kurz")
656 {
657 SetProp(P_REFERENCE_OBJECT, 0);
658 write( env_descr(1,2,1) );
659 return 1;
660 }
Zesstra55f94fe2018-11-14 23:16:01 +0100661 // Ansonsten wird in _examine() weitergemacht, wobei Flags vorher
662 // rausgeschnitten werden. _examine() benutzt die Flags, falls es eine
663 // Langbeschreibung eines Objektes ausgeben wird.
MG Mud User88f12472016-06-24 23:31:02 +0200664 if(str[0..2]=="-f "){
665 flag=2;
666 str=str[3..];
667 }
668 else if(str[0..5]=="genau "){
669 flag=2;
670 str=str[6..];
671 }
672 else flag = 0;
Zesstra55f94fe2018-11-14 23:16:01 +0100673
MG Mud User88f12472016-06-24 23:31:02 +0200674 if (sscanf(str,"%s an",s)) str=s;
Zesstra55f94fe2018-11-14 23:16:01 +0100675 // "in mir", "in dir" soll in _examine rein, aber "in ..." in look_into().
MG Mud User88f12472016-06-24 23:31:02 +0200676 if (sscanf(str,"%s in mir",s)||sscanf(str,"%s in dir",s)) return _examine(str,flag);
677 if (sscanf(str,"in %s",s)) return look_into(s,flag);
Zesstra55f94fe2018-11-14 23:16:01 +0100678 // Alles andere weiter an _examine().
MG Mud User88f12472016-06-24 23:31:02 +0200679 return _examine(str,flag);
680}
681
682int _equipment(string arg)
683{
684 if (CannotSee()) return 1;
685 call_other("/std/player/invmaster/invmaster", "ShowInv", ME, arg);
686 return 1;
687}
688
689static mixed _query_localcmds()
690{
691 return
692 ({({"ausruestung", "_equipment",0,0}),
693 ({"i","_inventory",0,0}),
694 ({"inv","_inventory",0,0}),
695 ({"inventur","_inventory",0,0}),
696 ({"schau","_look",0,0}),
697 ({"schaue","_look",0,0}),
698 ({"unt","_examine",0,0}),
699 ({"untersuch","_examine",0,0}),
700 ({"betracht","_examine",0,0}),
701 ({"untersuche","_examine",0,0}),
702 ({"betrachte","_examine",0,0}),
703 ({"betr","_examine",0,0}),
Zesstra55f94fe2018-11-14 23:16:01 +0100704 ({"lausche","_examine",0,0}),
705 ({"lausch","_examine",0,0}),
706 ({"hoer","_examine",0,0}),
707 ({"hoere","_examine",0,0}),
708 ({"lies","_examine",0,0}),
709 ({"lese","_examine",0,0}),
710 ({"les","_examine",0,0}),
711 ({"schnupper","_examine",0,0}),
712 ({"schnuppere","_examine",0,0}),
713 ({"riech","_examine",0,0}),
714 ({"rieche","_examine",0,0}),
715 ({"taste","_examine",0,0}),
716 ({"beruehre","_examine",0,0}),
717 ({"beruehr","_examine",0,0}),
MG Mud User88f12472016-06-24 23:31:02 +0200718 ({"kurz","_toggle_brief",0,0}),
719 ({"lang","_toggle_brief",0,0}),
720 ({"ultrakurz","_toggle_brief",0,0})
721 });
722}