public Unit GetAttackableUnit() { float MaxRange = AIInterface.MAX_AGGRO_RANGE; Unit Target = null; Unit Me = GetUnit(); float Dist; foreach (Unit Enemy in RangedEnemies) { if (Enemy.Realm == GameData.Realms.REALMS_REALM_NEUTRAL) { continue; } if (!CombatInterface.CanAttack(Me, Enemy)) { continue; } Dist = _Owner.GetDistanceTo(Enemy); if (Dist < MaxRange) { MaxRange = Dist; Target = Enemy; } } return(Target); }
public override void Update(long Tick) { if (!CombatInterface.CanAttack(Ab.Caster, Target)) { Stop(); } }
public override void Start(Ability Ab) { if (!CombatInterface.CanAttack(Ab.Caster, Target)) { Stop(); } }
public override IAbilityTypeHandler Cast() { if (!CombatInterface.CanAttack(Ab.Caster, Target)) { return(null); } //Log.Info("DealDamage", "Cast"); uint Damage = Ab.Info.GetHeal(0) / Ab.Info.GetTime(0); CallOnCast(this, Damage); if (Target.ActionPoints >= Damage) { Target.ActionPoints -= (ushort)Damage; Ab.Caster.ActionPoints += (ushort)Damage; } else { Ab.Caster.ActionPoints += Target.ActionPoints; Target.ActionPoints -= 0; } return(null); }
public override void GetTargets(OnTargetFind OnFind) { if (OnFind == null) { return; } if (Ab.Info.GetDamage(0) == 0) { return; } Unit Target; foreach (Object Obj in InvisibleObject._ObjectRanged) { if (!Obj.IsUnit()) { continue; } Target = Obj.GetUnit(); if (!CombatInterface.CanAttack(Ab.Caster, Target)) { continue; } if (Obj.GetDistanceTo(Ab.Px, Ab.Py, Ab.Pz) < Ab.Info.GetRadius(0)) { OnFind(Target); } } }
public override void OnReceiveDamages(Unit Attacker, Ability Spell, ref uint Damages) { if (IsValid) { if (CombatInterface.CanAttack(Ab.Caster, Attacker)) { IsValid = false; Ab.Caster.DealDamages(Attacker, Ab, GetAbilityDamage()); } } }
public override IAbilityTypeHandler Cast() { if (!CombatInterface.CanAttack(Ab.Caster, Target)) { return(null); } //Log.Info("DealDamage", "Cast"); uint Damage = GetAbilityDamage() / Ab.Info.GetTime(0); CallOnCast(this, Damage); Ab.Caster.DealDamages(Target, Ab, Damage); return(null); }
public override GameData.AbilityResult CanCast(bool IsStart) { GameData.AbilityResult Result = GameData.AbilityResult.ABILITYRESULT_OK; if (Target == null) { Result = GameData.AbilityResult.ABILITYRESULT_ILLEGALTARGET; } else if (Target.IsDead) { Result = GameData.AbilityResult.ABILITYRESULT_ILLEGALTARGET_DEAD; } else if (!CombatInterface.CanAttack(Ab.Caster.GetUnit(), Target)) { Result = GameData.AbilityResult.ABILITYRESULT_ILLEGALTARGET_NOT_PVP_FLAGGED; } else if (!CombatInterface.IsEnemy(Ab.Caster.GetUnit(), Target)) { Result = GameData.AbilityResult.ABILITYRESULT_ILLEGALTARGET_IN_YOUR_ALLIANCE; } else if (IsStart) { float Distance = Ab.Caster.GetDistanceTo(Target); if (Distance > Ab.Info.Info.MaxRange) { Result = GameData.AbilityResult.ABILITYRESULT_OUTOFRANGE; } else if (Distance < Ab.Info.Info.MinRange) { Result = GameData.AbilityResult.ABILITYRESULT_TOOCLOSE; } else if (Ab.Info.Info.MaxRange <= 5 && !Ab.Caster.IsObjectInFront(Target, 110)) { Result = GameData.AbilityResult.ABILITYRESULT_OUT_OF_ARC; } } else { CalcualteStat(); // get Offensive/Defensive stat //Result = CheckBlock(); // check for parry, evade or disrupt. } return(Result); }
public override void Update(long tick) { if (tick <= _rezTime) { return; } _slayerChoppa.RezUnit(_slayerChoppa.Realm == Realms.REALMS_REALM_ORDER ? (ushort)1489 : (ushort)1795, 25, true); AbilityDamageInfo damageThisPass = AbilityMgr.GetExtraDamageFor(_slayerChoppa.Realm == Realms.REALMS_REALM_ORDER ? (ushort)1489 : (ushort)1795, 0, 0); List <Object> objects; lock (_slayerChoppa.PlayersInRange) objects = new List <Object>(_slayerChoppa.ObjectsInRange); int count = 0; foreach (Object obj in objects) { Unit unit = obj as Unit; if (unit == null || unit == _slayerChoppa) { continue; } if (unit.ObjectWithinRadiusFeet(_slayerChoppa, 40) && CombatInterface.CanAttack(_slayerChoppa, unit) && _slayerChoppa.LOSHit(unit)) { CombatManager.InflictDamage(damageThisPass.Clone(), _slayerChoppa.AbtInterface.GetMasteryLevelFor(3), _slayerChoppa, unit); } ++count; if (count == 9) { break; } } Dispose(); }
public override void GetTargets(OnTargetFind OnFind) { Unit Target; foreach (Object Obj in Ab.Caster._ObjectRanged) { if (!Obj.IsUnit()) { continue; } Target = Obj.GetUnit(); if (!CombatInterface.CanAttack(Ab.Caster, Target)) { continue; } if (Obj.GetDistanceTo(Ab.Px, Ab.Py, Ab.Pz) < Ab.Info.GetRadius(0) && Ab.Caster.IsObjectInFront(Target, 90)) { OnFind(Target); } } }
/*private bool IsNeutralFaction(Creature c) * { * if (c.Spawn.Faction == 0 || (((c.Spawn.Faction >> 8 & 0x1))) == 0) return true; * else return false; * }*/ public Unit GetAttackableUnit() { Unit unitOwner = GetUnit(); float maxRange = MaxAggroRange + unitOwner.Level / 1.5f; Unit target = null; lock (RangedEnemies) foreach (Unit enemy in RangedEnemies) { Player player = enemy as Player; if (player != null && player.StealthLevel > 0 && unitOwner.Level <= player.EffectiveLevel + 2) { continue; } if (!CombatInterface.CanAttack(unitOwner, enemy)) { continue; } float dist = _Owner.GetDistanceToObject(enemy, true); if (dist > maxRange) { continue; } if (unitOwner != null) { if (unitOwner is KeepNpcCreature.KeepCreature) { KeepNpcCreature.KeepCreature npc = unitOwner as KeepNpcCreature.KeepCreature; //Keep NPCs have additional hardening. If their target goes outside the keep, instantly reset. if (enemy.Z - npc.SpawnPoint.Z > 120 || npc.SpawnPoint.Z - enemy.Z > 30 || !enemy.PointWithinRadiusFeet(npc.WorldSpawnPoint, 200) || !npc.PointWithinRadiusFeet(npc.WorldSpawnPoint, 200)) { continue; } if (!enemy.LOSHit(npc)) { continue; } } else if (unitOwner is Creature) { Creature creature = unitOwner as Creature; if (creature is Pet) { Pet pet = creature as Pet; if (pet == null || pet.Owner == null) { continue; } //Only aggro if we have LOS to the owner. if (!enemy.LOSHit(pet.Owner)) { continue; } } else { //Standard NPC checks. if (!creature.PointWithinRadiusFeet(creature.WorldSpawnPoint, 200)) { continue; } if (!enemy.LOSHit(creature)) { continue; } } } else { } } maxRange = dist; target = enemy; } return(target); }
public void Fire(Player player, ushort targetID, ushort targetX, ushort targetY, ushort targetZ, ushort zoneId, ushort power) { if (!HasPlayer(player) || !_weapon.AbtInterface.CanCastCooldown(_abilityId)) { return; } // RB 6/25/2016 Reset timer before death every time the siege is fired _deathTime = TCPManager.GetTimeStampMS() + 300 * 1000; switch (Type) { case SiegeType.GTAOE: Point3D targetPos = ZoneService.GetWorldPosition(_weapon.Zone.Info, targetX, targetY, targetZ); if (!ArcHit(zoneId, new Point3D(targetX, targetY, targetZ), targetPos)) { player.SendClientMessage("Can't hit that position from here", ChatLogFilters.CHATLOGFILTERS_C_ABILITY_ERROR); return; } Siege artillery = _weapon as Siege; if (artillery != null && !artillery.CanFire(player)) { return; } _weapon.AbtInterface.StartCastAtPos(player, _abilityId, ZoneService.GetWorldPosition(_weapon.Zone.Info, targetX, targetY, targetZ), _weapon.Zone.ZoneId, 0); break; case SiegeType.OIL: _weapon.AbtInterface.StartCastAtPos(player, _abilityId, ZoneService.GetWorldPosition(_weapon.Zone.Info, targetX, targetY, targetZ), _weapon.Zone.ZoneId, 0); break; case SiegeType.SNIPER: Unit target = _weapon.Region.GetObject(targetID) as Unit; if (target == null || !CombatInterface.CanAttack(player, target)) { return; } Siege cannon = _weapon as Siege; if (cannon != null && !cannon.CanFire(player)) { return; } _weapon.CbtInterface.SetTarget(targetID, TargetTypes.TARGETTYPES_TARGET_ENEMY); _weapon.AbtInterface.StartCast(player, _abilityId, 0, 0, Math.Max((byte)1, (byte)(_weapon.Level * power * 0.01f))); break; case SiegeType.RAM: Unit ramTarget = null; foreach (Object obj in _Owner.ObjectsInRange) { KeepDoor.KeepGameObject door = obj as KeepDoor.KeepGameObject; if (door == null) { continue; } if (!CombatInterface.CanAttack(player, door)) { continue; } if (!_Owner.IsObjectInFront(door, 90) || !door.IsWithinRadiusFeet(_Owner, 20)) { continue; } ramTarget = door; break; } //Unit target = _weapon.Region.GetObject(targetID) as Unit; if (ramTarget != null) { _weapon.CbtInterface.SetTarget(ramTarget.Oid, TargetTypes.TARGETTYPES_TARGET_ENEMY); _weapon.AbtInterface.StartCast(player, _abilityId, 0, 0, Math.Max((byte)1, (byte)(_weapon.Level * power * 0.01f))); } else { foreach (var plrInfo in Players) { plrInfo.Key.SendClientMessage("No target", ChatLogFilters.CHATLOGFILTERS_C_ABILITY_ERROR); } } break; } SendSiegeCooldown(); // Disable Firing? /* * Out = new PacketOut((byte)Opcodes.F_UPDATE_STATE); * Out.WriteUInt16(_Owner.Oid); * Out.WriteByte(0x1C); * Out.WriteByte(2); * Out.Fill(0, 6); * player.SendPacket(Out); */ SendSiegeUserUpdate(); /* * Out = new PacketOut((byte)Opcodes.F_UPDATE_STATE); * Out.WriteUInt16(_Owner.Oid); * Out.WriteByte(0x1E); * Out.WriteUInt16(0); * Out.WriteByte((byte)_Owner.Name.Length); * Out.WriteUInt16(0); * Out.WriteCString(_Owner.Name); * Out.WriteByte(0); * player.SendPacket(Out); */ SendSiegeIdleTimer(player); }
/// <summary> /// This method assigns aggro from heals and selects new target, based on current max hate /// </summary> private void ProcessAggro() { if (!_unit.IsPet()) { ulong maxHatred = 0; int nextTargetOid = 0; Unit nextTarget = null; foreach (Player player in _unit.PlayersInRange.ToList()) { if (player != null && CombatInterface.CanAttack(_unit, player)) { if (player.IsDead) { Aggros[player.Oid].Hatred = 0; } else { if (player.CbtInterface.IsInCombat) { foreach (KeyValuePair <ushort, AggroInfo> healAggro in player.HealAggros) { foreach (KeyValuePair <ushort, AggroInfo> aggro in Aggros) { if (!(_unit is Pet) && healAggro.Key == aggro.Key && _combatStart < healAggro.Value.HealingReceivedTime && aggro.Value.HealingReceivedTime != healAggro.Value.HealingReceivedTime) { aggro.Value.Hatred += (ulong)((healAggro.Value.HealingReceived) * GetDetaunt(healAggro.Key)); healAggro.Value.HealingReceivedTime = aggro.Value.HealingReceivedTime; } } } } } } } foreach (Object obj in _unit.ObjectsInRange.ToList()) { Unit u = obj as Unit; if (u != null && (!u.IsDead && !u.PendingDisposal && !u.IsDisposed) && CombatInterface.CanAttack(_unit, u)) { foreach (KeyValuePair <ushort, AggroInfo> aggro in Aggros) { if (aggro.Key == obj.Oid) { if (aggro.Value.Hatred > maxHatred) { maxHatred = aggro.Value.Hatred; nextTargetOid = obj.Oid; nextTarget = u; } } } } } if (nextTarget != null && _pet == null) { AddHatred(nextTarget, nextTarget.IsPlayer(), 0); } } }
/// <summary> /// Identifies target of an ability before it is casted and checks its validity (pvp flag, visibility...). /// </summary> /// <param name="abInfo">Ability that is about to be casted</param> /// <param name="instigator">Instigator of the ability</param> /// <param name="foeVisible">True if current targeted foe is visible</param> /// <param name="allyVisible">True if current targeted ally is visible</param> /// <returns>True if target is valid for the ability</returns> private bool GetTarget(AbilityInfo abInfo, Unit instigator, bool foeVisible, bool allyVisible) { if (_pendingInfo.Range == 0 || _pendingInfo.CommandInfo == null) { _pendingInfo.Target = _caster; return(true); } if (_pendingInfo.TargetType == CommandTargetTypes.SiegeCannon) { _pendingInfo.Target = ((Creature)_caster).SiegeInterface.BuildTargetList(instigator); return(true); } CommandTargetTypes selectType = (CommandTargetTypes)((int)_pendingInfo.TargetType & 7); switch (selectType) { case CommandTargetTypes.Caster: _pendingInfo.Target = _caster; break; case CommandTargetTypes.Ally: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY); if (_pendingInfo.Target == _caster || !CombatInterface.IsFriend(_caster, _pendingInfo.Target) || (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } break; case CommandTargetTypes.AllyOrSelf: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY) ?? _caster; if (!CombatInterface.IsFriend(_caster, _pendingInfo.Target) || (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.Target != _caster) { if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } } break; case CommandTargetTypes.AllyOrCareerTarget: if (!allyVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ALLY); if (!CombatInterface.IsFriend(_caster, _pendingInfo.Target) || _pendingInfo.Target != null && (_pendingInfo.Target is Creature && !(_pendingInfo.Target is Pet))) { return(false); } if (_pendingInfo.Target != null && _pendingInfo.Target != _caster) { if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates)) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } } else { Player petCareerPlr = null; if (_caster is Player) { petCareerPlr = _caster as Player; } if (petCareerPlr != null) { _pendingInfo.Target = petCareerPlr.CrrInterface.GetTargetOfInterest(); } if (_pendingInfo.Target == null || _pendingInfo.Target == _caster) { _pendingInfo.Target = null; return(false); } } break; case CommandTargetTypes.Enemy: if (!foeVisible) { return(false); } _pendingInfo.Target = _caster.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY); if (!CombatInterface.CanAttack(_caster, _pendingInfo.Target)) { _pendingInfo.Target = null; } else { if (!_caster.CbtInterface.IsPvp) { Player plrCaster = _caster as Player; if (plrCaster != null && _pendingInfo.Target.CbtInterface.IsPvp) { ((CombatInterface_Player)plrCaster.CbtInterface).EnablePvp(); } } } Player plrTarget = _pendingInfo.Target as Player; if (plrTarget != null && plrTarget.Palisade != null && (plrTarget.Palisade.IsObjectInFront(_caster, 180) ^ plrTarget.Palisade.IsObjectInFront(plrTarget, 180))) { _pendingInfo.Target = plrTarget.Palisade; } //8410 - Terrible Embrace ; 9057 - Wings of Heaven ; 9178 - Fetch! ; 9186 - Pounce if (_pendingInfo.Target != null && (abInfo.Entry == 8410 || abInfo.Entry == 9057 || abInfo.Entry == 9178 || abInfo.Entry == 9186) && Math.Abs(_caster.Z - _pendingInfo.Target.Z) > 300) { _caster.AbtInterface.SetCooldown(abInfo.Entry, -1); return(false); } break; case CommandTargetTypes.CareerTarget: // Target of Interest (oath friend/dark protector/pet if player, master if pet) var player = _caster as Player; if (player != null) { _pendingInfo.Target = player.CrrInterface.GetTargetOfInterest(); } else { var pet = _caster as Pet; if (pet != null) { _pendingInfo.Target = pet.Owner; } else { Log.Error("NewAbility", "Ability " + _pendingInfo.Entry + " with targettype 5 has no target!"); _pendingInfo.Target = null; } } break; default: Log.Error("NewAbility", "Ability " + _pendingInfo.Entry + " with TargetType zero in 3 LSBs!"); _pendingInfo.Target = _caster; break; } if (_pendingInfo.TargetType.HasFlag(CommandTargetTypes.Groupmates) && _pendingInfo.Target != _caster) { Group myGroup = ((Player)_caster).PriorityGroup; if (myGroup == null || !myGroup.HasMember(_pendingInfo.Target)) { return(false); } } return(_pendingInfo.Target != null); }
private void PropagateFoe() { int addedThisTick = 0; if (_otherPendingTargetList.Count > 0) { lock (_otherPendingTargetList) { foreach (NewBuff buff in _otherPendingTargetList) { _otherTargetList.Add(buff.Target, new AuraInfo(buff, _passNum)); } _otherPendingTargetList.Clear(); } } foreach (Object obj in Target.ObjectsInRange) { Unit foe = obj as Unit; if (foe == null || foe.IsInvulnerable) { continue; } if (!Target.IsDead && foe.ObjectWithinRadiusFeet(Target, MaxFoeRadius - 10) && CombatInterface.CanAttack(Caster, foe) && ((Caster is Creature) || (!(foe is Player) || foe.CbtInterface.IsPvp)) && Target.LOSHit(foe)) { if (_otherTargetList.ContainsKey(foe)) { if (_otherTargetList[foe].Buff.BuffHasExpired) { _otherTargetList.Remove(foe); } else { _otherTargetList[foe].PassNum = _passNum; } continue; } if (addedThisTick + _otherTargetList.Count == 9) { continue; } if (Duration == 0) { foe.BuffInterface.QueueBuff(new BuffQueueInfo(Caster, BuffLevel, AbilityMgr.GetBuffInfo(_buffInfo.Entry, Caster, foe), RegisterOtherBuff)); } else { BuffInfo BI = AbilityMgr.GetBuffInfo(_buffInfo.Entry, Caster, foe); BI.IsAoE = true; BI.Duration = Math.Max((ushort)1, (ushort)(RemainingTimeMs * 0.001f)); foe.BuffInterface.QueueBuff(new BuffQueueInfo(Caster, BuffLevel, BI, RegisterOtherBuff)); } ++addedThisTick; } else { if (!_otherTargetList.ContainsKey(foe)) { continue; } // Group member out of range - finish the buff and remove them if (!_otherTargetList[foe].Buff.BuffHasExpired) { _otherTargetList[foe].Buff.BuffHasExpired = true; } _otherTargetList.Remove(foe); } } List <Unit> oldUnits = _otherTargetList.Keys.ToList(); // Remove any units not refreshed on this tick foreach (Unit oldfoe in oldUnits) { if (_otherTargetList[oldfoe].PassNum == _passNum) { continue; } _otherTargetList[oldfoe].Buff.BuffHasExpired = true; _otherTargetList.Remove(oldfoe); } }
public static void F_COMMAND_CONTROLLED(BaseClient client, PacketIn packet) { GameClient cclient = (GameClient)client; if (cclient.Plr?.CrrInterface == null) { return; } IPetCareerInterface petInterface = cclient.Plr.CrrInterface as IPetCareerInterface; Pet myPet = petInterface?.myPet; if (myPet == null) { return; } ushort abilityid = packet.GetUint16(); PetCommand command = (PetCommand)packet.GetUint8(); switch (command) { case PetCommand.Stay: if (cclient.Plr.IsMounted) { return; } myPet.MvtInterface.StopMove(); myPet.FollowMode = 1; myPet.IsHeeling = false; myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Holding position by request."); myPet.SendPetUpdate(); break; // stay case PetCommand.Follow: if (cclient.Plr.IsMounted) { return; } myPet.AiInterface.ProcessCombatEnd(); if (myPet.StsInterface.Speed == 0) { break; } myPet.MvtInterface.ScaleSpeed(myPet.SpeedMult); myPet.MvtInterface.Recall(cclient.Plr); myPet.FollowMode = 2; myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Heeling by request."); myPet.SendPetUpdate(); break; // heel case PetCommand.Passive: myPet.AiInterface.SetBrain(new PassiveBrain(myPet)); petInterface.AIMode = 3; myPet.AIMode = 3; myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Passive state."); break; // mode Passive case PetCommand.Defensive: myPet.AiInterface.SetBrain(new GuardBrain(myPet)); petInterface.AIMode = 4; myPet.AIMode = 4; myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Defensive state."); break; // mode Defensive case PetCommand.Aggressive: myPet.AiInterface.SetBrain(new AggressiveBrain(myPet)); petInterface.AIMode = 5; myPet.AIMode = 5; myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Aggressive state."); break; // mode Aggressive case PetCommand.Attack: long now = TCPManager.GetTimeStampMS(); if (cclient.Plr.IsMounted || now <= myPet.AttackReuseTimer + COMMAND_ATTACK_REUSE) { return; } myPet.AttackReuseTimer = now; Unit target = cclient.Plr.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY); if (target == null || !CombatInterface.CanAttack(myPet, target)) { return; } if (!cclient.Plr.LOSHit(target)) { return; } myPet.AiInterface.Debugger?.SendClientMessage("[MR]: Attacking by request."); myPet.IsHeeling = false; myPet.FollowMode = 0; myPet.Owner.CbtInterface.RefreshCombatTimer(); myPet.AiInterface.ProcessCombatStart(target); myPet.SendPetUpdate(); break; //attack case PetCommand.Release: myPet.Destroy(); break; case PetCommand.AbilityCast: if (cclient.Plr.IsMounted) { return; } foreach (NPCAbility pa in myPet.AbtInterface.NPCAbilities) { if (pa.Entry == abilityid) { if (pa.Range > 0) { Unit abTarget = myPet.CbtInterface.GetCurrentTarget(); if (abTarget == null || !myPet.LOSHit(abTarget)) { return; } } myPet.AbtInterface.StartCast(myPet, abilityid, 1); break; } } break; case PetCommand.Autocast: if (cclient.Plr.IsMounted) { return; } foreach (NPCAbility pa in myPet.AbtInterface.NPCAbilities) { if (pa.Entry != abilityid) { continue; } pa.AutoUse = !pa.AutoUse; myPet.SendPetUpdate(); break; } break; } }
/// <summary> /// Builds a list of targets which would be hit by a line attack performed by a siege cannon. /// </summary> /// <param name="instigator">The player firing the cannon.</param> /// <returns>The farthest target from the siege weapon which would be struck by the attack, for use as the target of the ability.</returns> public Unit BuildTargetList(Unit instigator) { CurrentTargetList.Clear(); Unit initialTarget = _weapon.CbtInterface.GetTarget(TargetTypes.TARGETTYPES_TARGET_ENEMY); Unit bestTarget = initialTarget; int bestDist = _weapon.GetDistanceToObject(initialTarget); CurrentTargetList.Add(initialTarget); Vector3 unitDir = new Vector3(initialTarget.WorldPosition.X - _weapon.WorldPosition.X, initialTarget.WorldPosition.Y - _weapon.WorldPosition.Y, initialTarget.WorldPosition.Z - _weapon.WorldPosition.Z); unitDir.Normalize(); Vector3 toTarget = new Vector3(); Vector3 projection = new Vector3(); foreach (Object obj in _weapon.ObjectsInRange) { Unit unit = obj as Unit; if (unit == null || unit == initialTarget || unit.Realm == instigator.Realm || !_weapon.IsObjectInFront(unit, 45) || !CombatInterface.CanAttack(instigator, unit)) { continue; } // Determine whether this unit is within 5ft on either side of the cannon's attack. // Unit vector in direction of cannon's view projection.X = unitDir.X; projection.Y = unitDir.Y; projection.Z = unitDir.Z; toTarget.X = unit.WorldPosition.X - _weapon.WorldPosition.X; toTarget.Y = unit.WorldPosition.Y - _weapon.WorldPosition.Y; toTarget.Z = unit.WorldPosition.Z - _weapon.WorldPosition.Z; // Vector projection ((a dot ^b) ^b) projection.Multiply(Vector3.DotProduct3D(toTarget, unitDir)); // Vector rejection (a - (a dot ^b) ^b) toTarget.X -= projection.X; toTarget.Y -= projection.Y; toTarget.Z -= projection.Z; if (toTarget.MagnitudeSquare < 60 * 60 && _weapon.LOSHit(unit)) // 5ft either side { CurrentTargetList.Add(unit); // Select the target furthest away as the target of the ability, for the projectile effect to look best if (!_weapon.IsWithinRadiusFeet(unit, bestDist)) { bestTarget = unit; bestDist = _weapon.GetDistanceToObject(bestTarget); } } } return(bestTarget); }