private void DoPerkRemoval() { if (!CanRefundPerk()) { return; } var model = GetDialogCustomData <Model>(); var player = GetPC(); var pcPerk = _data.Single <PCPerk>(x => x.ID == model.PCPerkID); var perk = _data.Get <Data.Entity.Perk>(pcPerk.PerkID); var minimumLevel = 1; if (IsGrantedByBackground((PerkType)perk.ID)) { minimumLevel = 2; } var refundAmount = _data.Where <PerkLevel>(x => x.PerkID == perk.ID && x.Level <= pcPerk.PerkLevel && x.Level >= minimumLevel).Sum(x => x.Price); var dbPlayer = _data.Single <Player>(x => x.ID == player.GlobalID); var scriptName = perk.ScriptName; dbPlayer.DatePerkRefundAvailable = DateTime.UtcNow.AddHours(24); RemovePerkItem(perk); RemovePerkFeat(perk); _customEffect.RemoveStance(GetPC()); _stat.ApplyStatChanges(GetPC(), null); dbPlayer.UnallocatedSP += refundAmount; var refundAudit = new PCPerkRefund { PlayerID = player.GlobalID, DateAcquired = pcPerk.AcquiredDate, DateRefunded = DateTime.UtcNow, Level = pcPerk.PerkLevel, PerkID = pcPerk.PerkID }; // Bypass caching for perk refunds. _data.DataQueue.Enqueue(new DatabaseAction(refundAudit, DatabaseActionType.Insert)); _data.SubmitDataChange(pcPerk, DatabaseActionType.Delete); _data.SubmitDataChange(dbPlayer, DatabaseActionType.Update); // If perk refunded was one granted by a background bonus, we need to reapply it. ReapplyBackgroundBonus((PerkType)pcPerk.PerkID); GetPC().FloatingText("Perk refunded! You reclaimed " + refundAmount + " SP."); model.TomeItem.Destroy(); App.ResolveByInterface <IPerk>("Perk." + scriptName, perkAction => { perkAction?.OnRemoved(player); }); }
public void OnModuleUseFeat() { NWPlayer pc = Object.OBJECT_SELF; NWCreature target = _nwnxEvents.OnFeatUsed_GetTarget().Object; int featID = _nwnxEvents.OnFeatUsed_GetFeatID(); Data.Entity.Perk perk = _data.GetAll <Data.Entity.Perk>().SingleOrDefault(x => x.FeatID == featID); if (perk == null) { return; } App.ResolveByInterface <IPerk>("Perk." + perk.ScriptName, (perkAction) => { if (perkAction == null) { return; } Player playerEntity = _data.Get <Player>(pc.GlobalID); int pcPerkLevel = _perk.GetPCPerkLevel(pc, perk.ID); // If player is disabling an existing stance, remove that effect. if (perk.ExecutionTypeID == (int)PerkExecutionType.Stance) { PCCustomEffect stanceEffect = _data.GetAll <PCCustomEffect>().SingleOrDefault(x => { var customEffect = _data.Get <Data.Entity.CustomEffect>(x.CustomEffectID); return(x.PlayerID == pc.GlobalID && customEffect.CustomEffectCategoryID == (int)CustomEffectCategoryType.Stance); }); if (stanceEffect != null && perk.ID == stanceEffect.StancePerkID) { if (_customEffect.RemoveStance(pc)) { return; } } } if (pcPerkLevel <= 0) { pc.SendMessage("You do not meet the prerequisites to use this ability."); return; } if (perkAction.IsHostile() && target.IsPlayer) { if (!_pvpSanctuary.IsPVPAttackAllowed(pc, target.Object)) { return; } } if (pc.Area.Resref != target.Area.Resref || _.LineOfSightObject(pc.Object, target.Object) == 0) { pc.SendMessage("You cannot see your target."); return; } if (!perkAction.CanCastSpell(pc, target)) { pc.SendMessage(perkAction.CannotCastSpellMessage(pc, target) ?? "That ability cannot be used at this time."); return; } int fpCost = perkAction.FPCost(pc, perkAction.FPCost(pc, perk.BaseFPCost)); if (playerEntity.CurrentFP < fpCost) { pc.SendMessage("You do not have enough FP. (Required: " + fpCost + ". You have: " + playerEntity.CurrentFP + ")"); return; } if (pc.IsBusy || pc.CurrentHP <= 0) { pc.SendMessage("You are too busy to activate that ability."); return; } // Check cooldown PCCooldown pcCooldown = _data.GetAll <PCCooldown>().SingleOrDefault(x => x.PlayerID == pc.GlobalID && x.CooldownCategoryID == perk.CooldownCategoryID); if (pcCooldown == null) { pcCooldown = new PCCooldown { CooldownCategoryID = Convert.ToInt32(perk.CooldownCategoryID), DateUnlocked = DateTime.UtcNow.AddSeconds(-1), PlayerID = pc.GlobalID }; _data.SubmitDataChange(pcCooldown, DatabaseActionType.Insert); } DateTime unlockDateTime = pcCooldown.DateUnlocked; DateTime now = DateTime.UtcNow; if (unlockDateTime > now) { string timeToWait = _time.GetTimeToWaitLongIntervals(now, unlockDateTime, false); pc.SendMessage("That ability can be used in " + timeToWait + "."); return; } // Force Abilities (aka Spells) if (perk.ExecutionTypeID == (int)PerkExecutionType.ForceAbility) { ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.ForceAbility); } // Combat Abilities else if (perk.ExecutionTypeID == (int)PerkExecutionType.CombatAbility) { ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.CombatAbility); } // Queued Weapon Skills else if (perk.ExecutionTypeID == (int)PerkExecutionType.QueuedWeaponSkill) { HandleQueueWeaponSkill(pc, perk, perkAction); } // Stances else if (perk.ExecutionTypeID == (int)PerkExecutionType.Stance) { ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.Stance); } }); }