From ad0464ab50d1615b71a7acd857e68252939196cd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 1 Aug 2018 10:04:12 +0200 Subject: [PATCH] BUG 2168: call sink_ship for ships that take too much damage. --- clibs | 2 +- scripts/tests/e2/e2features.lua | 13 +++++++++++++ src/battle.c | 5 ++++- src/bind_unit.c | 2 +- src/chaos.c | 20 +++++++++++--------- src/chaos.h | 2 -- src/kernel/ship.h | 6 +++--- src/laws.c | 1 + src/move.c | 9 +++++++-- src/randenc.c | 3 +++ src/spy.c | 25 +++++++++++++++---------- src/spy.h | 6 ++---- 12 files changed, 61 insertions(+), 33 deletions(-) diff --git a/clibs b/clibs index 9b6e34959..d86c85254 160000 --- a/clibs +++ b/clibs @@ -1 +1 @@ -Subproject commit 9b6e34959f77d7ca3a4ce3826cb487487f557441 +Subproject commit d86c8525489d7f11b7ba13e101bb59ecf160b871 diff --git a/scripts/tests/e2/e2features.lua b/scripts/tests/e2/e2features.lua index be09ec448..721ad7a1c 100644 --- a/scripts/tests/e2/e2features.lua +++ b/scripts/tests/e2/e2features.lua @@ -517,3 +517,16 @@ function test_buy_sell() assert_equal(4, u:get_item(item)) assert_not_equal(0, u:get_item('money')) end + +function test_seaserpent_attack() + local r = region.create(0, 0, 'ocean') + local sh = ship.create(r, 'boat') + local us = unit.create(get_monsters(), r, 1, 'seaserpent') + local u = unit.create(faction.create('human'), r, 20, 'human') + u.ship = sh + us:clear_orders() + us:add_order('ATTACKIERE ' .. itoa36(u.id)) + us:set_skill('unarmed', 10) + process_orders() + write_reports() +end diff --git a/src/battle.c b/src/battle.c index 38590b8a6..9e2f841c0 100644 --- a/src/battle.c +++ b/src/battle.c @@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "move.h" #include "skill.h" #include "study.h" +#include "spy.h" #include #include @@ -2787,10 +2788,12 @@ static void aftermath(battle * b) ship *sh = *sp; freset(sh, SF_DAMAGED); if (sh->damage >= sh->size * DAMAGE_SCALE) { + sink_ship(sh); remove_ship(sp, sh); } - if (*sp == sh) + else { sp = &sh->next; + } } } diff --git a/src/bind_unit.c b/src/bind_unit.c index e0fa9f86b..7858aadf2 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -909,8 +909,8 @@ static int tolua_unit_create(lua_State * L) faction *f = (faction *)tolua_tousertype(L, 1, 0); region *r = (region *)tolua_tousertype(L, 2, 0); unit *u; - const char *rcname = tolua_tostring(L, 4, NULL); int num = (int)tolua_tonumber(L, 3, 1); + const char *rcname = tolua_tostring(L, 4, NULL); const race *rc; assert(f && r); diff --git a/src/chaos.c b/src/chaos.c index 21a5a8624..1ec431b7e 100644 --- a/src/chaos.c +++ b/src/chaos.c @@ -21,6 +21,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "chaos.h" #include "monsters.h" #include "move.h" +#include "spy.h" #include #include @@ -144,19 +145,20 @@ static void chaos(region * r) break; } if (dir != MAXDIRECTIONS) { - ship *sh = r->ships; + ship **slist = &r->ships; unit **up; - while (sh) { - ship *nsh = sh->next; - double dmg = - config_get_flt("rules.ship.damage.atlantis", - 0.50); - damage_ship(sh, dmg); + while (*slist) { + ship *sh = *slist; + + damage_ship(sh, 0.5); if (sh->damage >= sh->size * DAMAGE_SCALE) { - remove_ship(&sh->region->ships, sh); + sink_ship(sh); + remove_ship(slist, sh); + } + else { + slist = &sh->next; } - sh = nsh; } for (up = &r->units; *up;) { diff --git a/src/chaos.h b/src/chaos.h index 550aa3efb..cb913d1a0 100644 --- a/src/chaos.h +++ b/src/chaos.h @@ -22,8 +22,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif - struct region; - void chaos_update(void); #ifdef __cplusplus diff --git a/src/kernel/ship.h b/src/kernel/ship.h index c726b4839..ce3283a6f 100644 --- a/src/kernel/ship.h +++ b/src/kernel/ship.h @@ -124,9 +124,9 @@ extern "C" { extern void write_ship_reference(const struct ship *sh, struct storage *store); - extern void remove_ship(struct ship **slist, struct ship *s); - extern void free_ship(struct ship *s); - extern void free_ships(void); + void remove_ship(struct ship **slist, struct ship *s); + void free_ship(struct ship *s); + void free_ships(void); const char *ship_getname(const struct ship *sh); void ship_setname(struct ship *self, const char *name); diff --git a/src/laws.c b/src/laws.c index aa6e237e2..35e4732f1 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2590,6 +2590,7 @@ void sinkships(struct region * r) } } if (sh->damage >= sh->size * DAMAGE_SCALE) { + sink_ship(sh); remove_ship(shp, sh); } if (*shp == sh) diff --git a/src/move.c b/src/move.c index 205b52416..b815f5ea5 100644 --- a/src/move.c +++ b/src/move.c @@ -47,6 +47,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "laws.h" #include "reports.h" #include "study.h" +#include "spy.h" #include "alchemy.h" #include "travelthru.h" #include "vortex.h" @@ -541,6 +542,7 @@ static ship *do_maelstrom(region * r, unit * u) if (sh->damage >= sh->size * DAMAGE_SCALE) { ADDMSG(&u->faction->msgs, msg_message("entermaelstrom", "region ship damage sink", r, sh, damage, 1)); + sink_ship(sh); remove_ship(&sh->region->ships, sh); return NULL; } @@ -882,12 +884,14 @@ static void drifting_ships(region * r) } if (sh->damage >= sh->size * DAMAGE_SCALE) { msg_to_ship_inmates(sh, &firstu, &lastu, msg_message("shipsink", "ship", sh)); - remove_ship(&sh->region->ships, sh); + sink_ship(sh); + remove_ship(shp, sh); } } - if (*shp == sh) + if (*shp == sh) { shp = &sh->next; + } } } } @@ -1926,6 +1930,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting) if (sh->damage >= sh->size * DAMAGE_SCALE) { if (sh->region) { ADDMSG(&f->msgs, msg_message("shipsink", "ship", sh)); + sink_ship(sh); remove_ship(&sh->region->ships, sh); } sh = NULL; diff --git a/src/randenc.c b/src/randenc.c index 7de49b9e2..820d3760f 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "economy.h" #include "monsters.h" #include "move.h" +#include "spy.h" #include "study.h" #include "volcano.h" @@ -295,6 +296,7 @@ static void move_iceberg(region * r) ADDMSG(&u->faction->msgs, msg_message("overrun_by_iceberg_des", "ship", sh)); } + sink_ship(sh); remove_ship(&sh->region->ships, sh); } else if (u != NULL) { @@ -421,6 +423,7 @@ static void godcurse(void) ADDMSG(&uo->faction->msgs, msg_message("godcurse_destroy_ship", "ship", sh)); } + sink_ship(sh); remove_ship(&sh->region->ships, sh); } sh = shn; diff --git a/src/spy.c b/src/spy.c index 94d6c4e7d..c0afbe43c 100644 --- a/src/spy.c +++ b/src/spy.c @@ -392,19 +392,22 @@ static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff) return 1; /* success */ } -static void sink_ship(region * r, ship * sh, unit * saboteur) +#define OCEAN_SWIMMER_CHANCE 0.1 +#define COAST_SWIMMER_CHANCE 0.9 + +void sink_ship(ship * sh) { unit **ui, *u; - region *safety = r; + region *r, *safety; int i; direction_t d; double probability = 0.0; message *sink_msg = NULL; faction *f; - assert(r); - assert(sh); - assert(saboteur); + assert(sh && sh->region); + r = sh->region; + for (f = NULL, u = r->units; u; u = u->next) { /* slight optimization to avoid dereferencing u->faction each time */ if (f != u->faction) { @@ -414,8 +417,9 @@ static void sink_ship(region * r, ship * sh, unit * saboteur) } /* figure out what a unit's chances of survival are: */ + safety = r; if (!(r->terrain->flags & SEA_REGION)) { - probability = CANAL_SWIMMER_CHANCE; + probability = COAST_SWIMMER_CHANCE; } else { for (d = 0; d != MAXDIRECTIONS; ++d) { @@ -479,10 +483,9 @@ static void sink_ship(region * r, ship * sh, unit * saboteur) } ui = &u->next; } - if (sink_msg) + if (sink_msg) { msg_release(sink_msg); - /* finally, get rid of the ship */ - remove_ship(&sh->region->ships, sh); + } } int sabotage_cmd(unit * u, struct order *ord) @@ -514,7 +517,9 @@ int sabotage_cmd(unit * u, struct order *ord) effskill(u, SK_SPY, 0) - top_skill(u->region, u2->faction, sh, SK_PERCEPTION); } if (try_destruction(u, u2, sh, skdiff)) { - sink_ship(u->region, sh, u); + sink_ship(sh); + /* finally, get rid of the ship */ + remove_ship(&sh->region->ships, sh); } break; default: diff --git a/src/spy.h b/src/spy.h index 665595ef4..b0bd7ae0e 100644 --- a/src/spy.h +++ b/src/spy.h @@ -27,6 +27,7 @@ extern "C" { struct strlist; struct order; struct faction; + struct ship; int setstealth_cmd(struct unit *u, struct order *ord); int spy_cmd(struct unit *u, struct order *ord); @@ -34,10 +35,7 @@ extern "C" { void spy_message(int spy, const struct unit *u, const struct unit *target); void set_factionstealth(struct unit * u, struct faction * f); - - -#define OCEAN_SWIMMER_CHANCE 0.1 -#define CANAL_SWIMMER_CHANCE 0.9 + void sink_ship(struct ship * sh); #ifdef __cplusplus }