server/src/common/kernel/curse.h

334 lines
12 KiB
C

/* vi: set ts=2:
*
* Eressea PB(E)M host Copyright (C) 1998-2003
* Christian Schlittchen (corwin@amber.kn-bremen.de)
* Katja Zedel (katze@felidae.kn-bremen.de)
* Henning Peters (faroul@beyond.kn-bremen.de)
* Enno Rehling (enno@eressea-pbem.de)
* Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
*
* This program may not be used, modified or distributed without
* prior permission by the authors of Eressea.
*/
#ifndef CURSE_H
#define CURSE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Sprueche in der struct region und auf Einheiten, Schiffen oder Burgen
* (struct attribute)
*/
/* Brainstorming Überarbeitung curse
*
* Ziel: Keine Enum-Liste, flexible, leicht erweiterbare Curse-Objekte
*
* Was wird gebraucht?
* - Eindeutige Kennung für globale Suche
* - eine Wirkung, die sich einfach 'anwenden' läßt, dabei flexibel ist,
* Raum läßt für variable Boni, Anzahl betroffener Personen,
* spezielle Effekte oder anderes
* - einfacher Zugriff auf allgemeine Funktionen wie zb Alterung, aber
* auch Antimagieverhalten
* - Ausgabe von Beschreibungen in verschiedenen Sprachen
* - definiertes gekapseltes Verhalten zb bei Zusammenlegung von
* Einheiten, Übergabe von Personen, Mehrfachverzauberung
* - (Rück-)Referenzen auf Objekt, Verursacher (Magier), ?
*
* Vieleicht wäre ein Wirkungsklassensystem sinnvoll, so das im übrigen
* source einfach alle curse-attribs abgefragt werden können und bei
* gewünschter Wirkungsklasse angewendet, also nicht für jeden curse
* spezielle Änderungen im übrigen source notwendig sind.
*
* Die (Wirkungs-)Typen sollten die wichtigen Funktionen speziell
* belegen können, zb Alterung, Ausgabetexte, Merge-Verhalten
*
* Was sind wichtige individuelle Eigenschaften?
* - Referenzen auf Objekt und Verursacher
* - Referenzen für globale Liste
* > die Wirkung:
* - Dauer
* - Widerstandskraft, zb gegen Antimagie
* - Seiteneffekte zb Flag ONLYONE, Unverträglichkeiten
* - Alterungsverhalten zb Flag NOAGE
* - Effektverhalten, zb Bonus (variabel)
* - bei Einheitenzaubern die Zahl der betroffenen Personen
*
* Dabei sind nur die beiden letzten Punkte wirklich reine individuelle
* Wirkung, die anderen sind eher allgemeine Kennzeichen eines jeden
* Curse, die individuell belegt sind.
* ONLYONE und NOAGE könnten auch Eigenschaften des Typs sein, nicht des
* individuellen curse. Allgemein ist Alterung wohl eher eine
* Typeigenschaft als die eines individuellen curse.
* Dagegen ist der Widerstand gegen Antimagie sowohl abhängig von der
* Güte des Verursachers, also des Magiers zum Zeitpunkt des Zaubers,
* als auch vom Typ, der gegen bestimmte Arten des 'Fluchbrechens' immun
* sein könnte.
*
* Was sind wichtige Typeigenschaften?
* - Verhalten bei Personenübergaben
* - allgemeine Wirkung
* - Beschreibungstexte
* - Verhalten bei Antimagie
* - Alterung
* - Speicherung des C-Objekts
* - Laden des C-Objekts
* - Erzeugen des C-Objekts
* - Löschen und Aufräumen des C-Objekts
* - Funktionen zur Änderung der Werte
*
* */
#include <util/variant.h>
/* ------------------------------------------------------------- */
/* Zauberwirkungen */
/* nicht vergessen curse_type zu aktualisieren und Reihenfolge beachten!
*/
enum {
/* struct's vom typ curse: */
C_FOGTRAP,
C_ANTIMAGICZONE,
C_FARVISION,
C_GBDREAM,
C_AURA,
C_MAELSTROM,
C_BLESSEDHARVEST,
C_DROUGHT,
C_BADLEARN,
C_SHIP_SPEEDUP, /* 9 - Sturmwind-Zauber */
C_SHIP_FLYING, /* 10 - Luftschiff-Zauber */
C_SHIP_NODRIFT, /* 11 - GünstigeWinde-Zauber */
C_DEPRESSION,
C_MAGICWALLS, /* 13 - Heimstein */
C_STRONGWALL, /* 14 - Feste Mauer - Precombat*/
C_ASTRALBLOCK, /* 15 - Astralblock */
C_GENEROUS, /* 16 - Unterhaltung vermehren */
C_PEACE, /* 17 - Regionsweit Attacken verhindern */
C_REGCONF, /* 18 - Erschwert Bewegungen */
C_MAGICSTREET, /* 19 - magisches Straßennetz */
C_RESIST_MAGIC, /* 20 - verändert Magieresistenz von Objekten */
C_SONG_BADMR, /* 21 - verändert Magieresistenz */
C_SONG_GOODMR, /* 22 - verändert Magieresistenz */
C_SLAVE, /* 23 - dient fremder Partei */
C_DISORIENTATION, /* 24 - Spezielle Auswirkung auf Schiffe */
C_CALM, /* 25 - Beinflussung */
C_OLDRACE,
C_FUMBLE,
C_RIOT, /*region in Aufruhr */
C_NOCOST,
C_HOLYGROUND,
C_CURSED_BY_THE_GODS,
C_FREE_14,
C_FREE_15,
C_FREE_16,
C_FREE_17,
C_FREE_18,
C_FREE_19,
/* struct's vom untertyp curse_unit: */
C_SPEED, /* Beschleunigt */
C_ORC,
C_MBOOST,
C_KAELTESCHUTZ,
C_STRENGTH,
C_ALLSKILLS,
C_MAGICRESISTANCE, /* 44 - verändert Magieresistenz */
C_ITEMCLOAK,
C_SPARKLE,
C_FREE_22,
C_FREE_23,
C_FREE_24,
/* struct's vom untertyp curse_skill: */
C_SKILL,
MAXCURSE
};
/* ------------------------------------------------------------- */
/* Flags */
#define CURSE_ISNEW 1 /* wirkt in der zauberrunde nicht (default)*/
#define CURSE_NOAGE 2 /* wirkt ewig */
#define CURSE_IMMUNE 4 /* ignoriert Antimagie */
#define CURSE_ONLYONE 8 /* Verhindert, das ein weiterer Zauber dieser Art
auf das Objekt gezaubert wird */
/* Verhalten von Zaubern auf Units beim Übergeben von Personen */
typedef enum {
CURSE_SPREADNEVER, /* wird nie mit übertragen */
CURSE_SPREADALWAYS, /* wird immer mit übertragen */
CURSE_SPREADMODULO, /* personenweise weitergabe */
CURSE_SPREADCHANCE /* Ansteckungschance je nach Mengenverhältnis*/
} spread_t;
/* typ von struct */
enum {
CURSETYP_NORM,
CURSETYP_UNIT,
MAXCURSETYP
};
/* Verhalten beim Zusammenfassen mit einem schon bestehenden Zauber
* gleichen Typs */
#define NO_MERGE 0 /* erzeugt jedesmal einen neuen Zauber */
#define M_DURATION 1 /* Die Zauberdauer ist die maximale Dauer beider */
#define M_SUMDURATION 2 /* die Dauer des Zaubers wird summiert */
#define M_MAXEFFECT 4 /* der Effekt ist der maximale Effekt beider */
#define M_SUMEFFECT 8 /* der Effekt summiert sich */
#define M_MEN 16 /* die Anzahl der betroffenen Personen summiert
sich */
#define M_VIGOUR 32 /* das Maximum der beiden Stärken wird die
Stärke des neuen Zaubers */
#define M_VIGOUR_ADD 64 /* Vigour wird addiert */
/* ------------------------------------------------------------- */
/* Allgemeine Zauberwirkungen */
typedef struct curse {
struct curse *nexthash;
int no; /* 'Einheitennummer' dieses Curse */
const struct curse_type * type; /* Zeiger auf ein curse_type-struct */
int flag; /* generelle Flags wie zb CURSE_ISNEW oder CURSE_NOAGE */
int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */
double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */
struct unit *magician; /* Pointer auf den Magier, der den Spruch gewirkt hat */
variant effect;
void *data; /* pointer auf spezielle curse-unterstructs*/
} curse;
/* Die Unterattribute curse->data: */
/* Einheitenzauber:
* auf Einzelpersonen in einer Einheit bezogene Zauber. Für Zauber, die
* nicht immer auf ganze Einheiten wirken brauchen
*/
typedef struct curse_unit {
int cursedmen; /* verzauberte Personen in der Einheit */
} curse_unit;
/* ------------------------------------------------------------- */
typedef struct curse_type {
const char *cname; /* Name der Zauberwirkung, Identifizierung des curse */
int typ;
spread_t spread;
unsigned int mergeflags;
const char *info_str; /* Wirkung des curse, wird bei einer gelungenen
Zauberanalyse angezeigt */
int (*curseinfo)(const struct locale*, const void*, typ_t, curse*, int);
void (*change_vigour)(curse*, double);
int (*read)(FILE * F, curse * c);
int (*write)(FILE * F, const curse * c);
int (*cansee)(const struct faction*, const void*, typ_t, curse *, int);
} curse_type;
extern attrib_type at_curse;
extern void curse_write(const attrib * a,FILE * f);
extern int curse_read(struct attrib * a,FILE * f);
/* ------------------------------------------------------------- */
/* Kommentare:
* Bei einigen Typen von Verzauberungen (z.B.Skillmodif.) muss neben
* der curse-id noch ein weiterer Identifizierer angegeben werden (id2).
*
* Wenn der Typ korrekt definiert wurde, erfolgt die Verzweigung zum
* korrekten Typus automatisch, und die unterschiedlichen struct-typen
* sind nach aussen unsichtbar.
*
* allgemeine Funktionen *
*/
curse * create_curse(struct unit *magician, struct attrib**ap, const curse_type * ctype,
double vigour, int duration, int ceffect, int men);
/* Verzweigt automatisch zum passenden struct-typ. Sollte es schon
* einen Zauber dieses Typs geben, so wird der neue dazuaddiert. Die
* Zahl der verzauberten Personen sollte beim Aufruf der Funktion
* nochmal gesondert auf min(get_cursedmen, u->number) gesetzt werden.
*/
boolean is_cursed_internal(struct attrib *ap, const curse_type * ctype);
/* ignoriert CURSE_ISNEW */
extern void remove_curse(struct attrib **ap, const curse * c);
/* löscht einen konkreten Spruch auf einem Objekt.
*/
extern int curse_geteffect(const curse * c);
/* gibt die Auswirkungen der Verzauberungen zurück. zB bei
* Skillmodifiziernden Verzauberungen ist hier der Modifizierer
* gespeichert. Wird automatisch beim Anlegen eines neuen curse
* gesetzt. Gibt immer den ersten Treffer von ap aus zurück.
*/
extern double curse_changevigour(struct attrib **ap, curse * c, double i);
/* verändert die Stärke der Verzauberung um i */
extern int get_cursedmen(struct unit *u, struct curse *c);
/* gibt bei Personenbeschränkten Verzauberungen die Anzahl der
* betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */
extern void curse_setflag(curse * c, int flag);
/* setzt Spezialflag einer Verzauberung (zB 'dauert ewig') */
void transfer_curse(struct unit * u, struct unit * u2, int n);
/* sorgt dafür, das bei der Übergabe von Personen die curse-attribute
* korrekt gehandhabt werden. Je nach internen Flag kann dies
* unterschiedlich gewünscht sein
* */
extern curse * get_cursex(attrib *ap, const curse_type * ctype, void * data,
boolean(*compare)(const curse *, const void *));
/* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist,
* und für die compare() true liefert, oder einen NULL-pointer.
* */
extern curse * get_curse(struct attrib *ap, const curse_type * ctype);
/* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist,
* oder einen NULL-pointer
* */
struct unit * get_tracingunit(struct attrib **ap, const curse_type * ct);
int find_cursebyname(const char *c);
const curse_type * ct_find(const char *c);
void ct_register(const curse_type *);
/* Regionszauber */
curse * cfindhash(int i);
curse * findcurse(int curseid);
extern void curse_init(struct attrib * a);
extern void curse_done(struct attrib * a);
extern int curse_age(struct attrib * a);
extern boolean cmp_curse(const attrib * a, const void * data);
extern boolean cmp_cursetype(const attrib * a, const void * data);
extern boolean cmp_curseeffect(const curse * c, const void * data);
extern boolean cmp_cursedata(const curse * c, const void * data);
extern void * resolve_curse(void * data);
extern boolean is_cursed_with(attrib *ap, curse *c);
extern boolean curse_active(const curse * c);
/* gibt true, wenn der Curse nicht NULL oder inaktiv ist */
/*** COMPATIBILITY MACROS. DO NOT USE FOR NEW CODE, REPLACE IN OLD CODE: */
extern const char * oldcursename(int id);
extern void register_curses(void);
#define get_oldcurse(id) \
get_curse(a, ct_find(oldcursename(id)))
#define is_cursed(a, id, id2) \
curse_active(get_curse(a, ct_find(oldcursename(id))))
#define get_curseeffect(a, id, id2) \
curse_geteffect(get_curse(a, ct_find(oldcursename(id))))
#ifdef __cplusplus
}
#endif
#endif