void CGBorderGate::onHeroVisit( const CGHeroInstance * h ) const //TODO: passability { if (!wasMyColorVisited (h->getOwner()) ) { showInfoDialog(h,18,0); AddQuest aq; aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); } }
void CGObjectInstance::setType(si32 ID, si32 subID) { const TerrainTile &tile = cb->gameState()->map->getTile(visitablePos()); this->ID = Obj(ID); this->subID = subID; //recalculate blockvis tiles - new appearance might have different blockmap than before cb->gameState()->map->removeBlockVisTiles(this, true); auto handler = VLC->objtypeh->getHandlerFor(ID, subID); if(!handler) { logGlobal->error("Unknown object type %d:%d at %s", ID, subID, visitablePos().toString()); return; } 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); }
void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const { InfoWindow iw; iw.player = h->getOwner(); if (quest->progress < CQuest::COMPLETE) { bool firstVisit = !quest->progress; bool failRequirements = !checkQuest(h); bool isCustom=false; if (firstVisit) { isCustom = quest->isCustomFirst; cb->setObjProperty (id, 10, CQuest::IN_PROGRESS); AddQuest aq; aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); //TODO: merge with setObjProperty? } else if (failRequirements) { isCustom = quest->isCustomNext; } if (firstVisit || failRequirements) { getVisitText (iw.text, iw.components, isCustom, firstVisit, h); cb->showInfoDialog(&iw); } if (!failRequirements) // propose completion, also on first visit { BlockingDialog bd (true, false); bd.player = h->getOwner(); bd.soundID = soundBase::QUEST; getCompletionText (bd.text, bd.components, isCustom, h); cb->showBlockingDialog (&bd); return; } } else { iw.text << VLC->generaltexth->seerEmpty[quest->textOption]; if (ID == Obj::SEER_HUT) iw.text.addReplacement(seerName); cb->showInfoDialog(&iw); } }
void CGBorderGuard::onHeroVisit( const CGHeroInstance * h ) const { if (wasMyColorVisited (h->getOwner()) ) { BlockingDialog bd (true, false); bd.player = h->getOwner(); bd.soundID = soundBase::QUEST; bd.text.addTxt (MetaString::ADVOB_TXT, 17); cb->showBlockingDialog (&bd); } else { showInfoDialog(h,18,soundBase::CAVEHEAD); AddQuest aq; aq.quest = QuestInfo (quest, this, visitablePos()); aq.player = h->tempOwner; cb->sendAndApply (&aq); //TODO: add this quest only once OR check for multiple instances later } }
void CGHeroInstance::initObj() { blockVisit = true; auto hs = new HeroSpecial(); hs->setNodeType(CBonusSystemNode::SPECIALTY); attachTo(hs); //do we ever need to detach it? if(!type) initHero(); //TODO: set up everything for prison before specialties are configured skillsInfo.rand.setSeed(cb->gameState()->getRandomGenerator().nextInt()); skillsInfo.resetMagicSchoolCounter(); skillsInfo.resetWisdomCounter(); if (ID != Obj::PRISON) { auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->id)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this); if (customApp) appearance = customApp.get(); } for(const auto &spec : type->spec) //TODO: unfity with bonus system { auto bonus = new Bonus(); bonus->val = spec.val; bonus->sid = id.getNum(); //from the hero, specialty has no unique id bonus->duration = Bonus::PERMANENT; bonus->source = Bonus::HERO_SPECIAL; switch (spec.type) { case 1:// creature specialty { hs->growsWithLevel = true; const CCreature &specCreature = *VLC->creh->creatures[spec.additionalinfo]; //creature in which we have specialty //int creLevel = specCreature.level; //if(!creLevel) //{ // if(spec.additionalinfo == 146) // creLevel = 5; //treat ballista as 5-level // else // { // logGlobal->warnStream() << "Warning: unknown level of " << specCreature.namePl; // continue; // } //} //bonus->additionalInfo = spec.additionalinfo; //creature id, should not be used again - this works only with limiter bonus->limiter.reset(new CCreatureTypeLimiter (specCreature, true)); //with upgrades bonus->type = Bonus::PRIMARY_SKILL; bonus->valType = Bonus::ADDITIVE_VALUE; bonus->subtype = PrimarySkill::ATTACK; hs->addNewBonus(bonus); bonus = new Bonus(*bonus); bonus->subtype = PrimarySkill::DEFENSE; hs->addNewBonus(bonus); //values will be calculated later bonus = new Bonus(*bonus); bonus->type = Bonus::STACKS_SPEED; bonus->val = 1; //+1 speed hs->addNewBonus(bonus); } break; case 2://secondary skill hs->growsWithLevel = true; bonus->type = Bonus::SPECIAL_SECONDARY_SKILL; //needs to be recalculated with level, based on this value bonus->valType = Bonus::BASE_NUMBER; // to receive nonzero value bonus->subtype = spec.subtype; //skill id bonus->val = spec.val; //value per level, in percent hs->addNewBonus(bonus); bonus = new Bonus(*bonus); switch (spec.additionalinfo) { case 0: //normal bonus->valType = Bonus::PERCENT_TO_BASE; break; case 1: //when it's navigation or there's no 'base' at all bonus->valType = Bonus::PERCENT_TO_ALL; break; } bonus->type = Bonus::SECONDARY_SKILL_PREMY; //value will be calculated later hs->addNewBonus(bonus); break; case 3://spell damage bonus, level dependent but calculated elsewhere bonus->type = Bonus::SPECIAL_SPELL_LEV; bonus->subtype = spec.subtype; hs->addNewBonus(bonus); break; case 4://creature stat boost switch (spec.subtype) { case 1://attack bonus->type = Bonus::PRIMARY_SKILL; bonus->subtype = PrimarySkill::ATTACK; break; case 2://defense bonus->type = Bonus::PRIMARY_SKILL; bonus->subtype = PrimarySkill::DEFENSE; break; case 3: bonus->type = Bonus::CREATURE_DAMAGE; bonus->subtype = 0; //both min and max break; case 4://hp bonus->type = Bonus::STACK_HEALTH; break; case 5: bonus->type = Bonus::STACKS_SPEED; break; default: continue; } bonus->additionalInfo = spec.additionalinfo; //creature id bonus->valType = Bonus::ADDITIVE_VALUE; bonus->limiter.reset(new CCreatureTypeLimiter (*VLC->creh->creatures[spec.additionalinfo], true)); hs->addNewBonus(bonus); break; case 5://spell damage bonus in percent bonus->type = Bonus::SPECIFIC_SPELL_DAMAGE; bonus->valType = Bonus::BASE_NUMBER; // current spell system is screwed bonus->subtype = spec.subtype; //spell id hs->addNewBonus(bonus); break; case 6://damage bonus for bless (Adela) bonus->type = Bonus::SPECIAL_BLESS_DAMAGE; bonus->subtype = spec.subtype; //spell id if you ever wanted to use it otherwise bonus->additionalInfo = spec.additionalinfo; //damage factor hs->addNewBonus(bonus); break; case 7://maxed mastery for spell bonus->type = Bonus::MAXED_SPELL; bonus->subtype = spec.subtype; //spell i hs->addNewBonus(bonus); break; case 8://peculiar spells - enchantments bonus->type = Bonus::SPECIAL_PECULIAR_ENCHANT; bonus->subtype = spec.subtype; //spell id bonus->additionalInfo = spec.additionalinfo;//0, 1 for Coronius hs->addNewBonus(bonus); break; case 9://upgrade creatures { const auto &creatures = VLC->creh->creatures; bonus->type = Bonus::SPECIAL_UPGRADE; bonus->subtype = spec.subtype; //base id bonus->additionalInfo = spec.additionalinfo; //target id hs->addNewBonus(bonus); bonus = new Bonus(*bonus); for(auto cre_id : creatures[spec.subtype]->upgrades) { bonus->subtype = cre_id; //propagate for regular upgrades of base creature hs->addNewBonus(bonus); bonus = new Bonus(*bonus); } vstd::clear_pointer(bonus); break; } case 10://resource generation bonus->type = Bonus::GENERATE_RESOURCE; bonus->subtype = spec.subtype; hs->addNewBonus(bonus); break; case 11://starting skill with mastery (Adrienne) setSecSkillLevel(SecondarySkill(spec.val), spec.additionalinfo, true); break; case 12://army speed bonus->type = Bonus::STACKS_SPEED; hs->addNewBonus(bonus); break; case 13://Dragon bonuses (Mutare) bonus->type = Bonus::PRIMARY_SKILL; bonus->valType = Bonus::ADDITIVE_VALUE; switch (spec.subtype) { case 1: bonus->subtype = PrimarySkill::ATTACK; break; case 2: bonus->subtype = PrimarySkill::DEFENSE; break; } bonus->limiter.reset(new HasAnotherBonusLimiter(Bonus::DRAGON_NATURE)); hs->addNewBonus(bonus); break; default: logGlobal->warnStream() << "Unexpected hero specialty " << type; } } specialty.push_back(hs); //will it work? for (auto hs2 : type->specialty) //copy active (probably growing) bonuses from hero prootype to hero object { auto hs = new HeroSpecial(); attachTo(hs); //do we ever need to detach it? hs->setNodeType(CBonusSystemNode::SPECIALTY); for (auto bonus : hs2.bonuses) { hs->addNewBonus (bonus); } hs->growsWithLevel = hs2.growsWithLevel; specialty.push_back(hs); //will it work? } //initialize bonuses recreateSecondarySkillsBonuses(); Updatespecialty(); mana = manaLimit(); //after all bonuses are taken into account, make sure this line is the last one type->name = name; }
int3 CGObjectInstance::getSightCenter() const { return visitablePos(); }