mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-15 20:03:15 +02:00
@@ -1358,13 +1358,9 @@ std::string CBuildWindow::getTextForState(int state)
|
|||||||
{
|
{
|
||||||
return town->town->buildings.at(build)->Name();
|
return town->town->buildings.at(build)->Name();
|
||||||
};
|
};
|
||||||
/*auto toBool = [&](const BuildingID build)
|
|
||||||
{
|
|
||||||
return town->hasBuilt(build);
|
|
||||||
};*/
|
|
||||||
|
|
||||||
ret = CGI->generaltexth->allTexts[52];
|
ret = CGI->generaltexth->allTexts[52];
|
||||||
ret += "\n" + building->requirements.toString(toStr);
|
ret += "\n" + town->genBuildingRequirements(building->bid).toString(toStr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EBuildingState::MISSING_BASE:
|
case EBuildingState::MISSING_BASE:
|
||||||
|
@@ -75,7 +75,8 @@ void Graphics::loadPaletteAndColors()
|
|||||||
neutralColorPalette[i].r = reader.readUInt8();
|
neutralColorPalette[i].r = reader.readUInt8();
|
||||||
neutralColorPalette[i].g = reader.readUInt8();
|
neutralColorPalette[i].g = reader.readUInt8();
|
||||||
neutralColorPalette[i].b = reader.readUInt8();
|
neutralColorPalette[i].b = reader.readUInt8();
|
||||||
CSDL_Ext::colorSetAlpha(neutralColorPalette[i], !reader.readUInt8());
|
reader.readUInt8(); // this is "flags" entry, not alpha
|
||||||
|
CSDL_Ext::colorSetAlpha(neutralColorPalette[i], SDL_ALPHA_OPAQUE);
|
||||||
}
|
}
|
||||||
//colors initialization
|
//colors initialization
|
||||||
SDL_Color colors[] = {
|
SDL_Color colors[] = {
|
||||||
|
@@ -164,7 +164,7 @@ void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & char
|
|||||||
switch(srcLine[dx])
|
switch(srcLine[dx])
|
||||||
{
|
{
|
||||||
case 1: //black "shadow"
|
case 1: //black "shadow"
|
||||||
std::fill(dstPixel, dstPixel + bpp, 0);
|
colorPutter(dstPixel, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
case 255: //text colour
|
case 255: //text colour
|
||||||
colorPutter(dstPixel, color.r, color.g, color.b);
|
colorPutter(dstPixel, color.r, color.g, color.b);
|
||||||
|
@@ -110,7 +110,7 @@
|
|||||||
},
|
},
|
||||||
"dwarvenTreasury" : {
|
"dwarvenTreasury" : {
|
||||||
"index" : 1,
|
"index" : 1,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Dwarven Treasury",
|
"name" : "Dwarven Treasury",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 2000,
|
"value" : 2000,
|
||||||
@@ -197,7 +197,7 @@
|
|||||||
},
|
},
|
||||||
"griffinConservatory" : {
|
"griffinConservatory" : {
|
||||||
"index" : 2,
|
"index" : 2,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Griffin Conservatory",
|
"name" : "Griffin Conservatory",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 2000,
|
"value" : 2000,
|
||||||
@@ -268,7 +268,7 @@
|
|||||||
},
|
},
|
||||||
"inpCache" : {
|
"inpCache" : {
|
||||||
"index" : 3,
|
"index" : 3,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Imp Cache",
|
"name" : "Imp Cache",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 5000,
|
"value" : 5000,
|
||||||
@@ -354,7 +354,7 @@
|
|||||||
},
|
},
|
||||||
"medusaStore" : {
|
"medusaStore" : {
|
||||||
"index" : 4,
|
"index" : 4,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Medusa Stores",
|
"name" : "Medusa Stores",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 1500,
|
"value" : 1500,
|
||||||
@@ -441,7 +441,7 @@
|
|||||||
},
|
},
|
||||||
"nagaBank" : {
|
"nagaBank" : {
|
||||||
"index" : 5,
|
"index" : 5,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Naga Bank",
|
"name" : "Naga Bank",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 3000,
|
"value" : 3000,
|
||||||
@@ -528,7 +528,7 @@
|
|||||||
},
|
},
|
||||||
"dragonflyHive" : {
|
"dragonflyHive" : {
|
||||||
"index" : 6,
|
"index" : 6,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Dragon Fly Hive",
|
"name" : "Dragon Fly Hive",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 9000,
|
"value" : 9000,
|
||||||
@@ -605,7 +605,7 @@
|
|||||||
"types" : {
|
"types" : {
|
||||||
"shipwreck" : {
|
"shipwreck" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Shipwreck",
|
"name" : "Shipwreck",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 2000,
|
"value" : 2000,
|
||||||
@@ -696,7 +696,7 @@
|
|||||||
"types" : {
|
"types" : {
|
||||||
"derelictShip" : {
|
"derelictShip" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Derelict Ship",
|
"name" : "Derelict Ship",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 4000,
|
"value" : 4000,
|
||||||
@@ -788,7 +788,7 @@
|
|||||||
"types" : {
|
"types" : {
|
||||||
"crypt" : {
|
"crypt" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Crypt",
|
"name" : "Crypt",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 1000,
|
"value" : 1000,
|
||||||
@@ -877,7 +877,7 @@
|
|||||||
"types" : {
|
"types" : {
|
||||||
"dragonUtopia" : {
|
"dragonUtopia" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Dragon Utopia",
|
"name" : "Dragon Utopia",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 10000,
|
"value" : 10000,
|
||||||
@@ -986,7 +986,7 @@
|
|||||||
"types" : {
|
"types" : {
|
||||||
"pyramid" : {
|
"pyramid" : {
|
||||||
"index" : 0,
|
"index" : 0,
|
||||||
"resetDuraition" : 28,
|
"resetDuration" : 28,
|
||||||
"name" : "Pyramid",
|
"name" : "Pyramid",
|
||||||
"rmg" : {
|
"rmg" : {
|
||||||
"value" : 5000,
|
"value" : 5000,
|
||||||
|
@@ -1675,8 +1675,11 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleStackIsImmune(co
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spell->isRisingSpell())
|
if (spell->isRisingSpell() && spell->id != SpellID::SACRIFICE)
|
||||||
{
|
{
|
||||||
|
// following does apply to resurrect and animate dead(?) only
|
||||||
|
// for sacrifice health calculation and health limit check don't matter
|
||||||
|
|
||||||
if(subject->count >= subject->baseAmount)
|
if(subject->count >= subject->baseAmount)
|
||||||
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
|
||||||
|
|
||||||
@@ -1783,12 +1786,27 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
|||||||
const CGHeroInstance * caster = battleGetFightingHero(side);
|
const CGHeroInstance * caster = battleGetFightingHero(side);
|
||||||
const CSpell::TargetInfo ti = spell->getTargetInfo(caster->getSpellSchoolLevel(spell));
|
const CSpell::TargetInfo ti = spell->getTargetInfo(caster->getSpellSchoolLevel(spell));
|
||||||
bool targetExists = false;
|
bool targetExists = false;
|
||||||
for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway
|
bool targetToSacrificeExists = false; // for sacrifice we have to check for 2 targets (one dead to resurrect and one living to destroy)
|
||||||
|
|
||||||
|
for(const CStack * stack : battleGetAllStacks()) //dead stacks will be immune anyway
|
||||||
{
|
{
|
||||||
bool immune = ESpellCastProblem::OK != battleStackIsImmune(caster, spell, mode, stack);
|
bool immune = ESpellCastProblem::OK != battleStackIsImmune(caster, spell, mode, stack);
|
||||||
bool casterStack = stack->owner == caster->getOwner();
|
bool casterStack = stack->owner == caster->getOwner();
|
||||||
|
|
||||||
if(!immune)
|
if(spell->id == SpellID::SACRIFICE)
|
||||||
|
{
|
||||||
|
if(!immune && casterStack)
|
||||||
|
{
|
||||||
|
if(stack->alive())
|
||||||
|
targetToSacrificeExists = true;
|
||||||
|
else
|
||||||
|
targetExists = true;
|
||||||
|
if(targetExists && targetToSacrificeExists)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!immune)
|
||||||
|
{
|
||||||
switch (spell->positiveness)
|
switch (spell->positiveness)
|
||||||
{
|
{
|
||||||
case CSpell::POSITIVE:
|
case CSpell::POSITIVE:
|
||||||
@@ -1810,8 +1828,9 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleCanCastThisSpell
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(!targetExists)
|
if(!targetExists || (spell->id == SpellID::SACRIFICE && !targetExists && !targetToSacrificeExists))
|
||||||
{
|
{
|
||||||
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
return ESpellCastProblem::NO_APPROPRIATE_TARGET;
|
||||||
}
|
}
|
||||||
|
@@ -403,20 +403,17 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
|
|||||||
return EBuildingState::NO_WATER; //lack of water
|
return EBuildingState::NO_WATER; //lack of water
|
||||||
}
|
}
|
||||||
|
|
||||||
auto buildTest = [&](const BuildingID & id)
|
auto buildTest = [&](BuildingID id) -> bool
|
||||||
{
|
{
|
||||||
return t->hasBuilt(id);
|
return t->hasBuilt(id);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!building->requirements.test(buildTest))
|
if (!t->genBuildingRequirements(ID).test(buildTest))
|
||||||
return EBuildingState::PREREQUIRES;
|
return EBuildingState::PREREQUIRES;
|
||||||
|
|
||||||
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
if(t->builded >= VLC->modh->settings.MAX_BUILDING_PER_TURN)
|
||||||
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
return EBuildingState::CANT_BUILD_TODAY; //building limit
|
||||||
|
|
||||||
if (building->upgrade != BuildingID::NONE && !t->hasBuilt(building->upgrade))
|
|
||||||
return EBuildingState::MISSING_BASE;
|
|
||||||
|
|
||||||
//checking resources
|
//checking resources
|
||||||
if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
|
if(!building->resources.canBeAfforded(getPlayer(t->tempOwner)->resources))
|
||||||
return EBuildingState::NO_RESOURCES; //lack of res
|
return EBuildingState::NO_RESOURCES; //lack of res
|
||||||
|
@@ -45,6 +45,11 @@ namespace LogicalExpressionDetail
|
|||||||
|
|
||||||
std::vector<Variant> expressions;
|
std::vector<Variant> expressions;
|
||||||
|
|
||||||
|
bool operator == (const Element & other) const
|
||||||
|
{
|
||||||
|
return expressions == other.expressions;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
void serialize(Handler & h, const int version)
|
void serialize(Handler & h, const int version)
|
||||||
{
|
{
|
||||||
@@ -147,39 +152,73 @@ namespace LogicalExpressionDetail
|
|||||||
|
|
||||||
/// Simple foreach visitor
|
/// Simple foreach visitor
|
||||||
template <typename ContainedClass>
|
template <typename ContainedClass>
|
||||||
class ForEachVisitor : public boost::static_visitor<void>
|
class ForEachVisitor : public boost::static_visitor<typename ExpressionBase<ContainedClass>::Variant>
|
||||||
{
|
{
|
||||||
typedef ExpressionBase<ContainedClass> Base;
|
typedef ExpressionBase<ContainedClass> Base;
|
||||||
|
|
||||||
std::function<void(typename Base::Value &)> visitor;
|
std::function<typename Base::Variant(const typename Base::Value &)> visitor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ForEachVisitor(std::function<void(typename Base::Value &)> visitor):
|
ForEachVisitor(std::function<typename Base::Variant(const typename Base::Value &)> visitor):
|
||||||
visitor(visitor)
|
visitor(visitor)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
//FIXME: duplicated code
|
typename Base::Variant operator()(const typename Base::Value & element) const
|
||||||
void operator()(typename Base::OperatorAny & element) const
|
|
||||||
{
|
{
|
||||||
for (auto & entry : element.expressions)
|
return visitor(element);
|
||||||
boost::apply_visitor(*this, entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(typename Base::OperatorAll & element) const
|
template <typename Type>
|
||||||
|
typename Base::Variant operator()(Type element) const
|
||||||
{
|
{
|
||||||
for (auto & entry : element.expressions)
|
for (auto & entry : element.expressions)
|
||||||
boost::apply_visitor(*this, entry);
|
entry = boost::apply_visitor(*this, entry);
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Minimizing visitor that removes all redundant elements from variant (e.g. AllOf inside another AllOf can be merged safely)
|
||||||
|
template <typename ContainedClass>
|
||||||
|
class MinimizingVisitor : public boost::static_visitor<typename ExpressionBase<ContainedClass>::Variant>
|
||||||
|
{
|
||||||
|
typedef ExpressionBase<ContainedClass> Base;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typename Base::Variant operator()(const typename Base::Value & element) const
|
||||||
|
{
|
||||||
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(typename Base::OperatorNone & element) const
|
template <typename Type>
|
||||||
|
typename Base::Variant operator()(const Type & element) const
|
||||||
{
|
{
|
||||||
for (auto & entry : element.expressions)
|
Type ret;
|
||||||
boost::apply_visitor(*this, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(typename Base::Value & element) const
|
for (auto & entryRO : element.expressions)
|
||||||
{
|
{
|
||||||
visitor(element);
|
auto entry = boost::apply_visitor(*this, entryRO);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// copy entries from child of this type
|
||||||
|
auto sublist = boost::get<Type>(entry).expressions;
|
||||||
|
std::move(sublist.begin(), sublist.end(), std::back_inserter(ret.expressions));
|
||||||
|
}
|
||||||
|
catch (boost::bad_get &)
|
||||||
|
{
|
||||||
|
// different type (e.g. allOf vs oneOf) just copy
|
||||||
|
ret.expressions.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto it = ret.expressions.begin(); it != ret.expressions.end();)
|
||||||
|
{
|
||||||
|
if (std::find(ret.expressions.begin(), it, *it) != it)
|
||||||
|
it = ret.expressions.erase(it); // erase duplicate
|
||||||
|
else
|
||||||
|
it++; // goto next
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -370,16 +409,23 @@ public:
|
|||||||
std::swap(data, expr.data);
|
std::swap(data, expr.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Variant get()
|
Variant get() const
|
||||||
{
|
{
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simple visitor that visits all entries in expression
|
/// Simple visitor that visits all entries in expression
|
||||||
void forEach(std::function<void(Value &)> visitor)
|
Variant morph(std::function<Variant(const Value &)> morpher) const
|
||||||
{
|
{
|
||||||
LogicalExpressionDetail::ForEachVisitor<Value> testVisitor(visitor);
|
LogicalExpressionDetail::ForEachVisitor<Value> visitor(morpher);
|
||||||
boost::apply_visitor(testVisitor, data);
|
return boost::apply_visitor(visitor, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Minimizes expression, removing any redundant elements
|
||||||
|
void minimize()
|
||||||
|
{
|
||||||
|
LogicalExpressionDetail::MinimizingVisitor<Value> visitor;
|
||||||
|
data = boost::apply_visitor(visitor, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// calculates if expression evaluates to "true".
|
/// calculates if expression evaluates to "true".
|
||||||
|
@@ -396,7 +396,7 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
|
|||||||
|
|
||||||
for (TriggeredEvent & event : gs->map->triggeredEvents)
|
for (TriggeredEvent & event : gs->map->triggeredEvents)
|
||||||
{
|
{
|
||||||
auto patcher = [&](EventCondition & cond)
|
auto patcher = [&](EventCondition cond) -> EventExpression::Variant
|
||||||
{
|
{
|
||||||
if (cond.object == obj)
|
if (cond.object == obj)
|
||||||
{
|
{
|
||||||
@@ -411,8 +411,9 @@ DLL_LINKAGE void RemoveObject::applyGs( CGameState *gs )
|
|||||||
cond.value = 0; // destroyed object, from now on can not be fulfilled
|
cond.value = 0; // destroyed object, from now on can not be fulfilled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return cond;
|
||||||
};
|
};
|
||||||
event.trigger.forEach(patcher);
|
event.trigger = event.trigger.morph(patcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
gs->map->objects[id.getNum()].dellNull();
|
gs->map->objects[id.getNum()].dellNull();
|
||||||
|
@@ -1004,6 +1004,40 @@ bool CGTownInstance::hasBuilt(BuildingID buildingID) const
|
|||||||
return vstd::contains(builtBuildings, buildingID);
|
return vstd::contains(builtBuildings, buildingID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBuilding::TRequired CGTownInstance::genBuildingRequirements(BuildingID buildID) const
|
||||||
|
{
|
||||||
|
const CBuilding * building = town->buildings.at(buildID);
|
||||||
|
|
||||||
|
std::function<CBuilding::TRequired::Variant(const BuildingID &)> dependTest =
|
||||||
|
[&](const BuildingID & id) -> CBuilding::TRequired::Variant
|
||||||
|
{
|
||||||
|
const CBuilding * build = town->buildings.at(id);
|
||||||
|
|
||||||
|
if (!hasBuilt(id))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
if (build->upgrade != BuildingID::NONE && !hasBuilt(build->upgrade))
|
||||||
|
return build->upgrade;
|
||||||
|
|
||||||
|
return build->requirements.morph(dependTest);
|
||||||
|
};
|
||||||
|
|
||||||
|
CBuilding::TRequired::OperatorAll requirements;
|
||||||
|
if (building->upgrade != BuildingID::NONE)
|
||||||
|
{
|
||||||
|
const CBuilding * upgr = town->buildings.at(building->upgrade);
|
||||||
|
|
||||||
|
requirements.expressions.push_back(upgr->bid);
|
||||||
|
requirements.expressions.push_back(upgr->requirements.morph(dependTest));
|
||||||
|
}
|
||||||
|
requirements.expressions.push_back(building->requirements.morph(dependTest));
|
||||||
|
|
||||||
|
CBuilding::TRequired::Variant variant(requirements);
|
||||||
|
CBuilding::TRequired ret(variant);
|
||||||
|
ret.minimize();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void CGTownInstance::addHeroToStructureVisitors( const CGHeroInstance *h, si32 structureInstanceID ) const
|
void CGTownInstance::addHeroToStructureVisitors( const CGHeroInstance *h, si32 structureInstanceID ) const
|
||||||
{
|
{
|
||||||
if(visitingHero == h)
|
if(visitingHero == h)
|
||||||
|
@@ -232,6 +232,8 @@ public:
|
|||||||
bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero
|
bool armedGarrison() const; //true if town has creatures in garrison or garrisoned hero
|
||||||
int getTownLevel() const;
|
int getTownLevel() const;
|
||||||
|
|
||||||
|
CBuilding::TRequired genBuildingRequirements(BuildingID build) const;
|
||||||
|
|
||||||
void removeCapitols (PlayerColor owner) const;
|
void removeCapitols (PlayerColor owner) const;
|
||||||
void addHeroToStructureVisitors(const CGHeroInstance *h, si32 structureInstanceID) const; //hero must be visiting or garrisoned in town
|
void addHeroToStructureVisitors(const CGHeroInstance *h, si32 structureInstanceID) const; //hero must be visiting or garrisoned in town
|
||||||
|
|
||||||
|
@@ -191,7 +191,10 @@ void CGObjectInstance::setType(si32 ID, si32 subID)
|
|||||||
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
//recalculate blockvis tiles - new appearance might have different blockmap than before
|
||||||
cb->gameState()->map->removeBlockVisTiles(this, true);
|
cb->gameState()->map->removeBlockVisTiles(this, true);
|
||||||
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
auto handler = VLC->objtypeh->getHandlerFor(ID, subID);
|
||||||
appearance = handler->getTemplates(tile.terType).at(0);
|
if (!handler->getTemplates(tile.terType).empty())
|
||||||
|
appearance = handler->getTemplates(tile.terType)[0];
|
||||||
|
else
|
||||||
|
appearance = handler->getTemplates()[0]; // get at least some appearance since alternative is crash
|
||||||
cb->gameState()->map->addBlockVisTiles(this);
|
cb->gameState()->map->addBlockVisTiles(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -421,7 +421,7 @@ void CRewardableObject::setPropertyDer(ui8 what, ui32 val)
|
|||||||
|
|
||||||
void CRewardableObject::newTurn() const
|
void CRewardableObject::newTurn() const
|
||||||
{
|
{
|
||||||
if (resetDuration != 0 && cb->getDate(Date::DAY) % resetDuration == 0)
|
if (resetDuration != 0 && cb->getDate(Date::DAY) % (resetDuration+1) == 0)
|
||||||
cb->setObjProperty(id, ObjProperty::REWARD_RESET, 0);
|
cb->setObjProperty(id, ObjProperty::REWARD_RESET, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -303,6 +303,7 @@ void CBankInstanceConstructor::configureObject(CGObjectInstance * object, CRando
|
|||||||
CBankInfo::CBankInfo(JsonVector config):
|
CBankInfo::CBankInfo(JsonVector config):
|
||||||
config(config)
|
config(config)
|
||||||
{
|
{
|
||||||
|
assert(!config.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
static void addStackToArmy(IObjectInfo::CArmyStructure & army, const CCreature * crea, si32 amount)
|
||||||
|
@@ -184,4 +184,10 @@ public:
|
|||||||
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
|
||||||
|
|
||||||
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const;
|
std::unique_ptr<IObjectInfo> getObjectInfo(ObjectTemplate tmpl) const;
|
||||||
|
|
||||||
|
template <typename Handler> void serialize(Handler &h, const int version)
|
||||||
|
{
|
||||||
|
h & levels & bankResetDuration;
|
||||||
|
h & static_cast<CDefaultObjectTypeHandler<CBank>&>(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@@ -202,6 +202,7 @@ namespace JsonRandom
|
|||||||
for (auto creaID : crea->upgrades)
|
for (auto creaID : crea->upgrades)
|
||||||
info.allowedCreatures.push_back(VLC->creh->creatures[creaID]);
|
info.allowedCreatures.push_back(VLC->creh->creatures[creaID]);
|
||||||
}
|
}
|
||||||
|
ret.push_back(info);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@@ -441,7 +441,7 @@ void CMap::checkForObjectives()
|
|||||||
// NOTE: probably should be moved to MapFormatH3M.cpp
|
// NOTE: probably should be moved to MapFormatH3M.cpp
|
||||||
for (TriggeredEvent & event : triggeredEvents)
|
for (TriggeredEvent & event : triggeredEvents)
|
||||||
{
|
{
|
||||||
auto patcher = [&](EventCondition & cond)
|
auto patcher = [&](EventCondition cond) -> EventExpression::Variant
|
||||||
{
|
{
|
||||||
switch (cond.condition)
|
switch (cond.condition)
|
||||||
{
|
{
|
||||||
@@ -491,8 +491,9 @@ void CMap::checkForObjectives()
|
|||||||
//break; case EventCondition::DAYS_WITHOUT_TOWN:
|
//break; case EventCondition::DAYS_WITHOUT_TOWN:
|
||||||
//break; case EventCondition::STANDARD_WIN:
|
//break; case EventCondition::STANDARD_WIN:
|
||||||
}
|
}
|
||||||
|
return cond;
|
||||||
};
|
};
|
||||||
event.trigger.forEach(patcher);
|
event.trigger = event.trigger.morph(patcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -676,16 +676,17 @@ void CMapLoaderH3M::readAllowedArtifacts()
|
|||||||
// Messy, but needed
|
// Messy, but needed
|
||||||
for (TriggeredEvent & event : map->triggeredEvents)
|
for (TriggeredEvent & event : map->triggeredEvents)
|
||||||
{
|
{
|
||||||
auto patcher = [&](EventCondition & cond)
|
auto patcher = [&](EventCondition cond) -> EventExpression::Variant
|
||||||
{
|
{
|
||||||
if (cond.condition == EventCondition::HAVE_ARTIFACT ||
|
if (cond.condition == EventCondition::HAVE_ARTIFACT ||
|
||||||
cond.condition == EventCondition::TRANSPORT)
|
cond.condition == EventCondition::TRANSPORT)
|
||||||
{
|
{
|
||||||
map->allowedArtifact[cond.objectType] = false;
|
map->allowedArtifact[cond.objectType] = false;
|
||||||
}
|
}
|
||||||
|
return cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
event.trigger.forEach(patcher);
|
event.trigger = event.trigger.morph(patcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user