diff --git a/src/common/gamecode/creport.c b/src/common/gamecode/creport.c index c198a212f..9c7eabe5f 100644 --- a/src/common/gamecode/creport.c +++ b/src/common/gamecode/creport.c @@ -665,18 +665,17 @@ cr_output_unit(FILE * F, const region * r, /* talents */ pr = 0; for (sk = 0; sk != MAXSKILLS; ++sk) { - int gsk = get_skill(u, sk); - if (gsk) { + if (has_skill(u, sk)) { int esk = eff_skill(u, sk, r); if (!pr) { pr = 1; fprintf(F, "TALENTE\n"); } #if SKILLPOINTS - fprintf(F, "%d %d;%s\n", gsk, esk, + fprintf(F, "%d %d;%s\n", get_skill(u, sk), esk, add_translation(skillname(sk, NULL), skillname(sk, f->locale))); #else - fprintf(F, "%d %d;%s\n", level_days(gsk/u->number), esk, + fprintf(F, "%d %d;%s\n", level_days(get_level(u, sk)), esk, add_translation(skillname(sk, NULL), skillname(sk, f->locale))); #endif } diff --git a/src/common/gamecode/economy.c b/src/common/gamecode/economy.c index a2aba00cb..fda37016b 100644 --- a/src/common/gamecode/economy.c +++ b/src/common/gamecode/economy.c @@ -296,34 +296,42 @@ expandrecruit(region * r, request * recruitorders) for (u = r->units; u; u = u->next) { if (u->n >= 0) { - if (u->number) - u->hp += u->n * unit_max_hp(u); - if (u->race == new_race[RC_URUK]) { - change_skill(u, SK_SWORD, skill_level(1) * u->n); - change_skill(u, SK_SPEAR, skill_level(1) * u->n); + unit * unew; + if (u->number==0) unew = u; + else unew = createunit(r, u->faction, u->n, u->race); + if (unew->race == new_race[RC_URUK]) { + change_level(unew, SK_SWORD, 1); + change_level(unew, SK_SPEAR, 1); } - if (u->race->ec_flags & ECF_REC_HORSES) { - change_skill(u, SK_RIDING, skill_level(1) * u->n); + if (unew->race->ec_flags & ECF_REC_HORSES) { + change_level(unew, SK_RIDING, 1); } - i = fspecial(u->faction, FS_MILITIA); + i = fspecial(unew->faction, FS_MILITIA); if (i > 0) { - int ld = skill_level(i); - if (u->race->bonus[SK_SPEAR] >= 0) - change_skill(u, SK_SPEAR, u->n * ld); - if (u->race->bonus[SK_SWORD] >= 0) - change_skill(u, SK_SWORD, u->n * ld); - if (u->race->bonus[SK_LONGBOW] >= 0) - change_skill(u, SK_LONGBOW, u->n * ld); - if (u->race->bonus[SK_CROSSBOW] >= 0) - change_skill(u, SK_CROSSBOW, u->n * ld); - if (u->race->bonus[SK_RIDING] >= 0) - change_skill(u, SK_RIDING, u->n * ld); - if (u->race->bonus[SK_AUSDAUER] >= 0) - change_skill(u, SK_AUSDAUER, u->n * ld); + if (unew->race->bonus[SK_SPEAR] >= 0) + change_level(unew, SK_SPEAR, i); + if (unew->race->bonus[SK_SWORD] >= 0) + change_level(unew, SK_SWORD, i); + if (unew->race->bonus[SK_LONGBOW] >= 0) + change_level(unew, SK_LONGBOW, i); + if (unew->race->bonus[SK_CROSSBOW] >= 0) + change_level(unew, SK_CROSSBOW, i); + if (unew->race->bonus[SK_RIDING] >= 0) + change_level(unew, SK_RIDING, i); + if (unew->race->bonus[SK_AUSDAUER] >= 0) + change_level(unew, SK_AUSDAUER, i); + } + if (unew!=u) { + unit ** up=&u->next; + transfermen(unew, u, unew->number); + while (*up!=unew) up=&(*up)->next; + assert(unew->next==NULL); + *up = NULL; + free(unew); } if (u->n < u->wants) { - add_message(&u->faction->msgs, - msg_message("recruit", "unit region amount want", u, r, u->n, u->wants)); + ADDMSG(&unew->faction->msgs, msg_message("recruit", + "unit region amount want", unew, r, u->n, u->wants)); } } } @@ -577,7 +585,7 @@ givemen(int n, unit * u, unit * u2, const char * cmd) } else if (count_migrants(u2->faction) + n > count_max_migrants(u2->faction)) { error = 128; } - else if (teure_talente(u) == 0 || teure_talente(u2) == 0) { + else if (teure_talente(u) || teure_talente(u2)) { error = 154; } else if (u2->number!=0) { error = 139; @@ -709,7 +717,7 @@ giveunit(region * r, unit * u, unit * u2, strlist * S) cmistake(u, S->s, 128, MSG_COMMERCE); return; } - if (teure_talente(u) == 0) { + if (teure_talente(u)) { cmistake(u, S->s, 154, MSG_COMMERCE); return; } diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 31f845fc0..ed62382cc 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -349,10 +349,11 @@ live(region * r) un = u->next; if (!is_monstrous(u)) { - if (get_effect(u, oldpotiontype[P_FOOL]) > 0) { /* Trank "Dumpfbackenbrot" */ + int effect = get_effect(u, oldpotiontype[P_FOOL]); + if (effect > 0) { /* Trank "Dumpfbackenbrot" */ +#if SKILLPOINTS skill_t sk, ibest = NOSKILL; int best = 0; - for (sk = 0; sk < MAXSKILLS; sk++) { if (get_skill(u, sk) > best) { best = get_skill(u, sk); @@ -360,21 +361,28 @@ live(region * r) } } /* bestes Talent raussuchen */ if (best > 0) { - int value = get_effect(u, oldpotiontype[P_FOOL]); -#if SKILLPOINTS int k = get_skill(u, ibest); - value = min(value, u->number) * 30; + int value = min(effect, u->number) * 30; k = min(k, value); change_skill(u, ibest, -k); -#else - /* Talent sinkt für max. 10 Personen um 1 Stufe */ - int k = min(u->number, value); - int sk = get_skill(u, ibest); - change_skill(u, ibest, -min(k, sk)); -#endif ADDMSG(&u->faction->msgs, msg_message("dumbeffect", - "unit days skill", u, value, ibest)); + "unit days skill", u, (k+29)/30, ibest)); } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */ +#else + skill * sv = u->skills, * sb = NULL; + while (sv!=u->skills+u->skill_size) { + if (sb==NULL || skill_compare(sv, sb)>0) { + sb = sv; + } + ++sv; + } /* bestes Talent raussuchen */ + if (sb!=NULL) { + int weeks = min(effect, u->number); + reduce_skill(sb, weeks); + ADDMSG(&u->faction->msgs, msg_message("dumbeffect", + "unit weeks skill", u, weeks, (skill_t)sb->id)); + } /* sonst Glück gehabt: wer nix weiß, kann nix vergessen... */ +#endif } } age_unit(r, u); @@ -3440,10 +3448,6 @@ processorders (void) puts(" - Attribute altern"); ageing(); -#ifdef REMOVE_ZERO_SKILLS - puts(" - Skills ohne Talenttage werden gelöscht"); - remove_zero_skills(); -#endif #ifdef SKILLFIX_SAVE write_skillfix(); #endif diff --git a/src/common/gamecode/monster.c b/src/common/gamecode/monster.c index 78cb1d077..441a9c231 100644 --- a/src/common/gamecode/monster.c +++ b/src/common/gamecode/monster.c @@ -948,13 +948,7 @@ plan_monsters(void) if (u->faction->no != MONSTER_FACTION) continue; /* Monster bekommen jede Runde ein paar Tage Wahrnehmung dazu */ -#if SKILLPOINTS - change_skill(u, SK_OBSERVATION, u->number * 10); -#else - if (learn_skill(u, SK_OBSERVATION, u->number * 10)) { - change_skill(u, SK_OBSERVATION, u->number); - } -#endif + produceexp(u, SK_OBSERVATION, u->number); ta = a_find(u->attribs, &at_hate); if (ta && strncmp(u->lastorder, "WARTEN", 6) != 0) { @@ -1167,36 +1161,15 @@ age_unit(region * r, unit * u) void split_unit(region * r, unit *u) { - unit *u2; - skill_t sk; - int newsize; - assert(u->number!=1); + unit *u2 = createunit(r, u->faction, 0, u->race); + int newsize = u->number/2; - newsize = u->number/2; - - u2 = createunit(r, u->faction, newsize, u->race); set_string(&u2->name, u->name); set_string(&u2->display, u->display); set_string(&u2->thisorder, "WARTEN"); set_string(&u2->lastorder, "WARTEN"); -#if SKILLPOINTS - for(sk = 0; sk < MAXSKILLS; sk++) { - int n = get_skill(u, sk); - int i = (n / u->number) * newsize; - i += (n % u->number) * newsize / u->number; - set_skill(u2, sk, i); - set_skill(u, sk, n-i); - } - set_number(u, u->number - newsize); -#else - scale_number(u, u->number - newsize); - for(sk = 0; sk < MAXSKILLS; sk++) { - int n = get_skill(u, sk); - int level = n / u->number; - set_level(u2, sk, level); - } -#endif + transfermen(u, u2, newsize); } boolean diff --git a/src/common/gamecode/randenc.c b/src/common/gamecode/randenc.c index 7b4ee16f4..0ba358a86 100644 --- a/src/common/gamecode/randenc.c +++ b/src/common/gamecode/randenc.c @@ -168,7 +168,7 @@ dissolve_units(void) } static int -improve_all(faction * f, skill_t sk, int days) +improve_all(faction * f, skill_t sk, int weeks) { region *r; unit *u; @@ -179,11 +179,11 @@ improve_all(faction * f, skill_t sk, int days) for (u = r->units; u; u = u->next) { if (u->faction == f && get_skill(u, sk)) { #if SKILLPOINTS - change_skill(u, sk, u->number * days); + change_skill(u, sk, u->number * weeks * 30); n += u->number; #else - if (learn_skill(u, sk, days * u->number)) { - change_skill(u, sk, 1); + for (n=0;n!=weeks;++n) { + learn_skill(u, sk, 1.0); } #endif } @@ -298,11 +298,12 @@ find_manual(region * r, unit * u) scat(". Der Wissensschub ist enorm."); addmessage(r, u->faction, buf, MSG_EVENT, ML_IMPORTANT); - if (improve_all(u->faction, skill, 90) == 0) { + if (improve_all(u->faction, skill, 3) == 0) { #if SKILLPOINTS change_skill(u, skill, 270); #else - change_skill(u, skill, 1); + int i; + for (i=0;i!=9;++i) learn_skill(u, skill, 1.0); #endif } } @@ -1020,22 +1021,27 @@ godcurse(void) { region *r; ship *sh, *shn; - skill_t sk; for(r=regions; r; r=r->next) { if(is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { unit * u; for(u=r->units; u; u=u->next) { +#if SKILLPOINTS + skill_t sk; for(sk=0; sk < MAXSKILLS; sk++) { int s = get_skill(u, sk); if (s > 0) { -#if SKILLPOINTS change_skill(u, sk, -min(s, (30+rand()%90)*u->number)); -#else - change_skill(u, sk, -min(s, u->number)); -#endif } } +#else + skill * sv = u->skills; + while (sv!=u->skills+u->skill_size) { + int weeks = 1+rand()%3; + reduce_skill(sv, weeks); + ++sv; + } +#endif } } } @@ -1061,7 +1067,6 @@ randomevents(void) region *r; building *b, *b2; unit *u; - int n; int unfed; /* Eiseberge */ @@ -1147,7 +1152,11 @@ randomevents(void) * Es ist auch deshalb fast egal, weil es ja im Grunde nicht dem Dämon, * sondern der Region zu gute kommt - und da ist der anwender schnuppe */ +#if SKILLPOINTS skill_t sk; +#else + skill * sv; +#endif int dc; if (!bfind) { unit * ud = u; @@ -1184,31 +1193,30 @@ randomevents(void) dc = rpeasants(r) - max(u->number - bauernblut, 0); dc = max(0, dc); rsetpeasants(r, dc); +#if SKILLPOINTS for (sk = 0; sk != MAXSKILLS; sk++) { if (get_skill(u, sk) && rand() % 100 < 25) { int change = rand() % 90 + 1; if (rand() % 100 < 60) { -#if SKILLPOINTS change_skill(u, sk, u->number * change); -#else - if (learn_skill(u, sk, change * u->number)) { - change_skill(u, sk, u->number); - } -#endif } else { int s = get_skill(u, sk); -#ifdef SKILLPOINTS s = min(s, u->number * change); change_skill(u, sk, -s); -#else - s = min(s, u->number); - if (learn_skill(u, sk, change * u->number)) { - change_skill(u, sk, -s); - } -#endif } } } +#else + sv = u->skills; + while (sv!=u->skills+u->skill_size) { + if (rand() % 100 < 25) { + int weeks = 0+rand()%3; + if (rand() % 100 < 40) reduce_skill(sv, weeks); + else while (weeks--) learn_skill(u, sv->id, 1.0); + } + ++sv; + } +#endif } } } @@ -1510,13 +1518,8 @@ randomevents(void) u = createunit(r, findfaction(MONSTER_FACTION),treemen, new_race[RC_TREEMAN]); set_string(&u->lastorder, "WARTEN"); /* guard(u, GUARD_ALL); kein auto-guard! erst in monster.c! */ -#if SKILLPOINTS - change_skill(u, SK_OBSERVATION, u->number * 180); -#else - if (learn_skill(u, SK_OBSERVATION, u->number * 180)) { - change_skill(u, SK_OBSERVATION, u->number); - } -#endif + + set_level(u, SK_OBSERVATION, 2); if (u->number == 1) set_string(&u->name, "Ein wütender Ent"); else diff --git a/src/common/gamecode/spy.c b/src/common/gamecode/spy.c index 6a6c2017d..e06074b9a 100644 --- a/src/common/gamecode/spy.c +++ b/src/common/gamecode/spy.c @@ -249,34 +249,34 @@ setstealth(unit * u, strlist * S) } static int -faction_skill(region * r, faction * f, skill_t skill) +faction_skill(region * r, faction * f, skill_t sk) { - int sk = 0; + int value = 0; unit *u; list_foreach(unit, r->units, u) if (u->faction == f) { - int s = eff_skill(u, skill, r); - sk = max(sk, s); + int s = eff_skill(u, sk, r); + value = max(value, s); } list_next(u); - return sk; + return value; } static int -crew_skill(region * r, faction * f, ship * sh, skill_t skill) +crew_skill(region * r, faction * f, ship * sh, skill_t sk) { - int sk = 0; + int value = 0; unit *u; - list_foreach(unit, r->units, u) + for (u=r->units;u;u=u->next) { if (u->ship == sh && u->faction == f) { - sk = eff_skill(u, skill, r); - sk = max(skill, sk); + int s = eff_skill(u, sk, r); + value = max(s, value); } - list_next(u); - return sk; + } + return value; } static int diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c index 85b823fc7..17b3602e9 100644 --- a/src/common/gamecode/study.c +++ b/src/common/gamecode/study.c @@ -112,7 +112,7 @@ study_cost(unit *u, int talent) break; case SK_MAGIC: /* Die Magiekosten betragen 50+Summe(50*Stufe) */ /* 'Stufe' ist dabei die nächste zu erreichende Stufe */ - stufe = 1 + pure_skill(u, SK_MAGIC, u->region); + stufe = 1 + get_level(u, SK_MAGIC); return k*(1+((stufe+1)*stufe/2)); break; } @@ -128,7 +128,8 @@ static const attrib_type at_learning = { }; static int -teach_unit(unit * teacher, unit * student, int teaching, skill_t sk, boolean report) +teach_unit(unit * teacher, unit * student, int teaching, skill_t sk, + boolean report, int * academy) { attrib * a; int n; @@ -172,13 +173,7 @@ teach_unit(unit * teacher, unit * student, int teaching, skill_t sk, boolean rep /* Jeder Schüler zusätzlich +10 Tage wenn in Uni. */ a->data.i += (n / 30) * 10; /* learning erhöhen */ /* Lehrer zusätzlich +1 Tag pro Schüler. */ -#if SKILLPOINTS - change_skill(teacher, sk, n / 30); -#else - if (learn_skill(teacher, sk, n / 30)) { - change_skill(teacher, sk, teacher->number); - } -#endif + if (academy) *academy += n; } /* sonst nehmen sie nicht am Unterricht teil */ } /* Teaching ist die Anzahl Leute, denen man noch was beibringen kann. Da @@ -231,7 +226,7 @@ teach(region * r, unit * u) /* Parameter r gebraucht, um kontrollieren zu können, daß die Ziel-Unit auch * in der selben Region ist (getunit). Lehren vor lernen. */ static char order[BUFSIZE]; - int teaching, i, j, count; + int teaching, i, j, count, academy=0; unit *u2; char *s; skill_t sk; @@ -257,8 +252,7 @@ teach(region * r, unit * u) add_message(&u->faction->msgs, msg_message("teachdumb", "teacher amount", u, j)); } - if (teaching == 0) - return; + if (teaching == 0) return; strcpy(order, locale_string(u->faction->locale, keywords[K_TEACH])); @@ -283,7 +277,7 @@ teach(region * r, unit * u) sk = teachskill[i]; } if (sk != NOSKILL && eff_skill(u, sk, r) > eff_skill(student, sk, r)) { - teaching -= teach_unit(u, student, teaching, sk, true); + teaching -= teach_unit(u, student, teaching, sk, true, &academy); } } } @@ -296,7 +290,7 @@ teach(region * r, unit * u) /* Input ist nun von student->thisorder !! */ sk = getskill(student->faction->locale); if (sk != NOSKILL && eff_skill(u, sk, r) >= eff_skill(student, sk, r)+TEACHDIFFERENCE) { - teaching -= teach_unit(u, student, teaching, sk, true); + teaching -= teach_unit(u, student, teaching, sk, true, &academy); } } } @@ -410,9 +404,17 @@ teach(region * r, unit * u) } } - teaching -= teach_unit(u, u2, teaching, sk, false); + teaching -= teach_unit(u, u2, teaching, sk, false, &academy); } + if (academy) { +#if SKILLPOINTS + change_skill(u, sk, academy / 30); +#else + academy = academy/30; + learn_skill(u, sk, academy/30.0/TEACHNUMBER); +#endif + } } /* ------------------------------------------------------------- */ @@ -649,8 +651,14 @@ learn(void) #if SKILLPOINTS change_skill(u, (skill_t)i, days); #else - if (learn_skill(u, (skill_t)i, days)) { - change_skill(u, (skill_t)i, u->number); + while (days) { + if (days>u->number*30) { + learn_skill(u, (skill_t)i, 1.0); + days -= u->number*30; + } else { + double chance = (double)days/u->number/30; + learn_skill(u, (skill_t)i, chance); + } } #endif if (a) { diff --git a/src/common/items/xerewards.c b/src/common/items/xerewards.c index 8f7445ebc..dc9611e0f 100644 --- a/src/common/items/xerewards.c +++ b/src/common/items/xerewards.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ static int use_skillpotion(struct unit * u, const struct item_type * itype, const char *cm) { +#if SKILLPOINTS skill_t sk; for(sk = 0; sk != MAXSKILLS; sk++) { int skillvalue = get_skill(u, sk)/u->number; @@ -43,6 +45,14 @@ use_skillpotion(struct unit * u, const struct item_type * itype, const char *cm) change_skill(u, sk, change); } } +#else + skill * sv = u->skills; + while (sv!=u->skills+u->skill_size) { + int i; + for (i=0;i!=3;++i) learn_skill(u, sv->id, 1.0); + ++sv; + } +#endif add_message(&u->faction->msgs, new_message(u->faction, "skillpotion_use%u:unit", u)); diff --git a/src/common/kernel/battle.c b/src/common/kernel/battle.c index eef17858c..677fda2c2 100644 --- a/src/common/kernel/battle.c +++ b/src/common/kernel/battle.c @@ -946,7 +946,7 @@ remove_troop(troop dt) /* ------------------------------------------------------------- */ #if SKILLPOINTS -void +static void drain_exp(unit *u, int n) { skill_t sk = (skill_t)(rand() % MAXSKILLS); @@ -954,7 +954,7 @@ drain_exp(unit *u, int n) ssk = sk; - while(get_skill(u, sk) <= 0) { + while (get_skill(u, sk) <= 0) { sk++; if (sk == MAXSKILLS) sk = 0; @@ -968,7 +968,10 @@ drain_exp(unit *u, int n) } } #else -void +/** reduces the target's exp by an equivalent of n points learning + * 30 points = 1 week + */ +static void drain_exp(unit *u, int n) { skill_t sk = (skill_t)(rand() % MAXSKILLS); @@ -976,7 +979,7 @@ drain_exp(unit *u, int n) ssk = sk; - while(get_skill(u, sk) <= 0) { + while (get_level(u, sk)==0) { sk++; if (sk == MAXSKILLS) sk = 0; @@ -986,10 +989,7 @@ drain_exp(unit *u, int n) } } if (sk != NOSKILL) { - n = min(n, get_skill(u, sk)); - if (learn_skill(u, sk, n) { - change_skill(u, sk, -1); - } + change_skillpoints(u, sk, -n); } } #endif diff --git a/src/common/kernel/combatspells.c b/src/common/kernel/combatspells.c index 86fc18d28..fe6872e44 100644 --- a/src/common/kernel/combatspells.c +++ b/src/common/kernel/combatspells.c @@ -486,7 +486,7 @@ random_skill(unit *u) skill_t sk; for(sk=0;skrace) == RC_ELF) m += 1; @@ -324,7 +324,7 @@ count_all_money(const region * r) } int -count_skill(faction * f, skill_t skill) +count_skill(faction * f, skill_t sk) { int n = 0; region *r; @@ -333,9 +333,8 @@ count_skill(faction * f, skill_t skill) for (r = firstregion(f); r != last; r = r->next) for (u = r->units; u; u = u->next) - if (u->faction == f && get_skill(u, skill)) - if(!is_familiar(u)) - n += u->number; + if (u->faction == f && has_skill(u, sk)) + if (!is_familiar(u)) n += u->number; return n; } @@ -663,7 +662,7 @@ eff_stealth (const unit * u, const region * r) void scale_number (unit * u, int n) { - skill_t skill; + skill_t sk; const attrib * a; int remain; @@ -693,19 +692,23 @@ scale_number (unit * u, int n) } data->value = snew; } - for (skill = 0; skill < MAXSKILLS; skill++) { + for (sk = 0; sk < MAXSKILLS; sk++) { if (n==0 || u->number == 0) { - set_level(u, skill, 0); - } else { - int sval = get_skill(u, skill); + set_level(u, sk, 0); + } +#if SKILLPOINTS + /* not necessary to scale in the new system */ + else { + int sval = get_skill(u, sk); int snew = sval / u->number * n; remain = sval - snew / n * u->number; snew += remain * n / u->number; remain = (remain * n) % u->number; if ((rand() % u->number) < remain) ++snew; /* Nachkommastellen */ - set_skill(u, skill, snew); + set_skill(u, sk, snew); } +#endif } set_number(u, n); @@ -965,19 +968,6 @@ strcheck (const char *s, size_t maxlen) return s; } #endif -/* Zaehlfunktionen fuer Typen ------------------------------------- */ - -int -teure_talente (unit * u) -{ - if (get_skill (u, SK_MAGIC) > 0 || get_skill (u, SK_ALCHEMY) > 0 || - get_skill (u, SK_TACTICS) > 0 || get_skill (u, SK_HERBALISM) > 0 || - get_skill (u, SK_SPY) > 0) { - return 0; - } else { - return 1; - } -} attrib_type at_lighthouse = { "lighthouse" @@ -1069,7 +1059,7 @@ igetstrtoken (const char *s1) if (i > 0 && lbuf[i - 1] == ESCAPE_CHAR) lbuf[--i] = SPACE_REPLACEMENT; else - lbuf[i] = SPACE; + lbuf[i] = ' '; } i++; s++; @@ -2009,7 +1999,7 @@ init_tokens(const struct locale * lang) for (i=0;i!=MAXPARAMS;++i) addtoken(&lnames->tokens[UT_PARAM], LOC(lang, parameters[i]), (void*)i); for (i=0;i!=MAXSKILLS;++i) - addtoken(&lnames->skillnames, skillname(i, lang), (void*)i); + addtoken(&lnames->skillnames, skillname((skill_t)i, lang), (void*)i); for (i=0;i!=MAXKEYWORDS;++i) addtoken(&lnames->keywords, LOC(lang, keywords[i]), (void*)i); for (i=0;i!=MAXOPTIONS;++i) @@ -3070,11 +3060,20 @@ produceexp(struct unit * u, skill_t sk, int n) change_skill(u, sk, PRODUCEEXP * n); return 1; #else - if (learn_skill(u, sk, PRODUCEEXP * n)) { - change_skill(u, sk, n); - return 1; - } + learn_skill(u, sk, 30.0/PRODUCEEXP); return 0; #endif } +boolean +teure_talente (const struct unit * u) +{ + if (has_skill(u, SK_MAGIC) || has_skill(u, SK_ALCHEMY) || + has_skill(u, SK_TACTICS) || has_skill(u, SK_HERBALISM) || + has_skill(u, SK_SPY)) { + return true; + } else { + return false; + } +} + diff --git a/src/common/kernel/eressea.h b/src/common/kernel/eressea.h index 03225ccba..d3c88027d 100644 --- a/src/common/kernel/eressea.h +++ b/src/common/kernel/eressea.h @@ -91,7 +91,6 @@ struct xml_stack; #define OLD_FAMILIAR_MOD /* conversion required */ /* feature-dis/en-able */ #undef WEATHER /* Kein Wetter-Modul */ -#undef NEW_UNITS /* unit-split */ #define NEW_DRIVE /* Neuer Algorithmus Transportiere/Fahre */ #define PARTIAL_STUDY /* Wenn nicht genug Silber vorhanden, wird ein Talent anteilig gelernt */ #define HUNGER_REDUCES_SKILL /* Hunger reduziert den Talentwert auf die Hälfte */ @@ -339,7 +338,6 @@ extern void plagues(struct region * r, boolean ismagic); #define ENCCHANCE 10 /* %-Chance für einmalige Zufallsbegegnung */ #define SPACE_REPLACEMENT '~' -#define SPACE ' ' #define ESCAPE_CHAR '\\' #define DISPLAYSIZE 8191 /* max. Länge einer Beschreibung, ohne trailing 0 */ @@ -842,10 +840,6 @@ typedef struct strlist { } strlist; extern int max_unique_id; -typedef struct skillvalue { - skill_t id; - int value; -} skillvalue; #define FL_GUARD (1<<0) /* 1 */ #define FL_ISNEW (1<<1) /* 2 */ @@ -1024,8 +1018,8 @@ char *xunitid(const struct unit * u); struct building *largestbuilding(const struct region * r, boolean img); +extern boolean teure_talente(const struct unit * u); int count_all(const struct faction * f); -int teure_talente(struct unit * u); int count_maxmigrants(const struct faction * f); const struct race * findrace(const char *, const struct locale *); diff --git a/src/common/kernel/item.c b/src/common/kernel/item.c index 0c57875d3..cb24c516d 100644 --- a/src/common/kernel/item.c +++ b/src/common/kernel/item.c @@ -247,7 +247,7 @@ wt_register(weapon_type * wtype) weapon_type * new_weapontype(item_type * itype, - int wflags, double magres, const char* damage[], int offmod, int defmod, int reload, skill_t skill, int minskill) + int wflags, double magres, const char* damage[], int offmod, int defmod, int reload, skill_t sk, int minskill) { weapon_type * wtype; @@ -266,7 +266,7 @@ new_weapontype(item_type * itype, wtype->minskill = minskill; wtype->offmod = offmod; wtype->reload = reload; - wtype->skill = skill; + wtype->skill = sk; wt_register(wtype); return wtype; @@ -850,7 +850,7 @@ use_tacticcrystal(region * r, unit * u, strlist * cmdstrings) } t_item itemdata[MAXITEMS] = { - /* name[4]; typ; skill; minskill; material[6]; gewicht; preis; + /* name[4]; typ; sk; minskill; material[6]; gewicht; preis; * benutze_funktion; */ { /* I_IRON */ {"Eisen", "Eisen", "Eisen", "Eisen"}, G_N, @@ -2102,7 +2102,7 @@ tagbegin(struct xml_stack * stack) state->rtype->flags |= RTF_ITEM; state->itype = new_itemtype(state->rtype, flags, weight, capacity); } else if (strcmp(tag->name, "weapon")==0) { - skill_t skill = sk_find(xml_value(tag, "skill")); + skill_t sk = sk_find(xml_value(tag, "sk")); int minskill = xml_ivalue(tag, "minskill"); int offmod = xml_ivalue(tag, "offmod"); int defmod = xml_ivalue(tag, "defmod"); @@ -2114,7 +2114,7 @@ tagbegin(struct xml_stack * stack) assert(state->itype!=NULL); state->itype->flags |= ITF_WEAPON; state->wtype = new_weapontype(state->itype, - flags, magres, NULL, offmod, defmod, reload, skill, minskill); + flags, magres, NULL, offmod, defmod, reload, sk, minskill); } else if (strcmp(tag->name, "damage")==0) { /* damage of a weapon */ int pos = 0; @@ -2139,7 +2139,7 @@ tagbegin(struct xml_stack * stack) if (xml_bvalue(tag, "offensive")) flags|=WMF_OFFENSIVE; if (xml_bvalue(tag, "defensive")) flags|=WMF_DEFENSIVE; if (xml_bvalue(tag, "damage")) flags|=WMF_DAMAGE; - if (xml_bvalue(tag, "skill")) flags|=WMF_SKILL; + if (xml_bvalue(tag, "sk")) flags|=WMF_SKILL; if (xml_bvalue(tag, "missile_target")) flags|=WMF_MISSILE_TARGET; if (state->wmods) { memcpy(mods, state->wtype->modifiers, sizeof(weapon_mod)*state->wmods); @@ -2559,9 +2559,11 @@ xml_writeitems(const char * file) item_type * it = itemtypes; weapon_type * wt = weapontypes; +/* luxury_type * lt = luxurytypes; potion_type * pt = potiontypes; herb_type * ht = herbtypes; +*/ if (stream==NULL) return -1; fputs("\n", stream); @@ -2630,7 +2632,7 @@ xml_writeitems(const char * file) requirement * cm = ic->materials; fputs("\t\tskill!=NOSKILL) { - fprintf(stream, " skill=\"%s\"", skillname(ic->skill, NULL)); + fprintf(stream, " sk=\"%s\"", skillname(ic->skill, NULL)); if (ic->minskill) fprintf(stream, " minskill=\"%d\"", ic->minskill); } if (ic->reqsize!=1) { @@ -2679,7 +2681,7 @@ xml_writeitems(const char * file) weapon_mod * wm = wt->modifiers; fprintf(stream, "\titype->rtype->_name[0]); if (wt->minskill) fprintf(stream, " minskill=\"%d\"", wt->minskill); - fprintf(stream, " skill=\"%s\"", skillname(wt->skill, NULL)); + fprintf(stream, " sk=\"%s\"", skillname(wt->skill, NULL)); if (wt->defmod) fprintf(stream, " offmod=\"%d\"", wt->offmod); if (wt->offmod) fprintf(stream, " defmod=\"%d\"", wt->defmod); if (wt->reload!=0) fprintf(stream, " reload=\"%d\"", wt->reload); @@ -2702,7 +2704,7 @@ xml_writeitems(const char * file) if (fval(wm, WMF_OFFENSIVE)) fputs(" offensive", stream); if (fval(wm, WMF_DEFENSIVE)) fputs(" defensive", stream); if (fval(wm, WMF_DAMAGE)) fputs(" damage", stream); - if (fval(wm, WMF_SKILL)) fputs(" skill", stream); + if (fval(wm, WMF_SKILL)) fputs(" sk", stream); fputs(">\n", stream); ++wm; } diff --git a/src/common/kernel/item.h b/src/common/kernel/item.h index 0319a8d7d..ebed3e7e2 100644 --- a/src/common/kernel/item.h +++ b/src/common/kernel/item.h @@ -245,7 +245,7 @@ extern int i_get(const item * i, const item_type * it); extern resource_type * new_resourcetype(const char ** names, const char ** appearances, int flags); extern item_type * new_itemtype(resource_type * rtype, int iflags, int weight, int capacity); extern luxury_type * new_luxurytype(item_type * itype, int price); -extern weapon_type * new_weapontype(item_type * itype, int wflags, double magres, const char* damage[], int offmod, int defmod, int reload, skill_t skill, int minskill); +extern weapon_type * new_weapontype(item_type * itype, int wflags, double magres, const char* damage[], int offmod, int defmod, int reload, skill_t sk, int minskill); extern potion_type * new_potiontype(item_type * itype, int level); extern herb_type * new_herbtype(item_type * itype, terrain_t terrain); diff --git a/src/common/kernel/karma.c b/src/common/kernel/karma.c index 3786c8bf3..469b66ee6 100644 --- a/src/common/kernel/karma.c +++ b/src/common/kernel/karma.c @@ -393,7 +393,7 @@ sacrificings(void) cmistake(u, u->thisorder, 214, MSG_EVENT); continue; } - if(pure_skill(u, SK_MAGIC, u->region) < 10) { + if (get_level(u, SK_MAGIC) < 10) { cmistake(u, u->thisorder, 253, MSG_EVENT); continue; } diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index a9f2862f7..630b2683e 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -294,7 +294,7 @@ is_mage(const unit * u) sc_mage * get_mage(const unit * u) { - if (get_skill(u, SK_MAGIC) != 0) { + if (has_skill(u, SK_MAGIC)) { attrib * a = a_find(u->attribs, &at_mage); if (a) return a->data.v; } @@ -3238,7 +3238,7 @@ magic(void) for (r = regions; r; r = r->next) { for (u = r->units; u; u = u->next) { if (is_mage(u) && countspells(u,0) > 0) { - change_skill(u, SK_MAGIC, PRODUCEEXP); + produceexp(u, SK_MAGIC, u->number); /* Spruchlistenaktualiesierung ist in Regeneration */ } } diff --git a/src/common/kernel/reports.c b/src/common/kernel/reports.c index f8b6e1620..167fc1e27 100644 --- a/src/common/kernel/reports.c +++ b/src/common/kernel/reports.c @@ -595,16 +595,15 @@ bufunit_ugroupleader(const faction * f, const unit * u, int indent, int mode) #endif void -spskill(const struct locale * lang, const struct unit * u, skill_t sk, int *dh, int days) +spskill(const struct locale * lang, const struct unit * u, skill_t sk, int *dh, + boolean days) { char * sbuf = buf+strlen(buf); - int i, d; + int i; if (!u->number) return; - d = get_skill(u, sk); - if (!d) - return; + if (!has_skill(u, sk)) return; strcat(sbuf, ", "); sbuf+=2; @@ -631,7 +630,7 @@ spskill(const struct locale * lang, const struct unit * u, skill_t sk, int *dh, #if SKILLPOINTS if (days) { assert(u->number); - sbuf += sprintf(sbuf, " [%d]", d / u->number); + sbuf += sprintf(sbuf, " [%d]", get_skill(u, sk) / u->number); } #endif } @@ -758,7 +757,7 @@ spy_message(int spy, unit *u, unit *target) skill_t sk; for (sk = 0; sk != MAXSKILLS; sk++) { - if (get_skill(target, sk)) { + if (has_skill(target, sk)) { found++; if (first == 1) { first = 0; diff --git a/src/common/kernel/save.c b/src/common/kernel/save.c index 417ab92b8..82fece6a7 100644 --- a/src/common/kernel/save.c +++ b/src/common/kernel/save.c @@ -1452,13 +1452,26 @@ readgame(boolean backup) assert(u->number >= 0); assert(u->race); - +#ifdef CONVERT_SKILLPOINTS while ((sk = (skill_t) ri(F)) != NOSKILL) { - set_skill(u, sk, ri(F)); - if (sk == SK_ALCHEMY) { - /* init_potions(r, u); */ + int skill = ri(F) / u->number; + int lvl = level(skill); + int weeks = (skill - level_days(lvl))/30; + if (weeks || lvl) { + set_skill(u, sk, lvl, weeks); } } +#elif SKILLPOINTS + while ((sk = (skill_t) ri(F)) != NOSKILL) { + set_skill(u, sk, ri(F)); + } +#else + while ((sk = (skill_t) ri(F)) != NOSKILL) { + int level = ri(F); + int weeks = ri(F); + set_skill(u, sk, level, weeks); + } +#endif if (global.data_version>=ITEMTYPE_VERSION) { read_items(F, &u->items); } else { @@ -1478,7 +1491,7 @@ readgame(boolean backup) /* assert(u->hp >= u->number); */ if (global.data_version < MAGE_ATTRIB_VERSION) { if (global.data_version < NEWMAGIC) { - if (get_skill(u, SK_MAGIC) > 0) { + if (has_skill(u, SK_MAGIC)) { /* ist Magier und muss in neuen Magier konvertiert werden */ create_mage(u, u->faction->magiegebiet); /* bekommt anfangs soviel Aura wie er Magie kann */ @@ -1633,9 +1646,16 @@ readgame(boolean backup) } /* ------------------------------------------------------------- */ -#define wc(F, c) putc(c, F) -#define wnl(F) putc('\n', F) -#define wspace(F) putc(' ', F) +#ifndef NDEBUG +int space=0; +# define DOSPACE space=1; +# define UNSPACE space=0; +#endif + +#define wc(F, c) { putc(c, F); UNSPACE } +#define wnl(F) { putc('\n', F); DOSPACE } +#define wspace(F) { assert (!space); putc(' ', F); UNSPACE } +#define whs(F, s) { fputs(s, F); UNSPACE } void wsn(FILE * F, const char *s) @@ -1646,27 +1666,25 @@ wsn(FILE * F, const char *s) wc(F, *s++); } -#define whs(F, s) fputs(s, F) - void ws(FILE * F, const char *s) { - wc(F, '"'); + fputc('"', F); wsn(F, s); - wc(F, '"'); + fputs("\" ", F); DOSPACE } void wi(FILE * F, int n) { - sprintf(buf, "%d", n); - wsn(F, buf); + sprintf(buf, "%d ", n); + wsn(F, buf); DOSPACE } void wi36(FILE * F, int n) { - sprintf(buf, "%s", itoa36(n)); - wsn(F, buf); + sprintf(buf, "%s ", itoa36(n)); + wsn(F, buf); DOSPACE } void @@ -2053,7 +2071,11 @@ writegame(char *path, char quiet) wi(F, listlen(r->units)); wnl(F); for (u = r->units; u; u = u->next) { +#if !SKILLPOINTS || defined(CONVERT_SKILLPOINTS) + int i; +#else skill_t sk; +#endif wid(F, u->no); wspace(F); wid(F, u->faction->no); @@ -2116,14 +2138,28 @@ writegame(char *path, char quiet) assert(u->race); #endif +#if SKILLPOINTS for (sk = 0; sk != MAXSKILLS; sk++) { - if (get_skill(u, sk) > 0) { + if (get_skill(u, sk)) { wi(F, sk); wspace(F); wi(F, get_skill(u, sk)); wspace(F); } } +#else + for (i=0;i!=u->skill_size;++i) { + skill * sv = u->skills+i; + if (sv->learning || sv->level) { + wi(F, sv->id); + wspace(F); + wi(F, sv->level); + wspace(F); + wi(F, sv->learning); + wspace(F); + } + } +#endif wi(F, -1); wnl(F); write_items(F, u->items); diff --git a/src/common/kernel/skill.c b/src/common/kernel/skill.c index 2a45dfe55..418cd4dfb 100644 --- a/src/common/kernel/skill.c +++ b/src/common/kernel/skill.c @@ -26,7 +26,6 @@ #include "unit.h" #include "item.h" #include "magic.h" -#include "plane.h" #include "race.h" #include "curse.h" #include "region.h" @@ -110,12 +109,12 @@ attrib_type at_skillmod = { }; attrib * -make_skillmod(skill_t skill, unsigned int flags, int(*special)(const struct unit*, const struct region*, skill_t, int), double multiplier, int bonus) +make_skillmod(skill_t sk, unsigned int flags, int(*special)(const struct unit*, const struct region*, skill_t, int), double multiplier, int bonus) { attrib * a = a_new(&at_skillmod); skillmod_data * smd = (skillmod_data*)a->data.v; - smd->skill=skill; + smd->skill=sk; smd->special=special; smd->bonus=bonus; smd->multiplier=multiplier; @@ -141,63 +140,6 @@ skillmod(const attrib * a, const unit * u, const region * r, skill_t sk, int val return value; } -int -att_modification(const unit *u, skill_t sk) -{ - curse *c; - unit *mage; - int result = 0; - - result += get_curseeffect(u->attribs, C_ALLSKILLS, 0); - result += get_curseeffect(u->attribs, C_SKILL, (int)sk); - - /* 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); - } - result = result + bonus + malus; - } - - return result; -} - -void -item_modification(const unit *u, skill_t sk, int *val) -{ - /* Presseausweis: *2 Spionage, 0 Tarnung */ - if(sk == SK_SPY && get_item(u, I_PRESSCARD) >= u->number) { - *val = *val * 2; - } - if(sk == SK_STEALTH && get_item(u, I_PRESSCARD) >= u->number) { - *val = 0; - } -} - - int skill_mod(const race * rc, skill_t sk, terrain_t t) { @@ -248,7 +190,7 @@ init_skills(const race * rc) } int -rc_skillmod(const struct race * rc, const region *r, skill_t skill) +rc_skillmod(const struct race * rc, const region *r, skill_t sk) { int mods; unsigned int index = ((unsigned int)rc) % RCMODMAXHASH; @@ -257,9 +199,9 @@ rc_skillmod(const struct race * rc, const region *r, skill_t skill) if (*imods==NULL) { *imods = init_skills(rc); } - mods = (*imods)->mod[rterrain(r)].value[skill]; + mods = (*imods)->mod[rterrain(r)].value[sk]; - if (rc == new_race[RC_ELF] && r_isforest(r)) switch (skill) { + if (rc == new_race[RC_ELF] && r_isforest(r)) switch (sk) { case SK_OBSERVATION: ++mods; break; @@ -314,82 +256,39 @@ level(int days) } #endif -int -eff_skill(const unit * u, skill_t sk, const region * r) +#if !SKILLPOINTS +void +reduce_skill(skill * sv, int change) { - int i, result = 0; - - if (u->number==0) return 0; - if (r->planep && sk == SK_STEALTH && fval(r->planep, PFL_NOSTEALTH)) return 0; - -#if SKILLPOINTS - result = level(get_skill(u, sk) / u->number); -#else - result = get_skill(u, sk) / u->number; -#endif - if (result == 0) return 0; - - assert(r); - result = result + rc_skillmod(u->race, r, sk); - - result += att_modification(u, sk); - item_modification(u, sk, &result); - - i = skillmod(u->attribs, u, r, sk, result, SMF_ALWAYS); - if (i!=result) result = i; - - if (fspecial(u->faction, FS_TELEPATHY)) { - switch(sk) { - case SK_ALCHEMY: - case SK_HERBALISM: - case SK_MAGIC: - case SK_SPY: - case SK_STEALTH: - case SK_OBSERVATION: - break; - default: - result -= 2; + int weeks = (sv->level * sv->level - sv->level) / 2 + sv->learning; + if (sv->learning>=change) { + /* just forget a few weeks */ + weeks -= change; + } else { + change -= sv->learning; + while (change>=sv->level && sv->level > 0) { + change -= sv->level; + --sv->level; + } + if (change && changelevel) { + /* this is not an exact science... it would be better to set + * sv->learning so that the average time to rise was = change. + */ + weeks = (sv->level-change)*2; + } else { + weeks = 0; } } - -#ifdef HUNGER_REDUCES_SKILL - if (fval(u, FL_HUNGER)) result = result/2; -#endif - return max(result, 0); + sv->learning = (unsigned char)weeks; } -int -pure_skill(unit * u, skill_t sk, region * r) +int +skill_compare(const skill * sk, const skill * sc) { - int result = 0; - unused(r); - - if (u->number==0) return 0; - -#if SKILLPOINTS - result = level(get_skill(u, sk) / u->number); -#else - result = get_skill(u, sk) / u->number; + if (sk->level > sc->level) return 1; + if (sk->level < sc->level) return -1; + if (sk->learning > sc->learning) return 1; + if (sk->learning < sc->learning) return -1; + return 0; +} #endif - - return max(result, 0); -} - -void -remove_zero_skills(void) -{ - region *r; - unit *u; - skill_t sk; - - for(r=regions; r; r=r->next) { - for(u=r->units; u; u=u->next) { - for (sk = 0; sk != MAXSKILLS; sk++) { - if (get_skill(u, sk) < u->number) { - set_level(u, sk, 0); - } - } - } - } -} - diff --git a/src/common/kernel/skill.h b/src/common/kernel/skill.h index 6959c0573..da9935050 100644 --- a/src/common/kernel/skill.h +++ b/src/common/kernel/skill.h @@ -16,33 +16,49 @@ #define SKILL_H extern signed char skill_bonus(struct unit * u, struct region * r); -int eff_skill(const struct unit * u, skill_t sk, const struct region * r); - -int pure_skill(struct unit * u, skill_t sk, struct region * r); /* skillmod_data::flags -- wann gilt der modifier? */ #define SMF_ALWAYS (1<<0) /* immer */ #define SMF_PRODUCTION (1<<1) /* für Produktion - am gebäude, an der einheit */ #define SMF_RIDING (1<<2) /* Bonus für berittene - an der rasse*/ +typedef struct skill { +#if SKILLPOINTS + skill_t id; + int value; +#else + unsigned char id; + unsigned char level; + unsigned char learning; +#endif +} skill; + typedef struct skillmod_data { skill_t skill; - int (*special)(const struct unit * u, const struct region * r, skill_t skill, int value); + int (*special)(const struct unit * u, const struct region * r, skill_t sk, int value); double multiplier; int bonus; int flags; } skillmod_data; extern attrib_type at_skillmod; -extern int rc_skillmod(const struct race * rc, const struct region *r, skill_t skill); +extern int rc_skillmod(const struct race * rc, const struct region *r, skill_t sk); extern int skillmod(const attrib * a, const struct unit * u, const struct region * r, skill_t sk, int value, int flags); extern void skill_init(void); extern void skill_done(void); -extern struct attrib * make_skillmod(skill_t skill, unsigned int flags, int(*special)(const struct unit*, const struct region*, skill_t, int), double multiplier, int bonus); +extern struct attrib * make_skillmod(skill_t sk, unsigned int flags, int(*special)(const struct unit*, const struct region*, skill_t, int), double multiplier, int bonus); extern const char * skillname(skill_t, const struct locale *); extern skill_t sk_find(const char * name); extern int level_days(int level); -extern void remove_zero_skills(void); + +#if SKILLPOINTS +# define skill_level(level) level_days(level) +#else +# define skill_level(level) (level) +extern void reduce_skill(skill * sv, int change); +extern int skill_compare(const skill * sk, const skill * sc); +#endif + #endif diff --git a/src/common/kernel/spell.c b/src/common/kernel/spell.c index e99fc4c88..7139a35cc 100644 --- a/src/common/kernel/spell.c +++ b/src/common/kernel/spell.c @@ -124,7 +124,11 @@ report_failure(unit * mage, const char * sa) { void do_shock(unit *u, char *reason) { +#if SKILLPOINTS skill_t sk; +#else + int i; +#endif if(u->number == 0) return; /* HP - Verlust */ @@ -144,11 +148,11 @@ do_shock(unit *u, char *reason) } } #else - for (sk=0; sk < MAXSKILLS; sk++) { - int n = get_skill(u, sk); - if (n!=0 && rand()%10 < 2) { - change_level(u, sk, -1); - } + for (i=0;i!=u->skill_size;++i) if (rand()%5==0) { + skill * sv = u->skills+i; + int weeks = (sv->level * sv->level - sv->level) / 2 + sv->learning; + int change = (weeks+9) / 10; + reduce_skill(sv, change); } #endif @@ -3382,7 +3386,7 @@ sp_summonshadow(castorder *co) fset(u, FL_PARTEITARNUNG); /* Bekommen Tarnung = (Magie+Tarnung)/2 und Wahrnehmung 1. */ - val = (get_skill(mage, SK_MAGIC) + get_skill(mage, SK_STEALTH))/(2*mage->number); + val = get_level(mage, SK_MAGIC) + get_level(mage, SK_STEALTH); set_level(u, SK_STEALTH, val); set_level(u, SK_OBSERVATION, 1); @@ -4244,10 +4248,7 @@ sp_migranten(castorder *co) return 0; } /* niemand mit teurem Talent */ - if (get_skill(target, SK_MAGIC) || get_skill(target, SK_ALCHEMY) - || get_skill(target, SK_TACTICS) || get_skill(target, SK_SPY) - || get_skill(target, SK_HERBALISM)) - { + if (teure_talente(target)) { sprintf(buf, "%s hat unaufkündbare Bindungen an seine alte Partei.", unitname(target)); addmessage(0, mage->faction, buf, MSG_EVENT, ML_WARN); @@ -4698,10 +4699,16 @@ sp_calm_monster(castorder *co) static int sp_headache(castorder *co) { - unit *target; - skill_t i, sk = 0; +#if SKILLPOINTS + skill_t sk = 0; + skill_t i; int sk_val = 0; int days; +#else + skill * smax = NULL; + int i; +#endif + unit *target; region *r = co->rt; unit *mage = (unit *)co->magician; spellparameter *pa = co->par; @@ -4715,21 +4722,30 @@ sp_headache(castorder *co) target = pa->param[0]->data.u; /* Zieleinheit */ +#if SKILLPOINTS /* finde das größte Talent: */ - for(i=0;inumber) * lovar(60); -#if SKILLPOINTS + days = min(10, target->number) * lovar(60); change_skill(target, sk, -days); #else - if (learn_skill(target, sk, days)) { - change_skill(target, sk, -1); + /* finde das größte Talent: */ + for (i=0;i!=target->skill_size;++i) { + skill * sv = target->skills+i; + if (smax==NULL || skill_compare(sv, smax)>0) { + smax = sv; + } + } + if (smax!=NULL) { + /* wirkt auf maximal 10 Personen */ + int change = min(10, target->number) * (rand()%2+1) / target->number; + reduce_skill(smax, change); } #endif set_string(&target->thisorder, ""); diff --git a/src/common/kernel/unit.c b/src/common/kernel/unit.c index 10683fb51..2fd0546e7 100644 --- a/src/common/kernel/unit.c +++ b/src/common/kernel/unit.c @@ -25,11 +25,12 @@ #include "building.h" #include "faction.h" -#include "goodies.h" #include "group.h" +#include "karma.h" #include "border.h" #include "item.h" #include "movement.h" +#include "plane.h" #include "race.h" #include "region.h" #include "ship.h" @@ -38,9 +39,10 @@ #include /* util includes */ -#include #include #include +#include +#include #ifdef OLD_TRIGGER # include #endif @@ -494,10 +496,11 @@ u_geteffstealth(const struct unit * u) return (a?a->data.i:-1); } +#if SKILLPOINTS int change_skill(unit * u, skill_t id, int byvalue) { - skillvalue *i = u->skills; + skill *i = u->skills; int wounds = 0; if (id == SK_AUSDAUER) { @@ -523,7 +526,7 @@ change_skill(unit * u, skill_t id, int byvalue) static int change_skill_transfermen(unit * u, skill_t id, int byvalue) { - skillvalue *i = u->skills; + skill *i = u->skills; for (; i != u->skills + u->skill_size; ++i) if (i->id == id) { @@ -539,7 +542,7 @@ change_skill_transfermen(unit * u, skill_t id, int byvalue) int get_skill(const unit * u, skill_t id) { - skillvalue *i = u->skills; + skill *i = u->skills; for (; i != u->skills + u->skill_size; ++i) if (i->id == id) @@ -547,38 +550,10 @@ get_skill(const unit * u, skill_t id) return 0; } -#if SKILLPOINTS -extern int level(int days); -#endif - -int -get_level(const unit * u, skill_t id) -{ - skillvalue *i = u->skills; - for (; i != u->skills + u->skill_size; ++i) - if (i->id == id) -#if SKILLPOINTS - return level(i->value/u->number); -#else - return i->value/u->number; -#endif - return 0; -} - -void -set_level(unit * u, skill_t id, int value) -{ -#if SKILLPOINTS - set_skill(u, id, level_days(value)*u->number); -#else - set_skill(u, id, u->number*value); -#endif -} - void set_skill(unit * u, skill_t id, int value) { - skillvalue *i = u->skills; + skill *i = u->skills; assert(value>=0); for (; i != u->skills + u->skill_size; ++i) @@ -594,11 +569,50 @@ set_skill(unit * u, skill_t id, int value) if (!value) return; ++u->skill_size; - u->skills = realloc(u->skills, u->skill_size * sizeof(skillvalue)); + u->skills = realloc(u->skills, u->skill_size * sizeof(skill)); (u->skills + u->skill_size - 1)->value = value; (u->skills + u->skill_size - 1)->id = id; } +#endif + +#if SKILLPOINTS +extern int level(int days); +#endif + +int +get_level(const unit * u, skill_t id) +{ + skill * sv = u->skills; + while (sv != u->skills + u->skill_size) { + if (sv->id == id) { +#if SKILLPOINTS + return level(sv->value/u->number); +#else + return sv->level; +#endif + } + ++sv; + } + return 0; +} + +void +set_level(unit * u, skill_t id, int value) +{ +#if SKILLPOINTS + set_skill(u, id, level_days(value)*u->number); +#else + skill * sv = u->skills; + while (sv != u->skills + u->skill_size) { + if (sv->id == id) { + sv->level = (unsigned char)value; + sv->learning = 0; + } + } +#endif +} + static attrib_type at_leftship = { "leftship", }; @@ -741,10 +755,11 @@ move_unit(unit * u, region * r, unit ** ulist) void transfermen(unit * u, unit * u2, int n) { - skill_t sk; - const attrib * a; +#if SKILLPOINTS int skills[MAXSKILLS]; - int hp = 0; +#endif + const attrib * a; + int hp = u->hp; region * r = u->region; if (!n) return; @@ -752,36 +767,51 @@ transfermen(unit * u, unit * u2, int n) /* "hat attackiert"-status wird übergeben */ if (u2) { - if (fval(u, FL_LONGACTION)) fset(u2, FL_LONGACTION); - hp = u->hp; - if (u->skills) - for (sk = 0; sk < MAXSKILLS; ++sk) +#if SKILLPOINTS + skill_t sk; + if (u->skills) { + for (sk = 0; sk < MAXSKILLS; ++sk) { skills[sk] = get_skill(u, sk); + } + } +#else + skill * sv; + for (sv=u->skills;sv!=u->skills+u->skill_size;++sv) { + if (u2->number == 0) { + set_skill(u2, sv->id, sv->level, sv->learning); + } else { + skill * sn = get_skill(u2, sv->id); + sn->level = (unsigned char)((sv->level*n+sn->level*u2->number)/(u2->number+n)); + if (sn->learning>sv->learning) sn->learning=sv->learning; + } + } +#endif a = a_find(u->attribs, &at_effect); while (a) { effect_data * olde = (effect_data*)a->data.v; change_effect(u2, olde->type, olde->value); a = a->nexttype; } - if (is_mage(u)) { - /* Magier sind immer 1-Personeneinheiten und können nicht - * übergeben werden. Sollte bereits in givemen abgefangen - * werden */ - } + if (fval(u, FL_LONGACTION)) fset(u2, FL_LONGACTION); if (u->attribs) { transfer_curse(u, u2, n); } } scale_number(u, u->number - n); if (u2) { +#if SKILLPOINTS + skill_t sk; +#endif set_number(u2, u2->number + n); hp -= u->hp; u2->hp += hp; +#if SKILLPOINTS if (u->skills) { for (sk = 0; sk < MAXSKILLS; ++sk) { change_skill_transfermen(u2, sk, skills[sk] - get_skill(u, sk)); } } +#endif /* TODO: Das ist schnarchlahm! und gehört ncht hierhin */ a = a_find(u2->attribs, &at_effect); while (a) { @@ -879,15 +909,143 @@ set_number(unit * u, int count) #if !SKILLPOINTS boolean -learn_skill(const unit * u, skill_t sk, int days) +learn_skill(const unit * u, skill_t sk, double chance) { - int now = get_skill(u, sk); - int nowlvl = now / u->number; - int need = (nowlvl+1) * u->number - now; - int needdays = level_days(nowlvl+1) - level_days(nowlvl); - needdays = needdays * u->number / need; - if ((rand()%needdays) < days) return true; + /** rewrite me **/ + assert(!"rewrite me!"); + return 0; +} + +skill * +get_skill(unit * u, skill_t sk) +{ + skill * sv = u->skills; + while (sv!=u->skills+u->skill_size) { + assert(sv->level>=0 && sv->learning>=0); + if (sv->id==sk) return sv; + ++sv; + } + return NULL; +} + +boolean +has_skill(unit * u, skill_t sk) +{ + skill * sv = u->skills; + while (sv!=u->skills+u->skill_size) { + assert(sv->level>=0 && sv->learning>=0); + if (sv->id==sk) { + return (sv->level>0 || sv->learning>0); + } + ++sv; + } return false; } + #endif +static int +item_modification(const unit *u, skill_t sk, int val) +{ + /* Presseausweis: *2 Spionage, 0 Tarnung */ + if(sk == SK_SPY && get_item(u, I_PRESSCARD) >= u->number) { + val = val * 2; + } + if(sk == SK_STEALTH && get_item(u, I_PRESSCARD) >= u->number) { + val = 0; + } + return val; +} + +static int +att_modification(const unit *u, skill_t sk) +{ + curse *c; + unit *mage; + int result = 0; + + result += get_curseeffect(u->attribs, C_ALLSKILLS, 0); + result += get_curseeffect(u->attribs, C_SKILL, (int)sk); + + /* 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); + } + result = result + bonus + malus; + } + + return result; +} + +int +get_modifier(const unit * u, skill_t sk, int level, const region * r) +{ + int bskill = level; + int skill = bskill; + + if (r->planep && sk == SK_STEALTH && fval(r->planep, PFL_NOSTEALTH)) return 0; + + assert(r); + skill += rc_skillmod(u->race, r, sk); + skill += att_modification(u, sk); + + skill = item_modification(u, sk, skill); + skill = skillmod(u->attribs, u, r, sk, skill, SMF_ALWAYS); + + if (fspecial(u->faction, FS_TELEPATHY)) { + switch(sk) { + case SK_ALCHEMY: + case SK_HERBALISM: + case SK_MAGIC: + case SK_SPY: + case SK_STEALTH: + case SK_OBSERVATION: + break; + default: + skill -= 2; + } + } + +#ifdef HUNGER_REDUCES_SKILL + if (fval(u, FL_HUNGER)) { + skill = skill/2; + } +#endif + return skill - bskill; +} + +int +eff_skill(const unit * u, skill_t sk, const region * r) +{ + int level = get_level(u, sk); + int mlevel = level - get_modifier(u, sk, level, r); + +#if SKILLPOINTS + if (mlevel<0) return 0; +#endif + return mlevel; +} diff --git a/src/common/kernel/unit.h b/src/common/kernel/unit.h index 15eaf46fd..085c95448 100644 --- a/src/common/kernel/unit.h +++ b/src/common/kernel/unit.h @@ -22,54 +22,7 @@ #ifndef UNIT_H #define UNIT_H -#ifdef NEW_UNITS -typedef struct party { - struct party *next; - struct party *nexthash; - struct party *nextF; /* nächste Einheit der Partei */ - struct party *prevF; /* letzte Einheit der Partei */ - int no; - char *name; - char *display; - short age; - struct region *region; - struct faction *faction; - struct building *building; - struct ship *ship; - struct strlist *orders; - struct strlist *botschaften; - int n; - int wants; - struct race * race; - struct race * irace; - char *thisorder; - char *lastorder; - struct item * items; - struct reservation { - struct reservation * next; - const struct resource_type * type; - int value; - } * reservations; - struct unit *units; /* new */ - struct attrib * attribs; -} party; - -typedef struct unit { - struct unit *next; /* new */ - struct party *party; - int no; - int number; - int hp; - int skill_size; - struct skillvalue *skills; - struct strlist *orders; /* new */ - struct attrib *attribs; /* new */ - unsigned int flags; - char effstealth; - status_t status; -} struct unit; - -#else +struct skill; typedef struct unit { struct unit *next; @@ -89,7 +42,7 @@ typedef struct unit { char *thisorder; char *lastorder; int skill_size; - struct skillvalue *skills; + struct skill *skills; struct item * items; struct reservation { struct reservation * next; @@ -111,7 +64,6 @@ typedef struct unit { int n; /* enno: attribut? */ int wants; /* enno: attribut? */ } unit; -#endif extern attrib_type at_alias; extern attrib_type at_siege; @@ -157,14 +109,27 @@ extern const struct unit u_unknown; extern struct unit * udestroy; +#if SKILLPOINTS extern int change_skill(struct unit * u, skill_t id, int byvalue); -extern int change_level(struct unit * u, skill_t id, int bylevel); extern void set_skill(struct unit * u, skill_t id, int value); -extern void set_level(struct unit * u, skill_t id, int level); extern int get_skill(const struct unit * u, skill_t id); +#define has_skill(u, id) (get_skill(u, id)>0) +#define change_level(u, sk, bylevel) set_level(u, sk, max(0,get_level(u,sk)+bylevel)); +#else +extern void set_skill(struct unit * u, skill_t id, int level, int weeks); +extern struct skill * get_skill(struct unit * u, skill_t id); +extern boolean has_skill(const unit* u, skill_t sk); +extern int change_level(struct unit * u, skill_t id, int bylevel); +#endif + +extern int change_skillpoints(struct unit * u, skill_t id, int byvalue); +extern void set_level(struct unit * u, skill_t id, int level); extern int get_level(const struct unit * u, skill_t id); extern void transfermen(struct unit * u, struct unit * u2, int n); +extern int eff_skill(const struct unit * u, skill_t sk, const struct region * r); +extern int get_modifier(const struct unit * u, skill_t sk, int lvl, const struct region * r); + #undef DESTROY /* Einheiten werden nicht wirklich zerstört. */ @@ -194,7 +159,7 @@ extern void u_setfaction(struct unit * u, struct faction * f); extern void set_number(struct unit * u, int count); #if !SKILLPOINTS -extern boolean learn_skill(const struct unit * u, skill_t sk, int days); +extern boolean learn_skill(const struct unit * u, skill_t sk, double chance); #endif #endif diff --git a/src/common/modules/arena.c b/src/common/modules/arena.c index 47e758fbc..8fd503ba8 100644 --- a/src/common/modules/arena.c +++ b/src/common/modules/arena.c @@ -26,18 +26,19 @@ #include /* kernel includes */ -#include +#include #include #include -#include +#include #include -#include +#include #include #include -#include -#include -#include #include +#include +#include +#include +#include /* util include */ #include @@ -129,7 +130,7 @@ enter_arena(unit * u, const item_type * itype, const char * cmd) if (u->number!=1 && enter_fail(u)) return -1; if (get_pooled(u, r, R_SILVER) < fee && enter_fail(u)) return -1; for (sk=0;sk!=MAXSKILLS;++sk) { - if (get_skill(u, sk)>30 && enter_fail(u)) return -1; + if (get_level(u, sk)>1 && enter_fail(u)) return -1; } for (u2=r->units;u2;u2=u2->next) if (u2->faction==u->faction) break; #ifdef NEW_ITEMS @@ -185,14 +186,21 @@ use_wand_of_tears(unit * user, const struct item_type * itype, const char * cmd) unused(cmd); for (u=user->region->units;u;u=u->next) { if (u->faction != user->faction) { - int i; + int i, k=SKILLPOINTS; - for (i=0;i!=u->skill_size;++i) + for (i=0;i!=u->skill_size;++i) { +#if SKILLPOINTS change_skill(u, u->skills[i].id, -10); - add_message(&u->faction->msgs, new_message(u->faction, "wand_of_tears_effect%u:unit", u)); +#else + if (rand()%3) reduce_skill(u->skills+i, 1); +#endif + } + if (k) ADDMSG(&u->faction->msgs, msg_message("wand_of_tears_effect", + "unit", u)); } } - add_message(&user->region->msgs, new_message(NULL, "wand_of_tears_usage%u:unit", user)); + ADDMSG(&user->region->msgs, msg_message("wand_of_tears_usage", + "unit", user)); return 0; } diff --git a/src/common/settings-eressea.h b/src/common/settings-eressea.h index cf700f8d4..0f55f36a3 100644 --- a/src/common/settings-eressea.h +++ b/src/common/settings-eressea.h @@ -24,7 +24,13 @@ #define REDUCED_PEASANTGROWTH 0 #define RACE_ADJUSTMENTS 1 -#define SKILLPOINTS 1 #define TEACHDIFFERENCE 1 #define PEASANT_ADJUSTMENT 1 + +#define SKILLPOINTS 1 +#undef CONVERT_SKILLPOINTS + +#if defined(CONVERT_SKILLPOINTS) && !SKILLPOINTS +# error "cannot have both CONVERT_SKILLPOINTS && !SKILLPOINTS" +#endif diff --git a/src/common/util/xml.c b/src/common/util/xml.c index 4d8fcc19a..fc7ee36fe 100644 --- a/src/common/util/xml.c +++ b/src/common/util/xml.c @@ -114,7 +114,6 @@ xml_register(struct xml_callbacks * cb, const char * path, unsigned int flags) { xml_hierarchy ** node=&callbacks; xml_hierarchy * parent = NULL; - size_t len = strlen(path); for (;;) { const char * nextspace = path; diff --git a/src/eressea/korrektur.c b/src/eressea/korrektur.c index 73584c49b..1d488c84e 100644 --- a/src/eressea/korrektur.c +++ b/src/eressea/korrektur.c @@ -122,46 +122,6 @@ verify_owners(boolean bOnce) } } -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 = find_key(global.attribs, magic); - if (a) { - log_warning(("[fix_skills] function was called a second time\n")); - return; - } - a_add(&global.attribs, make_key(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) \ { \ @@ -2416,32 +2376,6 @@ dump_sql(void) return 0; } -static int -fix_ratfamiliar(void) -{ - region *r; - unit *u; - - for(r=regions; r; r=r->next) { - for(u=r->units; u; u=u->next){ - if (old_race(u->race) == RC_RAT){ - if (u->number > 1){ - int mod = skill_level(1); - scale_number(u, 1); - set_skill(u, SK_MAGIC, get_skill(u, SK_MAGIC)+mod); - create_mage(u, M_GRAU); - set_skill(u, SK_SPY, get_skill(u, SK_SPY)+mod); - set_skill(u, SK_STEALTH, get_skill(u, SK_STEALTH)+mod); - set_skill(u, SK_OBSERVATION, get_skill(u, SK_OBSERVATION)+mod); - set_skill(u, SK_AUSDAUER, get_skill(u, SK_AUSDAUER)+skill_level(3)); - u->hp = unit_max_hp(u); - } - } - } - } - return 0; -} - #if NEW_RESOURCEGROWTH static int randomized_resources(void) @@ -2661,47 +2595,6 @@ fix_astralplane(void) return 0; } -#if SKILLPOINTS == 0 -static int -level(int days) -{ - int l = 0; - while (level_days(l)<=days) ++l; - return l-1; -} -#endif - -#if defined(CONVERT_SKILLPOINTS) || !SKILLPOINTS -static int -convert_skills(void) -{ - region * r; - for (r=regions;r;r=r->next) { - unit * u; - for (u=r->units;u;u=u->next) { - skill_t sk; - for (sk=0;sk!=MAXSKILLS;++sk) { - int val = get_skill(u, sk); - if (val) { - int lvl = level(val/u->number); - int days = val-level_days(lvl)*u->number; - set_skill(u, sk, lvl * u->number); - /* hat die Einheit mehr Lerntage als notwendig für den Skill, - * bekommt sie einen Bonus Lernversuch (die chance ist umso - * besser, je mehr tage sie hat) */ - if (days) { - if (learn_skill(u, sk, days)){ - change_skill(u,sk, u->number); - } - } - } - } - } - } - return 0; -} -#endif - static int fix_questcoors(void) { @@ -2729,9 +2622,6 @@ korrektur(void) { #if TEST_LOCALES setup_locales(); -#endif -#if !SKILLPOINTS - do_once("nskp", convert_skills()); #endif fix_astralplane(); fix_firewalls(); @@ -2751,9 +2641,6 @@ korrektur(void) fix_allies(); update_gmquests(); /* test gm quests */ /* fix_unitrefs(); */ -#ifndef SKILLFIX_SAVE - fix_skills(); -#endif stats(); do_once("sql2", dump_sql()); #if NEW_RESOURCEGROWTH @@ -2766,7 +2653,6 @@ korrektur(void) do_once("grtr", growing_trees()); #endif - do_once("grat", fix_ratfamiliar()); do_once("fgms", fix_gms()); #if NEW_RESOURCEGROWTH do_once("rndr", randomized_resources()); diff --git a/src/res/de/messages.xml b/src/res/de/messages.xml index 8e3bacca2..e0ab39327 100644 --- a/src/res/de/messages.xml +++ b/src/res/de/messages.xml @@ -4513,17 +4513,14 @@ - + - + - - - "$unit($unit) vergißt durch Dumpfbackenbrot $int($days) Tage des Talentes $skill($skill)." - - + "$unit($unit) vergißt durch Dumpfbackenbrot $int($weeks) Wochen des Talentes $skill($skill)." + "$unit($unit) eats a Dumpfbackenbrot and forgets $int($weeks) weeks worth of $skill($skill)."