private static void HandleQueueWeaponSkill(NWCreature activator, Data.Entity.Perk entity, IPerkHandler ability, Feat spellFeatID) { var perkFeat = DataService.PerkFeat.GetByFeatID((int)spellFeatID); int? cooldownCategoryID = ability.CooldownCategoryID(activator, entity.CooldownCategoryID, perkFeat.PerkLevelUnlocked); var cooldownCategory = DataService.CooldownCategory.GetByID(Convert.ToInt32(cooldownCategoryID)); string queueUUID = Guid.NewGuid().ToString(); activator.SetLocalInt("ACTIVE_WEAPON_SKILL", entity.ID); activator.SetLocalString("ACTIVE_WEAPON_SKILL_UUID", queueUUID); activator.SetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID", (int)spellFeatID); activator.SendMessage("Weapon skill '" + entity.Name + "' queued for next attack."); SendAOEMessage(activator, activator.Name + " readies weapon skill '" + entity.Name + "'."); ApplyCooldown(activator, cooldownCategory, ability, perkFeat.PerkLevelUnlocked, 0.0f); // Player must attack within 30 seconds after queueing or else it wears off. _.DelayCommand(30f, () => { if (activator.GetLocalString("ACTIVE_WEAPON_SKILL_UUID") == queueUUID) { activator.DeleteLocalInt("ACTIVE_WEAPON_SKILL"); activator.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID"); activator.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID"); activator.SendMessage("Your weapon skill '" + entity.Name + "' is no longer queued."); SendAOEMessage(activator, activator.Name + " no longer has weapon skill '" + entity.Name + "' readied."); } }); }
/// <summary> /// Ends a creature's concentration effect immediately. /// No message is sent by this method, so be sure to send one if you need to inform a player. /// </summary> /// <param name="creature">The creatures whose concentration we're ending.</param> public static void EndConcentrationEffect(NWCreature creature) { if (creature.IsPlayer) { Player player = DataService.Player.GetByID(creature.GlobalID); if (player.ActiveConcentrationPerkID == null) { return; } player.ActiveConcentrationPerkID = null; player.ActiveConcentrationTier = 0; DataService.SubmitDataChange(player, DatabaseActionType.Update); } else { creature.DeleteLocalInt("ACTIVE_CONCENTRATION_PERK_ID"); } creature.DeleteLocalInt("ACTIVE_CONCENTRATION_ABILITY_TICK"); creature.DeleteLocalObject("CONCENTRATION_TARGET"); creature.RemoveEffect(EffectTypeScript.SkillIncrease); // Remove the effect icon. ConcentratingCreatures.Remove(creature); }
private void ApplyEffect(NWCreature creature, NWObject target, int spellTier) { Effect effectMindShield; // Handle effects for differing spellTier values switch (spellTier) { case 1: effectMindShield = _.EffectImmunity(ImmunityType.Dazed); creature.AssignCommand(() => { _.ApplyEffectToObject(DurationType.Temporary, effectMindShield, target, 6.1f); }); break; case 2: effectMindShield = _.EffectImmunity(ImmunityType.Dazed); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(ImmunityType.Confused)); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(ImmunityType.Dominate)); // Force Pursuade is DOMINATION effect creature.AssignCommand(() => { _.ApplyEffectToObject(DurationType.Temporary, effectMindShield, target, 6.1f); }); break; case 3: effectMindShield = _.EffectImmunity(ImmunityType.Dazed); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(ImmunityType.Confused)); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(ImmunityType.Dominate)); // Force Pursuade is DOMINATION effect if (target.GetLocalInt("FORCE_DRAIN_IMMUNITY") == 1) { creature.SetLocalInt("FORCE_DRAIN_IMMUNITY", 0); } creature.DelayAssignCommand(() => { creature.DeleteLocalInt("FORCE_DRAIN_IMMUNITY"); }, 6.1f); creature.AssignCommand(() => { _.ApplyEffectToObject(DurationType.Temporary, effectMindShield, target, 6.1f); }); break; default: throw new ArgumentOutOfRangeException(nameof(spellTier)); } // Play VFX _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Dur_Mind_Affecting_Positive), target); if (creature.IsPlayer) { SkillService.RegisterPCToAllCombatTargetsForSkill(creature.Object, SkillType.ForceControl, null); } }
private void ApplyEffect(NWCreature creature, NWObject target, int spellTier) { Effect effectMindShield; // Handle effects for differing spellTier values switch (spellTier) { case 1: effectMindShield = _.EffectImmunity(IMMUNITY_TYPE_DAZED); creature.AssignCommand(() => { _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, effectMindShield, target, 6.1f); }); break; case 2: effectMindShield = _.EffectImmunity(IMMUNITY_TYPE_DAZED); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(IMMUNITY_TYPE_CONFUSED)); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(IMMUNITY_TYPE_DOMINATE)); // Force Pursuade is DOMINATION effect creature.AssignCommand(() => { _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, effectMindShield, target, 6.1f); }); break; case 3: effectMindShield = _.EffectImmunity(IMMUNITY_TYPE_DAZED); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(IMMUNITY_TYPE_CONFUSED)); effectMindShield = _.EffectLinkEffects(effectMindShield, _.EffectImmunity(IMMUNITY_TYPE_DOMINATE)); // Force Pursuade is DOMINATION effect if (target.GetLocalInt("FORCE_DRAIN_IMMUNITY") == 1) { creature.SetLocalInt("FORCE_DRAIN_IMMUNITY", 0); } creature.DelayAssignCommand(() => { creature.DeleteLocalInt("FORCE_DRAIN_IMMUNITY"); }, 6.1f); creature.AssignCommand(() => { _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, effectMindShield, target, 6.1f); }); break; default: throw new ArgumentOutOfRangeException(nameof(spellTier)); } // Play VFX _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectVisualEffect(_.VFX_DUR_MIND_AFFECTING_POSITIVE), target); }
public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData) { NWPlayer player = user.Object; ResourceQuality quality = (ResourceQuality)target.GetLocalInt("RESOURCE_QUALITY"); int tier = target.GetLocalInt("RESOURCE_TIER"); int remaining = target.GetLocalInt("RESOURCE_COUNT") - 1; string itemResref = target.GetLocalString("RESOURCE_RESREF"); int gemChance = ResourceService.CalculateChanceForComponentBonus(player, tier, quality); int roll = RandomService.Random(1, 100); int rank = SkillService.GetPCSkillRank(player, SkillType.Harvesting); if (item.RecommendedLevel < rank) { rank = item.RecommendedLevel; } int difficulty = (tier - 1) * 10 + ResourceService.GetDifficultyAdjustment(quality); int delta = difficulty - rank; int baseXP = 0; if (delta >= 6) { baseXP = 400; } else if (delta == 5) { baseXP = 350; } else if (delta == 4) { baseXP = 325; } else if (delta == 3) { baseXP = 300; } else if (delta == 2) { baseXP = 250; } else if (delta == 1) { baseXP = 225; } else if (delta == 0) { baseXP = 200; } else if (delta == -1) { baseXP = 150; } else if (delta == -2) { baseXP = 100; } else if (delta == -3) { baseXP = 50; } else if (delta == -4) { baseXP = 25; } int itemHarvestBonus = item.HarvestingBonus; int scanningBonus = user.GetLocalInt(target.GlobalID.ToString()); gemChance += itemHarvestBonus * 2 + scanningBonus * 2; baseXP = baseXP + scanningBonus * 5; // Spawn the normal resource. NWItem resource = CreateItemOnObject(itemResref, player); user.SendMessage("You harvest " + resource.Name + "."); // If player meets the chance to acquire a gem, create one and modify its properties. if (quality > ResourceQuality.Low && roll <= gemChance) { // Gemstone quality is determined by the quality of the vein. switch (quality) { case ResourceQuality.Normal: resource = CreateItemOnObject("flawed_gemstone", player); break; case ResourceQuality.High: resource = CreateItemOnObject("gemstone", player); break; case ResourceQuality.VeryHigh: resource = CreateItemOnObject("perfect_gemstone", player); break; } var ip = ResourceService.GetRandomComponentBonusIP(quality); BiowareXP2.IPSafeAddItemProperty(resource, ip.Item1, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); switch (ip.Item2) { case 0: resource.Name = ColorTokenService.Green(resource.Name); break; case 1: resource.Name = ColorTokenService.Blue(resource.Name); break; case 2: resource.Name = ColorTokenService.Purple(resource.Name); break; case 3: resource.Name = ColorTokenService.Orange(resource.Name); break; case 4: resource.Name = ColorTokenService.LightPurple(resource.Name); break; case 5: resource.Name = ColorTokenService.Yellow(resource.Name); break; case 6: resource.Name = ColorTokenService.Red(resource.Name); break; case 7: resource.Name = ColorTokenService.Cyan(resource.Name); break; } user.SendMessage("You harvest " + resource.Name + "."); } float decayMinimum = 0.03f; float decayMaximum = 0.07f; if (delta > 0) { decayMinimum += delta * 0.1f; decayMaximum += delta * 0.1f; } DurabilityService.RunItemDecay(player, item, RandomService.RandomFloat(decayMinimum, decayMaximum)); int xp = baseXP; SkillService.GiveSkillXP(player, SkillType.Harvesting, xp); if (remaining <= 0) { NWPlaceable prop = target.GetLocalObject("RESOURCE_PROP_OBJ"); if (prop.IsValid) { prop.Destroy(); } target.Destroy(); user.DeleteLocalInt(target.GlobalID.ToString()); } else { target.SetLocalInt("RESOURCE_COUNT", remaining); } ApplyEffectAtLocation(DurationType.Instant, EffectVisualEffect(VisualEffect.Vfx_Fnf_Summon_Monster_3), target.Location); }
public void ApplyEffects(NWCreature user, NWItem item, NWObject target, Location targetLocation, CustomData customData) { NWPlayer player = user.Object; ResourceQuality quality = (ResourceQuality)target.GetLocalInt("RESOURCE_QUALITY"); int tier = target.GetLocalInt("RESOURCE_TIER"); int remaining = target.GetLocalInt("RESOURCE_COUNT") - 1; string itemResref = target.GetLocalString("RESOURCE_RESREF"); int ipBonusChance = _resource.CalculateChanceForComponentBonus(player, tier, quality); int roll = _random.Random(1, 100); int rank = _skill.GetPCSkillRank(player, SkillType.Harvesting); if (item.RecommendedLevel < rank) { rank = item.RecommendedLevel; } int difficulty = (tier - 1) * 10 + _resource.GetDifficultyAdjustment(quality); int delta = difficulty - rank; int baseXP = 0; if (delta >= 6) { baseXP = 400; } else if (delta == 5) { baseXP = 350; } else if (delta == 4) { baseXP = 325; } else if (delta == 3) { baseXP = 300; } else if (delta == 2) { baseXP = 250; } else if (delta == 1) { baseXP = 225; } else if (delta == 0) { baseXP = 200; } else if (delta == -1) { baseXP = 150; } else if (delta == -2) { baseXP = 100; } else if (delta == -3) { baseXP = 50; } else if (delta == -4) { baseXP = 25; } int itemHarvestBonus = item.HarvestingBonus; int scanningBonus = user.GetLocalInt(target.GlobalID.ToString()); ipBonusChance += itemHarvestBonus * 2 + scanningBonus * 2; baseXP = baseXP + scanningBonus * 5; NWItem resource = _.CreateItemOnObject(itemResref, player.Object); if (roll <= ipBonusChance) { var ip = _resource.GetRandomComponentBonusIP(quality); _biowareXP2.IPSafeAddItemProperty(resource, ip.Item1, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true); switch (ip.Item2) { case 0: resource.Name = _color.Green(resource.Name); break; case 1: resource.Name = _color.Blue(resource.Name); break; case 2: resource.Name = _color.Purple(resource.Name); break; case 3: resource.Name = _color.Orange(resource.Name); break; } } float decayMinimum = 0.03f; float decayMaximum = 0.07f; if (delta > 0) { decayMinimum += delta * 0.1f; decayMaximum += delta * 0.1f; } user.SendMessage("You harvest " + resource.Name + "."); _durability.RunItemDecay(player, item, _random.RandomFloat(decayMinimum, decayMaximum)); int xp = baseXP; _skill.GiveSkillXP(player, SkillType.Harvesting, xp); if (remaining <= 0) { NWPlaceable prop = target.GetLocalObject("RESOURCE_PROP_OBJ"); if (prop.IsValid) { prop.Destroy(); } target.Destroy(); user.DeleteLocalInt(target.GlobalID.ToString()); } else { target.SetLocalInt("RESOURCE_COUNT", remaining); } _.ApplyEffectAtLocation(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3), target.Location); }
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); } }
private bool UseFeat(int featID, string featName, NWCreature caster, NWCreature target) { // Note - this code is loosely based on code from AbilityService. However, the perk interface // is written assuming players will always be using perks. To allow NPCs to use them requires some hackery. int perkLevel = (int)caster.ChallengeRating / 5; if (perkLevel < 1) { perkLevel = 1; } if (caster.Area.Resref != target.Area.Resref || _.LineOfSightObject(caster.Object, target.Object) == 0) { return(false); } // Give NPCs a bit longer range than most PCs. if (_.GetDistanceBetween(caster, target) > 20.0f) { return(false); } // Note - NPCs are assumed to have infinite FPs. if (_.GetIsDead(caster) == 1) { return(false); } // Cooldown of 1 round. string timeout = caster.GetLocalString("TIMEOUT_" + featName); DateTime unlockTime = DateTime.UtcNow; if (!string.IsNullOrWhiteSpace(timeout)) { unlockTime = DateTime.Parse(timeout); } DateTime now = DateTime.UtcNow; if (unlockTime > now) { return(false); } else { unlockTime = now.AddSeconds(6); caster.SetLocalString("TIMEOUT_" + featName, unlockTime.ToString()); } // Do the actual force attack. Code taken from perks. if (featID == (int)CustomFeatType.ForceLightning) { int length; int dotAmount; int basePotency; const float Tier1Modifier = 1.0f; const float Tier2Modifier = 1.6f; const float Tier3Modifier = 2.2f; const float Tier4Modifier = 0; switch (perkLevel) { case 1: basePotency = 15; length = 0; dotAmount = 0; break; case 2: basePotency = 20; length = 6; dotAmount = 4; break; case 3: basePotency = 25; length = 6; dotAmount = 6; break; case 4: basePotency = 40; length = 12; dotAmount = 6; break; case 5: basePotency = 50; length = 12; dotAmount = 6; break; case 6: basePotency = 60; length = 12; dotAmount = 6; break; case 7: basePotency = 70; length = 12; dotAmount = 6; break; case 8: basePotency = 80; length = 12; dotAmount = 8; break; case 9: basePotency = 90; length = 12; dotAmount = 8; break; default: basePotency = 100; length = 12; dotAmount = 10; break; } var calc = CombatService.CalculateForceDamage( caster, target.Object, ForceAbilityType.Electrical, basePotency, Tier1Modifier, Tier2Modifier, Tier3Modifier, Tier4Modifier); caster.AssignCommand(() => { _.SetFacingPoint(target.Location.Position); _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, 1.0f); }); caster.SetLocalInt("CASTING", 1); _.DelayCommand(1.0f, () => { caster.AssignCommand(() => { Effect damage = _.EffectDamage(calc.Damage, DAMAGE_TYPE_ELECTRICAL); _.ApplyEffectToObject(DURATION_TYPE_INSTANT, damage, target); }); if (length > 0.0f && dotAmount > 0) { CustomEffectService.ApplyCustomEffect(caster, target.Object, CustomEffectType.ForceShock, length, perkLevel, dotAmount.ToString()); } caster.AssignCommand(() => { _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectVisualEffect(VFX_BEAM_LIGHTNING), target, 1.0f); caster.DeleteLocalInt("CASTING"); }); CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Electrical); }); } else if (featID == (int)CustomFeatType.DrainLife) { float recoveryPercent; int basePotency; const float Tier1Modifier = 1; const float Tier2Modifier = 2; const float Tier3Modifier = 0; const float Tier4Modifier = 0; switch (perkLevel) { case 1: basePotency = 10; recoveryPercent = 0.2f; break; case 2: basePotency = 15; recoveryPercent = 0.2f; break; case 3: basePotency = 20; recoveryPercent = 0.4f; break; case 4: basePotency = 25; recoveryPercent = 0.4f; break; default: basePotency = 30; recoveryPercent = 0.5f; break; } var calc = CombatService.CalculateForceDamage( caster, target.Object, ForceAbilityType.Dark, basePotency, Tier1Modifier, Tier2Modifier, Tier3Modifier, Tier4Modifier); caster.AssignCommand(() => { _.SetFacingPoint(target.Location.Position); _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, 1.0f); }); caster.SetLocalInt("CASTING", 1); _.DelayCommand(1.0f, () => { _.AssignCommand(caster, () => { int heal = (int)(calc.Damage * recoveryPercent); if (heal > target.CurrentHP) { heal = target.CurrentHP; } _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDamage(calc.Damage), target); _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(heal), caster); _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectVisualEffect(VFX_BEAM_MIND), target, 1.0f); caster.DeleteLocalInt("CASTING"); }); }); CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Dark); } return(true); }