diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 939d23c42..1be549d64 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -2023,7 +2023,7 @@ instant_orders(void) spell = find_spellbyname(u, s); if(!spell){ - cmistake(u, S->s, 169, MSG_MAGIC); + cmistake(u, S->s, 173, MSG_MAGIC); break; } diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index d88d220ff..67c3b744f 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -1642,9 +1642,9 @@ report_building(FILE *F, const region * r, const building * b, const faction * f /* Leere Burgen verursachten sonst segfault! */ if(buildingowner(r,b) != NULL){ print_curses(F, b, TYP_BUILDING, b->attribs, - (buildingowner(r,b)->faction == f)? 1 : 0, 2); + (buildingowner(r,b)->faction == f)? 1 : 0, 4); } else { - print_curses(F, b, TYP_BUILDING, b->attribs, 0, 2); + print_curses(F, b, TYP_BUILDING, b->attribs, 0, 4); } for (u = r->units; u; u = u->next) @@ -2047,9 +2047,9 @@ report(FILE *F, faction * f, const char * pzTime) /* Leere Schiffe verursachten sonst segfault! */ if(shipowner(r,sh) != NULL){ print_curses(F, sh, TYP_SHIP, sh->attribs, - (shipowner(r,sh)->faction == f)? 1 : 0, 2); + (shipowner(r,sh)->faction == f)? 1 : 0, 4); } else { - print_curses(F, sh, TYP_SHIP, sh->attribs, 0, 2); + print_curses(F, sh, TYP_SHIP, sh->attribs, 0, 4); } for (u = r->units; u; u = u->next) @@ -2567,7 +2567,13 @@ reports(void) int wants_report, wants_computer_report, wants_compressed, wants_bzip2; time_t ltime = time(NULL); - char * pzTime = strdup(asctime( localtime( <ime ) )); + char pzTime[64]; + +#ifdef _GNU_SOURCE + strftime(pzTime, 64, "%A, %-e. %B %Y, %-k:%M", localtime(<ime)); +#else + strftime(pzTime, 64, "%A, %e. %B %Y, %k:%M", localtime(<ime)); +#endif nmr_warnings(); #ifdef DMALLOC @@ -2591,7 +2597,7 @@ reports(void) init_intervals(); #endif remove_empty_units(); - log_printf("Report timestamp: %s", pzTime); + log_printf("Report timestamp - %s", pzTime); for (f = factions; f; f = f->next) { attrib * a = a_find(f->attribs, &at_reportspell); current_faction = f; diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index 891deffd4..3fa98cd33 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -1383,6 +1383,8 @@ do_combatmagic(battle *b, combatmagic_t was) level = eff_skill(mage, SK_MAGIC, r); if (level > 0) { + char cmd[128]; + switch(was) { case DO_PRECOMBATSPELL: sp = get_combatspell(mage, 0); @@ -1398,7 +1400,10 @@ do_combatmagic(battle *b, combatmagic_t was) } if (sp == NULL) continue; - if (cancast(mage, sp, 1, 1) == false) + + snprintf(cmd, 128, "ZAUBER %s", sp->name); + + if (cancast(mage, sp, 1, 1, cmd) == false) continue; level = eff_spelllevel(mage, sp, level, 1); @@ -1465,13 +1470,15 @@ do_combatspell(troop at) int fumblechance = 0; void **mg; int sl; + char cmd[128]; sp = get_combatspell(mage, 1); if (sp == NULL) { fi->magic = 0; /* Hat keinen Kampfzauber, kämpft nichtmagisch weiter */ return; } - if (cancast(mage, sp, 1, 1) == false) { + snprintf(cmd, 128, "ZAUBER %s", sp->name); + if (cancast(mage, sp, 1, 1, cmd) == false) { fi->magic = 0; /* Kann nicht mehr Zaubern, kämpft nichtmagisch weiter */ return; } diff --git a/src/common/kernel/building.c b/src/common/kernel/building.c index 67336599f..df6626ea4 100644 --- a/src/common/kernel/building.c +++ b/src/common/kernel/building.c @@ -580,7 +580,7 @@ building_type bt_caravan = { /** Building: tunnel */ static const maintenance tunnel_keep[] = { /* resource, number, flags */ - { R_HORSE, 2, MTF_NONE }, + { R_STONE, 2, MTF_NONE }, { R_SILVER, 100, MTF_VITAL }, { NORESOURCE, 0, MTF_NONE }, }; diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index 606b5bd01..ab8d006df 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -635,9 +635,10 @@ set_combatspell(unit *u, spell *sp, const char * cmd, int level) m = get_mage(u); if (!m) return; - if (!sp) { - /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, cmd, 169, MSG_MAGIC); + /* knowsspell prüft auf ist_magier, ist_spruch, kennt_spruch */ + if (!sp || !knowsspell(u->region, u, sp)) { + /* Fehler 'Spell not found' */ + cmistake(u, cmd, 173, MSG_MAGIC); return; } if (getspell(u, sp->id) == false) { @@ -976,10 +977,11 @@ pay_spell(unit * u, spell * sp, int cast_level, int range) /* ------------------------------------------------------------- */ -/* Um einen Spruch zu beherrschen, muss der Magier die Stufe des - * Spruchs besitzen, nicht nur wissen, das es ihn gibt (also den Spruch - * in seiner Spruchliste haben) */ - +/* Ein Magier kennt den Spruch und kann sich die Beschreibung anzeigen + * lassen, wenn diese in seiner Spruchliste steht. Zaubern muss er ihn + * aber dann immer noch nicht können, vieleicht ist seine Stufe derzeit + * nicht ausreichend oder die Komponenten fehlen. + */ boolean knowsspell(const region * r, const unit * u, const spell * sp) { @@ -989,36 +991,53 @@ knowsspell(const region * r, const unit * u, const spell * sp) } /* Magier? */ if (get_mage(u) == NULL) { + log_warning(("%s ist kein Magier, versucht aber zu zaubern.\n", + unitname(u))); return false; } - /* reicht die Stufe aus? */ - if (eff_skill(u, SK_MAGIC, r) < sp->level) { + /* steht der Spruch in der Spruchliste? */ + if (getspell(u, sp->id) == false){ + /* ist der Spruch aus einem anderen Magiegebiet? */ + if (find_magetype(u) != sp->magietyp){ + return false; + } + 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)); + } return false; } - /* ist der Spruch aus einem anderen Magiegebiet? */ - if (find_magetype(u) != sp->magietyp) { - return (getspell(u, sp->id)); - } + /* hier sollten alle potentiellen Fehler abgefangen sein */ return true; } -/* Kosten für einen Spruch können Magiepunkte, Silber, Kraeuter +/* Um einen Spruch zu beherrschen, muss der Magier die Stufe des + * Spruchs besitzen, nicht nur wissen, das es ihn gibt (also den Spruch + * in seiner Spruchliste haben). + * Kosten für einen Spruch können Magiepunkte, Silber, Kraeuter * und sonstige Gegenstaende sein. */ boolean -cancast(unit * u, spell * sp, int level, int range) +cancast(unit * u, spell * sp, int level, int range, char * cmd) { int k; resource_t res; int itemanz; boolean b = true; - const char * cmd = sp->name; if (knowsspell(u->region, u, sp) == false) { /* Diesen Zauber kennt die Einheit nicht */ - cmistake(u, cmd, 169, MSG_MAGIC); + cmistake(u, strdup(cmd), 173, MSG_MAGIC); + return false; + } + /* 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)); + /* die Einheit ist nicht erfahren genug für diesen Zauber */ + cmistake(u, strdup(cmd), 169, MSG_MAGIC); return false; } @@ -2762,6 +2781,17 @@ magic(void) cmistake(u, so->s, 173, MSG_MAGIC); continue; } + /* um testen auf spruchnamen zu unterbinden sollte vor allen + * fehlermeldungen die anzeigen das der magier diesen Spruch + * nur in diese Situation nicht anwenden kann, noch eine + * einfache Sicherheitsprüfung kommen */ + if (knowsspell(r, u, sp) == false){ + /* vorsicht! u kann der familiar sein */ + if (!familiar){ + cmistake(u, so->s, 173, MSG_MAGIC); + continue; + } + } if (sp->sptyp & ISCOMBATSPELL) { /* Fehler: "Dieser Zauber ist nur im Kampf sinnvoll" */ cmistake(u, so->s, 174, MSG_MAGIC); @@ -2872,6 +2902,7 @@ magic(void) } for (spellrank = 0; spellrank < MAX_SPELLRANK; spellrank++) { for (co = cll[spellrank]; co; co = co->next) { + char *cmd = co->order; u = (unit *)co->magician; sp = co->sp; @@ -2889,7 +2920,7 @@ magic(void) level = eff_spelllevel(u, sp, level, co->distance); if (level < 1) { /* Fehlermeldung mit Komponenten generieren */ - cancast(u, sp, co->level, co->distance); + cancast(u, sp, co->level, co->distance, cmd); continue; } if (level < co->level){ @@ -2905,7 +2936,7 @@ magic(void) /* Prüfen, ob die realen Kosten für die gewünschten Stufe bezahlt * werden können */ - if (cancast(u, sp, level, co->distance) == false) { + if (cancast(u, sp, level, co->distance, cmd) == false) { /* die Fehlermeldung wird in cancast generiert */ continue; } diff --git a/src/common/kernel/magic.h b/src/common/kernel/magic.h index abf75b627..819bd7262 100644 --- a/src/common/kernel/magic.h +++ b/src/common/kernel/magic.h @@ -358,7 +358,7 @@ int spellcost(struct unit *u, spell *spruch); /* gibt die für diesen Spruch derzeit notwendigen Magiepunkte auf der * geringstmöglichen Stufe zurück, schon um den Faktor der bereits * zuvor gezauberten Sprüche erhöht */ -boolean cancast (struct unit *u, spell *spruch, int eff_stufe, int distance); +boolean cancast (struct unit *u, spell *spruch, int eff_stufe, int distance, char *cmd); /* true, wenn Einheit alle Komponenten des Zaubers (incl. MP) für die * geringstmögliche Stufe hat und den Spruch beherrscht */ void pay_spell(struct unit *u, spell *spruch, int eff_stufe, int distance); diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c index 34e619163..036fc1092 100644 --- a/src/common/kernel/movement.c +++ b/src/common/kernel/movement.c @@ -1586,7 +1586,7 @@ sail(region * starting_point, unit * u, region * next_point, boolean move_on_lan if (fval(u, FL_FOLLOWING)) caught_target(current_point, u); if (starting_point != current_point) { - tt[step+1] = NULL; + tt[step] = NULL; sh = move_ship(sh, starting_point, current_point, tt); /* Hafengebühren ? */ diff --git a/src/common/util/goodies.c b/src/common/util/goodies.c index c7f858d8a..9569378f3 100644 --- a/src/common/util/goodies.c +++ b/src/common/util/goodies.c @@ -30,6 +30,23 @@ /* Simple Integer-Liste */ +char * +sncat(char * buffer, size_t size, const char * str) +{ + static char * b = NULL; + static char * end = NULL; + int n = 0; + if (b==buffer) { + end += strlen(end); + size -= (end-b); + } else { + end = b = buffer; + } + while (size-- > 0 && (*end++=*str++)!=0) ++n; + *end='\0'; + return b; +} + int * intlist_init(void) { diff --git a/src/common/util/goodies.h b/src/common/util/goodies.h index 2559552a7..48451b0a7 100644 --- a/src/common/util/goodies.h +++ b/src/common/util/goodies.h @@ -22,6 +22,8 @@ extern unsigned int hashstring(const char* s); extern char *space_replace(char * str, char replace); extern const char *escape_string(const char * str, char * buffer, size_t len); extern boolean locale_check(void); +extern char *sncat(char * buffer, size_t size, const char * str); + /* grammar constants: */ #define GR_PLURAL 0x01 /* 0x02-0x08 left unused for individual use */ diff --git a/src/common/util/log.c b/src/common/util/log.c index db3577fc7..1b18ffff0 100644 --- a/src/common/util/log.c +++ b/src/common/util/log.c @@ -6,12 +6,8 @@ #include #include -#define LOG_FLUSH (1<<0) -#define LOG_CPERROR (1<<1) -#define LOG_CPWARNING (1<<1) - /* TODO: set from external function */ -static int flags = LOG_FLUSH|LOG_CPERROR; +static int flags = LOG_FLUSH|LOG_CPERROR|LOG_CPWARNING; static FILE * logfile; void @@ -101,3 +97,26 @@ _log_error(const char * format, ...) } } } + +void +_log_info(unsigned int flag, const char * format, ...) +{ + va_list marker; + if (!logfile) logfile = stderr; + + fprintf(logfile, "INFO[%u]: ", flag); + va_start(marker, format); + vfprintf(logfile, format, marker); + va_end(marker); + if (logfile!=stderr) { + if (flags & flag) { + fprintf(stderr, "\bINFO[%u]: ", flag); + va_start(marker, format); + vfprintf(stderr, format, marker); + va_end(marker); + } + if (flags & LOG_FLUSH) { + fflush(logfile); + } + } +} diff --git a/src/common/util/log.h b/src/common/util/log.h index 802ec5135..5bc1e93dd 100644 --- a/src/common/util/log.h +++ b/src/common/util/log.h @@ -5,7 +5,13 @@ extern void log_close(void); #define log_warning(x) _log_warn x #define log_error(x) _log_error x +#define log_info(x) _log_info x /* use macros above instead of these: */ extern void _log_warn(const char * format, ...); extern void _log_error(const char * format, ...); +extern void _log_info(unsigned int flag, const char * format, ...); + +#define LOG_FLUSH (1<<0) +#define LOG_CPWARNING (1<<1) +#define LOG_CPERROR (1<<2) diff --git a/src/corwin.mk b/src/corwin.mk index 002cc6d87..014ac7ae4 100644 --- a/src/corwin.mk +++ b/src/corwin.mk @@ -4,7 +4,7 @@ ifndef ERESSEA endif # Hier definieren, damit nicht '@gcc' -CC = gcc +CC = gcc -D_GNU_SOURCE AR = ar CTAGS = ctags LD = gcc diff --git a/src/res/de/messages.txt b/src/res/de/messages.txt index b60fb97dc..b4d8b4478 100644 --- a/src/res/de/messages.txt +++ b/src/res/de/messages.txt @@ -168,7 +168,7 @@ error165;errors:0;de;{unit} in {region}: '{command}' - Der Trank bekommt der Ein error166;errors:0;de;{unit} in {region}: '{command}' - Diese Rasse kann eine Burg nicht belagern. error167;errors:0;de;{unit} in {region}: '{command}' - Die Einheit geht nicht zu den Bauern. error168;errors:0;de;{unit} in {region}: '{command}' - Es konnten keine Luxusgüter verkauft werden. -error169;errors:0;de;{unit} in {region}: '{command}' - Diesen Zauber kennt die Einheit nicht. +error169;errors:0;de;{unit} in {region}: '{command}' - Die Einheit ist nicht erfahren genug für diesen Zauber. error170;errors:0;de;{unit} in {region}: '{command}' - Die Bauern nehmen dieses großzügige Geschenk nicht an. error171;errors:0;de;{unit} in {region}: '{command}' - Diesen Kampfzauber gibt es nicht. error172;errors:0;de;{unit} in {region}: '{command}' - Es wurde kein Zauber angegeben.