From 70775878340d49e6449a5f0d96e68274a336a3bf Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 28 Jul 2006 01:31:23 +0000 Subject: [PATCH] =?UTF-8?q?http://eressea.upb.de/mantis/view.php=3Fid=3D68?= =?UTF-8?q?1=20"Todeswolke=20l=C3=A4=C3=9Ft=20sich=20nicht=20bannen"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Todeswolke in einen echten curse umgewandelt. Kompatibilitaet zur alten TW sollte gewaehrleistet sein. Alles muss nochmal getestet werden, denk ich. --- src/common/kernel/curse.c | 765 +++++++++++++++++++------------------ src/common/kernel/curse.h | 6 +- src/common/spells/spells.c | 124 +++--- 3 files changed, 460 insertions(+), 435 deletions(-) diff --git a/src/common/kernel/curse.c b/src/common/kernel/curse.c index 4a591f796..db0d65ef0 100644 --- a/src/common/kernel/curse.c +++ b/src/common/kernel/curse.c @@ -1,7 +1,7 @@ /* vi: set ts=2: * * - * Eressea PB(E)M host Copyright (C) 1998-2003 + * 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) @@ -65,158 +65,169 @@ curse *cursehash[MAXENTITYHASH]; void chash(curse *c) { - curse *old = cursehash[c->no %MAXENTITYHASH]; + curse *old = cursehash[c->no %MAXENTITYHASH]; - cursehash[c->no %MAXENTITYHASH] = c; - c->nexthash = old; + cursehash[c->no %MAXENTITYHASH] = c; + c->nexthash = old; } static void cunhash(curse *c) { - curse **show; + curse **show; - for (show = &cursehash[c->no % MAXENTITYHASH]; *show; show = &(*show)->nexthash) { - if ((*show)->no == c->no) - break; - } - if (*show) { - assert(*show == c); - *show = (*show)->nexthash; - c->nexthash = 0; - } + for (show = &cursehash[c->no % MAXENTITYHASH]; *show; show = &(*show)->nexthash) { + if ((*show)->no == c->no) + break; + } + if (*show) { + assert(*show == c); + *show = (*show)->nexthash; + c->nexthash = 0; + } } curse * cfindhash(int i) { - curse *old; + curse *old; - for (old = cursehash[i % MAXENTITYHASH]; old; old = old->nexthash) - if (old->no == i) - return old; - return NULL; + for (old = cursehash[i % MAXENTITYHASH]; old; old = old->nexthash) + if (old->no == i) + return old; + return NULL; } /* ------------------------------------------------------------- */ /* at_curse */ void curse_init(attrib * a) { - a->data.v = calloc(1, sizeof(curse)); + a->data.v = calloc(1, sizeof(curse)); } int curse_age(attrib * a) { - curse * c = (curse*)a->data.v; + curse * c = (curse*)a->data.v; - if (c->flag & CURSE_NOAGE) { - c->duration = 1; - } else { - c->duration = max(0, c->duration-1); - } - return (c->duration); + if (c->flag & CURSE_NOAGE) { + c->duration = 1; + } else { + c->duration = max(0, c->duration-1); + } + return (c->duration); +} + +void +destroy_curse(curse * c) +{ + cunhash(c); + + if (c->data.v && c->type->typ == CURSETYP_UNIT) { + free(c->data.v); + } + free(c); } void curse_done(attrib * a) { - curse *c = (curse *)a->data.v; - - cunhash(c); - - if( c->data.v && c->type->typ == CURSETYP_UNIT) - free(c->data.v); - free(c); + destroy_curse((curse *)a->data.v); } /* ------------------------------------------------------------- */ int curse_read(attrib * a, FILE * f) { - variant mageid; - curse * c = (curse*)a->data.v; - const curse_type * ct; + variant mageid; + curse * c = (curse*)a->data.v; + const curse_type * ct; - char cursename[64]; + char cursename[64]; - if(global.data_version >= CURSEVIGOURISFLOAT_VERSION) { - fscanf(f, "%d %s %d %d %lf %d %d ", &c->no, cursename, &c->flag, - &c->duration, &c->vigour, &mageid.i, &c->effect.i); - } else { - int vigour; - fscanf(f, "%d %s %d %d %d %d %d ", &c->no, cursename, &c->flag, - &c->duration, &vigour, &mageid.i, &c->effect.i); - c->vigour = vigour; - } - ct = ct_find(cursename); + if(global.data_version >= CURSEVIGOURISFLOAT_VERSION) { + fscanf(f, "%d %s %d %d %lf %d %d ", &c->no, cursename, &c->flag, + &c->duration, &c->vigour, &mageid.i, &c->effect.i); + } else { + int vigour; + fscanf(f, "%d %s %d %d %d %d %d ", &c->no, cursename, &c->flag, + &c->duration, &vigour, &mageid.i, &c->effect.i); + c->vigour = vigour; + } + ct = ct_find(cursename); - assert(ct!=NULL); + assert(ct!=NULL); #ifdef CONVERT_DBLINK - if (global.data_versioneffect.v = uniquefaction(c->effect.i); - } - } + if (global.data_versioneffect.v = uniquefaction(c->effect.i); + } + } #endif - c->type = ct; + c->type = ct; - /* beim Einlesen sind noch nicht alle units da, muss also - * zwischengespeichert werden. */ - if (mageid.i == -1){ - c->magician = (unit *)NULL; - } else { - ur_add(mageid, (void**)&c->magician, resolve_unit); - } + /* beim Einlesen sind noch nicht alle units da, muss also + * zwischengespeichert werden. */ + if (mageid.i == -1){ + c->magician = (unit *)NULL; + } else { + ur_add(mageid, (void**)&c->magician, resolve_unit); + } - if (c->type->read) c->type->read(f, c); - else if (c->type->typ==CURSETYP_UNIT) { - curse_unit * cc = calloc(1, sizeof(curse_unit)); + if (c->type->read) c->type->read(f, c); + else if (c->type->typ==CURSETYP_UNIT) { + curse_unit * cc = calloc(1, sizeof(curse_unit)); - c->data.v = cc; - fscanf(f, "%d ", &cc->cursedmen); - } - chash(c); + c->data.v = cc; + fscanf(f, "%d ", &cc->cursedmen); + } + if (c->type->typ == CURSETYP_REGION) { + read_region_reference((region**)&c->data.v, f); + } + chash(c); - return AT_READ_OK; + return AT_READ_OK; } void curse_write(const attrib * a, FILE * f) { - int flag; - int mage_no; - curse * c = (curse*)a->data.v; - const curse_type * ct = c->type; + int flag; + int mage_no; + curse * c = (curse*)a->data.v; + const curse_type * ct = c->type; - flag = (c->flag & ~(CURSE_ISNEW)); + flag = (c->flag & ~(CURSE_ISNEW)); - if (c->magician){ - mage_no = c->magician->no; - } else { - mage_no = -1; - } + if (c->magician){ + mage_no = c->magician->no; + } else { + mage_no = -1; + } - fprintf(f, "%d %s %d %d %f %d %d ", c->no, ct->cname, flag, - c->duration, c->vigour, mage_no, c->effect.i); + fprintf(f, "%d %s %d %d %f %d %d ", c->no, ct->cname, flag, + c->duration, c->vigour, mage_no, c->effect.i); - if (c->type->write) c->type->write(f, c); - else if (c->type->typ == CURSETYP_UNIT) { - curse_unit * cc = (curse_unit*)c->data.v; - fprintf(f, "%d ", cc->cursedmen); - } + if (c->type->write) c->type->write(f, c); + else if (c->type->typ == CURSETYP_UNIT) { + curse_unit * cc = (curse_unit*)c->data.v; + fprintf(f, "%d ", cc->cursedmen); + } + if (c->type->typ == CURSETYP_REGION) { + write_region_reference((region*)c->data.v, f); + } } attrib_type at_curse = { - "curse", - curse_init, - curse_done, - curse_age, - curse_write, - curse_read, - ATF_CURSE + "curse", + curse_init, + curse_done, + curse_age, + curse_write, + curse_read, + ATF_CURSE }; /* ------------------------------------------------------------- */ /* Spruch identifizieren */ @@ -224,8 +235,8 @@ attrib_type at_curse = #include "umlaut.h" typedef struct cursetype_list { - struct cursetype_list * next; - const curse_type * type; + struct cursetype_list * next; + const curse_type * type; } cursetype_list; cursetype_list * cursetypes[256]; @@ -234,32 +245,32 @@ void ct_register(const curse_type * ct) { unsigned int hash = tolower(ct->cname[0]); - cursetype_list ** ctlp = &cursetypes[hash]; - while (*ctlp) { - cursetype_list * ctl = *ctlp; - if (ctl->type==ct) return; - ctlp=&ctl->next; - } - *ctlp = calloc(1, sizeof(cursetype_list)); - (*ctlp)->type = ct; + cursetype_list ** ctlp = &cursetypes[hash]; + while (*ctlp) { + cursetype_list * ctl = *ctlp; + if (ctl->type==ct) return; + ctlp=&ctl->next; + } + *ctlp = calloc(1, sizeof(cursetype_list)); + (*ctlp)->type = ct; } const curse_type * ct_find(const char *c) { unsigned int hash = tolower(c[0]); - cursetype_list * ctl = cursetypes[hash]; - while (ctl) { - size_t k = min(strlen(c), strlen(ctl->type->cname)); - if (!strncasecmp(c, ctl->type->cname, k)) return ctl->type; - ctl = ctl->next; - } - /* disable this assert to be able to remoce certain curses from the game - * make sure that all locations using that curse can deal with a NULL - * return value. - */ - assert(!"unknown cursetype"); - return NULL; + cursetype_list * ctl = cursetypes[hash]; + while (ctl) { + size_t k = min(strlen(c), strlen(ctl->type->cname)); + if (!strncasecmp(c, ctl->type->cname, k)) return ctl->type; + ctl = ctl->next; + } + /* disable this assert to be able to remoce certain curses from the game + * make sure that all locations using that curse can deal with a NULL + * return value. + */ + assert(!"unknown cursetype"); + return NULL; } /* ------------------------------------------------------------- */ @@ -269,39 +280,39 @@ ct_find(const char *c) boolean cmp_curse(const attrib * a, const void * data) { - const curse * c = (const curse*)data; - if (a->type->flags & ATF_CURSE) { - if (!data || c == (curse*)a->data.v) return true; - } - return false; + const curse * c = (const curse*)data; + if (a->type->flags & ATF_CURSE) { + if (!data || c == (curse*)a->data.v) return true; + } + return false; } boolean cmp_cursetype(const attrib * a, const void * data) { - const curse_type * ct = (const curse_type *)data; - if (a->type->flags & ATF_CURSE) { - if (!data || ct == ((curse*)a->data.v)->type) return true; - } - return false; + const curse_type * ct = (const curse_type *)data; + if (a->type->flags & ATF_CURSE) { + if (!data || ct == ((curse*)a->data.v)->type) return true; + } + return false; } curse * get_cursex(attrib *ap, const curse_type * ctype, variant data, boolean(*compare)(const curse *, variant)) { - attrib * a = a_select(ap, ctype, cmp_cursetype); - while (a) { - curse * c = (curse*)a->data.v; - if (compare(c, data)) return c; - a = a_select(a->next, ctype, cmp_cursetype); - } - return NULL; + attrib * a = a_select(ap, ctype, cmp_cursetype); + while (a) { + curse * c = (curse*)a->data.v; + if (compare(c, data)) return c; + a = a_select(a->next, ctype, cmp_cursetype); + } + return NULL; } curse * get_curse(attrib *ap, const curse_type * ctype) { - attrib * a = ap; + attrib * a = ap; while (a) { if (a->type->flags & ATF_CURSE) { const attrib_type * at = a->type; @@ -323,15 +334,15 @@ get_curse(attrib *ap, const curse_type * ctype) curse * findcurse(int cid) { - return cfindhash(cid); + return cfindhash(cid); } /* ------------------------------------------------------------- */ void remove_curse(attrib **ap, const curse *c) { - attrib *a = a_select(*ap, c, cmp_curse); - if (a) a_remove(ap, a); + attrib *a = a_select(*ap, c, cmp_curse); + if (a) a_remove(ap, a); } /* gibt die allgemeine Stärke der Verzauberung zurück. id2 wird wie @@ -340,16 +351,16 @@ remove_curse(attrib **ap, const curse *c) static double get_cursevigour(const curse *c) { - if (c) return c->vigour; - return 0; + if (c) return c->vigour; + return 0; } /* setzt die Stärke der Verzauberung auf i */ static void set_cursevigour(curse *c, double vigour) { - assert(c && vigour > 0); - c->vigour = vigour; + assert(c && vigour > 0); + c->vigour = vigour; } /* verändert die Stärke der Verzauberung um +i und gibt die neue @@ -359,15 +370,15 @@ set_cursevigour(curse *c, double vigour) double curse_changevigour(attrib **ap, curse *c, double vigour) { - vigour += get_cursevigour(c); + vigour += get_cursevigour(c); - if (vigour <= 0) { - remove_curse(ap, c); - vigour = 0; - } else { - set_cursevigour(c, vigour); - } - return vigour; + if (vigour <= 0) { + remove_curse(ap, c); + vigour = 0; + } else { + set_cursevigour(c, vigour); + } + return vigour; } /* ------------------------------------------------------------- */ @@ -375,18 +386,18 @@ curse_changevigour(attrib **ap, curse *c, double vigour) int curse_geteffect(const curse *c) { - if (c) return c->effect.i; - return 0; + if (c) return c->effect.i; + return 0; } /* ------------------------------------------------------------- */ static void set_curseingmagician(struct unit *magician, struct attrib *ap_target, const curse_type *ct) { - curse * c = get_curse(ap_target, ct); - if (c) { - c->magician = magician; - } + curse * c = get_curse(ap_target, ct); + if (c) { + c->magician = magician; + } } /* ------------------------------------------------------------- */ @@ -395,37 +406,37 @@ set_curseingmagician(struct unit *magician, struct attrib *ap_target, const curs int get_cursedmen(unit *u, curse *c) { - int cursedmen = u->number; + int cursedmen = u->number; - if (!c) return 0; + if (!c) return 0; - /* je nach curse_type andere data struct */ - if (c->type->typ == CURSETYP_UNIT) { - curse_unit * cc = (curse_unit*)c->data.v; - cursedmen = cc->cursedmen; - } + /* je nach curse_type andere data struct */ + if (c->type->typ == CURSETYP_UNIT) { + curse_unit * cc = (curse_unit*)c->data.v; + cursedmen = cc->cursedmen; + } - return min(u->number, cursedmen); + return min(u->number, cursedmen); } /* setzt die Anzahl der betroffenen Personen auf cursedmen */ static void set_cursedmen(curse *c, int cursedmen) { - if (!c) return; + if (!c) return; - /* je nach curse_type andere data struct */ - if (c->type->typ == CURSETYP_UNIT) { - curse_unit * cc = (curse_unit*)c->data.v; - cc->cursedmen = cursedmen; - } + /* je nach curse_type andere data struct */ + if (c->type->typ == CURSETYP_UNIT) { + curse_unit * cc = (curse_unit*)c->data.v; + cc->cursedmen = cursedmen; + } } /* ------------------------------------------------------------- */ void curse_setflag(curse *c, int flag) { - if (c) c->flag = (c->flag | flag); + if (c) c->flag = (c->flag | flag); } /* ------------------------------------------------------------- */ @@ -434,39 +445,39 @@ curse_setflag(curse *c, int flag) */ static curse * set_curse(unit *mage, attrib **ap, const curse_type *ct, double vigour, - int duration, variant effect, int men) + int duration, variant effect, int men) { - curse *c; - attrib * a; + curse *c; + attrib * a; - a = a_new(&at_curse); - a_add(ap, a); - c = (curse*)a->data.v; + a = a_new(&at_curse); + a_add(ap, a); + c = (curse*)a->data.v; - c->type = ct; - c->flag = 0; - c->vigour = vigour; - c->duration = duration; - c->effect = effect; - c->magician = mage; + c->type = ct; + c->flag = 0; + c->vigour = vigour; + c->duration = duration; + c->effect = effect; + c->magician = mage; - c->no = newunitid(); - chash(c); + c->no = newunitid(); + chash(c); - switch (c->type->typ) { - case CURSETYP_NORM: - break; + switch (c->type->typ) { + case CURSETYP_NORM: + break; - case CURSETYP_UNIT: - { - curse_unit *cc = calloc(1, sizeof(curse_unit)); - cc->cursedmen += men; - c->data.v = cc; - break; - } + case CURSETYP_UNIT: + { + curse_unit *cc = calloc(1, sizeof(curse_unit)); + cc->cursedmen += men; + c->data.v = cc; + break; + } - } - return c; + } + return c; } @@ -475,54 +486,54 @@ set_curse(unit *mage, attrib **ap, const curse_type *ct, double vigour, */ curse * create_curse(unit *magician, attrib **ap, const curse_type *ct, double vigour, - int duration, variant effect, int men) + int duration, variant effect, int men) { - curse *c; + curse *c; - /* die Kraft eines Spruchs darf nicht 0 sein*/ - assert(vigour > 0); + /* die Kraft eines Spruchs darf nicht 0 sein*/ + assert(vigour > 0); - c = get_curse(*ap, ct); + c = get_curse(*ap, ct); - if(c && (c->flag & CURSE_ONLYONE)){ - return NULL; - } - assert(c==NULL || ct==c->type); + if(c && (c->flag & CURSE_ONLYONE)){ + return NULL; + } + assert(c==NULL || ct==c->type); - /* es gibt schon eins diese Typs */ - if (c && ct->mergeflags != NO_MERGE) { - if(ct->mergeflags & M_DURATION){ - c->duration = max(c->duration, duration); - } - if(ct->mergeflags & M_SUMDURATION){ - c->duration += duration; - } - if(ct->mergeflags & M_SUMEFFECT){ - c->effect.i += effect.i; - } - if(ct->mergeflags & M_MAXEFFECT){ - c->effect.i = max(c->effect.i, effect.i); - } - if(ct->mergeflags & M_VIGOUR){ - c->vigour = max(vigour, c->vigour); - } - if(ct->mergeflags & M_VIGOUR_ADD){ - c->vigour = vigour + c->vigour; - } - if(ct->mergeflags & M_MEN){ - switch (ct->typ) { - case CURSETYP_UNIT: - { - curse_unit * cc = (curse_unit*)c->data.v; - cc->cursedmen += men; - } - } - } - set_curseingmagician(magician, *ap, ct); - } else { - c = set_curse(magician, ap, ct, vigour, duration, effect, men); - } - return c; + /* es gibt schon eins diese Typs */ + if (c && ct->mergeflags != NO_MERGE) { + if(ct->mergeflags & M_DURATION){ + c->duration = max(c->duration, duration); + } + if(ct->mergeflags & M_SUMDURATION){ + c->duration += duration; + } + if(ct->mergeflags & M_SUMEFFECT){ + c->effect.i += effect.i; + } + if(ct->mergeflags & M_MAXEFFECT){ + c->effect.i = max(c->effect.i, effect.i); + } + if(ct->mergeflags & M_VIGOUR){ + c->vigour = max(vigour, c->vigour); + } + if(ct->mergeflags & M_VIGOUR_ADD){ + c->vigour = vigour + c->vigour; + } + if(ct->mergeflags & M_MEN){ + switch (ct->typ) { + case CURSETYP_UNIT: + { + curse_unit * cc = (curse_unit*)c->data.v; + cc->cursedmen += men; + } + } + } + set_curseingmagician(magician, *ap, ct); + } else { + c = set_curse(magician, ap, ct, vigour, duration, effect, men); + } + return c; } /* ------------------------------------------------------------- */ @@ -532,73 +543,73 @@ create_curse(unit *magician, attrib **ap, const curse_type *ct, double vigour, void do_transfer_curse(curse *c, unit * u, unit * u2, int n) { - int flag = c->flag; - int cursedmen = 0; - int men = 0; - boolean dogive = false; - const curse_type *ct = c->type; + int flag = c->flag; + int cursedmen = 0; + int men = 0; + boolean dogive = false; + const curse_type *ct = c->type; - switch (ct->typ) { - case CURSETYP_UNIT: - { - curse_unit * cc = (curse_unit*)c->data.v; - men = cc->cursedmen; - break; - } - default: - cursedmen = u->number; - } + switch (ct->typ) { + case CURSETYP_UNIT: + { + curse_unit * cc = (curse_unit*)c->data.v; + men = cc->cursedmen; + break; + } + default: + cursedmen = u->number; + } - switch (ct->spread){ - case CURSE_SPREADALWAYS: - dogive = true; - men = u2->number + n; - break; + switch (ct->spread){ + case CURSE_SPREADALWAYS: + dogive = true; + men = u2->number + n; + break; - case CURSE_SPREADMODULO: - { - int i; - int u_number = u->number; - for (i=0;i0;i++){ - if (rng_int()%u_number < cursedmen){ - ++men; - --cursedmen; - dogive = true; - } - --u_number; - } - break; - } - case CURSE_SPREADCHANCE: - if (chance(u2->number/(double)(u2->number + n))) { - men = u2->number + n; - dogive = true; - } - break; - case CURSE_SPREADNEVER: - break; - } + case CURSE_SPREADMODULO: + { + int i; + int u_number = u->number; + for (i=0;i0;i++){ + if (rng_int()%u_number < cursedmen){ + ++men; + --cursedmen; + dogive = true; + } + --u_number; + } + break; + } + case CURSE_SPREADCHANCE: + if (chance(u2->number/(double)(u2->number + n))) { + men = u2->number + n; + dogive = true; + } + break; + case CURSE_SPREADNEVER: + break; + } - if (dogive == true) { - curse * cnew = set_curse(c->magician, &u2->attribs, c->type, c->vigour, + if (dogive == true) { + curse * cnew = set_curse(c->magician, &u2->attribs, c->type, c->vigour, c->duration, c->effect, men); - curse_setflag(cnew, flag); + curse_setflag(cnew, flag); - if (ct->typ == CURSETYP_UNIT) set_cursedmen(cnew, men); - } + if (ct->typ == CURSETYP_UNIT) set_cursedmen(cnew, men); + } } void transfer_curse(unit * u, unit * u2, int n) { - attrib * a; + attrib * a; - a = a_find(u->attribs, &at_curse); - while (a && a->type==&at_curse) { - curse *c = (curse*)a->data.v; - do_transfer_curse(c, u, u2, n); - a = a->next; - } + a = a_find(u->attribs, &at_curse); + while (a && a->type==&at_curse) { + curse *c = (curse*)a->data.v; + do_transfer_curse(c, u, u2, n); + a = a->next; + } } /* ------------------------------------------------------------- */ @@ -606,53 +617,53 @@ transfer_curse(unit * u, unit * u2, int n) boolean curse_active(const curse *c) { - if (!c) return false; - if (c->flag & CURSE_ISNEW) return false; - if (c->vigour <= 0) return false; + if (!c) return false; + if (c->flag & CURSE_ISNEW) return false; + if (c->vigour <= 0) return false; - return true; + return true; } boolean is_cursed_internal(attrib *ap, const curse_type *ct) { - curse *c = get_curse(ap, ct); + curse *c = get_curse(ap, ct); - if (!c) - return false; + if (!c) + return false; - return true; + return true; } boolean is_cursed_with(attrib *ap, curse *c) { - attrib *a = ap; + attrib *a = ap; - while (a) { - if ((a->type->flags & ATF_CURSE) && (c == (curse *)a->data.v)) { - return true; - } - a = a->next; - } + while (a) { + if ((a->type->flags & ATF_CURSE) && (c == (curse *)a->data.v)) { + return true; + } + a = a->next; + } - return false; + return false; } /* ------------------------------------------------------------- */ /* cursedata */ /* ------------------------------------------------------------- */ /* * 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*, int, curse*, int); - * void (*change_vigour)(curse*, double); - * int (*read)(FILE * F, curse * c); - * int (*write)(FILE * F, const curse * c); + * 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*, int, curse*, int); + * void (*change_vigour)(curse*, double); + * int (*read)(FILE * F, curse * c); + * int (*write)(FILE * F, const curse * c); * } curse_type; */ @@ -665,70 +676,70 @@ resolve_curse(variant id) void register_curses(void) { - register_unitcurse(); - register_regioncurse(); - register_shipcurse(); - register_buildingcurse(); + register_unitcurse(); + register_regioncurse(); + register_shipcurse(); + register_buildingcurse(); } static const char * oldnames[MAXCURSE] = { - "fogtrap", - "antimagiczone", - "farvision", - "gbdream", - "auraboost", - "maelstrom", - "blessedharvest", - "drought", - "badlearn", - "stormwind", - "flyingship", - "nodrift", - "depression", - "magicwalls", - "strongwall", - "astralblock", - "generous", - "peacezone", - "disorientationzone", - "magicstreet", - "magicrunes", - "badmagicresistancezone", - "goodmagicresistancezone", - "slavery", - "shipdisorientation", - "calmmonster", - "oldrace", - "fumble", - "riotzone", - "nocostbuilding", - "holyground", - "godcursezone", - "", - "", - "", - "", - "", - "", - "speed", - "orcish", - "magicboost", - "insectfur", - "strength", - "worse", - "magicresistance", - "itemcloak", - "sparkle", - "", - "", - "", - "skillmod" + "fogtrap", + "antimagiczone", + "farvision", + "gbdream", + "auraboost", + "maelstrom", + "blessedharvest", + "drought", + "badlearn", + "stormwind", + "flyingship", + "nodrift", + "depression", + "magicwalls", + "strongwall", + "astralblock", + "generous", + "peacezone", + "disorientationzone", + "magicstreet", + "magicrunes", + "badmagicresistancezone", + "goodmagicresistancezone", + "slavery", + "shipdisorientation", + "calmmonster", + "oldrace", + "fumble", + "riotzone", + "nocostbuilding", + "holyground", + "godcursezone", + "", + "", + "", + "", + "", + "", + "speed", + "orcish", + "magicboost", + "insectfur", + "strength", + "worse", + "magicresistance", + "itemcloak", + "sparkle", + "", + "", + "", + "skillmod" }; const char * oldcursename(int id) { - return oldnames[id]; + return oldnames[id]; } diff --git a/src/common/kernel/curse.h b/src/common/kernel/curse.h index 8eeb381b5..2480d5d8d 100644 --- a/src/common/kernel/curse.h +++ b/src/common/kernel/curse.h @@ -169,7 +169,8 @@ typedef enum { /* typ von struct */ enum { CURSETYP_NORM, - CURSETYP_UNIT, + CURSETYP_UNIT, + CURSETYP_REGION, /* stores the region in c->data.v */ MAXCURSETYP }; @@ -254,6 +255,9 @@ curse * create_curse(struct unit *magician, struct attrib**ap, const curse_type * nochmal gesondert auf min(get_cursedmen, u->number) gesetzt werden. */ +extern void destroy_curse(curse * c); + + boolean is_cursed_internal(struct attrib *ap, const curse_type * ctype); /* ignoriert CURSE_ISNEW */ diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index 6307ac29b..78e73b5c5 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -16,13 +16,13 @@ #include #include "spells.h" +#include "regioncurse.h" #include "alp.h" #include "combatspells.h" #include struct curse_type; -extern const struct curse_type ct_firewall; extern void ct_register(const struct curse_type * ct); /* kernel includes */ @@ -326,7 +326,7 @@ destr_curse(curse* c, int cast_level, double force) } int -destroy_curse(attrib **alist, int cast_level, double force, curse * c) +break_curse(attrib **alist, int cast_level, double force, curse * c) { int succ = 0; /* attrib **a = a_find(*ap, &at_curse); */ @@ -511,7 +511,7 @@ make_familiar(unit *familiar, unit *mage) if (familiar->race->init_familiar!=NULL) { familiar->race->init_familiar(familiar); } else { - log_error(("could not perform initialization for familiar %s.\n", + log_error(("could not perform initialization for familiar %s.\n", familiar->faction->race->_name[0])); } @@ -541,7 +541,7 @@ sp_summon_familiar(castorder *co) } rc = select_familiar(mage->faction->race, mage->faction->magiegebiet); if (rc==NULL) { - log_error(("could not find suitable familiar for %s.\n", + log_error(("could not find suitable familiar for %s.\n", mage->faction->race->_name[0])); return 0; } @@ -692,7 +692,7 @@ sp_destroy_magic(castorder *co) return 0; } - succ = destroy_curse(ap, cast_level, force, c); + succ = break_curse(ap, cast_level, force, c); if (succ) { ADDMSG(&mage->faction->msgs, msg_message( @@ -3182,36 +3182,38 @@ sp_unholypower(castorder *co) * (FARCASTING | REGIONSPELL | TESTRESISTANCE) */ -typedef struct dc_data { - region * r; - unit * mage; - double strength; - int countdown; - boolean active; -} dc_data; +static struct curse_type ct_deathcloud = { + "deathcloud", CURSETYP_REGION, 0, NO_MERGE, NULL, cinfo_region, +}; -static void -dc_initialize(struct attrib *a) +static curse * +mk_deathcloud(unit * mage, region * r, double force, int duration) { - dc_data * data = (dc_data *)malloc(sizeof(dc_data)); - a->data.v = data; - data->active = true; + variant effect; + curse * c; + + effect.f = (float)force/2; + c = create_curse(mage, &r->attribs, &ct_deathcloud, force, duration, effect, 0); + c->data.v = r; + return c; } static void dc_finalize(struct attrib * a) { - free(a->data.v); + curse * c = (curse*)a->data.v; + c->data.v = NULL; + destroy_curse(c); } static int dc_age(struct attrib * a) /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ { - dc_data * data = (dc_data *)a->data.v; - region * r = data->r; + curse * c = (curse*)a->data.v; + region * r = (region*)c->data.v; unit ** up = &r->units; - unit * mage = data->mage; + unit * mage = c->magician; unit * u; if (mage==NULL || mage->number==0) { @@ -3219,9 +3221,9 @@ dc_age(struct attrib * a) return 0; } - if (data->active) while (*up!=NULL) { + if (curse_active(c)) while (*up!=NULL) { unit * u = *up; - double damage = data->strength * u->number; + double damage = c->effect.f * u->number; freset(u->faction, FL_DH); if (target_resists_magic(mage, u, TYP_UNIT, 0)){ @@ -3249,46 +3251,51 @@ dc_age(struct attrib * a) "mage region", mage, r)); } - return --data->countdown; + return --c->duration; } -static void -dc_write(const struct attrib * a, FILE* F) -{ - const dc_data * data = (const dc_data *)a->data.v; - fprintf(F, "%d %lf ", data->countdown, data->strength); - write_unit_reference(data->mage, F); - write_region_reference(data->r, F); -} - -static int -dc_read(struct attrib * a, FILE* F) -/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */ -{ - dc_data * data = (dc_data *)a->data.v; - fscanf(F, "%d %lf ", &data->countdown, &data->strength); - read_unit_reference(&data->mage, F); - return read_region_reference(&data->r, F); -} attrib_type at_deathcloud = { - "zauber_todeswolke", dc_initialize, dc_finalize, dc_age, dc_write, dc_read + "curse_dc", curse_init, curse_done, dc_age, curse_write, curse_read, ATF_CURSE }; -static attrib * -mk_deathcloud(unit * mage, region * r, double strength, int duration) +#define COMPAT_DEATHCLOUD +#ifdef COMPAT_DEATHCLOUD +static int +dc_read_compat(struct attrib * a, FILE* F) +/* return AT_READ_OK on success, AT_READ_FAIL if attrib needs removal */ { - attrib * a = a_new(&at_deathcloud); - dc_data * data = (dc_data *)a->data.v; + char zId[10]; + region * r = NULL; + unit * u; + variant var; + int duration; + double strength; - data->countdown = duration; - data->r = r; - data->mage = mage; - data->strength = strength; - data->active = false; - return a; + fscanf(F, "%d %lf %s", &duration, &strength, zId); + var.i = atoi36(zId); + u = findunit(var.i); + + read_region_reference(&r, F); + if (r!=NULL) { + variant effect; + curse * c; + + effect.f = (float)strength; + c = create_curse(u, &r->attribs, &ct_deathcloud, strength * 2, duration, effect, 0); + if (u==NULL) { + ur_add(var, (void**)&c->magician, resolve_unit); + } + } + return AT_READ_FAIL; /* we don't care for the attribute. */ } + +attrib_type at_deathcloud_compat = { + "zauber_todeswolke", NULL, NULL, NULL, NULL, dc_read_compat +}; +#endif + static int sp_deathcloud(castorder *co) { @@ -3302,7 +3309,7 @@ sp_deathcloud(castorder *co) return 0; } - a_add(&r->attribs, mk_deathcloud(mage, r, co->force/2, co->level)); + mk_deathcloud(mage, r, co->force, co->level); return co->level; } @@ -6908,7 +6915,7 @@ sp_q_antimagie(castorder *co) return 0; } - succ = destroy_curse(ap, cast_level, force, c); + succ = break_curse(ap, cast_level, force, c); if (succ) { ADDMSG(&mage->faction->msgs, msg_message( @@ -6942,7 +6949,7 @@ sp_q_antimagie(castorder *co) * (FARCASTING | SPELLLEVEL | ONSHIPCAST | TESTCANSEE) */ int -sp_destroy_curse(castorder *co) +sp_break_curse(castorder *co) { attrib **ap; int obj; @@ -9026,7 +9033,7 @@ static spelldata spelldaten[] = { 0, 0, 0 }, { 0, 0, 0 } }, - (spell_f)sp_destroy_curse, NULL + (spell_f)sp_break_curse, NULL }, { SPL_ETERNIZEWALL, "eternal_walls", NULL, @@ -9479,6 +9486,9 @@ register_spells(void) register_alp(); /* init_firewall(); */ ct_register(&ct_firewall); + ct_register(&ct_deathcloud); + + at_register(&at_deathcloud_compat); register_curses(); register_function((pf_generic)&sp_wdwpyramid, "wdwpyramid"); }