forked from github/server
Merge branch 'develop' of github.com:eressea/server into develop
This commit is contained in:
commit
bf8d3b57b3
|
@ -1,3 +1,4 @@
|
||||||
|
.vscode/
|
||||||
*.orig
|
*.orig
|
||||||
eressea.ini
|
eressea.ini
|
||||||
Debug
|
Debug
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
<race name="dragon" magres="0.700000" maxaura="1.0" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac=
|
<race name="dragon" magres="0.700000" maxaura="1.0" regaura="2.000000" weight="10000" capacity="1000000" speed="1.500000" hp="900" ac=
|
||||||
"6" damage="2d30" unarmedattack="0" unarmeddefense="0"
|
"6" damage="2d30" unarmedattack="0" unarmeddefense="0"
|
||||||
attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes"
|
attackmodifier="7" defensemodifier="7" scarepeasants="yes" fly="yes"
|
||||||
walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes">
|
income="1000" walk="yes" teach="no" getitem="yes" resistbash="yes"
|
||||||
|
dragon="yes">
|
||||||
<ai splitsize="2" killpeasants="yes" learn="yes" scare="400"/>
|
<ai splitsize="2" killpeasants="yes" learn="yes" scare="400"/>
|
||||||
<function name="name" value="namedragon"/>
|
<function name="name" value="namedragon"/>
|
||||||
<function name="age" value="agedragon"/>
|
<function name="age" value="agedragon"/>
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
<race name="wyrm" magres="0.900000" maxaura="1.0" regaura="3.000000" weight="18000" capacity="1000000" speed="1.0" hp="2700" ac="8" damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10" defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes">
|
<race name="wyrm" magres="0.900000" maxaura="1.0" regaura="3.000000"
|
||||||
|
weight="18000" capacity="1000000" speed="1.0" hp="2700" ac="8"
|
||||||
|
damage="2d60" unarmedattack="0" unarmeddefense="0" attackmodifier="10"
|
||||||
|
defensemodifier="10" scarepeasants="yes" fly="yes" walk="yes"
|
||||||
|
teach="no" getitem="yes" resistbash="yes" dragon="yes" income="5000">
|
||||||
<ai splitsize="1" killpeasants="yes" learn="yes" scare="1000"/>
|
<ai splitsize="1" killpeasants="yes" learn="yes" scare="1000"/>
|
||||||
<function name="name" value="namedragon"/>
|
<function name="name" value="namedragon"/>
|
||||||
<function name="move" value="movedragon"/>
|
<function name="move" value="movedragon"/>
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
<race name="youngdragon" magres="0.500000" maxaura="1.0" regaura="1.0" weight="8000" capacity="10000" speed="1.0" hp="300" ac="4" damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4" defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes" teach="no" getitem="yes" resistbash="yes" dragon="yes">
|
<race name="youngdragon" magres="0.500000" maxaura="1.0" regaura="1.0"
|
||||||
|
weight="8000" capacity="10000" speed="1.0" hp="300" ac="4"
|
||||||
|
damage="2d15" unarmedattack="0" unarmeddefense="0" attackmodifier="4"
|
||||||
|
defensemodifier="4" scarepeasants="yes" fly="yes" walk="yes"
|
||||||
|
teach="no" getitem="yes" resistbash="yes" dragon="yes" income="150">
|
||||||
<ai splitsize="6" killpeasants="yes" learn="yes" scare="160"/>
|
<ai splitsize="6" killpeasants="yes" learn="yes" scare="160"/>
|
||||||
<function name="name" value="namedragon"/>
|
<function name="name" value="namedragon"/>
|
||||||
<function name="age" value="agefiredragon"/>
|
<function name="age" value="agefiredragon"/>
|
||||||
|
|
|
@ -10,7 +10,7 @@ $BUILD/iniparser/inifile eressea.ini add lua:paths lunit:scripts
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
integraton_tests() {
|
integration_tests() {
|
||||||
cd tests
|
cd tests
|
||||||
./write-reports.sh
|
./write-reports.sh
|
||||||
./run-turn.sh
|
./run-turn.sh
|
||||||
|
@ -24,4 +24,4 @@ cd $ROOT
|
||||||
inifile
|
inifile
|
||||||
s/runtests
|
s/runtests
|
||||||
|
|
||||||
integraton_tests
|
integration_tests
|
||||||
|
|
11
src/battle.c
11
src/battle.c
|
@ -1886,7 +1886,13 @@ int skilldiff(troop at, troop dt, int dist)
|
||||||
unit *au = af->unit, *du = df->unit;
|
unit *au = af->unit, *du = df->unit;
|
||||||
int is_protected = 0, skdiff = 0;
|
int is_protected = 0, skdiff = 0;
|
||||||
weapon *awp = select_weapon(at, true, dist > 1);
|
weapon *awp = select_weapon(at, true, dist > 1);
|
||||||
|
static int rc_cache;
|
||||||
|
static const race *rc_halfling, *rc_goblin;
|
||||||
|
|
||||||
|
if (rc_changed(&rc_cache)) {
|
||||||
|
rc_halfling = get_race(RC_HALFLING);
|
||||||
|
rc_goblin = get_race(RC_GOBLIN);
|
||||||
|
}
|
||||||
skdiff += af->person[at.index].attack;
|
skdiff += af->person[at.index].attack;
|
||||||
skdiff -= df->person[dt.index].defence;
|
skdiff -= df->person[dt.index].defence;
|
||||||
|
|
||||||
|
@ -1894,11 +1900,10 @@ int skilldiff(troop at, troop dt, int dist)
|
||||||
skdiff += 2;
|
skdiff += 2;
|
||||||
|
|
||||||
/* Effekte durch Rassen */
|
/* Effekte durch Rassen */
|
||||||
if (awp != NULL && u_race(au) == get_race(RC_HALFLING) && dragonrace(u_race(du))) {
|
if (awp != NULL && u_race(au) == rc_halfling && dragonrace(u_race(du))) {
|
||||||
skdiff += 5;
|
skdiff += 5;
|
||||||
}
|
}
|
||||||
|
else if (u_race(au) == rc_goblin) {
|
||||||
if (u_race(au) == get_race(RC_GOBLIN)) {
|
|
||||||
if (af->side->size[SUM_ROW] >= df->side->size[SUM_ROW] * rule_goblin_bonus) {
|
if (af->side->size[SUM_ROW] >= df->side->size[SUM_ROW] * rule_goblin_bonus) {
|
||||||
skdiff += 1;
|
skdiff += 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,20 +114,8 @@ static void recruit_init(void)
|
||||||
|
|
||||||
int income(const unit * u)
|
int income(const unit * u)
|
||||||
{
|
{
|
||||||
// TODO: make this a property, like race.income, no hard-coding of values
|
const race *rc = u_race(u);
|
||||||
if (fval(u_race(u), RCF_DRAGON)) {
|
return rc->income * u->number;
|
||||||
switch (old_race(u_race(u))) {
|
|
||||||
case RC_FIREDRAGON:
|
|
||||||
return 150 * u->number;
|
|
||||||
case RC_DRAGON:
|
|
||||||
return 1000 * u->number;
|
|
||||||
case RC_WYRM:
|
|
||||||
return 5000 * u->number;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 20 * u->number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scramble(void *data, unsigned int n, size_t width)
|
static void scramble(void *data, unsigned int n, size_t width)
|
||||||
|
|
|
@ -328,11 +328,25 @@ static void test_recruit(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_income(CuTest *tc)
|
||||||
|
{
|
||||||
|
race *rc;
|
||||||
|
unit *u;
|
||||||
|
test_setup();
|
||||||
|
rc = test_create_race("nerd");
|
||||||
|
u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0));
|
||||||
|
CuAssertIntEquals(tc, 20, income(u));
|
||||||
|
u->number = 5;
|
||||||
|
CuAssertIntEquals(tc, 100, income(u));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_economy_suite(void)
|
CuSuite *get_economy_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_give_control_building);
|
SUITE_ADD_TEST(suite, test_give_control_building);
|
||||||
SUITE_ADD_TEST(suite, test_give_control_ship);
|
SUITE_ADD_TEST(suite, test_give_control_ship);
|
||||||
|
SUITE_ADD_TEST(suite, test_income);
|
||||||
SUITE_ADD_TEST(suite, test_steal_okay);
|
SUITE_ADD_TEST(suite, test_steal_okay);
|
||||||
SUITE_ADD_TEST(suite, test_steal_ocean);
|
SUITE_ADD_TEST(suite, test_steal_ocean);
|
||||||
SUITE_ADD_TEST(suite, test_steal_nosteal);
|
SUITE_ADD_TEST(suite, test_steal_nosteal);
|
||||||
|
|
|
@ -137,16 +137,6 @@ int NMRTimeout(void)
|
||||||
return config_get_int("nmr.timeout", 0);
|
return config_get_int("nmr.timeout", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
race_t old_race(const struct race * rc)
|
|
||||||
{
|
|
||||||
race_t i;
|
|
||||||
// TODO: this sucks so bad!
|
|
||||||
for (i = 0; i != MAXRACES; ++i) {
|
|
||||||
if (get_race(i) == rc) return i;
|
|
||||||
}
|
|
||||||
return NORACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
helpmode helpmodes[] = {
|
helpmode helpmodes[] = {
|
||||||
{ "all", HELP_ALL }
|
{ "all", HELP_ALL }
|
||||||
,
|
,
|
||||||
|
|
|
@ -481,6 +481,9 @@ static void json_race(cJSON *json, race *rc) {
|
||||||
else if (strcmp(child->string, "capacity") == 0) {
|
else if (strcmp(child->string, "capacity") == 0) {
|
||||||
rc->capacity = child->valueint;
|
rc->capacity = child->valueint;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(child->string, "income") == 0) {
|
||||||
|
rc->income = child->valueint;
|
||||||
|
}
|
||||||
else if (strcmp(child->string, "hp") == 0) {
|
else if (strcmp(child->string, "hp") == 0) {
|
||||||
rc->hitpoints = child->valueint;
|
rc->hitpoints = child->valueint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,7 @@ static void test_races(CuTest * tc)
|
||||||
"\"maintenance\" : 2,"
|
"\"maintenance\" : 2,"
|
||||||
"\"weight\" : 3,"
|
"\"weight\" : 3,"
|
||||||
"\"capacity\" : 4,"
|
"\"capacity\" : 4,"
|
||||||
|
"\"income\" : 30,"
|
||||||
"\"hp\" : 5,"
|
"\"hp\" : 5,"
|
||||||
"\"ac\" : 6,"
|
"\"ac\" : 6,"
|
||||||
"\"flags\" : [ \"npc\", \"walk\", \"undead\" ]"
|
"\"flags\" : [ \"npc\", \"walk\", \"undead\" ]"
|
||||||
|
@ -167,6 +168,7 @@ static void test_races(CuTest * tc)
|
||||||
CuAssertIntEquals(tc, 2, rc->maintenance);
|
CuAssertIntEquals(tc, 2, rc->maintenance);
|
||||||
CuAssertIntEquals(tc, 3, rc->weight);
|
CuAssertIntEquals(tc, 3, rc->weight);
|
||||||
CuAssertIntEquals(tc, 4, rc->capacity);
|
CuAssertIntEquals(tc, 4, rc->capacity);
|
||||||
|
CuAssertIntEquals(tc, 30, rc->income);
|
||||||
CuAssertIntEquals(tc, 5, rc->hitpoints);
|
CuAssertIntEquals(tc, 5, rc->hitpoints);
|
||||||
CuAssertIntEquals(tc, 6, rc->armor);
|
CuAssertIntEquals(tc, 6, rc->armor);
|
||||||
cJSON_Delete(json);
|
cJSON_Delete(json);
|
||||||
|
|
|
@ -86,6 +86,50 @@ const struct race *get_race(race_t rt) {
|
||||||
return rc_find(name);
|
return rc_find(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct xref {
|
||||||
|
race_t id;
|
||||||
|
const race *rc;
|
||||||
|
} rc_xref;
|
||||||
|
|
||||||
|
int cmp_xref(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const rc_xref *l = (const rc_xref *)a;
|
||||||
|
const rc_xref *r = (const rc_xref *)b;
|
||||||
|
if (l->rc<r->rc) return -1;
|
||||||
|
if (l->rc>r->rc) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static rc_xref *xrefs;
|
||||||
|
race_t old_race(const struct race * rc)
|
||||||
|
{
|
||||||
|
static int cache;
|
||||||
|
int i, l, r;
|
||||||
|
|
||||||
|
if (rc_changed(&cache)) {
|
||||||
|
if (!xrefs) {
|
||||||
|
xrefs = malloc(sizeof(rc_xref) * MAXRACES);
|
||||||
|
}
|
||||||
|
for (i = 0; i != MAXRACES; ++i) {
|
||||||
|
xrefs[i].rc = get_race(i);
|
||||||
|
xrefs[i].id = (race_t)i;
|
||||||
|
}
|
||||||
|
qsort(xrefs, MAXRACES, sizeof(rc_xref), cmp_xref);
|
||||||
|
}
|
||||||
|
l=0; r=MAXRACES-1;
|
||||||
|
while (l<=r) {
|
||||||
|
int m = (l+r)/2;
|
||||||
|
if (rc<xrefs[m].rc) {
|
||||||
|
r = m-1;
|
||||||
|
} else if (rc>xrefs[m].rc) {
|
||||||
|
l = m+1;
|
||||||
|
} else {
|
||||||
|
return (race_t)xrefs[m].id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NORACE;
|
||||||
|
}
|
||||||
|
|
||||||
race_list *get_familiarraces(void)
|
race_list *get_familiarraces(void)
|
||||||
{
|
{
|
||||||
static int init = 0;
|
static int init = 0;
|
||||||
|
@ -126,6 +170,8 @@ void free_races(void) {
|
||||||
while (races) {
|
while (races) {
|
||||||
race * rc = races->next;
|
race * rc = races->next;
|
||||||
free_params(&races->parameters);
|
free_params(&races->parameters);
|
||||||
|
free(xrefs);
|
||||||
|
xrefs = 0;
|
||||||
free(races->_name);
|
free(races->_name);
|
||||||
free(races->def_damage);
|
free(races->def_damage);
|
||||||
free(races);
|
free(races);
|
||||||
|
@ -173,6 +219,7 @@ race *rc_create(const char *zName)
|
||||||
rc->hitpoints = 1;
|
rc->hitpoints = 1;
|
||||||
rc->weight = PERSON_WEIGHT;
|
rc->weight = PERSON_WEIGHT;
|
||||||
rc->capacity = 540;
|
rc->capacity = 540;
|
||||||
|
rc->income = 20;
|
||||||
rc->recruit_multi = 1.0F;
|
rc->recruit_multi = 1.0F;
|
||||||
rc->regaura = 1.0F;
|
rc->regaura = 1.0F;
|
||||||
rc->speed = 1.0F;
|
rc->speed = 1.0F;
|
||||||
|
|
|
@ -124,6 +124,7 @@ extern "C" {
|
||||||
int splitsize;
|
int splitsize;
|
||||||
int weight;
|
int weight;
|
||||||
int capacity;
|
int capacity;
|
||||||
|
int income;
|
||||||
float speed;
|
float speed;
|
||||||
float aggression; /* chance that a monster will attack */
|
float aggression; /* chance that a monster will attack */
|
||||||
int hitpoints;
|
int hitpoints;
|
||||||
|
|
|
@ -32,6 +32,7 @@ static void test_rc_defaults(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 0, rc->recruitcost);
|
CuAssertIntEquals(tc, 0, rc->recruitcost);
|
||||||
CuAssertIntEquals(tc, 0, rc->maintenance);
|
CuAssertIntEquals(tc, 0, rc->maintenance);
|
||||||
CuAssertIntEquals(tc, 540, rc->capacity);
|
CuAssertIntEquals(tc, 540, rc->capacity);
|
||||||
|
CuAssertIntEquals(tc, 20, rc->income);
|
||||||
CuAssertIntEquals(tc, 1, rc->hitpoints);
|
CuAssertIntEquals(tc, 1, rc->hitpoints);
|
||||||
CuAssertIntEquals(tc, 0, rc->armor);
|
CuAssertIntEquals(tc, 0, rc->armor);
|
||||||
CuAssertIntEquals(tc, 0, rc->at_bonus);
|
CuAssertIntEquals(tc, 0, rc->at_bonus);
|
||||||
|
@ -65,10 +66,26 @@ static void test_race_get(CuTest *tc) {
|
||||||
test_cleanup();
|
test_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_old_race(CuTest *tc)
|
||||||
|
{
|
||||||
|
race * rc1, *rc2;
|
||||||
|
test_setup();
|
||||||
|
test_create_race("dwarf");
|
||||||
|
rc1 = test_create_race("elf");
|
||||||
|
rc2 = test_create_race("onkel");
|
||||||
|
CuAssertIntEquals(tc, RC_ELF, old_race(rc1));
|
||||||
|
CuAssertIntEquals(tc, NORACE, old_race(rc2));
|
||||||
|
rc2 = test_create_race("human");
|
||||||
|
CuAssertIntEquals(tc, RC_ELF, old_race(rc1));
|
||||||
|
CuAssertIntEquals(tc, RC_HUMAN, old_race(rc2));
|
||||||
|
test_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
CuSuite *get_race_suite(void)
|
CuSuite *get_race_suite(void)
|
||||||
{
|
{
|
||||||
CuSuite *suite = CuSuiteNew();
|
CuSuite *suite = CuSuiteNew();
|
||||||
SUITE_ADD_TEST(suite, test_race_get);
|
SUITE_ADD_TEST(suite, test_race_get);
|
||||||
|
SUITE_ADD_TEST(suite, test_old_race);
|
||||||
SUITE_ADD_TEST(suite, test_rc_name);
|
SUITE_ADD_TEST(suite, test_rc_name);
|
||||||
SUITE_ADD_TEST(suite, test_rc_defaults);
|
SUITE_ADD_TEST(suite, test_rc_defaults);
|
||||||
SUITE_ADD_TEST(suite, test_rc_find);
|
SUITE_ADD_TEST(suite, test_rc_find);
|
||||||
|
|
|
@ -1656,6 +1656,7 @@ static int parse_races(xmlDocPtr doc)
|
||||||
rc->maintenance = xml_ivalue(node, "maintenance", rc->maintenance);
|
rc->maintenance = xml_ivalue(node, "maintenance", rc->maintenance);
|
||||||
rc->weight = xml_ivalue(node, "weight", rc->weight);
|
rc->weight = xml_ivalue(node, "weight", rc->weight);
|
||||||
rc->capacity = xml_ivalue(node, "capacity", rc->capacity);
|
rc->capacity = xml_ivalue(node, "capacity", rc->capacity);
|
||||||
|
rc->income = xml_ivalue(node, "income", rc->income);
|
||||||
rc->speed = (float)xml_fvalue(node, "speed", rc->speed);
|
rc->speed = (float)xml_fvalue(node, "speed", rc->speed);
|
||||||
rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints);
|
rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints);
|
||||||
rc->armor = (char)xml_ivalue(node, "ac", rc->armor);
|
rc->armor = (char)xml_ivalue(node, "ac", rc->armor);
|
||||||
|
|
|
@ -125,7 +125,13 @@ static bool RemoveNMRNewbie(void)
|
||||||
|
|
||||||
static void age_unit(region * r, unit * u)
|
static void age_unit(region * r, unit * u)
|
||||||
{
|
{
|
||||||
if (u_race(u) == get_race(RC_SPELL)) {
|
static int rc_cache;
|
||||||
|
static const race *rc_spell;
|
||||||
|
|
||||||
|
if (rc_changed(&rc_cache)) {
|
||||||
|
rc_spell = get_race(RC_SPELL);
|
||||||
|
}
|
||||||
|
if (u_race(u) == rc_spell) {
|
||||||
if (--u->age <= 0) {
|
if (--u->age <= 0) {
|
||||||
remove_unit(&r->units, u);
|
remove_unit(&r->units, u);
|
||||||
}
|
}
|
||||||
|
|
96
src/magic.c
96
src/magic.c
|
@ -1031,9 +1031,8 @@ cancast(unit * u, const spell * sp, int level, int range, struct order * ord)
|
||||||
double
|
double
|
||||||
spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order *ord)
|
spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order *ord)
|
||||||
{
|
{
|
||||||
curse *c;
|
|
||||||
double force = cast_level;
|
double force = cast_level;
|
||||||
int elf_power;
|
static int elf_power, config;
|
||||||
const struct resource_type *rtype;
|
const struct resource_type *rtype;
|
||||||
|
|
||||||
if (sp == NULL) {
|
if (sp == NULL) {
|
||||||
|
@ -1046,54 +1045,65 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order
|
||||||
if (btype && btype->flags & BTF_MAGIC) ++force;
|
if (btype && btype->flags & BTF_MAGIC) ++force;
|
||||||
}
|
}
|
||||||
|
|
||||||
elf_power = config_get_int("rules.magic.elfpower", 0);
|
if (config_changed(&config)) {
|
||||||
|
elf_power = config_get_int("rules.magic.elfpower", 0);
|
||||||
if (elf_power && u_race(u) == get_race(RC_ELF) && r_isforest(r)) {
|
}
|
||||||
++force;
|
if (elf_power) {
|
||||||
|
static int rc_cache;
|
||||||
|
static const race *rc_elf;
|
||||||
|
if (rc_changed(&rc_cache)) {
|
||||||
|
rc_elf = get_race(RC_ELF);
|
||||||
|
}
|
||||||
|
if (u_race(u) == rc_elf && r_isforest(r)) {
|
||||||
|
++force;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rtype = rt_find("rop");
|
rtype = rt_find("rop");
|
||||||
if (rtype && i_get(u->items, rtype->itype) > 0) {
|
if (rtype && i_get(u->items, rtype->itype) > 0) {
|
||||||
++force;
|
++force;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Antimagie in der Zielregion */
|
if (r->attribs) {
|
||||||
c = get_curse(r->attribs, ct_find("antimagiczone"));
|
curse *c;
|
||||||
if (curse_active(c)) {
|
|
||||||
unit *mage = c->magician;
|
/* Antimagie in der Zielregion */
|
||||||
force -= curse_geteffect(c);
|
c = get_curse(r->attribs, ct_find("antimagiczone"));
|
||||||
curse_changevigour(&r->attribs, c, -cast_level);
|
if (curse_active(c)) {
|
||||||
cmistake(u, ord, 185, MSG_MAGIC);
|
unit *mage = c->magician;
|
||||||
if (mage != NULL && mage->faction != NULL) {
|
force -= curse_geteffect(c);
|
||||||
if (force > 0) {
|
curse_changevigour(&r->attribs, c, -cast_level);
|
||||||
ADDMSG(&mage->faction->msgs, msg_message("reduce_spell",
|
cmistake(u, ord, 185, MSG_MAGIC);
|
||||||
"self mage region", mage, u, r));
|
if (mage != NULL && mage->faction != NULL) {
|
||||||
|
if (force > 0) {
|
||||||
|
ADDMSG(&mage->faction->msgs, msg_message("reduce_spell",
|
||||||
|
"self mage region", mage, u, r));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADDMSG(&mage->faction->msgs, msg_message("block_spell",
|
||||||
|
"self mage region", mage, u, r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
ADDMSG(&mage->faction->msgs, msg_message("block_spell",
|
|
||||||
"self mage region", mage, u, r));
|
/* Patzerfluch-Effekt: */
|
||||||
|
c = get_curse(r->attribs, ct_find("fumble"));
|
||||||
|
if (curse_active(c)) {
|
||||||
|
unit *mage = c->magician;
|
||||||
|
force -= curse_geteffect(c);
|
||||||
|
curse_changevigour(&u->attribs, c, -1);
|
||||||
|
cmistake(u, ord, 185, MSG_MAGIC);
|
||||||
|
if (mage != NULL && mage->faction != NULL) {
|
||||||
|
if (force > 0) {
|
||||||
|
ADDMSG(&mage->faction->msgs, msg_message("reduce_spell",
|
||||||
|
"self mage region", mage, u, r));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ADDMSG(&mage->faction->msgs, msg_message("block_spell",
|
||||||
|
"self mage region", mage, u, r));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Patzerfluch-Effekt: */
|
|
||||||
c = get_curse(r->attribs, ct_find("fumble"));
|
|
||||||
if (curse_active(c)) {
|
|
||||||
unit *mage = c->magician;
|
|
||||||
force -= curse_geteffect(c);
|
|
||||||
curse_changevigour(&u->attribs, c, -1);
|
|
||||||
cmistake(u, ord, 185, MSG_MAGIC);
|
|
||||||
if (mage != NULL && mage->faction != NULL) {
|
|
||||||
if (force > 0) {
|
|
||||||
ADDMSG(&mage->faction->msgs, msg_message("reduce_spell",
|
|
||||||
"self mage region", mage, u, r));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ADDMSG(&mage->faction->msgs, msg_message("block_spell",
|
|
||||||
"self mage region", mage, u, r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _max(force, 0);
|
return _max(force, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2784,6 +2794,8 @@ void magic(void)
|
||||||
int rank;
|
int rank;
|
||||||
castorder *co;
|
castorder *co;
|
||||||
spellrank spellranks[MAX_SPELLRANK];
|
spellrank spellranks[MAX_SPELLRANK];
|
||||||
|
const race *rc_spell = get_race(RC_SPELL);
|
||||||
|
const race *rc_insect = get_race(RC_INSECT);
|
||||||
|
|
||||||
memset(spellranks, 0, sizeof(spellranks));
|
memset(spellranks, 0, sizeof(spellranks));
|
||||||
|
|
||||||
|
@ -2792,10 +2804,10 @@ void magic(void)
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
order *ord;
|
order *ord;
|
||||||
|
|
||||||
if (u->number <= 0 || u_race(u) == get_race(RC_SPELL))
|
if (u->number <= 0 || u_race(u) == rc_spell)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) &&
|
if (u_race(u) == rc_insect && r_insectstalled(r) &&
|
||||||
!is_cursed(u->attribs, C_KAELTESCHUTZ, 0))
|
!is_cursed(u->attribs, C_KAELTESCHUTZ, 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -269,47 +269,57 @@ static direction_t richest_neighbour(region * r, faction * f, int absolut)
|
||||||
|
|
||||||
static bool room_for_race_in_region(region * r, const race * rc)
|
static bool room_for_race_in_region(region * r, const race * rc)
|
||||||
{
|
{
|
||||||
unit *u;
|
if (rc->splitsize > 0) {
|
||||||
int c = 0;
|
unit *u;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
if (u_race(u) == rc)
|
if (u_race(u) == rc) {
|
||||||
c += u->number;
|
c += u->number;
|
||||||
|
if (c > rc->splitsize * 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c > (rc->splitsize * 2))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static direction_t random_neighbour(region * r, unit * u)
|
static direction_t random_neighbour(region * r, unit * u)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
region *rc;
|
region *next[MAXDIRECTIONS], *backup[MAXDIRECTIONS];
|
||||||
region * next[MAXDIRECTIONS];
|
region **pick;
|
||||||
int rr, c = 0, c2 = 0;
|
int rr, c = 0, c2 = 0;
|
||||||
|
const race *rc = u_race(u);
|
||||||
|
|
||||||
get_neighbours(r, next);
|
get_neighbours(r, next);
|
||||||
/* Nachsehen, wieviele Regionen in Frage kommen */
|
/* Nachsehen, wieviele Regionen in Frage kommen */
|
||||||
|
|
||||||
for (i = 0; i != MAXDIRECTIONS; i++) {
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
||||||
rc = next[i];
|
region *rn = next[i];
|
||||||
if (rc && can_survive(u, rc)) {
|
if (rn && can_survive(u, rn)) {
|
||||||
if (room_for_race_in_region(rc, u_race(u))) {
|
if (room_for_race_in_region(rn, rc)) {
|
||||||
c++;
|
c++;
|
||||||
|
} else {
|
||||||
|
next[i] = NULL;
|
||||||
}
|
}
|
||||||
|
backup[i] = rn;
|
||||||
c2++;
|
c2++;
|
||||||
|
} else {
|
||||||
|
next[i] = NULL;
|
||||||
|
backup[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pick = next;
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
if (c2 == 0) {
|
if (c2 == 0) {
|
||||||
return NODIRECTION;
|
return NODIRECTION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
pick = backup;
|
||||||
c = c2;
|
c = c2;
|
||||||
c2 = 0; /* c2 == 0 -> room_for_race nicht beachten */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,18 +329,14 @@ static direction_t random_neighbour(region * r, unit * u)
|
||||||
|
|
||||||
/* Durchzählen */
|
/* Durchzählen */
|
||||||
|
|
||||||
c = -1;
|
c = 0;
|
||||||
for (i = 0; i != MAXDIRECTIONS; i++) {
|
for (i = 0; i != MAXDIRECTIONS; i++) {
|
||||||
rc = next[i];
|
region *rn = pick[i];
|
||||||
if (rc && can_survive(u, rc)) {
|
if (rn) {
|
||||||
if (c2 == 0) {
|
if (c == rr) {
|
||||||
c++;
|
|
||||||
}
|
|
||||||
else if (room_for_race_in_region(rc, u_race(u))) {
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
if (c == rr)
|
|
||||||
return (direction_t)i;
|
return (direction_t)i;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,19 +552,21 @@ static order *monster_learn(unit * u)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_overpopulated(unit * u)
|
static bool check_overpopulated(const unit * u)
|
||||||
{
|
{
|
||||||
unit *u2;
|
const race *rc = u_race(u);
|
||||||
int c = 0;
|
if (rc->splitsize > 0) {
|
||||||
|
unit *u2;
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
for (u2 = u->region->units; u2; u2 = u2->next) {
|
for (u2 = u->region->units; u2; u2 = u2->next) {
|
||||||
if (u_race(u2) == u_race(u) && u != u2)
|
if (u != u2 && u_race(u2) == rc) {
|
||||||
c += u2->number;
|
c += u2->number;
|
||||||
|
if (c > rc->splitsize * 2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c > u_race(u)->splitsize * 2)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -731,11 +731,16 @@ static void orc_growth(void)
|
||||||
static void demon_skillchanges(void)
|
static void demon_skillchanges(void)
|
||||||
{
|
{
|
||||||
region *r;
|
region *r;
|
||||||
|
static const race *rc_demon;
|
||||||
|
static int rc_cache;
|
||||||
|
|
||||||
|
if (rc_changed(&rc_cache)) {
|
||||||
|
rc_demon = get_race(RC_DAEMON);
|
||||||
|
}
|
||||||
for (r = regions; r; r = r->next) {
|
for (r = regions; r; r = r->next) {
|
||||||
unit *u;
|
unit *u;
|
||||||
for (u = r->units; u; u = u->next) {
|
for (u = r->units; u; u = u->next) {
|
||||||
if (u_race(u) == get_race(RC_DAEMON)) {
|
if (u_race(u) == rc_demon) {
|
||||||
demon_skillchange(u);
|
demon_skillchange(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -546,6 +546,12 @@ int study_cmd(unit * u, order * ord)
|
||||||
int maxalchemy = 0;
|
int maxalchemy = 0;
|
||||||
int speed_rule = (study_rule_t)config_get_int("study.speedup", 0);
|
int speed_rule = (study_rule_t)config_get_int("study.speedup", 0);
|
||||||
bool learn_newskills = config_get_int("study.newskills", 1) != 0;
|
bool learn_newskills = config_get_int("study.newskills", 1) != 0;
|
||||||
|
static const race *rc_snotling;
|
||||||
|
static int rc_cache;
|
||||||
|
|
||||||
|
if (rc_changed(&rc_cache)) {
|
||||||
|
rc_snotling = get_race(RC_SNOTLING);
|
||||||
|
}
|
||||||
|
|
||||||
if (!unit_can_study(u)) {
|
if (!unit_can_study(u)) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_race_nolearn", "race",
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_race_nolearn", "race",
|
||||||
|
@ -575,7 +581,7 @@ int study_cmd(unit * u, order * ord)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* snotlings koennen Talente nur bis T8 lernen */
|
/* snotlings koennen Talente nur bis T8 lernen */
|
||||||
if (u_race(u) == get_race(RC_SNOTLING)) {
|
if (u_race(u) == rc_snotling) {
|
||||||
if (get_level(u, sk) >= 8) {
|
if (get_level(u, sk) >= 8) {
|
||||||
cmistake(u, ord, 308, MSG_EVENT);
|
cmistake(u, ord, 308, MSG_EVENT);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue