CMobSkillState::CMobSkillState(CMobEntity* PEntity, uint16 targid, uint16 wsid) : CState(PEntity, targid), m_PEntity(PEntity) { auto skill = battleutils::GetMobSkill(wsid); if (!skill) { throw CStateInitException(nullptr); } if (m_PEntity->StatusEffectContainer->HasStatusEffect({EFFECT_AMNESIA, EFFECT_IMPAIRMENT})) { throw CStateInitException(nullptr); } auto PTarget = m_PEntity->IsValidTarget(m_targid, skill->getValidTargets(), m_errorMsg); if (!PTarget || m_errorMsg) { throw CStateInitException(std::move(m_errorMsg)); } m_PSkill = std::make_unique<CMobSkill>(*skill); m_castTime = std::chrono::milliseconds(m_PSkill->getActivationTime()); if (m_castTime > 0s) { action_t action; action.id = m_PEntity->id; action.actiontype = ACTION_MOBABILITY_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_PSkill->getID(); actionTarget.messageID = 43; m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE, new CActionPacket(action)); } m_PEntity->PAI->EventHandler.triggerListener("WEAPONSKILL_STATE_ENTER", m_PEntity, m_PSkill->getID()); SpendCost(); }
bool CWeaponSkillState::Update(time_point tick) { if (!IsCompleted()) { SpendCost(); action_t action; m_PEntity->OnWeaponSkillFinished(*this, action); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(action)); auto delay = m_PSkill->getAnimationTime(); m_finishTime = tick + delay; Complete(); } else if (tick > m_finishTime) { m_PEntity->PAI->EventHandler.triggerListener("WEAPONSKILL_STATE_EXIT", m_PEntity, m_PSkill->getID()); return true; } return false; }
void CMagicState::FinishSpell() { DSP_DEBUG_BREAK_IF(m_PSpell == NULL); DSP_DEBUG_BREAK_IF(m_PEntity->PBattleAI->GetCurrentAction() != ACTION_MAGIC_FINISH); CSpell* PSpellCopy = new CSpell(*m_PSpell); luautils::OnSpellPrecast(m_PEntity, PSpellCopy); SpendCost(PSpellCopy); SetRecast(m_PSpell); // remove effects based on spell cast first int16 effectFlags = EFFECTFLAG_INVISIBLE | EFFECTFLAG_MAGIC_BEGIN; if (PSpellCopy->canTargetEnemy()) { effectFlags |= EFFECTFLAG_DETECTABLE; } m_PEntity->StatusEffectContainer->DelStatusEffectsByFlag(effectFlags); m_PTargetFind->reset(); m_PEntity->m_ActionList.clear(); // setup special targeting flags // can this spell target the dead? uint8 flags = FINDFLAGS_NONE; if (PSpellCopy->getValidTarget() & TARGET_PLAYER_DEAD) { flags |= FINDFLAGS_DEAD; } if (PSpellCopy->getFlag() & SPELLFLAG_HIT_ALL) { flags |= FINDFLAGS_HIT_ALL; } uint8 aoeType = battleutils::GetSpellAoEType(m_PEntity, PSpellCopy); if (aoeType == SPELLAOE_RADIAL) { float distance = spell::GetSpellRadius(PSpellCopy, m_PEntity); m_PTargetFind->findWithinArea(m_PTarget, AOERADIUS_TARGET, distance, flags); } else if (aoeType == SPELLAOE_CONAL) { //TODO: actual radius calculation float radius = spell::GetSpellRadius(PSpellCopy, m_PEntity); m_PTargetFind->findWithinCone(m_PTarget, radius, 45, flags); } else { // only add target m_PTargetFind->findSingleTarget(m_PTarget, flags); } uint16 totalTargets = m_PTargetFind->m_targets.size(); PSpellCopy->setTotalTargets(totalTargets); apAction_t action; action.ActionTarget = m_PTarget; action.reaction = REACTION_NONE; action.speceffect = SPECEFFECT_NONE; action.animation = PSpellCopy->getAnimationID(); action.param = 0; action.messageID = 0; uint16 msg = 0; int16 ce = 0; int16 ve = 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; ce = PSpellCopy->getCE(); ve = PSpellCopy->getVE(); // take all shadows if (PSpellCopy->canTargetEnemy() && aoeType > 0) { PTarget->StatusEffectContainer->DelStatusEffect(EFFECT_BLINK); PTarget->StatusEffectContainer->DelStatusEffect(EFFECT_COPY_IMAGE); } // TODO: this is really hacky and should eventually be moved into lua if (PSpellCopy->canHitShadow() && aoeType == SPELLAOE_NONE && battleutils::IsAbsorbByShadow(PTarget)) { // take shadow msg = 31; action.param = 1; ve = 0; ce = 0; } else { action.param = luautils::OnSpellCast(m_PEntity, PTarget, PSpellCopy); // remove effects from damage if (PSpellCopy->canTargetEnemy() && action.param > 0 && m_PSpell->dealsDamage()) { PTarget->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_DAMAGE); } if(msg == 0) { msg = PSpellCopy->getMessage(); } else { msg = PSpellCopy->getAoEMessage(); } } action.messageID = msg; if (PSpellCopy->getID() != 305) //I hate to do this, but there really is no other spell like Odin CharOnTarget(&action, ce, ve); m_PEntity->m_ActionList.push_back(action); } CharAfterFinish(); m_PEntity->StatusEffectContainer->DelStatusEffectsByFlag(EFFECTFLAG_MAGIC_END); DSP_DEBUG_BREAK_IF(m_PEntity->PBattleAI->GetCurrentAction() != ACTION_MAGIC_FINISH); m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(m_PEntity)); delete PSpellCopy; Clear(); }