Exemplo n.º 1
0
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);
	}
    }
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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);
}
Exemplo n.º 4
0
bool ActionSpellIdentifyHero(Heroes & hero)
{
    world.GetKingdom(hero.GetColor()).SetModes(Kingdom::IDENTIFYHERO);
    Message("", _("Enemy heroes are now fully identifiable."), Font::BIG, Dialog::OK);

    return true;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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());
}
Exemplo n.º 7
0
// 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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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();
}