/** * Recharge activatable objects in the player's equipment * and rods in the inventory and on the ground. */ static void recharge_objects(void) { int i; bool discharged_stack; struct object *obj; /* Recharge carried gear */ for (obj = player->gear; obj; obj = obj->next) { /* Skip non-objects */ assert(obj->kind); /* Recharge equipment */ if (object_is_equipped(player->body, obj)) { /* Recharge activatable objects */ if (recharge_timeout(obj)) { /* Message if an item recharged */ recharged_notice(obj, true); /* Window stuff */ player->upkeep->redraw |= (PR_EQUIP); } } else { /* Recharge the inventory */ discharged_stack = (number_charging(obj) == obj->number) ? true : false; /* Recharge rods, and update if any rods are recharged */ if (tval_can_have_timeout(obj) && recharge_timeout(obj)) { /* Entire stack is recharged */ if (obj->timeout == 0) recharged_notice(obj, true); /* Previously exhausted stack has acquired a charge */ else if (discharged_stack) recharged_notice(obj, false); /* Combine pack */ player->upkeep->notice |= (PN_COMBINE); /* Redraw stuff */ player->upkeep->redraw |= (PR_INVEN); } } } /* Recharge other level objects */ for (i = 1; i < cave->obj_max; i++) { obj = cave->objects[i]; if (!obj) continue; /* Recharge rods */ if (tval_can_have_timeout(obj)) recharge_timeout(obj); } }
/** * Prepare an object `dst` representing `amt` objects, based on an existing * object `src` representing at least `amt` objects. * * Takes care of the charge redistribution concerns of stacked items. */ void object_copy_amt(struct object *dest, struct object *src, int amt) { int charge_time = randcalc(src->time, 0, AVERAGE), max_time; /* Get a copy of the object */ object_copy(dest, src); /* Modify quantity */ dest->number = amt; dest->note = src->note; /* * If the item has charges/timeouts, set them to the correct level * too. We split off the same amount as distribute_charges. */ if (tval_can_have_charges(src)) dest->pval = src->pval * amt / src->number; if (tval_can_have_timeout(src)) { max_time = charge_time * amt; if (src->timeout > max_time) dest->timeout = max_time; else dest->timeout = src->timeout; } }
/** * Allow one item to "absorb" another, assuming they are similar. * * The blending of the "note" field assumes that either (1) one has an * inscription and the other does not, or (2) neither has an inscription. * In both these cases, we can simply use the existing note, unless the * blending object has a note, in which case we use that note. * * These assumptions are enforced by the "object_similar()" code. */ static void object_absorb_merge(struct object *obj1, const struct object *obj2) { int total; /* Blend all knowledge */ of_union(obj1->known_flags, obj2->known_flags); of_union(obj1->id_flags, obj2->id_flags); /* Merge inscriptions */ if (obj2->note) obj1->note = obj2->note; /* Combine timeouts for rod stacking */ if (tval_can_have_timeout(obj1)) obj1->timeout += obj2->timeout; /* Combine pvals for wands and staves */ if (tval_can_have_charges(obj1) || tval_is_money(obj1)) { total = obj1->pval + obj2->pval; obj1->pval = total >= MAX_PVAL ? MAX_PVAL : total; } /* Combine origin data as best we can */ if (obj1->origin != obj2->origin || obj1->origin_depth != obj2->origin_depth || obj1->origin_xtra != obj2->origin_xtra) { int act = 2; if (obj1->origin_xtra && obj2->origin_xtra) { monster_race *r_ptr = &r_info[obj1->origin_xtra]; monster_race *s_ptr = &r_info[obj2->origin_xtra]; bool r_uniq = rf_has(r_ptr->flags, RF_UNIQUE) ? TRUE : FALSE; bool s_uniq = rf_has(s_ptr->flags, RF_UNIQUE) ? TRUE : FALSE; if (r_uniq && !s_uniq) act = 0; else if (s_uniq && !r_uniq) act = 1; else act = 2; } switch (act) { /* Overwrite with obj2 */ case 1: { obj1->origin = obj2->origin; obj1->origin_depth = obj2->origin_depth; obj1->origin_xtra = obj2->origin_xtra; } /* Set as "mixed" */ case 2: { obj1->origin = ORIGIN_MIXED; } } } }
/** * Allow one item to "absorb" another, assuming they are similar. * * The blending of the "note" field assumes that either (1) one has an * inscription and the other does not, or (2) neither has an inscription. * In both these cases, we can simply use the existing note, unless the * blending object has a note, in which case we use that note. * * These assumptions are enforced by the "object_similar()" code. */ static void object_absorb_merge(struct object *obj1, const struct object *obj2) { int total; /* First object gains any extra knowledge from second */ if (obj1->known && obj2->known) { if (obj2->known->effect) obj1->known->effect = obj1->effect; player_know_object(player, obj1); } /* Merge inscriptions */ if (obj2->note) obj1->note = obj2->note; /* Combine timeouts for rod stacking */ if (tval_can_have_timeout(obj1)) obj1->timeout += obj2->timeout; /* Combine pvals for wands and staves */ if (tval_can_have_charges(obj1) || tval_is_money(obj1)) { total = obj1->pval + obj2->pval; obj1->pval = total >= MAX_PVAL ? MAX_PVAL : total; } /* Combine origin data as best we can */ if (obj1->origin != obj2->origin || obj1->origin_depth != obj2->origin_depth || obj1->origin_xtra != obj2->origin_xtra) { int act = 2; if (obj1->origin_xtra && obj2->origin_xtra) { struct monster_race *race1 = &r_info[obj1->origin_xtra]; struct monster_race *race2 = &r_info[obj2->origin_xtra]; bool r1_uniq = rf_has(race1->flags, RF_UNIQUE) ? true : false; bool r2_uniq = rf_has(race2->flags, RF_UNIQUE) ? true : false; if (r1_uniq && !r2_uniq) act = 0; else if (r2_uniq && !r1_uniq) act = 1; else act = 2; } switch (act) { /* Overwrite with obj2 */ case 1: { obj1->origin = obj2->origin; obj1->origin_depth = obj2->origin_depth; obj1->origin_xtra = obj2->origin_xtra; } /* Set as "mixed" */ case 2: { obj1->origin = ORIGIN_MIXED; } } } }