1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #3372 from IvanSavenko/bugfixing

[1.4.2] Bugfixing
This commit is contained in:
Ivan Savenko 2023-12-23 22:05:39 +02:00 committed by GitHub
commit 08a4b67cd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 100 additions and 43 deletions

View File

@ -239,6 +239,8 @@ void PlayerLocalState::swapWanderingHero(int pos1, int pos2)
{
assert(wanderingHeroes[pos1] && wanderingHeroes[pos2]);
std::swap(wanderingHeroes[pos1], wanderingHeroes[pos2]);
adventureInt->onHeroOrderChanged();
}
const std::vector<const CGTownInstance *> & PlayerLocalState::getOwnedTowns()

View File

@ -331,6 +331,11 @@ void AdventureMapInterface::onTownOrderChanged()
widget->getTownList()->updateWidget();
}
void AdventureMapInterface::onHeroOrderChanged()
{
widget->getHeroList()->updateWidget();
}
void AdventureMapInterface::onMapTilesChanged(boost::optional<std::unordered_set<int3>> positions)
{
if (positions)

View File

@ -149,6 +149,9 @@ public:
/// Called when town order changes
void onTownOrderChanged();
/// Called when hero order changes
void onHeroOrderChanged();
/// Called when map audio should be paused, e.g. on combat or town screen access
void onAudioPaused();

View File

@ -273,17 +273,15 @@ void CBonusSelection::createBonusesIcons()
}
case CampaignBonusType::HERO:
desc.appendLocalString(EMetaText::GENERAL_TXT, 718);
desc.replaceTextID(TextIdentifier("core", "genrltxt", "capColors", bonDescs[i].info1).get());
if(bonDescs[i].info2 == 0xFFFF)
{
desc.replaceLocalString(EMetaText::GENERAL_TXT, 101);
desc.appendLocalString(EMetaText::GENERAL_TXT, 720); // Start with random hero
picNumber = -1;
picName = "CBONN1A3.BMP";
}
else
{
desc.appendLocalString(EMetaText::GENERAL_TXT, 715); // Start with %s
desc.replaceTextID(CGI->heroh->objects[bonDescs[i].info2]->getNameTextID());
}
break;

View File

@ -135,7 +135,7 @@ InfoCard::InfoCard()
Rect descriptionRect(26, 149, 320, 115);
mapDescription = std::make_shared<CTextBox>("", descriptionRect, 1);
playerListBg = std::make_shared<CPicture>(ImagePath::builtin("CHATPLUG.bmp"), 16, 276);
chat = std::make_shared<CChatBox>(Rect(26, 132, 340, 132));
chat = std::make_shared<CChatBox>(Rect(18, 126, 335, 143));
if(SEL->screenType == ESelectionScreen::campaignList)
{
@ -332,9 +332,12 @@ CChatBox::CChatBox(const Rect & rect)
setRedrawParent(true);
const int height = static_cast<int>(graphics->fonts[FONT_SMALL]->getLineHeight());
inputBox = std::make_shared<CTextInput>(Rect(0, rect.h - height, rect.w, height), EFonts::FONT_SMALL, 0);
Rect textInputArea(1, rect.h - height, rect.w - 1, height);
Rect chatHistoryArea(3, 1, rect.w - 3, rect.h - height - 1);
inputBackground = std::make_shared<TransparentFilledRectangle>(textInputArea, ColorRGBA(0,0,0,192));
inputBox = std::make_shared<CTextInput>(textInputArea, EFonts::FONT_SMALL, 0);
inputBox->removeUsedEvents(KEYBOARD);
chatHistory = std::make_shared<CTextBox>("", Rect(0, 0, rect.w, rect.h - height), 1);
chatHistory = std::make_shared<CTextBox>("", chatHistoryArea, 1);
chatHistory->label->color = Colors::GREEN;
}

View File

