/// <summary> /// Lets this Pet cast the given spell /// </summary> public void CastPetSpell(SpellId spellId, WorldObject target) { var spell = NPCSpells.GetReadySpell(spellId); SpellFailedReason err; if (spell != null) { if (spell.HasTargets) { Target = m_master.Target; } err = spell.CheckCasterConstraints(this); if (err == SpellFailedReason.Ok) { err = SpellCast.Start(spell, false, target != null ? new[] { target } : null); } } else { err = SpellFailedReason.NotReady; } if (err != SpellFailedReason.Ok && m_master is IPacketReceiver) { PetHandler.SendCastFailed((IPacketReceiver)m_master, spellId, err); } }
private static void ApplyEventNPCData(WorldEvent worldEvent) { foreach (var eventNpcData in worldEvent.ModelEquips) { var spawnEntry = NPCMgr.GetSpawnEntry(eventNpcData.Guid); if (spawnEntry == null) { Log.Warn("Invalid Spawn Entry in World Event NPC Data, Entry: {0}", eventNpcData.Guid); continue; } if (eventNpcData.EntryId != 0) { eventNpcData.OriginalEntryId = spawnEntry.EntryId; spawnEntry.EntryId = eventNpcData.EntryId; spawnEntry.Entry = NPCMgr.GetEntry(spawnEntry.EntryId); if (spawnEntry.Entry == null) { Log.Warn("{0} had an invalid World Event EntryId.", spawnEntry); spawnEntry.EntryId = eventNpcData.OriginalEntryId; spawnEntry.Entry = NPCMgr.GetEntry(spawnEntry.EntryId); } } if (eventNpcData.ModelId != 0) { spawnEntry.DisplayIdOverride = eventNpcData.ModelId; } if (eventNpcData.EquipmentId != 0) { eventNpcData.OriginalEquipmentId = spawnEntry.EquipmentId; spawnEntry.EquipmentId = eventNpcData.EquipmentId; spawnEntry.Equipment = NPCMgr.GetEquipment(spawnEntry.EquipmentId); } foreach (var point in spawnEntry.SpawnPoints.ToArray().Where(point => point.IsActive)) { point.Respawn(); if (eventNpcData.SpellIdToCastAtStart == 0) { continue; } Spell spell = SpellHandler.Get(eventNpcData.SpellIdToCastAtStart); if (spell == null) { continue; } SpellCast cast = point.ActiveSpawnling.SpellCast; cast.Start(spell); } } }
private void InitImmovable() { m_Movement.MayMove = false; // if immovables have a single AreaAura, better cast it if (HasSpells && Spells.Count == 1) { var spell = Spells.First(); if (spell.IsAreaAura) { AddMessage(() => SpellCast.Start(spell, true)); } } }
protected internal override void Apply() { if (spell == null) { var channel = m_aura.Controller as SpellChannel; if (channel != null) { origCast = channel.Cast; } else { origCast = m_aura.Auras.Owner.SpellCast; } if (origCast == null) { return; //throw new Exception("Cannot apply a Periodic Trigger Spell Aura on anyone but the Caster"); } spell = m_spellEffect.TriggerSpell; if (spell == null) { LogManager.GetCurrentClassLogger().Warn("Found invalid periodic TriggerSpell in Spell {0} ({1}) ", m_spellEffect.Spell, (uint)m_spellEffect.TriggerSpellId); return; } } cast = SpellCast.ObtainPooledCast(origCast.Caster); cast.TargetLoc = origCast.TargetLoc; cast.Selected = origCast.Selected; //cast.Start(spell, m_spellEffect, true); cast.Start(spell, true); }
/// <summary> /// Tries to land a mainhand hit + maybe offhand hit on the current Target /// </summary> protected virtual void CombatTick(int timeElapsed) { // if currently casting a spell, skip this if (IsUsingSpell && !m_spellCast.IsPending) { m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); return; } if (!CheckCombatState()) { if (m_isInCombat) { // if still in combat - check soon again m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); } return; } if (!CanDoHarm || !CanMelee) { m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); return; } var target = m_target; if (target == null || target.IsDead) { IsFighting = false; if (this is NPC) { Movement.MayMove = true; } return; } var now = Environment.TickCount; var isRanged = IsUsingRangedWeapon; var mainHandDelay = m_lastStrike + (isRanged ? RangedAttackTime : MainHandAttackTime) - now; var strikeReady = mainHandDelay <= 0; // try to strike if (strikeReady) { if (this is NPC) { Movement.MayMove = true; } var distanceSq = GetDistanceSq(target); var mainWeapon = isRanged ? m_RangedWeapon : m_mainWeapon; if (mainWeapon != null) { if (IsInAttackRangeSq(mainWeapon, target, distanceSq)) { // close enough if (m_AutorepeatSpell != null) { // Auto-shot (only when not running) if (!IsMoving) { SpellCast.TargetFlags = SpellTargetFlags.Unit; SpellCast.SelectedTarget = target; SpellCast.Start(m_AutorepeatSpell, false); m_lastStrike = now; mainHandDelay += RangedAttackTime; } } else { var chr = this as Character; if (chr != null) { chr.IsMoving = false; } Strike(mainWeapon); m_lastStrike = now; mainHandDelay += MainHandAttackTime; if (this is NPC) { Movement.MayMove = false; } } } else { // too far away if (UsesPendingAbility(mainWeapon)) { // ability is pending -> Need to cancel m_spellCast.Cancel(SpellFailedReason.OutOfRange); } // no pending ability if (this is Character) { CombatHandler.SendAttackSwingNotInRange(this as Character); } else if (this is NPC) { Brain.OnCombatTargetOutOfRange(); } } } } m_attackTimer.Start(mainHandDelay <= 0 ? 1000 : mainHandDelay); }
/// <summary> /// Tries to land a mainhand hit + maybe offhand hit on the current Target /// </summary> protected virtual void CombatTick(int timeElapsed) { // if currently casting a spell, skip this if (IsUsingSpell && !m_spellCast.IsPending) { m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); return; } if (!CheckCombatState()) { if (m_isInCombat) { // if still in combat - check soon again m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); } return; } if (!CanDoHarm || !CanMelee) { m_attackTimer.Start(DamageAction.DefaultCombatTickDelay); return; } var target = m_target; var now = Environment.TickCount; var usesOffHand = UsesDualWield; var isRanged = IsUsingRangedWeapon; var mainHandDelay = m_lastStrike + (isRanged ? RangedAttackTime : MainHandAttackTime) - now; int offhandDelay; var strikeReady = mainHandDelay <= 0; bool offHandReady; if (usesOffHand) { offhandDelay = m_lastOffhandStrike + OffHandAttackTime - now; offHandReady = true; } else { offhandDelay = int.MaxValue; offHandReady = false; } // try to strike if (strikeReady || offHandReady) { if (this is Character && !target.IsInFrontOf(this)) { CombatHandler.SendAttackSwingBadFacing(this as Character); } else { var distanceSq = GetDistanceSq(target); if (strikeReady) { var mainWeapon = isRanged ? m_RangedWeapon : m_mainWeapon; if (mainWeapon != null) { if (IsInAttackRangeSq(mainWeapon, target, distanceSq)) { // close enough if (m_AutorepeatSpell != null) { // Auto-shot (only when not running) if (!IsMoving) { SpellCast.TargetFlags = SpellTargetFlags.Unit; SpellCast.SelectedTarget = target; SpellCast.Start(m_AutorepeatSpell, false); m_lastStrike = now; mainHandDelay += RangedAttackTime; } } else { Strike(mainWeapon); m_lastStrike = now; mainHandDelay += MainHandAttackTime; } } else { // too far away if (UsesPendingAbility(mainWeapon)) { // ability is pending -> Need to cancel m_spellCast.Cancel(SpellFailedReason.OutOfRange); } // no pending ability if (this is Character) { CombatHandler.SendAttackSwingNotInRange(this as Character); } else if (this is NPC) { Brain.OnCombatTargetOutOfRange(); } } } } if (offHandReady) { if (IsInAttackRangeSq(m_offhandWeapon, target, distanceSq)) { // in range for a strike Strike(m_offhandWeapon); m_lastOffhandStrike = now; offhandDelay += OffHandAttackTime; } else { // too far away if (UsesPendingAbility(m_offhandWeapon)) { // ability is pending -> Need to cancel m_spellCast.Cancel(SpellFailedReason.OutOfRange); } } } } } // determine the next strike int delay; strikeReady = mainHandDelay <= 0; offHandReady = usesOffHand && offhandDelay <= 0; if (strikeReady) { // mainhand is ready but not in reach if (offHandReady || !usesOffHand) { // mainhand is ready and offhand is either also ready or not present delay = DamageAction.DefaultCombatTickDelay; } else { // mainhand is ready and offhand is still waiting delay = Math.Min(DamageAction.DefaultCombatTickDelay, offhandDelay); } } else { // mainhand is not ready if (offHandReady) { // mainhand is not ready but offhand is ready delay = Math.Min(DamageAction.DefaultCombatTickDelay, mainHandDelay); } else { if (usesOffHand) { // mainhand and offhand are both not ready delay = Math.Min(offhandDelay, mainHandDelay); } else { // mainhand is not ready and there is no offhand delay = mainHandDelay; } } } m_attackTimer.Start(delay); }
/// <summary> /// Is called after Character has been added to a map the first time and /// before it receives the first Update packet /// </summary> internal protected void InitializeCharacter() { World.AddCharacter(this); m_initialized = true; try { Regenerates = true; ((PlayerSpellCollection)m_spells).PlayerInitialize(); OnLogin(); if (m_record.JustCreated) { if (!m_client.Account.Role.IsStaff) { CharacterHandler.SendCinematic(this); } if (m_zone != null) { m_zone.EnterZone(this, null); } m_spells.AddDefaultSpells(); m_reputations.Initialize(); if (Class == ClassId.Warrior && Spells.Contains(SpellId.ClassSkillBattleStance)) { CallDelayed(1000, obj => SpellCast.Start(SpellId.ClassSkillBattleStance, false)); } else if (Class == ClassId.DeathKnight && Spells.Contains(SpellId.ClassSkillBloodPresence)) { CallDelayed(1000, obj => SpellCast.Start(SpellId.ClassSkillBloodPresence, false)); } // set initial weapon skill max values Skills.UpdateSkillsForLevel(Level); } else { LoadDeathState(); LoadEquipmentState(); } // load items #if DEV // do this check in case that we did not load Items yet if (ItemMgr.Loaded) #endif InitItems(); // load ticket information var ticket = TicketMgr.Instance.GetTicket(EntityId.Low); if (ticket != null) { Ticket = ticket; Ticket.OnOwnerLogin(this); } // initialize sub systems GroupMgr.Instance.OnCharacterLogin(this); GuildMgr.Instance.OnCharacterLogin(this); RelationMgr.Instance.OnCharacterLogin(this); // set login date LastLogin = DateTime.Now; var isNew = m_record.JustCreated; // perform some stuff ingame AddMessage(() => { if (LastLogout == null) { RealmCommandHandler.ExecFirstLoginFileFor(this); } RealmCommandHandler.ExecAllCharsFileFor(this); if (Account.Role.IsStaff) { RealmCommandHandler.ExecFileFor(this); } Stunned--; if (m_record.NextTaxiVertexId != 0) { // we are on a Taxi var vertex = TaxiMgr.GetVertex(m_record.NextTaxiVertexId); if (vertex != null && vertex.MapId == m_Map.Id && vertex.ListEntry.Next != null && IsInRadius(vertex.Pos, vertex.ListEntry.Next.Value.DistFromPrevious)) { TaxiPaths.Enqueue(vertex.Path); TaxiMgr.FlyUnit(this, true, vertex.ListEntry); } else { m_record.NextTaxiVertexId = 0; } } else { // cannot stand up instantly because else no one will see the char sitting in the first place StandState = StandState.Stand; } GodMode = m_record.GodMode; if (isNew) { // newly created Char logs in the first time var evt = Created; if (evt != null) { evt(this); } } //if (Role.IsStaff) if (GodMode) { //Notify("Your GodMode is " + (GodMode ? "ON" : "OFF") + "!"); Notify(RealmLangKey.GodModeIsActivated); } var login = LoggedIn; if (login != null) { login(this, true); } }); if (isNew) { SaveLater(); m_record.JustCreated = false; } else { RealmServer.IOQueue.AddMessage(() => { try { m_record.Update(); } catch (Exception ex) { SaveLater(); LogUtil.ErrorException(ex, "Failed to Update CharacterRecord: " + m_record); } }); } } catch (Exception e) { if (m_record.JustCreated) { m_record.CanSave = false; m_record.Delete(); } World.RemoveCharacter(this); LogUtil.ErrorException(e, "Failed to initialize Character: " + this); m_client.Disconnect(); } }