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

+ Handled banning spells and artifacts

+ Rename allowedSpell => allowedSpells
This commit is contained in:
Tomasz Zieliński 2023-07-17 17:21:28 +02:00
parent fbd1d728ec
commit 025b0814c8
19 changed files with 101 additions and 44 deletions

View File

@ -1085,6 +1085,7 @@
}, },
"necklaceOfOceanGuidance": "necklaceOfOceanGuidance":
{ {
"onlyOnWaterMap" : true,
"bonuses" : [ "bonuses" : [
{ {
"type" : "MOVEMENT", "type" : "MOVEMENT",
@ -1325,6 +1326,7 @@
}, },
"bootsOfLevitation": "bootsOfLevitation":
{ {
"onlyOnWaterMap" : true,
"bonuses" : [ "bonuses" : [
{ {
"type" : "WATER_WALKING", "type" : "WATER_WALKING",
@ -1796,6 +1798,7 @@
}, },
"seaCaptainsHat": "seaCaptainsHat":
{ {
"onlyOnWaterMap" : true,
"bonuses" : [ "bonuses" : [
{ {
"type" : "WHIRLPOOL_PROTECTION", "type" : "WHIRLPOOL_PROTECTION",
@ -2159,6 +2162,7 @@
}, },
"admiralsHat": "admiralsHat":
{ {
"onlyOnWaterMap" : true,
"bonuses" : [ "bonuses" : [
{ {
"type" : "FREE_SHIP_BOARDING", "type" : "FREE_SHIP_BOARDING",

View File

@ -13,7 +13,8 @@
}, },
"flags" : { "flags" : {
"indifferent": true "indifferent": true
} },
"onlyOnWaterMap" : true
}, },
"scuttleBoat" : { "scuttleBoat" : {
"index" : 1, "index" : 1,
@ -29,7 +30,8 @@
}, },
"flags" : { "flags" : {
"indifferent": true "indifferent": true
} },
"onlyOnWaterMap" : true
}, },
"visions" : { "visions" : {
"index" : 2, "index" : 2,
@ -237,7 +239,8 @@
}, },
"flags" : { "flags" : {
"indifferent": true "indifferent": true
} },
"onlyOnWaterMap" : true
}, },
"dimensionDoor" : { "dimensionDoor" : {
"index" : 8, "index" : 8,

View File

@ -434,6 +434,7 @@ CArtifact * CArtHandler::loadFromJson(const std::string & scope, const JsonNode
art->advMapDef = graphics["map"].String(); art->advMapDef = graphics["map"].String();
art->price = static_cast<ui32>(node["value"].Float()); art->price = static_cast<ui32>(node["value"].Float());
art->onlyOnWaterMap = node["onlyOnWaterMap"].Bool();
loadSlots(art, node); loadSlots(art, node);
loadClass(art, node); loadClass(art, node);

View File

@ -111,6 +111,7 @@ public:
enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes
EartClass aClass = ART_SPECIAL; EartClass aClass = ART_SPECIAL;
bool onlyOnWaterMap;
int32_t getIndex() const override; int32_t getIndex() const override;
int32_t getIconIndex() const override; int32_t getIconIndex() const override;
@ -159,6 +160,7 @@ public:
h & modScope; h & modScope;
h & identifier; h & identifier;
h & warMachine; h & warMachine;
h & onlyOnWaterMap;
} }
CArtifact(); CArtifact();

View File

@ -57,7 +57,7 @@ bool CGameInfoCallback::isAllowed(int32_t type, int32_t id) const
switch(type) switch(type)
{ {
case 0: case 0:
return gs->map->allowedSpell[id]; return gs->map->allowedSpells[id];
case 1: case 1:
return gs->map->allowedArtifact[id]; return gs->map->allowedArtifact[id];
case 2: case 2:

View File

@ -174,7 +174,7 @@ void CPrivilegedInfoCallback::pickAllowedArtsSet(std::vector<const CArtifact *>
void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level) void CPrivilegedInfoCallback::getAllowedSpells(std::vector<SpellID> & out, std::optional<ui16> level)
{ {
for (ui32 i = 0; i < gs->map->allowedSpell.size(); i++) //spellh size appears to be greater (?) for (ui32 i = 0; i < gs->map->allowedSpells.size(); i++) //spellh size appears to be greater (?)
{ {
const spells::Spell * spell = SpellID(i).toSpell(); const spells::Spell * spell = SpellID(i).toSpell();

View File

@ -137,7 +137,7 @@ CMap::CMap()
allHeroes.resize(allowedHeroes.size()); allHeroes.resize(allowedHeroes.size());
allowedAbilities = VLC->skillh->getDefaultAllowed(); allowedAbilities = VLC->skillh->getDefaultAllowed();
allowedArtifact = VLC->arth->getDefaultAllowed(); allowedArtifact = VLC->arth->getDefaultAllowed();
allowedSpell = VLC->spellh->getDefaultAllowed(); allowedSpells = VLC->spellh->getDefaultAllowed();
} }
CMap::~CMap() CMap::~CMap()
@ -580,6 +580,63 @@ bool CMap::calculateWaterContent()
return waterMap; return waterMap;
} }
void CMap::banWaterContent()
{
banWaterHeroes();
banWaterArtifacts();
banWaterSpells();
}
void CMap::banWaterSpells()
{
for (int j = 0; j < allowedSpells.size(); j++)
{
if (allowedSpells[j])
{
auto* spell = dynamic_cast<const CSpell*>(VLC->spells()->getByIndex(j));
if (spell->onlyOnWaterMap && !isWaterMap())
{
allowedSpells[j] = false;
}
}
}
}
void CMap::banWaterArtifacts()
{
for (int j = 0; j < allowedArtifact.size(); j++)
{
if (allowedArtifact[j])
{
auto* art = dynamic_cast<const CArtifact*>(VLC->artifacts()->getByIndex(j));
if (art->onlyOnWaterMap && !isWaterMap())
{
allowedArtifact[j] = false;
}
}
}
}
void CMap::banWaterHeroes()
{
for (int j = 0; j < allowedHeroes.size(); j++)
{
if (allowedHeroes[j])
{
auto* h = dynamic_cast<const CHero*>(VLC->heroTypes()->getByIndex(j));
if ((h->onlyOnWaterMap && !isWaterMap()) || (h->onlyOnMapWithoutWater && isWaterMap()))
{
banHero(HeroTypeID(j));
}
}
}
}
void CMap::banHero(const HeroTypeID & id)
{
allowedHeroes.at(id) = false;
}
void CMap::initTerrain() void CMap::initTerrain()
{ {
terrain.resize(boost::extents[levels()][width][height]); terrain.resize(boost::extents[levels()][width][height]);

View File

@ -108,6 +108,11 @@ public:
bool isWaterMap() const; bool isWaterMap() const;
bool calculateWaterContent(); bool calculateWaterContent();
void banWaterArtifacts();
void banWaterHeroes();
void banHero(const HeroTypeID& id);
void banWaterSpells();
void banWaterContent();
/// Gets object of specified type on requested position /// Gets object of specified type on requested position
const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj::EObj type); const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj::EObj type);
@ -122,7 +127,7 @@ public:
std::vector<Rumor> rumors; std::vector<Rumor> rumors;
std::vector<DisposedHero> disposedHeroes; std::vector<DisposedHero> disposedHeroes;
std::vector<ConstTransitivePtr<CGHeroInstance> > predefinedHeroes; std::vector<ConstTransitivePtr<CGHeroInstance> > predefinedHeroes;
std::vector<bool> allowedSpell; std::vector<bool> allowedSpells;
std::vector<bool> allowedArtifact; std::vector<bool> allowedArtifact;
std::vector<bool> allowedAbilities; std::vector<bool> allowedAbilities;
std::list<CMapEvent> events; std::list<CMapEvent> events;
@ -163,7 +168,7 @@ public:
h & static_cast<CMapHeader&>(*this); h & static_cast<CMapHeader&>(*this);
h & triggeredEvents; //from CMapHeader h & triggeredEvents; //from CMapHeader
h & rumors; h & rumors;
h & allowedSpell; h & allowedSpells;
h & allowedAbilities; h & allowedAbilities;
h & allowedArtifact; h & allowedArtifact;
h & events; h & events;

View File

@ -119,6 +119,7 @@ void CMapLoaderH3M::init()
map->calculateGuardingGreaturePositions(); map->calculateGuardingGreaturePositions();
afterRead(); afterRead();
//map->banWaterContent(); //Not sure if force this for custom scenarios
} }
void CMapLoaderH3M::readHeader() void CMapLoaderH3M::readHeader()
@ -774,12 +775,12 @@ void CMapLoaderH3M::readAllowedArtifacts()
void CMapLoaderH3M::readAllowedSpellsAbilities() void CMapLoaderH3M::readAllowedSpellsAbilities()
{ {
map->allowedSpell = VLC->spellh->getDefaultAllowed(); map->allowedSpells = VLC->spellh->getDefaultAllowed();
map->allowedAbilities = VLC->skillh->getDefaultAllowed(); map->allowedAbilities = VLC->skillh->getDefaultAllowed();
if(features.levelSOD) if(features.levelSOD)
{ {
reader->readBitmaskSpells(map->allowedSpell, true); reader->readBitmaskSpells(map->allowedSpells, true);
reader->readBitmaskSkills(map->allowedAbilities, true); reader->readBitmaskSkills(map->allowedAbilities, true);
} }
} }

View File

@ -834,7 +834,7 @@ void CMapFormatJson::serializeOptions(JsonSerializeFormat & handler)
handler.serializeLIC("allowedArtifacts", &ArtifactID::decode, &ArtifactID::encode, VLC->arth->getDefaultAllowed(), map->allowedArtifact); handler.serializeLIC("allowedArtifacts", &ArtifactID::decode, &ArtifactID::encode, VLC->arth->getDefaultAllowed(), map->allowedArtifact);
handler.serializeLIC("allowedSpells", &SpellID::decode, &SpellID::encode, VLC->spellh->getDefaultAllowed(), map->allowedSpell); handler.serializeLIC("allowedSpells", &SpellID::decode, &SpellID::encode, VLC->spellh->getDefaultAllowed(), map->allowedSpells);
//todo:events //todo:events
} }

View File

@ -413,7 +413,7 @@ void CMapGenerator::addHeaderInfo()
m.difficulty = 1; m.difficulty = 1;
addPlayerInfo(); addPlayerInfo();
m.waterMap = (mapGenOptions.getWaterContent() != EWaterContent::EWaterContent::NONE); m.waterMap = (mapGenOptions.getWaterContent() != EWaterContent::EWaterContent::NONE);
banWaterHeroes(); m.banWaterContent();
} }
int CMapGenerator::getNextMonlithIndex() int CMapGenerator::getNextMonlithIndex()
@ -453,24 +453,6 @@ const std::vector<ArtifactID> & CMapGenerator::getAllPossibleQuestArtifacts() co
return questArtifacts; return questArtifacts;
} }
void CMapGenerator::banWaterHeroes()
{
//This also bans only-land heroes on wazter maps
auto isWaterMap = map->getMap(this).isWaterMap();
for (int j = 0; j < map->getMap(this).allowedHeroes.size(); j++)
{
if (map->getMap(this).allowedHeroes[j])
{
auto* h = dynamic_cast<const CHero*>(VLC->heroTypes()->getByIndex(j));
if ((h->onlyOnWaterMap && !isWaterMap) || (h->onlyOnMapWithoutWater && isWaterMap)) //TODO: Refactor? Move to hero?
{
banHero(HeroTypeID(j));
}
}
}
}
const std::vector<HeroTypeID> CMapGenerator::getAllPossibleHeroes() const const std::vector<HeroTypeID> CMapGenerator::getAllPossibleHeroes() const
{ {
auto isWaterMap = map->getMap(this).isWaterMap(); auto isWaterMap = map->getMap(this).isWaterMap();
@ -503,7 +485,7 @@ void CMapGenerator::banQuestArt(const ArtifactID & id)
void CMapGenerator::banHero(const HeroTypeID & id) void CMapGenerator::banHero(const HeroTypeID & id)
{ {
//TODO: Protect with mutex //TODO: Protect with mutex
map->getMap(this).allowedHeroes[id] = false; map->getMap(this).banHero(id);
} }
Zone * CMapGenerator::getZoneWater() const Zone * CMapGenerator::getZoneWater() const

View File

@ -63,7 +63,6 @@ public:
int getPrisonsRemaning() const; int getPrisonsRemaning() const;
std::shared_ptr<CZonePlacer> getZonePlacer() const; std::shared_ptr<CZonePlacer> getZonePlacer() const;
const std::vector<ArtifactID> & getAllPossibleQuestArtifacts() const; const std::vector<ArtifactID> & getAllPossibleQuestArtifacts() const;
void banWaterHeroes();
const std::vector<HeroTypeID> getAllPossibleHeroes() const; const std::vector<HeroTypeID> getAllPossibleHeroes() const;
void banQuestArt(const ArtifactID & id); void banQuestArt(const ArtifactID & id);
void banHero(const HeroTypeID& id); void banHero(const HeroTypeID& id);

View File

@ -343,9 +343,9 @@ ui32 RmgMap::getTotalZoneCount() const
bool RmgMap::isAllowedSpell(const SpellID & sid) const bool RmgMap::isAllowedSpell(const SpellID & sid) const
{ {
assert(sid >= 0); assert(sid >= 0);
if (sid < mapInstance->allowedSpell.size()) if (sid < mapInstance->allowedSpells.size())
{ {
return mapInstance->allowedSpell[sid]; return mapInstance->allowedSpells[sid];
} }
else else
return false; return false;

View File

@ -784,6 +784,8 @@ CSpell * CSpellHandler::loadFromJson(const std::string & scope, const JsonNode &
spell->special = flags["special"].Bool(); spell->special = flags["special"].Bool();
spell->onlyOnWaterMap = json["onlyOnWaterMap"].Bool();
auto findBonus = [&](const std::string & name, std::vector<BonusType> & vec) auto findBonus = [&](const std::string & name, std::vector<BonusType> & vec)
{ {
auto it = bonusNameMap.find(name); auto it = bonusNameMap.find(name);

View File

@ -199,7 +199,7 @@ public:
bool combat; //is this spell combat (true) or adventure (false) bool combat; //is this spell combat (true) or adventure (false)
bool creatureAbility; //if true, only creatures can use this spell bool creatureAbility; //if true, only creatures can use this spell
si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
bool onlyOnWaterMap; //Spell will be banned on maps without water
std::vector<SpellID> counteredSpells; //spells that are removed when effect of this spell is placed on creature (for bless-curse, haste-slow, and similar pairs) std::vector<SpellID> counteredSpells; //spells that are removed when effect of this spell is placed on creature (for bless-curse, haste-slow, and similar pairs)
JsonNode targetCondition; //custom condition on what spell can affect JsonNode targetCondition; //custom condition on what spell can affect
@ -305,6 +305,7 @@ public:
h & school; h & school;
h & animationInfo; h & animationInfo;
h & nonMagical; h & nonMagical;
h& onlyOnWaterMap;
} }
friend class CSpellHandler; friend class CSpellHandler;
friend class Graphics; friend class Graphics;

View File

@ -88,9 +88,9 @@ QList<QString> RewardsWidget::getListForType(RewardType typeId)
break; break;
case RewardType::SPELL: case RewardType::SPELL:
for(int i = 0; i < map.allowedSpell.size(); ++i) for(int i = 0; i < map.allowedSpells.size(); ++i)
{ {
if(map.allowedSpell[i]) if(map.allowedSpells[i])
result.append(QString::fromStdString(VLC->spells()->getByIndex(i)->getNameTranslated())); result.append(QString::fromStdString(VLC->spells()->getByIndex(i)->getNameTranslated()));
} }
break; break;

View File

@ -94,9 +94,9 @@ void MapController::repairMap()
{ {
map()->allowedArtifact.resize(VLC->arth->getDefaultAllowed().size()); map()->allowedArtifact.resize(VLC->arth->getDefaultAllowed().size());
} }
if(VLC->spellh->getDefaultAllowed().size() > map()->allowedSpell.size()) if(VLC->spellh->getDefaultAllowed().size() > map()->allowedSpells.size())
{ {
map()->allowedSpell.resize(VLC->spellh->getDefaultAllowed().size()); map()->allowedSpells.resize(VLC->spellh->getDefaultAllowed().size());
} }
if(VLC->heroh->getDefaultAllowed().size() > map()->allowedHeroes.size()) if(VLC->heroh->getDefaultAllowed().size() > map()->allowedHeroes.size())
{ {

View File

@ -116,12 +116,12 @@ MapSettings::MapSettings(MapController & ctrl, QWidget *parent) :
item->setCheckState(controller.map()->allowedAbilities[i] ? Qt::Checked : Qt::Unchecked); item->setCheckState(controller.map()->allowedAbilities[i] ? Qt::Checked : Qt::Unchecked);
ui->listAbilities->addItem(item); ui->listAbilities->addItem(item);
} }
for(int i = 0; i < controller.map()->allowedSpell.size(); ++i) for(int i = 0; i < controller.map()->allowedSpells.size(); ++i)
{ {
auto * item = new QListWidgetItem(QString::fromStdString(VLC->spellh->objects[i]->getNameTranslated())); auto * item = new QListWidgetItem(QString::fromStdString(VLC->spellh->objects[i]->getNameTranslated()));
item->setData(Qt::UserRole, QVariant::fromValue(i)); item->setData(Qt::UserRole, QVariant::fromValue(i));
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(controller.map()->allowedSpell[i] ? Qt::Checked : Qt::Unchecked); item->setCheckState(controller.map()->allowedSpells[i] ? Qt::Checked : Qt::Unchecked);
ui->listSpells->addItem(item); ui->listSpells->addItem(item);
} }
for(int i = 0; i < controller.map()->allowedArtifact.size(); ++i) for(int i = 0; i < controller.map()->allowedArtifact.size(); ++i)
@ -525,10 +525,10 @@ void MapSettings::on_pushButton_clicked()
auto * item = ui->listAbilities->item(i); auto * item = ui->listAbilities->item(i);
controller.map()->allowedAbilities[i] = item->checkState() == Qt::Checked; controller.map()->allowedAbilities[i] = item->checkState() == Qt::Checked;
} }
for(int i = 0; i < controller.map()->allowedSpell.size(); ++i) for(int i = 0; i < controller.map()->allowedSpells.size(); ++i)
{ {
auto * item = ui->listSpells->item(i); auto * item = ui->listSpells->item(i);
controller.map()->allowedSpell[i] = item->checkState() == Qt::Checked; controller.map()->allowedSpells[i] = item->checkState() == Qt::Checked;
} }
for(int i = 0; i < controller.map()->allowedArtifact.size(); ++i) for(int i = 0; i < controller.map()->allowedArtifact.size(); ++i)
{ {

View File

@ -140,7 +140,7 @@ std::list<Validator::Issue> Validator::validate(const CMap * map)
{ {
if(ins->storedArtifact) if(ins->storedArtifact)
{ {
if(!map->allowedSpell[ins->storedArtifact->getId().getNum()]) if(!map->allowedSpells[ins->storedArtifact->getId().getNum()])
issues.emplace_back(QString("Spell scroll %1 is prohibited by map settings").arg(ins->getObjectName().c_str()), false); issues.emplace_back(QString("Spell scroll %1 is prohibited by map settings").arg(ins->getObjectName().c_str()), false);
} }
else else