@ -33,6 +33,7 @@ class CChatBox;
class CLabel;
class CFlagBox;
class CLabelGroup;
class TransparentFilledRectangle;
class ISelectionScreenInfo
{
@ -122,6 +123,7 @@ class CChatBox : public CIntObject
public:
std::shared_ptr<CTextBox> chatHistory;
std::shared_ptr<CTextInput> inputBox;
std::shared_ptr<TransparentFilledRectangle> inputBackground;
CChatBox(const Rect & rect);

View File

@ -375,7 +375,7 @@ void CTextBox::setText(const std::string & text)
else if(slider)
{
// decrease width again if slider still used
label->pos.w = pos.w - 32;
label->pos.w = pos.w - 16;
assert(label->pos.w > 0);
label->setText(text);
slider->setAmount(label->textSize.y);
@ -383,12 +383,12 @@ void CTextBox::setText(const std::string & text)
else if(label->textSize.y > label->pos.h)
{
// create slider and update widget
label->pos.w = pos.w - 32;
label->pos.w = pos.w - 16;
assert(label->pos.w > 0);
label->setText(text);
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
slider = std::make_shared<CSlider>(Point(pos.w - 32, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1),
slider = std::make_shared<CSlider>(Point(pos.w - 16, 0), pos.h, std::bind(&CTextBox::sliderMoved, this, _1),
label->pos.h, label->textSize.y, 0, Orientation::VERTICAL, CSlider::EStyle(sliderStyle));
slider->setScrollStep((int)graphics->fonts[label->font]->getLineHeight());
slider->setPanningStep(1);

View File

@ -310,63 +310,73 @@ JsonMap & JsonNode::Struct()
const bool boolDefault = false;
bool JsonNode::Bool() const
{
if (getType() == JsonType::DATA_NULL)
return boolDefault;
assert(getType() == JsonType::DATA_BOOL);
return std::get<bool>(data);
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_BOOL);
if (getType() == JsonType::DATA_BOOL)
return std::get<bool>(data);
return boolDefault;
}
const double floatDefault = 0;
double JsonNode::Float() const
{
if(getType() == JsonType::DATA_NULL)
return floatDefault;
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
if(getType() == JsonType::DATA_FLOAT)
return std::get<double>(data);
if(getType() == JsonType::DATA_INTEGER)
return static_cast<double>(std::get<si64>(data));
assert(getType() == JsonType::DATA_FLOAT);
return std::get<double>(data);
return floatDefault;
}
const si64 integetDefault = 0;
const si64 integerDefault = 0;
si64 JsonNode::Integer() const
{
if(getType() == JsonType::DATA_NULL)
return integetDefault;
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_INTEGER || getType() == JsonType::DATA_FLOAT);
if(getType() == JsonType::DATA_INTEGER)
return std::get<si64>(data);
if(getType() == JsonType::DATA_FLOAT)
return static_cast<si64>(std::get<double>(data));
assert(getType() == JsonType::DATA_INTEGER);
return std::get<si64>(data);
return integerDefault;
}
const std::string stringDefault = std::string();
const std::string & JsonNode::String() const
{
if (getType() == JsonType::DATA_NULL)
return stringDefault;
assert(getType() == JsonType::DATA_STRING);
return std::get<std::string>(data);
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRING);
if (getType() == JsonType::DATA_STRING)
return std::get<std::string>(data);
return stringDefault;
}
const JsonVector vectorDefault = JsonVector();
const JsonVector & JsonNode::Vector() const
{
if (getType() == JsonType::DATA_NULL)
return vectorDefault;
assert(getType() == JsonType::DATA_VECTOR);
return std::get<JsonVector>(data);
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_VECTOR);
if (getType() == JsonType::DATA_VECTOR)
return std::get<JsonVector>(data);
return vectorDefault;
}
const JsonMap mapDefault = JsonMap();
const JsonMap & JsonNode::Struct() const
{
if (getType() == JsonType::DATA_NULL)
return mapDefault;
assert(getType() == JsonType::DATA_STRUCT);
return std::get<JsonMap>(data);
assert(getType() == JsonType::DATA_NULL || getType() == JsonType::DATA_STRUCT);
if (getType() == JsonType::DATA_STRUCT)
return std::get<JsonMap>(data);
return mapDefault;
}
JsonNode & JsonNode::operator[](const std::string & child)

