Crossfire Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CF: Admin patch



I was making the admin patch a while ago, but lost interest quickly :(
I never get anything done, because something else is always more
interesting than the project I'm currently working on :/ Interest in
CF won't probably return before summer, so here is what I have coded, it
should at least work without crashing ;)

* DM name-based authentication no longer works for sockets - you can
  change your name with "name" and just by guessing it you get to be dm.
  Eh.
* new command "cheat" which switches FLAG_WAS_WIZ on/off on any object
  (and recursively its inventory)
* A new command "shutdown"
* dm no longer sets FLAG_WAS_WIZ
* fixed dm command binding
* changed DM's archetype so he can easily be identified as admin
* added "Dungeon Master is gone" message
* added "set_god" so admins can change a god without searching for an altar..

And here's the diff:

diff -c -d -r crossfire-0.93.5.patch/common/object.c crossfire-0.93.5/common/object.c
*** crossfire-0.93.5.patch/common/object.c	Tue Sep 30 10:18:22 1997
--- crossfire-0.93.5/common/object.c	Fri Sep 19 12:22:12 1997
***************
*** 1830,1835 ****
--- 1830,1843 ----
        set_cheat(tmp);
  }
  
+ void clear_cheat(object *op) {
+   object *tmp;
+   CLEAR_FLAG(op, FLAG_WAS_WIZ);
+   if(op->inv)
+     for(tmp = op->inv; tmp != NULL; tmp = tmp->below)
+       clear_cheat(tmp);
+ }
+ 
  /*
   * find_free_spot(archetype, map, x, y, start, stop) will search for
   * a spot at the given map and coordinates which will be able to contain
diff -c -d -r crossfire-0.93.5.patch/include/libproto.h crossfire-0.93.5/include/libproto.h
*** crossfire-0.93.5.patch/include/libproto.h	Tue Sep 30 10:18:23 1997
--- crossfire-0.93.5/include/libproto.h	Fri Sep 19 12:21:59 1997
***************
*** 320,325 ****
--- 320,326 ----
  extern void set_attr_value ( living *stats, int attr, signed char value );
  extern void set_block ( int x, int y, int bx, int by );
  extern void set_cheat ( object *op );
+ extern void clear_cheat ( object *op );
  extern void set_clean_tmp_files ( type_func_void addr );
  extern void set_draw ( type_func_ob addr );
  extern void set_draw_info ( type_func_int_int_ob_cchar addr );
diff -c -d -r crossfire-0.93.5.patch/include/main.h crossfire-0.93.5/include/main.h
*** crossfire-0.93.5.patch/include/main.h	Mon Aug 18 05:45:17 1997
--- crossfire-0.93.5/include/main.h	Tue Sep 30 15:02:45 1997
***************
*** 25,30 ****
--- 25,33 ----
      The author can be reached via e-mail to mark@pyramid.com.
  */
  
+ extern int shuttime;
+ extern char *shutmsg;
+ extern void shutdown_check(void);
  
  #ifndef sgi
  extern int IOerrors();
diff -c -d -r crossfire-0.93.5.patch/include/object.h crossfire-0.93.5/include/object.h
*** crossfire-0.93.5.patch/include/object.h	Mon Aug 18 05:45:17 1997
--- crossfire-0.93.5/include/object.h	Tue Sep 30 15:02:52 1997
***************
*** 29,34 ****
--- 29,35 ----
  extern object *active_objects;
  extern object *free_objects;
  extern object objarray[STARTMAX];
+ extern struct archt *dm_arch;
  
  extern int nrofallocobjects;
  extern int nroffreeobjects;
diff -c -d -r crossfire-0.93.5.patch/include/sproto.h crossfire-0.93.5/include/sproto.h
*** crossfire-0.93.5.patch/include/sproto.h	Tue Sep 30 10:18:23 1997
--- crossfire-0.93.5/include/sproto.h	Tue Sep 30 16:36:07 1997
***************
*** 213,218 ****
--- 213,221 ----
  extern int command_reset ( object *op, char *params );
  extern int command_nowiz ( object *op, char *params );
  extern int command_dm ( object *op, char *params );
+ extern int command_setgod ( object *op, char *params );
+ extern int command_cheat ( object *op, char *params );
+ extern int command_shutdown ( object *op, char *params );
  extern void init_commands ( void );
  extern long xfire_kc2ks ( player *p, KeyCode kc, long foozit );
  extern long xfire_ks2kc ( player *p, KeySym ks );
***************
*** 220,225 ****
--- 223,229 ----
  extern void insert_key ( player *p, int baseflags, char *text );
  extern void load_default_keys ( player *p );
  extern char *find_func_name ( CommFunc func );
