Exemplo n.º 1
0
/**
** Spell cast!
**
** @param caster    Unit that casts the spell
** @param spell     Spell-type pointer
** @param target    Target unit that spell is addressed to
** @param goalPos   coord of target spot when/if target does not exist
**
** @return          !=0 if spell should/can continue or 0 to stop
*/
int SpellCast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &goalPos)
{
	Vec2i pos = goalPos;

	caster.Variable[INVISIBLE_INDEX].Value = 0;// unit is invisible until attacks // FIXME: Must be configurable
	if (target) {
		pos = target->tilePos;
	}
	//
	// For TargetSelf, you target.... YOURSELF
	//
	if (spell.Target == TargetSelf) {
		pos = caster.tilePos;
		target = &caster;
	}
	DebugPrint("Spell cast: (%s), %s -> %s (%d,%d)\n" _C_ spell.Ident.c_str() _C_
			   caster.Type->Name.c_str() _C_ target ? target->Type->Name.c_str() : "none" _C_ pos.x _C_ pos.y);
	if (CanCastSpell(caster, spell, target, pos)) {
		int cont = 1; // Should we recast the spell.
		bool mustSubtractMana = true; // false if action which have their own calculation is present.
		//
		//  Ugly hack, CastAdjustVitals makes it's own mana calculation.
		//
		PlayGameSound(spell.SoundWhenCast.Sound, MaxSampleVolume);
		for (std::vector<SpellActionType *>::const_iterator act = spell.Action.begin();
			 act != spell.Action.end(); ++act) {
			if ((*act)->ModifyManaCaster) {
				mustSubtractMana = false;
			}
			cont = cont & (*act)->Cast(caster, spell, target, pos);
		}
		if (mustSubtractMana) {
			caster.Variable[MANA_INDEX].Value -= spell.ManaCost;
		}
		caster.Player->SubCosts(spell.Costs);
		caster.SpellCoolDownTimers[spell.Slot] = spell.CoolDown;
		//
		// Spells like blizzard are casted again.
		// This is sort of confusing, we do the test again, to
		// check if it will be possible to cast again. Otherwise,
		// when you're out of mana the caster will try again ( do the
		// anim but fail in this proc.
		//
		if (spell.RepeatCast && cont) {
			return CanCastSpell(caster, spell, target, pos);
		}
	}
	//
	// Can't cast, STOP.
	//
	return 0;
}
Exemplo n.º 2
0
STATESTATUS CMagicState::CastSpell(CSpell* PSpell, CBattleEntity* PTarget, uint8 flags)
{
	if(!CanCastSpell(PSpell, PTarget, flags))
	{
		return STATESTATUS_ERROR;
	}

	Clear();

	m_PSpell = PSpell;
	m_PTarget = PTarget;
	m_flags = flags;
    m_startPosition = m_PEntity->loc.p;

	m_castTime = CalculateCastTime(PSpell);

	apAction_t action;

	action.ActionTarget = m_PTarget;
	action.reaction   = REACTION_NONE;
	action.speceffect = SPECEFFECT_NONE;
	action.animation  = 0;
	action.param	  = m_PSpell->getID();
	action.messageID  = 327; // starts casting

    m_PEntity->m_ActionList.clear();
	m_PEntity->m_ActionList.push_back(action);
	m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(m_PEntity));

	return STATESTATUS_START;
}
Exemplo n.º 3
0
/**
** Cast Area Adjust Vital on all valid units in range.
**
**  @param caster       Unit that casts the spell
**  @param spell        Spell-type pointer
**  @param target       Target unit that spell is addressed to
**  @param goalPos      TilePos of target spot when/if target does not exist
**
**  @return             =!0 if spell should be repeated, 0 if not
*/
/* virtual */ int Spell_AreaAdjustVital::Cast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &goalPos)
{
	const Vec2i range(this->Range, this->Range);
	const Vec2i typeSize(caster.Type->Width, caster.Type->Height);
	std::vector<CUnit *> units;

	// Get all the units around the unit
	Select(goalPos - range, goalPos + typeSize + range, units);
	int hp = this->HP;
	int mana = this->Mana;
	int shield = this->Shield;
	for (size_t j = 0; j != units.size(); ++j) {
		target = units[j];
		// if (!PassCondition(caster, spell, target, goalPos) {
		if (!CanCastSpell(caster, spell, target, goalPos)) {
			continue;
		}
		if (hp < 0) {
			HitUnit(&caster, *target, -hp);
		} else {
			target->Variable[HP_INDEX].Value += hp;
			target->Variable[HP_INDEX].Value = std::min(target->Variable[HP_INDEX].Max, target->Variable[HP_INDEX].Value);
		}
		target->Variable[MANA_INDEX].Value += mana;
		clamp(&target->Variable[MANA_INDEX].Value, 0, target->Variable[MANA_INDEX].Max);
		target->Variable[SHIELD_INDEX].Value += shield;
		clamp(&target->Variable[SHIELD_INDEX].Value, 0, target->Variable[SHIELD_INDEX].Max);
	}
	if (UseMana) {
		caster.Variable[MANA_INDEX].Value -= spell.ManaCost;
	}
	return 0;
}
Exemplo n.º 4
0
CMagicState::CMagicState(CBattleEntity* PEntity, uint16 targid, uint16 spellid, uint8 flags) :
    CState(PEntity, targid),
    m_PEntity(PEntity),
    m_PSpell(nullptr)
{
    CSpell* PSpell = spell::GetSpell(spellid);

    m_PSpell = PSpell->clone();

    if (!m_PSpell)
    {
        throw CStateInitException(std::make_unique<CMessageBasicPacket>(m_PEntity, m_PEntity, m_PSpell->getID(), 0, MSGBASIC_CANNOT_CAST_SPELL));
    }
    auto PTarget = m_PEntity->IsValidTarget(m_targid, m_PSpell->getValidTarget(), m_errorMsg);

    if (!PTarget || m_errorMsg)
    {
        throw CStateInitException(std::move(m_errorMsg));
    }

    if (!CanCastSpell(PTarget))
    {
        throw CStateInitException(std::move(m_errorMsg));
    }

    auto errorMsg = luautils::OnMagicCastingCheck(m_PEntity, PTarget, GetSpell());
    if (errorMsg)
    {
        throw CStateInitException(std::make_unique<CMessageBasicPacket>(m_PEntity, PTarget, m_PSpell->getID(), 0, errorMsg == 1 ? MSGBASIC_CANNOT_CAST_SPELL : errorMsg));
    }

    m_flags = flags;
    m_castTime = std::chrono::milliseconds(battleutils::CalculateSpellCastTime(m_PEntity, GetSpell()));
    m_startPos = m_PEntity->loc.p;

    action_t action;
    action.id = m_PEntity->id;
    action.spellgroup = m_PSpell->getSpellGroup();
    action.actiontype = ACTION_MAGIC_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_PSpell->getID();
    actionTarget.messageID = 327; // starts casting
    m_PEntity->PAI->EventHandler.triggerListener("MAGIC_START", m_PEntity, m_PSpell.get(), &action); //TODO: weaponskill lua object

    m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(action));
}
Exemplo n.º 5
0
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, ObjectGuid uiOriginalCasterGUID)
{
    // Target might be passed as NULL at script so better check it in core too for better safety.
    if(!pTarget)
        return CAST_FAIL_OTHER;

    Unit* pCaster = m_creature;

    if (uiCastFlags & CAST_FORCE_TARGET_SELF)
        pCaster = pTarget;

    if (!pTarget)
        return CAST_FAIL_OTHER;

    // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
    if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)))
    {
        if (const SpellEntry* pSpell = sSpellStore.LookupEntry(uiSpell))
        {
            // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
            if (uiCastFlags & CAST_AURA_NOT_PRESENT)
            {
                if (pTarget->HasAura(uiSpell))
                    return CAST_FAIL_TARGET_AURA;
            }

            // Check if cannot cast spell
            if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
            {
                CanCastResult castResult = CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED);

                if (castResult != CAST_OK)
                    return castResult;
            }

            // Interrupt any previous spell
            if (uiCastFlags & CAST_INTERRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
                pCaster->InterruptNonMeleeSpells(false);

            pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID);
            return CAST_OK;
        }
        else
        {
            sLog.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature->GetEntry(), uiSpell);
            return CAST_FAIL_OTHER;
        }
    }
    else
        return CAST_FAIL_IS_CASTING;
}
Exemplo n.º 6
0
bool HeroBase::CanTranscribeScroll(const Artifact & art) const
{
    Spell spell = art.GetSpell();

    if(spell.isValid() && CanCastSpell(spell))
    {
	int learning = GetLevelSkill(Skill::Secondary::LEARNING);

	return ((3 <  spell.Level() && Skill::Level::EXPERT == learning) ||
	    (3 == spell.Level() && Skill::Level::ADVANCED <= learning) ||
	    (3 > spell.Level() && Skill::Level::BASIC <= learning));
    }

    return false;
}
Exemplo n.º 7
0
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, ObjectGuid uiOriginalCasterGUID)
{
    Unit* pCaster = m_creature;

    if (uiCastFlags & CAST_FORCE_TARGET_SELF)
        pCaster = pTarget;

    // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
    if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)))
    {
        if (const SpellEntry* pSpell = sSpellStore.LookupEntry(uiSpell))
        {
            // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
            if (uiCastFlags & CAST_AURA_NOT_PRESENT)
            {
                if (pTarget->HasAura(uiSpell))
                    return CAST_FAIL_TARGET_AURA;
            }

            // Check if cannot cast spell
            if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
            {
                CanCastResult castResult = CanCastSpell(pTarget, pSpell, !!(uiCastFlags & CAST_TRIGGERED));

                if (castResult != CAST_OK)
                    return castResult;
            }

            // Interrupt any previous spell
            if (uiCastFlags & CAST_INTERRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
                pCaster->InterruptNonMeleeSpells(false);

            // Creature should always stop before it will cast a new spell (logic applies to combat movement only)
            if (pCaster->isInCombat())
                pCaster->StopMoving();

            pCaster->CastSpell(pTarget, pSpell, !!(uiCastFlags & CAST_TRIGGERED), nullptr, nullptr, uiOriginalCasterGUID);
            return CAST_OK;
        }
        else
        {
            sLog.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature->GetEntry(), uiSpell);
            return CAST_FAIL_OTHER;
        }
    }
    else
        return CAST_FAIL_IS_CASTING;
}
Exemplo n.º 8
0
bool Heroes::ActionSpellCast(const Spell & spell)
{
    std::string error;

    if(! CanMove())
    {
        Dialog::Message("", _("Your hero is too tired to cast this spell today. Try again tomorrow."), Font::BIG, Dialog::OK);
	return false;
    }
    else
    if(spell == Spell::NONE || spell.isCombat() || ! CanCastSpell(spell, &error))
    {
	if(error.size()) Dialog::Message("Error", error, Font::BIG, Dialog::OK);
	return false;
    }

    bool apply = false;

    switch(spell())
    {
	case Spell::VIEWMINES:		apply = ActionSpellViewMines(*this); break;
	case Spell::VIEWRESOURCES:	apply = ActionSpellViewResources(*this); break;
	case Spell::VIEWARTIFACTS:	apply = ActionSpellViewArtifacts(*this); break;
	case Spell::VIEWTOWNS:		apply = ActionSpellViewTowns(*this); break;
	case Spell::VIEWHEROES:		apply = ActionSpellViewHeroes(*this); break;
	case Spell::VIEWALL:		apply = ActionSpellViewAll(*this); break;
	case Spell::IDENTIFYHERO:	apply = ActionSpellIdentifyHero(*this); break;
	case Spell::SUMMONBOAT:		apply = ActionSpellSummonBoat(*this); break;
	case Spell::DIMENSIONDOOR:	apply = ActionSpellDimensionDoor(*this); break;
	case Spell::TOWNGATE:		apply = isShipMaster() ? false : ActionSpellTownGate(*this); break;
	case Spell::TOWNPORTAL:		apply = isShipMaster() ? false : ActionSpellTownPortal(*this); break;
	case Spell::VISIONS:		apply = ActionSpellVisions(*this); break;
	case Spell::HAUNT:		apply = ActionSpellSetGuardian(*this, spell, Monster::GHOST); break;
	case Spell::SETEGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::EARTH_ELEMENT); break;
	case Spell::SETAGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::AIR_ELEMENT); break;
	case Spell::SETFGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::FIRE_ELEMENT); break;
	case Spell::SETWGUARDIAN:	apply = ActionSpellSetGuardian(*this, spell, Monster::WATER_ELEMENT); break;
	default: break;
    }

    if(apply)
    {
	DEBUG(DBG_GAME, DBG_INFO, GetName() << " cast spell: " << spell.GetName());
	SpellCasted(spell);
	return true;
    }
    return false;
}
Exemplo n.º 9
0
/**
** Cast Area Adjust Vital on all valid units in range.
**
**  @param caster       Unit that casts the spell
**  @param spell        Spell-type pointer
**  @param target       Target unit that spell is addressed to
**  @param goalPos      TilePos of target spot when/if target does not exist
**
**  @return             =!0 if spell should be repeated, 0 if not
*/
/* virtual */ int Spell_AreaAdjustVital::Cast(CUnit &caster, const CSpell &spell, CUnit *target, const Vec2i &goalPos, int z, int modifier)
{
	const Vec2i range(this->Range, this->Range);
	const Vec2i typeSize(caster.Type->TileSize);
	std::vector<CUnit *> units;

	// Get all the units around the unit
	//Wyrmgus start
//	Select(goalPos - range, goalPos + typeSize + range, units);
	Select(goalPos - range, goalPos + typeSize + range, units, z);
	//Wyrmgus end
	int hp = this->HP * modifier / 100;
	int mana = this->Mana * modifier / 100;
	int shield = this->Shield * modifier / 100;
	for (size_t j = 0; j != units.size(); ++j) {
		target = units[j];
		// if (!PassCondition(caster, spell, target, goalPos) {
		//Wyrmgus start
//		if (!CanCastSpell(caster, spell, target, goalPos)) {
		if (!CanCastSpell(caster, spell, target, goalPos, Map.MapLayers[z])) {
		//Wyrmgus end
			continue;
		}
		if (hp < 0) {
			HitUnit(&caster, *target, -hp);
		} else {
			target->Variable[HP_INDEX].Value += hp;
			//Wyrmgus start
//			target->Variable[HP_INDEX].Value = std::min(target->Variable[HP_INDEX].Max, target->Variable[HP_INDEX].Value);
			target->Variable[HP_INDEX].Value = std::min(target->GetModifiedVariable(HP_INDEX, VariableMax), target->Variable[HP_INDEX].Value);
			//Wyrmgus end
		}
		target->Variable[MANA_INDEX].Value += mana;
		//Wyrmgus start
//		clamp(&target->Variable[MANA_INDEX].Value, 0, target->Variable[MANA_INDEX].Max);
		clamp(&target->Variable[MANA_INDEX].Value, 0, target->GetModifiedVariable(MANA_INDEX, VariableMax));
		//Wyrmgus end
		target->Variable[SHIELD_INDEX].Value += shield;
		clamp(&target->Variable[SHIELD_INDEX].Value, 0, target->Variable[SHIELD_INDEX].Max);
	}
	if (UseMana) {
		caster.Variable[MANA_INDEX].Value -= spell.ManaCost;
	}
	return 0;
}
Exemplo n.º 10
0
bool CMagicState::Update(time_point tick)
{
    if (tick > GetEntryTime() + m_castTime && !IsCompleted())
    {
        m_interrupted = false;
        auto PTarget = m_PEntity->IsValidTarget(m_targid, m_PSpell->getValidTarget(), m_errorMsg);
        MSGBASIC_ID msg = MSGBASIC_IS_INTERRUPTED;

        action_t action;

        if (HasMoved() || !CanCastSpell(PTarget))
        {
            m_interrupted = true;
        }
        else if (battleutils::IsParalyzed(m_PEntity))
        {
            msg = MSGBASIC_IS_PARALYZED;
            m_interrupted = true;
        }
        else if (battleutils::IsIntimidated(m_PEntity, static_cast<CBattleEntity*>(PTarget)))
        {
            msg = MSGBASIC_IS_INTIMIDATED;
            m_interrupted = true;
        }

        if (m_interrupted)
        {
            m_PEntity->OnCastInterrupted(*this, action, msg);
        }
        else
        {
            m_PEntity->OnCastFinished(*this,action);
        }
        m_PEntity->PAI->EventHandler.triggerListener("MAGIC_USE", m_PEntity, PTarget, m_PSpell.get(), &action);
        m_PEntity->loc.zone->PushPacket(m_PEntity, CHAR_INRANGE_SELF, new CActionPacket(action));
        Complete();
    }
    else if (IsCompleted() && tick > GetEntryTime() + m_castTime + std::chrono::milliseconds(m_PSpell->getAnimationTime()))
    {
        m_PEntity->PAI->EventHandler.triggerListener("MAGIC_STATE_EXIT", m_PEntity, m_PSpell.get());
        return true;
    }
    return false;
}
Exemplo n.º 11
0
CanCastResult UnitAI::DoCastSpellIfCan(Unit* target, uint32 spellId, uint32 castFlags, ObjectGuid originalCasterGUID) const
{
    Unit* caster = m_unit;

    if (target)
    {
        if (castFlags & CAST_SWITCH_CASTER_TARGET)
            std::swap(caster, target);

        if (castFlags & CAST_FORCE_TARGET_SELF)
            caster = target;
    }
    else if (castFlags & (CAST_FORCE_TARGET_SELF | CAST_SWITCH_CASTER_TARGET))
        return CAST_FAIL_OTHER;

    // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
    if (!caster->IsNonMeleeSpellCasted(false) || (castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)))
    {
        if (const SpellEntry* spellInfo = sSpellTemplate.LookupEntry<SpellEntry>(spellId))
        {
            // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
            if (castFlags & CAST_AURA_NOT_PRESENT)
            {
                if (!target)
                {
                    if (caster->HasAura(spellId))
                        return CAST_FAIL_TARGET_AURA;
                }
                else if (target->HasAura(spellId))
                    return CAST_FAIL_TARGET_AURA;
            }

            // Check if cannot cast spell
            if (!(castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
            {
                CanCastResult castResult = CanCastSpell(target, spellInfo, (castFlags & CAST_TRIGGERED) != 0);

                if (castResult != CAST_OK)
                    return castResult;
            }

            // Interrupt any previous spell
            if (castFlags & CAST_INTERRUPT_PREVIOUS && caster->IsNonMeleeSpellCasted(false))
                caster->InterruptNonMeleeSpells(false);

            // Creature should always stop before it will cast a non-instant spell
            if (GetSpellCastTime(spellInfo) || (IsChanneledSpell(spellInfo) && spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_MOVEMENT))
                caster->StopMoving();

            // Creature should interrupt any current melee spell
            caster->InterruptSpell(CURRENT_MELEE_SPELL);

            // Creature should stop wielding weapon while casting
            // caster->SetSheath(SHEATH_STATE_UNARMED);

            uint32 flags = (castFlags & CAST_TRIGGERED ? TRIGGERED_OLD_TRIGGERED : TRIGGERED_NONE) | (castFlags & CAST_IGNORE_UNSELECTABLE_TARGET ? TRIGGERED_IGNORE_UNSELECTABLE_FLAG : TRIGGERED_NONE);

            if (flags == TRIGGERED_NONE)
                flags |= TRIGGERED_NORMAL_COMBAT_CAST;

            caster->CastSpell(target, spellInfo, flags, nullptr, nullptr, originalCasterGUID);
            return CAST_OK;
        }
        sLog.outErrorDb("DoCastSpellIfCan by %s attempt to cast spell %u but spell does not exist.", m_unit->GetObjectGuid().GetString().c_str(), spellId);
        return CAST_FAIL_OTHER;
    }
    return CAST_FAIL_IS_CASTING;
}
Exemplo n.º 12
0
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, ObjectGuid uiOriginalCasterGUID) const
{
    Unit* pCaster = m_unit;

    if (!pTarget)
        return CAST_FAIL_OTHER;

    if (uiCastFlags & CAST_SWITCH_CASTER_TARGET)
        std::swap(pCaster, pTarget);

    if (uiCastFlags & CAST_FORCE_TARGET_SELF)
        pCaster = pTarget;

    // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
    if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)))
    {
        if (const SpellEntry* pSpell = sSpellTemplate.LookupEntry<SpellEntry>(uiSpell))
        {
            // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
            if (uiCastFlags & CAST_AURA_NOT_PRESENT)
            {
                if (pTarget->HasAura(uiSpell))
                    return CAST_FAIL_TARGET_AURA;
            }

            // Check if cannot cast spell
            if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
            {
                CanCastResult castResult = CanCastSpell(pTarget, pSpell, !!(uiCastFlags & CAST_TRIGGERED));

                if (castResult != CAST_OK)
                    return castResult;
            }

            // Interrupt any previous spell
            if (uiCastFlags & CAST_INTERRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
                pCaster->InterruptNonMeleeSpells(false);

            // Creature should always stop before it will cast a non-instant spell
            if (GetSpellCastTime(pSpell))
                pCaster->StopMoving();

            // Creature should interrupt any current melee spell
            pCaster->InterruptSpell(CURRENT_MELEE_SPELL);

            // Creature should stop wielding weapon while casting
            pCaster->SetSheath(SHEATH_STATE_UNARMED);

            uint32 flags = (uiCastFlags & CAST_TRIGGERED ? TRIGGERED_OLD_TRIGGERED : TRIGGERED_NONE) | (uiCastFlags & CAST_IGNORE_UNSELECTABLE_TARGET ? TRIGGERED_IGNORE_UNSELECTABLE_FLAG : TRIGGERED_NONE);

            pCaster->CastSpell(pTarget, pSpell, flags, nullptr, nullptr, uiOriginalCasterGUID);
            return CAST_OK;
        }
        else
        {
            sLog.outErrorDb("DoCastSpellIfCan by %s attempt to cast spell %u but spell does not exist.", m_unit->GetObjectGuid().GetString().c_str(), uiSpell);
            return CAST_FAIL_OTHER;
        }
    }
    else
        return CAST_FAIL_IS_CASTING;
}
Exemplo n.º 13
0
/* virtual */ void COrder_SpellCast::Execute(CUnit &unit)
{
	COrder_SpellCast &order = *this;

	if (unit.Wait) {
		unit.Wait--;
		return ;
	}
	const SpellType &spell = order.GetSpell();
	switch (this->State) {
		case 0:
			// Check if we can cast the spell.
			if (!CanCastSpell(unit, spell, order.GetGoal(), order.goalPos)) {
				// Notify player about this problem
				if (unit.Variable[MANA_INDEX].Value < spell.ManaCost) {
					unit.Player->Notify(NotifyYellow, unit.tilePos,
										_("%s: not enough mana for spell: %s"),
										unit.Type->Name.c_str(), spell.Name.c_str());
				} else {
					unit.Player->Notify(NotifyYellow, unit.tilePos,
										_("%s: can't cast spell: %s"),
										unit.Type->Name.c_str(), spell.Name.c_str());
				}

				if (unit.Player->AiEnabled) {
					DebugPrint("FIXME: do we need an AI callback?\n");
				}
				this->Finished = true;
				return ;
			}
			if (CheckForDeadGoal(unit)) {
				return;
			}
			// FIXME FIXME FIXME: Check if already in range and skip straight to 2(casting)
			unit.ReCast = 0; // repeat spell on next pass? (defaults to `no')
			this->State = 1;
			// FALL THROUGH
		case 1:                         // Move to the target.
			if (spell.Range && spell.Range != INFINITE_RANGE) {
				if (SpellMoveToTarget(unit) == true) {
					this->Finished = true;
					return ;
				}
				return ;
			} else {
				this->State = 2;
			}
			// FALL THROUGH
		case 2:                         // Cast spell on the target.
			if (!spell.IsCasterOnly()) {
				AnimateActionSpellCast(unit, *this);
				if (unit.Anim.Unbreakable) {
					return ;
				}
			} else {
				// FIXME: what todo, if unit/goal is removed?
				CUnit *goal = order.GetGoal();
				if (goal && goal != &unit && !goal->IsVisibleAsGoal(*unit.Player)) {
					unit.ReCast = 0;
				} else {
					unit.ReCast = SpellCast(unit, spell, goal, order.goalPos);
				}
			}

			// Target is dead ? Change order ?
			if (CheckForDeadGoal(unit)) {
				return;
			}

			// Check, if goal has moved (for ReCast)
			if (unit.ReCast && order.GetGoal() && unit.MapDistanceTo(*order.GetGoal()) > this->Range) {
				this->State = 0;
				return;
			}
			if (!unit.ReCast && unit.CurrentAction() != UnitActionDie) {
				this->Finished = true;
				return ;
			}
			break;

		default:
			this->State = 0; // Reset path, than move to target
			break;
	}
}