mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-25 22:42:04 +02:00
Docs
This commit is contained in:
@@ -144,7 +144,7 @@
|
||||
},
|
||||
"val" : {
|
||||
"type" : "number",
|
||||
"description" : "Default number of charges"
|
||||
"description" : "Default starting charge amount"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,5 +87,18 @@ In order to make functional artifact you also need:
|
||||
"bonusesPerLevel" : {},
|
||||
"thresholdBonuses" : {},
|
||||
}
|
||||
|
||||
// Optional, used for artifacts with charges.
|
||||
"charged" : {
|
||||
// Artifact discharging action
|
||||
// SPELLCAST - Consumes a charge for each spellcast. Applies to every spell added through the "bonuses" section.
|
||||
// BATTLE - Consumes one charge per battle.
|
||||
// BUILDING (not implemented)
|
||||
"usageType": "BATTLE",
|
||||
// Optional, by default is false. Remove when fully discharged
|
||||
"removeOnDepletion" : true,
|
||||
// Optional, by default is 0. Default starting charge amount.
|
||||
"val" : 2,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -152,20 +152,6 @@ std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope,
|
||||
JsonUtils::parseBonus(bonus["bonus"], &art->thresholdBonuses.back().second);
|
||||
}
|
||||
}
|
||||
if(!node["charged"].isNull())
|
||||
{
|
||||
art->setCondition(stringToDischargeCond(node["charged"]["usageType"].String()));
|
||||
if(!node["charged"]["removeOnDepletion"].isNull())
|
||||
art->setRemoveOnDepletion(node["charged"]["removeOnDepletion"].Bool());
|
||||
if(!node["charged"]["val"].isNull())
|
||||
{
|
||||
const auto charges = node["charged"]["val"].Integer();
|
||||
if(charges < 0)
|
||||
logMod->warn("Warning! Charged artifact number of charges cannot be less than zero %d!", charges);
|
||||
else
|
||||
art->setDefaultStartCharges(charges);
|
||||
}
|
||||
}
|
||||
|
||||
art->id = ArtifactID(index);
|
||||
art->identifier = identifier;
|
||||
@@ -235,6 +221,23 @@ std::shared_ptr<CArtifact> CArtHandler::loadFromJson(const std::string & scope,
|
||||
if(art->isTradable())
|
||||
art->possibleSlots.at(ArtBearer::ALTAR).push_back(ArtifactPosition::ALTAR);
|
||||
|
||||
if(!node["charged"].isNull())
|
||||
{
|
||||
art->setCondition(stringToDischargeCond(node["charged"]["usageType"].String()));
|
||||
if(!node["charged"]["removeOnDepletion"].isNull())
|
||||
art->setRemoveOnDepletion(node["charged"]["removeOnDepletion"].Bool());
|
||||
if(!node["charged"]["val"].isNull())
|
||||
{
|
||||
const auto charges = node["charged"]["val"].Integer();
|
||||
if(charges < 0)
|
||||
logMod->warn("Warning! Charged artifact %s number of charges cannot be less than zero %d!", art->getNameTranslated(), charges);
|
||||
else
|
||||
art->setDefaultStartCharges(charges);
|
||||
}
|
||||
if(art->getDischargeCondition() == DischargeArtifactCondition::SPELLCAST && art->getBonusesOfType(BonusType::SPELL)->size() == 0)
|
||||
logMod->warn("Warning! %s condition of discharge is \"SPELLCAST\", but there is not a single spell.", art->getNameTranslated());
|
||||
}
|
||||
|
||||
return art;
|
||||
}
|
||||
|
||||
@@ -326,7 +329,7 @@ EArtifactClass CArtHandler::stringToClass(const std::string & className)
|
||||
return EArtifactClass::ART_SPECIAL;
|
||||
}
|
||||
|
||||
DischargeArtifactCondition CArtHandler::stringToDischargeCond(const std::string & cond)
|
||||
DischargeArtifactCondition CArtHandler::stringToDischargeCond(const std::string & cond) const
|
||||
{
|
||||
const std::unordered_map<std::string, DischargeArtifactCondition> growingConditionsMap =
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
void addBonuses(CArtifact * art, const JsonNode & bonusList);
|
||||
|
||||
static EArtifactClass stringToClass(const std::string & className); //TODO: rework EartClass to make this a constructor
|
||||
DischargeArtifactCondition stringToDischargeCond(const std::string & cond);
|
||||
DischargeArtifactCondition stringToDischargeCond(const std::string & cond) const;
|
||||
|
||||
bool legalArtifact(const ArtifactID & id) const;
|
||||
static void makeItCreatureArt(CArtifact * a, bool onlyCreature = true);
|
||||
|
||||
@@ -257,9 +257,9 @@ bool CChargedArtifact::isCharged() const
|
||||
return condition.has_value();
|
||||
}
|
||||
|
||||
void CChargedArtifact::setCondition(const DischargeArtifactCondition & condition)
|
||||
void CChargedArtifact::setCondition(const DischargeArtifactCondition & dischargeCondition)
|
||||
{
|
||||
this->condition = condition;
|
||||
condition = dischargeCondition;
|
||||
}
|
||||
|
||||
void CChargedArtifact::setRemoveOnDepletion(const bool remove)
|
||||
|
||||
@@ -79,7 +79,7 @@ protected:
|
||||
public:
|
||||
bool isCharged() const;
|
||||
|
||||
void setCondition(const DischargeArtifactCondition & condition);
|
||||
void setCondition(const DischargeArtifactCondition & dischargeCondition);
|
||||
void setRemoveOnDepletion(const bool remove);
|
||||
void setDefaultStartCharges(const uint16_t charges);
|
||||
uint16_t getDefaultStartCharges() const;
|
||||
|
||||
@@ -101,7 +101,7 @@ void CGrowingArtifactInstance::growingUp()
|
||||
if(artType->isGrowing())
|
||||
{
|
||||
const auto growingBonus = artInst->getBonusesOfType(BonusType::ARTIFACT_GROWING);
|
||||
assert(!growingBonus.empty());
|
||||
assert(!growingBonus->empty());
|
||||
growingBonus->front()->val++;
|
||||
|
||||
for(const auto & bonus : artType->getBonusesPerLevel())
|
||||
@@ -179,7 +179,7 @@ void CChargedArtifactInstance::addCharges(const uint16_t charges)
|
||||
if(artInst->getType()->isCharged())
|
||||
{
|
||||
const auto chargedBonus = artInst->getBonusesOfType(BonusType::ARTIFACT_CHARGE);
|
||||
assert(!chargedBonus.empty());
|
||||
assert(!chargedBonus->empty());
|
||||
chargedBonus->front()->val += charges;
|
||||
onChargesChanged();
|
||||
}
|
||||
|
||||
@@ -3931,6 +3931,9 @@ void CGameHandler::castSpell(const spells::Caster * caster, SpellID spellID, con
|
||||
|
||||
const CSpell * s = spellID.toSpell();
|
||||
s->adventureCast(spellEnv, p);
|
||||
|
||||
if(const auto hero = caster->getHeroCaster())
|
||||
verifyChargedArtifactUsed(hero->id, spellID);
|
||||
}
|
||||
|
||||
bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & sl2)
|
||||
@@ -4337,3 +4340,35 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|
||||
{
|
||||
battles->startBattle(army1, army2);
|
||||
}
|
||||
|
||||
void CGameHandler::verifyChargedArtifactUsed(const ObjectInstanceID & heroObjectID, const SpellID & spellID)
|
||||
{
|
||||
if(const auto hero = getHero(heroObjectID))
|
||||
{
|
||||
assert(hero->canCastThisSpell(spellID.toSpell()));
|
||||
|
||||
if(vstd::contains(hero->getSpellsInSpellbook(), spellID))
|
||||
return;
|
||||
|
||||
std::vector<std::pair<ArtifactPosition, ArtifactInstanceID>> chargedArts;
|
||||
for(const auto & [slot, slotInfo] : hero->artifactsWorn)
|
||||
{
|
||||
const auto artInst = slotInfo.getArt();
|
||||
const auto artType = artInst->getType();
|
||||
if(artType->getDischargeCondition() == DischargeArtifactCondition::SPELLCAST)
|
||||
{
|
||||
chargedArts.emplace_back(slot, artInst->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(const auto bonuses = artInst->getBonusesOfType(BonusType::SPELL, spellID); !bonuses->empty())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assert(!chargedArts.empty());
|
||||
DischargeArtifact msg(chargedArts.front().second, 1);
|
||||
msg.artLoc.emplace(hero->id, chargedArts.front().first);
|
||||
sendAndApply(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ public:
|
||||
void changeFogOfWar(const std::unordered_set<int3> &tiles, PlayerColor player,ETileVisibility mode) override;
|
||||
|
||||
void castSpell(const spells::Caster * caster, SpellID spellID, const int3 &pos) override;
|
||||
void verifyChargedArtifactUsed(const ObjectInstanceID & heroObjectID, const SpellID & spellID);
|
||||
|
||||
/// Returns hero that is currently visiting this object, or nullptr if no visit is active
|
||||
const CGHeroInstance * getVisitingHero(const CGObjectInstance *obj);
|
||||
|
||||
@@ -124,6 +124,7 @@ bool BattleActionProcessor::doHeroSpellAction(const CBattleInfoCallback & battle
|
||||
}
|
||||
|
||||
parameters.cast(gameHandler->spellEnv, ba.getTarget(&battle));
|
||||
gameHandler->verifyChargedArtifactUsed(h->id, ba.spell);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user