Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/std/living/team.c b/std/living/team.c
new file mode 100644
index 0000000..2b31db9
--- /dev/null
+++ b/std/living/team.c
@@ -0,0 +1,650 @@
+// MorgenGrauen MUDlib
+//
+// living/team.c
+//
+// $Id: team.c 9138 2015-02-03 21:46:56Z Zesstra $
+#pragma strong_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+
+#include <properties.h>
+#include <thing/properties.h>
+#include <living/combat.h>
+#include <combat.h>
+#include <living/team.h>
+#include <wizlevels.h>
+#include <hook.h>
+
+#define ME this_object()
+#define TP this_player()
+#define PO previous_object()
+#define ENV environment()
+
+private nosave string team_attack_cmd;
+private nosave mapping team_follow_todo;
+private nosave int team_autofollow;
+private nosave object teammove;
+
+void create() {
+  Set(P_TEAM_ATTACK_CMD,-1,F_SET_METHOD);
+  Set(P_TEAM_ATTACK_CMD,PROTECTED,F_MODE_AS);
+  Set(P_TEAM_AUTOFOLLOW,-1,F_SET_METHOD);
+  Set(P_TEAM_AUTOFOLLOW,PROTECTED,F_MODE_AS);
+  teammove=0;
+  offerHook(H_HOOK_TEAMROWCHANGE, 1);
+}
+
+void add_team_commands() {
+  add_action("teamcmd","gruppe");
+  add_action("teamcmd","g");
+  add_action("teamcmd","team");
+}
+
+string _query_team_attack_cmd() {
+  return Set(P_TEAM_ATTACK_CMD,team_attack_cmd);
+}
+
+int _query_team_autofollow() {
+  return Set(P_TEAM_AUTOFOLLOW,team_autofollow);
+}
+
+private int team_help() {
+  // Syntax-Kompatiblitaet (Avalon) ist ganz nett :-)
+  write("\
+(Befehle des Teamleiters sind mit * gekennzeichnet\n\
+\n\
+* team angriff\n\
+  team angriffsbefehl <befehl>\n\
+* team aufnahme <name>\n\
+  team autof[olge] <ein/aus>\n\
+* team autoi[nfo] <ein/aus> [+[lp]] [+[kp]] [sofort]\n\
+* team entlasse <name>\n\
+  team farben lp_rot lp_gelb kp_rot kp_gelb\n\
+  team flucht[reihe] <reihe>\n\
+  team folge <name>\n\
+* team formation <min[-max]> [<min[-max]> ...]\n\
+  team hilfe|?\n\
+  team [info] [sortiert|alphabetisch]\n\
+  team [kampf]reihe <reihe>\n\
+* team leiter[in] <name>\n\
+  team liste\n\
+* team name <gruppenname>\n\
+  team orte [alle]\n\
+  team ruf[e]\n\
+  team uebersicht\n\
+  team verlasse\n");
+  return 1;
+}
+
+object IsTeamLeader() {
+  object team;
+
+  if (!objectp(team=Query(P_TEAM))
+      || team!=Query(P_TEAM_LEADER)
+      || team->Leader()!=ME)
+    return 0;
+  return team;
+}
+
+object *TeamMembers() {
+  object team;
+
+  if (!objectp(team=Query(P_TEAM)))
+    return ({ME});
+  return team->Members();
+}
+
+string TeamPrefix() {
+  object team;
+
+  if (!objectp(team=Query(P_TEAM)))
+    return "";
+  return "["+team->Name()+"] ";
+}
+
+
+private int team_aufnahmewunsch(string arg) {
+  object pl;
+
+  if ((!objectp(pl=find_player(arg)) && !objectp(pl=present(arg,ENV)))
+      || pl->QueryProp(P_INVIS) || environment(pl)!=ENV)
+    return notify_fail(capitalize(arg)+" nicht gefunden.\n"),0;
+  if (!living(pl))
+    return notify_fail(pl->Name(WER)+" ist etwas zu inaktiv.\n"),0;
+  if (pl==ME)
+    return notify_fail("Du bist eine Person zu wenig fuer ein Team.\n"),0;
+  SetProp(P_TEAM_NEWMEMBER,pl);
+  if (pl->IsTeamLeader()) {
+    write("Du bittest "+pl->name(WEN)+" um Aufnahme ins Team.\n");
+    tell_object(pl,TP->Name(WER)+" bittet Dich um Aufnahme ins Team.\n");
+  } else {
+    write("Du bittest "+pl->name(WEN)+" um Gruendung eines Teams.\n");
+    tell_object(pl,TP->Name(WER)+" bittet Dich um Gruendung eines Teams.\n");
+  }
+  return 1;
+}
+
+private int team_aufnahme(string arg) {
+  object pl,team;
+  int res;
+
+  if ((!objectp(pl=find_player(arg)) && !objectp(pl=present(arg,ENV)))
+      || pl->QueryProp(P_INVIS) || environment(pl)!=ENV)
+    return notify_fail(capitalize(arg)+" nicht gefunden.\n"),0;
+  if (pl->QueryProp(P_TEAM_NEWMEMBER)!=ME)
+    return notify_fail(pl->Name(WER)+" hat Dich nicht um Aufnahme gebeten.\n"),
+      0;
+  if (pl==ME)
+    return notify_fail("Du bist eine Person zu wenig fuer ein Team.\n"),0;
+  if (!objectp(team=QueryProp(P_TEAM)))
+    team=clone_object(TEAM_OBJECT);
+  res=team->AddMember(pl);
+  if (!sizeof(team->Members()))
+    team->remove();
+  return res;
+}
+
+object IsTeamMove() {
+  if (!objectp(teammove) || (teammove!=Query(P_TEAM)))
+    teammove=0;
+  return teammove;
+}
+
+static void DoTeamAttack(object env, object callbackto) {
+  if (env==ENV && stringp(team_attack_cmd) && !IS_LEARNER(ME)
+      && (interactive(ME) || !query_once_interactive(ME))
+      && objectp(callbackto) && callbackto==Query(P_TEAM)) {
+    teammove=callbackto;
+    command(team_attack_cmd);
+  }
+  if (objectp(callbackto))
+    callbackto->TeamAttackExecuted_Callback(teammove?1:0);
+  teammove=0;
+}
+
+int CallTeamAttack(object env) {
+  if (stringp(team_attack_cmd)
+      && find_call_out("DoTeamAttack")<0
+      && PO
+      && PO==Query(P_TEAM))
+    return call_out("DoTeamAttack",0,env,PO),1;
+  return 0;
+}
+
+static int DoTeamFollow() {
+  string cmd;
+
+  if (!team_autofollow
+      || (!interactive(ME) && query_once_interactive(ME))
+      || IS_LEARNER(ME)
+      || !mappingp(team_follow_todo))
+    return 0;
+  if (!stringp(cmd=team_follow_todo[ENV]))
+    return team_follow_todo=0;
+
+  do {
+    m_delete(team_follow_todo,ENV);
+    tell_object(ME,sprintf("Du folgst Deinem Team mit \"%s\".\n",cmd));
+    command(cmd);
+  } while (get_eval_cost()>900000 && random(1000)>20 && objectp(ME)
+           && stringp(cmd=team_follow_todo[ENV]));
+
+  // Ist Spieler in Umgebung gelandet, fuer die noch ein
+  // Befehl auszufuehren ist?
+  if (!objectp(ME) || !stringp(team_follow_todo[ENV]))
+    return team_follow_todo=0;
+  while  (remove_call_out("DoTeamFollow")!=-1) ;
+  call_out("DoTeamFollow",0);
+  return 0;
+}
+
+int CallTeamFollow(object env, string cmd) {
+  if (!team_autofollow
+      || PO!=Query(P_TEAM)
+      || !PO
+      || !objectp(env)
+      || !stringp(cmd))
+    return 0;
+  if (!mappingp(team_follow_todo))
+    team_follow_todo=([]);
+  if (ENV!=env && !team_follow_todo[ENV])
+    return 0;
+  team_follow_todo[env]=cmd;
+  if (find_call_out("DoTeamFollow")<0)
+    call_out("DoTeamFollow",0);
+  return 1;
+}
+
+int ClearTeamFollow() {
+  if (PO!=Query(P_TEAM) || !PO)
+    return 0;
+  team_follow_todo=([]);
+  return 1;
+}
+
+mixed *PresentTeamRows() {
+  object team;
+  mixed *res;
+  int i;
+
+  if (!objectp(team=Query(P_TEAM))) {
+    res=EMPTY_TEAMARRAY;
+    res[0]=({ME});
+    return res;
+  }
+  res=team->PresentRows(ENV);
+  for (i=0;i<MAX_TEAMROWS;i++)
+    if (member(res[i],ME)>=0)
+      return res;
+  res[0]+=({ME});
+  return res;
+}
+
+varargs mixed *PresentEnemyRows(object *here) {
+  mixed *res,*rows;
+  mapping added_teams;
+  int i,j;
+  object ob,team;
+
+  added_teams=([Query(P_TEAM):1]); // Nicht auf eigenes Team hauen
+  res=EMPTY_TEAMARRAY;
+  if (!pointerp(here))
+    here=PresentEnemies();
+  for (i=sizeof(here)-1;i>=0;i--) {
+    if (!objectp(ob=here[i]))
+      continue;
+    if (!objectp(team=ob->QueryProp(P_TEAM))) {
+      res[0]+=({ob});
+      continue;
+    }
+    if (added_teams[team])
+      continue;
+    added_teams[team]=1;
+    rows=team->PresentRows(ENV);
+    for (j=0;j<MAX_TEAMROWS;j++)
+      res[j]+=rows[j];
+  }
+  return res;
+}
+
+varargs object SelectNearEnemy(object *here, int forcefrom) {
+  object ob,en,team;
+  mixed *rows;
+  int *prob,prot,i,r,sz,upsz,sum;
+
+  if (!pointerp(here))
+    here=PresentEnemies();
+  if (!objectp(ob=SelectEnemy(here)))
+    return 0;
+  en=ob->QueryProp(P_TEAM);          // Feindliches Team
+  if (objectp(team=Query(P_TEAM))) { // Eigenes Team
+    if (en==team) // Feind im eigenen Team, kein ANDERES Mitglied waehlen.
+      return ob;  // Aber auch ausserhalb Reihe 1 draufhauen
+    rows=team->PresentRows(ENV);
+    if (member(rows[0],ME)<0) // Stehe ich in der ersten Reihe?
+      return 0; // Falls nein ist auch kein Gegner nahe.
+  }
+  if (!objectp(en))
+    return ob; // Ist nicht in einem Team, also drauf.
+  rows=en->PresentRows(environment(ob));
+  prob=({1,0,0,0,0});
+  prot=sum=0;
+  for (i=0;i<MAX_TEAMROWS;i++) {
+    if (prot>0) prot--;                // Schutzkegel nimmt ab.
+    if (!sz=sizeof(rows[i])) continue; // Gegner in dieser Reihe
+    upsz=sz-prot;if (upsz<0) continue; // Anzahl ungeschuetzter Gegner
+    prob[i]+=(upsz+sum);               // Wahrscheinlichkeit += ungeschuetzt
+    sum=prob[i];                       // Summe bisheriger Wahrscheinlichkeiten
+    if (sz>prot) prot=sz;              // Neuer Schutzkegel
+  }
+  r=random(sum);
+  for (i=0;i<MAX_TEAMROWS;i++)
+    if (r<prob[i])
+      break;
+  if (i>=MAX_TEAMROWS)
+    i=0;
+  if (objectp(en=SelectEnemy(forcefrom?(here&rows[i]):rows[i])))
+    return en;
+  if (i && objectp(en=SelectEnemy(forcefrom?(here&rows[0]):rows[0])))
+    return en;
+  return ob;
+}
+
+varargs object SelectFarEnemy(object *here, int min, int max, int forcefrom) {
+  mixed *rows;
+  int *prob,i,r,sum;
+  object en;
+
+  if (max<0 || min>=MAX_TEAMROWS || max<min)
+    return 0;
+  if (min<0) min=0;
+  if (max>=MAX_TEAMROWS) max=MAX_TEAMROWS-1;
+  if (!pointerp(here))
+    here=PresentEnemies();
+  rows=PresentEnemyRows(here);
+  prob=({0,0,0,0,0});
+  sum=0;
+  for (i=min;i<=max;i++)
+    sum=prob[i]=sum+sizeof(rows[i])+max-i;
+
+  r=random(sum);
+  for (i=min;i<=max;i++)
+    if (r<prob[i])
+      break;
+  if (i>max)
+    i=min;
+  if (objectp(en=SelectEnemy(forcefrom?(here&rows[i]):rows[i])))
+    return en;
+  for (i=min;i<=max;i++)
+    if (objectp(en=SelectEnemy(forcefrom?(here&rows[i]):rows[i])))
+      return en;
+  return 0;
+}
+
+mixed _query_friend() {
+  mixed res;
+
+  if (res=Query(P_FRIEND))
+    return res;
+  if (objectp(res=Query(P_TEAM_ASSOC_MEMBERS))
+      && query_once_interactive(res))
+    return res;
+  return 0;
+}
+
+int DeAssocMember(object npc) {
+  mixed obs;
+  object team;
+
+  if (extern_call() && PO!=npc &&
+      member(({"gilden","spellbooks"}),
+             explode(object_name(PO),"/")[1])<0)
+    return 0;
+  obs=QueryProp(P_TEAM_ASSOC_MEMBERS);
+  if (!pointerp(obs))
+    return 0;
+  obs-=({npc,0});
+  SetProp(P_TEAM_ASSOC_MEMBERS,obs);
+  if (objectp(team=QueryProp(P_TEAM)))
+    team->RemoveAssocMember(ME,npc);
+  return 1;
+}
+
+int AssocMember(object npc) {
+  mixed obs;
+  object team;
+
+  if (extern_call() && PO!=npc &&
+      member(({"gilden","spellbooks"}),
+             explode(object_name(PO),"/")[1])<0)
+    return 0;
+  if (!objectp(npc)
+      || npc->QueryProp(P_TEAM_ASSOC_MEMBERS)
+      || IsEnemy(npc)
+      || npc==ME
+      || query_once_interactive(npc))
+    return 0;
+  obs=QueryProp(P_TEAM_ASSOC_MEMBERS);
+  if (objectp(obs))
+    return 0;
+  if (!pointerp(obs))
+    obs=({});
+  obs=(obs-({npc,0}))+({npc});
+  SetProp(P_TEAM_ASSOC_MEMBERS,obs);
+  npc->SetProp(P_TEAM_ASSOC_MEMBERS,ME);
+  if (objectp(team=QueryProp(P_TEAM)))
+    team->AddAssocMember(ME,npc);
+  return 1;
+}
+
+varargs void InsertEnemyTeam(mixed ens, int rek) {
+  object *obs,ob,eteam,team;
+  int i;
+
+  team=Query(P_TEAM);
+  // Alle Teammitglieder des Gegners sind Feind:
+  if (objectp(ens)) {
+    if (objectp(eteam=ens->QueryProp(P_TEAM))) {
+      if (eteam==team) // feindliches Team = eigenes Team?
+        return;        // also nicht alle Teammitglieder gegeneinander hetzen
+      ens=eteam->Members();
+    } else {
+      ens=({ens});
+    }
+  }
+  if (!pointerp(ens))
+    return;
+  ens-=({ME});
+
+  // Interactives sollen keine Interactives durch Team angreifen:
+  if (query_once_interactive(ME)) {
+    for (i=sizeof(ens)-1;i>=0;i--)
+      if (objectp(ob=ens[i]) && environment(ob)==environment()
+          && !query_once_interactive(ob))
+        InsertSingleEnemy(ob);
+  } else {
+    for (i=sizeof(ens)-1;i>=0;i--)
+      if (objectp(ob=ens[i]) && environment(ob)==environment())
+        InsertSingleEnemy(ob);
+  }
+
+  // Alle anderen Teammitglieder Informieren:
+  if (rek || !objectp(team) || !pointerp(obs=team->Members()))
+    return;
+  obs-=({ME});
+  obs-=ens;
+  for (i=sizeof(obs)-1;i>=0;i--)
+    if (objectp(ob=obs[i]))
+      ob->InsertEnemyTeam(ens,1);
+}
+
+int TeamFlee() {
+  object team;
+
+  if (Query(P_TEAM_WIMPY_ROW)<2 || !objectp(team=Query(P_TEAM)))
+    return 0;
+  if (!team->FleeToRow(ME))
+     return 0;
+  if (Query(P_TEAM_LEADER)==team) {
+    if (team_autofollow)
+      tell_object(ME,"Du versuchst zu fliehen, "+
+                  "Dein Team folgt Dir nicht mehr.\n");
+    team_autofollow=0;
+  }
+  return 1;
+}
+
+varargs mapping PresentTeamPositions(mixed pres_rows) {
+  mapping res;
+  int i,j;
+  object *obs,ob;
+
+  res=([]);
+  if (!pointerp(pres_rows))
+    pres_rows=PresentTeamRows();
+  for (i=0;i<MAX_TEAMROWS;i++) {
+    obs=pres_rows[i];
+    for (j=sizeof(obs)-1;j>=0;j--)
+      if (objectp(ob=obs[j]) && !res[ob])
+        res[ob]=i+1;
+  }
+  return res;
+}
+
+varargs int PresentPosition(mixed pmap) {
+  object team;
+  int i;
+
+  if (!objectp(team=Query(P_TEAM)))
+    return 1;
+  if (mappingp(pmap))
+    return pmap[ME];
+  if (!pointerp(pmap))
+    pmap=team->PresentRows(ENV);
+  for (i=1;i<MAX_TEAMROWS;i++)
+    if (member(pmap[i],ME)>=0)
+      return i+1;
+  return 1;
+}
+
+#define FILLSTRING "                                        "
+varargs private string center_string(string str, int w) {
+  return (FILLSTRING[0..((w-sizeof(str))/2-1)]+str+FILLSTRING)[0..(w-1)];
+}
+
+private int ShowTeamRows() {
+  int i,j,sz;
+  mixed *pres_rows;
+  object *obs,ob;
+  string str;
+
+  pres_rows=PresentEnemyRows();
+  for (sz=MAX_TEAMROWS-1;sz>=0;sz--)
+    if (sizeof(pres_rows[sz]))
+      break;
+  for (i=sz;i>=0;i--) {
+    obs=pres_rows[i];str="";
+    for (j=sizeof(obs)-1;j>=0;j--)
+      if (objectp(ob=obs[j])) {
+        if (str!="") str+=" / ";
+        str+=ob->Name(RAW);
+      }
+    printf("%d. %s\n",i+1,center_string(str,75));
+  }
+  if (sz>=0)
+    write("   ---------------------------------------------------------------------------\n");
+  pres_rows=PresentTeamRows();
+  for (sz=MAX_TEAMROWS-1;sz>0;sz--)
+    if (sizeof(pres_rows[sz]))
+      break;
+  for (i=0;i<=sz;i++) {
+    obs=pres_rows[i];str="";
+    for (j=sizeof(obs)-1;j>=0;j--)
+      if (objectp(ob=obs[j])) {
+        if (str!="") str+=" / ";
+        str+=ob->Name(RAW);
+      }
+    printf("%d. %s\n",i+1,center_string(str,75));
+  }
+  return 1;
+}
+
+varargs int team_list(string arg) {
+  object *tobs,*obs,tob,ob,ld;
+  string *nms,*tnms,str;
+  int i,j;
+
+  if (!pointerp(tobs=TEAM_MASTER->ListTeamObjects())) return 0;
+  if (arg!="alle") arg=0;
+  tnms=({});
+  for (i=sizeof(tobs)-1;i>=0;i--) {
+    if (!objectp(tob=tobs[i])
+        || !objectp(ld=tob->Leader())
+        || (!query_once_interactive(ld) && !arg)
+        || !pointerp(obs=tob->Members()))
+      continue;
+    nms=({});
+    for (j=sizeof(obs)-1;j>=0;j--) {
+      if (!objectp(ob=obs[j])
+          || (!query_once_interactive(ob) &&!arg))
+        continue;
+      if (!stringp(str=ob->Name(WER))) str="?";
+      if (ob==ld) str+="(*)";
+      nms+=({str});
+      nms=sort_array(nms,#'>);
+    }
+    if (!stringp(str=tob->Name())) str="Team ?";
+    str+=": ";
+    tnms+=({break_string(implode(nms,", "),78,str)});
+    tnms=sort_array(tnms,#'<);
+  }
+  if (sizeof(tnms))
+    tell_object(ME, sprintf("%@s\n", tnms));
+  else
+    tell_object(ME, "Keine Teams gefunden.\n"); 
+  
+  return 1;
+}
+
+varargs int teamcmd(string arg) {
+  string *words,narg;
+  object team;
+
+  if (!arg)
+    arg="";
+  if (!stringp(narg=TP->_unparsed_args()))
+    narg = arg;
+  if (!sizeof(words=explode(arg," ")))
+    return 0;
+ 
+  if (sizeof(words) > 1) {
+      arg=implode(words[1..]," ");
+      narg = implode(explode(narg, " ")[1..], " ");
+  }
+  else
+      arg = narg = "";
+
+  switch(words[0]) { // Befehle die keine Mitgliedschaft erfordern:
+  case "aufnahme":
+    return team_aufnahme(arg);
+  case "folge":
+    return team_aufnahmewunsch(arg);
+  case "?":
+  case "hilfe":
+    return team_help();
+  case "liste":
+    return team_list(arg);  
+  case "uebersicht":
+    return ShowTeamRows();
+  default:;
+  }
+
+  if (!objectp(team=QueryProp(P_TEAM)))
+    return notify_fail("Du bist in keinem Team.\n"),0;
+
+  switch(words[0]) {
+  case "angriffsbefehl":
+    if (narg=="") narg=0;
+    team_attack_cmd=narg;
+    if (stringp(narg))
+      write("Du beginnst den Kampf mit \""+narg+"\"\n");
+    else
+      write("Du hast den Teamangriffsbefehl deaktiviert.\n");
+    break; // NICHT return!
+  case "autofolge":
+  case "autof":
+    if (arg=="ein" || arg=="an") {
+      team_autofollow=1;
+      if (IsTeamLeader())
+        write("Dein Team folgt Dir.\n");
+      else
+        write("Du folgst jetzt dem Teamleiter.\n");
+    } else {
+      team_autofollow=0;
+      if (IsTeamLeader())
+        write("Dein Team folgt Dir nicht mehr.\n");
+      else
+        write("Du folgst jetzt nicht mehr dem Teamleiter.\n");
+    }
+    break; // NICHT return!
+  default: ;
+  }
+  return team->TeamCmd(words[0],narg); // Befehle die Mitgliedschaft erfordern:
+}
+
+varargs void InformRowChange(int from, int to, object caster) {
+
+  if (caster) return; // Fuer den Fall, dass Gildenobjekt==ME ist
+  if (PO!=Query(P_TEAM)) return;
+#if __BOOT_TIME__ < 1281904437
+  mixed gilde = QueryProp(P_GUILD);
+  if (!stringp(gilde)) return;
+  if (!objectp(gilde=find_object("/gilden/"+gilde))) return;
+  gilde->InformRowChange(from,to,ME);
+#endif
+  HookFlow(H_HOOK_TEAMROWCHANGE, ({from,to}) );
+}