forked from github/server
Zauber, die von antimagiezonen komplett blockiert werden, kosten trotzdem Aura
This commit is contained in:
parent
d1cb08df6e
commit
55ffed1b26
1 changed files with 352 additions and 359 deletions
|
@ -2658,375 +2658,368 @@ is_moving_ship(const region * r, const ship *sh)
|
||||||
void
|
void
|
||||||
magic(void)
|
magic(void)
|
||||||
{
|
{
|
||||||
region *r;
|
region *r;
|
||||||
region *target_r;
|
region *target_r;
|
||||||
unit *u; /* Aktuelle unit in Region */
|
unit *u; /* Aktuelle unit in Region */
|
||||||
unit *familiar; /* wenn u ein Vertrauter ist */
|
unit *familiar; /* wenn u ein Vertrauter ist */
|
||||||
unit *mage; /* derjenige, der den Spruch am Ende zaubert */
|
unit *mage; /* derjenige, der den Spruch am Ende zaubert */
|
||||||
spell *sp;
|
spell *sp;
|
||||||
const char *s;
|
const char *s;
|
||||||
strlist *so;
|
strlist *so;
|
||||||
int spellrank;
|
int spellrank;
|
||||||
int level, success;
|
int range, t_x, t_y;
|
||||||
int range, t_x, t_y;
|
int skiptokens;
|
||||||
double force;
|
castorder *co;
|
||||||
int skiptokens;
|
castorder *cll[MAX_SPELLRANK];
|
||||||
castorder *co;
|
spellparameter *args;
|
||||||
castorder *cll[MAX_SPELLRANK];
|
|
||||||
spellparameter *args;
|
|
||||||
|
|
||||||
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
|
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
|
||||||
cll[spellrank] = (castorder*)NULL;
|
cll[spellrank] = (castorder*)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (r = regions; r; r = r->next) {
|
for (r = regions; r; r = r->next) {
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
boolean casted = false;
|
int level;
|
||||||
|
boolean casted = false;
|
||||||
|
|
||||||
if (old_race(u->race) == RC_SPELL || fval(u, UFL_LONGACTION))
|
if (old_race(u->race) == RC_SPELL || fval(u, UFL_LONGACTION))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (old_race(u->race) == RC_INSECT && r_insectstalled(r) &&
|
if (old_race(u->race) == RC_INSECT && r_insectstalled(r) &&
|
||||||
!is_cursed(u->attribs, C_KAELTESCHUTZ,0))
|
!is_cursed(u->attribs, C_KAELTESCHUTZ,0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(fval(u, UFL_WERE)) {
|
if(fval(u, UFL_WERE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attacked(u)) {
|
if (attacked(u)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (so = u->orders; so; so = so->next) {
|
for (so = u->orders; so; so = so->next) {
|
||||||
if (igetkeyword(so->s, u->faction->locale) == K_CAST) {
|
if (igetkeyword(so->s, u->faction->locale) == K_CAST) {
|
||||||
if (LongHunger() && fval(u, UFL_HUNGER)) {
|
if (LongHunger() && fval(u, UFL_HUNGER)) {
|
||||||
cmistake(u, so->s, 224, MSG_MAGIC);
|
cmistake(u, so->s, 224, MSG_MAGIC);
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
|
|
||||||
cmistake(u, so->s, 269, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
casted = true;
|
|
||||||
target_r = r;
|
|
||||||
mage = u;
|
|
||||||
level = eff_skill(u, SK_MAGIC, r);
|
|
||||||
familiar = NULL;
|
|
||||||
skiptokens = 1;
|
|
||||||
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);
|
|
||||||
s = getstrtoken();
|
|
||||||
skiptokens += 2;
|
|
||||||
if (level < 1) {
|
|
||||||
/* Fehler "Das macht wenig Sinn" */
|
|
||||||
cmistake(u, so->s, 10, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (findparam(s, u->faction->locale) == P_REGION) {
|
|
||||||
t_x = atoi(getstrtoken());
|
|
||||||
t_x = rel_to_abs(getplane(u->region),u->faction,t_x,0);
|
|
||||||
t_y = atoi(getstrtoken());
|
|
||||||
t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1);
|
|
||||||
target_r = findregion(t_x, t_y);
|
|
||||||
s = getstrtoken();
|
|
||||||
skiptokens += 3;
|
|
||||||
if (!target_r) {
|
|
||||||
/* Fehler "Es wurde kein Zauber angegeben" */
|
|
||||||
cmistake(u, so->s, 172, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 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();
|
|
||||||
skiptokens += 2;
|
|
||||||
if (level < 1) {
|
|
||||||
/* Fehler "Das macht wenig Sinn" */
|
|
||||||
cmistake(u, so->s, 10, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!s[0] || strlen(s) == 0) {
|
|
||||||
/* Fehler "Es wurde kein Zauber angegeben" */
|
|
||||||
cmistake(u, so->s, 172, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sp = find_spellbyname(u, s, u->faction->locale);
|
|
||||||
|
|
||||||
/* Vertraute können auch Zauber sprechen, die sie selbst nicht
|
|
||||||
* können. find_spellbyname findet aber nur jene Sprüche, die
|
|
||||||
* die Einheit beherrscht. */
|
|
||||||
if (sp == NULL && is_familiar(u)) {
|
|
||||||
familiar = u;
|
|
||||||
mage = get_familiar_mage(u);
|
|
||||||
sp = find_spellbyname(mage, s, mage->faction->locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sp == NULL) {
|
|
||||||
/* Fehler 'Spell not found' */
|
|
||||||
cmistake(u, so->s, 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) == false){
|
|
||||||
/* vorsicht! u kann der familiar sein */
|
|
||||||
if (!familiar){
|
|
||||||
cmistake(u, so->s, 173, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sp->sptyp & ISCOMBATSPELL) {
|
|
||||||
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
|
|
||||||
cmistake(u, so->s, 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 (rterrain(r) == T_OCEAN) {
|
|
||||||
if (old_race(u->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, so->s));
|
|
||||||
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, so->s, 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, so->s, 176, MSG_MAGIC);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
|
|
||||||
sprintf(buf, "%s in %s: 'ZAUBER %s' Zu der Region %s kann keine "
|
|
||||||
"Verbindung hergestellt werden", unitname(u),
|
|
||||||
regionid(u->region),
|
|
||||||
spell_name(sp, u->faction->locale),
|
|
||||||
regionid(target_r));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
|
||||||
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;
|
|
||||||
sprintf(buf, "%s in %s: 'ZAUBER %s' Dieser Zauber kann nicht "
|
|
||||||
"mit Stufenangabe gezaubert werden.", unitname(u),
|
|
||||||
regionid(u->region),
|
|
||||||
spell_name(sp, u->faction->locale));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_WARN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 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, so->s, 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 */
|
|
||||||
sprintf(buf, "%s kann Sprüche, die durch %s wirken, nicht "
|
|
||||||
"zusätzlich nochmal in die Ferne richten.",
|
|
||||||
unitname(mage), unitname(u));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) {
|
|
||||||
sprintf(buf, "%s kann nicht genug Kraft aufbringen, um "
|
|
||||||
"durch %s zu wirken", unitname(mage), unitname(u));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
|
||||||
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_string(&mage->thisorder, "");
|
|
||||||
level = min(level, eff_skill(mage, SK_MAGIC, mage->region)/2);
|
|
||||||
familiar = u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Weitere Argumente zusammenbasten */
|
|
||||||
if (sp->parameter) {
|
|
||||||
++skiptokens;
|
|
||||||
args = add_spellparameter(target_r, mage, sp->parameter,
|
|
||||||
so->s, skiptokens);
|
|
||||||
if (!args) {
|
|
||||||
/* Syntax war falsch */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
args = (spellparameter *) NULL;
|
|
||||||
}
|
|
||||||
co = new_castorder(mage, familiar, sp, target_r, level, 0, range,
|
|
||||||
strdup(so->s), args);
|
|
||||||
add_castorder(&cll[(int)(sp->rank)], co);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (casted) fset(u, UFL_LONGACTION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
|
|
||||||
for (co = cll[spellrank]; co; co = co->next) {
|
|
||||||
char *cmd = co->order;
|
|
||||||
|
|
||||||
u = (unit *)co->magician;
|
|
||||||
sp = co->sp;
|
|
||||||
level = co->level; /* Talent des Magiers oder gewünschte Stufe */
|
|
||||||
target_r = co->rt;
|
|
||||||
|
|
||||||
/* Da sich die Aura und Komponenten in der Zwischenzeit verändert
|
|
||||||
* haben können und sich durch vorherige Sprüche das Zaubern
|
|
||||||
* erschwert haben kann, muss hier erneut geprüft werden, ob der
|
|
||||||
* Spruch überhaupt gezaubert werden kann.
|
|
||||||
* (level) die effektive Stärke des Spruchs (= Stufe, auf der der
|
|
||||||
* Spruch gezaubert wird) */
|
|
||||||
|
|
||||||
/* reichen die Komponenten nicht, wird der Level reduziert. */
|
|
||||||
level = eff_spelllevel(u, sp, level, co->distance);
|
|
||||||
if (level < 1) {
|
|
||||||
/* Fehlermeldung mit Komponenten generieren */
|
|
||||||
cancast(u, sp, co->level, co->distance, cmd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (level < co->level){
|
|
||||||
/* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs
|
|
||||||
* gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */
|
|
||||||
if (spl_costtyp(sp) != SPC_FIX) {
|
|
||||||
sprintf(buf, "%s hat nur genügend Komponenten um %s auf Stufe %d "
|
|
||||||
"zu zaubern.", unitname(u),
|
|
||||||
spell_name(sp, u->faction->locale), level);
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_INFO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
co->level = level;
|
|
||||||
|
|
||||||
/* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt
|
|
||||||
* werden können */
|
|
||||||
if (cancast(u, sp, level, co->distance, cmd) == false) {
|
|
||||||
/* die Fehlermeldung wird in cancast generiert */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* die Stärke kann durch Antimagie auf 0 sinken */
|
|
||||||
force = spellpower(target_r, u, sp, level);
|
|
||||||
if (force <= 0) {
|
|
||||||
sprintf(buf, "%s schafft es nicht genügend Kraft aufzubringen "
|
|
||||||
"um %s dennoch zu zaubern.", unitname(u),
|
|
||||||
spell_name(sp, u->faction->locale));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
co->force = force;
|
|
||||||
|
|
||||||
/* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde
|
|
||||||
* kein Ziel gefunden, so ist verify_targets=0. Scheitert der
|
|
||||||
* Spruch an der Magieresistenz, so ist verify_targets = 1, bei
|
|
||||||
* Erfolg auf ganzer Linie ist verify_targets= 2
|
|
||||||
*/
|
|
||||||
switch (verify_targets(co)){
|
|
||||||
case 0:
|
|
||||||
/* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */
|
|
||||||
continue; /* äußere Schleife, nächster Zauberer */
|
|
||||||
case 1:
|
|
||||||
{ /* einige oder alle Ziele waren magieresistent */
|
|
||||||
spellparameter *pa = co->par;
|
|
||||||
int n;
|
|
||||||
for (n=0; n!=pa->length;++n) {
|
|
||||||
if(pa->param[n]->flag != TARGET_RESISTS
|
|
||||||
&& pa->param[n]->flag != TARGET_NOTFOUND)
|
|
||||||
{ /* mindestens ein erfolgreicher Zauberversuch, wir machen
|
|
||||||
normal weiter */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (n==pa->length) {
|
|
||||||
/* zwar wurde mindestens ein Ziel gefunden, das widerstand
|
|
||||||
* jedoch dem Zauber. Kosten abziehen und abbrechen. */
|
|
||||||
pay_spell(u, sp, level, co->distance);
|
|
||||||
countspells(u, 1);
|
|
||||||
sprintf(buf, "%s gelingt es %s zu zaubern, doch der Spruch zeigt "
|
|
||||||
"keine Wirkung.", unitname(u),
|
|
||||||
spell_name(sp, u->faction->locale));
|
|
||||||
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
|
||||||
continue; /* äußere Schleife, nächster Zauberer */
|
|
||||||
}
|
}
|
||||||
break;
|
if (r->planep && fval(r->planep, PFL_NOMAGIC)) {
|
||||||
}
|
cmistake(u, so->s, 269, MSG_MAGIC);
|
||||||
case 2:
|
continue;
|
||||||
default:
|
}
|
||||||
/* Zauber war erfolgreich */
|
casted = true;
|
||||||
break;
|
target_r = r;
|
||||||
}
|
mage = u;
|
||||||
|
level = eff_skill(u, SK_MAGIC, r);
|
||||||
|
familiar = NULL;
|
||||||
|
skiptokens = 1;
|
||||||
|
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);
|
||||||
|
s = getstrtoken();
|
||||||
|
skiptokens += 2;
|
||||||
|
if (level < 1) {
|
||||||
|
/* Fehler "Das macht wenig Sinn" */
|
||||||
|
cmistake(u, so->s, 10, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (findparam(s, u->faction->locale) == P_REGION) {
|
||||||
|
t_x = atoi(getstrtoken());
|
||||||
|
t_x = rel_to_abs(getplane(u->region),u->faction,t_x,0);
|
||||||
|
t_y = atoi(getstrtoken());
|
||||||
|
t_y = rel_to_abs(getplane(u->region),u->faction,t_y,1);
|
||||||
|
target_r = findregion(t_x, t_y);
|
||||||
|
s = getstrtoken();
|
||||||
|
skiptokens += 3;
|
||||||
|
if (!target_r) {
|
||||||
|
/* Fehler "Es wurde kein Zauber angegeben" */
|
||||||
|
cmistake(u, so->s, 172, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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();
|
||||||
|
skiptokens += 2;
|
||||||
|
if (level < 1) {
|
||||||
|
/* Fehler "Das macht wenig Sinn" */
|
||||||
|
cmistake(u, so->s, 10, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!s[0] || strlen(s) == 0) {
|
||||||
|
/* Fehler "Es wurde kein Zauber angegeben" */
|
||||||
|
cmistake(u, so->s, 172, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sp = find_spellbyname(u, s, u->faction->locale);
|
||||||
|
|
||||||
/* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten
|
/* Vertraute können auch Zauber sprechen, die sie selbst nicht
|
||||||
* bezahlt werden und die nachfolgenden Sprüche werden teurer */
|
* können. find_spellbyname findet aber nur jene Sprüche, die
|
||||||
if (fumble(target_r, u, sp, level) == true) {
|
* die Einheit beherrscht. */
|
||||||
/* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */
|
if (sp == NULL && is_familiar(u)) {
|
||||||
pay_spell(u, sp, level, co->distance);
|
familiar = u;
|
||||||
do_fumble(co);
|
mage = get_familiar_mage(u);
|
||||||
countspells(u, 1);
|
sp = find_spellbyname(mage, s, mage->faction->locale);
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
success = ((nspell_f)sp->sp_function)(co);
|
|
||||||
if (success > 0) {
|
|
||||||
/* Kosten nur für real benötige Stufe berechnen */
|
|
||||||
pay_spell(u, sp, success, co->distance);
|
|
||||||
/* erst bezahlen, dann Kostenzähler erhöhen */
|
|
||||||
countspells(u,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sind alle Zauber gesprochen gibts Erfahrung */
|
if (sp == NULL) {
|
||||||
for (r = regions; r; r = r->next) {
|
/* Fehler 'Spell not found' */
|
||||||
for (u = r->units; u; u = u->next) {
|
cmistake(u, so->s, 173, MSG_MAGIC);
|
||||||
if (is_mage(u) && countspells(u,0) > 0) {
|
continue;
|
||||||
produceexp(u, SK_MAGIC, u->number);
|
}
|
||||||
/* Spruchlistenaktualiesierung ist in Regeneration */
|
/* 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 */
|
||||||
for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) {
|
if (knowsspell(r, u, sp) == false){
|
||||||
free_castorders(cll[spellrank]);
|
/* vorsicht! u kann der familiar sein */
|
||||||
}
|
if (!familiar){
|
||||||
|
cmistake(u, so->s, 173, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sp->sptyp & ISCOMBATSPELL) {
|
||||||
|
/* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */
|
||||||
|
cmistake(u, so->s, 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 (rterrain(r) == T_OCEAN) {
|
||||||
|
if (old_race(u->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, so->s));
|
||||||
|
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, so->s, 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, so->s, 176, MSG_MAGIC);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (range > 1024) { /* (2^10) weiter als 10 Regionen entfernt */
|
||||||
|
sprintf(buf, "%s in %s: 'ZAUBER %s' Zu der Region %s kann keine "
|
||||||
|
"Verbindung hergestellt werden", unitname(u),
|
||||||
|
regionid(u->region),
|
||||||
|
spell_name(sp, u->faction->locale),
|
||||||
|
regionid(target_r));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
||||||
|
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;
|
||||||
|
sprintf(buf, "%s in %s: 'ZAUBER %s' Dieser Zauber kann nicht "
|
||||||
|
"mit Stufenangabe gezaubert werden.", unitname(u),
|
||||||
|
regionid(u->region),
|
||||||
|
spell_name(sp, u->faction->locale));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_WARN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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, so->s, 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 */
|
||||||
|
sprintf(buf, "%s kann Sprüche, die durch %s wirken, nicht "
|
||||||
|
"zusätzlich nochmal in die Ferne richten.",
|
||||||
|
unitname(mage), unitname(u));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (distance(mage->region, r) > eff_skill(mage, SK_MAGIC, mage->region)) {
|
||||||
|
sprintf(buf, "%s kann nicht genug Kraft aufbringen, um "
|
||||||
|
"durch %s zu wirken", unitname(mage), unitname(u));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
||||||
|
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_string(&mage->thisorder, "");
|
||||||
|
level = min(level, eff_skill(mage, SK_MAGIC, mage->region)/2);
|
||||||
|
familiar = u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Weitere Argumente zusammenbasten */
|
||||||
|
if (sp->parameter) {
|
||||||
|
++skiptokens;
|
||||||
|
args = add_spellparameter(target_r, mage, sp->parameter,
|
||||||
|
so->s, skiptokens);
|
||||||
|
if (!args) {
|
||||||
|
/* Syntax war falsch */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args = (spellparameter *) NULL;
|
||||||
|
}
|
||||||
|
co = new_castorder(mage, familiar, sp, target_r, level, 0, range,
|
||||||
|
strdup(so->s), args);
|
||||||
|
add_castorder(&cll[(int)(sp->rank)], co);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (casted) fset(u, UFL_LONGACTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Da sich die Aura und Komponenten in der Zwischenzeit verändert
|
||||||
|
* haben können und sich durch vorherige Sprüche das Zaubern
|
||||||
|
* erschwert haben kann, muss beim zaubern erneut geprüft werden, ob der
|
||||||
|
* Spruch überhaupt gezaubert werden kann.
|
||||||
|
* (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) {
|
||||||
|
char *cmd = co->order;
|
||||||
|
int verify, cast_level = co->level;
|
||||||
|
boolean fumbled = false;
|
||||||
|
unit * u = (unit *)co->magician;
|
||||||
|
spell * sp = co->sp;
|
||||||
|
region * target_r = co->rt;
|
||||||
|
|
||||||
|
/* reichen die Komponenten nicht, wird der Level reduziert. */
|
||||||
|
co->level = eff_spelllevel(u, sp, cast_level, co->distance);
|
||||||
|
|
||||||
|
if (co->level < 1) {
|
||||||
|
/* Fehlermeldung mit Komponenten generieren */
|
||||||
|
cancast(u, sp, co->level, co->distance, cmd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cast_level > co->level) {
|
||||||
|
/* Sprüche mit Fixkosten werden immer auf Stufe des Spruchs
|
||||||
|
* gezaubert, co->level ist aber defaultmäßig Stufe des Magiers */
|
||||||
|
if (spl_costtyp(sp) != SPC_FIX) {
|
||||||
|
sprintf(buf, "%s hat nur genügend Komponenten um %s auf Stufe %d "
|
||||||
|
"zu zaubern.", unitname(u), spell_name(sp, u->faction->locale),
|
||||||
|
co->level);
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt
|
||||||
|
* werden können */
|
||||||
|
if (cancast(u, sp, co->level, co->distance, cmd) == false) {
|
||||||
|
/* die Fehlermeldung wird in cancast generiert */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
co->force = spellpower(target_r, u, sp, co->level);
|
||||||
|
/* die Stärke kann durch Antimagie auf 0 sinken */
|
||||||
|
if (co->force <= 0) {
|
||||||
|
co->force = 0;
|
||||||
|
sprintf(buf, "%s schafft es nicht genügend Kraft aufzubringen "
|
||||||
|
"um %s dennoch zu zaubern.", unitname(u),
|
||||||
|
spell_name(sp, u->faction->locale));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ziele auf Existenz prüfen und Magieresistenz feststellen. Wurde
|
||||||
|
* kein Ziel gefunden, so ist verify_targets=0. Scheitert der
|
||||||
|
* Spruch an der Magieresistenz, so ist verify_targets = 1, bei
|
||||||
|
* Erfolg auf ganzer Linie ist verify_targets= 2
|
||||||
|
*/
|
||||||
|
verify = verify_targets(co);
|
||||||
|
if (verify==0) {
|
||||||
|
/* kein Ziel gefunden, Fehlermeldungen sind in verify_targets */
|
||||||
|
/* keine kosten für den zauber */
|
||||||
|
continue; /* äußere Schleife, nächster Zauberer */
|
||||||
|
} else if (co->force>0 && verify==1) {
|
||||||
|
/* einige oder alle Ziele waren magieresistent */
|
||||||
|
spellparameter *pa = co->par;
|
||||||
|
int n;
|
||||||
|
for (n=0; n!=pa->length;++n) {
|
||||||
|
if ((pa->param[n]->flag & (TARGET_RESISTS|TARGET_NOTFOUND)) ==0) {
|
||||||
|
/* mindestens ein erfolgreicher Zauberversuch, wir machen normal weiter */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n==pa->length) {
|
||||||
|
co->force = 0;
|
||||||
|
/* zwar wurde mindestens ein Ziel gefunden, das widerstand
|
||||||
|
* jedoch dem Zauber. Kosten abziehen und abbrechen. */
|
||||||
|
sprintf(buf, "%s gelingt es %s zu zaubern, doch der Spruch zeigt "
|
||||||
|
"keine Wirkung.", unitname(u),
|
||||||
|
spell_name(sp, u->faction->locale));
|
||||||
|
addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE);
|
||||||
|
co->force = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Auch für Patzer gibt es Erfahrung, müssen die Spruchkosten
|
||||||
|
* bezahlt werden und die nachfolgenden Sprüche werden teurer */
|
||||||
|
if (co->force>0 && fumble(target_r, u, sp, co->level)) {
|
||||||
|
/* zuerst bezahlen, dann evt in do_fumble alle Aura verlieren */
|
||||||
|
fumbled = true;
|
||||||
|
co->force = 0;
|
||||||
|
} else if (co->force>0) {
|
||||||
|
co->level = ((nspell_f)sp->sp_function)(co);
|
||||||
|
if (co->level <= 0) {
|
||||||
|
/* Kosten nur für real benötige Stufe berechnen */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pay_spell(u, sp, co->level, co->distance);
|
||||||
|
/* erst bezahlen, dann Kostenzähler erhöhen */
|
||||||
|
if (fumbled) do_fumble(co);
|
||||||
|
countspells(u, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sind alle Zauber gesprochen gibts Erfahrung */
|
||||||
|
for (r = regions; r; r = r->next) {
|
||||||
|
for (u = r->units; u; u = u->next) {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attrib *
|
attrib *
|
||||||
|
|
Loading…
Reference in a new issue