void CArmedInstance::updateMoraleBonusFromArmy() { if(!validTypes(false)) //object not randomized, don't bother return; auto b = getExportedBonusList().getFirst(Selector::sourceType(Bonus::ARMY).And(Selector::type(Bonus::MORALE))); if(!b) { b = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, 0, -1); addNewBonus(b); } //number of alignments and presence of undead std::set<TFaction> factions; bool hasUndead = false; for(auto slot : Slots()) { const CStackInstance * inst = slot.second; const CCreature * creature = VLC->creh->creatures[inst->getCreatureID()]; factions.insert(creature->faction); // Check for undead flag instead of faction (undead mummies are neutral) hasUndead |= inst->hasBonusOfType(Bonus::UNDEAD); } size_t factionsInArmy = factions.size(); //town garrison seems to take both sets into account // Take Angelic Alliance troop-mixing freedom of non-evil units into account. if (hasBonusOfType(Bonus::NONEVIL_ALIGNMENT_MIX)) { size_t mixableFactions = 0; for(TFaction f : factions) { if (VLC->townh->factions[f]->alignment != EAlignment::EVIL) mixableFactions++; } if (mixableFactions > 0) factionsInArmy -= mixableFactions - 1; } if(factionsInArmy == 1) { b->val = +1; b->description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1 b->description = b->description.substr(0, b->description.size()-3);//trim "+1" } else if (!factions.empty()) // no bonus from empty garrison { b->val = 2 - factionsInArmy; b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factionsInArmy % b->val); //Troops of %d alignments %d b->description = b->description.substr(0, b->description.size()-2);//trim value } boost::algorithm::trim(b->description); CBonusSystemNode::treeHasChanged(); //-1 modifier for any Undead unit in army const ui8 UNDEAD_MODIFIER_ID = -2; auto undeadModifier = getExportedBonusList().getFirst(Selector::source(Bonus::ARMY, UNDEAD_MODIFIER_ID)); if(hasUndead) { if(!undeadModifier) { undeadModifier = std::make_shared<Bonus>(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]); undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value addNewBonus(undeadModifier); } } else if(undeadModifier) removeBonus(undeadModifier); }
void CGHeroInstance::initHero() { assert(validTypes(true)); if(!type) type = VLC->heroh->heroes[subID]; if (ID == Obj::HERO) appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->id)->getTemplates().front(); if(!vstd::contains(spells, SpellID::PRESET)) //hero starts with a spell { for(auto spellID : type->spells) spells.insert(spellID); } else //remove placeholder spells -= SpellID::PRESET; if(!getArt(ArtifactPosition::MACH4) && !getArt(ArtifactPosition::SPELLBOOK) && type->haveSpellBook) //no catapult means we haven't read pre-existent set -> use default rules for spellbook putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0)); if(!getArt(ArtifactPosition::MACH4)) putArtifact(ArtifactPosition::MACH4, CArtifactInstance::createNewArtifactInstance(3)); //everyone has a catapult if(portrait < 0 || portrait == 255) portrait = type->imageIndex; if(!hasBonus(Selector::sourceType(Bonus::HERO_BASE_SKILL))) { for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g) { pushPrimSkill(static_cast<PrimarySkill::PrimarySkill>(g), type->heroClass->primarySkillInitial[g]); } } if(secSkills.size() == 1 && secSkills[0] == std::pair<SecondarySkill,ui8>(SecondarySkill::DEFAULT, -1)) //set secondary skills to default secSkills = type->secSkillsInit; if (!name.length()) name = type->name; if (sex == 0xFF)//sex is default sex = type->sex; setFormation(false); if (!stacksCount()) //standard army//initial army { initArmy(); } assert(validTypes()); level = 1; if(exp == 0xffffffff) { initExp(); } else { levelUpAutomatically(); } if (VLC->modh->modules.COMMANDERS && !commander) { commander = new CCommanderInstance(type->heroClass->commander->idNumber); commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders commander->giveStackExp (exp); //after our exp is set } if (mana < 0) mana = manaLimit(); }