Example #1
0
inline int32 CLuaItem::getMod(lua_State* L)
{
    DSP_DEBUG_BREAK_IF(m_PLuaItem == nullptr);
    DSP_DEBUG_BREAK_IF(lua_isnil(L, 1) || !lua_isnumber(L, 1));

    CItemArmor* PItem = (CItemArmor*)m_PLuaItem;

    uint16 mod = lua_tointeger(L, 1);

    lua_pushinteger(L, PItem->getModifier(mod));
    return 1;
}
int8 CCharEntity::getShieldSize()
{
	CItemArmor* PItem = (CItemArmor*)(getStorage(LOC_INVENTORY)->GetItem(equip[SLOT_SUB]));

    if(PItem == NULL){
        return 0;
    }

    if(!PItem->IsShield()){
        return 0;
    }

    return PItem->getShieldSize();
}
Example #3
0
inline int32 CLuaItem::delMod(lua_State* L)
{
    DSP_DEBUG_BREAK_IF(m_PLuaItem == nullptr);
    DSP_DEBUG_BREAK_IF(lua_isnil(L, 1) || !lua_isnumber(L, 1));
    DSP_DEBUG_BREAK_IF(lua_isnil(L, 2) || !lua_isnumber(L, 2));

    CItemArmor* PItem = (CItemArmor*)m_PLuaItem;

    uint32 mod = lua_tointeger(L, 1);
    int32 power = lua_tointeger(L, 2);

    PItem->addModifier(new CModifier(mod, -power));
    return 0;
}
Example #4
0
inline int32 CLuaItem::getAugment(lua_State* L)
{
    DSP_DEBUG_BREAK_IF(m_PLuaItem == nullptr);
    DSP_DEBUG_BREAK_IF(lua_isnil(L, 1) || !lua_isnumber(L, 1));

    CItemArmor* PItem = (CItemArmor*)m_PLuaItem;

    uint8 slot = lua_tointeger(L, 1);
    uint16 augment = PItem->getAugment(slot);
    uint16 augmentid = unpackBitsBE((uint8*)(&augment), 0, 11);
    uint8 augmentVal = unpackBitsBE((uint8*)(&augment), 11, 5);

    lua_pushinteger(L, augmentid);
    lua_pushinteger(L, augmentVal);

    return 2;
}
Example #5
0
void CAIPetDummy::ActionAbilityStart()
{
    if (m_PPet->StatusEffectContainer->HasPreventActionEffect())
    {
        return;
    }

    if (m_PPet->objtype == TYPE_MOB && m_PPet->PMaster->objtype == TYPE_PC)
    {
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr)
        {
            m_MasterCommand = MASTERCOMMAND_NONE;
            CMobEntity* PMob = (CMobEntity*)m_PPet->PMaster->PPet;
            std::vector<CMobSkill*> MobSkills = battleutils::GetMobSkillsByFamily(PMob->m_Family);

            if (MobSkills.size() > 0)
            {
                int maxSearch = 10;
                // keep looking for an ability until one is valid
                do {
                    SetCurrentMobSkill(MobSkills.at(dsprand::GetRandomNumber(MobSkills.size())));
                } while (luautils::OnMobSkillCheck(m_PBattleTarget, m_PPet, GetCurrentMobSkill()) != 0 && maxSearch--);

                // could not find skill
                if (maxSearch == 0)
                {
                    TransitionBack(true);
                    return;
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }
            return;
        }
    }


    if (m_PPet->getPetType() == PETTYPE_JUG_PET){
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr){ //choose random tp move
            m_MasterCommand = MASTERCOMMAND_NONE;
            if (m_PPet->PetSkills.size() > 0){
                SetCurrentMobSkill(m_PPet->PetSkills.at(dsprand::GetRandomNumber(m_PPet->PetSkills.size())));
                preparePetAbility(m_PBattleTarget);
                return;
            }
        }
    }
    else if (m_PPet->getPetType() == PETTYPE_AVATAR){
        for (int i = 0; i < m_PPet->PetSkills.size(); i++){
            if (m_PPet->PetSkills[i]->getAnimationTime() == m_MasterCommand){
                SetCurrentMobSkill(m_PPet->PetSkills[i]);
                m_MasterCommand = MASTERCOMMAND_NONE;
                preparePetAbility(m_PPet);
                return;
            }
        }
        m_MasterCommand = MASTERCOMMAND_NONE;
    }
    else if (m_PPet->getPetType() == PETTYPE_WYVERN){

        WYVERNTYPE wyverntype = m_PPet->getWyvernType();

        if (m_MasterCommand == MASTERCOMMAND_ELEMENTAL_BREATH && (wyverntype == WYVERNTYPE_MULTIPURPOSE || wyverntype == WYVERNTYPE_OFFENSIVE)){
            m_MasterCommand = MASTERCOMMAND_NONE;

            //offensive or multipurpose wyvern
            if (m_PBattleTarget != nullptr){ //prepare elemental breaths
                int skip = dsprand::GetRandomNumber(6);
                int hasSkipped = 0;

                for (int i = 0; i < m_PPet->PetSkills.size(); i++){
                    if (m_PPet->PetSkills[i]->getValidTargets() == TARGET_ENEMY){
                        if (hasSkipped == skip){
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else{
                            hasSkipped++;
                        }
                    }
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }

        }
        else if (m_MasterCommand == MASTERCOMMAND_HEALING_BREATH && (wyverntype == WYVERNTYPE_DEFENSIVE || wyverntype == WYVERNTYPE_MULTIPURPOSE))
        {

            m_MasterCommand = MASTERCOMMAND_NONE;
            m_PBattleSubTarget = nullptr;
            //TODO: CHECK FOR STATUS EFFECTS FOR REMOVE- BREATH (higher priority than healing breaths)

            //	if(m_PPet->PMaster->PParty==nullptr){//solo with master-kun
            CItemArmor* masterHeadItem = ((CCharEntity*)(m_PPet->PMaster))->getEquip(SLOT_HEAD);

            uint16 masterHead = masterHeadItem ? masterHeadItem->getID() : 0;

			// Determine what the required HP percentage will need to be 
			// at or under in order for healing breath to activate.
			uint8 requiredHPP = 0;
			if (((CCharEntity*)(m_PPet->PMaster))->objtype == TYPE_PC && (masterHead == 12519 || masterHead == 15238)) { //Check for player & AF head, or +1
				if (wyverntype == WYVERNTYPE_DEFENSIVE) { //healer wyvern
					requiredHPP = 50;
				}
				else if (wyverntype == WYVERNTYPE_MULTIPURPOSE) { //hybrid wyvern
					requiredHPP = 33;
				}
			}
			else {
				if (wyverntype == WYVERNTYPE_DEFENSIVE) { //healer wyvern
					requiredHPP = 33;
				}
				else if (wyverntype == WYVERNTYPE_MULTIPURPOSE) { //hybrid wyvern
					requiredHPP = 25;
				}
			}

			// Only attempt to find a target if there is an HP percentage to calculate.
			if (requiredHPP) {
				CBattleEntity* master = m_PPet->PMaster;
				// Check the master first.
				if (master->GetHPP() <= requiredHPP) {
					m_PBattleSubTarget = master;
				}

				// Otherwise if this is a healer wyvern, and the member is in a party 
				// check all of the party members who qualify.
				else if (wyverntype == WYVERNTYPE_DEFENSIVE && master->PParty != nullptr) {
					master->ForParty([this, requiredHPP](CBattleEntity* PTarget){
						if (PTarget->GetHPP() <= requiredHPP) {
							m_PBattleSubTarget = PTarget;
						}
					});
				}
			}

            if (m_PBattleSubTarget != nullptr){ //target to heal
                //get highest breath for wyverns level
                m_PMobSkill = nullptr;
                for (int i = 0; i < m_PPet->PetSkills.size(); i++){
                    if (m_PPet->PetSkills[i]->getValidTargets() == TARGET_PLAYER_PARTY){
                        if (m_PPet->PetSkills[i]->getID() == 638 &&
                            m_PPet->PMaster->GetMLevel() < 20){ //can only using hb1
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else if (m_PPet->PetSkills[i]->getID() == 639 &&
                            m_PPet->PMaster->GetMLevel() < 40){ //can only using hb2
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else if (m_PPet->PetSkills[i]->getID() == 640 &&
                            m_PPet->PMaster->GetMLevel() >= 40){ //can only using hb3
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                    }
                }
                preparePetAbility(m_PBattleSubTarget);
                return;
            }
        }
    }

    TransitionBack(true);
}
Example #6
0
/************************************************************************
*                                                                       *
*  Creates up to many attacks for a particular hand.			        *
*                                                                       *
************************************************************************/
void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction)
{
    uint8 num = 1;
    
    bool isPC = m_attacker->objtype == TYPE_PC;

    // Checking the players weapon hit count
    if (PWeapon->getReqLvl() <= m_attacker->GetMLevel())
    {
        num = PWeapon->getHitCount();
    }
    
    // If the attacker is a mobentity or derived from mobentity, check to see if it has any special mutli-hit capabilties
    if (dynamic_cast<CMobEntity*>(m_attacker))
    {
        auto multiHitMax = static_cast<CMobEntity*>(m_attacker)->getMobMod(MOBMOD_MULTI_HIT);
        
        if (multiHitMax > 0)
            num = 1 + battleutils::getHitCount(multiHitMax);
    }

    AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, num);

    // Checking the players triple, double and quadruple attack
    int16 tripleAttack = m_attacker->getMod(Mod::TRIPLE_ATTACK);
    int16 doubleAttack = m_attacker->getMod(Mod::DOUBLE_ATTACK);
    int16 quadAttack = m_attacker->getMod(Mod::QUAD_ATTACK);

    //check for merit upgrades
    if (isPC)
    {
        CCharEntity* PChar = (CCharEntity*)m_attacker;

        //merit chance only applies if player has the job trait
        if (charutils::hasTrait(PChar, TRAIT_TRIPLE_ATTACK)) tripleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_TRIPLE_ATTACK_RATE, PChar);
        if (charutils::hasTrait(PChar, TRAIT_DOUBLE_ATTACK)) doubleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_DOUBLE_ATTACK_RATE, PChar);
        // TODO: Quadruple attack merits when SE release them.
    }

    quadAttack = dsp_cap(quadAttack, 0, 100);
    doubleAttack = dsp_cap(doubleAttack, 0, 100);
    tripleAttack = dsp_cap(tripleAttack, 0, 100);

    // Checking Mikage Effect - Hits Vary With Num of Utsusemi Shadows for Main Weapon
    if (m_attacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIKAGE) && m_attacker->m_Weapons[SLOT_MAIN]->getID() == PWeapon->getID())
    {
        int16 shadows = m_attacker->getMod(Mod::UTSUSEMI);
        //ShowDebug(CL_CYAN"Create Attacks: Mikage Active, Rolling Attack Chance for %d Shadowss...\n" CL_RESET, shadows);
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, shadows);
    }
    else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::QUAD, direction, 3);

    else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::TRIPLE, direction, 2);

    else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack)
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::DOUBLE, direction, 1);

    // Ammo extra swing - players only
    if (isPC && m_attacker->getMod(Mod::AMMO_SWING) > 0)
    {
        // Check for ammo
        CCharEntity* PChar = (CCharEntity*)m_attacker;
        CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO);
        CItemArmor* PMain = PChar->getEquip(SLOT_MAIN);
        CItemArmor* PSub = PChar->getEquip(SLOT_SUB);
        uint8 slot = PChar->equip[SLOT_AMMO];
        uint8 loc = PChar->equipLoc[SLOT_AMMO];
        uint8 ammoCount = 0;

        // Handedness check, checking mod of the weapon for the purposes of level scaling
        if (battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 2 &&
            dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
        {
            AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, direction, 1);
            ammoCount += 1;
        }
        else
        {
            if (direction == RIGHTATTACK && battleutils::GetScaledItemModifier(PChar, PMain, Mod::AMMO_SWING_TYPE) == 1 &&
                dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
            {
                AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1);
                ammoCount += 1;
            }
            if (direction == LEFTATTACK && PSub != nullptr && battleutils::GetScaledItemModifier(PChar, PSub, Mod::AMMO_SWING_TYPE) == 1 &&
                dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::AMMO_SWING) && PAmmo != nullptr && ammoCount < PAmmo->getQuantity())
            {
                AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, LEFTATTACK, 1);
                ammoCount += 1;
            }
        }

        if (PAmmo != nullptr)
        {
            if (PAmmo->getQuantity() == ammoCount)
            {
                charutils::UnequipItem(PChar, SLOT_AMMO);
                charutils::SaveCharEquip(PChar);
            }
            charutils::UpdateItem(PChar, loc, slot, -ammoCount);
            PChar->pushPacket(new CInventoryFinishPacket());
        }
    }


    // TODO: Possible Lua function for the nitty gritty stuff below.

    // Iga mod: Extra attack chance whilst dual wield is on.
    if (direction == LEFTATTACK && dsprand::GetRandomNumber(100) < m_attacker->getMod(Mod::EXTRA_DUAL_WIELD_ATTACK))
        AddAttackSwing(PHYSICAL_ATTACK_TYPE::NORMAL, RIGHTATTACK, 1);

}
Example #7
0
/************************************************************************
*                                                                       *
*  Creates up to many attacks for a particular hand.			        *
*                                                                       *
************************************************************************/
void CAttackRound::CreateAttacks(CItemWeapon* PWeapon, PHYSICAL_ATTACK_DIRECTION direction)
{
    uint8 num = 1;

    // Checking the players weapon hit count
    if (PWeapon->getReqLvl() <= m_attacker->GetMLevel())
    {
        num = PWeapon->getHitCount();
    }

    AddAttackSwing(ATTACK_NORMAL, direction, num);

    // Checking the players triple, double and quadruple attack
    int16 tripleAttack = m_attacker->getMod(MOD_TRIPLE_ATTACK);
    int16 doubleAttack = m_attacker->getMod(MOD_DOUBLE_ATTACK);
    int16 quadAttack = m_attacker->getMod(MOD_QUAD_ATTACK);

    //check for merit upgrades
    if (m_attacker->objtype == TYPE_PC)
    {
        CCharEntity* PChar = (CCharEntity*)m_attacker;

        //merit chance only applies if player has the job trait
        if (charutils::hasTrait(PChar, TRAIT_TRIPLE_ATTACK)) tripleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_TRIPLE_ATTACK_RATE, PChar);
        if (charutils::hasTrait(PChar, TRAIT_DOUBLE_ATTACK)) doubleAttack += PChar->PMeritPoints->GetMeritValue(MERIT_DOUBLE_ATTACK_RATE, PChar);
        // TODO: Quadruple attack merits when SE release them.
    }

    quadAttack = dsp_cap(quadAttack,0,100);
    doubleAttack = dsp_cap(doubleAttack,0,100);
    tripleAttack = dsp_cap(tripleAttack,0,100);

    // Checking Mikage Effect - Hits Vary With Num of Utsusemi Shadows for Main Weapon
    if (m_attacker->StatusEffectContainer->HasStatusEffect(EFFECT_MIKAGE) && m_attacker->m_Weapons[SLOT_MAIN]->getID() == PWeapon->getID())
    {
        int16 shadows = m_attacker->getMod(MOD_UTSUSEMI);
        //ShowDebug(CL_CYAN"Create Attacks: Mikage Active, Rolling Attack Chance for %d Shadowss...\n" CL_RESET, shadows);
        AddAttackSwing(ATTACK_NORMAL, direction, shadows);
    }
    else if (num == 1 && dsprand::GetRandomNumber(100) < quadAttack)
        AddAttackSwing(QUAD_ATTACK, direction, 3);

    else if (num == 1 && dsprand::GetRandomNumber(100) < tripleAttack)
        AddAttackSwing(TRIPLE_ATTACK, direction, 2);

    else if (num == 1 && dsprand::GetRandomNumber(100) < doubleAttack)
        AddAttackSwing(DOUBLE_ATTACK, direction, 1);

    // Ammo extra swing - players only
    if (m_attacker->objtype == TYPE_PC && m_attacker->getMod(MOD_AMMO_SWING) > 0)
    {
        // Check for ammo
        CCharEntity* PChar = (CCharEntity*)m_attacker;
        CItemArmor* PAmmo = PChar->getEquip(SLOT_AMMO);
        uint8 slot = PChar->equip[SLOT_AMMO];
        uint8 loc = PChar->equipLoc[SLOT_AMMO];
        if (dsprand::GetRandomNumber(100) < m_attacker->getMod(MOD_AMMO_SWING))
        {
            // Add swing, then subtract an ammo item, unequip if there's one left.
            AddAttackSwing(ATTACK_NORMAL, direction, 1);
            if (PAmmo->getQuantity() == 1)
            {
                charutils::UnequipItem(PChar, SLOT_AMMO);
                charutils::SaveCharEquip(PChar);
            }
            charutils::UpdateItem(PChar, loc, slot, -1);
            PChar->pushPacket(new CInventoryFinishPacket());
        }
    }

    // TODO: Possible Lua function for the nitty gritty stuff below.

    // Iga mod: Extra attack chance whilst dual wield is on.
    if (direction == LEFTATTACK && dsprand::GetRandomNumber(100) < m_attacker->getMod(MOD_EXTRA_DUAL_WIELD_ATTACK))
        AddAttackSwing(ATTACK_NORMAL, RIGHTATTACK, 1);

}
Example #8
0
void CAIPetDummy::ActionAbilityStart()
{
    if (m_PPet->StatusEffectContainer->HasPreventActionEffect())
    {
        return;
    }

    if (m_PPet->objtype == TYPE_MOB && m_PPet->PMaster->objtype == TYPE_PC)
    {
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr)
        {
            m_MasterCommand = MASTERCOMMAND_NONE;
            CMobEntity* PMob = (CMobEntity*)m_PPet->PMaster->PPet;
            std::vector<CMobSkill*> MobSkills = battleutils::GetMobSkillsByFamily(PMob->m_Family);

            if (MobSkills.size() > 0)
            {
                int maxSearch = 10;
                // keep looking for an ability until one is valid
                do {
                    SetCurrentMobSkill(MobSkills.at(WELL512::irand() % MobSkills.size()));
                } while (luautils::OnMobSkillCheck(m_PBattleTarget, m_PPet, GetCurrentMobSkill()) != 0 && maxSearch--);

                // could not find skill
                if (maxSearch == 0)
                {
                    TransitionBack(true);
                    return;
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }
            return;
        }
    }


    if (m_PPet->getPetType() == PETTYPE_JUG_PET){
        if (m_MasterCommand == MASTERCOMMAND_SIC && m_PPet->health.tp >= 1000 && m_PBattleTarget != nullptr){ //choose random tp move
            m_MasterCommand = MASTERCOMMAND_NONE;
            if (m_PPet->PetSkills.size() > 0){
                SetCurrentMobSkill(m_PPet->PetSkills.at(WELL512::irand() % m_PPet->PetSkills.size()));
                preparePetAbility(m_PBattleTarget);
                return;
            }
        }
    }
    else if (m_PPet->getPetType() == PETTYPE_AVATAR){
        for (int i = 0; i < m_PPet->PetSkills.size(); i++){
            if (m_PPet->PetSkills[i]->getAnimationTime() == m_MasterCommand){
                SetCurrentMobSkill(m_PPet->PetSkills[i]);
                m_MasterCommand = MASTERCOMMAND_NONE;
                preparePetAbility(m_PPet);
                return;
            }
        }
        m_MasterCommand = MASTERCOMMAND_NONE;
    }
    else if (m_PPet->getPetType() == PETTYPE_WYVERN){

        WYVERNTYPE wyverntype = m_PPet->getWyvernType();

        if (m_MasterCommand == MASTERCOMMAND_ELEMENTAL_BREATH && (wyverntype == WYVERNTYPE_MULTIPURPOSE || wyverntype == WYVERNTYPE_OFFENSIVE)){
            m_MasterCommand = MASTERCOMMAND_NONE;

            //offensive or multipurpose wyvern
            if (m_PBattleTarget != nullptr){ //prepare elemental breaths
                int skip = WELL512::irand() % 6;
                int hasSkipped = 0;

                for (int i = 0; i < m_PPet->PetSkills.size(); i++){
                    if (m_PPet->PetSkills[i]->getValidTargets() == TARGET_ENEMY){
                        if (hasSkipped == skip){
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else{
                            hasSkipped++;
                        }
                    }
                }

                preparePetAbility(m_PBattleTarget);
                return;
            }

        }
        else if (m_MasterCommand == MASTERCOMMAND_HEALING_BREATH && (wyverntype == WYVERNTYPE_DEFENSIVE || wyverntype == WYVERNTYPE_MULTIPURPOSE))
        {

            m_MasterCommand = MASTERCOMMAND_NONE;
            m_PBattleSubTarget = nullptr;
            //TODO: CHECK FOR STATUS EFFECTS FOR REMOVE- BREATH (higher priority than healing breaths)

            //	if(m_PPet->PMaster->PParty==nullptr){//solo with master-kun
            CItemArmor* masterHeadItem = ((CCharEntity*)(m_PPet->PMaster))->getEquip(SLOT_HEAD);

            uint16 masterHead = masterHeadItem ? masterHeadItem->getID() : 0;

            if (((CCharEntity*)(m_PPet->PMaster))->objtype == TYPE_PC && (masterHead == 12519 || masterHead == 15238)) { //Check for player & AF head, or +1
                if (m_PPet->PMaster->GetHPP() <= 50 && wyverntype == WYVERNTYPE_DEFENSIVE){//healer wyvern
                    m_PBattleSubTarget = m_PPet->PMaster;
                }
                else if (m_PPet->PMaster->GetHPP() <= 33 && wyverntype == WYVERNTYPE_MULTIPURPOSE){//hybrid wyvern
                    m_PBattleSubTarget = m_PPet->PMaster;
                }
            }
            else {
                if (m_PPet->PMaster->GetHPP() <= 33 && wyverntype == WYVERNTYPE_DEFENSIVE)
                {//healer wyvern
                    m_PBattleSubTarget = m_PPet->PMaster;
                }
                else if (m_PPet->PMaster->GetHPP() <= 25 && wyverntype == WYVERNTYPE_MULTIPURPOSE)
                {//hybrid wyvern
                    m_PBattleSubTarget = m_PPet->PMaster;
                }
            }
            //	}
            //	else{ //group play
            //		//for( int i=0; i<
            //	}
            if (m_PBattleSubTarget != nullptr){ //target to heal
                //get highest breath for wyverns level
                m_PMobSkill = nullptr;
                for (int i = 0; i < m_PPet->PetSkills.size(); i++){
                    if (m_PPet->PetSkills[i]->getValidTargets() == TARGET_PLAYER_PARTY){
                        if (m_PPet->PetSkills[i]->getID() == 638 &&
                            m_PPet->PMaster->GetMLevel() < 20){ //can only using hb1
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else if (m_PPet->PetSkills[i]->getID() == 639 &&
                            m_PPet->PMaster->GetMLevel() < 40){ //can only using hb2
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                        else if (m_PPet->PetSkills[i]->getID() == 640 &&
                            m_PPet->PMaster->GetMLevel() >= 40){ //can only using hb3
                            SetCurrentMobSkill(m_PPet->PetSkills[i]);
                            break;
                        }
                    }
                }
                preparePetAbility(m_PBattleSubTarget);
                return;
            }
        }
    }

    TransitionBack(true);
}