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);
fputs("KOMPONENTEN\n", F);
for (k = 0; k < MAXINGREDIENT; k++) {
resource_t res = sp->komponenten[k][0];
int itemanz = sp->komponenten[k][1];
int costtyp = sp->komponenten[k][2];
for (k = 0; sp->components[k].type; ++k) {
const resource_type * rtype = sp->components[k].type;
int itemanz = sp->components[k].amount;
int costtyp = sp->components[k].cost;
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,
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)
{
int k, itemanz, costtyp;
resource_t res;
int dh = 0;
spell *sp = find_spellbyid(id);
char * bufp;
@ -430,13 +429,13 @@ report_spell(FILE * F, spellid_t id, const struct locale * lang)
strcpy(buf, "Komponenten:");
rps(F, buf);
for (k = 0; k < MAXINGREDIENT; k++) {
res = sp->komponenten[k][0];
itemanz = sp->komponenten[k][1];
costtyp = sp->komponenten[k][2];
if(itemanz > 0){
for (k = 0; sp->components[k].type; ++k) {
const resource_type * rtype = sp->components[k].type;
itemanz = sp->components[k].amount;
costtyp = sp->components[k].cost;
if (itemanz > 0){
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 ) {
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 ) {
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);
}

View File

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

View File

@ -52,32 +52,6 @@ enum {
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);
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 *);

View File

@ -99,7 +99,6 @@ struct building_type;
/* feature-dis/en-able */
#define NEW_DRIVE /* Neuer Algorithmus Transportiere/Fahre */
#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 MONSTER_FACTION 0 /* Die Partei, in der die Monster sind. */

View File

@ -55,6 +55,32 @@ potion_type * potiontypes;
#define IMAXHASH 127
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
res_changeaura(unit * u, const resource_type * rtype, int delta)
{
@ -351,8 +377,9 @@ rt_find(const char * name)
unsigned int hash = hashstring(name);
resource_type * rtype;
for (rtype=resourcetypes; rtype; rtype=rtype->next)
if (rtype->hashkey==hash && !strcmp(rtype->_name[0], name)) break;
for (rtype=resourcetypes; rtype; rtype=rtype->next) {
if (rtype->hashkey==hash && !strcmp(rtype->_name[0], name)) break;
}
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 *
oldherbtype(herb_t h)
{
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] =
{
/* Stufe 1: */
@ -1609,7 +1362,7 @@ heal(unit * user, int effect)
}
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;
unit * u = user->region->units;
@ -1620,13 +1373,17 @@ use_healingpotion(struct unit *user, const struct potion_type *ptype, int amount
}
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;
}
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]) {
fset(u, UFL_WARMTH);
} else {
@ -1634,8 +1391,12 @@ use_warmthpotion(struct unit *u, const struct potion_type *ptype, int amount, st
cmistake(u, ord, 163, MSG_EVENT);
return ECUSTOM;
}
unused(ptype);
return 0;
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;
}
static int
@ -1652,19 +1413,17 @@ use_foolpotion(struct unit *u, int targetno, const struct item_type *itype, int
}
ADDMSG(&u->faction->msgs, msg_message("givedumb",
"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);
return 0;
}
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] ) {
change_effect(u, ptype, 100*amount);
change_effect(u, itype->rtype->ptype, 100*amount);
} else {
trigger * trestore = trigger_changerace(u, u->race, u->irace);
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));
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;
}
@ -1728,85 +1492,17 @@ use_snowball(struct unit * user, const struct item_type * itype, int amount, str
static 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;
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) {
item_type * itype;
resource_type * rtype;
construction * con = calloc(sizeof(construction), 1);
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;
for (p=0;p!=MAXPOTIONS;++p) {
item_type * itype = it_find(potionnames[p]);
itype->rtype->ptype->text = potiontext[p];
oldpotiontype[p] = itype->rtype->ptype;
}
oldpotiontype[P_WARMTH]->use = &use_warmthpotion;
oldpotiontype[P_HEILWASSER]->use = &use_healingpotion;
oldpotiontype[P_BAUERNBLUT]->use = &use_bloodpotion;
}
resource_type * r_silver;
@ -1924,7 +1620,6 @@ init_resources(void)
/* alte typen registrieren: */
init_olditems();
init_oldherbs();
init_oldpotions();
init_oldscores();
}
@ -2127,6 +1822,7 @@ register_resources(void)
register_function((pf_generic)use_birthdayamulet, "usebirthdayamulet");
register_function((pf_generic)use_warmthpotion, "usewarmthpotion");
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_mistletoe, "usemistletoe");
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 struct resource_type {
/* --- constants --- */
const char * _name[2]; /* wie es heißt */
const char * _appearance[2]; /* wie es für andere aussieht */
char * _name[2]; /* wie es heißt */
char * _appearance[2]; /* wie es für andere aussieht */
unsigned int flags;
/* --- functions --- */
rtype_uchange uchange;
@ -137,7 +137,6 @@ typedef struct potion_type {
const item_type * itype;
int level;
const char * text;
int (*use)(struct unit *, const struct potion_type *, int, struct order *);
} potion_type;
extern potion_type * potiontypes;

View File

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

View File

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

View File

@ -130,6 +130,22 @@ xml_cleanup_string(xmlChar * 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
xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
{
@ -147,12 +163,11 @@ xml_readrequirements(xmlNodePtr * nodeTab, int nodeNr, requirement ** reqArray)
const resource_type * rtype;
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);
property = xmlGetProp(node, BAD_CAST "type");
rtype = rt_find((const char*)property);
assert(rtype!=NULL);
rtype = rt_findorcreate((const char*)property);
for (type=0;type!=MAX_RESOURCES;++type) {
if (oldresourcetype[type]==rtype) {
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 *
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, "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, "animal", false)) flags |= ITF_ANIMAL;
itype = new_itemtype(rtype, flags, weight, capacity);
@ -717,6 +743,17 @@ xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype)
}
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 */
xpath->node = node;
result = xmlXPathEvalExpression(BAD_CAST "armor", xpath);
@ -770,43 +807,56 @@ parse_resources(xmlDocPtr doc)
xmlNodeSetPtr nodes;
int i;
/* make sure old items (used in requirements) are available */
init_resources();
/* reading eressea/resources/resource */
resources = xmlXPathEvalExpression(BAD_CAST "/eressea/resources/resource", xpath);
nodes = resources->nodesetval;
for (i=0;i!=nodes->nodeNr;++i) {
xmlNodePtr node = nodes->nodeTab[i];
xmlChar * property;
char *names[2], *appearance[2];
xmlChar *property, *name, *appearance;
const char *names[2], *appearances[2];
char * namep = NULL, * appearancep = NULL;
resource_type * rtype;
unsigned int flags = RTF_NONE;
xmlXPathObjectPtr result;
int k;
if (xml_bvalue(node, "pooled", true)) flags |= RTF_POOLED;
if (xml_bvalue(node, "sneak", true)) flags |= RTF_SNEAK;
property = xmlGetProp(node, BAD_CAST "name");
assert(property!=NULL);
names[0] = strdup((const char*)property);
names[1] = strcat(strcpy((char*)malloc(strlen(names[0])+3), names[0]), "_p");
xmlFree(property);
name = xmlGetProp(node, BAD_CAST "name");
appearance = xmlGetProp(node, BAD_CAST "appearance");
assert(name!=NULL);
property = xmlGetProp(node, BAD_CAST "appearance");
if (property!=NULL) {
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);
if (appearance!=NULL) {
appearancep = strcat(strcpy((char*)malloc(strlen((char*)appearance)+3), (char*)appearance), "_p");
}
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) {
/* reading eressea/resources/resource/function */
@ -892,6 +942,9 @@ parse_resources(xmlDocPtr doc)
xmlXPathFreeContext(xpath);
/* make sure old items (used in requirements) are available */
init_resources();
/* old resources now extern (for spells */
oldresourcetype[R_SWORD] = rt_find("sword");
@ -1158,32 +1211,29 @@ parse_spells(xmlDocPtr doc)
/* reading eressea/spells/spell/resource */
xpath->node = node;
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];
resource_t res;
sp->komponenten[k][0] = 0;
property = xmlGetProp(node, BAD_CAST "name");
assert(property);
for (res=0;res!=MAX_RESOURCES;++res) {
if (strcmp(oldresourcetype[res]->_name[0], (const char *)property)==0) {
sp->komponenten[k][0] = res;
break;
}
}
sp->components[k].type = rt_find((const char *)property);
assert(sp->components[k].type);
xmlFree(property);
sp->komponenten[k][1] = (resource_t)xml_ivalue(node, "amount", 1);
sp->komponenten[k][2] = SPC_FIX;
sp->components[k].amount = (resource_t)xml_ivalue(node, "amount", 1);
sp->components[k].cost = SPC_FIX;
property = xmlGetProp(node, BAD_CAST "cost");
if (property!=NULL) {
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) {
sp->komponenten[k][2] = SPC_LEVEL;
sp->components[k].cost = SPC_LEVEL;
}
xmlFree(property);
}
}
if (k<MAXINGREDIENT) sp->komponenten[k][0] = 0;
xmlXPathFreeObject(result);
sp->id = 0;
register_spell(sp);
@ -1496,6 +1546,7 @@ parse_terrains(xmlDocPtr doc)
property = xmlGetProp(nodeProd, BAD_CAST "name");
assert(property!=NULL);
terrain->production[k].type = rt_find((const char*)property);
assert(terrain->production[k].type);
xmlFree(property);
property = xmlGetProp(nodeProd, BAD_CAST "level");

File diff suppressed because it is too large Load Diff

View File

@ -214,4 +214,281 @@
</item>
</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>