1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-10 22:31:40 +02:00

Implemented playerGlobal visit mode for objects like cartographer

This commit is contained in:
Ivan Savenko
2025-05-06 18:53:43 +03:00
parent 1b5d00cc99
commit 4b77140f4a
11 changed files with 32 additions and 31 deletions

View File

@@ -18,7 +18,7 @@
"rarity" : 20
},
"compatibilityIdentifiers" : [ "water" ],
"visitMode" : "unlimited",
"visitMode" : "playerGlobal",
"canRefuse" : true,
"rewards" : [
{
@@ -44,7 +44,7 @@
"rarity" : 2
},
"compatibilityIdentifiers" : [ "land" ],
"visitMode" : "unlimited",
"visitMode" : "playerGlobal",
"canRefuse" : true,
"rewards" : [
{
@@ -72,7 +72,7 @@
"rarity" : 20
},
"compatibilityIdentifiers" : [ "subterra" ],
"visitMode" : "unlimited",
"visitMode" : "playerGlobal",
"canRefuse" : true,
"rewards" : [
{
@@ -94,4 +94,4 @@
}
}
}
}
}

View File

@@ -815,7 +815,7 @@ void CGKeymasterTent::onHeroVisit( const CGHeroInstance * h ) const
if (!wasMyColorVisited (h->getOwner()) )
{
ChangeObjectVisitors cow;
cow.mode = ChangeObjectVisitors::VISITOR_GLOBAL;
cow.mode = ChangeObjectVisitors::VISITOR_ADD_PLAYER;
cow.hero = h->id;
cow.object = id;
cb->sendAndApply(cow);

View File

@@ -137,7 +137,9 @@ bool CRewardableObject::wasVisitedBefore(const CGHeroInstance * contextHero) con
case Rewardable::VISIT_ONCE:
return onceVisitableObjectCleared;
case Rewardable::VISIT_PLAYER:
return vstd::contains(cb->getPlayerState(contextHero->getOwner())->visitedObjects, ObjectInstanceID(id));
return cb->getPlayerState(contextHero->getOwner())->visitedObjects.count(ObjectInstanceID(id)) != 0;
case Rewardable::VISIT_PLAYER_GLOBAL:
return cb->getPlayerState(contextHero->getOwner())->visitedObjectsGlobal.count({ID, subID}) != 0;
case Rewardable::VISIT_BONUS:
return contextHero->hasBonusFrom(BonusSource::OBJECT_TYPE, BonusSourceID(ID));
case Rewardable::VISIT_HERO:
@@ -160,7 +162,9 @@ bool CRewardableObject::wasVisited(PlayerColor player) const
return false;
case Rewardable::VISIT_ONCE:
case Rewardable::VISIT_PLAYER:
return vstd::contains(cb->getPlayerState(player)->visitedObjects, ObjectInstanceID(id));
return cb->getPlayerState(player)->visitedObjects.count(ObjectInstanceID(id)) != 0;
case Rewardable::VISIT_PLAYER_GLOBAL:
return cb->getPlayerState(player)->visitedObjectsGlobal.count({ID, subID}) != 0;
default:
return false;
}
@@ -205,7 +209,7 @@ std::string CRewardableObject::getDisplayTextImpl(PlayerColor player, const CGHe
}
else
{
if(configuration.visitMode == Rewardable::VISIT_PLAYER || configuration.visitMode == Rewardable::VISIT_ONCE)
if(configuration.visitMode == Rewardable::VISIT_PLAYER || configuration.visitMode == Rewardable::VISIT_ONCE || configuration.visitMode == Rewardable::VISIT_PLAYER_GLOBAL)
{
if (wasVisited(player))
result += "\n" + configuration.visitedTooltip.toString();

View File

@@ -172,6 +172,7 @@ bool TownRewardableBuildingInstance::wasVisitedBefore(const CGHeroInstance * con
case Rewardable::VISIT_ONCE:
return !visitors.empty();
case Rewardable::VISIT_PLAYER:
case Rewardable::VISIT_PLAYER_GLOBAL:
return false; //not supported
case Rewardable::VISIT_BONUS:
{
@@ -211,6 +212,7 @@ bool TownRewardableBuildingInstance::wasVisited(PlayerColor player) const
case Rewardable::VISIT_BONUS:
case Rewardable::VISIT_HERO:
case Rewardable::VISIT_LIMITER:
case Rewardable::VISIT_PLAYER_GLOBAL:
return false;
case Rewardable::VISIT_ONCE:
case Rewardable::VISIT_PLAYER:

View File

@@ -1045,16 +1045,16 @@ void ChangeObjPos::applyGs(CGameState *gs)
void ChangeObjectVisitors::applyGs(CGameState *gs)
{
auto objectPtr = gs->getObjInstance(object);
switch (mode) {
case VISITOR_ADD_HERO:
gs->getPlayerTeam(gs->getHero(hero)->tempOwner)->scoutedObjects.insert(object);
gs->getHero(hero)->visitedObjects.insert(object);
gs->getPlayerState(gs->getHero(hero)->tempOwner)->visitedObjects.insert(object);
break;
[[fallthrough]];
case VISITOR_ADD_PLAYER:
gs->getPlayerTeam(gs->getHero(hero)->tempOwner)->scoutedObjects.insert(object);
for(const auto & color : gs->getPlayerTeam(gs->getHero(hero)->tempOwner)->players)
gs->getPlayerState(color)->visitedObjects.insert(object);
gs->getPlayerState(gs->getHero(hero)->tempOwner)->visitedObjects.insert(object);
gs->getPlayerState(gs->getHero(hero)->tempOwner)->visitedObjectsGlobal.insert({objectPtr->ID, objectPtr->subID});
break;
case VISITOR_CLEAR:
@@ -1076,12 +1076,6 @@ void ChangeObjectVisitors::applyGs(CGameState *gs)
gs->getPlayerTeam(gs->getHero(hero)->tempOwner)->scoutedObjects.insert(object);
break;
case VISITOR_GLOBAL:
{
CGObjectInstance * objectPtr = gs->getObjInstance(object);
gs->getPlayerState(gs->getHero(hero)->tempOwner)->visitedObjectsGlobal.insert({objectPtr->ID, objectPtr->subID});
break;
}
}
}

View File

@@ -1215,7 +1215,6 @@ struct DLL_LINKAGE ChangeObjectVisitors : public CPackForClient
{
VISITOR_ADD_HERO, // mark hero as one that have visited this object
VISITOR_ADD_PLAYER, // mark player as one that have visited this object instance
VISITOR_GLOBAL, // mark player as one that have visited object of this type
VISITOR_SCOUTED, // marks targeted team as having scouted this object
VISITOR_CLEAR, // clear all visitors from this object (object reset)
};

View File

@@ -22,7 +22,7 @@ VCMI_LIB_NAMESPACE_BEGIN
namespace Rewardable
{
enum EVisitMode
enum EVisitMode : uint8_t
{
VISIT_UNLIMITED, // any number of times. Side effect - object hover text won't contain visited/not visited text
VISIT_ONCE, // only once, first to visit get all the rewards
@@ -34,7 +34,7 @@ enum EVisitMode
};
/// controls selection of reward granted to player
enum ESelectMode
enum ESelectMode : uint8_t
{
SELECT_FIRST, // first reward that matches limiters
SELECT_PLAYER, // player can select from all allowed rewards
@@ -42,7 +42,7 @@ enum ESelectMode
SELECT_ALL // grant all rewards that match limiters
};
enum class EEventType
enum class EEventType : uint8_t
{
EVENT_INVALID = 0,
EVENT_FIRST_VISIT,
@@ -52,7 +52,7 @@ enum class EEventType
};
constexpr std::array<std::string_view, 4> SelectModeString{"selectFirst", "selectPlayer", "selectRandom", "selectAll"};
constexpr std::array<std::string_view, 6> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player"};
constexpr std::array<std::string_view, 7> VisitModeString{"unlimited", "once", "hero", "bonus", "limiter", "player", "playerGlobal" };
struct DLL_LINKAGE ResetInfo
{
@@ -150,10 +150,10 @@ struct DLL_LINKAGE Configuration
std::vector<Rewardable::VisitInfo> info;
/// how reward will be selected, uses ESelectMode enum
ui8 selectMode = Rewardable::SELECT_FIRST;
ESelectMode selectMode = Rewardable::SELECT_FIRST;
/// controls who can visit an object, uses EVisitMode enum
ui8 visitMode = Rewardable::VISIT_UNLIMITED;
EVisitMode visitMode = Rewardable::VISIT_UNLIMITED;
/// how and when should the object be reset
Rewardable::ResetInfo resetParameters;

View File

@@ -471,7 +471,7 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, vstd:
{
if(Rewardable::VisitModeString[i] == visitMode)
{
object.visitMode = i;
object.visitMode = static_cast<EVisitMode>(i);
break;
}
}
@@ -481,7 +481,7 @@ void Rewardable::Info::configureObject(Rewardable::Configuration & object, vstd:
{
if(Rewardable::SelectModeString[i] == selectMode)
{
object.selectMode = i;
object.selectMode = static_cast<ESelectMode>(i);
break;
}
}

View File

@@ -32,7 +32,7 @@ struct Configuration;
struct Variables;
struct VisitInfo;
struct ResetInfo;
enum class EEventType;
enum class EEventType : uint8_t;
class DLL_LINKAGE Info : public IObjectInfo
{

View File

@@ -30,6 +30,8 @@ Rewardable::Limiter::Limiter()
, manaPercentage(0)
, manaPoints(0)
, canLearnSkills(false)
, commanderAlive(false)
, hasExtraCreatures(false)
, primary(GameConstants::PRIMARY_SKILLS, 0)
{
}

View File

@@ -249,8 +249,8 @@ void RewardsWidget::obtainData()
bool RewardsWidget::commitChanges()
{
//common parameters
object.configuration.visitMode = ui->visitMode->currentIndex();
object.configuration.selectMode = ui->selectMode->currentIndex();
object.configuration.visitMode = static_cast<Rewardable::EVisitMode>(ui->visitMode->currentIndex());
object.configuration.selectMode = static_cast<Rewardable::ESelectMode>(ui->selectMode->currentIndex());
object.configuration.infoWindowType = EInfoWindowMode(ui->windowMode->currentIndex());
if(ui->onSelectText->text().isEmpty())
object.configuration.onSelect.clear();