forked from github/server
BUG 2423: only apply other skill modifiers if race-modifier doesn't drop skill below 1.
This commit is contained in:
parent
7e33b2a94d
commit
ef3b72ceb7
6 changed files with 111 additions and 74 deletions
|
@ -21,10 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "skill.h"
|
||||
|
||||
#include "curse.h"
|
||||
#include "race.h"
|
||||
#include "region.h"
|
||||
#include "terrain.h"
|
||||
#include "terrainid.h"
|
||||
#include "unit.h"
|
||||
|
||||
#include <util/attrib.h>
|
||||
|
@ -91,61 +88,6 @@ skillmod(const unit * u, const region * r, skill_t sk, int value)
|
|||
return value;
|
||||
}
|
||||
|
||||
int skill_mod(const race * rc, skill_t sk, const struct terrain_type *terrain)
|
||||
{
|
||||
int result = 0;
|
||||
static int rc_cache;
|
||||
static const race *rc_dwarf, *rc_insect;
|
||||
|
||||
if (rc_changed(&rc_cache)) {
|
||||
rc_dwarf = get_race(RC_DWARF);
|
||||
rc_insect = get_race(RC_INSECT);
|
||||
}
|
||||
result = rc->bonus[sk];
|
||||
|
||||
if (rc == rc_dwarf) {
|
||||
if (sk == SK_TACTICS) {
|
||||
if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION))
|
||||
++result;
|
||||
}
|
||||
}
|
||||
else if (rc == rc_insect) {
|
||||
if (terrain == newterrain(T_MOUNTAIN) || fval(terrain, ARCTIC_REGION))
|
||||
--result;
|
||||
else if (terrain == newterrain(T_DESERT) || terrain == newterrain(T_SWAMP))
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int rc_skillmod(const struct race *rc, const region * r, skill_t sk)
|
||||
{
|
||||
int mods = 0;
|
||||
if (!skill_enabled(sk)) {
|
||||
return 0;
|
||||
}
|
||||
if (r) {
|
||||
mods = skill_mod(rc, sk, r->terrain);
|
||||
}
|
||||
if (r && r_isforest(r)) {
|
||||
static int rc_cache;
|
||||
static const race * rc_elf;
|
||||
if (rc_changed(&rc_cache)) {
|
||||
rc_elf = get_race(RC_ELF);
|
||||
}
|
||||
if (rc == rc_elf) {
|
||||
if (sk == SK_PERCEPTION || sk == SK_STEALTH) {
|
||||
++mods;
|
||||
}
|
||||
else if (sk == SK_TACTICS) {
|
||||
mods += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
||||
int level_days(int level)
|
||||
{
|
||||
/* FIXME STUDYDAYS * ((level + 1) * level / 2); */
|
||||
|
|
|
@ -44,7 +44,6 @@ extern "C" {
|
|||
|
||||
extern struct attrib_type at_skillmod;
|
||||
|
||||
int rc_skillmod(const struct race *rc, const struct region *r, skill_t sk);
|
||||
int skillmod(const struct unit *u, const struct region *r, skill_t sk, int value);
|
||||
struct attrib *make_skillmod(skill_t sk, skillmod_fun special, double multiplier, int bonus);
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "ship.h"
|
||||
#include "skill.h"
|
||||
#include "terrain.h"
|
||||
#include "terrainid.h"
|
||||
|
||||
#include <attributes/otherfaction.h>
|
||||
#include <attributes/racename.h>
|
||||
|
@ -1132,8 +1133,8 @@ skill *add_skill(unit * u, skill_t sk)
|
|||
skill *sv;
|
||||
int i;
|
||||
|
||||
for (i=0; i != u->skill_size; ++i) {
|
||||
sv = u->skills+i;
|
||||
for (i = 0; i != u->skill_size; ++i) {
|
||||
sv = u->skills + i;
|
||||
if (sv->id >= sk) break;
|
||||
}
|
||||
u->skills = realloc(u->skills, (1 + u->skill_size) * sizeof(skill));
|
||||
|
@ -1235,8 +1236,62 @@ static int att_modification(const unit * u, skill_t sk)
|
|||
return (int)result;
|
||||
}
|
||||
|
||||
static int terrain_mod(const race * rc, skill_t sk, const region *r)
|
||||
{
|
||||
static int rc_cache, t_cache;
|
||||
static const race *rc_dwarf, *rc_insect, *rc_elf;
|
||||
static const terrain_type *t_mountain, *t_desert, *t_swamp;
|
||||
const struct terrain_type *terrain = r->terrain;
|
||||
|
||||
if (terrain_changed(&t_cache)) {
|
||||
t_mountain = get_terrain(terrainnames[T_MOUNTAIN]);
|
||||
t_desert = get_terrain(terrainnames[T_DESERT]);
|
||||
t_swamp = get_terrain(terrainnames[T_SWAMP]);
|
||||
}
|
||||
if (rc_changed(&rc_cache)) {
|
||||
rc_elf = get_race(RC_ELF);
|
||||
rc_dwarf = get_race(RC_DWARF);
|
||||
rc_insect = get_race(RC_INSECT);
|
||||
}
|
||||
|
||||
if (rc == rc_dwarf) {
|
||||
if (sk == SK_TACTICS) {
|
||||
if (terrain == t_mountain || fval(terrain, ARCTIC_REGION))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (rc == rc_insect) {
|
||||
if (terrain == t_mountain || fval(terrain, ARCTIC_REGION)) {
|
||||
return -1;
|
||||
}
|
||||
else if (terrain == t_desert || terrain == t_swamp) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (rc == rc_elf) {
|
||||
if (r_isforest(r)) {
|
||||
if (sk == SK_PERCEPTION || sk == SK_STEALTH) {
|
||||
return 1;
|
||||
}
|
||||
else if (sk == SK_TACTICS) {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rc_skillmod(const struct race *rc, skill_t sk)
|
||||
{
|
||||
if (!skill_enabled(sk)) {
|
||||
return 0;
|
||||
}
|
||||
return rc->bonus[sk];
|
||||
}
|
||||
|
||||
int get_modifier(const unit * u, skill_t sk, int level, const region * r, bool noitem)
|
||||
{
|
||||
const struct race *rc = u_race(u);
|
||||
int bskill = level;
|
||||
int skill = bskill;
|
||||
|
||||
|
@ -1247,12 +1302,16 @@ int get_modifier(const unit * u, skill_t sk, int level, const region * r, bool n
|
|||
}
|
||||
}
|
||||
|
||||
skill += rc_skillmod(u_race(u), r, sk);
|
||||
skill += rc_skillmod(rc, sk);
|
||||
if (skill > 0) {
|
||||
if (r) {
|
||||
skill += terrain_mod(rc, sk, r);
|
||||
}
|
||||
skill += att_modification(u, sk);
|
||||
if (u->attribs) {
|
||||
skill = skillmod(u, r, sk, skill);
|
||||
}
|
||||
|
||||
}
|
||||
if (fval(u, UFL_HUNGER)) {
|
||||
if (sk == SK_SAILING && skill > 2) {
|
||||
skill = skill - 1;
|
||||
|
@ -1374,7 +1433,7 @@ void default_name(const unit *u, char name[], int len) {
|
|||
const char * prefix;
|
||||
prefix = LOC(lang, "unitdefault");
|
||||
if (!prefix) {
|
||||
prefix= parameters[P_UNIT];
|
||||
prefix = parameters[P_UNIT];
|
||||
}
|
||||
result = prefix;
|
||||
}
|
||||
|
@ -1631,7 +1690,7 @@ int unit_max_hp(const unit * u)
|
|||
h = u_race(u)->hitpoints;
|
||||
|
||||
if (config_changed(&config)) {
|
||||
rule_stamina = config_get_int("rules.stamina", 1)!=0;
|
||||
rule_stamina = config_get_int("rules.stamina", 1) != 0;
|
||||
}
|
||||
if (rule_stamina) {
|
||||
double p = pow(effskill(u, SK_STAMINA, u->region) / 2.0, 1.5) * 0.2;
|
||||
|
@ -1654,7 +1713,7 @@ void scale_number(unit * u, int n)
|
|||
return;
|
||||
}
|
||||
if (u->number > 0) {
|
||||
if (n>0) {
|
||||
if (n > 0) {
|
||||
const attrib *a = a_find(u->attribs, &at_effect);
|
||||
|
||||
u->hp = (long long)u->hp * n / u->number;
|
||||
|
@ -1928,7 +1987,7 @@ bool has_limited_skills(const struct unit * u)
|
|||
double u_heal_factor(const unit * u)
|
||||
{
|
||||
const race * rc = u_race(u);
|
||||
if (rc->healing>0) {
|
||||
if (rc->healing > 0) {
|
||||
return rc->healing / 100.0;
|
||||
}
|
||||
if (r_isforest(u->region)) {
|
||||
|
|
|
@ -622,6 +622,37 @@ static void test_transfermen(CuTest *tc) {
|
|||
test_teardown();
|
||||
}
|
||||
|
||||
static void test_get_modifier(CuTest *tc) {
|
||||
race * rc;
|
||||
region *r;
|
||||
unit *u;
|
||||
terrain_type *t_plain, *t_desert;
|
||||
|
||||
test_setup();
|
||||
t_desert = test_create_terrain("desert", -1);
|
||||
t_plain = test_create_terrain("plain", -1);
|
||||
rc = test_create_race("insect");
|
||||
rc->bonus[SK_ARMORER] = 1;
|
||||
rc->bonus[SK_TAXING] = 0;
|
||||
rc->bonus[SK_TRADE] = -1;
|
||||
u = test_create_unit(test_create_faction(rc), r = test_create_region(0, 0, t_plain));
|
||||
|
||||
/* no effects for insects in plains: */
|
||||
CuAssertIntEquals(tc, 0, get_modifier(u, SK_TAXING, 0, r, true));
|
||||
CuAssertIntEquals(tc, 0, get_modifier(u, SK_TAXING, 1, r, true));
|
||||
CuAssertIntEquals(tc, 0, get_modifier(u, SK_TAXING, 7, r, true));
|
||||
|
||||
r = test_create_region(1, 0, t_desert);
|
||||
/* terrain effect: +1 for insects in deserts: */
|
||||
CuAssertIntEquals(tc, 1, get_modifier(u, SK_TAXING, 1, r, true));
|
||||
/* no terrain effects if no region is given: */
|
||||
CuAssertIntEquals(tc, 0, get_modifier(u, SK_TAXING, 1, NULL, true));
|
||||
/* only get terrain effect if they have at least level 1: */
|
||||
CuAssertIntEquals(tc, 0, get_modifier(u, SK_TAXING, 0, r, true));
|
||||
|
||||
test_teardown();
|
||||
}
|
||||
|
||||
CuSuite *get_unit_suite(void)
|
||||
{
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
@ -652,5 +683,6 @@ CuSuite *get_unit_suite(void)
|
|||
SUITE_ADD_TEST(suite, test_renumber_unit);
|
||||
SUITE_ADD_TEST(suite, test_name_unit);
|
||||
SUITE_ADD_TEST(suite, test_heal_factor);
|
||||
SUITE_ADD_TEST(suite, test_get_modifier);
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -266,9 +266,14 @@ void test_teardown(void)
|
|||
}
|
||||
|
||||
terrain_type *
|
||||
test_create_terrain(const char * name, unsigned int flags)
|
||||
test_create_terrain(const char * name, int flags)
|
||||
{
|
||||
terrain_type * t = get_or_create_terrain(name);
|
||||
|
||||
if (flags < 0) {
|
||||
/* sensible defaults for most terrains */
|
||||
flags = LAND_REGION | WALK_INTO | FLY_INTO;
|
||||
}
|
||||
if (flags & LAND_REGION) {
|
||||
t->size = 1000;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ extern "C" {
|
|||
void test_log_stop(struct log_t *log, struct strlist *slist);
|
||||
|
||||
struct locale * test_create_locale(void);
|
||||
struct terrain_type * test_create_terrain(const char * name, unsigned int flags);
|
||||
struct terrain_type * test_create_terrain(const char * name, int flags);
|
||||
struct race *test_create_race(const char *name);
|
||||
struct region *test_create_region(int x, int y, const struct terrain_type *terrain);
|
||||
struct region *test_create_ocean(int x, int y);
|
||||
|
|
Loading…
Reference in a new issue