/* vi: set ts=2: * * Eressea PB(E)M host Copyright (C) 1998-2000 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) * Henning Peters (faroul@beyond.kn-bremen.de) * Enno Rehling (enno@eressea-pbem.de) * Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de) * * based on: * * Atlantis v1.0 13 September 1993 Copyright 1993 by Russell Wallace * Atlantis v1.7 Copyright 1996 by Alex Schröder * * This program may not be used, modified or distributed without * prior permission by the authors of Eressea. * This program may not be sold or used commercially without prior written * permission from the authors. */ #include #include #include #include /* gamecode includes */ #include #include /* kernel includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* util includes */ #include #include #include #include #include #include /* libc includes */ #include #include #include /* attributes includes */ #include #include extern void reorder_owners(struct region * r); static void verify_owners(boolean bOnce) { region * r; for (r=regions;r;r=r->next) { unit * u; boolean bFail = false; for (u=r->units;u;u=u->next) { if (u->building) { unit * bo = buildingowner(r, u->building); if (!fval(bo, FL_OWNER)) { log_error(("[verify_owners] %u ist Besitzer von %s, hat aber FL_OWNER nicht.\n", unitname(bo), buildingname(u->building))); bFail = true; if (bOnce) break; } if (bo!=u && fval(u, FL_OWNER)) { log_error(("[verify_owners] %u ist NICHT Besitzer von %s, hat aber FL_OWNER.\n", unitname(u), buildingname(u->building))); bFail = true; if (bOnce) break; } } if (u->ship) { unit * bo = shipowner(r, u->ship); if (!fval(bo, FL_OWNER)) { log_error(("[verify_owners] %u ist Besitzer von %s, hat aber FL_OWNER nicht.\n", unitname(bo), shipname(u->ship))); bFail = true; if (bOnce) break; } if (bo!=u && fval(u, FL_OWNER)) { log_error(("[verify_owners] %u ist NICHT Besitzer von %s, hat aber FL_OWNER.\n", unitname(u), shipname(u->ship))); bFail = true; if (bOnce) break; } } } if (bFail) reorder_owners(r); } } static void fix_skills(void) { int magic; char zText[128]; FILE * F = fopen("skills.fix", "r+"); if (F==NULL) return; fprintf(stderr, "==-------------==\n"); fprintf(stderr, " Fixing skills \n"); fprintf(stderr, "==-------------==\n"); fscanf(F, "%s", zText); magic = atoi36(zText); { /* check for magic key */ attrib * a = a_find(global.attribs, &at_key); /* make sure that this is done only once! */ while (a && a->data.i!=magic) a=a->next; if (a) { log_warning(("[fix_skills] function was called a second time\n")); return; } a_add(&global.attribs, a_new(&at_key))->data.i = magic; } for (;;) { int from, self, teach, skill; int myskill, change, number; unit * u; if (fscanf(F, "%s %d %d %d %d %d\n", zText, &skill, &number, &from, &self, &teach)<=0) break; u = findunit(atoi36(zText)); if (u==NULL) { log_warning(("[fix_skills] unit %s not found!\n", zText)); continue; } myskill = get_skill(u, (skill_t)skill); if (myskill < from+self) { /* todesfälle oder orkvermehrung führen zu veränderungen */ change = (teach * myskill) / (from + teach); } else change = teach; change_skill(u, (skill_t)skill, change); } } /* make sure that this is done only once! */ #define do_once(magic, fun) \ { \ attrib * a = a_find(global.attribs, &at_key); \ while (a && a->data.i!=(magic)) a=a->next; \ if (a) { \ log_warning(("[do_once] a unique fix %d=\"%s\" was called a second time\n", magic, itoa36(magic))); \ } else { \ (fun); \ a_add(&global.attribs, make_key(magic)); \ } \ } #if 0 static void fix_vertrautenmagie(void) { region *r; for(r=regions; r; r=r->next) { unit *u; for(u=r->units;u;u=u->next) { sc_mage *m = get_mage(u); if (m != NULL) { /* Vertraute und Monster haben alle Magiegebiet M_GRAU */ if (m->magietyp != M_GRAU) continue; switch(u->race) { case RC_PSEUDODRAGON: if(!getspell(u, SPL_FLEE)) addspell(u, SPL_FLEE); if(!getspell(u, SPL_SLEEP)) addspell(u, SPL_SLEEP); if(!getspell(u, SPL_FRIGHTEN)) addspell(u, SPL_FRIGHTEN); break; case RC_NYMPH: if(!getspell(u, SPL_SEDUCE)) addspell(u, SPL_SEDUCE); if(!getspell(u, SPL_CALM_MONSTER)) addspell(u, SPL_CALM_MONSTER); if(!getspell(u, SPL_SONG_OF_CONFUSION)) addspell(u, SPL_SONG_OF_CONFUSION); if(!getspell(u, SPL_DENYATTACK)) addspell(u, SPL_DENYATTACK); break; case RC_UNICORN: if(!getspell(u, SPL_RESISTMAGICBONUS)) addspell(u, SPL_RESISTMAGICBONUS); if(!getspell(u, SPL_SONG_OF_PEACE)) addspell(u, SPL_SONG_OF_PEACE); if(!getspell(u, SPL_CALM_MONSTER)) addspell(u, SPL_CALM_MONSTER); if(!getspell(u, SPL_HERO)) addspell(u, SPL_HERO); if(!getspell(u, SPL_HEALINGSONG)) addspell(u, SPL_HEALINGSONG); if(!getspell(u, SPL_DENYATTACK)) addspell(u, SPL_DENYATTACK); break; case RC_WRAITH: if(!getspell(u, SPL_STEALAURA)) addspell(u, SPL_STEALAURA); if(!getspell(u, SPL_FRIGHTEN)) addspell(u, SPL_FRIGHTEN); if(!getspell(u, SPL_SUMMONUNDEAD)) addspell(u, SPL_SUMMONUNDEAD); break; case RC_IMP: if(!getspell(u, SPL_STEALAURA)) addspell(u, SPL_STEALAURA); break; case RC_DREAMCAT: if(!getspell(u, SPL_ILL_SHAPESHIFT)) addspell(u, SPL_ILL_SHAPESHIFT); if(!getspell(u, SPL_TRANSFERAURA_TRAUM)) addspell(u, SPL_TRANSFERAURA_TRAUM); break; case RC_FEY: if(!getspell(u, SPL_DENYATTACK)) addspell(u, SPL_DENYATTACK); if(!getspell(u, SPL_CALM_MONSTER)) addspell(u, SPL_CALM_MONSTER); if(!getspell(u, SPL_SEDUCE)) addspell(u, SPL_SEDUCE); break; /* kein break, ein Wyrm hat alle Drachensprüche */ case RC_WYRM: if(!getspell(u, SPL_WYRMODEM)) addspell(u, SPL_WYRMODEM); case RC_DRAGON: if(!getspell(u, SPL_DRAGONODEM)) addspell(u, SPL_DRAGONODEM); case RC_FIREDRAGON: case RC_SEASERPENT: if(!getspell(u, SPL_FIREDRAGONODEM)) addspell(u, SPL_FIREDRAGONODEM); break; } } } } } #endif #if 0 static void addunitsilver(unit * u, int count, int mode) { if (mode) change_money(u, count * u->number); else u->money = count * u->number; } static void addunititems(unit * u, int count, char item, int mode) { if (mode) change_item(u, item, count * u->number); else set_item(u, item, count * u->number); } static void addfactionsilver(faction * f, int count, int mode) { unit * u; for (u=f->units;u;u=u->nextF) { addunitsilver(u, count, mode); } } static void addfactionitems(faction * f, int count, char item, int mode) { unit * u; for (u=f->units;u;u=u->nextF) { addunititems(u, count, item, mode); } } static void showallspells(void) { faction * f; for (f=factions;f;f=f->next) { if (f->no==MONSTER_FACTION) continue; a_removeall(&f->attribs, &at_seenspell); } } static void add_magrathea(void) { unit * tans = ufindhash(atoi36("tans")); if (tans) u_setfaction(tans, findfaction(999)); } #endif #ifdef XMAS #include "race.h" #include "movement.h" static void santa_comes_to_town(void) { unit * santa = ufindhash(atoi36("xmas")); unit * tans = ufindhash(atoi36("tans")); faction * f; region * r; if (!tans) r = findregion(0,0); else r = tans->region; if (!r) return; while (santa && santa->race!=RC_ILLUSION) { uunhash(santa); santa->no = newunitid(); uhash(santa); santa = ufindhash(atoi36("xmas")); } if (!santa) { santa = createunit(r, findfaction(MONSTER_FACTION), 1, RC_ILLUSION); uunhash(santa); santa->no = atoi36("xmas"); uhash(santa); } santa->age = 2; santa->irace = RC_DAEMON; set_string(&santa->name, "Ein dicker Gnom mit einem Rentierschlitten"); set_string(&santa->display, "hat: 6 Rentiere, Schlitten, Sack mit Geschenken, Kekse für Khorne"); fset(santa, FL_TRAVELTHRU); for (f=factions;f;f=f->next) { unit * u; runit *ru; region * r; item_t i = (item_t) (rand() % 4 + I_KEKS); unit * senior = f->units; for (u = f->units; u; u=u->nextF) { if (senior->age < u->age) senior = u; } if (!senior) continue; r = senior->region; sprintf(buf, "%s gibt %d %s an %s.", unitname(santa), 1, itemdata[i].name[0], unitname(senior)); change_item(senior, i, 1); addmessage(r, senior->faction, buf, MSG_COMMERCE, ML_INFO); sprintf(buf, "von %s: 'Ho ho ho. Frohe Weihnachten, und %s für %s.'", unitname(santa), itemdata[i].name[1], unitname(senior)); addmessage(r, 0, buf, MSG_MESSAGE, ML_IMPORTANT); for (ru = r->durchgezogen; ru ; ru=ru->next) if (ru->unit==santa) break; if (!ru) { ru = calloc(1, sizeof(runit)); ru->next = r->durchgezogen; ru->unit = santa; r->durchgezogen = ru; } } } #endif #if 0 static void init_hp(void) { region *r; unit *u; for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { if (u->hp == -1) { u->hp = unit_max_hp(u) * u->number; } } } } static void convert(int x, int y, int *nx, int *ny) { *ny = -y; *nx = x + (y + ((y>=0)?1:0))/2; } #endif #if 0 static void loesche_coasts(void) { region *r; ship *sh; for(r=regions;r;r=r->next) { for(sh=r->ships;sh;sh=sh->next) { sh->coast = NODIRECTION; } } } #endif #if 0 static void create_underworld(void) { int x, y; region *r; attrib *a; plane * hell = create_new_plane(-1, "Hölle", 100000, 100000, 100020, 100020, PFL_NOCOORDS); for(x=0;x<=20;x++) { for(y=0;y<=20;y++) { r = new_region(x+100000,y); r->planep = hell; if(x==0 || x == 20 || y == 0 || y == 20) { rsetterrain(r, T_FIREWALL); } else { rsetterrain(r, T_HELL); } } } /* Verbindungen schaffen */ a = create_special_direction(findregion(4,4),100005,5,-1, "Ein dunkler Schlund fuehrt in die Tiefe der Erde", "Schlund"); a = create_special_direction(findregion(100005,5),4,4,-1, "Ein hell erleuchteter Tunnel fuehrt nach oben", "Tunnel"); } #endif #if 0 static void bename_dracoide(void) { region *r; unit *u; for(r=regions;r;r=r->next) { for(u=r->units;u;u=u->next) { if(u->race == RC_DRACOID) name_unit(u); } } } #endif #if 0 static void repair_illusion(void) { region * r; for (r=regions;r;r=r->next) { unit * u; for (u=r->units;u;u=u->next) { if (!race[u->race].nonplayer && (get_item(u, I_PLATE_ARMOR) == u->number || get_item(u, I_CHAIN_MAIL) == u->number) && get_item(u, I_HORSE) == u->number && get_skill(u, SK_SPEAR) == 0 && get_skill(u, SK_SWORD) == 0 && (get_item(u, I_SWORD) == u->number || get_item(u, I_SPEAR) == u->number)) { int i = 0; skill_t sk; for (sk=0;sk!=MAXSKILLS;++sk) if (sk!=SK_RIDING) i+=get_skill(u, sk); if (get_skill(u, SK_OBSERVATION) == i) u->race=RC_SPELL; else if (i) continue; else { u->race = RC_ILLUSION; log_puts("[repair_illusion] repariert: %s in Partei %s\n", unitname(u), factionid(u->faction)); } } if(!race[u->race].nonplayer && ( strcmp(u->name, "Ausgemergelte Skelette") == 0 || strcmp(u->name, "Zerfallende Zombies") == 0 || strcmp(u->name, "Keuchende Ghoule") == 0 )) { u->race = RC_UNDEAD; u->irace = RC_UNDEAD; } } } } #endif #if 0 typedef struct border_info { border_type * type; region * from; direction_t dir; attrib * attribs; } border_info; static void * resolve_border(void * data) { border_info * info = (border_info *)data; region * to = rconnect(info->from, info->dir); if (!to) fprintf(stderr, "WARNING: border can only exist between two regions\n"); else { border * b = new_border(info->type, info->from, to); b->attribs = info->attribs; } free(data); return NULL; } #endif #if 0 static void repair_undead(void) { int no, age; FILE * f = fopen("undeads", "rt"); if (!f) return; while (fscanf(f, "%d %d\n", &no, &age)!=EOF) { unit * u = findunitg(no, NULL); if (u && (u->race!=RC_UNDEAD || u->irace != RC_UNDEAD)) { if (u->age>=age) u->race = u->irace = RC_UNDEAD; fprintf(stderr, "Repariere %s\n", unitname(u)); } } } #endif #if 0 static void reset_dragon_irace(void) { region *r; unit *u; for(r=regions;r;r=r->next) { for(u=r->units;u;u=u->next) { if(u->race == RC_DRAGON || u->race == RC_WYRM) { u->irace = u->race; } } } } #endif #if 0 static void fix_irace(void) { region *r; unit *u; for(r=regions; r; r=r->next) { for(u=r->units; u; u=u->next) { if(u->race != u->irace && u->race <= RC_AQUARIAN && u->race!=RC_DAEMON) u->irace = u->race; } } } #endif #if 0 static void fix_regions(void) { region * r; for (r=regions;r;r=r->next) { if (r->terrain!=T_GLACIER && r->terrain!=T_MOUNTAIN) { rsetiron(r, 0); } if (r->terrain==T_OCEAN) { unit * u; rsethorses(r, 0); rsetmoney(r, 0); rsetpeasants(r, 0); rsettrees(r, 0); for (u=r->units;u;u=u->next) if (humanoid(u) && u->ship==NULL) set_number(u, 0); } } } #endif #if 0 static void read_herbrepair(void) { FILE * f = fopen("repair.herbs", "rt"); if (!f) return; while (!feof(f)) { int n, x; unit * u; fscanf(f, "%d %d", &n, &x); u = findunitg(x, NULL); if (!u) u = findunitg(n, NULL); fscanf(f, "%d", &x); while (x!=-1) { fscanf(f, "%d", &n); if (u) change_herb(u, (herb_t)x, n); fscanf(f, "%d", &x); } } fclose(f); } static void write_herbrepair(void) { FILE * f = fopen("repair.herbs", "wt"); region * r; for (r=regions;r;r=r->next) { unit * u; for (u=r->units;u;u=u->next) { strlist * o; for (o=u->orders;o;o=o->next) { if (igetkeyword(o->s)==K_GIVE) { int n = read_unitid(u->faction, r); herb_t h; if (n<0) continue; if (getparam()==P_HERBS) { fprintf(f, "%d %d ", u->no, n); for (h=0;h!=MAXHERBS;++h) { int i = get_herb(u, h); if (i) fprintf(f, "%d %d ", h, i); } fputs("-1\n", f); } } } } } fclose(f); } #endif #if 0 static void write_migrepair(void) { FILE * f = fopen("repair.migrants", "wt"); region * r; for (r=regions;r;r=r->next) { if(rterrain(r) != T_OCEAN) fprintf(f, "%d %d %d %d\n", r->x, r->y, rhorses(r), rtrees(r)); } fclose(f); } static void read_migrepair(void) { FILE * f = fopen("repair.migrants", "rt"); int x, y, h, t; region *r; for(r=regions; r; r=r->next) freset(r, FL_DH); while (fscanf(f, "%d %d %d %d\n", &x, &y, &h, &t) != EOF) { r = findregion(x, y); if (r) { rsethorses(r, h); rsettrees(r, t); fset(r, FL_DH); } } for(r=regions; r; r=r->next) if(!fval(r, FL_DH) && rterrain(r) == T_PLAIN) { rsethorses(r, rand() % (terrain[rterrain(r)].production_max / 5)); } fclose(f); } #endif static void fix_migrants(void) { region * r; for (r=regions;r;r=r->next) { unit * u; for (u=r->units;u;u=u->next) { if (u->race==RC_HUMAN) u->irace=RC_HUMAN; if (u->irace!=u->race && u->race!=RC_ILLUSION && u->race!=RC_DAEMON) { log_warning(("[fix_migrants] %s ist ein %s, als %s getarnt\n", unitname(u), race[u->race].name[0], race[u->irace].name[0])); } } } } #if 0 static void fix_folge_bug(void) { region *td = findregion(64,-101); region *tl = findregion(65,-101); unit *u, *un; for(u=td->units;u;) { un = u->next; if(igetkeyword(u->lastorder) == K_FOLLOW) { move_unit(u, tl, NULL); freset(u, FL_MOVED); u = td->units; } else { u = un; } } } #endif #if 0 static void katja_erschaffe_elf(void) { region *xon = findregion(6,-4); unit *u; faction *mon = findfaction(MONSTER_FACTION); strlist *S; u = createunit(xon, mon, 1, RC_ELF); set_string(&u->name,"Corwin"); set_string(&u->display,"Ein kleiner, unscheinbarer Elf."); set_item(u, I_BIRTHDAYAMULET, 1); u->money = 10; sprintf(buf, "GIB H 1 Katzenamulett"); S = makestrlist(buf); addlist(&u->orders, S); sprintf(buf, "BOTSCHAFT AN EINHEIT H %s",estring("Ein kleiner Elf verbeugt sich vor euch: 'Nehmt dieses Geschenk vom Gott aller Götter. Auf das euch noch ein langes und sehr glückliches Leben beschieden sei.'")); S = makestrlist(buf); addlist(&u->orders, S); set_string(&u->thisorder, "LERNE WAHRNEHMUNG"); set_string(&u->thisorder, "LERNE WAHRNEHMUNG"); } #endif #if 0 static boolean kor_teure_talente(unit *u) { if(effskill(u, SK_TACTICS) >= 1 || effskill(u, SK_MAGIC) >= 1 || effskill(u, SK_ALCHEMY) >= 1 || effskill(u, SK_HERBALISM) >= 1 || effskill(u, SK_SPY) >= 1) { return true; } return false; } #endif #if 0 static void no_teurefremde(boolean convert) { region *r; unit *u; for(r=regions;r;r=r->next) { for(u=r->units;u;u=u->next) { if(u->faction->no != MONSTER_FACTION && u->race != RC_ILLUSION && u->race != RC_UNDEAD && u->race != u->faction->race && kor_teure_talente(u)) { if(convert) { u->race = u->faction->race; u->faction->num_migrants -= u->number; } else { printf("* Warnung, teurer Migrant: %s\n", unitname(u)); } } } } } #endif #if 0 static void give_arena_gates(void) { faction * f; for (f=factions;f;f=f->next) { unit * u; region * r; unit * senior = f->units; if (f->age>2) return; for (u = f->units; u; u=u->nextF) { if (senior->age < u->age) senior = u; if (f->no==MONSTER_FACTION && get_item(u, I_ARENA_GATE)) return; } if (!senior) continue; r = senior->region; sprintf(buf, "Der Himmel über %s reißt auf und ein Licht aus den Wolken scheint auf %s. Ein Gesang wie von tausend Walküren ertönt, dazu Schlachtenlärm. Nach einer Weile endet die Vision, und %s hält ein %s in den Händen.", regionid(senior->region), unitname(senior), unitname(senior), itemdata[I_ARENA_GATE].name[0]); change_item(senior, I_ARENA_GATE, 1); addmessage(NULL, senior->faction, buf, MSG_MESSAGE, ML_IMPORTANT); } } #endif static void remove_impossible_dragontargets(void) { region *r; for (r=regions;r;r=r->next) { unit *u; for (u=r->units;u;u=u->next) { attrib *a; if(u->faction->no != MONSTER_FACTION) continue; a = a_find(u->attribs, &at_targetregion); if (a!=NULL) { boolean cango = false; region * r2 = a->data.v; if(r2!=NULL) { #ifdef NEW_PATH cango = path_exists(r, r2, DRAGON_RANGE, allowed_dragon); #else cango = path_exists(r, r2, FLY|DRAGON_LIMIT); #endif } if(!cango) { printf("Lösche Ziel von %s\n", unitname(u)); a_remove(&u->attribs, a); } } } } } #if 0 static void fix_score_option(void) { faction * f; for (f=factions;f;f=f->next) { f->options &= ((1<options &= ~(1<options |= (1<next) { if (!r->land || rterrain(r)==T_GLACIER || r->units || r->ships || r->buildings) continue; if (fval(r, RF_ENCOUNTER)) { fputs("\n\nWARNING: FI_RANDENCOUNTER WAS STILL ENABLED\n\n", stderr); return; } fset(r, RF_ENCOUNTER); } } #endif #if 0 static void fix_wounds(void) { region *r; unit *u; for(r=regions; r; r=r->next) { for(u=r->units; u; u=u->next) { int wounds = unit_max_hp(u)*u->number - u->hp; u->hp = max(1, u->hp - wounds); } } } #endif #if 0 static void fix_beached(void) { region * r; for (r=regions;r;r=r->next) { if (r->land && rterrain(r)!=T_PLAIN) { ship * s; building *b; for(b=r->buildings; b; b=b->next) { if(b->typ == BT_HAFEN) break; } if(b == NULL) { for (s=r->ships;s;s=s->next) { if (s->coast!=NODIRECTION && s->type>SH_BOAT) { region * r2 = rconnect(r, s->coast); assert(rterrain(r2)==T_OCEAN || fval(r2, RF_CHAOTIC)); move_ship(s, r, r2, NULL); } } } } } } #endif #if 0 static void fix_hungrydead(void) { region *r; unit *u; for (r=regions;r;r=r->next) { for (u=r->units;u;u=u->next) { if(u->hp == 0) u->hp = 1; } } } #endif static void name_seaserpents(void) { region *r; unit *u; for (r=regions;r;r=r->next) { for (u=r->units;u;u=u->next) { if(u->race == RC_SEASERPENT && strncmp(u->name, "Nummer ", 7)) { set_string(&u->name, "Seeschlange"); } } } } static void give_questling(void) { unit *u1, *u2; if((u1=findunitg(15474, NULL))==NULL) /* Questling */ return; if((u2=findunitg(1429665, NULL))==NULL) /* Harmloser Wanderer */ return; if (u1->faction==u2->faction) return; add_message(&u1->faction->msgs, new_message(u1->faction, "give%u:unit%u:target%r:region%X:resource%i:amount", u1, u2, u1->region, r_unit, 1)); u_setfaction(u1, u2->faction); add_message(&u2->faction->msgs, new_message(u1->faction, "give%u:unit%u:target%r:region%X:resource%i:amount", u1, u2, u1->region, r_unit, 1)); } #if 0 static void old_rsetroad(region * r, int val) { attrib * a = a_find(r->attribs, &at_road); if (!a && val) a = a_add(&r->attribs, a_new(&at_road)); else if (a && !val) a_remove(&r->attribs, a); if (val) a->data.i = val; } #endif static int old_rroad(region * r) { attrib * a = a_find(r->attribs, &at_road); if (!a) return 0; return a->data.i; } attrib_type at_roadfix = { "roadfix", DEFAULT_INIT, DEFAULT_FINALIZE, DEFAULT_AGE, #if RELEASE_VERSIONnext) if (terrain[rterrain(r)].roadreq>0) { direction_t d; int connections = 0; int maxcon = MAXDIRECTIONS; int stones = old_rroad(r); if (stones<=0) continue; for (d=0;d!=MAXDIRECTIONS;++d) { region * r2 = rconnect(r, d); if (r2 && old_rroad(r2)) ++connections; else if (terrain[rterrain(r2)].roadreq<=0) --maxcon; } if (!connections) connections=maxcon; else maxcon=0; for (d=0;d!=MAXDIRECTIONS && connections;++d) { region * r2 = rconnect(r, d); int use = stones/connections; if (!r2 || terrain[rterrain(r2)].roadreq<=0 || (old_rroad(r2)<=0 && !maxcon)) continue; if (use>terrain[rterrain(r)].roadreq) { /* wenn etwas übrig bleibt (connections==1) kriegt es der regionserste */ int give = use-terrain[rterrain(r)].roadreq; unit * u = r->units; use = terrain[rterrain(r)].roadreq; if (u) change_item(u, I_STONE, give); } rsetroad(r, d, use); stones = stones - use; --connections; if (old_rroad(r)==terrain[rterrain(r)].roadreq*2 && old_rroad(r2)==terrain[rterrain(r2)].roadreq*2) { border * b = get_borders(r, r2); attrib * a = a_find(b->attribs, &at_roadfix); if (a) continue; while (b && b->type!=&bt_road) b = b->next; assert(b); a = a_add(&b->attribs, a_new(&at_roadfix)); } } } } /* ************************************************************ */ /* GANZ WICHTIG! ALLE GEÄNDERTEN SPRÜCHE NEU ANZEIGEN */ /* GANZ WICHTIG! FÜGT AUCH NEUE ZAUBER IN DIE LISTE DER BEKANNTEN EIN */ /* ************************************************************ */ static void show_newspells(void) { region *r; /* Alle geänderten Zauber in das array newspellids[]. mit SPL_NOSPELL * terminieren */ spellid_t newspellids[] = { SPL_NOSPELL }; /* die id's der neuen oder veränderten Sprüche werden in newspellids[] * abgelegt */ for(r=regions; r; r=r->next) { unit *u; for(u=r->units;u;u=u->next) { sc_mage *m = get_mage(u); if (u->faction->no == MONSTER_FACTION) continue; if (m != NULL) { int i; if (m->magietyp == M_GRAU) continue; for (i = 0; newspellids[i] != SPL_NOSPELL; i++) { spell *sp = find_spellbyid(newspellids[i]); if (!sp) continue; if (m->magietyp == sp->magietyp || getspell(u, sp->id)) { attrib * a = a_find(u->faction->attribs, &at_reportspell); while (a && a->data.i != sp->id) a = a->nexttype; if (!a) { /* spell is not being shown yet. if seen before, remove to show again */ a = a_find(u->faction->attribs, &at_seenspell); while (a && a->data.i != sp->id) a = a->nexttype; if (a) a_remove(&u->faction->attribs, a); } } } } } } } static void fix_laen(void) { region *r; for(r=regions; r; r=r->next) { if(rterrain(r) != T_MOUNTAIN) rsetlaen(r, -1); } } static void fix_feuerwand_orks(void) { unit *u; if((u=findunitg(atoi36("1j1L"), NULL))==NULL) { printf("Korrektur: kann Orks nicht finden!\n"); return; } if(u->number < 1000) { printf("Korrektur: Orks sind schon korrigiert!\n"); return; } scale_number(u,170); u->hp=2337; /* Buggy Anzahl Personen = Normale HP */ } static void fix_buildings(void) { building *burg; unit *u, *uf = NULL; const requirement *req; const construction *con; FILE *statfile; vset done; int s1, s2; char buf[256]; int a,b,c,d; int first; if((statfile=fopen("building.txt","r"))==NULL) { printf("WARNING: fix_buildings: cannot open building.txt!\n"); return; } vset_init(&done); s1=s2=-1; while(fgets(buf, 256, statfile)!=NULL) { if(*buf=='#') continue; a=b=c=d=0; first=0; sscanf(buf,"%d;%d;%d;%d",&a,&b,&c,&d); if((u=findunitg(b,NULL))==NULL) { printf("fix_buildings: Einheit %d nicht gefunden.\n",b); continue; } if((burg=findbuilding(a))==NULL) { printf("fix_buildings: Burg %d nicht gefunden.\n", a); if((burg=u->building)==NULL) { printf("Einheit %d steht auch in keinem Gebäude. (gebe auf)\n",u->no); continue; } if(burg->type->construction->maxsize > 0 && burg->type->construction->reqsize > 0) printf("Ersatz: Burg %d\n",burg->no); else { printf("Ersatzgebäude ist nicht vom betroffenen Typ.\n"); continue; } } printf("Burg %d; Einheit %d; vorher %d; + %d\n",burg->no,u->no,c,d); s2=vset_add(&done, (void *)a); if(s2>s1) { printf("ERSTER !\n"); first=1; uf=u; } s1=s2; con=burg->type->construction; if(con->maxsize != -1 || con->reqsize == 1) continue; for(req=con->materials; req->number!=0; req++) { int diff=burg->size-c; if(req->type==R_SILVER) change_resource(uf, R_SILVER, diff*req->number-d*req->number/con->reqsize); else { if(first) change_resource(uf, req->type, diff*req->number); assert(uf!=NULL); change_resource(uf, req->type, -d*req->number/con->reqsize); } } if(first) burg->size=c+d; else burg->size+=d; } vset_destroy(&done); fclose(statfile); } extern plane * arena; static void fix_age(void) { faction * f; for (f=factions;f;f=f->next) { if (f->no!=MONSTER_FACTION && !nonplayer_race(f->race)) continue; if (f->age!=turn) { fprintf(stderr, " - Alter von Partei %s anpassen", factionid(f)); f->age = turn; } } } #if 0 static boolean balsambug(const region *r) { direction_t dir; for (dir=0; dir 0) return false; } return true; } static void fix_balsamfiasko(void) { region *r, *rc; direction_t dir; int i; for (r=regions; r; r=r->next) freset(r, RF_DH); /* Zufällig verteilen */ for (r=regions; r; r=r->next) { if (r->x < -36 && r->y < -45 && landregion(rterrain(r))) { if(rdemand(r,0) <= 0 && balsambug(r)) { rsetdemand(r,0,(char)(1+rand()%5)); rsetdemand(r,rand()%7,0); fset(r, RF_DH); } } } /* Smoothing */ for(i=0; i<3; i++) { for (r=regions; r; r=r->next) if(fval(r, RF_DH)) { for (dir=0; dir < MAXDIRECTIONS; dir++) { rc = rconnect(r, dir); if(rc && fval(rc, RF_DH) && rand()%100 < 20) { int p1, p2; for (p1 = 0; p1 != MAXLUXURIES; p1++) if (rdemand(r, p1) == 0) break; for (p2 = 0; p2 != MAXLUXURIES; p2++) if (rdemand(rc, p2) == 0) break; if(p1 != p2) { rsetdemand(rc, p2, (char)(1+rand()%5)); rsetdemand(rc, p1, 0); } } } } } } #endif #if 0 static int count_demand(const region *r) { struct demand *dmd; int c = 0; if (r->land) { for (dmd=r->land->demands;dmd;dmd=dmd->next) c++; } return c; } #endif static int recurse_regions(region * r, regionlist **rlist, boolean(*fun)(const region * r)) { if (!fun(r)) return 0; else { int len = 0; direction_t d; regionlist * rl = calloc(sizeof(regionlist), 1); rl->next = *rlist; rl->region = r; (*rlist) = rl; fset(r, FL_MARK); for (d=0;d!=MAXDIRECTIONS;++d) { region * nr = rconnect(r, d); if (nr && !fval(nr, FL_MARK)) len += recurse_regions(nr, rlist, fun); } return len+1; } } static int maxluxuries = 0; #if 0 static boolean f_nolux(const region * r) { if (r->land && count_demand(r) != maxluxuries) return true; return false; } static void fix_demand_region(region *r) { regionlist *rl, *rlist = NULL; static const luxury_type **mlux = 0, ** ltypes; const luxury_type *sale = NULL; int maxlux = 0; recurse_regions(r, &rlist, f_nolux); if (mlux==0) { int i = 0; if (maxluxuries==0) for (sale=luxurytypes;sale;sale=sale->next) { maxluxuries++; } mlux = (const luxury_type **)gc_add(calloc(maxluxuries, sizeof(const luxury_type *))); ltypes = (const luxury_type **)gc_add(calloc(maxluxuries, sizeof(const luxury_type *))); for (sale=luxurytypes;sale;sale=sale->next) { ltypes[i++] = sale; } } else { int i; for (i=0;i!=maxluxuries;++i) mlux[i] = 0; } for (rl=rlist;rl;rl=rl->next) { region * r = rl->region; direction_t d; for (d=0;d!=MAXDIRECTIONS;++d) { region * nr = rconnect(r, d); if (nr && nr->land && nr->land->demands) { struct demand * dmd; for (dmd = nr->land->demands;dmd;dmd=dmd->next) { if (dmd->value == 0) { int i; for (i=0;i!=maxluxuries;++i) { if (mlux[i]==NULL) { maxlux = i; mlux[i] = dmd->type; break; } else if (mlux[i]==dmd->type) { break; } } break; } } } } freset(r, FL_MARK); /* undo recursive marker */ } if (maxlux<2) { int i; for (i=maxlux;i!=2;++i) { int j; do { int k = rand() % maxluxuries; mlux[i] = ltypes[k]; for (j=0;j!=i;++j) { if (mlux[j]==mlux[i]) break; } } while (j!=i); } maxlux=2; } for (rl=rlist;rl;rl=rl->next) { region * r = rl->region; setluxuries(r, mlux[rand() % maxlux]); } while (rlist) { rl = rlist->next; free(rlist); rlist = rl; } } #endif extern attrib * make_atgmcreate(const struct item_type * itype); extern attrib * make_atpermissions(void); extern struct attrib_type at_permissions; static void make_gms(void) { faction * f = findfaction(atoi36("rr")); if (f) { attrib * a = a_find(f->attribs, &at_permissions); if (!a) { item_type * itype; a = a_add(&f->attribs, make_atpermissions()); for (itype=itemtypes;itype;itype=itype->next) { a_add((attrib**)&a->data.v, make_atgmcreate(itype)); } a_add((attrib**)&a->data.v, make_key(atoi36("gmtf"))); } } } #if 0 static void fix_demand(void) { region *r; const luxury_type *sale = NULL; if (maxluxuries==0) for (sale=luxurytypes;sale;sale=sale->next) ++maxluxuries; for (r=regions; r; r=r->next) { if ((r->land) && count_demand(r) != maxluxuries) { fix_demand_region(r); } } } #endif #if 0 static void read_laenrepair(boolean active) { FILE * f = fopen("repair.laen", "rt"); FILE * log = fopen("report.laen", "wt"); if (!f || !log) return; while (!feof(f)) { int n, x, y; region * r; fscanf(f, "%d %d %d", &x, &y, &n); r = findregion(x, y); if (!r) fprintf(log, "%d,%d:\tnot found\n", x, y); else if (fval(r, RF_CHAOTIC)) continue; else { int laen = rlaen(r); if (n==-1 && laen>=0) { fprintf(log, "%d,%d:\tillegal laen (%d)\n", x, y, laen); if (active) rsetlaen(r, n); } else if (laen==-1 && n!=-1) { fprintf(log, "%d,%d:\tlaen was lost (%d)\n", x, y, n); if (active) rsetlaen(r, n); } } } fclose(f); } static void write_laenrepair(void) { FILE * f = fopen("repair.laen", "wt"); region * r; for (r=regions;r;r=r->next) if (!fval(r, RF_CHAOTIC)) { int laen = rlaen(r); fprintf(f, "%d %d %d\n", r->x, r->y, laen); } fclose(f); } #endif #include "group.h" static void fix_allies(void) { faction * f; for (f=factions;f;f=f->next) { group * g; for (g=f->groups;g;g=g->next) { ally ** ap=&g->allies; while (*ap) { ally * an, * a = *ap; for (an = a->next;an;an=an->next) { if (a->faction==an->faction) { *ap = a->next; free(a); break; } } if (an==NULL) ap = &(*ap)->next; } } } } #ifdef FUZZY_BASE36 extern boolean enable_fuzzy; #endif static void fix_icastles(void) { region * r; for (r=regions; r; r=r->next) { building * b; for (b=r->buildings; b; b=b->next) { attrib * a; const building_type * btype = &bt_castle; icastle_data * data; a = a_find(b->attribs, &at_icastle); if (b->type!=&bt_illusion && !a) continue; if (!a) { /* attribut hat gefehle */ a = a_add(&b->attribs, a_new(&at_icastle)); } if (b->type!=&bt_illusion) { /* gebäudetyp war falsch */ btype = b->type; b->type = &bt_illusion; } data = (icastle_data*)a->data.v; if (data->time<=0) { /* zeit war kaputt oder abgelaufen */ data->time = 1; } if (!data->type) { /* typ muss gesetzt werden, weil er nicht geladen wurde */ data->type = btype; } if (data->building!=b) { /* rückwärtszeiger auf das gebäude reparieren */ data->building=b; } } } } #if 0 static void fix_ponnukis(void) /* Es kann nur einen geben! */ { unit * ponn = findunit(atoi36("ponn")); if (ponn) { region * mag = ponn->region; unit * u; for (u=mag->units;u;u=u->next) { if (u!=ponn && u->faction==ponn->faction && u->race==ponn->race && !strcmp(ponn->name, u->name)) { set_number(u, 0); } } } } #endif #if 0 static void fix_traveldir(void) { region *r; attrib *a, *a2; traveldir *t; for(r=regions; r; r=r->next) { a = a_find(r->attribs, &at_traveldir); while (a) { a2 = a_add(&r->attribs, a_new(&at_traveldir_new)); t = (traveldir *)(a2->data.v); t->no = a->data.sa[0]; t->dir = a->data.ca[2]; t->age = a->data.ca[3]; a = a->nexttype; } } for(r=regions; r; r=r->next) { a = a_find(r->attribs, &at_traveldir); while(a) { a_remove(&r->attribs, a); a = a->nexttype; } } } #endif static void stats(void) { FILE * F; item * items = NULL; char zText[MAX_PATH]; strcat(strcpy(zText, resourcepath()), "/stats"); F = fopen(zText, "wt"); if (F) { region * r; const item_type * itype; for (r=regions;r;r=r->next) { unit * u; item * itm; for (u=r->units;u;u=u->next) { for (itm=u->items;itm;itm=itm->next) { i_change(&items, itm->type, itm->number); } } } for (itype=itemtypes;itype;itype=itype->next) { item * itm = *i_find(&items, itype); if (itm && itm->number) fprintf(F, "%4d %s\n", itm->number, locale_string(NULL, resourcename(itype->rtype, 0))); else fprintf(F, "%4d %s\n", 0, locale_string(NULL, resourcename(itype->rtype, 0))); } fclose(F); } else { perror(zText); } } static void fix_prices(void) { region *r; puts(" - Korrigiere Handelsgüterpreise"); for(r=regions; r; r=r->next) if(r->land) { int sales = 0, buys = 0; const luxury_type *sale, *ltype; struct demand *dmd; for (dmd=r->land->demands;dmd;dmd=dmd->next) { if(dmd->value == 0) { sales++; sale = dmd->type; } else { buys++; } } if(sales == 0) { int c = 0; for(ltype=luxurytypes; ltype; ltype=ltype->next) c++; c = rand()%c; for(ltype=luxurytypes; c>0; c--) ltype=ltype->next; r_setdemand(r, ltype, 0); sale = ltype; } if(buys == 0) { for(ltype=luxurytypes; ltype; ltype=ltype->next) { if(ltype != sale) r_setdemand(r, ltype, 1 + rand() % 5); } } } } static void fix_options(void) { faction *f; puts(" - Korrigiere Parteioptionen"); for(f=factions;f;f=f->next) { f->options = f->options | Pow(O_REPORT); f->options = f->options | Pow(O_ZUGVORLAGE); } } static void init_region_age(void) { region *r; puts(" - Initialisiere r->age"); /* Initialisieren mit dem Alter der ältesten Partei in 2 Feldern * Umkreis */ for(r=regions; r; r=r->next) { regionlist *rl = all_in_range(r,2); regionlist *rl2; unit *u; int maxage = 0; for(rl2 = rl; rl2; rl2 = rl2->next) { for(u=rl2->region->units; u; u=u->next) { if(u->faction->age > maxage) maxage = u->faction->age; } } r->age = (unsigned short)maxage; } } #if 0 static void fix_herbtypes(void) { region * r; for (r=regions;r!=NULL;r=r->next) if (r->land) { const herb_type * htype = r->land->herbtype; if (htype==NULL) { if (terrain[r->terrain].herbs!=NULL) { const item_type * itype; int i=0; while (terrain[r->terrain].herbs[i]!=NULL) ++i; itype = finditemtype(terrain[r->terrain].herbs[rand()%i], NULL); r->land->herbtype = resource2herb(itype->rtype); } } else { if (r->terrain==T_PLAIN) { #ifdef NO_FOREST if (r_isforest(r)) { int i = rand()%3+3; const char * name = terrain[T_PLAIN].herbs[i]; const item_type * itype = finditemtype(name, NULL); r->land->herbtype = resource2herb(itype->rtype); } #endif } else { /* Das geht so nicht, wegen der Eisberg-Terrains */ /* assert(htype->terrain==r->terrain); */ } } } } #endif #ifdef SKILLFIX_SAVE typedef struct skillfix_data { unit * u; skill_t skill; int value; int number; int self; int teach; } skillfix_data; static void init_skillfix(attrib * a) { a->data.v = calloc(sizeof(skillfix_data), 1); } static void free_skillfix(attrib * a) { free(a->data.v); } attrib_type at_skillfix = { "skillfix", init_skillfix, free_skillfix }; void skillfix(struct unit * u, skill_t skill, int from, int self, int teach) { attrib * a = a_add(&u->attribs, a_new(&at_skillfix)); skillfix_data * data = (skillfix_data*)a->data.v; data->u = u; data->skill = skill; data->number = u->number; data->value = from; data->self = self; data->teach = teach; } void write_skillfix(void) { FILE * F = fopen("skills.fix", "w+"); region * r; fprintf(F, "S%d\n", turn); for (r=regions;r;r=r->next) { unit * u; for (u=r->units;u;u=u->next) { attrib * a = a_find(u->attribs, &at_skillfix); while (a) { skillfix_data * data = (skillfix_data*)a->data.v; fprintf(F, "%s %d %d %d %d %d\n", itoa36(data->u->no), data->skill, data->number, data->value, data->self, data->teach); a = a->nexttype; } } } fclose(F); } #endif static void init_mwarden(void) { unit *u = findunitg(atoi36("mwar"), NULL); attrib *a; if(!u) return; a = a_add(&u->attribs, a_new(&at_warden)); a->data.i = 0; } #ifdef CONVERT_TRIGGER #include "old/relation.h" #include "old/trigger.h" #include "old/trigger_internal.h" #include #include #include #include #include #include #include #include #include typedef struct { void *obj2; typ_t typ2; relation_t id; spread_t spread; } reldata; extern timeout *all_timeouts; static void convert_triggers(void) { region * r=regions; timeout * t; while (r) { unit * u = r->units; while (u) { attrib * a = a_find(u->attribs, &at_relation); while (a) { reldata *rel = (reldata *)a->data.v; unit * u2 = (unit*)rel->obj2; switch (rel->id) { case REL_FAMILIAR: if (u && u2) { if (nonplayer(u) || (!nonplayer(u2) && u->race==RC_GOBLIN)) set_familiar(u2, u); else set_familiar(u, u2); } else { if (u2) fprintf(stderr, "WARNING: FAMILIAR info for %s may be broken!\n", unitname(u2)); if (u) fprintf(stderr, "WARNING: FAMILIAR info for %s may be broken!\n", unitname(u)); } break; case REL_CREATOR: break; case REL_TARGET: fprintf(stderr, "WARNING: TARGET relation between %s and 0x%p not converted\n", unitname(u), u2); break; default: fprintf(stderr, "WARNING: unknown relation %d between %s and 0x%p not converted\n", rel->id, unitname(u), u2); break; } a = a->nexttype; } u = u->next; } r=r->next; } for (t=all_timeouts;t;t=t->next) { actionlist * al = t->acts; int time = t->ticks; for (;al;al=al->next) { action * act = al->act; if (act) switch( act->atype ) { case AC_DESTROY: { /* conversion keeper */ unit * u = (unit*)act->obj; trigger * tkill = trigger_killunit(u); add_trigger(&u->attribs, "timer", trigger_timeout(time, tkill)); } case AC_CHANGERACE: { /* conversion for toads */ unit *u = (unit*)act->obj; race_t race = (race_t)act->i[0]; race_t irace = (race_t)act->i[1]; trigger * trestore = trigger_changerace(u, race, irace); if (rand()%10>2) t_add(&trestore, trigger_giveitem(u, olditemtype[I_TOADSLIME], 1)); add_trigger(&u->attribs, "timer", trigger_timeout(time, trestore)); break; } case AC_CHANGEIRACE: { /* conversion for shapeshift */ unit *u = (unit*)act->obj; race_t irace = (race_t)act->i[0]; trigger * trestore = trigger_changerace(u, NORACE, irace); add_trigger(&u->attribs, "timer", trigger_timeout(time, trestore)); break; } case AC_CHANGEFACTION: { /* charmingsong */ faction *f = findfaction_unique_id(act->i[0]); unit *u = (unit*)act->obj; trigger *trestore = trigger_changefaction(u, f); add_trigger(&u->attribs, "timer", trigger_timeout(time, trestore)); add_trigger(&u->faction->attribs, "destroy", trigger_killunit(u)); add_trigger(&f->attribs, "destroy", trigger_killunit(u)); break; } case AC_CREATEUNIT: { /* conversion summon_dragon */ faction *f = findfaction_unique_id(act->i[0]); region *r = (region *)act->obj; int number = act->i[1]; race_t race = (race_t)act->i[2]; trigger *tsummon = trigger_createunit(r, f, race, number); add_trigger(&r->attribs, "timer", trigger_timeout(time, tsummon)); break; } case AC_CREATEMAGICBOOSTCURSE:{ /* delayed magic boost curse */ unit *mage = (unit*)act->obj; trigger *tsummon = trigger_createcurse(mage, mage, C_AURA, 0, act->i[0], 6, 50, 1); add_trigger(&mage->attribs, "timer", trigger_timeout(5, tsummon)); break; } default: fprintf(stderr, "WARNING: timeout not converted\n"); } } } } #endif #if 0 #include static void lms_special(unit * u) { if (u) i_change(&u->items, &it_lmsreward, 1); } #endif #if 0 #define LIFEEXPECTANCY (27*40) static void undo_deadpeasants(void) { region * r = regions; while (r) { int dead = rpeasants(r) / LIFEEXPECTANCY; deathcounts(r, -dead); r = r->next; } } #endif #if 0 static void fix_targetregion_resolve(void) { region *r; unit *u; attrib *a; for(r=regions; r; r=r->next) { for(u=r->units; u; u=u->next) { a = a_find(u->attribs, &at_targetregion); if(a) a->data.v = findregion(a->data.sa[0], a->data.sa[1]); } } } #endif static void fix_herbs(void) { const char * plain_herbs[] = {"Flachwurz", "Würziger Wagemut", "Eulenauge", "Grüner Spinnerich", "Blauer Baumringel", "Elfenlieb"}; const herb_type * htypes[6]; int herbs[6]; int hneed[6]; region *r; int i, hsum = 0, left = 0; for (i=0;i!=6;++i) { htypes[i] = resource2herb(finditemtype(plain_herbs[i], NULL)->rtype); herbs[i] = 0; } for (r=regions; r; r=r->next) if (rterrain(r) == T_PLAIN) { const herb_type *htype = rherbtype(r); assert(htype); for (i=0;i!=6;++i) if (htypes[i]==htype) break; assert(i!=6); herbs[i]++; hsum++; } for (i=0;i!=6;++i) { int hwant = hsum / (6-i); hneed[i] = hwant - herbs[i]; if (hneed[i]>0) left += hneed[i]; hsum -= hwant; } for (r=regions; r; r=r->next) if (rterrain(r) == T_PLAIN) { const herb_type *htype = rherbtype(r); assert(htype); for (i=0;i!=6;++i) if (htypes[i]==htype) break; assert(i!=6); if (hneed[i]<0) { int p; int k = rand() % left; for (p=0;p!=6;++p) if (hneed[p]>0) { k-=hneed[p]; if (k<0) break; } assert(p!=6); hneed[p]--; hneed[i]++; left--; rsetherbtype(r, htypes[p]); } hsum++; } for (i=0;i!=6;++i) herbs[i] = 0; for (r=regions; r; r=r->next) if (rterrain(r) == T_PLAIN) { const herb_type *htype = rherbtype(r); assert(htype); for (i=0;i!=6;++i) if (htypes[i]==htype) break; assert(i!=6); herbs[i]++; } for (i=0;i!=6;++i) { fprintf(stderr, "%s : %d\n", locale_string(NULL, resourcename(htypes[i]->itype->rtype, 0)), herbs[i]); } } #if 0 #include #include void setup_gm_faction(void); static void set_atgm(faction * f) { plane * p = planes; if (!f) return; while (p) { a_add(&f->attribs, make_gm(p)); p = p->next; } } #endif #include #include #include #include #include #include #include #include typedef struct handler_info { char * event; trigger * triggers; } handler_info; typedef struct timeout_data { trigger * triggers; int timer; variant trigger_data; } timeout_data; trigger * get_timeout(trigger * td, trigger * tfind) { trigger * t = td; while (t) { if (t->type==&tt_timeout) { timeout_data * tdata = (timeout_data *)t->data.v; trigger * tr = tdata->triggers; while (tr) { if (tr==tfind) break; tr=tr->next; } if (tr==tfind) break; } t=t->next; } return t; } static void fix_timeouts(void) { region * r; for (r=regions;r;r=r->next) { unit * u; for (u=r->units;u;u=u->next) { attrib * a = a_find(u->attribs, &at_eventhandler); boolean toad = (u->race==RC_TOAD); boolean keeper = (u->race==RC_IRONKEEPER); while (a!=NULL) { trigger * t; handler_info * td = (handler_info *)a->data.v; for (t=td->triggers;t;t=t->next) { trigger ** tptr=&t->next; while (*tptr) { /* remove duplicates */ if ((*tptr)->type==t->type) { *tptr = (*tptr)->next; } else tptr = &(*tptr)->next; } if (t->type == &tt_changerace || t->type == &tt_changefaction || t->type == &tt_createcurse || t->type == &tt_createunit) { trigger * timer = get_timeout(td->triggers, t); if (toad && t->type == &tt_changerace) { toad = false; } if (timer==NULL) { add_trigger(&u->attribs, "timer", trigger_timeout(1+(rand()%2), t)); } } else if (t->type == &tt_killunit) { if (u->race==RC_IRONKEEPER) { trigger * timer = get_timeout(td->triggers, t); keeper = false; if (timer==NULL) { add_trigger(&u->attribs, "timer", trigger_timeout(1+(rand()%2), t)); } } } } a = a->nexttype; } if (keeper) { int duration = 1+ (rand() % 2); trigger * tkill = trigger_killunit(u); add_trigger(&u->attribs, "timer", trigger_timeout(duration, tkill)); } if (toad) { /* repair toad-only mage */ int duration = 1+ (rand() % 2); trigger * trestore = trigger_changerace(u, u->faction->race, u->faction->race); if (rand()%10>2) t_add(&trestore, trigger_giveitem(u, olditemtype[I_TOADSLIME], 1)); add_trigger(&u->attribs, "timer", trigger_timeout(duration, trestore)); } } } } #include static void test_gmquest(void) { const struct faction * f; /* enno's world */ f = gm_addquest("enno@eressea.upb.de", "GM Zone", 1, PFL_NOATTACK|PFL_NOALLIANCES|PFL_NOFEED|PFL_FRIENDLY); log_printf("Neue Questenpartei %s\n", factionname(f)); f = gm_addquest("xandril@att.net", "Mardallas Welt", 40, 0); log_printf("Neue Questenpartei %s\n", factionname(f)); f = gm_addquest("moritzsalinger@web.de", "Laen-Kaiser", 7, /*PFL_NORECRUITS |*/ PFL_NOMAGIC /*| PFL_NOBUILD*/); log_printf("Neue Questenpartei %s\n", factionname(f)); f = gm_addquest("Denise.Muenstermann@home.gelsen-net.de", "Mochikas Queste", 7, PFL_NOMAGIC); log_printf("Neue Questenpartei %s\n", factionname(f)); f = gm_addquest("feeron@aol.com", "Eternath", 11, 0); log_printf("Neue Questenpartei %s\n", factionname(f)); f = gm_addquest("BigBear@nord-com.net", "Leonidas Vermächtnis", 15, PFL_NOMAGIC|PFL_NOSTEALTH); log_printf("Neue Questenpartei %s\n", factionname(f)); } void korrektur(void) { #ifdef TEST_GM_COMMANDS setup_gm_faction(); #endif make_gms(); /* Wieder entfernen! */ verify_owners(false); /* fix_herbtypes(); */ #ifdef CONVERT_TRIGGER convert_triggers(); #endif fix_migrants(); fix_allies(); do_once(atoi36("fhrb"), fix_herbs()); do_once(atoi36("ftos"), fix_timeouts()); do_once(atoi36("gmtst"), test_gmquest()); /* test gm quests */ do_once(atoi36("fixsl"), fix_prices()); #ifndef SKILLFIX_SAVE fix_skills(); #endif stats(); /* Turn ist noch nicht inkrementiert! Also immer . * das gilt aber nicht, wenn man es aus der console ('c') aufruft. */ switch (turn) { case 188: name_seaserpents(); break; case 189: break; case 190: give_questling(); break; case 191: give_questling(); /* try again */ break; case 194: remove_impossible_dragontargets(); break; case 195: remove_impossible_dragontargets(); break; case 197: fix_laen(); break; case 208: fix_feuerwand_orks(); break; case 209: fix_buildings(); #if 0 fix_traveldir(); #endif break; case 212: fix_prices(); break; case 215: fix_options(); init_region_age(); break; case 217: init_mwarden(); break; } /* trade_orders(); */ if (global.data_version < NEWROAD_VERSION) { newroads(); } /* immer ausführen, wenn neue Sprüche dazugekommen sind, oder sich * Beschreibungen geändert haben */ show_newspells(); fix_age(); /* Immer ausführen! Erschafft neue Teleport-Regionen, wenn nötig */ create_teleport_plane(); if (global.data_version