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

Some server bugs, oddities, and fixes



I've tried Crossfire for the first time in a long while, and I've noticed a
few bugs.  I have fixes for some of them.  This is rather longish and
probably only of interest to developers.

1) Map saves - When a unique map as a temporary file and also marked as
compressed, it can never be loaded again.  The reason for this is in
common/map.c line 942.  The code there tags a .gz suffix on the filename. The
code at line 960 then refuses to actually compress it since it's a temporary
file.  Since it has the .gz suffix without being compressed, the server has
problems loading it, since gunzip fails.  The patch makes the test at 960
match the test at 942 (map.c.uniquemapsave.diff)

2) There's a bug somewhere that I haven't tracked down that causes the name
of items to be changed to reflect how many items there are.  So, if I have
"two key", under some conditions I can end up with "two two key", or "a a
keychain".  I haven't quite locked down what the conditions that cause this
are.  Anyone else see this?

3) The command "pickup 6" causes the player to automatically pick up all
magic items.  The problem is, it picks up all items if they are magic without
regard for if the player knows if they are magic.  In a multiplayer game,
removing the advantage of one class (casters who can cast 'detect magic')
gives an advantage to another class (non-casters who can't).  I've fixed this
in my server by  changing the is_magical(item) on line 843 of server/player.c
to QUERY_FLAG(item, KNOWN_MAGICAL). (player.c.pickup.diff)

4) This brings up another quirk.  This is a multiplayer game.  If I cast a
detect magic, other players who weren't there when I cast it shouldn't be able
to see if the item is magical. My spell, my knowledge.  I think the
KNOWN_MAGICAL flag needs to be replaced. The only alternative I can see adds
complication.  That is, storing the object's state in the player's data.  The
changes I'd suggest are these:

 - An object's "identified" flag is reset when it is dropped outside of a
   store.

 - A structure is created:

   struct obj_known {
     object *op;           /* object pointer */
     uint32 flags[4];      /* what do I know about this object */
     struct mapdef * map;  /* what map was it on when I knew about it */
     sint16 x,y;           /* where was it on the map when I knew about it */
   }

 - This structure holds what I know about this object that no one else does. 
   Each player will have an array of this structure with intelligence*3
   elements or so (a character can't remember everything).  When a detect
   magic spell is cast, any magical items are noted in the player's array,
   plus any other players who are in the cast area of the spell.

 - When the player's array is full, and more items are to be added, they
   overwrite the oldest.

 - When a player comes in contact with the item again, if it is in the same
   location it was before, and if it is still 'remembered', then the player
   knows everything about it that was known before.

I'd be happy to make a sample diff of these changes.  It could be an option
that is set in config.h perhaps.

        Kurt.

--- ../../crossfire-clean/server/player.c	Mon Jul 12 23:42:16 1999
+++ player.c	Sun Jan 16 15:40:57 2000
@@ -838,11 +838,11 @@
 	    
 	    for (item = op->below; item; item=temp) {
 		temp = item->below;
 		if (can_pick(op, item)) {
 			if (op->contr->mode==6) {
-			    if (is_magical(item) &&
+			    if (QUERY_FLAG(item, FLAG_KNOWN_MAGICAL) &&
 			      !QUERY_FLAG(item, FLAG_KNOWN_CURSED)) {
 				pick_up(op, item);
 			    }
 			}
 			else if (op->contr->mode==7) {
--- ../../crossfire-clean/common/map.c	Mon Jul 12 23:42:14 1999
+++ map.c	Sun Jan 16 15:24:01 2000
@@ -955,11 +955,12 @@
     if (!m->map_object) {
 	LOG(llevError, "no map object for map %s!\n", m->path);
 	return -1;
     }
 
-    if (m->compressed && flag) { /* Compress if it isn't a temporary save */
+    /* Compress if it isn't a temporary save, or if it's unique */
+    if (m->compressed && (QUERY_FLAG(m->map_object, FLAG_UNIQUE) || flag)) {
 	char buf[MAX_BUF];
 	strcpy(buf, uncomp[m->compressed][2]);
 	strcat(buf, " > ");
 	strcat(buf, filename);
 	fp = popen(buf, "w");