nightmare3_fluffos_v2/
nightmare3_fluffos_v2/bin/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/ChangeLog.old/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/Win32/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/compat/simuls/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/clone/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/command/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/data/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/etc/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/include/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/inherit/master/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/log/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/compiler/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/efuns/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/single/tests/operators/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/testsuite/u/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/tmp/
nightmare3_fluffos_v2/fluffos-2.9-ds2.08/windows/
nightmare3_fluffos_v2/lib/cmds/ambassador/
nightmare3_fluffos_v2/lib/cmds/database/
nightmare3_fluffos_v2/lib/cmds/hm/
nightmare3_fluffos_v2/lib/cmds/soul/
nightmare3_fluffos_v2/lib/daemon/cfg/
nightmare3_fluffos_v2/lib/daemon/cfg/mon_races/
nightmare3_fluffos_v2/lib/daemon/cfg/races/
nightmare3_fluffos_v2/lib/daemon/include/
nightmare3_fluffos_v2/lib/daemon/save/
nightmare3_fluffos_v2/lib/daemon/services/
nightmare3_fluffos_v2/lib/daemon/soul/
nightmare3_fluffos_v2/lib/doc/
nightmare3_fluffos_v2/lib/doc/TestPlans/
nightmare3_fluffos_v2/lib/doc/approval/
nightmare3_fluffos_v2/lib/doc/approval/QC/
nightmare3_fluffos_v2/lib/doc/approval/balance/
nightmare3_fluffos_v2/lib/doc/build/
nightmare3_fluffos_v2/lib/doc/build/armours/
nightmare3_fluffos_v2/lib/doc/build/economy/
nightmare3_fluffos_v2/lib/doc/build/etc/
nightmare3_fluffos_v2/lib/doc/build/monster/
nightmare3_fluffos_v2/lib/doc/build/room/
nightmare3_fluffos_v2/lib/doc/build/virtual/
nightmare3_fluffos_v2/lib/doc/build/weapon/
nightmare3_fluffos_v2/lib/doc/classes/
nightmare3_fluffos_v2/lib/doc/efun/
nightmare3_fluffos_v2/lib/doc/etc/
nightmare3_fluffos_v2/lib/doc/help/creator/
nightmare3_fluffos_v2/lib/doc/help/hm/
nightmare3_fluffos_v2/lib/doc/law/
nightmare3_fluffos_v2/lib/doc/lpc/basic/
nightmare3_fluffos_v2/lib/doc/lpc/data_types/
nightmare3_fluffos_v2/lib/doc/lpc/etc/
nightmare3_fluffos_v2/lib/doc/lpc/intermediate/
nightmare3_fluffos_v2/lib/doc/lpc/types/
nightmare3_fluffos_v2/lib/doc/mudlib/
nightmare3_fluffos_v2/lib/doc/mudlib/features/
nightmare3_fluffos_v2/lib/domains/Examples/etc/
nightmare3_fluffos_v2/lib/domains/Examples/room/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaA/
nightmare3_fluffos_v2/lib/domains/Examples/virtual/exaB/
nightmare3_fluffos_v2/lib/domains/Examples/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/
nightmare3_fluffos_v2/lib/domains/Praxis/adm/
nightmare3_fluffos_v2/lib/domains/Praxis/attic/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/
nightmare3_fluffos_v2/lib/domains/Praxis/cemetary/mon/
nightmare3_fluffos_v2/lib/domains/Praxis/data/
nightmare3_fluffos_v2/lib/domains/Praxis/death/
nightmare3_fluffos_v2/lib/domains/Praxis/mountains/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/armour/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/magic/
nightmare3_fluffos_v2/lib/domains/Praxis/obj/weapon/
nightmare3_fluffos_v2/lib/domains/Praxis/orc_valley/
nightmare3_fluffos_v2/lib/domains/Praxis/quests/
nightmare3_fluffos_v2/lib/domains/Praxis/standardOld/
nightmare3_fluffos_v2/lib/include/
nightmare3_fluffos_v2/lib/log/
nightmare3_fluffos_v2/lib/log/errors/
nightmare3_fluffos_v2/lib/log/reports/
nightmare3_fluffos_v2/lib/log/watch/
nightmare3_fluffos_v2/lib/news/
nightmare3_fluffos_v2/lib/secure/cfg/
nightmare3_fluffos_v2/lib/secure/cmds/ambassador/
nightmare3_fluffos_v2/lib/secure/cmds/mortal/
nightmare3_fluffos_v2/lib/secure/save/users/d/
nightmare3_fluffos_v2/lib/secure/std/
nightmare3_fluffos_v2/lib/std/hm/
nightmare3_fluffos_v2/lib/std/living/
nightmare3_fluffos_v2/lib/std/room/
nightmare3_fluffos_v2/lib/std/user/
nightmare3_fluffos_v2/lib/std/virtual/
nightmare3_fluffos_v2/lib/www/
nightmare3_fluffos_v2/lib/www/errors/
nightmare3_fluffos_v2/lib/www/gateways/
nightmare3_fluffos_v2/win32/
// /adm/daemons/multi_d.c
// A Nightmarish object.
// Keeps track of multiple characters (See also: /bin/adm/_link.c)
// Created by Pallando (93-05-26)
// NB No checks have been put in to prevent wizards faking calls.
//    I'll leave the Law arches to decide how paranoid they wish to be. 8-)


