static App() { // Create the ability service passing to it the resources // folder named "resources" AbilityService = new AbilityService("resources"); Logger.Write.ResourcesLocated("Resources loaded"); }
public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args) { // Did the player pass in the 'end' argument? If so, we're ending the concentration effect. bool doEnd = args.Length > 0 && args[0] == "end"; if (doEnd) { AbilityService.EndConcentrationEffect(user); user.SendMessage("You have ended your concentration ability."); } // Otherwise just notify them about what effect is currently active. else { var effect = AbilityService.GetActiveConcentrationEffect(user); if (effect.Type == PerkType.Unknown) { user.SendMessage("No concentration ability is currently active."); } else { var perk = PerkService.GetPerkByID((int)effect.Type); user.SendMessage("Currently active concentration ability: " + perk.Name); } } }
// GET: Ability public ActionResult Index() { var service = new AbilityService(); var model = service.GetAllAbilities(); return(View(model)); }
static App() { // Create the ability service passing to it the resources // folder named "resources" AbilityService = new AbilityService("resources"); Logger.Write.ResourcesLocated("Resources loaded"); }
/// <summary> /// Gets the user's selected fface Session and /// starts up the program. /// </summary> /// <param name="e"></param> protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); LogViewModel.Write("Resources loaded"); AbilityService = new AbilityService("resources"); LogViewModel.Write("Application starting"); Logger.Log(new LogEntry(LoggingEventType.Information, "EasyFarm Started ...")); }
/// <summary> /// Gets the user's selected fface Session and /// starts up the program. /// </summary> /// <param name="e"></param> protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); LogViewModel.Write("Resources loaded"); AbilityService = new AbilityService("resources"); LogViewModel.Write("Application starting"); Logger.Log(new LogEntry(LoggingEventType.Information, "EasyFarm Started ...")); }
private static void ProcessPerkFeats(NWCreature self) { // Bail early if any of the following is true: // - Creature has a weapon skill queued. // - Creature does not have a PerkFeat cache. // - There are no perk feats in the cache. // - Creature has no target. if (self.GetLocalInt("ACTIVE_WEAPON_SKILL") > 0) { return; } if (!self.Data.ContainsKey("PERK_FEATS")) { return; } Dictionary <int, AIPerkDetails> cache = self.Data["PERK_FEATS"]; if (cache.Count <= 0) { return; } NWObject target = _.GetAttackTarget(self); if (!target.IsValid) { return; } // Pull back whatever concentration effect is currently active, if any. var concentration = AbilityService.GetActiveConcentrationEffect(self); // Exclude any concentration effects, if necessary, then randomize potential feats to use. var randomizedFeatIDs = concentration.Type == PerkType.Unknown ? cache.Values // No concentration exclusions : cache.Values.Where(x => x.ExecutionType != PerkExecutionType.ConcentrationAbility); // Exclude concentration abilities randomizedFeatIDs = randomizedFeatIDs.OrderBy(o => RandomService.Random()); foreach (var perkDetails in randomizedFeatIDs) { // Move to next feat if this creature cannot use this one. if (!AbilityService.CanUsePerkFeat(self, target, perkDetails.FeatID)) { continue; } self.AssignCommand(() => { _.ActionUseFeat(perkDetails.FeatID, target); }); break; } }
/// <summary> /// Revives and heals user completely. /// </summary> /// <param name="user"></param> /// <param name="target"></param> /// <param name="targetLocation"></param> /// <param name="args"></param> public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args) { if (user.IsDead) { _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectResurrection(), user.Object); } _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectHeal(999), user.Object); AbilityService.RestorePlayerFP(user, 9999); }
/// <summary> /// Revives and heals user completely. /// </summary> /// <param name="user"></param> /// <param name="target"></param> /// <param name="targetLocation"></param> /// <param name="args"></param> public void DoAction(NWPlayer user, NWObject target, NWLocation targetLocation, params string[] args) { if (user.IsDead) { _.ApplyEffectToObject(DurationType.Instant, _.EffectResurrection(), user.Object); } _.ApplyEffectToObject(DurationType.Instant, _.EffectHeal(999), user.Object); AbilityService.RestorePlayerFP(user, 9999); }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { float percent = 0.0f; switch (spellTier) { case 1: percent = 0.10f; break; case 2: percent = 0.20f; break; case 3: percent = 0.35f; break; case 4: percent = 0.50f; break; } int recovery = (int)(target.CurrentHP * percent); if (recovery < 1) { recovery = 1; } // Damage user. _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectDamage(recovery), creature); // Check lucky chance. int luck = PerkService.GetCreaturePerkLevel(creature, PerkType.Lucky); if (RandomService.D100(1) <= luck) { recovery *= 2; creature.SendMessage("Lucky Force Body!"); } // Recover FP on target. AbilityService.RestorePlayerFP(target.Object, recovery); // Play VFX _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectVisualEffect(_.VFX_IMP_HEAD_ODD), target); // Grant XP, if player. if (creature.IsPlayer) { SkillService.GiveSkillXP(creature.Object, SkillType.ForceControl, recovery * 2); } }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { float duration = 0.0f; switch (spellTier) { case 1: duration = 6f; break; case 2: duration = 12f; break; case 3: duration = 18f; break; case 4: duration = 24f; break; } var result = CombatService.CalculateAbilityResistance(creature, target.Object, SkillType.ForceAlter, ForceBalanceType.Universal); // Resisted - Only apply slow for six seconds if (result.IsResisted) { _.ApplyEffectToObject(DurationType.Temporary, _.EffectSlow(), target, 6.0f); } // Not resisted - Apply knockdown for the specified duration else { // Check lucky chance. int luck = PerkService.GetCreaturePerkLevel(creature, PerkType.Lucky); if (RandomService.D100(1) <= luck) { duration *= 2; creature.SendMessage("Lucky Force Push!"); } _.ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(target, 3.0f), target, 3.0f); _.ApplyEffectToObject(DurationType.Temporary, _.EffectSlow(), target, duration); } if (creature.IsPlayer) { SkillService.RegisterPCToAllCombatTargetsForSkill(creature.Object, SkillType.ForceAlter, target.Object); } _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Com_Blood_Spark_Small), target); }
public void Ranged_IsCaseInsensitive() { // Fixture setup var sut = new AbilityService(null); // Excercise system var result = sut.GetAbilitiesWithName("ranged").FirstOrDefault(); // Verify outcome Assert.NotNull(result); // Teardown }
/// <summary> /// Gets the user's selected fface Session and /// starts up the program. /// </summary> /// <param name="e"></param> protected override void OnStartup(StartupEventArgs e) { Log.Initialize(); Log.Write("Resources loaded"); AbilityService = new AbilityService("resources"); Log.Write("Application starting"); var bootStrapper = new Bootstrapper(); bootStrapper.Run(); }
public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData) { NWPlayer player = (user.Object); var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player); int rank = SkillService.GetPCSkillRank(player, SkillType.Medicine); int luck = PerkService.GetCreaturePerkLevel(player, PerkType.Lucky); int perkDurationBonus = PerkService.GetCreaturePerkLevel(player, PerkType.HealingKitExpert) * 6 + (luck * 2); float duration = 30.0f + (rank * 0.4f) + perkDurationBonus + effectiveStats.Medicine; int restoreAmount = 1 + item.GetLocalInt("HEALING_BONUS") + (rank / 10); int delta = item.RecommendedLevel - rank; float effectivenessPercent = 1.0f; if (delta > 0) { effectivenessPercent = effectivenessPercent - (delta * 0.1f); } restoreAmount = (int)(restoreAmount * effectivenessPercent) + item.MedicineBonus; int perkBlastBonus = PerkService.GetCreaturePerkLevel(player, PerkType.ImmediateForcePack); if (perkBlastBonus > 0) { int blastHeal = restoreAmount * perkBlastBonus; if (RandomService.Random(100) + 1 <= luck / 2) { blastHeal *= 2; } AbilityService.RestorePlayerFP(target.Object, blastHeal); } float interval = 6.0f; BackgroundType background = (BackgroundType)player.Class1; if (background == BackgroundType.Medic) { interval *= 0.5f; } string data = (int)interval + ", " + restoreAmount; CustomEffectService.ApplyCustomEffect(user, target.Object, CustomEffectType.ForcePack, (int)duration, restoreAmount, data); player.SendMessage("You successfully apply a force pack to " + target.Name + ". The force pack will expire in " + duration + " seconds."); _.DelayCommand(duration + 0.5f, () => { player.SendMessage("The force pack that you applied to " + target.Name + " has expired."); }); int xp = (int)SkillService.CalculateRegisteredSkillLevelAdjustedXP(300, item.RecommendedLevel, rank); SkillService.GiveSkillXP(player, SkillType.Medicine, xp); }
public void Tick(NWCreature oCaster, NWObject oTarget, int currentTick, int effectiveLevel, string data) { string[] split = data.Split(','); int interval = Convert.ToInt32(split[0]); int amount = Convert.ToInt32(split[1]); if (currentTick % interval != 0) { return; } AbilityService.RestorePlayerFP(oTarget.Object, amount); }
public void Tick(NWCreature oCaster, NWObject oTarget, int currentTick, int effectiveLevel, string data) { AbilityService.EndConcentrationEffect(oCaster); NWPlayer player = oTarget.Object; int restTick = oTarget.GetLocalInt("REST_TICK") + 1; // Pull original position from data string[] values = data.Split(','); Vector3 originalPosition = _.Vector3 ( Convert.ToSingle(values[0]), Convert.ToSingle(values[1]), Convert.ToSingle(values[2]) ); // Check position Vector3 position = player.Position; if ((Math.Abs(position.X - originalPosition.X) > 0.01f || Math.Abs(position.Y - originalPosition.Y) > 0.01f || Math.Abs(position.Z - originalPosition.Z) > 0.01f) || !CanRest(player) || !player.IsValid) { player.IsBusy = false; CustomEffectService.RemovePCCustomEffect(player, CustomEffectType.Rest); return; } player.IsBusy = true; player.AssignCommand(() => { _.ActionPlayAnimation(Animation.LoopingSitCross, 1.0f, 6.1f); }); if (restTick >= 6) { int amount = CalculateAmount(player); _.ApplyEffectToObject(DurationType.Instant, _.EffectHeal(amount), player); Effect vfx = _.EffectVisualEffect(VisualEffect.Vfx_Imp_Head_Holy); _.ApplyEffectToObject(DurationType.Instant, vfx, player); restTick = 0; } oTarget.SetLocalInt("REST_TICK", restTick); }
public void Tick(NWCreature oCaster, NWObject oTarget, int currentTick, int effectiveLevel, string data) { AbilityService.EndConcentrationEffect(oCaster); NWPlayer player = oTarget.Object; int restTick = oTarget.GetLocalInt("REST_TICK") + 1; // Pull original position from data string[] values = data.Split(','); Vector originalPosition = _.Vector ( Convert.ToSingle(values[0]), Convert.ToSingle(values[1]), Convert.ToSingle(values[2]) ); // Check position Vector position = player.Position; if ((Math.Abs(position.m_X - originalPosition.m_X) > 0.01f || Math.Abs(position.m_Y - originalPosition.m_Y) > 0.01f || Math.Abs(position.m_Z - originalPosition.m_Z) > 0.01f) || !CanRest(player) || !player.IsValid) { player.IsBusy = false; CustomEffectService.RemovePCCustomEffect(player, CustomEffectType.Rest); return; } player.IsBusy = true; player.AssignCommand(() => { _.ActionPlayAnimation(ANIMATION_LOOPING_SIT_CROSS, 1.0f, 6.1f); }); if (restTick >= 6) { int amount = CalculateAmount(player); _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(amount), player); Effect vfx = _.EffectVisualEffect(VFX_IMP_HEAD_HOLY); _.ApplyEffectToObject(DURATION_TYPE_INSTANT, vfx, player); restTick = 0; } oTarget.SetLocalInt("REST_TICK", restTick); }
public void Ranged_ShouldReturnRangedAttack() { // Fixture setup var sut = new AbilityService(null); // Excercise system var result = sut.GetAbilitiesWithName("Ranged").FirstOrDefault(); // Verify outcome Assert.NotNull(result); Assert.Equal(AbilityType.Range, result.AbilityType); Assert.Equal(TargetType.Enemy, result.TargetType); Assert.Equal("Ranged", result.English); Assert.Equal("/range <t>", result.Command); // Teardown }
public string CanCastSpell(NWCreature oPC, NWObject oTarget, int spellTier) { NWCreature targetCreature = oTarget.Object; var concentrationEffect = AbilityService.GetActiveConcentrationEffect(targetCreature); switch (spellTier) { case 1: if (!oTarget.IsCreature) { return("This ability can only be used on living creatures."); } if (targetCreature.RacialType == (int)CustomRaceType.Robot) { return("This ability cannot be used on droids."); } if (concentrationEffect.Type == PerkType.MindShield) { return("Your target is immune to tranquilization effects."); } break; case 2: if (!oTarget.IsCreature) { return("This ability can only be used on living creatures."); } if (targetCreature.RacialType == (int)CustomRaceType.Robot) { return("This ability cannot be used on droids."); } if (concentrationEffect.Type == PerkType.MindShield) { return("Your target is immune to tranquilization effects."); } break; case 3: break; default: throw new ArgumentOutOfRangeException(nameof(spellTier)); } return(string.Empty); }
private void RunEffect(NWCreature creature, NWObject target) { var concentrationEffect = AbilityService.GetActiveConcentrationEffect(target.Object); if (concentrationEffect.Type == PerkType.MindShield) { creature.SendMessage("Your target is immune to tranquilization effects."); return; } AbilityResistanceResult result = CombatService.CalculateAbilityResistance(creature, target.Object, SkillType.ForceAlter, ForceBalanceType.Dark); // Tranquilization effect - Daze target(s). Occurs on succeeding the DC check. Effect successEffect = EffectDazed(); successEffect = EffectLinkEffects(successEffect, EffectVisualEffect(VisualEffect.Vfx_Dur_Iounstone_Blue)); successEffect = TagEffect(successEffect, "TRANQUILIZER_EFFECT"); // AC & AB decrease effect - Occurs on failing the DC check. Effect failureEffect = EffectLinkEffects(EffectAttackDecrease(5), EffectACDecrease(5)); if (!result.IsResisted) { creature.AssignCommand(() => { ApplyEffectToObject(DurationType.Temporary, successEffect, target, 6.1f); }); } else { creature.AssignCommand(() => { ApplyEffectToObject(DurationType.Temporary, failureEffect, target, 6.1f); }); } if (creature.IsPlayer) { SkillService.RegisterPCToNPCForSkill(creature.Object, target, SkillType.ForceAlter); } EnmityService.AdjustEnmity(target.Object, creature, 1); }
private static void InitializeApp(App app) { Application.Current.DispatcherUnhandledException += (sender, e) => { Logger.Log(new LogEntry(LoggingEventType.Fatal, "Unhandled Exception", e.Exception)); MessageBox.Show(e.Exception.Message, "An exception has occurred. ", MessageBoxButton.OK, MessageBoxImage.Error); }; LogViewModel.Write("Resources loaded"); AbilityService = new AbilityService("resources"); LogViewModel.Write("Application starting"); Logger.Log(new LogEntry(LoggingEventType.Information, "EasyFarm Started ...")); var appBoot = new AppBoot(app); appBoot.Initialize(); appBoot.Navigate <MasterViewModel>(); appBoot.Show(); }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { int damage; float length; switch (perkLevel) { case 1: damage = RandomService.D4(1); length = 6.0f; break; case 2: damage = RandomService.D4(2); length = 6.0f; break; case 3: damage = RandomService.D6(2); length = 6.0f; break; case 4: damage = RandomService.D6(2); length = 9.0f; break; case 5: damage = RandomService.D6(3); length = 9.0f; break; case 6: damage = RandomService.D8(3); length = 9.0f; break; default: return; } _.ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(target, length), target.Object, length); _.ApplyEffectToObject(DurationType.Instant, _.EffectDamage(damage, DamageType.Bludgeoning), target); }
/// <summary> /// Set up session from given EliteApi session. /// </summary> /// <param name="fface"></param> public static void SetSession(IMemoryAPI fface) { if (fface == null) { return; } // Save EliteApi Write FFACE = fface; // Create a new game engine to control our character. GameEngine = new GameEngine(FFACE); // Create path record for navigation PathRecorder = new PathRecorder(FFACE); AbilityService = new AbilityService(FFACE); AutoLoadSettings(); }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { int chance = perkLevel * 25; // Failed to interrupt. if (RandomService.D100(1) > chance) { creature.SendMessage("You fail to interrupt your target's concentration."); return; } NWCreature targetCreature = target.Object; var effect = AbilityService.GetActiveConcentrationEffect(targetCreature); if (effect.Type != PerkType.Unknown) { targetCreature.SendMessage("Your concentration effect has been interrupted by " + creature.Name + "."); AbilityService.EndConcentrationEffect(target.Object); } }
private void SetAttribute(AbilityData abilityData) { int attributeInfoIndex = 0; var abilityDataList = abilityData.GetAbilityDataList(); for (int abilityIndex = 0; abilityIndex < abilityDataList.Count; abilityIndex++) { if (abilityDataList[abilityIndex] == 0) { continue; } var abilityName = AbilityService.GetAbilityNameByIndex(abilityIndex); attributeInfoList[attributeInfoIndex].SetAttributeText($"{abilityName} + {abilityDataList[abilityIndex]}"); attributeInfoList[attributeInfoIndex].OnShow(); ++attributeInfoIndex; } for (int i = attributeInfoIndex; i < attributeInfoList.Count; i++) { attributeInfoList[i].OnHide(); } }
public void DoImpact(NWCreature user, NWItem item, Location targetLocation, string grenadeType, int perkLevel, float fExplosionRadius, ObjectType nObjectFilter) { Effect damageEffect = EffectDamage(0, DamageType.Negative); Effect durationEffect = null; int duration = perkLevel + 1; int bonus = item.DamageBonus; int medbonus = item.MedicineBonus; switch (grenadeType) { case "SMOKE": durationEffect = EffectAreaOfEffect(AreaOfEffect.FogOfBewilderment, "grenade_smoke_en", "grenade_smoke_hb", ""); break; case "BACTABOMB": durationEffect = EffectAreaOfEffect(AreaOfEffect.FogMind, "grenade_bbomb_en", "grenade_bbomb_hb", ""); break; case "INCENDIARY": durationEffect = EffectAreaOfEffect(AreaOfEffect.FogFire, "grenade_incen_en", "grenade_incen_hb", ""); break; case "GAS": durationEffect = EffectAreaOfEffect(AreaOfEffect.FogAcid, "grenade_gas_en", "grenade_gas_hb", ""); break; default: break; } if (durationEffect != null) { //Apply AOE ApplyEffectAtLocation(DurationType.Temporary, durationEffect, targetLocation, duration * 6.0f); } else { //Apply impact // Target the next nearest creature and do the same thing. NWObject targetCreature = GetFirstObjectInShape(Shape.Sphere, fExplosionRadius, targetLocation, true, nObjectFilter); while (targetCreature.IsValid) { //Console.WriteLine("Grenade hit on " + targetCreature.Name); switch (grenadeType) { case "FRAG": damageEffect = EffectDamage(RandomService.D6(perkLevel) + bonus, DamageType.Fire); damageEffect = EffectLinkEffects(EffectDamage(RandomService.D6(perkLevel) + bonus, DamageType.Piercing), damageEffect); if (RandomService.D6(1) > 4) { //Console.WriteLine("grenade effect bleeding - frag"); CustomEffectService.ApplyCustomEffect(user, targetCreature.Object, CustomEffectType.Bleeding, duration * 6, perkLevel, Convert.ToString(perkLevel)); } if (RandomService.D6(1) > 4) { //Console.WriteLine("grenade effects burning - frag"); CustomEffectService.ApplyCustomEffect(user, targetCreature.Object, CustomEffectType.Burning, duration * 6, perkLevel, Convert.ToString(perkLevel)); } //Console.WriteLine("grenade effects set - frag"); break; case "CONCUSSION": damageEffect = EffectDamage(RandomService.D12(perkLevel) + bonus, DamageType.Sonic); durationEffect = EffectDeaf(); if (RandomService.D6(1) > 4) { FloatingTextStringOnCreature("Your ears ring and your body shakes.", targetCreature); durationEffect = EffectLinkEffects(AbilityService.EffectKnockdown(targetCreature, duration), durationEffect); } break; case "FLASHBANG": duration = RandomService.D4(1); durationEffect = EffectDeaf(); if (RandomService.D6(1) > 4) { FloatingTextStringOnCreature("Your vision blurs and blacks out.", targetCreature); durationEffect = EffectLinkEffects(EffectBlindness(), durationEffect); } break; case "ION": duration = RandomService.D4(1); damageEffect = EffectDamage(RandomService.D6(perkLevel) + bonus, DamageType.Electrical); if (GetRacialType(targetCreature) == RacialType.Robot || (RandomService.D6(1) > 4 && GetRacialType(targetCreature) == RacialType.Cyborg)) { FloatingTextStringOnCreature("Your circuits are overloaded.", targetCreature); durationEffect = EffectStunned(); } break; case "BACTA": damageEffect = null; durationEffect = EffectRegenerate(perkLevel + 1 + medbonus, 6.0f); break; case "ADHESIVE": durationEffect = EffectSlow(); if (RandomService.D6(1) > 4) { FloatingTextStringOnCreature("You are slowed by the adhesive explosion.", targetCreature); durationEffect = EffectLinkEffects(EffectCutsceneImmobilize(), durationEffect); } break; default: throw new ArgumentOutOfRangeException(nameof(grenadeType)); } //Console.WriteLine("applying effects to " + GetName(targetCreature)); if (damageEffect != null) { ApplyEffectToObject(DurationType.Instant, damageEffect, targetCreature); } if (durationEffect != null) { ApplyEffectToObject(DurationType.Temporary, durationEffect, targetCreature, duration * 6.0f); } if (!targetCreature.IsPlayer) { SkillService.RegisterPCToNPCForSkill(user.Object, targetCreature, SkillType.Throwing); } targetCreature = GetNextObjectInShape(Shape.Sphere, fExplosionRadius, targetLocation, true, nObjectFilter); } } }
//Service READONLY private AbilityService CreateAbilityService() { var service = new AbilityService(); return(service); }
public bool Run(params object[] args) { using (new Profiler(nameof(FinishAbilityUse))) { NWPlayer pc = (NWPlayer)args[0]; string spellUUID = Convert.ToString(args[1]); int perkID = (int)args[2]; NWObject target = (NWObject)args[3]; int pcPerkLevel = (int)args[4]; int featID = (int)args[5]; Data.Entity.Perk entity = DataService.Single <Data.Entity.Perk>(x => x.ID == perkID); PerkExecutionType executionType = (PerkExecutionType)entity.ExecutionTypeID; IPerkHandler perk = PerkService.GetPerkHandler(perkID); int?cooldownID = perk.CooldownCategoryID(pc, entity.CooldownCategoryID, featID); CooldownCategory cooldown = cooldownID == null ? null : DataService.SingleOrDefault <CooldownCategory>(x => x.ID == cooldownID); if (pc.GetLocalInt(spellUUID) == (int)SpellStatusType.Interrupted || // Moved during casting pc.CurrentHP < 0 || pc.IsDead) // Or is dead/dying { pc.DeleteLocalInt(spellUUID); return(false); } pc.DeleteLocalInt(spellUUID); if (executionType == PerkExecutionType.ForceAbility || executionType == PerkExecutionType.CombatAbility || executionType == PerkExecutionType.Stance) { perk.OnImpact(pc, target, pcPerkLevel, featID); if (entity.CastAnimationID != null && entity.CastAnimationID > 0) { pc.AssignCommand(() => { _.ActionPlayAnimation((int)entity.CastAnimationID, 1f, 1f); }); } if (target.IsNPC) { AbilityService.ApplyEnmity(pc, (target.Object), entity); } } else if (executionType == PerkExecutionType.QueuedWeaponSkill) { AbilityService.HandleQueueWeaponSkill(pc, entity, perk, featID); } // Adjust FP only if spell cost > 0 Data.Entity.Player pcEntity = DataService.Single <Data.Entity.Player>(x => x.ID == pc.GlobalID); int fpCost = perk.FPCost(pc, entity.BaseFPCost, featID); if (fpCost > 0) { pcEntity.CurrentFP = pcEntity.CurrentFP - fpCost; DataService.SubmitDataChange(pcEntity, DatabaseActionType.Update); pc.SendMessage(ColorTokenService.Custom("FP: " + pcEntity.CurrentFP + " / " + pcEntity.MaxFP, 32, 223, 219)); } bool hasChainspell = CustomEffectService.DoesPCHaveCustomEffect(pc, CustomEffectType.Chainspell) && executionType == PerkExecutionType.ForceAbility; if (!hasChainspell && cooldown != null) { // Mark cooldown on category AbilityService.ApplyCooldown(pc, cooldown, perk, featID); } pc.IsBusy = false; pc.SetLocalInt(spellUUID, (int)SpellStatusType.Completed); return(true); } }
public bool Run(params object[] args) { using (new Profiler(nameof(FinishAbilityUse))) { // These arguments are sent from the AbilityService's ActivateAbility method. NWCreature activator = (NWCreature)args[0]; string spellUUID = Convert.ToString(args[1]); int perkID = (int)args[2]; NWObject target = (NWObject)args[3]; int pcPerkLevel = (int)args[4]; int spellTier = (int)args[5]; float armorPenalty = (float)args[6]; // Get the relevant perk information from the database. Data.Entity.Perk dbPerk = DataService.Single <Data.Entity.Perk>(x => x.ID == perkID); // The execution type determines how the perk behaves and the rules surrounding it. PerkExecutionType executionType = dbPerk.ExecutionTypeID; // Get the class which handles this perk's behaviour. IPerkHandler perk = PerkService.GetPerkHandler(perkID); // Pull back cooldown information. int?cooldownID = perk.CooldownCategoryID(activator, dbPerk.CooldownCategoryID, spellTier); CooldownCategory cooldown = cooldownID == null ? null : DataService.SingleOrDefault <CooldownCategory>(x => x.ID == cooldownID); // If the activator interrupted the spell or died, we can bail out early. if (activator.GetLocalInt(spellUUID) == (int)SpellStatusType.Interrupted || // Moved during casting activator.CurrentHP < 0 || activator.IsDead) // Or is dead/dying { activator.DeleteLocalInt(spellUUID); return(false); } // Remove the temporary UUID which is tracking this spell cast. activator.DeleteLocalInt(spellUUID); // Force Abilities, Combat Abilities, Stances, and Concentration Abilities if (executionType == PerkExecutionType.ForceAbility || executionType == PerkExecutionType.CombatAbility || executionType == PerkExecutionType.Stance || executionType == PerkExecutionType.ConcentrationAbility) { // Run the impact script. perk.OnImpact(activator, target, pcPerkLevel, spellTier); // If an animation is specified for this perk, play it now. if (dbPerk.CastAnimationID != null && dbPerk.CastAnimationID > 0) { activator.AssignCommand(() => { _.ActionPlayAnimation((int)dbPerk.CastAnimationID, 1f, 1f); }); } // If the target is an NPC, assign enmity towards this creature for that NPC. if (target.IsNPC) { AbilityService.ApplyEnmity(activator, target.Object, dbPerk); } } // Adjust creature's current FP, if necessary. // Adjust FP only if spell cost > 0 PerkFeat perkFeat = DataService.Single <PerkFeat>(x => x.PerkID == perkID && x.PerkLevelUnlocked == spellTier); int fpCost = perk.FPCost(activator, perkFeat.BaseFPCost, spellTier); if (fpCost > 0) { int currentFP = AbilityService.GetCurrentFP(activator); int maxFP = AbilityService.GetMaxFP(activator); currentFP -= fpCost; AbilityService.SetCurrentFP(activator, currentFP); activator.SendMessage(ColorTokenService.Custom("FP: " + currentFP + " / " + maxFP, 32, 223, 219)); } // Notify activator of concentration ability change and also update it in the DB. if (executionType == PerkExecutionType.ConcentrationAbility) { AbilityService.StartConcentrationEffect(activator, perkID, spellTier); activator.SendMessage("Concentration ability activated: " + dbPerk.Name); // The Skill Increase effect icon and name has been overwritten. Apply the effect to the player now. // This doesn't do anything - it simply gives a visual cue that the player has an active concentration effect. _.ApplyEffectToObject(_.DURATION_TYPE_PERMANENT, _.EffectSkillIncrease(_.SKILL_USE_MAGIC_DEVICE, 1), activator); } // Handle applying cooldowns, if necessary. if (cooldown != null) { AbilityService.ApplyCooldown(activator, cooldown, perk, spellTier, armorPenalty); } // Mark the creature as no longer busy. activator.IsBusy = false; // Mark the spell cast as complete. activator.SetLocalInt(spellUUID, (int)SpellStatusType.Completed); return(true); } }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { int massLevel = PerkService.GetCreaturePerkLevel(creature, PerkType.MassTranquilizer); int tranqLevel = PerkService.GetCreaturePerkLevel(creature, PerkType.Tranquilizer); int luck = PerkService.GetCreaturePerkLevel(creature, PerkType.Lucky); float duration; float range = 5 * massLevel; switch (tranqLevel) { case 0: duration = 6; break; case 1: duration = 12; break; case 2: duration = 24; break; case 3: duration = 36; break; case 4: duration = 48; break; case 5: duration = 60; break; case 6: duration = 72; break; case 7: duration = 84; break; case 8: duration = 96; break; case 9: duration = 108; break; case 10: duration = 120; break; default: return; } if (RandomService.D100(1) <= luck) { duration *= 2; creature.SendMessage("Lucky shot!"); } // Check if Mind Shield is on target. var concentrationEffect = AbilityService.GetActiveConcentrationEffect(target.Object); if (concentrationEffect.Type == PerkType.MindShield) { creature.SendMessage("Your target is immune to tranquilization effects."); } else { // Apply to the target. if (!RemoveExistingEffect(target, duration)) { target.SetLocalInt("TRANQUILIZER_EFFECT_FIRST_RUN", 1); Effect effect = _.EffectDazed(); effect = _.EffectLinkEffects(effect, _.EffectVisualEffect(VFX_DUR_IOUNSTONE_BLUE)); effect = _.TagEffect(effect, "TRANQUILIZER_EFFECT"); _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, effect, target, duration); } } // Iterate over all nearby hostiles. Apply the effect to them if they meet the criteria. int current = 1; NWCreature nearest = _.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, target, current); while (nearest.IsValid) { float distance = _.GetDistanceBetween(nearest, target); // Check distance. Exit loop if we're too far. if (distance > range) { break; } concentrationEffect = AbilityService.GetActiveConcentrationEffect(nearest); // If this creature isn't hostile to the attacking player or if this creature is already tranquilized, move to the next one. if (_.GetIsReactionTypeHostile(nearest, creature) == FALSE || nearest.Object == target.Object || RemoveExistingEffect(nearest, duration) || concentrationEffect.Type == PerkType.MindShield) { current++; nearest = _.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, target, current); continue; } target.SetLocalInt("TRANQUILIZER_EFFECT_FIRST_RUN", 1); Effect effect = _.EffectDazed(); effect = _.EffectLinkEffects(effect, _.EffectVisualEffect(VFX_DUR_IOUNSTONE_BLUE)); effect = _.TagEffect(effect, "TRANQUILIZER_EFFECT"); _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, effect, nearest, duration); current++; nearest = _.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, TRUE, target, current); } }
private void ApplyEffect(NWCreature creature, NWObject target, int spellTier) { int strBonus; int conBonus; int acPenalty; int hpPenalty; int attacks; // Figure out what the bonuses are for this spell tier. switch (spellTier) { case 1: strBonus = 2; conBonus = 2; acPenalty = 2; hpPenalty = 2; attacks = 0; break; case 2: strBonus = 4; conBonus = 4; acPenalty = 2; hpPenalty = 4; attacks = 0; break; case 3: strBonus = 6; conBonus = 6; acPenalty = 4; hpPenalty = 6; attacks = 1; break; case 4: strBonus = 8; conBonus = 8; acPenalty = 4; hpPenalty = 8; attacks = 1; break; case 5: strBonus = 10; conBonus = 10; acPenalty = 6; hpPenalty = 10; attacks = 2; break; default: throw new ArgumentOutOfRangeException(nameof(spellTier)); } // If creature can't afford the HP hit for this tick, bail out early. if (target.CurrentHP < hpPenalty) { AbilityService.EndConcentrationEffect(creature); creature.SendMessage("Concentration effect has ended because you do not have enough HP to maintain it."); return; } // Build a linked effect which handles applying these bonuses and penalties. Effect strEffect = _.EffectAbilityIncrease(_.ABILITY_STRENGTH, strBonus); Effect conEffect = _.EffectAbilityIncrease(_.ABILITY_CONSTITUTION, conBonus); Effect acEffect = _.EffectACDecrease(acPenalty); Effect attackEffect = _.EffectModifyAttacks(attacks); Effect finalEffect = _.EffectLinkEffects(strEffect, conEffect); finalEffect = _.EffectLinkEffects(finalEffect, acEffect); // Only apply the attack effect if this spell tier increases it. if (attacks > 0) { finalEffect = _.EffectLinkEffects(finalEffect, attackEffect); } finalEffect = _.TagEffect(finalEffect, "FORCE_ABILITY_RAGE"); Effect damageEffect = _.EffectDamage(hpPenalty); // Apply both effects. _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, damageEffect, target); _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, finalEffect, target, 6.1f); }
private void ApplyEffect(NWCreature creature, NWObject target, int spellTier) { int strBonus; int conBonus; int acPenalty; int hpPenalty; int attacks; // Figure out what the bonuses are for this spell tier. switch (spellTier) { case 1: strBonus = 2; conBonus = 2; acPenalty = 0; hpPenalty = 2; attacks = 0; break; case 2: strBonus = 4; conBonus = 4; acPenalty = 0; hpPenalty = 4; attacks = 0; break; case 3: strBonus = 6; conBonus = 6; acPenalty = 0; hpPenalty = 6; attacks = 1; break; case 4: strBonus = 8; conBonus = 8; acPenalty = 0; hpPenalty = 8; attacks = 1; break; case 5: strBonus = 10; conBonus = 10; acPenalty = 0; hpPenalty = 10; attacks = 2; break; default: throw new ArgumentOutOfRangeException(nameof(spellTier)); } // If creature can't afford the HP hit for this tick, bail out early. if (target.CurrentHP < hpPenalty) { AbilityService.EndConcentrationEffect(creature); creature.SendMessage("Concentration effect has ended because you do not have enough HP to maintain it."); return; } // Build a linked effect which handles applying these bonuses and penalties. Effect visualEffect = _.EffectVisualEffect(VisualEffect.Vfx_Dur_Aura_Red); Effect strEffect = _.EffectAbilityIncrease(AbilityType.Strength, strBonus); Effect conEffect = _.EffectAbilityIncrease(AbilityType.Constitution, conBonus); Effect acEffect = _.EffectACDecrease(0); Effect attackEffect = _.EffectModifyAttacks(attacks); Effect finalEffect = _.EffectLinkEffects(strEffect, conEffect); finalEffect = _.EffectLinkEffects(finalEffect, acEffect); // Only apply the attack effect if this spell tier increases it. if (attacks > 0) { finalEffect = _.EffectLinkEffects(finalEffect, attackEffect); } finalEffect = _.TagEffect(finalEffect, "FORCE_ABILITY_RAGE"); Effect damageEffect = _.EffectDamage(hpPenalty, DamageType.Divine); // Apply both effects. creature.AssignCommand(() => { _.ApplyEffectToObject(DurationType.Instant, damageEffect, creature.Object); _.ApplyEffectToObject(DurationType.Temporary, finalEffect, creature.Object, 6.1f); _.ApplyEffectToObject(DurationType.Temporary, visualEffect, creature.Object, 6.1f); }); }