+ extern char *find_any_func_name ( CommFunc func );
  extern void dump_keys ( player *p, FILE *fp );
  extern void configure_keys ( object *op, KeyCode k, KeySym keysym );
  extern int parse_string ( object *op, char *str );
***************
*** 354,359 ****
--- 358,364 ----
  extern int command_berzerk ( object *op, char *params );
  extern int command_strength ( object *op, char *params );
  extern int command_pickup ( object *op, char *params );
+ extern int command_shutdown ( object *op, char *params );
  extern int command_protocol ( object *op, char *params );
  extern int command_set ( object *op, char *params );
  extern int command_unset ( object *op, char *params );
diff -c -d -r crossfire-0.93.5.patch/server/apply.c crossfire-0.93.5/server/apply.c
*** crossfire-0.93.5.patch/server/apply.c	Tue Sep 30 10:18:19 1997
--- crossfire-0.93.5/server/apply.c	Fri Sep 19 12:03:33 1997
***************
*** 1952,1957 ****
--- 1952,1961 ----
        new_draw_info(NDI_UNIQUE, 0,op,"You don't deserve to save your character yet.");
        return 1;
      }
+     if(QUERY_FLAG(op,FLAG_WIZ)) {
+       new_draw_info(NDI_UNIQUE,0,op,"Use nodm before saving.");
+       return 1;
+     }
      if(QUERY_FLAG(op,FLAG_WAS_WIZ)) {
        new_draw_info(NDI_UNIQUE, 0,op,"Since you have cheated you can't save.");
        return 1;
diff -c -d -r crossfire-0.93.5.patch/server/c_object.c crossfire-0.93.5/server/c_object.c
*** crossfire-0.93.5.patch/server/c_object.c	Tue Sep 30 10:18:19 1997
--- crossfire-0.93.5/server/c_object.c	Fri Sep 19 12:07:28 1997
***************
*** 416,422 ****
  	new_draw_info(NDI_UNIQUE, 0,pl, "You are levitating, you can't reach the ground!");
  	return;
      }
