Skillsystem, 3. Version

Das linkt momentan wegen zwei fehlenden Funktionen noch nicht, die ich morgen nachreiche. Alte Varainte kompoiliert und linkt aber, also einfach nicht an den defines spielen im Moment.
This commit is contained in:
Enno Rehling 2002-02-15 16:13:30 +00:00
parent 2a76e58542
commit 1aa45368a5
28 changed files with 611 additions and 628 deletions

View file

@ -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
}

View file

@ -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;
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -20,6 +20,7 @@
#include <region.h>
#include <faction.h>
#include <unit.h>
#include <skill.h>
#include <curse.h>
#include <message.h>
#include <magic.h>
@ -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));

View file

@ -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

View file

@ -486,7 +486,7 @@ random_skill(unit *u)
skill_t sk;
for(sk=0;sk<MAXSKILLS;sk++) {
if(get_skill(u, sk)) n++;
if (get_level(u, sk)) n++;
}
if(n == 0)
@ -495,7 +495,7 @@ random_skill(unit *u)
n = rand()%n;
for(sk=0;sk<MAXSKILLS;sk++) {
if(get_skill(u, sk)) {
if (get_level(u, sk)) {
if(n == 0) return sk;
n--;
}
@ -542,9 +542,7 @@ sp_mindblast(fighter * fi, int level, int power, spell * sp)
#if SKILLPOINTS
change_skill(du, sk, -(30+rand()%61));
#else
if (learn_skill(du, sk, 30+rand()%61)) {
change_skill(du, sk, -1);
}
change_skillpoints(du, sk, -(30+rand()%61));
#endif
--enemies;
} else {

View file

@ -275,11 +275,11 @@ const char *options[MAXOPTIONS] =
};
int
max_skill(faction * f, skill_t skill)
max_skill(faction * f, skill_t sk)
{
int m = INT_MAX;
switch (skill) {
switch (sk) {
case SK_MAGIC:
m = MAXMAGICIANS;
if (old_race(f->race) == 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;
}
}

View file

@ -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 *);

View file

@ -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("<resources>\n", stream);
@ -2630,7 +2632,7 @@ xml_writeitems(const char * file)
requirement * cm = ic->materials;
fputs("\t\t<construction", stream);
if (ic->skill!=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, "\t<weapon resource=\"%s\"", wt->itype->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("></modifier>\n", stream);
++wm;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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 */
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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 && change<sv->level) {
/* 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);
}
}
}
}
}

View file

@ -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

View file

@ -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;i<MAXSKILLS;i++){
int t = get_skill(target, i);
if (sk_val < t){
for (i=0;i<MAXSKILLS;i++){
int l = get_level(target, i);
if (sk_val < l) {
sk = i;
sk_val = t;
sk_val = l;
}
}
/* wirkt auf maximal 10 Personen */
days = min(10,target->number) * 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, "");

View file

@ -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 <attributes/moved.h>
/* util includes */
#include <resolve.h>
#include <base36.h>
#include <event.h>
#include <goodies.h>
#include <resolve.h>
#ifdef OLD_TRIGGER
# include <old/trigger.h>
#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;
}

View file

@ -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

View file

@ -26,18 +26,19 @@
#include <items/demonseye.h>
/* kernel includes */
#include <unit.h>
#include <building.h>
#include <faction.h>
#include <item.h>
#include <movement.h>
#include <magic.h>
#include <message.h>
#include <reports.h>
#include <movement.h>
#include <plane.h>
#include <pool.h>
#include <region.h>
#include <building.h>
#include <magic.h>
#include <race.h>
#include <region.h>
#include <reports.h>
#include <skill.h>
#include <unit.h>
/* util include */
#include <base36.h>
@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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());

View file

@ -4513,17 +4513,14 @@
</locale>
</message>
<message name="dumbeffect">
<message name="dumbeffect" section="events">
<type>
<arg name="unit" type="unit"></arg>
<arg name="days" type="int"></arg>
<arg name="weeks" type="int"></arg>
<arg name="skill" type="skill"></arg>
</type>
<locale name="de">
<nr section="events">
<text>"$unit($unit) vergißt durch Dumpfbackenbrot $int($days) Tage des Talentes $skill($skill)."</text>
</nr>
</locale>
<text locale="de">"$unit($unit) vergißt durch Dumpfbackenbrot $int($weeks) Wochen des Talentes $skill($skill)."</text>
<text locale="en">"$unit($unit) eats a Dumpfbackenbrot and forgets $int($weeks) weeks worth of $skill($skill)."</text>
</message>
<message name="donation">