cleaning up in the magic code a little, and making the actual casting a separate function for easier debugging.

This commit is contained in:
Enno Rehling 2007-03-25 18:37:28 +00:00
parent 98141baec1
commit c95342a88b
4 changed files with 318 additions and 321 deletions

View File

@ -3847,7 +3847,8 @@ process(void)
cmistake(u, ord, 52, MSG_PRODUCE); cmistake(u, ord, 52, MSG_PRODUCE);
ord = NULL; ord = NULL;
} else if (fval(r->terrain, SEA_REGION) && u->race != new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) { } else if (fval(r->terrain, SEA_REGION) && u->race != new_race[RC_AQUARIAN] && !(u->race->flags & RCF_SWIM)) {
cmistake(u, ord, 242, MSG_INCOME); /* error message disabled by popular demand */
/* cmistake(u, ord, 242, MSG_INCOME); */
ord = NULL; ord = NULL;
} }
} }

View File

@ -1494,14 +1494,10 @@ do_combatmagic(battle *b, combatmagic_t was)
side * s; side * s;
region *r = b->region; region *r = b->region;
castorder *co; castorder *co;
castorder *cll[MAX_SPELLRANK]; int level, rank, sl;
int level; spellrank spellranks[MAX_SPELLRANK];
int spellrank;
int sl;
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { memset(spellranks, 0, sizeof(spellranks));
cll[spellrank] = (castorder*)NULL;
}
for (s = b->sides; s; s = s->next) { for (s = b->sides; s; s = s->next) {
fighter * fig; fighter * fig;
@ -1561,13 +1557,13 @@ do_combatmagic(battle *b, combatmagic_t was)
pay_spell(mage, sp, level, 1); pay_spell(mage, sp, level, 1);
} else { } else {
co = new_castorder(fig, 0, sp, r, level, power, 0, 0, 0); co = new_castorder(fig, 0, sp, r, level, power, 0, 0, 0);
add_castorder(&cll[(int)(sp->rank)], co); add_castorder(&spellranks[sp->rank], co);
} }
} }
} }
} }
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { for (rank = 0; rank < MAX_SPELLRANK; rank++) {
for (co = cll[spellrank]; co; co = co->next) { for (co = spellranks[rank].begin; co; co = co->next) {
fighter * fig = co->magician.fig; fighter * fig = co->magician.fig;
const spell * sp = co->sp; const spell * sp = co->sp;
int level = co->level; int level = co->level;
@ -1583,8 +1579,8 @@ do_combatmagic(battle *b, combatmagic_t was)
} }
} }
} }
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { for (rank = 0; rank < MAX_SPELLRANK; rank++) {
free_castorders(cll[spellrank]); free_castorders(spellranks[rank].begin);
} }
} }

View File