!     if(!can_pick(pl,tmp)) {
  	if (tmp->name!=NULL) {
  	sprintf(buf,"You can't pick up a %s", tmp->name);
  	new_draw_info(NDI_UNIQUE, 0,pl, buf);
--- 416,424 ----
  	new_draw_info(NDI_UNIQUE, 0,pl, "You are levitating, you can't reach the ground!");
  	return;
      }
!     if(!can_pick(pl,tmp)||
!        (QUERY_FLAG(tmp,FLAG_WAS_WIZ)&&!QUERY_FLAG(pl,FLAG_WAS_WIZ)))
!     {
  	if (tmp->name!=NULL) {
  	sprintf(buf,"You can't pick up a %s", tmp->name);
  	new_draw_info(NDI_UNIQUE, 0,pl, buf);
***************
*** 427,441 ****
      }
      if (QUERY_FLAG (tmp, FLAG_NO_DROP))
  	return;
-     if(QUERY_FLAG(tmp,FLAG_WAS_WIZ) && !QUERY_FLAG(pl, FLAG_WAS_WIZ)) {
- 	new_draw_info(NDI_UNIQUE, 0,pl, "The object disappears in a puff of smoke!");
- 	new_draw_info(NDI_UNIQUE, 0,pl, "It must have been an illusion.");
- 	if (pl->contr->eric_server > 0)
- 	    esrv_del_item (pl->contr->eric_server, tmp->count);
- 	remove_ob(tmp);
- 	free_object(tmp);
- 	return;
-     }
      if(QUERY_FLAG(pl, FLAG_WAS_WIZ))
  	SET_FLAG(tmp, FLAG_WAS_WIZ);
  
--- 429,434 ----
diff -c -d -r crossfire-0.93.5.patch/server/c_wiz.c crossfire-0.93.5/server/c_wiz.c
*** crossfire-0.93.5.patch/server/c_wiz.c	Mon Aug 18 05:45:14 1997
--- crossfire-0.93.5/server/c_wiz.c	Tue Sep 30 17:03:40 1997
***************
*** 40,45 ****
--- 40,158 ----
  #include <main.h>
  #include <spells.h>
  #include <treasure.h>
+ #include <object.h>
+ #include <skills.h>
+ 
+ /* This is a general parser for an object argument.
+    This recognizes either name or object number (of form #123).
+  */
+ object *get_object_param(char *params)
+ {
+ 	object *ob;
+ 	char *tmp,*str;
+ 
+ 	tmp=strdup(params);
+ 	if(!tmp) return NULL;
+ 	str=strtok(tmp," ");
+ 	if(!str) { free(tmp); return NULL; }
+ 	if(str[0]=='#') ob=find_object(atol(str+1));
+ 	 else
+ 	ob=find_object_name(strtok(str," "));
+ 	free(tmp);
+ 	return ob;
+ }
+ 
+ char *skip_param(char *params)
+ {
+ 	while(*params!=' '&&*params!=0) params++;
+ 	while(*params==' ') params++;
+ 	return params;
+ }
+ 
+ int command_setgod(object *op, char *params)
+ {
+ 	object *ob;
+ 	int old;
+ 
+ 	if(!params||!(ob=get_object_param(params))||ob->type!=PLAYER) {
+ 		new_draw_info(NDI_UNIQUE,0,op,"Set whose god?");
+ 		return 1;
+ 	}
+ 	change_skill(op,SK_PRAYING);
+ 	if(!op->chosen_skill||op->chosen_skill->stats.sp!=SK_PRAYING) {
+ 		new_draw_info(NDI_UNIQUE,0,op,"It doesn't have praying skill.");
+ 		return 1;
+ 	}
+ 	params=skip_param(params);
+ 	if(find_god(params)==NULL) {
+ 		new_draw_info_format(NDI_UNIQUE,0,op,"No such god \"%s\".",params);
+ 		return 1;
+ 	}
+ 	old=QUERY_FLAG(op,FLAG_WIZ);
+ 	SET_FLAG(ob,FLAG_WIZ);
+ 	become_follower(ob,params);
+ 	if(!old) CLEAR_FLAG(ob,FLAG_WIZ);
+ 	return 1;
+ }
+ 
+ int command_shutdown(object *op, char *params)
+ {
+ 	char *param,*ret;
+ 
+ 	if(params) {
+ 		param=strdup(params);
+ 		if(!param) return 0;
+ 		ret=strtok(param," ");
+ 	}
+ 	if(!params||ret==NULL||!op||!QUERY_FLAG(op,FLAG_WIZ)) {
+ 		if(shuttime==-1) new_draw_info(NDI_UNIQUE,0,op,"No shutdown"
+ 				               " scheduled.");
+ 		else {
+ 		   new_draw_info_format(NDI_UNIQUE,0,op,"CF will shut down "
+ 				        "in %d.%d minute(s).",shuttime/60,
+ 				        shuttime-(60*(shuttime/60)));
+ 		   if(shutmsg)
+ 		     new_draw_info_format(NDI_UNIQUE,0,op,"Reason: %s",
+ 					  shutmsg);
+                 }
+ 		return 1;
+ 	}
+ 	shuttime=atol(ret)*60;
+ 	ret=strchr(ret,'.');
+ 	if(ret!=NULL) shuttime+=atol(ret+1);
+ 	ret=strtok(NULL," ");
+ 	if(shutmsg!=NULL) { free(shutmsg); shutmsg=NULL; }
+ 	if(ret!=NULL) shutmsg=strdup(ret);
+ 	free(param);
+ 	if(shuttime<0) {
+ 		shuttime=-1;
+ 		new_draw_info(NDI_ALL|NDI_RED,0,NULL,"Shutdown cancelled.");
+ 	}
+ 	shutdown_check();
+ 	return 1;
+ }
+ 
+ int command_cheat(object *op, char *params)
+ {
+ 	object *ob=get_object_param(params);
+ 
+ 	if(!ob) {
+ 		new_draw_info(NDI_UNIQUE,0,op,"Switch cheat flag on WHAT?");
+ 		return 1;
+ 	}
+ 	if(QUERY_FLAG(ob,FLAG_WAS_WIZ)) {
+ 		clear_cheat(ob);
+ 		new_draw_info(NDI_UNIQUE,0,op,"Cheat flag cleared.");
+ 		if(ob->type==PLAYER) new_draw_info(NDI_UNIQUE|NDI_NAVY,0,ob,
+ 					           "You can save again.");
+ 	} else {
+ 		set_cheat(ob);
+ 		new_draw_info(NDI_UNIQUE,0,op,"Cheat flag set.");
+ 		if(ob->type==PLAYER) new_draw_info(NDI_UNIQUE|NDI_NAVY,0,ob,
+ 						   "You can't save anymore.");
+ 	}
+ 	return 1;
+ }
  
  int command_goto (object *op, char *params)
  {
***************
*** 66,79 ****
           * Now, if we entered a new, unloaded map, set the cheat-flag in
           * all objects here.
           */
- #ifdef SET_WIZCHEAT
-         if(op->map != prev && !m) {
-           object *tmp;
-           for(tmp = objects; tmp != NULL; tmp = tmp->next)
-             if(tmp->map == op->map)
-               SET_WAS_WIZ(tmp);
-         }
- #endif
        }
        return 1;
      }
--- 179,184 ----
***************
*** 208,214 ****
          if (set_nrof)
            tmp->nrof = nrof;
          tmp->map=op->map;
- 	SET_FLAG(tmp, FLAG_WAS_WIZ);
          if (set_magic)
            set_abs_magic(tmp, magic);
          if (art)
--- 313,318 ----
***************
*** 228,234 ****
          object *prev=NULL,*head=NULL;
          for (atmp=at;atmp!=NULL;atmp=atmp->more) {
            tmp=arch_to_object(atmp);
- 	  SET_FLAG(tmp, FLAG_WAS_WIZ);
            if(head==NULL)
              head=tmp;
            tmp->x=op->x+tmp->arch->clone.x;
--- 332,337 ----
***************
*** 343,349 ****
      }
      if((arg2=strchr(++arg,' ')))
        arg2++;
-     SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
      if(set_variable(tmp,arg) == -1)
        new_draw_info(NDI_UNIQUE, 0,op,errmsg);
      else {
--- 446,451 ----
***************
*** 419,425 ****
  #endif
      pl->ob->stats.exp += i;
      add_exp(pl->ob,0);
-     SET_FLAG(pl->ob, FLAG_WAS_WIZ);
      draw_stats(pl->ob);
      return 1;
    }
--- 521,526 ----
***************
*** 509,515 ****
      }
      for(pl=first_player;pl!=NULL;pl=pl->next) 
         if(!strcmp(pl->ob->name,thing)){   
- 	  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
            if(!strcmp("str",thing2))
              pl->ob->stats.Str = iii,pl->orig_stats.Str = iii;
            if(!strcmp("dex",thing2))   
--- 610,615 ----
***************
*** 604,611 ****
--- 704,716 ----
         return 1;
       }
       CLEAR_FLAG(op, FLAG_WIZ);
