示例#1
0
        public override void OnCollideObject(WorldObject target)
        {
            //Console.WriteLine($"{Name}.OnCollideObject({target.Name})");

            var player = ProjectileSource as Player;

            if (Info != null && player != null && player.DebugSpell)
            {
                player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{Name}.OnCollideObject({target?.Name} ({target?.Guid}))", ChatMessageType.Broadcast));
                player.Session.Network.EnqueueSend(new GameMessageSystemChat(Info.ToString(), ChatMessageType.Broadcast));
            }

            ProjectileImpact();

            // ensure valid creature target
            var creatureTarget = target as Creature;

            if (creatureTarget == null || target == ProjectileSource)
            {
                return;
            }

            if (player != null)
            {
                player.LastHitSpellProjectile = Spell;
            }

            // ensure caster can damage target
            var sourceCreature = ProjectileSource as Creature;

            if (sourceCreature != null && !sourceCreature.CanDamage(creatureTarget))
            {
                return;
            }

            // if player target, ensure matching PK status
            var targetPlayer = creatureTarget as Player;

            var pkError = ProjectileSource?.CheckPKStatusVsTarget(creatureTarget, Spell);

            if (pkError != null)
            {
                if (player != null)
                {
                    player.Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(player.Session, pkError[0], creatureTarget.Name));
                }

                if (targetPlayer != null)
                {
                    targetPlayer.Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(targetPlayer.Session, pkError[1], ProjectileSource.Name));
                }

                return;
            }

            var critical     = false;
            var critDefended = false;
            var overpower    = false;

            var damage = CalculateDamage(ProjectileSource, Caster, creatureTarget, ref critical, ref critDefended, ref overpower);

            if (damage != null)
            {
                // handle void magic DoTs:
                // instead of instant damage, add DoT to target's enchantment registry
                if (Spell.School == MagicSchool.VoidMagic && Spell.Duration > 0)
                {
                    var dot = ProjectileSource.CreateEnchantment(creatureTarget, ProjectileSource, Spell);
                    if (dot.Message != null && player != null)
                    {
                        player.Session.Network.EnqueueSend(dot.Message);
                    }

                    // corruption / corrosion playscript?
                    //target.EnqueueBroadcast(new GameMessageScript(target.Guid, PlayScript.HealthDownVoid));
                    //target.EnqueueBroadcast(new GameMessageScript(target.Guid, PlayScript.DirtyFightingDefenseDebuff));
                }
                else
                {
                    DamageTarget(creatureTarget, damage.Value, critical, critDefended, overpower);
                }

                if (player != null)
                {
                    Proficiency.OnSuccessUse(player, player.GetCreatureSkill(Spell.School), Spell.PowerMod);
                }

                // handle target procs
                // note that for untargeted multi-projectile spells,
                // ProjectileTarget will be null here, so procs will not apply
                if (sourceCreature != null && ProjectileTarget != null)
                {
                    // TODO figure out why cross-landblock group operations are happening here. We shouldn't need this code Mag-nus 2021-02-09
                    bool threadSafe = true;

                    if (LandblockManager.CurrentlyTickingLandblockGroupsMultiThreaded)
                    {
                        // Ok... if we got here, we're likely in the parallel landblock physics processing.
                        if (sourceCreature.CurrentLandblock == null || creatureTarget.CurrentLandblock == null || sourceCreature.CurrentLandblock.CurrentLandblockGroup != creatureTarget.CurrentLandblock.CurrentLandblockGroup)
                        {
                            threadSafe = false;
                        }
                    }

                    if (threadSafe)
                    {
                        // This can result in spell projectiles being added to either sourceCreature or creatureTargets landblock.
                        sourceCreature.TryProcEquippedItems(creatureTarget, false);
                    }
                    else
                    {
                        // sourceCreature and creatureTarget are now in different landblock groups.
                        // What has likely happened is that sourceCreature sent a projectile toward creatureTarget. Before impact, sourceCreature was teleported away.
                        // To perform this fully thread safe, we would enqueue the work onto worldManager.
                        // WorldManager.EnqueueAction(new ActionEventDelegate(() => sourceCreature.TryProcEquippedItems(creatureTarget, false)));
                        // But, to keep it simple, we will just ignore it and not bother with TryProcEquippedItems for this particular impact.
                    }
                }
            }

            // also called on resist
            if (player != null && targetPlayer == null)
            {
                player.OnAttackMonster(creatureTarget);
            }

            if (player == null && targetPlayer == null)
            {
                // check for faction combat
                if (sourceCreature != null && creatureTarget != null && (sourceCreature.AllowFactionCombat(creatureTarget) || sourceCreature.PotentialFoe(creatureTarget)))
                {
                    sourceCreature.MonsterOnAttackMonster(creatureTarget);
                }
            }
        }
