MantisBT - VCMI
View Issue Details
0002781VCMIModspublic2017-08-31 01:332017-09-06 12:29
hkoehler 
hkoehler 
normalminoralways
resolvedfixed 
0.99 
1.next 
0002781: Granting bonuses to war machines
It seems that bonuses granted to a hero do not propagate to war machines. E.g. granting the bonus below to a hero has no effect on the health of his ammo cart during combat (but works fine for normal creatures).

"type" : "STACK_HEALTH",
"val" : 150,
"valueType" : "BASE_NUMBER",
"limiters": [{
    "type" : "CREATURE_TYPE_LIMITER",
    "parameters" : [ "ammoCart" ]
}]
Seems related to the limiter - without it the bonus applies to war machines as well.
No tags attached.
Issue History
2017-08-31 01:33hkoehlerNew Issue
2017-08-31 02:39hkoehlerNote Added: 0007245
2017-09-01 22:52hkoehlerNote Edited: 0007245bug_revision_view_page.php?rev_id=3393
2017-09-02 00:23SXXSummaryGranting bonuses to war machines => Granting bonuses to war machines1
2017-09-02 00:24SXXSummaryGranting bonuses to war machines1 => Granting bonuses to war machines
2017-09-02 02:27hkoehlerAssigned To => hkoehler
2017-09-02 02:27hkoehlerStatusnew => assigned
2017-09-02 02:27hkoehlerAdditional Information Updatedbug_revision_view_page.php?rev_id=3395#r3395
2017-09-02 02:28hkoehlerNote Deleted: 0007245
2017-09-02 02:28hkoehlerNote Added: 0007247
2017-09-02 02:31hkoehlerNote Added: 0007248
2017-09-02 02:46hkoehlerNote Added: 0007249
2017-09-02 03:02hkoehlerNote Edited: 0007249bug_revision_view_page.php?bugnote_id=7249#r3397
2017-09-02 06:32SXXNote Edited: 0007249bug_revision_view_page.php?bugnote_id=7249#r3398
2017-09-02 06:32SXXNote Added: 0007250
2017-09-02 06:32SXXNote Edited: 0007250bug_revision_view_page.php?rev_id=3400
2017-09-02 06:33SXXNote Deleted: 0007250
2017-09-02 06:36SXXNote Added: 0007251
2017-09-02 07:07SXXNote Edited: 0007251bug_revision_view_page.php?rev_id=3402
2017-09-02 07:07SXXNote Added: 0007252
2017-09-02 07:08SXXNote Added: 0007253
2017-09-02 07:08SXXNote Deleted: 0007252
2017-09-02 07:08SXXNote Deleted: 0007251
2017-09-02 07:08SXXNote Deleted: 0007253
2017-09-06 12:29AVSNote Added: 0007264
2017-09-06 12:29AVSStatusassigned => resolved
2017-09-06 12:29AVSFixed in Version => 1.next
2017-09-06 12:29AVSResolutionopen => fixed

Notes
(0007247)
hkoehler   
2017-09-02 02:28   
BattleInfo * BattleInfo::setupBattle(
...
        auto handleWarMachine= [&](int side, ArtifactPosition artslot, BattleHex hex)
        {
            const CArtifactInstance * warMachineArt = heroes[side]->getArt(artslot);

            if(nullptr != warMachineArt)
            {
                CreatureID cre = warMachineArt->artType->warMachine;

                if(cre != CreatureID::NONE)
                    stacks.push_back(curB->generateNewStack(CStackBasicDescriptor(cre, 1), side, SlotID::WAR_MACHINES_SLOT, hex));
            }
        };
...
}

CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor & base, ui8 side, SlotID slot, BattleHex position) const
{
    int stackID = getIdForNewStack();
    PlayerColor owner = sides[side].color;
    auto ret = new CStack(&base, owner, stackID, side, slot);
    ret->position = position;
    ret->state.insert(EBattleStackState::ALIVE); //alive state indication
    return ret;
}

---

In CCreatureSet.cpp:
CStackBasicDescriptor::CStackBasicDescriptor(CreatureID id, TQuantity Count)
    : type (VLC->creh->creatures[id]), count(Count)
{
}

---

CStack::CStack(const CStackBasicDescriptor * stack, PlayerColor O, int I, ui8 Side, SlotID S):
    base(nullptr), ID(I), owner(O), slot(S), side(Side),
    counterAttacks(this), shots(this), casts(this), health(this), cloneID(-1),
    position()
{
    type = stack->type;
    baseAmount = stack->count;
    health.init(); //???
    setNodeType(STACK_BATTLE);
}

---

In HeroBonus.cpp:
int CCreatureTypeLimiter::limit(const BonusLimitationContext &context) const
{
    const CCreature *c = retrieveCreature(&context.node);
    if(!c)
        return true;
    return c != creature && (!includeUpgrades || !creature->isMyUpgrade(c));
    //drop bonus if it's not our creature and (we don`t check upgrades or its not our upgrade)
}

const CCreature * retrieveCreature(const CBonusSystemNode *node)
{
    switch(node->getNodeType())
    {
    case CBonusSystemNode::CREATURE:
        return (static_cast<const CCreature *>(node));
    default:
        const CStackInstance *csi = retreiveStackInstance(node);
        if(csi)
            return csi->type;
        return nullptr;
    }
}

const CStackInstance * retreiveStackInstance(const CBonusSystemNode *node)
{
    switch(node->getNodeType())
    {
    case CBonusSystemNode::STACK_INSTANCE:
        return (static_cast<const CStackInstance *>(node));
    case CBonusSystemNode::STACK_BATTLE:
        return (static_cast<const CStack*>(node))->base;
    default:
        return nullptr;
    }
}
(0007248)
hkoehler   
2017-09-02 02:31   
Looks like war machines stacks are created with base = nullptr, which is what retrieveStackInstance returns, and hence retrieveCreature as well.

As a result, CCreatureTypeLimiter::limit will return true, stopping propagation.
(0007249)
hkoehler   
2017-09-02 02:46   
(edited on: 2017-09-02 06:32)
Problem is that retrieveCreature shouldn't depend on retrieveStackInstance, as it only requires creature type, not creature instance, and there are stacks without instances (e.g. war machines). Creature type is stored in type, so no need to use base->type.

Fix:

const CCreature * retrieveCreature(const CBonusSystemNode *node)
{
    switch(node->getNodeType())
    {
    case CBonusSystemNode::CREATURE:
        return (static_cast<const CCreature *>(node));
    case CBonusSystemNode::STACK_BATTLE:
        return (static_cast<const CStack*>(node))->type;
    default:
        const CStackInstance *csi = retreiveStackInstance(node);
        if(csi)
            return csi->type;
        return nullptr;
    }
}

(0007264)
AVS   
2017-09-06 12:29   
Fixed in https://github.com/vcmi/vcmi/pull/374 [^]