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);
ord = NULL;
} 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;
}
}

View File

@ -1494,14 +1494,10 @@ do_combatmagic(battle *b, combatmagic_t was)
side * s;
region *r = b->region;
castorder *co;
castorder *cll[MAX_SPELLRANK];
int level;
int spellrank;
int sl;
int level, rank, sl;
spellrank spellranks[MAX_SPELLRANK];
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
cll[spellrank] = (castorder*)NULL;
}
memset(spellranks, 0, sizeof(spellranks));
for (s = b->sides; s; s = s->next) {
fighter * fig;
@ -1561,13 +1557,13 @@ do_combatmagic(battle *b, combatmagic_t was)
pay_spell(mage, sp, level, 1);
} else {
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 (co = cll[spellrank]; co; co = co->next) {
for (rank = 0; rank < MAX_SPELLRANK; rank++) {
for (co = spellranks[rank].begin; co; co = co->next) {
fighter * fig = co->magician.fig;
const spell * sp = co->sp;
int level = co->level;
@ -1583,8 +1579,8 @@ do_combatmagic(battle *b, combatmagic_t was)
}
}
}
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
free_castorders(cll[spellrank]);
for (rank = 0; rank < MAX_SPELLRANK; rank++) {
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 */
void
add_castorder(castorder **cll, castorder *co)
add_castorder(spellrank *cll, castorder *co)
{
castorder *co2;
/* Anfang der Liste? */
if (*cll == NULL) {
*cll = co;
return;
if (cll->begin==NULL) {
cll->end = &cll->begin;
}
/* suche letztes element */
for (co2 = *cll; co2->next != NULL; co2 = co2->next) {
}
co2->next = co;
*cll->end = co;
cll->end = &co->next;
return;
}
@ -2438,77 +2433,27 @@ is_moving_ship(const region * r, const ship *sh)
return false;
}
/* ------------------------------------------------------------- */
/* 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)
static castorder *
cast_cmd(unit * u, order * ord)
{
region *r;
region *target_r;
unit *u; /* Aktuelle unit in Region */
unit *familiar; /* wenn u ein Vertrauter ist */
unit *mage; /* derjenige, der den Spruch am Ende zaubert */
spell *sp;
region * r = u->region;
region * target_r = r;
int level, range;
unit *familiar = NULL, *mage = u;
const char * s;
int spellrank;
int range;
short t_x, t_y;
castorder *co;
castorder *cll[MAX_SPELLRANK];
spellparameter *args;
spell * sp;
spellparameter *args = NULL;
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)) {
cmistake(u, ord, 224, MSG_MAGIC);
continue;
return 0;
}
if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
cmistake(u, ord, 269, MSG_MAGIC);
continue;
return 0;
}
casted = true;
target_r = r;
mage = u;
level = eff_skill(u, SK_MAGIC, r);
familiar = NULL;
init_tokens(ord);
skip_token();
s = getstrtoken();
@ -2519,21 +2464,21 @@ magic(void)
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
continue;
return 0;
}
s = getstrtoken();
}
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_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;
return 0;
}
s = getstrtoken();
}
@ -2546,13 +2491,13 @@ magic(void)
if (level < 1) {
/* Fehler "Das macht wenig Sinn" */
cmistake(u, ord, 10, MSG_MAGIC);
continue;
return 0;
}
}
if (!s[0] || strlen(s) == 0) {
/* Fehler "Es wurde kein Zauber angegeben" */
cmistake(u, ord, 172, MSG_MAGIC);
continue;
return 0;
}
sp = get_spellfromtoken(u, s, u->faction->locale);
@ -2568,7 +2513,7 @@ magic(void)
if (sp == NULL) {
/* Fehler 'Spell not found' */
cmistake(u, ord, 173, MSG_MAGIC);
continue;
return 0;
}
/* um testen auf spruchnamen zu unterbinden sollte vor allen
* fehlermeldungen die anzeigen das der magier diesen Spruch
@ -2578,13 +2523,13 @@ magic(void)
/* vorsicht! u kann der familiar sein */
if (!familiar) {
cmistake(u, ord, 173, MSG_MAGIC);
continue;
return 0;
}
}
if (sp->sptyp & ISCOMBATSPELL) {
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
cmistake(u, ord, 174, MSG_MAGIC);
continue;
return 0;
}
/* Auf dem Ozean Zaubern als quasi-langer Befehl können
* normalerweise nur Meermenschen, ausgenommen explizit als
@ -2596,7 +2541,7 @@ magic(void)
/* Fehlermeldung */
ADDMSG(&u->faction->msgs, msg_message("spellfail_onocean",
"unit region command", u, u->region, ord));
continue;
return 0;
}
/* Auf bewegenden Schiffen kann man nur explizit als
* ONSHIPCAST deklarierte Zauber sprechen */
@ -2606,7 +2551,7 @@ magic(void)
/* Fehler: "Diesen Spruch kann man nicht auf einem sich
* bewegenden Schiff stehend zaubern" */
cmistake(u, ord, 175, MSG_MAGIC);
continue;
return 0;
}
}
}
@ -2617,13 +2562,13 @@ magic(void)
/* Fehler "Diesen Spruch kann man nicht in die Ferne
* richten" */
cmistake(u, ord, 176, MSG_MAGIC);
continue;
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)));
continue;
return 0;
}
}
/* Stufenangabe bei nicht Stufenvariierbaren Sprüchen abfangen */
@ -2646,19 +2591,19 @@ magic(void)
if ((sp->sptyp & NOTFAMILIARCAST)) {
/* Fehler: "Diesen Spruch kann der Vertraute nicht zaubern" */
cmistake(u, ord, 177, MSG_MAGIC);
continue;
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));
continue;
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));
continue;
return 0;
}
/* mage auf magier setzen, level anpassen, range für Erhöhung
* der Spruchkosten nutzen, langen Befehl des Magiers
@ -2688,17 +2633,66 @@ magic(void)
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
* 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;
}
} else {
args = (spellparameter *) NULL;
}
co = new_castorder(mage, familiar, sp, target_r, level, 0, range,
ord, args);
add_castorder(&cll[(int)(sp->rank)], co);
for (ord = u->orders; ord; ord = ord->next) {
if (get_keyword(ord) == K_CAST) {
castorder * co = cast_cmd(u, ord);
fset(u, UFL_LONGACTION|UFL_NOTMOVING);
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
* Spruch gezaubert wird) */
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
for (co = cll[spellrank]; co; co = co->next) {
for (rank = 0; rank < MAX_SPELLRANK; rank++) {
for (co = spellranks[rank].begin; co; co = co->next) {
order * ord = co->order;
int verify, cast_level = co->level;
boolean fumbled = false;
@ -2807,6 +2801,7 @@ magic(void)
/* Sind alle Zauber gesprochen gibts Erfahrung */
for (r = regions; r; r = r->next) {
unit *u;
for (u = r->units; u; u = u->next) {
if (is_mage(u) && countspells(u, 0) > 0) {
produceexp(u, SK_MAGIC, u->number);
@ -2814,8 +2809,8 @@ magic(void)
}
}
}
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
free_castorders(cll[spellrank]);
for (rank = 0; rank < MAX_SPELLRANK; rank++) {
free_castorders(spellranks[rank].begin);
}
remove_empty_units();
}

View File

@ -161,7 +161,7 @@ typedef struct spell {
char *parameter;
magic_t magietyp;
int sptyp;
char rank; /* Reihenfolge der Zauber */
int rank; /* Reihenfolge der Zauber */
int level; /* Stufe des Zaubers */
struct spell_component * components;
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);
/* 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,
int lev, double force, int distance, struct order * ord, spellparameter *p);
/* 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 */
void free_castorders(castorder *co);
void free_castorders(struct castorder *co);
/* Speicher wieder freigeben */
/* Prüfroutinen für Zaubern */