Exemple #1
0
        /// <summary>
        /// Removes threat
        /// </summary>
        public override sealed void RemoveThreat(MmoObject cUnit, float amount, Spell spell)
        {
            if (IsDead())
            {
                return;
            }

            if (amount <= 0)
            {
                return;
            }

            switch ((ObjectType)cUnit.Guid.Type)
            {
            case ObjectType.Npc:
            case ObjectType.Player:
            {
                var id = cUnit.Guid;

                float oldThreat;
                if (threatTable.TryGetValue(id, out oldThreat) == false)
                {
                    return;
                }

                // dont use += (two lookups)
                // making sure to clamp the threat between 1 to max
                // remember, threat of 1 means that the unit is in the npc's visible range
                this.threatTable[id] = Mathf.Clamp(oldThreat - amount, 1, int.MaxValue);
            }
            break;
            }
        }
Exemple #2
0
        /// <summary>
        /// Heals the character.
        /// </summary>
        public void Heal(MmoObject cUnit, int value, Spell spell)
        {
            if (state == UnitState.Dead)
                return;

            // set hp and publish
            this.SetHealth(currentHealth + value, true);
            // TODO: Add threat to all attackers from cUnit
        }
Exemple #3
0
        /// <summary>
        /// Gains power.
        /// </summary>
        public void GainPower(MmoObject cUnit, int value, Spell spell)
        {
            // already dead so move along
            if (state == UnitState.Dead)
                return;

            // set pow and publish
            this.SetPower(currentPower + value, true);
        }
Exemple #4
0
        /// <summary>
        /// Drains power. Calls <see cref="AddThreat(MmoObject, float, Spell)"/> if <see cref="CanAddThreat()"/> returns <value>true</value>.
        /// </summary>
        public void DrainPower(MmoObject cUnit, int value, Spell spell)
        {
            // already dead so move along
            if (state == UnitState.Dead)
                return;

            // set pow and publish
            this.SetPower(currentPower - value, true);
            if (CanAddThreat())
            {
                var threat = value * ServerGameSettings.THREAT_POWER_MULTIPLIER;
                this.AddThreat(cUnit, threat, spell);
            }
        }
Exemple #5
0
        /// <summary>
        /// Kills the <see cref="Character"/> and calls <see cref="OnDeath(MmoObject)"/>.
        /// Updates the <see cref="State"/> to <see cref="UnitState.Dead"/> and resets <see cref="CurrentHealth"/> and <see cref="CurrentPower"/> to <value>0</value>.
        /// Publishes the current <see cref="UnitState"/>.
        /// </summary>
        public void Kill(MmoObject killer)
        {
            if (state == UnitState.Dead)
                return;

            // set state and publish
            this.SetUnitState(UnitState.Dead, true);
            // curr hp and curr pow dont need to be published
            // since when the client receives SetUnitState(Dead)
            // it will automatically updates them and the revision
            this.SetHealth(0);
            this.SetPower(0);

            this.OnDeath(killer);
        }
Exemple #6
0
        /// <summary>
        /// Adds threat
        /// </summary>
        public override sealed void AddThreat(MmoObject cUnit, float amount, Spell spell)
        {
            if (IsDead())
            {
                return;
            }

            if (amount <= 0)
            {
                return;
            }

            switch ((ObjectType)cUnit.Guid.Type)
            {
            case ObjectType.Npc:
            case ObjectType.Player:
            {
                var id = cUnit.Guid;

                float oldThreat;
                if (threatTable.TryGetValue(id, out oldThreat) == false)
                {
                    // this will not happen in regular scenarios
                    // will only happen when damaging npc without entering its aggro range
                    // mostly when debugging or via gm commands
                    if (ManualAggro(cUnit as Character) == false)
                    {
                        return;
                    }

                    // looking up again to make sure that the manual aggro worked
                    if (threatTable.TryGetValue(id, out oldThreat) == false)
                    {
                        return;
                    }
                }

                // dont use += (two lookups)
                // making sure to clamp the threat between 1 to max
                // remember, threat of 1 means that the unit is in the npc's visible range
                this.threatTable[id] = Mathf.Clamp(oldThreat + amount, 1, int.MaxValue);
            }
            break;
            }
        }