// 3600 = 60 * 60 = number of second in an hour =
// amount of time after logging out that a user can log in a second character
#include <save.h>
#include <security.h>

#define DELAY_PERIOD 3600

mapping links;
string *non_voting;
static mapping entered;

static void save_data() {
    save_object(SAVE_MULTI);
}

static void restore_data() { restore_object(SAVE_MULTI); }

void create()
{
  restore_data();
  if( !links ) links = ([]);
  if( !non_voting ) non_voting = ({ });
  entered = ([ ]);
}

void list_links()
{
  string *names;
  int loop;

  names = keys( links );
  names -= non_voting;
  loop = sizeof( names );
  if( !loop ) { write( "No multiple characters yet."); return; }
  write( "The following multiple characters are registered:");
  while( loop-- )
    write( names[loop] + " is also: " +
      implode( links[names[loop]], ", " ));
}

mixed is_linked_char( string name ) { return links[name]; }

int non_voter( string name ) { return -1 != member_array( name, non_voting ); }

int make_link( string *names )
{
  int loop, size;
  if( !pointerp( names ) ) return 0;
  size = sizeof( names );
  if( size < 2 ) return 0;
  for( loop = 0 ; loop < size ; loop++ )
    if( links[names[loop]] )
    {
      write( names[loop] + " is already in a link." );
      return 0;
    }
  non_voting += names[1..size-1];
  for( loop = 0 ; loop < size ; loop++ )
    links[names[loop]] = ( names - names[loop..loop] );
  save_data();
  return 1;
}

int unlink( string name )
{
  // If name is the main character, break the entire link
  // Otherwise just remove name fom it.
  string *names;
  int loop, size;

  names = ({ name }) + links[name];
  size = sizeof( names );
  for( loop = 0 ; loop < size ; loop++ )
    map_delete( links, names[loop] );
  if( ( size > 2 ) && non_voter( name ) )
  {
    non_voting -= names;
    make_link( names[1..size-1] );
  } else {
    non_voting -= names;
    save_data();
  }
  return 1;
}

/************** Functions to keep track of who has logged in or out ***/

// Called by the remove() function in /std/user.c
void quit( string name )
{
  if( !name ) return;
  if( links[name] )
  {
    if( !entered[name] )
    {
      // Possible cheat attempt.
      // Law can decide if they want to log it or not.
      // Will also be caused if chars are linked while logged in.
    }
    entered[name] = time();
  }
}

// Called by the switch_player() function in /adm/login.c
int query_prevent_login( string name )
{
  // Put a test for arches here, if you want to make sure they can
  // always log in.
  string *names;
  // st = -1 if character is logged in, else time of logout
  int loop, size, st;

  if( !name ) return 0;
  if( undefinedp( names = links[name] ) ) return 0;
  // Always allow arches in.
  if( member_group( name, "superuser" ) ||
      member_group( name, "assist"    )    ) return 0;
  size = sizeof( names );
  for( loop = 0 ; loop < size ; loop++ )
  {
    // The next line is only useful in the case that you link some chars
    // While they are loged in, then one logs out and trys to log in again.
    if( find_player( names[loop] ) ) entered[names[loop]] = -1;
    if( st = entered[names[loop]] )
    {
      if( st < 0 )
      {
        write( "Another character of yours, " + capitalize( names[loop] ) +
          " is already logged in." );
        // Log this event if you want to.
        return 1; // prevent login
      }
      if( ( time() - st ) < DELAY_PERIOD )
      {
        write( "Sorry, " + capitalize( names[loop] ) + " logged out only "+
          ( time() - st ) / 60 + " minutes ago.  Try later." );
        // Log this event if you want to.
        return 1;
      }
      map_delete( entered, names[loop] );
    }
  }
  entered[name] = -1;
  return 0;
}