MACHE beschädigte Konvois

This commit is contained in:
Enno Rehling 2019-10-21 20:04:32 +02:00
parent d04fe741a9
commit 70b148296f
7 changed files with 100 additions and 34 deletions

View File

@ -312,7 +312,6 @@ function test_give_ship_compatible_coasts()
assert_equal(1, u1.ship.number) assert_equal(1, u1.ship.number)
assert_equal(4, u2.ship.number) assert_equal(4, u2.ship.number)
assert_equal(2, u2.ship.coast) assert_equal(2, u2.ship.coast)
end end
function test_give_ship_only_from_captain() function test_give_ship_only_from_captain()
@ -453,3 +452,66 @@ function test_no_speedsail_on_convoy()
process_orders() process_orders()
assert_equal(nil, sh:get_curse('shipspeedup')) assert_equal(nil, sh:get_curse('shipspeedup'))
end end
function test_build_ship()
local r = region.create(1, 0, 'plain')
local f = faction.create("insect")
local u = unit.create(f, r, 25)
local sh = ship.create(r, 'longboat')
u.ship = sh
sh.size = 25
u:set_skill('shipcraft', 1)
u:add_item("log", 50)
u:add_order("MACHE SCHIFF " .. itoa36(sh.id))
process_orders()
assert_equal(50, sh.size)
assert_equal(25, u:get_item('log'))
end
function test_build_convoi()
local r = region.create(1, 0, 'plain')
local f = faction.create("insect")
local u = unit.create(f, r, 50)
local sh = ship.create(r, 'longboat')
u.ship = sh
sh.number = 2
sh.size = 25
u:set_skill('shipcraft', 1)
u:add_item("log", 100)
u:add_order("MACHE SCHIFF " .. itoa36(sh.id))
process_orders()
assert_equal(75, sh.size)
assert_equal(50, u:get_item('log'))
end
function test_repair_convoi()
local r = region.create(1, 0, 'plain')
local f = faction.create("insect")
local u = unit.create(f, r, 50)
local sh = ship.create(r, 'longboat')
u.ship = sh
sh.number = 2
sh.damage = 7500 -- 75 Holz
u:set_skill('shipcraft', 1)
u:add_item("log", 100)
u:add_order("MACHE SCHIFF " .. itoa36(sh.id))
process_orders()
assert_equal(2500, sh.damage)
assert_equal(50, u:get_item('log'))
end
function test_build_convoi_max()
local r = region.create(1, 0, 'plain')
local f = faction.create("insect")
local u = unit.create(f, r, 100)
local sh = ship.create(r, 'longboat')
u.ship = sh
sh.number = 2
sh.size = 25
u:set_skill('shipcraft', 1)
u:add_item("log", 100)
u:add_order("MACHE SCHIFF " .. itoa36(sh.id))
process_orders()
assert_equal(100, sh.size)
assert_equal(25, u:get_item('log'))
end

View File

