start removing dependencies on potion_type.

use item_type where we can. does not compile, is WIP.
This commit is contained in:
Enno Rehling 2018-01-12 09:17:01 +01:00
parent 9f486f20b7
commit 3d69f4e372
19 changed files with 191 additions and 194 deletions

View file

@ -48,7 +48,41 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
/* ------------------------------------------------------------- */ 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) 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; static int config;
assert(ptype != NULL); 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) { if (!rule_multipotion) {
const potion_type *use = ugetpotionuse(u); const item_type *use = ugetpotionuse(u);
if (use != NULL && use != ptype) { if (use != NULL && use != itype) {
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
msg_message("errusingpotion", "unit using command", msg_message("errusingpotion", "unit using command",
u, use->itype->rtype, ord)); u, use->rtype, ord));
return ECUSTOM; return ECUSTOM;
} }
} }
return 0; 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); amount);
usetpotionuse(u, ptype); usetpotionuse(u, itype);
ADDMSG(&u->faction->msgs, msg_message("usepotion", 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) { 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; 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) { static int potion_healing(unit * u, int amount) {
int maxhp = unit_max_hp(u) * u->number; int maxhp = unit_max_hp(u) * u->number;
u->hp = u->hp + 400 * amount; u->hp = u->hp + 400 * amount;
@ -185,42 +239,40 @@ static int potion_power(unit *u, int amount) {
return 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); 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); 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); 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); 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); return potion_power(u, amount);
} }
else { else {
change_effect(u, ptype, 10 * amount); change_effect(u, itype, 10 * amount);
} }
return amount; return amount;
} }
int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) 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] && itype == oldpotiontype[P_HEAL]) {
if (oldpotiontype[P_HEAL] && ptype == oldpotiontype[P_HEAL]) {
return EUNUSABLE; return EUNUSABLE;
} }
else { else {
int result = begin_potion(u, ptype, ord); int result = begin_potion(u, itype, ord);
if (result) if (result)
return result; return result;
amount = do_potion(u, u->region, ptype, amount); amount = do_potion(u, u->region, itype, amount);
end_potion(u, ptype, amount); end_potion(u, itype, amount);
} }
return 0; return 0;
} }
@ -228,7 +280,7 @@ int use_potion(unit * u, const item_type * itype, int amount, struct order *ord)
typedef struct potiondelay { typedef struct potiondelay {
unit *u; unit *u;
region *r; region *r;
const potion_type *ptype; const item_type *itype;
int amount; int amount;
} potiondelay; } potiondelay;
@ -245,7 +297,7 @@ static int age_potiondelay(attrib * a, void *owner)
{ {
potiondelay *pd = (potiondelay *)a->data.v; potiondelay *pd = (potiondelay *)a->data.v;
UNUSED_ARG(owner); 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; return AT_AGE_REMOVE;
} }
@ -256,13 +308,13 @@ attrib_type at_potiondelay = {
age_potiondelay, 0, 0 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); attrib *a = a_new(&at_potiondelay);
potiondelay *pd = (potiondelay *)a->data.v; potiondelay *pd = (potiondelay *)a->data.v;
pd->u = u; pd->u = u;
pd->r = u->region; pd->r = u->region;
pd->ptype = ptype; pd->itype = itype;
pd->amount = amount; pd->amount = amount;
return a; return a;
} }
@ -271,14 +323,13 @@ int
use_potion_delayed(unit * u, const item_type * itype, int amount, use_potion_delayed(unit * u, const item_type * itype, int amount,
struct order *ord) struct order *ord)
{ {
const potion_type *ptype = resource2potion(itype->rtype); int result = begin_potion(u, itype, ord);
int result = begin_potion(u, ptype, ord);
if (result) if (result)
return 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; 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; effect_data *edata = (effect_data *)a->data.v;
UNUSED_ARG(owner); 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); WRITE_INT(store, edata->value);
} }
@ -318,14 +369,16 @@ static int a_readeffect(attrib * a, void *owner, struct gamedata *data)
rtype = rt_find(zText); rtype = rt_find(zText);
READ_INT(store, &power); READ_INT(store, &power);
if (rtype == NULL || rtype->ptype == NULL || power <= 0) { if (rtype == NULL || rtype->itype == NULL || power <= 0) {
return AT_READ_FAIL; return AT_READ_FAIL;
} }
if (rtype->ptype==oldpotiontype[P_HEAL]) { if (data->version < NOLANDITEM_VERSION) {
/* healing potions used to have long-term effects */ if (rtype->itype == oldpotiontype[P_HEAL]) {
return AT_READ_FAIL; /* healing potions used to have long-term effects */
return AT_READ_FAIL;
}
} }
edata->type = rtype->ptype; edata->type = rtype->itype;
edata->value = power; edata->value = power;
return AT_READ_OK; return AT_READ_OK;
} }
@ -339,7 +392,7 @@ attrib_type at_effect = {
a_readeffect, 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; const attrib *a;
for (a = a_find(u->attribs, &at_effect); a != NULL && a->type == &at_effect; 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; 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) { if (delta != 0) {
attrib *a = a_find(u->attribs, &at_effect); attrib *a = a_find(u->attribs, &at_effect);

View file

@ -26,9 +26,12 @@ extern "C" {
struct potion_type; struct potion_type;
struct unit; struct unit;
struct region; struct region;
struct faction;
struct item_type; struct item_type;
struct order; struct order;
extern struct attrib_type at_effect;
enum { enum {
/* Stufe 1 */ /* Stufe 1 */
P_FAST, P_FAST,
@ -52,22 +55,23 @@ extern "C" {
MAX_POTIONS 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); 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 *); 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 *); int amount, struct order *);
extern void init_potions(void);
int get_effect(const struct unit *u, const struct item_type *effect);
extern int get_effect(const struct unit *u, const struct potion_type *effect); int change_effect(struct unit *u, const struct item_type *effect,
extern int change_effect(struct unit *u, const struct potion_type *effect,
int value); int value);
extern struct attrib_type at_effect;
/* rausnehmen, sobald man attribute splitten kann: */ /* rausnehmen, sobald man attribute splitten kann: */
typedef struct effect_data { typedef struct effect_data {
const struct potion_type *type; const struct item_type *type;
int value; int value;
} effect_data; } effect_data;

View file

@ -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 (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); message *m = msg_message("potionsave", "unit", du);
battle_message_faction(b, du->faction, m); battle_message_faction(b, du->faction, m);
msg_release(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); fset(&df->person[dt.index], FL_HEALING_USED);
df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */ df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */
return false; return false;

View file

@ -366,13 +366,10 @@ static int tolua_unit_get_effect(lua_State * L)
const unit *self = (unit *)tolua_tousertype(L, 1, 0); const unit *self = (unit *)tolua_tousertype(L, 1, 0);
const char *potion_name = tolua_tostring(L, 2, 0); const char *potion_name = tolua_tostring(L, 2, 0);
int result = -1; int result = -1;
const potion_type *pt_potion;
const item_type *it_potion = it_find(potion_name); const item_type *it_potion = it_find(potion_name);
if (it_potion != NULL) { if (it_potion != NULL) {
pt_potion = it_potion->rtype->ptype; result = get_effect(self, it_potion);
if (pt_potion != NULL)
result = get_effect(self, pt_potion);
} }
lua_pushinteger(L, result); lua_pushinteger(L, result);

View file

@ -276,7 +276,7 @@ cr_output_curses(struct stream *out, const faction * viewer, const void *obj, ob
else if (a->type == &at_effect && self) { else if (a->type == &at_effect && self) {
effect_data *data = (effect_data *)a->data.v; effect_data *data = (effect_data *)a->data.v;
if (data->value > 0) { if (data->value > 0) {
const char *key = resourcename(data->type->itype->rtype, 0); const char *key = resourcename(data->type->rtype, 0);
if (!header) { if (!header) {
header = 1; header = 1;
stream_printf(out, "EFFECTS\n"); 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; for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;
a = a->next) { a = a->next) {
const potion_type *ptype = const item_type *itype = (const item_type *)a->data.v;
resource2potion(((const item_type *)a->data.v)->rtype);
const char *ch; const char *ch;
const char *description = NULL; const char *description = NULL;
if (ptype == NULL) if (itype == NULL)
continue; continue;
ch = resourcename(ptype->itype->rtype, 0); ch = resourcename(itype->rtype, 0);
fprintf(F, "TRANK %d\n", str_hash(ch)); fprintf(F, "TRANK %d\n", str_hash(ch));
fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, 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) { if (description == NULL) {
const char *pname = resourcename(ptype->itype->rtype, 0); const char *pname = resourcename(itype->rtype, 0);
const char *potiontext = mkname("potion", pname); const char *potiontext = mkname("potion", pname);
description = LOC(f->locale, potiontext); description = LOC(f->locale, potiontext);
} }
fprintf(F, "\"%s\";Beschr\n", description); fprintf(F, "\"%s\";Beschr\n", description);
if (ptype->itype->construction) { if (itype->construction) {
requirement *m = ptype->itype->construction->materials; requirement *m = itype->construction->materials;
fprintf(F, "ZUTATEN\n"); fprintf(F, "ZUTATEN\n");

View file

@ -1233,14 +1233,14 @@ void split_allocations(region * r)
allocations = NULL; 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; int built;
if (want == 0) { 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) { switch (built) {
case ELOWSKILL: case ELOWSKILL:
case ENEEDSKILL: case ENEEDSKILL:
@ -1253,16 +1253,16 @@ static void create_potion(unit * u, const potion_type * ptype, int want)
case ENOMATERIALS: case ENOMATERIALS:
/* something missing from the list of materials */ /* something missing from the list of materials */
ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder,
ptype->itype->construction, want)); itype->construction, want));
return; return;
break; break;
default: default:
i_change(&u->items, ptype->itype, built); i_change(&u->items, itype, built);
if (want == INT_MAX) if (want == INT_MAX)
want = built; want = built;
ADDMSG(&u->faction->msgs, msg_message("produce", ADDMSG(&u->faction->msgs, msg_message("produce",
"unit region amount wanted resource", u, u->region, built, want, "unit region amount wanted resource", u, u->region, built, want,
ptype->itype->rtype)); itype->rtype));
break; break;
} }
} }
@ -1277,11 +1277,12 @@ void make_item(unit * u, const item_type * itype, int want)
allocate_resource(u, itype->rtype, want); allocate_resource(u, itype->rtype, want);
} }
else { else {
const potion_type *ptype = resource2potion(itype->rtype); if (itype->flags & ITF_POTION) {
if (ptype != NULL) create_potion(u, itype, want);
create_potion(u, ptype, want); }
else if (itype->construction && itype->construction->materials) else if (itype->construction && itype->construction->materials) {
manufacture(u, itype, want); manufacture(u, itype, want);
}
else { else {
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
"error_cannotmake", "")); "error_cannotmake", ""));

View file

@ -281,7 +281,7 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord)
return result; return result;
} }
lua_pop(L, 1); lua_pop(L, 1);
if (itype->rtype->ptype) { if (itype->flags & ITF_POTION) {
return use_potion(u, itype, amount, ord); return use_potion(u, itype, amount, ord);
} else { } else {
log_error("no such callout: %s", fname); log_error("no such callout: %s", fname);

View file

@ -268,7 +268,7 @@ static int use_foolpotion(unit *u, const item_type *itype, int amount,
ADDMSG(&u->faction->msgs, msg_message("givedumb", ADDMSG(&u->faction->msgs, msg_message("givedumb",
"unit recipient amount", u, target, amount)); "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); use_pooled(u, itype->rtype, GET_DEFAULT, amount);
return 0; return 0;
} }
@ -278,7 +278,7 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount,
struct order *ord) struct order *ord)
{ {
if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) { 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 { else {
const race *irace = u_irace(u); 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, use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount); amount);
usetpotionuse(u, itype->rtype->ptype); usetpotionuse(u, itype);
ADDMSG(&u->faction->msgs, msg_message("usepotion", ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype)); "unit potion", u, itype->rtype));
@ -335,7 +335,7 @@ struct order *ord)
} }
use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount); amount);
usetpotionuse(user, itype->rtype->ptype); usetpotionuse(user, itype);
ADDMSG(&user->faction->msgs, msg_message("usepotion", ADDMSG(&user->faction->msgs, msg_message("usepotion",
"unit potion", user, itype->rtype)); "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, use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK,
amount); amount);
usetpotionuse(u, itype->rtype->ptype); usetpotionuse(u, itype);
ADDMSG(&u->faction->msgs, msg_message("usepotion", ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype)); "unit potion", u, itype->rtype));

