private static void _DoWindKnockdown(NWObject oCreature) { LoggingService.Trace(TraceComponent.Weather, "Checking whether " + GetName(oCreature) + " is blown over"); int nDC = (GetHitDice(oCreature) / 2) + 10; int nDiscipline = GetSkillRank(Skill.Discipline, oCreature); int nReflexSave = GetReflexSavingThrow(oCreature); int nSuccess; if (nDiscipline > nReflexSave) { nSuccess = GetIsSkillSuccessful(oCreature, Skill.Discipline, nDC) ? 1 : 0; } else { nSuccess = ReflexSave(oCreature, nDC) == SaveReturn.Success ? 1 : 0; } if (nSuccess == 0) { ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(oCreature, 6.0f), oCreature, 6.0f); FloatingTextStringOnCreature("*is unbalanced by a strong gust*", oCreature); } }
private static void HandleFPRegenerationTick(NWPlayer oPC, Player entity) { entity.CurrentFPTick = entity.CurrentFPTick - 1; int rate = 5; int amount = 1; if (entity.CurrentFPTick <= 0) { if (entity.CurrentFP < entity.MaxFP) { var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC); // CHA bonus int cha = oPC.CharismaModifier; if (cha > 0) { amount += cha; } amount += effectiveStats.FPRegen; if (oPC.Chest.CustomItemType == CustomItemType.ForceArmor) { int clarityLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.Clarity); if (clarityLevel > 0) { amount += clarityLevel + 1; } } entity = AbilityService.RestorePlayerFP(oPC, amount, entity); } entity.CurrentFPTick = rate; } }
private static void _Thunderstorm(NWLocation lLocation, int nPower) { float fRange = IntToFloat(nPower) * 0.1f; // Caps on sphere of influence if (fRange < 3.0) { fRange = 3.0f; } if (fRange > 6.0) { fRange = 6.0f; } //Effects Effect eEffBolt = EffectVisualEffect(VisualEffect.Vfx_Imp_Lightning_M); ApplyEffectAtLocation(DurationType.Instant, eEffBolt, lLocation); Effect eEffDam; ObjectType nType; NWObject oObject = GetFirstObjectInShape(Shape.Sphere, fRange, lLocation, false, ObjectType.Creature | ObjectType.Door | ObjectType.Placeable); while (GetIsObjectValid(oObject)) { nType = GetObjectType(oObject); if (nType == ObjectType.Creature || nType == ObjectType.Door || nType == ObjectType.Placeable) { eEffDam = EffectDamage( FloatToInt(IntToFloat(nPower) - (GetDistanceBetweenLocations(lLocation, GetLocation(oObject)) * 10.0f)), DamageType.Electrical); ApplyEffectToObject(DurationType.Instant, eEffDam, oObject); if (nType == ObjectType.Creature) { if (GetIsPC(oObject)) { SendMessageToPC(oObject, FB_T_WEATHER_LIGHTNING); } PlayVoiceChat(VoiceChat.Pain1, oObject); float duration = IntToFloat(d6(1)); ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(oObject, duration), oObject, duration); } } oObject = GetNextObjectInShape(Shape.Sphere, fRange, lLocation, false, ObjectType.Creature | ObjectType.Door | ObjectType.Placeable); } }
private static void HandleGrenadeProficiency(NWPlayer oPC, NWObject target) { NWItem weapon = _.GetSpellCastItem(); if (weapon.BaseItemType != BaseItem.Grenade) { return; } int perkLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.GrenadeProficiency); int chance = 10 * perkLevel; float duration; switch (perkLevel) { case 1: case 2: case 3: case 4: duration = 6; break; case 5: case 6: case 7: case 8: case 9: duration = 9; break; default: return; } if (RandomService.D100(1) <= chance) { _.ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(target, duration), target, duration); } }
private static void HandleAbsorptionFieldEffect() { DamageEventData data = NWNXDamage.GetDamageEventData(); if (data.Total <= 0) { return; } NWObject target = NWGameObject.OBJECT_SELF; if (!target.IsPlayer) { return; } NWPlayer player = target.Object; int effectLevel = CustomEffectService.GetCustomEffectLevel(player, CustomEffectType.AbsorptionField); if (effectLevel <= 0) { return; } // Remove effect if player activates ability and removes the armor. if (player.Chest.CustomItemType != CustomItemType.ForceArmor) { CustomEffectService.RemovePCCustomEffect(player, CustomEffectType.AbsorptionField); } float absorptionRate = effectLevel * 0.1f; int absorbed = (int)(data.Total * absorptionRate); if (absorbed < 1) { absorbed = 1; } AbilityService.RestorePlayerFP(player, absorbed); }
private static void HandleDamageImmunity() { DamageEventData data = NWNXDamage.GetDamageEventData(); if (data.Total <= 0) { return; } NWCreature target = NWGameObject.OBJECT_SELF; NWItem shield = target.LeftHand; var concentrationEffect = AbilityService.GetActiveConcentrationEffect(target); double reduction = 0.0f; // Shield damage reduction and absorb energy are calculated here. They don't stack, so the one // with the highest reduction will take precedence. // Calculate shield damage reduction. if (ItemService.ShieldBaseItemTypes.Contains(shield.BaseItemType)) { // Apply damage scaling based on shield presence int perkLevel = PerkService.GetCreaturePerkLevel(target.Object, PerkType.ShieldProficiency); float perkBonus = 0.02f * perkLevel; // DI = 10% + 1% / 3 AC bonuses on the shield + 2% per perk bonus. reduction = (0.1 + 0.01 * shield.AC / 3) + perkBonus; } // Calculate Absorb Energy concentration effect reduction. if (concentrationEffect.Type == PerkType.AbsorbEnergy) { double perkReduction = concentrationEffect.Tier * 0.1; if (perkReduction > reduction) { reduction = perkReduction; // Calculate and award force XP based on total damage reduced. int xp = (int)(data.Total * reduction * 3); if (xp < 5) { xp = 5; } SkillService.GiveSkillXP(target.Object, SkillType.ForceControl, xp); // Play a visual effect signifying the ability was activated. _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_BLUR), target, 0.5f); } } // No reduction found. Bail out early. if (reduction <= 0.0f) { return; } target.SendMessage("Damage reduced by " + (int)(reduction * 100) + "%"); reduction = 1.0f - reduction; data.Bludgeoning = (int)(data.Bludgeoning * reduction); data.Pierce = (int)(data.Pierce * reduction); data.Slash = (int)(data.Slash * reduction); data.Magical = (int)(data.Magical * reduction); data.Acid = (int)(data.Acid * reduction); data.Cold = (int)(data.Cold * reduction); data.Divine = (int)(data.Divine * reduction); data.Electrical = (int)(data.Electrical * reduction); data.Fire = (int)(data.Fire * reduction); data.Negative = (int)(data.Negative * reduction); data.Positive = (int)(data.Positive * reduction); data.Sonic = (int)(data.Sonic * reduction); data.Base = (int)(data.Base * reduction); NWNXDamage.SetDamageEventData(data); }
private static void HandleBattlemagePerk() { DamageEventData data = NWNXDamage.GetDamageEventData(); if (data.Base <= 0) { return; } NWObject target = Object.OBJECT_SELF; if (!data.Damager.IsPlayer || !target.IsNPC) { return; } if (_.GetHasFeat((int)CustomFeatType.Battlemage, data.Damager.Object) == FALSE) { return; } NWPlayer player = data.Damager.Object; NWItem weapon = _.GetLastWeaponUsed(player.Object); if (weapon.CustomItemType != CustomItemType.Baton) { return; } if (player.Chest.CustomItemType != CustomItemType.ForceArmor) { return; } int perkRank = PerkService.GetPCPerkLevel(player, PerkType.Battlemage); int restoreAmount = 0; bool metRoll = RandomService.Random(100) + 1 <= 50; switch (perkRank) { case 1 when metRoll: restoreAmount = 1; break; case 2: restoreAmount = 1; break; case 3: restoreAmount = 1; if (metRoll) { restoreAmount++; } break; case 4: restoreAmount = 2; break; case 5: restoreAmount = 2; if (metRoll) { restoreAmount++; } break; case 6: restoreAmount = 3; break; } if (restoreAmount > 0) { AbilityService.RestoreFP(player, restoreAmount); } }