void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator &rng) const { CGDwelling * dwelling = dynamic_cast<CGDwelling*>(object); dwelling->creatures.clear(); dwelling->creatures.reserve(availableCreatures.size()); for (auto & entry : availableCreatures) { dwelling->creatures.resize(dwelling->creatures.size() + 1); for (const CCreature * cre : entry) dwelling->creatures.back().second.push_back(cre->idNumber); } if (guards.getType() == JsonNode::DATA_BOOL) { if (guards.Bool()) { const CCreature * crea = availableCreatures.at(0).at(0); dwelling->putStack(SlotID(0), new CStackInstance(crea->idNumber, crea->growth * 3 )); } } else for (auto & stack : JsonRandom::loadCreatures(guards, rng)) { dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->idNumber, stack.count)); } }
SlotID CCreatureSet::getFreeSlot(ui32 slotsAmount/*=ARMY_SIZE*/) const { for(ui32 i=0; i<slotsAmount; i++) { if(!vstd::contains(stacks, SlotID(i))) { return SlotID(i); //return first free slot } } return SlotID(); //no slot available }
bool TradeOnMarketplace::applyGh( CGameHandler *gh ) { //market must be owned or visited const IMarket *m = IMarket::castFrom(market); if(!m) COMPLAIN_AND_RETURN("market is not-a-market! :/"); PlayerColor player = market->tempOwner; if(player >= PlayerColor::PLAYER_LIMIT) player = gh->getTile(market->visitablePos())->visitableObjects.back()->tempOwner; if(player >= PlayerColor::PLAYER_LIMIT) COMPLAIN_AND_RETURN("No player can use this market!"); if(hero && (player != hero->tempOwner || hero->visitablePos() != market->visitablePos())) COMPLAIN_AND_RETURN("This hero can't use this marketplace!"); ERROR_IF_NOT(player); switch(mode) { case EMarketMode::RESOURCE_RESOURCE: return gh->tradeResources(m, val, player, r1, r2); case EMarketMode::RESOURCE_PLAYER: return gh->sendResources(val, player, static_cast<Res::ERes>(r1), PlayerColor(r2)); case EMarketMode::CREATURE_RESOURCE: if(!hero) COMPLAIN_AND_RETURN("Only hero can sell creatures!"); return gh->sellCreatures(val, m, hero, SlotID(r1), static_cast<Res::ERes>(r2)); case EMarketMode::RESOURCE_ARTIFACT: if(!hero) COMPLAIN_AND_RETURN("Only hero can buy artifacts!"); return gh->buyArtifact(m, hero, static_cast<Res::ERes>(r1), ArtifactID(r2)); case EMarketMode::ARTIFACT_RESOURCE: if(!hero) COMPLAIN_AND_RETURN("Only hero can sell artifacts!"); return gh->sellArtifact(m, hero, ArtifactInstanceID(r1), static_cast<Res::ERes>(r2)); case EMarketMode::CREATURE_UNDEAD: return gh->transformInUndead(m, hero, SlotID(r1)); case EMarketMode::RESOURCE_SKILL: return gh->buySecSkill(m, hero, SecondarySkill(r2)); case EMarketMode::CREATURE_EXP: return gh->sacrificeCreatures(m, hero, SlotID(r1), val); case EMarketMode::ARTIFACT_EXP: return gh->sacrificeArtifact(m, hero, ArtifactPosition(r1)); default: COMPLAIN_AND_RETURN("Unknown exchange mode!"); } }
SlotID CCreatureSet::findStack(const CStackInstance *stack) const { auto h = dynamic_cast<const CGHeroInstance *>(this); if (h && h->commander == stack) return SlotID::COMMANDER_SLOT_PLACEHOLDER; if(!stack) return SlotID(); for(TSlots::const_iterator i = stacks.begin(); i != stacks.end(); ++i) if(i->second == stack) return i->first; return SlotID(); }
void CGSeerHut::completeQuest (const CGHeroInstance * h) const //reward { switch (rewardType) { case EXPERIENCE: { TExpType expVal = h->calculateXp(rVal); cb->changePrimSkill(h, PrimarySkill::EXPERIENCE, expVal, false); break; } case MANA_POINTS: { cb->setManaPoints(h->id, h->mana+rVal); break; } case MORALE_BONUS: case LUCK_BONUS: { Bonus hb(Bonus::ONE_WEEK, (rewardType == 3 ? Bonus::MORALE : Bonus::LUCK), Bonus::OBJECT, rVal, h->id.getNum(), "", -1); GiveBonus gb; gb.id = h->id.getNum(); gb.bonus = hb; cb->giveHeroBonus(&gb); } break; case RESOURCES: cb->giveResource(h->getOwner(), static_cast<Res::ERes>(rID), rVal); break; case PRIMARY_SKILL: cb->changePrimSkill(h, static_cast<PrimarySkill::PrimarySkill>(rID), rVal, false); break; case SECONDARY_SKILL: cb->changeSecSkill(h, SecondarySkill(rID), rVal, false); break; case ARTIFACT: cb->giveHeroNewArtifact(h, VLC->arth->artifacts[rID],ArtifactPosition::FIRST_AVAILABLE); break; case SPELL: { std::set<SpellID> spell; spell.insert (SpellID(rID)); cb->changeSpells(h, true, spell); } break; case CREATURE: { CCreatureSet creatures; creatures.setCreature(SlotID(0), CreatureID(rID), rVal); cb->giveCreatures(this, h, creatures, false); } break; default: break; } }
void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= nullptr*/) { if(!dst) dst = this; int howManyStacks = 0; //how many stacks will hero receives <1 - 3> int pom = cb->gameState()->getRandomGenerator().nextInt(99); int warMachinesGiven = 0; if(pom < 9) howManyStacks = 1; else if(pom < 79) howManyStacks = 2; else howManyStacks = 3; vstd::amin(howManyStacks, type->initialArmy.size()); for(int stackNo=0; stackNo < howManyStacks; stackNo++) { auto & stack = type->initialArmy[stackNo]; int count = cb->gameState()->getRandomGenerator().nextInt(stack.minAmount, stack.maxAmount); if(stack.creature >= CreatureID::CATAPULT && stack.creature <= CreatureID::ARROW_TOWERS) //war machine { warMachinesGiven++; if(dst != this) continue; int slot = -1; ArtifactID aid = ArtifactID::NONE; switch (stack.creature) { case CreatureID::CATAPULT: slot = ArtifactPosition::MACH4; aid = ArtifactID::CATAPULT; break; default: aid = CArtHandler::creatureToMachineID(stack.creature); slot = 9 + aid; break; } auto convSlot = ArtifactPosition(slot); if(!getArt(convSlot)) putArtifact(convSlot, CArtifactInstance::createNewArtifactInstance(aid)); else logGlobal->warnStream() << "Hero " << name << " already has artifact at " << slot << ", omitting giving " << aid; } else dst->setCreature(SlotID(stackNo-warMachinesGiven), stack.creature, count); } }
void CGSeerHut::setObjToKill() { if (quest->missionType == CQuest::MISSION_KILL_CREATURE) { quest->stackToKill = getCreatureToKill(false)->getStack(SlotID(0)); //FIXME: stacks tend to disappear (desync?) on server :? assert(quest->stackToKill.type); quest->stackToKill.count = 0; //no count in info window quest->stackDirection = checkDirection(); } else if (quest->missionType == CQuest::MISSION_KILL_HERO) { quest->heroName = getHeroToKill(false)->name; quest->heroPortrait = getHeroToKill(false)->portrait; } }
/** * Calculates what creatures and how many to be raised from a battle. * @param battleResult The results of the battle. * @return Returns a pair with the first value indicating the ID of the creature * type and second value the amount. Both values are returned as -1 if necromancy * could not be applied. */ CStackBasicDescriptor CGHeroInstance::calculateNecromancy (const BattleResult &battleResult) const { const ui8 necromancyLevel = getSecSkillLevel(SecondarySkill::NECROMANCY); // Hero knows necromancy or has Necromancer Cloak if (necromancyLevel > 0 || hasBonusOfType(Bonus::IMPROVED_NECROMANCY)) { double necromancySkill = valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, SecondarySkill::NECROMANCY)/100.0; vstd::amin(necromancySkill, 1.0); //it's impossible to raise more creatures than all... const std::map<ui32,si32> &casualties = battleResult.casualties[!battleResult.winner]; ui32 raisedUnits = 0; // Figure out what to raise and how many. const CreatureID creatureTypes[] = {CreatureID::SKELETON, CreatureID::WALKING_DEAD, CreatureID::WIGHTS, CreatureID::LICHES}; const bool improvedNecromancy = hasBonusOfType(Bonus::IMPROVED_NECROMANCY); const CCreature *raisedUnitType = VLC->creh->creatures[creatureTypes[improvedNecromancy ? necromancyLevel : 0]]; const ui32 raisedUnitHP = raisedUnitType->valOfBonuses(Bonus::STACK_HEALTH); //calculate creatures raised from each defeated stack for (auto & casualtie : casualties) { // Get lost enemy hit points convertible to units. CCreature * c = VLC->creh->creatures[casualtie.first]; const ui32 raisedHP = c->valOfBonuses(Bonus::STACK_HEALTH) * casualtie.second * necromancySkill; raisedUnits += std::min<ui32>(raisedHP / raisedUnitHP, casualtie.second * necromancySkill); //limit to % of HP and % of original stack count } // Make room for new units. SlotID slot = getSlotFor(raisedUnitType->idNumber); if (slot == SlotID()) { // If there's no room for unit, try it's upgraded version 2/3rds the size. raisedUnitType = VLC->creh->creatures[*raisedUnitType->upgrades.begin()]; raisedUnits = (raisedUnits*2)/3; slot = getSlotFor(raisedUnitType->idNumber); } if (raisedUnits <= 0) raisedUnits = 1; return CStackBasicDescriptor(raisedUnitType->idNumber, raisedUnits); } return CStackBasicDescriptor(); }
* License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #define INSTANTIATE_BASE_FOR_ID_HERE #include "StdInc.h" #include "VCMI_Lib.h" #include "mapObjects/CObjectClassesHandler.h" #include "CArtHandler.h" #include "CCreatureHandler.h" #include "spells/CSpellHandler.h" const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); const PlayerColor PlayerColor::PLAYER_LIMIT = PlayerColor(PLAYER_LIMIT_I); const TeamID TeamID::NO_TEAM = TeamID(255); #define ID_LIKE_OPERATORS_INTERNAL(A, B, AN, BN) \ bool operator==(const A & a, const B & b) \ { \ return AN == BN ; \ } \ bool operator!=(const A & a, const B & b) \ { \ return AN != BN ; \ } \
void CGHeroInstance::setPropertyDer( ui8 what, ui32 val ) { if(what == ObjProperty::PRIMARY_STACK_COUNT) setStackCount(SlotID(0), val); }
#include "StdInc.h" #ifndef VCMI_NO_EXTRA_VERSION #include "../Version.h" #endif #include "VCMI_Lib.h" #include "mapObjects/CObjectClassesHandler.h" #include "CArtHandler.h" #include "CCreatureHandler.h" #include "spells/CSpellHandler.h" #include "StringConstants.h" #include "CGeneralTextHandler.h" const SlotID SlotID::COMMANDER_SLOT_PLACEHOLDER = SlotID(-2); const SlotID SlotID::SUMMONED_SLOT_PLACEHOLDER = SlotID(-3); const SlotID SlotID::WAR_MACHINES_SLOT = SlotID(-4); const SlotID SlotID::ARROW_TOWERS_SLOT = SlotID(-5); const PlayerColor PlayerColor::CANNOT_DETERMINE = PlayerColor(253); const PlayerColor PlayerColor::UNFLAGGABLE = PlayerColor(254); const PlayerColor PlayerColor::NEUTRAL = PlayerColor(255); const PlayerColor PlayerColor::PLAYER_LIMIT = PlayerColor(PLAYER_LIMIT_I); const TeamID TeamID::NO_TEAM = TeamID(255); namespace GameConstants { #ifdef VCMI_NO_EXTRA_VERSION const std::string VCMI_VERSION = std::string("VCMI 0.99"); #else