diff --git a/src/alchemy.c b/src/alchemy.c index 83b4ffcd0..29db8ce85 100644 --- a/src/alchemy.c +++ b/src/alchemy.c @@ -48,7 +48,41 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* ------------------------------------------------------------- */ +typedef struct potion_type { + struct potion_type *next; + const struct item_type *itype; + int level; +} potion_type; + +static potion_type *potiontypes; + +static void pt_register(potion_type * ptype) +{ + ptype->next = potiontypes; + potiontypes = ptype; +} + +void new_potiontype(item_type * itype, int level) +{ + potion_type *ptype; + + ptype = (potion_type *)calloc(sizeof(potion_type), 1); + itype->flags |= ITF_POTION; + ptype->itype = itype; + ptype->level = level; + pt_register(ptype); +} + +int potion_level(const item_type *itype) +{ + potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->itype == itype) { + return ptype->level; + } + } + return 0; +} void herbsearch(unit * u, int max_take) { @@ -95,33 +129,37 @@ void herbsearch(unit * u, int max_take) } } -static int begin_potion(unit * u, const potion_type * ptype, struct order *ord) +static int begin_potion(unit * u, const item_type * itype, struct order *ord) { - bool rule_multipotion; - assert(ptype != NULL); + static int config; + static bool rule_multipotion; + + assert(itype); + if (config_changed(&config)) { + /* should we allow multiple different potions to be used the same turn? */ + rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; + } - /* should we allow multiple different potions to be used the same turn? */ - rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; if (!rule_multipotion) { - const potion_type *use = ugetpotionuse(u); - if (use != NULL && use != ptype) { + const item_type *use = ugetpotionuse(u); + if (use != NULL && use != itype) { ADDMSG(&u->faction->msgs, msg_message("errusingpotion", "unit using command", - u, use->itype->rtype, ord)); + u, use->rtype, ord)); return ECUSTOM; } } return 0; } -static void end_potion(unit * u, const potion_type * ptype, int amount) +static void end_potion(unit * u, const item_type * itype, int amount) { - use_pooled(u, ptype->itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", - "unit potion", u, ptype->itype->rtype)); + "unit potion", u, itype->rtype)); } static int potion_water_of_life(unit * u, region *r, int amount) { @@ -157,6 +195,22 @@ static int potion_water_of_life(unit * u, region *r, int amount) { return amount; } +void show_potions(faction *f, int sklevel) +{ + const potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->level > 0 && sklevel == ptype->level * 2) { + attrib *a = a_find(f->attribs, &at_showitem); + while (a && a->type == &at_showitem && a->data.v != ptype) + a = a->next; + if (a == NULL || a->type != &at_showitem) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)ptype->itype; + } + } + } +} + static int potion_healing(unit * u, int amount) { int maxhp = unit_max_hp(u) * u->number; u->hp = u->hp + 400 * amount; @@ -185,42 +239,40 @@ static int potion_power(unit *u, int amount) { return amount; } -static int do_potion(unit * u, region *r, const potion_type * ptype, int amount) +static int do_potion(unit * u, region *r, const item_type * itype, int amount) { - if (ptype == oldpotiontype[P_LIFE]) { + if (itype == oldpotiontype[P_LIFE]) { return potion_water_of_life(u, r, amount); } - else if (ptype == oldpotiontype[P_HEILWASSER]) { + else if (itype == oldpotiontype[P_HEILWASSER]) { return potion_healing(u, amount); } - else if (ptype == oldpotiontype[P_PEOPLE]) { + else if (itype == oldpotiontype[P_PEOPLE]) { return potion_luck(u, r, &at_peasantluck, amount); } - else if (ptype == oldpotiontype[P_HORSE]) { + else if (itype == oldpotiontype[P_HORSE]) { return potion_luck(u, r, &at_horseluck, amount); } - else if (ptype == oldpotiontype[P_MACHT]) { + else if (itype == oldpotiontype[P_MACHT]) { return potion_power(u, amount); } else { - change_effect(u, ptype, 10 * amount); + change_effect(u, itype, 10 * amount); } return amount; } int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - - if (oldpotiontype[P_HEAL] && ptype == oldpotiontype[P_HEAL]) { + if (oldpotiontype[P_HEAL] && itype == oldpotiontype[P_HEAL]) { return EUNUSABLE; } else { - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - amount = do_potion(u, u->region, ptype, amount); - end_potion(u, ptype, amount); + amount = do_potion(u, u->region, itype, amount); + end_potion(u, itype, amount); } return 0; } @@ -228,7 +280,7 @@ int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) typedef struct potiondelay { unit *u; region *r; - const potion_type *ptype; + const item_type *itype; int amount; } potiondelay; @@ -245,7 +297,7 @@ static int age_potiondelay(attrib * a, void *owner) { potiondelay *pd = (potiondelay *)a->data.v; UNUSED_ARG(owner); - pd->amount = do_potion(pd->u, pd->r, pd->ptype, pd->amount); + pd->amount = do_potion(pd->u, pd->r, pd->itype, pd->amount); return AT_AGE_REMOVE; } @@ -256,13 +308,13 @@ attrib_type at_potiondelay = { age_potiondelay, 0, 0 }; -static attrib *make_potiondelay(unit * u, const potion_type * ptype, int amount) +static attrib *make_potiondelay(unit * u, const item_type * itype, int amount) { attrib *a = a_new(&at_potiondelay); potiondelay *pd = (potiondelay *)a->data.v; pd->u = u; pd->r = u->region; - pd->ptype = ptype; + pd->itype = itype; pd->amount = amount; return a; } @@ -271,14 +323,13 @@ int use_potion_delayed(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - a_add(&u->attribs, make_potiondelay(u, ptype, amount)); + a_add(&u->attribs, make_potiondelay(u, itype, amount)); - end_potion(u, ptype, amount); + end_potion(u, itype, amount); return 0; } @@ -301,7 +352,7 @@ a_writeeffect(const attrib * a, const void *owner, struct storage *store) { effect_data *edata = (effect_data *)a->data.v; UNUSED_ARG(owner); - WRITE_TOK(store, resourcename(edata->type->itype->rtype, 0)); + WRITE_TOK(store, resourcename(edata->type->rtype, 0)); WRITE_INT(store, edata->value); } @@ -318,14 +369,16 @@ static int a_readeffect(attrib * a, void *owner, struct gamedata *data) rtype = rt_find(zText); READ_INT(store, &power); - if (rtype == NULL || rtype->ptype == NULL || power <= 0) { + if (rtype == NULL || rtype->itype == NULL || power <= 0) { return AT_READ_FAIL; } - if (rtype->ptype==oldpotiontype[P_HEAL]) { - /* healing potions used to have long-term effects */ - return AT_READ_FAIL; + if (data->version < NOLANDITEM_VERSION) { + if (rtype->itype == oldpotiontype[P_HEAL]) { + /* healing potions used to have long-term effects */ + return AT_READ_FAIL; + } } - edata->type = rtype->ptype; + edata->type = rtype->itype; edata->value = power; return AT_READ_OK; } @@ -339,7 +392,7 @@ attrib_type at_effect = { a_readeffect, }; -int get_effect(const unit * u, const potion_type * effect) +int get_effect(const unit * u, const item_type * effect) { const attrib *a; for (a = a_find(u->attribs, &at_effect); a != NULL && a->type == &at_effect; @@ -351,7 +404,7 @@ int get_effect(const unit * u, const potion_type * effect) return 0; } -int change_effect(unit * u, const potion_type * effect, int delta) +int change_effect(unit * u, const item_type * effect, int delta) { if (delta != 0) { attrib *a = a_find(u->attribs, &at_effect); diff --git a/src/alchemy.h b/src/alchemy.h index b89d1c27f..f8cebd3db 100644 --- a/src/alchemy.h +++ b/src/alchemy.h @@ -26,9 +26,12 @@ extern "C" { struct potion_type; struct unit; struct region; + struct faction; struct item_type; struct order; + extern struct attrib_type at_effect; + enum { /* Stufe 1 */ P_FAST, @@ -52,22 +55,23 @@ extern "C" { MAX_POTIONS }; + void new_potiontype(struct item_type * itype, int level); + int potion_level(const struct item_type *itype); + void show_potions(struct faction *f, int sklevel); + void herbsearch(struct unit *u, int max); - extern int use_potion(struct unit *u, const struct item_type *itype, + int use_potion(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern int use_potion_delayed(struct unit *u, const struct item_type *itype, + int use_potion_delayed(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern void init_potions(void); - - extern int get_effect(const struct unit *u, const struct potion_type *effect); - extern int change_effect(struct unit *u, const struct potion_type *effect, + int get_effect(const struct unit *u, const struct item_type *effect); + int change_effect(struct unit *u, const struct item_type *effect, int value); - extern struct attrib_type at_effect; /* rausnehmen, sobald man attribute splitten kann: */ typedef struct effect_data { - const struct potion_type *type; + const struct item_type *type; int value; } effect_data; diff --git a/src/battle.c b/src/battle.c index ab5fa2ca1..04cc1904d 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1298,11 +1298,11 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) } if (oldpotiontype[P_HEAL] && !fval(&df->person[dt.index], FL_HEALING_USED)) { - if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) { + if (i_get(du->items, oldpotiontype[P_HEAL]) > 0) { message *m = msg_message("potionsave", "unit", du); battle_message_faction(b, du->faction, m); msg_release(m); - i_change(&du->items, oldpotiontype[P_HEAL]->itype, -1); + i_change(&du->items, oldpotiontype[P_HEAL], -1); fset(&df->person[dt.index], FL_HEALING_USED); df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */ return false; diff --git a/src/bind_unit.c b/src/bind_unit.c index a681a201d..aea404597 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -366,13 +366,10 @@ static int tolua_unit_get_effect(lua_State * L) const unit *self = (unit *)tolua_tousertype(L, 1, 0); const char *potion_name = tolua_tostring(L, 2, 0); int result = -1; - const potion_type *pt_potion; const item_type *it_potion = it_find(potion_name); if (it_potion != NULL) { - pt_potion = it_potion->rtype->ptype; - if (pt_potion != NULL) - result = get_effect(self, pt_potion); + result = get_effect(self, it_potion); } lua_pushinteger(L, result); diff --git a/src/creport.c b/src/creport.c index 4e8fe95b6..912011911 100644 --- a/src/creport.c +++ b/src/creport.c @@ -276,7 +276,7 @@ cr_output_curses(struct stream *out, const faction * viewer, const void *obj, ob else if (a->type == &at_effect && self) { effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { - const char *key = resourcename(data->type->itype->rtype, 0); + const char *key = resourcename(data->type->rtype, 0); if (!header) { header = 1; stream_printf(out, "EFFECTS\n"); @@ -1652,27 +1652,26 @@ report_computer(const char *filename, report_context * ctx, const char *bom) } for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *ch; const char *description = NULL; - if (ptype == NULL) + if (itype == NULL) continue; - ch = resourcename(ptype->itype->rtype, 0); + ch = resourcename(itype->rtype, 0); fprintf(F, "TRANK %d\n", str_hash(ch)); fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch))); - fprintf(F, "%d;Stufe\n", ptype->level); + fprintf(F, "%d;Stufe\n", potion_level(itype)); if (description == NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + const char *pname = resourcename(itype->rtype, 0); const char *potiontext = mkname("potion", pname); description = LOC(f->locale, potiontext); } fprintf(F, "\"%s\";Beschr\n", description); - if (ptype->itype->construction) { - requirement *m = ptype->itype->construction->materials; + if (itype->construction) { + requirement *m = itype->construction->materials; fprintf(F, "ZUTATEN\n"); diff --git a/src/economy.c b/src/economy.c index ef38ef8af..fcba85955 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1233,14 +1233,14 @@ void split_allocations(region * r) allocations = NULL; } -static void create_potion(unit * u, const potion_type * ptype, int want) +static void create_potion(unit * u, const item_type * itype, int want) { int built; if (want == 0) { - want = maxbuild(u, ptype->itype->construction); + want = maxbuild(u, itype->construction); } - built = build(u, ptype->itype->construction, 0, want, 0); + built = build(u, itype->construction, 0, want, 0); switch (built) { case ELOWSKILL: case ENEEDSKILL: @@ -1253,16 +1253,16 @@ static void create_potion(unit * u, const potion_type * ptype, int want) case ENOMATERIALS: /* something missing from the list of materials */ ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - ptype->itype->construction, want)); + itype->construction, want)); return; break; default: - i_change(&u->items, ptype->itype, built); + i_change(&u->items, itype, built); if (want == INT_MAX) want = built; ADDMSG(&u->faction->msgs, msg_message("produce", "unit region amount wanted resource", u, u->region, built, want, - ptype->itype->rtype)); + itype->rtype)); break; } } @@ -1277,11 +1277,12 @@ void make_item(unit * u, const item_type * itype, int want) allocate_resource(u, itype->rtype, want); } else { - const potion_type *ptype = resource2potion(itype->rtype); - if (ptype != NULL) - create_potion(u, ptype, want); - else if (itype->construction && itype->construction->materials) + if (itype->flags & ITF_POTION) { + create_potion(u, itype, want); + } + else if (itype->construction && itype->construction->materials) { manufacture(u, itype, want); + } else { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", "")); diff --git a/src/helpers.c b/src/helpers.c index 5015fe401..b5c4c05ba 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -281,7 +281,7 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord) return result; } lua_pop(L, 1); - if (itype->rtype->ptype) { + if (itype->flags & ITF_POTION) { return use_potion(u, itype, amount, ord); } else { log_error("no such callout: %s", fname); diff --git a/src/items.c b/src/items.c index 94afd8ca1..2a2248279 100644 --- a/src/items.c +++ b/src/items.c @@ -268,7 +268,7 @@ static int use_foolpotion(unit *u, const item_type *itype, int amount, ADDMSG(&u->faction->msgs, msg_message("givedumb", "unit recipient amount", u, target, amount)); - change_effect(target, itype->rtype->ptype, amount); + change_effect(target, itype, amount); use_pooled(u, itype->rtype, GET_DEFAULT, amount); return 0; } @@ -278,7 +278,7 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) { - change_effect(u, itype->rtype->ptype, 100 * amount); + change_effect(u, itype, 100 * amount); } else { const race *irace = u_irace(u); @@ -302,7 +302,7 @@ struct order *ord) } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); @@ -335,7 +335,7 @@ struct order *ord) } use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(user, itype->rtype->ptype); + usetpotionuse(user, itype); ADDMSG(&user->faction->msgs, msg_message("usepotion", "unit potion", user, itype->rtype)); @@ -408,7 +408,7 @@ static int use_warmthpotion(unit *u, const item_type *itype, } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index eab2a6f00..ece28f4eb 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -161,12 +161,12 @@ static void test_build_with_ring(CuTest *tc) { static void test_build_with_potion(CuTest *tc) { build_fixture bf = { 0 }; unit *u; - const potion_type *ptype; + const item_type *ptype; const struct resource_type *rtype; u = setup_build(&bf); rtype = bf.cons.materials[0].rtype; - oldpotiontype[P_DOMORE] = ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + oldpotiontype[P_DOMORE] = ptype = it_get_or_create(rt_get_or_create("hodor")); assert(rtype && ptype); i_change(&u->items, rtype->itype, 20); diff --git a/src/kernel/item.c b/src/kernel/item.c index 2eabd4aa5..f7ce28835 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -60,7 +60,6 @@ static critbit_tree inames[MAXLOCALES]; static critbit_tree rnames[MAXLOCALES]; static critbit_tree cb_resources; luxury_type *luxurytypes; -potion_type *potiontypes; #define RTYPENAMELEN 24 typedef struct rt_entry { @@ -315,28 +314,8 @@ armor_type *new_armortype(item_type * itype, double penalty, variant magres, return atype; } -static void pt_register(potion_type * ptype) +void it_set_appearance(item_type *itype, const char *appearance) { - ptype->itype->rtype->ptype = ptype; - ptype->next = potiontypes; - potiontypes = ptype; -} - -potion_type *new_potiontype(item_type * itype, int level) -{ - potion_type *ptype; - - assert(resource2potion(itype->rtype) == NULL); - - ptype = (potion_type *)calloc(sizeof(potion_type), 1); - ptype->itype = itype; - ptype->level = level; - pt_register(ptype); - - return ptype; -} - -void it_set_appearance(item_type *itype, const char *appearance) { assert(itype); assert(itype->rtype); if (appearance) { @@ -377,18 +356,6 @@ const luxury_type *resource2luxury(const resource_type * rtype) #endif } -const potion_type *resource2potion(const resource_type * rtype) -{ -#ifdef AT_PTYPE - attrib *a = a_find(rtype->attribs, &at_ptype); - if (a) - return (const potion_type *)a->data.v; - return NULL; -#else - return rtype->ptype; -#endif -} - resource_type *rt_find(const char *name) { const void *match; @@ -573,7 +540,7 @@ item *i_new(const item_type * itype, int size) return i; } -const potion_type *oldpotiontype[MAX_POTIONS + 1]; +const item_type *oldpotiontype[MAX_POTIONS + 1]; /*** alte items ***/ @@ -677,7 +644,7 @@ static void init_oldpotions(void) for (p = 0; p != MAX_POTIONS; ++p) { item_type *itype = it_find(potionnames[p]); if (itype != NULL) { - oldpotiontype[p] = itype->rtype->ptype; + oldpotiontype[p] = itype; } } } diff --git a/src/kernel/item.h b/src/kernel/item.h index cc5991ed6..c289005df 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -80,7 +80,6 @@ extern "C" { struct resource_mod *modifiers; /* --- pointers --- */ struct item_type *itype; - struct potion_type *ptype; struct luxury_type *ltype; struct weapon_type *wtype; struct armor_type *atype; @@ -99,6 +98,7 @@ extern "C" { #define ITF_ANIMAL 0x0010 /* an animal */ #define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */ #define ITF_CANUSE 0x0040 /* can be used with use_item_fun callout */ +#define ITF_POTION 0x0080 /* is a potion (for use_potion) */ /* error codes for item_type::use */ #define ECUSTOM -1 @@ -128,13 +128,6 @@ extern "C" { } luxury_type; extern luxury_type *luxurytypes; - typedef struct potion_type { - struct potion_type *next; - const item_type *itype; - int level; - } potion_type; - extern potion_type *potiontypes; - #define WMF_WALKING 0x0001 #define WMF_RIDING 0x0002 #define WMF_ANYONE 0x000F /* convenience */ @@ -206,7 +199,6 @@ extern "C" { const resource_type *item2resource(const item_type * i); const weapon_type *resource2weapon(const resource_type * i); - const potion_type *resource2potion(const resource_type * i); const luxury_type *resource2luxury(const resource_type * i); item **i_find(item ** pi, const item_type * it); @@ -234,8 +226,6 @@ extern "C" { skill_t sk); armor_type *new_armortype(item_type * itype, double penalty, variant magres, int prot, unsigned int flags); - potion_type *new_potiontype(item_type * itype, int level); - /* these constants are used with get_resourcetype. * The order of the enum is not important for stored data. @@ -285,7 +275,7 @@ extern "C" { NORESOURCE = -1 } resource_t; - extern const struct potion_type *oldpotiontype[]; + extern const struct item_type *oldpotiontype[]; const struct resource_type *get_resourcetype(resource_t rt); struct item *item_spoil(const struct race *rc, int size); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 28f227ff5..fb07d782e 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -585,7 +585,7 @@ attrib_type at_potionuser = { NO_READ }; -void usetpotionuse(unit * u, const potion_type * ptype) +void usetpotionuse(unit * u, const item_type * ptype) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) @@ -593,12 +593,12 @@ void usetpotionuse(unit * u, const potion_type * ptype) a->data.v = (void *)ptype; } -const potion_type *ugetpotionuse(const unit * u) +const item_type *ugetpotionuse(const unit * u) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) return NULL; - return (const potion_type *)a->data.v; + return (const item_type *)a->data.v; } /*********************/ diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 53f9836db..91a3ec930 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -28,11 +28,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif -#define MAXUNITS 1048573 /* must be prime for hashing. 524287 was >90% full */ struct skill; struct item; struct sc_mage; struct gamedata; + struct item_type; + +#define MAXUNITS 1048573 /* should be prime for hashing. 524287 was >90% full */ + #define UFL_DEAD (1<<0) #define UFL_ISNEW (1<<1) /* 2 */ #define UFL_LONGACTION (1<<2) /* 4 */ @@ -147,8 +150,8 @@ extern "C" { const char *uprivate(const struct unit *u); void usetprivate(struct unit *u, const char *c); - const struct potion_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ - void usetpotionuse(struct unit *u, const struct potion_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ + const struct item_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ + void usetpotionuse(struct unit *u, const struct item_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ bool ucontact(const struct unit *u, const struct unit *u2); void usetcontact(struct unit *u, const struct unit *c); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 9391e7012..20d23e7a8 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -101,11 +101,11 @@ static void test_remove_units_with_dead_faction(CuTest *tc) { static void test_scale_number(CuTest *tc) { unit *u; - const struct potion_type *ptype; + const struct item_type *ptype; test_setup(); test_create_world(); - ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + ptype = it_get_or_create(rt_get_or_create("hodor")); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); change_effect(u, ptype, 1); u->hp = 35; diff --git a/src/laws.c b/src/laws.c index bccefab20..faf680272 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2252,17 +2252,17 @@ static void display_item(unit * u, const item_type * itype) itype->weight, itype->rtype, info)); } -static void display_potion(unit * u, const potion_type * ptype) +static void display_potion(unit * u, const item_type * itype) { faction * f = u->faction; attrib *a; a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != ptype) + while (a && a->data.v != itype) a = a->next; if (!a) { a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; + a->data.v = (void *)itype; } } @@ -2429,21 +2429,16 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { err = 36; /* we do not have this item? */ if (i <= 0) { /* we don't have the item, but it may be a potion that we know */ - const potion_type *ptype = resource2potion(item2resource(itype)); - if (ptype) { - if (2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) { - itype = NULL; - } - } else { + int level = potion_level(itype); + if (2 * level > effskill(u, SK_ALCHEMY, 0)) { itype = NULL; } } } if (itype) { - const potion_type *ptype = itype->rtype->ptype; - if (ptype) { - display_potion(u, ptype); + if (itype->flags & ITF_POTION) { + display_potion(u, itype); } else { display_item(u, itype); @@ -2471,26 +2466,30 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { cmistake(u, ord, err, MSG_EVENT); } +bool display_potions(unit *u) +{ + int skill = effskill(u, SK_ALCHEMY, 0); + int c = 0; + const potion_type *ptype; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + display_potion(u, ptype); + ++c; + } + } + return (c > 0); +} + static void reshow(unit * u, struct order *ord, const char *s, param_t p) { - int skill, c; - const potion_type *ptype; - switch (p) { case P_ZAUBER: a_removeall(&u->faction->attribs, &at_seenspell); break; case P_POTIONS: - skill = effskill(u, SK_ALCHEMY, 0); - c = 0; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - display_potion(u, ptype); - ++c; - } - } - if (c == 0) + if (!display_potions(u)) { cmistake(u, ord, 285, MSG_EVENT); + } break; case NOPARAM: reshow_other(u, ord, s); diff --git a/src/report.c b/src/report.c index e154ab045..25a92ede2 100644 --- a/src/report.c +++ b/src/report.c @@ -578,7 +578,7 @@ nr_curses_i(struct stream *out, int indent, const faction *viewer, objtype_t typ effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { msg = msg_message("nr_potion_effect", "potion left", - data->type->itype->rtype, data->value); + data->type->rtype, data->value); } } if (msg) { @@ -2198,11 +2198,10 @@ report_plaintext(const char *filename, report_context * ctx, CHECK_ERRNO(); for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *description = NULL; - if (ptype != NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + if (itype) { + const char *pname = resourcename(itype->rtype, 0); if (ch == 0) { newline(out); @@ -2213,7 +2212,7 @@ report_plaintext(const char *filename, report_context * ctx, newline(out); centre(out, LOC(f->locale, pname), true); snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), - ptype->level); + potion_level(itype)); centre(out, buf, true); newline(out); @@ -2223,8 +2222,8 @@ report_plaintext(const char *filename, report_context * ctx, if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - if (ptype->itype->construction) { - requirement *rm = ptype->itype->construction->materials; + if (itype->construction) { + requirement *rm = itype->construction->materials; while (rm->number) { bytes = (int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size); diff --git a/src/study.c b/src/study.c index c5d657c48..f446e34ab 100644 --- a/src/study.c +++ b/src/study.c @@ -779,21 +779,10 @@ int study_cmd(unit * u, order * ord) /* Spruchlistenaktualiesierung ist in Regeneration */ if (sk == SK_ALCHEMY) { - const potion_type *ptype; faction *f = u->faction; int skill = effskill(u, SK_ALCHEMY, 0); if (skill > maxalchemy) { - for (ptype = potiontypes; ptype; ptype = ptype->next) { - if (skill == ptype->level * 2) { - a = a_find(f->attribs, &at_showitem); - while (a && a->type == &at_showitem && a->data.v != ptype) - a = a->next; - if (a == NULL || a->type != &at_showitem) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; - } - } - } + show_potions(f, skill); } } else if (sk == SK_MAGIC) { diff --git a/src/upkeep.c b/src/upkeep.c index 3bd77710e..6748d620c 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -245,26 +245,22 @@ void get_food(region * r) int hungry = u->number; /* use peasantblood before eating the peasants themselves */ - const struct potion_type *pt_blood = 0; - const resource_type *rt_blood = rt_find("peasantblood"); - if (rt_blood) { - pt_blood = rt_blood->ptype; - } - if (pt_blood) { + const struct item_type *it_blood = it_find("peasantblood"); + if (it_blood) { /* always start with the unit itself, then the first known unit that may have some blood */ unit *donor = u; while (donor != NULL && hungry > 0) { - int blut = get_effect(donor, pt_blood); + int blut = get_effect(donor, it_blood); if (hungry < blut) blut = hungry; if (blut > 0) { - change_effect(donor, pt_blood, -blut); + change_effect(donor, it_blood, -blut); hungry -= blut; } if (donor == u) donor = r->units; while (donor != NULL) { if (u_race(donor) == rc_demon && donor != u) { - if (get_effect(donor, pt_blood)) { + if (get_effect(donor, it_blood)) { /* if he's in our faction, drain him: */ if (donor->faction == u->faction) break; diff --git a/src/volcano.c b/src/volcano.c index d90ef47ee..df70a864f 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -133,8 +133,8 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic) change_effect(u, oldpotiontype[P_HEAL], -1); heiltrank = 1; } - else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { - i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); + else if (i_get(u->items, oldpotiontype[P_HEAL]) > 0) { + i_change(&u->items, oldpotiontype[P_HEAL], -1); change_effect(u, oldpotiontype[P_HEAL], 3); heiltrank = 1; }