void Kingdom::ApplyPlayWithStartingHero(void) { if(isPlay() && castles.size()) { // get first castle Castle* first = castles.GetFirstCastle(); if(NULL == first) first = castles.front(); // check manual set hero (castle position + point(0, 1))? const Point & cp = (first)->GetCenter(); Heroes* hero = world.GetTiles(cp.x, cp.y + 1).GetHeroes(); // and move manual set hero to castle if(hero && hero->GetColor() == GetColor()) { bool patrol = hero->Modes(Heroes::PATROL); hero->SetFreeman(0); hero->Recruit(*first); if(patrol) { hero->SetModes(Heroes::PATROL); hero->SetCenterPatrol(cp); } } else if(Settings::Get().GameStartWithHeroes()) { Heroes* hero = world.GetFreemanHeroes(first->GetRace()); if(hero && AllowRecruitHero(false, 0)) hero->Recruit(*first); } } }
s32 GetRandomHeroesPosition(Heroes & hero, u32 scoute) { Maps::Indexes v = Maps::GetAroundIndexes(hero.GetIndex(), scoute, true); Maps::Indexes res; v.resize(std::distance(v.begin(), std::remove_if(v.begin(), v.end(), std::ptr_fun(&Maps::TileIsUnderProtection)))); #if defined(ANDROID) const MapsIndexes::const_reverse_iterator crend = v.rend(); for(MapsIndexes::const_reverse_iterator it = v.rbegin(); it != crend && res.size() < 4; ++it) #else for(MapsIndexes::const_reverse_iterator it = v.rbegin(); it != v.rend() && res.size() < 4; ++it) #endif { if(world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) && hero.GetPath().Calculate(*it)) res.push_back(*it); } const s32 result = res.size() ? *Rand::Get(res) : -1; if(0 <= result) { DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) << ", hero: " << hero.GetName() << ", added task: " << result); } return result; }
Sprite SpriteFlag(const Heroes & hero, int index, bool reflect, bool rotate) { int icn_flag = ICN::UNKNOWN; int index_sprite = 0; switch(hero.GetColor()) { case Color::BLUE: icn_flag = hero.isShipMaster() ? ICN::B_BFLG32 : ICN::B_FLAG32; break; case Color::GREEN: icn_flag = hero.isShipMaster() ? ICN::G_BFLG32 : ICN::G_FLAG32; break; case Color::RED: icn_flag = hero.isShipMaster() ? ICN::R_BFLG32 : ICN::R_FLAG32; break; case Color::YELLOW: icn_flag = hero.isShipMaster() ? ICN::Y_BFLG32 : ICN::Y_FLAG32; break; case Color::ORANGE: icn_flag = hero.isShipMaster() ? ICN::O_BFLG32 : ICN::O_FLAG32; break; case Color::PURPLE: icn_flag = hero.isShipMaster() ? ICN::P_BFLG32 : ICN::P_FLAG32; break; default: DEBUG(DBG_GAME, DBG_WARN, "unknown color"); break; } if(rotate) index_sprite = 45; else switch(hero.GetDirection()) { case Direction::TOP: index_sprite = 0; break; case Direction::TOP_RIGHT: index_sprite = 9; break; case Direction::RIGHT: index_sprite = 18; break; case Direction::BOTTOM_RIGHT: index_sprite = 27; break; case Direction::BOTTOM: index_sprite = 36; break; case Direction::BOTTOM_LEFT: index_sprite = 27; break; case Direction::LEFT: index_sprite = 18; break; case Direction::TOP_LEFT: index_sprite = 9; break; default: DEBUG(DBG_GAME, DBG_WARN, "unknown direction"); break; } return AGG::GetICN(icn_flag, index_sprite + (index % 9), reflect); }
bool ActionSpellIdentifyHero(Heroes & hero) { world.GetKingdom(hero.GetColor()).SetModes(Kingdom::IDENTIFYHERO); Message("", _("Enemy heroes are now fully identifiable."), Font::BIG, Dialog::OK); return true; }
int Interface::Basic::EventDigArtifact(void) { Heroes* hero = GetFocusHeroes(); if(hero) { if(hero->isShipMaster()) Dialog::Message("", _("Try looking on land!!!"), Font::BIG, Dialog::OK); else if(hero->GetMaxMovePoints() <= hero->GetMovePoints()) { if(world.GetTiles(hero->GetIndex()).GoodForUltimateArtifact()) { AGG::PlaySound(M82::DIGSOUND); hero->ResetMovePoints(); if(world.DiggingForUltimateArtifact(hero->GetCenter())) { AGG::PlaySound(M82::TREASURE); const Artifact & ultimate = world.GetUltimateArtifact().GetArtifact(); hero->PickupArtifact(ultimate); std::string msg(_("After spending many hours digging here, you have uncovered the %{artifact}")); StringReplace(msg, "%{artifact}", ultimate.GetName()); Dialog::ArtifactInfo(_("Congratulations!"), msg, ultimate()); // set all obelisks visited Kingdom & kingdom = world.GetKingdom(hero->GetColor()); const MapsIndexes obelisks = Maps::GetObjectPositions(MP2::OBJ_OBELISK, true); for(MapsIndexes::const_iterator it = obelisks.begin(); it != obelisks.end(); ++it) if(!hero->isVisited(world.GetTiles(*it), Visit::GLOBAL)) hero->SetVisited(*it, Visit::GLOBAL); kingdom.PuzzleMaps().Update(kingdom.CountVisitedObjects(MP2::OBJ_OBELISK), world.CountObeliskOnMaps()); } else Dialog::Message("", _("Nothing here. Where could it be?"), Font::BIG, Dialog::OK); Cursor::Get().Hide(); iconsPanel.RedrawIcons(ICON_HEROES); Cursor::Get().Show(); Display::Get().Flip(); // check game over for ultimate artifact return GameOver::Result::Get().LocalCheckGameOver(); } else Dialog::Message("", _("Try searching on clear ground."), Font::BIG, Dialog::OK); } } else Dialog::Message("", _("Digging for artifacts requires a whole day, try again tomorrow."), Font::BIG, Dialog::OK); return Game::CANCEL; }
bool isNeedStayFrontObject(const Heroes & hero, const Maps::Tiles & next) { if(next.GetObject() == MP2::OBJ_CASTLE) { const Castle *castle = world.GetCastle(next.GetIndex()); return (castle && hero.GetColor() != castle->GetColor() && !Players::isFriends(hero.GetColor(), castle->GetColor())); } else // to coast action if(hero.isShipMaster() && next.GetObject() == MP2::OBJ_COAST) return true; return MP2::isNeedStayFront(next.GetObject()); }
// get priority object for AI independent of distance (1 day) bool AIHeroesPriorityObject(const Heroes & hero, s32 index) { Maps::Tiles & tile = world.GetTiles(index); if(MP2::OBJ_CASTLE == tile.GetObject()) { const Castle* castle = world.GetCastle(Maps::GetPoint(index)); if(castle) { if(hero.GetColor() == castle->GetColor()) { // maybe need join army return hero.Modes(AI::HEROES_HUNTER) && castle->GetArmy().isValid() && ! hero.isVisited(world.GetTiles(castle->GetIndex())); } else if(! hero.isFriends(castle->GetColor())) return AI::HeroesValidObject(hero, index); } } else if(MP2::OBJ_HEROES == tile.GetObject()) { // kill enemy hero const Heroes* hero2 = tile.GetHeroes(); return hero2 && ! hero.isFriends(hero2->GetColor()) && AI::HeroesValidObject(hero, index); } switch(tile.GetObject()) { case MP2::OBJ_MONSTER: case MP2::OBJ_SAWMILL: case MP2::OBJ_MINES: case MP2::OBJ_ALCHEMYLAB: case MP2::OBJ_ARTIFACT: case MP2::OBJ_RESOURCE: case MP2::OBJ_CAMPFIRE: case MP2::OBJ_TREASURECHEST: return AI::HeroesValidObject(hero, index); default: break; } return false; }
s32 FindUncharteredTerritory(Heroes & hero, const u8 & scoute) { Maps::Indexes v = Maps::GetAroundIndexes(hero.GetIndex(), scoute, true); Maps::Indexes res; v.resize(std::distance(v.begin(), std::remove_if(v.begin(), v.end(), std::ptr_fun(&Maps::TileIsUnderProtection)))); #if (__GNUC__ == 3 && __GNUC_MINOR__ == 4) const MapsIndexes::const_reverse_iterator crend = v.rend(); for(MapsIndexes::const_reverse_iterator it = v.rbegin(); it != crend && res.size() < 4; ++it) #else MapsIndexes::reverse_iterator it = v.rbegin(); for(; it != v.rend() && (res.size() < 4); ++it) #endif { // find fogs if(world.GetTiles(*it).isFog(hero.GetColor()) && world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) && hero.GetPath().Calculate(*it)) res.push_back(*it); } const s32 result = res.size() ? *Rand::Get(res) : -1; if(0 <= result) { DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) << ", hero: " << hero.GetName() << ", added task: " << result); } return result; }
bool ActionSpellTownGate(Heroes & hero) { const Kingdom & kingdom = world.GetKingdom(hero.GetColor()); const KingdomCastles & castles = kingdom.GetCastles(); KingdomCastles::const_iterator it; const Castle* castle = NULL; const s32 center = hero.GetIndex(); s32 min = -1; // find the nearest castle for(it = castles.begin(); it != castles.end(); ++it) if(*it && !(*it)->GetHeroes().Guest()) { const u16 min2 = Maps::GetApproximateDistance(center, (*it)->GetIndex()); if(0 > min || min2 < min) { min = min2; castle = *it; } } Interface::Basic & I = Interface::Basic::Get(); Cursor & cursor = Cursor::Get(); // center hero cursor.Hide(); I.gameArea.SetCenter(hero.GetCenter()); GameFocus::SetRedraw(); I.Redraw(); if(!castle) { Dialog::Message("", _("No avaialble town. Spell Failed!!!"), Font::BIG, Dialog::OK); return false; } return HeroesTownGate(hero, castle); }
Dialog::answer_t PocketPC::HeroesOpenDialog(Heroes & hero, bool readonly) { Cursor & cursor = Cursor::Get(); Display & display = Display::Get(); LocalEvent & le = LocalEvent::Get(); cursor.Hide(); cursor.SetThemes(cursor.POINTER); const u16 window_w = 320; const u16 window_h = 224; Dialog::FrameBorder frameborder; frameborder.SetPosition((display.w() - window_w) / 2 - BORDERWIDTH, (display.h() - window_h) / 2 - BORDERWIDTH, window_w, window_h); frameborder.Redraw(); const Rect & dst_rt = frameborder.GetArea(); const Sprite & background = AGG::GetICN(ICN::STONEBAK, 0); const Sprite & backSprite = AGG::GetICN(ICN::SWAPWIN, 0); background.Blit(Rect(0, 0, window_w, window_h), dst_rt); // portrait AGG::GetICN(ICN::BRCREST, 6).Blit(dst_rt.x + 8, dst_rt.y, display); hero.GetPortrait50x46().Blit(dst_rt.x + 12, dst_rt.y + 4, display); // name std::string message = _("%{name} the %{race} ( Level %{level} )"); String::Replace(message, "%{name}", hero.GetName()); String::Replace(message, "%{race}", Race::String(hero.GetRace())); String::Replace(message, "%{level}", hero.GetLevel()); Text text(message, Font::SMALL); text.Blit(dst_rt.x + 73, dst_rt.y + 1); // experience ExperienceIndicator experienceInfo(hero); experienceInfo.SetPos(Point(dst_rt.x + 205, dst_rt.y + 14)); experienceInfo.Redraw(); // spell points SpellPointsIndicator spellPointsInfo(hero); spellPointsInfo.SetPos(Point(dst_rt.x + 238, dst_rt.y + 16)); spellPointsInfo.Redraw(); // morale MoraleIndicator moraleIndicator(hero); moraleIndicator.SetPos(Point(dst_rt.x + 280, dst_rt.y + 20)); moraleIndicator.Redraw(); // luck LuckIndicator luckIndicator(hero); luckIndicator.SetPos(Point(dst_rt.x + 280, dst_rt.y + 60)); luckIndicator.Redraw(); // prim skill const Rect ras(dst_rt.x + 74, dst_rt.y + 14, 34, 34); backSprite.Blit(Rect(216, 51, ras.w, ras.h), ras); text.Set(GetString(hero.GetAttack())); text.Blit(dst_rt.x + 74 + (34 - text.w()) / 2, dst_rt.y + 47); const Rect rds(dst_rt.x + 107, dst_rt.y + 14, 34, 34); backSprite.Blit(Rect(216, 84, rds.w, rds.h), rds); text.Set(GetString(hero.GetDefense())); text.Blit(dst_rt.x + 107 + (34 - text.w()) / 2, dst_rt.y + 47); const Rect rps(dst_rt.x + 140, dst_rt.y + 14, 34, 34); backSprite.Blit(Rect(216, 117, rps.w, rps.h), rps); text.Set(GetString(hero.GetPower())); text.Blit(dst_rt.x + 140 + (34 - text.w()) / 2, dst_rt.y + 47); const Rect rks(dst_rt.x + 173, dst_rt.y + 14, 34, 34); backSprite.Blit(Rect(216, 150, rks.w, rks.h), rks); text.Set(GetString(hero.GetKnowledge())); text.Blit(dst_rt.x + 173 + (34 - text.w()) / 2, dst_rt.y + 47); // sec skill backSprite.Blit(Rect(21, 198, 267, 36), dst_rt.x + 7, dst_rt.y + 57); // secondary skill SecondarySkillBar secskill_bar; secskill_bar.SetPos(dst_rt.x + 9, dst_rt.y + 59); secskill_bar.SetUseMiniSprite(); secskill_bar.SetInterval(1); secskill_bar.SetSkills(hero.GetSecondarySkills()); secskill_bar.Redraw(); // army bar const Rect rt1(36, 267, 43, 53); Surface sfb1(rt1.w, rt1.h); backSprite.Blit(rt1, 0, 0, sfb1); Surface sfc1(rt1.w, rt1.h - 10); Cursor::DrawCursor(sfc1, 0xd6, true); SelectArmyBar selectArmy; selectArmy.SetArmy(hero.GetArmy()); selectArmy.SetPos(dst_rt.x + 50, dst_rt.y + 170); selectArmy.SetInterval(2); selectArmy.SetBackgroundSprite(sfb1); selectArmy.SetCursorSprite(sfc1); selectArmy.SetUseMons32Sprite(); selectArmy.SetSaveLastTroop(); if(readonly) selectArmy.SetReadOnly(); const Castle* castle = hero.inCastle(); if(castle) selectArmy.SetCastle(*castle); selectArmy.Redraw(); // art bar const Rect rt2(23, 347, 34, 34); Surface sfb2(rt2.w, rt2.h); backSprite.Blit(rt2, 0, 0, sfb2); Surface sfc2(rt2.w, rt2.h); Cursor::DrawCursor(sfc2, 0xd6, true); SelectArtifactsBar selectArtifacts(hero); selectArtifacts.SetPos(dst_rt.x + 37, dst_rt.y + 95); selectArtifacts.SetInterval(2); selectArtifacts.SetBackgroundSprite(sfb2); selectArtifacts.SetCursorSprite(sfc2); selectArtifacts.SetUseArts32Sprite(); if(readonly) selectArtifacts.SetReadOnly(); selectArtifacts.Redraw(); Button buttonDismiss(dst_rt.x + dst_rt.w / 2 - 160, dst_rt.y + dst_rt.h - 125, ICN::HSBTNS, 0, 1); Button buttonExit(dst_rt.x + dst_rt.w / 2 + 130, dst_rt.y + dst_rt.h - 125, ICN::HSBTNS, 2, 3); Button buttonPrev(dst_rt.x + 34, dst_rt.y + 200, ICN::TRADPOST, 3, 4); Button buttonNext(dst_rt.x + 275, dst_rt.y + 200, ICN::TRADPOST, 5, 6); if(castle || readonly) { buttonDismiss.Press(); buttonDismiss.SetDisable(true); } if(readonly || 2 > world.GetKingdom(hero.GetColor()).GetHeroes().size()) { buttonNext.Press(); buttonPrev.Press(); buttonNext.SetDisable(true); buttonPrev.SetDisable(true); } buttonDismiss.Draw(); buttonExit.Draw(); buttonNext.Draw(); buttonPrev.Draw(); cursor.Show(); display.Flip(); while(le.HandleEvents()) { le.MousePressLeft(buttonNext) ? buttonNext.PressDraw() : buttonNext.ReleaseDraw(); le.MousePressLeft(buttonPrev) ? buttonPrev.PressDraw() : buttonPrev.ReleaseDraw(); le.MousePressLeft(buttonExit) ? buttonExit.PressDraw() : buttonExit.ReleaseDraw(); if(buttonDismiss.isEnable()) le.MousePressLeft(buttonDismiss) ? buttonDismiss.PressDraw() : buttonDismiss.ReleaseDraw(); if(buttonNext.isEnable() && le.MouseClickLeft(buttonNext)) return Dialog::NEXT; else if(buttonPrev.isEnable() && le.MouseClickLeft(buttonPrev)) return Dialog::PREV; else // exit if(le.MouseClickLeft(buttonExit) || Game::HotKeyPress(Game::EVENT_DEFAULT_EXIT)) return Dialog::CANCEL; else // dismiss if(buttonDismiss.isEnable() && le.MouseClickLeft(buttonDismiss) && Dialog::YES == Dialog::Message(hero.GetName(), _("Are you sure you want to dismiss this Hero?"), Font::BIG, Dialog::YES | Dialog::NO)) { return Dialog::DISMISS; } // primary click info if(le.MouseClickLeft(ras)) Dialog::Message(_("Attack Skill"), _("Your attack skill is a bonus added to each creature's attack skill."), Font::BIG, Dialog::OK); else if(le.MouseClickLeft(rds)) Dialog::Message(_("Defense Skill"), _("Your defense skill is a bonus added to each creature's defense skill."), Font::BIG, Dialog::OK); else if(le.MouseClickLeft(rps)) Dialog::Message(_("Spell Power"), _("Your spell power determines the length or power of a spell."), Font::BIG, Dialog::OK); else if(le.MouseClickLeft(rks)) Dialog::Message(_("Knowledge"), _("Your knowledge determines how many spell points your hero may have. Under normal cirumstances, a hero is limited to 10 spell points per level of knowledge."), Font::BIG, Dialog::OK); if(le.MouseCursor(secskill_bar.GetArea())) secskill_bar.QueueEventProcessing(); // selector troops event if(le.MouseCursor(selectArmy.GetArea())) { if(selectArtifacts.isSelected()) selectArtifacts.Reset(); if(SelectArmyBar::QueueEventProcessing(selectArmy)) { cursor.Hide(); moraleIndicator.Redraw(); luckIndicator.Redraw(); cursor.Show(); display.Flip(); } } // selector artifacts event if(le.MouseCursor(selectArtifacts.GetArea())) { if(selectArmy.isSelected()) selectArmy.Reset(); SelectArtifactsBar::QueueEventProcessing(selectArtifacts); } if(le.MouseCursor(moraleIndicator.GetArea())) MoraleIndicator::QueueEventProcessing(moraleIndicator); else if(le.MouseCursor(luckIndicator.GetArea())) LuckIndicator::QueueEventProcessing(luckIndicator); else if(le.MouseCursor(experienceInfo.GetArea())) experienceInfo.QueueEventProcessing(); else if(le.MouseCursor(spellPointsInfo.GetArea())) spellPointsInfo.QueueEventProcessing(); } return Dialog::ZERO; }
bool Dialog::SelectGoldOrExp(const std::string & header, const std::string & message, u32 gold, u32 expr, const Heroes & hero) { Display & display = Display::Get(); const int system = Settings::Get().ExtGameEvilInterface() ? ICN::SYSTEME : ICN::SYSTEM; // cursor Cursor & cursor = Cursor::Get(); cursor.Hide(); cursor.SetThemes(cursor.POINTER); const Sprite & sprite_gold = AGG::GetICN(ICN::RESOURCE, 6); const Sprite & sprite_expr = AGG::GetICN(ICN::EXPMRL, 4); Point pt; TextBox box1(header, Font::YELLOW_BIG, BOXAREA_WIDTH); TextBox box2(message, Font::BIG, BOXAREA_WIDTH); Text text; text.Set(GetString(gold) + " " + "(" + "total: " + GetString(world.GetKingdom(hero.GetColor()).GetFunds().Get(Resource::GOLD)) + ")", Font::SMALL); const int spacer = Settings::Get().QVGA() ? 5 : 10; FrameBox box(box1.h() + spacer + box2.h() + spacer + sprite_expr.h() + 2 + text.h(), true); pt.x = box.GetArea().x + box.GetArea().w / 2 - AGG::GetICN(system, 9).w() - 20; pt.y = box.GetArea().y + box.GetArea().h - AGG::GetICN(system, 5).h(); Button button_yes(pt.x, pt.y, system, 5, 6); pt.x = box.GetArea().x + box.GetArea().w / 2 + 20; pt.y = box.GetArea().y + box.GetArea().h - AGG::GetICN(system, 7).h(); Button button_no(pt.x, pt.y, system, 7, 8); Rect pos = box.GetArea(); if(header.size()) box1.Blit(pos); pos.y += box1.h() + spacer; if(message.size()) box2.Blit(pos); pos.y += box2.h() + spacer; pos.y += sprite_expr.h(); // sprite1 pos.x = box.GetArea().x + box.GetArea().w / 2 - sprite_gold.w() - 30; sprite_gold.Blit(pos.x, pos.y - sprite_gold.h()); // text text.Blit(pos.x + (sprite_gold.w() - text.w()) / 2, pos.y + 2); // sprite2 pos.x = box.GetArea().x + box.GetArea().w / 2 + 30; sprite_expr.Blit(pos.x, pos.y - sprite_expr.h()); // text text.Set(GetString(expr) + " " + "(" + "need: " + GetString(Heroes::GetExperienceFromLevel(hero.GetLevel()) - hero.GetExperience()) + ")", Font::SMALL); text.Blit(pos.x + (sprite_expr.w() - text.w()) / 2, pos.y + 2); button_yes.Draw(); button_no.Draw(); cursor.Show(); display.Flip(); LocalEvent & le = LocalEvent::Get(); bool result = false; // message loop while(le.HandleEvents()) { le.MousePressLeft(button_yes) ? button_yes.PressDraw() : button_yes.ReleaseDraw(); le.MousePressLeft(button_no) ? button_no.PressDraw() : button_no.ReleaseDraw(); if(Game::HotKeyPressEvent(Game::EVENT_DEFAULT_READY) || le.MouseClickLeft(button_yes)){ result = true; break; } if(Game::HotKeyPressEvent(Game::EVENT_DEFAULT_EXIT) || le.MouseClickLeft(button_no)){ result = false; break; } } cursor.Hide(); return result; }
bool AI::HeroesGetTask(Heroes & hero) { std::vector<s32> results; results.reserve(5); const Settings & conf = Settings::Get(); AIHero & ai_hero = AIHeroes::Get(hero); AIKingdom & ai_kingdom = AIKingdoms::Get(hero.GetColor()); Queue & task = ai_hero.sheduled_visit; IndexObjectMap & ai_objects = ai_kingdom.scans; const u8 objs1[] = { MP2::OBJ_ARTIFACT, MP2::OBJ_RESOURCE, MP2::OBJ_CAMPFIRE, MP2::OBJ_TREASURECHEST, 0 }; const u8 objs2[] = { MP2::OBJ_SAWMILL, MP2::OBJ_MINES, MP2::OBJ_ALCHEMYLAB, 0 }; const u8 objs3[] = { MP2::OBJ_CASTLE, MP2::OBJ_HEROES, MP2::OBJ_MONSTER, 0 }; // rescan path hero.RescanPath(); Castle* castle = hero.inCastle(); // if hero in castle if(castle) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", in castle"); castle->RecruitAllMonster(); hero.GetArmy().UpgradeTroops(*castle); // recruit army if(hero.Modes(AI::HEROES_HUNTER)) hero.GetArmy().JoinStrongestFromArmy(castle->GetArmy()); else if(hero.Modes(AI::HEROES_SCOUTER)) hero.GetArmy().KeepOnlyWeakestTroops(castle->GetArmy()); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", " << hero.GetArmy().String()); } // patrol task if(hero.Modes(Heroes::PATROL)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", is patrol mode"); // goto patrol center if(hero.GetCenterPatrol() != hero.GetCenter() && hero.GetPath().Calculate(Maps::GetIndexFromAbsPoint(hero.GetCenterPatrol()))) return true; // scan enemy hero if(hero.GetSquarePatrol()) { const Maps::Indexes & results = Maps::ScanAroundObject(Maps::GetIndexFromAbsPoint(hero.GetCenterPatrol()), hero.GetSquarePatrol(), MP2::OBJ_HEROES); for(MapsIndexes::const_iterator it = results.begin(); it != results.end(); ++it) { const Heroes* enemy = world.GetTiles(*it).GetHeroes(); if(enemy && ! enemy->isFriends(hero.GetColor())) { if(hero.GetPath().Calculate(enemy->GetIndex())) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", find enemy"); return true; } } } } // can pickup objects if(conf.ExtHeroPatrolAllowPickup()) { const Maps::Indexes & results = Maps::ScanAroundObjects(hero.GetIndex(), hero.GetSquarePatrol(), objs1); for(MapsIndexes::const_iterator it = results.begin(); it != results.end(); ++it) if(AI::HeroesValidObject(hero, *it) && hero.GetPath().Calculate(*it)) { ai_objects.erase(*it); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ": find object: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); return true; } } // random move /* // disable move: https://sourceforge.net/tracker/?func=detail&aid=3157397&group_id=96859&atid=616180 { Maps::ScanAroundObject(hero.GetIndex(), hero.GetSquarePatrol(), MP2::OBJ_ZERO); if(results.size()) { std::random_shuffle(results.begin(), results.end()); std::vector<s32>::const_iterator it = results.begin(); for(; it != results.end(); ++it) if(world.GetTiles(*it).isPassable(&hero, Direction::CENTER, true) && hero.GetPath().Calculate(*it)) { DEBUG(DBG_AI, Color::String(hero.GetColor()) << ", Patrol " << hero.GetName() << ": move: " << *it); return; } } } */ hero.SetModes(AI::HEROES_STUPID); return false; } if(ai_hero.fix_loop > 3) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ": loop"); hero.SetModes(hero.Modes(AI::HEROES_WAITING) ? AI::HEROES_STUPID : AI::HEROES_WAITING); return false; } // primary target if(Maps::isValidAbsIndex(ai_hero.primary_target)) { if(hero.GetIndex() == ai_hero.primary_target) { ai_hero.primary_target = -1; hero.GetPath().Reset(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", reset path"); } else { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", primary target: " << ai_hero.primary_target << ", " << MP2::StringObject(world.GetTiles(ai_hero.primary_target).GetObject())); const Castle* castle = NULL; if(NULL != (castle = world.GetCastle(Maps::GetPoint(ai_hero.primary_target))) && NULL != castle->GetHeroes().Guest() && castle->isFriends(hero.GetColor())) { hero.SetModes(AI::HEROES_WAITING); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", castle busy.."); } // make path if(ai_hero.primary_target != hero.GetPath().GetDestinationIndex() && !hero.GetPath().Calculate(ai_hero.primary_target)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", path unknown, primary target reset"); ai_hero.primary_target = -1; } } if(hero.GetPath().isValid()) return true; } // scan heroes and castle const Maps::Indexes & enemies = Maps::ScanAroundObjects(hero.GetIndex(), hero.GetScoute(), objs3); for(MapsIndexes::const_iterator it = enemies.begin(); it != enemies.end(); ++it) if(AIHeroesPriorityObject(hero, *it) && hero.GetPath().Calculate(*it)) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", set primary target: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); ai_hero.primary_target = *it; return true; } // check destination if(hero.GetPath().isValid()) { if(! AI::HeroesValidObject(hero, hero.GetPath().GetDestinationIndex())) hero.GetPath().Reset(); else if(hero.GetPath().size() < 5) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", continue short"); ai_hero.fix_loop++; return true; } } // scan 2x2 pickup objects Maps::Indexes pickups = Maps::ScanAroundObjects(hero.GetIndex(), 2, objs1); // scan 3x3 capture objects const Maps::Indexes & captures = Maps::ScanAroundObjects(hero.GetIndex(), 3, objs2); if(captures.size()) pickups.insert(pickups.end(), captures.begin(), captures.end()); if(pickups.size()) { hero.GetPath().Reset(); for(MapsIndexes::const_iterator it = pickups.begin(); it != pickups.end(); ++it) if(AI::HeroesValidObject(hero, *it)) { task.push_front(*it); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", find object: " << MP2::StringObject(world.GetTiles(*it).GetObject()) << "(" << *it << ")"); } } if(hero.GetPath().isValid()) { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", continue"); ai_hero.fix_loop++; return true; } if(task.empty()) { // get task from kingdom DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", empty task"); AIHeroesAddedTask(hero); } else // remove invalid task task.remove_if(std::not1(std::bind1st(std::ptr_fun(&AIHeroesValidObject2), &hero))); // random shuffle if(1 < task.size() && Rand::Get(1)) { Queue::iterator it1, it2; it2 = it1 = task.begin(); ++it2; std::swap(*it1, *it2); } // find passable index while(task.size()) { const s32 & index = task.front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", look for: " << MP2::StringObject(world.GetTiles(index).GetObject()) << "(" << index << ")"); if(hero.GetPath().Calculate(index)) break; DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: unable get object: " << index << ", remove task..."); task.pop_front(); } // success if(task.size()) { const s32 & index = task.front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " go to: " << index); ai_objects.erase(index); task.pop_front(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << ", route: " << hero.GetPath().String()); return true; } else if(hero.Modes(AI::HEROES_WAITING)) { hero.GetPath().Reset(); DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: unknown task., help my please.."); hero.ResetModes(AI::HEROES_WAITING); hero.SetModes(AI::HEROES_STUPID); } else { DEBUG(DBG_AI, DBG_TRACE, hero.GetName() << " say: waiting..."); hero.SetModes(AI::HEROES_WAITING); } return false; }
void AIHeroesAddedTask(Heroes & hero) { AIHero & ai_hero = AIHeroes::Get(hero); AIKingdom & ai_kingdom = AIKingdoms::Get(hero.GetColor()); Queue & task = ai_hero.sheduled_visit; IndexObjectMap & ai_objects = ai_kingdom.scans; // load minimal distance tasks std::vector<IndexDistance> objs; objs.reserve(ai_objects.size()); for(std::map<s32, int>::const_iterator it = ai_objects.begin(); it != ai_objects.end(); ++it) { const Maps::Tiles & tile = world.GetTiles((*it).first); if(hero.isShipMaster()) { if(MP2::OBJ_COAST != tile.GetObject() && ! tile.isWater()) continue; // check previous positions if(MP2::OBJ_COAST == (*it).second && hero.isVisited(world.GetTiles((*it).first))) continue; } else { if(tile.isWater() && MP2::OBJ_BOAT != tile.GetObject()) continue; } objs.push_back(IndexDistance((*it).first, Maps::GetApproximateDistance(hero.GetIndex(), (*it).first))); } DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) << ", hero: " << hero.GetName() << ", task prepare: " << objs.size()); std::sort(objs.begin(), objs.end(), IndexDistance::Shortest); for(std::vector<IndexDistance>::const_iterator it = objs.begin(); it != objs.end(); ++it) { if(task.size() >= HERO_MAX_SHEDULED_TASK) break; const bool validobj = AI::HeroesValidObject(hero, (*it).first); if(validobj && hero.GetPath().Calculate((*it).first)) { DEBUG(DBG_AI, DBG_INFO, Color::String(hero.GetColor()) << ", hero: " << hero.GetName() << ", added tasks: " << MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first << ", distance: " << (*it).second); task.push_back((*it).first); ai_objects.erase((*it).first); } else { DEBUG(DBG_AI, DBG_TRACE, Color::String(hero.GetColor()) << ", hero: " << hero.GetName() << (!validobj ? ", invalid: " : ", impossible: ") << MP2::StringObject(ai_objects[(*it).first]) << ", index: " << (*it).first << ", distance: " << (*it).second); } } if(task.empty()) AIHeroesAddedRescueTask(hero); }
int Dialog::ArmyJoinWithCost(const Troop & troop, u32 join, u32 gold, Heroes & hero) { Display & display = Display::Get(); const Settings & conf = Settings::Get(); // cursor Cursor & cursor = Cursor::Get(); int oldthemes = cursor.Themes(); cursor.Hide(); cursor.SetThemes(cursor.POINTER); std::string message; if(troop.GetCount() == 1) message = _("The creature is swayed by your diplomatic tongue, and offers to join your army for the sum of %{gold} gold.\nDo you accept?"); else { message = _("The creatures are swayed by your diplomatic\ntongue, and make you an offer:\n \n"); if(join != troop.GetCount()) message += _("%{offer} of the %{total} %{monster} will join your army, and the rest will leave you alone, for the sum of %{gold} gold.\nDo you accept?"); else message += _("All %{offer} of the %{monster} will join your army for the sum of %{gold} gold.\nDo you accept?"); } StringReplace(message, "%{offer}", join); StringReplace(message, "%{total}", troop.GetCount()); StringReplace(message, "%{monster}", StringLower(troop.GetPluralName(join))); StringReplace(message, "%{gold}", gold); TextBox textbox(message, Font::BIG, BOXAREA_WIDTH); const int buttons = Dialog::YES | Dialog::NO; const Sprite & sprite = AGG::GetICN(ICN::RESOURCE, 6); int posy = 0; Text text; message = _("(Rate: %{percent})"); StringReplace(message, "%{percent}", troop.GetMonster().GetCost().gold * join * 100 / gold); text.Set(message, Font::BIG); FrameBox box(10 + textbox.h() + 10 + text.h() + 40 + sprite.h() + 10, buttons); const Rect & pos = box.GetArea(); posy = pos.y + 10; textbox.Blit(pos.x, posy); posy += textbox.h() + 10; text.Blit(pos.x + (pos.w - text.w()) / 2, posy); posy += text.h() + 40; sprite.Blit(pos.x + (pos.w - sprite.w()) / 2, posy); TextSprite tsTotal(GetString(gold) + " " + "(" + "total: " + GetString(world.GetKingdom(hero.GetColor()).GetFunds().Get(Resource::GOLD)) + ")", Font::SMALL, pos.x + (pos.w - text.w()) / 2, posy + sprite.h() + 5); tsTotal.Show(); ButtonGroups btnGroups(pos, buttons); Button btnMarket(pos.x + pos.w / 2 - 60 - 36, posy, (conf.ExtGameEvilInterface() ? ICN::ADVEBTNS : ICN::ADVBTNS), 4, 5); Button btnHeroes(pos.x + pos.w / 2 + 60, posy, (conf.ExtGameEvilInterface() ? ICN::ADVEBTNS : ICN::ADVBTNS), 0, 1); const Kingdom & kingdom = hero.GetKingdom(); if(! kingdom.AllowPayment(payment_t(Resource::GOLD, gold))) btnGroups.DisableButton1(true); TextSprite tsEnough; if(kingdom.GetCountMarketplace()) { if(kingdom.AllowPayment(payment_t(Resource::GOLD, gold))) btnMarket.SetDisable(true); else { std::string msg = _("Not enough gold (%{gold})"); StringReplace(msg, "%{gold}", gold - kingdom.GetFunds().Get(Resource::GOLD)); tsEnough.SetText(msg, Font::YELLOW_SMALL); tsEnough.SetPos(btnMarket.x - 25, btnMarket.y - 17); tsEnough.Show(); btnMarket.Draw(); } } if(hero.GetArmy().GetCount() < hero.GetArmy().Size() || hero.GetArmy().HasMonster(troop)) btnHeroes.SetDisable(true); else { TextBox textbox2(_("Not room in\nthe garrison"), Font::SMALL, 100); textbox2.Blit(btnHeroes.x - 35, btnHeroes.y - 30); btnHeroes.Draw(); btnGroups.DisableButton1(true); } btnGroups.Draw(); cursor.Show(); display.Flip(); LocalEvent & le = LocalEvent::Get(); // message loop int result = Dialog::ZERO; while(result == Dialog::ZERO && le.HandleEvents()) { if(btnMarket.isEnable()) le.MousePressLeft(btnMarket) ? btnMarket.PressDraw() : btnMarket.ReleaseDraw(); if(btnHeroes.isEnable()) le.MousePressLeft(btnHeroes) ? btnHeroes.PressDraw() : btnHeroes.ReleaseDraw(); if(!buttons && !le.MousePressRight()) break; result = btnGroups.QueueEventProcessing(); if(btnMarket.isEnable() && le.MouseClickLeft(btnMarket)) { Marketplace(false); cursor.Hide(); tsTotal.Hide(); tsTotal.SetText(GetString(gold) + " " + "(" + "total: " + GetString(world.GetKingdom(hero.GetColor()).GetFunds().Get(Resource::GOLD)) + ")"); tsTotal.Show(); if(kingdom.AllowPayment(payment_t(Resource::GOLD, gold))) { tsEnough.Hide(); btnGroups.DisableButton1(false); btnGroups.Draw(); } else { tsEnough.Hide(); std::string msg = _("Not enough gold (%{gold})"); StringReplace(msg, "%{gold}", gold - kingdom.GetFunds().Get(Resource::GOLD)); tsEnough.SetText(msg, Font::SMALL); tsEnough.Show(); } cursor.Show(); display.Flip(); } else if(btnHeroes.isEnable() && le.MouseClickLeft(btnHeroes)) { hero.OpenDialog(false, false); if(hero.GetArmy().GetCount() < hero.GetArmy().Size()) { btnGroups.DisableButton1(false); btnGroups.Draw(); } cursor.Show(); display.Flip(); } } cursor.Hide(); cursor.SetThemes(oldthemes); cursor.Show(); return result; }
bool ActionSpellTownPortal(Heroes & hero) { const Kingdom & kingdom = world.GetKingdom(hero.GetColor()); std::vector<s32> castles; Display & display = Display::Get(); Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); cursor.Hide(); cursor.SetThemes(cursor.POINTER); for(KingdomCastles::const_iterator it = kingdom.GetCastles().begin(); it != kingdom.GetCastles().end(); ++it) if(*it && !(*it)->GetHeroes().Guest()) castles.push_back((**it).GetIndex()); if(castles.empty()) { Dialog::Message("", _("No avaialble town. Spell Failed!!!"), Font::BIG, Dialog::OK); return false; } const u16 window_w = 280; const u16 window_h = 200; Dialog::FrameBorder* frameborder = new Dialog::FrameBorder(); frameborder->SetPosition((display.w() - window_w) / 2 - BORDERWIDTH, (display.h() - window_h) / 2 - BORDERWIDTH, window_w, window_h); frameborder->Redraw(); const Rect & area = frameborder->GetArea(); const Sprite & background = AGG::GetICN(ICN::STONEBAK, 0); background.Blit(Rect(0, 0, window_w, window_h), area); u16 result = Dialog::ZERO; CastleIndexListBox listbox(area, result); listbox.RedrawBackground(area); listbox.SetScrollButtonUp(ICN::LISTBOX, 3, 4, Point(area.x + 256, area.y + 55)); listbox.SetScrollButtonDn(ICN::LISTBOX, 5, 6, Point(area.x + 256, area.y + 145)); listbox.SetScrollSplitter(AGG::GetICN(ICN::LISTBOX, 10), Rect(area.x + 261, area.y + 78, 14, 64)); listbox.SetAreaMaxItems(5); listbox.SetAreaItems(Rect(area.x + 10, area.y + 60, 250, 100)); listbox.SetListContent(castles); listbox.Redraw(); ButtonGroups btnGroups(area, Dialog::OK|Dialog::CANCEL); btnGroups.Draw(); cursor.Show(); display.Flip(); while(result == Dialog::ZERO && le.HandleEvents()) { result = btnGroups.QueueEventProcessing(); listbox.QueueEventProcessing(); if(!cursor.isVisible()) { listbox.Redraw(); cursor.Show(); display.Flip(); } } delete frameborder; // store if(result == Dialog::OK) return HeroesTownGate(hero, world.GetCastle(listbox.GetCurrent())); return false; }
void Dialog::QuickInfo(const Heroes & hero) { Display & display = Display::Get(); Cursor & cursor = Cursor::Get(); cursor.Hide(); const ICN::icn_t qwikhero = ICN::QWIKHERO; AGG::PreloadObject(qwikhero); // image box const Sprite &box = AGG::GetICN(qwikhero, 0); const Interface::GameArea & gamearea = Interface::GameArea::Get(); const Rect ar(BORDERWIDTH, BORDERWIDTH, gamearea.GetArea().w, gamearea.GetArea().h); LocalEvent & le = LocalEvent::Get(); const Point & mp = le.GetMouseCursor(); Rect cur_rt; u16 mx = (mp.x - BORDERWIDTH) / TILEWIDTH; mx *= TILEWIDTH; u16 my = (mp.y - BORDERWIDTH) / TILEWIDTH; my *= TILEWIDTH; // top left if(mx <= ar.x + ar.w / 2 && my <= ar.y + ar.h / 2) cur_rt = Rect(mx + TILEWIDTH, my + TILEWIDTH, box.w(), box.h()); else // top right if(mx > ar.x + ar.w / 2 && my <= ar.y + ar.h / 2) cur_rt = Rect(mx - box.w(), my + TILEWIDTH, box.w(), box.h()); else // bottom left if(mx <= ar.x + ar.w / 2 && my > ar.y + ar.h / 2) cur_rt = Rect(mx + TILEWIDTH, my - box.h(), box.w(), box.h()); else // bottom right cur_rt = Rect(mx - box.w(), my - box.h(), box.w(), box.h()); if(Settings::Get().QVGA()) { cur_rt = Rect((display.w() - box.w()) / 2, (display.h() - box.h()) / 2, box.w(), box.h()); } Background back(cur_rt); back.Save(); display.Blit(box, cur_rt.x, cur_rt.y); cur_rt = Rect(back.GetRect().x + 28 , back.GetRect().y + 10, 146, 144); Point dst_pt; Text text; // heroes name text.Set(hero.GetName(), Font::SMALL); dst_pt.x = cur_rt.x + (cur_rt.w - text.w()) / 2; dst_pt.y = cur_rt.y + 2; text.Blit(dst_pt); // mini port heroes const Surface & port = hero.GetPortrait30x22(); dst_pt.x = cur_rt.x + (cur_rt.w - port.w()) / 2; dst_pt.y += 15; display.Blit(port, dst_pt); // color flags u8 index = 0; switch(hero.GetColor()) { case Color::BLUE: index = 0; break; case Color::GREEN: index = 2; break; case Color::RED: index = 4; break; case Color::YELLOW: index = 6; break; case Color::ORANGE: index = 8; break; case Color::PURPLE: index = 10; break; case Color::GRAY: index = 12; break; } const Sprite & l_flag = AGG::GetICN(ICN::FLAG32, index); dst_pt.x = cur_rt.x + (cur_rt.w - 40) / 2 - l_flag.w(); display.Blit(l_flag, dst_pt); const Sprite & r_flag = AGG::GetICN(ICN::FLAG32, index + 1); dst_pt.x = cur_rt.x + (cur_rt.w + 40) / 2; display.Blit(r_flag, dst_pt); std::string message; // attack message = _("Attack"); message += ":"; text.Set(message); dst_pt.x = cur_rt.x + 35; dst_pt.y += port.h() + 4; text.Blit(dst_pt); message.clear(); String::AddInt(message, hero.GetAttack()); text.Set(message); dst_pt.x += 75; text.Blit(dst_pt); // defense message = _("Defense"); message += ":"; text.Set(message); dst_pt.x = cur_rt.x + 35; dst_pt.y += 12; text.Blit(dst_pt); message.clear(); String::AddInt(message, hero.GetDefense()); text.Set(message); dst_pt.x += 75; text.Blit(dst_pt); // power message = _("Spell Power"); message += ":"; text.Set(message); dst_pt.x = cur_rt.x + 35; dst_pt.y += 12; text.Blit(dst_pt); message.clear(); String::AddInt(message, hero.GetPower()); text.Set(message); dst_pt.x += 75; text.Blit(dst_pt); // knowledge message = _("Knowledge"); message += ":"; text.Set(message); dst_pt.x = cur_rt.x + 35; dst_pt.y += 12; text.Blit(dst_pt); message.clear(); String::AddInt(message, hero.GetKnowledge()); text.Set(message); dst_pt.x += 75; text.Blit(dst_pt); // spell point message = _("Spell Points"); message += ":"; text.Set(message); dst_pt.x = cur_rt.x + 35; dst_pt.y += 12; text.Blit(dst_pt); message.clear(); String::AddInt(message, hero.GetSpellPoints()); message += "/"; String::AddInt(message, hero.GetMaxSpellPoints()); text.Set(message); dst_pt.x += 75; text.Blit(dst_pt); // draw monster sprite in one string const u8 mycolor = Settings::Get().MyColor(); const bool hide = mycolor != hero.GetColor() && !world.GetKingdom(mycolor).Modes(Kingdom::IDENTIFYHERO); hero.GetArmy().DrawMons32Line(cur_rt.x - 5, cur_rt.y + 114, 160, 0, 0, hide); cursor.Show(); display.Flip(); // quick info loop while(le.HandleEvents() && le.MousePressRight()); // restore background cursor.Hide(); back.Restore(); cursor.Show(); display.Flip(); }