forked from github/server
fix the academy make academy, curses and potions work for LERNE AUTO remove E3 study.speedup
This commit is contained in:
parent
940e56b6ef
commit
f78aa507f8
|
@ -67,7 +67,6 @@
|
||||||
"init_spells": 0,
|
"init_spells": 0,
|
||||||
"recruit.allow_merge": true,
|
"recruit.allow_merge": true,
|
||||||
"study.expensivemigrants": true,
|
"study.expensivemigrants": true,
|
||||||
"study.speedup": 2,
|
|
||||||
"game.era": 3,
|
"game.era": 3,
|
||||||
"game.start": 1,
|
"game.start": 1,
|
||||||
"rules.reserve.twophase": true,
|
"rules.reserve.twophase": true,
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
void academy_teaching_bonus(struct unit *u, skill_t sk, int students) {
|
void academy_teaching_bonus(struct unit *u, skill_t sk, int students) {
|
||||||
if (students > 0 && sk != NOSKILL) {
|
if (students > 0 && sk != NOSKILL) {
|
||||||
/* actually students * EXPERIENCEDAYS / MAX_STUDENTS */
|
/* actually students * EXPERIENCEDAYS / MAX_STUDENTS */
|
||||||
learn_skill(u, sk, students);
|
change_skill_days(u, sk, students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "kernel/order.h"
|
#include "kernel/order.h"
|
||||||
#include "kernel/region.h"
|
#include "kernel/region.h"
|
||||||
#include "kernel/unit.h"
|
#include "kernel/unit.h"
|
||||||
|
#include "kernel/pool.h"
|
||||||
|
#include "kernel/item.h"
|
||||||
|
|
||||||
#include "util/keyword.h"
|
#include "util/keyword.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
@ -210,7 +212,12 @@ void do_autostudy(region *r)
|
||||||
autostudy_run(scholars, nscholars);
|
autostudy_run(scholars, nscholars);
|
||||||
for (i = 0; i != nscholars; ++i) {
|
for (i = 0; i != nscholars; ++i) {
|
||||||
int days = STUDYDAYS * scholars[i].learn;
|
int days = STUDYDAYS * scholars[i].learn;
|
||||||
learn_skill(scholars[i].u, skill, days);
|
int money = learn_skill(scholars[i].u, skill, days, 0);
|
||||||
|
if (money > 0) {
|
||||||
|
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money);
|
||||||
|
ADDMSG(&u->faction->msgs, msg_message("studycost",
|
||||||
|
"unit region cost skill", u, u->region, money, skill));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -899,7 +899,7 @@ void drain_exp(struct unit *u, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sk != NOSKILL) {
|
if (sk != NOSKILL) {
|
||||||
reduce_skill_days(u, sk, n);
|
change_skill_days(u, sk, -n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,18 +310,6 @@ static int tolua_create_curse(lua_State * L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_learn_skill(lua_State * L)
|
|
||||||
{
|
|
||||||
unit *u = (unit *)tolua_tousertype(L, 1, 0);
|
|
||||||
const char *skname = tolua_tostring(L, 2, 0);
|
|
||||||
int days = (int)tolua_tonumber(L, 3, 0);
|
|
||||||
skill_t sk = findskill(skname);
|
|
||||||
if (sk != NOSKILL) {
|
|
||||||
learn_skill(u, sk, days);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tolua_update_scores(lua_State * L)
|
static int tolua_update_scores(lua_State * L)
|
||||||
{
|
{
|
||||||
UNUSED_ARG(L);
|
UNUSED_ARG(L);
|
||||||
|
@ -973,7 +961,6 @@ int tolua_bindings_open(lua_State * L, const dictionary *inifile)
|
||||||
tolua_function(L, TOLUA_CAST "remove_empty_units", tolua_remove_empty_units);
|
tolua_function(L, TOLUA_CAST "remove_empty_units", tolua_remove_empty_units);
|
||||||
tolua_function(L, TOLUA_CAST "update_scores", tolua_update_scores);
|
tolua_function(L, TOLUA_CAST "update_scores", tolua_update_scores);
|
||||||
tolua_function(L, TOLUA_CAST "update_owners", tolua_update_owners);
|
tolua_function(L, TOLUA_CAST "update_owners", tolua_update_owners);
|
||||||
tolua_function(L, TOLUA_CAST "learn_skill", tolua_learn_skill);
|
|
||||||
tolua_function(L, TOLUA_CAST "create_curse", tolua_create_curse);
|
tolua_function(L, TOLUA_CAST "create_curse", tolua_create_curse);
|
||||||
tolua_function(L, TOLUA_CAST "translate", &tolua_translate);
|
tolua_function(L, TOLUA_CAST "translate", &tolua_translate);
|
||||||
tolua_function(L, TOLUA_CAST "spells", tolua_get_spells);
|
tolua_function(L, TOLUA_CAST "spells", tolua_get_spells);
|
||||||
|
|
|
@ -37,7 +37,7 @@ struct order *ord)
|
||||||
skill *sv = u->skills;
|
skill *sv = u->skills;
|
||||||
while (sv != u->skills + u->skill_size) {
|
while (sv != u->skills + u->skill_size) {
|
||||||
/* only one person learns for 3 weeks */
|
/* only one person learns for 3 weeks */
|
||||||
learn_skill(u, (skill_t)sv->id, STUDYDAYS * 3);
|
change_skill_days(u, (skill_t)sv->id, STUDYDAYS * 3);
|
||||||
++sv;
|
++sv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,17 +52,17 @@ static void test_skillpotion(CuTest *tc) {
|
||||||
itype = test_create_itemtype("skillpotion");
|
itype = test_create_itemtype("skillpotion");
|
||||||
change_resource(u, itype->rtype, 2);
|
change_resource(u, itype->rtype, 2);
|
||||||
|
|
||||||
learn_skill(u, SK_ENTERTAINMENT, STUDYDAYS * u->number);
|
change_skill_days(u, SK_ENTERTAINMENT, STUDYDAYS * u->number);
|
||||||
pSkill = unit_skill(u, SK_ENTERTAINMENT);
|
pSkill = unit_skill(u, SK_ENTERTAINMENT);
|
||||||
sk_set(pSkill, 5);
|
sk_set(pSkill, 5);
|
||||||
initialWeeks_Entertainment = pSkill->weeks = 4;
|
initialWeeks_Entertainment = pSkill->weeks = 4;
|
||||||
|
|
||||||
learn_skill(u, SK_STAMINA, STUDYDAYS * u->number);
|
change_skill_days(u, SK_STAMINA, STUDYDAYS * u->number);
|
||||||
pSkill = unit_skill(u, SK_STAMINA);
|
pSkill = unit_skill(u, SK_STAMINA);
|
||||||
sk_set(pSkill, 5);
|
sk_set(pSkill, 5);
|
||||||
initialWeeks_Stamina = pSkill->weeks = 4;
|
initialWeeks_Stamina = pSkill->weeks = 4;
|
||||||
|
|
||||||
learn_skill(u, SK_MAGIC, STUDYDAYS * u->number);
|
change_skill_days(u, SK_MAGIC, STUDYDAYS * u->number);
|
||||||
pSkill = unit_skill(u, SK_MAGIC);
|
pSkill = unit_skill(u, SK_MAGIC);
|
||||||
sk_set(pSkill, 5);
|
sk_set(pSkill, 5);
|
||||||
initialWeeks_Magic = pSkill->weeks = 4;
|
initialWeeks_Magic = pSkill->weeks = 4;
|
||||||
|
|
310
src/study.c
310
src/study.c
|
@ -154,37 +154,37 @@ const attrib_type at_learning = {
|
||||||
|
|
||||||
#define EXPERIENCEDAYS 10
|
#define EXPERIENCEDAYS 10
|
||||||
|
|
||||||
static int study_days(unit * scholar, skill_t sk)
|
static int study_days(unit * u, skill_t sk)
|
||||||
{
|
{
|
||||||
int speed = STUDYDAYS;
|
int speed = STUDYDAYS;
|
||||||
if (u_race(scholar)->study_speed) {
|
if (u_race(u)->study_speed) {
|
||||||
speed += u_race(scholar)->study_speed[sk];
|
speed += u_race(u)->study_speed[sk];
|
||||||
if (speed < STUDYDAYS) {
|
if (speed < STUDYDAYS) {
|
||||||
skill *sv = unit_skill(scholar, sk);
|
skill *sv = unit_skill(u, sk);
|
||||||
if (sv == 0) {
|
if (sv == 0) {
|
||||||
speed = STUDYDAYS;
|
speed = STUDYDAYS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return scholar->number * speed;
|
return u->number * speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
teach_unit(unit * teacher, unit * scholar, int nteaching, skill_t sk,
|
teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk,
|
||||||
bool report, int *academy_students)
|
bool report, int *academy_students)
|
||||||
{
|
{
|
||||||
teaching_info *teach = NULL;
|
teaching_info *teach = NULL;
|
||||||
attrib *a;
|
attrib *a;
|
||||||
int students;
|
int students;
|
||||||
|
|
||||||
if (magic_lowskill(scholar)) {
|
if (magic_lowskill(student)) {
|
||||||
cmistake(teacher, teacher->thisorder, 292, MSG_EVENT);
|
cmistake(teacher, teacher->thisorder, 292, MSG_EVENT);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
students = scholar->number;
|
students = student->number;
|
||||||
/* subtract already taught students */
|
/* subtract already taught students */
|
||||||
a = a_find(scholar->attribs, &at_learning);
|
a = a_find(student->attribs, &at_learning);
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
teach = (teaching_info *)a->data.v;
|
teach = (teaching_info *)a->data.v;
|
||||||
students -= teach->students;
|
students -= teach->students;
|
||||||
|
@ -194,18 +194,18 @@ teach_unit(unit * teacher, unit * scholar, int nteaching, skill_t sk,
|
||||||
|
|
||||||
if (students > 0) {
|
if (students > 0) {
|
||||||
if (teach == NULL) {
|
if (teach == NULL) {
|
||||||
a = a_add(&scholar->attribs, a_new(&at_learning));
|
a = a_add(&student->attribs, a_new(&at_learning));
|
||||||
teach = (teaching_info *)a->data.v;
|
teach = (teaching_info *)a->data.v;
|
||||||
}
|
}
|
||||||
selist_push(&teach->teachers, teacher);
|
selist_push(&teach->teachers, teacher);
|
||||||
teach->days += students * STUDYDAYS;
|
teach->days += students * STUDYDAYS;
|
||||||
teach->students += students;
|
teach->students += students;
|
||||||
|
|
||||||
if (scholar->building) {
|
if (student->building) {
|
||||||
/* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und
|
/* Solange Akademien groessenbeschraenkt sind, sollte Lehrer und
|
||||||
* Student auch in unterschiedlichen Gebaeuden stehen duerfen */
|
* Student auch in unterschiedlichen Gebaeuden stehen duerfen */
|
||||||
/* FIXME comment contradicts implementation */
|
/* FIXME comment contradicts implementation */
|
||||||
if (academy_can_teach(teacher, scholar, sk)) {
|
if (academy_can_teach(teacher, student, sk)) {
|
||||||
/* Jeder Schueler zusaetzlich +10 Tage wenn in Uni. */
|
/* Jeder Schueler zusaetzlich +10 Tage wenn in Uni. */
|
||||||
teach->days += students * EXPERIENCEDAYS; /* learning erhoehen */
|
teach->days += students * EXPERIENCEDAYS; /* learning erhoehen */
|
||||||
/* Lehrer zusaetzlich +1 Tag pro Schueler. */
|
/* Lehrer zusaetzlich +1 Tag pro Schueler. */
|
||||||
|
@ -258,12 +258,12 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
|
#if TEACH_ALL
|
||||||
init_order(ord, NULL);
|
init_order(ord, NULL);
|
||||||
|
|
||||||
#if TEACH_ALL
|
|
||||||
if (getparam(teacher->faction->locale) == P_ANY) {
|
if (getparam(teacher->faction->locale) == P_ANY) {
|
||||||
skill_t sk;
|
skill_t sk;
|
||||||
unit *scholar;
|
unit *student;
|
||||||
skill_t teachskill[MAXSKILLS];
|
skill_t teachskill[MAXSKILLS];
|
||||||
int t = 0;
|
int t = 0;
|
||||||
|
|
||||||
|
@ -272,15 +272,15 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
teachskill[t] = getskill(teacher->faction->locale);
|
teachskill[t] = getskill(teacher->faction->locale);
|
||||||
} while (sk != NOSKILL);
|
} while (sk != NOSKILL);
|
||||||
|
|
||||||
for (scholar = r->units; teaching > 0 && scholar; scholar = scholar->next) {
|
for (student = r->units; teaching > 0 && student; student = student->next) {
|
||||||
if (LongHunger(scholar)) {
|
if (LongHunger(student)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (scholar->faction == teacher->faction) {
|
else if (student->faction == teacher->faction) {
|
||||||
if (getkeyword(scholar->thisorder) == K_STUDY) {
|
if (getkeyword(student->thisorder) == K_STUDY) {
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
init_order(scholar->thisorder, scholar->faction->locale);
|
init_order(student->thisorder, student->faction->locale);
|
||||||
sk = getskill(scholar->faction->locale);
|
sk = getskill(student->faction->locale);
|
||||||
if (sk != NOSKILL && teachskill[0] != NOSKILL) {
|
if (sk != NOSKILL && teachskill[0] != NOSKILL) {
|
||||||
for (t = 0; teachskill[t] != NOSKILL; ++t) {
|
for (t = 0; teachskill[t] != NOSKILL; ++t) {
|
||||||
if (sk == teachskill[t]) {
|
if (sk == teachskill[t]) {
|
||||||
|
@ -290,20 +290,20 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
sk = teachskill[t];
|
sk = teachskill[t];
|
||||||
}
|
}
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk) - TEACHDIFFERENCE > effskill_study(scholar, sk)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE > effskill_study(student, sk)) {
|
||||||
teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef TEACH_FRIENDS
|
#ifdef TEACH_FRIENDS
|
||||||
else if (alliedunit(teacher, scholar->faction, HELP_GUARD)) {
|
else if (alliedunit(teacher, student->faction, HELP_GUARD)) {
|
||||||
if (getkeyword(scholar->thisorder) == K_STUDY) {
|
if (getkeyword(student->thisorder) == K_STUDY) {
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
init_order(scholar->thisorder, scholar->faction->locale);
|
init_order(student->thisorder, student->faction->locale);
|
||||||
sk = getskill(scholar->faction->locale);
|
sk = getskill(student->faction->locale);
|
||||||
if (sk != NOSKILL
|
if (sk != NOSKILL
|
||||||
&& effskill_study(teacher, sk) - TEACHDIFFERENCE >= effskill(scholar, sk, NULL)) {
|
&& effskill_study(teacher, sk) - TEACHDIFFERENCE >= effskill(student, sk, NULL)) {
|
||||||
teaching -= teach_unit(teacher, scholar, teaching, sk, true, &academy_students);
|
teaching -= teach_unit(teacher, student, teaching, sk, true, &academy_students);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,15 +322,15 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
|
|
||||||
while (!parser_end()) {
|
while (!parser_end()) {
|
||||||
skill_t sk;
|
skill_t sk;
|
||||||
unit *scholar;
|
unit *student;
|
||||||
bool feedback;
|
bool feedback;
|
||||||
|
|
||||||
getunit(r, teacher->faction, &scholar);
|
getunit(r, teacher->faction, &student);
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
/* Falls die Unit nicht gefunden wird, Fehler melden */
|
||||||
|
|
||||||
if (!scholar) {
|
if (!student) {
|
||||||
char tbuf[20];
|
char tbuf[20];
|
||||||
const char *uid;
|
const char *uid;
|
||||||
const char *token;
|
const char *token;
|
||||||
|
@ -362,8 +362,8 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
feedback = teacher->faction == scholar->faction
|
feedback = teacher->faction == student->faction
|
||||||
|| alliedunit(scholar, teacher->faction, HELP_GUARD);
|
|| alliedunit(student, teacher->faction, HELP_GUARD);
|
||||||
|
|
||||||
/* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
|
/* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in
|
||||||
* ihre neuen Nummern uebersetzt. */
|
* ihre neuen Nummern uebersetzt. */
|
||||||
|
@ -371,51 +371,51 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
strncat(zOrder, " ", sz - 1);
|
strncat(zOrder, " ", sz - 1);
|
||||||
--sz;
|
--sz;
|
||||||
}
|
}
|
||||||
sz -= str_strlcpy(zOrder + 4096 - sz, itoa36(scholar->no), sz);
|
sz -= str_strlcpy(zOrder + 4096 - sz, itoa36(student->no), sz);
|
||||||
|
|
||||||
if (getkeyword(scholar->thisorder) != K_STUDY) {
|
if (getkeyword(student->thisorder) != K_STUDY) {
|
||||||
ADDMSG(&teacher->faction->msgs,
|
ADDMSG(&teacher->faction->msgs,
|
||||||
msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
|
msg_feedback(teacher, ord, "teach_nolearn", "student", student));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Input ist nun von student->thisorder !! */
|
/* Input ist nun von student->thisorder !! */
|
||||||
parser_pushstate();
|
parser_pushstate();
|
||||||
init_order(scholar->thisorder, scholar->faction->locale);
|
init_order(student->thisorder, student->faction->locale);
|
||||||
sk = getskill(scholar->faction->locale);
|
sk = getskill(student->faction->locale);
|
||||||
parser_popstate();
|
parser_popstate();
|
||||||
|
|
||||||
if (sk == NOSKILL) {
|
if (sk == NOSKILL) {
|
||||||
ADDMSG(&teacher->faction->msgs,
|
ADDMSG(&teacher->faction->msgs,
|
||||||
msg_feedback(teacher, ord, "teach_nolearn", "student", scholar));
|
msg_feedback(teacher, ord, "teach_nolearn", "student", student));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (effskill_study(scholar, sk) > effskill_study(teacher, sk)
|
if (effskill_study(student, sk) > effskill_study(teacher, sk)
|
||||||
- TEACHDIFFERENCE) {
|
- TEACHDIFFERENCE) {
|
||||||
if (feedback) {
|
if (feedback) {
|
||||||
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood",
|
||||||
"student", scholar));
|
"student", student));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sk == SK_MAGIC) {
|
if (sk == SK_MAGIC) {
|
||||||
/* ist der Magier schon spezialisiert, so versteht er nur noch
|
/* ist der Magier schon spezialisiert, so versteht er nur noch
|
||||||
* Lehrer seines Gebietes */
|
* Lehrer seines Gebietes */
|
||||||
magic_t mage2 = unit_get_magic(scholar);
|
magic_t mage2 = unit_get_magic(student);
|
||||||
if (mage2 != M_GRAY) {
|
if (mage2 != M_GRAY) {
|
||||||
magic_t mage1 = unit_get_magic(teacher);
|
magic_t mage1 = unit_get_magic(teacher);
|
||||||
if (mage1 != mage2) {
|
if (mage1 != mage2) {
|
||||||
if (feedback) {
|
if (feedback) {
|
||||||
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
|
ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord,
|
||||||
"error_different_magic", "target", scholar));
|
"error_different_magic", "target", student));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sk_academy = sk;
|
sk_academy = sk;
|
||||||
teaching -= teach_unit(teacher, scholar, teaching, sk, false, &academy_students);
|
teaching -= teach_unit(teacher, student, teaching, sk, false, &academy_students);
|
||||||
}
|
}
|
||||||
new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder);
|
new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder);
|
||||||
replace_order(&teacher->orders, ord, new_order);
|
replace_order(&teacher->orders, ord, new_order);
|
||||||
|
@ -428,45 +428,6 @@ int teach_cmd(unit * teacher, struct order *ord)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum study_rule_t {
|
|
||||||
STUDY_DEFAULT = 0,
|
|
||||||
STUDY_FASTER = 1,
|
|
||||||
STUDY_AUTOTEACH = 2
|
|
||||||
} study_rule_t;
|
|
||||||
|
|
||||||
static double study_speedup(unit * u, skill_t s, study_rule_t rule)
|
|
||||||
{
|
|
||||||
#define MINTURN 16
|
|
||||||
if (turn > MINTURN) {
|
|
||||||
if (rule == STUDY_FASTER) {
|
|
||||||
double learnweeks = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i != u->skill_size; ++i) {
|
|
||||||
skill *sv = u->skills + i;
|
|
||||||
if (sv->id == s) {
|
|
||||||
learnweeks = sv->level * (sv->level + 1) / 2.0;
|
|
||||||
if (learnweeks < turn / 3.0) {
|
|
||||||
return 2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 2.0; /* If the skill was not found it is the first study. */
|
|
||||||
}
|
|
||||||
if (rule == STUDY_AUTOTEACH) {
|
|
||||||
double learnweeks = 0;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i != u->skill_size; ++i) {
|
|
||||||
skill *sv = u->skills + i;
|
|
||||||
learnweeks += (sv->level * (sv->level + 1) / 2.0);
|
|
||||||
}
|
|
||||||
if (learnweeks < turn / 2.0) {
|
|
||||||
return 2.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool ExpensiveMigrants(void)
|
static bool ExpensiveMigrants(void)
|
||||||
{
|
{
|
||||||
static bool rule;
|
static bool rule;
|
||||||
|
@ -552,17 +513,12 @@ bool check_student(const struct unit *u, struct order *ord, skill_t sk) {
|
||||||
|
|
||||||
int study_cmd(unit * u, order * ord)
|
int study_cmd(unit * u, order * ord)
|
||||||
{
|
{
|
||||||
region *r = u->region;
|
|
||||||
int p;
|
|
||||||
int l;
|
|
||||||
int studycost, days;
|
int studycost, days;
|
||||||
double multi = 1.0;
|
|
||||||
attrib *a = NULL;
|
attrib *a = NULL;
|
||||||
teaching_info *teach = NULL;
|
teaching_info *teach = NULL;
|
||||||
int money = 0;
|
int money = 0;
|
||||||
skill_t sk;
|
skill_t sk;
|
||||||
int maxalchemy = 0;
|
int maxalchemy = 0;
|
||||||
int speed_rule = (study_rule_t)config_get_int("study.speedup", 0);
|
|
||||||
static const race *rc_snotling;
|
static const race *rc_snotling;
|
||||||
static int rc_cache;
|
static int rc_cache;
|
||||||
|
|
||||||
|
@ -585,7 +541,6 @@ int study_cmd(unit * u, order * ord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = studycost = study_cost(u, sk);
|
|
||||||
a = a_find(u->attribs, &at_learning);
|
a = a_find(u->attribs, &at_learning);
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
teach = (teaching_info *)a->data.v;
|
teach = (teaching_info *)a->data.v;
|
||||||
|
@ -594,16 +549,13 @@ int study_cmd(unit * u, order * ord)
|
||||||
/* keine kostenpflichtigen Talente fuer Migranten. Vertraute sind
|
/* keine kostenpflichtigen Talente fuer Migranten. Vertraute sind
|
||||||
* keine Migranten, wird in is_migrant abgefangen. Vorsicht,
|
* keine Migranten, wird in is_migrant abgefangen. Vorsicht,
|
||||||
* studycost darf hier noch nicht durch Akademie erhoeht sein */
|
* studycost darf hier noch nicht durch Akademie erhoeht sein */
|
||||||
|
studycost = study_cost(u, sk);
|
||||||
|
|
||||||
if (studycost > 0 && !ExpensiveMigrants() && is_migrant(u)) {
|
if (studycost > 0 && !ExpensiveMigrants() && is_migrant(u)) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_migrants_nolearn",
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_migrants_nolearn",
|
||||||
""));
|
""));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Akademie: */
|
|
||||||
if (active_building(u, bt_find("academy"))) {
|
|
||||||
studycost = studycost * 2;
|
|
||||||
if (studycost < 50) studycost = 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk == SK_MAGIC) {
|
if (sk == SK_MAGIC) {
|
||||||
magic_t mtype;
|
magic_t mtype;
|
||||||
|
@ -684,71 +636,31 @@ int study_cmd(unit * u, order * ord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
days = teach ? teach->days : 0;
|
||||||
|
days += study_days(u, sk);
|
||||||
|
|
||||||
if (studycost) {
|
if (studycost) {
|
||||||
int cost = studycost * u->number;
|
int cost = studycost * u->number;
|
||||||
money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost);
|
money = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, cost);
|
||||||
if (money > cost) money = cost;
|
if (money > cost) money = cost;
|
||||||
}
|
|
||||||
if (money < studycost * u->number) {
|
if (money < studycost * u->number) {
|
||||||
studycost = p; /* Ohne Univertreurung */
|
int cost = studycost * u->number;
|
||||||
if (money > studycost) money = studycost;
|
if (money > studycost) money = studycost;
|
||||||
if (p > 0 && money < studycost * u->number) {
|
if (money < cost) {
|
||||||
|
/* we cannot afford everyone, but use as much as we have */
|
||||||
cmistake(u, ord, 65, MSG_EVENT);
|
cmistake(u, ord, 65, MSG_EVENT);
|
||||||
multi = money / (double)(studycost * u->number);
|
days = days * money / cost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
money += learn_skill(u, sk, days, studycost);
|
||||||
|
|
||||||
if (teach == NULL) {
|
|
||||||
a = a_add(&u->attribs, a_new(&at_learning));
|
|
||||||
teach = (teaching_info *)a->data.v;
|
|
||||||
assert(teach);
|
|
||||||
teach->teachers = NULL;
|
|
||||||
}
|
|
||||||
if (money > 0) {
|
if (money > 0) {
|
||||||
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money);
|
use_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, money);
|
||||||
ADDMSG(&u->faction->msgs, msg_message("studycost",
|
ADDMSG(&u->faction->msgs, msg_message("studycost",
|
||||||
"unit region cost skill", u, u->region, money, sk));
|
"unit region cost skill", u, u->region, money, sk));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_effect(u, oldpotiontype[P_WISE])) {
|
|
||||||
l = get_effect(u, oldpotiontype[P_WISE]);
|
|
||||||
if (l > u->number) l = u->number;
|
|
||||||
teach->days += l * EXPERIENCEDAYS;
|
|
||||||
change_effect(u, oldpotiontype[P_WISE], -l);
|
|
||||||
}
|
|
||||||
if (get_effect(u, oldpotiontype[P_FOOL])) {
|
|
||||||
l = get_effect(u, oldpotiontype[P_FOOL]);
|
|
||||||
if (l > u->number) l = u->number;
|
|
||||||
teach->days -= l * STUDYDAYS;
|
|
||||||
change_effect(u, oldpotiontype[P_FOOL], -l);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p != studycost) {
|
|
||||||
/* ist_in_gebaeude(r, u, BT_UNIVERSITAET) == 1) { */
|
|
||||||
/* p ist Kosten ohne Uni, studycost mit; wenn
|
|
||||||
* p!=studycost, ist die Einheit zwangsweise
|
|
||||||
* in einer Uni */
|
|
||||||
teach->days += u->number * EXPERIENCEDAYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_cursed(r->attribs, &ct_badlearn)) {
|
|
||||||
teach->days -= u->number * EXPERIENCEDAYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
multi *= study_speedup(u, sk, speed_rule);
|
|
||||||
days = study_days(u, sk);
|
|
||||||
days = (int)((days + teach->days) * multi);
|
|
||||||
|
|
||||||
/* the artacademy currently improves the learning of entertainment
|
|
||||||
of all units in the region, to be able to make it cumulative with
|
|
||||||
with an academy */
|
|
||||||
|
|
||||||
if (sk == SK_ENTERTAINMENT
|
|
||||||
&& buildingtype_exists(r, bt_find("artacademy"), false)) {
|
|
||||||
days *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
learn_skill(u, sk, days);
|
|
||||||
if (a != NULL) {
|
if (a != NULL) {
|
||||||
if (teach->teachers) {
|
if (teach->teachers) {
|
||||||
msg_teachers(teach->teachers, u, sk);
|
msg_teachers(teach->teachers, u, sk);
|
||||||
|
@ -789,26 +701,17 @@ void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void produceexp(struct unit *u, skill_t sk, int n)
|
|
||||||
{
|
|
||||||
produceexp_ex(u, sk, n, learn_skill);
|
|
||||||
}
|
|
||||||
|
|
||||||
static learn_fun inject_learn_fun = 0;
|
static learn_fun inject_learn_fun = 0;
|
||||||
|
|
||||||
void inject_learn(learn_fun fun) {
|
void inject_learn(learn_fun fun) {
|
||||||
inject_learn_fun = fun;
|
inject_learn_fun = fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** days should be scaled by u->number; STUDYDAYS * u->number is one week worth of learning */
|
static void increase_skill_days(unit *u, skill_t sk, int days) {
|
||||||
void learn_skill(unit *u, skill_t sk, int days) {
|
assert(sk >= 0 && sk < MAXSKILLS && days >= 0);
|
||||||
|
if (days > 0) {
|
||||||
int leveldays = STUDYDAYS * u->number;
|
int leveldays = STUDYDAYS * u->number;
|
||||||
int weeks = 0;
|
int weeks = 0;
|
||||||
|
|
||||||
if (fval(u, UFL_HUNGER)) {
|
|
||||||
days /= 2;
|
|
||||||
}
|
|
||||||
assert(sk >= 0 && sk < MAXSKILLS);
|
|
||||||
if (inject_learn_fun) {
|
if (inject_learn_fun) {
|
||||||
inject_learn_fun(u, sk, days);
|
inject_learn_fun(u, sk, days);
|
||||||
return;
|
return;
|
||||||
|
@ -823,9 +726,11 @@ void learn_skill(unit *u, skill_t sk, int days) {
|
||||||
if (weeks > 0) {
|
if (weeks > 0) {
|
||||||
increase_skill(u, sk, weeks);
|
increase_skill(u, sk, weeks);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void reduce_skill_days(unit *u, skill_t sk, int days) {
|
static void reduce_skill_days(unit *u, skill_t sk, int days) {
|
||||||
|
if (days > 0) {
|
||||||
skill *sv = unit_skill(u, sk);
|
skill *sv = unit_skill(u, sk);
|
||||||
if (sv) {
|
if (sv) {
|
||||||
while (days > 0) {
|
while (days > 0) {
|
||||||
|
@ -834,12 +739,99 @@ void reduce_skill_days(unit *u, skill_t sk, int days) {
|
||||||
days -= STUDYDAYS;
|
days -= STUDYDAYS;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (chance (days / ((double) STUDYDAYS * u->number))) /* (rng_int() % (30 * u->number) < days)*/
|
if (chance(days / ((double)STUDYDAYS * u->number))) /* (rng_int() % (30 * u->number) < days)*/
|
||||||
reduce_skill(u, sv, 1);
|
reduce_skill(u, sv, 1);
|
||||||
days = 0;
|
days = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void produceexp(struct unit *u, skill_t sk, int n)
|
||||||
|
{
|
||||||
|
produceexp_ex(u, sk, n, increase_skill_days);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int speed_rule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* days should be scaled by u->number; STUDYDAYS * u->number is one week worth of learning
|
||||||
|
* @return int
|
||||||
|
* The additional spend, i.e. from an academy.
|
||||||
|
*/
|
||||||
|
int learn_skill(unit *u, skill_t sk, int days, int studycost) {
|
||||||
|
region *r = u->region;
|
||||||
|
int cost = 0;
|
||||||
|
|
||||||
|
if (r->buildings) {
|
||||||
|
static const building_type *bt_artacademy;
|
||||||
|
static const building_type *bt_academy;
|
||||||
|
static int config;
|
||||||
|
|
||||||
|
if (bt_changed(&config)) {
|
||||||
|
bt_artacademy = bt_find("artacademy");
|
||||||
|
bt_academy = bt_find("academy");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Akademie: */
|
||||||
|
if (bt_academy && active_building(u, bt_academy)) {
|
||||||
|
int avail, n = u->number;
|
||||||
|
if (studycost < 50) studycost = 50;
|
||||||
|
cost = studycost * u->number;
|
||||||
|
avail = get_pooled(u, get_resourcetype(R_SILVER), GET_DEFAULT, studycost * u->number);
|
||||||
|
if (avail < cost) {
|
||||||
|
/* not all students can afford the academy */
|
||||||
|
cost = avail;
|
||||||
|
n = n * avail / cost;
|
||||||
|
cost = n * studycost;
|
||||||
|
}
|
||||||
|
days += EXPERIENCEDAYS * n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the artacademy currently improves the learning of entertainment
|
||||||
|
of all units in the region, to be able to make it cumulative with
|
||||||
|
with an academy */
|
||||||
|
|
||||||
|
if (bt_artacademy && sk == SK_ENTERTAINMENT
|
||||||
|
&& buildingtype_exists(r, bt_artacademy, false)) {
|
||||||
|
days *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u->attribs) {
|
||||||
|
if (get_effect(u, oldpotiontype[P_WISE])) {
|
||||||
|
int effect = get_effect(u, oldpotiontype[P_WISE]);
|
||||||
|
if (effect > u->number) effect = u->number;
|
||||||
|
days += effect * EXPERIENCEDAYS;
|
||||||
|
change_effect(u, oldpotiontype[P_WISE], -effect);
|
||||||
|
}
|
||||||
|
if (get_effect(u, oldpotiontype[P_FOOL])) {
|
||||||
|
int effect = get_effect(u, oldpotiontype[P_FOOL]);
|
||||||
|
if (effect > u->number) effect = u->number;
|
||||||
|
days -= effect * STUDYDAYS;
|
||||||
|
change_effect(u, oldpotiontype[P_FOOL], -effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_cursed(r->attribs, &ct_badlearn)) {
|
||||||
|
days -= EXPERIENCEDAYS * u->number;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fval(u, UFL_HUNGER)) {
|
||||||
|
days /= 2;
|
||||||
|
}
|
||||||
|
increase_skill_days(u, sk, days);
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void change_skill_days(unit *u, skill_t sk, int days) {
|
||||||
|
if (days < 0) {
|
||||||
|
reduce_skill_days(u, sk, -days);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
increase_skill_days(u, sk, days);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -885,7 +877,7 @@ void demon_skillchange(unit *u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
learn_skill(u, sv->id, STUDYDAYS * u->number * weeks);
|
change_skill_days(u, sv->id, STUDYDAYS * u->number * weeks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++sv;
|
++sv;
|
||||||
|
|
|
@ -34,8 +34,8 @@ extern "C" {
|
||||||
|
|
||||||
typedef void(*learn_fun)(struct unit *u, skill_t sk, int days);
|
typedef void(*learn_fun)(struct unit *u, skill_t sk, int days);
|
||||||
|
|
||||||
void learn_skill(struct unit *u, skill_t sk, int days);
|
int learn_skill(struct unit *u, skill_t sk, int days, int studycost);
|
||||||
void reduce_skill_days(struct unit *u, skill_t sk, int days);
|
void change_skill_days(struct unit *u, skill_t sk, int days);
|
||||||
|
|
||||||
void produceexp(struct unit *u, skill_t sk, int n);
|
void produceexp(struct unit *u, skill_t sk, int n);
|
||||||
void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn);
|
void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn);
|
||||||
|
|
|
@ -364,14 +364,14 @@ void test_learn_skill_single(CuTest *tc) {
|
||||||
setup_study();
|
setup_study();
|
||||||
config_set("study.random_progress", "0");
|
config_set("study.random_progress", "0");
|
||||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS, 0));
|
||||||
CuAssertPtrNotNull(tc, sv = u->skills);
|
CuAssertPtrNotNull(tc, sv = u->skills);
|
||||||
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
|
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
|
||||||
CuAssertIntEquals(tc, 1, sv->level);
|
CuAssertIntEquals(tc, 1, sv->level);
|
||||||
CuAssertIntEquals(tc, 2, sv->weeks);
|
CuAssertIntEquals(tc, 2, sv->weeks);
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS, 0));
|
||||||
CuAssertIntEquals(tc, 1, sv->weeks);
|
CuAssertIntEquals(tc, 1, sv->weeks);
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS * 2);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS * 2, 0));
|
||||||
CuAssertIntEquals(tc, 2, sv->level);
|
CuAssertIntEquals(tc, 2, sv->level);
|
||||||
CuAssertIntEquals(tc, 2, sv->weeks);
|
CuAssertIntEquals(tc, 2, sv->weeks);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
@ -385,14 +385,14 @@ void test_learn_skill_multi(CuTest *tc) {
|
||||||
config_set("study.random_progress", "0");
|
config_set("study.random_progress", "0");
|
||||||
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL));
|
||||||
scale_number(u, 10);
|
scale_number(u, 10);
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number, 0));
|
||||||
CuAssertPtrNotNull(tc, sv = u->skills);
|
CuAssertPtrNotNull(tc, sv = u->skills);
|
||||||
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
|
CuAssertIntEquals(tc, SK_ALCHEMY, sv->id);
|
||||||
CuAssertIntEquals(tc, 1, sv->level);
|
CuAssertIntEquals(tc, 1, sv->level);
|
||||||
CuAssertIntEquals(tc, 2, sv->weeks);
|
CuAssertIntEquals(tc, 2, sv->weeks);
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number, 0));
|
||||||
CuAssertIntEquals(tc, 1, sv->weeks);
|
CuAssertIntEquals(tc, 1, sv->weeks);
|
||||||
learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number * 2);
|
CuAssertIntEquals(tc, 0, learn_skill(u, SK_ALCHEMY, STUDYDAYS * u->number * 2, 0));
|
||||||
CuAssertIntEquals(tc, 2, sv->level);
|
CuAssertIntEquals(tc, 2, sv->level);
|
||||||
CuAssertIntEquals(tc, 2, sv->weeks);
|
CuAssertIntEquals(tc, 2, sv->weeks);
|
||||||
test_teardown();
|
test_teardown();
|
||||||
|
|
Loading…
Reference in New Issue