Example #1
0
bool Trap::Process()
{
	if (chkarea_timer.Enabled() && chkarea_timer.Check() && !reset_timer.Enabled())
	{
		Mob* trigger = entity_list.GetTrapTrigger(this);
		if (trigger && !(trigger->IsClient() && trigger->CastToClient()->GetGM()))
		{
			Trigger(trigger);
		}
	}
	else if (reset_timer.Enabled() && reset_timer.Check())
	{
		Log.Out(Logs::General, Logs::Traps, "Reset timer disabled in Reset Check Process for trap %d.", trap_id);
		reset_timer.Disable();
		charid = 0;
	}

	if (respawn_timer.Enabled() && respawn_timer.Check())
	{
		detected = false;
		disarmed = false;
		chkarea_timer.Enable();
		respawn_timer.Disable();
	}


	return true;
}
Example #2
0
void HateList::Wipe()
{
	LinkedListIterator<tHateEntry*> iterator(list);
	iterator.Reset();

	while(iterator.MoreElements()) 
	{
		Mob* m = iterator.GetData()->ent;
        parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0); 
       	iterator.RemoveCurrent();

		if(m->IsClient())
			m->CastToClient()->DecrementAggroCount();
	}
}
Example #3
0
void HateList::Wipe()
{
	auto iterator = list.begin();

	while(iterator != list.end())
	{
		Mob* m = (*iterator)->ent;
		parse->EventNPC(EVENT_HATE_LIST, owner->CastToNPC(), m, "0", 0);
		//iterator

		delete (*iterator);
		iterator = list.erase(iterator);

		if(m->IsClient())
			m->CastToClient()->DecrementAggroCount();
	}
}
Example #4
0
bool Trap::Process()
{
	if (chkarea_timer.Enabled() && chkarea_timer.Check()
		/*&& zone->GetClientCount() > 0*/ )
	{
		Mob* trigger = entity_list.GetTrapTrigger(this);
		if (trigger && !(trigger->IsClient() && trigger->CastToClient()->GetGM()))
		{
			Trigger(trigger);
		}
	}
	if (respawn_timer.Enabled() && respawn_timer.Check())
	{
		detected = false;
		disarmed = false;
		chkarea_timer.Enable();
		respawn_timer.Disable();
	}
	return true;
}
Example #5
0
/*
	If you change this function, you should update the above function
	to keep the #aggro command accurate.
*/
bool Mob::CheckWillAggro(Mob *mob) {
	if(!mob)
		return false;

	//sometimes if a client has some lag while zoning into a dangerous place while either invis or a GM
	//they will aggro mobs even though it's supposed to be impossible, to lets make sure we've finished connecting
	if (mob->IsClient()) {
		if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn())
			return false;
	}

	Mob *ownr = mob->GetOwner();
	if(ownr && ownr->IsClient() && !ownr->CastToClient()->ClientFinishedLoading())
		return false;

	float iAggroRange = GetAggroRange();

	// Check If it's invisible and if we can see invis
	// Check if it's a client, and that the client is connected and not linkdead,
	// and that the client isn't Playing an NPC, with thier gm flag on
	// Check if it's not a Interactive NPC
	// Trumpcard: The 1st 3 checks are low cost calcs to filter out unnessecary distance checks. Leave them at the beginning, they are the most likely occurence.
	// Image: I moved this up by itself above faction and distance checks because if one of these return true, theres no reason to go through the other information

	float t1, t2, t3;
	t1 = mob->GetX() - GetX();
	t2 = mob->GetY() - GetY();
	t3 = mob->GetZ() - GetZ();
	//Cheap ABS()
	if(t1 < 0)
		t1 = 0 - t1;
	if(t2 < 0)
		t2 = 0 - t2;
	if(t3 < 0)
		t3 = 0 - t3;
	if(( t1 > iAggroRange)
		|| ( t2 > iAggroRange)
		|| ( t3 > iAggroRange)
		||(mob->IsInvisible(this))
		|| (mob->IsClient() &&
			(!mob->CastToClient()->Connected()
				|| mob->CastToClient()->IsLD()
				|| mob->CastToClient()->IsBecomeNPC()
				|| mob->CastToClient()->GetGM()
			)
		))
	{
		return(false);
	}

	// Don't aggro new clients if we are already engaged unless PROX_AGGRO is set
	if (IsEngaged() && (!GetSpecialAbility(PROX_AGGRO) || (GetSpecialAbility(PROX_AGGRO) && !CombatRange(mob)))) {
		Log.Out(Logs::Moderate, Logs::Aggro,
			"%s is in combat, and does not have prox_aggro, or does and is out of combat range with %s",
			GetName(), mob->GetName());
		return false;
	}

	//im not sure I understand this..
	//if I have an owner and it is not this mob, then I cannot
	//aggro this mob...???
	//changed to be 'if I have an owner and this is it'
	if(mob == GetOwner()) {
		return(false);
	}

	float dist2 = DistanceSquared(mob->GetPosition(), m_Position);
	float iAggroRange2 = iAggroRange*iAggroRange;

	if( dist2 > iAggroRange2 ) {
		// Skip it, out of range
		return(false);
	}

	//Image: Get their current target and faction value now that its required
	//this function call should seem backwards
	FACTION_VALUE fv = mob->GetReverseFactionCon(this);

	// Make sure they're still in the zone
	// Are they in range?
	// Are they kos?
	// Are we stupid or are they green
	// and they don't have their gm flag on
	int heroicCHA_mod = mob->itembonuses.HeroicCHA/25; // 800 Heroic CHA cap
	if(heroicCHA_mod > THREATENLY_ARRGO_CHANCE)
		heroicCHA_mod = THREATENLY_ARRGO_CHANCE;
	if
	(
	//old InZone check taken care of above by !mob->CastToClient()->Connected()
	(
		( GetINT() <= RuleI(Aggro, IntAggroThreshold) )
		||( mob->IsClient() && mob->CastToClient()->IsSitting() )
		||( mob->GetLevelCon(GetLevel()) != CON_GREEN )

	)
	&&
	(
		(
			fv == FACTION_SCOWLS
			||
			(mob->GetPrimaryFaction() != GetPrimaryFaction() && mob->GetPrimaryFaction() == -4 && GetOwner() == nullptr)
			||
			(
				fv == FACTION_THREATENLY
				&& zone->random.Roll(THREATENLY_ARRGO_CHANCE - heroicCHA_mod)
			)
		)
	)
	)
	{
		//FatherNiwtit: make sure we can see them. last since it is very expensive
		if(CheckLosFN(mob)) {
			Log.Out(Logs::Detail, Logs::Aggro, "Check aggro for %s target %s.", GetName(), mob->GetName());
			return( mod_will_aggro(mob, this) );
		}
	}

	Log.Out(Logs::Detail, Logs::Aggro, "Is In zone?:%d\n", mob->InZone());
	Log.Out(Logs::Detail, Logs::Aggro, "Dist^2: %f\n", dist2);
	Log.Out(Logs::Detail, Logs::Aggro, "Range^2: %f\n", iAggroRange2);
	Log.Out(Logs::Detail, Logs::Aggro, "Faction: %d\n", fv);
	Log.Out(Logs::Detail, Logs::Aggro, "Int: %d\n", GetINT());
	Log.Out(Logs::Detail, Logs::Aggro, "Con: %d\n", GetLevelCon(mob->GetLevel()));

	return(false);
}
Example #6
0
// causes caster to hit every mob within dist range of center with
// spell_id.
// NPC spells will only affect other NPCs with compatible faction
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
	Mob *curmob;

	float dist = caster->GetAOERange(spell_id);
	float dist2 = dist * dist;
	float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
	float dist_targ = 0;

	bool bad = IsDetrimentalSpell(spell_id);
	bool isnpc = caster->IsNPC();
	int MAX_TARGETS_ALLOWED = 4;

	if (spells[spell_id].aemaxtargets)
		MAX_TARGETS_ALLOWED = spells[spell_id].aemaxtargets;

	int iCounter = 0;

	for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
		curmob = it->second;
		// test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized
		if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading())
			continue;
		if (curmob == center)	//do not affect center
			continue;
		if (curmob == caster && !affect_caster)	//watch for caster too
			continue;
		if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && curmob->IsPetOwnerClient())
			continue;
		if (spells[spell_id].targettype == ST_AreaClientOnly && !curmob->IsClient())
			continue;
		if (spells[spell_id].targettype == ST_AreaNPCOnly && !curmob->IsNPC())
			continue;

		if (spells[spell_id].targettype == ST_Ring) {
			dist_targ = DistanceSquared(static_cast<glm::vec3>(curmob->GetPosition()), caster->GetTargetRingLocation());
		}
		else if (center) {
			dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition());
		}

		if (dist_targ > dist2)	//make sure they are in range
			continue;
		if (dist_targ < min_range2)	//make sure they are in range
			continue;
		if (isnpc && curmob->IsNPC()) {	//check npc->npc casting
			FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
			if (bad) {
				//affect mobs that are on our hate list, or
				//which have bad faction with us
				if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) )
					continue;
			} else {
				//only affect mobs we would assist.
				if (!(f <= FACTION_AMIABLE))
					continue;
			}
		}
		//finally, make sure they are within range
		if (bad) {
			if (!caster->IsAttackAllowed(curmob, true))
				continue;
			if (center &&  !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob))
				continue;
			if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize()))
				continue;
		} else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
			// This does not check faction for beneficial AE buffs..only agro and attackable.
			// I've tested for spells that I can find without problem, but a faction-based
			// check may still be needed. Any changes here should also reflect in BardAEPulse()
			if (caster->IsAttackAllowed(curmob, true))
				continue;
			if (caster->CheckAggro(curmob))
				continue;
		}

		curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ);

		//if we get here... cast the spell.
		if (IsTargetableAESpell(spell_id) && bad) {
			if (iCounter < MAX_TARGETS_ALLOWED) {
				caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
			}
		} else {
			if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets)
				caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
			if (!spells[spell_id].aemaxtargets)
				caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
		}

		if (!isnpc || spells[spell_id].aemaxtargets) //npcs are not target limited (unless casting a spell with a target limit)...
			iCounter++;
	}
}
Example #7
0
// solar: causes caster to hit every mob within dist range of center with
// spell_id.
// NPC spells will only affect other NPCs with compatible faction
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
	Mob *curmob;

	float dist = caster->GetAOERange(spell_id);
	float dist2 = dist * dist;

	bool bad = IsDetrimentalSpell(spell_id);
	bool isnpc = caster->IsNPC();
	const int MAX_TARGETS_ALLOWED = 4;
	int iCounter = 0;

	for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
		curmob = it->second;
		// test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized
		if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading())
			continue;
		if (curmob == center)	//do not affect center
			continue;
		if (curmob == caster && !affect_caster)	//watch for caster too
			continue;
		if (center->DistNoRoot(*curmob) > dist2)	//make sure they are in range
			continue;
		if (isnpc && curmob->IsNPC()) {	//check npc->npc casting
			FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
			if (bad) {
				//affect mobs that are on our hate list, or
				//which have bad faction with us
				if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS) )
					continue;
			} else {
				//only affect mobs we would assist.
				if (!(f <= FACTION_AMIABLE))
					continue;
			}
		}
		//finally, make sure they are within range
		if (bad) {
			if (!caster->IsAttackAllowed(curmob, true))
				continue;
			if (!center->CheckLosFN(curmob))
				continue;
		} else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
			// This does not check faction for beneficial AE buffs..only agro and attackable.
			// I've tested for spells that I can find without problem, but a faction-based
			// check may still be needed. Any changes here should also reflect in BardAEPulse() -U
			if (caster->IsAttackAllowed(curmob, true))
				continue;
			if (caster->CheckAggro(curmob))
				continue;
		}

		//if we get here... cast the spell.
		if (IsTargetableAESpell(spell_id) && bad) {
			if (iCounter < MAX_TARGETS_ALLOWED) {
				caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
			}
		} else {
			caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
		}

		if (!isnpc) //npcs are not target limited...
			iCounter++;
	}
}
Example #8
0
//o--------------------------------------------------------------
//| BuffFadeBySlot; Yeahlight, Nov 16, 2008
//o--------------------------------------------------------------
//| Adapted from EQEMU 7.0: Removes the buff in the supplied
//| buff slot 'slot'
//o--------------------------------------------------------------
void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
{
	bool debugFlag = true;

	if(slot < 0 || slot > BUFF_COUNT)
		return;

	if(!buffs[slot].spell || !buffs[slot].spell->IsValidSpell())
		return;

	if(IsClient())
		CastToClient()->MakeBuffFadePacket(buffs[slot].spell, slot);


	if(debugFlag && this->IsClient() && this->CastToClient()->GetDebugMe())
		this->Message(LIGHTEN_BLUE, "Debug: Fading buff %d from slot %d", buffs[slot].spell->GetSpellID(), slot);

	for(int i = 0; i < EFFECT_COUNT; i++)
	{
		if(buffs[slot].spell->IsBlankSpellEffect(i))
			continue;
		switch(buffs[slot].spell->GetSpellEffectID(i))
		{
			case SE_WeaponProc:
			{
				SetBonusProcSpell(0);
				break;
			}
			case SE_Illusion: case SE_IllusionCopy:
			{
				SendIllusionPacket(GetBaseRace(), GetBaseGender(), GetTexture(), GetHelmTexture());
				SendAppearancePacket(this->GetID(), SAT_Size, GetDefaultSize(), true);
				break;
			}
			case SE_Levitate:
			{
				SendAppearancePacket(this->GetID(), SAT_Levitate, 0, true);
				break;
			}
			case SE_Invisibility:
			{
				SetInvisible(false);
				break;
			}
			case SE_InvisVsUndead:
			{
				SetInvisibleUndead(false);
				break;
			}
			case SE_InvisVsAnimals:
			{
				SetInvisibleAnimal(false);
				break;
			}
			case SE_Silence:
			{
				break;
			}
			case SE_DivineAura:
			{
				SetInvulnerable(false);
				break;
			}
			case SE_Rune:
			{
				break;
			}
			case SE_AbsorbMagicAtt:
			{
				break;
			}
			case SE_Mez:
			{
				//Yeahlight: Unfreeze the PC's UI
				if(IsClient())
					SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true);
				this->mesmerized = false;
				break;
			}
			case SE_Charm:
			{
				Mob* charmer = entity_list.GetMob(this->GetOwnerID());
				if(charmer && charmer->IsClient())
				{
					char npcNameSuffix[] = "_CHARM00";
					char npcNamePrefix[100] = "";
					strcpy(npcNamePrefix, charmer->GetName());
					strcat(npcNamePrefix, npcNameSuffix);
					Mob* charmPH = entity_list.GetMob(npcNamePrefix);
					if(charmPH && charmPH->IsNPC())
					{
						charmPH->Depop();
					}
					//Yeahlight: Check for _CHARM01 NPC, too
					npcNamePrefix[strlen(npcNamePrefix) - 1] = '1';
					charmPH = entity_list.GetMob(npcNamePrefix);
					if(charmPH && charmPH->IsNPC())
					{
						charmPH->Depop();
					}
					//Yeahlight: Generate hate for towards the charmer if the charmer is not FD'ed
					if(this->IsNPC() && charmer->IsClient() && !charmer->CastToClient()->GetFeigned())
					{
						CastToNPC()->AddToHateList(charmer, 0, GetSpellHate(SE_Charm, this->GetLevel(), false));
					}
				}
				//Yeahlight: Unfreeze the PC's UI
				if(IsClient())
				{
					SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true);
					CastToClient()->SetCharmed(false);
					CastToClient()->charmPositionUpdate_timer->Disable();
				}
				//Yeahlight: Deflag the NPC as charmed
				else if(IsNPC())
				{
					CastToNPC()->SetCharmed(false);
				}
				this->SetOwnerID(0, false);
				break;
			}
			case SE_Root:
			{
				break;
			}
			case SE_Fear:
			{
				//Yeahlight: Unfreeze the PC's UI
				if(IsClient())
				{
					CastToClient()->SetFeared(false);
					SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true);
				}
				else if(IsNPC())
				{
					CastToNPC()->SetFeared(false);
					CastToNPC()->SetOnFearPath(false);
				}
				break;
			}
			case SE_SpinTarget:
			{
				//Yeahlight: Unfreeze the PC's UI
				if(IsClient())
					SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Sitting_To_Standing, true);
				break;
			}
			case SE_EyeOfZomm:
			{
				//Yeahlight: Clear the eye of zomm pointer and depop the eye
				if(IsClient() && CastToClient()->myEyeOfZomm)
				{
					CastToClient()->myEyeOfZomm->Depop();
					CastToClient()->myEyeOfZomm = NULL;
				}
				break;
			}
			case SE_DeathSave:
			{
				//Yeahlight: Clear the death save chance
				if(IsClient())
					CastToClient()->SetDeathSave(0);
				break;
			}
			case SE_VoiceGraft:
			{
				//Yeahlight: Drop the voice grafting flag from the client
				if(GetOwner() && GetOwner()->IsClient())
				{
					GetOwner()->CastToClient()->SetVoiceGrafting(false);
				}
				break;
			}
			case SE_SeeInvis:
			{
				//Yeahlight: Mob may no longer see through invis
				SetCanSeeThroughInvis(false);
				break;
			}
		}
	}

	buffs[slot].spell = NULL;

	if(iRecalcBonuses)
		CalcBonuses(true, true);
}
Example #9
0
///////////////////////////////////////////////////
// Quagmire - that case above getting to long and spells are gonna have a lot of cases of their own
// Cofruben - Reorganised this a little.
void Mob::SpellEffect(Mob* caster, Spell* spell, int8 caster_level, bool partialResist)
{
	//Spells not loaded!
	if(!spells_handler.SpellsLoaded())
		return;
	//Spell not loaded!
	if(!spell)
		return;
	//Yeahlight: Caster was not supplied
	if(!caster)
		return;

	int i = 0;
	const int16	spell_id		= spell->GetSpellID();
	const char*	teleport_zone	= spell->GetSpellTeleportZone();
	
	// 1. Is it a buff? If so, handle its time based effects.
	if (spell->IsBuffSpell())
		spells_handler.HandleBuffSpellEffects(caster, this, spell);
	
	// 2. Handle its single-time effect.
	for (i = 0; i < EFFECT_COUNT; i++)
	{
		TSpellEffect effect_id = spell->GetSpellEffectID(i);
		if(effect_id == SE_Blank || effect_id == 0xFF)
			continue;
		int8   formula = spell->GetSpellFormula(i);
		sint16 base    = spell->GetSpellBase(i);
		sint16 max     = spell->GetSpellMax(i);	
		sint32 amount  = spells_handler.CalcSpellValue(spell, i, caster_level);
		//Yeahlight: This is an NPC and had a detremental spell casted upon it
		if(this->IsNPC() && (spell->IsDetrimentalSpell() || spell->IsUtilitySpell()))
		{
			CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): aggroing %s because of the spell effect!", spell->GetSpellName(), this->GetName());
			//Yeahlight: Generate hate based on the spells's effect type
			sint16 tempHate = GetSpellHate(effect_id, spell->GetMinLevel(), false, amount);
			if(tempHate)
			{
				this->CastToNPC()->AddToHateList(caster, 0, tempHate);
			}
		}
		switch(effect_id)
		{
			case SE_CurrentHP:
			case SE_CurrentHPOnce:
			{
				sint32 OldHP = this->GetHP();
				sint32 damage = amount;
				//Yeahlight: Partial resist calculations
				if(partialResist)
				{
					damage = damage / 2;
					damage = damage * (float)((float)(rand()%90 + 10) / 100.00f);
					if(caster->IsClient() && caster->CastToClient()->GetDebugMe())
						caster->Message(YELLOW, "Debug: Your direct damage spell resist has been upgrade to a partial resist.");
				}
				this->ChangeHP(caster, damage, spell_id);
				sint32 NewHP = this->GetHP();
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You changed %s's hp by %+i.", spell->GetSpellName(), this->GetName(), damage);
				break;
			}
			case SE_MovementSpeed:
			{
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Movement Speed spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_AttackSpeed:
			{
				//Yeahlight: There should not be any work to be done here
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Attack Speed spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Invisibility: 
			{
				this->SetInvisible(true);
				//Yeahlight: Castee has a pet; remove it
				if(GetPet())
				{
					Mob* myPet = GetPet();
					//Yeahlight: Castee's pet is an NPC
					if(myPet->IsNPC())
					{
						//Yeahlight: Castee's pet is a charmed NPC
						if(myPet->CastToNPC()->IsCharmed())
						{
							myPet->CastToNPC()->BuffFadeByEffect(SE_Charm);
						}
						//Yeahlight: Castee's pet is a summoned NPC
						else
						{
							myPet->Depop();
						}
					}
					//Yeahlight: Castee's pet is a charmed PC
					else if(myPet->IsClient() && myPet->CastToClient()->IsCharmed())
					{
						myPet->CastToClient()->BuffFadeByEffect(SE_Charm);
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an invisibility spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_CurrentMana:
			{
				SetMana(GetMana() + amount);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a mana recovery spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_AddFaction:
			{
				//Yeahlight: Only continue if the target is an NPC and the caster is a PC
				if(this->IsNPC() && caster->IsClient())
				{
					caster->CastToClient()->SetCharacterFactionLevelModifier(this->CastToNPC()->GetPrimaryFactionID(), amount);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an add faction spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Stun:
			{
				if (IsClient())
				{
					CastToClient()->Stun(base);
				}
				else if(IsNPC())
				{
					//Yeahlight: NPC is immune to stun effects
					if(CastToNPC()->GetCannotBeStunned())
					{
						if(caster->IsClient())
						{
							caster->Message(RED, "Your target is immune to the stun portion of this effect");
						}
					}
					else
					{
						CastToNPC()->Stun(base);
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a stun spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_Charm:
			{
				//Yeahlight: Can only charm a non-pet and the caster may only have one pet
				if(this->GetOwner() == NULL && caster->GetPet() == NULL && caster != this)
				{
					//Yeahlight: Flag the NPC as a pet
					if(this->IsNPC())
					{
						caster->SetPet(this);
						this->SetOwnerID(caster->GetID());
						this->CastToNPC()->SetCharmed(true);
						this->SetPetOrder(SPO_Follow);
						if(caster->IsClient())
							caster->CastToClient()->SendCharmPermissions();
						this->CastToNPC()->WhipeHateList();
						this->CastToNPC()->StartTaunting();
					}
					else if(this->IsClient())
					{
						if(caster->IsNPC())
						{
							caster->SetPet(this);
							this->SetOwnerID(caster->GetID());
							Mob* myTarget = caster->CastToNPC()->GetHateTop();
							if(!myTarget)
								myTarget = caster->CastToMob();
							this->SetTarget(myTarget);
							this->animation = 0;
							this->delta_heading = 0;
							this->delta_x = 0;
							this->delta_y = 0;
							this->delta_z = 0;
							this->SendPosUpdate(true, PC_UPDATE_RANGE, false);
							this->CastToClient()->charmPositionUpdate_timer->Start(200);
							this->CastToClient()->SetCharmed(true);
							this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false);
							this->SetPetOrder(SPO_Follow);
						}
						else if(caster->IsClient())
						{
							caster->SetPet(this);
							this->SetOwnerID(caster->GetID());
							this->SetTarget(caster);
							this->animation = 0;
							this->delta_heading = 0;
							this->delta_x = 0;
							this->delta_y = 0;
							this->delta_z = 0;
							this->SendPosUpdate(true, PC_UPDATE_RANGE, false);
							this->CastToClient()->charmPositionUpdate_timer->Start(200);
							this->CastToClient()->SetCharmed(true);
							this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false);
							this->SetPetOrder(SPO_Follow);
							caster->CastToClient()->SendCharmPermissions();
						}
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a charm spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Fear:
			{
				//Yeahlight: Victim is a PC
				if(this->IsClient())
				{
					this->CastToClient()->SetFeared(true);
					this->SendAppearancePacket(this->GetID(), SAT_Position_Update, SAPP_Lose_Control, false);
					this->CastToClient()->GetFearDestination(GetX(), GetY(), GetZ());
				}
				//Yeahlight: Victim is an NPC
				else if(this->IsNPC())
				{
					this->CastToNPC()->SetFeared(true);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a fear spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Stamina:
			{
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a stamina spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_BindAffinity:
			{
				//Yeahlight: Target of the bind affinity spell is a client
				if(this->IsClient())
				{
					this->CastToClient()->SetBindPoint();
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Bind Affinity spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Gate:
			{
				if(IsClient())
					CastToClient()->GoToBind();
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a gate spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_CancelMagic:
			{
				for(int i = 0; i < 15; i++)
				{
					//Yeahlight: Buff must exist and the buff may not have any poison or disease counters
					if(buffs[i].spell && buffs[i].spell->IsValidSpell() && buffs[i].casterlevel <= (caster_level + base) && buffs[i].spell->GetDiseaseCounters() == 0 && buffs[i].spell->GetPoisonCounters() == 0)
					{	
						this->BuffFadeBySlot(i, true);
						break;
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a cancel magic spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_InvisVsUndead:
			{
				this->SetInvisibleUndead(true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an Invis VS Undead spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_InvisVsAnimals:
			{
				this->SetInvisibleAnimal(true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an Invis VS Animal spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Mez:
			{
				// Pinedepain // When a mezz spell is casted, we mesmerize this mob
				Mesmerize();
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a mesmerize spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_SummonItem:
			{
				if(this->IsClient())
				{
					if(amount == 0)
						this->CastToClient()->SummonItem(base, 1);
					else
						this->CastToClient()->SummonItem(base, (amount > 20) ? 20 : amount);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a summon item spell: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_NecPet:
			case SE_SummonPet:
			{
				if (this->GetPetID() != 0) {
					Message(RED, "You\'ve already got a pet.");
					break;
				}
				this->MakePet(teleport_zone);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Summon pet / nec pet spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_DivineAura:
			{
				this->SetInvulnerable(true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Divine Aura, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_ShadowStep:
			{
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Shadow Step spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Rune:
			{
				//Yeahlight: Flag entity with rune for damage calculations
				hasRuneOn = true;
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Rune spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Levitate:
			{
				this->SendAppearancePacket(0, SAT_Levitate, 2, true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a levitate spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_SummonCorpse:
			{
				bool permit = false;
				Mob* corpseOwner = target;
				//Yeahlight: The target of this spell is not a PC or the caster is targeting themself
				if(!target || (target && !target->IsClient()) || target == this)
				{
					corpseOwner = this;
					permit = true;
				}
				//Yeahlight: Can only summon a PC's corpse
				if(corpseOwner && corpseOwner->IsClient())
				{
					//Yeahlight: PCs must be grouped to summon a corpse
					if(!permit)
					{
						Group* targetGroup = entity_list.GetGroupByClient(corpseOwner->CastToClient());
						Group* myGroup = NULL;
						if(this->IsClient())
							myGroup = entity_list.GetGroupByClient(this->CastToClient());
						//Yeahlight: Caster is in a group and they share the same group as the target
						if(myGroup != NULL && myGroup == targetGroup)
							permit = true;
					}
					//Yeahlight: Caster may proceed with the summon
					if(permit)
					{
						Corpse *corpse = entity_list.GetCorpseByOwner(corpseOwner->CastToClient());
						//Yeahlight: Corpse has been located
						if(corpse)
						{
							corpse->Summon(corpseOwner->CastToClient(), caster->CastToClient(), true);
							CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a summon corpse spell: %s.", spell->GetSpellName(), this->GetName());
						}
						//Yeahlight: There is no corpse available
						else
						{
							//Yeahlight: Caster failed to locate his/her corpse
							if(caster == corpseOwner)
							{
								caster->Message(RED, "You do not have a corpse in this zone.");
							}
							//Yeahlight: Caster failed to locate their target's corpse
							else
							{
								caster->Message(RED, "Your target does not have a corpse in this zone.");
							}
							CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): Summon corpse: you can't sense the corpse: %i.", spell->GetSpellName());
						}
					}
					else
					{
						//Yeahlight: TODO: This is not the correct message
						Message(RED, "You and your target must be in the same group to perform this action.");
					}
				}
				break;
			}
			case SE_Illusion:
			{
				SendIllusionPacket(base, GetDefaultGender(base, GetBaseGender()), GetTexture(), GetHelmTexture());
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an illusion spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Identify:
			{
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an identify spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_WipeHateList:
			{
				//Yeahlight: NOTE: Do NOT wipe the rampage list here; that never goes away until the mob resets
				if(this->IsNPC())
				{
					//Yeahlight: TODO: I don't remember this message, look into this
					entity_list.MessageClose(this, true, DEFAULT_MESSAGE_RANGE, DARK_BLUE, "My mind fogs. Who are my friends? Who are my enemies?... it was all so clear a moment ago...");
					this->CastToNPC()->WhipeHateList();
					CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a whipe hate list spell, amount: %i.", spell->GetSpellName(), amount);
				}
				break;
			}
			case SE_SpinTarget:
			{
				Spin(caster, spell);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a spin target spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_EyeOfZomm:
			{
				//Yeahlignt: Only produce eyes of zomm for PCs
				if(this->IsClient())
				{
					if(this->CastToClient()->myEyeOfZomm == 0)
						MakeEyeOfZomm(this);
					else
						Message(RED, "You may only have one eye of zomm out at a time!");
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a Eye Of Zomm spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_ReclaimPet:
			{
				//Yeahlight: Target of the spell is an uncharmed NPC, has an owner and the owner is the caster of the spell
				if(IsNPC() && CastToNPC()->IsCharmed() == false && GetOwnerID() && caster->GetID() == GetOwnerID())
				{
					//Yeahlight: TODO: Research this formula
					caster->SetMana(caster->GetMana()+(GetLevel()*4));
					if(caster->IsClient())
					{
						caster->CastToClient()->SetPet(0);
					}
					SetOwnerID(0);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a reclaim pet spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_FeignDeath:
			{
				if(this->IsClient())
					this->CastToClient()->FeignDeath(this->CastToClient()->GetSkill(ABJURATION));
				break;
			}
			case SE_VoiceGraft:
			{
				//Yeahlight: Only allow voice graft to be casted on NPCs (we don't want PCs griefing other charmed PCs with /say)
				if(IsNPC() && caster->IsClient() && CastToNPC()->GetOwner() == caster)
				{
					caster->CastToClient()->SetVoiceGrafting(true);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a voice graft spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Revive:
			{
				//Yeahlight: Handled in client_process.cpp
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a revive spell, amount: %i, corpse: %s.", spell->GetSpellName(), amount, this->GetName());
				break;
			}
			case SE_Teleport:
			{
				char teleport_zone_char[64];
				if(this->IsClient())
					strcpy(teleport_zone_char, teleport_zone);
					this->CastToClient()->MovePC(teleport_zone_char, spell->GetSpellBase(1), spell->GetSpellBase(0), spell->GetSpellBase(2), false, false);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a teleport spell to %s (%f, %f, %f).", spell->GetSpellName(), teleport_zone, spell->GetSpellBase(1), spell->GetSpellBase(0), spell->GetSpellBase(2));
				break;
			}
			case SE_Translocate:
			{
				bool permit = false;
				Mob* translocatee = CastToMob();

				//Enraged: The target of this spell is an NPC.
				//if(translocatee && !translocatee->IsClient())
				//{
				//	//Enraged: TODO: This is not the correct message?
				//	Message(RED, "You cannot cast that spell on your current target.");
				//	break;
				//}

				//Enraged: The target of this spell is the caster.
				//TODO: Can players target themselves with translocate spells?
				if(translocatee && (translocatee == this))
					permit = true;

				//Enraged: Check if the targetted client is in the casters group.
				//TODO: Translocate only worked on group players, right?
				if(!permit && translocatee)
				{
					Group* translocateeGroup = entity_list.GetGroupByClient(translocatee->CastToClient());
					Group* casterGroup = NULL;
					if(this->IsClient())
						casterGroup = entity_list.GetGroupByClient(this->CastToClient());
					//Enraged: The translocatee is in a group and they share the same group as the target
					if(casterGroup != NULL && casterGroup == translocateeGroup)
						permit = true;
				}

				//Enraged: Target is clear to be translocated.
				if(permit)
				{
					CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a translocation spell on %s.", spell->GetSpellName(), translocatee->GetName());
					//TODO: Translocate code here
					translocatee->CastToClient()->SendTranslocateConfirmation(caster, spell);
				}
				else
				{
					//The translocatee was not in the casters group.
					//Enraged: TODO: This is not the correct message
					Message(RED, "You can only cast that spell on players in your group.");
				}
				break;
			}
			case SE_InfraVision:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an infravision spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_UltraVision:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an ultravision spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_BindSight:
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a bind sight spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_SeeInvis:
				SetCanSeeThroughInvis(true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a see invis spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_WaterBreathing:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted an water breathing spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_SenseDead:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense dead spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_SenseSummoned:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense summoned spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_TrueNorth: 
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a true north spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_SenseAnimals:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sense animals spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_DamageShield:
				//Yeahlight: There should not be any work to be done here
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a damage shield spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_Sentinel:
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a sentinel spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_LocateCorpse:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a locate corpse spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_ModelSize:
			{
				//Yeahlight: Grow/Shrink
				float newSize = (GetSize() * (float)base) / 100.00f;
				//Yeahlight: Size of a gnome (minimum)
				if(newSize < 3)
					newSize = 3;
				//Yeahlight: Size of an ogre (maximum)
				else if(newSize > 9)
					newSize = 9;
				this->size = newSize;
				this->SendAppearancePacket(GetID(), SAT_Size, GetSize(), true);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a model size spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Root:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a root spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_Blind:
				//Yeahlight: Handled client side
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a blind spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			case SE_DiseaseCounter:
			{
				//Yeahlight: Spell is a cure disease spell
				if(amount < 0)
				{
					//Yeahlight: Iterate through all the debuffs on the target and check for the chance to cure it
					for(int i = 0; i < 15; i++)
					{
						if(buffs[i].spell && buffs[i].diseasecounters)
						{
							buffs[i].diseasecounters = buffs[i].diseasecounters + amount;
							if(buffs[i].diseasecounters <= 0)
								BuffFadeBySlot(i, true);
							break;
						}
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a disease counter spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_PoisonCounter:
			{
				//Yeahlight: Spell is a cure poison spell
				if(amount < 0)
				{
					//Yeahlight: Iterate through all the debuffs on the target and check for the chance to cure it
					for(int i = 0; i < 15; i++)
					{
						if(buffs[i].spell && buffs[i].poisoncounters)
						{
							buffs[i].poisoncounters = buffs[i].poisoncounters + amount;
							if(buffs[i].poisoncounters <= 0)
								BuffFadeBySlot(i, true);
							break;
						}
					}
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a poison counter spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_Calm:
			{
				//Yeahlight: Only add/remove hate from NPCs
				if(this->IsNPC())
				{
					this->CastToNPC()->AddToHateList(caster, 0, amount);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): You casted a calm hate spell, amount: %i.", spell->GetSpellName(), amount);
				break;
			}
			case SE_WeaponProc:
			{
				Spell* spell = spells_handler.GetSpellPtr(base);
				//Yeahlight: Legit spell proc bonus found
				if(spell)
					SetBonusProcSpell(spell);
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell name = %s): Weapon proc bonus of spell ID %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_StopRain:
			{
				zone->zone_weather = 0;
				zone->weatherSend();
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a stop rain spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_CallOfHero:
			{
				//Yeahlight: Call of the Hero may only be used on PCs
				int32 zoneid = 0;
				if(this->IsClient())
					this->CastToClient()->MovePC(zoneid, caster->GetX(), caster->GetY(), caster->GetZ(), false, true);
				else
					caster->Message(RED, "This spell may only be cast on players.");
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a call of the hero spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_CallPet:
			{
				//Yeahlight: This spell line may only be used on NPC pets
				if(GetPet() && GetPet()->IsNPC())
				{
					GetPet()->CastToNPC()->GMMove(GetX(), GetY(), GetZ(), GetHeading());
					GetPet()->pStandingPetOrder = SPO_Follow;
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a call pet spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_DeathSave:
			{
				//Yeahlight: Only apply divine intervention to players
				if(this->IsClient())
				{
					sint16 successChance = 0;
					float baseChance = 0.00f;
					switch(base)
					{
						//Yeahlight: Death Pact (CLR: 51)
						case 1:
						{
							baseChance = 0.10f;
							break;
						}
						//Yeahlight: Divine Intervention (CLR: 60)
						case 2:
						{
							baseChance = 0.30f;
							break;
						}
						default:
						{
							baseChance = 0.10f;
						}
					}
					//Yeahlight: The target's CHA is calculated into the bonus save chance
					successChance = (((float)CastToClient()->GetCHA() * 0.0005f) + baseChance) * 100;
					//Yeahlight: The worst possible save chance is the spell's base chance
					if(successChance < baseChance)
						successChance = baseChance;
					else if(successChance > 100)
						successChance = 100;
					this->CastToClient()->SetDeathSave(successChance);
				}
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a death save spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case SE_Succor:
			{
				//Yeahlight: There should be nothing to do here
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::ApplySpellsBonuses(spell name = %s): You casted a succor spell, amount: %i.", spell->GetSpellName(), base);
				break;
			}
			case 0xFE:
			case 0xFF:
			case SE_Harmony:
			case SE_ChangeFrenzyRad:
			case SE_Lull:
			case SE_TotalHP:
			case SE_ArmorClass:
			case SE_MagnifyVision:
			case SE_ATK:
			case SE_STR:
			case SE_DEX:
			case SE_AGI:
			case SE_STA:
			case SE_INT:
			case SE_WIS:
			case SE_CHA:
			case SE_ResistFire:
			case SE_ResistCold:
			case SE_ResistPoison:
			case SE_ResistDisease:
			case SE_ResistMagic:
			{
				// Buffs are handeled elsewhere
				break;
			}
			default:
			{
				CAST_CLIENT_DEBUG_PTR(caster)->Log(CP_SPELL, "Mob::SpellEffect(spell_name = %s): unknown effect (%i) for amount: %i.", spell->GetSpellName(), effect_id, amount);
				break;
			}
		}
	}
	if(this->IsClient())
		this->CastToClient()->Save();
}
Example #10
0
//Yeahlight: Searches for the group that will be rewarded with exp and first loot rights
returnGroup HateList::GetRewardingGroup()
{
	groupDamage groupsToConsider[255] = {0};
	int16 groupCounter = 0;
	int16 groupID = 0;
	int16 leadingGroupID = 0;
	sint32 highestGroupDamage = 0;
	sint32 entityDamage = 0;
	Mob* entity = NULL;
	returnGroup groupToReward;
	Group* group = NULL;
	bool groupFound = false;

	for(int i = 0; i < 255; i++)
	{
		groupsToConsider[i].groupID = -1;
		groupsToConsider[i].groupDamageTotal = -1;
	}
	groupToReward.damage = 0;
	groupToReward.group = NULL;

	LinkedListIterator<tHateEntry*> iterator(list);
    iterator.Reset();
	while(iterator.MoreElements())
    {
		entityDamage = 0;
		if(iterator.GetData())
			entityDamage = iterator.GetData()->damage;
		if(entityDamage > 0)
		{
			entity = iterator.GetData()->ent;
			//Yeahlight: Entity exists in the zone
			if(entity)
			{
				//Yeahlight: Entity is a client
				if(entity->IsClient())
				{
					//Yeahlight: PC is grouped
					if(entity->CastToClient()->IsGrouped())
					{
						group = entity_list.GetGroupByClient(entity->CastToClient());
						//Yeahlight: Group exists
						if(group)
						{
							groupID = group->GetID();
							//Yeahlight: We do not have a group list started yet, so start it off with this group
							if(groupCounter == 0)
							{
								groupsToConsider[0].groupID = groupID;
								groupsToConsider[0].groupDamageTotal = iterator.GetData()->damage;
								groupsToConsider[0].group = group;
								groupCounter++;
							}
							//Yeahlight: A group list has been created already
							else
							{
								//Yeahlight: Iterate through the group list
								for(int i = 0; i < groupCounter; i++)
								{
									//Yeahlight: Found the group for which this PC resides
									if(groupID == groupsToConsider[i].groupID)
									{
										//Yeahlight: Add the client's damage to the group's total
										groupsToConsider[i].groupDamageTotal += iterator.GetData()->damage;
										//Yeahlight: Flag the PC as found
										groupFound = true;
										//Yeahlight: "Break out" of the loop
										i = groupCounter;
									}
								}
								//Yeahlight: This grouped PC did not find their group in the list, so we need to add their group
								if(!groupFound)
								{
									groupsToConsider[groupCounter].groupID = groupID;
									groupsToConsider[groupCounter].groupDamageTotal = iterator.GetData()->damage;
									groupsToConsider[groupCounter].group = group;
									groupCounter++;
								}
							}
						}
						//Yeahlight: Group does not exist
						else
						{
							
						}
					}
					//Yeahlight: PC is not grouped
					else
					{

					}
				}
				//Yeahlight: Entity is the pet of a client
				else if(entity->IsNPC() && entity->GetOwner() && entity->GetOwner()->IsClient())
				{
					//Yeahlight: Owner of the pet is grouped
					if(entity->GetOwner()->CastToClient()->IsGrouped())
					{
						group = entity_list.GetGroupByClient(entity->GetOwner()->CastToClient());
						//Yeahlight: Group exists
						if(group)
						{
							groupID = group->GetID();
							//Yeahlight: We do not have a group list started yet, so start it off with this group
							if(groupCounter == 0)
							{
								groupsToConsider[0].groupID = groupID;
								groupsToConsider[0].groupDamageTotal = iterator.GetData()->damage;
								groupsToConsider[0].group = group;
								groupCounter++;
							}
							//Yeahlight: A group list has been created already
							else
							{
								//Yeahlight: Iterate through the group list
								for(int i = 0; i < groupCounter; i++)
								{
									//Yeahlight: Found the group for which this pet resides
									if(groupID == groupsToConsider[i].groupID)
									{
										//Yeahlight: Add the pet's damage to the group's total
										groupsToConsider[i].groupDamageTotal += iterator.GetData()->damage;
										//Yeahlight: Flag the pet as found
										groupFound = true;
										//Yeahlight: "Break out" of the loop
										i = groupCounter;
									}
								}
								//Yeahlight: This grouped pet did not find their group in the list, so we need to add their group
								if(!groupFound)
								{
									groupsToConsider[groupCounter].groupID = groupID;
									groupsToConsider[groupCounter].groupDamageTotal = iterator.GetData()->damage;
									groupsToConsider[groupCounter].group = group;
									groupCounter++;
								}
							}
						}
						//Yeahlight: Group does not exist
						else
						{
							
						}
					}
					//Yeahlight: Pet's owner is not grouped
					else
					{

					}
				}
			}
			//Yeahlight: Entity does not exist in the zone
			else
			{

			}
		}
        iterator.Advance();
		//Yeahlight: Zone freeze debug
		if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1)
			EQC_FREEZE_DEBUG(__LINE__, __FILE__);
    }

	//Yeahlight: Iterate through the group list and record for the highest damaging group
	for(int i = 0; i < groupCounter; i++)
	{
		//Yeahlight: Found a group with more total damage than our current leader
		if(groupsToConsider[i].groupDamageTotal > highestGroupDamage)
		{
			highestGroupDamage = groupsToConsider[i].groupDamageTotal;
			groupToReward.damage = groupsToConsider[i].groupDamageTotal;
			groupToReward.group = groupsToConsider[i].group;
		}
	}

	return groupToReward;
}
Example #11
0
// solar: causes caster to hit every mob within dist range of center with
// spell_id.
// NPC spells will only affect other NPCs with compatible faction
void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust)
{
    Mob *curmob;

    float dist = caster->GetAOERange(spell_id);
    float dist2 = dist * dist;
    float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
    float dist_targ = 0;

    bool detrimental = IsDetrimentalSpell(spell_id);
    bool clientcaster = caster->IsClient();
    const int MAX_TARGETS_ALLOWED = 4;
    int targets_hit = 0;
    if(center->IsBeacon())
        targets_hit = center->CastToBeacon()->GetTargetsHit();

    for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
        curmob = it->second;
        // test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized
        if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading())
            continue;
        if (curmob == center)	//do not affect center
            continue;
        if (curmob == caster && !affect_caster)	//watch for caster too
            continue;

        dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition());

        if (dist_targ > dist2)	//make sure they are in range
            continue;
        if (dist_targ < min_range2)	//make sure they are in range
            continue;
        if (!clientcaster && curmob->IsNPC()) {	//check npc->npc casting
            FACTION_VALUE f = curmob->GetReverseFactionCon(caster);
            if (detrimental) {
                //affect mobs that are on our hate list, or
                //which have bad faction with us
                if (!(caster->CheckAggro(curmob) || f == FACTION_THREATENLY || f == FACTION_SCOWLS))
                    continue;
            }
            else {
                //only affect mobs we would assist.
                if (!(f <= FACTION_AMIABLE))
                    continue;
            }
        }
        //finally, make sure they are within range
        if (detrimental) {
            if (!caster->IsAttackAllowed(curmob, true))
            {
                Log.Out(Logs::Detail, Logs::Spells, "Attempting to cast a detrimental AE spell/song on a player.");
                continue;
            }
            if (!zone->SkipLoS() && !spells[spell_id].npc_no_los && curmob != caster && !center->CheckLosFN(curmob))
                continue;
        }
        else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
            // This does not check faction for beneficial AE buffs..only agro and attackable.
            // I've tested for spells that I can find without problem, but a faction-based
            // check may still be needed. Any changes here should also reflect in BardAEPulse() -U
            if (caster->IsAttackAllowed(curmob, true))
            {
                Log.Out(Logs::Detail, Logs::Spells, "Attempting to cast a beneficial AE spell/song on a NPC.");
                caster->Message_StringID(MT_SpellFailure, SPELL_NO_HOLD);
                continue;
            }
            if (caster->CheckAggro(curmob))
                continue;
        }

        curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ);

        //if we get here... cast the spell.
        if (IsTargetableAESpell(spell_id) && detrimental)
        {
            if (targets_hit < MAX_TARGETS_ALLOWED || (clientcaster && curmob == caster))
            {
                caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
                Log.Out(Logs::Detail, Logs::Spells, "AE Rain Spell: %d has hit target #%d: %s", spell_id, targets_hit, curmob->GetCleanName());

                if (clientcaster && curmob != caster) //npcs are not target limited, pc caster does not count towards the limit.
                    ++targets_hit;
            }
        }
        else
        {
            caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust);
        }

    }

    if(center->IsBeacon())
        center->CastToBeacon()->SetTargetsHit(targets_hit);
}