示例#2
0
        public override void OnCollideObject(WorldObject target)
        {
            //Console.WriteLine($"{Name}.OnCollideObject({target.Name})");

            var player = ProjectileSource as Player;

            if (Info != null && player != null && player.DebugSpell)
            {
                player.Session.Network.EnqueueSend(new GameMessageSystemChat($"{Name}.OnCollideObject({target?.Name} ({target?.Guid}))", ChatMessageType.Broadcast));
                player.Session.Network.EnqueueSend(new GameMessageSystemChat(Info.ToString(), ChatMessageType.Broadcast));
            }

            ProjectileImpact();

            // ensure valid creature target
            var creatureTarget = target as Creature;

            if (creatureTarget == null || target == ProjectileSource)
            {
                return;
            }

            if (player != null)
            {
                player.LastHitSpellProjectile = Spell;
            }

            // ensure caster can damage target
            var sourceCreature = ProjectileSource as Creature;

            if (sourceCreature != null && !sourceCreature.CanDamage(creatureTarget))
            {
                return;
            }

            // if player target, ensure matching PK status
            var targetPlayer = creatureTarget as Player;

            var pkError = ProjectileSource?.CheckPKStatusVsTarget(creatureTarget, Spell);

            if (pkError != null)
            {
                if (player != null)
                {
                    player.Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(player.Session, pkError[0], creatureTarget.Name));
                }

                if (targetPlayer != null)
                {
                    targetPlayer.Session.Network.EnqueueSend(new GameEventWeenieErrorWithString(targetPlayer.Session, pkError[1], ProjectileSource.Name));
                }

                return;
            }

            var critical     = false;
            var critDefended = false;
            var overpower    = false;

            var damage = CalculateDamage(ProjectileSource, Caster, creatureTarget, ref critical, ref critDefended, ref overpower);

            if (damage != null)
            {
                // handle void magic DoTs:
                // instead of instant damage, add DoT to target's enchantment registry
                if (Spell.School == MagicSchool.VoidMagic && Spell.Duration > 0)
                {
                    var dot = ProjectileSource.CreateEnchantment(creatureTarget, ProjectileSource, Spell);
                    if (dot.Message != null && player != null)
                    {
                        player.Session.Network.EnqueueSend(dot.Message);
                    }

                    // corruption / corrosion playscript?
                    //target.EnqueueBroadcast(new GameMessageScript(target.Guid, PlayScript.HealthDownVoid));
                    //target.EnqueueBroadcast(new GameMessageScript(target.Guid, PlayScript.DirtyFightingDefenseDebuff));
                }
                else
                {
                    DamageTarget(creatureTarget, damage.Value, critical, critDefended, overpower);
                }

                if (player != null)
                {
                    Proficiency.OnSuccessUse(player, player.GetCreatureSkill(Spell.School), Spell.PowerMod);
                }

                // handle target procs
                // note that for untargeted multi-projectile spells,
                // ProjectileTarget will be null here, so procs will not apply
                if (sourceCreature != null && ProjectileTarget != null)
                {
                    // Ok... if we got here, we're likely in the parallel landblock physics processing.
                    // We're currently on the thread for this, but we're wanting to perform some work on sourceCreature which can result in a new spell being created
                    // and added to the sourceCreature's current landblock, which, could be on a separate thread.
                    // Any chance of a cross landblock group work (and thus cross thread), should be enqueued onto the target object to maintain thread safety.
                    if (sourceCreature.CurrentLandblock == null || sourceCreature.CurrentLandblock == CurrentLandblock)
                    {
                        sourceCreature.TryProcEquippedItems(creatureTarget, false);
                    }
                    else
                    {
                        sourceCreature.EnqueueAction(new ActionEventDelegate(() => sourceCreature.TryProcEquippedItems(creatureTarget, false)));
                    }
                }
            }

            // also called on resist
            if (player != null && targetPlayer == null)
            {
                player.OnAttackMonster(creatureTarget);
            }

            if (player == null && targetPlayer == null)
            {
                // check for faction combat
                if (sourceCreature != null && creatureTarget != null && sourceCreature.AllowFactionCombat(creatureTarget))
                {
                    sourceCreature.MonsterOnAttackMonster(creatureTarget);
                }
            }
        }