forked from townforge/townforge
add terrain features
such as islands, peaks, etc will be detected and assigned to places
This commit is contained in:
parent
6d5529d323
commit
e62d9478de
@ -9,10 +9,14 @@ TBLayout: axis: y, distribution-position: "left top", distribution: "gravity"
|
||||
TBTextField: text: "You can create more complex shapes by creating several areas sharing the same name."
|
||||
TBTextField: text: "Holes may be made by creating an area with an empty name."
|
||||
|
||||
TBEditField: multiline: 1, readonly: 1, gravity: "left right", adapt-to-content: 1, skin: 0, is-focusable: 0
|
||||
text: "Place name"
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
TBTextField: text: "Terrain type:"
|
||||
TBTextField: id: "terrain-feature"
|
||||
TBButton: id: "help", text: "?"
|
||||
|
||||
TBEditField: id: "name", gravity: "all", placeholder: "Give this place a name", multiline: 0
|
||||
TBLayout: axis: x, distribution: "gravity", distribution-position: "left"
|
||||
TBTextField: text: "Place name:"
|
||||
TBEditField: id: "name", gravity: "all", placeholder: "Give this place a name", multiline: 0, autofocus: 1
|
||||
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "Naming a place this size needs"
|
||||
|
@ -223,6 +223,7 @@ elements
|
||||
padding 10
|
||||
|
||||
travel-to-place-row
|
||||
padding 10
|
||||
|
||||
TBButton.tradelink
|
||||
|
||||
|
@ -2,3 +2,7 @@ WindowInfo
|
||||
|
||||
TBLayout: axis: y, size: "available", distribution: "gravity", skin: "travel-to-place-row"
|
||||
TBTextField: id: "name"
|
||||
TBToggleContainer: id: "feature-container", toggle: "expanded", value: 0
|
||||
TBLayout: axis: x
|
||||
TBTextField: id: "feature", gravity: "left right"
|
||||
TBTextField: id: "distance"
|
||||
|
@ -1224,6 +1224,7 @@ typedef struct mdb_cc_place_data_t
|
||||
uint32_t y0;
|
||||
uint32_t x1;
|
||||
uint32_t y1;
|
||||
uint32_t terrain_feature;
|
||||
std::string name;
|
||||
uint32_t priority;
|
||||
|
||||
@ -1234,6 +1235,7 @@ typedef struct mdb_cc_place_data_t
|
||||
FIELD(y0)
|
||||
FIELD(x1)
|
||||
FIELD(y1)
|
||||
VARINT_FIELD(terrain_feature)
|
||||
TEXT_FIELD(name)
|
||||
VARINT_FIELD(priority)
|
||||
END_SERIALIZE()
|
||||
@ -11657,6 +11659,7 @@ void BlockchainLMDB::add_cc_place(const cc::place_t &place)
|
||||
pd.y0 = place.y0;
|
||||
pd.x1 = place.x1;
|
||||
pd.y1 = place.y1;
|
||||
pd.terrain_feature = place.terrain_feature;
|
||||
pd.name = place.name;
|
||||
pd.priority = priority;
|
||||
|
||||
@ -11719,6 +11722,7 @@ bool BlockchainLMDB::for_all_cc_places(uint32_t city, const std::function<bool(c
|
||||
place.y0 = pd.y0;
|
||||
place.x1 = pd.x1;
|
||||
place.y1 = pd.y1;
|
||||
place.terrain_feature = pd.terrain_feature;
|
||||
place.name = std::move(pd.name);
|
||||
place.priority = pd.priority;
|
||||
|
||||
|
@ -111,6 +111,7 @@ set(cc_sources
|
||||
cc_special_events.cpp
|
||||
cc_temperature.cpp
|
||||
cc_terrain.cc
|
||||
cc_terrain_features.cc
|
||||
cc_whisper.cc
|
||||
cc.cpp
|
||||
fixed.cc
|
||||
@ -199,6 +200,7 @@ set(cc_headers
|
||||
cc_special_events.h
|
||||
cc_temperature.h
|
||||
cc_terrain.h
|
||||
cc_terrain_features.h
|
||||
cc.h)
|
||||
|
||||
set(cc_private_headers
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "cc/cc_influence.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "cc/cc_place.h"
|
||||
#include "cc/cc_terrain_features.h"
|
||||
#include "cc_command_handler_helpers.h"
|
||||
#include "cc_command_handler_name_place.h"
|
||||
|
||||
@ -168,7 +169,11 @@ bool cc_command_handler_name_place::execute(cryptonote::BlockchainDB &db, const
|
||||
CHECK_AND_ASSERT_MES(cc::decrease_item_count(db, ITEM_RUNESTONE, num_runestones), false, "Item count anomaly");
|
||||
}
|
||||
|
||||
db.add_cc_place(make_place(name_place));
|
||||
cc::place_t place = make_place(name_place);
|
||||
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(name_place.city, cd.seed);
|
||||
place.terrain_feature = cc::classify_terrain_feature(state, place.x0, place.y0, place.x1, place.y1);
|
||||
|
||||
db.add_cc_place(place);
|
||||
events.add_full(cmd, name_place.cc_account, 0, 0, ITEM_NONE, 0, 0, tx_fee) << "Mamed '" + name_place.name + "' in " << cd.name;
|
||||
|
||||
return true;
|
||||
|
@ -17,6 +17,7 @@ struct place_t
|
||||
uint32_t y0;
|
||||
uint32_t x1;
|
||||
uint32_t y1;
|
||||
uint32_t terrain_feature;
|
||||
std::string name;
|
||||
uint32_t priority;
|
||||
|
||||
@ -24,7 +25,7 @@ struct place_t
|
||||
{
|
||||
return id == other.id && height == other.height && city == other.city && namer == other.namer
|
||||
&& x0 == other.x0 && y0 == other.y0 && x1 == other.x1 && y1 == other.y1
|
||||
&& name == other.name && priority == other.priority;
|
||||
&& terrain_feature == other.terrain_feature && name == other.name && priority == other.priority;
|
||||
}
|
||||
|
||||
};
|
||||
|
125
src/cc/cc_terrain_features.cc
Normal file
125
src/cc/cc_terrain_features.cc
Normal file
@ -0,0 +1,125 @@
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include "cc/cc.h"
|
||||
#include "sqrtint.h"
|
||||
#include "cc_terrain_features.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
const char *terrain_feature_names[] =
|
||||
{
|
||||
"none",
|
||||
"open sea",
|
||||
"sand bank",
|
||||
"beach",
|
||||
"peak",
|
||||
"island",
|
||||
"lake",
|
||||
"plain",
|
||||
};
|
||||
|
||||
terrain_feature_t classify_terrain_feature(const std::shared_ptr<cc_potential_state_t> &state, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1)
|
||||
{
|
||||
const uint32_t w = x1 - x0 + 1;
|
||||
const uint32_t h = y1 - y0 + 1;
|
||||
const int32_t maxwh = std::max(w, h);
|
||||
std::vector<uint16_t> height(w * h);
|
||||
|
||||
uint32_t offset = 0;
|
||||
for (uint32_t y = y0; y <= y1; ++y)
|
||||
for (uint32_t x = x0; x <= x1; ++x)
|
||||
height[offset++] = cc::get_cc_height(state, x, y);
|
||||
|
||||
// open sea
|
||||
bool above_water = false;
|
||||
uint16_t min_height = 0xffff;
|
||||
uint16_t max_height = 0;
|
||||
for (uint16_t h: height)
|
||||
{
|
||||
min_height = std::min(min_height, h);
|
||||
max_height = std::max(max_height, h);
|
||||
if (h >= BASE_WATER_LEVEL)
|
||||
above_water = true;
|
||||
}
|
||||
if (!above_water)
|
||||
return terrain_feature_open_sea;
|
||||
|
||||
// island or sand bank
|
||||
bool water = true;
|
||||
for (uint32_t y = y0; y <= y1; ++y)
|
||||
{
|
||||
if (height[(y - y0) * w] >= BASE_WATER_LEVEL || height[(y - y0) * w + x1 - x0] >= BASE_WATER_LEVEL)
|
||||
{
|
||||
water = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (water) for (uint32_t x = x0; x <= x1; ++x)
|
||||
{
|
||||
if (height[x - x0] >= BASE_WATER_LEVEL || height[(y1 - y0) * w + x - x0] >= BASE_WATER_LEVEL)
|
||||
{
|
||||
water = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (water) // already not open sea
|
||||
{
|
||||
if (max_height < SAND_LEVEL)
|
||||
return terrain_feature_sand_bank;
|
||||
else
|
||||
return terrain_feature_island;
|
||||
}
|
||||
|
||||
// lake
|
||||
bool land = true;
|
||||
for (uint32_t y = y0; y <= y1; ++y)
|
||||
{
|
||||
if (height[(y - y0) * w] <= BASE_WATER_LEVEL || height[(y - y0) * w + x1 - x0] <= BASE_WATER_LEVEL)
|
||||
{
|
||||
land = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (land) for (uint32_t x = x0; x <= x1; ++x)
|
||||
{
|
||||
if (height[x - x0] <= BASE_WATER_LEVEL || height[(y1 - y0) * w + x - x0] <= BASE_WATER_LEVEL)
|
||||
{
|
||||
land = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (land && min_height < BASE_WATER_LEVEL)
|
||||
return terrain_feature_lake;
|
||||
|
||||
// beach
|
||||
uint32_t beach_height = 0;
|
||||
for (uint16_t h: height)
|
||||
if (h > BASE_WATER_LEVEL && h <= SAND_LEVEL)
|
||||
++beach_height;
|
||||
if (beach_height >= w * h * 30 / 100)
|
||||
return terrain_feature_beach;
|
||||
|
||||
// peak
|
||||
uint16_t max_border_height = 0;
|
||||
const uint32_t peak_border_w = w / 10;
|
||||
const uint32_t peak_border_h = h / 10;
|
||||
for (uint32_t y = y0; y <= y1; ++y)
|
||||
for (uint32_t x = x0; x <= x1; ++x)
|
||||
if (y < y0 + peak_border_h || y > y1 - peak_border_h || x < x0 + peak_border_w || x > x1 - peak_border_w)
|
||||
max_border_height = std::max(max_border_height, height[(y - y0) * w + x - x0]);
|
||||
const uint16_t d_peak_height = max_height - max_border_height;
|
||||
const uint64_t peak_rating = 100 * d_peak_height * sqrtint(sqrtint(maxwh * 65536ull * 65536ull)) / (768 * HEIGHT_UNITS_PER_BLOCK * maxwh);
|
||||
if (peak_rating >= 20)
|
||||
return terrain_feature_peak;
|
||||
|
||||
// plain
|
||||
const uint16_t dheight = max_height - min_height;
|
||||
if (min_height > SAND_LEVEL && dheight < maxwh * HEIGHT_UNITS_PER_BLOCK / 12)
|
||||
return terrain_feature_plain;
|
||||
|
||||
return terrain_feature_none;
|
||||
}
|
||||
|
||||
}
|
23
src/cc/cc_terrain_features.h
Normal file
23
src/cc/cc_terrain_features.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "cc/cc_potential.h"
|
||||
|
||||
namespace cc
|
||||
{
|
||||
|
||||
enum terrain_feature_t
|
||||
{
|
||||
terrain_feature_none = 0,
|
||||
terrain_feature_open_sea,
|
||||
terrain_feature_sand_bank,
|
||||
terrain_feature_beach,
|
||||
terrain_feature_peak,
|
||||
terrain_feature_island,
|
||||
terrain_feature_lake,
|
||||
terrain_feature_plain,
|
||||
};
|
||||
|
||||
extern const char *terrain_feature_names[];
|
||||
terrain_feature_t classify_terrain_feature(const std::shared_ptr<cc_potential_state_t> &state, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1);
|
||||
|
||||
}
|
@ -382,6 +382,7 @@ struct cc_snapshot
|
||||
uint32_t y0;
|
||||
uint32_t x1;
|
||||
uint32_t y1;
|
||||
uint32_t terrain_feature;
|
||||
std::string name;
|
||||
uint32_t priority;
|
||||
|
||||
@ -394,6 +395,7 @@ struct cc_snapshot
|
||||
KV_SERIALIZE(y0)
|
||||
KV_SERIALIZE(x1)
|
||||
KV_SERIALIZE(y1)
|
||||
KV_SERIALIZE(terrain_feature)
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(priority)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
@ -407,6 +409,7 @@ struct cc_snapshot
|
||||
FIELD(y0)
|
||||
FIELD(x1)
|
||||
FIELD(y1)
|
||||
VARINT_FIELD(terrain_feature)
|
||||
FIELD(name)
|
||||
VARINT_FIELD(priority)
|
||||
END_SERIALIZE()
|
||||
|
@ -1068,6 +1068,7 @@ bool GameState::process_name_place(const cryptonote::cc_command_name_place_t &cm
|
||||
eventData[NewPlaceName::P_X1] = cmd.x1;
|
||||
eventData[NewPlaceName::P_Y1] = cmd.y1;
|
||||
eventData[NewPlaceName::P_NAME] = cmd.name.c_str();
|
||||
eventData[NewPlaceName::P_TERRAIN_FEATURE] = 0;
|
||||
eventData[NewPlaceName::P_PRIORITY] = 0;
|
||||
SendEvent(E_CRYPTOCITY_NEW_PLACE_NAME, eventData);
|
||||
return true;
|
||||
@ -1632,6 +1633,7 @@ bool GameState::reset(const cryptonote::cc_snapshot *snapshot)
|
||||
eventData[NewPlaceName::P_X1] = p.x1;
|
||||
eventData[NewPlaceName::P_Y1] = p.y1;
|
||||
eventData[NewPlaceName::P_NAME] = p.name.c_str();
|
||||
eventData[NewPlaceName::P_TERRAIN_FEATURE] = p.terrain_feature;
|
||||
eventData[NewPlaceName::P_PRIORITY] = p.priority;
|
||||
SendEvent(E_CRYPTOCITY_NEW_PLACE_NAME, eventData);
|
||||
}
|
||||
|
@ -77,6 +77,7 @@ URHO3D_EVENT(E_CRYPTOCITY_NEW_PLACE_NAME, NewPlaceName)
|
||||
URHO3D_PARAM(P_Y0, Y0);
|
||||
URHO3D_PARAM(P_X1, X1);
|
||||
URHO3D_PARAM(P_Y1, Y1);
|
||||
URHO3D_PARAM(P_TERRAIN_FEATURE, TerrainFeature);
|
||||
URHO3D_PARAM(P_NAME, Name);
|
||||
URHO3D_PARAM(P_PRIORITY, Priority);
|
||||
}
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "cc/cc_influence.h"
|
||||
#include "cc/cc_potential.h"
|
||||
#include "cc/cc_temperature.h"
|
||||
#include "cc/cc_terrain_features.h"
|
||||
#include "selection.h"
|
||||
#include "selection-info.h"
|
||||
#include "game-util.h"
|
||||
@ -1911,6 +1912,7 @@ void CryptoCityUrho3D::UpdateTargetting()
|
||||
selection_tooltip->SetTop(true);
|
||||
SubscribeToEvent(selection_tooltip, E_TB_WINDOW_DEAD, [this](StringHash eventType, VariantMap& eventData){ selection_tooltip = NULL; cached_potential.clear(); });
|
||||
}
|
||||
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
|
||||
std::string s = std::to_string(sel_w) + " x " + std::to_string(sel_h);
|
||||
bool error = sel_w > 256 || sel_h > 256;
|
||||
if (!error)
|
||||
@ -1929,7 +1931,6 @@ void CryptoCityUrho3D::UpdateTargetting()
|
||||
|
||||
if (flags.empty())
|
||||
{
|
||||
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
|
||||
uint32_t ox, oy;
|
||||
uint64_t cost = 0;
|
||||
cc::get_city_origin(gameState.cityState.id, ox, oy);
|
||||
@ -2077,8 +2078,13 @@ void CryptoCityUrho3D::UpdateTargetting()
|
||||
s += "\nUnderwater area: " + std::string(buf);
|
||||
}
|
||||
}
|
||||
if (error)
|
||||
s = "<color #f04040>" + s + "</color>";
|
||||
}
|
||||
if (error)
|
||||
s = "<color #f04040>" + s + "</color>";
|
||||
if (HasSelectionInfo(selection_info_terrain_feature))
|
||||
{
|
||||
const cc::terrain_feature_t feature = cc::classify_terrain_feature(state, selection.x0, selection.y0, selection.x1, selection.y1);
|
||||
s += "\nTerrain feature: " + std::string(cc::terrain_feature_names[feature]);
|
||||
}
|
||||
selection_tooltip->SetText(s.c_str());
|
||||
}
|
||||
@ -7342,7 +7348,13 @@ void CryptoCityUrho3D::HandleNewPlaceName(StringHash eventType, VariantMap& even
|
||||
if (gameState.ignore_player(namer))
|
||||
return;
|
||||
|
||||
map.add_place(id, height, gameState.cityState.id, namer, x0, y0, x1, y1, name.CString(), priority);
|
||||
uint32_t terrain_feature = eventData[NewPlaceName::P_TERRAIN_FEATURE].GetInt();
|
||||
if (!eventData.Contains(NewPlaceName::P_TERRAIN_FEATURE))
|
||||
{
|
||||
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(gameState.cityState.id, gameState.cityState.seed);
|
||||
terrain_feature = cc::classify_terrain_feature(state, x0, y0, x1, y1);
|
||||
}
|
||||
map.add_place(id, height, gameState.cityState.id, namer, x0, y0, x1, y1, terrain_feature, name.CString(), priority);
|
||||
|
||||
cityMesh->RebuildNamedAreas();
|
||||
}
|
||||
|
@ -534,7 +534,7 @@ void Map::remove_flag(const std::shared_ptr<Flag> &flag)
|
||||
flags.erase(flag->id);
|
||||
}
|
||||
|
||||
void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const std::string &name, uint32_t priority)
|
||||
void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t terrain_feature, const std::string &name, uint32_t priority)
|
||||
{
|
||||
if (priority == 0)
|
||||
priority = ++highest_place_priority;
|
||||
@ -549,6 +549,7 @@ void Map::add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer,
|
||||
place->y0 = y0;
|
||||
place->x1 = x1;
|
||||
place->y1 = y1;
|
||||
place->terrain_feature = terrain_feature;
|
||||
place->name = name;
|
||||
place->priority = priority;
|
||||
qplaces.insert(place);
|
||||
|
@ -215,7 +215,7 @@ public:
|
||||
void set_flag_palette(uint32_t id, const std::vector<uint16_t> &new_palette);
|
||||
void resize_flag(const std::shared_ptr<Flag> &flag, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const uint8_t potential[NUM_POTENTIALS], uint16_t base_height, uint32_t elevation_bonus, uint32_t average_slope, int32_t average_slope_modifier, uint32_t south_facing, uint32_t bridge_score, const uint32_t underwater_area[2]);
|
||||
void remove_flag(const std::shared_ptr<Flag> &flag);
|
||||
void add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const std::string &name, uint32_t priority);
|
||||
void add_place(uint64_t id, uint64_t height, uint32_t city, uint32_t namer, uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint32_t terrain_feature, const std::string &name, uint32_t priority);
|
||||
void get_places(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, std::set<std::shared_ptr<cc::place_t>> &res) const;
|
||||
void get_all_places(std::set<std::shared_ptr<cc::place_t>> &res) const;
|
||||
bool get_place(uint32_t x, uint32_t y, std::string &name, const std::function<bool(uint32_t)> &allow_namer = NULL) const;
|
||||
|
@ -22,6 +22,7 @@ static const char *text[] =
|
||||
"Influences",
|
||||
"Bridge score",
|
||||
"Underwater area",
|
||||
"Terrain feature",
|
||||
};
|
||||
|
||||
const char *get_selection_info_text(selection_info_t si)
|
||||
|
@ -22,6 +22,7 @@ enum selection_info_t
|
||||
selection_info_influences,
|
||||
selection_info_bridge_score,
|
||||
selection_info_underwater_area,
|
||||
selection_info_terrain_feature,
|
||||
num_selection_info
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "cryptonote_config.h"
|
||||
#include "cc/cc_config.h"
|
||||
#include "cc/cc.h"
|
||||
#include "cc/cc_terrain_features.h"
|
||||
#include "UTBRendererBatcher.h"
|
||||
#include "game-util.h"
|
||||
#include "game-state.h"
|
||||
@ -32,6 +33,11 @@ UINamePlaceDialog::UINamePlaceDialog(Context *ctx, const GameState *game, uint32
|
||||
nameWidget = GetWidgetByIDAndType<TBEditField>(TBIDC("name"));
|
||||
runestonesNeededWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("runestones-needed"));
|
||||
runestonesOwnedWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("runestones-owned"));
|
||||
terrainFeatureWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("terrain-feature"));
|
||||
|
||||
std::shared_ptr<cc::cc_potential_state_t> state = cc::get_cc_potential_state(game->cityState.id, game->cityState.seed);
|
||||
const cc::terrain_feature_t feature = cc::classify_terrain_feature(state, x0, y0, x1, y1);
|
||||
terrainFeatureWidget->SetText(cc::terrain_feature_names[feature]);
|
||||
|
||||
SubscribeToEvent(this, E_TB_WIDGET_EVENT, URHO3D_HANDLER(UINamePlaceDialog, HandleTBMessage));
|
||||
SubscribeToEvent(this, E_TB_WINDOW_CLOSED, URHO3D_HANDLER(UINamePlaceDialog, HandleClose));
|
||||
@ -73,6 +79,18 @@ void UINamePlaceDialog::HandleNameChanged(StringHash eventType, VariantMap& even
|
||||
refresh = true;
|
||||
}
|
||||
|
||||
void UINamePlaceDialog::HandleHelp(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
new MessageBox(context_,
|
||||
"Terrain features are automatically detected, and so have particular rules.\n"
|
||||
"While most are obvious from the name, some rules need spelling out:\n"
|
||||
" - islands MUST have the entirety of their edge be water - no exception\n"
|
||||
" - lakes MUST have the entirety of their edge be on land - no exception\n"
|
||||
" - the entire 10% outer bands inside the area around a peak must be substantially lower than the peak itself\n",
|
||||
"Info"
|
||||
);
|
||||
}
|
||||
|
||||
void UINamePlaceDialog::HandleCancel(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
VariantMap& newEventData = GetEventDataMap();
|
||||
@ -117,6 +135,7 @@ void UINamePlaceDialog::HandleTBMessage(StringHash eventType, VariantMap& eventD
|
||||
TBWidgetEvent *ev = (TBWidgetEvent*)eventData[P_WIDGET_EVENT].GetVoidPtr();
|
||||
if (ev->type == EVENT_TYPE_CLICK)
|
||||
{
|
||||
CONNECT("help", HandleHelp);
|
||||
CONNECT("ok", HandleOK);
|
||||
CONNECT("cancel", HandleCancel);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
|
||||
private:
|
||||
void HandleNameChanged(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleHelp(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleOK(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleCancel(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
void HandleTBMessage(Urho3D::StringHash eventType, Urho3D::VariantMap& eventData);
|
||||
@ -55,6 +56,7 @@ private:
|
||||
tb::TBEditField *nameWidget;
|
||||
tb::TBTextField *runestonesNeededWidget;
|
||||
tb::TBTextField *runestonesOwnedWidget;
|
||||
tb::TBTextField *terrainFeatureWidget;
|
||||
|
||||
std::string last_refresh_stop_hash;
|
||||
bool refresh;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <tb/tb_font_renderer.h>
|
||||
#include "cc/cc.h"
|
||||
#include "cc/cc_influence.h"
|
||||
#include "cc/cc_terrain_features.h"
|
||||
#include "rpc/core_rpc_server_commands_defs.h"
|
||||
#include "game-wallet.h"
|
||||
#include "game-state.h"
|
||||
@ -30,8 +31,55 @@ UITravelToPlaceDialog::PlaceWidget::PlaceWidget(PlaceItem *item, PlaceSource *so
|
||||
|
||||
g_widgets_reader->LoadFile(GetContentRoot(), "cc/travel-to-place-row.tb.txt");
|
||||
|
||||
const tb::TBFontDescription fd = g_font_manager->GetDefaultFontDescription();
|
||||
|
||||
TBTextField *nameWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("name"));
|
||||
nameWidget->SetText(item->place->name);
|
||||
tb::TBFontDescription fd_large = fd;
|
||||
fd_large.SetSize(fd.GetSize() * 4 / 3);
|
||||
nameWidget->SetFontDescription(fd_large);
|
||||
|
||||
if (item->place->terrain_feature != cc::terrain_feature_none)
|
||||
{
|
||||
TBToggleContainer *featureContainer = GetWidgetByIDAndType<TBToggleContainer>(TBIDC("feature-container"));
|
||||
featureContainer->SetValue(1);
|
||||
TBTextField *featureWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("feature"));
|
||||
featureWidget->SetText(cc::terrain_feature_names[item->place->terrain_feature]);
|
||||
}
|
||||
|
||||
TBTextField *distanceWidget = GetWidgetByIDAndType<TBTextField>(TBIDC("distance"));
|
||||
uint32_t distance = cc::get_distance(item->place->x0, item->place->y0, item->place->x1, item->place->y1, item->x, item->y);
|
||||
std::string s;
|
||||
if (distance < 5)
|
||||
{
|
||||
s = "right here";
|
||||
}
|
||||
else
|
||||
{
|
||||
s = std::to_string(distance) + " feet away ";
|
||||
const uint32_t midx = item->place->x0 + (item->place->x1 - item->place->x0) / 2;
|
||||
const uint32_t midy = item->place->y0 + (item->place->y1 - item->place->y0) / 2;
|
||||
float angle = 180.0f * atan2f((int32_t)(midy - item->y), (int32_t)(midx - item->x)) / M_PI;
|
||||
if (fabsf(angle) < 11.25f)
|
||||
s += "E";
|
||||
else if (fabsf(angle) < 33.75f)
|
||||
s += angle > 0.0f ? "WNE" : "WSE";
|
||||
else if (fabsf(angle) < 56.25f)
|
||||
s += angle > 0.0f ? "NE" : "SE";
|
||||
else if (fabsf(angle) < 78.75f)
|
||||
s += angle > 0.0f ? "NNE" : "SSE";
|
||||
else if (fabsf(angle) < 101.25f)
|
||||
s += "N";
|
||||
else if (fabsf(angle) < 123.75f)
|
||||
s += angle > 0.0f ? "NNW" : "SSW";
|
||||
else if (fabsf(angle) < 146.25f)
|
||||
s += angle > 0.0f ? "NW" : "SW";
|
||||
else if (fabsf(angle) < 168.75f)
|
||||
s += angle > 0.0f ? "WNW" : "WSW";
|
||||
else
|
||||
s += "W";
|
||||
}
|
||||
distanceWidget->SetText(s.c_str());
|
||||
}
|
||||
|
||||
WIDGET_HIT_STATUS UITravelToPlaceDialog::PlaceWidget::GetHitStatus(int x, int y)
|
||||
@ -39,9 +87,11 @@ WIDGET_HIT_STATUS UITravelToPlaceDialog::PlaceWidget::GetHitStatus(int x, int y)
|
||||
return x >= 0 && y >= 0 && x < GetRect().w && y < GetRect().h ? tb::WIDGET_HIT_STATUS_HIT_NO_CHILDREN : tb::WIDGET_HIT_STATUS_NO_HIT;
|
||||
}
|
||||
|
||||
UITravelToPlaceDialog::PlaceItem::PlaceItem(const std::shared_ptr<cc::place_t> &place):
|
||||
UITravelToPlaceDialog::PlaceItem::PlaceItem(const std::shared_ptr<cc::place_t> &place, uint32_t x, uint32_t y):
|
||||
TBGenericStringItem(place->name),
|
||||
place(place)
|
||||
place(place),
|
||||
x(x),
|
||||
y(y)
|
||||
{
|
||||
}
|
||||
|
||||
@ -132,7 +182,7 @@ void UITravelToPlaceDialog::UpdatePlacesList(const std::shared_ptr<GameWallet> &
|
||||
{
|
||||
if (game->ignore_player(e->namer))
|
||||
continue;
|
||||
PlaceItem *item = new PlaceItem(e);
|
||||
PlaceItem *item = new PlaceItem(e, x, y);
|
||||
item->tag.SetInt(e->id);
|
||||
if (e->id == select_place_id)
|
||||
sel = builder.GetNumItems();
|
||||
|
@ -48,10 +48,12 @@ private:
|
||||
class PlaceItem: public tb::TBGenericStringItem
|
||||
{
|
||||
public:
|
||||
PlaceItem(const std::shared_ptr<cc::place_t> &place);
|
||||
PlaceItem(const std::shared_ptr<cc::place_t> &place, uint32_t x, uint32_t y);
|
||||
std::shared_ptr<cc::place_t> place;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
bool operator==(const PlaceItem &item) const { return place == item.place; }
|
||||
bool operator==(const PlaceItem &item) const { return place == item.place && x == item.x && y == item.y; }
|
||||
};
|
||||
|
||||
class PlaceSource: public tb::TBSelectItemSourceList<PlaceItem>
|
||||
|
@ -4388,7 +4388,7 @@ namespace cryptonote
|
||||
return true;
|
||||
});
|
||||
db.for_all_cc_places(city, [&snapshot](const cc::place_t &p) {
|
||||
snapshot.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.name, p.priority});
|
||||
snapshot.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, p.name, p.priority});
|
||||
return true;
|
||||
});
|
||||
|
||||
@ -6407,7 +6407,7 @@ namespace cryptonote
|
||||
if (!db.for_all_cc_places(req.city, [&req, &res](const cc::place_t &p) {
|
||||
uint32_t ix0, iy0, ix1, iy1;
|
||||
if (cc::intersection(p.x0, p.y0, p.x1, p.y1, req.x0, req.y0, req.x1, req.y1, ix0, iy0, ix1, iy1))
|
||||
res.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.name, p.priority});
|
||||
res.places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, p.name, p.priority});
|
||||
return true;
|
||||
}))
|
||||
{
|
||||
|
@ -5667,6 +5667,7 @@ namespace cryptonote
|
||||
uint32_t y0;
|
||||
uint32_t x1;
|
||||
uint32_t y1;
|
||||
uint32_t terrain_feature;
|
||||
std::string name;
|
||||
uint32_t priority;
|
||||
|
||||
@ -5679,6 +5680,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(y0)
|
||||
KV_SERIALIZE(x1)
|
||||
KV_SERIALIZE(y1)
|
||||
KV_SERIALIZE(terrain_feature)
|
||||
KV_SERIALIZE(name)
|
||||
KV_SERIALIZE(priority)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
@ -1390,7 +1390,7 @@ bool wallet2::get_cc_places(uint32_t city, uint32_t x0, uint32_t y0, uint32_t x1
|
||||
places.reserve(res.places.size());
|
||||
for (auto &p: res.places)
|
||||
{
|
||||
places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, std::move(p.name)});
|
||||
places.push_back({p.id, p.height, p.city, p.namer, p.x0, p.y0, p.x1, p.y1, p.terrain_feature, std::move(p.name)});
|
||||
}
|
||||
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user