@ -728,22 +728,22 @@ change_maxspellpoints(unit * u, int csp)
int int
countspells(unit *u, int step) countspells(unit *u, int step)
{ {
sc_mage *m; sc_mage *m;
int count; int count;
m = get_mage(u); m = get_mage(u);
if (!m) if (!m)
return 0; return 0;
if (step == 0) if (step == 0)
return m->spellcount; return m->spellcount;
count = m->spellcount + step; count = m->spellcount + step;
/* negative Werte abfangen. */ /* negative Werte abfangen. */
m->spellcount = max(0,count); m->spellcount = max(0,count);
return m->spellcount; return m->spellcount;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -2032,58 +2032,53 @@ add_spellparameter(region *target_r, unit *u, const char *syntax, char ** param,
castorder * castorder *
new_castorder(void *u, unit *u2, const spell *sp, region *r, int lev, new_castorder(void *u, unit *u2, const spell *sp, region *r, int lev,
double force, int range, struct order * ord, spellparameter *p) double force, int range, struct order * ord, spellparameter *p)
{ {
castorder *corder; castorder *corder;
corder = calloc(1, sizeof(castorder)); corder = calloc(1, sizeof(castorder));
corder->magician.u = u; corder->magician.u = u;
corder->familiar = u2; corder->familiar = u2;
corder->sp = sp; corder->sp = sp;
corder->level = lev; corder->level = lev;
corder->force = force; corder->force = force;
corder->rt = r; corder->rt = r;
corder->distance = range; corder->distance = range;
corder->order = copy_order(ord); corder->order = copy_order(ord);
corder->par = p; corder->par = p;
return corder; return corder;
} }
/* Hänge c-order co an die letze c-order von cll an */ /* Hänge c-order co an die letze c-order von cll an */
void void
add_castorder(castorder **cll, castorder *co) add_castorder(spellrank *cll, castorder *co)
{ {
castorder *co2; if (cll->begin==NULL) {
cll->end = &cll->begin;
}
/* Anfang der Liste? */ *cll->end = co;
if (*cll == NULL) { cll->end = &co->next;
*cll = co;
return;
}
/* suche letztes element */ return;
for (co2 = *cll; co2->next != NULL; co2 = co2->next) {
}
co2->next = co;
return;
} }
void void
free_castorders(castorder *co) free_castorders(castorder *co)
{ {
castorder *co2; castorder *co2;
while(co) { while (co) {
co2 = co; co2 = co;
co = co->next; co = co->next;
if (co2->par) { if (co2->par) {
free_spellparameter(co2->par); free_spellparameter(co2->par);
} }
if (co2->order) free_order(co2->order); if (co2->order) free_order(co2->order);
free(co2); free(co2);
} }
return; return;
} }
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -2092,8 +2087,8 @@ free_castorders(castorder *co)
**/ **/
typedef struct familiar_data { typedef struct familiar_data {
unit * mage; unit * mage;
unit * familiar; unit * familiar;
} famililar_data; } famililar_data;
boolean boolean
@ -2106,27 +2101,27 @@ is_familiar(const unit *u)
static void static void
write_unit(const attrib * a, FILE * F) write_unit(const attrib * a, FILE * F)
{ {
unit * u = (unit*)a->data.v; unit * u = (unit*)a->data.v;
write_unit_reference(u, F); write_unit_reference(u, F);
} }
static int static int
sm_familiar(const unit * u, const region * r, skill_t sk, int value) /* skillmod */ sm_familiar(const unit * u, const region * r, skill_t sk, int value) /* skillmod */
{ {
if (sk==SK_MAGIC) return value; if (sk==SK_MAGIC) return value;
else { else {
int mod; int mod;
unit * familiar = get_familiar(u); unit * familiar = get_familiar(u);
if (familiar==NULL) { if (familiar==NULL) {
log_error(("[sm_familiar] %s has a familiar-skillmod, but no familiar\n", unitname(u))); log_error(("[sm_familiar] %s has a familiar-skillmod, but no familiar\n", unitname(u)));
return value; return value;
} }
mod = eff_skill(familiar, sk, r)/2; mod = eff_skill(familiar, sk, r)/2;
if (r != familiar->region) { if (r != familiar->region) {
mod /= distance(r, familiar->region); mod /= distance(r, familiar->region);
} }
return value + mod; return value + mod;
} }
} }
static void static void
@ -2438,6 +2433,212 @@ is_moving_ship(const region * r, const ship *sh)
return false; return false;
} }
static castorder *
cast_cmd(unit * u, order * ord)
{
region * r = u->region;
region * target_r = r;
int level, range;
unit *familiar = NULL, *mage = u;
const char * s;
spell * sp;
spellparameter *args = NULL;
if (LongHunger(u)) {
cmistake(u, ord, 224, MSG_MAGIC);
return 0;
}
if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
cmistake(u, ord, 269, MSG_MAGIC);
return 0;
}
level = eff_skill(u, SK_MAGIC, r);
init_tokens(ord);
skip_token();
s = getstrtoken();
/* für Syntax ' STUFE x REGION y z ' */
if (findparam(s, u->faction->locale) == P_LEVEL) {
s = getstrtoken();
level = min(atoip(s), level);
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
return 0;
}
s = getstrtoken();
}
if (findparam(s, u->faction->locale) == P_REGION) {
short t_x = (short)atoi(getstrtoken());
short t_y = (short)atoi(getstrtoken());
t_x = rel_to_abs(getplane(u->region),u->faction,t_x,0);
t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1);
target_r = findregion(t_x, t_y);
if (!target_r) {
/* Fehler "Die Region konnte nicht verzaubert werden" */
ADDMSG(&mage->faction->msgs, msg_message("spellregionresists",
"unit region command", mage, mage->region, ord));
return 0;
}
s = getstrtoken();
}
/* für Syntax ' REGION x y STUFE z '
* hier nach REGION nochmal auf STUFE prüfen */
if (findparam(s, u->faction->locale) == P_LEVEL) {
s = getstrtoken();
level = min(atoip(s), level);
s = getstrtoken();
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
return 0;
}
}
if (!s[0] || strlen(s) == 0) {
/* Fehler "Es wurde kein Zauber angegeben" */
cmistake(u, ord, 172, MSG_MAGIC);
return 0;
}
sp = get_spellfromtoken(u, s, u->faction->locale);
/* Vertraute können auch Zauber sprechen, die sie selbst nicht
* können. get_spellfromtoken findet aber nur jene Sprüche, die
* die Einheit beherrscht. */
if (sp == NULL && is_familiar(u)) {
familiar = u;
mage = get_familiar_mage(u);
if (mage!=NULL) sp = get_spellfromtoken(mage, s, mage->faction->locale);
}
if (sp == NULL) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
return 0;
}
/* um testen auf spruchnamen zu unterbinden sollte vor allen
* fehlermeldungen die anzeigen das der magier diesen Spruch
* nur in diese Situation nicht anwenden kann, noch eine
* einfache Sicherheitsprüfung kommen */
if (!knowsspell(r, u, sp)) {
/* vorsicht! u kann der familiar sein */
if (!familiar) {
cmistake(u, ord, 173, MSG_MAGIC);
return 0;
}
}
if (sp->sptyp & ISCOMBATSPELL) {
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
cmistake(u, ord, 174, MSG_MAGIC);
return 0;
}
/* Auf dem Ozean Zaubern als quasi-langer Befehl können
* normalerweise nur Meermenschen, ausgenommen explizit als
* OCEANCASTABLE deklarierte Sprüche */
if (fval(r->terrain, SEA_REGION)) {
if (u->race != new_race[RC_AQUARIAN]
&& !fval(u->race, RCF_SWIM)
&& !(sp->sptyp & OCEANCASTABLE)) {
/* Fehlermeldung */
ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean",
"unit region command", u, u->region, ord));
return 0;
}
/* Auf bewegenden Schiffen kann man nur explizit als
* ONSHIPCAST deklarierte Zauber sprechen */
} else if (u->ship) {
if (is_moving_ship(r, u->ship)) {
if (!(sp->sptyp & ONSHIPCAST)) {
/* Fehler: "Diesen Spruch kann man nicht auf einem sich
* bewegenden Schiff stehend zaubern" */
cmistake(u, ord, 175, MSG_MAGIC);
return 0;
}
}
}
/* Farcasting bei nicht farcastbaren Sprüchen abfangen */
range = farcasting(u, target_r);
if (range > 1) {
if (!(sp->sptyp & FARCASTING)) {
/* Fehler "Diesen Spruch kann man nicht in die Ferne
* richten" */
cmistake(u, ord, 176, MSG_MAGIC);
return 0;
}
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
ADDMSG(&u->faction->msgs, msg_message("spellfail::nocontact",
"mage region command target", u, u->region, ord,
regionname(target_r, u->faction)));
return 0;
}
}
/* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */
if (!(sp->sptyp & SPELLLEVEL)) {
int ilevel = eff_skill(u, SK_MAGIC, u->region);
if (ilevel!=level) {
level = ilevel;
ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel",
"mage region command", u, u->region, ord));
}
}
/* Vertrautenmagie */
/* Kennt der Vertraute den Spruch, so zaubert er ganz normal.
* Ansonsten zaubert der Magier durch seinen Vertrauten, dh
* zahlt Komponenten und Aura. Dabei ist die maximale Stufe
* die des Vertrauten!
* Der Spruch wirkt dann auf die Region des Vertrauten und
* gilt nicht als Farcasting. */
if (familiar || is_familiar(u)) {
if ((sp->sptyp & NOTFAMILIARCAST)) {
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
cmistake(u, ord, 177, MSG_MAGIC);
return 0;
}
if (!knowsspell(r, u, sp)) { /* Magier zaubert durch Vertrauten */
mage = get_familiar_mage(u);
if (range > 1) { /* Fehler! Versucht zu Farcasten */
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast",
"mage", mage));
return 0;
}
if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar",
"mage", mage));
return 0;
}
/* mage auf magier setzen, level anpassen, range für Erhöhung
* der Spruchkosten nutzen, langen Befehl des Magiers
* löschen, zaubern kann er noch */
range *= 2;
set_order(&mage->thisorder, NULL);
level = min(level, eff_skill(mage, SK_MAGIC, mage->region)/2);
familiar = u;
}
}
/* Weitere Argumente zusammenbasten */
if (sp->parameter) {
char ** params = malloc(2*sizeof(char*));
int p = 0, size = 2;
for (;;) {
s = getstrtoken();
if (*s==0) break;
if (p+1>=size) {
size*=2;
params = realloc(params, sizeof(char*)*size);
}
params[p++] = strdup(s);
}
params[p] = 0;
args = add_spellparameter(target_r, mage, sp->parameter, params, p, ord);
for (p=0;params[p];++p) free(params[p]);
free(params);
if (args==NULL) {
/* Syntax war falsch */
return 0;
}
}
return new_castorder(mage, familiar, sp, target_r, level, 0, range, ord, args);
}
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Damit man keine Rituale in fremden Gebiet machen kann, diese vor /* Damit man keine Rituale in fremden Gebiet machen kann, diese vor
* Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde * Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde
@ -2460,27 +2661,15 @@ void
magic(void) magic(void)
{ {
region *r; region *r;
region *target_r; int rank;
unit *u; /* Aktuelle unit in Region */
unit *familiar; /* wenn u ein Vertrauter ist */
unit *mage; /* derjenige, der den Spruch am Ende zaubert */
spell *sp;
const char *s;
int spellrank;
int range;
short t_x, t_y;
castorder *co; castorder *co;
castorder *cll[MAX_SPELLRANK]; spellrank spellranks[MAX_SPELLRANK];
spellparameter *args;
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { memset(spellranks, 0, sizeof(spellranks));
cll[spellrank] = (castorder*)NULL;
}
for (r = regions; r; r = r->next) { for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
int level;
boolean casted = false;
order * ord; order * ord;
if (u->number<=0 || u->race == new_race[RC_SPELL]) if (u->number<=0 || u->race == new_race[RC_SPELL])
@ -2496,221 +2685,26 @@ magic(void)
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {
if (get_keyword(ord) == K_CAST) { if (get_keyword(ord) == K_CAST) {
if (LongHunger(u)) { castorder * co = cast_cmd(u, ord);
cmistake(u, ord, 224, MSG_MAGIC); fset(u, UFL_LONGACTION|UFL_NOTMOVING);
continue; if (co) {
const spell * sp = co->sp;
add_castorder(&spellranks[sp->rank], co);
} }
if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
cmistake(u, ord, 269, MSG_MAGIC);
continue;
}
casted = true;
target_r = r;
mage = u;
level = eff_skill(u, SK_MAGIC, r);
familiar = NULL;
init_tokens(ord);
skip_token();
s = getstrtoken();
/* für Syntax ' STUFE x REGION y z ' */
if (findparam(s, u->faction->locale) == P_LEVEL) {
s = getstrtoken();
level = min(atoip(s), level);
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
continue;
}
s = getstrtoken();
}
if (findparam(s, u->faction->locale) == P_REGION) {
t_x = (short)atoi(getstrtoken());
t_x = rel_to_abs(getplane(u->region),u->faction,t_x,0);
t_y = (short)atoi(getstrtoken());
t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1);
target_r = findregion(t_x, t_y);
if (!target_r) {
/* Fehler "Die Region konnte nicht verzaubert werden" */
ADDMSG(&mage->faction->msgs, msg_message("spellregionresists",
"unit region command", mage, mage->region, ord));
continue;
}
s = getstrtoken();
}
/* für Syntax ' REGION x y STUFE z '
* hier nach REGION nochmal auf STUFE prüfen */
if (findparam(s, u->faction->locale) == P_LEVEL) {
s = getstrtoken();
level = min(atoip(s), level);
s = getstrtoken();
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
continue;
}
}
if (!s[0] || strlen(s) == 0) {
/* Fehler "Es wurde kein Zauber angegeben" */
cmistake(u, ord, 172, MSG_MAGIC);
continue;
}
sp = get_spellfromtoken(u, s, u->faction->locale);
/* Vertraute können auch Zauber sprechen, die sie selbst nicht
* können. get_spellfromtoken findet aber nur jene Sprüche, die
* die Einheit beherrscht. */
if (sp == NULL && is_familiar(u)) {
familiar = u;
mage = get_familiar_mage(u);
if (mage!=NULL) sp = get_spellfromtoken(mage, s, mage->faction->locale);
}
if (sp == NULL) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
continue;
}
/* um testen auf spruchnamen zu unterbinden sollte vor allen
* fehlermeldungen die anzeigen das der magier diesen Spruch
* nur in diese Situation nicht anwenden kann, noch eine
* einfache Sicherheitsprüfung kommen */
if (!knowsspell(r, u, sp)) {
/* vorsicht! u kann der familiar sein */
if (!familiar) {
cmistake(u, ord, 173, MSG_MAGIC);
continue;
}
}
if (sp->sptyp & ISCOMBATSPELL) {
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
cmistake(u, ord, 174, MSG_MAGIC);
continue;
}
/* Auf dem Ozean Zaubern als quasi-langer Befehl können
* normalerweise nur Meermenschen, ausgenommen explizit als
* OCEANCASTABLE deklarierte Sprüche */
if (fval(r->terrain, SEA_REGION)) {
if (u->race != new_race[RC_AQUARIAN]
&& !fval(u->race, RCF_SWIM)
&& !(sp->sptyp & OCEANCASTABLE)) {
/* Fehlermeldung */
ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean",
"unit region command", u, u->region, ord));
continue;
}
/* Auf bewegenden Schiffen kann man nur explizit als
* ONSHIPCAST deklarierte Zauber sprechen */
} else if (u->ship) {
if (is_moving_ship(r, u->ship)) {
if (!(sp->sptyp & ONSHIPCAST)) {
/* Fehler: "Diesen Spruch kann man nicht auf einem sich
* bewegenden Schiff stehend zaubern" */
cmistake(u, ord, 175, MSG_MAGIC);
continue;
}
}
}
/* Farcasting bei nicht farcastbaren Sprüchen abfangen */
range = farcasting(u, target_r);
if (range > 1) {
if (!(sp->sptyp & FARCASTING)) {
/* Fehler "Diesen Spruch kann man nicht in die Ferne
* richten" */
cmistake(u, ord, 176, MSG_MAGIC);
continue;
}
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
ADDMSG(&u->faction->msgs, msg_message("spellfail::nocontact",
"mage region command target", u, u->region, ord,
regionname(target_r, u->faction)));
continue;
}
}
/* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */
if (!(sp->sptyp & SPELLLEVEL)) {
int ilevel = eff_skill(u, SK_MAGIC, u->region);
if (ilevel!=level) {
level = ilevel;
ADDMSG(&u->faction->msgs, msg_message("spellfail::nolevel",
"mage region command", u, u->region, ord));
}
}
/* Vertrautenmagie */
/* Kennt der Vertraute den Spruch, so zaubert er ganz normal.
* Ansonsten zaubert der Magier durch seinen Vertrauten, dh
* zahlt Komponenten und Aura. Dabei ist die maximale Stufe
* die des Vertrauten!
* Der Spruch wirkt dann auf die Region des Vertrauten und
* gilt nicht als Farcasting. */
if (familiar || is_familiar(u)) {
if ((sp->sptyp & NOTFAMILIARCAST)) {
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
cmistake(u, ord, 177, MSG_MAGIC);
continue;
}
if (!knowsspell(r, u, sp)) { /* Magier zaubert durch Vertrauten */
mage = get_familiar_mage(u);
if (range > 1) { /* Fehler! Versucht zu Farcasten */
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast",
"mage", mage));
continue;
}
if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar",
"mage", mage));
continue;
}
/* mage auf magier setzen, level anpassen, range für Erhöhung
* der Spruchkosten nutzen, langen Befehl des Magiers
* löschen, zaubern kann er noch */
range *= 2;
set_order(&mage->thisorder, NULL);
level = min(level, eff_skill(mage, SK_MAGIC, mage->region)/2);
familiar = u;
}
}
/* Weitere Argumente zusammenbasten */
if (sp->parameter) {
char ** params = malloc(2*sizeof(char*));
int p = 0, size = 2;
for (;;) {
s = getstrtoken();
if (*s==0) break;
if (p+1>=size) {
size*=2;
params = realloc(params, sizeof(char*)*size);
}
params[p++] = strdup(s);
}
params[p] = 0;
args = add_spellparameter(target_r, mage, sp->parameter, params, p, ord);
for (p=0;params[p];++p) free(params[p]);
free(params);
if (args==NULL) {
/* Syntax war falsch */
continue;
}
} else {
args = (spellparameter *) NULL;
}
co = new_castorder(mage, familiar, sp, target_r, level, 0, range,
ord, args);
add_castorder(&cll[(int)(sp->rank)], co);
} }
} }
if (casted) fset(u, UFL_LONGACTION|UFL_NOTMOVING);
} }
} }
/* Da sich die Aura und Komponenten in der Zwischenzeit verändert /* Da sich die Aura und Komponenten in der Zwischenzeit verändert
* haben können und sich durch vorherige Sprüche das Zaubern * haben können und sich durch vorherige Sprüche das Zaubern
* erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der * erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der
* Spruch überhaupt gezaubert werden kann. * Spruch überhaupt gezaubert werden kann.
* (level) die effektive Stärke des Spruchs (= Stufe, auf der der * (level) die effektive Stärke des Spruchs (= Stufe, auf der der
* Spruch gezaubert wird) */ * Spruch gezaubert wird) */
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { for (rank = 0; rank < MAX_SPELLRANK; rank++) {
for (co = cll[spellrank]; co; co = co->next) { for (co = spellranks[rank].begin; co; co = co->next) {
order * ord = co->order; order * ord = co->order;
int verify, cast_level = co->level; int verify, cast_level = co->level;
boolean fumbled = false; boolean fumbled = false;
@ -2807,15 +2801,16 @@ magic(void)
/* Sind alle Zauber gesprochen gibts Erfahrung */ /* Sind alle Zauber gesprochen gibts Erfahrung */
for (r = regions; r; r = r->next) { for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) { for (u = r->units; u; u = u->next) {
if (is_mage(u) && countspells(u,0) > 0) { if (is_mage(u) && countspells(u, 0) > 0) {
produceexp(u, SK_MAGIC, u->number); produceexp(u, SK_MAGIC, u->number);
/* Spruchlistenaktualiesierung ist in Regeneration */ /* Spruchlistenaktualiesierung ist in Regeneration */
} }
} }
} }
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { for (rank = 0; rank < MAX_SPELLRANK; rank++) {
free_castorders(cll[spellrank]); free_castorders(spellranks[rank].begin);
} }
remove_empty_units(); remove_empty_units();
} }
@ -2823,13 +2818,13 @@ magic(void)
const char * const char *
spell_info(const spell * sp, const struct locale * lang) spell_info(const spell * sp, const struct locale * lang)
{ {
return LOC(lang, mkname("spellinfo", sp->sname)); return LOC(lang, mkname("spellinfo", sp->sname));
} }
const char * const char *
spell_name(const spell * sp, const struct locale * lang) spell_name(const spell * sp, const struct locale * lang)
{ {
return LOC(lang, mkname("spell", sp->sname)); return LOC(lang, mkname("spell", sp->sname));
} }
void void

