/* Copyright (c) 1998-2015, Enno Rehling Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. **/ #ifndef H_KRNL_MAGIC #define H_KRNL_MAGIC #include #include #include #ifdef __cplusplus extern "C" { #endif #define MAXCOMBATSPELLS 3 /* PRECOMBAT COMBAT POSTCOMBAT */ #define MAX_SPELLRANK 9 /* Standard-Rank 5 */ #define MAXINGREDIENT 5 /* bis zu 5 Komponenten pro Zauber */ #define CHAOSPATZERCHANCE 10 /* +10% Chance zu Patzern */ #define IRONGOLEM_CRUMBLE 15 /* monatlich Chance zu zerfallen */ #define STONEGOLEM_CRUMBLE 10 /* monatlich Chance zu zerfallen */ struct sc_mage; struct unit; extern const char *magic_school[MAXMAGIETYP]; extern struct attrib_type at_familiar; extern struct attrib_type at_familiarmage; /* ------------------------------------------------------------- */ /* Spruchparameter * Wir suchen beim Parsen des Befehls erstmal nach lokalen Objekten, * erst in verify_targets wird dann global gesucht, da in den meisten * Faellen das Zielobjekt lokal sein duerfte */ /* siehe auch objtype_t in objtypes.h */ typedef enum { SPP_REGION, /* "r" : findregion(x,y) -> *region */ SPP_UNIT, /* - : atoi36() -> int */ SPP_TEMP, /* - : temp einheit */ SPP_BUILDING, /* - : atoi() -> int */ SPP_SHIP, /* - : atoi() -> int */ SPP_STRING, /* "c" */ SPP_INT /* "i" : atoi() -> int */ } sppobj_t; typedef struct spllprm { sppobj_t typ; int flag; union { struct region *r; struct unit *u; struct building *b; struct ship *sh; char *s; char *xs; int i; } data; } spllprm; typedef struct spellparameter { int length; /* Anzahl der Elemente */ struct spllprm **param; } spellparameter; typedef struct strarray { int length; /* Anzahl der Elemente */ char **strings; } strarray; #define TARGET_RESISTS (1<<0) #define TARGET_NOTFOUND (1<<1) /* ------------------------------------------------------------- */ /* Magier: * - Magierichtung * - Magiepunkte derzeit * - Malus (neg. Wert)/ Bonus (pos. Wert) auf maximale Magiepunkte * (koennen sich durch Questen absolut veraendern und durch Gegenstände * temporaer). Auch fuer Artefakt benoetigt man permanente MP * - Anzahl bereits gezauberte Sprueche diese Runde * - Kampfzauber (3) (vor/waehrend/nach) * - Spruchliste */ typedef struct spell_names { struct spell_names *next; const struct locale *lang; void * tokens; } spell_names; /* ------------------------------------------------------------- */ /* Zauberliste */ typedef struct castorder { struct castorder *next; union { struct unit *u; struct fighter *fig; } magician; /* Magier (kann vom Typ struct unit oder fighter sein) */ struct unit *_familiar; /* Vertrauter, gesetzt, wenn der Spruch durch den Vertrauten gezaubert wird */ const struct spell *sp; /* Spruch */ int level; /* gewuenschte Stufe oder Stufe des Magiers */ double force; /* Staerke des Zaubers */ struct region *_rtarget; /* Zielregion des Spruchs */ int distance; /* Entfernung zur Zielregion */ struct order *order; /* Befehl */ struct spellparameter *par; /* fuer weitere Parameter */ } castorder; struct unit * co_get_caster(const struct castorder * co); struct unit * co_get_magician(const struct castorder * co); struct region * co_get_region(const struct castorder * co); typedef struct spell_component { const struct resource_type *type; int amount; int cost; } spell_component; /* ------------------------------------------------------------- */ /* besondere Spruchtypen */ #define FARCASTING (1<<0) /* ZAUBER [struct region x y] */ #define SPELLLEVEL (1<<1) /* ZAUBER [STUFE x] */ #define OCEANCASTABLE (1<<2) /* Koennen auch nicht-Meermenschen auf hoher See zaubern */ #define ONSHIPCAST (1<<3) /* kann auch auf von Land ablegenden Schiffen stehend gezaubert werden */ #define TESTCANSEE (1<<4) /* alle Zielunits auf cansee pruefen */ /* ID's koennen zu drei unterschiedlichen Entitaeten gehören: Einheiten, * Gebaeuden und Schiffen. */ #define UNITSPELL (1<<5) /* ZAUBER .. [ ..] */ #define SHIPSPELL (1<<6) /* ZAUBER .. [ ..] */ #define BUILDINGSPELL (1<<7) /* ZAUBER .. [ ..] */ #define REGIONSPELL (1<<8) /* wirkt auf struct region */ #define GLOBALTARGET (1<<9) /* Ziel kann ausserhalb der region sein */ #define PRECOMBATSPELL (1<<10) /* PRÄKAMPFZAUBER .. */ #define COMBATSPELL (1<<11) /* KAMPFZAUBER .. */ #define POSTCOMBATSPELL (1<<12) /* POSTKAMPFZAUBER .. */ #define ISCOMBATSPELL (PRECOMBATSPELL|COMBATSPELL|POSTCOMBATSPELL) #define TESTRESISTANCE (1<<13) /* Zielobjekte auf Magieresistenz pruefen. not used in XML? */ #define NOTFAMILIARCAST (1<<14) /* not used by XML? */ #define ANYTARGET (UNITSPELL|REGIONSPELL|BUILDINGSPELL|SHIPSPELL) /* wirkt auf alle objekttypen (unit, ship, building, region) */ /* Flag Spruchkostenberechnung: */ enum { SPC_FIX, /* Fixkosten */ SPC_LEVEL, /* Komponenten pro Level */ SPC_LINEAR /* Komponenten pro Level und muessen vorhanden sein */ }; /* ------------------------------------------------------------- */ /* Prototypen */ void magic(void); void regenerate_aura(void); extern struct attrib_type at_mage; extern struct attrib_type at_familiarmage; extern struct attrib_type at_familiar; extern struct attrib_type at_clonemage; extern struct attrib_type at_clone; extern struct attrib_type at_icastle; void make_icastle(struct building *b, const struct building_type *btype, int timeout); const struct building_type *icastle_type(const struct attrib *a); /* ------------------------------------------------------------- */ /* Kommentare: * * Spruchzauberrei und Gegenstandszauberrei werden getrennt behandelt. * Das macht u.a. bestimmte Fehlermeldungen einfacher, das * identifizieren der Komponennten ueber den Missversuch ist nicht * moeglich * Spruchzauberrei: 'ZAUBER [struct region x y] [STUFE a] "Spruchname" [Ziel]' * Gegenstandszauberrei: 'BENUTZE "Gegenstand" [Ziel]' * * Die Funktionen: */ /* Magier */ struct sc_mage *create_mage(struct unit *u, magic_t mtyp); /* macht die struct unit zu einem neuen Magier: legt die struct u->mage an * und initialisiert den Magiertypus mit mtyp. */ struct sc_mage *get_mage(const struct unit *u); enum magic_t mage_get_type(const struct sc_mage *mage); const struct spell *mage_get_combatspell(const struct sc_mage *mage, int nr, int *level); struct spellbook * mage_get_spellbook(const struct sc_mage * mage); int mage_get_spellpoints(const struct sc_mage *m); int mage_change_spellpoints(struct sc_mage *m, int delta); enum magic_t unit_get_magic(const struct unit *u); void unit_set_magic(struct unit *u, enum magic_t mtype); struct spellbook * unit_get_spellbook(const struct unit * u); void unit_add_spell(struct unit * u, struct spell * sp, int level); bool is_mage(const struct unit *u); /* gibt true, wenn u->mage gesetzt. */ bool is_familiar(const struct unit *u); /* gibt true, wenn eine Familiar-Relation besteht. */ /* Sprueche */ int get_combatspelllevel(const struct unit *u, int nr); /* versucht, eine eingestellte maximale Kampfzauberstufe * zurueckzugeben. 0 = Maximum, -1 u ist kein Magier. */ const struct spell *get_combatspell(const struct unit *u, int nr); /* gibt den Kampfzauber nr [pre/kampf/post] oder NULL zurueck */ void set_combatspell(struct unit *u, struct spell * sp, struct order *ord, int level); /* setzt Kampfzauber */ void unset_combatspell(struct unit *u, struct spell * sp); /* loescht Kampfzauber */ /* fuegt den Spruch mit der Id spellid der Spruchliste der Einheit hinzu. */ int u_hasspell(const struct unit *u, const struct spell *sp); /* prueft, ob der Spruch in der Spruchliste der Einheit steht. */ void pick_random_spells(struct faction *f, int level, struct spellbook * book, int num_spells); bool knowsspell(const struct region *r, const struct unit *u, const struct spell * sp); /* prueft, ob die Einheit diesen Spruch gerade beherrscht, dh * mindestens die erforderliche Stufe hat. Hier koennen auch Abfragen * auf spezielle Antimagiezauber auf Regionen oder Einheiten eingefuegt * werden */ /* Magiepunkte */ int get_spellpoints(const struct unit *u); /* Gibt die aktuelle Anzahl der Magiepunkte der Einheit zurueck */ void set_spellpoints(struct unit *u, int sp); /* setzt die Magiepunkte auf sp */ int change_spellpoints(struct unit *u, int mp); /* veraendert die Anzahl der Magiepunkte der Einheit um +mp */ int max_spellpoints_depr(const struct region *r, const struct unit *u); int max_spellpoints(const struct unit *u, const struct region *r); /* gibt die aktuell maximal moeglichen Magiepunkte der Einheit zurueck */ int change_maxspellpoints(struct unit *u, int csp); /* veraendert die maximalen Magiepunkte einer Einheit */ /* Zaubern */ extern double spellpower(struct region *r, struct unit *u, const struct spell * sp, int cast_level, struct order *ord); /* ermittelt die Staerke eines Spruchs */ bool fumble(struct region *r, struct unit *u, const struct spell * sp, int cast_level); /* true, wenn der Zauber misslingt, bei false gelingt der Zauber */ typedef struct spellrank { struct castorder *begin; struct castorder **handle_end; } spellrank; struct castorder *create_castorder(struct castorder * co, struct unit *caster, struct unit * familiar, const struct spell * sp, struct region * r, int lev, double force, int range, struct order * ord, struct spellparameter * p); void free_castorder(struct castorder *co); /* Zwischenspreicher fuer Zauberbefehle, notwendig für Prioritaeten */ void add_castorder(struct spellrank *cll, struct castorder *co); /* Haenge c-order co an die letze c-order von cll an */ void free_castorders(struct castorder *co); /* Speicher wieder freigeben */ int cast_spell(struct castorder *co); /* Pruefroutinen für Zaubern */ int countspells(struct unit *u, int step); int spellcount(const struct unit *u); /* erhoeht den Counter fuer Zaubersprüche um 'step' und gibt die neue * Anzahl der gezauberten Sprueche zurück. */ int auracost(const struct unit *caster, const struct spell *sp); int spellcost(const struct unit *caster, const struct spell_component *spc); /* gibt die fuer diesen Spruch derzeit notwendigen Magiepunkte auf der * geringstmoeglichen Stufe zurueck, schon um den Faktor der bereits * zuvor gezauberten Sprueche erhoeht */ bool cancast(struct unit *u, const struct spell * spruch, int eff_stufe, int distance, struct order *ord); /* true, wenn Einheit alle Komponenten des Zaubers (incl. MP) fuer die * geringstmoegliche Stufe hat und den Spruch beherrscht */ void pay_spell(struct unit *mage, const struct unit *caster, const struct spell * sp, int eff_stufe, int distance); /* zieht die Komponenten des Zaubers aus dem Inventory der Einheit * ab. Die effektive Stufe des gezauberten Spruchs ist wichtig fuer * die korrekte Bestimmung der Magiepunktkosten */ int eff_spelllevel(struct unit *mage, struct unit *caster, const struct spell * sp, int cast_level, int distance); /* ermittelt die effektive Stufe des Zaubers. Dabei ist cast_level * die gewuenschte maximale Stufe (im Normalfall Stufe des Magiers, * bei Farcasting Stufe*2^Entfernung) */ bool is_magic_resistant(struct unit *magician, struct unit *target, int resist_bonus); /* Mapperfunktion fuer target_resists_magic() vom Typ struct unit. */ variant magic_resistance(struct unit *target); /* gibt die Chance an, mit der einem Zauber widerstanden wird. Je * groesser, desto resistenter ist da Opfer */ bool target_resists_magic(struct unit *magician, void *obj, int objtyp, int resist_bonus); /* gibt false zurueck, wenn der Zauber gelingt, true, wenn das Ziel * widersteht */ extern struct spell * unit_getspell(struct unit *u, const char *s, const struct locale *lang); const char *magic_name(magic_t mtype, const struct locale *lang); /* Sprueche in der struct region */ /* (sind in curse) */ void set_familiar(struct unit * mage, struct unit * familiar); struct unit *get_familiar(const struct unit *u); struct unit *get_familiar_mage(const struct unit *u); struct unit *get_clone(const struct unit *u); void remove_familiar(struct unit *mage); void create_newfamiliar(struct unit *mage, struct unit *familiar); void create_newclone(struct unit *mage, struct unit *familiar); void fix_fam_mage(struct unit *u); const char *spell_info(const struct spell *sp, const struct locale *lang); const char *spell_name(const struct spell *sp, const struct locale *lang); const char *curse_name(const struct curse_type *ctype, const struct locale *lang); struct message *msg_unitnotfound(const struct unit *mage, struct order *ord, const struct spllprm *spobj); bool FactionSpells(void); struct spellbook * get_spellbook(const char * name); void free_spellbooks(void); void free_spellbook(struct spellbook *sb); #ifdef __cplusplus } #endif #endif