Beispiel #1
0
void CMobController::CastSpell(uint16 spellid)
{
    CSpell* PSpell = spell::GetSpell(spellid);
    if (PSpell == nullptr)
    {
        ShowWarning(CL_YELLOW"ai_mob_dummy::CastSpell: SpellId <%i> is not found\n" CL_RESET, spellid);
    }
    else
    {
        CBattleEntity* PCastTarget = nullptr;
        // check valid targets
        if (PSpell->getValidTarget() & TARGET_SELF)
        {
            PCastTarget = PMob;

            // only buff other targets if i'm roaming
            if ((PSpell->getValidTarget() & TARGET_PLAYER_PARTY))
            {
                // chance to target my master
                if (PMob->PMaster != nullptr && dsprand::GetRandomNumber(2) == 0)
                {
                    // target my master
                    PCastTarget = PMob->PMaster;
                }
                else if (dsprand::GetRandomNumber(2) == 0)
                {
                    // chance to target party
                    PMob->PAI->TargetFind->reset();
                    PMob->PAI->TargetFind->findWithinArea(PMob, AOERADIUS_ATTACKER, PSpell->getRange());

                    if (!PMob->PAI->TargetFind->m_targets.empty())
                    {
                        // randomly select a target
                        PCastTarget = PMob->PAI->TargetFind->m_targets[dsprand::GetRandomNumber(PMob->PAI->TargetFind->m_targets.size())];

                        // only target if are on same action
                        if (PMob->PAI->IsEngaged() == PCastTarget->PAI->IsEngaged())
                        {
                            PCastTarget = PMob;
                        }
                    }
                }
            }
        }
        else
        {
            PCastTarget = PTarget;
        }
        Cast(PCastTarget->targid, spellid);
    }
}
Beispiel #2
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();
}