View File

@ -155,17 +155,17 @@ typedef struct spell_component {
} spell_component; } spell_component;
typedef struct spell { typedef struct spell {
spellid_t id; spellid_t id;
char *sname; char *sname;
char *syntax; char *syntax;
char *parameter; char *parameter;
magic_t magietyp; magic_t magietyp;
int sptyp; int sptyp;
char rank; /* Reihenfolge der Zauber */ int rank; /* Reihenfolge der Zauber */
int level; /* Stufe des Zaubers */ int level; /* Stufe des Zaubers */
struct spell_component * components; struct spell_component * components;
spell_f sp_function; spell_f sp_function;
void (*patzer) (castorder*); void (*patzer) (castorder*);
} spell; } spell;
typedef struct spell_list { typedef struct spell_list {
@ -315,13 +315,18 @@ extern double spellpower(struct region *r, struct unit *u, const spell *sp, int
boolean fumble (struct region *r, struct unit *u, const spell *sp, int cast_level); boolean fumble (struct region *r, struct unit *u, const spell *sp, int cast_level);
/* true, wenn der Zauber misslingt, bei false gelingt der Zauber */ /* true, wenn der Zauber misslingt, bei false gelingt der Zauber */
/* */
typedef struct spellrank {
struct castorder * begin;
struct castorder ** end;
} spellrank;
castorder *new_castorder(void *u, struct unit *familiar, const spell *sp, struct region *r, castorder *new_castorder(void *u, struct unit *familiar, const spell *sp, struct region *r,
int lev, double force, int distance, struct order * ord, spellparameter *p); int lev, double force, int distance, struct order * ord, spellparameter *p);
/* Zwischenspreicher für Zauberbefehle, notwendig für Prioritäten */ /* Zwischenspreicher für Zauberbefehle, notwendig für Prioritäten */
void add_castorder(castorder **cll, castorder *co); void add_castorder(struct spellrank *cll, struct castorder *co);
/* Hänge c-order co an die letze c-order von cll an */ /* Hänge c-order co an die letze c-order von cll an */
void free_castorders(castorder *co); void free_castorders(struct castorder *co);
/* Speicher wieder freigeben */ /* Speicher wieder freigeben */
/* Prüfroutinen für Zaubern */ /* Prüfroutinen für Zaubern */