diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index 8d199e081..c491a891c 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -660,13 +660,23 @@ cr_output_unit(FILE * F, const region * r, fprintf(F, "SPRUECHE\n"); for (;spt; spt = spt->next) { sp = find_spellbyid(spt->spellid); - fprintf(F, "\"%s\"\n", sp->name); + if (sp) { + const char * name = sp->sname; + if (sp->info==NULL) { + name = add_translation(mkname("spell", name), spell_name(sp, f->locale)); + } + fprintf(F, "\"%s\"\n", name); + } } for (i=0;i!=MAXCOMBATSPELLS;++i) { sp = find_spellbyid(mage->combatspell[i]); if (sp) { + const char * name = sp->sname; + if (sp->info==NULL) { + name = add_translation(mkname("spell", name), spell_name(sp, f->locale)); + } fprintf(F, "KAMPFZAUBER %d\n", i); - fprintf(F, "\"%s\";name\n", sp->name); + fprintf(F, "\"%s\";name\n", name); fprintf(F, "%d;level\n", mage->combatspelllevel[i]); } } @@ -776,12 +786,16 @@ cr_reportspell(FILE * F, spellid_t id, const struct locale * lang) { int k, itemanz, res, costtyp; spell *sp = find_spellbyid(id); + const char * name = sp->sname; + if (sp->info==NULL) { + name = add_translation(mkname("spell", name), spell_name(sp, lang)); + } - fprintf(F, "ZAUBER %d\n", hashstring(sp->name)); - fprintf(F, "\"%s\";name\n", sp->name); + fprintf(F, "ZAUBER %d\n", hashstring(spell_name(sp, default_locale))); + fprintf(F, "\"%s\";name\n", name); fprintf(F, "%d;level\n", sp->level); fprintf(F, "%d;rank\n", sp->rank); - fprintf(F, "\"%s\";info\n", sp->beschreibung); + fprintf(F, "\"%s\";info\n", spell_info(sp, lang)); if (sp->sptyp & PRECOMBATSPELL) fputs("\"precombat\";class\n", F); else if (sp->sptyp & COMBATSPELL) fputs("\"combat\";class\n", F); diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 108cfbee1..7a6421282 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -689,9 +689,9 @@ horses(region * r) horses = rhorses(r); if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { rsethorses(r, (int)(horses*0.9)); - } else if (maxhorses > 0) { + } else if (maxhorses > 0) { int i; - int growth = (RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses-horses))/maxhorses; + int growth = (int)((RESOURCE_QUANTITY * HORSEGROWTH * 200 * (maxhorses-horses))/maxhorses); if(a_find(r->attribs, &at_horseluck)) growth *= 2; /* printf("Horses: <%d> %d -> ", growth, horses); */ @@ -2489,7 +2489,7 @@ instant_orders(void) } else level = 0; - spell = find_spellbyname(u, s); + spell = find_spellbyname(u, s, u->faction->locale); if(!spell){ cmistake(u, S->s, 173, MSG_MAGIC); @@ -2554,7 +2554,7 @@ instant_orders(void) break; } - spell = find_spellbyname(u, s); + spell = find_spellbyname(u, s, u->faction->locale); rc = findrace(s, u->faction->locale); itype = finditemtype(s, u->faction->locale); if (spell == NULL && itype == NULL && rc==NULL) { @@ -3003,7 +3003,7 @@ ageing(void) } if (is_cursed(u->attribs, C_OLDRACE, 0)){ - curse *c = get_curse(u->attribs, C_OLDRACE, 0); + curse *c = get_curse(u->attribs, ct_find("oldrace")); if (c->duration == 1 && !(c->flag & CURSE_NOAGE)) { u->race = new_race[c->effect]; u->irace = new_race[c->effect]; diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c index 03f3c8bf5..2226b6638 100644 --- a/src/common/gamecode/randenc.c +++ b/src/common/gamecode/randenc.c @@ -1063,12 +1063,12 @@ randomevents(void) for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { - curse *c = get_curse(u->attribs, C_ORC, 0); + curse *c = get_curse(u->attribs, ct_find("orcish")); if (c && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY)) { int n; int increase = 0; int num = get_cursedmen(u, c); - int prob = get_curseeffect(u->attribs, C_ORC, 0); + int prob = curse_geteffect(c); for (n = (num - get_item(u, I_CHASTITY_BELT)); n > 0; n--) { if (rand() % 100 < prob) { diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index bb12984f8..84f21c154 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -455,11 +455,11 @@ report_spell(FILE * F, spellid_t id, const struct locale * lang) spell *sp = find_spellbyid(id); rnl(F); - centre(F, sp->name, true); + centre(F, spell_name(sp, lang), true); rnl(F); strcpy(buf,"Beschreibung:"); rps(F, buf); - rparagraph(F, sp->beschreibung, 0, 0); + rparagraph(F, spell_info(sp, lang), 0, 0); rnl(F); @@ -544,7 +544,7 @@ report_spell(FILE * F, spellid_t id, const struct locale * lang) scat("[STUFE n] "); } scat("\""); - scat(sp->name); + scat(spell_name(sp, lang)); scat("\" "); if (sp->sptyp & ONETARGET){ if (sp->sptyp & UNITSPELL) { diff --git a/src/common/items/items.dsp b/src/common/items/items.dsp index 29c4f1e4b..edbf744d5 100644 --- a/src/common/items/items.dsp +++ b/src/common/items/items.dsp @@ -90,6 +90,10 @@ SOURCE=.\birthday_firework.h # End Source File # Begin Source File +SOURCE=.\catapultammo.h +# End Source File +# Begin Source File + SOURCE=.\demonseye.h # End Source File # Begin Source File @@ -102,6 +106,10 @@ SOURCE=.\lmsreward.h # End Source File # Begin Source File +SOURCE=.\questkeys.h +# End Source File +# Begin Source File + SOURCE=.\seed.h # End Source File # Begin Source File @@ -119,6 +127,10 @@ SOURCE=.\birthday_firework.c # End Source File # Begin Source File +SOURCE=.\catapultammo.c +# End Source File +# Begin Source File + SOURCE=.\demonseye.c # End Source File # Begin Source File @@ -131,6 +143,10 @@ SOURCE=.\lmsreward.c # End Source File # Begin Source File +SOURCE=.\questkeys.c +# End Source File +# Begin Source File + SOURCE=.\seed.c # End Source File # Begin Source File diff --git a/src/common/items/lmsreward.c b/src/common/items/lmsreward.c index fb89b4d40..a8828b6c0 100644 --- a/src/common/items/lmsreward.c +++ b/src/common/items/lmsreward.c @@ -39,7 +39,7 @@ info_lmsstory(const void* vp, int i, curse * c, int i2) } static curse_type ct_lmsstory = { - 0, 0, 0, NULL, NULL, &info_lmsstory + "lmsstory", 0, 0, 0, "xxx", &info_lmsstory }; diff --git a/src/common/items/questkeys.c b/src/common/items/questkeys.c index 8910150f2..adc17b814 100644 --- a/src/common/items/questkeys.c +++ b/src/common/items/questkeys.c @@ -54,7 +54,7 @@ use_questkey(struct unit * u, const struct item_type * itype, int amount, const key1 = region_hashkey(r1); key2 = region_hashkey(r2); - key = min(key2, key) % BMAXHASH; + key = min(key2, key1) % BMAXHASH; bo = borders[key]; @@ -68,10 +68,10 @@ use_questkey(struct unit * u, const struct item_type * itype, int amount, const assert(bo != NULL); lock = (int)bo->data; - if(itype == &it_questkey1) k = 1; - if(itype == &it_questkey2) k = 2; + if (itype == &it_questkey1) k = 1; + else k = 2; - if(lock & k) { + if (lock & k) { m = msg_message("questportal_unlock","region unit key", u->region, u, k); lock = lock & ~k; } else { diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index 8d083a6d7..fe6888fc2 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -1425,6 +1425,7 @@ do_combatmagic(battle *b, combatmagic_t was) level = eff_skill(mage, SK_MAGIC, r); if (level > 0) { + const struct locale * lang = mage->faction->locale; char cmd[128]; switch(was) { @@ -1443,7 +1444,8 @@ do_combatmagic(battle *b, combatmagic_t was) if (sp == NULL) continue; - snprintf(cmd, 128, "ZAUBER %s", sp->name); + snprintf(cmd, 128, "%s \"%s\"", + LOC(lang, keywords[K_CAST]), spell_name(sp, lang)); if (cancast(mage, sp, 1, 1, cmd) == false) continue; @@ -1452,7 +1454,7 @@ do_combatmagic(battle *b, combatmagic_t was) if (sl > 0) level = min(sl, level); if (level < 0) { sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); continue; } @@ -1460,14 +1462,14 @@ do_combatmagic(battle *b, combatmagic_t was) power = spellpower(r, mage, sp, level); if (power <= 0) { /* Effekt von Antimagie */ sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); continue; } if (fumble(r, mage, sp, sp->level) == true) { sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); pay_spell(mage, sp, level, 1); continue; @@ -1512,6 +1514,7 @@ do_combatspell(troop at, int row) void **mg; int sl; char cmd[128]; + const struct locale * lang = mage->faction->locale; if (row>BEHIND_ROW) return; @@ -1520,7 +1523,7 @@ do_combatspell(troop at, int row) fi->magic = 0; /* Hat keinen Kampfzauber, kämpft nichtmagisch weiter */ return; } - snprintf(cmd, 128, "ZAUBER %s", sp->name); + snprintf(cmd, 128, "ZAUBER %s", spell_name(sp, lang)); if (cancast(mage, sp, 1, 1, cmd) == false) { fi->magic = 0; /* Kann nicht mehr Zaubern, kämpft nichtmagisch weiter */ return; @@ -1531,7 +1534,7 @@ do_combatspell(troop at, int row) if (fumble(r, mage, sp, sp->level) == true) { sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); pay_spell(mage, sp, level, 1); return; @@ -1550,14 +1553,14 @@ do_combatspell(troop at, int row) /* Antimagie die Fehlschlag erhöht */ if (rand()%100 < fumblechance) { sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); return; } power = spellpower(r, mage, sp, level); if (power <= 0) { /* Effekt von Antimagie */ sprintf(buf, "%s versucht %s zu zaubern, doch der Zauber schlägt " - "fehl!", unitname(mage), sp->name); + "fehl!", unitname(mage), spell_name(sp, lang)); battlerecord(b, buf); pay_spell(mage, sp, level, 1); return; @@ -1633,6 +1636,13 @@ skilldiff(troop at, troop dt, int dist) #endif if (df->building) { + boolean init = false; + static const curse_type * strongwall_ct, * magicstone_ct; + if (!init) { + strongwall_ct = ct_find("strongwall"); + magicstone_ct = ct_find("magicstone"); + init=true; + } if (df->building->type->flags & BTF_PROTECTION) { if(fspecial(au->faction, FS_SAPPER)) { /* Halbe Schutzwirkung, aufgerundet */ @@ -1643,12 +1653,15 @@ skilldiff(troop at, troop dt, int dist) } is_protected = 2; } - if (is_cursed(df->building->attribs, C_STRONGWALL, 0)) { - /* wirkt auf alle Gebäude */ - skdiff -= get_curseeffect(df->building->attribs, C_STRONGWALL, 0); - is_protected = 2; + if (strongwall_ct) { + curse * c = get_curse(df->building->attribs, strongwall_ct); + if (curse_active(c)) { + /* wirkt auf alle Gebäude */ + skdiff -= curse_geteffect(c); + is_protected = 2; + } } - if (is_cursed(df->building->attribs, C_MAGICSTONE, 0)) { + if (magicstone_ct && curse_active(get_curse(df->building->attribs, magicstone_ct))) { /* Verdoppelt Burgenbonus */ skdiff -= buildingeffsize(df->building, false); } @@ -2745,11 +2758,16 @@ make_fighter(battle * b, unit * u, boolean attack) rest = u->hp % u->number; /* Effekte von Sprüchen */ + { - curse *c = get_curse(u->attribs, C_SPEED, 0); - if (c) { - speeded = get_cursedmen(u, c); - speed = get_curseeffect(u->attribs, C_SPEED, 0); + static const curse_type * speed_ct; + speed_ct = ct_find("speed"); + if (speed_ct) { + curse *c = get_curse(u->attribs, speed_ct); + if (c) { + speeded = get_cursedmen(u, c); + speed = curse_geteffect(c); + } } } @@ -3354,6 +3372,14 @@ do_battle(void) strlist *sl; list_foreach(strlist, u->orders, sl) { + boolean init=false; + static const curse_type * peace_ct, * slave_ct, * calm_ct; + if (!init) { + init = true; + peace_ct = ct_find("peacezone"); + slave_ct = ct_find("slavery"); + calm_ct = ct_find("calmmonster"); + } if (igetkeyword(sl->s, u->faction->locale) == K_ATTACK) { unit *u2; fighter *c1, *c2; @@ -3385,14 +3411,14 @@ do_battle(void) /* ist ein Flüchtling aus einem andern Kampf */ if (fval(u, FL_MOVED)) list_continue(sl); - if (is_spell_active(r, C_PEACE)) { + if (peace_ct && curse_active(get_curse(r->attribs, peace_ct))) { sprintf(buf, "Hier ist es so schön friedlich, %s möchte " "hier niemanden angreifen.", unitname(u)); mistake(u, sl->s, buf, MSG_BATTLE); list_continue(sl); } - if (is_cursed(u->attribs, C_SLAVE, 0)) { + if (slave_ct && curse_active(get_curse(u->attribs, slave_ct))) { sprintf(buf, "%s kämpft nicht.", unitname(u)); mistake(u, sl->s, buf, MSG_BATTLE); list_continue(sl); @@ -3467,13 +3493,13 @@ do_battle(void) sprintf(buf, "%s ist böse gewesen...", unitname(u)); mistake(u, sl->s, buf, MSG_BATTLE); list_continue(sl); - }if (u2->faction->age < IMMUN_GEGEN_ANGRIFF) { + } if (u2->faction->age < IMMUN_GEGEN_ANGRIFF) { add_message(&u->faction->msgs, msg_error(u, findorder(u, u->thisorder), "newbie_immunity_error", "turns", IMMUN_GEGEN_ANGRIFF)); list_continue(sl); } /* Fehler: "Die Einheit ist mit uns alliert" */ - if (is_cursed(u->attribs, C_CALM, u2->faction->unique_id)) { + if (calm_ct && curse_active(get_cursex(u->attribs, calm_ct, (void*)u2->faction->unique_id, cmp_curseeffect))) { cmistake(u, sl->s, 47, MSG_BATTLE); list_continue(sl); } diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c index 741dc4c53..61a56a336 100644 --- a/src/common/kernel/build.c +++ b/src/common/kernel/build.c @@ -182,7 +182,9 @@ siege(region * r, unit * u) building *b; int d; int bewaffnete, katapultiere = 0; - + static boolean init = false; + static const curse_type * magicstone_ct; + if (!init) { init = true; magicstone_ct = ct_find("magicstone"); } /* gibt es ueberhaupt Burgen? */ b = getbuilding(r); @@ -232,7 +234,7 @@ siege(region * r, unit * u) d = min(d, b->size - 1); /* meldung, schaden anrichten */ - if (d && !(is_cursed(b->attribs, C_MAGICSTONE, 0))) { + if (d && !curse_active(get_curse(b->attribs, magicstone_ct))) { b->size -= d; new_use_pooled(u, &rt_catapultammo, GET_SLACK|GET_RESERVE|GET_POOLED_SLACK, d); d = 100 * d / b->size; diff --git a/src/common/kernel/building.c b/src/common/kernel/building.c index 521bffc80..747029c27 100644 --- a/src/common/kernel/building.c +++ b/src/common/kernel/building.c @@ -121,7 +121,10 @@ buildingmaintenance(const building * b, resource_t rtype) { const building_type * bt = b->type; int c, cost=0; - if (is_cursed(b->attribs, C_NOCOST, 0)) { + static boolean init = false; + static const curse_type * nocost_ct; + if (!init) { init = true; nocost_ct = ct_find("nocost"); } + if (curse_active(get_curse(b->attribs, nocost_ct))) { return 0; } for (c=0;bt->maintenance && bt->maintenance[c].number;++c) { diff --git a/src/common/kernel/combatspells.c b/src/common/kernel/combatspells.c index fd019bde0..19cd8d235 100644 --- a/src/common/kernel/combatspells.c +++ b/src/common/kernel/combatspells.c @@ -113,7 +113,8 @@ sp_kampfzauber(fighter * fi, int level, int power, spell * sp) if (power <= 0) return 0; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); switch(sp->id) { /* lovar halbiert im Schnitt! */ @@ -171,7 +172,8 @@ sp_versteinern(fighter * fi, int level, int power, spell * sp) int force, enemies; int stoned = 0; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); force = lovar(get_force(power,0)); @@ -224,7 +226,8 @@ sp_stun(fighter * fi, int level, int power, spell * sp) if (power <= 0) return 0; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); switch(sp->id) { case SPL_SHOCKWAVE: @@ -374,7 +377,8 @@ sp_sleep(fighter * fi, int level, int power, spell * sp) int minrow = FIGHT_ROW; int maxrow = BEHIND_ROW; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); force = lovar(power * 25); enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow); @@ -448,7 +452,8 @@ sp_speed(fighter * fi, int level, int power, spell * sp) int allies; int targets = 0; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); scat(":"); battlerecord(b, buf); @@ -519,7 +524,8 @@ sp_mindblast(fighter * fi, int level, int power, spell * sp) int minrow = FIGHT_ROW; int maxrow = BEHIND_ROW; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); force = lovar(power * 25); enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow); @@ -600,7 +606,8 @@ sp_dragonodem(fighter * fi, int level, int power, spell * sp) int killed = 0; const char *damage; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); /* 11-26 HP */ damage = spell_damage(4); /* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */ @@ -649,7 +656,8 @@ sp_drainodem(fighter * fi, int level, int power, spell * sp) int killed = 0; const char *damage; - sprintf(buf, "%s zaubert %s", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s", unitname(fi->unit), + spell_name(sp, default_locale)); /* 11-26 HP */ damage = spell_damage(4); /* Jungdrache 3->54, Drache 6->216, Wyrm 12->864 Treffer */ @@ -817,6 +825,10 @@ sp_strong_wall(fighter * fi, int level, int force, spell * sp) unit *mage = fi->unit; building *burg; int effect; + static boolean init = false; + static const curse_type * strongwall_ct; + if (!init) { init = true; strongwall_ct = ct_find("strongwall"); } + unused(sp); if (!mage->building) { @@ -831,7 +843,7 @@ sp_strong_wall(fighter * fi, int level, int force, spell * sp) if (rand()%4 < force%4) effect++; - create_curse(mage, &burg->attribs, C_STRONGWALL, 0, force, 1, effect, 0); + create_curse(mage, &burg->attribs, strongwall_ct, force, 1, effect, 0); sprintf(buf, "%s Mauern erglühen in einem unheimlichen magischen Licht.", buildingname(burg)); @@ -949,7 +961,8 @@ sp_flee(fighter * fi, int level, int power, spell * sp) switch(sp->id) { case SPL_FLEE: - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); force = get_force(power,4); break; case SPL_SONG_OF_FEAR: @@ -1019,7 +1032,8 @@ sp_hero(fighter * fi, int level, int power, spell * sp) int allies; int targets = 0; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); switch(sp->id) { case SPL_HERO: df_bonus = power/5; @@ -1075,7 +1089,8 @@ sp_berserk(fighter * fi, int level, int power, spell * sp) int allies = 0; int targets = 0; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); switch(sp->id) { case SPL_BERSERK: case SPL_BLOODTHIRST: @@ -1139,7 +1154,8 @@ sp_frighten(fighter * fi, int level, int power, spell * sp) df_malus = 2; force = get_force(power, 2); - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); enemies = count_enemies(b, fi->side, FS_ENEMY, minrow, maxrow); if (!enemies) { @@ -1189,7 +1205,8 @@ sp_tiredsoldiers(fighter * fi, int level, int force, spell * sp) force = force * force * 4; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); if (!count_enemies(b, fi->side, FS_ENEMY, FIGHT_ROW, BEHIND_ROW)) { scat(", aber niemand war in Reichweite."); @@ -1239,7 +1256,8 @@ sp_windshield(fighter * fi, int level, int power, spell * sp) int minrow = BEHIND_ROW; int maxrow = BEHIND_ROW; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); switch(sp->id) { case SPL_WINDSHIELD: force = get_force(power,4); @@ -1287,7 +1305,8 @@ sp_reeling_arrows(fighter * fi, int level, int force, spell * sp) unused(force); b->reelarrow = true; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); scat(": "); scat("Ein Sturm kommt auf und die Schützen können kaum noch zielen."); battlerecord(b, buf); @@ -1305,7 +1324,8 @@ sp_denyattack(fighter * fi, int level, int power, spell * sp) region *r = b->region; unused(power); - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); scat(": "); /* Fliehende Einheiten verlassen auf jeden Fall Gebäude und Schiffe. */ @@ -1364,7 +1384,8 @@ sp_armorshield(fighter * fi, int level, int power, spell * sp) unit *mage = fi->unit; battle *b = fi->side->battle; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); battlerecord(b, buf); /* gibt Rüstung +effect für duration Treffer */ @@ -1391,7 +1412,8 @@ sp_reduceshield(fighter * fi, int level, int power, spell * sp) unit *mage = fi->unit; battle *b = fi->side->battle; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); battlerecord(b, buf); /* jeder Schaden wird um effect% reduziert bis der Schild duration @@ -1419,7 +1441,8 @@ sp_fumbleshield(fighter * fi, int level, int power, spell * sp) unit *mage = fi->unit; battle *b = fi->side->battle; - sprintf(buf, "%s zaubert %s", unitname(mage), sp->name); + sprintf(buf, "%s zaubert %s", unitname(mage), + spell_name(sp, default_locale)); battlerecord(b, buf); /* der erste Zauber schlägt mit 100% fehl */ @@ -1477,7 +1500,8 @@ sp_reanimate(fighter * fi, int level, int force, spell * sp) default: sprintf(buf, "%s zaubert %s", - unitname(mage), sp->name); + unitname(mage), + spell_name(sp, default_locale)); k = EFFECT_HEALING_SPELL*force; c = 0.50; } @@ -1535,7 +1559,8 @@ sp_keeploot(fighter * fi, int level, int force, spell * sp) { battle *b = fi->side->battle; - sprintf(buf, "%s zaubert %s.", unitname(fi->unit), sp->name); + sprintf(buf, "%s zaubert %s.", unitname(fi->unit), + spell_name(sp, default_locale)); battlerecord(b, buf); b->keeploot = max(50, b->keeploot + 5*force); diff --git a/src/common/kernel/curse.c b/src/common/kernel/curse.c index 50cf4388d..8167d30b7 100644 --- a/src/common/kernel/curse.c +++ b/src/common/kernel/curse.c @@ -55,7 +55,6 @@ dirmirror(direction_t dir) /* ------------------------------------------------------------- */ /* at_curse */ - void curse_init(attrib * a) { a->data.v = calloc(1, sizeof(curse)); @@ -80,7 +79,7 @@ curse_done(attrib * a) { cunhash(c); - if( c->data ) + if( c->data && c->type->typ == CURSETYP_UNIT) free(c->data); free(c); } @@ -168,33 +167,22 @@ ct_find(const char *c) { cursetype_list * ctl = cursetypes; while (ctl) { - int k = min(strlen(c), strlen(ctl->type->name)); - if (!strncasecmp(c, ctl->type->name, k)) return ctl->type; - ctl = ctl->next; - } - return NULL; -} - -const curse_type * -find_cursetype(curse_t id) -{ - cursetype_list * ctl = cursetypes; - - /* sollte eigendlich nie mit 0 aufgerufen werden */ - if (!id) return NULL; - - while (ctl) { - if(ctl->type->cspellid == id) return ctl->type; + int 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; } /* ------------------------------------------------------------- */ boolean -is_normalcurse(curse_t id) +is_normalcurse(const curse_type * ct) { - curse_type *ct = find_cursetype(id); if (!ct) return false; @@ -205,10 +193,8 @@ is_normalcurse(curse_t id) } boolean -is_curseunit(curse_t id) +is_curseunit(const curse_type * ct) { - curse_type *ct = find_cursetype(id); - if (!ct) return false; if (ct->typ == CURSETYP_UNIT) @@ -217,29 +203,29 @@ is_curseunit(curse_t id) return false; } -boolean -is_curseskill(curse_t id) -{ - curse_type *ct = find_cursetype(id); - - if (!ct) return false; - - if (ct->typ == CURSETYP_SKILL) - return true; - - return false; -} - /* ------------------------------------------------------------- */ /* get_curse identifiziert eine Verzauberung über die ID und gibt * einen pointer auf die struct zurück. */ -typedef struct twoids { +typedef struct cid { int id; int id2; } twoids; +boolean +cmp_curseeffect(const curse * c, const void * data) +{ + int effect = (int)data; + return (c->effect==effect); +} + +boolean +cmp_cursedata(const curse * c, const void * data) +{ + return (c->data==data); +} + boolean cmp_curse(const attrib * a, const void * data) { const curse * c = (const curse*)data; @@ -250,42 +236,31 @@ cmp_curse(const attrib * a, const void * data) { } boolean -cmp_oldcurse(const attrib * a, const void * data) +cmp_cursetype(const attrib * a, const void * data) { - twoids * ti = (twoids*)data; - const curse * c = (const curse*)a->data.v; - const curse_type * ct; - - if (a->type!=&at_curse) return false; - ct = c->type; - - if (ct->cspellid != ti->id) return false; - - /* TODO: prüfen auf namen */ - - if (is_curseskill(ti->id)){ - curse_skill * cc = (curse_skill*)c->data; - if (cc->skill == (skill_t) ti->id2){ - return true; - } else { - 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 true; -} - -twoids * -packids(int id, int id2) { - static twoids ti; - ti.id = id; - ti.id2 = id2; - return &ti; + return false; } curse * -get_curse(attrib *ap, curse_t id, int id2) +get_cursex(attrib *ap, const curse_type * ctype, void * data, boolean(*compare)(const curse *, const void *)) { - attrib * a = a_select(ap, packids(id, id2), cmp_oldcurse); + 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 = a_select(ap, ctype, cmp_cursetype); if (!a) return NULL; return (curse*)a->data.v; @@ -295,9 +270,9 @@ get_curse(attrib *ap, curse_t id, int id2) /* findet einen curse global anhand seiner 'curse-Einheitnummer' */ curse * -findcurse(int curseid) +findcurse(int cid) { - return cfindhash(curseid); + return cfindhash(cid); } /* ------------------------------------------------------------- */ @@ -306,14 +281,14 @@ findcurse(int curseid) * identifizieren benötigt man je nach Typ einen weiteren Identifier. */ void -remove_curse(attrib **ap, curse_t id, int id2) +remove_cursetype(attrib **ap, const curse_type *ct) { - attrib *a = a_select(*ap, packids(id, id2), cmp_oldcurse); + attrib *a = a_select(*ap, ct, cmp_cursetype); if (a) a_remove(ap, a); } void -remove_cursec(attrib **ap, curse *c) +remove_curse(attrib **ap, const curse *c) { attrib *a = a_select(*ap, c, cmp_curse); if (a) a_remove(ap, a); @@ -330,25 +305,22 @@ remove_allcurse(attrib **ap, const void * data, boolean(*compare)(const attrib * } } -/* ------------------------------------------------------------- */ -/* - * Staerke einer Verzauberung - */ -int -get_cursevigour(attrib *ap, curse_t id, int id2) +/* gibt die allgemeine Stärke der Verzauberung zurück. id2 wird wie + * oben benutzt. Dies ist nicht die Wirkung, sondern die Kraft und + * damit der gegen Antimagie wirkende Widerstand einer Verzauberung */ +static int +get_cursevigour(const curse *c) { - int vigour = 0; - curse * c = get_curse(ap, id, id2); - if (c) vigour = c->vigour; - return vigour; + if (c) return c->vigour; + return 0; } -void -set_cursevigour(attrib *ap, curse_t id, int id2, int i) +/* setzt die Stärke der Verzauberung auf i */ +static void +set_cursevigour(curse *c, int vigour) { - curse * c = get_curse(ap, id, id2); - assert(i>0); - if (c) c->vigour = i; + assert(c && vigour > 0); + c->vigour = vigour; } /* verändert die Stärke der Verzauberung um +i und gibt die neue @@ -356,44 +328,42 @@ set_cursevigour(attrib *ap, curse_t id, int id2, int i) * sich auf. */ int -change_cursevigour(attrib **ap, curse_t id, int id2, int i) +curse_changevigour(attrib **ap, curse *c, int vigour) { - i += get_cursevigour(*ap,id,id2); + vigour += get_cursevigour(c); - if (i <= 0) { - remove_curse(ap, id, id2); - }else{ - set_cursevigour(*ap,id,id2,i); + if (vigour <= 0) { + remove_curse(ap, c); + vigour = 0; + } else { + set_cursevigour(c, vigour); } - return i; + return vigour; } /* ------------------------------------------------------------- */ int -get_curseeffect(attrib *ap, curse_t id, int id2) +curse_geteffect(const curse *c) { - int effect = 0; - - curse * c = get_curse(ap, id, id2); - if (c) effect = c->effect; - return effect; + if (c) return c->effect; + return 0; } /* ------------------------------------------------------------- */ void -set_curseingmagician(struct unit *magician, struct attrib *ap_target, curse_t id, int id2) +set_curseingmagician(struct unit *magician, struct attrib *ap_target, const curse_type *ct) { - curse * c = get_curse(ap_target, id, id2); - if (c){ + curse * c = get_curse(ap_target, ct); + if (c) { c->magician = magician; } } unit * -get_cursingmagician(struct attrib *ap, curse_t id, int id2) +get_cursingmagician(struct attrib *ap, const curse_type *ct) { - curse *c = get_curse(ap, id, id2); + curse *c = get_curse(ap, ct); if( !c ) return NULL; @@ -419,6 +389,8 @@ remove_cursemagepointer(unit *magician, attrib *ap_target) /* ------------------------------------------------------------- */ +/* gibt bei Personenbeschränkten Verzauberungen die Anzahl der + * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ int get_cursedmen(unit *u, curse *c) { @@ -431,19 +403,14 @@ get_cursedmen(unit *u, curse *c) curse_unit * cc = (curse_unit*)c->data; cursedmen = cc->cursedmen; } - if (c->type->typ == CURSETYP_SKILL){ - curse_skill * cc = (curse_skill*)c->data; - cursedmen = cc->cursedmen; - } return min(u->number, cursedmen); } -void -set_cursedmen(attrib *ap, curse_t id, int id2, int cursedmen) +/* setzt die Anzahl der betroffenen Personen auf cursedmen */ +static void +set_cursedmen(curse *c, int cursedmen) { - curse *c = get_curse(ap, id, id2); - if (!c) return; /* je nach curse_type andere data struct */ @@ -451,17 +418,11 @@ set_cursedmen(attrib *ap, curse_t id, int id2, int cursedmen) curse_unit * cc = (curse_unit*)c->data; cc->cursedmen = cursedmen; } - if (c->type->typ == CURSETYP_SKILL) { - curse_skill * cc = (curse_skill*)c->data; - cc->cursedmen = cursedmen; - } } int -change_cursedmen(attrib **ap, curse_t id, int id2, int cursedmen) +change_cursedmen(attrib **ap, curse *c, int cursedmen) { - curse *c = get_curse(*ap, id, id2); - if (!c) return 0; /* je nach curse_type andere data struct */ @@ -469,14 +430,10 @@ change_cursedmen(attrib **ap, curse_t id, int id2, int cursedmen) curse_unit * cc = (curse_unit*)c->data; cursedmen += cc->cursedmen; } - if (c->type->typ == CURSETYP_SKILL) { - curse_skill * cc = (curse_skill*)c->data; - cursedmen += cc->cursedmen; - } - if (cursedmen <= 0){ - remove_curse(ap,id,id2); + if (cursedmen <= 0) { + remove_curse(ap, c); } else { - set_cursedmen(*ap, id, id2, cursedmen); + set_cursedmen(c, cursedmen); } return cursedmen; @@ -484,26 +441,17 @@ change_cursedmen(attrib **ap, curse_t id, int id2, int cursedmen) /* ------------------------------------------------------------- */ void -set_curseflag(attrib *ap, curse_t id, int id2, int flag) +curse_setflag(curse *c, int flag) { - curse * c = get_curse(ap, id, id2); if (c) c->flag = (c->flag | flag); } -void -remove_curseflag(attrib *ap, curse_t id, int id2, int flag) -{ - curse * c = get_curse(ap, id, id2); - if (c) c->flag = (c->flag & ~(flag)); -} - - /* ------------------------------------------------------------- */ /* Legt eine neue Verzauberung an. Sollte es schon einen Zauber * dieses Typs geben, gibt es den bestehenden zurück. */ curse * -set_curse(unit *mage, attrib **ap, curse_t id, int id2, int vigour, +set_curse(unit *mage, attrib **ap, const curse_type *ct, int vigour, int duration, int effect, int men) { curse *c; @@ -513,8 +461,8 @@ set_curse(unit *mage, attrib **ap, curse_t id, int id2, int vigour, a_add(ap, a); c = (curse*)a->data.v; - c->type = find_cursetype(id); - c->flag = (0); + c->type = ct; + c->flag = 0; c->vigour = vigour; c->duration = duration; c->effect = effect; @@ -534,14 +482,6 @@ set_curse(unit *mage, attrib **ap, curse_t id, int id2, int vigour, c->data = cc; break; } - case CURSETYP_SKILL: - { - curse_skill *cc = calloc(1, sizeof(curse_skill)); - cc->skill = (skill_t) id2; - cc->cursedmen += men; - c->data = cc; - break; - } } return c; @@ -552,25 +492,20 @@ set_curse(unit *mage, attrib **ap, curse_t id, int id2, int vigour, * passenden Typ verzweigt und die relevanten Variablen weitergegeben. */ curse * -create_curse(unit *magician, attrib **ap, curse_t id, int id2, int vigour, +create_curse(unit *magician, attrib **ap, const curse_type *ct, int vigour, int duration, int effect, int men) { curse *c; - const curse_type *ct; /* die Kraft eines Spruchs darf nicht 0 sein*/ assert(vigour >= 0); - c = get_curse(*ap, id, id2); + c = get_curse(*ap, ct); if(c && (c->flag & CURSE_ONLYONE)){ return NULL; } - if(c){ - ct = c->type; - } else { - ct = find_cursetype(id); - } + assert(c==NULL || ct==c->type); /* es gibt schon eins diese Typs */ if (c && ct->mergeflags != NO_MERGE) { @@ -599,16 +534,11 @@ create_curse(unit *magician, attrib **ap, curse_t id, int id2, int vigour, curse_unit * cc = (curse_unit*)c->data; cc->cursedmen += men; } - case CURSETYP_SKILL: - { - curse_skill * cc = (curse_skill*)c->data; - cc->cursedmen += men; - } } } - set_curseingmagician(magician, *ap, id, id2); + set_curseingmagician(magician, *ap, ct); } else { - c = set_curse(magician, ap, id, id2, vigour, duration, effect, men); + c = set_curse(magician, ap, ct, vigour, duration, effect, men); } return c; } @@ -620,8 +550,6 @@ create_curse(unit *magician, attrib **ap, curse_t id, int id2, int vigour, void do_transfer_curse(curse *c, unit * u, unit * u2, int n) { - curse_t id = c->type->cspellid; - int id2 = 0; int flag = c->flag; int duration = c->duration; int vigour = c->vigour; @@ -639,18 +567,11 @@ do_transfer_curse(curse *c, unit * u, unit * u2, int n) men = cc->cursedmen; break; } - case CURSETYP_SKILL: - { - curse_skill * cc = (curse_skill*)c->data; - id2 = (int)cc->skill; - men = cc->cursedmen; - break; - } default: cursedmen = u->number; } - switch (ct->givemenacting){ + switch (ct->spread){ case CURSE_SPREADALWAYS: dogive = true; men = u2->number + n; @@ -684,16 +605,11 @@ do_transfer_curse(curse *c, unit * u, unit * u2, int n) } if (dogive == true) { - set_curse(magician, &u2->attribs, id, id2, vigour, duration, + curse * cnew = set_curse(magician, &u2->attribs, c->type, vigour, duration, effect, men); - set_curseflag(u2->attribs, id, id2, flag); + curse_setflag(cnew, flag); - switch (ct->typ){ - case CURSETYP_UNIT: - case CURSETYP_SKILL: - set_cursedmen(u2->attribs, id, id2, men); - break; - } + if (ct->typ == CURSETYP_UNIT) set_cursedmen(cnew, men); } } @@ -713,26 +629,19 @@ transfer_curse(unit * u, unit * u2, int n) /* ------------------------------------------------------------- */ boolean -is_cursed(attrib *ap, curse_t id, int id2) +curse_active(const curse *c) { - curse *c = get_curse(ap, id, id2); - - 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; } boolean -is_cursed_internal(attrib *ap, curse_t id, int id2) +is_cursed_internal(attrib *ap, const curse_type *ct) { - curse *c = get_curse(ap, id, id2); + curse *c = get_curse(ap, ct); if (!c) return false; @@ -746,7 +655,7 @@ is_cursed_with(attrib *ap, curse *c) { attrib *a = ap; - while (a){ + while (a) { if ((a->type->flags & ATF_CURSE) && (c == (curse *)a->data.v)) { return true; } @@ -1278,17 +1187,14 @@ cinfo_allskills(void * obj, typ_t typ, curse *c, int self) static int cinfo_skill(void * obj, typ_t typ, curse *c, int self) { - unit *u; - curse_skill *ck; - unused(typ); + unit *u = (unit *)obj; + int sk = (int)c->data; - assert(typ == TYP_UNIT); - u = (unit *)obj; - ck = (curse_skill*)c->data; + unused(typ); if (self){ sprintf(buf, "%s ist in %s ungewöhnlich ungeschickt. (%s)", u->name, - skillname(ck->skill, u->faction->locale), curseid(c)); + skillname((skill_t)sk, u->faction->locale), curseid(c)); return 1; } return 0; @@ -1340,6 +1246,26 @@ cinfo_riot(void * obj, typ_t typ, curse *c, int self) return 1; } +static int +read_skill(FILE * F, curse * c) +{ + int skill; + if (global.data_versiondata = (void*)skill; + return 0; +} + +static int +write_skill(FILE * F, const curse * c) +{ + fprintf(F, "%d ", (int)c->data); + return 0; +} /* ------------------------------------------------------------- */ /* cursedata */ /* ------------------------------------------------------------- */ @@ -1347,7 +1273,7 @@ cinfo_riot(void * obj, typ_t typ, curse *c, int self) * int id; (altlast für kompatibiliät) * char *name; * int typ; - * int givemenacting; + * spread_t spread; * int mergeflags; * char *info; * void (*display)(void*,typ_t, curse*); @@ -1361,19 +1287,17 @@ cinfo_riot(void * obj, typ_t typ, curse *c, int self) * der wohl noch etwa %s Wochen andauert. * %info, "Dieser Zauber blafalsel blub" */ -curse_type cursedaten[MAXCURSE] = +static curse_type cursedaten[MAXCURSE] = { /* struct's vom typ curse: */ { - C_FOGTRAP, - "ct_fogtrap", + "fogtrap", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), "", (cdesc_fun)cinfo_fogtrap }, { - C_ANTIMAGICZONE, - "ct_antimagiczone", + "antimagiczone", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), "Dieser Zauber scheint magische Energien irgendwie abzuleiten und " "so alle in der Region gezauberten Sprüche in ihrer Wirkung zu " @@ -1381,23 +1305,20 @@ curse_type cursedaten[MAXCURSE] = NULL }, { - C_FARVISION, - "ct_farvision", + "farvision", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, { - C_GBDREAM, - "ct_gbdream", + "gbdream", CURSETYP_NORM, 0, (NO_MERGE), "", (cdesc_fun)cinfo_dreamcurse }, { /* Verändert die max Aura und Regeneration um effect% */ - C_AURA, - "ct_auraboost", + "auraboost", CURSETYP_NORM, CURSE_SPREADMODULO, (NO_MERGE), "Dieser Zauber greift irgendwie in die Verbindung zwischen Magier " "und Magischer Essenz ein. Mit positiver Ausrichtung kann er wohl " @@ -1405,49 +1326,49 @@ curse_type cursedaten[MAXCURSE] = "benutzt werden.", (cdesc_fun)cinfo_auraboost }, - { C_MAELSTROM, - "ct_maelstrom", + { + "maelstrom", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), "Dieser Zauber verursacht einen gigantischen magischen Strudel. Der " "Mahlstrom wird alle Schiffe, die in seinen Sog geraten, schwer " "beschädigen.", NULL }, - { C_BLESSEDHARVEST, - "ct_blessedharvest", + { + "blessedharvest", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR ), "Dieser Fruchtbarkeitszauber erhöht die Erträge der Felder.", (cdesc_fun)cinfo_blessedharvest }, - { C_DROUGHT, - "ct_drought", + { + "drought", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR ), "Dieser Zauber strahlt starke negative Energien aus. Warscheinlich " "ist er die Ursache der Dürre." , (cdesc_fun)cinfo_drought }, - { C_BADLEARN, - "ct_badlearn", + { + "badlearn", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR ), "Dieser Zauber scheint die Ursache für die Schlaflosigkeit und " "Mattigkeit zu sein, unter der die meisten Leute hier leiden und " "die dazu führt, das Lernen weniger Erfolg bringt. ", (cdesc_fun)cinfo_badlearn }, - { C_SHIP_SPEEDUP, /* Sturmwind-Zauber, wirkt nur 1 Runde */ - "ct_stormwind", + { /* Sturmwind-Zauber, wirkt nur 1 Runde */ + "stormwind", CURSETYP_NORM, 0, NO_MERGE, "", NULL }, - { C_SHIP_FLYING, /* Luftschiff-Zauber, wirkt nur 1 Runde */ - "ct_flyingship", + { /* Luftschiff-Zauber, wirkt nur 1 Runde */ + "flyingship", CURSETYP_NORM, 0, NO_MERGE, "", NULL }, - { C_SHIP_NODRIFT, /* GünstigeWinde-Zauber */ - "ct_nodrift", + { /* GünstigeWinde-Zauber */ + "nodrift", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR ), "Der Zauber auf diesem Schiff ist aus den elementaren Magien der Luft " "und des Wassers gebunden. Der dem Wasser verbundene Teil des Zaubers " @@ -1455,8 +1376,8 @@ curse_type cursedaten[MAXCURSE] = "Teil scheint es vor widrigen Winden zu schützen.", (cdesc_fun)cinfo_shipnodrift }, - { C_DEPRESSION, /* Trübsal-Zauber */ - "ct_depression", + { /* Trübsal-Zauber */ + "depression", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR ), "Wie schon zu vermuten war, sind der ewig graue Himmel und die " "depressive Stimmung in der Region nicht natürlich. Dieser Fluch " @@ -1465,8 +1386,8 @@ curse_type cursedaten[MAXCURSE] = "sich an Gaukelleien erfreuen können.", (cdesc_fun)cinfo_depression }, - { C_MAGICSTONE, /* Heimstein-Zauber */ - "ct_magicwalls", + { /* Heimstein-Zauber */ + "magicwalls", CURSETYP_NORM, 0, NO_MERGE, "Die Macht dieses Zaubers ist fast greifbar und tief in die Mauern " "gebunden. Starke elementarmagische Kräfte sind zu spüren. " @@ -1475,48 +1396,48 @@ curse_type cursedaten[MAXCURSE] = "gefährden können.", (cdesc_fun)cinfo_magicstone }, - { C_STRONGWALL, /* Feste Mauer - Präkampfzauber, wirkt nur 1 Runde */ - "ct_strongwall", + { /* Feste Mauer - Präkampfzauber, wirkt nur 1 Runde */ + "strongwall", CURSETYP_NORM, 0, NO_MERGE, "", NULL }, - { C_ASTRALBLOCK, /* Astralblock, auf Astralregion */ - "ct_astralblock", + { /* Astralblock, auf Astralregion */ + "astralblock", CURSETYP_NORM, 0, NO_MERGE, "", (cdesc_fun)cinfo_astralblock }, - { C_GENEROUS, /* Unterhaltungsanteil vermehren */ - "ct_generous", + { /* Unterhaltungsanteil vermehren */ + "generous", CURSETYP_NORM, 0, ( M_DURATION | M_VIGOUR | M_MAXEFFECT ), "Dieser Zauber beeinflusst die allgemeine Stimmung in der Region positiv. " "Die gute Laune macht die Leute freigiebiger.", (cdesc_fun)cinfo_generous }, - { C_PEACE, /* verhindert Attackiere regional */ - "ct_peacezone", + { /* verhindert Attackiere regional */ + "peacezone", CURSETYP_NORM, 0, NO_MERGE, "Dieser machtvoller Beeinflussungszauber erstickt jeden Streit schon im " "Keim.", (cdesc_fun)cinfo_peace }, - { C_REGCONF, /* erschwert geordnete Bewegungen */ - "ct_disorientationzone", + { /* erschwert geordnete Bewegungen */ + "disorientationzone", CURSETYP_NORM, 0, NO_MERGE, "", (cdesc_fun)cinfo_regconf }, - { C_MAGICSTREET, /* erzeugt Straßennetz */ - "ct_magicstreet", + { /* erzeugt Straßennetz */ + "magicstreet", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), "Es scheint sich um einen elementarmagischen Zauber zu handeln, der alle " "Pfade und Wege so gut festigt, als wären sie gepflastert. Wie auf einer " "Straße kommt man so viel besser und schneller vorwärts.", (cdesc_fun)cinfo_magicstreet }, - { C_RESIST_MAGIC, - "ct_magicrunes", + { + "magicrunes", CURSETYP_NORM, 0, M_SUMEFFECT, "Dieses Zauber verstärkt die natürliche Widerstandskraft gegen eine " "Verzauberung.", @@ -1524,8 +1445,7 @@ curse_type cursedaten[MAXCURSE] = }, { /* erniedigt Magieresistenz von nicht-aliierten Einheiten, wirkt nur 1x pro Einheit */ - C_SONG_BADMR, - "ct_badmagicresistancezone", + "badmagicresistancezone", CURSETYP_NORM, 0, NO_MERGE, "Dieses Lied, das irgendwie in die magische Essenz der Region gewoben " "ist, schwächt die natürliche Widerstandskraft gegen eine " @@ -1534,8 +1454,7 @@ curse_type cursedaten[MAXCURSE] = }, { /* erhöht Magieresistenz von aliierten Einheiten, wirkt nur 1x pro Einheit */ - C_SONG_GOODMR, - "ct_goodmagicresistancezone", + "goodmagicresistancezone", CURSETYP_NORM, 0, NO_MERGE, "Dieser Lied, das irgendwie in die magische Essenz der Region gewoben " "ist, verstärkt die natürliche Widerstandskraft gegen eine " @@ -1543,22 +1462,21 @@ curse_type cursedaten[MAXCURSE] = NULL }, { /* dient fremder Partei. Zählt nicht zu Migranten, attackiert nicht */ - C_SLAVE, - "ct_slavery", + "slavery", CURSETYP_NORM, 0, NO_MERGE, "Dieser mächtige Bann scheint die Einheit ihres freien Willens " "zu berauben. Solange der Zauber wirkt, wird sie nur den Befehlen " "ihres neuen Herrn gehorchen.", (cdesc_fun)cinfo_slave }, - { C_DISORIENTATION, - "ct_shipdisorientation", + { + "shipdisorientation", CURSETYP_NORM, 0, NO_MERGE, "Dieses Schiff hat sich verfahren.", (cdesc_fun)cinfo_disorientation }, - { C_CALM, - "ct_calmmonster", + { + "calmmonster", CURSETYP_NORM, CURSE_SPREADNEVER, NO_MERGE, "Dieser Beeinflussungszauber scheint die Einheit einem ganz " "bestimmten Volk wohlgesonnen zu machen.", @@ -1566,41 +1484,40 @@ curse_type cursedaten[MAXCURSE] = }, { /* Merkt sich die alte 'richtige' Rasse einer gestalltwandelnden Einheit */ - C_OLDRACE, - "ct_oldrace", + "oldrace", CURSETYP_NORM, CURSE_SPREADALWAYS, NO_MERGE, "", NULL }, - { C_FUMBLE, - "ct_fumble", + { + "fumble", CURSETYP_NORM, CURSE_SPREADNEVER, NO_MERGE, "Eine Wolke negativer Energie umgibt die Einheit.", (cdesc_fun)cinfo_fumble }, - { C_RIOT, - "ct_riotzone", + { + "riotzone", CURSETYP_NORM, 0, (M_DURATION), "Eine Wolke negativer Energie liegt über der Region.", (cdesc_fun)cinfo_riot }, - { C_NOCOST, /* Ewige Mauern-Zauber */ - "ct_nocostbuilding", + { /* Ewige Mauern-Zauber */ + "nocostbuilding", CURSETYP_NORM, 0, NO_MERGE, "Die Macht dieses Zaubers ist fast greifbar und tief in die Mauern " "gebunden. Unbeeindruck vom Zahn der Zeit wird dieses Gebäude wohl " "auf Ewig stehen.", (cdesc_fun)cinfo_nocost }, - { C_HOLYGROUND, - "ct_holyground", + { + "holyground", CURSETYP_NORM, 0, (M_VIGOUR_ADD), "Verschiedene Naturgeistern sind im Boden der Region gebunden und " "beschützen diese vor dem der dunklen Magie des lebenden Todes.", (cdesc_fun)cinfo_holyground }, - { C_CURSED_BY_THE_GODS, - "ct_goodcursezone", + { + "godcursezone", CURSETYP_NORM, 0, (NO_MERGE), "Diese Region wurde von den Göttern verflucht. Stinkende Nebel ziehen " "über die tote Erde, furchbare Kreaturen ziehen über das Land. Die Brunnen " @@ -1608,37 +1525,37 @@ curse_type cursedaten[MAXCURSE] = "überzogen. Niemand kann hier lange überleben.", (cdesc_fun)cinfo_cursed_by_the_gods, }, - { C_FREE_14, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, - { C_FREE_15, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, - { C_FREE_16, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, - { C_FREE_17, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, - { C_FREE_18, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", NULL }, - { C_FREE_19, + { "", CURSETYP_NORM, 0, (NO_MERGE), "", @@ -1646,76 +1563,76 @@ curse_type cursedaten[MAXCURSE] = }, /* struct's vom typ curse_unit: */ - { C_SPEED, - "ct_speed", + { + "speed", CURSETYP_UNIT, CURSE_SPREADNEVER, M_MEN, "Diese Einheit bewegt sich doppelt so schnell.", (cdesc_fun)cinfo_speed }, - { C_ORC, - "ct_orcish", + { + "orcish", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, "Dieser Zauber scheint die Einheit zu 'orkisieren'. Wie bei Orks " "ist eine deutliche Neigung zur Fortpflanzung zu beobachten.", (cdesc_fun)cinfo_orc }, - { C_MBOOST, - "ct_magicboost", + { + "magicboost", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, "", NULL }, - { C_KAELTESCHUTZ, - "ct_insectfur", + { + "insectfur", CURSETYP_UNIT, CURSE_SPREADMODULO, ( M_MEN | M_DURATION ), "Dieser Zauber schützt vor den Auswirkungen der Kälte.", (cdesc_fun)cinfo_kaelteschutz }, - { C_STRENGTH, /* */ - "ct_strength", + { /* */ + "strength", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, "Dieser Zauber vermehrt die Stärke der verzauberten Personen um ein " "vielfaches.", (cdesc_fun)cinfo_strength }, - { C_ALLSKILLS, /* Alp */ - "ct_worse", + { /* Alp */ + "worse", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, "", (cdesc_fun)cinfo_allskills }, - { C_MAGICRESISTANCE, /* */ - "ct_magicresistance", + { /* */ + "magicresistance", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, "Dieser Zauber verstärkt die natürliche Widerstandskraft gegen eine " "Verzauberung.", NULL }, - { C_ITEMCLOAK, /* */ - "ct_itemcloak", + { /* */ + "itemcloak", CURSETYP_UNIT, CURSE_SPREADNEVER, M_DURATION, "Dieser Zauber macht die Ausrüstung unsichtbar.", (cdesc_fun)cinfo_itemcloak }, - { C_SPARKLE, /* */ - "ct_sparkle", + { /* */ + "sparkle", CURSETYP_UNIT, CURSE_SPREADMODULO, ( M_MEN | M_DURATION ), "Dieser Zauber ist einer der ersten, den junge Magier in der Schule lernen.", (cdesc_fun)cinfo_sparkle }, - { C_FREE_22, /* */ + { "", CURSETYP_UNIT, 0, (NO_MERGE), "", NULL }, - { C_FREE_23, /* */ + { "", CURSETYP_UNIT, 0, (NO_MERGE), "", NULL }, - { C_FREE_24, /* */ + { "", CURSETYP_UNIT, 0, (NO_MERGE), "", @@ -1723,35 +1640,33 @@ curse_type cursedaten[MAXCURSE] = }, /* struct's vom typ curse_skill: */ - { C_SKILL, /* */ - "ct_skillmod", - CURSETYP_SKILL, CURSE_SPREADMODULO, M_MEN, + { + "skillmod", + CURSETYP_NORM, CURSE_SPREADMODULO, M_MEN, "", - (cdesc_fun)cinfo_skill - }, + (cdesc_fun)cinfo_skill, + NULL, /* void (*change_vigour)(curse*, int); */ + read_skill, write_skill + } }; +const char * +oldcursename(int id) +{ + return cursedaten[id].cname; +} + void * resolve_curse(void * id) { return cfindhash((int)id); } -/* ------------------------------------------------------------- */ -/* Überbleibsel des alten source: - * Nur Regionszauber - */ -boolean -is_spell_active(const region * r, curse_t id) +void +register_curses(void) { - curse *c; - c = get_curse(r->attribs, id, 0); - - if (!c) - return false; - - if (c->flag & CURSE_ISNEW) - return false; - - return true; + int i; + for (i=0;i!=MAXCURSE;++i) { + if (strlen(cursedaten[i].cname)) ct_register(&cursedaten[i]); + } } diff --git a/src/common/kernel/curse.h b/src/common/kernel/curse.h index 17cdc51aa..e5212e59e 100644 --- a/src/common/kernel/curse.h +++ b/src/common/kernel/curse.h @@ -140,32 +140,30 @@ enum { C_FREE_24, /* struct's vom untertyp curse_skill: */ C_SKILL, - C_DUMMY, MAXCURSE }; /* ------------------------------------------------------------- */ /* Flags */ -#define CURSE_ISNEW 1 /* wirkt in der zauberrunde nicht (default)*/ -#define CURSE_NOAGE 2 /* wirkt ewig */ -#define CURSE_IMMUN 4 /* ignoriert Antimagie */ +#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 */ -enum{ +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, - CURSETYP_SKILL, MAXCURSETYP }; @@ -189,7 +187,7 @@ enum { typedef struct curse { struct curse *nexthash; int no; /* 'Einheitennummer' dieses Curse */ - struct curse_type * type; /* Zeiger auf ein curse_type-struct */ + 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 */ int vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */ @@ -207,17 +205,6 @@ typedef struct curse_unit { int cursedmen; /* verzauberte Personen in der Einheit */ } curse_unit; -/* Einheitenzauber: - * Spezialtyp, der Talentmodifizierer. Bei Handwerkstalenten oder - * Kampftalenten können Personenbezogenen Boni oder Mali berücksichtigt - * werden, bei anderen Talenten muss sich der Implementiere genauere - * Gedanken zu den Auswirkungen bei nicht ganz voll verzauberten - * Einheiten machen. - */ -typedef struct curse_skill { - int cursedmen; /* verzauberte Personen in der Einheit */ - skill_t skill; /* Talent auf das der Spruch wirkt (id2) */ -} curse_skill; typedef int (*cdesc_fun)(const void*, int, curse*, int); /* Parameter: Objekt, auf dem curse liegt, Typ des Objekts, curse, @@ -226,19 +213,18 @@ typedef int (*cdesc_fun)(const void*, int, curse*, int); /* ------------------------------------------------------------- */ typedef struct curse_type { - curse_t cspellid; /* Id des Cursezaubers */ - const char *name; /* Name der Zauberwirkung, Identifizierung des curse */ + const char *cname; /* Name der Zauberwirkung, Identifizierung des curse */ int typ; - int givemenacting; - int mergeflags; - const char *info; /* Wirkung des curse, wird bei einer gelungenen + spread_t spread; + unsigned int mergeflags; + const char *info_str; /* Wirkung des curse, wird bei einer gelungenen Zauberanalyse angezeigt */ int (*curseinfo)(const void*, int, curse*, int); void (*change_vigour)(curse*, int); + int (*read)(FILE * F, curse * c); + int (*write)(FILE * F, const curse * c); } curse_type; -extern struct curse_type cursedaten[]; - extern attrib_type at_curse; extern void curse_write(const attrib * a,FILE * f); extern int curse_read(struct attrib * a,FILE * f); @@ -247,8 +233,6 @@ 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). - * Das ist bei curse_skill der Skill, bei curse_secondid irgendwas frei - * definierbares. In allen anderen Fällen ist id2 egal. * * Wenn der Typ korrekt definiert wurde, erfolgt die Verzweigung zum * korrekten Typus automatisch, und die unterschiedlichen struct-typen @@ -257,7 +241,7 @@ extern int curse_read(struct attrib * a,FILE * f); * allgemeine Funktionen * */ -curse * create_curse(struct unit *magician, struct attrib**ap, curse_t id, int id2, +curse * create_curse(struct unit *magician, struct attrib**ap, const curse_type * ctype, int vigour, int duration, int effect, int men); /* Verzweigt automatisch zum passenden struct-typ. Sollte es schon * einen Zauber dieses Typs geben, so wird der neue dazuaddiert. Die @@ -265,23 +249,18 @@ curse * create_curse(struct unit *magician, struct attrib**ap, curse_t id, int i * nochmal gesondert auf min(get_cursedmen, u->number) gesetzt werden. */ -boolean is_cursed(struct attrib *ap, curse_t id, int id2); - /* gibt true, wenn bereits ein Zauber dieses Typs vorhanden ist */ -boolean is_cursed_internal(struct attrib *ap, curse_t id, int id2); +boolean is_cursed_internal(struct attrib *ap, const curse_type * ctype); /* ignoriert CURSE_ISNEW */ -void remove_curse(struct attrib **ap, curse_t id, int id2); - /* löscht einen Spruch auf einem Objekt. Bei einigen Typen von - * Verzauberungen (z.B. Skillmodif.) muss neben der curse-id noch - * ein weiterer Identifizierer angegeben werden, zb der Skill. In - * allen anderen Fällen ist id2 egal. - */ void remove_allcurse(struct attrib **ap, const void * data, boolean(*compare)(const attrib *, const void *)); /* löscht alle Curse dieses Typs */ -void remove_cursec(attrib **ap, curse *c); +void remove_cursetype(struct attrib **ap, const curse_type *ct); /* löscht den curse c, wenn dieser in ap steht */ +extern void remove_curse(struct attrib **ap, const curse * c); + /* löscht einen konkreten Spruch auf einem Objekt. + */ -int get_curseeffect(struct attrib *ap, curse_t id, int id2); +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 @@ -289,27 +268,17 @@ int get_curseeffect(struct attrib *ap, curse_t id, int id2); */ -int get_cursevigour(struct attrib *ap, curse_t id, int id2); - /* gibt die allgemeine Stärke der Verzauberung zurück. id2 wird wie - * oben benutzt. Dies ist nicht die Wirkung, sondern die Kraft und - * damit der gegen Antimagie wirkende Widerstand einer Verzauberung */ -void set_cursevigour(struct attrib *ap, curse_t id, int id2, int i); - /* setzt die Stärke der Verzauberung auf i */ -int change_cursevigour(struct attrib **ap, curse_t id, int id2, int i); +extern int curse_changevigour(struct attrib **ap, curse * c, int i); /* verändert die Stärke der Verzauberung um i */ -int get_cursedmen(struct unit *u, struct curse *c); +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. */ -int change_cursedmen(struct attrib **ap, curse_t id, int id2, int cursedmen); +extern int change_cursedmen(struct attrib **ap, curse * c, int cursedmen); /* verändert die Anzahl der betroffenen Personen um cursedmen */ -void set_cursedmen(struct attrib *ap, curse_t id, int id2, int cursedmen); - /* setzt die Anzahl der betroffenen Personen auf cursedmen */ -void set_curseflag(struct attrib *ap, curse_t id, int id2, int flag); +extern void curse_setflag(curse * c, int flag); /* setzt Spezialflag einer Verzauberung (zB 'dauert ewig') */ -void remove_curseflag(struct attrib *ap, curse_t id, int id2, int flag); - /* löscht Spezialflag einer Verzauberung (zB 'ist neu') */ void transfer_curse(struct unit * u, struct unit * u2, int n); /* sorgt dafür, das bei der Übergabe von Personen die curse-attribute @@ -320,12 +289,19 @@ void remove_cursemagepointer(struct unit *magician, attrib *ap_target); /* wird von remove_empty_units verwendet um alle Verweise auf * gestorbene Magier zu löschen. * */ -curse * get_curse(struct attrib *ap, curse_t id, int id2); - /* gibt pointer auf die passende curse-struct zurück, oder einen - * NULL-pointer + +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. * */ -struct unit * get_tracingunit(struct attrib **ap, curse_t id); -struct unit * get_cursingmagician(struct attrib *ap, curse_t id, int id2); +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); +struct unit * get_cursingmagician(struct attrib *ap, const curse_type * ctype); /* gibt struct unit-pointer auf Magier zurück, oder einen Nullpointer * */ int find_cursebyname(const char *c); @@ -344,17 +320,30 @@ extern void curse_done(struct attrib * a); extern int curse_age(struct attrib * a); extern boolean cmp_curse(const attrib * a, const void * data); -/* compatibility mode für katjas curses: */ +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); + +/* compatibility mode für katjas curses: extern boolean cmp_oldcurse(const attrib * a, const void * data); extern struct twoids * packids(int id, int id2); +*/ extern void * resolve_curse(void * data); - -extern boolean is_spell_active(const struct region * r, curse_t id); - /* prüft, ob ein bestimmter Zauber auf einer struct region liegt */ - extern boolean is_cursed_with(attrib *ap, curse *c); -const curse_type * find_cursetype(curse_t id); - + +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)))) #endif diff --git a/src/common/kernel/eressea.c b/src/common/kernel/eressea.c index f9428756d..64666297d 100644 --- a/src/common/kernel/eressea.c +++ b/src/common/kernel/eressea.c @@ -377,13 +377,21 @@ int shipspeed (ship * sh, const unit * u) { int k = sh->type->range; + static const curse_type * stormwind_ct, * nodrift_ct; + static boolean init; + if (!init) { + init = true; + stormwind_ct = ct_find("stormwind"); + nodrift_ct = ct_find("nodrift"); + } + assert(u->ship==sh); assert(sh->type->construction->improvement==NULL); /* sonst ist construction::size nicht ship_type::maxsize */ if (sh->size!=sh->type->construction->maxsize) return 0; - if( is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0) ) + if( curse_active(get_curse(sh->attribs, stormwind_ct))) k *= 2; - if( is_cursed(sh->attribs, C_SHIP_NODRIFT, 0) ) + if( curse_active(get_curse(sh->attribs, nodrift_ct))) k += 1; if (old_race(u->faction->race) == RC_AQUARIAN @@ -2688,8 +2696,16 @@ wage(const region *r, const unit *u, boolean img) { building *b = largestbuilding(r, img); int esize = 0; + curse * c; int wage; attrib *a; + static const curse_type * drought_ct, * blessedharvest_ct; + static boolean init; + if (!init) { + init = true; + drought_ct = ct_find("drought"); + blessedharvest_ct = ct_find("blessedharvest"); + } if (b) esize = buildingeffsize(b, img); @@ -2706,17 +2722,19 @@ wage(const region *r, const unit *u, boolean img) } else { wage = wagetable[esize][2]; } - wage += get_curseeffect(r->attribs, C_BLESSEDHARVEST, 0); + wage += curse_geteffect(get_curse(r->attribs, blessedharvest_ct)); } /* Godcurse: Income -10 */ - if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + if (curse_active(get_curse(r->attribs, ct_find("godcursezone")))) { wage = max(0,wage-10); } /* Bei einer Dürre verdient man nur noch ein Viertel */ - if (is_spell_active(r, C_DROUGHT)) - wage /= get_curseeffect(r->attribs, C_DROUGHT, 0); + if (drought_ct) { + c = get_curse(r->attribs, drought_ct); + if (curse_active(c)) wage /= curse_geteffect(c); + } a = a_find(r->attribs, &at_reduceproduction); if (a) wage = (wage * a->data.sa[0])/100; @@ -2731,6 +2749,7 @@ fwage(const region *r, const faction *f, boolean img) int esize = 0; int wage; attrib *a; + curse * c; if (b) esize = buildingeffsize(b, img); @@ -2747,17 +2766,17 @@ fwage(const region *r, const faction *f, boolean img) } else { wage = wagetable[esize][2]; } - wage += get_curseeffect(r->attribs, C_BLESSEDHARVEST, 0); + wage += curse_geteffect(get_curse(r->attribs, ct_find("blessedharvest"))); } /* Godcurse: Income -10 */ - if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + if (curse_active(get_curse(r->attribs, ct_find("godcursezone")))) { wage = max(0,wage-10); } /* Bei einer Dürre verdient man nur noch ein Viertel */ - if (is_spell_active(r, C_DROUGHT)) - wage /= get_curseeffect(r->attribs, C_DROUGHT, 0); + c = get_curse(r->attribs, ct_find("drought")); + if (curse_active(c)) wage /= curse_geteffect(c); a = a_find(r->attribs, &at_reduceproduction); if (a) wage = (wage * a->data.sa[0])/100; diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index 6a30eb768..30db8afe5 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -38,7 +38,6 @@ typedef unsigned char order_t; typedef char terrain_t; typedef char direction_t; typedef int race_t; -typedef int curse_t; typedef int magic_t; typedef short skill_t; typedef int herb_t; @@ -50,6 +49,7 @@ typedef int resource_t; typedef int spellid_t; struct plane; +struct spell; struct region; struct race; struct ship; @@ -152,9 +152,10 @@ struct xml_stack; #define NEWSKILL_VERSION 309 #define WATCHERS_VERSION 310 #define OVERRIDE_VERSION 311 +#define CURSETYPE_VERSION 312 #define UGROUPS_VERSION 400 /* nicht aktivieren, nicht fertig */ -#define RELEASE_VERSION OVERRIDE_VERSION +#define RELEASE_VERSION CURSETYPE_VERSION /* #if RELEASE_VERSION >= UGROUPS_VERSION diff --git a/src/common/kernel/item.c b/src/common/kernel/item.c index 88dae404c..0b16da42b 100644 --- a/src/common/kernel/item.c +++ b/src/common/kernel/item.c @@ -829,7 +829,7 @@ use_antimagiccrystal(region * r, unit * mage, int amount, strlist * cmdstrings) c = (curse*)a->data.v; /* Immunität prüfen */ - if (c->flag & CURSE_IMMUN) { + if (c->flag & CURSE_IMMUNE) { do { ap = &(*ap)->next; } while (*ap && a->type==(*ap)->type); continue; } @@ -842,7 +842,7 @@ use_antimagiccrystal(region * r, unit * mage, int amount, strlist * cmdstrings) } if(force) { - create_curse(mage, &r->attribs, C_ANTIMAGICZONE, 0, force, duration, effect, 0); + create_curse(mage, &r->attribs, ct_find("antimagiczone"), force, duration, effect, 0); } } @@ -865,10 +865,10 @@ use_tacticcrystal(region * r, unit * u, int amount, strlist * cmdstrings) int power = 5; /* Widerstand gegen Antimagiesprüche, ist in diesem Fall egal, da der curse für den Kampf gelten soll, der vor den Antimagiezaubern passiert */ + curse * c = create_curse(u, &u->attribs, ct_find("skill"), power, + duration, effect, u->number); + c->data = (void*)SK_TACTICS; unused(cmdstrings); - - create_curse(u, &u->attribs, C_SKILL, SK_TACTICS, power, - duration, effect, u->number); } use_pooled(u, u->region, R_TACTICCRYSTAL, amount); add_message(&u->faction->msgs, @@ -2596,7 +2596,6 @@ register_resources(void) xml_register(&xml_resource, "eressea resource", 0); } -#ifdef BETA_CODE int xml_writeitems(const char * file) { @@ -2774,4 +2773,3 @@ xml_writeitems(const char * file) fclose(stream); return 0; } -#endif diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index 77d440f50..0f56d35d8 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -551,49 +551,44 @@ getspell(const unit *u, spellid_t spellid) #include "umlaut.h" -#define SPELLNAMES_HACK 1 -#if SPELLNAMES_HACK -struct tnode spellnames; - -static void init_spellnames(void) +static local_names * spellnames; +static local_names * +init_spellnames(const struct locale * lang) { int i; - for (i=0; spelldaten[i].id != SPL_NOSPELL; i++) - addtoken(&spellnames, spelldaten[i].name, (void*)i); + local_names * sn = calloc(sizeof(local_names), 1); + sn->next = spellnames; + sn->lang = lang; + for (i=0; spelldaten[i].id != SPL_NOSPELL; i++) { + const char * n = spelldaten[i].sname; + if (spelldaten[i].info==NULL) n = locale_string(lang, n); + addtoken(&sn->names, n, (void*)(spelldaten+i)); + } + return spellnames = sn; } -#endif + spell * -find_spellbyname(unit *u, char *s) +find_spellbyname(unit *u, char *name, const struct locale * lang) { - sc_mage *m; + local_names * sn = spellnames; spell_ptr *spt; - spell *sp; + sc_mage * m = get_mage(u); + spell * sp; - m = get_mage(u); - if (!m) { - return (spell *) NULL; + if (!m) return NULL; + while (sn) { + if (sn->lang==lang) break; + sn=sn->next; } + if (!sn) sn = init_spellnames(lang); + if (findtoken(&sn->names, name, &sp)==E_TOK_NOMATCH) return NULL; for (spt = m->spellptr; spt; spt = spt->next) { - sp = find_spellbyid(spt->spellid); - if (!strncasecmp(sp->name, s, strlen(s))) { - return sp; - } + if (sp->id==spt->spellid) return sp; } -#if SPELLNAMES_HACK /* enno: geht vorerst nicht mit locales */ - { - static int init = 0; - int i; - if (!init) { - init=1; - init_spellnames(); - } - if (findtoken(&spellnames, s, (void**)&i)==0 && getspell(u, spelldaten[i].id)) - return &spelldaten[i]; - } -#endif - return (spell *) NULL; + if (lang==default_locale) return NULL; + return find_spellbyname(u, name, default_locale); } spell * @@ -1022,7 +1017,7 @@ knowsspell(const region * r, const unit * u, const spell * sp) } if (eff_skill(u, SK_MAGIC, u->region) >= sp->level){ log_warning(("%s ist hat die erforderliche Stufe, kennt aber %s nicht.\n", - unitname(u), sp->name)); + unitname(u), spell_name(sp, default_locale))); } return false; } @@ -1054,7 +1049,7 @@ cancast(unit * u, spell * sp, int level, int range, char * cmd) /* reicht die Stufe aus? */ if (eff_skill(u, SK_MAGIC, u->region) < sp->level) { log_warning(("Zauber von %s schlug fehl: %s braucht Stufe %d.\n", - unitname(u), sp->name, sp->level)); + unitname(u), spell_name(sp, default_locale), sp->level)); /* die Einheit ist nicht erfahren genug für diesen Zauber */ cmistake(u, strdup(cmd), 169, MSG_MAGIC); return false; @@ -1096,7 +1091,8 @@ cancast(unit * u, spell * sp, int level, int range, char * cmd) /* Noch fehlte keine Komponente, wir generieren den Anfang der * Fehlermeldung */ sprintf(buf, "%s in %s: 'ZAUBER %s' Für diesen Zauber fehlen " - "noch %d ", unitname(u), regionid(u->region), sp->name, + "noch %d ", unitname(u), regionid(u->region), + spell_name(sp, u->faction->locale), itemanz); scat(locale_string(u->faction->locale, resname(res, (itemanz == 1 ? 0 : 1)))); @@ -1128,6 +1124,7 @@ cancast(unit * u, spell * sp, int level, int range, char * cmd) int spellpower(region * r, unit * u, spell * sp, int cast_level) { + curse * c; int force = cast_level; if (sp==NULL) return 0; else { @@ -1139,16 +1136,18 @@ spellpower(region * r, unit * u, spell * sp, int cast_level) if (get_item(u, I_RING_OF_POWER) > 0) ++force; /* Antimagie in der Zielregion */ - if (is_spell_active(r, C_ANTIMAGICZONE)) { - force -= get_curseeffect(r->attribs, C_ANTIMAGICZONE, 0); - change_cursevigour(&r->attribs, C_ANTIMAGICZONE, 0, -cast_level); + c = get_curse(r->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + force -= curse_geteffect(c); + curse_changevigour(&r->attribs, c, -cast_level); cmistake(u, findorder(u, u->thisorder), 185, MSG_MAGIC); } /* Patzerfluch-Effekt: */ - if (is_cursed(u->attribs, C_FUMBLE, 0) == true) { - force -= get_curseeffect(u->attribs, C_FUMBLE, 0); - change_cursevigour(&u->attribs, C_FUMBLE, 0, -1); + c = get_curse(r->attribs, ct_find("fumble")); + if (curse_active(c)) { + force -= curse_geteffect(c); + curse_changevigour(&u->attribs, c, -1); cmistake(u, findorder(u, u->thisorder), 185, MSG_MAGIC); } @@ -1210,9 +1209,9 @@ magic_resistance(unit *target) chance += effskill(target, SK_MAGIC)*5; /* Auswirkungen von Zaubern auf der Einheit */ - c = get_curse(target->attribs, C_MAGICRESISTANCE, 0); + c = get_curse(target->attribs, ct_find("magicresistance")); if (c) { - chance += get_curseeffect(target->attribs, C_MAGICRESISTANCE, 0) * get_cursedmen(target, c); + chance += curse_geteffect(c) * get_cursedmen(target, c); } /* Unicorn +10 */ @@ -1225,38 +1224,22 @@ magic_resistance(unit *target) curse *c = (curse*)a->data.v; unit *mage = c->magician; - if (c->type->cspellid == C_SONG_GOODMR) { - if (mage != NULL) { + if (mage!=NULL) { + if (c->type == ct_find("goodmagicresistancezone")) { if (allied(mage, target->faction, HELP_GUARD)) { chance += c->effect; break; } - } else { - a = a->nexttype; - continue; } - } - a = a->nexttype; - } - a = a_find(target->region->attribs, &at_curse); - while (a) { - curse *c = (curse*)a->data.v; - unit *mage = c->magician; - - if (c->type->cspellid == C_SONG_BADMR) { - if (mage != NULL) { + else if (c->type == ct_find("badmagicresistancezone")) { if (allied(mage, target->faction, HELP_GUARD)) { a = a->nexttype; continue; - } else { - chance -= c->effect; - break; } } } a = a->nexttype; } - /* Bonus durch Artefakte */ /* TODO (noch gibs keine)*/ @@ -1425,6 +1408,7 @@ fumble(region * r, unit * u, spell * sp, int cast_grade) void do_fumble(castorder *co) { + curse * c; region * r = co->rt; unit * u = (unit*)co->magician; spell * sp = co->sp; @@ -1458,8 +1442,9 @@ do_fumble(castorder *co) case 2: /* temporärer Stufenverlust */ duration = max(rand()%level/2, 2); - create_curse(u, &u->attribs, C_SKILL, SK_MAGIC, level, duration, - -(level/2), 1); + c = create_curse(u, &u->attribs, ct_find("skil"), level, duration, + -(level/2), 1); + c->data = (void*)SK_MAGIC; add_message(&u->faction->msgs, new_message(u->faction, "patzer2%u:unit%r:region", u, r)); break; @@ -1467,9 +1452,9 @@ do_fumble(castorder *co) case 4: /* Spruch schlägt fehl, alle Magiepunkte weg */ set_spellpoints(u, 0); - add_message(&u->faction->msgs, new_message(u->faction, - "patzer3%u:unit%r:region%s:command", - u, r, sp->name)); + add_message(&u->faction->msgs, msg_message("patzer3", + "unit region command", + u, r, spell_name(sp, u->faction->locale))); break; case 5: @@ -1482,7 +1467,7 @@ do_fumble(castorder *co) "Gestalten kreisen um den Magier und scheinen sich von " "den magischen Energien des Zaubers zu ernähren. Mit letzter " "Kraft gelingt es %s dennoch den Spruch zu zaubern.", - unitname(u), sp->name, unitname(u)); + unitname(u), spell_name(sp, u->faction->locale), unitname(u)); addmessage(0, u->faction, buf, MSG_MAGIC, ML_WARN); break; @@ -1494,7 +1479,8 @@ do_fumble(castorder *co) ((nspell_f)sp->sp_function)(co); sprintf(buf, "%s fühlt sich nach dem Zaubern von %s viel erschöpfter " "als sonst und hat das Gefühl, dass alle weiteren Zauber deutlich " - "mehr Kraft als normalerweise kosten werden.", unitname(u), sp->name); + "mehr Kraft als normalerweise kosten werden.", unitname(u), + spell_name(sp, u->faction->locale)); addmessage(0, u->faction, buf, MSG_MAGIC, ML_WARN); countspells(u,3); } @@ -2962,7 +2948,7 @@ magic(void) cmistake(u, so->s, 172, MSG_MAGIC); continue; } - sp = find_spellbyname(u, s); + 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 @@ -2970,7 +2956,7 @@ magic(void) if (sp == NULL && is_familiar(u)) { familiar = u; mage = get_familiar_mage(u); - sp = find_spellbyname(mage, s); + sp = find_spellbyname(mage, s, mage->faction->locale); } if (sp == NULL) { @@ -3028,7 +3014,9 @@ magic(void) 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), sp->name, regionid(target_r)); + regionid(u->region), + spell_name(sp, u->faction->locale), + regionid(target_r)); addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE); continue; } @@ -3040,7 +3028,8 @@ magic(void) level = ilevel; sprintf(buf, "%s in %s: 'ZAUBER %s' Dieser Zauber kann nicht " "mit Stufenangabe gezaubert werden.", unitname(u), - regionid(u->region), sp->name); + regionid(u->region), + spell_name(sp, u->faction->locale)); addmessage(0, u->faction, buf, MSG_MAGIC, ML_WARN); } } @@ -3129,7 +3118,8 @@ magic(void) * 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), sp->name, level); + "zu zaubern.", unitname(u), + spell_name(sp, u->faction->locale), level); addmessage(0, u->faction, buf, MSG_MAGIC, ML_INFO); } } @@ -3146,7 +3136,8 @@ magic(void) force = spellpower(target_r, u, sp, level); if (force < 1) { sprintf(buf, "%s schafft es nicht genügend Kraft aufzubringen " - "um %s dennoch zu zaubern.", unitname(u), sp->name); + "um %s dennoch zu zaubern.", unitname(u), + spell_name(sp, u->faction->locale)); addmessage(0, u->faction, buf, MSG_MAGIC, ML_MISTAKE); continue; } @@ -3178,7 +3169,8 @@ magic(void) 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), sp->name); + "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 */ } @@ -3237,3 +3229,21 @@ create_special_direction(region *r, int x, int y, int duration, return a; } + +const char * +spell_info(const struct spell * sp, const struct locale * lang) +{ + if (sp->info==NULL) { + return LOC(lang, mkname("spellinfo", sp->sname)); + } + return sp->info; +} + +const char * +spell_name(const struct spell * sp, const struct locale * lang) +{ + if (sp->info==NULL) { + return LOC(lang, mkname("spell", sp->sname)); + } + return sp->sname; +} \ No newline at end of file diff --git a/src/common/kernel/magic.h b/src/common/kernel/magic.h index d73652278..029cc0813 100644 --- a/src/common/kernel/magic.h +++ b/src/common/kernel/magic.h @@ -145,8 +145,8 @@ struct spell_ptr { typedef struct spell { spellid_t id; - const char *name; - const char *beschreibung; + const char *sname; + const char *info; const char *syntax; const char *parameter; magic_t magietyp; @@ -285,7 +285,7 @@ boolean is_familiar(const struct unit *u); /* gibt true, wenn eine Familiar-Relation besteht. */ /* Sprüche */ -spell *find_spellbyname(struct unit *u, char *s); +spell *find_spellbyname(struct unit *u, char *s, const struct locale * lang); /* versucht einen Spruch über den Namen zu identifizieren, gibt * ansonsten NULL zurück */ spell *find_spellbyid(spellid_t i); @@ -402,4 +402,7 @@ extern struct attrib *create_special_direction(struct region *r, int x, int y, i extern struct plane * astral_plane; +extern const char * spell_info(const struct spell * sp, const struct locale * lang); +extern const char * spell_name(const struct spell * sp, const struct locale * lang); + #endif diff --git a/src/common/kernel/message.c b/src/common/kernel/message.c index 56d125257..b3dfdb71a 100644 --- a/src/common/kernel/message.c +++ b/src/common/kernel/message.c @@ -385,6 +385,7 @@ new_message(struct faction * receiver, const char* sig, ...) void * args[16]; memset(args, 0, sizeof(args)); + assert(signature-sig < sizeof(buffer)); strnzcpy(buffer, sig, signature-sig); mtype = mt_find(buffer); diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c index 2203ef62d..07b4a3581 100644 --- a/src/common/kernel/movement.c +++ b/src/common/kernel/movement.c @@ -903,6 +903,14 @@ travel(region * first, unit * u, region * next, int flucht) unit *ut, *u2; int gereist = 0; static direction_t route[MAXSPEED]; + static boolean init = false; + static const curse_type * speed_ct; + static const curse_type * fogtrap_ct; + if (!init) { + init = true; + speed_ct = ct_find("speed"); + fogtrap_ct = ct_find("fogtrap"); + } /* tech: * @@ -959,8 +967,8 @@ travel(region * first, unit * u, region * next, int flucht) dk = u->race->speed; - { - curse *c = get_curse(u->attribs, C_SPEED, 0); + if (speed_ct) { + curse *c = get_curse(u->attribs, speed_ct); if(c) { int men = get_cursedmen(u, c); dk *= 1.0 + (double)men/(double)u->number; @@ -1051,7 +1059,7 @@ travel(region * first, unit * u, region * next, int flucht) if (k<0) break; /* r2 -> Zielregion, r3 -> Momentane Region */ if (move_blocked(u, current, reldirection(current, next)) - || is_spell_active(current, C_FOGTRAP)) + || curse_active(get_curse(current->attribs, fogtrap_ct))) { ADDMSG(&u->faction->msgs, msg_message("leavefail", "unit region", u, next)); @@ -1064,19 +1072,21 @@ travel(region * first, unit * u, region * next, int flucht) wache)); break; } - if (is_spell_active(next, C_ANTIMAGICZONE) && fval(u->race, RCF_ILLUSIONARY)) { - change_cursevigour(&next->attribs, C_ANTIMAGICZONE, 0, - u->number); - - add_message(&u->faction->msgs, new_message(u->faction, - "illusionantimagic%u:unit", u)); - destroy_unit(u); - - return route; + + if (fval(u->race, RCF_ILLUSIONARY)) { + curse * c = get_curse(next->attribs, ct_find("antimagiczone")); + if (curse_active(c)) { + curse_changevigour(&next->attribs, c, - u->number); + add_message(&u->faction->msgs, new_message(u->faction, + "illusionantimagic%u:unit", u)); + destroy_unit(u); + return route; + } } /* Ozeanfelder können nur von Einheiten mit Schwimmen und ohne * Pferde betreten werden. Drachen können fliegen. */ - if(rterrain(next) == T_OCEAN && !canswim(u)) { + if (rterrain(next) == T_OCEAN && !canswim(u)) { plane *pl = getplane(next); if(pl && fval(pl, PFL_NOCOORDS)) { add_message(&u->faction->msgs, new_message(u->faction, @@ -1363,6 +1373,12 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan region *rv[MAXSPEED + 1]; region *tt[MAXSPEED + 1]; /* travelthru */ static direction_t route[MAXSPEED+1]; /* route[i] := direction from tt[i] to tt[i-1] */ + static boolean init = false; + static const curse_type * fogtrap_ct; + if (!init) { + init = true; + fogtrap_ct = ct_find("fogtrap"); + } if (!ship_ready(starting_point, u)) return NULL; @@ -1449,7 +1465,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan /* Falls Blockade, endet die Seglerei hier */ if (move_blocked(u, current_point, reldirection(current_point, next_point)) - || is_spell_active(current_point, C_FOGTRAP)) { + || curse_active(get_curse(current_point->attribs, fogtrap_ct))) { add_message(&u->faction->msgs, new_message(u->faction, "sailfail%h:ship%r:region", u->ship, current_point)); break; @@ -1967,10 +1983,17 @@ destroy_damaged_ships(void) boolean is_disorientated(unit *u) { - if(u->ship && get_curse(u->ship->attribs, C_DISORIENTATION, 0)) + static boolean init = false; + static const curse_type * shipconf_ct, * regconf_ct; + if (!init) { + init = true; + regconf_ct = ct_find("disorientationzone"); + shipconf_ct = ct_find("shipdisorientation"); + } + if (u->ship && curse_active(get_curse(u->ship->attribs, shipconf_ct))) return true; - if(is_spell_active(u->region, C_REGCONF)) + if (curse_active(get_curse(u->region->attribs, regconf_ct))) return true; return false; diff --git a/src/common/kernel/region.c b/src/common/kernel/region.c index 38b2fa5d7..0586ec4ba 100644 --- a/src/common/kernel/region.c +++ b/src/common/kernel/region.c @@ -1029,7 +1029,7 @@ production(const region *r) { /* muß r->terrain sein, nicht rterrain() wegen rekursion */ int p = terrain[r->terrain].production_max; - if (is_spell_active(r, C_DROUGHT)) p /= 2; + if (curse_active(get_curse(r->attribs, ct_find("drought")))) p /= 2; return p; } diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c index 4bad54c90..5ce593966 100644 --- a/src/common/kernel/reports.c +++ b/src/common/kernel/reports.c @@ -34,6 +34,7 @@ #include "ship.h" #include "skill.h" #include "unit.h" +#include "spell.h" #include "plane.h" #ifdef USE_UGROUPS # include "ugroup.h" @@ -373,7 +374,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode) }else{ scat(", "); } - scat(sp->name); + scat(spell_name(sp, f->locale)); } } dh = 0; @@ -395,7 +396,7 @@ bufunit(const faction * f, const unit * u, int indent, int mode) sp = get_combatspell(u,i); if (sp) { int sl; - scat(sp->name); + scat(spell_name(sp, u->faction->locale)); if((sl = get_combatspelllevel(u,i)) > 0) { scat(" ("); icat(sl); @@ -736,7 +737,7 @@ spy_message(int spy, unit *u, unit *target) } else { scat(", "); } - scat(sp->name); + scat(spell_name(sp, u->faction->locale)); } if (found == 0) { scat("Keine"); diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 86312b583..eb5739e69 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -435,7 +435,7 @@ static faction * factionorders(void) { char b[16]; - char * fid = strnzcpy(b, getstrtoken(), 16); + char * fid = strnzcpy(b, getstrtoken(), 15); char * pass = getstrtoken(); faction *f; @@ -1353,11 +1353,11 @@ writegame(char *path, char quiet) /* ------------------------------------------------------------- */ void -curse_write(const attrib * a,FILE * f) { +curse_write(const attrib * a, FILE * f) { int flag; int mage_no; curse * c = (curse*)a->data.v; - curse_type * ct = c->type; + const curse_type * ct = c->type; flag = (c->flag & ~(CURSE_ISNEW)); @@ -1367,45 +1367,39 @@ curse_write(const attrib * a,FILE * f) { mage_no = -1; } - fprintf(f, "%d %d %d %d %d %d %d ", c->no, (int)ct->cspellid, flag, + fprintf(f, "%d %s %d %d %d %d %d ", c->no, ct->cname, flag, c->duration, c->vigour, mage_no, c->effect); - switch(c->type->typ){ - case CURSETYP_UNIT: - { - curse_unit * cc = (curse_unit*)c->data; - fprintf(f, "%d ", cc->cursedmen); - break; - } - case CURSETYP_SKILL: - { - curse_skill * cc = (curse_skill*)c->data; - fprintf(f, "%d %d ", (int)cc->skill, cc->cursedmen); - break; - } - case CURSETYP_NORM: - default: - break; + if (c->type->write) c->type->write(f, c); + else if (c->type->typ == CURSETYP_UNIT) { + curse_unit * cc = (curse_unit*)c->data; + fprintf(f, "%d ", cc->cursedmen); } } int curse_read(attrib * a, FILE * f) { - int cspellid; int mageid; curse * c = (curse*)a->data.v; - curse_type * ct; + const curse_type * ct; - if (global.data_version < CURSE_NO_VERSION){ - fscanf(f, "%d %d %d %d %d %d ",&cspellid, &c->flag, &c->duration, - &c->vigour, &mageid, &c->effect); - c->no = newunitid(); + if (global.data_version >= CURSETYPE_VERSION) { + char cursename[64]; + fscanf(f, "%d %s %d %d %d %d %d ", &c->no, cursename, &c->flag, + &c->duration, &c->vigour, &mageid, &c->effect); + ct = ct_find(cursename); } else { - fscanf(f, "%d %d %d %d %d %d %d ", &c->no, &cspellid, &c->flag, + int cspellid; + if (global.data_version < CURSE_NO_VERSION) { + fscanf(f, "%d %d %d %d %d %d ",&cspellid, &c->flag, &c->duration, + &c->vigour, &mageid, &c->effect); + c->no = newunitid(); + } else { + fscanf(f, "%d %d %d %d %d %d %d ", &c->no, &cspellid, &c->flag, &c->duration, &c->vigour, &mageid, &c->effect); + } + ct = ct_find(oldcursename(cspellid)); } - - ct = find_cursetype((curse_t)cspellid); assert(ct!=NULL); c->type = ct; @@ -1418,28 +1412,12 @@ curse_read(attrib * a, FILE * f) { ur_add((void*)mageid, (void**)&c->magician, resolve_unit); } - switch(c->type->typ){ - case 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 = cc; - fscanf(f, "%d ", &cc->cursedmen); - break; - } - case CURSETYP_SKILL: - { - curse_skill * cc = calloc(1, sizeof(curse_skill)); - int skill; - - c->data = cc; - fscanf(f, "%d %d ", &skill, &cc->cursedmen); - cc->skill = (skill_t)skill; - break; - } - case CURSETYP_NORM: - default: - break; + c->data = cc; + fscanf(f, "%d ", &cc->cursedmen); } chash(c); diff --git a/src/common/kernel/spell.c b/src/common/kernel/spell.c index 18632d124..b06af1e1e 100644 --- a/src/common/kernel/spell.c +++ b/src/common/kernel/spell.c @@ -56,6 +56,7 @@ #include #include #include +#include #include /* libc includes */ @@ -169,6 +170,7 @@ magicanalyse_region(region *r, unit *mage, int force) { attrib *a; boolean found = false; + const struct locale * lang = mage->faction->locale; for (a=r->attribs;a;a=a->next) { curse * c; @@ -186,14 +188,14 @@ magicanalyse_region(region *r, unit *mage, int force) found = true; if(rand()%100 < chance){ /* Analyse geglückt */ - if(c->flag & CURSE_NOAGE){ + if(c->flag & CURSE_NOAGE) { add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_region_noage%u:mage%r:region%s:spell", - mage, r, c->type->name)); + mage, r, LOC(lang, c->type->cname))); }else{ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_region_age%u:mage%r:region%s:spell%i:months", - mage, r, c->type->name, mon)); + mage, r, LOC(lang, c->type->cname), mon)); } } else { add_message(&mage->faction->msgs, new_message(mage->faction, @@ -211,6 +213,7 @@ magicanalyse_unit(unit *u, unit *mage, int force) { attrib *a; boolean found = false; + const struct locale * lang = mage->faction->locale; for (a=u->attribs;a;a=a->next) { curse * c; @@ -229,11 +232,11 @@ magicanalyse_unit(unit *u, unit *mage, int force) if(c->flag & CURSE_NOAGE){ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_unit_noage%u:mage%u:unit%s:spell", - mage, u, c->type->name)); + mage, u, LOC(lang, c->type->cname))); }else{ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_unit_age%u:mage%u:unit%s:spell%i:months", - mage, u, c->type->name, mon)); + mage, u, LOC(lang, c->type->cname), mon)); } } else { add_message(&mage->faction->msgs, new_message(mage->faction, @@ -251,6 +254,7 @@ magicanalyse_building(building *b, unit *mage, int force) { attrib *a; boolean found = false; + const struct locale * lang = mage->faction->locale; for (a=b->attribs;a;a=a->next) { curse * c; @@ -269,11 +273,11 @@ magicanalyse_building(building *b, unit *mage, int force) if(c->flag & CURSE_NOAGE){ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_building_age%u:mage%b:building%s:spell", - mage, b, c->type->name)); + mage, b, LOC(lang, c->type->cname))); }else{ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_building_age%u:mage%b:building%s:spell%i:months", - mage, b, c->type->name, mon)); + mage, b, LOC(lang, c->type->cname))); } } else { add_message(&mage->faction->msgs, new_message(mage->faction, @@ -292,6 +296,7 @@ magicanalyse_ship(ship *sh, unit *mage, int force) { attrib *a; boolean found = false; + const struct locale * lang = mage->faction->locale; for (a=sh->attribs;a;a=a->next) { curse * c; @@ -310,11 +315,11 @@ magicanalyse_ship(ship *sh, unit *mage, int force) if(c->flag & CURSE_NOAGE){ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_ship_noage%u:mage%h:ship%s:spell", - mage, sh, c->type->name)); + mage, sh, LOC(lang, c->type->cname))); }else{ add_message(&mage->faction->msgs, new_message(mage->faction, "analyse_ship_age%u:mage%h:ship%s:spell", - mage, sh, c->type->name, mon)); + mage, sh, LOC(lang, c->type->cname))); } } else { add_message(&mage->faction->msgs, new_message(mage->faction, @@ -387,7 +392,7 @@ destroy_curse(attrib **alist, int cast_level, int force, c1 = (curse*)a->data.v; /* Immunität prüfen */ - if (c1->flag & CURSE_IMMUN) { + if (c1->flag & CURSE_IMMUNE) { do { ap = &(*ap)->next; } while (*ap && a->type==(*ap)->type); continue; } @@ -850,7 +855,7 @@ sp_goodwinds(castorder *co) /* keine Probleme mit C_SHIP_SPEEDUP und C_SHIP_FLYING */ /* NODRIFT bewirkt auch +1 Geschwindigkeit */ - create_curse(mage, &sh->attribs, C_SHIP_NODRIFT, 0, power, cast_level, 0, 0); + create_curse(mage, &sh->attribs, ct_find("nodrift"), power, cast_level, 0, 0); /* melden, 1x pro Partei */ freset(mage->faction, FL_DH); @@ -908,7 +913,7 @@ sp_magicstreet(castorder *co) } /* wirkt schon in der Zauberrunde! */ - create_curse(mage, &r->attribs, C_MAGICSTREET, 0, power, cast_level, 0, 0); + create_curse(mage, &r->attribs, ct_find("magicstreet"), power, cast_level, 0, 0); /* melden, 1x pro Partei */ { @@ -1056,6 +1061,7 @@ sp_maelstrom(castorder *co) region *r = co->rt; unit *mage = (unit *)co->magician; int cast_level = co->level; + curse * c; int power = co->force; if(rterrain(r) != T_OCEAN) { @@ -1067,8 +1073,8 @@ sp_maelstrom(castorder *co) /* Attribut auf Region. * Existiert schon ein curse, so wird dieser verstärkt * (Max(Dauer), Max(Stärke))*/ - create_curse(mage,&mage->attribs,C_MAELSTROM,0,power,power,power,0); - set_curseflag(r->attribs, C_MAELSTROM, 0, CURSE_ISNEW); + c = create_curse(mage, &mage->attribs, ct_find("maelstrom"), power, power, power,0); + curse_setflag(c, CURSE_ISNEW); /* melden, 1x pro Partei */ { @@ -1150,8 +1156,7 @@ sp_blessedharvest(castorder *co) /* Attribut auf Region. * Existiert schon ein curse, so wird dieser verstärkt * (Max(Dauer), Max(Stärke))*/ - create_curse(mage,&r->attribs,C_BLESSEDHARVEST,0,power,power,1,0); - + create_curse(mage,&r->attribs, ct_find("blessedharvest"), power, power, 1, 0); { message * seen = msg_message("harvest_effect", "mage", mage); message * unseen = msg_message("harvest_effect", "mage", NULL); @@ -1192,7 +1197,7 @@ sp_hain(castorder *co) return 0; } - trees = lovar(force * 10 * RESOURCE_QUANTITY) + force; + trees = lovar((int)(force * 10 * RESOURCE_QUANTITY)) + force; #if GROWING_TREES rsettrees(r, 1, rtrees(r,1) + trees); #else @@ -1239,7 +1244,7 @@ sp_mallornhain(castorder *co) return 0; } - trees = lovar(force * 10 * RESOURCE_QUANTITY) + force; + trees = lovar((int)(force * 10 * RESOURCE_QUANTITY)) + force; #if GROWING_TREES rsettrees(r, 1, rtrees(r,1) + trees); #else @@ -1431,7 +1436,7 @@ sp_kaelteschutz(castorder *co) men = u->number; } - create_curse(mage, &u->attribs, C_KAELTESCHUTZ, 0, cast_level, + create_curse(mage, &u->attribs, ct_find("insectfur"), cast_level, duration, 1, men); force -= u->number; @@ -1477,7 +1482,7 @@ sp_sparkle(castorder *co) if(pa->param[0]->flag == TARGET_RESISTS) return cast_level; u = pa->param[0]->data.u; - create_curse(mage, &u->attribs, C_SPARKLE, 0, cast_level, + create_curse(mage, &u->attribs, ct_find("sparkle"), cast_level, cast_level, rand(), u->number); add_message(&mage->faction->msgs, new_message(mage->faction, @@ -1531,7 +1536,7 @@ sp_create_irongolem(castorder *co) return 0; } - u2 = create_unit(r, mage->faction, max(1,force*8*RESOURCE_QUANTITY), new_race[RC_IRONGOLEM], 0, + u2 = create_unit(r, mage->faction, max(1,(int)(force*8*RESOURCE_QUANTITY)), new_race[RC_IRONGOLEM], 0, LOC(mage->faction->locale, rc_name(new_race[RC_IRONGOLEM], 1)), mage); set_level(u2, SK_ARMORER, 1); @@ -1592,7 +1597,7 @@ sp_create_stonegolem(castorder *co) return 0; } - u2 = create_unit(r, mage->faction, max(1,force*5*RESOURCE_QUANTITY), new_race[RC_STONEGOLEM], 0, + u2 = create_unit(r, mage->faction, max(1,(int)(force*5*RESOURCE_QUANTITY)), new_race[RC_STONEGOLEM], 0, LOC(mage->faction->locale, rc_name(new_race[RC_STONEGOLEM], 1)), mage); set_level(u2, SK_ROAD_BUILDING, 1); set_level(u2, SK_BUILDING, 1); @@ -1668,7 +1673,7 @@ sp_great_drought(castorder *co) rsethorses(r, rhorses(r)/2); /* Arbeitslohn = 1/4 */ - create_curse(mage, &r->attribs, C_DROUGHT, 0, force, 1, 4, 0); + create_curse(mage, &r->attribs, ct_find("drought"), force, 1, 4, 0); /* terraforming */ if (rand() % 100 < 25){ @@ -2042,13 +2047,14 @@ sp_holyground(castorder *co) unit *mage = (unit *)co->magician; int cast_level = co->level; int power = co->force; + curse * c; message * msg = r_addmessage(r, mage->faction, msg_message("holyground", "mage", mage)); msg_release(msg); - create_curse(mage, &r->attribs, C_HOLYGROUND, 0, - power*power, 1, 0, 0); + c = create_curse(mage, &r->attribs, ct_find("holyground"), + power*power, 1, 0, 0); - set_curseflag(mage->region->attribs, C_HOLYGROUND, 0, CURSE_NOAGE); + curse_setflag(c, CURSE_NOAGE); a_removeall(&r->attribs, &at_deathcount); @@ -2072,7 +2078,7 @@ static int sp_homestone(castorder *co) { unit *u; - curse * success; + curse * c; region *r = co->rt; unit *mage = (unit *)co->magician; int cast_level = co->level; @@ -2083,23 +2089,20 @@ sp_homestone(castorder *co) return 0; } - success = create_curse(mage, &mage->building->attribs, C_MAGICSTONE, 0, + c = create_curse(mage, &mage->building->attribs, ct_find("magicstone"), force*force, 1, 0, 0); - if(!success) { + if (c==NULL) { cmistake(mage, strdup(co->order), 206, MSG_MAGIC); return 0; } - set_curseflag(mage->building->attribs, C_MAGICSTONE, 0, CURSE_NOAGE); - - /* Nur ein Heimstein pro Burg möglich */ - set_curseflag(mage->building->attribs, C_MAGICSTONE, 0, CURSE_ONLYONE); + curse_setflag(c, CURSE_NOAGE|CURSE_ONLYONE); /* Magieresistenz der Burg erhöht sich um 50% */ - create_curse(mage, &mage->building->attribs, C_RESIST_MAGIC, 0, - force*force, 1, 50, 0); - set_curseflag(mage->building->attribs, C_RESIST_MAGIC, 0, CURSE_NOAGE); + c = create_curse(mage, &mage->building->attribs, + ct_find("magicresistance"), force*force, 1, 50, 0); + curse_setflag(c, CURSE_NOAGE); /* melden, 1x pro Partei in der Burg */ for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); @@ -2169,8 +2172,8 @@ sp_drought(castorder *co) * hoch (evtl dauert dann die Duerre laenger). Ansonsten volle * Auswirkungen. */ - c = get_curse(r->attribs, C_DROUGHT, 0); - if(c) { + c = get_curse(r->attribs, ct_find("drought")); + if (c) { c->vigour = max(c->vigour, power); c->duration = max(c->duration, power); } else { @@ -2184,7 +2187,7 @@ sp_drought(castorder *co) #endif rsethorses(r, rhorses(r)/2); - create_curse(mage, &r->attribs, C_DROUGHT, 0, power, power, 4, 0); + create_curse(mage, &r->attribs, ct_find("drought"), power, power, 4, 0); } return cast_level; } @@ -2221,6 +2224,7 @@ sp_fog_of_confusion(castorder *co) rl = all_in_range(r, range); for(rl2 = rl; rl2; rl2 = rl2->next) { + curse * c; if(rterrain(rl2->region) != T_OCEAN && !r_isforest(rl2->region)) continue; @@ -2230,10 +2234,10 @@ sp_fog_of_confusion(castorder *co) continue; } - create_curse(mage, &rl2->region->attribs, C_REGCONF,0, - power, duration, cast_level*5, 0); + c = create_curse(mage, &rl2->region->attribs, + ct_find("disorientationzone"), power, duration, cast_level*5, 0); /* Soll der schon in der Zauberrunde wirken? */ - set_curseflag(rl2->region->attribs, C_REGCONF, 0, CURSE_ISNEW); + curse_setflag(c, CURSE_ISNEW); for (u = rl2->region->units; u; u = u->next) freset(u->faction, FL_DH); for(u = rl2->region->units; u; u = u->next ) { @@ -2360,7 +2364,7 @@ sp_stormwinds(castorder *co) } /* Duration = 1, nur diese Runde */ - create_curse(mage, &sh->attribs, C_SHIP_SPEEDUP, 0, power, 1, 0, 0); + create_curse(mage, &sh->attribs, ct_find("stormwind"), power, 1, 0, 0); /* Da der Spruch nur diese Runde wirkt, brauchen wir kein * set_cursedisplay() zu benutzten - es sieht eh niemand... */ erfolg++; @@ -2685,6 +2689,7 @@ sp_fumblecurse(castorder *co) unit *mage = (unit *)co->magician; int cast_level = co->level; int force = co->force; + curse * c; spellparameter *pa = co->par; /* wenn kein Ziel gefunden, Zauber abbrechen */ @@ -2698,14 +2703,14 @@ sp_fumblecurse(castorder *co) effect = force/2; - if (create_curse(mage, &target->attribs, C_FUMBLE, 0, - force, duration+1, effect, 0) == NULL) - { + c = create_curse(mage, &target->attribs, ct_find("fumble"), + force, duration+1, effect, 0); + if (c == NULL) { report_failure(mage, co->order); return 0; } - set_curseflag(target->attribs, C_FUMBLE, 0, CURSE_ONLYONE); + curse_setflag(c, CURSE_ONLYONE); add_message(&target->faction->msgs, new_message(target->faction, "fumblecurse%u:unit%r:region", target, target->region)); @@ -2719,16 +2724,17 @@ patzer_fumblecurse(castorder *co) int cast_level = co->level; int force = co->force; int effect; + curse * c; effect = force/2; - if (create_curse(mage, &mage->attribs, C_FUMBLE, 0, force, - (cast_level/2)+1, effect, 0)) - { + c = create_curse(mage, &mage->attribs, ct_find("fumble"), force, + (cast_level/2)+1, effect, 0); + if (c!=NULL) { add_message(&mage->faction->msgs, new_message(mage->faction, "magic_fumble%u:unit%r:region%s:command", mage, mage->region, strdup(co->order))); - set_curseflag(mage->attribs, C_FUMBLE, 0, CURSE_ONLYONE); + curse_setflag(c, CURSE_ONLYONE); } return; } @@ -2862,7 +2868,7 @@ wall_vigour(curse* c, int delta) } const curse_type ct_firewall = { - C_DUMMY, "Feuerwand", + "Feuerwand", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR | NO_MERGE), "Eine Feuerwand blockiert die Ein- und Ausreise", NULL, /* curseinfo */ @@ -3575,6 +3581,7 @@ sp_chaossuction(castorder *co) static int sp_magicboost(castorder *co) { + curse * c; unit *mage = (unit *)co->magician; int cast_level = co->level; int power = co->force; @@ -3584,17 +3591,18 @@ sp_magicboost(castorder *co) report_failure(mage, co->order); return 0; } - /* (magier, attribut, curseid, id2, power, duration, effect, men) */ - create_curse(mage, &mage->attribs, C_MBOOST, 0, power, 10, 6, 1); - create_curse(mage, &mage->attribs, C_AURA, 0, power, 4, 200, 1); + + c = create_curse(mage, &mage->attribs, ct_find("magicboost"), power, 10, 6, 1); + /* kann nicht durch Antimagie beeinflusst werden */ + curse_setflag(c, CURSE_IMMUNE); + + c = create_curse(mage, &mage->attribs, ct_find("aura"), power, 4, 200, 1); { - trigger * tsummon = trigger_createcurse(mage, mage, C_AURA, 0, power, 6, 50, 1); + trigger * tsummon = trigger_createcurse(mage, mage, c->type, power, 6, 50, 1); add_trigger(&mage->attribs, "timer", trigger_timeout(5, tsummon)); } - /* kann nicht durch Antimagie beeinflusst werden */ - set_curseflag(mage->attribs, C_MBOOST, 0, CURSE_IMMUN); add_message(&mage->faction->msgs, new_message(mage->faction, "magicboost_effect%u:unit%r:region%s:command", @@ -3851,7 +3859,7 @@ sp_babbler(castorder *co) * * Wirkung: * Zeigt die Verzauberungen eines Objekts an (curse->name, - * cures->info). Aus der Differenz Spruchstärke und Curse->vigour + * curse::info). Aus der Differenz Spruchstärke und Curse->vigour * ergibt sich die Chance den Spruch zu identifizieren ((force - * c->vigour)*10 + 100 %). * @@ -3902,7 +3910,7 @@ sp_analysesong_obj(castorder *co) * Gebiet: Cerddor * Wirkung: * Zeigt die Verzauberungen eines Objekts an (curse->name, - * cures->info). Aus der Differenz Spruchstärke und Curse->vigour + * curse::info). Aus der Differenz Spruchstärke und Curse->vigour * ergibt sich die Chance den Spruch zu identifizieren ((force - * c->vigour)*10 + 100 %). * @@ -4014,7 +4022,7 @@ sp_charmingsong(castorder *co) add_trigger(&mage->faction->attribs, "destroy", trigger_killunit(target)); } /* sperre ATTACKIERE, GIB PERSON und überspringe Migranten */ - create_curse(mage, &target->attribs, C_SLAVE, 0, force, duration, 0, 0); + create_curse(mage, &target->attribs, ct_find("slavery"), force, duration, 0, 0); /* setze Partei um und lösche langen Befehl aus Sicherheitsgründen */ u_setfaction(target,mage->faction); @@ -4054,7 +4062,7 @@ sp_song_resistmagic(castorder *co) int force = co->force; - create_curse(mage, &r->attribs, C_SONG_GOODMR, 0, + create_curse(mage, &r->attribs, ct_find("goodmagicresistancezone"), force, force, mr_bonus, 0); /* Erfolg melden */ @@ -4084,7 +4092,7 @@ sp_song_susceptmagic(castorder *co) int cast_level = co->level; int force = co->force; - create_curse(mage, &r->attribs, C_SONG_BADMR, 0, + create_curse(mage, &r->attribs, ct_find("badmagicresistancezone"), force, force, mr_malus, 0); add_message(&mage->faction->msgs, new_message(mage->faction, @@ -4203,7 +4211,7 @@ sp_raisepeasantmob(castorder *co) a->data.ca[1] = 15; /* 15% */ a_add(&u->attribs, a); - create_curse(mage, &r->attribs, C_RIOT, 0, cast_level, anteil, 0, 0); + create_curse(mage, &r->attribs, ct_find("riotzone"), cast_level, anteil, 0, 0); for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); for (u = r->units; u; u = u->next ) { @@ -4264,7 +4272,8 @@ sp_migranten(castorder *co) /* Keine Monstereinheiten */ if (!playerrace(target->race)){ - sprintf(buf, "%s kann nicht auf Monster gezaubert werden.", sp->name); + sprintf(buf, "%s kann nicht auf Monster gezaubert werden.", + spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_EVENT, ML_WARN); return 0; } @@ -4281,7 +4290,7 @@ sp_migranten(castorder *co) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': So viele Personen übersteigen " "meine Kräfte.", unitname(mage), regionid(mage->region), - sp->name); + spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_WARN); } @@ -4324,7 +4333,8 @@ sp_migranten(castorder *co) if (kontaktiert == 0){ sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Die Einheit %s hat keinen " "Kontakt mit uns aufgenommen.", unitname(mage), - regionid(mage->region), sp->name, unitname(target)); + regionid(mage->region), spell_name(sp, mage->faction->locale) + , unitname(target)); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -4362,7 +4372,7 @@ sp_song_of_peace(castorder *co) else duration = lovar(force/2); - create_curse(mage,&r->attribs,C_PEACE,0,force,duration,1,0); + create_curse(mage,&r->attribs, ct_find("peacezone"), force, duration, 1,0); for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); for (u = r->units; u; u = u->next ) { @@ -4409,7 +4419,7 @@ sp_generous(castorder *co) addmessage(0, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } - create_curse(mage,&r->attribs,C_GENEROUS,0,force,force,2,0); + create_curse(mage,&r->attribs, ct_find("generous"), force,force,2,0); for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); for (u = r->units; u; u = u->next ) { @@ -4509,7 +4519,8 @@ sp_pump(castorder *co) target = pa->param[0]->data.u; /* Zieleinheit */ if (fval(target->race, RCF_UNDEAD)) { - sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", sp->name); + sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", + spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_EVENT, ML_WARN); return 0; } @@ -4579,7 +4590,8 @@ sp_seduce(castorder *co) target = pa->param[0]->data.u; /* Zieleinheit */ if (fval(target->race, RCF_UNDEAD)) { - sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", sp->name); + sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", + spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_WARN); return 0; } @@ -4669,6 +4681,7 @@ static int sp_calm_monster(castorder *co) { int duration; + curse * c; unit *target; region *r = co->rt; unit *mage = (unit *)co->magician; @@ -4685,18 +4698,20 @@ sp_calm_monster(castorder *co) target = pa->param[0]->data.u; /* Zieleinheit */ if (fval(target->race, RCF_UNDEAD)) { - sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", sp->name); + sprintf(buf, "%s kann nicht auf Untote gezaubert werden.", + spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_WARN); return 0; } - if (!create_curse(mage, &target->attribs, C_CALM, 0, force, duration, - mage->faction->unique_id, 0)){ + c = create_curse(mage, &target->attribs, ct_find("calmmonster"), force, duration, + mage->faction->unique_id, 0); + if (c==NULL) { report_failure(mage, co->order); return 0; } /* Nur ein Beherrschungszauber pro Unit */ - set_curseflag(target->attribs, C_CALM, 0, CURSE_ONLYONE); + curse_setflag(c, CURSE_ONLYONE); sprintf(buf, "%s besänftigt %s.", unitname(mage), unitname(target)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_INFO); @@ -4858,7 +4873,7 @@ sp_depression(castorder *co) int cast_level = co->level; int power = co->force; - create_curse(mage,&r->attribs,C_DEPRESSION,0,power,power,0,0); + create_curse(mage,&r->attribs, ct_find("depression"), power, power, 0, 0); for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); for (u = r->units; u; u = u->next ) { @@ -4948,18 +4963,14 @@ sp_songofAttraction(castorder *co) { region *r = co->rt; /* Zauberregion */ unit *mage = (unit *)co->magician; - unit *u; int cast_level = co->level; - int power = co->force; - region *rn; - faction *f; - int range; + /* int power = co->force; */ /* TODO Wander Effekt */ add_message(&mage->faction->msgs, new_message(mage->faction, "summon%u:unit%r:region%s:command%u:unit%r:region", - mage, mage->region, strdup(co->order),mage, co->rt)); + mage, mage->region, strdup(co->order),mage, r)); return cast_level; } @@ -5172,7 +5183,7 @@ sp_readmind(castorder *co) * Kosten: SPC_FIX * Wirkung: * Zeigt die Verzauberungen eines Objekts an (curse->name, - * cures->info). Aus der Differenz Spruchstärke und Curse->vigour + * curse::info). Aus der Differenz Spruchstärke und Curse->vigour * ergibt sich die Chance den Spruch zu identifizieren ((force - * c->vigour)*10 + 100 %). */ @@ -5196,7 +5207,7 @@ sp_analyseregionsdream(castorder *co) * Kosten: SPC_FIX * Wirkung: * Zeigt die Verzauberungen eines Objekts an (curse->name, - * cures->info). Aus der Differenz Spruchstärke und Curse->vigour + * curse::info). Aus der Differenz Spruchstärke und Curse->vigour * ergibt sich die Chance den Spruch zu identifizieren ((force - * c->vigour)*10 + 100 %). */ @@ -5242,6 +5253,7 @@ sp_baddreams(castorder *co) int cast_level = co->level; int power = co->force; region *r = co->rt; + curse * c; /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, * also duration+2 */ @@ -5249,8 +5261,8 @@ sp_baddreams(castorder *co) duration = 2 + rand()%duration; /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ - create_curse(mage, &r->attribs, C_GBDREAM, 0, power, duration, -1, 0); - set_curseflag(r->attribs, C_GBDREAM, 0, CURSE_ISNEW); + c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, -1, 0); + curse_setflag(c, CURSE_ISNEW); /* Erfolg melden*/ add_message(&mage->faction->msgs, new_message(mage->faction, @@ -5276,6 +5288,7 @@ int sp_gooddreams(castorder *co) { int duration; + curse * c; region *r = co->rt; unit *mage = (unit *)co->magician; int cast_level = co->level; @@ -5285,8 +5298,8 @@ sp_gooddreams(castorder *co) * also duration+2 */ duration = max(1, power/2); /* Stufe 1 macht sonst mist */ duration = 2 + rand()%duration; - create_curse(mage, &r->attribs, C_GBDREAM, 0, power, duration, 1, 0); - set_curseflag(r->attribs, C_GBDREAM, 0, CURSE_ISNEW); + c = create_curse(mage, &r->attribs, ct_find("gbdream"), power, duration, 1, 0); + curse_setflag(c, CURSE_ISNEW); /* Erfolg melden*/ add_message(&mage->faction->msgs, new_message(mage->faction, @@ -5392,7 +5405,6 @@ sp_dreamreading(castorder *co) int sp_sweetdreams(castorder *co) { - unit *u; region *r = co->rt; unit *mage = (unit *)co->magician; int cast_level = co->level; @@ -5404,12 +5416,13 @@ sp_sweetdreams(castorder *co) /* Schleife über alle angegebenen Einheiten */ for (n = 0; n < pa->length; n++) { + curse * c; + unit *u; /* sollte nie negativ werden */ - if (opfer < 1) - break; + if (opfer < 1) break; - if(pa->param[n]->flag == TARGET_RESISTS - || pa->param[n]->flag == TARGET_NOTFOUND) + if (pa->param[n]->flag == TARGET_RESISTS || + pa->param[n]->flag == TARGET_NOTFOUND) continue; /* Zieleinheit */ @@ -5419,8 +5432,8 @@ sp_sweetdreams(castorder *co) opfer -= men; /* Nichts machen als ein entsprechendes Attribut an die Einheit legen. */ - create_curse(mage,&u->attribs,C_ORC,0,power,duration,5,men); - set_curseflag(u->attribs, C_ORC, 0, CURSE_ISNEW); + c = create_curse(mage,&u->attribs, ct_find("orcish"), power,duration,5,men); + curse_setflag(c, CURSE_ISNEW); sprintf(buf, "%s verschafft %s ein interessanteres Nachtleben.", unitname(mage), unitname(u)); @@ -5449,9 +5462,8 @@ sp_disturbingdreams(castorder *co) unit *mage = (unit *)co->magician; int cast_level = co->level; int power = co->force; - - create_curse(mage, &r->attribs, C_BADLEARN, 0, power, power/6, 10, 0); - set_curseflag(r->attribs, C_BADLEARN, 0, CURSE_ISNEW); + curse * c = create_curse(mage, &r->attribs, ct_find("badlearn"), power, power/6, 10, 0); + curse_setflag(c, CURSE_ISNEW); sprintf(buf, "%s sorgt für schlechten Schlaf in %s.", unitname(mage), regionid(r)); @@ -5475,17 +5487,17 @@ sp_dream_of_confusion(castorder *co) rl = all_in_range(r, range); for(rl2 = rl; rl2; rl2 = rl2->next) { - + curse * c; /* Magieresistenz jeder Region prüfen */ if (target_resists_magic(mage, rl2->region, TYP_REGION, 0)){ report_failure(mage, co->order); continue; } - create_curse(mage, &rl2->region->attribs, C_REGCONF,0, - power, duration, cast_level*5, 0); + c = create_curse(mage, &rl2->region->attribs, + ct_find("disorientationzone"), power, duration, cast_level*5, 0); /* soll der Zauber schon in der Zauberrunde wirken? */ - set_curseflag(rl2->region->attribs, C_REGCONF, 0, CURSE_ISNEW); + curse_setflag(c, CURSE_ISNEW); for (u = rl2->region->units; u; u = u->next) freset(u->faction, FL_DH); for (u = rl2->region->units; u; u = u->next ) { @@ -5517,7 +5529,7 @@ sp_dream_of_confusion(castorder *co) * * Wirkung: * Zeigt die Verzauberungen eines Objekts an (curse->name, - * cures->info). Aus der Differenz Spruchstärke und Curse->vigour + * curse::info). Aus der Differenz Spruchstärke und Curse->vigour * ergibt sich die Chance den Spruch zu identifizieren ((force - * c->vigour)*10 + 100 %). * @@ -5589,7 +5601,7 @@ sp_itemcloak(castorder *co) /* Zieleinheit */ target = pa->param[0]->data.u; - create_curse(mage,&target->attribs,C_ITEMCLOAK,0,power,power,0,0); + create_curse(mage,&target->attribs, ct_find("itemcloak"), power,power,0,0); add_message(&mage->faction->msgs, new_message(mage->faction, "itemcloak%u:mage%u:target", mage, target)); @@ -5647,8 +5659,8 @@ sp_resist_magic_bonus(castorder *co) m = min(u->number,opfer); opfer -= m; - create_curse(mage, &u->attribs, C_MAGICRESISTANCE, 0, power, duration, - resistbonus, m); + create_curse(mage, &u->attribs, ct_find("magicresistance"), + power, duration, resistbonus, m); sprintf(buf, "%s wird kurz von einem magischen Licht umhüllt.", unitname(u)); @@ -5695,7 +5707,7 @@ sp_enterastral(castorder *co) default: sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Dieser Zauber funktioniert " "nur in der materiellen Welt.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -5703,7 +5715,7 @@ sp_enterastral(castorder *co) if(!rt) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Es kann hier kein Kontakt zur " "Astralwelt hergestellt werden.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -5712,7 +5724,7 @@ sp_enterastral(castorder *co) is_cursed(ro->attribs, C_ASTRALBLOCK, 0)) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Es kann kein Kontakt zu " "dieser astralen Region hergestellt werden.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -5818,7 +5830,7 @@ sp_pullastral(castorder *co) if(!rl2) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Es kann kein Kontakt zu " "dieser Region hergestellt werden.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); free_regionlist(rl); return 0; @@ -5828,7 +5840,7 @@ sp_pullastral(castorder *co) default: sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Dieser Zauber funktioniert " "nur in der astralen Welt.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -5837,7 +5849,7 @@ sp_pullastral(castorder *co) is_cursed(ro->attribs, C_ASTRALBLOCK, 0)) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Es kann kein Kontakt zu " "dieser Region hergestellt werden.", unitname(mage), - regionid(mage->region),sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(r, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; } @@ -6346,8 +6358,8 @@ sp_disruptastral(castorder *co) } /* Kontakt unterbinden */ - create_curse(mage,&rl2->region->attribs,C_ASTRALBLOCK,0,power,power/3, - 100, 0); + create_curse(mage,&rl2->region->attribs, ct_find("astralblock"), + power, power/3, 100, 0); addmessage(r, 0, "Mächtige Magie verhindert den Kontakt zur Realität.", MSG_COMMENT, ML_IMPORTANT); } @@ -6391,7 +6403,7 @@ static int sp_eternizewall(castorder *co) { unit *u; - curse * success; + curse * c; building *b; region *r = co->rt; unit *mage = (unit *)co->magician; @@ -6403,18 +6415,15 @@ sp_eternizewall(castorder *co) if(pa->param[0]->flag == TARGET_NOTFOUND) return 0; b = pa->param[0]->data.b; - success = create_curse(mage, &b->attribs, C_NOCOST, 0, - power*power, 1, 0, 0); + c = create_curse(mage, &b->attribs, ct_find("nocost"), + power*power, 1, 0, 0); - if(!success){ /* ist bereits verzaubert */ + if(c==NULL) { /* ist bereits verzaubert */ cmistake(mage, strdup(co->order), 206, MSG_MAGIC); return 0; } - set_curseflag(b->attribs, C_NOCOST, 0, CURSE_NOAGE); - - /* Nur einmal pro Burg möglich */ - set_curseflag(b->attribs, C_NOCOST, 0, CURSE_ONLYONE); + curse_setflag(c, CURSE_NOAGE|CURSE_ONLYONE); /* melden, 1x pro Partei in der Burg */ for (u = r->units; u; u = u->next) freset(u->faction, FL_DH); @@ -6521,7 +6530,8 @@ sp_movecastle(castorder *co) if(dir == NODIRECTION) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Ungültige Richtung %s.", - unitname(mage), regionid(mage->region), sp->name, + unitname(mage), regionid(mage->region), + spell_name(sp, mage->faction->locale), pa->param[1]->data.s); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return 0; @@ -6530,7 +6540,7 @@ sp_movecastle(castorder *co) if(b->size > (cast_level-12) * 250) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Der Elementar ist " "zu klein, um das Gebäude zu tragen.", unitname(mage), - regionid(mage->region), sp->name); + regionid(mage->region), spell_name(sp, mage->faction->locale)); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return cast_level; } @@ -6540,7 +6550,8 @@ sp_movecastle(castorder *co) if(!(terrain[target_region->terrain].flags & LAND_REGION)) { sprintf(buf, "%s in %s: 'ZAUBER \"%s\"': Der Erdelementar " "weigert sich, nach %s zu gehen.", - unitname(mage), regionid(mage->region), sp->name, + unitname(mage), regionid(mage->region), + spell_name(sp, mage->faction->locale), locale_string(mage->faction->locale, directions[dir])); addmessage(0, mage->faction, buf, MSG_MAGIC, ML_MISTAKE); return cast_level; @@ -6624,7 +6635,7 @@ sp_flying_ship(castorder *co) /* mit C_SHIP_NODRIFT haben wir kein Problem */ /* Duration = 1, nur diese Runde */ - create_curse(mage, &sh->attribs, C_SHIP_FLYING, 0, power, 1, 0, 0); + create_curse(mage, &sh->attribs, ct_find("flyingship"), power, 1, 0, 0); /* Da der Spruch nur diese Runde wirkt, brauchen wir kein * set_cursedisplay() zu benutzten - es sieht eh niemand... */ @@ -6766,7 +6777,7 @@ sp_antimagiczone(castorder *co) /* Reduziert die Stärke jedes Spruchs um effect */ effect = cast_level; - create_curse(mage, &r->attribs, C_ANTIMAGICZONE, 0, power, force, + create_curse(mage, &r->attribs, ct_find("antimagiczone"), power, force, effect, 0); /* Erfolg melden*/ @@ -6809,8 +6820,8 @@ sp_antimagiczone(castorder *co) * "kc" */ -int -sp_antimagicshild(castorder *co) +static int +sp_magicrunes(castorder *co) { int duration; unit *mage = (unit *)co->magician; @@ -6827,7 +6838,7 @@ sp_antimagicshild(castorder *co) b = pa->param[0]->data.b; /* Magieresistenz der Burg erhöht sich um 20% */ - create_curse(mage, &b->attribs, C_RESIST_MAGIC, 0, force, + create_curse(mage, &b->attribs, ct_find("magicrunes"), force, duration, 20, 0); /* Erfolg melden */ @@ -6841,7 +6852,7 @@ sp_antimagicshild(castorder *co) ship *sh; sh = pa->param[0]->data.sh; /* Magieresistenz des Schiffs erhöht sich um 20% */ - create_curse(mage, &sh->attribs, C_RESIST_MAGIC, 0, force, + create_curse(mage, &sh->attribs, ct_find("magicrunes"), force, duration, 20, 0); /* Erfolg melden */ @@ -6892,7 +6903,7 @@ sp_speed2(castorder *co) u = pa->param[n]->data.u; men = min(maxmen,u->number); - create_curse(mage, &u->attribs, C_SPEED, 0, force, dur, 2, men); + create_curse(mage, &u->attribs, ct_find("speed"), force, dur, 2, men); maxmen -= men; used += men; } @@ -7082,7 +7093,7 @@ sp_destroy_curse(castorder *co) c->vigour = max(0, succ); if(succ <= 0) { - remove_cursec(ap, c); + remove_curse(ap, c); add_message(&mage->faction->msgs, new_message(mage->faction, "destroy_magic_effect%u:unit%r:region%s:command%i:id%s:target", @@ -7440,10 +7451,8 @@ spell spelldaten[] = /* M_DRUIDE */ - {SPL_BLESSEDHARVEST, "Segen der Erde", - "Dieses Ernteritual verbessert die Erträge der arbeitenden Bauern in der " - "Region um ein Silberstück. Je mehr Kraft der Druide investiert, desto " - "länger wirkt der Zauber.", + {SPL_BLESSEDHARVEST, "blessedharvest", + NULL, NULL, NULL, M_DRUIDE, @@ -7459,12 +7468,8 @@ spell spelldaten[] = patzer }, - {SPL_GWYRRD_EARN_SILVER, "Viehheilung", - "Die Fähigkeiten der Gwyrrd-Magier in der Viehzucht und Heilung sind bei " - "den Bauern sehr begehrt. Grade auf Märkten sind ihre Dienste häufig sehr " - "gefragt. Manch einer mag auch sein Talent dazu nutzen, ein Tier für einen " - "besseren Preis zu verkaufen. Pro Stufe kann der Magier so 50 Silber " - "verdienen.", + {SPL_GWYRRD_EARN_SILVER, "veterinarian", + NULL, NULL, NULL, M_DRUIDE, @@ -10253,7 +10258,7 @@ spell spelldaten[] = {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, - (spell_f)sp_antimagicshild, patzer + (spell_f)sp_magicrunes, patzer }, diff --git a/src/common/kernel/spell.h b/src/common/kernel/spell.h index 84842d6a8..16dac45a7 100644 --- a/src/common/kernel/spell.h +++ b/src/common/kernel/spell.h @@ -266,4 +266,5 @@ typedef struct wall_data { extern struct attrib_type at_cursewall; extern struct attrib_type at_unitdissolve; + #endif diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index 0f1175f99..ea8fd0db6 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -951,43 +951,44 @@ item_modification(const unit *u, skill_t sk, int val) static int att_modification(const unit *u, skill_t sk) { - curse *c; - unit *mage; + int bonus = 0, malus = 0; + attrib * a; int result = 0; + static boolean init = false; + static const curse_type * skillmod_ct; + static const curse_type * gbdream_ct; + if (!init) { + init = true; + skillmod_ct = ct_find("skillmod"); + gbdream_ct = ct_find("gbdream"); + } result += get_curseeffect(u->attribs, C_ALLSKILLS, 0); - result += get_curseeffect(u->attribs, C_SKILL, (int)sk); + if (skillmod_ct) { + curse * c = get_cursex(u->attribs, skillmod_ct, (void*)(int)sk, cmp_cursedata); + result += curse_geteffect(c); + } /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurückgegen wird, wir aber alle * durchsuchen und aufaddieren müssen */ - if (is_cursed(u->region->attribs, C_GBDREAM, 0)){ - attrib *a; - int bonus = 0, malus = 0; - int mod; - - a = a_select(u->region->attribs, packids(C_GBDREAM, 0), cmp_oldcurse); - while(a) { - c = (curse*)a->data.v; - mage = c->magician; - mod = c->effect; - /* wir suchen jeweils den größten Bonus und den größten Malus */ - if (mod > 0 - && (mage == NULL - || allied(mage, u->faction, HELP_GUARD))) - { - if (mod > bonus ) bonus = mod; - - } else if (mod < 0 - && (mage == NULL - || !allied(mage, u->faction, HELP_GUARD))) - { - if (mod < malus ) malus = mod; - } - a = a_select(a->next, packids(C_GBDREAM, 0), cmp_oldcurse); + a = a_select(u->region->attribs, gbdream_ct, cmp_cursetype); + while (a) { + curse * c = (curse*)a->data.v; + int mod = c->effect; + unit * mage = c->magician; + /* wir suchen jeweils den größten Bonus und den größten Malus */ + if (mod>0 && (mage==NULL || allied(mage, u->faction, HELP_GUARD))) + { + if (mod > bonus ) bonus = mod; + } else if (mod < 0 && + (mage == NULL || !allied(mage, u->faction, HELP_GUARD))) + { + if (mod < malus ) malus = mod; } - result = result + bonus + malus; + a = a_select(a->next, gbdream_ct, cmp_cursetype); } + result = result + bonus + malus; return result; } diff --git a/src/common/modules/modules.dsp b/src/common/modules/modules.dsp index 74b071c5e..0249629e4 100644 --- a/src/common/modules/modules.dsp +++ b/src/common/modules/modules.dsp @@ -118,6 +118,10 @@ SOURCE=.\weather.h # End Source File # Begin Source File +SOURCE=.\xecmd.h +# End Source File +# Begin Source File + SOURCE=.\xmas.h # End Source File # Begin Source File @@ -163,6 +167,10 @@ SOURCE=.\weather.c # End Source File # Begin Source File +SOURCE=.\xecmd.c +# End Source File +# Begin Source File + SOURCE=.\xmas.c # End Source File # Begin Source File diff --git a/src/common/spells/alp.c b/src/common/spells/alp.c index ffd3c4288..6e04ec711 100644 --- a/src/common/spells/alp.c +++ b/src/common/spells/alp.c @@ -156,11 +156,11 @@ alp_findet_opfer(unit *alp, region *r) */ a_removeall(&alp->attribs, &at_eventhandler); /* Alp umwandeln in Curse */ - c = create_curse(mage, &opfer->attribs, C_ALLSKILLS, 0, 0, 0, -2, opfer->number); + c = create_curse(mage, &opfer->attribs, ct_find("worse"), 0, 0, -2, opfer->number); /* solange es noch keine spezielle alp-Antimagie gibt, reagiert der * auch auf normale */ /* set_curseflag(opfer->attribs, C_ALLSKILLS, 0, CURSE_NOAGE+CURSE_IMMUN); */ - set_curseflag(opfer->attribs, C_ALLSKILLS, 0, CURSE_NOAGE); + curse_setflag(c, CURSE_NOAGE); destroy_unit(alp); { diff --git a/src/common/spells/spells.c b/src/common/spells/spells.c index a5d6ba47f..6de8662dc 100644 --- a/src/common/spells/spells.c +++ b/src/common/spells/spells.c @@ -26,18 +26,13 @@ struct curse_type; extern const struct curse_type ct_firewall; extern void ct_register(const struct curse_type * ct); -extern curse_type cursedaten[MAXCURSE]; void register_spells(void) { - int i; /* sp_summon_alp */ register_alp(); /* init_firewall(); */ ct_register(&ct_firewall); - - for (i=0;i!=MAXCURSE;++i) { - ct_register(&cursedaten[i]); - } + register_curses(); } diff --git a/src/common/triggers/createcurse.c b/src/common/triggers/createcurse.c index 72c61f059..f14981358 100644 --- a/src/common/triggers/createcurse.c +++ b/src/common/triggers/createcurse.c @@ -39,8 +39,7 @@ typedef struct createcurse_data { struct unit * mage; struct unit * target; - curse_t id; - int id2; + const curse_type * type; int vigour; int duration; int effect; @@ -68,7 +67,7 @@ createcurse_handle(trigger * t, void * data) createcurse_data * td = (createcurse_data*)t->data.v; if (td->mage!=NULL && td->target!=NULL) { create_curse(td->mage, &td->target->attribs, - td->id, td->id2, td->vigour, td->duration, td->effect, td->men); + td->type, td->vigour, td->duration, td->effect, td->men); } else { log_error(("could not perform createcurse::handle()\n")); } @@ -82,7 +81,7 @@ createcurse_write(const trigger * t, FILE * F) createcurse_data * td = (createcurse_data*)t->data.v; fprintf(F, "%s ", itoa36(td->mage->no)); fprintf(F, "%s ", itoa36(td->target->no)); - fprintf(F, "%d %d %d %d %d %d ", td->id, td->id2, td->vigour, td->duration, td->effect, td->men); + fprintf(F, "%s %d %d %d %d ", td->type->cname, td->vigour, td->duration, td->effect, td->men); } static int @@ -102,7 +101,15 @@ createcurse_read(trigger * t, FILE * F) td->target = findunit(i); if (td->target==NULL) ur_add((void*)i, (void**)&td->target, resolve_unit); - fscanf(F, "%d %d %d %d %d %d ", &td->id, &td->id2, &td->vigour, &td->duration, &td->effect, &td->men); + if (global.data_versionvigour, &td->duration, &td->effect, &td->men); + assert(id2==0); + td->type = ct_find(oldcursename(id1)); + } else { + fscanf(F, "%s %d %d %d %d ", zText, &td->vigour, &td->duration, &td->effect, &td->men); + td->type = ct_find(zText); + } return AT_READ_OK; } @@ -117,15 +124,14 @@ trigger_type tt_createcurse = { trigger * trigger_createcurse(struct unit * mage, struct unit * target, - curse_t id, int id2, int vigour, int duration, - int effect, int men) + const curse_type * ct, int vigour, int duration, + int effect, int men) { trigger * t = t_new(&tt_createcurse); createcurse_data * td = (createcurse_data*)t->data.v; td->mage = mage; td->target = target; - td->id = id; - td->id2 = id2; + td->type = ct; td->vigour = vigour; td->duration = duration; td->effect = effect; diff --git a/src/common/triggers/createcurse.h b/src/common/triggers/createcurse.h index c434b9683..930fe4c14 100644 --- a/src/common/triggers/createcurse.h +++ b/src/common/triggers/createcurse.h @@ -16,6 +16,7 @@ #define CREATECURSE_H /* all types we use are defined here to reduce dependencies */ +struct curse_type; struct trigger_type; struct trigger; struct region; @@ -24,6 +25,6 @@ struct unit; extern struct trigger_type tt_createcurse; -extern struct trigger * trigger_createcurse(struct unit * mage, struct unit * target, curse_t id, int id2, int vigour, int duration, int effect, int men); +extern struct trigger * trigger_createcurse(struct unit * mage, struct unit * target, const struct curse_type * ct, int vigour, int duration, int effect, int men); #endif diff --git a/src/common/util/language.h b/src/common/util/language.h index 1cc2cdd2d..8c0cfef0d 100644 --- a/src/common/util/language.h +++ b/src/common/util/language.h @@ -28,7 +28,7 @@ extern unsigned int locale_hashkey(const struct locale * lang); extern const char * locale_name(const struct locale * lang); extern const char * reverse_lookup(const struct locale * lang, const char * str); -extern const char * mkname(const char * name, const char * space); +extern const char * mkname(const char * namespc, const char * key); extern void debug_language(const char * log); diff --git a/src/eressea/main.c b/src/eressea/main.c index 4f3a18a19..706cd264e 100644 --- a/src/eressea/main.c +++ b/src/eressea/main.c @@ -610,8 +610,8 @@ main(int argc, char *argv[]) game_init(); #if defined(BETA_CODE) /* xml_writeships(); */ - xml_writebuildings(); - /* xml_writeitems("items.xml"); */ + /* xml_writebuildings(); */ + xml_writeitems("items.xml"); return 0; #endif diff --git a/src/res/de/strings.xml b/src/res/de/strings.xml index fd16a4a38..ab41b9f81 100644 --- a/src/res/de/strings.xml +++ b/src/res/de/strings.xml @@ -10,32 +10,32 @@ Tresen counter - + wenige few - + viele many - + relativ viele rather many - + sehr wenige very few - + sehr viele a great many - + Dunkel dark @@ -1172,10 +1172,12 @@ Feuerwerke - Lebkuchenherz mit der Aufschrift 'Erz und Stein, das ist fein' + Lebkuchenherz mit der Aufschrift 'Erz und + Stein, das ist fein' - Lebkuchenherzen mit der Aufschrift 'Erz und Stein, das ist fein' + Lebkuchenherzen mit der Aufschrift 'Erz und + Stein, das ist fein' Achatener Schlüssel @@ -1551,7 +1553,7 @@ ZAUBER - + XETRANK @@ -2158,7 +2160,9 @@ beschädigt - Unglücklicherweise wurde deine Partei ausgelöscht. Du kannst gerne an einer anderen Stelle wieder einsteigen. Melde Dich einfach wieder an. + Unglücklicherweise wurde deine Partei + ausgelöscht. Du kannst gerne an einer anderen Stelle wieder + einsteigen. Melde Dich einfach wieder an. Talente @@ -2200,16 +2204,23 @@ report newbie info - Deine Partei hat letzte Runde keinen Zug abgegeben! + Deine Partei hat letzte Runde keinen Zug + abgegeben! - Im Mistelzweig ruht eine magische Kraft - besonderer Art. Der Anwender wird von seinen Feinden in Frieden - gelassen, eine Woche lang läßt jeder Kämpfer ihn unbeschadet + Im Mistelzweig ruht eine magische + Kraft + besonderer Art. Der Anwender wird von seinen Feinden + in Frieden + gelassen, eine Woche lang läßt jeder Kämpfer ihn + unbeschadet seines Weges ziehen. - The magical misteltoe has a wonderous property: It's use will make one person able to escape unharmed from every conflict, no enemy will lay hand on the bearer for one week. + The magical misteltoe has a + wonderous property: It's use will make one person able + to escape unharmed from every conflict, no enemy will + lay hand on the bearer for one week. @@ -3011,7 +3022,7 @@ Schattendrachen shadow dragon - + Todesflatter darkbat @@ -3028,7 +3039,7 @@ Todesflatter darkbat - + Alptraum nightmare @@ -3045,7 +3056,7 @@ Alptraum nightmare - + Nachteinhorn vampiric unicorn @@ -3300,7 +3311,7 @@ Altork oldorc - + Snotling snotling @@ -3317,7 +3328,7 @@ Snotling snotling - + Ork orc @@ -3409,4 +3420,44 @@ exhausted + + + Segen der Erde + Blessed Harvest + + + Viehheilung + Cattle Healing + + + + + Dieses Ernteritual verbessert die + Erträge der arbeitenden Bauern in der Region um ein + Silberstück. Je mehr Kraft der Druide investiert, + desto länger wirkt der Zauber. + This harvest ritual increases the + income of each working peasant by one silver piece. + The more power the druid invests, the longer the spell + lasts. + + + Die Fähigkeiten der Gwyrrd-Magier in + der Viehzucht und Heilung sind bei den Bauern sehr + begehrt. Grade auf Märkten sind ihre Dienste häufig + sehr gefragt. Manch einer mag auch sein Talent dazu + nutzen, ein Tier für einen besseren Preis zu + verkaufen. Pro Stufe kann der Magier so 50 Silber + verdienen. + The abilities of the mages of Gwyrrd + concerning the breeding and healing of cattle are + highly appreciated among the peasants. Especially at + the markets, their services are demanded frequently. + Some of them also use their talents to sell an animal + at a higher price. A mage can earn 50 silver pieces + per level in this way. + + + +