forked from github/server
cleaning up in the magic code a little, and making the actual casting a separate function for easier debugging.
This commit is contained in:
parent
98141baec1
commit
c95342a88b
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -2074,7 +2069,7 @@ free_castorders(castorder *co)
|
|||
{
|
||||
castorder *co2;
|
||||
|
||||
while(co) {
|
||||
while (co) {
|
||||
co2 = co;
|
||||
co = co->next;
|
||||
if (co2->par) {
|
||||
|
@ -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;
|
||||
const char *s;
|
||||
int spellrank;
|
||||
int range;
|
||||
short t_x, t_y;
|
||||
castorder *co;
|
||||
castorder *cll[MAX_SPELLRANK];
|
||||
spellparameter *args;
|
||||
region * r = u->region;
|
||||
region * target_r = r;
|
||||
int level, range;
|
||||
unit *familiar = NULL, *mage = u;
|
||||
const char * s;
|
||||
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,15 +2801,16 @@ 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) {
|
||||
if (is_mage(u) && countspells(u, 0) > 0) {
|
||||
produceexp(u, SK_MAGIC, u->number);
|
||||
/* Spruchlistenaktualiesierung ist in Regeneration */
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue