Example #1
0
        public static int GetCustomEffectLevel(NWCreature creature, CustomEffectType customEffectType)
        {
            int effectLevel = 0;

            if (creature.IsNPC)
            {
                var effect = AppCache.NPCEffects.SingleOrDefault(x => x.Key.Target.Equals(creature) && x.Key.CustomEffectID == (int)customEffectType);

                if (effect.Key != null)
                {
                    effectLevel = effect.Key.EffectiveLevel;
                }
            }
            else if (creature.IsPlayer)
            {
                PCCustomEffect dbEffect = DataService.PCCustomEffect.GetByPlayerIDAndCustomEffectIDOrDefault(creature.GlobalID, (int)customEffectType);
                if (dbEffect != null)
                {
                    if (!AppCache.PCEffectsForRemoval.Contains(dbEffect.ID))
                    {
                        effectLevel = dbEffect.EffectiveLevel;
                    }
                }
            }
            else
            {
                return(0);
            }
            return(effectLevel);
        }
Example #2
0
        private static void ProcessPCCustomEffects()
        {
            foreach (var player in NWModule.Get().Players)
            {
                if (!player.IsInitializedAsPlayer)
                {
                    continue;                                // Ignored to prevent a timing issue where new characters would be included in this processing.
                }
                List <PCCustomEffect> effects = DataService.PCCustomEffect.GetAllByPlayerID(player.GlobalID).Where(x => x.StancePerkID == null).ToList();

                foreach (var effect in effects)
                {
                    if (player.CurrentHP <= -11)
                    {
                        CustomEffectService.RemovePCCustomEffect(player, effect.CustomEffectID);
                        return;
                    }

                    PCCustomEffect result = RunPCCustomEffectProcess(player, effect);
                    if (result == null)
                    {
                        ICustomEffectHandler handler = CustomEffectService.GetCustomEffectHandler(effect.CustomEffectID);
                        string message = handler.WornOffMessage;
                        player.SendMessage(message);
                        player.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + effect.CustomEffectID);
                        DataService.SubmitDataChange(effect, DatabaseActionType.Delete);
                        handler.WearOff(null, player, effect.EffectiveLevel, effect.Data);
                    }
                    else
                    {
                        DataService.SubmitDataChange(effect, DatabaseActionType.Update);
                    }
                }
            }
        }
Example #3
0
        public static void ApplyStance(NWCreature creature, CustomEffectType customEffect, PerkType perkType, int effectiveLevel, string data)
        {
            // Can't process NPC stances at the moment. Need to do some more refactoring before this is possible.
            // todo: handle NPC stances.
            if (!creature.IsPlayer)
            {
                return;
            }

            var pcStanceEffect = DataService.PCCustomEffect.GetByPlayerStanceOrDefault(creature.GlobalID);
            int customEffectID = (int)customEffect;

            // Player selected to cancel their stance. Cancel it and end.
            if (pcStanceEffect != null && pcStanceEffect.CustomEffectID == customEffectID && pcStanceEffect.EffectiveLevel == effectiveLevel)
            {
                RemoveStance(creature, pcStanceEffect);
                return;
            }
            // Otherwise remove existing stance
            else if (pcStanceEffect != null)
            {
                RemoveStance(creature, pcStanceEffect, false);
            }

            // Player selected to switch stances
            pcStanceEffect = new PCCustomEffect
            {
                PlayerID          = creature.GlobalID,
                Ticks             = -1,
                CustomEffectID    = customEffectID,
                CasterNWNObjectID = _.ObjectToString(creature),
                EffectiveLevel    = effectiveLevel,
                StancePerkID      = (int)perkType
            };
            DataService.SubmitDataChange(pcStanceEffect, DatabaseActionType.Insert);
            ICustomEffectHandler handler = GetCustomEffectHandler(customEffect);

            if (string.IsNullOrWhiteSpace(data))
            {
                data = handler.Apply(creature, creature, effectiveLevel);
            }

            if (!string.IsNullOrWhiteSpace(handler.StartMessage))
            {
                creature.SendMessage(handler.StartMessage);
            }

            if (string.IsNullOrWhiteSpace(data))
            {
                data = string.Empty;
            }
            pcStanceEffect.Data = data;
            DataService.SubmitDataChange(pcStanceEffect, DatabaseActionType.Update);

            // Was already queued for removal, but got cast again. Take it out of the list to be removed.
            if (AppCache.PCEffectsForRemoval.Contains(pcStanceEffect.ID))
            {
                AppCache.PCEffectsForRemoval.Remove(pcStanceEffect.ID);
            }
        }
Example #4
0
        private static PCCustomEffect RunPCCustomEffectProcess(NWPlayer oPC, PCCustomEffect effect)
        {
            NWCreature caster = oPC;

            if (!string.IsNullOrWhiteSpace(effect.CasterNWNObjectID))
            {
                var obj = NWNXObject.StringToObject(effect.CasterNWNObjectID);
                if (obj.IsValid)
                {
                    caster = obj.Object;
                }
            }

            if (effect.Ticks > 0)
            {
                effect.Ticks = effect.Ticks - 1;
            }

            if (effect.Ticks == 0)
            {
                return(null);
            }
            ICustomEffectHandler handler = CustomEffectService.GetCustomEffectHandler(effect.CustomEffectID);

            if (!string.IsNullOrWhiteSpace(handler.ContinueMessage) &&
                effect.Ticks % 6 == 0) // Only show the message once every six seconds
            {
                oPC.SendMessage(handler.ContinueMessage);
            }
            handler?.Tick(caster, oPC, effect.Ticks, effect.EffectiveLevel, effect.Data);

            return(effect);
        }
Example #5
0
        public static bool RemoveStance(NWCreature creature, PCCustomEffect stanceEffect = null, bool sendMessage = true)
        {
            // Can't process NPC stances at the moment. Need to do some more refactoring before this is possible.
            // todo: handle NPC stances.
            if (!creature.IsPlayer)
            {
                return(false);
            }

            if (stanceEffect == null)
            {
                stanceEffect = DataService.PCCustomEffect.GetByPlayerStanceOrDefault(creature.GlobalID);
            }
            if (stanceEffect == null)
            {
                return(false);
            }

            if (sendMessage)
            {
                creature.SendMessage("You return to your normal stance.");
            }

            int    effectiveLevel = stanceEffect.EffectiveLevel;
            string data           = stanceEffect.Data;

            DataService.SubmitDataChange(stanceEffect, DatabaseActionType.Delete);
            ICustomEffectHandler handler = GetCustomEffectHandler(stanceEffect.CustomEffectID);

            handler?.WearOff(creature, creature, effectiveLevel, data);

            return(true);
        }
Example #6
0
        public bool RemoveStance(NWPlayer player, PCCustomEffect stanceEffect = null, bool sendMessage = true)
        {
            if (stanceEffect == null)
            {
                stanceEffect = _data.SingleOrDefault <PCCustomEffect>(x =>
                {
                    var customEffect = _data.Get <Data.Entity.CustomEffect>(x.CustomEffectID);
                    return(x.PlayerID == player.GlobalID &&
                           customEffect.CustomEffectCategoryID == (int)CustomEffectCategoryType.Stance);
                });
            }
            if (stanceEffect == null)
            {
                return(false);
            }

            if (sendMessage)
            {
                player.SendMessage("You return to your normal stance.");
            }

            int    effectiveLevel     = stanceEffect.EffectiveLevel;
            string data               = stanceEffect.Data;
            var    stanceCustomEffect = _data.Get <Data.Entity.CustomEffect>(stanceEffect.CustomEffectID);
            string scriptHandler      = stanceCustomEffect.ScriptHandler;

            _data.SubmitDataChange(stanceEffect, DatabaseActionType.Delete);

            App.ResolveByInterface <ICustomEffect>("CustomEffect." + scriptHandler, handler =>
            {
                handler?.WearOff(player, player, effectiveLevel, data);
            });

            return(true);
        }
Example #7
0
        public int GetCustomEffectLevel(NWCreature creature, CustomEffectType customEffectType)
        {
            int effectLevel = 0;

            if (creature.IsNPC)
            {
                var effect = _cache.NPCEffects.SingleOrDefault(x => x.Key.Target.Equals(creature) && x.Key.CustomEffectID == (int)customEffectType);

                if (effect.Key != null)
                {
                    effectLevel = effect.Key.EffectiveLevel;
                }
            }
            else if (creature.IsPlayer)
            {
                PCCustomEffect dbEffect = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == creature.GlobalID && x.CustomEffectID == (int)customEffectType);
                if (dbEffect != null)
                {
                    if (!_cache.PCEffectsForRemoval.Contains(dbEffect.ID))
                    {
                        effectLevel = dbEffect.EffectiveLevel;
                    }
                }
            }
            else
            {
                return(0);
            }
            return(effectLevel);
        }
Example #8
0
        public static bool RemoveStance(NWPlayer player, PCCustomEffect stanceEffect = null, bool sendMessage = true)
        {
            if (stanceEffect == null)
            {
                stanceEffect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == player.GlobalID &&
                                                                            x.StancePerkID != null);
            }
            if (stanceEffect == null)
            {
                return(false);
            }

            if (sendMessage)
            {
                player.SendMessage("You return to your normal stance.");
            }

            int    effectiveLevel = stanceEffect.EffectiveLevel;
            string data           = stanceEffect.Data;

            DataService.SubmitDataChange(stanceEffect, DatabaseActionType.Delete);
            ICustomEffectHandler handler = GetCustomEffectHandler(stanceEffect.CustomEffectID);

            handler?.WearOff(player, player, effectiveLevel, data);

            return(true);
        }
Example #9
0
        public void OnPlayerHeartbeat(NWPlayer oPC)
        {
            List <PCCustomEffect> effects = _db.PCCustomEffects.Where(x => x.PlayerID == oPC.GlobalID).ToList();
            string areaResref             = oPC.Area.Resref;

            foreach (PCCustomEffect effect in effects)
            {
                if (oPC.CurrentHP <= -11 || areaResref == "death_realm")
                {
                    RemovePCCustomEffect(oPC, effect.CustomEffectID);
                    return;
                }

                PCCustomEffect result = RunPCCustomEffectProcess(oPC, effect);
                if (result == null)
                {
                    string message       = effect.CustomEffect.WornOffMessage;
                    string scriptHandler = effect.CustomEffect.ScriptHandler;
                    oPC.SendMessage(message);
                    oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + effect.CustomEffectID);
                    _db.PCCustomEffects.Remove(effect);
                    _db.SaveChanges();

                    ICustomEffect handler = App.ResolveByInterface <ICustomEffect>("CustomEffect." + scriptHandler);
                    handler?.WearOff(null, oPC);
                }
                else
                {
                    _db.SaveChanges();
                }
            }
        }
Example #10
0
        public static void ApplyStance(NWPlayer player, CustomEffectType customEffect, PerkType perkType, int effectiveLevel, string data)
        {
            var pcStanceEffect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == player.GlobalID &&
                                                                              x.StancePerkID != null);
            int customEffectID = (int)customEffect;

            // Player selected to cancel their stance. Cancel it and end.
            if (pcStanceEffect != null && pcStanceEffect.CustomEffectID == customEffectID && pcStanceEffect.EffectiveLevel == effectiveLevel)
            {
                RemoveStance(player, pcStanceEffect);
                return;
            }
            // Otherwise remove existing stance
            else if (pcStanceEffect != null)
            {
                RemoveStance(player, pcStanceEffect, false);
            }

            // Player selected to switch stances
            pcStanceEffect = new PCCustomEffect
            {
                PlayerID          = player.GlobalID,
                Ticks             = -1,
                CustomEffectID    = customEffectID,
                CasterNWNObjectID = _.ObjectToString(player),
                EffectiveLevel    = effectiveLevel,
                StancePerkID      = (int)perkType
            };
            DataService.SubmitDataChange(pcStanceEffect, DatabaseActionType.Insert);
            ICustomEffectHandler handler = GetCustomEffectHandler(customEffect);

            if (string.IsNullOrWhiteSpace(data))
            {
                data = handler.Apply(player, player, effectiveLevel);
            }

            if (!string.IsNullOrWhiteSpace(handler.StartMessage))
            {
                player.SendMessage(handler.StartMessage);
            }

            if (string.IsNullOrWhiteSpace(data))
            {
                data = string.Empty;
            }
            pcStanceEffect.Data = data;
            DataService.SubmitDataChange(pcStanceEffect, DatabaseActionType.Update);

            // Was already queued for removal, but got cast again. Take it out of the list to be removed.
            if (AppCache.PCEffectsForRemoval.Contains(pcStanceEffect.ID))
            {
                AppCache.PCEffectsForRemoval.Remove(pcStanceEffect.ID);
            }
        }
Example #11
0
        public static ForceSpreadDetails GetForceSpreadDetails(NWPlayer player)
        {
            PCCustomEffect     spreadEffect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == player.GlobalID && x.CustomEffectID == (int)CustomEffectType.ForceSpread);
            ForceSpreadDetails details      = new ForceSpreadDetails();
            string             spreadData   = spreadEffect?.Data ?? string.Empty;

            details.Level = spreadEffect?.EffectiveLevel ?? 0;
            details.Uses  = spreadEffect == null ? 0 : Convert.ToInt32(spreadData.Split(',')[0]);
            details.Range = spreadEffect == null ? 0 : Convert.ToSingle(spreadData.Split(',')[1]);

            return(details);
        }
        public void GetByID_OneItem_ReturnsPCCustomEffect()
        {
            // Arrange
            var            id     = Guid.NewGuid();
            PCCustomEffect entity = new PCCustomEffect {
                ID = id
            };

            // Act
            MessageHub.Instance.Publish(new OnCacheObjectSet <PCCustomEffect>(entity));

            // Assert
            Assert.AreNotSame(entity, _cache.GetByID(id));
        }
Example #13
0
        public void RemovePCCustomEffect(NWPlayer oPC, long customEffectID)
        {
            PCCustomEffect effect = _db.PCCustomEffects.SingleOrDefault(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            if (effect == null)
            {
                return;
            }

            _db.PCCustomEffects.Remove(effect);
            oPC.SendMessage(effect.CustomEffect.WornOffMessage);
        }
Example #14
0
        public static bool DoesPCHaveCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = DataService.PCCustomEffect.GetByPlayerIDAndCustomEffectIDOrDefault(oPC.GlobalID, customEffectID);

            if (effect == null)
            {
                return(false);
            }
            else if (AppCache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return(false);
            }

            return(true);
        }
