dsIIr4/bin/
dsIIr4/extra/creremote/
dsIIr4/extra/wolfpaw/
dsIIr4/lib/cmds/admins/
dsIIr4/lib/cmds/common/
dsIIr4/lib/cmds/creators/include/
dsIIr4/lib/cmds/creators/include/SCCS/
dsIIr4/lib/daemon/services/
dsIIr4/lib/doc/
dsIIr4/lib/domains/Ylsrim/
dsIIr4/lib/domains/Ylsrim/adm/
dsIIr4/lib/domains/Ylsrim/armor/
dsIIr4/lib/domains/Ylsrim/broken/
dsIIr4/lib/domains/Ylsrim/fish/
dsIIr4/lib/domains/Ylsrim/meal/
dsIIr4/lib/domains/Ylsrim/npc/
dsIIr4/lib/domains/Ylsrim/virtual/
dsIIr4/lib/domains/Ylsrim/weapon/
dsIIr4/lib/domains/campus/adm/
dsIIr4/lib/domains/campus/etc/
dsIIr4/lib/domains/campus/meals/
dsIIr4/lib/domains/campus/npc/
dsIIr4/lib/domains/campus/save/
dsIIr4/lib/domains/campus/txt/
dsIIr4/lib/domains/campus/txt/ai/charles/
dsIIr4/lib/domains/campus/txt/ai/charles/bak2/
dsIIr4/lib/domains/campus/txt/ai/charles/bak2/bak1/
dsIIr4/lib/domains/campus/txt/ai/charly/
dsIIr4/lib/domains/campus/txt/ai/charly/bak/
dsIIr4/lib/domains/campus/txt/jenny/
dsIIr4/lib/domains/default/creator/
dsIIr4/lib/domains/default/doors/
dsIIr4/lib/domains/default/etc/
dsIIr4/lib/domains/default/virtual/
dsIIr4/lib/domains/default/weap/
dsIIr4/lib/domains/town/virtual/
dsIIr4/lib/lib/comp/
dsIIr4/lib/lib/lvs/
dsIIr4/lib/lib/user/
dsIIr4/lib/lib/virtual/
dsIIr4/lib/log/
dsIIr4/lib/obj/book_source/
dsIIr4/lib/obj/include/
dsIIr4/lib/realms/template/
dsIIr4/lib/realms/template/adm/
dsIIr4/lib/realms/template/area/armor/
dsIIr4/lib/realms/template/area/npc/
dsIIr4/lib/realms/template/area/obj/
dsIIr4/lib/realms/template/area/room/
dsIIr4/lib/realms/template/area/weap/
dsIIr4/lib/realms/template/bak/
dsIIr4/lib/realms/template/cmds/
dsIIr4/lib/save/
dsIIr4/lib/save/kills/o/
dsIIr4/lib/secure/cfg/classes/
dsIIr4/lib/secure/cmds/creators/include/
dsIIr4/lib/secure/cmds/players/
dsIIr4/lib/secure/cmds/players/include/
dsIIr4/lib/secure/daemon/include/
dsIIr4/lib/secure/lib/
dsIIr4/lib/secure/lib/include/
dsIIr4/lib/secure/lib/net/include/
dsIIr4/lib/secure/lib/std/
dsIIr4/lib/secure/modules/
dsIIr4/lib/secure/npc/
dsIIr4/lib/secure/obj/include/
dsIIr4/lib/secure/room/
dsIIr4/lib/secure/save/
dsIIr4/lib/secure/save/boards/
dsIIr4/lib/secure/save/players/g/
dsIIr4/lib/secure/tmp/
dsIIr4/lib/secure/verbs/creators/
dsIIr4/lib/shadows/
dsIIr4/lib/spells/
dsIIr4/lib/std/board/
dsIIr4/lib/std/lib/
dsIIr4/lib/tmp/
dsIIr4/lib/verbs/admins/include/
dsIIr4/lib/verbs/common/
dsIIr4/lib/verbs/common/include/
dsIIr4/lib/verbs/creators/include/
dsIIr4/lib/verbs/players/include/SCCS/
dsIIr4/lib/verbs/rooms/
dsIIr4/lib/verbs/rooms/include/
dsIIr4/lib/www/
dsIIr4/v22.2b14-dsouls2/
dsIIr4/v22.2b14-dsouls2/ChangeLog.old/
dsIIr4/v22.2b14-dsouls2/Win32/
dsIIr4/v22.2b14-dsouls2/compat/
dsIIr4/v22.2b14-dsouls2/compat/simuls/
dsIIr4/v22.2b14-dsouls2/include/
dsIIr4/v22.2b14-dsouls2/mudlib/
dsIIr4/v22.2b14-dsouls2/testsuite/
dsIIr4/v22.2b14-dsouls2/testsuite/clone/
dsIIr4/v22.2b14-dsouls2/testsuite/command/
dsIIr4/v22.2b14-dsouls2/testsuite/data/
dsIIr4/v22.2b14-dsouls2/testsuite/etc/
dsIIr4/v22.2b14-dsouls2/testsuite/include/
dsIIr4/v22.2b14-dsouls2/testsuite/inherit/
dsIIr4/v22.2b14-dsouls2/testsuite/inherit/master/
dsIIr4/v22.2b14-dsouls2/testsuite/log/
dsIIr4/v22.2b14-dsouls2/testsuite/single/
dsIIr4/v22.2b14-dsouls2/testsuite/single/tests/compiler/
dsIIr4/v22.2b14-dsouls2/testsuite/single/tests/efuns/
dsIIr4/v22.2b14-dsouls2/testsuite/single/tests/operators/
dsIIr4/v22.2b14-dsouls2/testsuite/u/
dsIIr4/v22.2b14-dsouls2/tmp/
dsIIr4/win32/
/*    /daemon/classes.c
 *    from the Dead Souls  Object Library
 *    handles race configuration and administration
 *    created by Descartes of Borg 960929
 *    Version: @(#) classes.c 1.4@(#)
 *    Last modified: 96/10/17
 */

