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);
    }
}
Exemple #10
0
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);
}