void CZone::FindPartyForMob(CBaseEntity* PEntity) { DSP_DEBUG_BREAK_IF(PEntity == NULL); DSP_DEBUG_BREAK_IF(PEntity->objtype != TYPE_MOB); CMobEntity* PMob = (CMobEntity*)PEntity; // force all mobs in a burning circle to link bool forceLink = GetType() == ZONETYPE_BATTLEFIELD || GetType() == ZONETYPE_DYNAMIS || PMob->getMobMod(MOBMOD_SUPERLINK); if ((forceLink || PMob->m_Link) && PMob->PParty == NULL) { for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it) { CMobEntity* PCurrentMob = (CMobEntity*)it->second; if(!forceLink && !PCurrentMob->m_Link) continue; int16 sublink = PMob->getMobMod(MOBMOD_SUBLINK); if (forceLink || PCurrentMob->m_Family == PMob->m_Family || sublink && sublink == PCurrentMob->getMobMod(MOBMOD_SUBLINK)) { if(PCurrentMob->PMaster == NULL || PCurrentMob->PMaster->objtype == TYPE_MOB) { PCurrentMob->PParty->AddMember(PMob); return; } } } PMob->PParty = new CParty(PMob); } }
void CZone::SpawnMOBs(CCharEntity* PChar) { for (EntityList_t::const_iterator it = m_mobList.begin() ; it != m_mobList.end() ; ++it) { CMobEntity* PCurrentMob = (CMobEntity*)it->second; SpawnIDList_t::iterator MOB = PChar->SpawnMOBList.lower_bound(PCurrentMob->id); float CurrentDistance = distance(PChar->loc.p, PCurrentMob->loc.p); if (PCurrentMob->status == STATUS_UPDATE && CurrentDistance < 50) { if( MOB == PChar->SpawnMOBList.end() || PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first)) { PChar->SpawnMOBList.insert(MOB, SpawnIDList_t::value_type(PCurrentMob->id, PCurrentMob)); PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_SPAWN)); } if (PChar->isDead() || PChar->nameflags.flags & FLAG_GM || PCurrentMob->PMaster != NULL) continue; // проверка ночного/дневного сна монстров уже учтена в проверке CurrentAction, т.к. во сне монстры не ходят ^^ uint16 expGain = (uint16)charutils::GetRealExp(PChar->GetMLevel(),PCurrentMob->GetMLevel()); CAIMobDummy* PAIMob = (CAIMobDummy*)PCurrentMob->PBattleAI; bool validAggro = expGain > 50 || PChar->animation == ANIMATION_HEALING || PCurrentMob->getMobMod(MOBMOD_ALWAYS_AGGRO); if(validAggro && PAIMob->CanAggroTarget(PChar)) { PCurrentMob->PEnmityContainer->AddBaseEnmity(PChar); } } else { if( MOB != PChar->SpawnMOBList.end() && !(PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first))) { PChar->SpawnMOBList.erase(MOB); PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob,ENTITY_DESPAWN)); } } } }
void CZoneEntities::SpawnMOBs(CCharEntity* PChar) { for (EntityList_t::const_iterator it = m_mobList.begin(); it != m_mobList.end(); ++it) { CMobEntity* PCurrentMob = (CMobEntity*)it->second; SpawnIDList_t::iterator MOB = PChar->SpawnMOBList.lower_bound(PCurrentMob->id); float CurrentDistance = distance(PChar->loc.p, PCurrentMob->loc.p); if (PCurrentMob->status != STATUS_DISAPPEAR && CurrentDistance < 50) { if (MOB == PChar->SpawnMOBList.end() || PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first)) { PChar->SpawnMOBList.insert(MOB, SpawnIDList_t::value_type(PCurrentMob->id, PCurrentMob)); PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_SPAWN, UPDATE_ALL_MOB)); } if (PChar->isDead() || PChar->nameflags.flags & FLAG_GM || PCurrentMob->PMaster != nullptr) continue; // проверка ночного/дневного сна монстров уже учтена в проверке CurrentAction, т.к. во сне монстры не ходят ^^ uint16 expGain = (uint16)charutils::GetRealExp(PChar->GetMLevel(), PCurrentMob->GetMLevel()); CMobController* PController = static_cast<CMobController*>(PCurrentMob->PAI->GetController()); bool validAggro = expGain > 50 || PChar->isSitting() || PCurrentMob->getMobMod(MOBMOD_ALWAYS_AGGRO); if (validAggro && PController->CanAggroTarget(PChar)) { PCurrentMob->PEnmityContainer->AddBaseEnmity(PChar); } } else { if (MOB != PChar->SpawnMOBList.end() && !(PChar->SpawnMOBList.key_comp()(PCurrentMob->id, MOB->first))) { PChar->SpawnMOBList.erase(MOB); PChar->pushPacket(new CEntityUpdatePacket(PCurrentMob, ENTITY_DESPAWN, UPDATE_NONE)); } } } }
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); }