#include <lib.h>
#include <save.h>
#include <privs.h>
#include "include/classes.h"

inherit LIB_DAEMON;

private mapping Classes = ([]);

static void create() {
    daemon::create();
    if( unguarded((: file_size(SAVE_CLASSES __SAVE_EXTENSION__) :)) > 0 )
	unguarded((: restore_object(SAVE_CLASSES) :));
    if( !Classes ) Classes = ([]);
}

static private void validate() {
    if( !((int)master()->valid_apply(({ PRIV_ASSIST }))) )
	error("Illegal attempt to modify class data");
}

int ClassMember(string my_class, string query_class) {
    class Class cls;

    if( my_class == query_class ) {
	return 1;
    }
    cls = Classes[query_class];
    if( !cls ) { // query class is a multi-class, thus must be equal to mine
	return 0; // This should change for triple classing
    }
    return (member_array(my_class, values(cls->Multis)) != -1);
}

void AddClass(string file) {
    class Class cls;
    string array lines, tmp;
    string class_name;

    validate();
    if( !file_exists(file) ) error("No such file: " + file);
    lines = explode(read_file(file), "\n");
    lines = filter(lines, function(string str) {
	  if( strlen(str) == 0 ) {
	      return 0;
	  }
	  if( str[0] == '#' ) {
	      return 0;
	  }
	  if( str[0] == ' ' || str[0] == '\t' ) {
	      return 0;
	  }
	  return 1;
	});
      class_name = lines[0];
      if( Classes[class_name] ) error("Class already exists");
      cls = new(class Class);
      Classes[class_name] = cls;
      lines = lines[1..];
      cls->Multis = ([]);
      while( sizeof(tmp = explode(lines[0], ":")) == 2 ) {
	  cls->Multis[tmp[0]] = tmp[1];
	  lines = lines[1..];
      }
      cls->Skills = ([]);
      while(sizeof(tmp = explode(lines[0], ":")) == 3) {
	  class Skill s = new (class Skill);

	  s->Average = to_int(tmp[1]);
	  s->SkillClass = to_int(tmp[2]);
	  cls->Skills[tmp[0]] = s;
	  if( sizeof(lines) == 1 ) {
	      lines = ({});
	      break;
	  }
	  else {
	      lines = lines[1..];
	  }
      }
      cls->Complete = 1;
      save_object(SAVE_CLASSES);
  }

    void RemoveClass(string class_name) {
	validate();
	map_delete(Classes, class_name);
	save_object(SAVE_CLASSES);
    }

    void SetClass(string class_name, mixed array args) {
	class Class cls = Classes[class_name];
	mixed array primes, ots;

	if( !cls || !cls->Complete || sizeof(args) != 3 ) return;
	args[0] = cls->Multis;
	primes = ({});
	ots = ({});
	foreach(string key, class Skill skill in cls->Skills) {
	    if( skill->SkillClass == 1 ) {
		primes = ({ primes..., ({ key, skill->Average, 1 }) });
	    }
	    else {
		ots = ({ ots..., ({ key, skill->Average, skill->SkillClass }) });
	    }
	}
	args[1] = primes;
	args[2] = ots;
    }

    void SetComplete(string class_name) {
	class Class cls;

	validate();
	if( !Classes[class_name] ) error("No such class");
	else cls = Classes[class_name];
	cls->Complete = 1;
	save_object(SAVE_CLASSES);
    }

    varargs string array GetClasses() {
	return filter(keys(Classes), (: ((class Class)Classes[$1])->Complete :));
    }

    string GetHelp(string class_name) {
	class Class cls = Classes[class_name];
	string help = "Class: " + class_name + "\n\n";

	if( !cls ) return 0;
	if( !sizeof(cls->Multis) ) {
	    help += capitalize(class_name) + " cannot multi-class.\n";
	}
	else {
	    help += capitalize(pluralize(class_name)) + " can multi-class with " +
	    "the following primary classes:\n";
	    foreach(string prime, string other in cls->Multis) {
		help += "\t" + capitalize(class_name) + " + " + prime + " = " +
		other +  "\n";
	    }
	}
	help += "\n" + capitalize(pluralize(class_name)) + " has the following " +
	"primary skills:\n";
	foreach(string skill, class Skill s in cls->Skills) {
	    if( s->SkillClass == 1 ) {
		help += "\t" + skill + "\n";
	    }
	}
	return help + "\n";
    }