Example #15
0
        public bool DoesPCHaveCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            if (effect == null)
            {
                return(false);
            }
            else if (_cache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return(false);
            }

            return(true);
        }
        private void ProcessPCCustomEffects()
        {
            foreach (var player in NWModule.Get().Players)
            {
                if (!player.IsInitializedAsPlayer)
                {
                    continue;                                // Ignored to prevent a timing issue where new characters would be included in this processing.
                }
                List <PCCustomEffect> effects = _data.Where <PCCustomEffect>(x =>
                {
                    var customEffect = _data.Get <Data.Entity.CustomEffect>(x.CustomEffectID);
                    return(x.PlayerID == player.GlobalID &&
                           customEffect.CustomEffectCategoryID != (int)CustomEffectCategoryType.Stance);
                }).ToList();

                foreach (var effect in effects)
                {
                    if (player.CurrentHP <= -11)
                    {
                        _customEffect.RemovePCCustomEffect(player, effect.CustomEffectID);
                        return;
                    }

                    PCCustomEffect result = RunPCCustomEffectProcess(player, effect);
                    if (result == null)
                    {
                        var    customEffect  = _data.Get <Data.Entity.CustomEffect>(effect.CustomEffectID);
                        string message       = customEffect.WornOffMessage;
                        string scriptHandler = customEffect.ScriptHandler;
                        player.SendMessage(message);
                        player.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + effect.CustomEffectID);
                        _data.SubmitDataChange(effect, DatabaseActionType.Delete);

                        App.ResolveByInterface <ICustomEffect>("CustomEffect." + scriptHandler, (handler) =>
                        {
                            handler?.WearOff(null, player, effect.EffectiveLevel, effect.Data);
                        });
                    }
                    else
                    {
                        _data.SubmitDataChange(effect, DatabaseActionType.Update);
                    }
                }
            }
        }
Example #17
0
        public void RemovePCCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            // Doesn't exist in DB or is already marked for removal
            if (effect == null ||
                _cache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return;
            }
            var customEffect = _data.Get <Data.Entity.CustomEffect>(effect.CustomEffectID);

            oPC.SendMessage(customEffect.WornOffMessage);

            _cache.PCEffectsForRemoval.Add(effect.ID);
        }
Example #18
0
        public static void RemovePCCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            oPC.DeleteLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID);

            // Doesn't exist in DB or is already marked for removal
            if (effect == null ||
                AppCache.PCEffectsForRemoval.Contains(effect.ID))
            {
                return;
            }
            var handler = GetCustomEffectHandler(customEffectID);

            oPC.SendMessage(handler.WornOffMessage);

            AppCache.PCEffectsForRemoval.Add(effect.ID);
        }
Example #19
0
        private PCCustomEffect RunPCCustomEffectProcess(NWPlayer oPC, PCCustomEffect effect)
        {
            effect.Ticks = effect.Ticks - 1;
            if (effect.Ticks < 0)
            {
                return(null);
            }

            if (!string.IsNullOrWhiteSpace(effect.CustomEffect.ContinueMessage))
            {
                oPC.SendMessage(effect.CustomEffect.ContinueMessage);
            }

            ICustomEffect handler = App.ResolveByInterface <ICustomEffect>("CustomEffect." + effect.CustomEffect.ScriptHandler);

            handler?.Tick(null, oPC);

            return(effect);
        }
        public void GetByID_TwoItems_ReturnsCorrectObject()
        {
            // Arrange
            var            id1     = Guid.NewGuid();
            var            id2     = Guid.NewGuid();
            PCCustomEffect entity1 = new PCCustomEffect {
                ID = id1
            };
            PCCustomEffect entity2 = new PCCustomEffect {
                ID = id2
            };

            // Act
            MessageHub.Instance.Publish(new OnCacheObjectSet <PCCustomEffect>(entity1));
            MessageHub.Instance.Publish(new OnCacheObjectSet <PCCustomEffect>(entity2));

            // Assert
            Assert.AreNotSame(entity1, _cache.GetByID(id1));
            Assert.AreNotSame(entity2, _cache.GetByID(id2));
        }
