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); }
void CAIPetDummy::ActionAbilityFinish(){ DSP_DEBUG_BREAK_IF(m_PMobSkill == nullptr); DSP_DEBUG_BREAK_IF(m_PBattleSubTarget == nullptr); // reset AoE finder m_PTargetFind->reset(); m_PPet->m_ActionList.clear(); float distance = m_PMobSkill->getDistance(); if (m_PTargetFind->isWithinRange(&m_PBattleSubTarget->loc.p, distance)) { if (m_PMobSkill->isAoE()) { float radius = m_PMobSkill->getDistance(); m_PTargetFind->findWithinArea(m_PBattleSubTarget, (AOERADIUS)m_PMobSkill->getAoe(), distance); } else if (m_PMobSkill->isConal()) { float angle = 45.0f; m_PTargetFind->findWithinCone(m_PBattleSubTarget, distance, angle); } else { m_PTargetFind->findSingleTarget(m_PBattleSubTarget); } } uint16 totalTargets = m_PTargetFind->m_targets.size(); //call the script for each monster hit m_PMobSkill->setTotalTargets(totalTargets); m_PMobSkill->setTP(m_skillTP); apAction_t Action; Action.ActionTarget = nullptr; Action.reaction = REACTION_HIT; Action.speceffect = SPECEFFECT_HIT; Action.animation = m_PMobSkill->getAnimationID(); Action.knockback = 0; uint16 msg = 0; for (std::vector<CBattleEntity*>::iterator it = m_PTargetFind->m_targets.begin(); it != m_PTargetFind->m_targets.end(); ++it) { CBattleEntity* PTarget = *it; Action.ActionTarget = PTarget; if (m_PPet->isBstPet()){ Action.param = luautils::OnMobWeaponSkill(PTarget, m_PPet, GetCurrentMobSkill()); } else { Action.param = luautils::OnPetAbility(PTarget, m_PPet, GetCurrentMobSkill(), m_PPet->PMaster); } if (msg == 0){ msg = m_PMobSkill->getMsg(); } else { msg = m_PMobSkill->getAoEMsg(); } Action.messageID = msg; battleutils::ClaimMob(m_PBattleSubTarget, m_PPet); if (PTarget->objtype == TYPE_MOB && !m_PTargetFind->checkIsPlayer(PTarget) && m_PMobSkill->isDamageMsg()) { ((CMobEntity*)PTarget)->PEnmityContainer->UpdateEnmityFromDamage(m_PPet, Action.param); } if (m_PBattleSubTarget->objtype == TYPE_MOB) { uint16 PWeaponskill = m_PMobSkill->getID(); luautils::OnWeaponskillHit(m_PBattleSubTarget, m_PPet, PWeaponskill); } // If we dealt damage.. we should wake up our target.. if (m_PMobSkill->isDamageMsg() && Action.param > 0 && PTarget->StatusEffectContainer != nullptr) PTarget->StatusEffectContainer->WakeUp(); m_PPet->m_ActionList.push_back(Action); } m_PPet->loc.zone->PushPacket(m_PPet, CHAR_INRANGE, new CActionPacket(m_PPet)); if (Action.ActionTarget != nullptr && m_PPet->getPetType() == PETTYPE_AVATAR){ //todo: remove pet type avatar maybe Action.ActionTarget->loc.zone->PushPacket(Action.ActionTarget, CHAR_INRANGE, new CEntityUpdatePacket(Action.ActionTarget, ENTITY_UPDATE, UPDATE_COMBAT)); } m_PBattleSubTarget = nullptr; m_ActionType = ACTION_ATTACK; }
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); }