BUG 2478: Fleeing units cannot move.

This commit is contained in:
Enno Rehling 2018-09-23 20:01:12 +02:00
parent 0759482934
commit d70f05f8db
2 changed files with 87 additions and 31 deletions

View File

@ -101,7 +101,7 @@ typedef enum combatmagic {
#define MAXSPELLRANGE 7
#define ROW_FACTOR 3 /* factor for combat row advancement rule */
#define EFFECT_PANIC_SPELL 0.25
#define EFFECT_PANIC_SPELL 25
#define TROLL_REGENERATION 0.10
/* Nach dem alten System: */
@ -126,6 +126,9 @@ const troop no_troop = { 0, 0 };
static int max_turns;
static int rule_damage;
static int rule_loot;
static int flee_chance_max_percent;
static int flee_chance_base;
static int flee_chance_skill_bonus;
static int skill_formula;
static int rule_cavalry_skill;
static int rule_population_damage;
@ -144,6 +147,9 @@ static void init_rules(void)
{
it_mistletoe = it_find("mistletoe");
flee_chance_skill_bonus = config_get_int("rules.combat.flee_chance_bonus", 5);
flee_chance_base = config_get_int("rules.combat.flee_chance_base", 20);
flee_chance_max_percent = config_get_int("rules.combat.flee_chance_limit", 90);
rule_nat_armor = config_get_int("rules.combat.nat_armor", 0);
rule_tactics_formula = config_get_int("rules.tactics.formula", 0);
rule_goblin_bonus = config_get_int("rules.combat.goblinbonus", 10);
@ -2276,7 +2282,7 @@ static void add_tactics(tactics * ta, fighter * fig, int value)
ta->value = value;
}
static double horse_fleeing_bonus(const unit * u)
static int horse_fleeing_bonus(const unit * u)
{
const item_type *it_horse, *it_elvenhorse, *it_charger;
int n1 = 0, n2 = 0, n3 = 0;
@ -2299,26 +2305,26 @@ static double horse_fleeing_bonus(const unit * u)
}
}
if (skl >= 5 && n3 >= u->number)
return 0.30;
return 30;
if (skl >= 2 && n2 + n3 >= u->number)
return 0.20;
return 20;
if (n1 + n2 + n3 >= u->number)
return 0.10;
return 0.0F;
return 10;
return 0;
}
double fleechance(unit * u)
static int fleechance(unit * u)
{
double p = 0.20; /* Fluchtwahrscheinlichkeit in % */
int p = flee_chance_base; /* Fluchtwahrscheinlichkeit in % */
/* Einheit u versucht, dem Get<65>mmel zu entkommen */
p += (effskill(u, SK_STEALTH, 0) * 0.05);
p += (effskill(u, SK_STEALTH, 0) * flee_chance_skill_bonus);
p += horse_fleeing_bonus(u);
if (u_race(u) == get_race(RC_HALFLING)) {
p += 0.20;
if (p > 0.9) {
p = 0.9;
p += flee_chance_base;
if (p > flee_chance_max_percent) {
p = flee_chance_max_percent;
}
}
return p;
@ -2617,7 +2623,7 @@ static void aftermath(battle * b)
}
}
snumber += du->number;
if (df->alive == 0) {
if (dead == df->unit->number) {
flags = UFL_DEAD;
}
else if (relevant) {
@ -3631,14 +3637,22 @@ static void flee(const troop dt)
{
fighter *fig = dt.fighter;
unit *u = fig->unit;
int fchance = fleechance(u);
if (fig->person[dt.index].flags & FL_PANICED) {
fchance += EFFECT_PANIC_SPELL;
}
if (fchance > flee_chance_max_percent) {
fchance = flee_chance_max_percent;
}
if (rng_int() % 100 < fchance) {
fig->run.hp += fig->person[dt.index].hp;
++fig->run.number;
setguard(u, false);
kill_troop(dt);
}
}
static bool is_calmed(const unit *u, const faction *f) {
attrib *a = a_find(u->attribs, &at_curse);
@ -3881,7 +3895,6 @@ static void battle_flee(battle * b)
dt.fighter = fig;
dt.index = fig->alive - fig->removed;
while (s->size[SUM_ROW] && dt.index != 0) {
double ispaniced = 0.0;
--dt.index;
assert(dt.index >= 0 && dt.index < fig->unit->number);
assert(fig->person[dt.index].hp > 0);
@ -3906,18 +3919,12 @@ static void battle_flee(battle * b)
}
continue;
}
if (fig->person[dt.index].flags & FL_PANICED) {
ispaniced = EFFECT_PANIC_SPELL;
}
if (chance(fmin(fleechance(u) + ispaniced, 0.90))) {
flee(dt);
}
}
}
}
}
}
static bool is_enemy(battle *b, unit *u1, unit *u2) {
if (u1->faction != u2->faction) {
@ -3966,8 +3973,7 @@ void force_leave(region *r, battle *b) {
}
void do_battle(region * r)
{
static void do_battle(region * r) {
battle *b = NULL;
bool fighting;
ship *sh;

View File

@ -2,6 +2,8 @@
#include "battle.h"
#include "guard.h"
#include "keyword.h"
#include "reports.h"
#include "skill.h"
@ -10,6 +12,7 @@
#include <kernel/faction.h>
#include <kernel/curse.h>
#include <kernel/item.h>
#include <kernel/order.h>
#include <kernel/race.h>
#include <kernel/region.h>
#include <kernel/ship.h>
@ -17,6 +20,7 @@
#include <spells/buildingcurse.h>
#include <util/base36.h>
#include <util/functions.h>
#include <util/language.h>
#include <util/message.h>
@ -31,6 +35,21 @@
#include "tests.h"
static void setup_messages(void) {
mt_create_va(mt_new("start_battle", NULL), "factions:string", MT_NEW_END);
mt_create_va(mt_new("para_army_index", NULL), "index:int", "name:string", MT_NEW_END);
mt_create_va(mt_new("battle_msg", NULL), "string:string", MT_NEW_END);
mt_create_va(mt_new("battle_row", NULL), "row:int", MT_NEW_END);
mt_create_va(mt_new("para_lineup_battle", NULL), "turn:int", MT_NEW_END);
mt_create_va(mt_new("para_after_battle", NULL), MT_NEW_END);
mt_create_va(mt_new("army_report", NULL),
"index:int", "abbrev:string", "dead:int", "fled:int", "survived:int",
MT_NEW_END);
mt_create_va(mt_new("casualties", NULL),
"unit:unit", "runto:region", "run:int", "alive:int", "fallen:int",
MT_NEW_END);
}
static void test_make_fighter(CuTest * tc)
{
unit *au;
@ -566,7 +585,7 @@ static void test_battle_report_one(CuTest *tc)
fighter *fig;
test_setup();
mt_create_va(mt_new("start_battle", NULL), "factions:string", MT_NEW_END);
setup_messages();
r = test_create_plain(0, 0);
u1 = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
@ -597,7 +616,7 @@ static void test_battle_report_two(CuTest *tc)
test_setup();
lang = test_create_locale();
locale_setstring(lang, "and", "and");
mt_create_va(mt_new("start_battle", NULL), "factions:string", MT_NEW_END);
setup_messages();
r = test_create_plain(0, 0);
u1 = test_create_unit(test_create_faction(NULL), r);
u1->faction->locale = lang;
@ -630,7 +649,7 @@ static void test_battle_report_three(CuTest *tc)
test_setup();
lang = test_create_locale();
locale_setstring(lang, "and", "and");
mt_create_va(mt_new("start_battle", NULL), "factions:string", MT_NEW_END);
setup_messages();
r = test_create_plain(0, 0);
u1 = test_create_unit(test_create_faction(NULL), r);
u1->faction->locale = lang;
@ -783,12 +802,43 @@ static void test_tactics_chance(CuTest *tc) {
test_teardown();
}
static void test_battle_fleeing(CuTest *tc) {
region *r;
unit *u1, *u2;
test_setup();
setup_messages();
r = test_create_plain(0, 0);
u1 = test_create_unit(test_create_faction(NULL), r);
u2 = test_create_unit(test_create_faction(NULL), r);
u1->status = ST_FLEE;
u2->status = ST_AGGRO;
#if 0
setguard(u1, true);
CuAssertIntEquals(tc, UFL_GUARD, (u1->flags & UFL_GUARD));
CuAssertIntEquals(tc, RF_GUARDED, (r->flags & RF_GUARDED));
#endif
config_set_int("rules.combat.flee_chance_base", 100);
config_set_int("rules.combat.flee_chance_limit", 100);
unit_addorder(u2, create_order(K_ATTACK, u2->faction->locale, itoa36(u1->no)));
do_battles();
CuAssertIntEquals(tc, 1, u1->number);
CuAssertIntEquals(tc, 1, u2->number);
#if 0
CuAssertIntEquals(tc, 0, (u1->flags & UFL_GUARD));
CuAssertIntEquals(tc, 0, (r->flags & RF_GUARDED));
#endif
CuAssertIntEquals(tc, UFL_LONGACTION, (u1->flags & UFL_LONGACTION));
CuAssertIntEquals(tc, UFL_LONGACTION | UFL_NOTMOVING, (u2->flags & (UFL_LONGACTION | UFL_NOTMOVING)));
test_teardown();
}
CuSuite *get_battle_suite(void)
{
CuSuite *suite = CuSuiteNew();
SUITE_ADD_TEST(suite, test_make_fighter);
SUITE_ADD_TEST(suite, test_select_weapon_restricted);
SUITE_ADD_TEST(suite, test_select_armor);
SUITE_ADD_TEST(suite, test_battle_fleeing);
SUITE_ADD_TEST(suite, test_battle_skilldiff);
SUITE_ADD_TEST(suite, test_battle_skilldiff_building);
SUITE_ADD_TEST(suite, test_battle_report_one);