/// <summary> /// Checks caster's position. If they have moved too far from the initial casting position, the spell will be cancelled. /// </summary> /// <param name="stats">The user stats</param> private static void CheckMovement(UserStats stats) { if (stats.IsComplete) { return; } if (!GetIsObjectValid(stats.User)) { return; } var position = GetPosition(stats.User); // Player moved too far from starting position. Cancel the spell. if (Math.Abs(position.X - stats.CastingPosition.X) > 0.01f || Math.Abs(position.Y - stats.CastingPosition.Y) > 0.01f || Math.Abs(position.Z - stats.CastingPosition.Z) > 0.01f) { stats.IsCancelled = true; NWNXPlayer.StopGuiTimingBar(stats.User, string.Empty); SetIsBusy(stats.User, false); SendMessageToPC(stats.User, "You move and interrupt your concentration."); return; } DelayCommand(0.5f, () => CheckMovement(stats)); }
public static void Main() { NWGameObject player = GetExitingObject(); if (!GetIsPlayer(player)) { return; } var playerID = GetGlobalID(player); var area = GetArea(player); if (!GetIsObjectValid(area)) { area = NWGameObject.OBJECT_SELF; } var areaResref = GetResRef(area); var progress = NWNXPlayer.GetAreaExplorationState(player, area); var progression = MapProgressionRepo.Get(playerID, areaResref); progression.Progression = progress; MapProgressionRepo.Set(playerID, progression); }
private static void CheckForSpellInterruption(NWCreature activator, string spellUUID, Vector position) { if (activator.GetLocalInt(spellUUID) == (int)SpellStatusType.Completed) { return; } Vector currentPosition = activator.Position; if (currentPosition.X != position.X || currentPosition.Y != position.Y || currentPosition.Z != position.Z) { var effect = activator.Effects.SingleOrDefault(x => _.GetEffectTag(x) == "ACTIVATION_VFX"); if (effect != null) { _.RemoveEffect(activator, effect); } NWNXPlayer.StopGuiTimingBar(activator, "", -1); activator.IsBusy = false; activator.SetLocalInt(spellUUID, (int)SpellStatusType.Interrupted); activator.SendMessage("Your ability has been interrupted."); return; } _.DelayCommand(0.5f, () => { CheckForSpellInterruption(activator, spellUUID, position); }); }
private void SalvagePageResponses(int responseID) { var player = GetPC(); var model = CraftService.GetPlayerCraftingData(player); switch (responseID) { case 1: // Reassemble Component(s) NWItem fuel = _.GetItemPossessedBy(player, "ass_power"); // Look for reassembly fuel in the player's inventory. if (!fuel.IsValid) { player.SendMessage(ColorTokenService.Red("You must have a 'Reassembly Fuel Cell' in your inventory in order to start this process.")); return; } if (model.IsConfirmingReassemble) { // Calculate delay, fire off delayed event, and show timing bar. float delay = CraftService.CalculateCraftingDelay(player, (int)SkillType.Harvesting); NWNXPlayer.StartGuiTimingBar(player, delay, string.Empty); var @event = new OnReassembleComplete(player, model.SerializedSalvageItem, model.SalvageComponentTypeID); player.DelayEvent(delay, @event); // Make the player play an animation. player.AssignCommand(() => { _.ClearAllActions(); _.ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0f, delay); }); // Show sparks halfway through the process. _.DelayCommand(1.0f * (delay / 2.0f), () => { _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_COM_BLOOD_SPARK_MEDIUM), NWGameObject.OBJECT_SELF); }); // Immobilize the player while crafting. Effect immobilize = _.EffectCutsceneImmobilize(); immobilize = _.TagEffect(immobilize, "CRAFTING_IMMOBILIZATION"); _.ApplyEffectToObject(DURATION_TYPE_PERMANENT, immobilize, player); // Clear the temporary crafting data and end this conversation. model.SerializedSalvageItem = string.Empty; EndConversation(); } else { model.IsConfirmingReassemble = true; SetResponseText("SalvagePage", 1, "CONFIRM REASSEMBLE COMPONENT(S)"); } break; } }
/// <summary> /// Initializes the casting process. /// </summary> /// <param name="stats"></param> private static void StartCasting(UserStats stats) { var castingTime = stats.AbilityDefinition.CastingTime(stats.User); NWNXPlayer.StartGuiTimingBar(stats.User, castingTime, string.Empty); SetIsBusy(stats.User, true); PlayAnimation(stats.User, stats.AbilityDefinition.Category); DelayCommand(0.5f, () => CheckMovement(stats)); DelayCommand(castingTime, () => FinishCasting(stats)); }
private static void InitializeHotBar(NWPlayer player) { var openRestMenu = NWNXPlayerQuickBarSlot.UseFeat(Feat.OpenRestMenu); var structure = NWNXPlayerQuickBarSlot.UseFeat(Feat.StructureManagementTool); var renameCraftedItem = NWNXPlayerQuickBarSlot.UseFeat(Feat.RenameCraftedItem); var chatCommandTargeter = NWNXPlayerQuickBarSlot.UseFeat(Feat.ChatCommandTargeter); NWNXPlayer.SetQuickBarSlot(player, 0, openRestMenu); NWNXPlayer.SetQuickBarSlot(player, 1, structure); NWNXPlayer.SetQuickBarSlot(player, 2, renameCraftedItem); NWNXPlayer.SetQuickBarSlot(player, 3, chatCommandTargeter); }
private static void LoadMapProgression(NWArea area, NWPlayer player) { var map = DataService.PCMapProgression.GetByPlayerIDAndAreaResrefOrDefault(player.GlobalID, area.Resref); // No progression set - do a save which will create the record. if (map == null) { SaveMapProgression(area, player); return; } NWNXPlayer.SetAreaExplorationState(player, area, map.Progression); }
private void StartSmelt(NWPlaceable forge, NWPlayer pc, NWItem item) { int charges = forge.GetLocalInt("FORGE_CHARGES"); if (item.Resref == "power_core") { item.Destroy(); charges += 10 + CalculatePerkCoalBonusCharges(pc) + GetPowerCoreDurability(item) * 2; forge.SetLocalInt("FORGE_CHARGES", charges); NWPlaceable flames = (forge.GetLocalObject("FORGE_FLAMES")); if (!flames.IsValid) { Vector flamePosition = BiowarePosition.GetChangedPosition(forge.Position, 0.36f, forge.Facing); Location flameLocation = _.Location(forge.Area.Object, flamePosition, 0.0f); flames = (_.CreateObject(_.OBJECT_TYPE_PLACEABLE, "forge_flame", flameLocation)); forge.SetLocalObject("FORGE_FLAMES", flames.Object); } return; } else if (charges <= 0) { ReturnItemToPC(pc, item, "You must power the refinery with a power unit before refining."); return; } // Ready to smelt float baseCraftDelay = 18.0f - (18.0f * PerkService.GetCreaturePerkLevel(pc, PerkType.SpeedyRefining) * 0.1f); pc.IsBusy = true; NWNXPlayer.StartGuiTimingBar(pc, baseCraftDelay, string.Empty); // Any component bonuses on the ore get applied to the end product. var itemProperties = item.ItemProperties.Where(x => _.GetItemPropertyType(x) == (int)CustomItemPropertyType.ComponentBonus || _.GetItemPropertyType(x) == (int)CustomItemPropertyType.RecommendedLevel).ToList(); string itemResref = item.Resref; var @event = new OnCompleteSmelt(pc, itemResref, itemProperties); pc.DelayEvent(baseCraftDelay, @event); _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, _.EffectCutsceneImmobilize(), pc.Object, baseCraftDelay); pc.AssignCommand(() => _.ActionPlayAnimation(_.ANIMATION_LOOPING_GET_MID, 1.0f, baseCraftDelay)); item.Destroy(); }
public static void CraftItem(NWPlayer oPC, NWPlaceable device) { var model = GetPlayerCraftingData(oPC); CraftBlueprint blueprint = DataService.Single <CraftBlueprint>(x => x.ID == model.BlueprintID); if (blueprint == null) { return; } if (oPC.IsBusy) { oPC.SendMessage("You are too busy right now."); return; } if (!model.CanBuildItem) { oPC.SendMessage("You are missing one or more components..."); return; } oPC.IsBusy = true; float modifiedCraftDelay = CalculateCraftingDelay(oPC, blueprint.SkillID); oPC.AssignCommand(() => { _.ClearAllActions(); _.ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0f, modifiedCraftDelay); }); _.DelayCommand(1.0f * (modifiedCraftDelay / 2.0f), () => { _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_COM_BLOOD_SPARK_MEDIUM), device.Object); }); Effect immobilize = _.EffectCutsceneImmobilize(); immobilize = _.TagEffect(immobilize, "CRAFTING_IMMOBILIZATION"); _.ApplyEffectToObject(DURATION_TYPE_PERMANENT, immobilize, oPC.Object); NWNXPlayer.StartGuiTimingBar(oPC, modifiedCraftDelay, ""); oPC.DelayEvent <CraftCreateItem>( modifiedCraftDelay, oPC); }
public static void CraftItem(NWPlayer oPC, NWPlaceable device) { var model = GetPlayerCraftingData(oPC); CraftBlueprint blueprint = DataService.CraftBlueprint.GetByID(model.BlueprintID); if (blueprint == null) { return; } if (oPC.IsBusy) { oPC.SendMessage("You are too busy right now."); return; } if (!model.CanBuildItem) { oPC.SendMessage("You are missing one or more components..."); return; } oPC.IsBusy = true; float modifiedCraftDelay = CalculateCraftingDelay(oPC, blueprint.SkillID); oPC.AssignCommand(() => { _.ClearAllActions(); _.ActionPlayAnimation(Animation.LoopingGetMid, 1.0f, modifiedCraftDelay); }); _.DelayCommand(1.0f * (modifiedCraftDelay / 2.0f), () => { _.ApplyEffectToObject(DurationType.Instant, _.EffectVisualEffect(VisualEffect.Vfx_Com_Blood_Spark_Medium), device.Object); }); var immobilize = _.EffectCutsceneImmobilize(); immobilize = _.TagEffect(immobilize, "CRAFTING_IMMOBILIZATION"); _.ApplyEffectToObject(DurationType.Permanent, immobilize, oPC.Object); NWNXPlayer.StartGuiTimingBar(oPC, modifiedCraftDelay, ""); var @event = new OnCreateCraftedItem(oPC); oPC.DelayEvent(modifiedCraftDelay, @event); }
private void SalvagePageResponses(int responseID) { var player = GetPC(); var model = CraftService.GetPlayerCraftingData(player); switch (responseID) { case 1: // Reassemble Component(s) if (model.IsConfirmingReassemble) { // Calculate delay, fire off delayed event, and show timing bar. float delay = CraftService.CalculateCraftingDelay(player, (int)SkillType.Harvesting); NWNXPlayer.StartGuiTimingBar(player, delay, string.Empty); player.DelayEvent <ReassembleComplete>(delay, player, model.SerializedSalvageItem, model.SalvageComponentTypeID); // Make the player play an animation. player.AssignCommand(() => { _.ClearAllActions(); _.ActionPlayAnimation(ANIMATION_LOOPING_GET_MID, 1.0f, delay); }); // Show sparks halfway through the process. _.DelayCommand(1.0f * (delay / 2.0f), () => { _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectVisualEffect(VFX_COM_BLOOD_SPARK_MEDIUM), Object.OBJECT_SELF); }); // Immobilize the player while crafting. Effect immobilize = _.EffectCutsceneImmobilize(); immobilize = _.TagEffect(immobilize, "CRAFTING_IMMOBILIZATION"); _.ApplyEffectToObject(DURATION_TYPE_PERMANENT, immobilize, player); // Clear the temporary crafting data and end this conversation. model.SerializedSalvageItem = string.Empty; EndConversation(); } else { model.IsConfirmingReassemble = true; SetResponseText("SalvagePage", 1, "CONFIRM REASSEMBLE COMPONENT(S)"); } break; } }
public static void Main() { var player = GetEnteringObject(); if (!GetIsPlayer(player)) { return; } var area = GetArea(player); var areaResref = GetResRef(area); var playerID = GetGlobalID(player); var progression = MapProgressionRepo.Get(playerID, areaResref); if (!string.IsNullOrWhiteSpace(progression.Progression)) { NWNXPlayer.SetAreaExplorationState(player, area, progression.Progression); } }
protected static void Recalculate(NWGameObject player) { var playerID = GetGlobalID(player); var playerEntity = PlayerRepo.Get(playerID); var @class = GetClassByPosition(ClassPosition.First, player); var level = GetLevelByPosition(ClassPosition.First, player); var jobDefinition = JobRegistry.Get(@class); // Retrieve the rating chart for the stat, then retrieve the value for that stat at this player's level. var hp = RatingRegistry.Get(jobDefinition.HPRating).Get(RatingStat.HP, level); var mp = RatingRegistry.Get(jobDefinition.MPRating).Get(RatingStat.MP, level); var ac = RatingRegistry.Get(jobDefinition.ACRating).Get(RatingStat.AC, level); var bab = RatingRegistry.Get(jobDefinition.BABRating).Get(RatingStat.BAB, level); var str = RatingRegistry.Get(jobDefinition.STRRating).Get(RatingStat.STR, level); var dex = RatingRegistry.Get(jobDefinition.DEXRating).Get(RatingStat.DEX, level); var con = RatingRegistry.Get(jobDefinition.CONRating).Get(RatingStat.CON, level); var wis = RatingRegistry.Get(jobDefinition.WISRating).Get(RatingStat.WIS, level); var @int = RatingRegistry.Get(jobDefinition.INTRating).Get(RatingStat.INT, level); var cha = RatingRegistry.Get(jobDefinition.CHARating).Get(RatingStat.CHA, level); // Now apply the changes to the player. ApplyHP(player, hp); playerEntity.MaxHP = hp; playerEntity.MaxMP = mp; playerEntity.HP = hp; playerEntity.MP = mp; NWNXCreature.SetBaseAC(player, ac); NWNXCreature.SetBaseAttackBonus(player, bab); NWNXCreature.SetRawAbilityScore(player, Ability.Strength, str); NWNXCreature.SetRawAbilityScore(player, Ability.Dexterity, dex); NWNXCreature.SetRawAbilityScore(player, Ability.Constitution, con); NWNXCreature.SetRawAbilityScore(player, Ability.Wisdom, wis); NWNXCreature.SetRawAbilityScore(player, Ability.Intelligence, @int); NWNXCreature.SetRawAbilityScore(player, Ability.Charisma, cha); PlayerRepo.Set(playerEntity); DelayCommand(1.0f, () => NWNXPlayer.UpdateCharacterSheet(player)); }
private static void SaveMapProgression(NWArea area, NWPlayer player) { var map = DataService.PCMapProgression.GetByPlayerIDAndAreaResrefOrDefault(player.GlobalID, area.Resref); DatabaseActionType action = DatabaseActionType.Update; if (map == null) { map = new PCMapProgression { PlayerID = player.GlobalID, AreaResref = area.Resref, Progression = string.Empty }; action = DatabaseActionType.Insert; } map.Progression = NWNXPlayer.GetAreaExplorationState(player, area); DataService.SubmitDataChange(map, action); }
private static void ActivateAbility( NWCreature activator, NWObject target, Data.Entity.Perk entity, IPerkHandler perkHandler, int pcPerkLevel, PerkExecutionType executionType, int spellTier) { string uuid = Guid.NewGuid().ToString(); float baseActivationTime = perkHandler.CastingTime(activator, (float)entity.BaseCastingTime, spellTier); float activationTime = baseActivationTime; var vfxID = VisualEffect.Invalid; var animationID = Animation.Invalid; if (baseActivationTime > 0f && activationTime < 1.0f) { activationTime = 1.0f; } // Force ability armor penalties float armorPenalty = 0.0f; if (executionType == PerkExecutionType.ForceAbility || executionType == PerkExecutionType.ConcentrationAbility) { string penaltyMessage = string.Empty; foreach (var item in activator.EquippedItems) { if (item.CustomItemType == CustomItemType.HeavyArmor) { armorPenalty = 2; penaltyMessage = "Heavy armor slows your force cooldown by 100%."; break; } else if (item.CustomItemType == CustomItemType.LightArmor) { armorPenalty = 1.25f; penaltyMessage = "Light armor slows your force cooldown by 25%."; } } // If there's an armor penalty, send a message to the player. if (armorPenalty > 0.0f) { activator.SendMessage(penaltyMessage); } } // If player is in stealth mode, force them out of stealth mode. if (_.GetActionMode(activator.Object, ActionMode.Stealth)) { _.SetActionMode(activator.Object, ActionMode.Stealth, false); } // Make the player face their target. _.ClearAllActions(); BiowarePosition.TurnToFaceObject(target, activator); // Force and Concentration Abilities will display a visual effect during the casting process. if (executionType == PerkExecutionType.ForceAbility || executionType == PerkExecutionType.ConcentrationAbility) { vfxID = VisualEffect.Vfx_Dur_Iounstone_Yellow; animationID = Animation.LoopingConjure1; } if (executionType == PerkExecutionType.ConcentrationAbility) { activator.SetLocalObject("CONCENTRATION_TARGET", target); } // If a VFX ID has been specified, play that effect instead of the default one. if (vfxID != VisualEffect.Invalid) { var vfx = _.EffectVisualEffect(vfxID); vfx = _.TagEffect(vfx, "ACTIVATION_VFX"); _.ApplyEffectToObject(DurationType.Temporary, vfx, activator.Object, activationTime + 0.2f); } // If an animation has been specified, make the player play that animation now. // bypassing if perk is throw saber due to couldn't get the animation to work via db table edit if (animationID != Animation.Invalid && entity.ID != (int)PerkType.ThrowSaber) { activator.AssignCommand(() => _.ActionPlayAnimation(animationID, 1.0f, activationTime - 0.1f)); } // Mark player as busy. Busy players can't take other actions (crafting, harvesting, etc.) activator.IsBusy = true; // Non-players can't be interrupted via movement. if (!activator.IsPlayer) { // Begin the check for spell interruption. If the activator moves, the spell will be canceled. CheckForSpellInterruption(activator, uuid, activator.Position); } activator.SetLocalInt(uuid, (int)SpellStatusType.Started); // If there's a casting delay, display a timing bar on-screen. if (activationTime > 0) { NWNXPlayer.StartGuiTimingBar(activator, (int)activationTime, string.Empty); } // Run the FinishAbilityUse event at the end of the activation time. int perkID = entity.ID; var @event = new OnFinishAbilityUse(activator, uuid, perkID, target, pcPerkLevel, spellTier, armorPenalty); activator.DelayEvent(activationTime + 0.2f, @event); }
public static void ApplyStatChanges(NWPlayer player, NWItem ignoreItem, bool isInitialization = false) { if (!player.IsPlayer) { return; } if (!player.IsInitializedAsPlayer) { return; } if (player.GetLocalInt("IS_SHIP") == 1) { return; } // Don't fire for ammo as it reapplies bonuses **just** removed from blasters. if (ignoreItem != null && (ignoreItem.BaseItemType == BASE_ITEM_BOLT || ignoreItem.BaseItemType == BASE_ITEM_ARROW || ignoreItem.BaseItemType == BASE_ITEM_BULLET)) { return; } Player pcEntity = DataService.Get <Player>(player.GlobalID); List <PCSkill> skills = DataService.Where <PCSkill>(x => x.PlayerID == player.GlobalID && x.Rank > 0).ToList(); EffectiveItemStats itemBonuses = GetPlayerItemEffectiveStats(player, ignoreItem); float strBonus = 0.0f; float dexBonus = 0.0f; float conBonus = 0.0f; float intBonus = 0.0f; float wisBonus = 0.0f; float chaBonus = 0.0f; using (new Profiler("PlayerStatService::ApplyStatChanges::AttributeApplication")) { foreach (PCSkill pcSkill in skills) { Skill skill = DataService.Get <Skill>(pcSkill.SkillID); CustomAttribute primary = (CustomAttribute)skill.Primary; CustomAttribute secondary = (CustomAttribute)skill.Secondary; CustomAttribute tertiary = (CustomAttribute)skill.Tertiary; // Primary Bonuses if (primary == CustomAttribute.STR) { strBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.DEX) { dexBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.CON) { conBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.INT) { intBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.WIS) { wisBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.CHA) { chaBonus += PrimaryIncrease * pcSkill.Rank; } // Secondary Bonuses if (secondary == CustomAttribute.STR) { strBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.DEX) { dexBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.CON) { conBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.INT) { intBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.WIS) { wisBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.CHA) { chaBonus += SecondaryIncrease * pcSkill.Rank; } // Tertiary Bonuses if (tertiary == CustomAttribute.STR) { strBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.DEX) { dexBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.CON) { conBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.INT) { intBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.WIS) { wisBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.CHA) { chaBonus += TertiaryIncrease * pcSkill.Rank; } } } // Check caps. if (strBonus > MaxAttributeBonus) { strBonus = MaxAttributeBonus; } if (dexBonus > MaxAttributeBonus) { dexBonus = MaxAttributeBonus; } if (conBonus > MaxAttributeBonus) { conBonus = MaxAttributeBonus; } if (intBonus > MaxAttributeBonus) { intBonus = MaxAttributeBonus; } if (wisBonus > MaxAttributeBonus) { wisBonus = MaxAttributeBonus; } if (chaBonus > MaxAttributeBonus) { chaBonus = MaxAttributeBonus; } // Apply item bonuses strBonus += itemBonuses.Strength / 3; dexBonus += itemBonuses.Dexterity / 3; conBonus += itemBonuses.Constitution / 3; wisBonus += itemBonuses.Wisdom / 3; intBonus += itemBonuses.Intelligence / 3; chaBonus += itemBonuses.Charisma / 3; // Check final caps if (strBonus > 55) { strBonus = 55; } if (dexBonus > 55) { dexBonus = 55; } if (conBonus > 55) { conBonus = 55; } if (intBonus > 55) { intBonus = 55; } if (wisBonus > 55) { wisBonus = 55; } if (chaBonus > 55) { chaBonus = 55; } // Apply attributes NWNXCreature.SetRawAbilityScore(player, ABILITY_STRENGTH, (int)strBonus + pcEntity.STRBase); NWNXCreature.SetRawAbilityScore(player, ABILITY_DEXTERITY, (int)dexBonus + pcEntity.DEXBase); NWNXCreature.SetRawAbilityScore(player, ABILITY_CONSTITUTION, (int)conBonus + pcEntity.CONBase); NWNXCreature.SetRawAbilityScore(player, ABILITY_INTELLIGENCE, (int)intBonus + pcEntity.INTBase); NWNXCreature.SetRawAbilityScore(player, ABILITY_WISDOM, (int)wisBonus + pcEntity.WISBase); NWNXCreature.SetRawAbilityScore(player, ABILITY_CHARISMA, (int)chaBonus + pcEntity.CHABase); // Apply AC using (new Profiler("PlayerStatService::ApplyStatChanges::CalcAC")) { int ac = EffectiveArmorClass(itemBonuses, player); NWNXCreature.SetBaseAC(player, ac); } // Apply BAB using (new Profiler("PlayerStatService::ApplyStatChanges::CalcBAB")) { int bab = CalculateBAB(player, ignoreItem, itemBonuses); NWNXCreature.SetBaseAttackBonus(player, bab); } // Apply HP using (new Profiler("PlayerStatService::ApplyStatChanges::CalcHP")) { int hp = EffectiveMaxHitPoints(player, itemBonuses); for (int level = 1; level <= 5; level++) { hp--; NWNXCreature.SetMaxHitPointsByLevel(player, level, 1); } for (int level = 1; level <= 5; level++) { if (hp > 255) // Levels can only contain a max of 255 HP { NWNXCreature.SetMaxHitPointsByLevel(player, level, 255); hp = hp - 254; } else // Remaining value gets set to the level. (<255 hp) { NWNXCreature.SetMaxHitPointsByLevel(player, level, hp + 1); break; } } } if (player.CurrentHP > player.MaxHP) { int amount = player.CurrentHP - player.MaxHP; Effect damage = _.EffectDamage(amount); _.ApplyEffectToObject(DURATION_TYPE_INSTANT, damage, player.Object); } // Apply FP using (new Profiler("PlayerStatService::ApplyStatChanges::CalcFP")) { pcEntity.MaxFP = EffectiveMaxFP(player, itemBonuses); if (isInitialization) { pcEntity.CurrentFP = pcEntity.MaxFP; } DataService.SubmitDataChange(pcEntity, DatabaseActionType.Update); } // Attempt a refresh of the character sheet UI in a second. _.DelayCommand(1.0f, () => { NWNXPlayer.UpdateCharacterSheet(player); }); }
public static void DoPerkUpgrade(NWPlayer oPC, int perkID, bool freeUpgrade = false) { var perk = DataService.Single <Data.Entity.Perk>(x => x.ID == perkID); var perkLevels = DataService.Where <PerkLevel>(x => x.PerkID == perkID); var pcPerk = DataService.SingleOrDefault <PCPerk>(x => x.PlayerID == oPC.GlobalID && x.PerkID == perkID); var player = DataService.Single <Player>(x => x.ID == oPC.GlobalID); if (freeUpgrade || CanPerkBeUpgraded(oPC, perkID)) { DatabaseActionType action = DatabaseActionType.Update; if (pcPerk == null) { pcPerk = new PCPerk(); DateTime dt = DateTime.UtcNow; pcPerk.AcquiredDate = dt; pcPerk.PerkID = perk.ID; pcPerk.PlayerID = oPC.GlobalID; pcPerk.PerkLevel = 0; action = DatabaseActionType.Insert; } PerkLevel nextPerkLevel = FindPerkLevel(perkLevels, pcPerk.PerkLevel + 1); if (nextPerkLevel == null) { return; } pcPerk.PerkLevel++; DataService.SubmitDataChange(pcPerk, action); if (!freeUpgrade) { player.UnallocatedSP -= nextPerkLevel.Price; DataService.SubmitDataChange(player, DatabaseActionType.Update); } // Look for any perk levels to grant. var perkFeatsToGrant = DataService.Where <PerkFeat>(x => x.PerkID == perkID && x.PerkLevelUnlocked == pcPerk.PerkLevel); // If at least one feat ID is assigned, add the feat(s) to the player if it doesn't exist yet. if (perkFeatsToGrant.Count > 0) { foreach (var perkFeat in perkFeatsToGrant) { if (_.GetHasFeat(perkFeat.FeatID, oPC.Object) == TRUE) { continue; } NWNXCreature.AddFeatByLevel(oPC, perkFeat.FeatID, 1); var qbs = NWNXPlayerQuickBarSlot.UseFeat(perkFeat.FeatID); // Try to add the new feat to the player's hotbar. if (NWNXPlayer.GetQuickBarSlot(oPC, 0).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 0, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 1).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 1, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 2).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 2, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 3).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 3, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 4).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 4, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 5).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 5, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 6).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 6, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 7).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 7, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 8).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 8, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 9).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 9, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 10).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 10, qbs); } } } oPC.SendMessage(ColorTokenService.Green("Perk Purchased: " + perk.Name + " (Lvl. " + pcPerk.PerkLevel + ")")); var handler = GetPerkHandler(perkID); handler.OnPurchased(oPC, pcPerk.PerkLevel); MessageHub.Instance.Publish(new PerkUpgradedMessage(oPC, perkID)); } else { oPC.FloatingText(ColorTokenService.Red("You cannot purchase the perk at this time.")); } }
private static void OnModuleNWNXChat() { NWPlayer sender = Object.OBJECT_SELF; string originalMessage = NWNXChat.GetMessage().Trim(); if (!CanHandleChat(sender, originalMessage)) { return; } var split = originalMessage.Split(' ').ToList(); // Commands with no arguments won't be split, so if we didn't split anything then add the command to the split list manually. if (split.Count <= 0) { split.Add(originalMessage); } split[0] = split[0].ToLower(); string command = split[0].Substring(1, split[0].Length - 1); split.RemoveAt(0); NWNXChat.SkipMessage(); if (!IsChatCommandRegistered(command)) { sender.SendMessage(ColorTokenService.Red("Invalid chat command. Use '/help' to get a list of available commands.")); return; } IChatCommand chatCommand = GetChatCommandHandler(command); string args = string.Join(" ", split); if (!chatCommand.RequiresTarget) { ProcessChatCommand(chatCommand, sender, null, null, args); } else { string error = chatCommand.ValidateArguments(sender, split.ToArray()); if (!string.IsNullOrWhiteSpace(error)) { sender.SendMessage(error); return; } sender.SetLocalString("CHAT_COMMAND", command); sender.SetLocalString("CHAT_COMMAND_ARGS", args); sender.SendMessage("Please use your 'Chat Command Targeter' feat to select the target of this chat command."); if (_.GetHasFeat((int)CustomFeatType.ChatCommandTargeter, sender) == FALSE || sender.IsDM) { NWNXCreature.AddFeatByLevel(sender, (int)CustomFeatType.ChatCommandTargeter, 1); if (sender.IsDM) { var qbs = NWNXPlayer.GetQuickBarSlot(sender, 11); if (qbs.ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(sender, 11, NWNXPlayerQuickBarSlot.UseFeat((int)CustomFeatType.ChatCommandTargeter)); } } } } }
private static void ActivateAbility(NWPlayer pc, NWObject target, Data.Entity.Perk entity, IPerkHandler perkHandler, int pcPerkLevel, PerkExecutionType executionType, int spellFeatID) { string uuid = Guid.NewGuid().ToString(); var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(pc); int itemBonus = effectiveStats.CastingSpeed; float baseActivationTime = perkHandler.CastingTime(pc, (float)entity.BaseCastingTime, spellFeatID); float activationTime = baseActivationTime; int vfxID = -1; int animationID = -1; // Activation Bonus % - Shorten activation time. if (itemBonus > 0) { float activationBonus = Math.Abs(itemBonus) * 0.01f; activationTime = activationTime - activationTime * activationBonus; } // Activation Penalty % - Increase activation time. else if (itemBonus < 0) { float activationPenalty = Math.Abs(itemBonus) * 0.01f; activationTime = activationTime + activationTime * activationPenalty; } if (baseActivationTime > 0f && activationTime < 1.0f) { activationTime = 1.0f; } // Force ability armor penalties if (executionType == PerkExecutionType.ForceAbility) { float armorPenalty = 0.0f; string penaltyMessage = string.Empty; foreach (var item in pc.EquippedItems) { if (item.CustomItemType == CustomItemType.HeavyArmor) { armorPenalty = 2; penaltyMessage = "Heavy armor slows your force activation speed by 100%."; break; } else if (item.CustomItemType == CustomItemType.LightArmor) { armorPenalty = 1.25f; penaltyMessage = "Light armor slows your force activation speed by 25%."; } } if (armorPenalty > 0.0f) { activationTime = baseActivationTime * armorPenalty; pc.SendMessage(penaltyMessage); } } if (_.GetActionMode(pc.Object, ACTION_MODE_STEALTH) == 1) { _.SetActionMode(pc.Object, ACTION_MODE_STEALTH, 0); } _.ClearAllActions(); BiowarePosition.TurnToFaceObject(target, pc); if (executionType == PerkExecutionType.ForceAbility) { vfxID = VFX_DUR_IOUNSTONE_YELLOW; animationID = ANIMATION_LOOPING_CONJURE1; } if (vfxID > -1) { var vfx = _.EffectVisualEffect(vfxID); vfx = _.TagEffect(vfx, "ACTIVATION_VFX"); _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, vfx, pc.Object, activationTime + 0.2f); } if (animationID > -1) { pc.AssignCommand(() => _.ActionPlayAnimation(animationID, 1.0f, activationTime - 0.1f)); } pc.IsBusy = true; CheckForSpellInterruption(pc, uuid, pc.Position); pc.SetLocalInt(uuid, (int)SpellStatusType.Started); NWNXPlayer.StartGuiTimingBar(pc, (int)activationTime, ""); int perkID = entity.ID; pc.DelayEvent <FinishAbilityUse>(activationTime + 0.2f, pc, uuid, perkID, target, pcPerkLevel, spellFeatID); }
private static void OnItemUsed() { NWPlayer user = _.OBJECT_SELF; NWItem oItem = _.StringToObject(NWNXEvents.GetEventData("ITEM_OBJECT_ID")); NWObject target = _.StringToObject(NWNXEvents.GetEventData("TARGET_OBJECT_ID")); var targetPositionX = (float)Convert.ToDouble(NWNXEvents.GetEventData("TARGET_POSITION_X")); var targetPositionY = (float)Convert.ToDouble(NWNXEvents.GetEventData("TARGET_POSITION_Y")); var targetPositionZ = (float)Convert.ToDouble(NWNXEvents.GetEventData("TARGET_POSITION_Z")); var targetPosition = Vector3(targetPositionX, targetPositionY, targetPositionZ); Location targetLocation = Location(user.Area, targetPosition, 0.0f); string className = oItem.GetLocalString("SCRIPT"); if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTIVATE_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTION_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("SCRIPT"); } // Legacy events follow. We can't remove these because of backwards compatibility issues with existing items. if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("JAVA_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTIVATE_JAVA_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("JAVA_ACTION_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { return; } // Bypass the NWN "item use" animation. NWNXEvents.SkipEvent(); user.ClearAllActions(); if (user.IsBusy) { user.SendMessage("You are busy."); return; } // Remove "Item." prefix if it exists. if (className.StartsWith("Item.")) { className = className.Substring(5); } IActionItem item = GetActionItemHandler(className); string invalidTargetMessage = item.IsValidTarget(user, oItem, target, targetLocation); if (!string.IsNullOrWhiteSpace(invalidTargetMessage)) { user.SendMessage(invalidTargetMessage); return; } // NOTE - these checks are duplicated in FinishActionItem. Keep both in sync. float maxDistance = item.MaxDistance(user, oItem, target, targetLocation); if (maxDistance > 0.0f) { NWObject owner = GetItemPossessor(target); if (target.IsValid && owner.IsValid) { // We are okay - we have targeted an item in our inventory (we can't target someone // else's inventory, so no need to actually check distance). } else if (target.Object == _.OBJECT_SELF) { // Also okay. } else if (target.IsValid && (GetDistanceBetween(user.Object, target.Object) > maxDistance || user.Area.Resref != target.Area.Resref)) { user.SendMessage("Your target is too far away."); return; } else if (!target.IsValid && (GetDistanceBetweenLocations(user.Location, targetLocation) > maxDistance || user.Area.Resref != ((NWArea)GetAreaFromLocation(targetLocation)).Resref)) { user.SendMessage("That location is too far away."); return; } } CustomData customData = item.StartUseItem(user, oItem, target, targetLocation); float delay = item.Seconds(user, oItem, target, targetLocation, customData); var animationID = item.AnimationID(); bool faceTarget = item.FaceTarget(); Vector3 userPosition = user.Position; user.AssignCommand(() => { user.IsBusy = true; if (faceTarget) { SetFacingPoint(!target.IsValid ? GetPositionFromLocation(targetLocation) : target.Position); } if (animationID > 0) { ActionPlayAnimation(animationID, 1.0f, delay); } }); if (delay > 0.0f) { NWNXPlayer.StartGuiTimingBar(user, delay, string.Empty); } var @event = new OnFinishActionItem(className, user, oItem, target, targetLocation, userPosition, customData); user.DelayEvent(delay, @event); }
public static void ApplyStatChanges(NWPlayer player, NWItem ignoreItem, bool isInitialization = false) { if (!player.IsPlayer) { return; } if (!player.IsInitializedAsPlayer) { return; } if (player.GetLocalInt("IS_SHIP") == 1) { return; } // Don't fire for ammo as it reapplies bonuses we **just** removed from blasters. if (ignoreItem != null && (ignoreItem.BaseItemType == BaseItem.Bolt || ignoreItem.BaseItemType == BaseItem.Arrow || ignoreItem.BaseItemType == BaseItem.Bullet)) { return; } Player pcEntity = DataService.Player.GetByID(player.GlobalID); List <PCSkill> skills = DataService.PCSkill .GetAllByPlayerID(player.GlobalID) .Where(x => x.Rank > 0).ToList(); EffectiveItemStats itemBonuses = GetPlayerItemEffectiveStats(player, ignoreItem); float strBonus = 0.0f; float dexBonus = 0.0f; float conBonus = 0.0f; float intBonus = 0.0f; float wisBonus = 0.0f; float chaBonus = 0.0f; foreach (PCSkill pcSkill in skills) { Skill skill = DataService.Skill.GetByID(pcSkill.SkillID); CustomAttribute primary = (CustomAttribute)skill.Primary; CustomAttribute secondary = (CustomAttribute)skill.Secondary; CustomAttribute tertiary = (CustomAttribute)skill.Tertiary; // Primary Bonuses if (primary == CustomAttribute.STR) { strBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.DEX) { dexBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.CON) { conBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.INT) { intBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.WIS) { wisBonus += PrimaryIncrease * pcSkill.Rank; } else if (primary == CustomAttribute.CHA) { chaBonus += PrimaryIncrease * pcSkill.Rank; } // Secondary Bonuses if (secondary == CustomAttribute.STR) { strBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.DEX) { dexBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.CON) { conBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.INT) { intBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.WIS) { wisBonus += SecondaryIncrease * pcSkill.Rank; } else if (secondary == CustomAttribute.CHA) { chaBonus += SecondaryIncrease * pcSkill.Rank; } // Tertiary Bonuses if (tertiary == CustomAttribute.STR) { strBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.DEX) { dexBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.CON) { conBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.INT) { intBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.WIS) { wisBonus += TertiaryIncrease * pcSkill.Rank; } else if (tertiary == CustomAttribute.CHA) { chaBonus += TertiaryIncrease * pcSkill.Rank; } } // Check caps. if (strBonus > MaxAttributeBonus) { strBonus = MaxAttributeBonus; } if (dexBonus > MaxAttributeBonus) { dexBonus = MaxAttributeBonus; } if (conBonus > MaxAttributeBonus) { conBonus = MaxAttributeBonus; } if (intBonus > MaxAttributeBonus) { intBonus = MaxAttributeBonus; } if (wisBonus > MaxAttributeBonus) { wisBonus = MaxAttributeBonus; } if (chaBonus > MaxAttributeBonus) { chaBonus = MaxAttributeBonus; } // Apply item bonuses strBonus += itemBonuses.Strength; dexBonus += itemBonuses.Dexterity; conBonus += itemBonuses.Constitution; wisBonus += itemBonuses.Wisdom; intBonus += itemBonuses.Intelligence; chaBonus += itemBonuses.Charisma; // Check final caps if (strBonus > 55) { strBonus = 55; } if (dexBonus > 55) { dexBonus = 55; } if (conBonus > 55) { conBonus = 55; } if (intBonus > 55) { intBonus = 55; } if (wisBonus > 55) { wisBonus = 55; } if (chaBonus > 55) { chaBonus = 55; } // Apply attributes NWNXCreature.SetRawAbilityScore(player, AbilityType.Strength, (int)strBonus + pcEntity.STRBase); NWNXCreature.SetRawAbilityScore(player, AbilityType.Dexterity, (int)dexBonus + pcEntity.DEXBase); NWNXCreature.SetRawAbilityScore(player, AbilityType.Constitution, (int)conBonus + pcEntity.CONBase); NWNXCreature.SetRawAbilityScore(player, AbilityType.Intelligence, (int)intBonus + pcEntity.INTBase); NWNXCreature.SetRawAbilityScore(player, AbilityType.Wisdom, (int)wisBonus + pcEntity.WISBase); NWNXCreature.SetRawAbilityScore(player, AbilityType.Charisma, (int)chaBonus + pcEntity.CHABase); // Apply AC int ac = EffectiveArmorClass(player, ignoreItem, itemBonuses); NWNXCreature.SetBaseAC(player, ac); // Apply BAB int bab = CalculateBAB(player, ignoreItem, itemBonuses); NWNXCreature.SetBaseAttackBonus(player, bab); // Apply HP int hp = EffectiveMaxHitPoints(player, itemBonuses); for (int level = 1; level <= 5; level++) { hp--; NWNXCreature.SetMaxHitPointsByLevel(player, level, 1); } for (int level = 1; level <= 5; level++) { if (hp >= 255) // Levels can only contain a max of 255 HP { NWNXCreature.SetMaxHitPointsByLevel(player, level, 255); hp = hp - 254; } else // Remaining value gets set to the level. (<255 hp) { NWNXCreature.SetMaxHitPointsByLevel(player, level, hp + 1); break; } } if (player.CurrentHP > player.MaxHP) { int amount = player.CurrentHP - player.MaxHP; var damage = _.EffectDamage(amount); _.ApplyEffectToObject(DurationType.Instant, damage, player.Object); } // Apply FP pcEntity.MaxFP = EffectiveMaxFP(player, itemBonuses); if (isInitialization) { pcEntity.CurrentFP = pcEntity.MaxFP; } DataService.SubmitDataChange(pcEntity, DatabaseActionType.Update); // Attempt a refresh of the character sheet UI in a second. _.DelayCommand(1.0f, () => { NWNXPlayer.UpdateCharacterSheet(player); }); }
/// <summary> /// Performs a perk purchase for a player. This handles deducting SP, inserting perk records, /// and adjusting hotbar slots as necessary. /// </summary> /// <param name="oPC">The player receiving the perk upgrade.</param> /// <param name="perkID">The ID number of the perk.</param> /// <param name="freeUpgrade">If true, no SP will be deducted. Otherwise, SP will be deducted from player.</param> public static void DoPerkUpgrade(NWPlayer oPC, int perkID, bool freeUpgrade = false) { var perk = DataService.Perk.GetByID(perkID); var perkLevels = DataService.PerkLevel.GetAllByPerkID(perkID); var pcPerk = DataService.PCPerk.GetByPlayerAndPerkIDOrDefault(oPC.GlobalID, perkID); var player = DataService.Player.GetByID(oPC.GlobalID); if (freeUpgrade || CanPerkBeUpgraded(oPC, perkID)) { DatabaseActionType action = DatabaseActionType.Update; if (pcPerk == null) { pcPerk = new PCPerk(); DateTime dt = DateTime.UtcNow; pcPerk.AcquiredDate = dt; pcPerk.PerkID = perk.ID; pcPerk.PlayerID = oPC.GlobalID; pcPerk.PerkLevel = 0; action = DatabaseActionType.Insert; } PerkLevel nextPerkLevel = FindPerkLevel(perkLevels, pcPerk.PerkLevel + 1); if (nextPerkLevel == null) { return; } pcPerk.PerkLevel++; DataService.SubmitDataChange(pcPerk, action); if (!freeUpgrade) { player.UnallocatedSP -= nextPerkLevel.Price; DataService.SubmitDataChange(player, DatabaseActionType.Update); } // Look for a perk feat to grant. var perkFeatToGrant = DataService.PerkFeat.GetByPerkIDAndLevelUnlockedOrDefault(perkID, pcPerk.PerkLevel); // Add the feat(s) to the player if it doesn't exist yet. if (perkFeatToGrant != null && _.GetHasFeat((Feat)perkFeatToGrant.FeatID, oPC.Object) == false) { NWNXCreature.AddFeatByLevel(oPC, (Feat)perkFeatToGrant.FeatID, 1); var qbs = NWNXPlayerQuickBarSlot.UseFeat((Feat)perkFeatToGrant.FeatID); // Try to add the new feat to the player's hotbar. if (NWNXPlayer.GetQuickBarSlot(oPC, 0).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 0, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 1).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 1, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 2).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 2, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 3).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 3, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 4).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 4, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 5).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 5, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 6).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 6, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 7).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 7, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 8).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 8, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 9).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 9, qbs); } else if (NWNXPlayer.GetQuickBarSlot(oPC, 10).ObjectType == QuickBarSlotType.Empty) { NWNXPlayer.SetQuickBarSlot(oPC, 10, qbs); } } oPC.SendMessage(ColorTokenService.Green("Perk Purchased: " + perk.Name + " (Lvl. " + pcPerk.PerkLevel + ")")); MessageHub.Instance.Publish(new OnPerkUpgraded(oPC, perkID)); var handler = GetPerkHandler(perkID); handler.OnPurchased(oPC, pcPerk.PerkLevel); } else { oPC.FloatingText(ColorTokenService.Red("You cannot purchase the perk at this time.")); } }
private static void OnModuleActivatedItem() { NWPlayer user = (_.GetItemActivator()); NWItem oItem = (_.GetItemActivated()); NWObject target = (_.GetItemActivatedTarget()); Location targetLocation = _.GetItemActivatedTargetLocation(); string className = oItem.GetLocalString("SCRIPT"); if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTIVATE_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTION_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("SCRIPT"); } // Legacy events follow. We can't remove these because of backwards compatibility issues with existing items. if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("JAVA_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("ACTIVATE_JAVA_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { className = oItem.GetLocalString("JAVA_ACTION_SCRIPT"); } if (string.IsNullOrWhiteSpace(className)) { return; } user.ClearAllActions(); if (user.IsBusy) { user.SendMessage("You are busy."); return; } // Remove "Item." prefix if it exists. if (className.StartsWith("Item.")) { className = className.Substring(5); } IActionItem item = GetActionItemHandler(className); string invalidTargetMessage = item.IsValidTarget(user, oItem, target, targetLocation); if (!string.IsNullOrWhiteSpace(invalidTargetMessage)) { user.SendMessage(invalidTargetMessage); return; } float maxDistance = item.MaxDistance(user, oItem, target, targetLocation); if (maxDistance > 0.0f) { if (target.IsValid && (_.GetDistanceBetween(user.Object, target.Object) > maxDistance || user.Area.Resref != target.Area.Resref)) { user.SendMessage("Your target is too far away."); return; } else if (!target.IsValid && (_.GetDistanceBetweenLocations(user.Location, targetLocation) > maxDistance || user.Area.Resref != ((NWArea)_.GetAreaFromLocation(targetLocation)).Resref)) { user.SendMessage("That location is too far away."); return; } } CustomData customData = item.StartUseItem(user, oItem, target, targetLocation); float delay = item.Seconds(user, oItem, target, targetLocation, customData); int animationID = item.AnimationID(); bool faceTarget = item.FaceTarget(); Vector userPosition = user.Position; user.AssignCommand(() => { user.IsBusy = true; if (faceTarget) { _.SetFacingPoint(!target.IsValid ? _.GetPositionFromLocation(targetLocation) : target.Position); } if (animationID > 0) { _.ActionPlayAnimation(animationID, 1.0f, delay); } }); NWNXPlayer.StartGuiTimingBar(user, delay, string.Empty); var @event = new OnFinishActionItem(className, user, oItem, target, targetLocation, userPosition, customData); user.DelayEvent(delay, @event); }