BUG 2168: call sink_ship for ships that take too much damage.

This commit is contained in:
Enno Rehling 2018-08-01 10:04:12 +02:00
parent 7eb951544a
commit ad0464ab50
12 changed files with 61 additions and 33 deletions

2
clibs

@ -1 +1 @@
Subproject commit 9b6e34959f77d7ca3a4ce3826cb487487f557441
Subproject commit d86c8525489d7f11b7ba13e101bb59ecf160b871

View file

@ -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

View file

@ -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 <spells/buildingcurse.h>
#include <spells/regioncurse.h>
@ -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;
}
}
}

View file

@ -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);

View file

@ -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 <kernel/building.h>
#include <kernel/faction.h>
@ -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;) {

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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:

View file

@ -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
}