1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Move ObjectConfig to ObjectInfo.cpp. Preliminary version of banning object categories.

This commit is contained in:
Tomasz Zieliński 2024-08-24 15:12:22 +02:00
parent 85ee859b6e
commit 64fc2e5ed0
8 changed files with 250 additions and 113 deletions

View File

@ -49,6 +49,9 @@
},
"additionalProperties" : false
}
},
"customObjects" : {
"type" : "object"
}
}
},

View File

@ -411,11 +411,8 @@ CompoundMapObjectID CObjectClassesHandler::getCompoundIdentifier(const std::stri
CompoundMapObjectID CObjectClassesHandler::getCompoundIdentifier(const std::string & objectName) const
{
// FIXME: Crash with no further log
//"core:object.creatureBank.experimentalShop",
//"core:object.creatureBank.wolfRiderPicket",
//"core:object.creatureBank.demonDomain"
// TODO: Use existing utilities for parsing id?
// TODO: Use existing utilities for parsing id?
JsonNode node(objectName);
auto modScope = node.getModScope();

View File

@ -11,9 +11,9 @@
#include "StdInc.h"
#include <vstd/ContainerUtils.h>
#include <boost/bimap.hpp>
#include "CRmgTemplate.h"
#include "Functions.h"
#include "../TerrainHandler.h"
#include "../VCMI_Lib.h"
#include "../constants/StringConstants.h"
@ -909,87 +909,19 @@ void CRmgTemplate::serializePlayers(JsonSerializeFormat & handler, CPlayerCountR
value.fromString(encodedValue);
}
void ZoneOptions::ObjectConfig::addBannedObject(const CompoundMapObjectID & objid)
{
// FIXME: We do not need to store the object info, just the id
bannedObjects.push_back(objid);
logGlobal->info("Banned object of type %d.%d", objid.primaryID, objid.secondaryID);
}
void ZoneOptions::ObjectConfig::serializeJson(JsonSerializeFormat & handler)
{
// TODO: Implement'
auto bannedObjectData = handler.enterArray("bannedObjects");
if (handler.saving)
{
// FIXME: Do we even need to serialize / store banned objects?
/*
for (const auto & object : bannedObjects)
{
// TODO: Translate id back to string?
JsonNode node;
node.String() = VLC->objtypeh->getHandlerFor(object.primaryID, object.secondaryID);
// TODO: Check if AI-generated code is right
}
// handler.serializeRaw("bannedObjects", node, std::nullopt);
*/
}
else
{
/*
auto zonesData = handler.enterStruct("zones");
for(const auto & idAndZone : zonesData->getCurrent().Struct())
{
auto guard = handler.enterStruct(idAndZone.first);
auto zone = std::make_shared<ZoneOptions>();
zone->setId(decodeZoneId(idAndZone.first));
zone->serializeJson(handler);
zones[zone->getId()] = zone;
}
*/
std::vector<std::string> objectNames;
bannedObjectData.serializeArray(objectNames);
for (const auto & objectName : objectNames)
{
VLC->objtypeh->resolveObjectCompoundId(objectName,
[this](CompoundMapObjectID objid)
{
addBannedObject(objid);
}
);
}
}
}
const std::vector<CompoundMapObjectID> & ZoneOptions::getBannedObjects() const
{
return objectConfig.getBannedObjects();
}
const std::vector<ObjectConfig::EObjectCategory> & ZoneOptions::getBannedObjectCategories() const
{
return objectConfig.getBannedObjectCategories();
}
const std::vector<ObjectInfo> & ZoneOptions::getCustomObjects() const
{
return objectConfig.getCustomObjects();
}
const std::vector<CompoundMapObjectID> & ZoneOptions::ObjectConfig::getBannedObjects() const
{
return bannedObjects;
}
const std::vector<ObjectInfo> & ZoneOptions::ObjectConfig::getCustomObjects() const
{
return customObjects;
}
VCMI_LIB_NAMESPACE_END

View File

@ -139,32 +139,6 @@ public:
TRmgTemplateZoneId sourceZone = NO_ZONE;
};
// TODO: Store config for custom objects to spawn in this zone
// TODO: Read custom object config from zone file
class DLL_LINKAGE ObjectConfig
{
public:
//ObjectConfig() = default;
void addBannedObject(const CompoundMapObjectID & objid);
void addCustomObject(const ObjectInfo & object);
void clearBannedObjects();
void clearCustomObjects();
const std::vector<CompoundMapObjectID> & getBannedObjects() const;
const std::vector<ObjectInfo> & getCustomObjects() const;
// TODO: Separate serializer
void serializeJson(JsonSerializeFormat & handler);
private:
// TODO: Add convenience method for banning objects by name
std::vector<CompoundMapObjectID> bannedObjects;
// TODO: In what format should I store custom objects?
// Need to convert map serialization format to ObjectInfo
std::vector<ObjectInfo> customObjects;
};
// TODO: Allow to copy all custom objects config from another zone
ZoneOptions();
TRmgTemplateZoneId getId() const;
@ -215,6 +189,7 @@ public:
bool isMatchTerrainToTown() const;
const std::vector<CompoundMapObjectID> & getBannedObjects() const;
const std::vector<ObjectConfig::EObjectCategory> & getBannedObjectCategories() const;
const std::vector<ObjectInfo> & getCustomObjects() const;
protected:

View File

@ -9,11 +9,14 @@
*/
#include "StdInc.h"
#include <boost/bimap.hpp>
#include <boost/assign.hpp>
#include "ObjectInfo.h"
#include "../VCMI_Lib.h"
#include "../mapObjectConstructors/CObjectClassesHandler.h"
#include "../mapObjectConstructors/AObjectTypeHandler.h"
#include "../serializer/JsonSerializeFormat.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -56,16 +59,121 @@ void ObjectInfo::setTemplates(MapObjectID type, MapObjectSubID subtype, TerrainI
templates = templHandler->getTemplates(terrainType);
}
/*
bool ObjectInfo::matchesId(const CompoundMapObjectID & id) const
void ObjectConfig::addBannedObject(const CompoundMapObjectID & objid)
{
for (const auto & templ : templates)
{
if (id.primaryID == templ->id && id.secondaryID == templ->subid)
return true;
}
return false;
// FIXME: We do not need to store the object info, just the id
bannedObjects.push_back(objid);
logGlobal->info("Banned object of type %d.%d", objid.primaryID, objid.secondaryID);
}
void ObjectConfig::serializeJson(JsonSerializeFormat & handler)
{
// TODO: We need serializer utility for list of enum values
static const boost::bimap<EObjectCategory, std::string> OBJECT_CATEGORY_STRINGS = boost::assign::list_of<boost::bimap<EObjectCategory, std::string>::relation>
(EObjectCategory::OTHER, "other")
(EObjectCategory::ALL, "all")
(EObjectCategory::NONE, "none")
(EObjectCategory::CREATURE_BANK, "creatureBank")
(EObjectCategory::PERMANENT_BONUS, "permanentBonus")
(EObjectCategory::NEXT_BATTLE_BONUS, "nextBattleBonus")
(EObjectCategory::DWELLING, "dwelling")
(EObjectCategory::RESOURCE, "resource")
(EObjectCategory::RESOURCE_GENERATOR, "resourceGenerator")
(EObjectCategory::SPELL_SCROLL, "spellScroll")
(EObjectCategory::RANDOM_ARTIFACT, "randomArtifact")
(EObjectCategory::PANDORAS_BOX, "pandorasBox")
(EObjectCategory::QUEST_ARTIFACT, "questArtifact");
auto categories = handler.enterArray("bannedCategories");
if (handler.saving)
{
for (const auto& category : bannedObjectCategories)
{
auto str = OBJECT_CATEGORY_STRINGS.left.at(category);
categories.serializeString(categories.size(), str);
}
}
else
{
std::vector<std::string> categoryNames;
categories.serializeArray(categoryNames);
for (const auto & categoryName : categoryNames)
{
auto it = OBJECT_CATEGORY_STRINGS.right.find(categoryName);
if (it != OBJECT_CATEGORY_STRINGS.right.end())
{
bannedObjectCategories.push_back(it->second);
}
}
}
auto bannedObjectData = handler.enterArray("bannedObjects");
if (handler.saving)
{
// FIXME: Do we even need to serialize / store banned objects?
/*
for (const auto & object : bannedObjects)
{
// TODO: Translate id back to string?
JsonNode node;
node.String() = VLC->objtypeh->getHandlerFor(object.primaryID, object.secondaryID);
// TODO: Check if AI-generated code is right
}
// handler.serializeRaw("bannedObjects", node, std::nullopt);
*/
}
else
{
/*
auto zonesData = handler.enterStruct("zones");
for(const auto & idAndZone : zonesData->getCurrent().Struct())
{
auto guard = handler.enterStruct(idAndZone.first);
auto zone = std::make_shared<ZoneOptions>();
zone->setId(decodeZoneId(idAndZone.first));
zone->serializeJson(handler);
zones[zone->getId()] = zone;
}
*/
std::vector<std::string> objectNames;
bannedObjectData.serializeArray(objectNames);
for (const auto & objectName : objectNames)
{
VLC->objtypeh->resolveObjectCompoundId(objectName,
[this](CompoundMapObjectID objid)
{
addBannedObject(objid);
}
);
}
}
}
const std::vector<ObjectInfo> & ObjectConfig::getCustomObjects() const
{
return customObjects;
}
const std::vector<CompoundMapObjectID> & ObjectConfig::getBannedObjects() const
{
return bannedObjects;
}
const std::vector<ObjectConfig::EObjectCategory> & ObjectConfig::getBannedObjectCategories() const
{
return bannedObjectCategories;
}
*/
VCMI_LIB_NAMESPACE_END

View File

@ -37,4 +37,49 @@ struct DLL_LINKAGE ObjectInfo
//bool matchesId(const CompoundMapObjectID & id) const;
};
// TODO: Store config for custom objects to spawn in this zone
// TODO: Read custom object config from zone file
class DLL_LINKAGE ObjectConfig
{
public:
enum class EObjectCategory
{
OTHER = -2,
ALL = -1,
NONE = 0,
CREATURE_BANK = 1,
PERMANENT_BONUS,
NEXT_BATTLE_BONUS,
DWELLING,
RESOURCE,
RESOURCE_GENERATOR,
SPELL_SCROLL,
RANDOM_ARTIFACT,
PANDORAS_BOX,
QUEST_ARTIFACT
// TODO: Seer huts?
};
void addBannedObject(const CompoundMapObjectID & objid);
void addCustomObject(const ObjectInfo & object);
void clearBannedObjects();
void clearCustomObjects();
const std::vector<CompoundMapObjectID> & getBannedObjects() const;
const std::vector<EObjectCategory> & getBannedObjectCategories() const;
const std::vector<ObjectInfo> & getCustomObjects() const;
// TODO: Separate serializer
void serializeJson(JsonSerializeFormat & handler);
private:
// TODO: Add convenience method for banning objects by name
std::vector<CompoundMapObjectID> bannedObjects;
std::vector<EObjectCategory> bannedObjectCategories;
// TODO: In what format should I store custom objects?
// Need to convert map serialization format to ObjectInfo
std::vector<ObjectInfo> customObjects;
};
// TODO: Allow to copy all custom objects config from another zone
VCMI_LIB_NAMESPACE_END

