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

@ -2052,20 +2052,15 @@ new_castorder(void *u, unit *u2, const spell *sp, region *r, int lev,
/* 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? */
if (*cll == NULL) {
*cll = co;
return;
} }
/* suche letztes element */ *cll->end = co;
for (co2 = *cll; co2->next != NULL; co2 = co2->next) { cll->end = &co->next;
}
co2->next = co;
return; return;
} }
@ -2438,77 +2433,27 @@ is_moving_ship(const region * r, const ship *sh)
return false; return false;
} }
/* ------------------------------------------------------------- */ static castorder *
/* Damit man keine Rituale in fremden Gebiet machen kann, diese vor cast_cmd(unit * u, order * ord)
* Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde
* lang verletzlich, da sie es betreten, und angegriffen werden können,
* bevor sie ein Ritual machen können.
*
* Syntax: ZAUBER [REGION X Y] [STUFE <stufe>] "Spruchname" [Einheit-1
* Einheit-2 ..]
*
* Nach Priorität geordnet die Zauber global auswerten.
*
* Die Kosten für Farcasting multiplizieren sich mit der Entfernung,
* cast_level gibt die virtuelle Stufe an, die den durch das Farcasten
* entstandenen Spruchkosten entspricht. Sind die Spruchkosten nicht
* levelabhängig, so sind die Kosten nur von der Entfernung bestimmt,
* die Stärke/Level durch den realen Skill des Magiers
*/
void
magic(void)
{ {
region *r; region * r = u->region;
region *target_r; region * target_r = r;
unit *u; /* Aktuelle unit in Region */ int level, range;
unit *familiar; /* wenn u ein Vertrauter ist */ unit *familiar = NULL, *mage = u;
unit *mage; /* derjenige, der den Spruch am Ende zaubert */
spell *sp;
const char * s; const char * s;
int spellrank; spell * sp;
int range; spellparameter *args = NULL;
short t_x, t_y;
castorder *co;
castorder *cll[MAX_SPELLRANK];
spellparameter *args;
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
cll[spellrank] = (castorder*)NULL;
}
for (r = regions; r; r = r->next) {
for (u = r->units; u; u = u->next) {
int level;
boolean casted = false;
order * ord;
if (u->number<=0 || u->race == new_race[RC_SPELL])
continue;
if (u->race == new_race[RC_INSECT] && r_insectstalled(r) &&
!is_cursed(u->attribs, C_KAELTESCHUTZ,0))
continue;
if (fval(u, UFL_WERE|UFL_LONGACTION)) {
continue;
}
for (ord = u->orders; ord; ord = ord->next) {
if (get_keyword(ord) == K_CAST) {
if (LongHunger(u)) { if (LongHunger(u)) {
cmistake(u, ord, 224, MSG_MAGIC); cmistake(u, ord, 224, MSG_MAGIC);
continue; return 0;
} }
if (r->planep && fval(r->planep, PFL_NOMAGIC)) { if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
cmistake(u, ord, 269, MSG_MAGIC); cmistake(u, ord, 269, MSG_MAGIC);
continue; return 0;
} }
casted = true;
target_r = r;
mage = u;
level = eff_skill(u, SK_MAGIC, r); level = eff_skill(u, SK_MAGIC, r);
familiar = NULL;
init_tokens(ord); init_tokens(ord);
skip_token(); skip_token();
s = getstrtoken(); s = getstrtoken();
@ -2519,21 +2464,21 @@ magic(void)
if (level < 1) { if (level < 1) {
/* Fehler "Das macht wenig Sinn" */ /* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC); cmistake(u, ord, 10, MSG_MAGIC);
continue; return 0;
} }
s = getstrtoken(); s = getstrtoken();
} }
if (findparam(s, u->faction->locale) == P_REGION) { if (findparam(s, u->faction->locale) == P_REGION) {
t_x = (short)atoi(getstrtoken()); 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_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); t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1);
target_r = findregion(t_x, t_y); target_r = findregion(t_x, t_y);
if (!target_r) { if (!target_r) {
/* Fehler "Die Region konnte nicht verzaubert werden" */ /* Fehler "Die Region konnte nicht verzaubert werden" */
ADDMSG(&mage->faction->msgs, msg_message("spellregionresists", ADDMSG(&mage->faction->msgs, msg_message("spellregionresists",
"unit region command", mage, mage->region, ord)); "unit region command", mage, mage->region, ord));
continue; return 0;
} }
s = getstrtoken(); s = getstrtoken();
} }
@ -2546,13 +2491,13 @@ magic(void)
if (level < 1) { if (level < 1) {
/* Fehler "Das macht wenig Sinn" */ /* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC); cmistake(u, ord, 10, MSG_MAGIC);
continue; return 0;
} }
} }
if (!s[0] || strlen(s) == 0) { if (!s[0] || strlen(s) == 0) {
/* Fehler "Es wurde kein Zauber angegeben" */ /* Fehler "Es wurde kein Zauber angegeben" */
cmistake(u, ord, 172, MSG_MAGIC); cmistake(u, ord, 172, MSG_MAGIC);
continue; return 0;
} }
sp = get_spellfromtoken(u, s, u->faction->locale); sp = get_spellfromtoken(u, s, u->faction->locale);
@ -2568,7 +2513,7 @@ magic(void)
if (sp == NULL) { if (sp == NULL) {
/* Fehler 'Spell not found' */ /* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC); cmistake(u, ord, 173, MSG_MAGIC);
continue; return 0;
} }
/* um testen auf spruchnamen zu unterbinden sollte vor allen /* um testen auf spruchnamen zu unterbinden sollte vor allen
* fehlermeldungen die anzeigen das der magier diesen Spruch * fehlermeldungen die anzeigen das der magier diesen Spruch
@ -2578,13 +2523,13 @@ magic(void)
/* vorsicht! u kann der familiar sein */ /* vorsicht! u kann der familiar sein */
if (!familiar) { if (!familiar) {
cmistake(u, ord, 173, MSG_MAGIC); cmistake(u, ord, 173, MSG_MAGIC);
continue; return 0;
} }
} }
if (sp->sptyp & ISCOMBATSPELL) { if (sp->sptyp & ISCOMBATSPELL) {
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
cmistake(u, ord, 174, MSG_MAGIC); cmistake(u, ord, 174, MSG_MAGIC);
continue; return 0;
} }
/* Auf dem Ozean Zaubern als quasi-langer Befehl können /* Auf dem Ozean Zaubern als quasi-langer Befehl können
* normalerweise nur Meermenschen, ausgenommen explizit als * normalerweise nur Meermenschen, ausgenommen explizit als
@ -2596,7 +2541,7 @@ magic(void)
/* Fehlermeldung */ /* Fehlermeldung */
ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean", ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean",
"unit region command", u, u->region, ord)); "unit region command", u, u->region, ord));
continue; return 0;
} }
/* Auf bewegenden Schiffen kann man nur explizit als /* Auf bewegenden Schiffen kann man nur explizit als
* ONSHIPCAST deklarierte Zauber sprechen */ * ONSHIPCAST deklarierte Zauber sprechen */
@ -2606,7 +2551,7 @@ magic(void)
/* Fehler: "Diesen Spruch kann man nicht auf einem sich /* Fehler: "Diesen Spruch kann man nicht auf einem sich
* bewegenden Schiff stehend zaubern" */ * bewegenden Schiff stehend zaubern" */
cmistake(u, ord, 175, MSG_MAGIC); cmistake(u, ord, 175, MSG_MAGIC);
continue; return 0;
} }
} }
} }
@ -2617,13 +2562,13 @@ magic(void)
/* Fehler "Diesen Spruch kann man nicht in die Ferne /* Fehler "Diesen Spruch kann man nicht in die Ferne
* richten" */ * richten" */
cmistake(u, ord, 176, MSG_MAGIC); cmistake(u, ord, 176, MSG_MAGIC);
continue; return 0;
} }
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */ if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
ADDMSG(&u->faction->msgs, msg_message("spellfail::nocontact", ADDMSG(&u->faction->msgs, msg_message("spellfail::nocontact",
"mage region command target", u, u->region, ord, "mage region command target", u, u->region, ord,
regionname(target_r, u->faction))); regionname(target_r, u->faction)));
continue; return 0;
} }
} }
/* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */ /* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */
@ -2646,19 +2591,19 @@ magic(void)
if ((sp->sptyp & NOTFAMILIARCAST)) { if ((sp->sptyp & NOTFAMILIARCAST)) {
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */ /* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
cmistake(u, ord, 177, MSG_MAGIC); cmistake(u, ord, 177, MSG_MAGIC);
continue; return 0;
} }
if (!knowsspell(r, u, sp)) { /* Magier zaubert durch Vertrauten */ if (!knowsspell(r, u, sp)) { /* Magier zaubert durch Vertrauten */
mage = get_familiar_mage(u); mage = get_familiar_mage(u);
if (range > 1) { /* Fehler! Versucht zu Farcasten */ if (range > 1) { /* Fehler! Versucht zu Farcasten */
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast", ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_farcast",
"mage", mage)); "mage", mage));
continue; return 0;
} }
if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) { if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) {
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar", ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "familiar_toofar",
"mage", mage)); "mage", mage));
continue; return 0;
} }
/* mage auf magier setzen, level anpassen, range für Erhöhung /* mage auf magier setzen, level anpassen, range für Erhöhung
* der Spruchkosten nutzen, langen Befehl des Magiers * der Spruchkosten nutzen, langen Befehl des Magiers
@ -2688,17 +2633,66 @@ magic(void)
free(params); free(params);
if (args==NULL) { if (args==NULL) {
/* Syntax war falsch */ /* 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
* Bewegung zaubern. Magier sind also in einem fremden Gebiet eine Runde
* lang verletzlich, da sie es betreten, und angegriffen werden können,
* bevor sie ein Ritual machen können.
*
* Syntax: ZAUBER [REGION X Y] [STUFE <stufe>] "Spruchname" [Einheit-1
* Einheit-2 ..]
*
* Nach Priorität geordnet die Zauber global auswerten.
*
* Die Kosten für Farcasting multiplizieren sich mit der Entfernung,
* cast_level gibt die virtuelle Stufe an, die den durch das Farcasten
* entstandenen Spruchkosten entspricht. Sind die Spruchkosten nicht
* levelabhängig, so sind die Kosten nur von der Entfernung bestimmt,
* die Stärke/Level durch den realen Skill des Magiers
*/
void
magic(void)
{
region *r;
int rank;
castorder *co;
spellrank spellranks[MAX_SPELLRANK];
memset(spellranks, 0, sizeof(spellranks));
for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) {
order * ord;
if (u->number<=0 || u->race == new_race[RC_SPELL])
continue;
if (u->race == new_race[RC_INSECT] && r_insectstalled(r) &&
!is_cursed(u->attribs, C_KAELTESCHUTZ,0))
continue;
if (fval(u, UFL_WERE|UFL_LONGACTION)) {
continue; continue;
} }
} else {
args = (spellparameter *) NULL; for (ord = u->orders; ord; ord = ord->next) {
} if (get_keyword(ord) == K_CAST) {
co = new_castorder(mage, familiar, sp, target_r, level, 0, range, castorder * co = cast_cmd(u, ord);
ord, args); fset(u, UFL_LONGACTION|UFL_NOTMOVING);
add_castorder(&cll[(int)(sp->rank)], co); if (co) {
const spell * sp = co->sp;
add_castorder(&spellranks[sp->rank], co);
}
} }
} }
if (casted) fset(u, UFL_LONGACTION|UFL_NOTMOVING);
} }
} }
@ -2709,8 +2703,8 @@ magic(void)
* (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,6 +2801,7 @@ 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);
@ -2814,8 +2809,8 @@ magic(void)
} }
} }
} }
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();
} }

View File

@ -161,7 +161,7 @@ typedef struct spell {
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;
@ -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 */