change tax break zone mechanics

There can be multiple tax break zones, unlocked at increasing
city levels, but they are fixed once set.
This will prevent mayorial bait and switch abuse.
This commit is contained in:
Crypto City 2022-08-24 11:10:49 +00:00
parent 614ead0d29
commit 1f636fbf8e
36 changed files with 243 additions and 170 deletions

View File

@ -265,7 +265,7 @@ TBLayout: axis: y, distribution-position: "center top", distribution: "available
TBButton: skin: "TBButton.column", id: "city-found", text: "Found new city"
TBButton: skin: "TBButton.column", id: "city-allow-settlers", text: "Allow settlers"
TBButton: skin: "TBButton.column", id: "city-allow-styling", text: "Allow styling"
TBButton: skin: "TBButton.column", id: "city-set-tax-break-zone", text: "Set tax break zone"
TBButton: skin: "TBButton.column", id: "city-add-tax-break-zone", text: "Add tax break zone"
TBSection: value: 0, text: "Selection", id: "selection-section"
TBLayout: axis: y, spacing: 0, size: available

View File

@ -269,8 +269,7 @@ struct cc_city_data_t
std::string name;
std::vector<uint32_t> allow_styling;
std::vector<uint32_t> allow_settlers;
int32_t tax_break_dx;
int32_t tax_break_dy;
std::vector<std::pair<int32_t, int32_t>> tax_break_zones;
};
#pragma pack(push, 1)
@ -2044,7 +2043,8 @@ public:
virtual void set_cc_city_fishing_population(uint32_t id, uint32_t close, uint32_t medium) = 0;
virtual void set_cc_city_allow_styling(uint32_t id, const std::vector<uint32_t> &accounts, bool allow) = 0;
virtual void set_cc_city_allow_settlers(uint32_t id, const std::vector<uint32_t> &accounts, bool allow) = 0;
virtual void set_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy) = 0;
virtual void add_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy) = 0;
virtual void remove_last_cc_city_tax_break_zone(uint32_t id) = 0;
virtual uint32_t get_num_cc_cities() const = 0;
virtual bool for_all_cc_cities(std::function<bool(const cc_city_data_t &cd)>) const = 0;

View File

@ -710,8 +710,7 @@ typedef struct mdb_cc_city_data
std::string name;
std::vector<uint32_t> allow_styling;
std::vector<uint32_t> allow_settlers;
int32_t tax_break_dx;
int32_t tax_break_dy;
std::vector<std::pair<int32_t, int32_t>> tax_break_zones;
BEGIN_SERIALIZE_OBJECT()
FIELD(seed)
@ -728,8 +727,7 @@ typedef struct mdb_cc_city_data
TEXT_FIELD(name)
FIELD(allow_styling)
FIELD(allow_settlers)
VARINT_FIELD_SIGNED(tax_break_dx)
VARINT_FIELD_SIGNED(tax_break_dy)
FIELD(tax_break_zones)
END_SERIALIZE()
} mdb_cc_city_data;
@ -6903,8 +6901,6 @@ uint32_t BlockchainLMDB::allocate_new_cc_city(uint32_t seed, uint32_t mayor, con
cd.close_fish = NUM_STARTING_CLOSE_FISH;
cd.medium_fish = NUM_STARTING_MEDIUM_FISH;
cd.name = name;
cd.tax_break_dx = 0;
cd.tax_break_dy = 0;
k.mv_data = (void*)&city_id;
k.mv_size = sizeof(city_id);
@ -7307,7 +7303,7 @@ void BlockchainLMDB::set_cc_city_allow_settlers(uint32_t id, const std::vector<u
throw0(DB_ERROR(lmdb_error("Failed to set city allowed settlers list in db transaction: ", result).c_str()));
}
void BlockchainLMDB::set_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy)
void BlockchainLMDB::add_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@ -7326,8 +7322,40 @@ void BlockchainLMDB::set_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t
if (!read_city_data(v, cd))
throw0(DB_ERROR("Failed to deserialize city data"));
cd.tax_break_dx = dx;
cd.tax_break_dy = dy;
cd.tax_break_zones.push_back(std::make_pair(dx, dy));
if (!write_city_data(v, cd))
throw0(DB_ERROR("Failed to serialize city data"));
result = mdb_cursor_put(m_cur_cc_cities, &k, &v, 0);
if (v.mv_data) free(v.mv_data);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to set city allowed settlers list in db transaction: ", result).c_str()));
}
void BlockchainLMDB::remove_last_cc_city_tax_break_zone(uint32_t id)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;
CURSOR(cc_cities)
// find city id
MDB_val_set(k, id);
MDB_val v;
int result = mdb_cursor_get(m_cur_cc_cities, &k, &v, MDB_SET);
if (result)
throw0(DB_ERROR(lmdb_error("City " + std::to_string(id) + " not found: ", result).c_str()));
mdb_cc_city_data cd;
if (!read_city_data(v, cd))
throw0(DB_ERROR("Failed to deserialize city data"));
if (cd.tax_break_zones.empty())
throw0(DB_ERROR("City " + std::to_string(id) + " has no tax break zones, cannot remove: "));
cd.tax_break_zones.pop_back();
if (!write_city_data(v, cd))
throw0(DB_ERROR("Failed to serialize city data"));
@ -7381,8 +7409,7 @@ bool BlockchainLMDB::for_all_cc_cities(std::function<bool(const cc_city_data_t &
ccd.name = cd.name;
ccd.allow_styling = cd.allow_styling;
ccd.allow_settlers = cd.allow_settlers;
ccd.tax_break_dx = cd.tax_break_dx;
ccd.tax_break_dy = cd.tax_break_dy;
ccd.tax_break_zones = cd.tax_break_zones;
if (!f(ccd))
{
@ -7430,8 +7457,7 @@ bool BlockchainLMDB::get_cc_city_data(uint32_t id, cc_city_data_t &ccd) const
ccd.name = cd.name;
ccd.allow_styling = cd.allow_styling;
ccd.allow_settlers = cd.allow_settlers;
ccd.tax_break_dx = cd.tax_break_dx;
ccd.tax_break_dy = cd.tax_break_dy;
ccd.tax_break_zones = cd.tax_break_zones;
TXN_POSTFIX_RDONLY();
return true;
@ -10623,8 +10649,7 @@ bool BlockchainLMDB::get_as_cc_city(const cryptonote::blobdata &bd, cc_city_data
ccd.name = cd.name;
ccd.allow_styling = cd.allow_styling;
ccd.allow_settlers = cd.allow_settlers;
ccd.tax_break_dx = cd.tax_break_dx;
ccd.tax_break_dy = cd.tax_break_dy;
ccd.tax_break_zones = cd.tax_break_zones;
return true;
}

View File

@ -586,7 +586,8 @@ private:
void set_cc_city_fishing_population(uint32_t id, uint32_t close, uint32_t medium);
void set_cc_city_allow_styling(uint32_t id, const std::vector<uint32_t> &accounts, bool allow);
void set_cc_city_allow_settlers(uint32_t id, const std::vector<uint32_t> &accounts, bool allow);
void set_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy);
void add_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy);
void remove_last_cc_city_tax_break_zone(uint32_t id);
uint32_t get_num_cc_cities() const;
bool get_cc_city_data(uint32_t id, cc_city_data_t &cd) const;
bool for_all_cc_cities(std::function<bool(const cc_city_data_t &cd)>) const;

View File

@ -218,7 +218,8 @@ public:
virtual void set_cc_city_fishing_population(uint32_t id, uint32_t close, uint32_t medium) {}
virtual void set_cc_city_allow_styling(uint32_t id, const std::vector<uint32_t> &accounts, bool allow) {}
virtual void set_cc_city_allow_settlers(uint32_t id, const std::vector<uint32_t> &accounts, bool allow) {}
virtual void set_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy) {}
virtual void add_cc_city_tax_break_zone(uint32_t id, int32_t dx, int32_t dy) {}
virtual void remove_last_cc_city_tax_break_zone(uint32_t id) {}
uint32_t get_num_cc_cities() const { return 1; }
bool for_all_cc_cities(std::function<bool(const cc_city_data_t &cd)>) const { return false; }

View File

