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); }
void Interface::Basic::EventDefaultAction(void) { Heroes* hero = GetFocusHeroes(); if(hero) { const Maps::Tiles & tile = world.GetTiles(hero->GetIndex()); // 1. action object if(MP2::isActionObject(hero->GetMapsObject(), hero->isShipMaster()) && (! MP2::isMoveObject(hero->GetMapsObject()) || hero->CanMove())) { hero->Action(hero->GetIndex()); if(MP2::OBJ_STONELIGHTS == tile.GetObject(false) || MP2::OBJ_WHIRLPOOL == tile.GetObject(false)) SetRedraw(REDRAW_HEROES); SetRedraw(REDRAW_GAMEAREA); } else // 2. continue if(hero->GetPath().isValid()) hero->SetMove(true); else // 3. hero dialog Game::OpenHeroesDialog(*hero); } else // 4. town dialog if(GetFocusCastle()) { Game::OpenCastleDialog(*GetFocusCastle()); } }
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 PassableToTile(const Heroes & hero, const Maps::Tiles & toTile, int direct, s32 dst) { // check end point if(toTile.GetIndex() == dst) { // fix toTilePassable with action object if(MP2::isPickupObject(toTile.GetObject())) return true; // check direct to object if(MP2::isActionObject(toTile.GetObject(false), hero.isShipMaster())) return Direction::Reflect(direct) & toTile.GetPassable(); if(MP2::OBJ_HEROES == toTile.GetObject()) return toTile.isPassable(NULL, Direction::Reflect(direct), (hero.isControlAI() ? AI::HeroesSkipFog() : false)); } // check to tile direct if(! toTile.isPassable(&hero, Direction::Reflect(direct), (hero.isControlAI() ? AI::HeroesSkipFog() : false))) return false; if(toTile.GetIndex() != dst) { if(MP2::isPickupObject(toTile.GetObject()) || MP2::isActionObject(toTile.GetObject(false), hero.isShipMaster())) return false; // check hero/monster on route switch(toTile.GetObject()) { case MP2::OBJ_HEROES: case MP2::OBJ_MONSTER: return false; default: break; } // check monster protection if(CheckMonsterProtectionAndNotDst(toTile.GetIndex(), dst)) return false; } return true; }
bool isNeedStayFrontObject(const Heroes & hero, const Maps::Tiles & next) { if(next.GetObject() == MP2::OBJ_CASTLE) { const Castle* castle = world.GetCastle(next.GetCenter()); return (castle && ! hero.isFriends(castle->GetColor())); } else // to coast action if(hero.isShipMaster() && next.GetObject() == MP2::OBJ_COAST) return true; return MP2::isNeedStayFront(next.GetObject()); }
bool ActionSpellDimensionDoor(Heroes & hero) { const u8 distance = Spell::CalculateDimensionDoorDistance(hero.GetPower(), hero.GetArmy().GetHitPoints()); Interface::Basic & I = Interface::Basic::Get(); Cursor & cursor = Cursor::Get(); // center hero cursor.Hide(); I.gameArea.SetCenter(hero.GetCenter()); GameFocus::SetRedraw(); I.Redraw(); const s32 src = hero.GetIndex(); // get destination const s32 dst = I.GetDimensionDoorDestination(src, distance, hero.isShipMaster()); if(Maps::isValidAbsIndex(src) && Maps::isValidAbsIndex(dst)) { AGG::PlaySound(M82::KILLFADE); hero.GetPath().Reset(); hero.FadeOut(); hero.SpellCasted(Spell::DIMENSIONDOOR); cursor.Hide(); hero.Move2Dest(dst, true); I.gameArea.SetCenter(hero.GetCenter()); GameFocus::SetRedraw(); I.Redraw(); AGG::PlaySound(M82::KILLFADE); hero.FadeIn(); hero.ActionNewPosition(); return false; /* SpellCasted apply */ } return false; }
Sprite SpriteShad(const Heroes & hero, int index) { int icn_shad = hero.isShipMaster() ? ICN::BOATSHAD : ICN::SHADOW32; int index_sprite = 0; 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 = 45; break; case Direction::LEFT: index_sprite = 54; break; case Direction::TOP_LEFT: index_sprite = 63; break; default: DEBUG(DBG_GAME, DBG_WARN, "unknown direction"); break; } return AGG::GetICN(icn_shad, index_sprite + (index % 9)); }
Sprite SpriteHero(const Heroes & hero, int index, bool reflect, bool rotate) { int icn_hero = ICN::UNKNOWN; int index_sprite = 0; if(hero.isShipMaster()) icn_hero = ICN::BOAT32; else switch(hero.GetRace()) { case Race::KNGT: icn_hero = ICN::KNGT32; break; case Race::BARB: icn_hero = ICN::BARB32; break; case Race::SORC: icn_hero = ICN::SORC32; break; case Race::WRLK: icn_hero = ICN::WRLK32; break; case Race::WZRD: icn_hero = ICN::WZRD32; break; case Race::NECR: icn_hero = ICN::NECR32; break; default: DEBUG(DBG_GAME, DBG_WARN, "unknown race"); 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_hero, index_sprite + (index % 9), reflect); }
void Interface::Basic::MoveHeroFromArrowKeys(Heroes & hero, int direct) { if(Maps::isValidDirection(hero.GetIndex(), direct)) { s32 dst = Maps::GetDirectionIndex(hero.GetIndex(), direct); const Maps::Tiles & tile = world.GetTiles(dst); bool allow = false; switch(tile.GetObject()) { case MP2::OBJN_CASTLE: { const Castle* to_castle = world.GetCastle(hero.GetCenter()); if(to_castle) { dst = to_castle->GetIndex(); allow = true; } break; } case MP2::OBJ_BOAT: case MP2::OBJ_CASTLE: case MP2::OBJ_HEROES: case MP2::OBJ_MONSTER: allow = true; break; default: allow = (tile.isPassable(&hero, Direction::CENTER, false) || MP2::isActionObject(tile.GetObject(), hero.isShipMaster())); break; } if(allow) ShowPathOrStartMoveHero(&hero, dst); } }
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); }
bool PassableFromToTile(const Heroes & hero, s32 from, const s32 & to, int direct, s32 dst) { const Maps::Tiles & fromTile = world.GetTiles(from); const Maps::Tiles & toTile = world.GetTiles(to); // check start point if(hero.GetIndex() == from) { if(MP2::isActionObject(fromTile.GetObject(false), hero.isShipMaster())) { // check direct from object if(! (direct & fromTile.GetPassable())) return false; } else { // check from tile direct if(! fromTile.isPassable(&hero, direct, (hero.isControlAI() ? AI::HeroesSkipFog() : false))) return false; } } else { if(MP2::isActionObject(fromTile.GetObject(), hero.isShipMaster())) { // check direct from object if(! (direct & fromTile.GetPassable())) return false; } else { // check from tile direct if(! fromTile.isPassable(&hero, direct, (hero.isControlAI() ? AI::HeroesSkipFog() : false))) return false; } } if(fromTile.isWater() && !toTile.isWater()) { switch(toTile.GetObject()) { case MP2::OBJ_BOAT: case MP2::OBJ_MONSTER: case MP2::OBJ_HEROES: return false; case MP2::OBJ_COAST: return toTile.GetIndex() == dst; default: break; } } else if(!fromTile.isWater() && toTile.isWater()) { switch(toTile.GetObject()) { case MP2::OBJ_BOAT: return true; case MP2::OBJ_HEROES: return toTile.GetIndex() == dst; default: break; } } // check corner water/coast if(hero.isShipMaster() && (direct & (Direction::TOP_LEFT | Direction::TOP_RIGHT | Direction::BOTTOM_RIGHT | Direction::BOTTOM_LEFT))) { switch(direct) { case Direction::TOP_LEFT: if((Maps::isValidDirection(from, Direction::TOP) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::TOP)).isWater()) || (Maps::isValidDirection(from, Direction::LEFT) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::LEFT)).isWater())) return false; break; case Direction::TOP_RIGHT: if((Maps::isValidDirection(from, Direction::TOP) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::TOP)).isWater()) || (Maps::isValidDirection(from, Direction::RIGHT) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::RIGHT)).isWater())) return false; break; case Direction::BOTTOM_RIGHT: if((Maps::isValidDirection(from, Direction::BOTTOM) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::BOTTOM)).isWater()) || (Maps::isValidDirection(from, Direction::RIGHT) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::RIGHT)).isWater())) return false; break; case Direction::BOTTOM_LEFT: if((Maps::isValidDirection(from, Direction::BOTTOM) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::BOTTOM)).isWater()) || (Maps::isValidDirection(from, Direction::LEFT) && ! world.GetTiles(Maps::GetDirectionIndex(from, Direction::LEFT)).isWater())) return false; break; default: break; } } return PassableToTile(hero, toTile, direct, dst); }