Funktion fuer Wechsel des SV-Objekts

Code zum Wechsel des Supervisors in Helferfunktion
ausgelagert zur Wiederverwendbarkeit.

Change-Id: Iedc559f5e1103c87913132e6b04d4277a0b80f4a
diff --git a/p/daemon/channeld.c b/p/daemon/channeld.c
index 92140df..3d4a7d6 100644
--- a/p/daemon/channeld.c
+++ b/p/daemon/channeld.c
@@ -612,10 +612,51 @@
   return 0;
 }
 
+
 #define CHAN_NAME(x) channels[x][I_NAME]
 #define SVISOR_OB(x) channels[x][I_SUPERVISOR]
 #define ACC_CLOSURE(x) channels[x][I_ACCESS]
 
+// Aendert das Supervisor-Objekt einer Ebene, ggf. mit Meldung.
+// Wenn kein neuer SV angegeben, wird der aelteste Zuhoerer gewaehlt.
+private int change_sv_object(string ch, object old_sv, object new_sv)
+{
+  if (!new_sv)
+  {
+    channels[ch][I_MEMBER] -= ({0});
+    if (sizeof(channels[ch][I_MEMBER]))
+      new_sv = channels[ch][I_MEMBER][0];
+    else
+      return 0; // kein neuer SV moeglich.
+  }
+  SVISOR_OB(ch) = new_sv;
+  if (old_sv && new_sv
+      && !old_sv->QueryProp(P_INVIS)
+      && !new_sv->QueryProp(P_INVIS))
+  {
+    // Die Zugriffskontrolle auf die Ebenen wird von der Funktion access()
+    // erledigt. Weil sowohl externe Aufrufe aus dem Spielerobjekt, als auch
+    // interne Aufrufe aus diesem Objekt vorkommen koennen, wird hier ein
+    // explizites call_other() auf this_object() gemacht, damit der
+    // Caller-Stack bei dem internen Aufruf denselben Aufbau hat wie bei
+    // einem externen.
+    this_object()->send(ch, old_sv,
+        sprintf("uebergibt die Ebene an %s.",new_sv->name(WEN)),
+        MSG_EMOTE);
+  }
+  else if (old_svn && !old_sv->QueryProp(P_INVIS))
+  {
+    this_object()->send(ch, old_sv,
+        "uebergibt die Ebene an jemand anderen.", MSG_EMOTE);
+  }
+  else if (new_sv && !new_sv->QueryProp(P_INVIS))
+  {
+    this_object()->send(ch, new_sv,
+        "uebernimmt die Ebene von jemand anderem.", MSG_EMOTE);
+  }
+  return 1;
+}
+
 // Stellt sicher, dass einen Ebenen-Supervisor gibt. Wenn dies nicht moeglich
 // ist (z.b. leere Ebene), dann wird die Ebene geloescht und 0
 // zurueckgegeben. Allerdings kann nach dieser Funktion sehr wohl die I_ACCESS
@@ -859,22 +900,16 @@
   // Erstmal den Zuhoerer raus.
   channels[ch][I_MEMBER] -= ({pl});
 
-  // Kontrolle an jemand anderen uebergeben, wenn der Ebenenbesitzer diese
-  // verlaesst.
-  if (pl == channels[ch][I_SUPERVISOR] && sizeof(channels[ch][I_MEMBER]))
+  // Wenn auf der Ebene jetzt noch Objekte zuhoeren, muss ggf. der SV
+  // wechseln.
+  if (sizeof(channels[ch][I_MEMBER]))
   {
-    channels[ch][I_SUPERVISOR] = channels[ch][I_MEMBER][0];
-
-    if (!pl->QueryProp(P_INVIS))
+    // Kontrolle an jemand anderen uebergeben, wenn der Ebenensupervisor
+    // diese verlassen hat. change_sv_object() waehlt per Default den
+    // aeltesten Zuhoerer.
+    if (pl == channels[ch][I_SUPERVISOR])
     {
-      // Die Zugriffskontrolle auf die Ebenen wird von der Funktion access()
-      // erledigt. Weil sowohl externe Aufrufe aus dem Spielerobjekt, als auch
-      // interne Aufrufe aus diesem Objekt vorkommen koennen, wird hier ein
-      // explizites call_other() auf this_object() gemacht, damit der
-      // Caller-Stack bei dem internen Aufruf denselben Aufbau hat wie bei
-      // einem externen.
-      this_object()->send(ch, pl, "uebergibt die Ebene an " +
-        channels[ch][I_SUPERVISOR]->name(WEN) + ".", MSG_EMOTE);
+      change_sv_object(ch, pl, 0);
     }
   }