View file

@ -161,12 +161,12 @@ static void test_build_with_ring(CuTest *tc) {
static void test_build_with_potion(CuTest *tc) { static void test_build_with_potion(CuTest *tc) {
build_fixture bf = { 0 }; build_fixture bf = { 0 };
unit *u; unit *u;
const potion_type *ptype; const item_type *ptype;
const struct resource_type *rtype; const struct resource_type *rtype;
u = setup_build(&bf); u = setup_build(&bf);
rtype = bf.cons.materials[0].rtype; 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); assert(rtype && ptype);
i_change(&u->items, rtype->itype, 20); i_change(&u->items, rtype->itype, 20);

View file

@ -60,7 +60,6 @@ static critbit_tree inames[MAXLOCALES];
static critbit_tree rnames[MAXLOCALES]; static critbit_tree rnames[MAXLOCALES];
static critbit_tree cb_resources; static critbit_tree cb_resources;
luxury_type *luxurytypes; luxury_type *luxurytypes;
potion_type *potiontypes;
#define RTYPENAMELEN 24 #define RTYPENAMELEN 24
typedef struct rt_entry { typedef struct rt_entry {
@ -315,28 +314,8 @@ armor_type *new_armortype(item_type * itype, double penalty, variant magres,
return atype; 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);
assert(itype->rtype); assert(itype->rtype);
if (appearance) { if (appearance) {
@ -377,18 +356,6 @@ const luxury_type *resource2luxury(const resource_type * rtype)
#endif #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) resource_type *rt_find(const char *name)
{ {
const void *match; const void *match;
@ -573,7 +540,7 @@ item *i_new(const item_type * itype, int size)
return i; return i;
} }
const potion_type *oldpotiontype[MAX_POTIONS + 1]; const item_type *oldpotiontype[MAX_POTIONS + 1];
/*** alte items ***/ /*** alte items ***/
@ -677,7 +644,7 @@ static void init_oldpotions(void)
for (p = 0; p != MAX_POTIONS; ++p) { for (p = 0; p != MAX_POTIONS; ++p) {
item_type *itype = it_find(potionnames[p]); item_type *itype = it_find(potionnames[p]);
if (itype != NULL) { if (itype != NULL) {
oldpotiontype[p] = itype->rtype->ptype; oldpotiontype[p] = itype;
} }
} }
} }

View file

@ -80,7 +80,6 @@ extern "C" {
struct resource_mod *modifiers; struct resource_mod *modifiers;
/* --- pointers --- */ /* --- pointers --- */
struct item_type *itype; struct item_type *itype;
struct potion_type *ptype;
struct luxury_type *ltype; struct luxury_type *ltype;
struct weapon_type *wtype; struct weapon_type *wtype;
struct armor_type *atype; struct armor_type *atype;
@ -99,6 +98,7 @@ extern "C" {
#define ITF_ANIMAL 0x0010 /* an animal */ #define ITF_ANIMAL 0x0010 /* an animal */
#define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */ #define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */
#define ITF_CANUSE 0x0040 /* can be used with use_item_fun callout */ #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 */ /* error codes for item_type::use */
#define ECUSTOM -1 #define ECUSTOM -1
@ -128,13 +128,6 @@ extern "C" {
} luxury_type; } luxury_type;
extern luxury_type *luxurytypes; 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_WALKING 0x0001
#define WMF_RIDING 0x0002 #define WMF_RIDING 0x0002
#define WMF_ANYONE 0x000F /* convenience */ #define WMF_ANYONE 0x000F /* convenience */
@ -206,7 +199,6 @@ extern "C" {
const resource_type *item2resource(const item_type * i); const resource_type *item2resource(const item_type * i);
const weapon_type *resource2weapon(const resource_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); const luxury_type *resource2luxury(const resource_type * i);
item **i_find(item ** pi, const item_type * it); item **i_find(item ** pi, const item_type * it);
@ -234,8 +226,6 @@ extern "C" {
skill_t sk); skill_t sk);
armor_type *new_armortype(item_type * itype, double penalty, armor_type *new_armortype(item_type * itype, double penalty,
variant magres, int prot, unsigned int flags); variant magres, int prot, unsigned int flags);
potion_type *new_potiontype(item_type * itype, int level);
/* these constants are used with get_resourcetype. /* these constants are used with get_resourcetype.
* The order of the enum is not important for stored data. * The order of the enum is not important for stored data.
@ -285,7 +275,7 @@ extern "C" {
NORESOURCE = -1 NORESOURCE = -1
} resource_t; } resource_t;
extern const struct potion_type *oldpotiontype[]; extern const struct item_type *oldpotiontype[];
const struct resource_type *get_resourcetype(resource_t rt); const struct resource_type *get_resourcetype(resource_t rt);
struct item *item_spoil(const struct race *rc, int size); struct item *item_spoil(const struct race *rc, int size);

View file

@ -585,7 +585,7 @@ attrib_type at_potionuser = {
NO_READ 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); attrib *a = a_find(u->attribs, &at_potionuser);
if (!a) if (!a)
@ -593,12 +593,12 @@ void usetpotionuse(unit * u, const potion_type * ptype)
a->data.v = (void *)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); attrib *a = a_find(u->attribs, &at_potionuser);
if (!a) if (!a)
return NULL; return NULL;
return (const potion_type *)a->data.v; return (const item_type *)a->data.v;
} }
/*********************/ /*********************/

View file

@ -28,11 +28,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
extern "C" { extern "C" {
#endif #endif
#define MAXUNITS 1048573 /* must be prime for hashing. 524287 was >90% full */
struct skill; struct skill;
struct item; struct item;
struct sc_mage; struct sc_mage;
struct gamedata; struct gamedata;
struct item_type;
#define MAXUNITS 1048573 /* should be prime for hashing. 524287 was >90% full */
#define UFL_DEAD (1<<0) #define UFL_DEAD (1<<0)
#define UFL_ISNEW (1<<1) /* 2 */ #define UFL_ISNEW (1<<1) /* 2 */
#define UFL_LONGACTION (1<<2) /* 4 */ #define UFL_LONGACTION (1<<2) /* 4 */
@ -147,8 +150,8 @@ extern "C" {
const char *uprivate(const struct unit *u); const char *uprivate(const struct unit *u);
void usetprivate(struct unit *u, const char *c); void usetprivate(struct unit *u, const char *c);
const struct potion_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ const struct item_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) */ 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); bool ucontact(const struct unit *u, const struct unit *u2);
void usetcontact(struct unit *u, const struct unit *c); void usetcontact(struct unit *u, const struct unit *c);

View file

@ -101,11 +101,11 @@ static void test_remove_units_with_dead_faction(CuTest *tc) {
static void test_scale_number(CuTest *tc) { static void test_scale_number(CuTest *tc) {
unit *u; unit *u;
const struct potion_type *ptype; const struct item_type *ptype;
test_setup(); test_setup();
test_create_world(); 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)); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0));
change_effect(u, ptype, 1); change_effect(u, ptype, 1);
u->hp = 35; u->hp = 35;

View file

@ -2252,17 +2252,17 @@ static void display_item(unit * u, const item_type * itype)
itype->weight, itype->rtype, info)); 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; faction * f = u->faction;
attrib *a; attrib *a;
a = a_find(f->attribs, &at_showitem); a = a_find(f->attribs, &at_showitem);
while (a && a->data.v != ptype) while (a && a->data.v != itype)
a = a->next; a = a->next;
if (!a) { if (!a) {
a = a_add(&f->attribs, a_new(&at_showitem)); 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? */ err = 36; /* we do not have this item? */
if (i <= 0) { if (i <= 0) {
/* we don't have the item, but it may be a potion that we know */ /* we don't have the item, but it may be a potion that we know */
const potion_type *ptype = resource2potion(item2resource(itype)); int level = potion_level(itype);
if (ptype) { if (2 * level > effskill(u, SK_ALCHEMY, 0)) {
if (2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) {
itype = NULL;
}
} else {
itype = NULL; itype = NULL;
} }
} }
} }
if (itype) { if (itype) {
const potion_type *ptype = itype->rtype->ptype; if (itype->flags & ITF_POTION) {
if (ptype) { display_potion(u, itype);
display_potion(u, ptype);
} }
else { else {
display_item(u, itype); 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); 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) static void reshow(unit * u, struct order *ord, const char *s, param_t p)
{ {
int skill, c;
const potion_type *ptype;
switch (p) { switch (p) {
case P_ZAUBER: case P_ZAUBER:
a_removeall(&u->faction->attribs, &at_seenspell); a_removeall(&u->faction->attribs, &at_seenspell);
break; break;
case P_POTIONS: case P_POTIONS:
skill = effskill(u, SK_ALCHEMY, 0); if (!display_potions(u)) {
c = 0;
for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) {
if (ptype->level * 2 <= skill) {
display_potion(u, ptype);
++c;
}
}
if (c == 0)
cmistake(u, ord, 285, MSG_EVENT); cmistake(u, ord, 285, MSG_EVENT);
}
break; break;
case NOPARAM: case NOPARAM:
reshow_other(u, ord, s); reshow_other(u, ord, s);

View file

@ -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; effect_data *data = (effect_data *)a->data.v;
if (data->value > 0) { if (data->value > 0) {
msg = msg_message("nr_potion_effect", "potion left", msg = msg_message("nr_potion_effect", "potion left",
data->type->itype->rtype, data->value); data->type->rtype, data->value);
} }
} }
if (msg) { if (msg) {
@ -2198,11 +2198,10 @@ report_plaintext(const char *filename, report_context * ctx,
CHECK_ERRNO(); CHECK_ERRNO();
for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem;
a = a->next) { a = a->next) {
const potion_type *ptype = const item_type *itype = (const item_type *)a->data.v;
resource2potion(((const item_type *)a->data.v)->rtype);
const char *description = NULL; const char *description = NULL;
if (ptype != NULL) { if (itype) {
const char *pname = resourcename(ptype->itype->rtype, 0); const char *pname = resourcename(itype->rtype, 0);
if (ch == 0) { if (ch == 0) {
newline(out); newline(out);
@ -2213,7 +2212,7 @@ report_plaintext(const char *filename, report_context * ctx,
newline(out); newline(out);
centre(out, LOC(f->locale, pname), true); centre(out, LOC(f->locale, pname), true);
snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"),
ptype->level); potion_level(itype));
centre(out, buf, true); centre(out, buf, true);
newline(out); newline(out);
@ -2223,8 +2222,8 @@ report_plaintext(const char *filename, report_context * ctx,
if (wrptr(&bufp, &size, bytes) != 0) if (wrptr(&bufp, &size, bytes) != 0)
WARN_STATIC_BUFFER(); WARN_STATIC_BUFFER();
if (ptype->itype->construction) { if (itype->construction) {
requirement *rm = ptype->itype->construction->materials; requirement *rm = itype->construction->materials;
while (rm->number) { while (rm->number) {
bytes = bytes =
(int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size); (int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size);

View file

@ -779,21 +779,10 @@ int study_cmd(unit * u, order * ord)
/* Spruchlistenaktualiesierung ist in Regeneration */ /* Spruchlistenaktualiesierung ist in Regeneration */
if (sk == SK_ALCHEMY) { if (sk == SK_ALCHEMY) {
const potion_type *ptype;
faction *f = u->faction; faction *f = u->faction;
int skill = effskill(u, SK_ALCHEMY, 0); int skill = effskill(u, SK_ALCHEMY, 0);
if (skill > maxalchemy) { if (skill > maxalchemy) {
for (ptype = potiontypes; ptype; ptype = ptype->next) { show_potions(f, skill);
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;
}
}
}
} }
} }
else if (sk == SK_MAGIC) { else if (sk == SK_MAGIC) {

View file

@ -245,26 +245,22 @@ void get_food(region * r)
int hungry = u->number; int hungry = u->number;
/* use peasantblood before eating the peasants themselves */ /* use peasantblood before eating the peasants themselves */
const struct potion_type *pt_blood = 0; const struct item_type *it_blood = it_find("peasantblood");
const resource_type *rt_blood = rt_find("peasantblood"); if (it_blood) {
if (rt_blood) {
pt_blood = rt_blood->ptype;
}
if (pt_blood) {
/* always start with the unit itself, then the first known unit that may have some blood */ /* always start with the unit itself, then the first known unit that may have some blood */
unit *donor = u; unit *donor = u;
while (donor != NULL && hungry > 0) { 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 (hungry < blut) blut = hungry;
if (blut > 0) { if (blut > 0) {
change_effect(donor, pt_blood, -blut); change_effect(donor, it_blood, -blut);
hungry -= blut; hungry -= blut;
} }
if (donor == u) if (donor == u)
donor = r->units; donor = r->units;
while (donor != NULL) { while (donor != NULL) {
if (u_race(donor) == rc_demon && donor != u) { 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 he's in our faction, drain him: */
if (donor->faction == u->faction) if (donor->faction == u->faction)
break; break;

View file

@ -133,8 +133,8 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic)
change_effect(u, oldpotiontype[P_HEAL], -1); change_effect(u, oldpotiontype[P_HEAL], -1);
heiltrank = 1; heiltrank = 1;
} }
else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { else if (i_get(u->items, oldpotiontype[P_HEAL]) > 0) {
i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); i_change(&u->items, oldpotiontype[P_HEAL], -1);
change_effect(u, oldpotiontype[P_HEAL], 3); change_effect(u, oldpotiontype[P_HEAL], 3);
heiltrank = 1; heiltrank = 1;
} }