Example #21
0
        public void OnImpact(NWPlayer player, NWObject target, int level)
        {
            var effectiveStats = _playerStat.GetPlayerItemEffectiveStats(player);
            int lightBonus     = effectiveStats.LightAbility;

            PCCustomEffect spreadEffect = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == player.GlobalID && x.CustomEffectID == (int)CustomEffectType.ForceSpread);
            string         spreadData   = spreadEffect?.Data ?? string.Empty;
            int            spreadLevel  = spreadEffect?.EffectiveLevel ?? 0;
            int            spreadUses   = spreadEffect == null ? 0 : Convert.ToInt32(spreadData.Split(',')[0]);
            float          spreadRange  = spreadEffect == null ? 0 : Convert.ToSingle(spreadData.Split(',')[1]);

            if (spreadLevel <= 0)
            {
                HealTarget(player, target, lightBonus, level);
            }
            else
            {
                var members = player.PartyMembers.Where(x => _.GetDistanceBetween(x, target) <= spreadRange ||
                                                        Equals(x, target));
                spreadUses--;

                foreach (var member in members)
                {
                    HealTarget(player, member, lightBonus, level);
                }

                if (spreadUses <= 0)
                {
                    _customEffect.RemovePCCustomEffect(player, CustomEffectType.ForceSpread);
                }
                else
                {
                    // ReSharper disable once PossibleNullReferenceException
                    spreadEffect.Data = spreadUses + "," + spreadRange;
                    _data.SubmitDataChange(spreadEffect, DatabaseActionType.Update);
                    player.SendMessage("Force Spread uses remaining: " + spreadUses);
                }
            }

            _skill.RegisterPCToAllCombatTargetsForSkill(player, SkillType.LightSideAbilities, target.Object);
        }
        public void GetByID_RemovedItem_ReturnsCorrectObject()
        {
            // Arrange
            var            id1     = Guid.NewGuid();
            var            id2     = Guid.NewGuid();
            PCCustomEffect entity1 = new PCCustomEffect {
                ID = id1
            };
            PCCustomEffect entity2 = new PCCustomEffect {
                ID = id2
            };

            // Act
            MessageHub.Instance.Publish(new OnCacheObjectSet <PCCustomEffect>(entity1));
            MessageHub.Instance.Publish(new OnCacheObjectSet <PCCustomEffect>(entity2));
            MessageHub.Instance.Publish(new OnCacheObjectDeleted <PCCustomEffect>(entity1));

            // Assert
            Assert.Throws <KeyNotFoundException>(() => { _cache.GetByID(id1); });
            Assert.AreNotSame(entity2, _cache.GetByID(id2));
        }
Example #23
0
        public static void SetForceSpreadUses(NWPlayer player, int uses)
        {
            PCCustomEffect spreadEffect = DataService.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == player.GlobalID && x.CustomEffectID == (int)CustomEffectType.ForceSpread);

            if (spreadEffect == null)
            {
                return;
            }

            if (uses <= 0)
            {
                RemovePCCustomEffect(player, CustomEffectType.ForceSpread);
            }

            string spreadData = spreadEffect.Data ?? string.Empty;

            float range = Convert.ToSingle(spreadData.Split(',')[1]);

            spreadEffect.Data = uses + "," + range;
            DataService.SubmitDataChange(spreadEffect, DatabaseActionType.Update);
            player.SendMessage("Force Spread uses remaining: " + uses);
        }
        private PCCustomEffect RunPCCustomEffectProcess(NWPlayer oPC, PCCustomEffect effect)
        {
            NWCreature caster = oPC;

            if (!string.IsNullOrWhiteSpace(effect.CasterNWNObjectID))
            {
                var obj = _nwnxObject.StringToObject(effect.CasterNWNObjectID);
                if (obj.IsValid)
                {
                    caster = obj.Object;
                }
            }

            if (effect.Ticks > 0)
            {
                effect.Ticks = effect.Ticks - 1;
            }

            if (effect.Ticks == 0)
            {
                return(null);
            }
            var customEffect = _data.Get <Data.Entity.CustomEffect>(effect.CustomEffectID);

            if (!string.IsNullOrWhiteSpace(customEffect.ContinueMessage) &&
                effect.Ticks % 6 == 0) // Only show the message once every six seconds
            {
                oPC.SendMessage(customEffect.ContinueMessage);
            }

            App.ResolveByInterface <ICustomEffect>("CustomEffect." + customEffect.ScriptHandler, (handler) =>
            {
                handler?.Tick(caster, oPC, effect.Ticks, effect.EffectiveLevel, effect.Data);
            });

            return(effect);
        }
