#include #include #include "alchemy.h" #include "guard.h" #include "skill.h" #include "study.h" #include #include #include #include #include #include #include #include /* util includes */ #include #include #include #include #include #include #include /* libc includes */ #include #include #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(1, sizeof(potion_type)); assert(ptype); 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) { region * r = u->region; int herbsfound; const item_type *whichherb; int effsk = effskill(u, SK_HERBALISM, NULL); int herbs = rherbs(r); if (effsk == 0) { cmistake(u, u->thisorder, 59, MSG_PRODUCE); return; } if (is_guarded(r, u)) { cmistake(u, u->thisorder, 70, MSG_EVENT); return; } whichherb = rherbtype(r); if (whichherb == NULL) { cmistake(u, u->thisorder, 108, MSG_PRODUCE); return; } if (max_take < herbs) { herbs = max_take; } herbsfound = ntimespprob(effsk * u->number, (double)rherbs(r) / 100.0F, -0.01F); if (herbsfound > herbs) herbsfound = herbs; rsetherbs(r, rherbs(r) - herbsfound); if (herbsfound) { produceexp(u, SK_HERBALISM, u->number); i_change(&u->items, whichherb, herbsfound); ADDMSG(&u->faction->msgs, msg_message("herbfound", "unit region amount herb", u, r, herbsfound, whichherb->rtype)); } else { ADDMSG(&u->faction->msgs, msg_message("researchherb_none", "unit region", u, r)); } } 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_luck(unit *u, region *r, attrib_type *atype, int amount) { attrib *a = (attrib *)a_find(r->attribs, atype); UNUSED_ARG(u); if (!a) { a = a_add(&r->attribs, a_new(atype)); } a->data.i += amount; return amount; } int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) { region *r = u->region; if (itype == oldpotiontype[P_PEOPLE]) { amount = potion_luck(u, r, &at_peasantluck, amount); } else if (itype == oldpotiontype[P_HORSE]) { amount = potion_luck(u, r, &at_horseluck, amount); } else { change_effect(u, itype, 10 * amount); } if (amount > 0) { ADDMSG(&u->faction->msgs, msg_message("use_item", "unit amount item", u, amount, itype->rtype)); } return amount; } /*****************/ /* at_effect */ /*****************/ static void a_initeffect(variant *var) { var->v = calloc(1, sizeof(effect_data)); } static void a_writeeffect(const variant *var, const void *owner, struct storage *store) { effect_data *edata = (effect_data *)var->v; UNUSED_ARG(owner); WRITE_TOK(store, resourcename(edata->type->rtype, 0)); WRITE_INT(store, edata->value); } static int a_readeffect(variant *var, void *owner, struct gamedata *data) { struct storage *store = data->store; int power; const resource_type *rtype; effect_data *edata = (effect_data *)var->v; char zText[32]; UNUSED_ARG(owner); READ_TOK(store, zText, sizeof(zText)); rtype = rt_find(zText); READ_INT(store, &power); if (rtype == NULL || rtype->itype == NULL || power <= 0) { 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->itype; edata->value = power; return AT_READ_OK; } attrib_type at_effect = { "effect", a_initeffect, a_free_voidptr, DEFAULT_AGE, a_writeeffect, a_readeffect, }; 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; a = a->next) { const effect_data *data = (const effect_data *)a->data.v; if (data->type == effect) return data->value; } return 0; } int change_effect(unit * u, const item_type * effect, int delta) { if (delta != 0) { attrib *a = a_find(u->attribs, &at_effect); effect_data *data = NULL; while (a && a->type == &at_effect) { data = (effect_data *)a->data.v; if (data->type == effect) { if (data->value + delta == 0) { a_remove(&u->attribs, a); return 0; } else { data->value += delta; return data->value; } } a = a->next; } a = a_add(&u->attribs, a_new(&at_effect)); data = (effect_data *)a->data.v; data->type = effect; data->value = delta; return data->value; } log_error("change effect with delta==0 for unit %s\n", itoa36(u->no)); return 0; } bool display_potions(struct unit *u) { int skill = effskill(u, SK_ALCHEMY, NULL); int c = 0; const potion_type *ptype; for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { if (ptype->level * 2 <= skill) { show_item(u, ptype->itype); ++c; } } return (c > 0); }