@ -700,8 +700,7 @@ static void cr_output_ship(struct stream *out, const ship *sh, const unit *u,
stream_printf(out, "%d;Anzahl\n", sh->number); 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 = ship_damage_percent(sh);
(sh->damage * 100 + DAMAGE_SCALE - 1) / (sh->size * DAMAGE_SCALE);
stream_printf(out, "%d;Schaden\n", percent); stream_printf(out, "%d;Schaden\n", percent);
} }
if (u) { if (u) {

View File

@ -509,7 +509,7 @@ static void manufacture(unit * u, const item_type * itype, int want)
if (want == 0) { if (want == 0) {
want = maxbuild(u, itype->construction); want = maxbuild(u, itype->construction);
} }
n = build(u, itype->construction, 0, want, skill_mod); n = build(u, 1, itype->construction, 0, want, skill_mod);
switch (n) { switch (n) {
case ENEEDSKILL: case ENEEDSKILL:
ADDMSG(&u->faction->msgs, ADDMSG(&u->faction->msgs,
@ -850,7 +850,7 @@ static void create_potion(unit * u, const item_type * itype, int want)
if (want == 0) { if (want == 0) {
want = maxbuild(u, itype->construction); want = maxbuild(u, itype->construction);
} }
built = build(u, itype->construction, 0, want, 0); built = build(u, 1, itype->construction, 0, want, 0);
switch (built) { switch (built) {
case ELOWSKILL: case ELOWSKILL:
case ENEEDSKILL: case ENEEDSKILL:

View File

@ -224,7 +224,7 @@ int destroy_cmd(unit * u, struct order *ord)
return 14; return 14;
} }
if (n >= (sh->size * 100) / sh->type->construction->maxsize) { if (n >= (sh->size * 100) / ship_maxsize(sh)) {
/* destroy completly */ /* destroy completly */
/* all units leave the ship */ /* all units leave the ship */
for (u2 = r->units; u2; u2 = u2->next) { for (u2 = r->units; u2; u2 = u2->next) {
@ -509,9 +509,9 @@ int build_skill(unit *u, int basesk, int skill_mod) {
* of the first object have already been finished. return the * of the first object have already been finished. return the
* actual size that could be built. * actual size that could be built.
*/ */
static int build_limited(unit * u, const construction * con, int completed, int want, int basesk, int *skill_total) { static int build_limited(unit * u, const construction * con, int completed, int number, int want, int basesk, int *skill_total) {
int skills = *skill_total; int skills = *skill_total;
int made = 0; int made = 0, maxsize = con->maxsize * number;
if (want <= 0) { if (want <= 0) {
return 0; return 0;
@ -519,7 +519,7 @@ static int build_limited(unit * u, const construction * con, int completed, int
if (con == NULL) { if (con == NULL) {
return ENOMATERIALS; return ENOMATERIALS;
} }
if (completed == con->maxsize) { if (completed == maxsize) {
return ECOMPLETE; return ECOMPLETE;
} }
for (; want > 0 && skills > 0;) { for (; want > 0 && skills > 0;) {
@ -530,8 +530,8 @@ static int build_limited(unit * u, const construction * con, int completed, int
* (enno): Nein, das ist fuer Dinge, bei denen die naechste Ausbaustufe * (enno): Nein, das ist fuer Dinge, bei denen die naechste Ausbaustufe
* die gleiche wie die vorherige ist. z.b. Gegenstaende. * die gleiche wie die vorherige ist. z.b. Gegenstaende.
*/ */
if (con->maxsize > 0) { if (maxsize > 0) {
completed = completed % con->maxsize; completed = completed % (maxsize);
} }
else { else {
completed = 0; completed = 0;
@ -566,8 +566,8 @@ static int build_limited(unit * u, const construction * con, int completed, int
if (want < n) n = want; if (want < n) n = want;
if (con->maxsize > 0) { if (maxsize > 0) {
int req = con->maxsize - completed; int req = maxsize - completed;
if (req < n) n = req; if (req < n) n = req;
want = n; want = n;
} }
@ -592,11 +592,12 @@ static int build_limited(unit * u, const construction * con, int completed, int
return made; return made;
} }
int build(unit * u, const construction * con, int completed, int want, int skill_mod) int build(unit * u, int number, const construction * con, int completed, int want, int skill_mod)
{ {
int skills = INT_MAX; /* number of skill points remainig */ int skills = INT_MAX; /* number of skill points remainig */
int made, basesk = 0; int made, basesk = 0;
assert(number >= 1);
assert(con->skill != NOSKILL); assert(con->skill != NOSKILL);
basesk = effskill(u, con->skill, NULL); basesk = effskill(u, con->skill, NULL);
if (basesk == 0) { if (basesk == 0) {
@ -604,7 +605,7 @@ int build(unit * u, const construction * con, int completed, int want, int skill
} }
skills = build_skill(u, basesk, skill_mod); skills = build_skill(u, basesk, skill_mod);
made = build_limited(u, con, completed, want, basesk, &skills); made = build_limited(u, con, completed, number, want, basesk, &skills);
/* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */ /* Nur soviel PRODUCEEXP wie auch tatsaechlich gemacht wurde */
if (made > 0) { if (made > 0) {
produceexp(u, con->skill, (made < u->number) ? made : u->number); produceexp(u, con->skill, (made < u->number) ? made : u->number);
@ -698,7 +699,7 @@ static int build_stages(unit *u, const building_type *btype, int built, int n, i
want = todo; want = todo;
} }
} }
err = build_limited(u, con, built, want, basesk, skill_total); err = build_limited(u, con, 1, built, want, basesk, skill_total);
if (err < 0) { if (err < 0) {
if (made == 0) { if (made == 0) {
/* could not make any part at all */ /* could not make any part at all */
@ -904,9 +905,9 @@ static void build_ship(unit * u, ship * sh, int want)
const construction *construction = sh->type->construction; const construction *construction = sh->type->construction;
int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE; int size = (sh->size * DAMAGE_SCALE - sh->damage) / DAMAGE_SCALE;
int n; int n;
int can = build(u, construction, size, want, 0); int can = build(u, sh->number, construction, size, want, 0);
if ((n = construction->maxsize - sh->size) > 0 && can > 0) { if ((n = ship_maxsize(sh) - sh->size) > 0 && can > 0) {
if (can >= n) { if (can >= n) {
sh->size += n; sh->size += n;
can -= n; can -= n;
@ -1000,11 +1001,12 @@ void continue_ship(unit * u, int want)
cmistake(u, u->thisorder, 20, MSG_PRODUCE); cmistake(u, u->thisorder, 20, MSG_PRODUCE);
return; return;
} }
cons = sh->type->construction; msize = ship_maxsize(sh);
if (sh->size == cons->maxsize && !sh->damage) { if (sh->size >= msize && !sh->damage) {
cmistake(u, u->thisorder, 16, MSG_PRODUCE); cmistake(u, u->thisorder, 16, MSG_PRODUCE);
return; return;
} }
cons = sh->type->construction;
if (effskill(u, cons->skill, NULL) < cons->minskill) { if (effskill(u, cons->skill, NULL) < cons->minskill) {
ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder,
"error_build_skill_low", "value", cons->minskill)); "error_build_skill_low", "value", cons->minskill));

View File

@ -44,7 +44,7 @@ extern "C" {
void sunhash(struct ship *sh); void sunhash(struct ship *sh);
int roqf_factor(void); int roqf_factor(void);
int build(struct unit *u, const construction * ctype, int completed, int want, int skill_mod); int build(struct unit *u, int number, const construction * ctype, int completed, int want, int skill_mod);
int maxbuild(const struct unit *u, const construction * cons); int maxbuild(const struct unit *u, const construction * cons);
struct message *msg_materials_required(struct unit *u, struct order *ord, struct message *msg_materials_required(struct unit *u, struct order *ord,
const struct construction *ctype, int multi); const struct construction *ctype, int multi);

View File

@ -145,10 +145,10 @@ static void test_build_requires_materials(CuTest *tc) {
u = setup_build(&bf); u = setup_build(&bf);
set_level(u, SK_ARMORER, 2); set_level(u, SK_ARMORER, 2);
CuAssertIntEquals(tc, ENOMATERIALS, build(u, &bf.cons, 0, 1, 0)); CuAssertIntEquals(tc, ENOMATERIALS, build(u, 1, &bf.cons, 0, 1, 0));
itype = bf.cons.materials[0].rtype->itype; itype = bf.cons.materials[0].rtype->itype;
i_change(&u->items, itype, 2); i_change(&u->items, itype, 2);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 1, 0)); CuAssertIntEquals(tc, 1, build(u, 1, &bf.cons, 0, 1, 0));
CuAssertIntEquals(tc, 1, i_get(u->items, itype)); CuAssertIntEquals(tc, 1, i_get(u->items, itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -161,7 +161,7 @@ static void test_build_failure_missing_skill(CuTest *tc) {
u = setup_build(&bf); u = setup_build(&bf);
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
CuAssertIntEquals(tc, ENEEDSKILL, build(u, &bf.cons, 1, 1, 0)); CuAssertIntEquals(tc, ENEEDSKILL, build(u, 1, &bf.cons, 1, 1, 0));
teardown_build(&bf); teardown_build(&bf);
} }
@ -174,7 +174,7 @@ static void test_build_failure_low_skill(CuTest *tc) {
rtype = bf.cons.materials[0].rtype; rtype = bf.cons.materials[0].rtype;
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill - 1); set_level(u, SK_ARMORER, bf.cons.minskill - 1);
CuAssertIntEquals(tc, ELOWSKILL, build(u, &bf.cons, 0, 10, 0)); CuAssertIntEquals(tc, ELOWSKILL, build(u, 1, &bf.cons, 0, 10, 0));
teardown_build(&bf); teardown_build(&bf);
} }
@ -188,7 +188,7 @@ static void test_build_failure_completed(CuTest *tc) {
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
bf.cons.maxsize = 1; bf.cons.maxsize = 1;
CuAssertIntEquals(tc, ECOMPLETE, build(u, &bf.cons, bf.cons.maxsize, 10, 0)); CuAssertIntEquals(tc, ECOMPLETE, build(u, 1, &bf.cons, bf.cons.maxsize, 10, 0));
CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 1, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -203,19 +203,19 @@ static void test_build_limits(CuTest *tc) {
assert(rtype); assert(rtype);
i_change(&u->items, rtype->itype, 1); i_change(&u->items, rtype->itype, 1);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
CuAssertIntEquals(tc, 1, build(u, &bf.cons, 0, 10, 0)); CuAssertIntEquals(tc, 1, build(u, 1, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
scale_number(u, 2); scale_number(u, 2);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
i_change(&u->items, rtype->itype, 2); i_change(&u->items, rtype->itype, 2);
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 10, 0)); CuAssertIntEquals(tc, 2, build(u, 1, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
scale_number(u, 2); scale_number(u, 2);
set_level(u, SK_ARMORER, bf.cons.minskill * 2); set_level(u, SK_ARMORER, bf.cons.minskill * 2);
i_change(&u->items, rtype->itype, 4); i_change(&u->items, rtype->itype, 4);
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 10, 0)); CuAssertIntEquals(tc, 4, build(u, 1, &bf.cons, 0, 10, 0));
CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 0, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -234,7 +234,7 @@ static void test_build_with_ring(CuTest *tc) {
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
i_change(&u->items, rtype->itype, 20); i_change(&u->items, rtype->itype, 20);
i_change(&u->items, ring, 1); i_change(&u->items, ring, 1);
CuAssertIntEquals(tc, 10, build(u, &bf.cons, 0, 20, 0)); CuAssertIntEquals(tc, 10, build(u, 1, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 10, i_get(u->items, rtype->itype));
teardown_build(&bf); teardown_build(&bf);
} }
@ -253,16 +253,16 @@ static void test_build_with_potion(CuTest *tc) {
i_change(&u->items, rtype->itype, 20); i_change(&u->items, rtype->itype, 20);
change_effect(u, ptype, 4); change_effect(u, ptype, 4);
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
CuAssertIntEquals(tc, 2, build(u, &bf.cons, 0, 20, 0)); CuAssertIntEquals(tc, 2, build(u, 1, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype)); CuAssertIntEquals(tc, 18, i_get(u->items, rtype->itype));
CuAssertIntEquals(tc, 3, get_effect(u, ptype)); CuAssertIntEquals(tc, 3, get_effect(u, ptype));
set_level(u, SK_ARMORER, bf.cons.minskill * 2); set_level(u, SK_ARMORER, bf.cons.minskill * 2);
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0)); CuAssertIntEquals(tc, 4, build(u, 1, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 2, get_effect(u, ptype)); CuAssertIntEquals(tc, 2, get_effect(u, ptype));
set_level(u, SK_ARMORER, bf.cons.minskill); set_level(u, SK_ARMORER, bf.cons.minskill);
scale_number(u, 2); /* OBS: this scales the effects, too: */ scale_number(u, 2); /* OBS: this scales the effects, too: */
CuAssertIntEquals(tc, 4, get_effect(u, ptype)); CuAssertIntEquals(tc, 4, get_effect(u, ptype));
CuAssertIntEquals(tc, 4, build(u, &bf.cons, 0, 20, 0)); CuAssertIntEquals(tc, 4, build(u, 1, &bf.cons, 0, 20, 0));
CuAssertIntEquals(tc, 2, get_effect(u, ptype)); CuAssertIntEquals(tc, 2, get_effect(u, ptype));
teardown_build(&bf); teardown_build(&bf);
} }

View File

@ -538,5 +538,8 @@ const char *ship_getname(const ship * sh)
} }
int ship_damage_percent(const ship *sh) { int ship_damage_percent(const ship *sh) {
return (sh->damage * 100 + DAMAGE_SCALE - 1) / (sh->size * DAMAGE_SCALE); /* Schaden muss granularer sein als Größe, deshalb ist er skaliert
* DAMAGE_SCALE ist der Faktor zwischen 1 Schadenspunkt und 1 Größenpunkt.
*/
return ((DAMAGE_SCALE - 1) + sh->damage * 100) / (sh->size * DAMAGE_SCALE);
} }