CItemState::CItemState(CCharEntity* PEntity, uint16 targid, uint8 loc, uint8 slotid) : CState(PEntity, targid), m_PEntity(PEntity), m_location(loc), m_slot(slotid), m_PItem(nullptr) { auto PItem = dynamic_cast<CItemUsable*>(m_PEntity->getStorage(loc)->GetItem(slotid)); m_PItem = PItem; if (m_PItem && m_PItem->isType(ITEM_USABLE)) { if (m_PItem->isType(ITEM_ARMOR)) { // check if this item is equipped bool found = false; for (auto equipslot = 0; equipslot < 18; ++equipslot) { if (m_PEntity->getEquip((SLOTTYPE)equipslot) == m_PItem && m_PItem->getCurrentCharges() > 0) { found = true; break; } } if (!found) m_PItem = nullptr; } else if (m_PItem->isSubType(ITEM_LOCKED)) { m_PItem = nullptr; } } if (!m_PItem) { throw CStateInitException(std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, 0, 0, 56)); } auto PTarget = m_PEntity->IsValidTarget(targid, m_PItem->getValidTarget(), m_errorMsg); auto error = luautils::OnItemCheck(PTarget, m_PItem); if (!PTarget || m_errorMsg) { throw CStateInitException(std::move(m_errorMsg)); } if (error || m_PEntity->StatusEffectContainer->HasPreventActionEffect()) { auto param = m_PItem->getFlag() & ITEM_FLAG_SCROLL ? m_PItem->getSubID() : m_PItem->getID(); throw CStateInitException(std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, param, 0, error == -1 ? 56 : error)); } m_PEntity->UContainer->SetType(UCONTAINER_USEITEM); m_PEntity->UContainer->SetItem(0, m_PItem); UpdateTarget(m_targid); m_startPos = m_PEntity->loc.p; m_castTime = std::chrono::milliseconds(m_PItem->getActivationTime()); m_animationTime = std::chrono::milliseconds(PItem->getAnimationTime()); action_t action; action.id = m_PEntity->id; action.actiontype = ACTION_ITEM_START; actionList_t& actionList = action.getNewActionList(); actionList.ActionTargetID = PTarget->id; actionTarget_t& actionTarget = actionList.getNewActionTarget(); actionTarget.reaction = REACTION_NONE; actionTarget.speceffect = SPECEFFECT_NONE; actionTarget.animation = 0; actionTarget.param = m_PItem->getID(); actionTarget.messageID = 28; actionTarget.knockback = 0; m_PEntity->PAI->EventHandler.triggerListener("ITEM_START", PTarget, m_PItem, &action); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(action)); m_PItem->setSubType(ITEM_LOCKED); m_PEntity->pushPacket(new CInventoryAssignPacket(m_PItem, INV_NOSELECT)); m_PEntity->pushPacket(new CInventoryFinishPacket()); }
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<uint16> MobSkills = battleutils::GetMobSkillList(PMob->getMobMod(MOBMOD_SKILL_LIST)); if (MobSkills.size() > 0) { std::shuffle(MobSkills.begin(), MobSkills.end(), dsprand::mt()); for (auto&& skillid : MobSkills) { auto PMobSkill = battleutils::GetMobSkill(skillid); if (PMobSkill && luautils::OnMobSkillCheck(m_PBattleTarget, m_PPet, PMobSkill) == 0) { SetCurrentMobSkill(PMobSkill); break; } } // could not find skill if (!GetCurrentMobSkill()) { 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) { auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(dsprand::GetRandomNumber(m_PPet->PetSkills.size()))); if (PMobSkill) { SetCurrentMobSkill(PMobSkill); preparePetAbility(m_PBattleTarget); return; } } } } else if (m_PPet->getPetType() == PETTYPE_AVATAR) { for (int i = 0; i < m_PPet->PetSkills.size(); i++) { auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i)); if (PMobSkill && PMobSkill->getAnimationTime() == m_MasterCommand) { SetCurrentMobSkill(PMobSkill); 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++) { auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i)); if (PMobSkill && PMobSkill->getValidTargets() == TARGET_ENEMY) { if (hasSkipped == skip) { SetCurrentMobSkill(PMobSkill); 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++) { auto PMobSkill = battleutils::GetMobSkill(m_PPet->PetSkills.at(i)); if (PMobSkill && PMobSkill->getValidTargets() == TARGET_PLAYER_PARTY) { if (PMobSkill->getID() == 638 && m_PPet->PMaster->GetMLevel() < 20) { //can only using hb1 SetCurrentMobSkill(PMobSkill); break; } else if (PMobSkill->getID() == 639 && m_PPet->PMaster->GetMLevel() < 40) { //can only using hb2 SetCurrentMobSkill(PMobSkill); break; } else if (PMobSkill->getID() == 640 && m_PPet->PMaster->GetMLevel() >= 40) { //can only using hb3 SetCurrentMobSkill(PMobSkill); break; } } } preparePetAbility(m_PBattleSubTarget); return; } } } TransitionBack(true); }