Exemple #7
0
        void DoProcessThreat(MmoObject mmoObject)
        {
            // this will make sure that we only subscribe world objects
            if (CanRadarSubscribe(mmoObject) == false)
            {
                return;
            }

            var character = mmoObject as Character;

            if (character != null)
            {
                if (!visibleCharacters.ContainsKey(character))
                {
                    // subscribing character
                    var subscription = mmoObject.PositionUpdateChannel.SubscribeToLast(this.CurrentZone.PrimaryFiber, this.Radar_OnCharacterPosition_AggroEnterCheck, ServerGameSettings.AGGRO_ENTER_CHECK_INTERVAL_MS);
                    this.visibleCharacters.Add(character, subscription);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Begins to chase a(n) <see cref="MmoObject"/> and calls <paramref name="onHitCallback"/> when hit.
        /// </summary>
        public void SpellChase(MmoObject target, MmoObject owner, int speed, Action onHitCallback)
        {
            // we are already being updated so skip
            if (updateSubscription != null)
            {
                return;
            }

            this.CurrentFocus = target;
            this.CurrentSpeed = speed;
            this.onHit        = onHitCallback;

            // creating the owner disposal subscription
            this.ownerDisposedSubscription = owner.DisposeChannel.Subscribe(this.CurrentZone.PrimaryFiber, m => this.OnSpellOwner_Disposed());

            this.destination        = this.CurrentFocus.Position;
            this.updateSubscription = this.CreateUpdateEvent(this.Update, ServerGameSettings.GAME_UPDATE_INTERVAL);

            // we are moving
            Interlocked.Exchange(ref this.interlockedIsMoving, 1);
        }
Exemple #9
0
        /// <summary>
        /// Damages the character. Calls <see cref="AddThreat(MmoObject, float, Spell)"/> if <see cref="CanAddThreat()"/> returns <value>true</value>.
        /// </summary>
        public void Damage(MmoObject cUnit, int value, Spell spell)
        {
            // already dead so move along
            if (state == UnitState.Dead)
                return;

            // dont publish curr hp since the char may die after dmg
            this.SetHealth(currentHealth - value);
            if (CanAddThreat())
            {
                var threat = value * ServerGameSettings.THREAT_DAMAGE_MULTIPLIER;
                this.AddThreat(cUnit, threat, spell);
            }

            // kills the char if health is 0
            if (currentHealth <= 0)
                this.Kill(cUnit);

            // only publish curr hp if the char is not dead
            if (state != UnitState.Dead)
                this.PublishProperty(PropertyCode.CurrHp, this.currentHealth);
        }
Exemple #10
0
        /// <summary>
        /// Called when this <see cref="Character"/> is killed. Remember the <paramref name="killer"/> could be <value>this</value>.
        /// </summary>
        protected override void OnDeath(MmoObject killer)
        {
            base.OnDeath(killer);
            if (IsMoving)
            {
                this.ResetMovement();
                this.PublishStopEvent();
            }

            this.DisposeRadarSubscriptions();

            this.CurrentAggroState = AggroState.Idle;
            this.CurrentFocus      = null;

            RandomLootContainer randomLootContainer = null;

            ICollection <MmoGuid> skipPlayers = null;

            foreach (var pair in threatTable)
            {
                // only players can be rewarded for now
                var pGuid = pair.Key;
                if (pGuid.Type != (byte)ObjectType.Player)
                {
                    continue;
                }
                // reward only if the threat is greater than this threshold
                if (pair.Value <= ServerGameSettings.THREAT_THRESHOLD_FOR_REWARD)
                {
                    continue;
                }

                if (skipPlayers != null)
                {
                    // making sure the player gets only one loot generation attempt
                    if (skipPlayers.Contains(pGuid))
                    {
                        continue;
                    }
                    skipPlayers.Add(pGuid);
                }

                WorldSession session;
                if (MmoWorld.Instance.SessionCache.TryGetSessionByPlayerGuid(pGuid.Id, out session))
                {
                    // generate loot, only if one of the killer is a player
                    if (randomLootContainer == null)
                    {
                        randomLootContainer = new RandomLootContainer(this, this.lootGroupId, (itemId, looter) => true);
                    }
                    // create the collection only if one killer is a player
                    if (skipPlayers == null)
                    {
                        skipPlayers = this.threatTable.Count > 10 ? (ICollection <MmoGuid>) new HashSet <MmoGuid>() : new List <MmoGuid>();
                    }

                    var player = session.Player;
                    // player is in a group
                    if (player.InGroup())
                    {
                        var members = player.Group.GetActiveMembers();
                        foreach (var member in members)
                        {
                            // making sure the member gets only one loot generation attempt
                            var mGuid = member.Guid;
                            if (skipPlayers.Contains(mGuid))
                            {
                                continue;
                            }

                            skipPlayers.Add(mGuid);
                            // finding the player
                            WorldSession memberSession;
                            if (MmoWorld.Instance.SessionCache.TryGetSessionByPlayerGuid(mGuid.Id, out memberSession))
                            {
                                continue;
                            }
                            // checking to see if the player is within the range of the member
                            var memberPlayer = memberSession.Player;
                            if (!player.HaveSubscriptionFor(memberPlayer.Guid) && player != memberPlayer)
                            {
                                continue;
                            }

                            randomLootContainer.GenerateLootFor(memberPlayer);
                        }
                    }
                    // always generate loot for the player
                    randomLootContainer.GenerateLootFor(player);
                    player.RewardKill(this);
                }
            }

            this.threatTable.Clear();

            var spawnDelay = ServerGameSettings.BASE_NPC_RESPAWN_TIME_MS;

            if (randomLootContainer != null)
            {
                spawnDelay = ServerGameSettings.BASE_NPC_WAIT_TIME_UNTIL_LOOTED_MS;
                // set the loot
                lootContainer = randomLootContainer;
                // notify all the looters
                randomLootContainer.NotifyLooters();
            }

            this.QueueRespawn(spawnDelay, ServerGameSettings.BASE_NPC_RESPAWN_TIME_MS, this.iPosition, this.iRotation);
        }
Exemple #11
0
        /// <summary>
        /// Tells whether a <see cref="MmoObject"/> can be subscribed or not.
        /// </summary>
        bool CanRadarSubscribe(MmoObject mmoObject)
        {
            var objectType = (ObjectType)mmoObject.Guid.Type;

            return(mmoObject != this && objectType == ObjectType.Npc || objectType == ObjectType.Player);
        }
Exemple #12
0
 /// <summary>
 /// Filters the <see cref="mmoObject"/> for combat eligibility and takes appropriate action
 /// </summary>
 void IEngager.ProcessThreat(MmoObject mmoObject)
 {
     this.DoProcessThreat(mmoObject);
 }
Exemple #13
0
 /// <summary>
 /// Rewards this <see cref="MmoObject"/> of the kill.
 /// </summary>
 /// <param name="killed"> The <see cref="MmoObject"/> that was killed. </param>
 public virtual void RewardKill(MmoObject killed)
 {
 }
Exemple #14
0
 /// <summary>
 /// Called when this <see cref="Character"/> is killed. Remember the <paramref name="killer"/> could be <value>this</value>.
 /// This will be called after calling <see cref="Kill(MmoObject)"/>.
 /// Does nothing by default.
 /// </summary>
 protected virtual void OnDeath(MmoObject killer)
 {
 }
Exemple #15
0
 /// <summary>
 /// Removes threat
 /// </summary>
 public virtual void RemoveThreat(MmoObject cUnit, float amount, Spell spell)
 {
 }