1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

Rewardable object randomization is now always server-sided

This commit is contained in:
Ivan Savenko 2024-07-12 15:10:03 +00:00
parent 388d65d6b2
commit d2839c8e52
17 changed files with 126 additions and 26 deletions

View File

@ -214,6 +214,8 @@ public:
void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value) override {};
void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) override {};
void setRewardableObjectConfiguration(ObjectInstanceID objid, const Rewardable::Configuration & configuration) override {};
void setRewardableObjectConfiguration(ObjectInstanceID townInstanceID, BuildingID buildingID, const Rewardable::Configuration & configuration) override{};
void showInfoDialog(InfoWindow * iw) override {};
void removeGUI() const;

View File

@ -529,6 +529,7 @@ set(lib_MAIN_HEADERS
networkPacks/PacksForClientBattle.h
networkPacks/PacksForLobby.h
networkPacks/PacksForServer.h
networkPacks/SetRewardableConfiguration.h
networkPacks/SetStackEffect.h
networkPacks/StackLocation.h
networkPacks/TradeItem.h

View File

@ -37,6 +37,11 @@ namespace spells
class Caster;
}
namespace Rewardable
{
struct Configuration;
}
#if SCRIPTING_ENABLED
namespace scripting
{
@ -79,6 +84,8 @@ class DLL_LINKAGE IGameEventCallback
{
public:
virtual void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value = 0) = 0;
virtual void setRewardableObjectConfiguration(ObjectInstanceID mapObjectID, const Rewardable::Configuration & configuration) = 0;
virtual void setRewardableObjectConfiguration(ObjectInstanceID townInstanceID, BuildingID buildingID, const Rewardable::Configuration & configuration) = 0;
virtual void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) = 0;
virtual void showInfoDialog(InfoWindow * iw) = 0;

View File