Example #25
0
        private static void ApplyPCEffect(NWCreature caster, NWCreature target, int customEffectID, int ticks, int effectiveLevel, string data)
        {
            PCCustomEffect           pcEffect = DataService.PCCustomEffect.GetByPlayerIDAndCustomEffectIDOrDefault(target.GlobalID, customEffectID);
            ICustomEffectHandler     handler  = GetCustomEffectHandler(customEffectID);
            CustomEffectCategoryType category = handler.CustomEffectCategoryType;

            if (category == CustomEffectCategoryType.FoodEffect)
            {
                var customEffectPC = DataService.CustomEffect.GetByID(pcEffect.CustomEffectID);
                if (customEffectPC != null)
                {
                    var foodHandler = GetCustomEffectHandler(customEffectPC.ID);
                    if (foodHandler.CustomEffectCategoryType == category)
                    {
                        caster.SendMessage("You are not hungry.");
                    }
                    return;
                }
            }

            DatabaseActionType action = DatabaseActionType.Update;

            if (pcEffect == null)
            {
                pcEffect = new PCCustomEffect {
                    PlayerID = target.GlobalID
                };
                action = DatabaseActionType.Insert;
            }

            if (pcEffect.EffectiveLevel > effectiveLevel)
            {
                caster.SendMessage("A more powerful effect already exists on your target.");
                return;
            }

            pcEffect.CustomEffectID    = customEffectID;
            pcEffect.EffectiveLevel    = effectiveLevel;
            pcEffect.Ticks             = ticks;
            pcEffect.CasterNWNObjectID = _.ObjectToString(caster);
            DataService.SubmitDataChange(pcEffect, action);

            target.SendMessage(handler.StartMessage);
            if (string.IsNullOrWhiteSpace(data))
            {
                data = handler?.Apply(caster, target, effectiveLevel);
            }

            if (string.IsNullOrWhiteSpace(data))
            {
                data = string.Empty;
            }
            pcEffect.Data = data;
            DataService.SubmitDataChange(pcEffect, DatabaseActionType.Update);

            // Was already queued for removal, but got cast again. Take it out of the list to be removed.
            if (AppCache.PCEffectsForRemoval.Contains(pcEffect.ID))
            {
                AppCache.PCEffectsForRemoval.Remove(pcEffect.ID);
            }
        }
Example #26
0
        public void ApplyStance(NWPlayer player, CustomEffectType customEffect, PerkType perkType, int effectiveLevel, string data)
        {
            var dbEffect       = _data.Single <Data.Entity.CustomEffect>(x => x.ID == (int)customEffect);
            var pcStanceEffect = _data.SingleOrDefault <PCCustomEffect>(x =>
            {
                var ce = _data.Get <Data.Entity.CustomEffect>(x.CustomEffectID);
                return(x.PlayerID == player.GlobalID &&
                       ce.CustomEffectCategoryID == (int)CustomEffectCategoryType.Stance);
            });
            int customEffectID = (int)customEffect;

            // Player selected to cancel their stance. Cancel it and end.
            if (pcStanceEffect != null && pcStanceEffect.CustomEffectID == customEffectID && pcStanceEffect.EffectiveLevel == effectiveLevel)
            {
                RemoveStance(player, pcStanceEffect);
                return;
            }
            // Otherwise remove existing stance
            else if (pcStanceEffect != null)
            {
                RemoveStance(player, pcStanceEffect, false);
            }

            // Player selected to switch stances
            pcStanceEffect = new PCCustomEffect
            {
                PlayerID          = player.GlobalID,
                Ticks             = -1,
                CustomEffectID    = customEffectID,
                CasterNWNObjectID = _.ObjectToString(player),
                EffectiveLevel    = effectiveLevel,
                StancePerkID      = (int)perkType
            };
            _data.SubmitDataChange(pcStanceEffect, DatabaseActionType.Insert);

            App.ResolveByInterface <ICustomEffect>("CustomEffect." + dbEffect.ScriptHandler, handler =>
            {
                if (string.IsNullOrWhiteSpace(data))
                {
                    data = handler?.Apply(player, player, effectiveLevel);
                }

                var stanceCustomEffect = _data.Get <Data.Entity.CustomEffect>(pcStanceEffect.CustomEffectID);
                if (!string.IsNullOrWhiteSpace(stanceCustomEffect.StartMessage))
                {
                    player.SendMessage(stanceCustomEffect.StartMessage);
                }

                if (string.IsNullOrWhiteSpace(data))
                {
                    data = string.Empty;
                }
                pcStanceEffect.Data = data;
                _data.SubmitDataChange(pcStanceEffect, DatabaseActionType.Update);

                // Was already queued for removal, but got cast again. Take it out of the list to be removed.
                if (_cache.PCEffectsForRemoval.Contains(pcStanceEffect.ID))
                {
                    _cache.PCEffectsForRemoval.Remove(pcStanceEffect.ID);
                }
            });
        }