View File

@ -2225,12 +2225,12 @@ bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8
bool CGameHandler::hasPlayerAt(PlayerColor player, std::shared_ptr<CConnection> c) const
{
return connections.at(player).count(c);
return connections.count(player) && connections.at(player).count(c);
}
bool CGameHandler::hasBothPlayersAtSameConnection(PlayerColor left, PlayerColor right) const
{
return connections.at(left) == connections.at(right);
return connections.count(left) && connections.count(right) && connections.at(left) == connections.at(right);
}
bool CGameHandler::disbandCreature(ObjectInstanceID id, SlotID pos)

View File

@ -9,6 +9,7 @@
*/
#include "StdInc.h"
#include "TurnOrderProcessor.h"
#include "PlayerMessageProcessor.h"
#include "../queries/QueriesProcessor.h"
#include "../queries/MapQueries.h"
@ -35,9 +36,9 @@ int TurnOrderProcessor::simturnsTurnsMinLimit() const
return gameHandler->getStartInfo()->simturnsInfo.requiredTurns;
}
void TurnOrderProcessor::updateContactStatus()
std::vector<TurnOrderProcessor::PlayerPair> TurnOrderProcessor::computeContactStatus() const
{
blockedContacts.clear();
std::vector<PlayerPair> result;
assert(actedPlayers.empty());
assert(actingPlayers.empty());
@ -50,9 +51,40 @@ void TurnOrderProcessor::updateContactStatus()
continue;
if (computeCanActSimultaneously(left, right))
blockedContacts.push_back({left, right});
result.push_back({left, right});
}
}
return result;
}
void TurnOrderProcessor::updateAndNotifyContactStatus()
{
auto newBlockedContacts = computeContactStatus();
if (newBlockedContacts.empty())
{
// Simturns between all players have ended - send single global notification
if (!blockedContacts.empty())
gameHandler->playerMessages->broadcastSystemMessage("Simultaneous turns have ended");
}
else
{
// Simturns between some players have ended - notify each pair
for (auto const & contact : blockedContacts)
{
if (vstd::contains(newBlockedContacts, contact))
continue;
MetaString message;
message.appendRawString("Simultaneous turns between players %s and %s have ended"); // FIXME: we should send MetaString itself and localize it on client side
message.replaceName(contact.a);
message.replaceName(contact.b);
gameHandler->playerMessages->broadcastSystemMessage(message.toString());
}
}
blockedContacts = newBlockedContacts;
}
bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) const
@ -204,7 +236,7 @@ void TurnOrderProcessor::doStartNewDay()
std::swap(actedPlayers, awaitingPlayers);
gameHandler->onNewTurn();
updateContactStatus();
updateAndNotifyContactStatus();
tryStartTurnsForPlayers();
}
@ -301,7 +333,7 @@ bool TurnOrderProcessor::onPlayerEndsTurn(PlayerColor which)
void TurnOrderProcessor::onGameStarted()
{
if (actingPlayers.empty())
updateContactStatus();
blockedContacts = computeContactStatus();
// this may be game load - send notification to players that they can act
auto actingPlayersCopy = actingPlayers;

View File

@ -62,7 +62,9 @@ class TurnOrderProcessor : boost::noncopyable
/// Starts turn for all players that can start turn
void tryStartTurnsForPlayers();
void updateContactStatus();
void updateAndNotifyContactStatus();
std::vector<PlayerPair> computeContactStatus() const;
void doStartNewDay();
void doStartPlayerTurn(PlayerColor which);