@ -83,7 +83,7 @@ set(cc_sources
cc_command_handler_resize_flag.cpp
cc_command_handler_script_choice.cpp
cc_command_handler_service.cpp
cc_command_handler_set_tax_break_zone.cpp
cc_command_handler_add_tax_break_zone.cpp
cc_command_handler_set_merchant_ship_items.cpp
cc_command_handler_set_script_variables.cpp
cc_command_handler_smelt.cpp
@ -181,7 +181,7 @@ set(cc_headers
cc_command_handler_resize_flag.h
cc_command_handler_script_choice.h
cc_command_handler_service.h
cc_command_handler_set_tax_break_zone.h
cc_command_handler_add_tax_break_zone.h
cc_command_handler_set_merchant_ship_items.h
cc_command_handler_set_script_variables.h
cc_command_handler_smelt.h

View File

@ -94,7 +94,7 @@
#include "cc_command_handler_service.h"
#include "cc_command_handler_set_merchant_ship_items.h"
#include "cc_command_handler_set_script_variables.h"
#include "cc_command_handler_set_tax_break_zone.h"
#include "cc_command_handler_add_tax_break_zone.h"
#include "cc_command_handler_smelt.h"
#include "cc_command_handler_sow.h"
#include "cc_command_handler_transfer.h"
@ -1210,12 +1210,13 @@ uint32_t get_management_level(const cryptonote::BlockchainDB &db, uint32_t accou
return 0;
}
bool get_land_tax(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t ox, uint32_t oy, uint32_t economic_power, uint32_t city_level, uint32_t cartography_level, int32_t dx, int32_t dy, uint64_t &cost)
bool get_land_tax(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t ox, uint32_t oy, uint32_t economic_power, uint32_t city_level, uint32_t cartography_level, const std::vector<std::pair<int32_t, int32_t>> &tax_break_zones, uint64_t &cost)
{
cost = (x1 - x0 + 1) * (y1 - y0 + 1) * std::max<uint32_t>(economic_power, 100) * (uint64_t)LAND_TAX_PER_TILE / 100;
const uint32_t d0 = cc::get_distance(x0, y0, x1, y1, ox, oy);
const uint32_t d1 = cc::get_distance(x0, y0, x1, y1, ox + dx, oy + dy);
const uint32_t rawd = std::min<uint32_t>(std::min(d0, d1), MAX_TAX_INCREASE_DISTANCE);
uint32_t d0 = cc::get_distance(x0, y0, x1, y1, ox, oy);
for (const auto &e: tax_break_zones)
d0 = std::min(d0, cc::get_distance(x0, y0, x1, y1, ox + e.first, oy + e.second));
const uint32_t rawd = std::min<uint32_t>(d0, MAX_TAX_INCREASE_DISTANCE);
const uint32_t d = rawd * 2 / (2 + cartography_level);
static_assert(LAND_TAX_QUANTIZATION_DISTANCE && (LAND_TAX_QUANTIZATION_DISTANCE & (LAND_TAX_QUANTIZATION_DISTANCE-1)) == 0, "LAND_TAX_QUANTIZATION_DISTANCE must be a power of 2");
const uint32_t qd = d & ~(LAND_TAX_QUANTIZATION_DISTANCE-1);
@ -3812,6 +3813,15 @@ uint32_t get_influence_bonus(const cryptonote::BlockchainDB &db, uint32_t city,
return influence_bonus;
}
uint32_t get_max_tax_break_zones(uint32_t city_level)
{
if (city_level < 5)
return 0;
if (city_level < 9)
return 1;
return 2 + (city_level - 9) / 3;
}
void cc_derive_keys(const crypto::secret_key &base, crypto::secret_key &skey, crypto::public_key &pkey)
{
char data[33];
@ -3910,7 +3920,7 @@ static cc_command_handler &get_cc_command_handler(const cryptonote::cc_command_t
cc_command_handler &operator()(const cryptonote::cc_command_service_t &cmd) const { return cc_command_handler_service::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return cc_command_handler_set_merchant_ship_items::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return cc_command_handler_set_script_variables::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return cc_command_handler_set_tax_break_zone::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return cc_command_handler_add_tax_break_zone::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_smelt_t &cmd) const { return cc_command_handler_smelt::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_sow_t &cmd) const { return cc_command_handler_sow::instance; }
cc_command_handler &operator()(const cryptonote::cc_command_start_script_t &cmd) const { return cc_command_handler_start_script::instance; }

View File

@ -76,7 +76,7 @@ uint32_t get_cartography_level(const cryptonote::BlockchainDB &db, uint32_t acco
uint32_t get_logging_level(const cryptonote::BlockchainDB &db, uint32_t account);
uint32_t get_quarrying_level(const cryptonote::BlockchainDB &db, uint32_t account);
uint32_t get_management_level(const cryptonote::BlockchainDB &db, uint32_t account);
bool get_land_tax(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t ox, uint32_t oy, uint32_t economic_power, uint32_t city_level, uint32_t cartography_level, int32_t dx, int32_t dy, uint64_t &cost);
bool get_land_tax(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t ox, uint32_t oy, uint32_t economic_power, uint32_t city_level, uint32_t cartography_level, const std::vector<std::pair<int32_t, int32_t>> &tax_break_zones, uint64_t &cost);
void get_repair_costs(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t role, uint32_t economic_power, uint32_t delta_repair, std::map<uint32_t, uint32_t> &costs);
void get_upgrade_costs(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t role, uint32_t economic_power, uint32_t new_economic_power, std::map<uint32_t, uint32_t> &costs);
std::string print_repair_percentage(int32_t repair);
@ -174,6 +174,7 @@ uint32_t get_item_balance_including_reserves(uint32_t item, const std::map<uint3
uint32_t get_num_players(const cryptonote::BlockchainDB &db);
bool has_specialization(const std::map<uint32_t, uint64_t> &specializations, uint32_t specialization, uint64_t *height = NULL);
uint32_t get_influence_bonus(const cryptonote::BlockchainDB &db, uint32_t city, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t role);
uint32_t get_max_tax_break_zones(uint32_t city_level);
bool encode_blocks(const uint8_t *src_types, uint32_t n_src_types, uint8_t *encoded_types, uint32_t *encoded_types_len);
bool decode_blocks(const uint8_t *encoded_types, uint32_t encoded_types_len, uint8_t *dst_types, uint32_t *n_dst_types);

View File

@ -125,7 +125,7 @@ static const struct
},
{
"Tax break zone",
"Land tax is based off the shortest distance between the town center and a mayor chosen alternate location",
"Land tax is based off the shortest distance between the town center and a number of mayor chosen alternate locations",
"receive-money",
},
{

View File

@ -29,7 +29,7 @@
#include "blockchain_db/blockchain_db.h"
#include "cc/cc.h"
#include "cc/cc_city_specialization.h"
#include "cc_command_handler_set_tax_break_zone.h"
#include "cc_command_handler_add_tax_break_zone.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "verify"
@ -37,53 +37,58 @@
namespace cc
{
cc_command_handler_set_tax_break_zone cc_command_handler_set_tax_break_zone::instance;
cc_command_handler_add_tax_break_zone cc_command_handler_add_tax_break_zone::instance;
void cc_command_handler_set_tax_break_zone::get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const
void cc_command_handler_add_tax_break_zone::get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const
{
cc_in = 0;
cc_out = 0;
}
uint64_t cc_command_handler_set_tax_break_zone::get_cost(const cryptonote::cc_command_t &cmd) const
uint64_t cc_command_handler_add_tax_break_zone::get_cost(const cryptonote::cc_command_t &cmd) const
{
return 0;
}
bool cc_command_handler_set_tax_break_zone::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const
bool cc_command_handler_add_tax_break_zone::check(const cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, cryptonote::tx_verification_context &tvc) const
{
const cryptonote::cc_command_set_tax_break_zone_t &set_tax_break_zone = boost::get<cryptonote::cc_command_set_tax_break_zone_t>(cmd);
const cryptonote::cc_command_add_tax_break_zone_t &add_tax_break_zone = boost::get<cryptonote::cc_command_add_tax_break_zone_t>(cmd);
CHECK_COMMAND_SET(set_tax_break_zone.dx || set_tax_break_zone.dy, tvc.m_cc_bad_coords, "Tax break zone is not moved");
CHECK_COMMAND_SET(add_tax_break_zone.dx || add_tax_break_zone.dy, tvc.m_cc_bad_coords, "Tax break zone is the town center");
cryptonote::cc_city_data_t cd;
CHECK_COMMAND_SET(db.get_cc_city_data(set_tax_break_zone.city, cd), tvc.m_cc_invalid_city, "City not found");
CHECK_COMMAND_SET(cd.mayor == set_tax_break_zone.cc_account, tvc.m_cc_not_owned, "Setting an alternate land tax center can only be done by the city mayor");
CHECK_COMMAND_SET(db.get_cc_city_data(add_tax_break_zone.city, cd), tvc.m_cc_invalid_city, "City not found");
const auto it = std::find(cd.tax_break_zones.begin(), cd.tax_break_zones.end(), std::make_pair(add_tax_break_zone.dx, add_tax_break_zone.dy));
CHECK_COMMAND_SET(it == cd.tax_break_zones.end(), tvc.m_cc_bad_coords, "Duplicate tax break zone");
CHECK_COMMAND_SET(cd.mayor == add_tax_break_zone.cc_account, tvc.m_cc_not_owned, "Setting an alternate land tax center can only be done by the city mayor");
CHECK_COMMAND_SET(cc::has_specialization(cd.specializations, cc::CITY_SPECIALIZATION_TAX_BREAK_ZONE), tvc.m_cc_not_allowed, "Setting an alternate land tax center can only be done if the city has the tax break specialization");
const uint32_t max_tax_break_zones = cc::get_max_tax_break_zones(cd.level);
CHECK_COMMAND_SET(cd.tax_break_zones.size() + 1 <= max_tax_break_zones, tvc.m_cc_level,
"City already has the maximum number of tax break zones for its level");
return true;
}
bool cc_command_handler_set_tax_break_zone::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const
bool cc_command_handler_add_tax_break_zone::execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const
{
const cryptonote::cc_command_set_tax_break_zone_t &set_tax_break_zone = boost::get<cryptonote::cc_command_set_tax_break_zone_t>(cmd);
const cryptonote::cc_command_add_tax_break_zone_t &add_tax_break_zone = boost::get<cryptonote::cc_command_add_tax_break_zone_t>(cmd);
cryptonote::cc_city_data_t cd;
CHECK_AND_ASSERT_MES(db.get_cc_city_data(set_tax_break_zone.city, cd), false, "City not found");
db.set_cc_city_tax_break_zone(set_tax_break_zone.city, cd.tax_break_dx + set_tax_break_zone.dx, cd.tax_break_dy + set_tax_break_zone.dy);
CHECK_AND_ASSERT_MES(db.get_cc_city_data(add_tax_break_zone.city, cd), false, "City not found");
db.add_cc_city_tax_break_zone(add_tax_break_zone.city, add_tax_break_zone.dx, add_tax_break_zone.dy);
events.add_full(cmd, set_tax_break_zone.cc_account, 0, 0, ITEM_NONE, 0, 0, tx_fee) << "Moved the tax break zone";
events.add_full(cmd, add_tax_break_zone.cc_account, 0, 0, ITEM_NONE, 0, 0, tx_fee) << "Added a tax break zone";
return true;
}
bool cc_command_handler_set_tax_break_zone::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const
bool cc_command_handler_add_tax_break_zone::revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const
{
const cryptonote::cc_command_set_tax_break_zone_t &set_tax_break_zone = boost::get<cryptonote::cc_command_set_tax_break_zone_t>(cmd);
const cryptonote::cc_command_add_tax_break_zone_t &add_tax_break_zone = boost::get<cryptonote::cc_command_add_tax_break_zone_t>(cmd);
cryptonote::cc_city_data_t cd;
CHECK_AND_ASSERT_MES(db.get_cc_city_data(set_tax_break_zone.city, cd), false, "City not found");
db.set_cc_city_tax_break_zone(set_tax_break_zone.city, cd.tax_break_dx - set_tax_break_zone.dx, cd.tax_break_dy - set_tax_break_zone.dy);
CHECK_AND_ASSERT_MES(db.get_cc_city_data(add_tax_break_zone.city, cd), false, "City not found");
db.remove_last_cc_city_tax_break_zone(add_tax_break_zone.city);
return true;
}

View File

@ -33,7 +33,7 @@
namespace cc
{
class cc_command_handler_set_tax_break_zone: public cc_command_handler
class cc_command_handler_add_tax_break_zone: public cc_command_handler
{
public:
virtual void get_in_out(const cryptonote::cc_command_t &cmd, uint64_t &cc_in, uint64_t &cc_out) const;
@ -42,7 +42,7 @@ public:
virtual bool execute(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version, uint64_t tx_fee, game_events_t &events) const;
virtual bool revert(cryptonote::BlockchainDB &db, const cryptonote::cc_command_t &cmd, uint8_t hf_version) const;
static cc_command_handler_set_tax_break_zone instance;
static cc_command_handler_add_tax_break_zone instance;
};
}

View File

@ -317,7 +317,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
std::map<uint32_t, uint32_t> city_seeds;
std::map<uint32_t, uint32_t> rare_fish_scores;
std::map<uint32_t, uint32_t> rare_fish_count;
std::map<uint32_t, std::pair<int32_t, int32_t>> tax_break_zones;
std::map<uint32_t, std::vector<std::pair<int32_t, int32_t>>> tax_break_zones;
std::map<uint32_t, uint32_t> item_prestige_bonuses;
std::vector<uint64_t> new_nonces;
bool merchant_ship_landed = false;
@ -467,7 +467,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
// gather all cities
r = db.for_all_cc_cities([&](const cryptonote::cc_city_data_t &cd) {
cities.insert(cd.id);
tax_break_zones[cd.id] = std::make_pair(cd.tax_break_dx, cd.tax_break_dy);
tax_break_zones[cd.id] = cd.tax_break_zones;
return true;
});
CHECK_AND_ASSERT_THROW_MES(r, "Failed to walk through cities");
@ -615,8 +615,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
uint32_t ox, oy;
cc::get_city_origin(flag.city, ox, oy);
const uint32_t cartography_level = cc::get_cartography_level(db, flag.owner);
const std::pair<int32_t, int32_t> tax_break_zone = tax_break_zones[flag.city];
CHECK_AND_ASSERT_THROW_MES(get_land_tax(flag.x0, flag.y0, flag.x1, flag.y1, ox, oy, flag.economic_power, cd.level, cartography_level, tax_break_zone.first, tax_break_zone.second, land_tax),
CHECK_AND_ASSERT_THROW_MES(get_land_tax(flag.x0, flag.y0, flag.x1, flag.y1, ox, oy, flag.economic_power, cd.level, cartography_level, tax_break_zones[flag.city], land_tax),
"Failed to calculate land tax");
uint64_t long_term_empty_tax = 0;
if (flag.role == ROLE_EMPTY && top_height - flag.construction_height > LONG_TERM_EMPTY_TAX_THRESHOLD)

View File

@ -105,7 +105,7 @@ const cc_command_basenonce_t *get_cc_command_basenonce(const cc_command_t &cmd)
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_service_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
const cc_command_basenonce_t *operator()(const cryptonote::cc_command_start_script_t &cmd) const { return &cmd; }
@ -175,7 +175,7 @@ cc_command_basenonce_t *get_cc_command_basenonce(cc_command_t &cmd)
cc_command_basenonce_t *operator()(cryptonote::cc_command_service_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
cc_command_basenonce_t *operator()(cryptonote::cc_command_start_script_t &cmd) const { return &cmd; }
@ -245,7 +245,7 @@ const cc_command_base_t *get_cc_command_base(const cc_command_t &cmd)
const cc_command_base_t *operator()(const cryptonote::cc_command_service_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
const cc_command_base_t *operator()(const cryptonote::cc_command_start_script_t &cmd) const { return &cmd; }
@ -315,7 +315,7 @@ cc_command_base_t *get_cc_command_base(cc_command_t &cmd)
cc_command_base_t *operator()(cryptonote::cc_command_service_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_script_variables_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_smelt_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_sow_t &cmd) const { return &cmd; }
cc_command_base_t *operator()(cryptonote::cc_command_start_script_t &cmd) const { return &cmd; }
@ -385,7 +385,7 @@ bool is_cc_command_restricted(const cc_command_t &cmd)
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_start_script_t &cmd) const { return false; }
@ -455,7 +455,7 @@ bool cc_command_has_signature(const cc_command_t &cmd)
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return true; }
bool operator()(const cryptonote::cc_command_start_script_t &cmd) const { return true; }

View File

@ -1318,7 +1318,7 @@ namespace cryptonote
END_SERIALIZE()
};
struct cc_command_set_tax_break_zone_t: public cc_command_base_t
struct cc_command_add_tax_break_zone_t: public cc_command_base_t
{
uint32_t city;
int32_t dx;
@ -1744,7 +1744,7 @@ namespace cryptonote
cc_command_new_texture_t,
cc_command_licence_texture_t,
cc_command_create_items_t,
cc_command_set_tax_break_zone_t,
cc_command_add_tax_break_zone_t,
cc_command_set_merchant_ship_items_t
> cc_command_t;
@ -1921,7 +1921,7 @@ CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_name_place_t, (uint8_t)0x3
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_new_texture_t, (uint8_t)0x39);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_licence_texture_t, (uint8_t)0x3a);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_create_items_t, (uint8_t)0x3b);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_set_tax_break_zone_t, (uint8_t)0x3c);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_add_tax_break_zone_t, (uint8_t)0x3c);
CC_VARIANT_TAG(binary_archive, cryptonote::cc_command_set_merchant_ship_items_t, (uint8_t)0x3d);
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_none_t, (const char*)"none");
@ -1984,7 +1984,7 @@ CC_VARIANT_TAG(json_archive, cryptonote::cc_command_name_place_t, (const char*)"
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_new_texture_t, (const char*)"new_texture");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_licence_texture_t, (const char*)"licence_texture");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_create_items_t, (const char*)"create_items");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_set_tax_break_zone_t, (const char*)"set_tax_break_zone");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_add_tax_break_zone_t, (const char*)"add_tax_break_zone");
CC_VARIANT_TAG(json_archive, cryptonote::cc_command_set_merchant_ship_items_t, (const char*)"set_merchant_ship_items");
VARIANT_TAG(debug_archive, cryptonote::cc_command_none_t, "none");
@ -2047,5 +2047,5 @@ VARIANT_TAG(debug_archive, cryptonote::cc_command_name_place_t, "name_place");
VARIANT_TAG(debug_archive, cryptonote::cc_command_new_texture_t, "new_texture");
VARIANT_TAG(debug_archive, cryptonote::cc_command_licence_texture_t, "licence_texture");
VARIANT_TAG(debug_archive, cryptonote::cc_command_create_items_t, "create_items");
VARIANT_TAG(debug_archive, cryptonote::cc_command_set_tax_break_zone_t, "set_tax_break_zone");
VARIANT_TAG(debug_archive, cryptonote::cc_command_add_tax_break_zone_t, "add_tax_break_zone");
VARIANT_TAG(debug_archive, cryptonote::cc_command_set_merchant_ship_items_t, "set_merchant_ship_items");

