Klingeltoene staerker konfigurierbar gemacht

Change-Id: Id83a543bc5e984ce7b44b602b734b72ae676e624
diff --git a/doc/pcmd/klingelton b/doc/pcmd/klingelton
index f855d2e..427d933 100644
--- a/doc/pcmd/klingelton
+++ b/doc/pcmd/klingelton
@@ -1,23 +1,41 @@
-KOMMANDO:
-	klingelton aus
-        klingelton 1..3600 
+KLINGELTON
+==========
 
-ARGUMENTE:
-                  : aktuellen Status anzeigen  
-	  1..3600 : Klingelton maximal aller n Sekunden 
-	  AUS     : Klingelton ausschalten.
+KOMMANDO
+--------
 
-BESCHREIBUNG:
-        Um Mitteilungen im Scroll nicht zu verpassen, wird bei eingeschaltetem
-        Klingelton in den voreingestellten Zeitintervallen ein Tonsignal vom
-        Mud erzeugt. Das ist besonders fuer blinde Spieler von Vorteil, denen
-        sonst Mitteilungen schnell mal verloren gehen.
-        Der Ton wird nur produziert, wenn man mit 'ton ein' die Tonausgabe
-        des Muds aktiviert hat.
-        Mitteilungen sind in diesem Zusammenhang 'sag' und 'teile mit'.
+  klingelton aus
+  klingelton <1..3600>
+  klingelton <+/-><tm / sag / ebenen / ruf / alle>
+
+ARGUMENTE
+---------
+
+  - Kein Argument
+    aktuellen Status anzeigen  
+  - 1..3600
+    Klingelton maximal aller n Sekunden 
+  - AUS
+    Klingelton ausschalten.
+  - <+/-><tm / sag / ebenen / ruf / alle>
+    Konfigurieren, fuer welche Art von Mitteilungen man Klingeltoene hoeren
+    moechte, es koennen auch mehrere gleichzeitig uebergeben werden,
+    z.B. "klingelton +tm -sag"
+
+BESCHREIBUNG
+------------
+
+  Um Mitteilungen im Scroll nicht zu verpassen, wird bei eingeschaltetem
+  Klingelton in den voreingestellten Zeitintervallen ein Tonsignal vom Mud
+  erzeugt, wenn eine Mitteilung aus den aktivierten Kategorien eingeht. Das
+  ist besonders fuer blinde Spieler von Vorteil, denen sonst Mitteilungen
+  schnell mal verloren gehen.
+  Der Ton wird nur produziert, wenn man mit 'ton ein' die Tonausgabe
+  des Muds aktiviert hat.
  
-SIEHE AUCH:
-	teile mit, sag, klingelton, grafik aus, ton, keepalive
+SIEHE AUCH
+----------
 
-LETZTE AENDERUNG:
-   16. Mai 2007  Ennox
+  teile mit, sag, grafik, ton, tmhist
+
+LETZTE AENDERUNG: 21.01.2022, Bugfix
diff --git a/doc/sphinx/props/P_ALERT.rst b/doc/sphinx/props/P_ALERT.rst
index 6be860a..b9ec630 100644
--- a/doc/sphinx/props/P_ALERT.rst
+++ b/doc/sphinx/props/P_ALERT.rst
@@ -23,6 +23,12 @@
   Aktuell gibt es folgende Moeglichkeiten:
   - AL_NO_SOUND
     Keine Pieptoene empfangen
+  - MB_SAY
+    Alert bei Messages mit MA_SAY
+  - MB_TELL
+    Alert bei Messages mit MA_TELL (tm)
+  - MB_CHANNEL
+    Alert bei Ebenennachrichten.
 
 BEMERKUNGEN
 -----------
diff --git a/std/player/comm.c b/std/player/comm.c
index dc447b7..716f0af 100644
--- a/std/player/comm.c
+++ b/std/player/comm.c
@@ -532,12 +532,20 @@
      (name == ignore[0] && member(ignore[1..], verb) != -1));
 }
 
