[CF-Devel] Bug in stealing code

crossfire-devel at archives.real-time.com crossfire-devel at archives.real-time.com
Fri May 28 16:02:51 CDT 2004


When an attempt to steal an item fails, the moved object may vanish from
the inventory view in the client.

In server/skills.c the function attempt_steal() reads

	else if (roll < chance ) {
	    if (op->type == PLAYER)
		esrv_del_item(op->contr, tmp->count);
	    pick_up(who, tmp);

The function pick_up() may fail (for various reasons). When this
happens, the item has been removed from the inventory view but may
actually remain in the inventory.

My attached patch tries to fix this. I tested it (player stealing from
monster into inventory or container; monster stealing from player with
or without success) but I still have some questions:

 1. I assume that

        for(tmp = op->inv; tmp != NULL; tmp = next)
            assert(tmp->env == op);

    hold for all items in the game.

    Is this assumption correct? If not: how can I detect if the object
    was actually moved? (The current "who == is_player_inv(tmp)"
    does not hold for monsters stealing items, I presume.)

 2. If the function pick_up() destroys the object (though don't know if
    that can happen here) attempt_steal() uses this object afterwards
    (as "tmp" or "success"). Is this acceptable?

 3. The character weight in the client does not get updated. Even the
    command 'fix_me' executed from the client does not fix it.

    How should I fix this issue?
-------------- next part --------------
Index: server/skills.c
===================================================================
RCS file: /cvsroot/crossfire/crossfire/server/skills.c,v
retrieving revision 1.51
diff -u -w -r1.51 skills.c
--- server/skills.c	12 May 2004 04:43:06 -0000	1.51
+++ server/skills.c	28 May 2004 19:41:19 -0000
@@ -146,15 +146,18 @@
 	if((chance=adj_stealchance(who,op,(stats_value+skill->level * 10 - op->level * 3)))==-1)
 	    return 0;
 	else if (roll < chance ) {
-	    if (op->type == PLAYER)
-		esrv_del_item(op->contr, tmp->count);
+	    tag_t tmp_count = tmp->count;
+
 	    pick_up(who, tmp);
 	    /* need to see if the player actually stole this item -
 	     * if it is in the players inv, assume it is.  This prevents
 	     * abuses where the player can not carry the item, so just
 	     * keeps stealing it over and over.
 	     */
-	    if (who == is_player_inv(tmp)) {
+	    if(was_destroyed(tmp, tmp_count) || tmp->env != op) {
+		if(op->type == PLAYER) {
+		    esrv_del_item(op->contr, tmp_count);
+		}
 		/* for players, play_sound: steals item */
 		success = tmp;
 		CLEAR_FLAG(tmp, FLAG_INV_LOCKED);
-------------- next part --------------
_______________________________________________
crossfire-devel mailing list
     
     crossfire-devel at lists.real-time.com
     
     
     https://mailman.real-time.com/mailman/listinfo/crossfire-devel
     
     
    


More information about the crossfire mailing list