Пример #1
0
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();
}
Пример #2
0
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;
}
Пример #3
0
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();
}