THis patch is for version 1.0.0 of the server. It implements a new autopickup scheme that's basically a superset of the old one, but it doesn't break compatibility so old clients will still work normally with it. One big change was turning mode from uint16->32; this requires all server files to be recompiled otherwise you'll see nice segv's. Nils. -------------- next part -------------- diff -ruN crossfire-1.0.0/include/define.h crossfire-1.0.0.autopickup/include/define.h --- crossfire-1.0.0/include/define.h Sun May 13 23:55:41 2001 +++ crossfire-1.0.0.autopickup/include/define.h Thu Aug 2 18:48:33 2001 @@ -257,6 +257,42 @@ #define MAX_NAME 16 #define BIG_NAME 32 + +/* definitions for detailed pickup descriptions. + * The objective is to define intelligent groups of items that the + * user can pick up or leave as he likes. */ + +/* high bit as flag for new pickup options */ +#define PU_NOTHING 0x00000000 + +#define PU_DEBUG 0x10000000 +#define PU_INHIBIT 0x20000000 +#define PU_STOP 0x40000000 +#define PU_NEWMODE 0x80000000 + +#define PU_RATIO 0x0000000F + +#define PU_FOOD 0x00000010 +#define PU_DRINK 0x00000020 +#define PU_VALUABLES 0x00000040 +#define PU_BOW 0x00000080 + +#define PU_ARROW 0x00000100 +#define PU_HELMET 0x00000200 +#define PU_SHIELD 0x00000400 +#define PU_ARMOUR 0x00000800 + +#define PU_BOOTS 0x00001000 +#define PU_GLOVES 0x00002000 +#define PU_CLOAK 0x00004000 +#define PU_KEY 0x00008000 + +#define PU_MISSILEWEAPON 0x00010000 +#define PU_ALLWEAPON 0x00020000 +#define PU_MAGICAL 0x00040000 +#define PU_POTION 0x00080000 + + /* Instead of using arbitrary constants for indexing the * freearr, add these values. <= SIZEOFFREE1 will get you * within 1 space. <= SIZEOFFREE2 wll get you withing @@ -354,6 +390,7 @@ #define FLAG_APPLIED 5 /* Object is ready for use by living */ #define FLAG_UNPAID 6 /* Object hasn't been paid for yet */ #define FLAG_AN 7 /* Name must be prepended by "an", not "a"*/ + #define FLAG_NO_PICK 8 /* Object can't be picked up */ #define FLAG_WALK_ON 9 /* Applied when it's walked upon */ #define FLAG_NO_PASS 10 /* Nothing can pass (wall() is true) */ @@ -362,6 +399,7 @@ #define FLAG_FLYING 13 /* Not affected by WALK_ON or SLOW_MOVE) */ #define FLAG_MONSTER 14 /* Will attack players */ #define FLAG_FRIENDLY 15 /* Will help players */ + #define FLAG_GENERATOR 16 /* Will generate type ob->stats.food */ #define FLAG_IS_THROWN 17 /* Object is designed to be thrown. */ #define FLAG_AUTO_APPLY 18 /* Will be applied when created */ @@ -371,6 +409,7 @@ #define FLAG_CAN_ROLL 22 /* Object can be rolled */ /* FLAG_IS_TURNING is no longer used */ /*#define FLAG_IS_TURNING 23 *//* Object will turn after player */ + #define FLAG_IS_TURNABLE 24 /* Object can change face with direction */ #define FLAG_WALK_OFF 25 /* Object is applied when left */ #define FLAG_FLY_ON 26 /* As WALK_ON, but only with FLAG_FLYING */ @@ -379,6 +418,7 @@ #define FLAG_IDENTIFIED 29 /* Not implemented yet */ #define FLAG_REFLECTING 30 /* Object reflects from walls (lightning) */ #define FLAG_CHANGING 31 /* Changes to other_arch when anim is done*/ + /* Start of values in flags[1] */ #define FLAG_SPLITTING 32 /* Object splits into stats.food other objs */ #define FLAG_HITBACK 33 /* Object will hit back when hit */ @@ -388,6 +428,7 @@ #define FLAG_SCARED 37 /* Monster is scared (mb player in future)*/ #define FLAG_UNAGGRESSIVE 38 /* Monster doesn't attack players */ #define FLAG_REFL_MISSILE 39 /* Arrows will reflect from object */ + #define FLAG_REFL_SPELL 40 /* Spells (some) will reflect from object */ #define FLAG_NO_MAGIC 41 /* Spells (some) can't pass this object */ #define FLAG_NO_FIX_PLAYER 42 /* fix_player() won't be called */ @@ -398,6 +439,7 @@ #define FLAG_PASS_THRU 46 /* Objects with can_pass_thru can pass \ thru this object as if it wasn't there */ #define FLAG_CAN_PASS_THRU 47 /* Can pass thru... */ + #define FLAG_PICK_UP 48 /* Can pick up */ #define FLAG_UNIQUE 49 /* Item is really unique (UNIQUE_ITEMS) */ #define FLAG_NO_DROP 50 /* Object can't be dropped */ @@ -406,6 +448,7 @@ #define FLAG_USE_SCROLL 53 /* (Monster) can read scroll */ #define FLAG_USE_WAND 54 /* (Monster) can apply and use wands */ #define FLAG_USE_BOW 55 /* (Monster) can apply and fire bows */ + #define FLAG_USE_ARMOUR 56 /* (Monster) can wear armour/shield/helmet */ #define FLAG_USE_WEAPON 57 /* (Monster) can wield weapons */ #define FLAG_USE_RING 58 /* (Monster) can use rings, boots, gauntlets, etc */ @@ -414,8 +457,9 @@ #define FLAG_XRAYS 61 /* X-ray vision */ #define FLAG_NO_APPLY 62 /* Avoids step_on/fly_on to this object */ #define FLAG_IS_FLOOR 63 /* Can't see what's underneath this object */ -#define FLAG_LIFESAVE 64 /* Saves a players' life once, then destr. */ + /* Start of values in flags[2] */ +#define FLAG_LIFESAVE 64 /* Saves a players' life once, then destr. */ #define FLAG_NO_STRENGTH 65 /* Strength-bonus not added to wc/dam */ #define FLAG_SLEEP 66 /* NPC is sleeping */ #define FLAG_STAND_STILL 67 /* NPC will not (ever) move */ @@ -423,6 +467,7 @@ #define FLAG_ONLY_ATTACK 69 /* NPC will evaporate if there is no enemy */ #define FLAG_CONFUSED 70 /* Will also be unable to cast spells */ #define FLAG_STEALTH 71 /* Will wake monsters with less range */ + #define FLAG_WIZPASS 72 /* The wizard can go through walls */ #define FLAG_IS_LINKED 73 /* The object is linked with other objects */ #define FLAG_CURSED 74 /* The object is cursed */ @@ -431,6 +476,7 @@ #define FLAG_KNOWN_MAGICAL 77 /* The object is known to be magical */ #define FLAG_KNOWN_CURSED 78 /* The object is known to be cursed */ #define FLAG_CAN_USE_SKILL 79 /* The monster can use skills */ + #define FLAG_BEEN_APPLIED 80 /* The object has been applied */ #define FLAG_READY_ROD 81 /* (Monster) has a rod readied... 8) */ #define FLAG_USE_ROD 82 /* (Monster) can apply and use rods */ @@ -439,6 +485,7 @@ #define FLAG_MAKE_INVIS 85 /* (Item) gives invisibility when applied */ #define FLAG_INV_LOCKED 86 /* Item will not be dropped from inventory */ #define FLAG_IS_WOODED 87 /* Item is wooded terrain */ + #define FLAG_IS_HILLY 88 /* Item is hilly/mountain terrain */ #define FLAG_READY_SKILL 89 /* (Monster or Player) has a skill readied */ #define FLAG_READY_WEAPON 90 /* (Monster or Player) has a weapon readied */ @@ -447,6 +494,7 @@ #define FLAG_SEE_IN_DARK 93 /* if set ob not effected by darkness */ #define FLAG_IS_CAULDRON 94 /* container can make alchemical stuff */ #define FLAG_DUST 95 /* item is a 'powder', effects throwing */ + /* Start of values in flags[3] */ #define FLAG_NO_STEAL 96 /* Item can't be stolen */ #define FLAG_ONE_HIT 97 /* Monster can only hit once before going diff -ruN crossfire-1.0.0/include/player.h crossfire-1.0.0.autopickup/include/player.h --- crossfire-1.0.0/include/player.h Sun May 13 23:55:41 2001 +++ crossfire-1.0.0.autopickup/include/player.h Thu Aug 2 12:58:59 2001 @@ -89,7 +89,7 @@ unsigned char prev_fire_on; unsigned char prev_keycode; /* Previous command executed */ unsigned char key_down; /* Last move-key still held down */ - uint16 mode; /* Mode of player for pickup. */ + uint32 mode; /* Mode of player for pickup. */ signed char digestion; /* Any bonuses/penalties to digestion */ signed char gen_hp; /* Bonuses to regeneration speed of hp */ signed char gen_sp; /* Bonuses to regeneration speed of sp */ Binary files crossfire-1.0.0/random_maps/standalone.o and crossfire-1.0.0.autopickup/random_maps/standalone.o differ diff -ruN crossfire-1.0.0/server/c_object.c crossfire-1.0.0.autopickup/server/c_object.c --- crossfire-1.0.0/server/c_object.c Sun May 13 23:55:41 2001 +++ crossfire-1.0.0.autopickup/server/c_object.c Thu Aug 2 21:27:46 2001 @@ -1235,19 +1235,99 @@ int command_pickup (object *op, char *params) { - int i; + unsigned int i, j; + char putstring[128]; if(!params) { + /* if the new mode is used, just print the settings */ + /* yes, a GOTO is ugly, but its simpple and should stay until this + * mode is cleanly integrated and the old one deprecated */ + if(op->contr->mode & PU_NEWMODE) + { + i=op->contr->mode; + goto NEWPICKUP; + } + if(1)fprintf(stderr,"command_pickup: !params\n"); op->contr->count_left=0; set_pickup_mode(op, (op->contr->mode > 6)? 0: op->contr->mode+1); return 0; } if(params==NULL || !sscanf(params, "%d", &i) || i<0 ) { - new_draw_info(NDI_UNIQUE, 0,op,"Usage: pickup <0-7> or <value_density> ."); - return 1; - } - set_pickup_mode(op,i); - return 1; + if(1)fprintf(stderr,"command_pickup: params==NULL\n"); + new_draw_info(NDI_UNIQUE, 0,op,"Usage: pickup <0-7> or <value_density> ."); + return 1; + } + set_pickup_mode(op,i); + + + sprintf(putstring,"command_pickup: set_pickup_mode\ndec %u, 0x%x", i, i); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"0b"); + for(j=0;j<32;j++) + { + strcat(putstring,((i>>(31-j))&0x01)?"1":"0"); + if(!((j+1)%4))strcat(putstring," "); + } + new_draw_info(NDI_UNIQUE, 0,op,putstring); + +#if 1 +NEWPICKUP: + if(!(i & PU_NEWMODE)) return 1; + + sprintf(putstring,"%d NEWMODE",i & PU_NEWMODE?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d DEBUG",i & PU_DEBUG?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d INHIBIT",i & PU_INHIBIT?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d STOP",i & PU_STOP?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d <= x pickup weight/value RATIO (0==off)",(i & PU_RATIO)*5); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d FOOD",i & PU_FOOD?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d DRINK",i & PU_DRINK?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d VALUABLES",i & PU_VALUABLES?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d BOW",i & PU_BOW?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d ARROW",i & PU_ARROW?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d HELMET",i & PU_HELMET?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d SHIELD",i & PU_SHIELD?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d ARMOUR",i & PU_ARMOUR?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d BOOTS",i & PU_BOOTS?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d GLOVES",i & PU_GLOVES?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d CLOAK",i & PU_CLOAK?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d KEY",i & PU_KEY?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"%d MISSILEWEAPON",i & PU_MISSILEWEAPON?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d ALLWEAPON",i & PU_ALLWEAPON?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d MAGICAL",i & PU_MAGICAL?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + sprintf(putstring,"%d POTION",i & PU_POTION?1:0); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + new_draw_info(NDI_UNIQUE, 0,op,""); +#endif + + return 1; } void set_pickup_mode(object *op,int i) { diff -ruN crossfire-1.0.0/server/player.c crossfire-1.0.0.autopickup/server/player.c --- crossfire-1.0.0/server/player.c Sun May 13 23:55:41 2001 +++ crossfire-1.0.0.autopickup/server/player.c Fri Aug 3 15:21:19 2001 @@ -184,7 +184,7 @@ */ if (checkbanned (defname, ns->host)){ - fprintf (logfile, "Banned player tryed to add. [%s@%s]\n", defname, ns->host); + fprintf (logfile, "Banned player tried to add. [%s@%s]\n", defname, ns->host); fflush (logfile); return 0; } @@ -863,7 +863,11 @@ object *tmp, *next; tag_t next_tag=0, op_tag; int stop = 0; + int j, k, wvratio; + char putstring[128], tmpstr[16]; + + /* if you're flying, you cna't pick up anything */ if (QUERY_FLAG (op, FLAG_FLYING)) return 1; @@ -872,6 +876,9 @@ next = op->below; if (next) next_tag = next->count; + + /* loop while there are items on the floor that are not marked as + * destroyed */ while (next && ! was_destroyed (next, next_tag)) { tmp = next; @@ -894,28 +901,21 @@ } #endif /* SEARCH_ITEMS */ + /* high bit set? We're using the new autopickup model */ + if(!(op->contr->mode & PU_NEWMODE)) + { switch (op->contr->mode) { case 0: return 1; /* don't pick up */ - - case 1: - pick_up (op, tmp); + case 1: pick_up (op, tmp); return 1; - - case 2: - pick_up (op, tmp); + case 2: pick_up (op, tmp); return 0; - case 3: return 0; /* stop before pickup */ - - case 4: - pick_up (op, tmp); + case 4: pick_up (op, tmp); break; - - case 5: - pick_up (op, tmp); + case 5: pick_up (op, tmp); stop = 1; break; - case 6: if (QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && ! QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)) @@ -935,6 +935,179 @@ >= op->contr->mode) pick_up(op,tmp); } + } /* old model */ + else + { + /* NEW pickup handling */ + if(op->contr->mode & PU_DEBUG) + { + /* some debugging code to figure out item information */ + if(tmp->name!=NULL) + sprintf(putstring,"item name: %s item type: %d weight/value: %d", + tmp->name, tmp->type, + (query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); + else + sprintf(putstring,"item name: %s item type: %d weight/value: %d", + tmp->arch->name, tmp->type, + (query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1)))); + new_draw_info(NDI_UNIQUE, 0,op,putstring); + + sprintf(putstring,"...flags: "); + for(k=0;k<4;k++) + { + for(j=0;j<32;j++) + { + if((tmp->flags[k]>>j)&0x01) + { + sprintf(tmpstr,"%d ",k*32+j); + strcat(putstring, tmpstr); + } + } + } + new_draw_info(NDI_UNIQUE, 0,op,putstring); + +#if 0 + /* print the flags too */ + for(k=0;k<4;k++) + { + fprintf(stderr,"%d [%d] ", k, k*32+31); + for(j=0;j<32;j++) + { + fprintf(stderr,"%d",tmp->flags[k]>>(31-j)&0x01); + if(!((j+1)%4))fprintf(stderr," "); + } + fprintf(stderr," [%d]\n", k*32); + } +#endif + } + /* philosophy: + * It's easy to grab an item type from a pile, as long as it's + * generic. This takes no game-time. For more detailed pickups + * and selections, select-items shoul dbe used. This is a + * grab-as-you-run type mode that's really useful for arrows for + * example. + * The drawback: right now it has no frontend, so you need to + * stick the bits you want into a calculator in hex mode and then + * convert to decimal and then 'pickup <#> + */ + + /* the first two modes are exclusive: if NOTHING we return, if + * STOP then we stop. All the rest are applied sequentially, + * meaning if any test passes, the item gets picked up. */ + + /* if mode is set to pick nothing up, return */ + if(op->contr->mode & PU_NOTHING) return 1; + /* if mode is set to stop when encountering objects, return */ + /* take STOP before INHIBIT since it doesn't actually pick + * anything up */ + if(op->contr->mode & PU_STOP) return 0; + /* useful for going into stores and not losing your settings... */ + /* and for battles wher you don't want to get loaded down while + * fighting *. + if(op->contr->mode & PU_INHIBIT) return 1; + + /* prevent us from turning into auto-thieves :) */ + if (QUERY_FLAG (tmp, FLAG_UNPAID)) continue; + + /* all food and drink if desired */ + /* question: don't pick up known-poisonous stuff? */ + if(op->contr->mode & PU_FOOD) + if (tmp->type == FOOD) + { pick_up(op, tmp); if(0)fprintf(stderr,"FOOD\n"); continue; } + if(op->contr->mode & PU_DRINK) + if (tmp->type == DRINK) + { pick_up(op, tmp); if(0)fprintf(stderr,"DRINK\n"); continue; } + if(op->contr->mode & PU_POTION) + if (tmp->type == POTION) + { pick_up(op, tmp); if(0)fprintf(stderr,"POTION\n"); continue; } + + /* pick up all magical items */ + if(op->contr->mode & PU_MAGICAL) + if (QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && ! QUERY_FLAG(tmp, FLAG_KNOWN_CURSED)) + { pick_up(op, tmp); if(0)fprintf(stderr,"MAGICAL\n"); continue; } + + if(op->contr->mode & PU_VALUABLES) + { + if (tmp->type == MONEY || tmp->type == GEM) + { pick_up(op, tmp); if(0)fprintf(stderr,"MONEY/GEM\n"); continue; } + } + + /* bows and arrows. Bows are good for selling! */ + if(op->contr->mode & PU_BOW) + if (tmp->type == BOW) + { pick_up(op, tmp); if(0)fprintf(stderr,"BOW\n"); continue; } + if(op->contr->mode & PU_ARROW) + if (tmp->type == ARROW) + { pick_up(op, tmp); if(0)fprintf(stderr,"ARROW\n"); continue; } + + /* all kinds of armor etc. */ + if(op->contr->mode & PU_ARMOUR) + if (tmp->type == ARMOUR) + { pick_up(op, tmp); if(0)fprintf(stderr,"ARMOUR\n"); continue; } + if(op->contr->mode & PU_HELMET) + if (tmp->type == HELMET) + { pick_up(op, tmp); if(0)fprintf(stderr,"HELMET\n"); continue; } + if(op->contr->mode & PU_SHIELD) + if (tmp->type == SHIELD) + { pick_up(op, tmp); if(0)fprintf(stderr,"SHIELD\n"); continue; } + if(op->contr->mode & PU_BOOTS) + if (tmp->type == BOOTS) + { pick_up(op, tmp); if(0)fprintf(stderr,"BOOTS\n"); continue; } + if(op->contr->mode & PU_GLOVES) + if (tmp->type == GLOVES) + { pick_up(op, tmp); if(0)fprintf(stderr,"GLOVES\n"); continue; } + if(op->contr->mode & PU_CLOAK) + if (tmp->type == CLOAK) + { pick_up(op, tmp); if(0)fprintf(stderr,"GLOVES\n"); continue; } + + /* hoping to catch throwing daggers here */ + if(op->contr->mode & PU_MISSILEWEAPON) + if(tmp->type == WEAPON && QUERY_FLAG(tmp, FLAG_IS_THROWN)) + { pick_up(op, tmp); if(0)fprintf(stderr,"MISSILEWEAPON\n"); continue; } + + /* careful: chairs and tables are weapons! */ + if(op->contr->mode & PU_ALLWEAPON) + { + if(tmp->type == WEAPON && tmp->name!=NULL) + { + if(strstr(tmp->name,"table")==NULL && + strstr(tmp->name,"chair")==NULL) + { pick_up(op, tmp); if(0)fprintf(stderr,"WEAPON\n"); continue; } + } + if(tmp->type == WEAPON && tmp->name==NULL) + { + if(strstr(tmp->arch->name,"table")==NULL && + strstr(tmp->arch->name,"chair")==NULL) + { pick_up(op, tmp); if(0)fprintf(stderr,"WEAPON\n"); continue; } + } + } + + /* misc stuff that's useful */ + if(op->contr->mode & PU_KEY) + if (tmp->type == KEY || tmp->type == SPECIAL_KEY) + { pick_up(op, tmp); if(0)fprintf(stderr,"KEY\n"); continue; } + + /* any of the last 4 bits set means we use the ratio for value + * pickups */ + if(op->contr->mode & PU_RATIO) + { + /* use value density to decide what else to grab */ + /* >=7 was >= op->contr->mode */ + /* >=7 is the old standard setting. Now we take the last 4 bits + * and multiply them by 5, giving 0..15*5== 5..75 */ + wvratio=(op->contr->mode & PU_RATIO) * 5; + if ((query_cost(tmp, op, F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof, 1))) >= wvratio) + { + pick_up(op, tmp); + if(0)fprintf(stderr,"HIGH WEIGHT/VALUE ["); + if(tmp->name!=NULL) if(0)fprintf(stderr,"%s", tmp->name); + else if(0)fprintf(stderr,"%s",tmp->arch->name); + if(0)fprintf(stderr,",%d] = ", tmp->type); + if(0)fprintf(stderr,"%d\n",query_cost(tmp,op,F_TRUE)*100 / (tmp->weight * MAX(tmp->nrof,1))); + continue; + } + } + } /* the new pickup model */ } return ! stop; }