Example #27
0
        public void ApplyCustomEffect(NWCreature oCaster, NWCreature oTarget, int customEffectID, int ticks, int effectLevel)
        {
            // Can't apply the effect if the existing one is stronger.
            int existingEffectLevel = GetActiveEffectLevel(oTarget, customEffectID);

            if (existingEffectLevel > effectLevel)
            {
                oCaster.SendMessage("A more powerful effect already exists on your target.");
                return;
            }

            Data.Entities.CustomEffect effectEntity = _db.CustomEffects.Single(x => x.CustomEffectID == customEffectID);

            // PC custom effects are tracked in the database.
            if (oTarget.IsPlayer)
            {
                PCCustomEffect entity = _db.PCCustomEffects.SingleOrDefault(x => x.PlayerID == oTarget.GlobalID && x.CustomEffectID == customEffectID);

                if (entity == null)
                {
                    entity = new PCCustomEffect
                    {
                        PlayerID       = oTarget.GlobalID,
                        CustomEffectID = customEffectID
                    };

                    _db.PCCustomEffects.Add(entity);
                }

                entity.Ticks = ticks;
                _db.SaveChanges();

                oTarget.SendMessage(effectEntity.StartMessage);
            }
            // NPCs custom effects are tracked in server memory.
            else
            {
                // Look for existing effect.
                foreach (var entry in _state.NPCEffects)
                {
                    CasterSpellVO casterSpellModel = entry.Key;

                    if (casterSpellModel.Caster.Equals(oCaster) &&
                        casterSpellModel.CustomEffectID == customEffectID &&
                        casterSpellModel.Target.Equals(oTarget))
                    {
                        _state.NPCEffects[entry.Key] = ticks;
                        return;
                    }
                }

                // Didn't find an existing effect. Create a new one.
                CasterSpellVO spellModel = new CasterSpellVO
                {
                    Caster         = oCaster,
                    CustomEffectID = customEffectID,
                    EffectName     = effectEntity.Name,
                    Target         = oTarget
                };

                _state.NPCEffects[spellModel] = ticks;
            }

            ICustomEffect handler = App.ResolveByInterface <ICustomEffect>("CustomEffect." + effectEntity.ScriptHandler);

            handler?.Apply(oCaster, oTarget);
            oTarget.SetLocalInt("CUSTOM_EFFECT_ACTIVE_" + customEffectID, effectLevel);
        }
Example #28
0
        private void ApplyPCEffect(NWCreature caster, NWCreature target, int customEffectID, int ticks, int effectiveLevel, string data)
        {
            Data.Entity.CustomEffect customEffect = _data.Single <Data.Entity.CustomEffect>(x => x.ID == customEffectID);
            PCCustomEffect           pcEffect     = _data.SingleOrDefault <PCCustomEffect>(x => x.PlayerID == target.GlobalID && x.CustomEffectID == customEffectID);
            CustomEffectCategoryType category     = (CustomEffectCategoryType)customEffect.CustomEffectCategoryID;

            if (category == CustomEffectCategoryType.FoodEffect)
            {
                var customEffectPC = _data.Get <Data.Entity.CustomEffect>(pcEffect.CustomEffectID);
                if (pcEffect != null && customEffectPC.CustomEffectCategoryID == (int)category)
                {
                    caster.SendMessage("You are not hungry.");
                    return;
                }
            }

            DatabaseActionType action = DatabaseActionType.Update;

            if (pcEffect == null)
            {
                pcEffect = new PCCustomEffect {
                    PlayerID = target.GlobalID
                };
                action = DatabaseActionType.Insert;
            }

            if (pcEffect.EffectiveLevel > effectiveLevel)
            {
                caster.SendMessage("A more powerful effect already exists on your target.");
                return;
            }

            pcEffect.CustomEffectID    = customEffectID;
            pcEffect.EffectiveLevel    = effectiveLevel;
            pcEffect.Ticks             = ticks;
            pcEffect.CasterNWNObjectID = _.ObjectToString(caster);
            _data.SubmitDataChange(pcEffect, action);

            target.SendMessage(customEffect.StartMessage);

            App.ResolveByInterface <ICustomEffect>("CustomEffect." + customEffect.ScriptHandler, handler =>
            {
                if (string.IsNullOrWhiteSpace(data))
                {
                    data = handler?.Apply(caster, target, effectiveLevel);
                }

                if (string.IsNullOrWhiteSpace(data))
                {
                    data = string.Empty;
                }
                pcEffect.Data = data;
                _data.SubmitDataChange(pcEffect, DatabaseActionType.Update);

                // Was already queued for removal, but got cast again. Take it out of the list to be removed.
                if (_cache.PCEffectsForRemoval.Contains(pcEffect.ID))
                {
                    _cache.PCEffectsForRemoval.Remove(pcEffect.ID);
                }
            });
        }