View File

@ -10,6 +10,7 @@
#include "StdInc.h"
#include "TreasurePlacer.h"
#include "../CRmgTemplate.h"
#include "../CMapGenerator.h"
#include "../Functions.h"
#include "ObjectManager.h"
@ -1133,6 +1134,19 @@ void TreasurePlacer::ObjectPool::patchWithZoneConfig(const Zone & zone)
}
}
*/
auto bannedObjectCategories = zone.getBannedObjectCategories();
auto categoriesSet = std::unordered_set<ObjectConfig::EObjectCategory>(bannedObjectCategories.begin(), bannedObjectCategories.end());
vstd::erase_if(possibleObjects, [this, &categoriesSet](const ObjectInfo & oi) -> bool
{
auto category = getObjectCategory(oi.templates.front()->id);
if (categoriesSet.count(category))
{
logGlobal->info("Removing object %s from possible objects", oi.templates.front()->stringID);
return true;
}
return false;
});
vstd::erase_if(possibleObjects, [&zone](const ObjectInfo & object)
{
@ -1180,4 +1194,64 @@ void TreasurePlacer::ObjectPool::discardObjectsAboveValue(ui32 value)
});
}
ObjectConfig::EObjectCategory TreasurePlacer::ObjectPool::getObjectCategory(MapObjectID id)
{
auto name = VLC->objtypeh->getObjectHandlerName(id);
if (name == "configurable")
{
// TODO: Need to check configuration here.
// Possible otions: PERMANENT_BONUS, NEXT_BATTLE_BONUS, RESOURCE
return ObjectConfig::EObjectCategory::RESOURCE;
}
else if (name == "dwelling" || name == "randomDwelling")
{
// TODO: Special handling for different tiers
return ObjectConfig::EObjectCategory::DWELLING;
}
else if (name == "bank")
return ObjectConfig::EObjectCategory::CREATURE_BANK;
else if (name == "market")
return ObjectConfig::EObjectCategory::OTHER;
else if (name == "hillFort")
return ObjectConfig::EObjectCategory::OTHER;
else if (name == "resource" || name == "randomResource")
return ObjectConfig::EObjectCategory::RESOURCE;
else if (name == "randomArtifact") //"artifact"
return ObjectConfig::EObjectCategory::RANDOM_ARTIFACT;
else if (name == "denOfThieves")
return ObjectConfig::EObjectCategory::OTHER;
else if (name == "lighthouse")
{
// TODO: So far Lighthouse is not generated
// Also, it gives global bonus as long as owned
return ObjectConfig::EObjectCategory::PERMANENT_BONUS;
}
else if (name == "magi")
return ObjectConfig::EObjectCategory::OTHER;
else if (name == "mine")
return ObjectConfig::EObjectCategory::RESOURCE_GENERATOR;
else if (name == "pandora")
return ObjectConfig::EObjectCategory::PANDORAS_BOX;
else if (name == "prison")
{
// TODO: Prisons are configurable
return ObjectConfig::EObjectCategory::OTHER;
}
else if (name == "seerHut")
{
// quest artifacts are configurable, but what about seer huts?
return ObjectConfig::EObjectCategory::QUEST_ARTIFACT;
}
else if (name == "siren")
return ObjectConfig::EObjectCategory::NEXT_BATTLE_BONUS;
else if (name == "obelisk")
return ObjectConfig::EObjectCategory::OTHER;
// TODO: ObjectConfig::EObjectCategory::SPELL_SCROLL
// Not interesting for us
return ObjectConfig::EObjectCategory::NONE;
}
VCMI_LIB_NAMESPACE_END

View File

@ -20,6 +20,7 @@ class CGObjectInstance;
class ObjectManager;
class RmgMap;
class CMapGenerator;
class ObjectConfig;
struct CompoundMapObjectID;
class TreasurePlacer: public Modificator
@ -72,6 +73,8 @@ protected:
void sortPossibleObjects();
void discardObjectsAboveValue(ui32 value);
ObjectConfig::EObjectCategory getObjectCategory(MapObjectID id);
private:
std::vector<ObjectInfo> possibleObjects;