public static int CalculateItemPotencyBonus(NWCreature caster, ForceAbilityType abilityType) { if (!caster.IsPlayer) { return(0); } EffectiveItemStats itemStats = PlayerStatService.GetPlayerItemEffectiveStats(caster.Object); int itemBonus = itemStats.ForcePotency; switch (abilityType) { case ForceAbilityType.Electrical: itemBonus += itemStats.ElectricalPotency; break; case ForceAbilityType.Mind: itemBonus += itemStats.MindPotency; break; case ForceAbilityType.Light: itemBonus += itemStats.LightPotency; break; case ForceAbilityType.Dark: itemBonus += itemStats.DarkPotency; break; default: throw new ArgumentOutOfRangeException(nameof(abilityType), abilityType, null); } return(itemBonus); }
private static void HandleRegenerationTick(NWPlayer oPC, Player entity) { entity.RegenerationTick = entity.RegenerationTick - 1; int rate = 5; int amount = entity.HPRegenerationAmount; if (entity.RegenerationTick <= 0) { if (oPC.CurrentHP < oPC.MaxHP) { var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC); // CON bonus int con = (oPC.ConstitutionModifier / 2); if (con > 0) { amount += con; } amount += effectiveStats.HPRegen; if (oPC.Chest.CustomItemType == CustomItemType.HeavyArmor) { int sturdinessLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.Sturdiness); if (sturdinessLevel > 0) { amount += sturdinessLevel + 1; } } ApplyEffectToObject(DurationType.Instant, EffectHeal(amount), oPC.Object); } entity.RegenerationTick = rate; } }
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 HandleRegenerationTick(NWPlayer oPC, Data.Entity.Player entity) { entity.RegenerationTick = entity.RegenerationTick - 1; int rate = 20; int amount = entity.HPRegenerationAmount; if (entity.RegenerationTick <= 0) { if (oPC.CurrentHP < oPC.MaxHP) { var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC); // CON bonus int con = oPC.ConstitutionModifier; if (con > 0) { amount += con; } amount += effectiveStats.HPRegen; if (oPC.Chest.CustomItemType == CustomItemType.HeavyArmor) { int sturdinessLevel = PerkService.GetPCPerkLevel(oPC, PerkType.Sturdiness); if (sturdinessLevel > 0) { amount += sturdinessLevel + 1; } } _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectHeal(amount), oPC.Object); } entity.RegenerationTick = rate; } }
private static void LoadCharacter() { NWPlayer player = GetEnteringObject(); if (!player.IsPlayer) { return; } Player entity = GetPlayerEntity(player.GlobalID); if (entity == null) { return; } int hp = player.CurrentHP; int damage; if (entity.HitPoints < 0) { damage = hp + Math.Abs(entity.HitPoints); } else { damage = hp - entity.HitPoints; } if (damage != 0) { ApplyEffectToObject(DurationType.Instant, EffectDamage(damage), player); } // Handle item stats for (int itemSlot = 0; itemSlot < NumberOfInventorySlots; itemSlot++) { NWItem item = _.GetItemInSlot((InventorySlot)itemSlot, player); PlayerStatService.CalculateEffectiveStats(player, item); } PlayerStatService.ApplyStatChanges(player, null); player.IsBusy = false; // Just in case player logged out in the middle of an action. // Cleanup code in case people log out as spaceships. var appearance = (AppearanceType)player.Chest.GetLocalInt("APPEARANCE"); if (appearance > 0 && appearance != GetAppearanceType(player)) { SetCreatureAppearanceType(player, appearance); SetObjectVisualTransform(player, ObjectVisualTransform.Scale, 1.0f); } }
private static void HandleApplySneakAttackDamage() { DamageEventData data = NWNXDamage.GetDamageEventData(); if (data.Total <= 0) { return; } NWObject damager = data.Damager; int sneakAttackType = damager.GetLocalInt("SNEAK_ATTACK_ACTIVE"); if (damager.IsPlayer && sneakAttackType > 0) { NWPlayer player = damager.Object; NWCreature target = _.OBJECT_SELF; var pcPerk = PerkService.GetPCPerkByID(damager.GlobalID, (int)PerkType.SneakAttack); int perkRank = pcPerk?.PerkLevel ?? 0; int perkBonus = 1; // Rank 4 increases damage bonus by 2x (total: 3x) if (perkRank == 4) { perkBonus = 2; } float perkRate; if (sneakAttackType == 1) // Player is behind target. { perkRate = 1.0f * perkBonus; } else // Player is anywhere else. { perkRate = 0.5f * perkBonus; } var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player); float damageRate = 1.0f + perkRate + effectiveStats.SneakAttack * 0.05f; data.Base = (int)(data.Base * damageRate); if (target.IsNPC) { EnmityService.AdjustEnmity(target, player, 5 * data.Base); } NWNXDamage.SetDamageEventData(data); } damager.DeleteLocalInt("SNEAK_ATTACK_ACTIVE"); }
public static void AdjustEnmity(NWCreature npc, NWCreature attacker, int volatileAdjust, int cumulativeAdjust = 0) { if (!npc.IsNPC) { return; } if (attacker == null || attacker.Area != npc.Area || LineOfSightObject(npc, attacker) == false) { return; } bool adjustVolatile = volatileAdjust != 0; bool adjustCumulative = cumulativeAdjust != 0; float effectiveEnmityRate = 1.0f; if (attacker.IsPlayer) { NWPlayer player = (attacker.Object); var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player); effectiveEnmityRate = effectiveStats.EnmityRate; } volatileAdjust = (int)(effectiveEnmityRate * volatileAdjust); cumulativeAdjust = (int)(effectiveEnmityRate * cumulativeAdjust); var table = GetEnmityTable(npc); // If this is the first creature to go on the enmity table, immediately attack them so they aren't // waiting around to do something the next time their AI runs. if (table.Count <= 0) { npc.AssignCommand(() => { _.ActionAttack(attacker); }); } var enmity = GetEnmity(npc, attacker); if (adjustVolatile) { enmity.VolatileAmount += volatileAdjust; } if (adjustCumulative) { enmity.CumulativeAmount += cumulativeAdjust; } }
private static void OnModuleUnequipItem() { NWPlayer oPC = _.GetPCItemLastUnequippedBy(); if (oPC.GetLocalInt("IS_CUSTOMIZING_ITEM") == _.TRUE) { return; // Don't run heavy code when customizing equipment. } NWItem oItem = _.GetPCItemLastUnequipped(); HandleGlovesUnequipEvent(); PlayerStatService.ApplyStatChanges(oPC, oItem); RemoveWeaponPenalties(oItem); RemoveEquipmentPenalties(oItem); }
public static void ApplyCooldown(NWCreature creature, CooldownCategory cooldown, IPerkHandler handler, int spellTier, float armorPenalty) { if (armorPenalty <= 0.0f) { armorPenalty = 1.0f; } // If player has a a cooldown recovery bonus on their equipment, apply that change now. if (creature.IsPlayer) { var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(creature.Object); if (effectiveStats.CooldownRecovery > 0) { armorPenalty -= (effectiveStats.CooldownRecovery * 0.01f); } } // There's a cap of 50% cooldown reduction from equipment. if (armorPenalty < 0.5f) { armorPenalty = 0.5f; } Console.WriteLine("armorPenalty final = " + armorPenalty); float finalCooldown = handler.CooldownTime(creature, (float)cooldown.BaseCooldownTime, spellTier) * armorPenalty; int cooldownSeconds = (int)finalCooldown; int cooldownMillis = (int)((finalCooldown - cooldownSeconds) * 100); DateTime unlockDate = DateTime.UtcNow.AddSeconds(cooldownSeconds).AddMilliseconds(cooldownMillis); if (creature.IsPlayer) { PCCooldown pcCooldown = DataService.Single <PCCooldown>(x => x.PlayerID == creature.GlobalID && x.CooldownCategoryID == cooldown.ID); pcCooldown.DateUnlocked = unlockDate; DataService.SubmitDataChange(pcCooldown, DatabaseActionType.Update); } else { string unlockDateString = unlockDate.ToString("yyyy-MM-dd hh:mm:ss"); creature.SetLocalString("ABILITY_COOLDOWN_ID_" + (int)handler.PerkType, unlockDateString); } }
private static void OnModuleEquipItem() { NWPlayer oPC = _.GetPCItemLastEquippedBy(); if (oPC.GetLocalInt("IS_CUSTOMIZING_ITEM") == _.TRUE) { return; // Don't run heavy code when customizing equipment. } if (!oPC.IsInitializedAsPlayer) { return; // Players who log in for the first time don't have an ID yet. } if (oPC.GetLocalInt("LOGGED_IN_ONCE") <= 0) { return; // Don't fire heavy calculations if this is the player's first log in after a restart. } NWItem oItem = _.GetPCItemLastEquipped(); PlayerStatService.ApplyStatChanges(oPC, null); ApplyWeaponPenalties(oPC, oItem); ApplyEquipmentPenalties(oPC, oItem); }
public static void GiveSkillXP(NWPlayer oPC, int skillID, int xp, bool enableResidencyBonus = true) { if (skillID <= 0 || xp <= 0 || !oPC.IsPlayer) { return; } if (enableResidencyBonus) { xp = (int)(xp + xp * PlayerStatService.EffectiveResidencyBonus(oPC)); } Player player = DataService.Get <Player>(oPC.GlobalID); Skill skill = GetSkill(skillID); // Check if the player has any undistributed skill ranks for this skill category. // If they haven't been distributed yet, the player CANNOT gain XP for this skill. var pool = DataService.SingleOrDefault <PCSkillPool>(x => x.PlayerID == oPC.GlobalID && x.SkillCategoryID == skill.SkillCategoryID && x.Levels > 0); if (pool != null) { oPC.FloatingText("You must distribute all pooled skill ranks before you can gain any new XP in the '" + skill.Name + "' skill. Access this menu from the 'View Skills' section of your rest menu."); return; } PCSkill pcSkill = GetPCSkill(oPC, skillID); SkillXPRequirement req = DataService.Single <SkillXPRequirement>(x => x.SkillID == skillID && x.Rank == pcSkill.Rank); int maxRank = skill.MaxRank; int originalRank = pcSkill.Rank; float xpBonusModifier = player.XPBonus * 0.01f; // Guard against XP bonuses being too high. if (xpBonusModifier > 0.25) { xpBonusModifier = 0.25f; } xp = CalculateTotalSkillPointsPenalty(player.TotalSPAcquired, xp); xp = xp + (int)(xp * xpBonusModifier); // Run the skill decay rules. // If the method returns false, that means all skills are locked. // So we can't give the player any XP. if (!ApplySkillDecay(oPC, pcSkill, xp)) { return; } pcSkill.XP = pcSkill.XP + xp; oPC.SendMessage("You earned " + skill.Name + " skill experience. (" + xp + ")"); // Skill is at cap and player would level up. // Reduce XP to required amount minus 1 XP if (pcSkill.Rank >= maxRank && pcSkill.XP > req.XP) { pcSkill.XP = req.XP - 1; } while (pcSkill.XP >= req.XP) { pcSkill.XP = pcSkill.XP - req.XP; if (player.TotalSPAcquired < SkillCap && skill.ContributesToSkillCap) { player.UnallocatedSP++; player.TotalSPAcquired++; } pcSkill.Rank++; oPC.FloatingText("Your " + skill.Name + " skill level increased to rank " + pcSkill.Rank + "!"); req = DataService.Single <SkillXPRequirement>(x => x.SkillID == skillID && x.Rank == pcSkill.Rank); // Reapply skill penalties on a skill level up. for (int slot = 0; slot < NUM_INVENTORY_SLOTS; slot++) { NWItem item = _.GetItemInSlot(slot, oPC.Object); RemoveWeaponPenalties(item); ApplyWeaponPenalties(oPC, item); RemoveEquipmentPenalties(item); ApplyEquipmentPenalties(oPC, item); } MessageHub.Instance.Publish(new SkillGainedMessage(oPC, skillID)); } DataService.SubmitDataChange(pcSkill, DatabaseActionType.Update); // Update player and apply stat changes only if a level up occurred. if (originalRank != pcSkill.Rank) { PlayerStatService.ApplyStatChanges(oPC, null); } }
private static bool ApplySkillDecay(NWPlayer oPC, PCSkill levelingSkill, int xp) { int totalSkillRanks = GetPCTotalSkillCount(oPC); if (totalSkillRanks < SkillCap) { return(true); } // Find out if we have enough XP to remove. If we don't, make no changes and return false signifying no XP could be removed. var pcSkills = DataService.Where <PCSkill>(x => x.PlayerID == oPC.GlobalID && x.SkillID != levelingSkill.SkillID); var totalXPs = pcSkills.Select(s => { var reqXP = DataService.Where <SkillXPRequirement>(x => x.SkillID == s.SkillID && (x.Rank < s.Rank || x.Rank == 0 && s.XP > 0)); var totalXP = reqXP.Sum(x => x.XP); return(new { s.SkillID, TotalSkillXP = totalXP }); }).ToList(); int aggregateXP = 0; foreach (var p in totalXPs) { aggregateXP += p.TotalSkillXP; } if (aggregateXP < xp) { return(false); } // We have enough XP to remove. Reduce XP, picking random skills each time we reduce. var skillsPossibleToDecay = GetAllPCSkills(oPC) .Where(x => { var skill = DataService.Get <Skill>(x.SkillID); return(!x.IsLocked && skill.ContributesToSkillCap && x.SkillID != levelingSkill.SkillID && (x.XP > 0 || x.Rank > 0)); }).ToList(); // There's an edge case where players can be at the cap, but we're unable to find a skill to decay. // In this scenario we can't go any further. Return false which will cause the GiveSkillXP method to // bail out with no changes to XP or decayed skills. if (skillsPossibleToDecay.Count <= 0) { return(false); } while (xp > 0) { int skillIndex = RandomService.Random(skillsPossibleToDecay.Count); PCSkill decaySkill = skillsPossibleToDecay[skillIndex]; int totalDecaySkillXP = totalXPs.Find(x => x.SkillID == decaySkill.SkillID).TotalSkillXP; int oldRank = decaySkill.Rank; if (totalDecaySkillXP >= xp) { totalDecaySkillXP = totalDecaySkillXP - xp; xp = 0; } else if (totalDecaySkillXP < xp) { totalDecaySkillXP = 0; xp = xp - totalDecaySkillXP; } // If skill drops to 0 total XP, remove it from the possible list of skills if (totalDecaySkillXP <= 0) { skillsPossibleToDecay.Remove(decaySkill); decaySkill.XP = 0; decaySkill.Rank = 0; } // Otherwise calculate what rank and XP value the skill should now be. else { // Get the XP amounts required per level, in ascending order, so we can see how many levels we're now meant to have. List <SkillXPRequirement> reqs = DataService.Where <SkillXPRequirement>(x => x.SkillID == decaySkill.SkillID && x.Rank <= decaySkill.Rank).OrderBy(o => o.Rank).ToList(); // The first entry in the database is for rank 0, and if passed, will raise us to 1. So start our count at 0. int newDecaySkillRank = 0; foreach (SkillXPRequirement req in reqs) { if (totalDecaySkillXP >= req.XP) { totalDecaySkillXP = totalDecaySkillXP - req.XP; newDecaySkillRank++; } else if (totalDecaySkillXP < req.XP) { break; } } decaySkill.Rank = newDecaySkillRank; decaySkill.XP = totalDecaySkillXP; } PCSkill dbDecaySkill = new PCSkill { SkillID = decaySkill.SkillID, IsLocked = decaySkill.IsLocked, ID = decaySkill.ID, PlayerID = decaySkill.PlayerID, Rank = decaySkill.Rank, XP = decaySkill.XP }; DataService.SubmitDataChange(dbDecaySkill, DatabaseActionType.Update); MessageHub.Instance.Publish(new SkillDecayedMessage(oPC, decaySkill.SkillID, oldRank, decaySkill.Rank)); } PlayerStatService.ApplyStatChanges(oPC, null); return(true); }
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 int CalculateForceAccuracy( NWCreature caster, NWCreature target, ForceAbilityType abilityType) { EffectiveItemStats casterItemStats = caster.IsPlayer ? PlayerStatService.GetPlayerItemEffectiveStats(caster.Object) : null; float casterPrimary; float casterSecondary; float casterItemAccuracy = casterItemStats?.ForceAccuracy ?? 0; EffectiveItemStats targetItemStats = target.IsPlayer ? PlayerStatService.GetPlayerItemEffectiveStats(target.Object) : null; float targetPrimary; float targetSecondary; float targetItemDefense = targetItemStats?.ForceDefense ?? 0; switch (abilityType) { case ForceAbilityType.Electrical: casterPrimary = caster.Intelligence; casterSecondary = caster.Wisdom; targetPrimary = target.Intelligence; targetSecondary = target.Wisdom; targetItemDefense = targetItemDefense + targetItemStats?.ElectricalDefense ?? 0; break; case ForceAbilityType.Dark: casterPrimary = caster.Intelligence; casterSecondary = caster.Wisdom; targetPrimary = target.Wisdom; targetSecondary = target.Intelligence; targetItemDefense = targetItemDefense + targetItemStats?.DarkDefense ?? 0; break; case ForceAbilityType.Mind: casterPrimary = caster.Wisdom; casterSecondary = caster.Intelligence; targetPrimary = target.Wisdom; targetSecondary = target.Intelligence; targetItemDefense = targetItemDefense + targetItemStats?.MindDefense ?? 0; break; case ForceAbilityType.Light: casterPrimary = caster.Wisdom; casterSecondary = caster.Intelligence; targetPrimary = target.Intelligence; targetSecondary = target.Wisdom; targetItemDefense = targetItemDefense + targetItemStats?.ElectricalDefense ?? 0; break; default: throw new ArgumentOutOfRangeException(nameof(abilityType), abilityType, null); } // Calculate accuracy based on the caster's primary and secondary stats. Add modifiers for overall item accuracy. float baseAccuracy = caster.Charisma * 0.25f + casterPrimary * 0.75f + casterSecondary * 0.5f + casterItemAccuracy * 0.15f; // Calculate defense based on target's primary and secondary stats. Add modifiers for specific defense types. float baseDefense = target.Charisma * 0.25f + targetPrimary * 0.75f + targetSecondary * 0.5f + targetItemDefense * 0.15f; // Temp defense increases whenever a hostile force ability is used. This is primarily a deterrant towards spamming the same ability over and over. string expiration = target.GetLocalString("TEMP_FORCE_DEFENSE_" + (int)abilityType); if (DateTime.TryParse(expiration, out var unused)) { int tempDefense = target.GetLocalInt("TEMP_FORCE_DEFENSE_" + (int)abilityType); baseDefense += tempDefense; } float delta = baseAccuracy - baseDefense; float finalAccuracy = delta < 0 ? 75 + (float)Math.Floor(delta / 2.0f) : 75 + delta; // Accuracy cannot go above 95% or below 0% if (finalAccuracy > 95) { finalAccuracy = 95; } else if (finalAccuracy < 0) { finalAccuracy = 0; } return((int)finalAccuracy); }
public static void InitializePlayer(NWPlayer player) { if (player == null) { throw new ArgumentNullException(nameof(player)); } if (!player.IsPlayer) { return; } // Player is initialized but not in the DB. Wipe the tag and rerun them through initialization - something went wrong before. if (player.IsInitializedAsPlayer) { if (!DataService.Player.ExistsByID(player.GlobalID)) { SetTag(player, string.Empty); } } if (!player.IsInitializedAsPlayer) { player.DestroyAllInventoryItems(); player.InitializePlayer(); AssignCommand(player, () => _.TakeGoldFromCreature(GetGold(player), player, true)); DelayCommand(0.5f, () => { GiveGoldToCreature(player, 100); }); // Capture original stats before we level up the player. int str = NWNXCreature.GetRawAbilityScore(player, AbilityType.Strength); int con = NWNXCreature.GetRawAbilityScore(player, AbilityType.Constitution); int dex = NWNXCreature.GetRawAbilityScore(player, AbilityType.Dexterity); int @int = NWNXCreature.GetRawAbilityScore(player, AbilityType.Intelligence); int wis = NWNXCreature.GetRawAbilityScore(player, AbilityType.Wisdom); int cha = NWNXCreature.GetRawAbilityScore(player, AbilityType.Charisma); // Take player to level 5 in NWN levels so that we have access to more HP slots GiveXPToCreature(player, 10000); for (int level = 1; level <= 5; level++) { LevelUpHenchman(player, player.Class1); } // Set stats back to how they were on entry. NWNXCreature.SetRawAbilityScore(player, AbilityType.Strength, str); NWNXCreature.SetRawAbilityScore(player, AbilityType.Constitution, con); NWNXCreature.SetRawAbilityScore(player, AbilityType.Dexterity, dex); NWNXCreature.SetRawAbilityScore(player, AbilityType.Intelligence, @int); NWNXCreature.SetRawAbilityScore(player, AbilityType.Wisdom, wis); NWNXCreature.SetRawAbilityScore(player, AbilityType.Charisma, cha); NWItem knife = (CreateItemOnObject("survival_knife", player)); knife.Name = player.Name + "'s Survival Knife"; knife.IsCursed = true; DurabilityService.SetMaxDurability(knife, 5); DurabilityService.SetDurability(knife, 5); NWItem book = (CreateItemOnObject("player_guide", player)); book.Name = player.Name + "'s Player Guide"; book.IsCursed = true; NWItem dyeKit = (CreateItemOnObject("tk_omnidye", player)); dyeKit.IsCursed = true; int numberOfFeats = NWNXCreature.GetFeatCount(player); for (int currentFeat = numberOfFeats; currentFeat >= 0; currentFeat--) { NWNXCreature.RemoveFeat(player, NWNXCreature.GetFeatByIndex(player, currentFeat - 1)); } NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyLight, 1); NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyMedium, 1); NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyHeavy, 1); NWNXCreature.AddFeatByLevel(player, Feat.ShieldProficiency, 1); NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencyExotic, 1); NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencyMartial, 1); NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencySimple, 1); NWNXCreature.AddFeatByLevel(player, Feat.UncannyDodge1, 1); NWNXCreature.AddFeatByLevel(player, Feat.StructureManagementTool, 1); NWNXCreature.AddFeatByLevel(player, Feat.OpenRestMenu, 1); NWNXCreature.AddFeatByLevel(player, Feat.RenameCraftedItem, 1); NWNXCreature.AddFeatByLevel(player, Feat.ChatCommandTargeter, 1); foreach (var skillType in Enum.GetValues(typeof(Skill))) { var skill = (Skill)skillType; if (skill == Skill.Invalid || skill == Skill.AllSkills) { continue; } NWNXCreature.SetSkillRank(player, skill, 0); } SetFortitudeSavingThrow(player, 0); SetReflexSavingThrow(player, 0); SetWillSavingThrow(player, 0); var classType = GetClassByPosition(1, player); for (int index = 0; index <= 255; index++) { NWNXCreature.RemoveKnownSpell(player, classType, 0, index); } Player entity = CreateDBPCEntity(player); DataService.SubmitDataChange(entity, DatabaseActionType.Insert); var skills = DataService.Skill.GetAll(); foreach (var skill in skills) { var pcSkill = new PCSkill { IsLocked = false, SkillID = skill.ID, PlayerID = entity.ID, Rank = 0, XP = 0 }; DataService.SubmitDataChange(pcSkill, DatabaseActionType.Insert); } RaceService.ApplyDefaultAppearance(player); NWNXCreature.SetAlignmentLawChaos(player, 50); NWNXCreature.SetAlignmentGoodEvil(player, 50); BackgroundService.ApplyBackgroundBonuses(player); PlayerStatService.ApplyStatChanges(player, null, true); LanguageService.InitializePlayerLanguages(player); DelayCommand(1.0f, () => ApplyEffectToObject(DurationType.Instant, EffectHeal(999), player)); InitializeHotBar(player); } }
public static void InitializePlayer(NWPlayer player) { if (player == null) { throw new ArgumentNullException(nameof(player)); } if (player.Object == null) { throw new ArgumentNullException(nameof(player.Object)); } if (!player.IsPlayer) { return; } // Player is initialized but not in the DB. Wipe the tag and rerun them through initialization - something went wrong before. if (player.IsInitializedAsPlayer) { if (DataService.GetAll <Player>().SingleOrDefault(x => x.ID == player.GlobalID) == null) { _.SetTag(player, string.Empty); } } if (!player.IsInitializedAsPlayer) { player.DestroyAllInventoryItems(); player.InitializePlayer(); _.AssignCommand(player, () => _.TakeGoldFromCreature(_.GetGold(player), player, 1)); _.DelayCommand(0.5f, () => { _.GiveGoldToCreature(player, 100); }); // Capture original stats before we level up the player. int str = NWNXCreature.GetRawAbilityScore(player, ABILITY_STRENGTH); int con = NWNXCreature.GetRawAbilityScore(player, ABILITY_CONSTITUTION); int dex = NWNXCreature.GetRawAbilityScore(player, ABILITY_DEXTERITY); int @int = NWNXCreature.GetRawAbilityScore(player, ABILITY_INTELLIGENCE); int wis = NWNXCreature.GetRawAbilityScore(player, ABILITY_WISDOM); int cha = NWNXCreature.GetRawAbilityScore(player, ABILITY_CHARISMA); // Take player to level 5 in NWN levels so that we have access to more HP slots _.GiveXPToCreature(player, 10000); for (int level = 1; level <= 5; level++) { _.LevelUpHenchman(player, player.Class1); } // Set stats back to how they were on entry. NWNXCreature.SetRawAbilityScore(player, ABILITY_STRENGTH, str); NWNXCreature.SetRawAbilityScore(player, ABILITY_CONSTITUTION, con); NWNXCreature.SetRawAbilityScore(player, ABILITY_DEXTERITY, dex); NWNXCreature.SetRawAbilityScore(player, ABILITY_INTELLIGENCE, @int); NWNXCreature.SetRawAbilityScore(player, ABILITY_WISDOM, wis); NWNXCreature.SetRawAbilityScore(player, ABILITY_CHARISMA, cha); NWItem knife = (_.CreateItemOnObject("survival_knife", player)); knife.Name = player.Name + "'s Survival Knife"; knife.IsCursed = true; DurabilityService.SetMaxDurability(knife, 5); DurabilityService.SetDurability(knife, 5); NWItem book = (_.CreateItemOnObject("player_guide", player)); book.Name = player.Name + "'s Player Guide"; book.IsCursed = true; NWItem dyeKit = (_.CreateItemOnObject("tk_omnidye", player)); dyeKit.IsCursed = true; int numberOfFeats = NWNXCreature.GetFeatCount(player); for (int currentFeat = numberOfFeats; currentFeat >= 0; currentFeat--) { NWNXCreature.RemoveFeat(player, NWNXCreature.GetFeatByIndex(player, currentFeat - 1)); } NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_LIGHT, 1); NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_MEDIUM, 1); NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_HEAVY, 1); NWNXCreature.AddFeatByLevel(player, FEAT_SHIELD_PROFICIENCY, 1); NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_EXOTIC, 1); NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_MARTIAL, 1); NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_SIMPLE, 1); NWNXCreature.AddFeatByLevel(player, FEAT_UNCANNY_DODGE_1, 1); NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.StructureManagementTool, 1); NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.OpenRestMenu, 1); NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.RenameCraftedItem, 1); NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.ChatCommandTargeter, 1); for (int iCurSkill = 1; iCurSkill <= 27; iCurSkill++) { NWNXCreature.SetSkillRank(player, iCurSkill - 1, 0); } _.SetFortitudeSavingThrow(player, 0); _.SetReflexSavingThrow(player, 0); _.SetWillSavingThrow(player, 0); int classID = _.GetClassByPosition(1, player); for (int index = 0; index <= 255; index++) { NWNXCreature.RemoveKnownSpell(player, classID, 0, index); } Player entity = CreateDBPCEntity(player); DataService.SubmitDataChange(entity, DatabaseActionType.Insert); var skills = DataService.GetAll <Skill>(); foreach (var skill in skills) { var pcSkill = new PCSkill { IsLocked = false, SkillID = skill.ID, PlayerID = entity.ID, Rank = 0, XP = 0 }; DataService.SubmitDataChange(pcSkill, DatabaseActionType.Insert); } RaceService.ApplyDefaultAppearance(player); NWNXCreature.SetAlignmentLawChaos(player, 50); NWNXCreature.SetAlignmentGoodEvil(player, 50); BackgroundService.ApplyBackgroundBonuses(player); PlayerStatService.ApplyStatChanges(player, null, true); LanguageService.InitializePlayerLanguages(player); _.DelayCommand(1.0f, () => _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(999), player)); InitializeHotBar(player); } }