-private int comm_beep() {
+private int comm_beep(string msg_action)
+{
   if (QueryProp(P_ALERT) & AL_NO_SOUND) return 0; // kein ton
   int beep_interval=({int})QueryProp(P_MESSAGE_BEEP);
-  if (!beep_interval || ((time()-last_beep_time) < beep_interval)) return 0;
-  last_beep_time=time();
-  return 1;
+  if(beep_interval && ((time()-last_beep_time) > beep_interval) &&
+    ((msg_action == MA_TELL && QueryProp(P_ALERT) & MB_TELL) ||
+    (msg_action == MA_SAY && QueryProp(P_ALERT) & MB_SAY) ||
+    (msg_action == MA_CHANNEL && QueryProp(P_ALERT) & MB_CHANNEL) ||
+    (msg_action == MA_SHOUT && QueryProp(P_ALERT) & MB_SHOUT)))
+  {
+    last_beep_time=time();
+    return 1;
+  }
+  return 0;
 }
 
 private varargs void add_to_tell_history( string uid, int sent, int recv,
@@ -909,7 +917,12 @@
   if(te && QueryProp(P_AWAY))
     msg = msg[0..<2]+" [" + strftime("%H:%M",time()) + "]\n";
 
-  if (flag & (MSGFLAG_SAY | MSGFLAG_TELL) && comm_beep()) {
+  if((!objectp(sender) || sender != ME) &&
+    ((flag & MSGFLAG_SAY) && comm_beep(MA_SAY) ||
+    (flag & MSGFLAG_TELL) && comm_beep(MA_TELL) ||
+    (flag & MSGFLAG_CHANNEL) && comm_beep(MA_CHANNEL) ||
+    (flag & MSGFLAG_SHOUT) && comm_beep(MA_SHOUT)))
+  {
     msg=MESSAGE_BEEP+msg;
   }
   efun::tell_object(ME, msg);
@@ -961,21 +974,71 @@
 }
 
 
+private int filter_flags(int flag, string text)
+{
+  return (flag & QueryProp(P_ALERT));
+}
+
 static int _msg_beep(string str) {
-  int beep_interval;
-  notify_fail("Syntax: klingelton <1 bis 3600 Sekunden> oder klingelton aus\n");
-  if (stringp(str)) {
+  int beep_interval = to_int(str);
+  if(beep_interval > 0)
+  {
+    SetProp(P_MESSAGE_BEEP,beep_interval);
+  }
+  else if (stringp(str))
+  {
+    notify_fail(
+      "Syntax:\n"
+      "- klingelton <1 bis 3600 Sekunden>\n"
+      "- klingelton aus\n"
+      "- klingelton <+/-><tm / sag / ebenen / ruf / alle>\n");
     if (str=="aus")
       SetProp(P_MESSAGE_BEEP,0);
-    else if ((beep_interval=to_int(str)) > 0 && beep_interval<=3600)
-      SetProp(P_MESSAGE_BEEP,beep_interval);
-    else return 0;
+    else
+    {
+      mapping flags = ([
+        "tm": MB_TELL,
+        "teilemit": MB_TELL,
+        "sag": MB_SAY,
+        "sage": MB_SAY,
+        "ebene": MB_CHANNEL,
+        "ebenen": MB_CHANNEL,
+        "ruf": MB_SHOUT,
+        "rufe": MB_SHOUT,
+        "alle": MB_ALL]);
+      foreach(string part : explode(str, " ") - ({""}))
+      {
+        if(!(part[1..] in flags)) continue;
+        if(part[0] == '+')
+        {
+          SetProp(P_ALERT,
+            QueryProp(P_ALERT) | flags[part[1..]]);
+        }
+        else if(part[0] == '-')
+        {
+          SetProp(P_ALERT,
+            QueryProp(P_ALERT) & ~ flags[part[1..]]);
+        }
+      }
+    }
   }
 
   beep_interval=({int})QueryProp(P_MESSAGE_BEEP);
-  ReceiveNotify("Ton bei Mitteilungen: "+
-        (beep_interval ? "aller "+beep_interval+" Sekunden." : "aus."),
-        query_verb());
+  mapping text = ([
+    MB_SAY: "sage",
+    MB_TELL: "teile mit",
+    MB_CHANNEL: "Ebenenmeldungen",
+    MB_SHOUT: "rufe"]);
+  string types = CountUp(map(filter(m_indices(text), #'filter_flags), text));
+  if(!sizeof(types))
+  {
+    types = "nichts";
+  }
+  ReceiveNotify(
+    "Klingelton bei "
+    + types
+    + (beep_interval ? ", alle " + beep_interval + " Sekunden." : ", nie."),
+    query_verb());
   return 1;
 }
 
@@ -1928,14 +1991,10 @@
       // entleeren.
       _flush_cache(0);
     }
-
-    // ggf. Piepston anhaengen. NACH Koboldablage, die sollen erstmal keinen
-    // Pieps kriegen.
-    if (comm_beep())
-      flags |= MSG_ALERT;
   }
 
-  if(flags & MSG_ALERT && !(QueryProp(P_ALERT) & AL_NO_SOUND))
+  if((flags & MSG_ALERT && !(QueryProp(P_ALERT) & AL_NO_SOUND)) ||
+    (interactive(origin) && origin != ME && comm_beep(msg_action)))
   {
     msg += MESSAGE_BEEP;
   }
diff --git a/sys/player/comm.h b/sys/player/comm.h
index 5459ecb..bbc01fb 100644
--- a/sys/player/comm.h
+++ b/sys/player/comm.h
@@ -31,6 +31,12 @@
 #define P_ALERT     "visualbell"
 #define AL_NO_SOUND 1
 // Bis 1024 (2^10) reserviert fuer allg. Einstellungen
+#define MB_TELL    2048
+#define MB_SAY     4096
+#define MB_CHANNEL 8192
+#define MB_SHOUT   16384
+// Flags < 1048576 (2^20) reserviert fuer Flags
+#define MB_ALL     (MB_SAY | MB_TELL | MB_CHANNEL | MB_SHOUT)
 
 // definitions for Message()