@ -40,19 +40,29 @@ CGObjectInstance * CRewardableConstructor::create(IGameCallback * cb, std::share
return ret;
}
Rewardable::Configuration CRewardableConstructor::generateConfiguration(IGameCallback * cb, vstd::RNG & rand, MapObjectID objectID) const
{
Rewardable::Configuration result;
objectInfo.configureObject(result, rand, cb);
for(auto & rewardInfo : result.info)
{
for (auto & bonus : rewardInfo.reward.bonuses)
{
bonus.source = BonusSource::OBJECT_TYPE;
bonus.sid = BonusSourceID(objectID);
}
}
return result;
}
void CRewardableConstructor::configureObject(CGObjectInstance * object, vstd::RNG & rng) const
{
if(auto * rewardableObject = dynamic_cast<CRewardableObject*>(object))
{
objectInfo.configureObject(rewardableObject->configuration, rng, object->cb);
for(auto & rewardInfo : rewardableObject->configuration.info)
{
for (auto & bonus : rewardInfo.reward.bonuses)
{
bonus.source = BonusSource::OBJECT_TYPE;
bonus.sid = BonusSourceID(rewardableObject->ID);
}
}
rewardableObject->configuration = generateConfiguration(object->cb, rng, object->ID);
if (rewardableObject->configuration.info.empty())
{
if (objectInfo.getParameters()["rewards"].isNull())

View File

@ -30,6 +30,8 @@ public:
void configureObject(CGObjectInstance * object, vstd::RNG & rng) const override;
std::unique_ptr<IObjectInfo> getObjectInfo(std::shared_ptr<const ObjectTemplate> tmpl) const override;
Rewardable::Configuration generateConfiguration(IGameCallback * cb, vstd::RNG & rand, MapObjectID objectID) const;
};
VCMI_LIB_NAMESPACE_END

View File

@ -328,11 +328,16 @@ CTownRewardableBuilding::CTownRewardableBuilding(const BuildingID & index, Build
void CTownRewardableBuilding::initObj(vstd::RNG & rand)
{
assert(town && town->town);
configuration = generateConfiguration(rand);
}
Rewardable::Configuration CTownRewardableBuilding::generateConfiguration(vstd::RNG & rand) const
{
Rewardable::Configuration result;
auto building = town->town->buildings.at(bID);
building->rewardableObjectInfo.configureObject(configuration, rand, cb);
for(auto & rewardInfo : configuration.info)
building->rewardableObjectInfo.configureObject(result, rand, cb);
for(auto & rewardInfo : result.info)
{
for (auto & bonus : rewardInfo.reward.bonuses)
{
@ -340,16 +345,16 @@ void CTownRewardableBuilding::initObj(vstd::RNG & rand)
bonus.sid = BonusSourceID(building->getUniqueTypeID());
}
}
return result;
}
void CTownRewardableBuilding::newTurn(vstd::RNG & rand) const
{
if (configuration.resetParameters.period != 0 && cb->getDate(Date::DAY) > 1 && ((cb->getDate(Date::DAY)-1) % configuration.resetParameters.period) == 0)
{
if(configuration.resetParameters.rewards)
{
cb->setObjPropertyValue(town->id, ObjProperty::REWARD_RANDOMIZE, indexOnTV);
}
auto newConfiguration = generateConfiguration(rand);
cb->setRewardableObjectConfiguration(town->id, bID, newConfiguration);
if(configuration.resetParameters.visitors)
{
cb->setObjPropertyValue(town->id, ObjProperty::STRUCTURE_CLEAR_VISITORS, indexOnTV);
@ -367,9 +372,6 @@ void CTownRewardableBuilding::setProperty(ObjProperty what, ObjPropertyID identi
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
visitors.clear();
break;
case ObjProperty::REWARD_RANDOMIZE:
initObj(cb->gameState()->getRandomGenerator());
break;
case ObjProperty::REWARD_SELECT:
selectedReward = identifier.getNum();
break;

View File

@ -118,6 +118,8 @@ class DLL_LINKAGE CTownRewardableBuilding : public CGTownBuilding, public Reward
bool wasVisitedBefore(const CGHeroInstance * contextHero) const;
void grantReward(ui32 rewardID, const CGHeroInstance * hero) const;
Rewardable::Configuration generateConfiguration(vstd::RNG & rand) const;
public:
void setProperty(ObjProperty what, ObjPropertyID identifier) override;

View File

@ -71,9 +71,6 @@ void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
case ObjProperty::BONUS_VALUE_SECOND:
bonusValue.second = identifier.getNum();
break;
case ObjProperty::REWARD_RANDOMIZE:
bonusingBuildings[identifier.getNum()]->setProperty(ObjProperty::REWARD_RANDOMIZE, NumericID(0));
break;
}
}
CGTownInstance::EFortLevel CGTownInstance::fortLevel() const //0 - none, 1 - fort, 2 - citadel, 3 - castle

View File

@ -16,6 +16,7 @@
#include "../IGameCallback.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjectConstructors/CRewardableConstructor.h"
#include "../mapObjects/CGHeroInstance.h"
#include "../networkPacks/PacksForClient.h"
#include "../serializer/JsonSerializeFormat.h"
@ -377,9 +378,6 @@ void CRewardableObject::setPropertyDer(ObjProperty what, ObjPropertyID identifie
{
switch (what)
{
case ObjProperty::REWARD_RANDOMIZE:
initObj(cb->gameState()->getRandomGenerator());
break;
case ObjProperty::REWARD_SELECT:
selectedReward = identifier.getNum();
break;
@ -395,7 +393,9 @@ void CRewardableObject::newTurn(vstd::RNG & rand) const
{
if (configuration.resetParameters.rewards)
{
cb->setObjPropertyValue(id, ObjProperty::REWARD_RANDOMIZE, 0);
auto handler = std::dynamic_pointer_cast<const CRewardableConstructor>(getObjectHandler());
auto newConfiguration = handler->generateConfiguration(cb, rand, ID);
cb->setRewardableObjectConfiguration(id, newConfiguration);
}
if (configuration.resetParameters.visitors)
{

View File

@ -50,6 +50,9 @@ public:
virtual void onHeroVisit(const CGHeroInstance * h) const;
virtual void onHeroLeave(const CGHeroInstance * h) const;
/// Called on new turn by server. This method can not modify object state on its own
/// Instead all changes must be propagated via netpacks
virtual void newTurn(vstd::RNG & rand) const;
virtual void initObj(vstd::RNG & rand); //synchr
virtual void pickRandomObject(vstd::RNG & rand);

View File

@ -13,6 +13,7 @@
#include "PacksForClientBattle.h"
#include "PacksForServer.h"
#include "PacksForLobby.h"
#include "SetRewardableConfiguration.h"
#include "SetStackEffect.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -34,6 +35,7 @@ public:
virtual void visitTurnTimeUpdate(TurnTimeUpdate & pack) {}
virtual void visitGamePause(GamePause & pack) {}
virtual void visitEntitiesChanged(EntitiesChanged & pack) {}
virtual void visitSetRewardableConfiguration(SetRewardableConfiguration & pack) {}
virtual void visitSetResources(SetResources & pack) {}
virtual void visitSetPrimSkill(SetPrimSkill & pack) {}
virtual void visitSetSecSkill(SetSecSkill & pack) {}

View File

@ -12,6 +12,7 @@
#include "PacksForClient.h"
#include "PacksForClientBattle.h"
#include "PacksForServer.h"
#include "SetRewardableConfiguration.h"
#include "StackLocation.h"
#include "PacksForLobby.h"
#include "SetStackEffect.h"
@ -123,6 +124,11 @@ void EntitiesChanged::visitTyped(ICPackVisitor & visitor)
visitor.visitEntitiesChanged(*this);
}
void SetRewardableConfiguration::visitTyped(ICPackVisitor & visitor)
{
visitor.visitSetRewardableConfiguration(*this);
}
void SetResources::visitTyped(ICPackVisitor & visitor)
{
visitor.visitSetResources(*this);
@ -2479,6 +2485,16 @@ void EntitiesChanged::applyGs(CGameState * gs)
gs->updateEntity(change.metatype, change.entityIndex, change.data);
}
void SetRewardableConfiguration::applyGs(CGameState * gs)
{
auto * objectPtr = gs->getObjInstance(objectID);
auto * rewardablePtr = dynamic_cast<CRewardableObject *>(objectPtr);
assert(rewardablePtr);
rewardablePtr->configuration = configuration;
}
const CArtifactInstance * ArtSlotInfo::getArt() const
{
if(locked)

View File

@ -47,7 +47,6 @@ enum class ObjProperty : int8_t
BANK_CLEAR,
//object with reward
REWARD_RANDOMIZE,
REWARD_SELECT,
REWARD_CLEARED
};

View File

@ -0,0 +1,35 @@
/*
* SetRewardableConfiguration.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "NetPacksBase.h"
#include "../rewardable/Configuration.h"
VCMI_LIB_NAMESPACE_BEGIN
struct DLL_LINKAGE SetRewardableConfiguration : public CPackForClient
{
void applyGs(CGameState * gs);
void visitTyped(ICPackVisitor & visitor) override;
ObjectInstanceID objectID;
BuildingID buildingID;
Rewardable::Configuration configuration;
template <typename Handler> void serialize(Handler & h)
{
h & objectID;
h & buildingID;
h & configuration;
}
};
VCMI_LIB_NAMESPACE_END

View File

@ -12,6 +12,7 @@
#include "../networkPacks/PacksForClient.h"
#include "../networkPacks/PacksForClientBattle.h"
#include "../networkPacks/SetStackEffect.h"
#include "../networkPacks/SetRewardableConfiguration.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -119,6 +120,8 @@ void registerTypesClientPacks(Serializer &s)
s.template registerType<CPackForClient, PlayerMessageClient>();
s.template registerType<CGarrisonOperationPack, BulkRebalanceStacks>();
s.template registerType<CGarrisonOperationPack, BulkSmartRebalanceStacks>();
s.template registerType<SetRewardableConfiguration, CPackForClient>();
}
VCMI_LIB_NAMESPACE_END

View File

@ -4374,6 +4374,23 @@ void CGameHandler::setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, Ob
sendAndApply(&sob);
}
void CGameHandler::setRewardableObjectConfiguration(ObjectInstanceID objid, const Rewardable::Configuration & configuration)
{
SetRewardableConfiguration srb;
srb.objectID = objid;
srb.configuration = configuration;
sendAndApply(&srb);
}
void CGameHandler::setRewardableObjectConfiguration(ObjectInstanceID townInstanceID, BuildingID buildingID, const Rewardable::Configuration & configuration)
{
SetRewardableConfiguration srb;
srb.objectID = townInstanceID;
srb.buildingID = buildingID;
srb.configuration = configuration;
sendAndApply(&srb);
}
void CGameHandler::showInfoDialog(InfoWindow * iw)
{
sendAndApply(iw);

View File

@ -162,6 +162,8 @@ public:
bool isVisitCoveredByAnotherQuery(const CGObjectInstance *obj, const CGHeroInstance *hero) override;
void setObjPropertyValue(ObjectInstanceID objid, ObjProperty prop, int32_t value) override;
void setObjPropertyID(ObjectInstanceID objid, ObjProperty prop, ObjPropertyID identifier) override;
void setRewardableObjectConfiguration(ObjectInstanceID objid, const Rewardable::Configuration & configuration) override;
void setRewardableObjectConfiguration(ObjectInstanceID townInstanceID, BuildingID buildingID, const Rewardable::Configuration & configuration) override;
void showInfoDialog(InfoWindow * iw) override;
//////////////////////////////////////////////////////////////////////////