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); } } }
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; } }
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); }
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); } }
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); } }
public void OnImpact(NWCreature creature, NWObject target, int perkLevel, int spellTier) { var concentrationEffect = AbilityService.GetActiveConcentrationEffect(target.Object); if (concentrationEffect.Type == PerkType.MindShield) { creature.SendMessage("Your target is immune to tranquilization effects."); return; } int luck = PerkService.GetCreaturePerkLevel(creature, PerkType.Lucky); float duration; switch (perkLevel) { 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!"); } if (RemoveExistingEffect(target, duration)) { creature.SendMessage("A more powerful effect already exists on your target."); return; } 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); }
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; } // todo: GetEffectType() returns EFFECT_TYPE_INVALIDEFFECT for knockdown effects. // todo: The following code is causing a segfault crash... look into other solutions or figure out what's causing that. // target.Effects.Any(x => NWNXEffect.UnpackEffect(x).Type == (int)EffectTypeEngine.Knockdown) || // Potential workaround: if (target.GetLocalBool("KNOCKDOWN")) return; if (target.GetLocalBool("KNOCKDOWN")) { return; } if (target.Effects.Any(x => _.GetEffectTag(x) == "TRANQUILIZER_EFFECT")) { 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, (Feat)perkDetails.FeatID)) { continue; } self.AssignCommand(() => { _.ActionUseFeat((Feat)perkDetails.FeatID, target); }); break; } }