예제 #1
0
Battle::Catapult::Catapult(const HeroBase & hero, bool fortification) : cat_shots(1), cat_first(20), cat_miss(true) /*, cat_fort(fortification) */
{
    switch(hero.GetLevelSkill(Skill::Secondary::BALLISTICS))
    {
	case Skill::Level::BASIC:
	    cat_first = 40;
	    cat_miss = false;
	    break;

	case Skill::Level::ADVANCED:
	    cat_first = 80;
	    cat_shots += 1;
	    cat_miss = false;
	    break;

	case Skill::Level::EXPERT:
	    cat_first = 100;
	    cat_shots += 1;
	    cat_miss = false;
	    break;

	default: break;
    }

    u32 acount = hero.HasArtifact(Artifact::BALLISTA);
    if(acount) cat_shots += acount * Artifact(Artifact::BALLISTA).ExtraValue();
}
예제 #2
0
void Battle::PickupArtifactsAction(HeroBase & hero1, HeroBase & hero2, bool local)
{
    BagArtifacts & bag1 = hero1.GetBagArtifacts();
    BagArtifacts & bag2 = hero2.GetBagArtifacts();

    for(u8 ii = 0; ii < bag2.size(); ++ii)
    {
	Artifact & art = bag2[ii];

	if(art.isUltimate())
	{
	    art = Artifact::UNKNOWN;
	}
	else
	if(art() != Artifact::UNKNOWN && art() != Artifact::MAGIC_BOOK)
        {
            BagArtifacts::iterator it = std::find(bag1.begin(), bag1.end(), Artifact((Artifact::UNKNOWN)));
            if(bag1.end() != it)
            {
        	*it = art;
        	if(local)
		{
		    Game::PlayPickupSound();
		    Dialog::ArtifactInfo(_("You have captured an enemy artifact!"), "", art);
		}
    	    }
    	    art = Artifact::UNKNOWN;
	}
    }
}
예제 #3
0
void Battle::EagleEyeSkillAction(HeroBase & hero, const SpellStorage & spells, bool local)
{
    if(spells.empty() ||
	!hero.HaveSpellBook()) return;

    SpellStorage new_spells;
    new_spells.reserve(10);

    const Skill::Secondary eagleeye(Skill::Secondary::EAGLEEYE, hero.GetLevelSkill(Skill::Secondary::EAGLEEYE));

    // filter spells
    for(SpellStorage::const_iterator
	it = spells.begin(); it != spells.end(); ++it)
    {
	const Spell & sp = *it;
    	if(!hero.HaveSpell(sp))
	{
	    switch(eagleeye.Level())
	    {
		case Skill::Level::BASIC:
		    // 20%
		    if(3 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		case Skill::Level::ADVANCED:
		    // 30%
		    if(4 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		case Skill::Level::EXPERT:
		    // 40%
		    if(5 > sp.Level() && eagleeye.GetValues() >= Rand::Get(1, 100)) new_spells.push_back(sp);
		    break;
		default: break;
    	    }
	}
    }

    // add new spell
    for(SpellStorage::const_iterator
	it = new_spells.begin(); it != new_spells.end(); ++it)
    {
	const Spell & sp = *it;
	if(local)
	{
	    std::string msg = _("Through eagle-eyed observation, %{name} is able to learn the magic spell %{spell}.");
	    String::Replace(msg, "%{name}", hero.GetName());
	    String::Replace(msg, "%{spell}", sp.GetName());
	    Game::PlayPickupSound();
	    Dialog::SpellInfo("", msg, sp);
	}
    }

    hero.AppendSpellsToBook(new_spells, true);
}
예제 #4
0
bool Battle::AIApplySpell(const Spell & spell, const Unit* b, const HeroBase & hero, Actions & a)
{
    u8 mass = Spell::NONE;

    switch(spell())
    {
        case Spell::CURE:	mass = Spell::MASSCURE; break;
        case Spell::HASTE:	mass = Spell::MASSHASTE; break;
        case Spell::SLOW:	mass = Spell::MASSSLOW; break;
        case Spell::BLESS:	mass = Spell::MASSBLESS; break;
        case Spell::CURSE:	mass = Spell::MASSCURSE; break;
        case Spell::DISPEL:	mass = Spell::MASSDISPEL; break;
        case Spell::SHIELD:	mass = Spell::MASSSHIELD; break;

	default: break;
    }

    if(mass != Spell::NONE &&
	AIApplySpell(mass, b, hero, a)) return true;

    if(hero.CanCastSpell(spell) && (!b || b->AllowApplySpell(spell, &hero)))
    {
	a.push_back(Battle::Command(MSG_BATTLE_CAST, spell(), (b ? b->GetHeadIndex() : -1)));
	return true;
    }

    return false;
}
예제 #5
0
void Battle::NecromancySkillAction(HeroBase & hero, u32 killed, bool local)
{
    Army & army = hero.GetArmy();

    if(0 == killed ||
	(army.isFullHouse() && !army.HasMonster(Monster::SKELETON))) return;

    // check necromancy shrine build
    u16 percent = 10 * world.GetKingdom(army.GetColor()).GetCountNecromancyShrineBuild();

    // check artifact
    u8 acount = hero.HasArtifact(Artifact::SPADE_NECROMANCY);
    if(acount) percent += acount * 10;

    // fix over 60%
    if(percent > 60) percent = 60;

    percent += hero.GetSecondaryValues(Skill::Secondary::NECROMANCY);

    // hard fix overflow
    if(percent > 90) percent = 90;

    const Monster mons(Monster::SKELETON);
    const u32 count = Monster::GetCountFromHitPoints(Monster::SKELETON, mons.GetHitPoints() * killed * percent / 100);
    army.JoinTroop(mons, count);

    if(local)
    {
	std::string msg = _("Practicing the dark arts of necromancy, you are able to raise %{count} of the enemy's dead to return under your service as %{monster}");
	String::Replace(msg, "%{count}", count);
	String::Replace(msg, "%{monster}", mons.GetMultiName());
	Surface sf1(40, 45);
	const Sprite & sf2 = AGG::GetICN(ICN::MONS32, mons.GetSpriteIndex());
	sf2.Blit((sf1.w() - sf2.w()) / 2, 0, sf1);
	Text text(GetString(count), Font::SMALL);
	text.Blit((sf1.w() - text.w()) / 2, sf2.h() + 3, sf1);
	Game::PlayPickupSound();

	Dialog::SpriteInfo("", msg, sf1);
    }

    DEBUG(DBG_BATTLE, DBG_TRACE, "raise: " << count << mons.GetMultiName());
}
예제 #6
0
int ArtifactsModifiersResult(int type, const u8* arts, u32 size, const HeroBase & base, std::string* strs)
{
    int result = 0;

    for(u32 ii = 0; ii < size; ++ii)
    {
	    const Artifact art(arts[ii]);

    	    if(art.isValid())
    	    {
		int acount = base.HasArtifact(art);
		if(acount)
		{
		    s32 mod = art.ExtraValue();

		    switch(art())
		    {
			case Artifact::SWORD_BREAKER:		if(type == MDF_ATTACK) mod = 1; break;
			// power
			case Artifact::BROACH_SHIELDING:	if(type == MDF_POWER) mod = -2; break;
			// morale/luck
			case Artifact::BATTLE_GARB:		if(type == MDF_MORALE || type == MDF_LUCK) mod = 10; break;
			case Artifact::MASTHEAD:		if(type == MDF_MORALE || type == MDF_LUCK) mod = base.Modes(Heroes::SHIPMASTER) ? art.ExtraValue() : 0; break;
			// morale
			case Artifact::FIZBIN_MISFORTUNE:	if(type == MDF_MORALE) mod = -art.ExtraValue(); break;
			default: break;
		    }

    		    result += mod * acount;

    		    if(strs && mod)
    		    {
        		strs->append(art.GetName());
			StringAppendModifiers(*strs, mod);
        		strs->append("\n");
		    }
		}
	    }
    }

    return result;
}
예제 #7
0
s16 Battle::AIAreaSpellDst(const HeroBase & hero)
{
    std::map<s16, u8> dstcount;

    Arena* arena = GetArena();
    Units enemies(arena->GetForce(hero.GetColor(), true), true);

    for(Units::const_iterator
	it1 = enemies.begin(); it1 != enemies.end(); ++it1)
    {
	const Indexes around = Board::GetAroundIndexes(**it1);

	for(Indexes::const_iterator
	    it2 = around.begin(); it2 != around.end(); ++it2)
	    dstcount[*it2] += 1;
    }

    // find max
    std::map<s16, u8>::const_iterator max = std::max_element(dstcount.begin(), dstcount.end(), MaxDstCount);

    return max != dstcount.end() ? (*max).first : -1;
}
예제 #8
0
void AI::HeroesPreBattle(HeroBase & hero)
{
    Castle* castle = world.GetCastle(hero.GetCenter());
    if(castle && hero.GetType() != HeroBase::CAPTAIN)
	hero.GetArmy().JoinTroops(castle->GetArmy());
}
예제 #9
0
bool Battle2::DialogBattleSurrender(const HeroBase & hero, u32 cost)
{
    Display & display = Display::Get();
    Cursor & cursor = Cursor::Get();
    LocalEvent & le = LocalEvent::Get();
    Settings & conf = Settings::Get();

    cursor.Hide();
    cursor.SetThemes(Cursor::POINTER);

    const Sprite & dialog = AGG::GetICN(conf.EvilInterface() ? ICN::SURDRBKE : ICN::SURDRBKG, 0);

    Rect pos_rt;
    pos_rt.x = (display.w() - dialog.w() + 16) / 2;
    pos_rt.y = (display.h() - dialog.h() + 16) / 2;
    pos_rt.w = dialog.w();
    pos_rt.h = dialog.h();

    Background back(pos_rt);
    back.Save();

    display.Blit(dialog, pos_rt.x, pos_rt.y);

    const ICN::icn_t icn = conf.EvilInterface() ? ICN::SURRENDE : ICN::SURRENDR;

    Button btnAccept(pos_rt.x + 90, pos_rt.y + 150, icn, 0, 1);
    Button btnDecline(pos_rt.x + 295, pos_rt.y + 150, icn, 2, 3);

    btnAccept.Draw();
    btnDecline.Draw();

    const Sprite & window = AGG::GetICN(icn, 4);
    display.Blit(window, pos_rt.x + 54, pos_rt.y + 30);
    display.Blit(Portrait::Get(hero, Portrait::BIG), pos_rt.x + 58, pos_rt.y + 38);

    std::string str = _("%{name} states:");
    String::Replace(str, "%{name}", hero.GetName());
    Text text(str, Font::BIG);
    text.Blit(pos_rt.x + 320 - text.w() / 2, pos_rt.y + 30);

    str = _("I will accept your surrender and grant you and your toops safe passage for the price of %{price} gold.");
    String::Replace(str, "%{price}", cost);

    TextBox box(str, Font::BIG, 275);
    box.Blit(pos_rt.x + 175, pos_rt.y + 65);
    u8 result = 0;

    cursor.Show();
    display.Flip();

    while(le.HandleEvents() && !result)
    {
	le.MousePressLeft(btnAccept) ? btnAccept.PressDraw() : btnAccept.ReleaseDraw();
	le.MousePressLeft(btnDecline) ? btnDecline.PressDraw() : btnDecline.ReleaseDraw();

	if(le.MouseClickLeft(btnAccept)) result = 1;

        // exit
	if(le.KeyPress(KEY_ESCAPE) || le.MouseClickLeft(btnDecline)) break;
    }

    cursor.Hide();
    back.Restore();
    cursor.Show();
    display.Flip();

    return result;
}
예제 #10
0
u8 Battle2::Arena::DialogBattleHero(const HeroBase & hero) const
{
    Display & display = Display::Get();
    Cursor & cursor = Cursor::Get();
    LocalEvent & le = LocalEvent::Get();
    Settings & conf = Settings::Get();

    cursor.Hide();
    cursor.SetThemes(Cursor::POINTER);

    const bool readonly = conf.MyColor() != hero.GetColor();
    const Sprite & dialog = AGG::GetICN((conf.EvilInterface() ? ICN::VGENBKGE : ICN::VGENBKG), 0);

    Rect pos_rt;
    pos_rt.x = (display.w() - dialog.w()) / 2;
    pos_rt.y = (display.h() - dialog.h()) / 2;
    pos_rt.w = dialog.w();
    pos_rt.h = dialog.h();

    Background back(pos_rt);
    back.Save();

    display.Blit(dialog, pos_rt.x, pos_rt.y);
    display.Blit(Portrait::Get(hero, Portrait::BIG), pos_rt.x + 27, pos_rt.y + 42);

    u8 col = (Color::GRAY == hero.GetColor() ? 1 : Color::GetIndex(hero.GetColor()) + 1);
    display.Blit(AGG::GetICN(ICN::VIEWGEN, col), pos_rt.x + 148, pos_rt.y + 36);

    Point tp(pos_rt);

    std::string str;
    Text text;
    text.Set(Font::SMALL);
    str = _("%{name} the %{race}");
    String::Replace(str, "%{name}", hero.GetName());
    String::Replace(str, "%{race}", Race::String(hero.GetRace()));
    text.Set(str);
    tp.x = pos_rt.x + (pos_rt.w - text.w()) / 2;
    tp.y += 10;
    text.Blit(tp);
    str = _("Attack") + std::string(": ");
    String::AddInt(str, hero.GetAttack());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 40;
    text.Blit(tp);
    str = _("Defense") + std::string(": ");
    String::AddInt(str, hero.GetDefense());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 51;
    text.Blit(tp);
    str = _("Spell Power") + std::string(": ");
    String::AddInt(str, hero.GetPower());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 62;
    text.Blit(tp);
    str = _("Knowledge") + std::string(": ");
    String::AddInt(str, hero.GetKnowledge());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 73;
    text.Blit(tp);
    str = _("Morale") + std::string(": ") + Morale::String(hero.GetMorale());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 84;
    text.Blit(tp);
    str = _("Luck") + std::string(": ") + Luck::String(hero.GetLuck());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 95;
    text.Blit(tp);
    str = _("Spell Points") + std::string(": ");
    String::AddInt(str, hero.GetSpellPoints());
    str += "/";
    String::AddInt(str, hero.GetMaxSpellPoints());
    text.Set(str);
    tp.x = pos_rt.x + 205 - text.w() / 2;
    tp.y = pos_rt.y + 117;
    text.Blit(tp);

    Button btnCast(pos_rt.x + 30, pos_rt.y + 148, ICN::VIEWGEN, 9, 10);
    Button btnRetreat(pos_rt.x + 89, pos_rt.y + 148, ICN::VIEWGEN, 11, 12);
    Button btnSurrender(pos_rt.x + 148, pos_rt.y + 148, ICN::VIEWGEN, 13, 14);
    Button btnClose(pos_rt.x + 207, pos_rt.y + 148, ICN::VIEWGEN, 15, 16);

    btnCast.SetDisable(readonly || !hero.HaveSpellBook() || hero.Modes(Heroes::SPELLCASTED));
    btnRetreat.SetDisable(readonly || !CanRetreatOpponent(hero.GetColor()));
    btnSurrender.SetDisable(readonly || !CanSurrenderOpponent(hero.GetColor()));

    btnCast.Draw();
    btnRetreat.Draw();
    btnSurrender.Draw();
    btnClose.Draw();

    if(!conf.QVGA())
    {
	Surface shadow(btnCast.w, btnCast.h);
	shadow.Fill(0, 0, 0);
	shadow.SetAlpha(80);
	if(btnCast.isDisable()) display.Blit(shadow, btnCast);
	if(btnRetreat.isDisable()) display.Blit(shadow, btnRetreat);
	if(btnSurrender.isDisable()) display.Blit(shadow, btnSurrender);
    }

    u8 result = 0;

    cursor.Show();
    display.Flip();

    while(le.HandleEvents() && !result)
    {
	btnCast.isEnable() && le.MousePressLeft(btnCast) ? btnCast.PressDraw() : btnCast.ReleaseDraw();
	btnRetreat.isEnable() && le.MousePressLeft(btnRetreat) ? btnRetreat.PressDraw() : btnRetreat.ReleaseDraw();
	btnSurrender.isEnable() && le.MousePressLeft(btnSurrender) ? btnSurrender.PressDraw() : btnSurrender.ReleaseDraw();
	le.MousePressLeft(btnClose) ? btnClose.PressDraw() : btnClose.ReleaseDraw();

	if(le.KeyPress(KEY_c) || (btnCast.isEnable() && le.MouseClickLeft(btnCast))) result = 1;
	if(le.KeyPress(KEY_r) || (btnRetreat.isEnable() && le.MouseClickLeft(btnRetreat))) result = 2;
	if(le.KeyPress(KEY_s) || (btnSurrender.isEnable() && le.MouseClickLeft(btnSurrender))) result = 3;

	if(le.MousePressRight(btnCast))
	    Dialog::Message(_("Cast Spell"), _("Cast a magical spell. You may only cast one spell per combat round. The round is reset when every creature has had a turn"), Font::BIG);
	else
	if(le.MousePressRight(btnRetreat))
	    Dialog::Message(_("Retreat"), _("Retreat your hero, abandoning your creatures. Your hero will be available for you to recruit again, however, the hero will have only a novice hero's forces."), Font::BIG);
	else
	if(le.MousePressRight(btnSurrender))
	    Dialog::Message(_("Surrender"), _("Surrendering costs gold. However if you pay the ransom, the hero and all of his or her surviving creatures will be available to recruit again."), Font::BIG);
	else
	if(le.MousePressRight(btnClose))
	    Dialog::Message(_("Cancel"), _("Return to the battle."), Font::BIG);

        // exit
	if(le.KeyPress(KEY_ESCAPE) || le.KeyPress(KEY_RETURN) || le.MouseClickLeft(btnClose)) break;
    }

    cursor.Hide();
    back.Restore();
    cursor.Show();
    display.Flip();

    return result;
}
예제 #11
0
void ExperienceLayer::heroChangeExp(Ref * obj)
{
	HeroBase * heroBase = dynamic_cast<HeroBase *>(obj);
	int heroExp = 100 * (1 - ((float)(heroBase->getExpValue() - heroBase->getNowExpValue()) /(float) heroBase->getNeedExpValue()));
	_fillExperience->setPercentage(heroExp);
}
예제 #12
0
void AI::HeroesPreBattle(HeroBase & hero)
{
    Castle* castle = world.GetCastle(hero.GetIndex());
    if(castle && hero.GetType() != Skill::Primary::CAPTAIN)
	hero.GetArmy().JoinTroops(castle->GetArmy());
}