Crossfire Archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: CF: patch: merging items
On Jan 14, 7:45pm, Christian Stieber wrote:
> Subject: CF: patch: merging items
> Hi,
>
> this patch attempts to merge most items where merging makes sense.
> It is "preliminary" --- I'd like to change things to merge everything
> by default, but I'm not sure whether this would affect other things
> (like 2 monsters on the same field suddenly turning into "2 zombies" -:)).
>
> You also need gcc to compile --- things basically work as follows:
> - CAN_MERGE checks almost everything
That seems reasonable.
> - if nrof is 0, MakeMergeable() checks an array to see if the object
> should be merged (based on type). If yes, nrof is set to 1.
> This step needs gcc to initialize the array, but it should be easy to
> modify to work on any compiler. I'm just too lazy right now -:(
> I suppose I could even use if()s to check the type.
Do not do that. If nrof is 0, it is specific information that that object
should not be merged. If you think there are objects that should be merged but
have nrof in the archetypes, change the nrof - don't change program code
because that might be easier.
> Also, sometimes two seemingly mergeable objects are not merged. I assume
> that the FLAG_BEEN_APPLIED causes this. I left it in, because I have no
> idea what the flag is good for.
That flag is used for selling objects - if you have applied it, you have more
information about it than normal objects, and then get more money if you sell
it than if it was completely unidentified (but less money than if it was fully
identified.)
> diff -C 5 -r crossfire-0.93.7/common/object.c crossfire/common/object.c
> *** crossfire-0.93.7/common/object.c Tue Jan 6 10:29:18 1998
> --- crossfire/common/object.c Wed Jan 14 19:21:49 1998
> ***************
> *** 75,84 ****
> --- 75,86 ----
> *
> * Improvements made with merge: Better checking on potion, and also
> * check weight
> */
>
> + #define COMPARE_LIVING(Attr) || (ob1->stats.Attr!=ob2->stats.Attr)
> + #define COMPARE_OBJ(Attr) || (ob1->Attr!=ob2->Attr)
>
> INLINE int CAN_MERGE(object *ob1, object *ob2) {
>
> /* A couple quicksanity checks */
> if ((ob1 == ob2) || (ob1->type != ob2->type)) return 0;
> ***************
> *** 91,121 ****
> if (!QUERY_FLAG(ob1,FLAG_ANIMATE) && FABS((ob1)->speed) > 0.001 )
return 0;
>
> /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something
> * being locked in inventory should prevent merging.
> */
> ! if ((ob1->arch != ob2->arch) || (ob1->stats.sp != ob2->stats.sp) ||
> ! (ob1->flags[0] != ob2->flags[0]) || (ob1->flags[1] != ob2->flags[1]) ||
> ! ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~ 0x400000)) ||
> ! (ob1->flags[3] != ob2->flags[3]) || (ob1->magic != ob2->magic) ||
> ! (ob1->name != ob2->name) || (ob1->title != ob2->title) ||
> ! (ob1->msg != ob2->msg) || (ob1->stats.food != ob2->stats.food) ||
> ! (ob1->protected != ob2->protected) || (ob1->immune != ob2->immune) ||
> ! (ob1->vulnerable != ob2->vulnerable) || (ob1->weight != ob2->weight))
> return 0;
>
> switch (ob1->type) {
> case SCROLL:
> if (ob1->level != ob2->level) return 0;
> break;
> ! case POTION:
> ! /* This should compare the value of the stats, and not the pointer
> ! * itself. There can be cases were potions seem to loose their
> ! * plus
> ! */
> ! if (memcmp(&ob1->stats,&ob2->stats, sizeof(living))) return 0;
> ! break;
> }
> /* Everything passes, must be OK. */
> return 1;
> }
>
> --- 93,171 ----
> if (!QUERY_FLAG(ob1,FLAG_ANIMATE) && FABS((ob1)->speed) > 0.001 )
return 0;
>
> /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something
> * being locked in inventory should prevent merging.
> */
> ! if (0
> ! COMPARE_OBJ(arch)
> !
> ! COMPARE_OBJ(flags[0])
> ! COMPARE_OBJ(flags[1])
> ! COMPARE_OBJ(flags[2] & ~0x400000)
> ! COMPARE_OBJ(flags[3])
> !
> ! || QUERY_FLAG(ob1,FLAG_APPLIED)
> !
> ! COMPARE_OBJ(name)
> ! COMPARE_OBJ(title)
> ! COMPARE_OBJ(real_name)
> ! COMPARE_OBJ(real_title)
> !
> ! COMPARE_OBJ(msg)
> ! COMPARE_OBJ(weight)
> ! COMPARE_OBJ(magic)
> !
> ! COMPARE_OBJ(armour)
> !
> ! COMPARE_OBJ(vulnerable)
> ! COMPARE_OBJ(protected)
> ! COMPARE_OBJ(immune)
> !
> ! COMPARE_OBJ(attacktype)
> !
> ! COMPARE_OBJ(path_repelled)
> ! COMPARE_OBJ(path_attuned)
> ! COMPARE_OBJ(path_denied)
> !
> ! COMPARE_OBJ(slaying)
> !
> ! COMPARE_OBJ(material)
> ! /* COMPARE_OBJ(value) */ /* don't think this is needed */
> ! COMPARE_OBJ(level)
> !
> ! COMPARE_LIVING(food)
> !
> ! COMPARE_LIVING(Str)
> ! COMPARE_LIVING(Dex)
> ! COMPARE_LIVING(Con)
> ! COMPARE_LIVING(Wis)
> ! COMPARE_LIVING(Cha)
> ! COMPARE_LIVING(Int)
> ! COMPARE_LIVING(Pow)
> !
> ! COMPARE_LIVING(wc)
> ! COMPARE_LIVING(ac)
> !
> ! COMPARE_LIVING(dam)
> ! COMPARE_LIVING(luck)
> !
> ! COMPARE_LIVING(hp)
> ! COMPARE_LIVING(sp)
> ! COMPARE_LIVING(maxhp)
> ! COMPARE_LIVING(maxsp)
> !
> ! COMPARE_LIVING(exp)
> ! COMPARE_LIVING(grace)
> ! )
> return 0;
>
> switch (ob1->type) {
> + #if 0
> case SCROLL:
> if (ob1->level != ob2->level) return 0;
> break;
> ! #endif
> }
> /* Everything passes, must be OK. */
> return 1;
> }
>
> ***************
> *** 1084,1093 ****
> --- 1134,1168 ----
> )
> update_all_los(op->map); /* first_player is no longer set there
*/
>
> }
>
> + static object *MakeMergeable(object *ob)
> + {
> + static char Mergeable[500]={[WEAPON] 1,
> + [ARMOUR] 1,
> + [SHIELD] 1,
> + [HELMET] 1,
> + [FLESH] 1,
> + [CLOAK] 1,
> + [BOOK] 1,
> + [BOOTS] 1,
> + [GLOVES] 1,
> + [BRACERS] 1,
> + [GIRDLE] 1,
> + [RING] 1,
> + [AMULET] 1,
> + [SKILL] 1,
> + [SPELLBOOK] 1};
> +
> + if (ob!=NULL && ob->nrof==0 && Mergeable[ob->type])
> + {
> + ob->nrof=1;
> + }
> + return ob;
> + }
> +
> /*
> * merge_ob(op,top):
> *
> * This function goes through all objects below and including top, and
> * merges op to the first matching object.
> ***************
> *** 1094,1110 ****
> * If top is NULL, it is calculated.
> * Returns pointer to object if it succeded in the merge, otherwise NULL
> */
>
> object *merge_ob(object *op, object *top) {
> ! if(!op->nrof)
> ! return 0;
> if(top==NULL)
> for(top=op;top!=NULL&&top->above!=NULL;top=top->above);
> for(;top!=NULL;top=top->below) {
> if(top==op)
> continue;
> if (CAN_MERGE(op,top))
> {
> top->nrof+=op->nrof;
> CLEAR_FLAG(top,FLAG_STARTEQUIP);
> op->weight = 0; /* Don't want any adjustements now */
> --- 1169,1191 ----
> * If top is NULL, it is calculated.
> * Returns pointer to object if it succeded in the merge, otherwise NULL
> */
>
> object *merge_ob(object *op, object *top) {
> ! if (MakeMergeable(op)->nrof==0)
> ! {
> ! return 0;
> ! }
> if(top==NULL)
> for(top=op;top!=NULL&&top->above!=NULL;top=top->above);
> for(;top!=NULL;top=top->below) {
> if(top==op)
> continue;
> + if (MakeMergeable(top)->nrof==0)
> + {
> + continue;
> + }
> if (CAN_MERGE(op,top))
> {
> top->nrof+=op->nrof;
> CLEAR_FLAG(top,FLAG_STARTEQUIP);
> op->weight = 0; /* Don't want any adjustements now */
> ***************
> *** 1274,1284 ****
> }
> if(op->more!=NULL) {
> insert_ob_in_map(op->more,m);
> }
> CLEAR_FLAG(op,FLAG_REMOVED);
> ! if(op->nrof)
> for(tmp=get_map_ob(m,op->x,op->y);tmp!=NULL;tmp=tmp->above)
> if (CAN_MERGE(op,tmp))
> {
> op->nrof+=tmp->nrof;
> CLEAR_FLAG(op,FLAG_STARTEQUIP);
> --- 1355,1365 ----
> }
> if(op->more!=NULL) {
> insert_ob_in_map(op->more,m);
> }
> CLEAR_FLAG(op,FLAG_REMOVED);
> ! if(MakeMergeable(op)->nrof)
> for(tmp=get_map_ob(m,op->x,op->y);tmp!=NULL;tmp=tmp->above)
> if (CAN_MERGE(op,tmp))
> {
> op->nrof+=tmp->nrof;
> CLEAR_FLAG(op,FLAG_STARTEQUIP);
> ***************
> *** 1573,1583 ****
> LOG(llevError, "Tried to insert multipart object %s (%d)\n",
> op->name, op->count);
> return op;
> }
> CLEAR_FLAG(op, FLAG_REMOVED);
> ! if(op->nrof) {
> for(tmp=where->inv;tmp!=NULL;tmp=tmp->below)
> if ( CAN_MERGE(tmp,op) ) {
> /* return the original object and remove inserted object
> (client needs the original object) */
> tmp->nrof += op->nrof;
> --- 1654,1664 ----
> LOG(llevError, "Tried to insert multipart object %s (%d)\n",
> op->name, op->count);
> return op;
> }
> CLEAR_FLAG(op, FLAG_REMOVED);
> ! if(MakeMergeable(op)->nrof) {
> for(tmp=where->inv;tmp!=NULL;tmp=tmp->below)
> if ( CAN_MERGE(tmp,op) ) {
> /* return the original object and remove inserted object
> (client needs the original object) */
> tmp->nrof += op->nrof;
> diff -C 5 -r crossfire-0.93.7/server/apply.c crossfire/server/apply.c
> *** crossfire-0.93.7/server/apply.c Tue Jan 6 10:29:23 1998
> --- crossfire/server/apply.c Wed Jan 14 19:21:50 1998
> ***************
> *** 1562,1583 ****
>
> new_draw_info_format(NDI_UNIQUE, 0, op,
> "The spellbook contains the %s level spell %s.",
> get_levelnumber(spells[tmp->stats.sp].level),
> spells[tmp->stats.sp].name);
> if(check_spell_known(op,tmp->stats.sp)) {
> new_draw_info(NDI_UNIQUE, 0,op,"You already know that spell.\n");
> -
> - if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
> - identify(tmp);
> - if (op->contr->eric_server > 0)
> - esrv_send_item(op, tmp);
> - else if (tmp->env)
> - draw_inventory(op);
> - else
> - draw_look(op);
> - }
> return 1;
> }
> /* I changed spell learning in 3 ways:
> *
> * 1- MU spells use Int to learn, Cleric spells use Wisdom
> --- 1562,1582 ----
>
> new_draw_info_format(NDI_UNIQUE, 0, op,
> "The spellbook contains the %s level spell %s.",
> get_levelnumber(spells[tmp->stats.sp].level),
> spells[tmp->stats.sp].name);
> + if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) {
> + identify(tmp);
> + if (op->contr->eric_server > 0)
> + esrv_send_item(op, tmp);
> + else if (tmp->env)
> + draw_inventory(op);
> + else
> + draw_look(op);
> + }
> if(check_spell_known(op,tmp->stats.sp)) {
> new_draw_info(NDI_UNIQUE, 0,op,"You already know that spell.\n");
> return 1;
> }
> /* I changed spell learning in 3 ways:
> *
> * 1- MU spells use Int to learn, Cleric spells use Wisdom
> ***************
> *** 1612,1623 ****
> #ifdef SOUND_EFFECTS
> play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL);
> #endif
> new_draw_info(NDI_UNIQUE, 0,op,"You fail to learn the spell.\n");
> }
> ! remove_ob(tmp);
> ! free_object(tmp);
> return 1;
> case SCROLL: {
> int scroll_spell=tmp->stats.sp, old_spell=0;
> rangetype old_shoot=range_none;
>
> --- 1611,1621 ----
> #ifdef SOUND_EFFECTS
> play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL);
> #endif
> new_draw_info(NDI_UNIQUE, 0,op,"You fail to learn the spell.\n");
> }
> ! decrease_ob(tmp);
> return 1;
> case SCROLL: {
> int scroll_spell=tmp->stats.sp, old_spell=0;
> rangetype old_shoot=range_none;
>
> [to unsubscribe etc., send mail to crossfire-request@ifi.uio.no]
>-- End of excerpt from Christian Stieber
--
-- Mark Wedel
mark@pyramid.com
[to unsubscribe etc., send mail to crossfire-request@ifi.uio.no]
Follow-Ups:
References: