removed a lot of old code that used or initialized potions and herbs, moved those to the xml data instead. also made spells use resource_type instead of resource_t to have one less place where those are used.

The tech-tree loading is now smart enough that a resource can depend on another one that isn't loaded yet (it builds a dummy of the resource at first). his can backfire if you then forget to define that resource for real, i'll eventually need error-handling there.
This commit is contained in:
Enno Rehling 2005-10-25 20:44:18 +00:00
parent 688b796aec
commit ac30257333
12 changed files with 747 additions and 710 deletions

View File

@ -983,12 +983,12 @@ cr_reportspell(FILE * F, spellid_t id, const struct locale * lang)
if (!(sp->sptyp & NOTFAMILIARCAST)) fputs("1;familiar\n", F); if (!(sp->sptyp & NOTFAMILIARCAST)) fputs("1;familiar\n", F);
fputs("KOMPONENTEN\n", F); fputs("KOMPONENTEN\n", F);
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; ++k) {
resource_t res = sp->komponenten[k][0]; const resource_type * rtype = sp->components[k].type;
int itemanz = sp->komponenten[k][1]; int itemanz = sp->components[k].amount;
int costtyp = sp->komponenten[k][2]; int costtyp = sp->components[k].cost;
if (itemanz > 0) { if (itemanz > 0) {
const char * name = resname(res, 0); const char * name = resourcename(rtype, 0);
fprintf(F, "%d %d;%s\n", itemanz, costtyp == SPC_LEVEL || costtyp == SPC_LINEAR, fprintf(F, "%d %d;%s\n", itemanz, costtyp == SPC_LEVEL || costtyp == SPC_LINEAR,
add_translation(name, LOC(lang, name))); add_translation(name, LOC(lang, name)));
} }

View File

@ -402,7 +402,6 @@ static void
report_spell(FILE * F, spellid_t id, const struct locale * lang) report_spell(FILE * F, spellid_t id, const struct locale * lang)
{ {
int k, itemanz, costtyp; int k, itemanz, costtyp;
resource_t res;
int dh = 0; int dh = 0;
spell *sp = find_spellbyid(id); spell *sp = find_spellbyid(id);
char * bufp; char * bufp;
@ -430,13 +429,13 @@ report_spell(FILE * F, spellid_t id, const struct locale * lang)
strcpy(buf, "Komponenten:"); strcpy(buf, "Komponenten:");
rps(F, buf); rps(F, buf);
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; ++k) {
res = sp->komponenten[k][0]; const resource_type * rtype = sp->components[k].type;
itemanz = sp->komponenten[k][1]; itemanz = sp->components[k].amount;
costtyp = sp->komponenten[k][2]; costtyp = sp->components[k].cost;
if(itemanz > 0){ if (itemanz > 0){
if (sp->sptyp & SPELLLEVEL) { if (sp->sptyp & SPELLLEVEL) {
bufp = buf + sprintf(buf, " %d %s", itemanz, LOC(lang, resname(res, itemanz!=1))); bufp = buf + sprintf(buf, " %d %s", itemanz, LOC(lang, resourcename(rtype, itemanz!=1)));
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR ) { if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR ) {
bufp += strxcpy(bufp, " * Stufe"); bufp += strxcpy(bufp, " * Stufe");
} }
@ -444,7 +443,7 @@ report_spell(FILE * F, spellid_t id, const struct locale * lang)
if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR ) { if (costtyp == SPC_LEVEL || costtyp == SPC_LINEAR ) {
itemanz *= sp->level; itemanz *= sp->level;
} }
sprintf(buf, " %d %s", itemanz, LOC(lang, resname(res, itemanz!=1))); sprintf(buf, " %d %s", itemanz, LOC(lang, resourcename(rtype, itemanz!=1)));
} }
rps(F, buf); rps(F, buf);
} }

View File

@ -100,10 +100,7 @@ use_potion(unit * u, const item_type * itype, int amount, struct order *ord)
return ECUSTOM; return ECUSTOM;
} }
if (ptype->use) { if (ptype==oldpotiontype[P_LIFE]) {
int nRetval = ptype->use(u, ptype, amount, ord);
if (nRetval) return nRetval;
} else if (ptype==oldpotiontype[P_LIFE]) {
region * r = u->region; region * r = u->region;
int holz = 0; int holz = 0;

View File

@ -52,32 +52,6 @@ enum {
NOPOTION = (potion_t) - 1 NOPOTION = (potion_t) - 1
}; };
enum {
H_PLAIN_1,
H_PLAIN_2,
H_PLAIN_3,
H_FOREST_1,
H_FOREST_2,
H_FOREST_3,
H_SWAMP_1,
H_SWAMP_2,
H_SWAMP_3,
H_DESERT_1,
H_DESERT_2,
H_DESERT_3,
H_HIGHLAND_1,
H_HIGHLAND_2,
H_HIGHLAND_3,
H_MOUNTAIN_1,
H_MOUNTAIN_2,
H_MOUNTAIN_3,
H_GLACIER_1,
H_GLACIER_2,
H_GLACIER_3,
MAX_HERBS,
NOHERB = (herb_t) - 1
};
herb_t rherb2herb(struct region *r); herb_t rherb2herb(struct region *r);
void herbsearch(struct region * r, struct unit * u, int max); void herbsearch(struct region * r, struct unit * u, int max);
int use_potion(struct unit * u, const struct item_type * itype, int amount, struct order *); int use_potion(struct unit * u, const struct item_type * itype, int amount, struct order *);

View File

@ -99,7 +99,6 @@ struct building_type;
/* feature-dis/en-able */ /* feature-dis/en-able */
#define NEW_DRIVE /* Neuer Algorithmus Transportiere/Fahre */ #define NEW_DRIVE /* Neuer Algorithmus Transportiere/Fahre */
#define PARTIAL_STUDY /* Wenn nicht genug Silber vorhanden, wird ein Talent anteilig gelernt */ #define PARTIAL_STUDY /* Wenn nicht genug Silber vorhanden, wird ein Talent anteilig gelernt */
#define NEW_RECEIPIES /* Vereinfachte, besser verteilte Kräuterzutaten für Tränke */
#define GOBLINKILL #define GOBLINKILL
#define MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */ #define MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */

View File

@ -55,6 +55,32 @@ potion_type * potiontypes;
#define IMAXHASH 127 #define IMAXHASH 127
static item_type * itemtypes[IMAXHASH]; static item_type * itemtypes[IMAXHASH];
enum {
H_PLAIN_1,
H_PLAIN_2,
H_PLAIN_3,
H_FOREST_1,
H_FOREST_2,
H_FOREST_3,
H_SWAMP_1,
H_SWAMP_2,
H_SWAMP_3,
H_DESERT_1,
H_DESERT_2,
H_DESERT_3,
H_HIGHLAND_1,
H_HIGHLAND_2,
H_HIGHLAND_3,
H_MOUNTAIN_1,
H_MOUNTAIN_2,
H_MOUNTAIN_3,
H_GLACIER_1,
H_GLACIER_2,
H_GLACIER_3,
MAX_HERBS,
NOHERB = (herb_t) - 1
};
static int static int
res_changeaura(unit * u, const resource_type * rtype, int delta) res_changeaura(unit * u, const resource_type * rtype, int delta)
{ {
@ -351,8 +377,9 @@ rt_find(const char * name)
unsigned int hash = hashstring(name); unsigned int hash = hashstring(name);
resource_type * rtype; resource_type * rtype;
for (rtype=resourcetypes; rtype; rtype=rtype->next) for (rtype=resourcetypes; rtype; rtype=rtype->next) {
if (rtype->hashkey==hash && !strcmp(rtype->_name[0], name)) break; if (rtype->hashkey==hash && !strcmp(rtype->_name[0], name)) break;
}
return rtype; return rtype;
} }
@ -1198,286 +1225,12 @@ init_olditems(void)
} }
} }
const char *herbdata[3][MAXHERBS] =
{
{
"Flachwurz", /* PLAIN_1 */
"Würziger Wagemut", /* PLAIN_2 */
"Eulenauge", /* PLAIN_3 */
"Grüner Spinnerich", /* H_FOREST_1 */
"Blauer Baumringel",
"Elfenlieb",
"Gurgelkraut", /* SWAMP_1 */
"Knotiger Saugwurz",
"Blasenmorchel", /* SWAMP_3 */
"Wasserfinder",
"Kakteenschwitz",
"Sandfäule",
"Windbeutel", /* HIGHLAND_1 */
"Fjordwuchs",
"Alraune",
"Steinbeißer", /* MOUNTAIN_1 */
"Spaltwachs",
"Höhlenglimm",
"Eisblume", /* GLACIER_1 */
"Weißer Wüterich",
"Schneekristall"
},
{
"Flachwurz",
"Würzige Wagemut",
"Eulenaugen",
"Grüne Spinneriche",
"Blaue Baumringel",
"Elfenlieb",
"Gurgelkräuter",
"Knotige Saugwurze",
"Blasenmorcheln",
"Wasserfinder",
"Kakteenschwitze",
"Sandfäulen",
"Windbeutel",
"Fjordwuchse",
"Alraunen",
"Steinbeißer",
"Spaltwachse",
"Höhlenglimme",
"Eisblumen",
"Weiße Wüteriche",
"Schneekristalle"
},
{
"4",
"10",
"7",
"2",
"4",
"1",
"5",
"5",
"4",
"3",
"3",
"5",
"4",
"6",
"1",
"3",
"1",
"5",
"1",
"1",
"3"
}
};
void
init_oldherbs(void)
{
herb_t h;
const char * names[2];
const char * appearance[2] = { "herbbag", "herbbag" };
const struct locale * lang = find_locale("de");
assert(lang);
for (h=0;h!=MAXHERBS;++h) {
item_type * itype;
resource_type * rtype;
names[0] = NULL;
{
int ci;
for (ci=0;translation[ci][0];++ci) {
if (!strcmp(translation[ci][0], herbdata[0][h])) {
names[0] = translation[ci][1];
names[1] = translation[ci][2];
}
}
}
if (!names[0]) {
names[0] = reverse_lookup(lang, herbdata[0][h]);
names[1] = reverse_lookup(lang, herbdata[1][h]);
}
rtype = new_resourcetype(names, appearance, RTF_ITEM|RTF_POOLED);
itype = new_itemtype(rtype, ITF_HERB, 0, 0);
oldresourcetype[herb2res(h)] = rtype;
}
}
const item_type * const item_type *
oldherbtype(herb_t h) oldherbtype(herb_t h)
{ {
return oldresourcetype[herb2res(h)]->itype; return oldresourcetype[herb2res(h)]->itype;
} }
static const char *potionnames[3][MAXPOTIONS] =
{
{
/* Stufe 1: */
"Siebenmeilentee",
"Goliathwasser",
"Wasser des Lebens",
/* Stufe 2: */
"Schaffenstrunk",
"Wundsalbe",
"Bauernblut",
/* Stufe 3: */
"Gehirnschmalz",
"Dumpfbackenbrot",
"Nestwärme",
"Pferdeglück",
"Berserkerblut",
/* Stufe 4: */
"Bauernlieb",
"Trank der Wahrheit",
"Elixier der Macht",
"Heiltrank"
},
{
/* Stufe 1: */
"Siebenmeilentees",
"Goliathwasser",
"Wasser des Lebens",
/* Stufe 2: */
"Schaffenstrünke",
"Wundsalben",
"Bauernblut",
/* Stufe 3: */
"Gehirnschmalz",
"Dumpfbackenbrote",
"Nestwärme",
"Pferdeglück",
"Berserkerblut",
/* Stufe 4: */
"Bauernlieb",
"Tränke der Wahrheit",
"Elixiere der Macht",
"Heiltränke"
},
{
/* Stufe 1: */
"einen Siebenmeilentee",
"ein Goliathwasser",
"ein Wasser des Lebens",
/* Stufe 2: */
"einen Schaffenstrunk",
"eine Wundsalbe",
"ein Bauernblut",
/* Stufe 3: */
"ein Gehirnschmalz",
"ein Dumpfbackenbrot",
"eine Nestwärme",
"ein Pferdeglück",
"ein Berserkerblut",
/* Stufe 4: */
"ein Bauernlieb",
"ein Trank der Wahrheit",
"ein Elixier der Macht",
"einen Heiltrank"
}
};
int potionlevel[MAXPOTIONS] =
{
1,
1,
1,
2,
2,
2,
3,
3,
3,
3,
3,
4,
1,
4,
4
};
#ifdef NEW_RECEIPIES
herb_t potionherbs[MAXPOTIONS][MAXHERBSPERPOTION] =
{ /* Benötigte Kräuter */
/* Stufe 1: */
/* Siebenmeilentee: */
{H_FOREST_2, H_HIGHLAND_1, NOHERB, NOHERB, NOHERB, NOHERB},
/* Goliathwasser: */
{H_SWAMP_1, H_HIGHLAND_2, NOHERB, NOHERB, NOHERB, NOHERB},
/* Wasser des Lebens: */
{H_FOREST_3, H_SWAMP_2, NOHERB, NOHERB, NOHERB, NOHERB},
/* Stufe 2: */
/* Schaffenstrunk: */
{H_HIGHLAND_3, H_MOUNTAIN_2, H_PLAIN_2, NOHERB, NOHERB, NOHERB},
/* Wundsalbe: */
{H_GLACIER_2, H_FOREST_2, H_PLAIN_2, NOHERB, NOHERB, NOHERB},
/* Bauernblut: */
{H_MOUNTAIN_3, H_HIGHLAND_2, H_FOREST_2, NOHERB, NOHERB, NOHERB},
/* Stufe 3: */
/* Gehirnschmalz: */
{H_DESERT_1, H_MOUNTAIN_1, H_HIGHLAND_1, H_SWAMP_1, NOHERB, NOHERB},
/* Dumpfbackenbrote: */
{H_PLAIN_3, H_FOREST_1, H_MOUNTAIN_3, H_HIGHLAND_2, NOHERB, NOHERB},
/* Nestwärme: */
{H_GLACIER_1, H_FOREST_1, H_MOUNTAIN_2, H_DESERT_2, NOHERB, NOHERB},
/* Pferdeglueck: */
{H_FOREST_2, H_DESERT_3, H_DESERT_2, H_SWAMP_2, NOHERB, NOHERB},
/* Berserkerblut: */
{H_GLACIER_2, H_HIGHLAND_3, H_PLAIN_1, H_DESERT_3, NOHERB, NOHERB},
/* Stufe 4: */
/* Bauernlieb: */
{H_HIGHLAND_3, H_GLACIER_3, H_MOUNTAIN_1, H_SWAMP_3, H_FOREST_3, NOHERB},
/* Trank der Wahrheit: */
{H_PLAIN_1, H_HIGHLAND_2, NOHERB, NOHERB, NOHERB, NOHERB},
/* Elixier der Macht: */
{H_FOREST_3, H_DESERT_1, H_HIGHLAND_1, H_FOREST_1, H_SWAMP_3, NOHERB},
/* Heiltrank: */
{H_SWAMP_1, H_HIGHLAND_1, H_GLACIER_1, H_FOREST_3, H_MOUNTAIN_2, NOHERB}
};
#else
herb_t potionherbs[MAXPOTIONS][MAXHERBSPERPOTION] =
{ /* Benötigte Kräuter */
/* Stufe 1: */
/* Siebenmeilentee: */
{H_PLAIN_2, H_FOREST_1, H_HIGHLAND_1, NOHERB, NOHERB, NOHERB},
/* Goliathwasser: */
{H_PLAIN_1, H_SWAMP_3, H_HIGHLAND_2, NOHERB, NOHERB, NOHERB},
/* Wasser des Lebens: */
{H_FOREST_2, H_PLAIN_1, H_SWAMP_2, NOHERB, NOHERB, NOHERB},
/* Stufe 2: */
/* Schaffenstrunk: */
{H_PLAIN_1, H_HIGHLAND_2, H_MOUNTAIN_1, H_PLAIN_2, NOHERB, NOHERB},
/* Scheusalsbier/Wundsalbe: */
{H_FOREST_2, H_MOUNTAIN_3, H_FOREST_1, H_PLAIN_3, NOHERB, NOHERB},
/* Duft der Rose/Bauernblut: */
{H_MOUNTAIN_1, H_HIGHLAND_1, H_FOREST_2, H_PLAIN_2, NOHERB, NOHERB},
/* Stufe 3: */
/* Gehirnschmalz: */
{H_FOREST_1, H_DESERT_1, H_MOUNTAIN_3, H_HIGHLAND_1, H_SWAMP_1, NOHERB},
/* Dumpfbackenbrote: */
{H_PLAIN_1, H_FOREST_1, H_MOUNTAIN_2, H_SWAMP_2, H_HIGHLAND_1, NOHERB},
/* Stahlpasten/Nestwärme: */
{H_GLACIER_3, H_FOREST_2, H_MOUNTAIN_3, H_DESERT_1, H_SWAMP_3, NOHERB},
/* Pferdeglueck: */
{H_FOREST_3, H_DESERT_2, H_HIGHLAND_1, H_MOUNTAIN_1, H_SWAMP_3, NOHERB},
/* Berserkerblut: */
{H_GLACIER_2, H_MOUNTAIN_1, H_HIGHLAND_1, H_PLAIN_2, H_DESERT_2, NOHERB},
/* Stufe 4: */
/* Bauernlieb: */
{H_FOREST_1, H_HIGHLAND_2, H_GLACIER_3, H_MOUNTAIN_2, H_SWAMP_3, H_FOREST_3},
/* Riesengras/Trank der Wahrheit: */
{H_PLAIN_1, H_SWAMP_3, H_HIGHLAND_1, NOHERB, NOHERB, NOHERB},
/* Faulobstschnaps/Elixier der Macht: */
{H_FOREST_2, H_DESERT_3, H_HIGHLAND_3, H_FOREST_1, H_SWAMP_2, H_SWAMP_1},
/* Heiltrank: */
{H_SWAMP_1, H_PLAIN_3, H_HIGHLAND_3, H_GLACIER_1, H_FOREST_1, H_MOUNTAIN_3}
};
#endif
static const char *potiontext[MAXPOTIONS] = static const char *potiontext[MAXPOTIONS] =
{ {
/* Stufe 1: */ /* Stufe 1: */
@ -1609,7 +1362,7 @@ heal(unit * user, int effect)
} }
static int static int
use_healingpotion(struct unit *user, const struct potion_type *ptype, int amount, struct order * ord) use_healingpotion(struct unit *user, const struct item_type *itype, int amount, struct order * ord)
{ {
int effect = amount * 400; int effect = amount * 400;
unit * u = user->region->units; unit * u = user->region->units;
@ -1620,13 +1373,17 @@ use_healingpotion(struct unit *user, const struct potion_type *ptype, int amount
} }
u = u->next; u = u->next;
} }
new_use_pooled(user, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, amount);
usetpotionuse(user, itype->rtype->ptype);
ADDMSG(&user->faction->msgs, msg_message("usepotion",
"unit potion", user, itype->rtype));
return 0; return 0;
} }
static int static int
use_warmthpotion(struct unit *u, const struct potion_type *ptype, int amount, struct order * ord) use_warmthpotion(struct unit *u, const struct item_type *itype, int amount, struct order * ord)
{ {
assert(ptype==oldpotiontype[P_WARMTH]);
if (u->faction->race == new_race[RC_INSECT]) { if (u->faction->race == new_race[RC_INSECT]) {
fset(u, UFL_WARMTH); fset(u, UFL_WARMTH);
} else { } else {
@ -1634,7 +1391,11 @@ use_warmthpotion(struct unit *u, const struct potion_type *ptype, int amount, st
cmistake(u, ord, 163, MSG_EVENT); cmistake(u, ord, 163, MSG_EVENT);
return ECUSTOM; return ECUSTOM;
} }
unused(ptype); new_use_pooled(u, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0; return 0;
} }
@ -1652,19 +1413,17 @@ use_foolpotion(struct unit *u, int targetno, const struct item_type *itype, int
} }
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));
assert(oldpotiontype[P_FOOL]->itype==itype);
change_effect(target, oldpotiontype[P_FOOL], amount); change_effect(target, itype->rtype->ptype, amount);
new_use_pooled(u, itype->rtype, GET_DEFAULT, amount); new_use_pooled(u, itype->rtype, GET_DEFAULT, amount);
return 0; return 0;
} }
static int static int
use_bloodpotion(struct unit *u, const struct potion_type *ptype, int amount, struct order * ord) use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struct order * ord)
{ {
assert(ptype==oldpotiontype[P_BAUERNBLUT]);
unused(ptype);
if (u->race == new_race[RC_DAEMON] ) { if (u->race == new_race[RC_DAEMON] ) {
change_effect(u, ptype, 100*amount); change_effect(u, itype->rtype->ptype, 100*amount);
} else { } else {
trigger * trestore = trigger_changerace(u, u->race, u->irace); trigger * trestore = trigger_changerace(u, u->race, u->irace);
int duration = 2 + rand() % 8; int duration = 2 + rand() % 8;
@ -1672,6 +1431,11 @@ use_bloodpotion(struct unit *u, const struct potion_type *ptype, int amount, str
add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore));
u->irace = u->race = new_race[RC_TOAD]; u->irace = u->race = new_race[RC_TOAD];
} }
new_use_pooled(u, itype->rtype, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, amount);
usetpotionuse(u, itype->rtype->ptype);
ADDMSG(&u->faction->msgs, msg_message("usepotion",
"unit potion", u, itype->rtype));
return 0; return 0;
} }
@ -1728,85 +1492,17 @@ use_snowball(struct unit * user, const struct item_type * itype, int amount, str
static void static void
init_oldpotions(void) init_oldpotions(void)
{ {
const char * potionnames[MAX_POTIONS] = {
"p0", "goliathwater", "p2", "p3", "p4", "peasantblood", "p6",
"p7", "nestwarmth", "p9", "p10", "p11", "truthpotion", "p13", "p14"
};
potion_t p; potion_t p;
const char * names[2];
const char * appearance[2] = { "vial", "vial_p" };
const struct locale * lang = find_locale("de");
assert(lang);
for (p=0;p!=MAXPOTIONS;++p) { for (p=0;p!=MAXPOTIONS;++p) {
item_type * itype; item_type * itype = it_find(potionnames[p]);
resource_type * rtype; itype->rtype->ptype->text = potiontext[p];
construction * con = calloc(sizeof(construction), 1); oldpotiontype[p] = itype->rtype->ptype;
int i = 0;
while (i!=MAXHERBSPERPOTION && potionherbs[p][i]!=NOHERB) ++i;
if (p==P_BAUERNBLUT || p==P_MACHT) ++i;
con->materials = calloc(sizeof(requirement), i + 1);
for (i=0;i!=MAXHERBSPERPOTION && potionherbs[p][i]!=NOHERB;++i) {
#ifdef NO_OLD_ITEMS
con->materials[i].rtype = oldresourcetype[herb2res(potionherbs[p][i])];
#else
con->materials[i].type = herb2res(potionherbs[p][i]);
#endif
con->materials[i].number = 1;
con->materials[i].recycle = 0;
} }
if (p == P_BAUERNBLUT) {
con->materials[i].number = 1;
con->materials[i].recycle = 0;
#ifdef NO_OLD_ITEMS
con->materials[i].rtype = oldresourcetype[R_PEASANTS];
#else
con->materials[i].type = R_PEASANTS;
#endif
++i;
}
else if (p == P_MACHT) {
con->materials[i].number = 1;
con->materials[i].recycle = 0;
#ifdef NO_OLD_ITEMS
con->materials[i].rtype = oldresourcetype[R_DRACHENBLUT];
#else
con->materials[i].type = R_DRACHENBLUT;
#endif
++i;
}
con->skill = SK_ALCHEMY;
con->minskill = potionlevel[p]*2;
con->maxsize = -1;
con->reqsize = 1;
names[0] = NULL;
{
int ci;
for (ci=0;translation[ci][0];++ci) {
if (!strcmp(translation[ci][0], potionnames[0][p])) {
names[0] = translation[ci][1];
names[1] = translation[ci][2];
}
}
}
if (!names[0]) {
names[0] = reverse_lookup(lang, potionnames[0][p]);
names[1] = reverse_lookup(lang, potionnames[1][p]);
}
rtype = new_resourcetype(names, appearance, RTF_ITEM|RTF_POOLED);
if (p==P_FOOL) rtype->flags |= RTF_SNEAK;
oldresourcetype[potion2res(p)] = rtype;
itype = new_itemtype(rtype, ITF_POTION, 0, 0);
itype->construction = con;
itype->use = use_potion;
oldpotiontype[p] = new_potiontype(itype, (terrain_t)p/3);
oldpotiontype[p]->level = potionlevel[p];
oldpotiontype[p]->text = potiontext[p];
if (p==P_FOOL) itype->useonother = &use_foolpotion;
}
oldpotiontype[P_WARMTH]->use = &use_warmthpotion;
oldpotiontype[P_HEILWASSER]->use = &use_healingpotion;
oldpotiontype[P_BAUERNBLUT]->use = &use_bloodpotion;
} }
resource_type * r_silver; resource_type * r_silver;
@ -1924,7 +1620,6 @@ init_resources(void)
/* alte typen registrieren: */ /* alte typen registrieren: */
init_olditems(); init_olditems();
init_oldherbs();
init_oldpotions(); init_oldpotions();
init_oldscores(); init_oldscores();
} }
@ -2127,6 +1822,7 @@ register_resources(void)
register_function((pf_generic)use_birthdayamulet, "usebirthdayamulet"); register_function((pf_generic)use_birthdayamulet, "usebirthdayamulet");
register_function((pf_generic)use_warmthpotion, "usewarmthpotion"); register_function((pf_generic)use_warmthpotion, "usewarmthpotion");
register_function((pf_generic)use_bloodpotion, "usebloodpotion"); register_function((pf_generic)use_bloodpotion, "usebloodpotion");
register_function((pf_generic)use_healingpotion, "usehealingpotion");
register_function((pf_generic)use_foolpotion, "usefoolpotion"); register_function((pf_generic)use_foolpotion, "usefoolpotion");
register_function((pf_generic)use_mistletoe, "usemistletoe"); register_function((pf_generic)use_mistletoe, "usemistletoe");
register_function((pf_generic)use_magicboost, "usemagicboost"); register_function((pf_generic)use_magicboost, "usemagicboost");

View File

@ -49,8 +49,8 @@ typedef int (*rtype_uget)(const struct unit * user, const struct resource_type *
typedef char * (*rtype_name)(const struct resource_type * rtype, int flags); typedef char * (*rtype_name)(const struct resource_type * rtype, int flags);
typedef struct resource_type { typedef struct resource_type {
/* --- constants --- */ /* --- constants --- */
const char * _name[2]; /* wie es heißt */ char * _name[2]; /* wie es heißt */
const char * _appearance[2]; /* wie es für andere aussieht */ char * _appearance[2]; /* wie es für andere aussieht */
unsigned int flags; unsigned int flags;
/* --- functions --- */ /* --- functions --- */
rtype_uchange uchange; rtype_uchange uchange;
@ -137,7 +137,6 @@ typedef struct potion_type {
const item_type * itype; const item_type * itype;
int level; int level;
const char * text; const char * text;
int (*use)(struct unit *, const struct potion_type *, int, struct order *);
} potion_type; } potion_type;
extern potion_type * potiontypes; extern potion_type * potiontypes;

View File

@ -718,12 +718,12 @@ spellcost(unit *u, const spell * sp)
int k, aura = 0; int k, aura = 0;
int count = countspells(u, 0); int count = countspells(u, 0);
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; k++) {
if (sp->komponenten[k][0] == R_AURA) { if (sp->components[k].type == r_aura) {
aura = sp->komponenten[k][1]; aura = sp->components[k].amount;
} }
} }
aura *= (int)pow(2.0,(double)count); aura *= (1<<count);
return aura; return aura;
} }
@ -740,16 +740,16 @@ spl_costtyp(const spell * sp)
int k; int k;
int costtyp = SPC_FIX; int costtyp = SPC_FIX;
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; k++) {
if (costtyp == SPC_LINEAR) return SPC_LINEAR; if (costtyp == SPC_LINEAR) return SPC_LINEAR;
if (sp->komponenten[k][2] == SPC_LINEAR) { if (sp->components[k].cost == SPC_LINEAR) {
return SPC_LINEAR; return SPC_LINEAR;
} }
/* wenn keine Fixkosten, Typ übernehmen */ /* wenn keine Fixkosten, Typ übernehmen */
if (sp->komponenten[k][2] != SPC_FIX) { if (sp->components[k].cost != SPC_FIX) {
costtyp = sp->komponenten[k][2]; costtyp = sp->components[k].cost;
} }
} }
return costtyp; return costtyp;
@ -770,32 +770,32 @@ eff_spelllevel(unit *u, const spell * sp, int cast_level, int range)
int needplevel; int needplevel;
int costtyp = SPC_FIX; int costtyp = SPC_FIX;
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; k++) {
if (cast_level == 0) if (cast_level == 0)
return 0; return 0;
if (sp->komponenten[k][1] > 0) { if (sp->components[k].amount > 0) {
/* Die Kosten für Aura sind auch von der Zahl der bereits /* Die Kosten für Aura sind auch von der Zahl der bereits
* gezauberten Sprüche abhängig */ * gezauberten Sprüche abhängig */
if (sp->komponenten[k][0] == R_AURA) { if (sp->components[k].type == r_aura) {
needplevel = spellcost(u, sp) * range; needplevel = spellcost(u, sp) * range;
} else { } else {
needplevel = sp->komponenten[k][1] * range; needplevel = sp->components[k].amount * range;
} }
maxlevel = get_pooled(u, u->region, sp->komponenten[k][0])/needplevel; maxlevel = new_get_pooled(u, sp->components[k].type, GET_DEFAULT)/needplevel;
/* sind die Kosten fix, so muss die Komponente nur einmal vorhanden /* sind die Kosten fix, so muss die Komponente nur einmal vorhanden
* sein und der cast_level ändert sich nicht */ * sein und der cast_level ändert sich nicht */
if (sp->komponenten[k][2] == SPC_FIX) { if (sp->components[k].cost == SPC_FIX) {
if (maxlevel < 1) cast_level = 0; if (maxlevel < 1) cast_level = 0;
/* ansonsten wird das Minimum aus maximal möglicher Stufe und der /* ansonsten wird das Minimum aus maximal möglicher Stufe und der
* gewünschten gebildet */ * gewünschten gebildet */
} else if (sp->komponenten[k][2] == SPC_LEVEL) { } else if (sp->components[k].cost == SPC_LEVEL) {
costtyp = SPC_LEVEL; costtyp = SPC_LEVEL;
cast_level = min(cast_level, maxlevel); cast_level = min(cast_level, maxlevel);
/* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden /* bei Typ Linear müssen die Kosten in Höhe der Stufe vorhanden
* sein, ansonsten schlägt der Spruch fehl */ * sein, ansonsten schlägt der Spruch fehl */
} else if (sp->komponenten[k][2] == SPC_LINEAR) { } else if (sp->components[k].cost == SPC_LINEAR) {
costtyp = SPC_LINEAR; costtyp = SPC_LINEAR;
if (maxlevel < cast_level) cast_level = 0; if (maxlevel < cast_level) cast_level = 0;
} }
@ -823,20 +823,20 @@ pay_spell(unit * u, const spell * sp, int cast_level, int range)
int k; int k;
int resuse; int resuse;
for (k = 0; k != MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; k++) {
if (sp->komponenten[k][0] == R_AURA) { if (sp->components[k].type == r_aura) {
resuse = spellcost(u, sp) * range; resuse = spellcost(u, sp) * range;
} else { } else {
resuse = sp->komponenten[k][1] * range; resuse = sp->components[k].amount * range;
} }
if (sp->komponenten[k][2] == SPC_LINEAR if (sp->components[k].cost == SPC_LINEAR
|| sp->komponenten[k][2] == SPC_LEVEL) || sp->components[k].cost == SPC_LEVEL)
{ {
resuse *= cast_level; resuse *= cast_level;
} }
use_pooled(u, u->region, sp->komponenten[k][0], resuse); new_use_pooled(u, sp->components[k].type, resuse, GET_DEFAULT);
} }
} }
@ -888,7 +888,6 @@ boolean
cancast(unit * u, const spell * sp, int level, int range, struct order * ord) cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
{ {
int k; int k;
resource_t res;
int itemanz; int itemanz;
boolean b = true; boolean b = true;
@ -904,21 +903,21 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
return false; return false;
} }
for (k = 0; k < MAXINGREDIENT; k++) { for (k = 0; sp->components[k].type; ++k) {
if (sp->komponenten[k][1] > 0) { if (sp->components[k].amount > 0) {
res = sp->komponenten[k][0]; const resource_type * rtype = sp->components[k].type;
/* Die Kosten für Aura sind auch von der Zahl der bereits /* Die Kosten für Aura sind auch von der Zahl der bereits
* gezauberten Sprüche abhängig */ * gezauberten Sprüche abhängig */
if (sp->komponenten[k][0] == R_AURA) { if (rtype == r_aura) {
itemanz = spellcost(u, sp) * range; itemanz = spellcost(u, sp) * range;
} else { } else {
itemanz = sp->komponenten[k][1] * range; itemanz = sp->components[k].amount * range;
} }
/* sind die Kosten stufenabhängig, so muss itemanz noch mit dem /* sind die Kosten stufenabhängig, so muss itemanz noch mit dem
* level multipliziert werden */ * level multipliziert werden */
switch(sp->komponenten[k][2]) { switch(sp->components[k].cost) {
case SPC_LEVEL: case SPC_LEVEL:
case SPC_LINEAR: case SPC_LINEAR:
itemanz *= level; itemanz *= level;
@ -928,7 +927,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
break; break;
} }
if (get_pooled(u, u->region, res) < itemanz) { if (new_get_pooled(u, rtype, GET_DEFAULT) < itemanz) {
if (b == false) { if (b == false) {
/* es fehlte schon eine andere Komponente, wir basteln die /* es fehlte schon eine andere Komponente, wir basteln die
* Meldung weiter zusammen */ * Meldung weiter zusammen */
@ -939,7 +938,7 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
} }
icat(itemanz); icat(itemanz);
scat(" "); scat(" ");
scat(LOC(u->faction->locale, resname(res, itemanz!=1))); scat(LOC(u->faction->locale, resourcename(rtype, (itemanz!=1)?NMF_PLURAL:0)));
} }
} }
} }
@ -2755,10 +2754,7 @@ magic(void)
const char * const char *
spell_info(const spell * sp, const struct locale * lang) spell_info(const spell * sp, const struct locale * lang)
{ {
if (sp->info==NULL) {
return LOC(lang, mkname("spellinfo", sp->sname)); return LOC(lang, mkname("spellinfo", sp->sname));
}
return sp->info;
} }
const char * const char *

View File

@ -145,17 +145,22 @@ typedef int (*cspell_f) (struct fighter*, int, double, const struct spell * sp);
/* zauber-patzer: */ /* zauber-patzer: */
typedef void (*pspell_f) (castorder *); typedef void (*pspell_f) (castorder *);
typedef struct spell_component {
const struct resource_type * type;
int amount;
int cost;
} spell_component;
typedef struct spell { typedef struct spell {
spellid_t id; spellid_t id;
const char *sname; char *sname;
const char *info; char *syntax;
const char *syntax; char *parameter;
const char *parameter;
magic_t magietyp; magic_t magietyp;
int sptyp; int sptyp;
char rank; /* Reihenfolge der Zauber */ char rank; /* Reihenfolge der Zauber */
int level; /* Stufe des Zaubers */ int level; /* Stufe des Zaubers */
resource_t komponenten[MAXINGREDIENT][3]; struct spell_component * components;
spell_f sp_function; spell_f sp_function;
void (*patzer) (castorder*); void (*patzer) (castorder*);
} spell; } spell;

View File

@ -130,6 +130,22 @@ xml_cleanup_string(xmlChar * str)
return str; return str;
} }
static const resource_type *
rt_findorcreate(const char * name)
{
resource_type * rtype = rt_find(name);
if (rtype==NULL) {
const char * names[2];
char * namep = strcat(strcpy((char*)malloc(strlen(name)+3), name), "_p");
/* we'll make a placeholder */
names[0] = name;
names[1] = namep;
rtype = new_resourcetype(names, NULL, RTF_NONE);
free(namep);
}
return rtype;
}
static void static void
xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray) xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
{ {
@ -147,12 +163,11 @@ xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
const resource_type * rtype; const resource_type * rtype;
resource_t type; resource_t type;
radd->number = xml_ivalue(node, "quantity", 0); radd->number = xml_ivalue(node, "quantity", 1);
radd->recycle = xml_fvalue(node, "recycle", 0.0); radd->recycle = xml_fvalue(node, "recycle", 0.0);
property = xmlGetProp(node, BAD_CAST "type"); property = xmlGetProp(node, BAD_CAST "type");
rtype = rt_find((const char*)property); rtype = rt_findorcreate((const char*)property);
assert(rtype!=NULL);
for (type=0;type!=MAX_RESOURCES;++type) { for (type=0;type!=MAX_RESOURCES;++type) {
if (oldresourcetype[type]==rtype) { if (oldresourcetype[type]==rtype) {
radd->type = type; radd->type = type;
@ -563,6 +578,16 @@ race_compat(void)
} }
} }
static potion_type *
xml_readpotion(xmlXPathContextPtr xpath, item_type * itype)
{
int level = xml_ivalue(xpath->node, "level", 0);
assert(level>0);
return new_potiontype(itype, level);
}
static armor_type * static armor_type *
xml_readarmor(xmlXPathContextPtr xpath, item_type * itype) xml_readarmor(xmlXPathContextPtr xpath, item_type * itype)
{ {
@ -693,6 +718,7 @@ xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
if (xml_bvalue(node, "cursed", false)) flags |= ITF_CURSED; if (xml_bvalue(node, "cursed", false)) flags |= ITF_CURSED;
if (xml_bvalue(node, "notlost", false)) flags |= ITF_NOTLOST; if (xml_bvalue(node, "notlost", false)) flags |= ITF_NOTLOST;
if (xml_bvalue(node, "herb", false)) flags |= ITF_HERB;
if (xml_bvalue(node, "big", false)) flags |= ITF_BIG; if (xml_bvalue(node, "big", false)) flags |= ITF_BIG;
if (xml_bvalue(node, "animal", false)) flags |= ITF_ANIMAL; if (xml_bvalue(node, "animal", false)) flags |= ITF_ANIMAL;
itype = new_itemtype(rtype, flags, weight, capacity); itype = new_itemtype(rtype, flags, weight, capacity);
@ -717,6 +743,17 @@ xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
} }
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
/* reading item/potion */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "potion", xpath);
assert(result->nodesetval->nodeNr<=1);
if (result->nodesetval->nodeNr!=0) {
itype->flags |= ITF_POTION;
xpath->node = result->nodesetval->nodeTab[0];
rtype->ptype = xml_readpotion(xpath, itype);
}
xmlXPathFreeObject(result);
/* reading item/armor */ /* reading item/armor */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "armor", xpath); result = xmlXPathEvalExpression(BAD_CAST "armor", xpath);
@ -770,43 +807,56 @@ parse_resources(xmlDocPtr doc)
xmlNodeSetPtr nodes; xmlNodeSetPtr nodes;
int i; int i;
/* make sure old items (used in requirements) are available */
init_resources();
/* reading eressea/resources/resource */ /* reading eressea/resources/resource */
resources = xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath); resources = xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath);
nodes = resources->nodesetval; nodes = resources->nodesetval;
for (i=0;i!=nodes->nodeNr;++i) { for (i=0;i!=nodes->nodeNr;++i) {
xmlNodePtr node = nodes->nodeTab[i]; xmlNodePtr node = nodes->nodeTab[i];
xmlChar * property; xmlChar *property, *name, *appearance;
char *names[2], *appearance[2]; const char *names[2], *appearances[2];
char * namep = NULL, * appearancep = NULL;
resource_type * rtype; resource_type * rtype;
unsigned int flags = RTF_NONE; unsigned int flags = RTF_NONE;
xmlXPathObjectPtr result; xmlXPathObjectPtr result;
int k; int k;
if (xml_bvalue(node, "pooled", true)) flags |= RTF_POOLED; if (xml_bvalue(node, "pooled", true)) flags |= RTF_POOLED;
if (xml_bvalue(node, "sneak", true)) flags |= RTF_SNEAK;
property = xmlGetProp(node, BAD_CAST "name"); name = xmlGetProp(node, BAD_CAST "name");
assert(property!=NULL); appearance = xmlGetProp(node, BAD_CAST "appearance");
names[0] = strdup((const char*)property); assert(name!=NULL);
names[1] = strcat(strcpy((char*)malloc(strlen(names[0])+3), names[0]), "_p");
xmlFree(property);
property = xmlGetProp(node, BAD_CAST "appearance"); if (appearance!=NULL) {
if (property!=NULL) { appearancep = strcat(strcpy((char*)malloc(strlen((char*)appearance)+3), (char*)appearance), "_p");
assert(property!=NULL);
appearance[0] = strdup((const char*)property);
appearance[1] = strcat(strcpy((char*)malloc(strlen(appearance[0])+3), appearance[0]), "_p");
rtype = new_resourcetype((const char**)names, (const char**)appearance, flags);
xmlFree(property);
free(appearance[0]);
free(appearance[1]);
} else {
rtype = new_resourcetype((const char**)names, NULL, flags);
} }
free(names[0]);
free(names[1]); rtype = rt_find((const char *)name);
if (rtype!=NULL) {
/* dependency from another item, was created earlier */
rtype->flags |= flags;
if (appearance) {
rtype->_appearance[0] = strdup((const char*)appearance);
rtype->_appearance[1] = appearancep;
free(appearancep);
}
} else {
namep = strcat(strcpy((char*)malloc(strlen((char*)name)+3), (char*)name), "_p");
names[0] = (const char*)name;
names[1] = namep;
if (appearance) {
appearances[0] = (const char*)appearance;
appearances[1] = appearancep;
rtype = new_resourcetype((const char**)names, (const char**)appearances, flags);
free(appearancep);
} else {
rtype = new_resourcetype(names, NULL, flags);
}
free(namep);
}
if (name) xmlFree(name);
if (appearance) xmlFree(appearance);
if (gamecode_enabled) { if (gamecode_enabled) {
/* reading eressea/resources/resource/function */ /* reading eressea/resources/resource/function */
@ -892,6 +942,9 @@ parse_resources(xmlDocPtr doc)
xmlXPathFreeContext(xpath); xmlXPathFreeContext(xpath);
/* make sure old items (used in requirements) are available */
init_resources();
/* old resources now extern (for spells */ /* old resources now extern (for spells */
oldresourcetype[R_SWORD] = rt_find("sword"); oldresourcetype[R_SWORD] = rt_find("sword");
@ -1158,32 +1211,29 @@ parse_spells(xmlDocPtr doc)
/* reading eressea/spells/spell/resource */ /* reading eressea/spells/spell/resource */
xpath->node = node; xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "resource", xpath); result = xmlXPathEvalExpression(BAD_CAST "resource", xpath);
for (k=0;k!=result->nodesetval->nodeNr && k!=MAXINGREDIENT;++k) { if (result->nodesetval->nodeNr) {
sp->components = malloc(sizeof(spell_component)*(result->nodesetval->nodeNr+1));
sp->components[result->nodesetval->nodeNr].type = 0;
}
for (k=0;k!=result->nodesetval->nodeNr;++k) {
xmlNodePtr node = result->nodesetval->nodeTab[k]; xmlNodePtr node = result->nodesetval->nodeTab[k];
resource_t res;
sp->komponenten[k][0] = 0;
property = xmlGetProp(node, BAD_CAST "name"); property = xmlGetProp(node, BAD_CAST "name");
assert(property); assert(property);
for (res=0;res!=MAX_RESOURCES;++res) { sp->components[k].type = rt_find((const char *)property);
if (strcmp(oldresourcetype[res]->_name[0], (const char *)property)==0) { assert(sp->components[k].type);
sp->komponenten[k][0] = res;
break;
}
}
xmlFree(property); xmlFree(property);
sp->komponenten[k][1] = (resource_t)xml_ivalue(node, "amount", 1); sp->components[k].amount = (resource_t)xml_ivalue(node, "amount", 1);
sp->komponenten[k][2] = SPC_FIX; sp->components[k].cost = SPC_FIX;
property = xmlGetProp(node, BAD_CAST "cost"); property = xmlGetProp(node, BAD_CAST "cost");
if (property!=NULL) { if (property!=NULL) {
if (strcmp((const char *)property, "linear")==0) { if (strcmp((const char *)property, "linear")==0) {
sp->komponenten[k][2] = SPC_LINEAR; sp->components[k].cost = SPC_LINEAR;
} else if (strcmp((const char *)property, "level")==0) { } else if (strcmp((const char *)property, "level")==0) {
sp->komponenten[k][2] = SPC_LEVEL; sp->components[k].cost = SPC_LEVEL;
} }
xmlFree(property); xmlFree(property);
} }
} }
if (k<MAXINGREDIENT) sp->komponenten[k][0] = 0;
xmlXPathFreeObject(result); xmlXPathFreeObject(result);
sp->id = 0; sp->id = 0;
register_spell(sp); register_spell(sp);
@ -1496,6 +1546,7 @@ parse_terrains(xmlDocPtr doc)
property = xmlGetProp(nodeProd, BAD_CAST "name"); property = xmlGetProp(nodeProd, BAD_CAST "name");
assert(property!=NULL); assert(property!=NULL);
terrain->production[k].type = rt_find((const char*)property); terrain->production[k].type = rt_find((const char*)property);
assert(terrain->production[k].type);
xmlFree(property); xmlFree(property);
property = xmlGetProp(nodeProd, BAD_CAST "level"); property = xmlGetProp(nodeProd, BAD_CAST "level");

File diff suppressed because it is too large Load Diff

View File

@ -214,4 +214,281 @@
</item> </item>
</resource> </resource>
<!-- 21 stupid herbs -->
<resource name="h0" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h1" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h2" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h3" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h4" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h5" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h6" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h7" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h8" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h9" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h10" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h11" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h12" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h13" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h14" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h15" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h16" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h17" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h18" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h19" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<resource name="h20" appearance="herbbag">
<item weight="0" score="10" herb="yes"/>
</resource>
<!-- potions -->
<resource name="p0" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<potion level="1"/>
<construction skill="herbalism" minskill="2" reqsize="1">
<requirement type="h4"/>
<requirement type="h12"/>
</construction>
</item>
</resource>
<resource name="goliathwater" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<potion level="1"/>
<construction skill="herbalism" minskill="2" reqsize="1">
<requirement type="h6"/>
<requirement type="h13"/>
</construction>
</item>
</resource>
<resource name="truthpotion" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<potion level="1"/>
<construction skill="herbalism" minskill="2" reqsize="1">
<requirement type="h0"/>
<requirement type="h13"/>
</construction>
</item>
</resource>
<resource name="p2" appearance="vial">
<item weight="0" score="30">
<function name="use" value="usepotion"/>
<potion level="1"/>
<construction skill="alchemy" minskill="2" reqsize="1">
<requirement type="h5"/>
<requirement type="h7"/>
</construction>
</item>
</resource>
<resource name="p3" appearance="vial">
<item weight="0" score="60">
<function name="use" value="usepotion"/>
<potion level="2"/>
<construction skill="alchemy" minskill="4" reqsize="1">
<requirement type="h14"/>
<requirement type="h16"/>
<requirement type="h1"/>
</construction>
</item>
</resource>
<resource name="p4" appearance="vial">
<!-- Heilwasser -->
<item weight="0" score="60">
<function name="use" value="usehealingpotion"/>
<potion level="2"/>
<construction skill="alchemy" minskill="4" reqsize="1">
<requirement type="h19"/>
<requirement type="h4"/>
<requirement type="h1"/>
</construction>
</item>
</resource>
<resource name="peasantblood" appearance="vial">
<!-- Bauernblut -->
<item weight="0" score="60">
<function name="use" value="usebloodpotion"/>
<potion level="2"/>
<construction skill="alchemy" minskill="4" reqsize="1">
<requirement type="h17"/>
<requirement type="h13"/>
<requirement type="h4"/>
<requirement type="peasant"/>
</construction>
</item>
</resource>
<resource name="p6" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<potion level="3"/>
<construction skill="alchemy" minskill="6" reqsize="1">
<requirement type="h9"/>
<requirement type="h15"/>
<requirement type="h12"/>
<requirement type="h6"/>
</construction>
</item>
</resource>
<resource name="p7" appearance="vial" sneak="yes">
<item weight="0" score="90">
<function name="use" value="usefoolpotion"/>
<potion level="3"/>
<construction skill="alchemy" minskill="6" reqsize="1">
<requirement type="h2"/>
<requirement type="h3"/>
<requirement type="h17"/>
<requirement type="h13"/>
</construction>
</item>
</resource>
<resource name="nestwarmth" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usewarmthpotion"/>
<potion level="3"/>
<construction skill="alchemy" minskill="6" reqsize="1">
<requirement type="h18"/>
<requirement type="h3"/>
<requirement type="h16"/>
<requirement type="h10"/>
</construction>
</item>
</resource>
<resource name="p9" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<potion level="3"/>
<construction skill="alchemy" minskill="6" reqsize="1">
<requirement type="h4"/>
<requirement type="h11"/>
<requirement type="h10"/>
<requirement type="h7"/>
</construction>
</item>
</resource>
<resource name="p10" appearance="vial">
<item weight="0" score="90">
<function name="use" value="usepotion"/>
<potion level="3"/>
<construction skill="alchemy" minskill="6" reqsize="1">
<requirement type="h19"/>
<requirement type="h14"/>
<requirement type="h0"/>
<requirement type="h11"/>
</construction>
</item>
</resource>
<resource name="p11" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<potion level="4"/>
<construction skill="alchemy" minskill="8" reqsize="1">
<requirement type="h14"/>
<requirement type="h20"/>
<requirement type="h15"/>
<requirement type="h8"/>
<requirement type="h5"/>
</construction>
</item>
</resource>
<resource name="p13" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<potion level="4"/>
<construction skill="alchemy" minskill="8" reqsize="1">
<requirement type="h5"/>
<requirement type="h9"/>
<requirement type="h12"/>
<requirement type="h3"/>
<requirement type="h8"/>
<requirement type="dragonblood"/>
</construction>
</item>
</resource>
<resource name="p14" appearance="vial">
<item weight="0" score="120">
<function name="use" value="usepotion"/>
<potion level="4"/>
<construction skill="alchemy" minskill="8" reqsize="1">
<requirement type="h6"/>
<requirement type="h12"/>
<requirement type="h18"/>
<requirement type="h5"/>
<requirement type="h16"/>
</construction>
</item>
</resource>
</resources> </resources>