forked from github/server
Merge branch 'develop' of github.com:eressea/server into develop
This commit is contained in:
commit
63c983e197
|
@ -4,6 +4,10 @@
|
||||||
"prefixes.json",
|
"prefixes.json",
|
||||||
"e2/terrains.json"
|
"e2/terrains.json"
|
||||||
],
|
],
|
||||||
|
"disabled": [
|
||||||
|
"pay",
|
||||||
|
"jsreport"
|
||||||
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"game.id": 2,
|
"game.id": 2,
|
||||||
"game.name": "Eressea",
|
"game.name": "Eressea",
|
||||||
|
|
|
@ -52,42 +52,6 @@
|
||||||
<xi:include href="config://default/names-zombies.xml"/>
|
<xi:include href="config://default/names-zombies.xml"/>
|
||||||
<xi:include href="config://default/names-ghouls.xml"/>
|
<xi:include href="config://default/names-ghouls.xml"/>
|
||||||
<xi:include href="config://default/names-dragons.xml"/>
|
<xi:include href="config://default/names-dragons.xml"/>
|
||||||
|
|
||||||
<game name="Eressea">
|
|
||||||
<!-- Game specific settings -->
|
|
||||||
|
|
||||||
<order name="pay" disable="yes"/>
|
|
||||||
|
|
||||||
<skill name="alchemy" enable="true"/>
|
|
||||||
<skill name="crossbow" enable="true"/>
|
|
||||||
<skill name="mining" enable="true"/>
|
|
||||||
<skill name="bow" enable="true"/>
|
|
||||||
<skill name="building" enable="true"/>
|
|
||||||
<skill name="trade" enable="true"/>
|
|
||||||
<skill name="forestry" enable="true"/>
|
|
||||||
<skill name="catapult" enable="true"/>
|
|
||||||
<skill name="herbalism" enable="true"/>
|
|
||||||
<skill name="magic" enable="true"/>
|
|
||||||
<skill name="training" enable="true"/>
|
|
||||||
<skill name="riding" enable="true"/>
|
|
||||||
<skill name="armorer" enable="true"/>
|
|
||||||
<skill name="shipcraft" enable="true"/>
|
|
||||||
<skill name="melee" enable="true"/>
|
|
||||||
<skill name="sailing" enable="true"/>
|
|
||||||
<skill name="polearm" enable="true"/>
|
|
||||||
<skill name="espionage" enable="true"/>
|
|
||||||
<skill name="quarrying" enable="true"/>
|
|
||||||
<skill name="roadwork" enable="true"/>
|
|
||||||
<skill name="tactics" enable="true"/>
|
|
||||||
<skill name="stealth" enable="true"/>
|
|
||||||
<skill name="entertainment" enable="true"/>
|
|
||||||
<skill name="weaponsmithing" enable="true"/>
|
|
||||||
<skill name="cartmaking" enable="true"/>
|
|
||||||
<skill name="perception" enable="true"/>
|
|
||||||
<skill name="taxation" enable="true"/>
|
|
||||||
<skill name="stamina" enable="true"/>
|
|
||||||
<skill name="unarmed" enable="true"/>
|
|
||||||
</game>
|
|
||||||
<strings>
|
<strings>
|
||||||
<string name="mailto">
|
<string name="mailto">
|
||||||
<text locale="de">eressea-server@eressea.de</text>
|
<text locale="de">eressea-server@eressea.de</text>
|
||||||
|
|
|
@ -4,6 +4,26 @@
|
||||||
"prefixes.json",
|
"prefixes.json",
|
||||||
"e3/terrains.json"
|
"e3/terrains.json"
|
||||||
],
|
],
|
||||||
|
"disabled": [
|
||||||
|
"herbalism",
|
||||||
|
"alchemy",
|
||||||
|
"entertainment",
|
||||||
|
"espionage",
|
||||||
|
"perception",
|
||||||
|
"stealth",
|
||||||
|
"taxation",
|
||||||
|
"trade",
|
||||||
|
"besiege",
|
||||||
|
"steal",
|
||||||
|
"buy",
|
||||||
|
"teach",
|
||||||
|
"sabotage",
|
||||||
|
"spy",
|
||||||
|
"tax",
|
||||||
|
"entertain",
|
||||||
|
"sell",
|
||||||
|
"jsreport"
|
||||||
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"game.id": 3,
|
"game.id": 3,
|
||||||
"game.name": "E3",
|
"game.name": "E3",
|
||||||
|
|
|
@ -41,51 +41,6 @@
|
||||||
<xi:include href="config://default/names-zombies.xml"/>
|
<xi:include href="config://default/names-zombies.xml"/>
|
||||||
<xi:include href="config://default/names-ghouls.xml"/>
|
<xi:include href="config://default/names-ghouls.xml"/>
|
||||||
<xi:include href="config://default/names-dragons.xml"/>
|
<xi:include href="config://default/names-dragons.xml"/>
|
||||||
|
|
||||||
<game name="E3">
|
|
||||||
<!-- Game specific settings -->
|
|
||||||
<order name="besiege" disable="yes"/>
|
|
||||||
<order name="steal" disable="yes"/>
|
|
||||||
<order name="buy" disable="yes"/>
|
|
||||||
<order name="teach" disable="yes"/>
|
|
||||||
<order name="sabotage" disable="yes"/>
|
|
||||||
<order name="spy" disable="yes"/>
|
|
||||||
<order name="tax" disable="yes"/>
|
|
||||||
<order name="entertain" disable="yes"/>
|
|
||||||
<order name="sell" disable="yes"/>
|
|
||||||
|
|
||||||
<skill name="armorer" enable="true"/>
|
|
||||||
<skill name="bow" enable="true"/>
|
|
||||||
<skill name="building" enable="true"/>
|
|
||||||
<skill name="cartmaking" enable="true"/>
|
|
||||||
<skill name="catapult" enable="true"/>
|
|
||||||
<skill name="crossbow" enable="true"/>
|
|
||||||
<skill name="forestry" enable="true"/>
|
|
||||||
<skill name="magic" enable="true"/>
|
|
||||||
<skill name="melee" enable="true"/>
|
|
||||||
<skill name="mining" enable="true"/>
|
|
||||||
<skill name="polearm" enable="true"/>
|
|
||||||
<skill name="quarrying" enable="true"/>
|
|
||||||
<skill name="riding" enable="true"/>
|
|
||||||
<skill name="roadwork" enable="true"/>
|
|
||||||
<skill name="sailing" enable="true"/>
|
|
||||||
<skill name="shipcraft" enable="true"/>
|
|
||||||
<skill name="stamina" enable="true"/>
|
|
||||||
<skill name="tactics" enable="true"/>
|
|
||||||
<skill name="training" enable="true"/>
|
|
||||||
<skill name="unarmed" enable="true"/>
|
|
||||||
<skill name="weaponsmithing" enable="true"/>
|
|
||||||
|
|
||||||
<skill name="herbalism" enable="false"/>
|
|
||||||
|
|
||||||
<skill name="alchemy" enable="false"/>
|
|
||||||
<skill name="entertainment" enable="false"/>
|
|
||||||
<skill name="espionage" enable="false"/>
|
|
||||||
<skill name="perception" enable="false"/>
|
|
||||||
<skill name="stealth" enable="false"/>
|
|
||||||
<skill name="taxation" enable="false"/>
|
|
||||||
<skill name="trade" enable="false"/>
|
|
||||||
</game>
|
|
||||||
<rules>
|
<rules>
|
||||||
<function name="wage" value="minimum_wage"/>
|
<function name="wage" value="minimum_wage"/>
|
||||||
</rules>
|
</rules>
|
||||||
|
|
|
@ -4,6 +4,26 @@
|
||||||
"prefixes.json",
|
"prefixes.json",
|
||||||
"e3/terrains.json"
|
"e3/terrains.json"
|
||||||
],
|
],
|
||||||
|
"disabled": [
|
||||||
|
"herbalism",
|
||||||
|
"alchemy",
|
||||||
|
"entertainment",
|
||||||
|
"espionage",
|
||||||
|
"perception",
|
||||||
|
"stealth",
|
||||||
|
"taxation",
|
||||||
|
"trade",
|
||||||
|
"besiege",
|
||||||
|
"steal",
|
||||||
|
"buy",
|
||||||
|
"teach",
|
||||||
|
"sabotage",
|
||||||
|
"spy",
|
||||||
|
"tax",
|
||||||
|
"entertain",
|
||||||
|
"sell",
|
||||||
|
"jsreport"
|
||||||
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"game.id": 4,
|
"game.id": 4,
|
||||||
"game.name": "Deveron",
|
"game.name": "Deveron",
|
||||||
|
@ -29,6 +49,7 @@
|
||||||
"recruit.allow_merge": true,
|
"recruit.allow_merge": true,
|
||||||
"study.expensivemigrants": true,
|
"study.expensivemigrants": true,
|
||||||
"study.speedup": 2,
|
"study.speedup": 2,
|
||||||
|
"study.from_use": 0.4,
|
||||||
"world.era": 3,
|
"world.era": 3,
|
||||||
"rules.migrants.max": 0,
|
"rules.migrants.max": 0,
|
||||||
"rules.reserve.twophase": true,
|
"rules.reserve.twophase": true,
|
||||||
|
|
|
@ -42,49 +42,6 @@
|
||||||
<xi:include href="config://default/names-ghouls.xml"/>
|
<xi:include href="config://default/names-ghouls.xml"/>
|
||||||
<xi:include href="config://default/names-dragons.xml"/>
|
<xi:include href="config://default/names-dragons.xml"/>
|
||||||
|
|
||||||
<game name="Deveron">
|
|
||||||
<order name="besiege" disable="yes"/>
|
|
||||||
<order name="steal" disable="yes"/>
|
|
||||||
<order name="buy" disable="yes"/>
|
|
||||||
<order name="teach" disable="yes"/>
|
|
||||||
<order name="sabotage" disable="yes"/>
|
|
||||||
<order name="spy" disable="yes"/>
|
|
||||||
<order name="tax" disable="yes"/>
|
|
||||||
<order name="entertain" disable="yes"/>
|
|
||||||
<order name="sell" disable="yes"/>
|
|
||||||
|
|
||||||
<skill name="armorer" enable="true"/>
|
|
||||||
<skill name="bow" enable="true"/>
|
|
||||||
<skill name="building" enable="true"/>
|
|
||||||
<skill name="cartmaking" enable="true"/>
|
|
||||||
<skill name="catapult" enable="true"/>
|
|
||||||
<skill name="crossbow" enable="true"/>
|
|
||||||
<skill name="forestry" enable="true"/>
|
|
||||||
<skill name="magic" enable="true"/>
|
|
||||||
<skill name="melee" enable="true"/>
|
|
||||||
<skill name="mining" enable="true"/>
|
|
||||||
<skill name="polearm" enable="true"/>
|
|
||||||
<skill name="quarrying" enable="true"/>
|
|
||||||
<skill name="riding" enable="true"/>
|
|
||||||
<skill name="roadwork" enable="true"/>
|
|
||||||
<skill name="sailing" enable="true"/>
|
|
||||||
<skill name="shipcraft" enable="true"/>
|
|
||||||
<skill name="stamina" enable="true"/>
|
|
||||||
<skill name="tactics" enable="true"/>
|
|
||||||
<skill name="training" enable="true"/>
|
|
||||||
<skill name="unarmed" enable="true"/>
|
|
||||||
<skill name="weaponsmithing" enable="true"/>
|
|
||||||
|
|
||||||
<skill name="herbalism" enable="false"/>
|
|
||||||
|
|
||||||
<skill name="alchemy" enable="false"/>
|
|
||||||
<skill name="entertainment" enable="false"/>
|
|
||||||
<skill name="espionage" enable="false"/>
|
|
||||||
<skill name="perception" enable="false"/>
|
|
||||||
<skill name="stealth" enable="false"/>
|
|
||||||
<skill name="taxation" enable="false"/>
|
|
||||||
<skill name="trade" enable="false"/>
|
|
||||||
</game>
|
|
||||||
<rules>
|
<rules>
|
||||||
<function name="wage" value="minimum_wage"/>
|
<function name="wage" value="minimum_wage"/>
|
||||||
</rules>
|
</rules>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
local pkg = {}
|
local pkg = {}
|
||||||
|
|
||||||
function pkg.init()
|
function pkg.init()
|
||||||
eressea.settings.set("feature.jsreport.enable", "1")
|
eressea.settings.set("jsreport.enabled", "1")
|
||||||
end
|
end
|
||||||
|
|
||||||
function pkg.update()
|
function pkg.update()
|
||||||
|
|
|
@ -2895,10 +2895,10 @@ static void aftermath(battle * b)
|
||||||
if (sh && fval(sh, SF_DAMAGED)) {
|
if (sh && fval(sh, SF_DAMAGED)) {
|
||||||
int n = b->turn - 2;
|
int n = b->turn - 2;
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.battleround",
|
get_param_flt(global.parameters, "rules.ship.damage.battleround",
|
||||||
0.05F);
|
0.05F);
|
||||||
damage_ship(sh, dmg * (float)n);
|
damage_ship(sh, dmg * n);
|
||||||
freset(sh, SF_DAMAGED);
|
freset(sh, SF_DAMAGED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ static void chaos(region * r)
|
||||||
|
|
||||||
while (sh) {
|
while (sh) {
|
||||||
ship *nsh = sh->next;
|
ship *nsh = sh->next;
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.atlantis",
|
get_param_flt(global.parameters, "rules.ship.damage.atlantis",
|
||||||
0.50);
|
0.50);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
|
|
|
@ -25,7 +25,7 @@ static void coor_from_tiled(int *x, int *y) {
|
||||||
|
|
||||||
static int report_json(const char *filename, report_context * ctx, const char *charset)
|
static int report_json(const char *filename, report_context * ctx, const char *charset)
|
||||||
{
|
{
|
||||||
if (get_param_int(global.parameters, "feature.jsreport.enable", 0) != 0) {
|
if (get_param_int(global.parameters, "jsreport.enabled", 0) != 0) {
|
||||||
FILE * F = fopen(filename, "w");
|
FILE * F = fopen(filename, "w");
|
||||||
if (F) {
|
if (F) {
|
||||||
int x, y, minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;
|
int x, y, minx = INT_MAX, maxx = INT_MIN, miny = INT_MAX, maxy = INT_MIN;
|
||||||
|
|
|
@ -1123,10 +1123,10 @@ void set_basepath(const char *path)
|
||||||
g_basedir = path;
|
g_basedir = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
float get_param_flt(const struct param *p, const char *key, float def)
|
double get_param_flt(const struct param *p, const char *key, double def)
|
||||||
{
|
{
|
||||||
const char *str = get_param(p, key);
|
const char *str = get_param(p, key);
|
||||||
return str ? (float)atof(str) : def;
|
return str ? atof(str) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_param(struct param **p, const char *key, const char *data)
|
void set_param(struct param **p, const char *key, const char *data)
|
||||||
|
@ -1599,16 +1599,6 @@ int maintenance_cost(const struct unit *u)
|
||||||
return u_race(u)->maintenance * u->number;
|
return u_race(u)->maintenance * u->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
int produceexp(struct unit *u, skill_t sk, int n)
|
|
||||||
{
|
|
||||||
if (global.producexpchance > 0.0F) {
|
|
||||||
if (n == 0 || !playerrace(u_race(u)))
|
|
||||||
return 0;
|
|
||||||
learn_skill(u, sk, global.producexpchance);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lovar(double xpct_x2)
|
int lovar(double xpct_x2)
|
||||||
{
|
{
|
||||||
int n = (int)(xpct_x2 * 500) + 1;
|
int n = (int)(xpct_x2 * 500) + 1;
|
||||||
|
|
|
@ -261,8 +261,6 @@ extern "C" {
|
||||||
unsigned int data_turn;
|
unsigned int data_turn;
|
||||||
struct param *parameters;
|
struct param *parameters;
|
||||||
void *vm_state;
|
void *vm_state;
|
||||||
float producexpchance;
|
|
||||||
int cookie;
|
|
||||||
int data_version; /* TODO: eliminate in favor of gamedata.version */
|
int data_version; /* TODO: eliminate in favor of gamedata.version */
|
||||||
struct _dictionary_ *inifile;
|
struct _dictionary_ *inifile;
|
||||||
|
|
||||||
|
@ -271,6 +269,10 @@ extern "C" {
|
||||||
const struct race * rc, int in_turn);
|
const struct race * rc, int in_turn);
|
||||||
int(*maintenance) (const struct unit * u);
|
int(*maintenance) (const struct unit * u);
|
||||||
} functions;
|
} functions;
|
||||||
|
/* the following are some cached values, because get_param can be slow.
|
||||||
|
* you should almost never need to touch them */
|
||||||
|
int cookie;
|
||||||
|
double producexpchance_;
|
||||||
} settings;
|
} settings;
|
||||||
|
|
||||||
typedef struct helpmode {
|
typedef struct helpmode {
|
||||||
|
@ -284,7 +286,7 @@ extern "C" {
|
||||||
const char *get_param(const struct param *p, const char *key);
|
const char *get_param(const struct param *p, const char *key);
|
||||||
int get_param_int(const struct param *p, const char *key, int def);
|
int get_param_int(const struct param *p, const char *key, int def);
|
||||||
int check_param(const struct param *p, const char *key, const char *searchvalue);
|
int check_param(const struct param *p, const char *key, const char *searchvalue);
|
||||||
float get_param_flt(const struct param *p, const char *key, float def);
|
double get_param_flt(const struct param *p, const char *key, double def);
|
||||||
void free_params(struct param **pp);
|
void free_params(struct param **pp);
|
||||||
|
|
||||||
bool ExpensiveMigrants(void);
|
bool ExpensiveMigrants(void);
|
||||||
|
|
|
@ -501,6 +501,45 @@ static void json_prefixes(cJSON *json) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** disable a feature.
|
||||||
|
* features are identified by eone of:
|
||||||
|
* 1. the keyword for their orders,
|
||||||
|
* 2. the name of the skill they use,
|
||||||
|
* 3. a "module.enabled" flag in the settings
|
||||||
|
*/
|
||||||
|
static void disable_feature(const char *str) {
|
||||||
|
char name[32];
|
||||||
|
int k;
|
||||||
|
skill_t sk;
|
||||||
|
sk = findskill(str);
|
||||||
|
if (sk != NOSKILL) {
|
||||||
|
enable_skill(sk, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (k = 0; k != MAXKEYWORDS; ++k) {
|
||||||
|
// FIXME: this loop is slow as balls.
|
||||||
|
if (strcmp(keywords[k], str) == 0) {
|
||||||
|
log_info("disable keyword %s\n", str);
|
||||||
|
enable_keyword(k, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_snprintf(name, sizeof(name), "%s.enabled", str);
|
||||||
|
log_info("disable feature %s\n", name);
|
||||||
|
set_param(&global.parameters, name, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void json_disable_features(cJSON *json) {
|
||||||
|
cJSON *child;
|
||||||
|
if (json->type != cJSON_Array) {
|
||||||
|
log_error("disabled is not a json array: %d", json->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (child = json->child; child; child = child->next) {
|
||||||
|
disable_feature(child->valuestring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void json_terrains(cJSON *json) {
|
static void json_terrains(cJSON *json) {
|
||||||
cJSON *child;
|
cJSON *child;
|
||||||
if (json->type != cJSON_Object) {
|
if (json->type != cJSON_Object) {
|
||||||
|
@ -854,6 +893,9 @@ void json_config(cJSON *json) {
|
||||||
else if (strcmp(child->string, "prefixes") == 0) {
|
else if (strcmp(child->string, "prefixes") == 0) {
|
||||||
json_prefixes(child);
|
json_prefixes(child);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(child->string, "disabled") == 0) {
|
||||||
|
json_disable_features(child);
|
||||||
|
}
|
||||||
else if (strcmp(child->string, "terrains") == 0) {
|
else if (strcmp(child->string, "terrains") == 0) {
|
||||||
json_terrains(child);
|
json_terrains(child);
|
||||||
init_terrains();
|
init_terrains();
|
||||||
|
|
|
@ -99,6 +99,31 @@ static void test_prefixes(CuTest * tc)
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_disable(CuTest * tc)
|
||||||
|
{
|
||||||
|
const char * data = "{\"disabled\": [ "
|
||||||
|
"\"alchemy\","
|
||||||
|
"\"pay\","
|
||||||
|
"\"besiege\","
|
||||||
|
"\"module\""
|
||||||
|
"]}";
|
||||||
|
cJSON *json = cJSON_Parse(data);
|
||||||
|
|
||||||
|
test_cleanup();
|
||||||
|
CuAssertTrue(tc, skill_enabled(SK_ALCHEMY));
|
||||||
|
CuAssertTrue(tc, !keyword_disabled(K_BANNER));
|
||||||
|
CuAssertTrue(tc, !keyword_disabled(K_PAY));
|
||||||
|
CuAssertTrue(tc, !keyword_disabled(K_BESIEGE));
|
||||||
|
CuAssertIntEquals(tc, 1, get_param_int(global.parameters, "module.enabled", 1));
|
||||||
|
json_config(json);
|
||||||
|
CuAssertTrue(tc, !skill_enabled(SK_ALCHEMY));
|
||||||
|
CuAssertTrue(tc, !keyword_disabled(K_BANNER));
|
||||||
|
CuAssertTrue(tc, keyword_disabled(K_PAY));
|
||||||
|
CuAssertTrue(tc, keyword_disabled(K_BESIEGE));
|
||||||
|
CuAssertIntEquals(tc, 0, get_param_int(global.parameters, "module.enabled", 1));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_races(CuTest * tc)
|
static void test_races(CuTest * tc)
|
||||||
{
|
{
|
||||||
const char * data = "{\"races\": { \"orc\" : { "
|
const char * data = "{\"races\": { \"orc\" : { "
|
||||||
|
@ -576,6 +601,7 @@ CuSuite *get_jsonconf_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_flags);
|
SUITE_ADD_TEST(suite, test_flags);
|
||||||
SUITE_ADD_TEST(suite, test_settings);
|
SUITE_ADD_TEST(suite, test_settings);
|
||||||
SUITE_ADD_TEST(suite, test_prefixes);
|
SUITE_ADD_TEST(suite, test_prefixes);
|
||||||
|
SUITE_ADD_TEST(suite, test_disable);
|
||||||
SUITE_ADD_TEST(suite, test_infinitive_from_config);
|
SUITE_ADD_TEST(suite, test_infinitive_from_config);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1933,3 +1933,27 @@ bool unit_name_equals_race(const unit *u) {
|
||||||
bool unit_can_study(const unit *u) {
|
bool unit_can_study(const unit *u) {
|
||||||
return !((u_race(u)->flags & RCF_NOLEARN) || fval(u, UFL_WERE));
|
return !((u_race(u)->flags & RCF_NOLEARN) || fval(u, UFL_WERE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double produceexp_chance(void) {
|
||||||
|
static int update = 0;
|
||||||
|
if (update != global.cookie) {
|
||||||
|
global.producexpchance_ = get_param_flt(global.parameters, "study.from_use", 1.0 / 3);
|
||||||
|
update = global.cookie;
|
||||||
|
}
|
||||||
|
return global.producexpchance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void produceexp_ex(struct unit *u, skill_t sk, int n, bool (*learn)(unit *, skill_t, double))
|
||||||
|
{
|
||||||
|
if (n != 0 && playerrace(u_race(u))) {
|
||||||
|
double chance = produceexp_chance();
|
||||||
|
if (chance > 0.0F) {
|
||||||
|
learn(u, sk, (n * chance) / u->number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void produceexp(struct unit *u, skill_t sk, int n)
|
||||||
|
{
|
||||||
|
produceexp_ex(u, sk, n, learn_skill);
|
||||||
|
}
|
||||||
|
|
|
@ -161,8 +161,9 @@ extern "C" {
|
||||||
struct skill *unit_skill(const struct unit *u, skill_t id);
|
struct skill *unit_skill(const struct unit *u, skill_t id);
|
||||||
bool has_skill(const unit * u, skill_t sk);
|
bool has_skill(const unit * u, skill_t sk);
|
||||||
int effskill(const struct unit *u, skill_t sk, const struct region *r);
|
int effskill(const struct unit *u, skill_t sk, const struct region *r);
|
||||||
int produceexp(struct unit *u, skill_t sk, int n);
|
|
||||||
int SkillCap(skill_t sk);
|
int SkillCap(skill_t sk);
|
||||||
|
void produceexp(struct unit *u, skill_t sk, int n);
|
||||||
|
void produceexp_ex(struct unit *u, skill_t sk, int n, bool (*learn)(unit *, skill_t, double));
|
||||||
|
|
||||||
void set_level(struct unit *u, skill_t id, int level);
|
void set_level(struct unit *u, skill_t id, int level);
|
||||||
int get_level(const struct unit *u, skill_t id);
|
int get_level(const struct unit *u, skill_t id);
|
||||||
|
|
|
@ -350,6 +350,32 @@ static void test_age_familiar(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CuTest *g_tc;
|
||||||
|
|
||||||
|
static bool cb_learn_one(unit *u, skill_t sk, double chance) {
|
||||||
|
CuAssertIntEquals(g_tc, SK_ALCHEMY, sk);
|
||||||
|
CuAssertDblEquals(g_tc, 0.5 / u->number, chance, 0.01);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cb_learn_two(unit *u, skill_t sk, double chance) {
|
||||||
|
CuAssertIntEquals(g_tc, SK_ALCHEMY, sk);
|
||||||
|
CuAssertDblEquals(g_tc, 2 * 0.5 / u->number, chance, 0.01);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_produceexp(CuTest *tc) {
|
||||||
|
unit *u;
|
||||||
|
|
||||||
|
g_tc = tc;
|
||||||
|
test_cleanup();
|
||||||
|
u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0));
|
||||||
|
set_param(&global.parameters, "study.from_use", "0.5");
|
||||||
|
produceexp_ex(u, SK_ALCHEMY, 1, cb_learn_one);
|
||||||
|
produceexp_ex(u, SK_ALCHEMY, 2, cb_learn_two);
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_unit_suite(void)
|
CuSuite *get_unit_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
|
@ -368,5 +394,6 @@ CuSuite *get_unit_suite(void)
|
||||||
SUITE_ADD_TEST(suite, test_skill_hunger);
|
SUITE_ADD_TEST(suite, test_skill_hunger);
|
||||||
SUITE_ADD_TEST(suite, test_skill_familiar);
|
SUITE_ADD_TEST(suite, test_skill_familiar);
|
||||||
SUITE_ADD_TEST(suite, test_age_familiar);
|
SUITE_ADD_TEST(suite, test_age_familiar);
|
||||||
|
SUITE_ADD_TEST(suite, test_produceexp);
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2052,79 +2052,8 @@ static int parse_strings(xmlDocPtr doc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_main(xmlDocPtr doc)
|
|
||||||
{
|
|
||||||
xmlXPathContextPtr xpath = xmlXPathNewContext(doc);
|
|
||||||
xmlXPathObjectPtr result =
|
|
||||||
xmlXPathEvalExpression(BAD_CAST "/eressea/game", xpath);
|
|
||||||
xmlNodeSetPtr nodes = result->nodesetval;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
xmlChar *propValue;
|
|
||||||
if (nodes->nodeNr > 0) {
|
|
||||||
xmlNodePtr node = nodes->nodeTab[0];
|
|
||||||
|
|
||||||
global.producexpchance =
|
|
||||||
(float)xml_fvalue(node, "learningbydoing", 1.0 / 3);
|
|
||||||
|
|
||||||
propValue = xmlGetProp(node, BAD_CAST "name");
|
|
||||||
if (propValue != NULL) {
|
|
||||||
global.gamename = _strdup((const char *)propValue);
|
|
||||||
xmlFree(propValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlXPathFreeObject(result);
|
|
||||||
|
|
||||||
xpath->node = node;
|
|
||||||
/* reading eressea/game/order */
|
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "order", xpath);
|
|
||||||
nodes = result->nodesetval;
|
|
||||||
for (i = 0; i != nodes->nodeNr; ++i) {
|
|
||||||
xmlNodePtr node = nodes->nodeTab[i];
|
|
||||||
xmlChar *propName = xmlGetProp(node, BAD_CAST "name");
|
|
||||||
bool disable = xml_bvalue(node, "disable", false);
|
|
||||||
|
|
||||||
if (disable) {
|
|
||||||
int k;
|
|
||||||
for (k = 0; k != MAXKEYWORDS; ++k) {
|
|
||||||
if (strcmp(keywords[k], (const char *)propName) == 0) {
|
|
||||||
enable_keyword(k, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (k == MAXKEYWORDS) {
|
|
||||||
log_error("trying to disable unknown command %s\n", (const char *)propName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlFree(propName);
|
|
||||||
}
|
|
||||||
|
|
||||||
xmlXPathFreeObject(result);
|
|
||||||
|
|
||||||
/* reading eressea/game/skill */
|
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "skill", xpath);
|
|
||||||
nodes = result->nodesetval;
|
|
||||||
for (i = 0; i != nodes->nodeNr; ++i) {
|
|
||||||
xmlNodePtr node = nodes->nodeTab[i];
|
|
||||||
xmlChar *propName = xmlGetProp(node, BAD_CAST "name");
|
|
||||||
skill_t sk = findskill((const char *)propName);
|
|
||||||
if (sk != NOSKILL) {
|
|
||||||
bool enable = xml_bvalue(node, "enable", true);
|
|
||||||
enable_skill(sk, enable);
|
|
||||||
}
|
|
||||||
xmlFree(propName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
xmlXPathFreeObject(result);
|
|
||||||
|
|
||||||
xmlXPathFreeContext(xpath);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void register_xmlreader(void)
|
void register_xmlreader(void)
|
||||||
{
|
{
|
||||||
xml_register_callback(parse_main);
|
|
||||||
|
|
||||||
xml_register_callback(parse_strings);
|
xml_register_callback(parse_strings);
|
||||||
xml_register_callback(parse_messages);
|
xml_register_callback(parse_messages);
|
||||||
xml_register_callback(parse_resources);
|
xml_register_callback(parse_resources);
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
#include <kernel/config.h>
|
#include <kernel/config.h>
|
||||||
#include "keyword.h"
|
#include "keyword.h"
|
||||||
|
|
||||||
#include "util/language.h"
|
#include <util/language.h>
|
||||||
#include "util/umlaut.h"
|
#include <util/umlaut.h>
|
||||||
|
#include <util/log.h>
|
||||||
|
|
||||||
#include <critbit.h>
|
#include <critbit.h>
|
||||||
|
|
||||||
|
|
|
@ -2762,14 +2762,14 @@ void sinkships(struct region * r)
|
||||||
if (fval(r->terrain, SEA_REGION)) {
|
if (fval(r->terrain, SEA_REGION)) {
|
||||||
if (!enoughsailors(sh, crew_skill(sh))) {
|
if (!enoughsailors(sh, crew_skill(sh))) {
|
||||||
// ship is at sea, but not enough people to control it
|
// ship is at sea, but not enough people to control it
|
||||||
float dmg = get_param_flt(global.parameters,
|
double dmg = get_param_flt(global.parameters,
|
||||||
"rules.ship.damage.nocrewocean",
|
"rules.ship.damage.nocrewocean",
|
||||||
0.30F);
|
0.30F);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
}
|
}
|
||||||
} else if (!ship_owner(sh)) {
|
} else if (!ship_owner(sh)) {
|
||||||
// any ship lying around without an owner slowly rots
|
// any ship lying around without an owner slowly rots
|
||||||
float dmg = get_param_flt(global.parameters, "rules.ship.damage.nocrew", 0.05F);
|
double dmg = get_param_flt(global.parameters, "rules.ship.damage.nocrew", 0.05F);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3496,7 +3496,7 @@ static int use_item(unit * u, const item_type * itype, int amount, struct order
|
||||||
|
|
||||||
static double heal_factor(const unit * u)
|
static double heal_factor(const unit * u)
|
||||||
{
|
{
|
||||||
static float elf_regen = -1;
|
static double elf_regen = -1;
|
||||||
switch (old_race(u_race(u))) {
|
switch (old_race(u_race(u))) {
|
||||||
case RC_TROLL:
|
case RC_TROLL:
|
||||||
case RC_DAEMON:
|
case RC_DAEMON:
|
||||||
|
|
|
@ -80,7 +80,7 @@ static void give_peasants(unit *u, const item_type *itype, int reduce) {
|
||||||
unit_addorder(u, parse_order(buf, u->faction->locale));
|
unit_addorder(u, parse_order(buf, u->faction->locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
static float monster_attack_chance(void) {
|
static double monster_attack_chance(void) {
|
||||||
return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f);
|
return get_param_flt(global.parameters, "rules.monsters.attack_chance", 0.4f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -704,7 +704,7 @@ static float damage_drift(void)
|
||||||
{
|
{
|
||||||
static float value = -1.0F;
|
static float value = -1.0F;
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
value = get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F);
|
value = (float)get_param_flt(global.parameters, "rules.ship.damage_drift", 0.02F);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -1955,7 +1955,7 @@ sail(unit * u, order * ord, bool move_on_land, region_list ** routep)
|
||||||
ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point));
|
ADDMSG(&f->msgs, msg_message("sailnolandingstorm", "ship region", sh, next_point));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.nolanding",
|
get_param_flt(global.parameters, "rules.ship.damage.nolanding",
|
||||||
0.10F);
|
0.10F);
|
||||||
ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh,
|
ADDMSG(&f->msgs, msg_message("sailnolanding", "ship region", sh,
|
||||||
|
|
|
@ -746,7 +746,7 @@ static void move_iceberg(region * r)
|
||||||
|
|
||||||
for (sh = r->ships; sh; sh = sh->next) {
|
for (sh = r->ships; sh; sh = sh->next) {
|
||||||
/* Meldung an Kapitän */
|
/* Meldung an Kapitän */
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.intoiceberg",
|
get_param_flt(global.parameters, "rules.ship.damage.intoiceberg",
|
||||||
0.10F);
|
0.10F);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
|
@ -759,7 +759,7 @@ static void move_iceberg(region * r)
|
||||||
translist(&rc->buildings, &r->buildings, rc->buildings);
|
translist(&rc->buildings, &r->buildings, rc->buildings);
|
||||||
}
|
}
|
||||||
while (rc->ships) {
|
while (rc->ships) {
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.withiceberg",
|
get_param_flt(global.parameters, "rules.ship.damage.withiceberg",
|
||||||
0.10F);
|
0.10F);
|
||||||
fset(rc->ships, SF_SELECT);
|
fset(rc->ships, SF_SELECT);
|
||||||
|
@ -893,7 +893,7 @@ static void godcurse(void)
|
||||||
ship *sh;
|
ship *sh;
|
||||||
for (sh = r->ships; sh;) {
|
for (sh = r->ships; sh;) {
|
||||||
ship *shn = sh->next;
|
ship *shn = sh->next;
|
||||||
float dmg =
|
double dmg =
|
||||||
get_param_flt(global.parameters, "rules.ship.damage.godcurse",
|
get_param_flt(global.parameters, "rules.ship.damage.godcurse",
|
||||||
0.10F);
|
0.10F);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
|
|
|
@ -71,6 +71,8 @@ struct unit *test_create_unit(struct faction *f, struct region *r)
|
||||||
|
|
||||||
void test_cleanup(void)
|
void test_cleanup(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
free_terrains();
|
free_terrains();
|
||||||
free_resources();
|
free_resources();
|
||||||
global.functions.maintenance = NULL;
|
global.functions.maintenance = NULL;
|
||||||
|
@ -87,6 +89,12 @@ void test_cleanup(void)
|
||||||
free_seen();
|
free_seen();
|
||||||
free_prefixes();
|
free_prefixes();
|
||||||
mt_clear();
|
mt_clear();
|
||||||
|
for (i = 0; i != MAXSKILLS; ++i) {
|
||||||
|
enable_skill(i, true);
|
||||||
|
}
|
||||||
|
for (i = 0; i != MAXKEYWORDS; ++i) {
|
||||||
|
enable_keyword(i, true);
|
||||||
|
}
|
||||||
if (!mt_find("missing_message")) {
|
if (!mt_find("missing_message")) {
|
||||||
mt_register(mt_new_va("missing_message", "name:string", 0));
|
mt_register(mt_new_va("missing_message", "name:string", 0));
|
||||||
mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0));
|
mt_register(mt_new_va("missing_feedback", "unit:unit", "region:region", "command:order", "name:string", 0));
|
||||||
|
|
Loading…
Reference in New Issue