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 |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 11 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 12 | //#include <player.h> |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 13 | #include <properties.h> |
| 14 | #include <rooms.h> |
| 15 | #include <wizlevels.h> |
| 16 | #include <defines.h> |
| 17 | #include <moving.h> |
| 18 | #include <new_skills.h> |
| 19 | #include <ansi.h> |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 20 | #include <notify_fail.h> |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 21 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 22 | #define NEED_PROTOTYPES |
| 23 | #include <container.h> |
| 24 | #include <thing/properties.h> |
| 25 | #include <living/put_and_get.h> |
| 26 | #include <living/description.h> |
| 27 | #include <living/put_and_get.h> |
| 28 | #include <player/command.h> |
| 29 | |
Zesstra | bd66df7 | 2019-04-04 20:53:43 +0200 | [diff] [blame] | 30 | //#define DEBUG(x, y, z) send_debug(x, y, z) |
| 31 | #define DEBUG(x, y, z) |
| 32 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 33 | varargs mixed More(string str, int fflag, string returnto); |
| 34 | |
| 35 | void create() |
| 36 | { |
| 37 | Set(P_BRIEF, SAVE, F_MODE); |
| 38 | Set(P_BLIND, SAVE, F_MODE); |
| 39 | } |
| 40 | |
| 41 | int _toggle_brief() |
| 42 | { |
| 43 | int brief; |
| 44 | |
| 45 | if (query_verb()=="kurz") |
| 46 | brief=1; |
| 47 | else if (query_verb()=="ultrakurz") |
| 48 | brief=2; |
| 49 | else brief=0; |
| 50 | SetProp(P_BRIEF, brief); |
| 51 | write("Du bist nun im \""+ |
| 52 | (brief?(brief==1?"Kurz":"Ultrakurz"):"Lang")+"\"modus.\n"); |
| 53 | return 1; |
| 54 | } |
| 55 | |
| 56 | private int sortinv(mixed a, mixed b) { return a[0] > b[0]; } |
| 57 | |
| 58 | private string collectinv(mixed obj) |
| 59 | { |
| 60 | if(obj[0]=="") return 0; |
| 61 | return (obj[2] ? " " : "") |
| 62 | + obj[0] |
| 63 | + (obj[1] > 1 ? " ("+obj[1]+")" : ""); |
| 64 | } |
| 65 | |
| 66 | #define I_AUTOLOAD 1 |
| 67 | #define I_KEEP 4 |
| 68 | #define I_FORMATTED 16 |
| 69 | #define I_ARMOUR 64 |
| 70 | #define I_SORT 256 |
| 71 | #define I_WEAPON 1024 |
| 72 | #define I_FORCE_SORT 4096 |
| 73 | #define I_NO_TABLE 16384 |
| 74 | |
| 75 | private string getflags(string arg, int flags) |
| 76 | { |
| 77 | int no, i; |
| 78 | if(sizeof(arg) < 2) return 0; |
| 79 | no = (arg[0] == '-'); |
| 80 | |
| 81 | for(i = 1; i < sizeof(arg); i++) |
| 82 | { |
| 83 | switch(arg[i]) |
| 84 | { |
| 85 | case 'a': flags |= I_AUTOLOAD << no; break; |
| 86 | case 'b': flags |= I_KEEP << no; break; |
| 87 | case 'f': flags |= I_FORMATTED << no; break; |
| 88 | case 'r': flags |= I_ARMOUR << no; break; |
| 89 | case 's': flags |= I_SORT << no; break; |
| 90 | case 'w': flags |= I_WEAPON << no; break; |
| 91 | case 'v': flags |= (I_ARMOUR | I_WEAPON) << !no; break; |
| 92 | case '1': flags |= I_NO_TABLE; break; |
| 93 | // Die Option macht nur Aerger und kommentiert ist sie eh nicht. |
| 94 | // Wer das dringend braucht, soll Wargons Schiebepuzzle benutzen. |
| 95 | // |
| 96 | // Tiamak, 15.10.2000 |
| 97 | // case 'S': flags |= I_FORCE_SORT << no; break; |
| 98 | default : return arg[i..i]; // wird ausgegeben an Spieler als unbekannt. |
| 99 | } |
| 100 | } |
| 101 | return 0; |
| 102 | } |
| 103 | |
| 104 | static int _check_keep(object ob) |
| 105 | { |
| 106 | return (ob->QueryProp(P_KEEP_ON_SELL))==geteuid(ME); |
| 107 | } |
| 108 | |
| 109 | int _inventory(string str) |
| 110 | { |
| 111 | mixed *args, output; |
Arathorn | b305145 | 2021-05-13 21:13:03 +0200 | [diff] [blame] | 112 | int ansi, flags, minv; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 113 | mixed inventory, weapons, armours, misc; |
| 114 | string format; |
| 115 | |
| 116 | if(CannotSee()) return 1; |
| 117 | |
| 118 | if((str = _unparsed_args()) && str!="") |
| 119 | { |
| 120 | string error; |
| 121 | error = "Benutzung: i[nventar] [-/+1abfrsvw]\n"; |
| 122 | args = regexp(regexplode(str, "[-+][1abfrswv][1abfrswv]*"), |
| 123 | "[-+][1abfrswv][1abfrswv]*"); |
| 124 | if(!sizeof(args)) return (_notify_fail(error), 0); |
| 125 | if(sizeof(args = map(args, #'getflags/*'*/, &flags) - ({ 0 }))) |
| 126 | { |
| 127 | printf("%s: Unbekanntes Argument.\n"+error, implode(args, ", ")); |
| 128 | return 1; |
| 129 | } |
| 130 | } |
| 131 | // Fuer Spieler gehen nur sichtbare Objekte in den Algorithmus |
| 132 | if (IS_LEARNING(ME)) |
| 133 | inventory = all_inventory(ME); |
| 134 | else |
| 135 | inventory = filter_objects(all_inventory(ME), "short"); |
| 136 | |
| 137 | ansi = member(({"vt100", "ansi"}), QueryProp(P_TTY)) != -1; |
| 138 | minv = 1 | (flags & (I_FORMATTED | (I_FORMATTED << 1)) ? 2 : 0); |
| 139 | format = (flags & I_NO_TABLE) ? "=" : "#"; |
| 140 | |
| 141 | // if(flags & (I_FORCE_SORT | I_FORCE_SORT << 1)) |
| 142 | // { |
| 143 | // closure sf; |
| 144 | // sf = flags & I_FORCE_SORT ? #'> : #'<; |
| 145 | // s = sort_array(s, lambda(({'a, 'b}), |
| 146 | // ({#'funcall, sf, |
| 147 | // ({#'||,({#'call_other,'a,"short"}),""}), |
| 148 | // ({#'||,({#'call_other,'b,"short"}),""})}))); |
| 149 | // map_objects(s, "move", this_object()); |
| 150 | // s = all_inventory(ME); |
| 151 | // } |
| 152 | |
| 153 | if (flags & I_AUTOLOAD) |
| 154 | inventory = filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ); |
| 155 | else if (flags & (I_AUTOLOAD << 1)) |
| 156 | inventory -= filter_objects(inventory,"QueryProp",P_AUTOLOADOBJ); |
| 157 | |
| 158 | if(flags & I_KEEP) |
| 159 | inventory = filter(inventory,#'_check_keep); |
| 160 | else if(flags & (I_KEEP << 1)) |
| 161 | inventory -= filter(inventory,#'_check_keep); |
| 162 | |
| 163 | armours = filter_objects(inventory, "QueryProp", P_ARMOUR_TYPE); |
| 164 | // Kleidung dazu addieren, vorher die erkannten Ruestungen abziehen, die |
| 165 | // muessen nicht nochmal durchiteriert werden. |
| 166 | armours += filter_objects(inventory-armours, "IsClothing"); |
| 167 | // Ruestungen werden hier nicht abgezogen, weil es Kram gibt, welche sowohl |
| 168 | // Ruestung als auch Waffe ist. |
| 169 | weapons = filter_objects(inventory, "QueryProp", P_WEAPON_TYPE); |
| 170 | misc = inventory - weapons - armours; // rest ;-) |
| 171 | |
| 172 | if(flags & I_WEAPON) |
| 173 | { |
| 174 | inventory = weapons; misc = ({}); |
| 175 | if(!(flags & (I_ARMOUR))) armours = ({}); |
| 176 | } |
| 177 | if(flags & I_ARMOUR) |
| 178 | { |
| 179 | inventory = armours; misc = ({}); |
| 180 | if(!(flags & I_WEAPON)) weapons = ({}); |
| 181 | } |
| 182 | if(flags & (I_WEAPON << 1)) { weapons = ({}); inventory = armours + misc; } |
| 183 | if(flags & (I_ARMOUR << 1)) { armours = ({}); inventory = weapons + misc; } |
| 184 | |
| 185 | output = ""; |
| 186 | if(flags & (I_FORMATTED | (I_FORMATTED << 1))) |
| 187 | { |
| 188 | inventory = make_invlist(this_player(), inventory, minv); |
| 189 | if(flags & (I_SORT | (I_SORT << 1))) |
| 190 | inventory = sort_array(inventory, #'sortinv/*'*/); |
| 191 | output += sprintf("%"+format+"-78s\n", |
| 192 | implode(map(inventory,#'collectinv/*'*/),"\n")); |
| 193 | } |
| 194 | else |
| 195 | { |
| 196 | if(weapons && sizeof(weapons)) |
| 197 | { |
| 198 | weapons = make_invlist(this_player(), weapons, minv); |
| 199 | if(flags & (I_SORT | (I_SORT << 1))) |
| 200 | weapons = sort_array(weapons, #'sortinv/*'*/); |
| 201 | output += (ansi?ANSI_BOLD:"") + "Waffen:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 202 | + sprintf("%"+format+"-78s\n", |
| 203 | implode(map(weapons, #'collectinv/*'*/), "\n")); |
| 204 | } |
| 205 | if(armours && sizeof(armours)) |
| 206 | { |
| 207 | armours = make_invlist(this_player(), armours, minv); |
| 208 | if(flags & (I_SORT | (I_SORT << 1))) |
| 209 | armours = sort_array(armours, #'sortinv/*'*/); |
| 210 | output += (ansi?ANSI_BOLD:"") |
| 211 | + "Kleidung & Ruestungen:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 212 | + sprintf("%"+format+"-78s\n", |
| 213 | implode(map(armours, #'collectinv/*'*/), "\n")); |
| 214 | } |
| 215 | if(misc && sizeof(misc)) |
| 216 | { |
| 217 | misc = make_invlist(this_player(), misc, minv); |
| 218 | if(flags & (I_SORT | (I_SORT << 1))) |
| 219 | misc = sort_array(misc, #'sortinv/*'*/); |
| 220 | output += (ansi?ANSI_BOLD:"") + "Verschiedenes:" + (ansi?ANSI_NORMAL:"")+"\n" |
| 221 | + sprintf("%"+format+"-78s\n", |
| 222 | implode(map(misc, #'collectinv/*'*/), "\n")); |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | // Spielerwunsch: 'inventar' sollte doch das Bezugsobjekt auf den Spieler |
| 227 | // aendern. |
| 228 | SetProp(P_REFERENCE_OBJECT, this_object()); |
| 229 | |
| 230 | if (output=="") |
Arathorn | 016025d | 2023-04-23 22:55:06 +0200 | [diff] [blame] | 231 | output += (ansi?ANSI_BOLD:"")+"Du hast nichts dabei."+(ansi?ANSI_NORMAL:""); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 232 | More(output); |
| 233 | return 1; |
| 234 | } |
| 235 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 236 | private int select_sense(string str, closure transparent_check) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 237 | { |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 238 | int sense = -1; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 239 | if(member(({"riech","rieche","schnupper","schnuppere"}),query_verb())!=-1) |
| 240 | { |
| 241 | _notify_fail("Du kannst nichts Besonderes riechen.\n"); |
| 242 | sense = SENSE_SMELL; |
| 243 | } |
| 244 | else if(member(({"lausche","lausch","hoer","hoere"}),query_verb())!=-1) |
| 245 | { |
| 246 | if(QueryProp(P_DEAF)) |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 247 | { |
| 248 | notify_fail("Du bist taub!\n"); |
| 249 | return -1; |
| 250 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 251 | _notify_fail("Du kannst nichts Besonderes hoeren.\n"); |
| 252 | sense = SENSE_SOUND; |
| 253 | } |
| 254 | else if(member(({"taste","beruehre","beruehr"}),query_verb())!=-1) |
| 255 | { |
| 256 | sense = SENSE_TOUCH; |
| 257 | // ein "ab" ganz am Ende von str wird abgeschnitten, es soll sowohl "taste |
| 258 | // x ab" als auch "taste x" funktionieren. |
| 259 | if (str) { |
| 260 | _notify_fail("Sowas kannst Du hier nicht ertasten!\n"); |
| 261 | string *tmp = explode(str," "); |
| 262 | if (sizeof(tmp) > 1 && tmp[<1] == "ab") |
| 263 | str = implode(tmp[0..<2], " "); |
| 264 | } |
| 265 | else |
| 266 | _notify_fail("Was willst Du denn abtasten?\n"); |
| 267 | } |
| 268 | else if (member(({"lies","lese","les"}), query_verb()) > -1) |
| 269 | { |
| 270 | _notify_fail("Was willst Du lesen?\n"); |
| 271 | if ( !str ) // Kein SENSE_DEFAULT zulassen. |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 272 | return -1; |
| 273 | if (CannotSee(1)) { |
| 274 | notify_fail("Du kannst nichts sehen!\n", NF_NL_MAX); |
| 275 | return -1; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 276 | } |
| 277 | sense = SENSE_READ; |
| 278 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 279 | // else ist normales Sehen/untersuchen |
| 280 | else |
| 281 | { |
| 282 | if (CannotSee(1)) { |
| 283 | notify_fail("Du kannst nichts sehen!\n", NF_NL_MAX); |
| 284 | return -1; |
| 285 | } |
| 286 | _notify_fail("Was willst Du denn untersuchen?\n"); |
| 287 | if (!str) return -1; |
| 288 | sense = SENSE_VIEW; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 289 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 290 | // "rieche an ..." etc.: das an rausschneiden, wird nicht gebraucht. |
| 291 | if (sizeof(str)) |
| 292 | { |
| 293 | if (sense!=SENSE_VIEW) |
| 294 | { |
| 295 | string what; |
| 296 | if (sscanf(str,"an %s",what)==1) str=what; |
| 297 | } |
| 298 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 299 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 300 | switch(sense) |
| 301 | { |
| 302 | // Fuer diese Sinne muss der Container offen sein. |
| 303 | case SENSE_SMELL: |
| 304 | case SENSE_TOUCH: |
| 305 | case SENSE_SOUND: |
| 306 | transparent_check = function int (object o) |
| 307 | { return o->QueryProp(P_CNT_STATUS) == CNT_STATUS_OPEN;}; |
| 308 | break; |
| 309 | // Fuer alle anderen reicht, wenn er transparent ist. |
| 310 | default: |
| 311 | transparent_check = function int (object o) |
Arathorn | c08a1e5 | 2019-01-21 18:56:32 +0100 | [diff] [blame] | 312 | { return (o->QueryProp(P_TRANSPARENT) != 0); }; |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 313 | } |
| 314 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 315 | return sense; |
| 316 | } |
| 317 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 318 | private object get_ref_object(string *tokens, closure transparent_check, |
| 319 | int ref_given) |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 320 | { |
| 321 | object ref_object; |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 322 | |
| 323 | // im Kommando speziell beschrieben ist, wo die Suche losgehen soll, spielt |
| 324 | // das Referenzobjekt keine Rolle. |
| 325 | if (sizeof(tokens) > 1 && tokens[<1] == "hier") { |
| 326 | tokens = tokens[..<2]; |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 327 | ref_object = environment(); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 328 | ref_given=1; |
| 329 | } |
| 330 | else if (sizeof(tokens) > 2 && tokens[<2] == "in") |
| 331 | { |
| 332 | if (tokens[<1] == "mir" || |
| 333 | tokens[<1] == "dir") |
| 334 | { |
| 335 | tokens = tokens[..<3]; |
| 336 | ref_object = this_object(); |
| 337 | ref_given=1; |
| 338 | } |
| 339 | else if (tokens[<1] == "raum") |
| 340 | { |
| 341 | tokens = tokens[..<3]; |
| 342 | ref_object = environment(); |
| 343 | ref_given=1; |
| 344 | } |
| 345 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 346 | else |
| 347 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 348 | // ansonsten bleibt tokens unmodifiziert und wir nehmen das |
| 349 | // Referenzobjekt (so existent). |
| 350 | ref_object = QueryProp(P_REFERENCE_OBJECT); |
| 351 | if (objectp(ref_object)) |
| 352 | { |
| 353 | // Dieses muss aber "irgendwo" in unserem Umfeld sein. |
| 354 | if (ref_object == environment() || ref_object==this_object()) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 355 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 356 | // Umgebung oder Spieler selber sind als Bezugsobjekt immer in |
| 357 | // Ordnung, nichts machen. |
| 358 | } |
| 359 | // Wenn es nicht wir oder environment ist, darf das Referenzobjekt |
| 360 | // nicht unsichtbar sein. |
Zesstra | a33e843 | 2020-06-13 20:20:12 +0200 | [diff] [blame] | 361 | else if (ref_object->QueryProp(P_INVIS)) |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 362 | ref_object = 0; |
| 363 | // Und nur wenn das Ref-Objekt irgendwie in unserer Umgebung ist |
| 364 | // (direkt, in uns, in einem Container etc.) kommt es in Frage. Es |
| 365 | // wird daher geprueft, ob all_environments() des Ref-Objekts auch |
| 366 | // unser environment enthaelt. |
| 367 | else |
| 368 | { |
Zesstra | 5f03eaf | 2018-12-17 22:40:55 +0100 | [diff] [blame] | 369 | object *all_envs=all_environment(ref_object) |
| 370 | || ref_object->AllVirtualEnvironments() |
| 371 | || ({}); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 372 | int i=member(all_envs, environment()); |
| 373 | if (i >= 0) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 374 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 375 | // dann von dem Environment an entlanglaufen und alle |
| 376 | // intermediaeren Objekt pruefen, ob sie einsehbar und sichtbar |
| 377 | // sind. |
| 378 | foreach(object env : all_envs[..i]) { |
| 379 | // Ist eine Umgebung Living oder intransparenter Container oder |
| 380 | // unsichtbar? |
| 381 | if (living(env) || !funcall(transparent_check, env) |
Zesstra | a33e843 | 2020-06-13 20:20:12 +0200 | [diff] [blame] | 382 | || env->QueryProp(P_INVIS)) |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 383 | { |
| 384 | // Kette zum Ref-Objekt unterbrochen. Wenn das unterbrechende |
| 385 | // Env nicht dieses Living selber oder sein Env ist, wird das |
| 386 | // Referenzobjekt zusaetzlich genullt. |
| 387 | if (env != this_object() && env != environment()) |
| 388 | ref_object = 0; |
| 389 | break; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 390 | } |
| 391 | } |
| 392 | } |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 393 | else |
| 394 | ref_object = 0; // nicht im Raum oder Inventory |
| 395 | } |
| 396 | } // ref_object exists |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 397 | } |
Zesstra | bd66df7 | 2019-04-04 20:53:43 +0200 | [diff] [blame] | 398 | DEBUG(PL, sprintf("%O\n",ref_object), "get_ref_object:"); |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 399 | return ref_object; |
| 400 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 401 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 402 | // Versucht ein Basisobjekt (ggf. in env) finden, was durch <tokens> |
| 403 | // beschrieben wird. |
| 404 | // Das Basisobjekt ist das, was bei einem "detail an parent" durch parent |
| 405 | // gekennzeichnet wird oder notfalls das Ref-Objekt selber. Zu beachten ist, |
| 406 | // dass find_base() ggf. rekursiv arbeitet, um sowas wie "riss an kerze in |
| 407 | // kerzenstaender auf tisch" zu finden. detail ist dann der letzte Teil der |
| 408 | // tokens (der Anfang!), was keinen Container mehr bezeichnet, das gefundene |
| 409 | // Objekt ist der letzte Container/Item auf dem Weg zu detail. |
| 410 | // detail muss als Referenz uebergeben werden. |
| 411 | // transparent_check ist die Closure, die prueft, ob man in einen |
| 412 | // Container reinforschen (sehen, lesen, riechen, tasten etc.) kann. Sie |
| 413 | // bekommt den Container uebergeben. |
| 414 | private object find_base(object env, string *tokens, string detail, |
| 415 | closure transparent_check) |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 416 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 417 | // zuerst pruefen, ob man in env reinsehen/reinforschen kann (in |
| 418 | // this_object() und environment() kann man immer reinsehen). |
| 419 | if (env && env != this_object() && env != environment()) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 420 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 421 | // Nicht in Lebewesen reingucken und nicht in intransparente/geschlossene |
| 422 | // Container |
| 423 | if (living(env) || !funcall(transparent_check, env)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 424 | { |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 425 | // suche nach Objekten in env ist jetzt zuende, weil nicht in env |
| 426 | // reinsehbar. |
| 427 | // Aber tokens koennte noch ein detail beschreiben, was der Aufrufer an |
| 428 | // env findet. Also tokens nach detail und env zurueckgeben. |
| 429 | detail = implode(tokens, " "); |
Zesstra | bd66df7 | 2019-04-04 20:53:43 +0200 | [diff] [blame] | 430 | DEBUG(PL, sprintf("Env: %O, Detail: %s\n",env, detail), |
| 431 | "find_base 1"); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 432 | return env; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 433 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 434 | } |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 435 | // ansonsten schauen, ob in tokens noch ein (weiterer) Container beschrieben |
| 436 | // wird. |
| 437 | for (int i = sizeof(tokens)-1; i > 1; i--) |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 438 | { |
Zesstra | dc0ef89 | 2018-11-18 23:36:03 +0100 | [diff] [blame] | 439 | object ob, *objs; |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 440 | // In env oder mir oder umgebung gucken, ob ein passendes Objekt da ist. |
| 441 | // Hierfuer werden mit jedem Schleifendurchlauf von hinten mehr worte aus |
| 442 | // tokens benutzt. (Beispiel "muenze in boerse 2") |
Zesstra | dc0ef89 | 2018-11-18 23:36:03 +0100 | [diff] [blame] | 443 | // present waere schneller und die Komplexitaet von present_objects waere |
| 444 | // hier nicht noetig. Allerdings beruecksichtigt es die Sichtbarkeit und |
| 445 | // ggf. virtuell anwesende Objekte, was present nicht tut. |
| 446 | string suchid=implode(tokens[i..], " "); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 447 | if (env) |
Zesstra | dc0ef89 | 2018-11-18 23:36:03 +0100 | [diff] [blame] | 448 | objs = env->present_objects(suchid) || ({}); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 449 | else |
Zesstra | dc0ef89 | 2018-11-18 23:36:03 +0100 | [diff] [blame] | 450 | objs = environment()->present_objects(suchid) || |
| 451 | this_object()->present_objects(suchid); |
| 452 | // wenn nicht genau ein Objekt gefunden wird, wird weitergesucht, im |
| 453 | // naechsten Durchlauf mit einem Wort mehr aus tokens |
Zesstra | a81a17b | 2018-12-03 21:25:21 +0100 | [diff] [blame] | 454 | if (!sizeof(objs)) |
Zesstra | dc0ef89 | 2018-11-18 23:36:03 +0100 | [diff] [blame] | 455 | { |
Zesstra | a81a17b | 2018-12-03 21:25:21 +0100 | [diff] [blame] | 456 | continue; |
| 457 | } |
Zesstra | 9298c2d | 2018-12-03 21:32:59 +0100 | [diff] [blame] | 458 | // falls mehr als ein Objekt gefunden wurden: das erste nehmen, wie |
| 459 | // ueberall sonst auch. |
Zesstra | a81a17b | 2018-12-03 21:25:21 +0100 | [diff] [blame] | 460 | ob = objs[0]; |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 461 | |
| 462 | // an dieser Stelle wird (noch) nicht geprueft, ob man in das gefundene |
| 463 | // Objekt hineinforschen kann. |
| 464 | |
| 465 | // Wenn passende Praeposition davor (z.B. "in" (beutel), "auf" (tisch)), |
| 466 | // rekursiv weitersuchen, ob der restliche Teil von tokens evtl. nochmal |
| 467 | // nen container in dem gefundenen Objekt bezeichnet. |
| 468 | if (tokens[i-1] == ob->QueryProp(P_PREPOSITION)) |
| 469 | return find_base(ob, tokens[..i-2], &detail, transparent_check); |
| 470 | |
| 471 | // Wenn tokens[i-1] "an" oder "am" ist, wird zwar nicht weiter verzweigt, |
| 472 | // aber vermutlich wird ein Detail an diesem Objekt gesucht, d.h. das |
| 473 | // Objekt wird env, tokens entsprechend gekuerzt und die Schleife beendet. |
| 474 | // Bemerkung: haette ob tatsaechlich eine Praeposition an|am gehabt, |
| 475 | // waeren wir vorher in find_base() verzweigt zum Suchen in dem Container. |
| 476 | if (tokens[i-1] == "an" || tokens[i-1] == "am") { |
| 477 | env = ob; |
| 478 | tokens=tokens[..i-2]; |
| 479 | break; |
| 480 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 481 | } |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 482 | // an diesem Punkt sind in tokens nur noch worte drin, die keinen Container |
| 483 | // mehr beschreiben. Die Resttokens kommen nach <detail>, sie beschreiben |
| 484 | // dann entweder ein Objekt oder ein Detail. |
| 485 | detail = implode(tokens, " "); |
| 486 | |
| 487 | // Wenn es ein env gibt, beschreibt detail nun ein Objekt in env oder ein |
| 488 | // Detail an env, was der Aufrufer prueft. |
| 489 | // Wenn es aber kein env gibt (das passiert, wenn der Aufrufer dieser |
| 490 | // Funktion schon kein env (->Referenzobjekt) hereingegeben hat, wurde auch |
| 491 | // kein Container gefunden, der durch die tokens beschrieben wurde. Dann |
| 492 | // kann der Aufrufer noch an/in this_object() oder environment() gucken, ob |
| 493 | // was zu finden ist. |
Zesstra | bd66df7 | 2019-04-04 20:53:43 +0200 | [diff] [blame] | 494 | DEBUG(PL, sprintf("Env: %O, Detail: %s\n",env, detail), |
| 495 | "find_base 2:"); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 496 | return env; |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 497 | } |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 498 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 499 | private nosave int exa_cnt; |
| 500 | private nosave int exa_time; |
| 501 | private nosave string *exa; |
| 502 | private void unt_script_dings(string str) |
| 503 | { |
| 504 | // unt-script-sucher |
| 505 | if (!sizeof(str)) return; |
| 506 | if (member(({"boden","decke","wand","waende"}),old_explode(str," ")[0]) == -1) { |
| 507 | exa_cnt -= (time() - exa_time)/2; |
| 508 | exa_time = time(); |
| 509 | exa_cnt++; |
| 510 | if (!exa) |
| 511 | exa = ({ str }); |
| 512 | else |
| 513 | exa += ({ str }); |
| 514 | if (exa_cnt > 10) { |
| 515 | log_file("ARCH/LOOK", |
| 516 | sprintf("%s: %s in %s\n%@O\n",dtime(time()),getuid(this_object()), |
| 517 | environment() ? object_name(environment()) : "???",exa), 150000); |
| 518 | exa_cnt = 0; |
| 519 | exa = ({}); |
| 520 | } |
| 521 | else if (exa_cnt < 0) { |
| 522 | exa_cnt = 0; |
| 523 | exa = ({}); |
| 524 | } |
| 525 | } |
| 526 | } |
| 527 | |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 528 | private string nf_meldung(string detail, int sense) |
Zesstra | 481215f | 2018-12-05 22:15:26 +0100 | [diff] [blame] | 529 | { |
| 530 | switch(sense) |
| 531 | { |
| 532 | case SENSE_SMELL: |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 533 | return "Du riechst nichts Besonderes.\n"; |
Zesstra | 481215f | 2018-12-05 22:15:26 +0100 | [diff] [blame] | 534 | case SENSE_SOUND: |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 535 | return "Du hoerst nichts Besonderes.\n"; |
Zesstra | 481215f | 2018-12-05 22:15:26 +0100 | [diff] [blame] | 536 | case SENSE_TOUCH: |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 537 | return "Du fuehlst nichts Besonderes.\n"; |
Zesstra | 481215f | 2018-12-05 22:15:26 +0100 | [diff] [blame] | 538 | // case SENSE_READ: |
| 539 | // default: |
| 540 | // return "siehst"; |
| 541 | } |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 542 | return sprintf("\'%s\' siehst Du da nicht!\n",capitalize(detail)); |
Zesstra | 481215f | 2018-12-05 22:15:26 +0100 | [diff] [blame] | 543 | } |
| 544 | |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 545 | private int _examine_rec(object *ref_objects, string *tokens, closure |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 546 | transparent_check, int sense, int mode, |
| 547 | int ref_given) |
| 548 | { |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 549 | // ref_objects sind alle in Frage kommenden Kandidaten, an denen wir suchen. |
Zesstra | bd66df7 | 2019-04-04 20:53:43 +0200 | [diff] [blame] | 550 | DEBUG(PL, sprintf("Refobjekt-Kandidaten: %O\n",ref_objects), |
| 551 | "_examine_rec 1:"); |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 552 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 553 | // Sodann ein Basisobjekt finden. Das Basisobjekt ist das, was bei einem |
| 554 | // "detail an parent" durch parent gekennzeichnet wird oder notfalls das |
| 555 | // Ref-Objekt von oben. Zu beachten ist, dass find_base() ggf. rekursiv |
| 556 | // arbeitet, um sowas wie "riss an kerze in kerzenstaender auf tisch" zu |
| 557 | // finden. detail ist dann das letzte Teil der tokens, der keinen Container |
| 558 | // mehr bezeichnet, das gefundene Objekt ist der letzte Container/Item auf |
| 559 | // dem Weg zu detail. (detail==riss, base==kerze) |
| 560 | string detail; // detail an parent |
| 561 | // das fuer parent gefundene objekt |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 562 | object base = find_base(ref_objects[0], tokens, &detail, transparent_check); |
| 563 | // BTW: find_base liefert immer was zurueck - wenn nix gefunden wird, das |
| 564 | // ref_object, was als Start der Suche uebergeben wurde. |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 565 | // Jetzt wird versucht, ein Objekt mit der ID "detail" in base oder |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 566 | // ein Detail an base zu finden. |
| 567 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 568 | object *objs; |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 569 | // Wenn wir in base reingucken koennen, ermitteln wir alle zu |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 570 | // detail in Frage kommenanden Objekte in seinem Inventar |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 571 | if (base == this_object() || base == environment() || |
| 572 | (funcall(transparent_check, base) && !living(base))) |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 573 | { |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 574 | objs = base->locate_objects(detail, 1) || ({}); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 575 | } |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 576 | else |
| 577 | { |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 578 | // Basisobjekt da, aber nicht reinguckbar, also keine Objekte |
| 579 | // gefunden. base aber nicht nullen, denn es ist ja noch gueltig fuer |
| 580 | // Detailsuchen an base... |
| 581 | objs = ({}); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 582 | } |
| 583 | // Und in jedem Fall werden alle Objekt raussortiert, die unsichtbar sind. |
| 584 | // ;-) |
Zesstra | a33e843 | 2020-06-13 20:20:12 +0200 | [diff] [blame] | 585 | objs -= filter_objects(objs, "QueryProp", P_INVIS); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 586 | |
| 587 | // Wenn es sichtbare gibt, werden die ggf. angeguckt. |
| 588 | if (sizeof(objs)) |
| 589 | { |
| 590 | // Objekte gefunden, mal schauen, ob die taugen (d.h. fuer den jew. Sinn |
| 591 | // Infos haben. Wenn nicht, muessen wir weitersuchen. |
| 592 | // Aber erstmal die Objekte durchlaufen. |
| 593 | foreach(object ob: objs) |
| 594 | { |
| 595 | string out; |
| 596 | if (sense == SENSE_VIEW) |
| 597 | { |
| 598 | out = ob->long(mode); |
| 599 | } |
| 600 | else if (sense == SENSE_READ) |
| 601 | { |
| 602 | // Extrawurst: P_READ_MSG auch noch abfragen. |
| 603 | out = ob->QueryProp(P_READ_MSG); |
| 604 | if (!stringp(out)) |
| 605 | out = ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),SENSE_READ); |
| 606 | } |
| 607 | else |
| 608 | out=ob->GetDetail(SENSE_DEFAULT,QueryProp(P_REAL_RACE),sense); |
| 609 | // Wenn was gefunden wurde, sind wir fertig. |
| 610 | if (stringp(out)) |
| 611 | { |
| 612 | SetProp(P_REFERENCE_OBJECT, ob); |
| 613 | tell_object(ME, out); |
| 614 | return 1; |
| 615 | } |
| 616 | } |
| 617 | } |
| 618 | // keine Objekte gefunden oder die hatten nix fuer unseren Sinn |
| 619 | // dabei. Also nach ordinaeren Details an base/parent suchen. |
| 620 | string out = base->GetDetail(detail, QueryProp(P_REAL_RACE), sense); |
| 621 | // Achja, Tueren gibt es ja auch noch. :-o (TODO: die solten vItems werden) |
| 622 | if (!out && sense==SENSE_VIEW) |
| 623 | out = base->GetDoorDesc(detail); |
| 624 | if (out) |
| 625 | { |
| 626 | // Detail gefunden, base darf neues Referenzobjekt werden und nach |
| 627 | // Ausgabe sind wir fertig. |
| 628 | SetProp(P_REFERENCE_OBJECT, base); |
| 629 | write(out); |
| 630 | return 1; |
| 631 | } |
| 632 | else |
| 633 | { |
| 634 | // wenn auch keine Details gefunden, dann schauen, unser Env evtl. |
| 635 | // noch nen passendes Detail oder Objekt hat. Das ist aber natuerlich |
| 636 | // nur der Fall, wenn ref_object nicht eh schon das Environment war. |
| 637 | // Ausserdem nicht machen, wenn der Nutzer ein spezifisches Referenzobjekt |
| 638 | // angegeben hat (z.B. "in raum"). |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 639 | if (sizeof(ref_objects) > 1) |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 640 | { |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 641 | // Wir schauen uns ggf. weitere Kandidaten an. Bei den anderen |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 642 | // Sinnen kein neues notify_fail, weil sonst staendig Meldungen kommen, |
| 643 | // dass x nicht da ist, nur weil es keine Beschreibung fuer den Sinn hat. |
Zesstra | efc5b30 | 2018-12-14 02:00:58 +0100 | [diff] [blame] | 644 | if (sense==SENSE_VIEW || sense==SENSE_READ) |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 645 | { |
Zesstra | 9a08375 | 2018-12-05 20:18:23 +0100 | [diff] [blame] | 646 | // Ausgabe, was gerade angeguckt hat. |
| 647 | if (ref_objects[0] == environment()) |
| 648 | out="Sowas siehst Du hier nicht. "; |
| 649 | else if (ref_objects[0] == this_object()) |
| 650 | out="Sowas siehst Du an Dir nicht. "; |
| 651 | else |
| 652 | out="Sowas siehst Du an/in "+ref_objects[0]->name(WEM) +" nicht. "; |
| 653 | // Ausgabe, was man als naechstes anguckt. |
| 654 | if (ref_objects[1] == environment()) |
| 655 | out+="Du schaust Dich um."; |
| 656 | else |
| 657 | out+="Du schaust Dich an."; |
| 658 | |
| 659 | write(break_string(out,78)); |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 660 | } |
| 661 | return _examine_rec(ref_objects[1..], tokens, transparent_check, |
| 662 | sense, mode, 0); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 663 | } |
| 664 | // Leider ist nix mehr uebrig zum angucken und in jedem Fall Ende. |
| 665 | else |
| 666 | { |
| 667 | // Wenn spezifisches ref_object vom Nutzer angegeben (ref_given!=0), |
| 668 | // gibt es eine leicht andere Meldung und das Bezugsobjekt muss weg. |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 669 | if (ref_given) { |
| 670 | SetProp(P_REFERENCE_OBJECT, 0); |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 671 | notify_fail(break_string(nf_meldung(detail, sense),78)); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 672 | } |
Zesstra | 9ed8c9b | 2018-12-03 21:23:56 +0100 | [diff] [blame] | 673 | // Ansonsten gibt es nur nen passendes notify_fail und Ende. |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 674 | else if (sense==SENSE_VIEW) { |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 675 | notify_fail(break_string("\'" + capitalize(detail) + "\'" |
| 676 | + " siehst Du auch da nicht!\n"),78); |
Zesstra | 9ed8c9b | 2018-12-03 21:23:56 +0100 | [diff] [blame] | 677 | } |
| 678 | else { |
Zesstra | f5621a2 | 2018-12-06 21:27:21 +0100 | [diff] [blame] | 679 | notify_fail(break_string(nf_meldung(detail, sense),78)); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 680 | } |
| 681 | return 0; |
| 682 | } |
| 683 | } |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 684 | } |
| 685 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 686 | varargs int _examine(string str, int mode) |
| 687 | { |
| 688 | // Sinn auswaehlen, der benutzt wird. Wenn -1, abbrechen (kein Sinn bzw. |
| 689 | // Sinn erlaubt ggf. kein leeren <str> fuer Defaulmeldung). Je nach Sinn |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 690 | // wird auch <str> modifiziert. |
| 691 | // transparent_check enthaelt spaeter die Closure, die entscheidet, |
| 692 | // ob man mit dem Sinn in einen Container reinforschen kann. |
| 693 | closure transparent_check; |
| 694 | int sense=select_sense(&str, &transparent_check); |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 695 | if (sense<0) return 0; |
| 696 | |
| 697 | unt_script_dings(str); |
| 698 | |
| 699 | // Wenn kein str, dann SENSE_DEFAULT vom Environment ausgeben. Bei |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 700 | // SENSE_VIEW wird das bereits bei den Aufrufern dieser Funktion gemacht und |
| 701 | // die Beschreibung der Umgebung ausgegeben. |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 702 | if (sense!=SENSE_VIEW) |
| 703 | { |
| 704 | if (!str) |
| 705 | { |
| 706 | string detail = environment()->GetDetail(SENSE_DEFAULT, |
| 707 | QueryProp(P_REAL_RACE),sense); |
| 708 | if(!detail) |
| 709 | return 0; |
| 710 | write(detail); |
| 711 | return 1; |
| 712 | } |
| 713 | } |
| 714 | |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 715 | string *tokens = explode(str, " "); |
| 716 | int ref_given; |
| 717 | // Das Ref-Objekt finden, das kann dann auch in tokens angegeben sein. In dem |
| 718 | // Fall wird die Liste an tokens um die Angabe des Ref-Objekts gekuerzt und |
| 719 | // ref_given gesetzt. |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 720 | object ref_ob = get_ref_object(&tokens, transparent_check, &ref_given); |
Zesstra | a19328a | 2018-11-16 01:28:20 +0100 | [diff] [blame] | 721 | // Bemerkung: Das Referenzobjekt ist garantiert sichtbar, aber nicht |
| 722 | // unbedingt einsehbar. Wird weiter unten geprueft. |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 723 | |
Zesstra | fc501e1 | 2018-12-02 23:37:33 +0100 | [diff] [blame] | 724 | // Falls nicht explizit ein Objekt als Ref-Objekt angegeben wurde, werden |
| 725 | // max. 3 Objekte angeguckt: das eigentliche Referenzobjekt, das |
| 726 | // Environment und das eigene Objekt. Da ref_object auch eines der letzten |
| 727 | // beiden sein kann, muss die Dublette ggf. raus. |
| 728 | object *ref_objects; |
| 729 | if (ref_ob) |
| 730 | { |
| 731 | ref_objects=({ref_ob}); |
| 732 | if (!ref_given) |
| 733 | ref_objects += ({environment(), this_object()}) - ref_objects; |
| 734 | |
| 735 | } |
| 736 | else |
| 737 | ref_objects = ({environment(), this_object()}); |
| 738 | |
| 739 | return _examine_rec(ref_objects, tokens, transparent_check, sense, mode, |
| 740 | ref_given); |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 741 | } |
| 742 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 743 | // Funktion fuer "schau in ..." |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 744 | varargs int look_into(string str,int mode) |
| 745 | { |
| 746 | object *found_obs; |
| 747 | |
| 748 | if( CannotSee() ) return 1; |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 749 | _notify_fail("Wo willst Du denn reinschauen?\n"); |
| 750 | found_obs=find_objects(str, 0, 0); |
| 751 | if (!sizeof(found_obs)) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 752 | { |
| 753 | if (environment() && |
| 754 | (environment()->GetDetail(str,QueryProp(P_REAL_RACE))|| |
| 755 | environment()->GetDoorDesc(str))) |
| 756 | _notify_fail("Da kannst Du so nicht reinsehen.\n"); |
| 757 | return 0; |
| 758 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 759 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 760 | return _examine(str, mode); |
| 761 | } |
| 762 | |
| 763 | /* Gebe die Umgebung des aktiven Spielers zurueck, lasse dabei */ |
| 764 | /* rekursiv geschachtelte Raeume zu. */ |
| 765 | /* Wenn allow_short 0 ist, so wird immer die long-descr benutzt */ |
| 766 | varargs string env_descr(int allow_short,int flags, int force_short ) |
| 767 | { |
| 768 | object env; |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 769 | |
| 770 | env = environment(ME); |
| 771 | |
| 772 | if(!env) |
| 773 | return "Du schwebst im Nichts ... Du siehst nichts, rein gar nichts ...\n"; |
| 774 | |
| 775 | if (!force_short && (!allow_short || !QueryProp(P_BRIEF))) |
| 776 | return env->int_long(ME,ME,flags); |
| 777 | |
Arathorn | b305145 | 2021-05-13 21:13:03 +0200 | [diff] [blame] | 778 | if (!flags && QueryProp(P_BRIEF)>=2) |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 779 | return ""; |
| 780 | |
| 781 | return env->int_short(ME,ME); |
| 782 | } |
| 783 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 784 | // Kommandofunktion fuer schau. |
| 785 | // Verzweigt ggf. in _examine() fuers normale Untersuchen. |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 786 | int _look(string str) |
| 787 | { |
| 788 | string s; |
| 789 | int flag; |
| 790 | |
| 791 | if(CannotSee()) return 1; |
| 792 | |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 793 | // nur schau mit ggf. Flags entsorgt das Ref-Objekt und schaut die |
| 794 | // Raumbeschreibung an. |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 795 | if(!str) |
| 796 | { |
| 797 | SetProp(P_REFERENCE_OBJECT, 0); |
| 798 | write( env_descr() ); |
| 799 | return 1; |
| 800 | } |
| 801 | if(str=="-f" || str=="genau") |
| 802 | { |
| 803 | SetProp(P_REFERENCE_OBJECT, 0); |
| 804 | write( env_descr(0,2) ); |
| 805 | return 1; |
| 806 | } |
| 807 | if(str=="-k" || str=="kurz") |
| 808 | { |
| 809 | SetProp(P_REFERENCE_OBJECT, 0); |
| 810 | write( env_descr(1,2,1) ); |
| 811 | return 1; |
| 812 | } |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 813 | // Ansonsten wird in _examine() weitergemacht, wobei Flags vorher |
| 814 | // rausgeschnitten werden. _examine() benutzt die Flags, falls es eine |
| 815 | // Langbeschreibung eines Objektes ausgeben wird. |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 816 | if(str[0..2]=="-f "){ |
| 817 | flag=2; |
| 818 | str=str[3..]; |
| 819 | } |
| 820 | else if(str[0..5]=="genau "){ |
| 821 | flag=2; |
| 822 | str=str[6..]; |
| 823 | } |
| 824 | else flag = 0; |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 825 | |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 826 | if (sscanf(str,"%s an",s)) str=s; |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 827 | // "in mir", "in dir" soll in _examine rein, aber "in ..." in look_into(). |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 828 | if (sscanf(str,"%s in mir",s)||sscanf(str,"%s in dir",s)) return _examine(str,flag); |
| 829 | if (sscanf(str,"in %s",s)) return look_into(s,flag); |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 830 | // Alles andere weiter an _examine(). |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 831 | return _examine(str,flag); |
| 832 | } |
| 833 | |
| 834 | int _equipment(string arg) |
| 835 | { |
| 836 | if (CannotSee()) return 1; |
| 837 | call_other("/std/player/invmaster/invmaster", "ShowInv", ME, arg); |
| 838 | return 1; |
| 839 | } |
| 840 | |
| 841 | static mixed _query_localcmds() |
| 842 | { |
| 843 | return |
| 844 | ({({"ausruestung", "_equipment",0,0}), |
| 845 | ({"i","_inventory",0,0}), |
| 846 | ({"inv","_inventory",0,0}), |
| 847 | ({"inventur","_inventory",0,0}), |
| 848 | ({"schau","_look",0,0}), |
| 849 | ({"schaue","_look",0,0}), |
| 850 | ({"unt","_examine",0,0}), |
| 851 | ({"untersuch","_examine",0,0}), |
| 852 | ({"betracht","_examine",0,0}), |
| 853 | ({"untersuche","_examine",0,0}), |
| 854 | ({"betrachte","_examine",0,0}), |
| 855 | ({"betr","_examine",0,0}), |
Zesstra | 55f94fe | 2018-11-14 23:16:01 +0100 | [diff] [blame] | 856 | ({"lausche","_examine",0,0}), |
| 857 | ({"lausch","_examine",0,0}), |
| 858 | ({"hoer","_examine",0,0}), |
| 859 | ({"hoere","_examine",0,0}), |
| 860 | ({"lies","_examine",0,0}), |
| 861 | ({"lese","_examine",0,0}), |
| 862 | ({"les","_examine",0,0}), |
| 863 | ({"schnupper","_examine",0,0}), |
| 864 | ({"schnuppere","_examine",0,0}), |
| 865 | ({"riech","_examine",0,0}), |
| 866 | ({"rieche","_examine",0,0}), |
| 867 | ({"taste","_examine",0,0}), |
| 868 | ({"beruehre","_examine",0,0}), |
| 869 | ({"beruehr","_examine",0,0}), |
MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame] | 870 | ({"kurz","_toggle_brief",0,0}), |
| 871 | ({"lang","_toggle_brief",0,0}), |
| 872 | ({"ultrakurz","_toggle_brief",0,0}) |
| 873 | }); |
| 874 | } |