forked from github/server
add number of ships for convoys.
check required crew skills. require number of captains >= ship.number.
This commit is contained in:
parent
84633b50e1
commit
178f7c2e19
|
@ -75,3 +75,92 @@ function test_speedy_ship_fast()
|
||||||
process_orders()
|
process_orders()
|
||||||
assert_equal(8, u1.region.x)
|
assert_equal(8, u1.region.x)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function test_ship_convoy_capacity()
|
||||||
|
local r1 = region.create(1, 0, 'ocean')
|
||||||
|
local r2 = region.create(2, 0, 'ocean')
|
||||||
|
local f = faction.create("human")
|
||||||
|
local u = unit.create(f, r1, 1)
|
||||||
|
|
||||||
|
u:add_order('NACH O')
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
u:add_item('jewel', 40)
|
||||||
|
u.ship = ship.create(r1, 'boat')
|
||||||
|
assert_equal(1, u.ship.number)
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r2, u.region)
|
||||||
|
|
||||||
|
u:add_order('NACH W')
|
||||||
|
u:add_item('jewel', 1)
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r2, u.region) -- too heavy
|
||||||
|
|
||||||
|
u:add_order('NACH W')
|
||||||
|
u:add_item('jewel', 39)
|
||||||
|
u.name = 'Xolgrim'
|
||||||
|
u.ship.number = 2
|
||||||
|
u.number = 2
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r1, u.region) -- double capacity
|
||||||
|
|
||||||
|
u:add_order('NACH O')
|
||||||
|
u.ship.number = 2
|
||||||
|
u.name = 'Bolgrim'
|
||||||
|
u:add_item('jewel', 1) -- too heavy again
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r1, u.region)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_ship_convoy_crew()
|
||||||
|
local r1 = region.create(1, 0, 'ocean')
|
||||||
|
local r2 = region.create(2, 0, 'ocean')
|
||||||
|
local f = faction.create("human")
|
||||||
|
local u = unit.create(f, r1, 1)
|
||||||
|
u.ship = ship.create(r1, 'boat')
|
||||||
|
u.ship.number = 2
|
||||||
|
|
||||||
|
u:set_skill('sailing', 4, true)
|
||||||
|
u:add_order('NACH O')
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r1, u.region) -- not enough captains
|
||||||
|
|
||||||
|
u.number = 2
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
u:add_order('NACH O')
|
||||||
|
process_orders()
|
||||||
|
u:clear_orders()
|
||||||
|
assert_equal(r2, u.region)
|
||||||
|
end
|
||||||
|
|
||||||
|
function test_ship_convoy_skill()
|
||||||
|
local r1 = region.create(1, 0, 'ocean')
|
||||||
|
local r2 = region.create(2, 0, 'ocean')
|
||||||
|
local r3 = region.create(3, 0, 'ocean')
|
||||||
|
local f = faction.create("human")
|
||||||
|
local u = unit.create(f, r1, 1)
|
||||||
|
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
u.ship = ship.create(r1, 'boat')
|
||||||
|
assert_equal(1, u.ship.number)
|
||||||
|
u:add_order('NACH O')
|
||||||
|
process_orders()
|
||||||
|
assert_equal(r2, u.region)
|
||||||
|
|
||||||
|
u.ship.number = 2
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
process_orders()
|
||||||
|
assert_equal(r2, u.region)
|
||||||
|
|
||||||
|
u.number = 2
|
||||||
|
u:set_skill('sailing', 2, true)
|
||||||
|
process_orders()
|
||||||
|
assert_equal(r3, u.region)
|
||||||
|
end
|
||||||
|
|
111
src/bind_ship.c
111
src/bind_ship.c
|
@ -38,39 +38,55 @@ int tolua_shiplist_next(lua_State * L)
|
||||||
return 0; /* no more values to return */
|
return 0; /* no more values to return */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tolua_ship_get_number(lua_State * L)
|
||||||
|
{
|
||||||
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
|
lua_pushinteger(L, sh->number);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tolua_ship_set_number(lua_State * L)
|
||||||
|
{
|
||||||
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
|
int n = (int)tolua_tonumber(L, 2, 0);
|
||||||
|
sh->number = n;
|
||||||
|
sh->size += sh->type->construction->maxsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_id(lua_State * L)
|
static int tolua_ship_get_id(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
lua_pushinteger(L, self->no);
|
lua_pushinteger(L, sh->no);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_name(lua_State * L)
|
static int tolua_ship_get_name(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
tolua_pushstring(L, ship_getname(self));
|
tolua_pushstring(L, ship_getname(sh));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_size(lua_State * L)
|
static int tolua_ship_get_size(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
lua_pushinteger(L, self->size);
|
lua_pushinteger(L, sh->size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_display(lua_State * L)
|
static int tolua_ship_get_display(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
tolua_pushstring(L, self->display);
|
tolua_pushstring(L, sh->display);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_region(lua_State * L)
|
static int tolua_ship_get_region(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
if (self) {
|
if (sh) {
|
||||||
tolua_pushusertype(L, self->region, TOLUA_CAST "region");
|
tolua_pushusertype(L, sh->region, TOLUA_CAST "region");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -78,43 +94,43 @@ static int tolua_ship_get_region(lua_State * L)
|
||||||
|
|
||||||
static int tolua_ship_set_region(lua_State * L)
|
static int tolua_ship_set_region(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
region *r = (region *)tolua_tousertype(L, 2, NULL);
|
region *r = (region *)tolua_tousertype(L, 2, NULL);
|
||||||
if (self) {
|
if (sh) {
|
||||||
move_ship(self, self->region, r, NULL);
|
move_ship(sh, sh->region, r, NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_name(lua_State * L)
|
static int tolua_ship_set_name(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
ship_setname(self, tolua_tostring(L, 2, NULL));
|
ship_setname(sh, tolua_tostring(L, 2, NULL));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_size(lua_State * L)
|
static int tolua_ship_set_size(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
self->size = lua_tointeger(L, 2);
|
sh->size = lua_tointeger(L, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_display(lua_State * L)
|
static int tolua_ship_set_display(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
free(self->display);
|
free(sh->display);
|
||||||
self->display = str_strdup(tolua_tostring(L, 2, NULL));
|
sh->display = str_strdup(tolua_tostring(L, 2, NULL));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_units(lua_State * L)
|
static int tolua_ship_get_units(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *));
|
unit **unit_ptr = (unit **)lua_newuserdata(L, sizeof(unit *));
|
||||||
unit *u = self->region->units;
|
unit *u = sh->region->units;
|
||||||
|
|
||||||
while (u && u->ship != self)
|
while (u && u->ship != sh)
|
||||||
u = u->next;
|
u = u->next;
|
||||||
luaL_getmetatable(L, TOLUA_CAST "unit");
|
luaL_getmetatable(L, TOLUA_CAST "unit");
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
|
@ -147,42 +163,42 @@ static int tolua_ship_create(lua_State * L)
|
||||||
static int
|
static int
|
||||||
tolua_ship_tostring(lua_State * L)
|
tolua_ship_tostring(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
lua_pushstring(L, shipname(self));
|
lua_pushstring(L, shipname(sh));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_flags(lua_State * L)
|
static int tolua_ship_get_flags(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
lua_pushinteger(L, self->flags);
|
lua_pushinteger(L, sh->flags);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_flags(lua_State * L)
|
static int tolua_ship_set_flags(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
self->flags = (int)lua_tointeger(L, 2);
|
sh->flags = (int)lua_tointeger(L, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_coast(lua_State * L)
|
static int tolua_ship_set_coast(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
if (lua_isnil(L, 2)) {
|
if (lua_isnil(L, 2)) {
|
||||||
self->coast = NODIRECTION;
|
sh->coast = NODIRECTION;
|
||||||
}
|
}
|
||||||
else if (lua_isnumber(L, 2)) {
|
else if (lua_isnumber(L, 2)) {
|
||||||
self->coast = (direction_t)lua_tointeger(L, 2);
|
sh->coast = (direction_t)lua_tointeger(L, 2);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_coast(lua_State * L)
|
static int tolua_ship_get_coast(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
if (self->coast) {
|
if (sh->coast) {
|
||||||
lua_pushinteger(L, self->coast);
|
lua_pushinteger(L, sh->coast);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -190,30 +206,30 @@ static int tolua_ship_get_coast(lua_State * L)
|
||||||
|
|
||||||
static int tolua_ship_get_type(lua_State * L)
|
static int tolua_ship_get_type(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
tolua_pushstring(L, self->type->_name);
|
tolua_pushstring(L, sh->type->_name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_damage(lua_State * L)
|
static int tolua_ship_get_damage(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
lua_pushinteger(L, self->damage);
|
lua_pushinteger(L, sh->damage);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_set_damage(lua_State * L)
|
static int tolua_ship_set_damage(lua_State * L)
|
||||||
{
|
{
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
self->damage = (int)lua_tointeger(L, 2);
|
sh->damage = (int)lua_tointeger(L, 2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_get_curse(lua_State *L) {
|
static int tolua_ship_get_curse(lua_State *L) {
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
const char *name = tolua_tostring(L, 2, NULL);
|
const char *name = tolua_tostring(L, 2, NULL);
|
||||||
if (self->attribs) {
|
if (sh->attribs) {
|
||||||
curse * c = get_curse(self->attribs, ct_find(name));
|
curse * c = get_curse(sh->attribs, ct_find(name));
|
||||||
if (c) {
|
if (c) {
|
||||||
lua_pushnumber(L, curse_geteffect(c));
|
lua_pushnumber(L, curse_geteffect(c));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -223,9 +239,9 @@ static int tolua_ship_get_curse(lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tolua_ship_has_attrib(lua_State *L) {
|
static int tolua_ship_has_attrib(lua_State *L) {
|
||||||
ship *self = (ship *)tolua_tousertype(L, 1, NULL);
|
ship *sh = (ship *)tolua_tousertype(L, 1, NULL);
|
||||||
const char *name = tolua_tostring(L, 2, NULL);
|
const char *name = tolua_tostring(L, 2, NULL);
|
||||||
attrib * a = a_find(self->attribs, at_find(name));
|
attrib * a = a_find(sh->attribs, at_find(name));
|
||||||
lua_pushboolean(L, a != NULL);
|
lua_pushboolean(L, a != NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -243,6 +259,7 @@ void tolua_ship_open(lua_State * L)
|
||||||
{
|
{
|
||||||
tolua_function(L, TOLUA_CAST "__tostring", tolua_ship_tostring);
|
tolua_function(L, TOLUA_CAST "__tostring", tolua_ship_tostring);
|
||||||
tolua_variable(L, TOLUA_CAST "id", tolua_ship_get_id, NULL);
|
tolua_variable(L, TOLUA_CAST "id", tolua_ship_get_id, NULL);
|
||||||
|
tolua_variable(L, TOLUA_CAST "number", tolua_ship_get_number, tolua_ship_set_number);
|
||||||
tolua_variable(L, TOLUA_CAST "name", tolua_ship_get_name,
|
tolua_variable(L, TOLUA_CAST "name", tolua_ship_get_name,
|
||||||
tolua_ship_set_name);
|
tolua_ship_set_name);
|
||||||
tolua_variable(L, TOLUA_CAST "size", tolua_ship_get_size,
|
tolua_variable(L, TOLUA_CAST "size", tolua_ship_get_size,
|
||||||
|
|
|
@ -884,9 +884,19 @@ static int tolua_unit_create(lua_State * L)
|
||||||
const char *rcname = tolua_tostring(L, 4, NULL);
|
const char *rcname = tolua_tostring(L, 4, NULL);
|
||||||
const race *rc;
|
const race *rc;
|
||||||
|
|
||||||
assert(f && r);
|
if (!r) {
|
||||||
|
log_warning("unit.create: arg(2) is not a region");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!f) {
|
||||||
|
log_warning("unit.create: arg(1) is not a faction");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
rc = rcname ? rc_find(rcname) : f->race;
|
rc = rcname ? rc_find(rcname) : f->race;
|
||||||
assert(rc);
|
if (!rc) {
|
||||||
|
log_warning("unit.create: unknown race %s", rcname);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
u = create_unit(r, f, num, rc, 0, NULL, NULL);
|
u = create_unit(r, f, num, rc, 0, NULL, NULL);
|
||||||
tolua_pushusertype(L, u, TOLUA_CAST "unit");
|
tolua_pushusertype(L, u, TOLUA_CAST "unit");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -515,8 +515,10 @@ static void report_crtypes(FILE * F, const struct locale *lang)
|
||||||
fputc('\"', F);
|
fputc('\"', F);
|
||||||
fputs(crescape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
|
fputs(crescape(nrt_string(kmt->mtype, lang), buffer, sizeof(buffer)), F);
|
||||||
fputs("\";text\n", F);
|
fputs("\";text\n", F);
|
||||||
|
if (kmt->mtype->section) {
|
||||||
fprintf(F, "\"%s\";section\n", kmt->mtype->section);
|
fprintf(F, "\"%s\";section\n", kmt->mtype->section);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
while (mtypehash[i]) {
|
while (mtypehash[i]) {
|
||||||
kmt = mtypehash[i];
|
kmt = mtypehash[i];
|
||||||
mtypehash[i] = mtypehash[i]->nexthash;
|
mtypehash[i] = mtypehash[i]->nexthash;
|
||||||
|
@ -695,6 +697,7 @@ static void cr_output_ship(struct stream *out, const ship *sh, const unit *u,
|
||||||
stream_printf(out, "\"%s\";Beschr\n", sh->display);
|
stream_printf(out, "\"%s\";Beschr\n", sh->display);
|
||||||
stream_printf(out, "\"%s\";Typ\n", translate(sh->type->_name,
|
stream_printf(out, "\"%s\";Typ\n", translate(sh->type->_name,
|
||||||
LOC(f->locale, sh->type->_name)));
|
LOC(f->locale, sh->type->_name)));
|
||||||
|
stream_printf(out, "%d;Anzahl\n", sh->number);
|
||||||
stream_printf(out, "%d;Groesse\n", sh->size);
|
stream_printf(out, "%d;Groesse\n", sh->size);
|
||||||
if (sh->damage) {
|
if (sh->damage) {
|
||||||
int percent =
|
int percent =
|
||||||
|
@ -710,7 +713,7 @@ static void cr_output_ship(struct stream *out, const ship *sh, const unit *u,
|
||||||
/* calculate cargo */
|
/* calculate cargo */
|
||||||
if (u && (u->faction == f || omniscient(f))) {
|
if (u && (u->faction == f || omniscient(f))) {
|
||||||
int n = 0, p = 0;
|
int n = 0, p = 0;
|
||||||
int mweight = shipcapacity(sh);
|
int mweight = ship_capacity(sh);
|
||||||
getshipweight(sh, &n, &p);
|
getshipweight(sh, &n, &p);
|
||||||
|
|
||||||
stream_printf(out, "%d;capacity\n", mweight);
|
stream_printf(out, "%d;capacity\n", mweight);
|
||||||
|
|
|
@ -1283,6 +1283,7 @@ void write_ship(gamedata *data, const ship *sh)
|
||||||
WRITE_STR(store, (const char *)sh->name);
|
WRITE_STR(store, (const char *)sh->name);
|
||||||
WRITE_STR(store, sh->display ? (const char *)sh->display : "");
|
WRITE_STR(store, sh->display ? (const char *)sh->display : "");
|
||||||
WRITE_TOK(store, sh->type->_name);
|
WRITE_TOK(store, sh->type->_name);
|
||||||
|
assert(sh->number > 0);
|
||||||
WRITE_INT(store, sh->number);
|
WRITE_INT(store, sh->number);
|
||||||
WRITE_INT(store, sh->size);
|
WRITE_INT(store, sh->size);
|
||||||
WRITE_INT(store, sh->damage);
|
WRITE_INT(store, sh->damage);
|
||||||
|
|
|
@ -181,6 +181,7 @@ ship *new_ship(const ship_type * stype, region * r, const struct locale *lang)
|
||||||
sh->coast = NODIRECTION;
|
sh->coast = NODIRECTION;
|
||||||
sh->type = stype;
|
sh->type = stype;
|
||||||
sh->region = r;
|
sh->region = r;
|
||||||
|
sh->number = 1;
|
||||||
|
|
||||||
if (lang) {
|
if (lang) {
|
||||||
sname = LOC(lang, stype->_name);
|
sname = LOC(lang, stype->_name);
|
||||||
|
@ -275,13 +276,13 @@ static int ShipSpeedBonus(const unit * u)
|
||||||
}
|
}
|
||||||
if (bonus > 0) {
|
if (bonus > 0) {
|
||||||
int skl = effskill(u, SK_SAILING, NULL);
|
int skl = effskill(u, SK_SAILING, NULL);
|
||||||
int minsk = (sh->type->cptskill + 1) / 2;
|
int minsk = (ship_captain_minskill(sh) + 1) / 2;
|
||||||
return (skl - minsk) / bonus;
|
return (skl - minsk) / bonus;
|
||||||
}
|
}
|
||||||
else if (sh->type->flags & SFL_SPEEDY) {
|
else if (sh->type->flags & SFL_SPEEDY) {
|
||||||
int base = 3;
|
int base = 3;
|
||||||
int speed = 0;
|
int speed = 0;
|
||||||
int minsk = sh->type->cptskill * base;
|
int minsk = ship_captain_minskill(sh) * base;
|
||||||
int skl = effskill(u, SK_SAILING, NULL);
|
int skl = effskill(u, SK_SAILING, NULL);
|
||||||
while (skl >= minsk) {
|
while (skl >= minsk) {
|
||||||
++speed;
|
++speed;
|
||||||
|
@ -292,21 +293,8 @@ static int ShipSpeedBonus(const unit * u)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int crew_skill(const ship *sh) {
|
int ship_captain_minskill(const ship *sh) {
|
||||||
int n = 0;
|
return sh->type->cptskill;
|
||||||
unit *u;
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
|
|
||||||
for (u = sh->region->units; u; u = u->next) {
|
|
||||||
if (u->ship == sh) {
|
|
||||||
int es = effskill(u, SK_SAILING, NULL);
|
|
||||||
if (es >= sh->type->minskill) {
|
|
||||||
n += es * u->number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int shipspeed(const ship * sh, const unit * u)
|
int shipspeed(const ship * sh, const unit * u)
|
||||||
|
@ -323,8 +311,9 @@ int shipspeed(const ship * sh, const unit * u)
|
||||||
assert(sh->type->construction);
|
assert(sh->type->construction);
|
||||||
|
|
||||||
k = sh->type->range;
|
k = sh->type->range;
|
||||||
if (sh->size != sh->type->construction->maxsize)
|
if (!ship_finished(sh)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (sh->attribs) {
|
if (sh->attribs) {
|
||||||
if (curse_active(get_curse(sh->attribs, &ct_stormwind))) {
|
if (curse_active(get_curse(sh->attribs, &ct_stormwind))) {
|
||||||
|
@ -343,7 +332,7 @@ int shipspeed(const ship * sh, const unit * u)
|
||||||
|
|
||||||
bonus = ShipSpeedBonus(u);
|
bonus = ShipSpeedBonus(u);
|
||||||
if (bonus > 0 && sh->type->range_max > sh->type->range) {
|
if (bonus > 0 && sh->type->range_max > sh->type->range) {
|
||||||
int crew = crew_skill(sh);
|
int crew = crew_skill(sh, NULL);
|
||||||
int crew_bonus = (crew / sh->type->sumskill / 2) - 1;
|
int crew_bonus = (crew / sh->type->sumskill / 2) - 1;
|
||||||
if (crew_bonus > 0) {
|
if (crew_bonus > 0) {
|
||||||
int sbonus = sh->type->range_max - sh->type->range;
|
int sbonus = sh->type->range_max - sh->type->range;
|
||||||
|
@ -385,18 +374,69 @@ const char *shipname(const ship * sh)
|
||||||
return write_shipname(sh, ibuf, sizeof(idbuf[0]));
|
return write_shipname(sh, ibuf, sizeof(idbuf[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
int shipcapacity(const ship * sh)
|
bool ship_finished(const ship *sh)
|
||||||
{
|
{
|
||||||
int i = sh->type->cargo;
|
if (sh->type->construction) {
|
||||||
|
return (sh->size >= sh->number * sh->type->construction->maxsize);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (sh->type->construction && sh->size < sh->number * sh->type->construction->maxsize)
|
int enoughsailors(const ship * sh, int crew_skill)
|
||||||
return 0;
|
{
|
||||||
|
return crew_skill >= sh->type->sumskill * sh->number;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crew_skill(const ship *sh, int *o_captains) {
|
||||||
|
int n = 0, captains = 0;
|
||||||
|
unit *u;
|
||||||
|
|
||||||
|
for (u = sh->region->units; u; u = u->next) {
|
||||||
|
if (u->ship == sh) {
|
||||||
|
int es = effskill(u, SK_SAILING, NULL);
|
||||||
|
if (es >= sh->type->cptskill) {
|
||||||
|
captains += u->number;
|
||||||
|
}
|
||||||
|
if (es >= sh->type->minskill) {
|
||||||
|
n += es * u->number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o_captains) {
|
||||||
|
*o_captains = captains;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ship_crewed(const ship *sh)
|
||||||
|
{
|
||||||
|
int num_caps, crew = crew_skill(sh, &num_caps);
|
||||||
|
return num_caps >= sh->number && enoughsailors(sh, crew);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ship_capacity(const ship * sh)
|
||||||
|
{
|
||||||
|
if (ship_finished(sh)) {
|
||||||
|
int i = sh->type->cargo * sh->number;
|
||||||
if (sh->damage) {
|
if (sh->damage) {
|
||||||
i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE));
|
i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE));
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ship_cabins(const ship * sh)
|
||||||
|
{
|
||||||
|
if (ship_finished(sh)) {
|
||||||
|
int i = sh->type->cabins * sh->number;
|
||||||
|
if (sh->damage) {
|
||||||
|
i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void getshipweight(const ship * sh, int *sweight, int *scabins)
|
void getshipweight(const ship * sh, int *sweight, int *scabins)
|
||||||
{
|
{
|
||||||
|
|
|
@ -90,8 +90,10 @@ extern "C" {
|
||||||
struct unit *ship_owner(const struct ship *sh);
|
struct unit *ship_owner(const struct ship *sh);
|
||||||
void ship_update_owner(struct ship * sh);
|
void ship_update_owner(struct ship * sh);
|
||||||
|
|
||||||
extern const char *shipname(const struct ship *self);
|
const char *shipname(const struct ship *self);
|
||||||
extern int shipcapacity(const struct ship *sh);
|
int ship_capacity(const struct ship *sh);
|
||||||
|
int ship_cabins(const struct ship *sh);
|
||||||
|
bool ship_finished(const struct ship *sh);
|
||||||
extern void getshipweight(const struct ship *sh, int *weight, int *cabins);
|
extern void getshipweight(const struct ship *sh, int *weight, int *cabins);
|
||||||
|
|
||||||
extern ship *new_ship(const struct ship_type *stype, struct region *r,
|
extern ship *new_ship(const struct ship_type *stype, struct region *r,
|
||||||
|
@ -114,7 +116,10 @@ extern "C" {
|
||||||
const char *ship_getname(const struct ship *sh);
|
const char *ship_getname(const struct ship *sh);
|
||||||
void ship_setname(struct ship *self, const char *name);
|
void ship_setname(struct ship *self, const char *name);
|
||||||
int shipspeed(const struct ship *sh, const struct unit *u);
|
int shipspeed(const struct ship *sh, const struct unit *u);
|
||||||
int crew_skill(const struct ship *sh);
|
|
||||||
|
bool ship_crewed(const struct ship *sh);
|
||||||
|
int crew_skill(const struct ship *sh, int *num_captains);
|
||||||
|
int ship_captain_minskill(const struct ship *sh);
|
||||||
|
|
||||||
int ship_damage_percent(const struct ship *sh);
|
int ship_damage_percent(const struct ship *sh);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -641,21 +641,21 @@ static void test_crew_skill(CuTest *tc) {
|
||||||
CuAssertIntEquals(tc, 1, stype->minskill);
|
CuAssertIntEquals(tc, 1, stype->minskill);
|
||||||
r = test_create_ocean(0, 0);
|
r = test_create_ocean(0, 0);
|
||||||
sh = test_create_ship(r, stype);
|
sh = test_create_ship(r, stype);
|
||||||
CuAssertIntEquals(tc, 0, crew_skill(sh));
|
CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
|
||||||
u = test_create_unit(test_create_faction(NULL), r);
|
u = test_create_unit(test_create_faction(NULL), r);
|
||||||
set_level(u, SK_SAILING, 1);
|
set_level(u, SK_SAILING, 1);
|
||||||
CuAssertIntEquals(tc, 0, crew_skill(sh));
|
CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
|
||||||
u_set_ship(u, sh);
|
u_set_ship(u, sh);
|
||||||
set_level(u, SK_SAILING, 1);
|
set_level(u, SK_SAILING, 1);
|
||||||
CuAssertIntEquals(tc, 1, crew_skill(sh));
|
CuAssertIntEquals(tc, 1, crew_skill(sh, NULL));
|
||||||
set_number(u, 10);
|
set_number(u, 10);
|
||||||
CuAssertIntEquals(tc, 10, crew_skill(sh));
|
CuAssertIntEquals(tc, 10, crew_skill(sh, NULL));
|
||||||
stype->minskill = 2;
|
stype->minskill = 2;
|
||||||
CuAssertIntEquals(tc, 0, crew_skill(sh));
|
CuAssertIntEquals(tc, 0, crew_skill(sh, NULL));
|
||||||
set_level(u, SK_SAILING, 2);
|
set_level(u, SK_SAILING, 2);
|
||||||
CuAssertIntEquals(tc, 20, crew_skill(sh));
|
CuAssertIntEquals(tc, 20, crew_skill(sh, NULL));
|
||||||
set_level(u, SK_SAILING, 3);
|
set_level(u, SK_SAILING, 3);
|
||||||
CuAssertIntEquals(tc, 30, crew_skill(sh));
|
CuAssertIntEquals(tc, 30, crew_skill(sh, NULL));
|
||||||
test_teardown();
|
test_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1094,8 +1094,8 @@ int enter_ship(unit * u, struct order *ord, int id, bool report)
|
||||||
}
|
}
|
||||||
if (CheckOverload()) {
|
if (CheckOverload()) {
|
||||||
int sweight, scabins;
|
int sweight, scabins;
|
||||||
int mweight = shipcapacity(sh);
|
int mweight = ship_capacity(sh);
|
||||||
int mcabins = sh->type->cabins;
|
int mcabins = ship_cabins(sh);
|
||||||
|
|
||||||
if (mweight > 0) {
|
if (mweight > 0) {
|
||||||
getshipweight(sh, &sweight, &scabins);
|
getshipweight(sh, &sweight, &scabins);
|
||||||
|
@ -2598,7 +2598,7 @@ void sinkships(struct region * r)
|
||||||
|
|
||||||
if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) {
|
if (!sh->type->construction || sh->size >= sh->type->construction->maxsize) {
|
||||||
if (fval(r->terrain, SEA_REGION)) {
|
if (fval(r->terrain, SEA_REGION)) {
|
||||||
if (!enoughsailors(sh, crew_skill(sh))) {
|
if (!ship_crewed(sh)) {
|
||||||
/* ship is at sea, but not enough people to control it */
|
/* ship is at sea, but not enough people to control it */
|
||||||
double dmg = config_get_flt("rules.ship.damage.nocrewocean", 0.3);
|
double dmg = config_get_flt("rules.ship.damage.nocrewocean", 0.3);
|
||||||
damage_ship(sh, dmg);
|
damage_ship(sh, dmg);
|
||||||
|
|
35
src/move.c
35
src/move.c
|
@ -470,13 +470,13 @@ static bool cansail(const region * r, ship * sh)
|
||||||
{
|
{
|
||||||
UNUSED_ARG(r);
|
UNUSED_ARG(r);
|
||||||
|
|
||||||
if (sh->type->construction && sh->size != sh->type->construction->maxsize) {
|
if (!ship_finished(sh)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int n = 0, p = 0;
|
int n = 0, p = 0;
|
||||||
int mweight = shipcapacity(sh);
|
int mweight = ship_capacity(sh);
|
||||||
int mcabins = sh->type->cabins;
|
int mcabins = ship_cabins(sh);
|
||||||
|
|
||||||
getshipweight(sh, &n, &p);
|
getshipweight(sh, &n, &p);
|
||||||
|
|
||||||
|
@ -492,12 +492,12 @@ static double overload(const region * r, ship * sh)
|
||||||
{
|
{
|
||||||
UNUSED_ARG(r);
|
UNUSED_ARG(r);
|
||||||
|
|
||||||
if (sh->type->construction && sh->size != sh->type->construction->maxsize) {
|
if (!ship_finished(sh)) {
|
||||||
return DBL_MAX;
|
return DBL_MAX;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int n = 0, p = 0;
|
int n = 0, p = 0;
|
||||||
int mcabins = sh->type->cabins;
|
int mcabins = sh->type->cabins * sh->number;
|
||||||
double ovl;
|
double ovl;
|
||||||
|
|
||||||
getshipweight(sh, &n, &p);
|
getshipweight(sh, &n, &p);
|
||||||
|
@ -509,11 +509,6 @@ static double overload(const region * r, ship * sh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int enoughsailors(const ship * sh, int crew_skill)
|
|
||||||
{
|
|
||||||
return crew_skill >= sh->type->sumskill;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------- */
|
/* ------------------------------------------------------------- */
|
||||||
|
|
||||||
static ship *do_maelstrom(region * r, unit * u)
|
static ship *do_maelstrom(region * r, unit * u)
|
||||||
|
@ -808,7 +803,7 @@ static void drifting_ships(region * r)
|
||||||
ship *sh = *shp;
|
ship *sh = *shp;
|
||||||
region *rnext = NULL;
|
region *rnext = NULL;
|
||||||
region_list *route = NULL;
|
region_list *route = NULL;
|
||||||
unit *firstu = r->units, *lastu = NULL, *captain;
|
unit *firstu = r->units, *lastu = NULL;
|
||||||
direction_t dir = NODIRECTION;
|
direction_t dir = NODIRECTION;
|
||||||
double ovl;
|
double ovl;
|
||||||
|
|
||||||
|
@ -822,16 +817,10 @@ static void drifting_ships(region * r)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kapitaen bestimmen */
|
|
||||||
captain = ship_owner(sh);
|
|
||||||
if (captain && effskill(captain, SK_SAILING, r) < sh->type->cptskill)
|
|
||||||
captain = NULL;
|
|
||||||
|
|
||||||
/* Kapitaen da? Beschaedigt? Genuegend Matrosen?
|
/* Kapitaen da? Beschaedigt? Genuegend Matrosen?
|
||||||
* Genuegend leicht? Dann ist alles OK. */
|
* Genuegend leicht? Dann ist alles OK. */
|
||||||
|
|
||||||
if (captain && sh->size == sh->type->construction->maxsize
|
if (ship_finished(sh) && ship_crewed(sh) && cansail(r, sh)) {
|
||||||
&& enoughsailors(sh, crew_skill(sh)) && cansail(r, sh)) {
|
|
||||||
shp = &sh->next;
|
shp = &sh->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1639,19 +1628,17 @@ static bool ship_ready(const region * r, unit * u, order * ord)
|
||||||
cmistake(u, ord, 146, MSG_MOVE);
|
cmistake(u, ord, 146, MSG_MOVE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (effskill(u, SK_SAILING, r) < u->ship->type->cptskill) {
|
if (effskill(u, SK_SAILING, r) < ship_captain_minskill(u->ship)) {
|
||||||
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
|
ADDMSG(&u->faction->msgs, msg_feedback(u, ord,
|
||||||
"error_captain_skill_low", "value ship", u->ship->type->cptskill,
|
"error_captain_skill_low", "value ship", ship_captain_minskill(u->ship),
|
||||||
u->ship));
|
u->ship));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (u->ship->type->construction) {
|
if (!ship_finished(u->ship)) {
|
||||||
if (u->ship->size != u->ship->type->construction->maxsize) {
|
|
||||||
cmistake(u, ord, 15, MSG_MOVE);
|
cmistake(u, ord, 15, MSG_MOVE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
if (!ship_crewed(u->ship)) {
|
||||||
if (!enoughsailors(u->ship, crew_skill(u->ship))) {
|
|
||||||
cmistake(u, ord, 1, MSG_MOVE);
|
cmistake(u, ord, 1, MSG_MOVE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@ extern "C" {
|
||||||
|
|
||||||
int personcapacity(const struct unit *u);
|
int personcapacity(const struct unit *u);
|
||||||
void movement(void);
|
void movement(void);
|
||||||
void run_to(struct unit *u, struct region *to);
|
|
||||||
int enoughsailors(const struct ship *sh, int sumskill);
|
int enoughsailors(const struct ship *sh, int sumskill);
|
||||||
bool canswim(struct unit *u);
|
bool canswim(struct unit *u);
|
||||||
bool canfly(struct unit *u);
|
bool canfly(struct unit *u);
|
||||||
|
|
|
@ -1728,7 +1728,7 @@ nr_ship(struct stream *out, const region *r, const ship * sh, const faction * f,
|
||||||
n = (n + 99) / 100; /* 1 Silber = 1 GE */
|
n = (n + 99) / 100; /* 1 Silber = 1 GE */
|
||||||
|
|
||||||
sbs_printf(&sbs, "%s, %s, (%d/%d)", shipname(sh),
|
sbs_printf(&sbs, "%s, %s, (%d/%d)", shipname(sh),
|
||||||
LOC(f->locale, sh->type->_name), n, shipcapacity(sh) / 100);
|
LOC(f->locale, sh->type->_name), n, ship_capacity(sh) / 100);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sbs_printf(&sbs, "%s, %s", shipname(sh), LOC(f->locale, sh->type->_name));
|
sbs_printf(&sbs, "%s, %s", shipname(sh), LOC(f->locale, sh->type->_name));
|
||||||
|
|
Loading…
Reference in New Issue