Example #29
0
        /// <summary>
        /// Runs validation checks to ensure activator can use a perk feat.
        /// Activation will fail if any of the following are true:
        ///     - Target is invalid
        ///     - Activator is a ship
        ///     - Feat is not a perk feat
        ///     - Cooldown has not passed
        /// </summary>
        /// <param name="activator">The creature activating a perk feat.</param>
        /// <param name="target">The target of the perk feat.</param>
        /// <param name="featID">The ID number of the feat being used.</param>
        /// <returns>true if able to use perk feat on target, false otherwise.</returns>
        public static bool CanUsePerkFeat(NWCreature activator, NWObject target, Feat featID)
        {
            var perkFeat = DataService.PerkFeat.GetByFeatIDOrDefault((int)featID);

            // There's no matching feat in the DB for this ability. Exit early.
            if (perkFeat == null)
            {
                return(false);
            }

            // Retrieve the perk information.
            Data.Entity.Perk perk = DataService.Perk.GetByIDOrDefault(perkFeat.PerkID);

            // No perk could be found. Exit early.
            if (perk == null)
            {
                return(false);
            }

            // Check to see if we are a spaceship.  Spaceships can't use abilities...
            if (activator.GetLocalInt("IS_SHIP") > 0 || activator.GetLocalInt("IS_GUNNER") > 0)
            {
                activator.SendMessage("You cannot use that ability while piloting a ship.");
                return(false);
            }

            // Retrieve the perk-specific handler logic.
            var handler = PerkService.GetPerkHandler(perkFeat.PerkID);

            // Get the creature's perk level.
            int creaturePerkLevel = PerkService.GetCreaturePerkLevel(activator, perk.ID);

            // If player is disabling an existing stance, remove that effect.
            if (perk.ExecutionTypeID == PerkExecutionType.Stance)
            {
                // Can't process NPC stances at the moment. Need to do some more refactoring before this is possible.
                // todo: handle NPC stances.
                if (!activator.IsPlayer)
                {
                    return(false);
                }

                PCCustomEffect stanceEffect = DataService.PCCustomEffect.GetByStancePerkOrDefault(activator.GlobalID, perk.ID);

                if (stanceEffect != null)
                {
                    if (CustomEffectService.RemoveStance(activator))
                    {
                        return(false);
                    }
                }
            }

            // Check for a valid perk level.
            if (creaturePerkLevel <= 0)
            {
                activator.SendMessage("You do not meet the prerequisites to use this ability.");
                return(false);
            }

            // Verify that this hostile action meets PVP sanctuary restriction rules.
            if (handler.IsHostile() && target.IsPlayer)
            {
                if (!PVPSanctuaryService.IsPVPAttackAllowed(activator.Object, target.Object))
                {
                    return(false);
                }
            }

            // Activator and target must be in the same area and within line of sight.
            if (activator.Area.Resref != target.Area.Resref ||
                _.LineOfSightObject(activator.Object, target.Object) == false)
            {
                activator.SendMessage("You cannot see your target.");
                return(false);
            }

            // Run this perk's specific checks on whether the activator may use this perk on the target.
            string canCast = handler.CanCastSpell(activator, target, perkFeat.PerkLevelUnlocked);

            if (!string.IsNullOrWhiteSpace(canCast))
            {
                activator.SendMessage(canCast);
                return(false);
            }

            // Calculate the FP cost to use this ability. Verify activator has sufficient FP.
            int fpCost    = handler.FPCost(activator, handler.FPCost(activator, perkFeat.BaseFPCost, perkFeat.PerkLevelUnlocked), perkFeat.PerkLevelUnlocked);
            int currentFP = GetCurrentFP(activator);

            if (currentFP < fpCost)
            {
                activator.SendMessage("You do not have enough FP. (Required: " + fpCost + ". You have: " + currentFP + ")");
                return(false);
            }

            // Verify activator isn't busy or dead.
            if (activator.IsBusy || activator.CurrentHP <= 0)
            {
                activator.SendMessage("You are too busy to activate that ability.");
                return(false);
            }

            // verify activator is commandable. https://github.com/zunath/SWLOR_NWN/issues/940#issue-467175951
            if (!activator.IsCommandable)
            {
                activator.SendMessage("You cannot take actions currently.");
                return(false);
            }

            // If we're executing a concentration ability, check and see if the activator currently has this ability
            // active. If it's active, then we immediately remove its effect and bail out.
            // Any other ability (including other concentration abilities) execute as normal.
            if (perk.ExecutionTypeID == PerkExecutionType.ConcentrationAbility)
            {
                // Retrieve the concentration effect for this creature.
                var concentrationEffect = GetActiveConcentrationEffect(activator);
                if ((int)concentrationEffect.Type == perk.ID)
                {
                    // It's active. Time to disable it.
                    EndConcentrationEffect(activator);
                    activator.SendMessage("Concentration ability '" + perk.Name + "' deactivated.");
                    SendAOEMessage(activator, activator.Name + " deactivates concentration ability '" + perk.Name + "'.");
                    return(false);
                }
            }

            // Retrieve the cooldown information and determine the unlock time.
            int?     cooldownCategoryID = handler.CooldownCategoryID(activator, perk.CooldownCategoryID, perkFeat.PerkLevelUnlocked);
            DateTime now            = DateTime.UtcNow;
            DateTime unlockDateTime = cooldownCategoryID == null ? now : GetAbilityCooldownUnlocked(activator, (int)cooldownCategoryID);

            // Check if we've passed the unlock date. Exit early if we have not.
            if (unlockDateTime > now)
            {
                string timeToWait = TimeService.GetTimeToWaitLongIntervals(now, unlockDateTime, false);
                activator.SendMessage("That ability can be used in " + timeToWait + ".");
                return(false);
            }

            // Passed all checks. Return true.
            return(true);
        }
Example #30
0
        public bool DoesPCHaveCustomEffect(NWPlayer oPC, int customEffectID)
        {
            PCCustomEffect effect = _db.PCCustomEffects.SingleOrDefault(x => x.PlayerID == oPC.GlobalID && x.CustomEffectID == customEffectID);

            return(effect != null);
        }