+      CLEAR_FLAG(op, FLAG_WAS_WIZ);
       CLEAR_FLAG(op, FLAG_WIZPASS);
       CLEAR_FLAG(op, FLAG_FLYING);
+      clear_cheat(op);
+      move_player(op,0);
+      new_draw_info(NDI_UNIQUE | NDI_ALL, 1, NULL,
+ 	"The Dungeon Master is gone..");
       return 1;
    }
  
***************
*** 644,650 ****
  int command_dm (object *op, char *params)
  {
    if (op==NULL) {
!     if (checkdm(op, active_socket->name, params?params:"*", active_socket->host)) {
        active_socket->wiz=1;
        new_draw_info(NDI_UNIQUE, 0,op, "Ok, you are the Dungeon Master!");
        new_draw_info(NDI_UNIQUE | NDI_ALL, 1, NULL,
--- 749,755 ----
  int command_dm (object *op, char *params)
  {
    if (op==NULL) {
!     if (checkdm(op, "", params?params:"*", active_socket->host)) {
        active_socket->wiz=1;
        new_draw_info(NDI_UNIQUE, 0,op, "Ok, you are the Dungeon Master!");
        new_draw_info(NDI_UNIQUE | NDI_ALL, 1, NULL,
***************
*** 673,682 ****
      /* op->contr->username is the name supplied with the name command via
       * the socket
       */
!     if (checkdm(op, (op->contr->username?op->contr->username:"*"), 
  		(params?params:"*"), player_host)) {
        SET_FLAG(op, FLAG_WIZ);
-       SET_FLAG(op, FLAG_WAS_WIZ);
        SET_FLAG(op, FLAG_WIZPASS);
        new_draw_info(NDI_UNIQUE, 0,op, "Ok, you are the Dungeon Master!");
        new_draw_info(NDI_UNIQUE | NDI_ALL, 1, NULL,
--- 778,786 ----
      /* op->contr->username is the name supplied with the name command via
       * the socket
       */
!     if (checkdm(op, (op->name?op->name:"*"), 
  		(params?params:"*"), player_host)) {
        SET_FLAG(op, FLAG_WIZ);
        SET_FLAG(op, FLAG_WIZPASS);
        new_draw_info(NDI_UNIQUE, 0,op, "Ok, you are the Dungeon Master!");
        new_draw_info(NDI_UNIQUE | NDI_ALL, 1, NULL,
***************
*** 685,690 ****
--- 789,795 ----
        clear_los(op);
        op->contr->writing =0;
        op->contr->write_buf[0] ='\0';
+       move_player(op,0);
        return 1;
      } else {
        new_draw_info(NDI_UNIQUE, 0,op, "Sorry Pal, I don't think so.");
diff -c -d -r crossfire-0.93.5.patch/server/commands.c crossfire-0.93.5/server/commands.c
*** crossfire-0.93.5.patch/server/commands.c	Tue Sep 30 10:21:20 1997
--- crossfire-0.93.5/server/commands.c	Tue Sep 30 16:19:01 1997
***************
*** 83,88 ****
--- 83,89 ----
    {"shout", command_shout,	0.0},
    {"show", command_show,	0.0},
    {"showinvicon", command_show_inv_icon, 0.0},
+   {"shutdown", command_shutdown, 0.0},
  #ifdef ALLOW_SKILLS
    {"skills", command_skills,	0.0},	/* shows player list of skills */
    {"use_skill", command_uskill, 0.0},
***************
*** 168,173 ****
--- 169,175 ----
  CommArray_s WizCommands [] = {
    {"abil", command_abil,0.0},
    {"addexp", command_addexp,0.0},
+   {"cheat", command_cheat,      0.0},
    {"create", command_create,0.0},
    {"debug", command_debug,0.0},
    {"dump", command_dump,0.0},
***************
*** 187,192 ****
--- 189,196 ----
    {"printlos", command_printlos,0.0},
    {"remove", command_remove,0.0},
    {"reset", command_reset,0.0},
+   {"set_god", command_setgod, 0.0},
+   {"shutdown", command_shutdown,        0.0},
    {"speed", command_speed,0.0},
    {"spellreset", command_spell_reset,0.0},
    {"ssdumptable", command_ssdumptable,0.0},
***************
*** 268,273 ****
--- 272,288 ----
    return NULL;
  }
  
+ static CommFunc find_anycommand(char *cmd)
+ {
+ 	CommFunc tmp;
+ 
+ 	if((tmp=find_command(cmd))) return tmp;
+ 	if((tmp=find_command(cmd))) return tmp;
+ 	if((tmp=find_wizcommand(cmd))) return tmp;
+ 	if((tmp=find_socketcommand(cmd))) return tmp;
+ 	return NULL;
+ }
+ 
  long xfire_kc2ks(player *p,KeyCode kc,long foozit)
  {
    if (p->eric_server == 0) {
***************
*** 333,344 ****
      }
      if ((cp=strchr(line, ' '))&&!strchr(line,';')) {
        *(cp++) ='\0';
!       if (!(newkey->func=find_command(line))) {
  		  cp[-1] =' ';
  		  cp =line;
        }
      } else {			/* ' ' */
!       if ((newkey->func=find_command(line))) {
  		  p->keys[ix] =newkey;
  		  return;
        }	
--- 348,359 ----
      }
      if ((cp=strchr(line, ' '))&&!strchr(line,';')) {
        *(cp++) ='\0';
!       if (!(newkey->func=find_anycommand(line))) {
  		  cp[-1] =' ';
  		  cp =line;
        }
      } else {			/* ' ' */
!       if ((newkey->func=find_anycommand(line))) {
  		  p->keys[ix] =newkey;
  		  return;
        }	
***************
*** 460,465 ****
--- 475,495 ----
    fclose(fp);
  }
  
+ char *find_any_func_name(CommFunc func)
+ {
+   int i;
+ 
+   for (i=0; i<CommandsSize; i++)
+     if (Commands[i].func == func)
+       return Commands[i].name;
+   for (i=0; i<SocketCommandsSize; i++)
+     if (SocketCommands[i].func == func)
+       return SocketCommands[i].name;
+   for (i=0; i<WizCommandsSize; i++)
+     if (WizCommands[i].func == func)
+       return WizCommands[i].name;
+   return "(null)";
+ }
  
  char *find_func_name(CommFunc func)
  {
diff -c -d -r crossfire-0.93.5.patch/server/gods.c crossfire-0.93.5/server/gods.c
*** crossfire-0.93.5.patch/server/gods.c	Mon Aug 18 05:45:14 1997
--- crossfire-0.93.5/server/gods.c	Tue Sep 30 16:31:28 1997
***************
*** 132,138 ****
    object *new_god = find_god(godname);
  
      if(!op||!new_god) return;
!     if(op->race&&new_god->slaying&&strstr(op->race,new_god->slaying)) { 
  	new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op,"Fool! %s detest your kind!",godname);
          if(RANDOM()%(op->level)-5>0) 
  	   cast_mana_storm(op,new_god->level+10);
--- 132,140 ----
    object *new_god = find_god(godname);
  
      if(!op||!new_god) return;
!     if(!QUERY_FLAG(op,FLAG_WIZ)&&op->race&&new_god->slaying&&
!        strstr(op->race,new_god->slaying))
!     { 
  	new_draw_info_format(NDI_UNIQUE|NDI_NAVY,0,op,"Fool! %s detest your kind!",godname);
          if(RANDOM()%(op->level)-5>0) 
  	   cast_mana_storm(op,new_god->level+10);
diff -c -d -r crossfire-0.93.5.patch/server/init.c crossfire-0.93.5/server/init.c
*** crossfire-0.93.5.patch/server/init.c	Mon Aug 18 05:45:14 1997
--- crossfire-0.93.5/server/init.c	Tue Sep 30 15:38:48 1997
***************
*** 35,40 ****
--- 35,42 ----
  #include <version.h>
  #include <X11/keysym.h>
  
+ struct archt *dm_arch;
+ 
  void set_chrfont(char *val) {    settings.chrfont=val; }
  void set_logfile(char *val) { settings.logfilename=val; }
  void set_servermode() { settings.servermode=SERVER_ENABLED; }
***************
*** 290,295 ****
--- 292,299 ----
      init_ericserver();
      init_socket();
      reset_sleep();
+     dm_arch=find_archetype("Ruggilli");
+     if(!dm_arch) LOG(llevError,"Can't find arch Ruggilli!\n");
      init_done=1;
  }
  
***************
*** 568,573 ****
--- 572,582 ----
  
  /* Signal handlers: */
  
+ void rec_alrm(int i)
+ {
+   if(shuttime>0) shuttime--;
+ }
+ 
  void rec_sigsegv(int i) {
    LOG(llevError,"\nSIGSEGV received.\n");
    fatal_signal(1, 1);
***************
*** 631,636 ****
--- 640,657 ----
  }
  
  void init_signals() {
+   struct sigaction act;
+   struct itimerval ival;
+ 
+   act.sa_handler=rec_alrm;
+   act.sa_mask=0;
+   act.sa_flags=SA_RESTART;
+   sigaction(SIGALRM,&act,NULL);
+   ival.it_interval.tv_sec=1;
+   ival.it_interval.tv_usec=0;
+   ival.it_value.tv_sec=1;
+   ival.it_value.tv_usec=0;
+   setitimer(ITIMER_REAL,&ival,NULL);
    signal(SIGHUP,rec_sighup);
    signal(SIGINT,rec_sigint);
    signal(SIGQUIT,rec_sigquit);
diff -c -d -r crossfire-0.93.5.patch/server/login.c crossfire-0.93.5/server/login.c
*** crossfire-0.93.5.patch/server/login.c	Tue Sep 30 10:18:19 1997
--- crossfire-0.93.5/server/login.c	Fri Sep 19 14:46:38 1997
***************
*** 40,82 ****
  
  /* If flag is non zero, it means that we want to try and save everyone, but
   * keep the game running.  Thus, we don't want to free any information.
   */
  void emergency_save(int flag) {
    player *pl;
! #ifndef NO_EMERGENCY_SAVE
!   trying_emergency_save = 1;
!   if(editor)
!     return;
!   LOG(llevError,"Emergency save:  ");
!   for(pl=first_player;pl!=NULL;pl=pl->next) {
!     if(!pl->ob) {
!       LOG(llevError, "No name, ignoring this.\n");
!       continue;
!     }
!     LOG(llevError,"%s ",pl->ob->name);
!     new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save...");
  
  /* If we are not exiting the game (ie, this is sort of a backup save), then
   * don't change the location back to the village.  Note that there are other
   * options to have backup saves be done at the starting village
   */
!     if (!flag) {
! 	strcpy(pl->maplevel, first_map_path);
! 	if(pl->ob->map!=NULL)
! 	    pl->ob->map = NULL;
! 	pl->ob->x = -1;
! 	pl->ob->y = -1;
!     }
!     if(!save_player(pl->ob,flag)) {
!       LOG(llevError, "(failed) ");
!       new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score...");
      }
!     check_score(pl->ob);
    }
-   LOG(llevError,"\n");
- #else
-   LOG(llevError,"Emergency saves disabled, no save attempted\n");
- #endif
    /* After we complete the emergency saves, then try and free
     * the pixmaps.  Without this effort, some X-Terminals (and maybe
     * even workstations) XServers will not free the space used by
--- 40,90 ----
  
  /* If flag is non zero, it means that we want to try and save everyone, but
   * keep the game running.  Thus, we don't want to free any information.
+  * If flag is 2, emergency save will be attempted even if they're disabled.
+  * That is for the shutdown code.
   */
  void emergency_save(int flag) {
    player *pl;
! #ifdef NO_EMERGENCY_SAVE
!   int emerg_save=0;
! #else
!   int emerg_save=1;
! #endif
! 
!   if(flag!=2&&!emerg_save) {
!     LOG(llevError,"Emergency saves disabled, no save attempted\n");
!   } else {
!     trying_emergency_save = 1;
!     if(editor)
!       return;
!     LOG(llevError,"Emergency save:  ");
!     for(pl=first_player;pl!=NULL;pl=pl->next) {
!       if(!pl->ob) {
!         LOG(llevError, "No name, ignoring this.\n");
!         continue;
!       }
!       LOG(llevError,"%s ",pl->ob->name);
!       new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save...");
  
  /* If we are not exiting the game (ie, this is sort of a backup save), then
   * don't change the location back to the village.  Note that there are other
   * options to have backup saves be done at the starting village
   */
!       if (!flag) {
! 	  strcpy(pl->maplevel, first_map_path);
! 	  if(pl->ob->map!=NULL)
! 	      pl->ob->map = NULL;
! 	  pl->ob->x = -1;
! 	  pl->ob->y = -1;
!       }
!       if(!save_player(pl->ob,flag)) {
!         LOG(llevError, "(failed) ");
!         new_draw_info(NDI_UNIQUE, 0,pl->ob,"Emergency save failed, checking score...");
!       }
!       check_score(pl->ob);
      }
!     LOG(llevError,"\n");
    }
    /* After we complete the emergency saves, then try and free
     * the pixmaps.  Without this effort, some X-Terminals (and maybe
     * even workstations) XServers will not free the space used by
***************
*** 247,252 ****
--- 255,264 ----
  
    flag&=1;
  
+   if(QUERY_FLAG(op,FLAG_WIZ)) {
+     new_draw_info(NDI_UNIQUE,0,op,"Use nodm before saving.\n");
+     return 0;
+   }
    if(QUERY_FLAG(op,FLAG_WAS_WIZ)||!pl->name_changed||(!flag&&!op->stats.exp)) {
      if(!flag) {
        new_draw_info(NDI_UNIQUE, 0,op,"Your game is not valid,");
diff -c -d -r crossfire-0.93.5.patch/server/main.c crossfire-0.93.5/server/main.c
*** crossfire-0.93.5.patch/server/main.c	Mon Aug 18 05:45:14 1997
--- crossfire-0.93.5/server/main.c	Tue Sep 30 16:32:53 1997
***************
*** 45,50 ****
--- 45,53 ----
  #include <time.h>
  #endif
  
+ int shuttime;
+ char *shutmsg=NULL;
+ 
  static char days[7][4] = {
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  
***************
*** 536,542 ****
  	    /* check for ST_PLAYING state so that we don't try to save off when
  	     * the player is logging in.
  	     */
! 	    if ((pl->last_save_tick+AUTOSAVE)<pticks && pl->state==ST_PLAYING) {
  		save_player(pl->ob,1);
  		pl->last_save_tick = pticks;
  	    }
--- 539,547 ----
  	    /* check for ST_PLAYING state so that we don't try to save off when
  	     * the player is logging in.
  	     */
! 	    if ((pl->last_save_tick+AUTOSAVE)<pticks && pl->state==ST_PLAYING
!                 && !QUERY_FLAG(pl->ob,FLAG_WAS_WIZ) &&
!                 !QUERY_FLAG(pl->ob,FLAG_WIZ)) {
  		save_player(pl->ob,1);
  		pl->last_save_tick = pticks;
  	    }
***************
*** 862,867 ****
--- 867,899 ----
  
  }
  
+ void shutdown_check(void)
+ {
+ 	if(shuttime>10&&!(shuttime%30)) shuttime--;
+ 	if(shuttime==-1) return;
+ 	if(shuttime==1) {
+ 		shuttime=0;
+ 		new_draw_info(NDI_ALL|NDI_RED,0,NULL,"Bye-bye!");
+ 		return;
+ 	}
+ 	if(!shuttime) {
+ 		emergency_save(3);
+ 		clean_tmp_files();
+ 		close_all_sockets();
+ 		exit(0);
+ 	}
+ 	if(shuttime<11) return;
+ 	if(shutmsg) {
+ 		new_draw_info_format(NDI_ALL|NDI_RED,0,NULL,"CF will shut down in %d"
+ 				     ".%d minute(s) (reason: %s)",shuttime/60,
+         	                     shuttime-(60*(shuttime/60)),shutmsg);
+ 	} else {
+ 		new_draw_info_format(NDI_ALL|NDI_RED,0,NULL,"CF will shut down in %d"
+ 				     ".%d minute(s)",shuttime/60,
+ 				     shuttime-(60*(shuttime/60)));
+ 	}
+ }
+ 
  /*
   * last_time is when the last tick was executed.
   * We don't need to know the timezone since we're only interested in
***************
*** 872,882 ****
  
  int main(int argc,char **argv)
  {
- 
  #ifdef DEBUG_MALLOC_LEVEL
    malloc_debug(DEBUG_MALLOC_LEVEL);
  #endif
  
    settings.argc=argc;
    settings.argv=argv;
    init(argc, argv);
--- 904,914 ----
  
  int main(int argc,char **argv)
  {
  #ifdef DEBUG_MALLOC_LEVEL
    malloc_debug(DEBUG_MALLOC_LEVEL);
  #endif
  
+   shuttime=-1;
    settings.argc=argc;
    settings.argv=argv;
    init(argc, argv);
***************
*** 887,892 ****
--- 919,925 ----
      setjmp(jump_addr);
  #endif
  
+     if(shuttime!=-1&&!(shuttime%30)||shuttime<11) { shutdown_check(); }
      check_socket();      /* Check for new connections/data */
      doeric_server();
      process_events(NULL);    /* "do" something with objects with speed */
diff -c -d -r crossfire-0.93.5.patch/server/player.c crossfire-0.93.5/server/player.c
*** crossfire-0.93.5.patch/server/player.c	Tue Sep 30 10:18:20 1997
--- crossfire-0.93.5/server/player.c	Tue Sep 30 15:53:59 1997
***************
*** 1498,1504 ****
  }
  
  int move_player(object *op,int dir) {
!   int face = dir ? (dir - 1) / 2 : -1;
  
    if(op->map == NULL || op->map->in_memory != MAP_IN_MEMORY)
      return 0;
--- 1498,1504 ----
  }
  
  int move_player(object *op,int dir) {
!   int face = dir ? (dir - 1) / 2 : 0;
  
    if(op->map == NULL || op->map->in_memory != MAP_IN_MEMORY)
      return 0;
***************
*** 1519,1533 ****
  
    if(op->contr->fire_on)
      fire(op,dir);
!   else move_player_attack(op,dir);
  
    if((check_pick(op)&&op->contr->run_on)||
       (op->contr->berzerk&&op->contr->run_on))
      op->direction=dir;
    else
      op->direction=0;
!   if(face != -1)
!     op->face = &new_faces[op->arch->faces[face]];
    update_object(op);
    return 0;
  }
--- 1519,1539 ----
  
    if(op->contr->fire_on)
      fire(op,dir);
!   else if(dir) move_player_attack(op,dir);
  
    if((check_pick(op)&&op->contr->run_on)||
       (op->contr->berzerk&&op->contr->run_on))
      op->direction=dir;
    else
      op->direction=0;
!   if(face != -1) {
!     if(!QUERY_FLAG(op,FLAG_WIZ))
!       op->face =  &new_faces[op->arch->faces[face]];
!     else
!       {
!         op->face = &new_faces[dm_arch->faces[face]];
!       }
!   }
    update_object(op);
    return 0;
  }
diff -c -d -r crossfire-0.93.5.patch/server/shop.c crossfire-0.93.5/server/shop.c
*** crossfire-0.93.5.patch/server/shop.c	Mon Aug 18 05:45:15 1997
--- crossfire-0.93.5/server/shop.c	Fri Sep 19 12:17:52 1997
***************
*** 299,305 ****
      object *tmp, *coin_objs[NUM_COINS];
      archetype *at;
  
!     if (item_cost==0) return 1;
      if(item_cost>query_money(pl))
          return 0;
  
--- 299,306 ----
      object *tmp, *coin_objs[NUM_COINS];
      archetype *at;
  
!     if (item_cost==0||QUERY_FLAG(op,FLAG_WAS_WIZ)||
!         QUERY_FLAG(pl,FLAG_WAS_WIZ)) return 1;
      if(item_cost>query_money(pl))
          return 0;
  
diff -c -d -r crossfire-0.93.5.patch/server/spell_util.c crossfire-0.93.5/server/spell_util.c
*** crossfire-0.93.5.patch/server/spell_util.c	Tue Sep 30 10:18:20 1997
--- crossfire-0.93.5/server/spell_util.c	Tue Sep 30 16:15:58 1997
***************
*** 156,162 ****
    int duration=SP_PARAMETERS[type].bdur;  /*  get the base duration */
  
  #ifdef MULTIPLE_GODS
!   if(!strcmp((godname=determine_god(op)),"none")) godname="A random spirit"; 
  #endif
  
    /* It looks like the only properties we ever care about from the casting
--- 156,162 ----
    int duration=SP_PARAMETERS[type].bdur;  /*  get the base duration */
  
  #ifdef MULTIPLE_GODS
!   if(!strcmp((godname=determine_god(op)),"none")) godname="A random spirit";
  #endif
  
    /* It looks like the only properties we ever care about from the casting

[to unsubscribe etc., send mail to crossfire-request@ifi.uio.no]