View File

@ -2694,8 +2694,8 @@ bool t_rpc_command_executor::cc_get_city(uint32_t id, const std::string &data)
}
}
tools::success_msg_writer() << "Specializations: " << ss.str();
if (res.tax_break_dx || res.tax_break_dy)
tools::success_msg_writer() << "Tax break zone: " << res.tax_break_dx << " " << res.tax_break_dy;
for (const auto &e: res.tax_break_zones)
tools::success_msg_writer() << "Tax break zone: " << e.dx << " " << e.dy;
tools::success_msg_writer() << "Treasury balance: " << cryptonote::print_money(res.treasury_balance);
tools::success_msg_writer() << "Special event: " << cc::get_special_event_name(res.special_event);
return true;

View File

@ -59,7 +59,7 @@ void CityState::update(const std::shared_ptr<GameWallet> &wallet, uint64_t top_h
*this = CityState(id);
return;
}
w->get_cc_city_data(id, ox, oy, seed, treasury, mayor, name, treasury_balance, specializations, level, max_level, moose, bears, close_fish, medium_fish, tax_break_dx, tax_break_dy);
w->get_cc_city_data(id, ox, oy, seed, treasury, mayor, name, treasury_balance, specializations, level, max_level, moose, bears, close_fish, medium_fish, tax_break_zones);
const bool cold_snap = special_event == cc::SPECIAL_EVENT_COLD_SNAP;
const bool heat_wave = special_event == cc::SPECIAL_EVENT_HEAT_WAVE;
const bool snowstorm = special_event == cc::SPECIAL_EVENT_SNOWSTORM;
@ -1066,14 +1066,13 @@ bool GameState::process_set_script_variables(const cryptonote::cc_command_set_sc
return true;
}
bool GameState::process_set_tax_break_zone(const cryptonote::cc_command_set_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w)
bool GameState::process_add_tax_break_zone(const cryptonote::cc_command_add_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w)
{
if (cmd.city == cityState.id)
{
cityState.tax_break_dx += cmd.dx;
cityState.tax_break_dy += cmd.dy;
cityState.tax_break_zones.push_back(std::make_pair(cmd.dx, cmd.dy));
}
TRIGGER_TUTORIAL(cmd, "set-tax-break-zone");
TRIGGER_TUTORIAL(cmd, "add-tax-break-zone");
return true;
}
@ -1203,7 +1202,7 @@ bool GameState::process_command(const cryptonote::cc_command_t &cmd, const std::
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return self.process_service(cmd, w); }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return self.process_set_merchant_ship_items(cmd, w); }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return self.process_set_script_variables(cmd, w); }
bool operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return self.process_set_tax_break_zone(cmd, w); }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return self.process_add_tax_break_zone(cmd, w); }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return self.process_smelt(cmd, w); }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return self.process_sow(cmd, w); }
bool operator()(const cryptonote::cc_command_start_script_t &cmd) const { return self.process_start_script(cmd, w); }

