forked from townforge/townforge
some material variants are now locked till a player level
This commit is contained in:
parent
734511b2df
commit
5b693a15b1
7
GameData/TB/cc/locked-material.tb.txt
Normal file
7
GameData/TB/cc/locked-material.tb.txt
Normal file
@ -0,0 +1,7 @@
|
||||
WindowInfo
|
||||
|
||||
TBLayout: axis: y, ignore-input: 1, size: "available"
|
||||
TBTextField: text: "LOCKED", skin: "locked"
|
||||
TBLayout: axis: x
|
||||
TBTextField: text: "till level"
|
||||
TBTextField: id: "level"
|
@ -102,3 +102,6 @@ elements
|
||||
|
||||
trade-cancel-button
|
||||
text-color #cf3f3f
|
||||
|
||||
locked
|
||||
text-color #cf3f3f
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "cc.h"
|
||||
#include "cc_palette.h"
|
||||
#include "cc_badge.h"
|
||||
#include "cc_command_handler_palette.h"
|
||||
#include "cc_command_handler_build.h"
|
||||
|
||||
@ -129,6 +130,7 @@ bool cc_command_handler_build::check(const cryptonote::BlockchainDB &db, const c
|
||||
}
|
||||
CHECK_COMMAND_SET(cc::palette_to_item(palette, decoded, decoded_len, items), tvc.m_cc_bad_palette_data, "Failed to apply palette");
|
||||
|
||||
uint8_t palette_index_needed[256] = { 0 };
|
||||
std::map<uint32_t, uint32_t> items_needed;
|
||||
unsigned int idx = 0;
|
||||
for (uint32_t y = ay0; y <= ay1; ++y)
|
||||
@ -163,12 +165,28 @@ bool cc_command_handler_build::check(const cryptonote::BlockchainDB &db, const c
|
||||
items_needed[ITEM_LABOUR] += labour;
|
||||
CHECK_COMMAND_SET(items_needed[items[idx]] < std::numeric_limits<uint32_t>::max(), tvc.m_cc_overflow, "Item overflow");
|
||||
++items_needed[items[idx]];
|
||||
palette_index_needed[decoded[idx]] = 1;
|
||||
}
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
|
||||
// check unlock state
|
||||
cryptonote::cc_account_data_t ad;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_account_data(build.cc_account, ad), false, "Failed to get account data");
|
||||
const auto score_level = cc::get_badge_score(ad.badges);
|
||||
const uint32_t level = score_level.second;
|
||||
for (size_t i = 1; i < 256; ++i)
|
||||
{
|
||||
if (palette_index_needed[i])
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(i < palette.size(), false, "Palette index out of range");
|
||||
const cc::block_variant_t variant = cc::get_block_variant(palette[i]);
|
||||
CHECK_COMMAND_SET(level >= variant.unlock_level, tvc.m_cc_locked, "Using material which is not unlocked yet");
|
||||
}
|
||||
}
|
||||
|
||||
// check block balances
|
||||
const uint64_t blockchain_height = db.height();
|
||||
for (const auto &e: items_needed)
|
||||
|
@ -12,44 +12,44 @@ static const struct block_variant_t block_variants[] =
|
||||
{
|
||||
{}, // none
|
||||
|
||||
{ BLOCK_VARIANT_SANDSTONE_BASIC, ITEM_SANDSTONE, "Sandstone" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_COBBLESTONES, ITEM_SANDSTONE, "Sandstone cobblestones" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_DARK, ITEM_SANDSTONE, "Dark sandstone" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_BLOCKS, ITEM_SANDSTONE, "Sandstone blocks" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_LIGHT_1, ITEM_SANDSTONE, "Light sandstone blocks, style 1" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_LIGHT_2, ITEM_SANDSTONE, "Light sandstone blocks, style 2" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_WALL, ITEM_SANDSTONE, "Sandstone wall" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_BASIC, ITEM_SANDSTONE, 0, "Sandstone" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_COBBLESTONES, ITEM_SANDSTONE, 0, "Sandstone cobblestones" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_DARK, ITEM_SANDSTONE, 0, "Dark sandstone" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_BLOCKS, ITEM_SANDSTONE, 0, "Sandstone blocks" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_LIGHT_1, ITEM_SANDSTONE, 5, "Light sandstone blocks, style 1" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_LIGHT_2, ITEM_SANDSTONE, 5, "Light sandstone blocks, style 2" },
|
||||
{ BLOCK_VARIANT_SANDSTONE_WALL, ITEM_SANDSTONE, 5, "Sandstone wall" },
|
||||
|
||||
{ BLOCK_VARIANT_GRANITE_BASIC, ITEM_GRANITE, "Granite" },
|
||||
{ BLOCK_VARIANT_GRANITE_COBBLESTONES, ITEM_GRANITE, "Granite cobblestones " },
|
||||
{ BLOCK_VARIANT_GRANITE_MID_DARK, ITEM_GRANITE, "Mid dark granite" },
|
||||
{ BLOCK_VARIANT_GRANITE_DARK, ITEM_GRANITE, "Dark granite" },
|
||||
{ BLOCK_VARIANT_GRANITE_BASIC, ITEM_GRANITE, 0, "Granite" },
|
||||
{ BLOCK_VARIANT_GRANITE_COBBLESTONES, ITEM_GRANITE, 0, "Granite cobblestones " },
|
||||
{ BLOCK_VARIANT_GRANITE_MID_DARK, ITEM_GRANITE, 0, "Mid dark granite" },
|
||||
{ BLOCK_VARIANT_GRANITE_DARK, ITEM_GRANITE, 5, "Dark granite" },
|
||||
|
||||
{ BLOCK_VARIANT_MARBLE_BASIC, ITEM_MARBLE, "Marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_GREY, ITEM_MARBLE, "Grey marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_RED, ITEM_MARBLE, "Red marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_BLUE, ITEM_MARBLE, "Blue marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_BASIC, ITEM_MARBLE, 0, "Marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_GREY, ITEM_MARBLE, 0, "Grey marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_RED, ITEM_MARBLE, 5, "Red marble" },
|
||||
{ BLOCK_VARIANT_MARBLE_BLUE, ITEM_MARBLE, 5, "Blue marble" },
|
||||
|
||||
{ BLOCK_VARIANT_PINE_BASIC, ITEM_PINE, "Pine" },
|
||||
{ BLOCK_VARIANT_PINE_BROWN, ITEM_PINE, "Brown pine" },
|
||||
{ BLOCK_VARIANT_PINE_RED, ITEM_PINE, "Red pine" },
|
||||
{ BLOCK_VARIANT_PINE_DARK, ITEM_PINE, "Dark pine" },
|
||||
{ BLOCK_VARIANT_PINE_YELLOWISH, ITEM_PINE, "Yellowish pine" },
|
||||
{ BLOCK_VARIANT_PINE_BLUISH, ITEM_PINE, "Bluish pine" },
|
||||
{ BLOCK_VARIANT_PINE_DARK_BROWN, ITEM_PINE, "Dark brown pine" },
|
||||
{ BLOCK_VARIANT_PINE_2, ITEM_PINE, "Pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_DARK, ITEM_PINE, "Dark pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_LIGHT_BROWN, ITEM_PINE, "Light brown pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_GREENISH, ITEM_PINE, "Greenish pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_BASIC, ITEM_PINE, 0, "Pine" },
|
||||
{ BLOCK_VARIANT_PINE_BROWN, ITEM_PINE, 0, "Brown pine" },
|
||||
{ BLOCK_VARIANT_PINE_RED, ITEM_PINE, 0, "Red pine" },
|
||||
{ BLOCK_VARIANT_PINE_DARK, ITEM_PINE, 5, "Dark pine" },
|
||||
{ BLOCK_VARIANT_PINE_YELLOWISH, ITEM_PINE, 5, "Yellowish pine" },
|
||||
{ BLOCK_VARIANT_PINE_BLUISH, ITEM_PINE, 10, "Bluish pine" },
|
||||
{ BLOCK_VARIANT_PINE_DARK_BROWN, ITEM_PINE, 10, "Dark brown pine" },
|
||||
{ BLOCK_VARIANT_PINE_2, ITEM_PINE, 10, "Pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_DARK, ITEM_PINE, 10, "Dark pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_LIGHT_BROWN, ITEM_PINE, 15, "Light brown pine planks, vertical" },
|
||||
{ BLOCK_VARIANT_PINE_2_GREENISH, ITEM_PINE, 15, "Greenish pine planks, vertical" },
|
||||
|
||||
{ BLOCK_VARIANT_OAK_BASIC, ITEM_OAK, "Oak" },
|
||||
{ BLOCK_VARIANT_OAK_BASIC, ITEM_OAK, 0, "Oak" },
|
||||
|
||||
{ BLOCK_VARIANT_TEAK_BASIC, ITEM_TEAK, "Teak" },
|
||||
{ BLOCK_VARIANT_TEAK_BASIC, ITEM_TEAK, 0, "Teak" },
|
||||
|
||||
{ BLOCK_VARIANT_VEGETATION_TEST1, ITEM_VEGETATION, "Vegetation test 1" },
|
||||
{ BLOCK_VARIANT_VEGETATION_TEST2, ITEM_VEGETATION, "Vegetation test 2" },
|
||||
{ BLOCK_VARIANT_VEGETATION_BARK1, ITEM_VEGETATION, "Bark 1" },
|
||||
{ BLOCK_VARIANT_VEGETATION_PLOUGHED_FIELD, ITEM_VEGETATION, "Ploughed field" },
|
||||
{ BLOCK_VARIANT_VEGETATION_TEST1, ITEM_VEGETATION, 0, "Vegetation test 1" },
|
||||
{ BLOCK_VARIANT_VEGETATION_TEST2, ITEM_VEGETATION, 0, "Vegetation test 2" },
|
||||
{ BLOCK_VARIANT_VEGETATION_BARK1, ITEM_VEGETATION, 0, "Bark 1" },
|
||||
{ BLOCK_VARIANT_VEGETATION_PLOUGHED_FIELD, ITEM_VEGETATION, 0, "Ploughed field" },
|
||||
};
|
||||
|
||||
namespace cc
|
||||
|
@ -57,6 +57,7 @@ struct block_variant_t
|
||||
{
|
||||
uint16_t variant;
|
||||
uint8_t item;
|
||||
uint8_t unlock_level;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
|
@ -92,6 +92,7 @@ namespace cryptonote
|
||||
bool m_cc_palette_in_use;
|
||||
bool m_cc_level;
|
||||
bool m_cc_invalid_signature;
|
||||
bool m_cc_locked;
|
||||
};
|
||||
|
||||
struct block_verification_context
|
||||
|
@ -3,10 +3,13 @@
|
||||
#include <Urho3D/Core/Context.h>
|
||||
#include <Urho3D/Graphics/Material.h>
|
||||
#include <tb/tb_widgets_common.h>
|
||||
#include <tb/tb_widgets_reader.h>
|
||||
#include <tb/image/tb_image_widget.h>
|
||||
#include <tb/animation/tb_widget_animation.h>
|
||||
#include "cc/cc_palette.h"
|
||||
#include "cc/cc_badge.h"
|
||||
#include "material-style.h"
|
||||
#include "game-state.h"
|
||||
#include "UTBRendererBatcher.h"
|
||||
#include "ui-tb-animated-image-widget.h"
|
||||
#include "ui-select-material.h"
|
||||
@ -92,16 +95,23 @@ UISelectMaterial::~UISelectMaterial()
|
||||
{
|
||||
}
|
||||
|
||||
void UISelectMaterial::Init(uint16_t variant)
|
||||
void UISelectMaterial::Init(const GameState *game, uint16_t variant)
|
||||
{
|
||||
selected = variant;
|
||||
UpdateMaterials();
|
||||
UpdateMaterials(game);
|
||||
SetFocus(WIDGET_FOCUS_REASON_UNKNOWN);
|
||||
}
|
||||
|
||||
void UISelectMaterial::UpdateMaterials()
|
||||
void UISelectMaterial::UpdateMaterials(const GameState *game)
|
||||
{
|
||||
for (auto &e: materials) for (auto &v: e) v.sprite->RemoveFromParent();
|
||||
for (auto &e: materials)
|
||||
{
|
||||
for (auto &v: e)
|
||||
{
|
||||
v.sprite->RemoveFromParent();
|
||||
v.locked_layout->RemoveFromParent();
|
||||
}
|
||||
}
|
||||
materials.clear();
|
||||
|
||||
VariantMap eventData;
|
||||
@ -109,6 +119,8 @@ void UISelectMaterial::UpdateMaterials()
|
||||
eventData[SelectMaterialGetTextures::P_TEXTURES] = (void*)&textures;
|
||||
SendEvent(E_SELECT_MATERIAL_GET_TEXTURES, eventData);
|
||||
|
||||
const uint32_t level = cc::get_badge_score(game->playerState.badges).second;
|
||||
|
||||
materials.resize(256);
|
||||
for (const auto &e: textures)
|
||||
{
|
||||
@ -124,7 +136,16 @@ void UISelectMaterial::UpdateMaterials()
|
||||
sprite->SetSize(SPRITE_SIZE, SPRITE_SIZE);
|
||||
sprite->SetPosition({0, 0});
|
||||
GetContentRoot()->AddChild(sprite);
|
||||
materials[e.first].push_back({cc::get_block_variant(v.first), sprite});
|
||||
TBLayout *locked_layout = new TBLayout();
|
||||
if (!g_widgets_reader->LoadFile(locked_layout, "cc/locked-material.tb.txt"))
|
||||
printf("Resource not found: %s\n", "cc/locked-material.tb.txt");
|
||||
const cc::block_variant_t block_variant = cc::get_block_variant(v.first);
|
||||
const bool locked = block_variant.unlock_level > level;
|
||||
TBTextField *levelWidget = locked_layout->GetWidgetByIDAndType<TBTextField>(TBIDC("level"));
|
||||
levelWidget->SetText(std::to_string(block_variant.unlock_level).c_str());
|
||||
locked_layout->SetVisibility(locked ? WIDGET_VISIBILITY_VISIBLE : WIDGET_VISIBILITY_INVISIBLE);
|
||||
GetContentRoot()->AddChild(locked_layout);
|
||||
materials[e.first].push_back({block_variant, sprite, locked_layout});
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,23 +202,35 @@ void UISelectMaterial::UpdateWidgets()
|
||||
}
|
||||
|
||||
TBWidgetsAnimationManager::AbortAnimations(materials[i][j].sprite);
|
||||
TBWidgetsAnimationManager::AbortAnimations(materials[i][j].locked_layout);
|
||||
if (std::abs(new_rect.x - old_rect.x) >= SPRITE_SIZE * 3 / 2 || std::abs(new_rect.y - old_rect.y) >= SPRITE_SIZE * 3 / 2)
|
||||
{
|
||||
// move to the other side, a bit further away
|
||||
const int dx = x - old_rect.x, dy = y - old_rect.y;
|
||||
old_rect.x = new_rect.x + dx;
|
||||
old_rect.y = new_rect.y + dy;
|
||||
materials[i][j].locked_layout->SetRect(old_rect);
|
||||
materials[i][j].locked_layout->SetZ(WIDGET_Z_BOTTOM);
|
||||
materials[i][j].sprite->SetRect(old_rect);
|
||||
materials[i][j].sprite->SetZ(WIDGET_Z_BOTTOM);
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
materials[i][j].sprite->SetRect(new_rect);
|
||||
else if (TBAnimationObject *anim = new TBWidgetAnimationRect(materials[i][j].sprite, old_rect, new_rect))
|
||||
TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_SLOW_DOWN, 200);
|
||||
materials[i][j].locked_layout->SetRect(new_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TBAnimationObject *anim = new TBWidgetAnimationRect(materials[i][j].sprite, old_rect, new_rect))
|
||||
TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_SLOW_DOWN, 200);
|
||||
if (TBAnimationObject *anim = new TBWidgetAnimationRect(materials[i][j].locked_layout, old_rect, new_rect))
|
||||
TBAnimationManager::StartAnimation(anim, ANIMATION_CURVE_SLOW_DOWN, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
materials[seli][selj].sprite->SetZ(WIDGET_Z_TOP);
|
||||
materials[seli][selj].locked_layout->SetZ(WIDGET_Z_TOP);
|
||||
TBStr str = materials[seli][selj].block_variant.name;
|
||||
str.Append(".");
|
||||
material_name->SetText(str);
|
||||
@ -296,7 +329,7 @@ void UISelectMaterial::Pick()
|
||||
{
|
||||
for (size_t j = 0; j < materials[i].size(); ++j)
|
||||
{
|
||||
if (TBWidget::hovered_widget == materials[i][j].sprite)
|
||||
if (TBWidget::hovered_widget == materials[i][j].sprite || TBWidget::hovered_widget == materials[i][j].locked_layout)
|
||||
{
|
||||
selected = materials[i][j].block_variant.variant;
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
URHO3D_EVENT(E_SELECT_MATERIAL_GET_TEXTURES, SelectMaterialGetTextures) { URHO3D_PARAM(P_TEXTURES, Textures); }
|
||||
URHO3D_EVENT(E_SELECT_MATERIAL_CLOSED, SelectMaterialClosed) { URHO3D_PARAM(P_VARIANT, Variant); }
|
||||
|
||||
class GameState;
|
||||
|
||||
namespace Urho3D
|
||||
{
|
||||
class Context;
|
||||
@ -26,7 +28,7 @@ public:
|
||||
UISelectMaterial(Urho3D::Context *ctx);
|
||||
virtual ~UISelectMaterial();
|
||||
|
||||
void Init(uint16_t variant);
|
||||
void Init(const GameState *game, uint16_t variant);
|
||||
|
||||
void CancelUI();
|
||||
|
||||
@ -44,13 +46,14 @@ private:
|
||||
bool EnsureSelection();
|
||||
bool FindSelection(size_t &i, size_t &j);
|
||||
void UpdateWidgets();
|
||||
void UpdateMaterials();
|
||||
void UpdateMaterials(const GameState *game);
|
||||
|
||||
private:
|
||||
struct material_slot_t
|
||||
{
|
||||
cc::block_variant_t block_variant;
|
||||
UIMaterialWidget *sprite;
|
||||
tb::TBLayout *locked_layout;
|
||||
};
|
||||
|
||||
bool reset;
|
||||
|
@ -2300,7 +2300,7 @@ void UIUrho3D::OpenSelectMaterial(uint16_t variant)
|
||||
SendEvent(E_CRYPTOCITY_VARIANT_SELECTED, newEventData);
|
||||
selectMaterial = NULL;
|
||||
});
|
||||
selectMaterial->Init(variant);
|
||||
selectMaterial->Init(gameState, variant);
|
||||
}
|
||||
|
||||
void UIUrho3D::CloseSelectMaterial(bool send_result)
|
||||
|
@ -1281,6 +1281,8 @@ namespace cryptonote
|
||||
add_reason(reason, "level too low");
|
||||
if ((res.cc_invalid_signature = tvc.m_cc_invalid_signature))
|
||||
add_reason(reason, "invalid signature");
|
||||
if ((res.cc_locked = tvc.m_cc_locked))
|
||||
add_reason(reason, "feature not unlocked yet");
|
||||
|
||||
const std::string punctuation = reason.empty() ? "" : ": ";
|
||||
if (tvc.m_verifivation_failed)
|
||||
|
@ -639,6 +639,7 @@ namespace cryptonote
|
||||
bool cc_palette_in_use;
|
||||
bool cc_level;
|
||||
bool cc_invalid_signature;
|
||||
bool cc_locked;
|
||||
|
||||
bool untrusted;
|
||||
|
||||
@ -693,6 +694,7 @@ namespace cryptonote
|
||||
KV_SERIALIZE(cc_palette_in_use)
|
||||
KV_SERIALIZE(cc_level)
|
||||
KV_SERIALIZE(cc_invalid_signature)
|
||||
KV_SERIALIZE(cc_locked)
|
||||
|
||||
KV_SERIALIZE(untrusted)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
|
@ -45,6 +45,7 @@ ITEM_STONE = 1
|
||||
ITEM_MEDIUM_STONE = 2
|
||||
ITEM_WOOD = 4
|
||||
MATERIAL_VARIANT_PLOUGHED_FIELD = 32
|
||||
MATERIAL_LOCKED_PINE = 26
|
||||
ITEM_LABOUR = 256
|
||||
ITEM_FIRST_PATENT = 1024
|
||||
ITEM_FIRST_FOOD = ITEM_FIRST_PATENT + 4096
|
||||
@ -773,6 +774,9 @@ class CCTest():
|
||||
assert 'data' not in res.tiles[271] or res.tiles[271].data == []
|
||||
assert res.tiles[272].data == [9]
|
||||
|
||||
# locked materials
|
||||
assert_exception(lambda self: self.wallet[2].cc_build(flag_id, 0, 3, 3, 1, block_data = [10, 0, 10], encoded = False, palette = [{'index': 10, 'variant_delta': MATERIAL_LOCKED_PINE}]))
|
||||
|
||||
def test_trading(self):
|
||||
daemon = self.daemon
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user