blob: 7fce3473b330198bf98f91361f180a852e7329c6 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001// MorgenGrauen MUDlib
2//
3// channel.c -- channel client
4//
5// $Id: channel.c 9404 2015-12-13 00:21:44Z Zesstra $
6#pragma strong_types
7#pragma save_types
8#pragma range_check
9#pragma no_clone
10#pragma pedantic
11
12#define NEED_PROTOTYPES
13#include <util.h>
14#include <thing/properties.h>
15#include <living/comm.h>
16#include <player.h>
17#include <player/comm.h>
18#include <daemon.h>
19#include <player/gmcp.h>
20#undef NEED_PROTOTYPES
21
22#include <wizlevels.h>
23#include <defines.h>
24#include <properties.h>
25#include <sys_debug.h>
26#include <regexp.h>
27
28#define P_SWAP_CHANNELS "swap_channels"
29#define P_CHANNEL_SHORT "short_channels"
30
31#define CHANNELCMDS "[#@%$&()<>a-zA-Z0-9\\-]"
32
33#define DEFAULT_CHANNELS ({"Abenteuer", "Anfaenger","Grats","Tod", "ZT"})
34#define DEFAULT_SHORTCUTS \
35([ \
36 "b":"Abenteuer", \
37 "a":"Allgemein", \
38 "B":"Beileid", \
39 "q":"D-chat", \
40 "G":"Grats", \
41 "M":"Moerder", \
42 "h":"Seher", \
43 "T":"Tod", \
44])
45
46#define WIZARD_SHORTCUTS \
47([ \
48 "P":"D-code", \
49 "D":"Debug", \
50 "O":"Intercode", \
51 "I":"Intermud", \
52 "m":"Magier", \
53])
54
55
56private nosave mapping shortcut;
57private nosave int c_status;
58
59void create()
60{
61 Set(P_CHANNELS, SAVE, F_MODE);
62 Set(P_CHANNELS, DEFAULT_CHANNELS);
63 Set(P_SWAP_CHANNELS, SAVE, F_MODE);
64 Set(P_STD_CHANNEL, "Allgemein");
65 Set(P_STD_CHANNEL, SAVE, F_MODE);
66 Set(P_CHANNEL_SHORT, SAVE, F_MODE);
67 Set(P_CHANNEL_SHORT, DEFAULT_SHORTCUTS
68 + (IS_LEARNER(this_object()) ? WIZARD_SHORTCUTS : ([])));
69}
70
71static mixed _query_localcmds()
72{
73 return ({({"-","ChannelParser", 1, 0}),
74 ({"ebene", "ChannelAdmin", 0, 0}),
75 ({"ebenen", "ChannelAdmin", 1, 0}),
76 });
77}
78
79mixed RegisterChannels()
80{
81 mixed err;
82 if(extern_call() &&
83 previous_object() != find_object(CHMASTER)) return;
84 c_status = 0;
85 shortcut = QueryProp(P_CHANNEL_SHORT);
86 SetProp(P_CHANNELS, map(QueryProp(P_CHANNELS) || ({}),
Zesstra57a693e2019-01-06 22:08:24 +010087 #'lower_case));
MG Mud User88f12472016-06-24 23:31:02 +020088 err = filter(QueryProp(P_CHANNELS),
89 symbol_function("join", CHMASTER),
90 this_object());
91 if(QueryProp(P_LEVEL) < 5) return err;
92 while(sizeof(err)) {
93 CHMASTER->new(err[0], this_object());
94 err[0..0] = ({});
95 }
96 return err;
97}
98
99mixed RemoveChannels()
100{
101 closure cl;
102 mixed err=({});
103 if(extern_call() &&
104 previous_object() != find_object(CHMASTER)) return;
105 if(!c_status) c_status = 1;
106 else return ({});
107 cl=symbol_function("leave", CHMASTER);
108 if (closurep(cl)) {
109 err = filter(QueryProp(P_CHANNELS), cl, this_object());
110 SetProp(P_CHANNELS, QueryProp(P_CHANNELS) - err);
111 }
112 return err;
113}
114
115varargs private string getName(mixed x, int fall) {
116
117 mixed o = closurep(x) ? query_closure_object(x) : x;
118 if(stringp(o) && sizeof(o) && (x = find_object(o)))
119 o = x;
120
121 // Objekte
122 if (objectp(o)) {
123 // Magier sehen unsichtbare nicht nur als "Jemand"
124 if (o->QueryProp(P_INVIS) && IS_LEARNING(this_object()))
125 return "("+capitalize(getuid(o))+")";
126 // Froesche mit Namen versorgen.
127 if (o->QueryProp(P_FROG))
128 return "Frosch "+capitalize(getuid(o));
129 // Default (Unsichtbare als "Jemand" (s. Name()))
130 return o->Name(fall, 2)||"<Unbekannt>";
131 }
132 // Strings
133 else if (stringp(o) && sizeof(o)) {
134 if (o[0] == '/') {
135 // unsichtbare Objekte...
136 int p = strstr(o, "$");
137 if (p != -1) {
Zesstra57a693e2019-01-06 22:08:24 +0100138 // Magier im Magiermodus kriegen den Realnamen, andere nicht.
139 if (IS_LEARNING(this_object()))
140 return o[1..p-1];
141 else
142 return o[p+1..];
MG Mud User88f12472016-06-24 23:31:02 +0200143 }
144 else
Zesstra57a693e2019-01-06 22:08:24 +0100145 // doch nicht unsichtbar
146 return (fall == WESSEN ? o+"s" : o);
MG Mud User88f12472016-06-24 23:31:02 +0200147 }
148 else
149 // nicht unsichtbar
150 return (fall == WESSEN ? o+"s" : o);
151 }
152 // Fall-through
153 return "<Unbekannt>";
154}
155
156// <nonint> unterdrueckt die AUsgabe an den Spieler und liefert den Text
157// zurueck. Wird nur fuer die Ebenenhistory benutzt.
158string ChannelMessage(mixed* msg, int nonint)
159{
160 string channel_message;
161 string channel=msg[0];
162 object sender=msg[1];
163 string message=msg[2];
164 int msg_type = msg[3];
165
166 if ( previous_object() != find_object(CHMASTER) &&
167 previous_object() != ME )
168 return 0;
169
170 string sender_name = getName(sender, msg_type == MSG_GEMOTE ? WESSEN : WER);
171 int prepend_indent_flag=QueryProp(P_MESSAGE_PREPEND) ? BS_PREPEND_INDENT : 0;
172 switch(msg_type) {
173 case MSG_EMPTY:
174 channel_message= message+"\n";
175 break;
176 case MSG_GEMOTE:
177 case MSG_EMOTE:
178 channel_message = break_string(sender_name + " "+ message+"]",
179 78, sprintf("[%s:", channel),
180 BS_INDENT_ONCE|prepend_indent_flag);
181 break;
182 case MSG_SAY:
183 default:
184 string presay=sprintf("[%s:%s] ", channel, sender_name);
185 channel_message = break_string(message, max(78,sizeof(presay)+10),
186 presay, prepend_indent_flag);
187 break;
188 }
189 if(nonint)
190 return channel_message;
191
192 // Wenn GMCP sich um Uebertragung der Nachricht kuemmert, wird ReceiveMsg()
Zesstra7ccec732019-01-06 22:10:09 +0100193 // nicht mehr aufgerufen. getName leider nochmal aufrufen, weil GMCP den
194 // Namen im Nominativ braucht.
195 if (msg_type == MSG_GEMOTE)
196 sender_name = getName(sender, WER);
MG Mud User88f12472016-06-24 23:31:02 +0200197 if (GMCP_Channel(channel_message, channel, sender_name) != 1)
198 {
199 // Der Ebenenname muss in Kleinbuchstaben uebergeben werden, damit die
200 // Ignorierepruefung funktioniert. Die ignorierestrings sind naemlich alle
201 // kleingeschrieben.
202 ReceiveMsg(channel_message,
203 MT_COMM|MT_FAR|MSG_DONT_STORE|MSG_DONT_WRAP,
204 MA_CHANNEL"." + lower_case(channel), 0, sender);
205 }
206 return 0;
207}
208
209private void createList(string n, mixed a, mixed m, mixed l)
210{
211 int pos; string sh, *mem;
212 if((pos = member(map(m_values(shortcut), #'lower_case/*'*/), n)) != -1)
213 sh = m_indices(shortcut)[pos];
214 else sh = "";
215 mem=map(a[I_MEMBER],#'getName/*'*/, WER);
216 mem-=({"<MasteR>"});
217 l += ({ sprintf("%-12.12'.'s %c[%-1.1s] %|12.12' 's (%-|3' 'd) %-42.42s\n",
218 a[I_NAME], (member(m, n) != -1 ? '*' : ' '), sh,
219 a[I_MASTER] ?
220 getName(a[I_MASTER]) : getName(a[I_ACCESS]),
221 sizeof(mem),
222 (closurep(a[I_INFO]) && objectp(query_closure_object(a[I_INFO]))) ?
223 funcall(a[I_INFO]) || "- Keine Beschreibung -" :
224 (stringp(a[I_INFO]) ? a[I_INFO] : "- Keine Beschreibung -")
225 ) });
226}
227
228private mixed getChannel(string ch)
229{
230 mixed ff;
231 if(!sizeof(ch)) ch = QueryProp(P_STD_CHANNEL);
232 if(shortcut && shortcut[ch]) ch = shortcut[ch];
233 return CHMASTER->find(ch, this_object());
234}
235
236#ifndef DEBUG
237#define DEBUG(x) if (funcall(symbol_function('find_player),"zesstra"))\
238 tell_object(funcall(symbol_function('find_player),"zesstra"),\
Zesstra57a693e2019-01-06 22:08:24 +0100239 "MDBG: "+x+"\n")
MG Mud User88f12472016-06-24 23:31:02 +0200240#endif
241int ChannelParser(string args)
242{
243 mixed ch, cmd, tmp;
244 int pos, type, err;
245 string txt;
246 cmd = query_verb();
247 args = _unparsed_args();
248 notify_fail("Benutzung: -<Ebene>[ ]['|:|;]<Text>\n"
249 " -<Ebene>[+|-|?|!|*]\n"
250 " -?\n");
251 if(!cmd && !args) return 0;
252 if(!args) args = "";
253 cmd = cmd[1..];
254 if(sizeof(cmd = regexplode(cmd,
255 "^" CHANNELCMDS "*"
256 "([+-]|\\!|\\?|\\*)*")) > 1)
257 {
258 //z.B. cmd= ({"","allgemein",":testet"})
259 if(sizeof(cmd[1]) > 1 &&
260 strstr("+-?!*", cmd[1][<1..<1]) > -1)
261 tmp = cmd[1][0..<2];
262 else
263 tmp = cmd[1];
264 if(cmd[1] != "?" && cmd[1] != "!")
Zesstra57a693e2019-01-06 22:08:24 +0100265 {
266 ch = getChannel(tmp);
267 if(pointerp(ch))
MG Mud User88f12472016-06-24 23:31:02 +0200268 {
269 notify_fail("Diese Angabe war nicht eindeutig! "
270 "Folgende Ebenen passen:\n"
271 +implode(ch, ", ")+"\n");
272 return 0;
273 }
Zesstra57a693e2019-01-06 22:08:24 +0100274 else if(!ch)
275 return (notify_fail("Die Ebene '"+tmp
276 + "' gibt es nicht!\n"), 0);
277 }
MG Mud User88f12472016-06-24 23:31:02 +0200278 //DEBUG(sprintf("ChanCmd: %O\n",cmd));
279 if (sizeof(cmd[1])) {
280 switch(cmd[1][<1]) {
281 case '+':
282 switch(CHMASTER->join(ch, this_object()))
283 {
284 case E_ACCESS_DENIED:
285 notify_fail("Du darfst an die Ebene '"+ch+"' nicht heran.\n");
286 return 0;
287 case E_ALREADY_JOINED:
288 notify_fail("Du hast diese Ebene schon betreten!\n");
289 return 0;
290 default: break;
291 }
292 write("Du betrittst die Ebene '"+ch+"'.\n");
293 if(member(QueryProp(P_CHANNELS), ch = lower_case(ch)) == -1)
294 SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({ ch }));
295 return 1;
296 case '-':
297 switch(CHMASTER->leave(ch, this_object()))
298 {
299 case E_ACCESS_DENIED:
300 write("Du kannst die Ebene '"+ch+"' nicht verlassen.\n");
301 break;
302 case E_NOT_MEMBER:
303 write("Wie willst Du eine Ebene verlassen, welche Du nicht "
304 "betreten hast?\n");
305 break;
306 default:
307 write("Du verlaesst die Ebene '"+ch+"'.\n");
308 SetProp(P_CHANNELS, QueryProp(P_CHANNELS) - ({ lower_case(ch), ch }));
309 break;
310 }
311 return 1;
312 case '!':
313 case '?':
314 {
315 mapping l;
316 if(mappingp(l = CHMASTER->list(this_object())))
Zesstra57a693e2019-01-06 22:08:24 +0100317 {
MG Mud User88f12472016-06-24 23:31:02 +0200318 if(stringp(ch) && sizeof(ch) && pointerp(l[ch = lower_case(ch)]))
319 {
320 int c; object o; string n; string *m;
321 m=sort_array(map(l[ch][I_MEMBER],#'getName/*'*/, WER),#'>/*'*/);
322 m-=({"<MasteR>"});
323 write(l[ch][I_NAME]+", "+funcall(l[ch][I_INFO])+".\n");
324 write("Du siehst "+((c = sizeof(m)) > 0
325 ? (c == 1 ? "ein Gesicht" : c+" Gesichter")
326 : "niemanden")+" auf der Ebene '"
327 +l[ch][I_NAME]+"':\n");
328 write(break_string(implode(m,", "), 78));
329 write((l[ch][I_MASTER] ?
330 getName(l[ch][I_MASTER]) : getName(l[ch][I_ACCESS], WER))
331 +" hat das Sagen auf dieser Ebene.\n");
332 }
333 else
334 {
335 mixed list; list = ({});
336 if(cmd[1][<1] == '!')
337 l -= mkmapping(m_indices(l) - QueryProp(P_CHANNELS));
338 walk_mapping(l, #'createList/*'*/, QueryProp(P_CHANNELS), &list);
339 list = sort_array(list, #'>/*'*/);
340 txt = sprintf("%-12.12' 's [A] %|12' 's (%-3' 's) %-42.42s\n",
341 "Name", "Eigner", "Sp", "Beschreibung")
342 + "-------------------------------------------------------"
343 + "-----------------------\n"
344 + implode(list, "");
345 More(txt);
346 }
Zesstra57a693e2019-01-06 22:08:24 +0100347 }
MG Mud User88f12472016-06-24 23:31:02 +0200348 return 1;
Zesstra57a693e2019-01-06 22:08:24 +0100349
MG Mud User88f12472016-06-24 23:31:02 +0200350 }
351 case '*':
352 {
353 mixed hist; int amount;
354 if(!pointerp(hist = CHMASTER->history(ch, this_object()))
Zesstra57a693e2019-01-06 22:08:24 +0100355 || !sizeof(hist))
MG Mud User88f12472016-06-24 23:31:02 +0200356 {
357 write("Es ist keine Geschichte fuer '"+ch+"' verfuegbar.\n");
358 return 1;
359 }
360
361 //(Zesstra) cmd hat offenbar immer 3 Elemente...
362 //bei -all* ({"","all*",""})
363 //bei -all*10 ({"","all*,"10"})
364 //also ist bei -all* amount immer == 0 und es funktioniert eher zufaellig.
365 /*if(sizeof(cmd) > 2)
366 amount = to_int(cmd[2]);
367 else
368 amount=sizeof(hist);*/
369 amount=to_int(cmd[2]);
370 if (amount <= 0 || amount >= sizeof(hist))
371 amount=sizeof(hist);
372
373 txt = "Folgendes ist auf '"+ch+"' passiert:\n"
374 + implode(map(hist[<amount..], #'ChannelMessage/*'*/, 1), "");
375 More(txt);
376 return 1;
377 }
378 default:
379 break;
380 }
381 }
382 }
383 if(sizeof(cmd = implode(cmd[2..], "")))
384 args = cmd + (sizeof(args) ? " " : "") + args;
385
386 // KOntrollchars ausfiltern.
387 args = regreplace(args,"[[:cntrl:]]","",RE_PCRE|RE_GLOBAL);
388 if(!sizeof(args)) return 0;
389
390 //Wenn cmd leer ist: MSG_SAY
391 if (!sizeof(cmd)) type=MSG_SAY;
392 else {
393 switch(cmd[0])
394 {
395 case ':' :
396 type = MSG_EMOTE;
397 args = args[1..];
398 break;
399 case ';' :
400 type = MSG_GEMOTE;
401 args = args[1..];
402 break;
403 case '\'':
404 args = args[1..];
405 default : type = MSG_SAY; break;
406 }
407 }
408 if(!ch || !sizeof(ch)) ch = QueryProp(P_STD_CHANNEL);
409 if((err = CHMASTER->send(ch, this_object(), args, type)) < 0)
410 if(!(err = CHMASTER->join(ch, this_object())))
411 {
412 if(member(QueryProp(P_CHANNELS), ch = lower_case(ch)) == -1)
413 SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({ ch }));
414 err = CHMASTER->send(ch, this_object(), args, type);
415 }
416
417 switch(err)
418 {
419 case E_ACCESS_DENIED:
420 notify_fail("Auf der Ebene '"+ch+"' darfst Du nichts sagen.\n");
421 return 0;
422 case E_NOT_MEMBER:
423 notify_fail("Du hast die Ebene '"+ch+"' nicht betreten!\n");
424 return 0;
425 }
426 return 1;
427}
428
429int ChannelAdmin(string args)
430{
431 string n, descr, sh, cn;
432 mixed pa, tmp;
433 args = _unparsed_args();
434 notify_fail("Benutzung: ebene <Abkuerzung>=<Ebene>\n"
435 " ebene <Abkuerzung>=\n"
436 " ebene abkuerzungen [standard]\n"
437 " ebene standard <Ebene>\n"
438 " ebene an|ein|aus\n"
439 +(QueryProp(P_LEVEL) >= 5 ?
440 " ebene neu <Name> <Bezeichnung>\n"
441 " ebene beschreibung <Name> <Beschreibung>\n" : "")
442 +(IS_ARCH(this_object()) ?
443 " ebene kill <Name>\n"
Zesstra57a693e2019-01-06 22:08:24 +0100444 " ebene clear <Name>\n": ""));
MG Mud User88f12472016-06-24 23:31:02 +0200445 if(!args || !sizeof(args)) return 0;
446 if(sscanf(args, "kill %s", n) && IS_ARCH(this_object()))
447 {
448 if(!(cn = CHMASTER->find(n, this_object()))) cn = n;
449 switch(CHMASTER->remove(cn, this_object()))
450 {
451 case E_ACCESS_DENIED:
452 notify_fail("Die Ebene '"+cn+"' lies sich nicht entfernen!\n");
453 return 0;
454 }
455 write("Du entfernst die Ebene '"+cn+"'.\n");
456 return 1;
457 }
458 if(sscanf(args, "clear %s", n) && IS_ARCH(this_object()))
459 {
460 if(!(cn = CHMASTER->find(n, this_object()))) cn = n;
461 switch(CHMASTER->clear_history(cn, this_object()))
462 {
463 case E_ACCESS_DENIED:
464 notify_fail("Der Verlauf zur Ebene '"+cn+"' lies sich nicht entfernen!\n");
465 return 0;
466 }
467 write("Du entfernst den Verlauf zur Ebene '"+cn+"'.\n");
468 return 1;
469 }
470 if(sscanf(args, "neu %s %s", n, descr) == 2)
471 {
472 mixed x;
473 if(QueryProp(P_LEVEL) < 5)
474 return (notify_fail("Neue Ebenen zu erstellen ist dir verwehrt.\n"), 0);
475 if(!sizeof(regexp(({ n }), "^" CHANNELCMDS CHANNELCMDS "*")))
476 return (notify_fail("Der Name '"+n+"' ist nicht konform!\n"), 0);
477 if (sizeof(n) > 20 )
478 return(notify_fail("Der Name '"+n+"' ist zu lang.\n"), 0);
479 switch(x = CHMASTER->new(n, this_object(), descr))
480 {
481 case E_ACCESS_DENIED:
482 notify_fail("Diese Ebene darfst du nicht erschaffen!\n"); break;
483 default:
484 write("Du erschaffst die Ebene '"+n+"'.\n");
485 SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({ lower_case(n) }));
486 return 1;
487 }
488 }
489 if(sscanf(args, "beschreibung %s %s", n, descr) == 2)
490 {
491 mixed ch;
492 cn = CHMASTER->find(n, this_object());
493 if(!cn || pointerp(cn))
494 return (notify_fail("Die Ebene '"+n+"' existiert nicht oder die Angabe "
495 "war nicht eindeutig.\n"), 0);
496 ch = CHMASTER->list(this_object());
497 if(ch[lower_case(cn)][I_MASTER] != this_object())
498 return (notify_fail("Du bist nicht berechtigt die Beschreibung der Ebene"
499 " '"+cn+"' zu aendern.\n"), 0);
500 ch[lower_case(cn)][I_INFO] = descr;
501 write("Die Ebene '"+cn+"' hat ab sofort die Beschreibung:\n"+descr+"\n");
502 return 1;
503 }
504 if(sscanf(args, "%s=%s", sh, n) == 2 && sizeof(n))
505 {
506 mapping sc;
507 if(pointerp(tmp = CHMASTER->find(n, this_object())) || !tmp)
508 return (notify_fail("Benutzung: ebene <Abkuerzung>=<Ebene>\n"
509 +(pointerp(tmp) ? implode(tmp, ", ") + "\n" :
510 "Ebene '"+n+"' nicht gefunden!\n")), 0);
511 sc = QueryProp(P_CHANNEL_SHORT);
512 if(!sc) sc = ([]);
513 sc[sh] = tmp;
514 SetProp(P_CHANNEL_SHORT, sc);
515 shortcut = QueryProp(P_CHANNEL_SHORT);
516 write("'"+sh+"' wird jetzt als Abkuerzung fuer '"+tmp+"' anerkannt.\n");
517 return 1;
518 }
519 if(sscanf(args, "%s=", sh))
520 {
521 SetProp(P_CHANNEL_SHORT, m_copy_delete(QueryProp(P_CHANNEL_SHORT) || ([]), sh));
522 shortcut = QueryProp(P_CHANNEL_SHORT);
523 write("Du loeschst die Abkuerzung '"+sh+"'.\n");
524 return 1;
525 }
526 if(args == "an" || args == "ein")
527 {
528 mixed excl;
529 if(pointerp(QueryProp(P_SWAP_CHANNELS)))
530 SetProp(P_CHANNELS, QueryProp(P_SWAP_CHANNELS));
531 else
532 SetProp(P_CHANNELS, m_indices(CHMASTER->list(this_object())));
533 excl = RegisterChannels();
534 write("Du schaltest folgende Ebenen ein:\n"
535 +break_string(implode(QueryProp(P_CHANNELS) - excl, ", "), 78));
536 SetProp(P_SWAP_CHANNELS, 0);
537 return 1;
538 }
539 if(args == "aus")
540 {
541 SetProp(P_SWAP_CHANNELS, QueryProp(P_CHANNELS));
542 RemoveChannels();
543 SetProp(P_CHANNELS, ({}));
544 write("Du stellst die Ebenen ab.\n");
545 return 1;
546 }
547 pa = old_explode(args, " ");
548 if(!strstr("abkuerzungen", pa[0]))
549 {
550 string txt; txt = "";
551 if(sizeof(pa) > 1 && !strstr("standard", pa[1]))
552 {
553 write("Die Standard Abkuerzungen werden gesetzt.\n");
554 SetProp(P_CHANNEL_SHORT, DEFAULT_SHORTCUTS
555 + (IS_LEARNER(this_object()) ? WIZARD_SHORTCUTS : ([])));
556 }
Arathorndc28afc2018-11-26 22:20:59 +0100557 foreach(string abk, string ch_name : QueryProp(P_CHANNEL_SHORT)) {
558 txt += sprintf("%5.5s = %s\n", abk, ch_name);
559 }
MG Mud User88f12472016-06-24 23:31:02 +0200560 txt = sprintf("Folgende Abkuerzungen sind definiert:\n%-78#s\n",
561 implode(sort_array(old_explode(txt, "\n"), #'>/*'*/), "\n"));
562 More(txt);
563 return 1;
564 }
565 if(!strstr("standard", pa[0]))
566 if(sizeof(pa) < 2)
567 return (notify_fail("Benutzung: ebene standard <Ebene>\n"
568 +(QueryProp(P_STD_CHANNEL)
569 ? "Momentan ist '"+QueryProp(P_STD_CHANNEL)
570 +"' eingestellt.\n"
571 : "Es ist keine Standardebene eingestellt.\n")),0);
572 else
573 if(pointerp(tmp = CHMASTER->find(pa[1], this_object())))
574 return (notify_fail("Das war keine eindeutige Angabe! "
575 "Folgende Ebenen passen:\n"
576 +break_string(implode(tmp, ", "), 78)), 0);
577 else
578 if(!tmp) return (notify_fail("Ebene '"+pa[1]+"' nicht gefunden!\n"),0);
579 else
580 {
581 write("'"+tmp+"' ist jetzt die Standardebene.\n");
582 SetProp(P_STD_CHANNEL, tmp);
583 return 1;
584 }
585 return(0);
586}
587