View File

@ -114,8 +114,7 @@ struct CityState
bool ready;
std::vector<uint32_t> allow_styling;
std::vector<uint32_t> allow_settlers;
int32_t tax_break_dx;
int32_t tax_break_dy;
std::vector<std::pair<int32_t, int32_t>> tax_break_zones;
uint64_t treasury_balance;
uint64_t last_payout_shares[NUM_ROLES];
@ -282,7 +281,7 @@ private:
bool process_service(const cryptonote::cc_command_service_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_merchant_ship_items(const cryptonote::cc_command_set_merchant_ship_items_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_script_variables(const cryptonote::cc_command_set_script_variables_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_set_tax_break_zone(const cryptonote::cc_command_set_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_add_tax_break_zone(const cryptonote::cc_command_add_tax_break_zone_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_smelt(const cryptonote::cc_command_smelt_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_sow(const cryptonote::cc_command_sow_t &cmd, const std::shared_ptr<GameWallet> &w);
bool process_start_script(const cryptonote::cc_command_start_script_t &cmd, const std::shared_ptr<GameWallet> &w);

View File

@ -174,7 +174,7 @@ std::string get_command_string(const GameState *game, const cryptonote::cc_comma
msg.push_back("'" + e.name + "' to " + std::to_string(e.new_value));
return "Setting script variables " + boost::join(msg, ", ");
}
std::string operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return "Setting tax break zone location"; }
std::string operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return "Adding a tax break zone"; }
std::string operator()(const cryptonote::cc_command_smelt_t &cmd) const { return "Smelting " + std::to_string(cmd.amount) + " collectible coins"; }
std::string operator()(const cryptonote::cc_command_sow_t &cmd) const { return "Sowing " + std::string(cc::get_crop_name(cmd.crop)) + " in " + game_util::get_building_name(game, cmd.flag); }
std::string operator()(const cryptonote::cc_command_start_script_t &cmd) const {

View File

@ -2505,7 +2505,7 @@ void GameWalletInternal::on_reorg(uint64_t height)
bool operator()(const cryptonote::cc_command_service_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_smelt_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_sow_t &cmd) const { return false; }
bool operator()(const cryptonote::cc_command_start_script_t &cmd) const { return false; }

View File

@ -510,7 +510,7 @@ public:
void HandleNewPlaceName(StringHash eventType, VariantMap& eventData);
void HandleNewUserTexture(StringHash eventType, VariantMap& eventData);
void HandleDeleteUserTexture(StringHash eventType, VariantMap& eventData);
void HandleSetTaxBreakZone(StringHash eventType, VariantMap& eventData);
void HandleAddTaxBreakZone(StringHash eventType, VariantMap& eventData);
void HandleSetMerchantShipAvailableItems(StringHash eventType, VariantMap& eventData);
void HandleSendMessage(StringHash eventType, VariantMap& eventData);
void HandleDeleteMessage(StringHash eventType, VariantMap& eventData);
@ -1675,7 +1675,7 @@ void CryptoCityUrho3D::SetupUI()
SubscribeToEvent(ui, E_CRYPTOCITY_GET_IMPORTED_PALETTE, URHO3D_HANDLER(CryptoCityUrho3D, HandleGetImportedPalette));
SubscribeToEvent(ui, E_CRYPTOCITY_SET_PALETTE_ENTRY, URHO3D_HANDLER(CryptoCityUrho3D, HandleSetPaletteEntry));
SubscribeToEvent(ui, E_CRYPTOCITY_GUESS_PALETTE, URHO3D_HANDLER(CryptoCityUrho3D, HandleGuessPalette));
SubscribeToEvent(ui, E_CRYPTOCITY_SET_TAX_BREAK_ZONE, URHO3D_HANDLER(CryptoCityUrho3D, HandleSetTaxBreakZone));
SubscribeToEvent(ui, E_CRYPTOCITY_ADD_TAX_BREAK_ZONE, URHO3D_HANDLER(CryptoCityUrho3D, HandleAddTaxBreakZone));
SubscribeToEvent(ui, E_CRYPTOCITY_SET_MERCHANT_SHIP_AVAILABLE_ITEMS, URHO3D_HANDLER(CryptoCityUrho3D, HandleSetMerchantShipAvailableItems));
SubscribeToEvent(ui, E_CRYPTOCITY_SEND_MESSAGE, URHO3D_HANDLER(CryptoCityUrho3D, HandleSendMessage));
SubscribeToEvent(ui, E_CRYPTOCITY_DELETE_MESSAGE, URHO3D_HANDLER(CryptoCityUrho3D, HandleDeleteMessage));
@ -2020,9 +2020,7 @@ void CryptoCityUrho3D::UpdateTargetting()
{
const uint32_t level = gameState.cityState.level;
const uint32_t cartography_level = gameState.get_cartography_level();
const int32_t tax_break_dx = gameState.cityState.tax_break_dx;
const int32_t tax_break_dy = gameState.cityState.tax_break_dy;
if (!cc::get_land_tax(selection.x0, selection.y0, selection.x1, selection.y1, ox, oy, 100, level, cartography_level, tax_break_dx, tax_break_dy, cost))
if (!cc::get_land_tax(selection.x0, selection.y0, selection.x1, selection.y1, ox, oy, 100, level, cartography_level, gameState.cityState.tax_break_zones, cost))
cost = 0;
s += "\nLand tax: " + game_util::print_money(cost) + "/tick";
}
@ -4219,12 +4217,12 @@ void CryptoCityUrho3D::HandleBuyLand(StringHash eventType, VariantMap& eventData
ui->AddToastNotification("After the land purchase goes through,\nyou can select Building Settings\nto start building on your new land");
}
void CryptoCityUrho3D::HandleSetTaxBreakZone(StringHash eventType, VariantMap& eventData)
void CryptoCityUrho3D::HandleAddTaxBreakZone(StringHash eventType, VariantMap& eventData)
{
UnsetFocus();
if (!wallet || !wallet->wallet())
{
new MessageBox(context_, "No wallet loaded - load a wallet to be able to set the city's tax break zone");
new MessageBox(context_, "No wallet loaded - load a wallet to be able to add a city tax break zone");
return;
}
if (gameState.cityState.mayor != gameState.playerState.id)
@ -4238,11 +4236,11 @@ void CryptoCityUrho3D::HandleSetTaxBreakZone(StringHash eventType, VariantMap& e
return;
}
cryptonote::cc_command_set_tax_break_zone_t cmd;
cryptonote::cc_command_add_tax_break_zone_t cmd;
cmd.cc_account = wallet->get_cc_account();
cmd.city = gameState.cityState.id;
cmd.dx = (int32_t)(eventData[SetTaxBreakZone::P_X].GetUInt() - gameState.cityState.ox - gameState.cityState.tax_break_dx);
cmd.dy = (int32_t)(eventData[SetTaxBreakZone::P_Y].GetUInt() - gameState.cityState.oy - gameState.cityState.tax_break_dy);
cmd.dx = (int32_t)(eventData[AddTaxBreakZone::P_X].GetUInt() - gameState.cityState.ox);
cmd.dy = (int32_t)(eventData[AddTaxBreakZone::P_Y].GetUInt() - gameState.cityState.oy);
SendCommand(cmd);
}

View File

@ -562,10 +562,8 @@ void UIBuildingSettingsDialog::SetBudget(const Map *map, const GameState *gameSt
std::vector<uint32_t> cartography_levels;
if (w->get_cc_cartography_levels({flag->owner}, cartography_levels) && cartography_levels.size() == 1)
cartography_level = cartography_levels[0];
const uint32_t tax_break_dx = game->cityState.tax_break_dx;
const uint32_t tax_break_dy = game->cityState.tax_break_dy;
uint64_t land_tax;
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, city.ox, city.oy, economic_power, city.level, cartography_level, tax_break_dx, tax_break_dy, land_tax))
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, city.ox, city.oy, economic_power, city.level, cartography_level, game->cityState.tax_break_zones, land_tax))
{
AddRow(rightLayout, "Land tax", game_util::print_money(land_tax).c_str());
estimated_cost += land_tax;

View File

@ -209,7 +209,7 @@ static std::string get_extra_command_info(const cryptonote::cc_command_t &cmd)
std::string operator()(const cryptonote::cc_command_service_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_merchant_ship_items_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_script_variables_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_set_tax_break_zone_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_add_tax_break_zone_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_smelt_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_sow_t &cmd) const { return ""; }
std::string operator()(const cryptonote::cc_command_start_script_t &cmd) const { return ""; }
@ -949,7 +949,7 @@ static std::vector<std::string> get_flag_data(const GameState *game, const std::
uint32_t ox, oy;
cc::get_city_origin(flag->city, ox, oy);
uint64_t tax;
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, game->cityState.level, cartography_level, game->cityState.tax_break_dx, game->cityState.tax_break_dy, tax))
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, game->cityState.level, cartography_level, game->cityState.tax_break_zones, tax))
contents[FC_LAND_TAX] = game_util::print_money(tax).c_str();
snprintf(s, sizeof(s), "%u", cc::get_cc_influence(flag->x0, flag->y0, flag->x1, flag->y1, flag->role, flag->economic_power, flag->elevation_bonus, flag->potential, game->cityState.special_event));
@ -1192,7 +1192,7 @@ TBWidget *UIPlayerInfoDialog::FlagSource::CreateItemWidget(int index, TBSelectIt
uint32_t ox, oy;
cc::get_city_origin(flag->city, ox, oy);
uint64_t tax;
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, item->game->cityState.level, item->cartography_level, item->game->cityState.tax_break_dx, item->game->cityState.tax_break_dy, tax))
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, item->game->cityState.level, item->cartography_level, item->game->cityState.tax_break_zones, tax))
running_land_tax += tax;
int64_t delta_gold;

