forked from github/server
fixed two bugs: harbours were not unique and multiple instances of unique buildings could still be built
This commit is contained in:
parent
d65d03db9c
commit
8714957a61
|
@ -128,7 +128,7 @@
|
|||
</construction>
|
||||
</building>
|
||||
|
||||
<building name="harbour" capacity="1" maxcapacity="25" maxsize="25">
|
||||
<building name="harbour" capacity="1" maxcapacity="25" maxsize="25" unique="yes">
|
||||
<maintenance type="money" amount="250" vital="yes"/>
|
||||
<construction skill="building" minskill="3" reqsize="25" maxsize="25">
|
||||
<requirement type="log" quantity="125"/>
|
||||
|
|
|
@ -5,6 +5,19 @@ local function _test_create_ship(r)
|
|||
return s
|
||||
end
|
||||
|
||||
local function _test_unique_btype()
|
||||
local utype = nil
|
||||
for i = 1, #config.buildings do
|
||||
bt = config.buildings[i]
|
||||
if (((config.get_building(bt).flags / 4) % 2) ~= 0) then -- #define BTF_UNIQUE 0x04
|
||||
if (((config.get_building(bt).flags / 2) % 2) == 0) then -- #define BTF_NOBUILD 0x02
|
||||
utype = bt
|
||||
end
|
||||
end
|
||||
end
|
||||
return utype
|
||||
end
|
||||
|
||||
local function one_unit(r, f)
|
||||
local u = unit.create(f, r, 1)
|
||||
u:add_item("money", u.number * 100)
|
||||
|
@ -943,3 +956,97 @@ function test_bson_with_multiple_attribs()
|
|||
end
|
||||
assert_equal(6, total)
|
||||
end
|
||||
|
||||
function test_building_unique0()
|
||||
local r = region.create(0, 0, "mountain")
|
||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 20)
|
||||
local f2 = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u2 = unit.create(f2, r, 20)
|
||||
local utype = _test_unique_btype()
|
||||
|
||||
if (utype ~= nil) then
|
||||
assert_equal("harbour", utype)
|
||||
u:set_skill("building", 20)
|
||||
u:add_item("log", 10000)
|
||||
u:add_item("iron", 10000)
|
||||
u:add_item("stone", 10000)
|
||||
u:add_item("money", 10000)
|
||||
u2:set_skill("building", 20)
|
||||
u2:add_item("log", 10000)
|
||||
u2:add_item("iron", 10000)
|
||||
u2:add_item("stone", 10000)
|
||||
u2:add_item("money", 10000)
|
||||
|
||||
-- build two harbours in one go
|
||||
u:clear_orders()
|
||||
u:add_order("MACHEN ".. translate(utype))
|
||||
u2:clear_orders()
|
||||
u2:add_order("MACHEN ".. translate(utype))
|
||||
process_orders()
|
||||
assert_not_nil(r.buildings)
|
||||
bcount = 0
|
||||
for bs in r.buildings do
|
||||
assert_equal(1, string.find(bs.name, translate(utype)))
|
||||
if (bs.size >= config.get_building(utype).maxsize) then
|
||||
bcount = bcount + 1
|
||||
end
|
||||
end
|
||||
assert_equal(1, bcount) -- only one should be completed
|
||||
else
|
||||
-- fail() -- no unique building in rules
|
||||
end
|
||||
end
|
||||
|
||||
function test_building_unique()
|
||||
local r = region.create(0, 0, "mountain")
|
||||
local f = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u = unit.create(f, r, 20)
|
||||
local f2 = faction.create("noreply@eressea.de", "human", "de")
|
||||
local u2 = unit.create(f2, r, 20)
|
||||
local utype = _test_unique_btype()
|
||||
|
||||
if (utype ~= nil) then
|
||||
u:set_skill("building", 20)
|
||||
u:add_item("log", 10000)
|
||||
u:add_item("iron", 10000)
|
||||
u:add_item("stone", 10000)
|
||||
u:add_item("money", 10000)
|
||||
u2:set_skill("building", 20)
|
||||
u2:add_item("log", 10000)
|
||||
u2:add_item("iron", 10000)
|
||||
u2:add_item("stone", 10000)
|
||||
u2:add_item("money", 10000)
|
||||
|
||||
-- start building two harbours
|
||||
u:clear_orders()
|
||||
u:add_order("MACHEN 1 Hafen")
|
||||
u2:clear_orders()
|
||||
u2:add_order("MACHEN 1 Hafen")
|
||||
process_orders()
|
||||
-- finish building partial harbours
|
||||
u:clear_orders()
|
||||
u:add_order("MACHEN ".. translate("harbour"))
|
||||
u2:clear_orders()
|
||||
u2:add_order("MACHEN Hafen")
|
||||
process_orders()
|
||||
if (r.buildings() == nil) then
|
||||
process_orders()
|
||||
end
|
||||
assert_not_nil(r.buildings)
|
||||
bcount = 0
|
||||
local h1 = nil
|
||||
for bs in r.buildings do
|
||||
if (h1 == nil) then
|
||||
h1 = bs.name
|
||||
else
|
||||
assert_equal(h1, bs.name)
|
||||
end
|
||||
assert_equal(1, string.find(bs.name, "Hafen"))
|
||||
if (bs.size >= 25) then
|
||||
bcount = bcount + 1
|
||||
end
|
||||
end
|
||||
assert_equal(1, bcount) -- only one should be completed
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,6 +20,7 @@ without prior permission by the authors of Eressea.
|
|||
#include <kernel/config.h>
|
||||
|
||||
#include <kernel/alliance.h>
|
||||
#include <kernel/building.h>
|
||||
#include <kernel/skill.h>
|
||||
#include <kernel/equipment.h>
|
||||
#include <kernel/calendar.h>
|
||||
|
@ -768,6 +769,19 @@ static int config_get_ships(lua_State * L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int config_get_buildings(lua_State * L)
|
||||
{
|
||||
quicklist *ql;
|
||||
int qi, i = 0;
|
||||
lua_createtable(L, ql_length(buildingtypes), 0);
|
||||
for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
|
||||
building_type *btype = (building_type *) ql_get(ql, qi);
|
||||
tolua_pushstring(L, TOLUA_CAST btype->_name);
|
||||
lua_rawseti(L, -2, ++i);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int config_get_locales(lua_State * L)
|
||||
{
|
||||
const struct locale *lang;
|
||||
|
@ -823,6 +837,136 @@ static int config_get_resource(lua_State * L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int config_get_btype(lua_State * L)
|
||||
{
|
||||
const char *name = tolua_tostring(L, 1, 0);
|
||||
|
||||
if (name) {
|
||||
const struct building_type *btype = bt_find(name);
|
||||
if (btype) {
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "flags");
|
||||
lua_pushinteger(L, btype->flags);
|
||||
lua_settable(L, -3);
|
||||
if (btype->capacity > 0) {
|
||||
lua_pushstring(L, "capacity");
|
||||
lua_pushinteger(L, btype->capacity);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
if (btype->maxcapacity > 0) {
|
||||
lua_pushstring(L, "maxcapacity");
|
||||
lua_pushinteger(L, btype->maxcapacity);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
if (btype->maxsize > 0) {
|
||||
lua_pushstring(L, "maxsize");
|
||||
lua_pushinteger(L, btype->maxsize);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
if (btype->maintenance) {
|
||||
int i;
|
||||
lua_pushstring(L, "maintenance");
|
||||
lua_newtable(L);
|
||||
for (i = 0; btype->maintenance[i].number; ++i) {
|
||||
lua_pushstring(L,
|
||||
btype->maintenance[i].rtype->_name[0]);
|
||||
lua_pushinteger(L, btype->maintenance[i].number);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
if (btype->construction) {
|
||||
int i;
|
||||
lua_pushstring(L, "build_skill_min");
|
||||
lua_pushinteger(L, btype->construction->minskill);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "build_skill_name");
|
||||
lua_pushstring(L, skillnames[btype->construction->skill]);
|
||||
lua_settable(L, -3);
|
||||
if (btype->construction->materials) {
|
||||
lua_pushstring(L, "materials");
|
||||
lua_newtable(L);
|
||||
for (i = 0; btype->construction->materials[i].number; ++i) {
|
||||
lua_pushstring(L,
|
||||
btype->construction->materials[i].rtype->_name[0]);
|
||||
lua_pushinteger(L, btype->construction->materials[i].number);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int config_get_stype(lua_State * L)
|
||||
{
|
||||
const char *name = tolua_tostring(L, 1, 0);
|
||||
|
||||
if (name) {
|
||||
const struct ship_type *stype = st_find(name);
|
||||
if (stype) {
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "range");
|
||||
lua_pushinteger(L, stype->range);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "cabins");
|
||||
lua_pushinteger(L, stype->cabins);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "cargo");
|
||||
lua_pushinteger(L, stype->cargo);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "cptskill");
|
||||
lua_pushinteger(L, stype->cptskill);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "minskill");
|
||||
lua_pushinteger(L, stype->minskill);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "sumskill");
|
||||
lua_pushinteger(L, stype->sumskill);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "fishing");
|
||||
lua_pushinteger(L, stype->fishing);
|
||||
lua_settable(L, -3);
|
||||
if (stype->coasts) {
|
||||
const terrain_type *coast = *stype->coasts;
|
||||
lua_pushstring(L, "coasts");
|
||||
lua_newtable(L);
|
||||
while(coast) {
|
||||
lua_pushstring(L, coast->_name);
|
||||
lua_pushinteger(L, 1);
|
||||
lua_settable(L, -3);
|
||||
coast = coast->next;
|
||||
}
|
||||
}
|
||||
if (stype->construction) {
|
||||
int i;
|
||||
lua_pushstring(L, "build_skill_min");
|
||||
lua_pushinteger(L, stype->construction->minskill);
|
||||
lua_settable(L, -3);
|
||||
lua_pushstring(L, "build_skill_name");
|
||||
lua_pushstring(L, skillnames[stype->construction->skill]);
|
||||
lua_settable(L, -3);
|
||||
if (stype->construction->materials) {
|
||||
lua_pushstring(L, "materials");
|
||||
lua_newtable(L);
|
||||
for (i = 0; stype->construction->materials[i].number; ++i) {
|
||||
lua_pushstring(L,
|
||||
stype->construction->materials[i].rtype->_name[0]);
|
||||
lua_pushinteger(L, stype->construction->materials[i].number);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tolua_get_spell_text(lua_State * L)
|
||||
{
|
||||
const struct locale *loc = default_locale;
|
||||
|
@ -1060,7 +1204,10 @@ int tolua_eressea_open(lua_State * L)
|
|||
parse_inifile(L, global.inifile, "config");
|
||||
tolua_variable(L, TOLUA_CAST "locales", &config_get_locales, 0);
|
||||
tolua_function(L, TOLUA_CAST "get_resource", &config_get_resource);
|
||||
tolua_variable(L, TOLUA_CAST "buildings", &config_get_buildings, 0);
|
||||
tolua_function(L, TOLUA_CAST "get_building", &config_get_btype);
|
||||
tolua_variable(L, TOLUA_CAST "ships", &config_get_ships, 0);
|
||||
tolua_function(L, TOLUA_CAST "get_ship", &config_get_stype);
|
||||
} tolua_endmodule(L);
|
||||
tolua_function(L, TOLUA_CAST "get_region_by_id", tolua_get_region_byid);
|
||||
tolua_function(L, TOLUA_CAST "get_faction", tolua_get_faction);
|
||||
|
|
|
@ -890,7 +890,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
|
|||
if (b)
|
||||
btype = b->type;
|
||||
|
||||
if (b && fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) {
|
||||
if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) {
|
||||
/* only one of these per region */
|
||||
cmistake(u, ord, 93, MSG_PRODUCE);
|
||||
return;
|
||||
|
|
|
@ -124,28 +124,28 @@ typedef struct building_typelist {
|
|||
building_type *type;
|
||||
} building_typelist;
|
||||
|
||||
static building_typelist *buildingtypes;
|
||||
quicklist *buildingtypes = NULL;
|
||||
|
||||
building_type *bt_find(const char *name)
|
||||
{
|
||||
const struct building_typelist *btl = buildingtypes;
|
||||
quicklist *ql;
|
||||
int qi;
|
||||
|
||||
assert(name);
|
||||
while (btl && strcmp(btl->type->_name, name))
|
||||
btl = btl->next;
|
||||
if (btl == NULL) {
|
||||
return NULL;
|
||||
|
||||
for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
|
||||
building_type *btype = (building_type *) ql_get(ql, qi);
|
||||
if (strcmp(btype->_name, name) == 0)
|
||||
return btype;
|
||||
}
|
||||
return btl->type;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bt_register(building_type * type)
|
||||
{
|
||||
struct building_typelist *btl = malloc(sizeof(building_type));
|
||||
if (type->init)
|
||||
type->init(type);
|
||||
btl->type = type;
|
||||
btl->next = buildingtypes;
|
||||
buildingtypes = btl;
|
||||
ql_push(&buildingtypes, (void *)type);
|
||||
}
|
||||
|
||||
int buildingcapacity(const building * b)
|
||||
|
@ -362,15 +362,19 @@ const building_type *findbuildingtype(const char *name,
|
|||
bn = bn->next;
|
||||
}
|
||||
if (!bn) {
|
||||
struct building_typelist *btl = buildingtypes;
|
||||
quicklist *ql = buildingtypes;
|
||||
int qi;
|
||||
|
||||
bn = calloc(sizeof(local_names), 1);
|
||||
bn->next = bnames;
|
||||
bn->lang = lang;
|
||||
while (btl) {
|
||||
const char *n = locale_string(lang, btl->type->_name);
|
||||
type.v = (void *)btl->type;
|
||||
|
||||
for (qi = 0, ql = buildingtypes; ql; ql_advance(&ql, &qi, 1)) {
|
||||
building_type *btype = (building_type *) ql_get(ql, qi);
|
||||
|
||||
const char *n = locale_string(lang, btype->_name);
|
||||
type.v = (void *)btype;
|
||||
addtoken(&bn->names, n, type);
|
||||
btl = btl->next;
|
||||
}
|
||||
bnames = bn;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,8 @@ extern "C" {
|
|||
struct attrib *attribs;
|
||||
} building_type;
|
||||
|
||||
extern struct quicklist *buildingtypes;
|
||||
|
||||
extern building_type *bt_find(const char *name);
|
||||
extern void register_buildings(void);
|
||||
extern void bt_register(struct building_type *type);
|
||||
|
|
|
@ -2715,3 +2715,7 @@ void follow_unit(unit * u)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DISABLE_TESTS
|
||||
#include "move_test.c"
|
||||
#endif
|
||||
|
|
|
@ -69,10 +69,10 @@ const ship_type *findshiptype(const char *name, const struct locale *lang)
|
|||
|
||||
for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) {
|
||||
ship_type *stype = (ship_type *) ql_get(ql, qi);
|
||||
variant var;
|
||||
variant var2;
|
||||
const char *n = locale_string(lang, stype->name[0]);
|
||||
var.v = (void *)stype;
|
||||
addtoken(&sn->names, n, var);
|
||||
var2.v = (void *)stype;
|
||||
addtoken(&sn->names, n, var2);
|
||||
}
|
||||
snames = sn;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
CuSuite *get_curse_suite(void);
|
||||
CuSuite *get_market_suite(void);
|
||||
CuSuite *get_move_suite(void);
|
||||
CuSuite *get_laws_suite(void);
|
||||
|
||||
#include <kernel/region.h>
|
||||
|
@ -34,6 +35,7 @@ int RunAllTests(void)
|
|||
CuSuiteAddSuite(suite, get_quicklist_suite());
|
||||
CuSuiteAddSuite(suite, get_curse_suite());
|
||||
CuSuiteAddSuite(suite, get_market_suite());
|
||||
CuSuiteAddSuite(suite, get_move_suite());
|
||||
CuSuiteAddSuite(suite, get_laws_suite());
|
||||
|
||||
CuSuiteRun(suite);
|
||||
|
|
Loading…
Reference in New Issue