View File

@ -1128,7 +1128,7 @@ void UIUrho3D::Update(float timeStep, uint32_t mouse_x, uint32_t mouse_y, uint32
EnableWidget("city-allow-settlers", hasAccount && gameState->cityState.mayor == gameState->playerState.id);
EnableWidget("city-name-place", hasAccount && sx0 && sy0 && sx1 && sy1);
EnableWidget("city-set-tax-break-zone", hasAccount && gameState->cityState.mayor == gameState->playerState.id && sx0 && sy0 && sx1 && sy1);
EnableWidget("city-add-tax-break-zone", hasAccount && gameState->cityState.mayor == gameState->playerState.id && sx0 && sy0 && sx1 && sy1);
ShowWidget(flagOwnerInfoButton, hasFlagSelected);
@ -1417,7 +1417,7 @@ void UIUrho3D::UpdateSelection(uint32_t mouse_x, uint32_t mouse_y, uint32_t sx0,
if (sx0 || sx1 || sy0 || sy1)
{
uint64_t land_tax;
if (cc::get_land_tax(sx0, sy0, sx1, sy1, city->ox, city->oy, 100, city->level, cartographpy_level, city->tax_break_dx, city->tax_break_dy, land_tax))
if (cc::get_land_tax(sx0, sy0, sx1, sy1, city->ox, city->oy, 100, city->level, cartographpy_level, city->tax_break_zones, land_tax))
snprintf(s, sizeof(s), "%s", game_util::print_money(land_tax).c_str());
else
snprintf(s, sizeof(s), "error");
@ -1425,7 +1425,7 @@ void UIUrho3D::UpdateSelection(uint32_t mouse_x, uint32_t mouse_y, uint32_t sx0,
else if (mouse_x || mouse_y)
{
uint64_t land_tax;
if (cc::get_land_tax(mouse_x, mouse_y, mouse_x, mouse_y, city->ox, city->oy, 100, city->level, cartographpy_level, city->tax_break_dx, city->tax_break_dy, land_tax))
if (cc::get_land_tax(mouse_x, mouse_y, mouse_x, mouse_y, city->ox, city->oy, 100, city->level, cartographpy_level, city->tax_break_zones, land_tax))
snprintf(s, sizeof(s), "%s", game_util::print_money(land_tax).c_str());
else
snprintf(s, sizeof(s), "error");
@ -1485,7 +1485,7 @@ void UIUrho3D::UpdateFlag(uint32_t mouse_x, uint32_t mouse_y, uint32_t sx0, uint
const uint32_t cartographpy_level = gameState->get_cartography_level();
uint64_t land_tax;
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, city->ox, city->oy, flag->economic_power, city->level, cartographpy_level, city->tax_break_dx, city->tax_break_dy, land_tax))
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, city->ox, city->oy, flag->economic_power, city->level, cartographpy_level, city->tax_break_zones, land_tax))
snprintf(s, sizeof(s), "%s", game_util::print_money(land_tax).c_str());
else
snprintf(s, sizeof(s), "error");
@ -2677,11 +2677,11 @@ void UIUrho3D::HandleSetGlobalVariable(StringHash eventType, VariantMap& eventDa
SendTutorialTrigger("screen-set-global-variable");
}
void UIUrho3D::HandleSetTaxBreakZone(StringHash eventType, VariantMap& eventData)
void UIUrho3D::HandleAddTaxBreakZone(StringHash eventType, VariantMap& eventData)
{
if (sel_x0 == 0 || sel_y0 == 0 || sel_x1 == 0 || sel_y1 == 0)
{
new MessageBox(context_, "Select a point or an area centered around the ppint from which land tax will be lowered");
new MessageBox(context_, "Select a point or an area centered around the point from which land tax will be lowered");
return;
}
if (!(gameState->cityState.specializations >> cc::CITY_SPECIALIZATION_TAX_BREAK_ZONE) & 1)
@ -2689,6 +2689,15 @@ void UIUrho3D::HandleSetTaxBreakZone(StringHash eventType, VariantMap& eventData
new MessageBox(context_, "The city does not have the tax break specialization yet");
return;
}
const uint32_t max_tax_break_zones = cc::get_max_tax_break_zones(gameState->cityState.level);
if (gameState->cityState.tax_break_zones.size() + 1 > max_tax_break_zones)
{
uint32_t level = gameState->cityState.level + 1;
while (cc::get_max_tax_break_zones(level) <= max_tax_break_zones)
++level;
new MessageBox(context_, "The city cannot have another tax break zone before reaching level " + String(level));
return;
}
const uint32_t x = sel_x0 + (sel_x1 - sel_x0) / 2;
const uint32_t y = sel_y0 + (sel_y1 - sel_y0) / 2;
@ -2696,21 +2705,47 @@ void UIUrho3D::HandleSetTaxBreakZone(StringHash eventType, VariantMap& eventData
const uint32_t oy = gameState->cityState.oy;
const uint32_t d = cc::get_distance(x, y, ox, oy);
const uint32_t city_level = gameState->cityState.level;
std::string msg = "This location is " + std::to_string(d) + " tiles from the town center\n";
std::string msg = "This location at " + std::to_string((int32_t)(x - ox)) + " " + std::to_string((int32_t)(y - oy)) + " is " + std::to_string(d) + " tiles from the town center\n";
if (!gameState->cityState.tax_break_zones.empty())
{
uint32_t dprime = std::numeric_limits<uint32_t>::max();
int32_t xprime = 0, yprime = 0;
for (const auto &e: gameState->cityState.tax_break_zones)
{
const uint32_t tmpd = cc::get_distance(x, y, ox + e.first, oy + e.second);
if (tmpd < dprime)
{
dprime = tmpd;
xprime = e.first;
yprime = e.second;
}
}
msg += "and " + std::to_string(dprime) + " tiles from the nearest other tax break center at " + std::to_string(xprime) + " " + std::to_string(yprime) + "\n";
msg += "Current tax break zones are:\n";
for (const auto &e: gameState->cityState.tax_break_zones)
msg += " " + std::to_string(e.first) + " " + std::to_string(e.second) + "\n";
}
uint64_t land_tax_before = 0;
cc::get_land_tax(x, y, x, y, ox, oy, 100, city_level, 0, 0, 0, land_tax_before);
msg += "The base land tax here is currently " + game_util::print_money(land_tax_before) + " gold\n";
cc::get_land_tax(x, y, x, y, ox, oy, 100, city_level, 0, gameState->cityState.tax_break_zones, land_tax_before);
msg += "The base land tax here is currently " + game_util::print_money(land_tax_before) + " gold.\n";
uint64_t land_tax_after = 0;
cc::get_land_tax(ox, oy, ox, oy, ox, oy, 100, city_level, 0, 0, 0, land_tax_after);
msg += "Setting the city's tax break zone here would make the base land tax here " + game_util::print_money(land_tax_after) + " gold\n";
msg += "Set the city's tax break zone here?";
std::vector<std::pair<int32_t, int32_t>> new_tax_break_zones = gameState->cityState.tax_break_zones;
new_tax_break_zones.push_back(std::make_pair(x - ox, y - oy));
cc::get_land_tax(x, y, x, y, ox, oy, 100, city_level, 0, new_tax_break_zones, land_tax_after);
msg += "Setting the city's tax break zone here would make the base land tax here " + game_util::print_money(land_tax_after) + " gold,\n";
char buf[64];
snprintf(buf, sizeof(buf), "%.1f%%", 100.0f * land_tax_after / land_tax_before);
msg += "or " + std::string(buf) + " of the current land tax.\n";
msg += "\n";
msg += "Once set, a tax break zone may not be changed.\n";
msg += "Add a tax break zone here?";
tb::TBMessageWindowSettings settings;
settings.msg = TB_MSG_YES_NO;
new MessageBox(context_, command_window, msg.c_str(), "Confirmation", &settings, TBID("confirm-set-tax-break-zone"));
new MessageBox(context_, command_window, msg.c_str(), "Confirmation", &settings, TBID("confirm-add-tax-break-zone"));
}
void UIUrho3D::HandleSetTaxBreakZoneConfirmation(StringHash eventType, VariantMap& eventData)
void UIUrho3D::HandleAddTaxBreakZoneConfirmation(StringHash eventType, VariantMap& eventData)
{
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[TBWidgetEventNamespace::P_WIDGET_EVENT].GetVoidPtr();
if (ev->ref_id != TBIDC("TBMessageWindow.yes"))
@ -2718,7 +2753,7 @@ void UIUrho3D::HandleSetTaxBreakZoneConfirmation(StringHash eventType, VariantMa
if (sel_x0 == 0 || sel_y0 == 0 || sel_x1 == 0 || sel_y1 == 0)
{
new MessageBox(context_, "Select a point or an area centered around the ppint from which land tax will be lowered");
new MessageBox(context_, "Select a point or an area centered around the point from which land tax will be lowered");
return;
}
@ -2726,9 +2761,9 @@ void UIUrho3D::HandleSetTaxBreakZoneConfirmation(StringHash eventType, VariantMa
const uint32_t y = sel_y0 + (sel_y1 - sel_y0) / 2;
VariantMap newEventData;
newEventData[SetTaxBreakZone::P_X] = x;
newEventData[SetTaxBreakZone::P_Y] = y;
SendEvent(E_CRYPTOCITY_SET_TAX_BREAK_ZONE, newEventData);
newEventData[AddTaxBreakZone::P_X] = x;
newEventData[AddTaxBreakZone::P_Y] = y;
SendEvent(E_CRYPTOCITY_ADD_TAX_BREAK_ZONE, newEventData);
}
void UIUrho3D::HandleMerchantShipAvailableItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData)
@ -3668,7 +3703,7 @@ void UIUrho3D::HandleTBMessage(StringHash eventType, VariantMap& eventData)
CONNECT("city-whisper", HandleWhisper);
CONNECT("city-name-place", HandleNamePlace);
CONNECT("city-go-to-place", HandleGoToPlace);
CONNECT("city-set-tax-break-zone", HandleSetTaxBreakZone);
CONNECT("city-add-tax-break-zone", HandleAddTaxBreakZone);
CONNECT("gm-new-event-badge", HandleNewEventBadge);
CONNECT("gm-award-event-badge", HandleAwardEventBadge);
@ -3710,7 +3745,7 @@ void UIUrho3D::HandleTBMessage(StringHash eventType, VariantMap& eventData)
CONNECT("place-model-rotate", [this](StringHash, VariantMap&) { PlaceModel(0, 0, 0, 1); });
CONNECT("place-model-done", [this](StringHash, VariantMap&) { PlaceModel(0, 0, 0, 0); });
CONNECT("confirm-set-tax-break-zone", HandleSetTaxBreakZoneConfirmation);
CONNECT("confirm-add-tax-break-zone", HandleAddTaxBreakZoneConfirmation);
CONNECT_PARENT("main-panel", [this](StringHash, VariantMap&) { SendTutorialTrigger("main-panel"); });
}

View File

@ -277,7 +277,7 @@ URHO3D_EVENT(E_CRYPTOCITY_ADD_TEXTURE, AddTexture) { URHO3D_PARAM(P_BLOCK, Block
URHO3D_EVENT(E_CRYPTOCITY_LICENCE_TEXTURE, LicenceTexture) { URHO3D_PARAM(P_TEXTURE, Texture); }
URHO3D_EVENT(E_CRYPTOCITY_CREATE_ITEMS, CreateItems) { URHO3D_PARAM(P_ITEM, Item); URHO3D_PARAM(P_AMOUNT, Amount); }
URHO3D_EVENT(E_CRYPTOCITY_TEXTURE_NOTILE, TextureNoTile) { URHO3D_PARAM(P_ENABLE, Enable); }
URHO3D_EVENT(E_CRYPTOCITY_SET_TAX_BREAK_ZONE, SetTaxBreakZone) { URHO3D_PARAM(P_X, X); URHO3D_PARAM(P_Y, Y); }
URHO3D_EVENT(E_CRYPTOCITY_ADD_TAX_BREAK_ZONE, AddTaxBreakZone) { URHO3D_PARAM(P_X, X); URHO3D_PARAM(P_Y, Y); }
URHO3D_EVENT(E_CRYPTOCITY_SET_MERCHANT_SHIP_AVAILABLE_ITEMS, SetMerchantShipAvailableItems) { URHO3D_PARAM(P_REMOVE, Remove); /* vector */ URHO3D_PARAM(P_ADD, Add); /* vector */ }
URHO3D_EVENT(E_CRYPTOCITY_SEND_MESSAGE, SendMessage) { URHO3D_PARAM(P_RECIPIENT, Recipient); URHO3D_PARAM(P_REPLY, Reply); URHO3D_PARAM(P_SUBJECT, Subject); URHO3D_PARAM(P_MESSAGE, Message); }
URHO3D_EVENT(E_CRYPTOCITY_DELETE_MESSAGE, DeleteMessage) { URHO3D_PARAM(P_ID, ID); }
@ -473,8 +473,8 @@ private:
void HandleNewAuctionItem(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleFish(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleCreateItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleSetTaxBreakZone(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleSetTaxBreakZoneConfirmation(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleAddTaxBreakZone(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleAddTaxBreakZoneConfirmation(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleMerchantShipAvailableItems(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
void HandleMessages(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);

View File

@ -288,7 +288,7 @@ const uint64_t cost = cc::get_new_city_cost(cities.size(), shares);
uint32_t ox, oy;
cc::get_city_origin(flag->city, ox, oy);
uint64_t tax;
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, game->cityState.level, cartography_level, game->cityState.tax_break_dx, game->cityState.tax_break_dy, tax))
if (cc::get_land_tax(flag->x0, flag->y0, flag->x1, flag->y1, ox, oy, flag->economic_power, game->cityState.level, cartography_level, game->cityState.tax_break_zones, tax))
delta_gold -= (int64_t)tax;
int64_t dgold = 0;

View File

@ -4152,8 +4152,8 @@ namespace cryptonote
res.medium_fish = cd.medium_fish;
res.allow_styling = cd.allow_styling;
res.allow_settlers = cd.allow_settlers;
res.tax_break_dx = cd.tax_break_dx;
res.tax_break_dy = cd.tax_break_dy;
for (const auto &e: cd.tax_break_zones)
res.tax_break_zones.push_back({e.first, e.second});
std::vector<cc::special_event_data_t> sed;
m_core.get_blockchain_storage().get_db().get_cc_special_events(req.id, sed);
@ -6074,10 +6074,10 @@ namespace cryptonote
res.num_active_flags = 0;
res.food_needed_per_tick = 0;
std::map<uint32_t, uint32_t> city_level;
std::map<uint32_t, std::pair<int32_t, int32_t>> tax_break_zones;
std::map<uint32_t, std::vector<std::pair<int32_t, int32_t>>> tax_break_zones;
db.for_all_cc_cities([&city_level, &tax_break_zones](const cryptonote::cc_city_data_t &cd) {
city_level[cd.id] = cd.level;
tax_break_zones[cd.id] = std::make_pair(cd.tax_break_dx, cd.tax_break_dy);
tax_break_zones[cd.id] = cd.tax_break_zones;
return true;
});
db.for_all_cc_flags([&res, &db, &city_level, &tax_break_zones](const cc_flag_data_t &flag) {
@ -6091,8 +6091,7 @@ namespace cryptonote
uint32_t ox, oy;
cc::get_city_origin(flag.city, ox, oy);
const uint32_t cartography_level = cc::get_cartography_level(db, flag.owner);
const std::pair<int32_t, int32_t> tax_break_zone = tax_break_zones[flag.city];
cc::get_land_tax(flag.x0, flag.y0, flag.x1, flag.y1, ox, oy, flag.economic_power, city_level[flag.city], cartography_level, tax_break_zone.first, tax_break_zone.second, land_tax);
cc::get_land_tax(flag.x0, flag.y0, flag.x1, flag.y1, ox, oy, flag.economic_power, city_level[flag.city], cartography_level, tax_break_zones[flag.city], land_tax);
res.land_tax += land_tax;
res.current_block_bytes += flag.tiles.size();

View File

@ -3181,6 +3181,17 @@ namespace cryptonote
};
typedef epee::misc_utils::struct_init<request_t> request;
struct tax_break_zone_t
{
int32_t dx;
int32_t dy;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(dx)
KV_SERIALIZE(dy)
END_KV_SERIALIZE_MAP()
};
struct response_t
{
uint32_t ox;
@ -3201,8 +3212,7 @@ namespace cryptonote
uint32_t special_event;
std::vector<uint32_t> allow_styling;
std::vector<uint32_t> allow_settlers;
int32_t tax_break_dx;
int32_t tax_break_dy;
std::vector<tax_break_zone_t> tax_break_zones;
std::string status;
BEGIN_KV_SERIALIZE_MAP()
@ -3224,8 +3234,7 @@ namespace cryptonote
KV_SERIALIZE(special_event)
KV_SERIALIZE(allow_styling)
KV_SERIALIZE(allow_settlers)
KV_SERIALIZE(tax_break_dx)
KV_SERIALIZE(tax_break_dy)
KV_SERIALIZE(tax_break_zones)
KV_SERIALIZE(status)
END_KV_SERIALIZE_MAP()
};

View File

@ -1179,7 +1179,7 @@ private:
bool get_cc_account_public_key(uint32_t id, crypto::public_key &pkey);
bool get_cc_account_pm_keys(uint32_t id, crypto::public_key &pmspk, crypto::public_key &pmvpk);
bool get_cc_account_reserve(uint32_t id, uint32_t account, uint64_t &balance, std::map<uint32_t, uint32_t> &items);
bool get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &seed, uint32_t &treasury, uint32_t &mayor, std::string &name, uint64_t &treasury_balance, uint32_t &specializations, uint32_t &level, uint32_t &max_level, uint32_t &moose, uint32_t &bears, uint32_t &close_fish, uint32_t &medium_fish, int32_t &tax_break_dx, int32_t &tax_break_dy);
bool get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &seed, uint32_t &treasury, uint32_t &mayor, std::string &name, uint64_t &treasury_balance, uint32_t &specializations, uint32_t &level, uint32_t &max_level, uint32_t &moose, uint32_t &bears, uint32_t &close_fish, uint32_t &medium_fish, std::vector<std::pair<int32_t, int32_t>> &tax_break_zones);
bool get_cc_special_events(uint32_t city, bool all, std::vector<cc::special_event_data_t> &special_events);
bool get_cc_snapshot(cryptonote::cc_snapshot &snapshot, uint32_t city_id, uint64_t &height, crypto::hash &top_hash, std::vector<cryptonote::cc_command_t> &top_commands);
bool get_cc_last_update_events(uint64_t &height, crypto::hash &block_hash, uint64_t &timestamp, cc::game_events_t &events);

View File

@ -236,7 +236,7 @@ bool wallet2::get_cc_account_reserve(uint32_t id, uint32_t account, uint64_t &ba
return true;
}
bool wallet2::get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &seed, uint32_t &treasury, uint32_t &mayor, std::string &name, uint64_t &treasury_balance, uint32_t &specializations, uint32_t &level, uint32_t &max_level, uint32_t &moose, uint32_t &bears, uint32_t &close_fish, uint32_t &medium_fish, int32_t &tax_break_dx, int32_t &tax_break_dy)
bool wallet2::get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t &seed, uint32_t &treasury, uint32_t &mayor, std::string &name, uint64_t &treasury_balance, uint32_t &specializations, uint32_t &level, uint32_t &max_level, uint32_t &moose, uint32_t &bears, uint32_t &close_fish, uint32_t &medium_fish, std::vector<std::pair<int32_t, int32_t>> &tax_break_zones)
{
cryptonote::COMMAND_RPC_CC_GET_CITY::request req = AUTO_VAL_INIT(req);
cryptonote::COMMAND_RPC_CC_GET_CITY::response res;
@ -262,8 +262,9 @@ bool wallet2::get_cc_city_data(uint32_t id, uint32_t &ox, uint32_t &oy, uint32_t
bears = res.bears;
close_fish = res.close_fish;
medium_fish = res.medium_fish;
tax_break_dx = res.tax_break_dx;
tax_break_dy = res.tax_break_dy;
tax_break_zones.reserve(res.tax_break_zones.size());
for (const auto &e: res.tax_break_zones)
tax_break_zones.push_back(std::make_pair(e.dx, e.dy));
return true;
}

View File

@ -7256,9 +7256,9 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_cc_set_tax_break_zone(const wallet_rpc::COMMAND_RPC_CC_SET_TAX_BREAK_ZONE::request& req, wallet_rpc::COMMAND_RPC_CC_SET_TAX_BREAK_ZONE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
bool wallet_rpc_server::on_cc_add_tax_break_zone(const wallet_rpc::COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE::request& req, wallet_rpc::COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
LOG_PRINT_L3("on_cc_set_tax_break_zone starts");
LOG_PRINT_L3("on_cc_add_tax_break_zone starts");
if (!m_wallet) return not_open(er);
if (m_restricted)
{
@ -7269,7 +7269,7 @@ namespace tools
try
{
cryptonote::cc_command_set_tax_break_zone_t cmd;
cryptonote::cc_command_add_tax_break_zone_t cmd;
cmd.cc_account = m_wallet->get_cc_account();
cmd.city = req.city;
cmd.dx = req.dx;

View File

@ -221,7 +221,7 @@ namespace tools
MAP_JON_RPC_WE("cc_new_texture", on_cc_new_texture, wallet_rpc::COMMAND_RPC_CC_NEW_TEXTURE)
MAP_JON_RPC_WE("cc_licence_texture", on_cc_licence_texture, wallet_rpc::COMMAND_RPC_CC_LICENCE_TEXTURE)
MAP_JON_RPC_WE("cc_create_items", on_cc_create_items, wallet_rpc::COMMAND_RPC_CC_CREATE_ITEMS)
MAP_JON_RPC_WE("cc_set_tax_break_zone", on_cc_set_tax_break_zone, wallet_rpc::COMMAND_RPC_CC_SET_TAX_BREAK_ZONE)
MAP_JON_RPC_WE("cc_add_tax_break_zone", on_cc_add_tax_break_zone, wallet_rpc::COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE)
MAP_JON_RPC_WE("cc_set_merchant_ship_items", on_cc_set_merchant_ship_items, wallet_rpc::COMMAND_RPC_CC_SET_MERCHANT_SHIP_ITEMS)
MAP_JON_RPC_WE("cc_get_pm_keys_state", on_cc_get_pm_keys_state, wallet_rpc::COMMAND_RPC_CC_GET_PM_KEYS_STATE)
MAP_JON_RPC_WE("cc_sweep_message_fees", on_cc_sweep_message_fees, wallet_rpc::COMMAND_RPC_CC_SWEEP_MESSAGE_FEES)
@ -379,7 +379,7 @@ namespace tools
bool on_cc_new_texture(const wallet_rpc::COMMAND_RPC_CC_NEW_TEXTURE::request& req, wallet_rpc::COMMAND_RPC_CC_NEW_TEXTURE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_licence_texture(const wallet_rpc::COMMAND_RPC_CC_LICENCE_TEXTURE::request& req, wallet_rpc::COMMAND_RPC_CC_LICENCE_TEXTURE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_create_items(const wallet_rpc::COMMAND_RPC_CC_CREATE_ITEMS::request& req, wallet_rpc::COMMAND_RPC_CC_CREATE_ITEMS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_set_tax_break_zone(const wallet_rpc::COMMAND_RPC_CC_SET_TAX_BREAK_ZONE::request& req, wallet_rpc::COMMAND_RPC_CC_SET_TAX_BREAK_ZONE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_add_tax_break_zone(const wallet_rpc::COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE::request& req, wallet_rpc::COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_set_merchant_ship_items(const wallet_rpc::COMMAND_RPC_CC_SET_MERCHANT_SHIP_ITEMS::request& req, wallet_rpc::COMMAND_RPC_CC_SET_MERCHANT_SHIP_ITEMS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_get_pm_keys_state(const wallet_rpc::COMMAND_RPC_CC_GET_PM_KEYS_STATE::request& req, wallet_rpc::COMMAND_RPC_CC_GET_PM_KEYS_STATE::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
bool on_cc_sweep_message_fees(const wallet_rpc::COMMAND_RPC_CC_SWEEP_MESSAGE_FEES::request& req, wallet_rpc::COMMAND_RPC_CC_SWEEP_MESSAGE_FEES::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);

View File

@ -6077,7 +6077,7 @@ namespace wallet_rpc
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_CC_SET_TAX_BREAK_ZONE
struct COMMAND_RPC_CC_ADD_TAX_BREAK_ZONE
{
struct request_t
{

View File

@ -3061,10 +3061,10 @@ bool gen_cc_tx_valid_cc_repair::generate(std::vector<test_event_entry>& events)
land_tax = 0;
uint64_t tax;
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, 0, 0, tax))
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, {}, tax))
return false;
land_tax += tax;
if (!cc::get_land_tax(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, settings.economic_power, 0, 0, 0, 0, tax))
if (!cc::get_land_tax(buy_land.x, buy_land.y, buy_land.x + buy_land.wm1, buy_land.y + buy_land.hm1, ox, oy, settings.economic_power, 0, 0, {}, tax))
return false;
land_tax += tax;
@ -3296,7 +3296,7 @@ bool gen_cc_tx_valid_huge_game_update::generate(std::vector<test_event_entry>& e
uint32_t ox, oy;
cc::get_city_origin(0, ox, oy);
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, 0, 0, land_tax))
if (!cc::get_land_tax(ox + PREP_BUY_LAND_X, oy + PREP_BUY_LAND_Y, ox + PREP_BUY_LAND_X + PREP_BUY_LAND_WM1, oy + PREP_BUY_LAND_Y + PREP_BUY_LAND_HM1, ox, oy, 100, 0, 0, {}, land_tax))
return false;
bool ret = generate_with_full(events, boost::none, boost::none, prep_buy_stuff, cmds.size(), 1, mixin, amount_paid, true, cmds, false, valid, true, NULL, NULL);

View File

@ -6618,7 +6618,7 @@ class CCTest():
print("Testing tax break zone")
# no specialization
self.assert_exception(lambda: self.wallet[1].cc_set_tax_break_zone(1, 8000, 3000))
self.assert_exception(lambda: self.wallet[1].cc_add_tax_break_zone(1, 8000, 3000))
# add the specialization
res = self.wallet[1].cc_add_city_specialization(1, CITY_SPECIALIZATION_TAX_BREAK_ZONE)
@ -6627,26 +6627,17 @@ class CCTest():
# other invalid cases:
# not mayor
self.assert_exception(lambda: self.wallet[2].cc_set_tax_break_zone(1, 8000, 3000))
self.assert_exception(lambda: self.wallet[2].cc_add_tax_break_zone(1, 8000, 3000))
# no change
self.assert_exception(lambda: self.wallet[1].cc_set_tax_break_zone(1, 0, 0))
self.assert_exception(lambda: self.wallet[1].cc_add_tax_break_zone(1, 0, 0))
# now it works
self.wallet[1].cc_set_tax_break_zone(1, 8000, 3000)
self.wallet[1].cc_add_tax_break_zone(1, 8000, 3000)
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
res = daemon.cc_get_city(1)
assert res.tax_break_dx == 8000
assert res.tax_break_dy == 3000
# it can be moved
self.wallet[1].cc_set_tax_break_zone(1, -11000, 500)
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', 1)
res = daemon.cc_get_city(1)
assert res.tax_break_dx == -3000
assert res.tax_break_dy == 3500
assert res.tax_break_zones == [{'dx': 8000, 'dy': 3000}]
# cities can be traded

View File

@ -3086,7 +3086,7 @@ TEST(cc, type_tags)
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x3a);
cmd = cryptonote::cc_command_create_items_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x3b);
cmd = cryptonote::cc_command_set_tax_break_zone_t();
cmd = cryptonote::cc_command_add_tax_break_zone_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x3c);
cmd = cryptonote::cc_command_set_merchant_ship_items_t();
ASSERT_EQ(get_cc_tag<uint8_t>(cmd), 0x3d);
@ -4123,15 +4123,17 @@ TEST(cc, land_tax)
uint64_t land_tax_d10000_l1_c1_a1024;
uint64_t land_tax_d10000_l1_c1_a1024_tax_break_zone;
ASSERT_TRUE(cc::get_land_tax(0, 0, 16, 16, 0, 0, 100, 0, 0, 0, 0, land_tax_d0_l0_c0_a256));
ASSERT_TRUE(cc::get_land_tax(0, 0, 32, 32, 0, 0, 100, 0, 0, 0, 0, land_tax_d0_l0_c0_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 0, 0, 0, 0, land_tax_d10000_l0_c0_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 0, 0, 0, 0, land_tax_d10000_l0_c0_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 0, 1, 0, 0, land_tax_d10000_l0_c1_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 0, 1, 0, 0, land_tax_d10000_l0_c1_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 1, 1, 0, 0, land_tax_d10000_l1_c1_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 1, 1, 0, 0, land_tax_d10000_l1_c1_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 1, 1, 5000, 0, land_tax_d10000_l1_c1_a1024_tax_break_zone));
ASSERT_TRUE(cc::get_land_tax(0, 0, 16, 16, 0, 0, 100, 0, 0, {}, land_tax_d0_l0_c0_a256));
ASSERT_TRUE(cc::get_land_tax(0, 0, 32, 32, 0, 0, 100, 0, 0, {}, land_tax_d0_l0_c0_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 0, 0, {}, land_tax_d10000_l0_c0_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 0, 0, {}, land_tax_d10000_l0_c0_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 0, 1, {}, land_tax_d10000_l0_c1_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 0, 1, {}, land_tax_d10000_l0_c1_a1024));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+16, 16, 0, 0, 100, 1, 1, {}, land_tax_d10000_l1_c1_a256));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 1, 1, {}, land_tax_d10000_l1_c1_a1024));
std::vector<std::pair<int32_t, int32_t>> zones;
zones.push_back(std::make_pair(5000, 0));
ASSERT_TRUE(cc::get_land_tax(10000, 0, 10000+32, 32, 0, 0, 100, 1, 1, zones, land_tax_d10000_l1_c1_a1024_tax_break_zone));
ASSERT_GT(land_tax_d0_l0_c0_a1024, land_tax_d0_l0_c0_a256);
ASSERT_GT(land_tax_d10000_l0_c0_a1024, land_tax_d10000_l0_c0_a256);

View File

@ -2225,9 +2225,9 @@ class Wallet(object):
}
return self.rpc.send_json_rpc_request(cc_create_items)
def cc_set_tax_break_zone(self, city, dx, dy, priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
cc_set_tax_break_zone = {
'method': 'cc_set_tax_break_zone',
def cc_add_tax_break_zone(self, city, dx, dy, priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
cc_add_tax_break_zone = {
'method': 'cc_add_tax_break_zone',
'params': {
'city': city,
'dx': dx,
@ -2240,7 +2240,7 @@ class Wallet(object):
'jsonrpc': '2.0',
'id': '0'
}
return self.rpc.send_json_rpc_request(cc_set_tax_break_zone)
return self.rpc.send_json_rpc_request(cc_add_tax_break_zone)
def cc_set_merchant_ship_items(self, remove, add, priority = 0, do_not_relay = False, get_tx_hex = False, get_tx_metadata = False):
cc_set_merchant_ship_items = {