internal static NwObject?CreateInternal(ICGameObject?gameObject) { if (gameObject == null) { return(null); } return(gameObject switch { CNWSArea area => new NwArea(area), CNWSAreaOfEffectObject areaOfEffect => new NwAreaOfEffect(areaOfEffect), CNWSCreature creature => new NwCreature(creature), CNWSDoor door => new NwDoor(door), CNWSEncounter encounter => new NwEncounter(encounter), CNWSItem item => new NwItem(item), CNWSPlaceable placeable => new NwPlaceable(placeable), CNWSSoundObject soundObject => new NwSound(soundObject), CNWSStore store => new NwStore(store), CNWSTrigger trigger => new NwTrigger(trigger), CNWSWaypoint waypoint => new NwWaypoint(waypoint), CNWSObject => CreateFromVirtualType(gameObject), CGameObject => CreateFromVirtualType(gameObject), CNWSModule => NwModule.Instance, _ => null, });
private static void OnOpenInventory(void *pItem, uint oidOpener) { OnItemInventoryOpen eventData = ProcessEvent(new OnItemInventoryOpen { OpenedBy = oidOpener.ToNwObject <NwCreature>() !, Container = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !, });
private static void OnCloseInventory(void *pItem, uint oidCloser, int bUpdatePlayer) { OnItemInventoryClose eventData = ProcessEvent(new OnItemInventoryClose { ClosedBy = oidCloser.ToNwObject <NwCreature>() !, Container = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !, });
private CNWSItem?GetEquippedWeapon(CNWSCreature creature, bool offHand) { CNWSItem weapon; if (offHand) { weapon = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.LeftHand); if (weapon == null) { CNWSItem main = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (main != null) { CNWBaseItem baseWeapon = NWNXLib.Rules().m_pBaseItemArray.GetBaseItem((int)main.m_nBaseItem); if (baseWeapon != null && baseWeapon.m_nWeaponWield == 8) { weapon = main; } } } } else { weapon = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); } return(weapon); }
private int OnGetRangedDamageBonus(void *pStats) { int damageBonus = getRangedDamageBonusHook.CallOriginal(pStats); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = stats.m_pBaseCreature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (weapon == null) { return(damageBonus); } uint baseItem = weapon.m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponSpecializationMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { return(damageBonus + GreaterWeaponSpecializationDamageBonus); } return(damageBonus); }
private static int OnAddItem(void *pItemRepository, void **ppItem, byte x, byte y, byte z, int bAllowEncumbrance, int bMergeItem) { CItemRepository itemRepository = CItemRepository.FromPointer(pItemRepository); NwGameObject? parent = itemRepository.m_oidParent.ToNwObject <NwGameObject>(); // Early out if parent isn't an item or placeable or Bad Things(tm) happen if (parent is null || parent is not NwItem && parent is not NwPlaceable) { return(Hook.CallOriginal(pItemRepository, ppItem, x, y, z, bAllowEncumbrance, bMergeItem)); } if (ppItem == null) { return(Hook.CallOriginal(pItemRepository, ppItem, x, y, z, bAllowEncumbrance, bMergeItem)); } OnInventoryItemAdd eventData = new OnInventoryItemAdd { AcquiredBy = parent, Item = CNWSItem.FromPointer(*ppItem).ToNwObject <NwItem>() !, }; eventData.Result = new Lazy <bool>(() => !eventData.PreventItemAdd && Hook.CallOriginal(pItemRepository, ppItem, x, y, z, bAllowEncumbrance, bMergeItem).ToBool()); ProcessEvent(eventData); return(eventData.Result.Value.ToInt()); } }
private static int OnCanUseItem(void *pCreature, void *pItem, int bIgnoreIdentifiedFlag) { OnItemValidateUse eventData = ProcessEvent(new OnItemValidateUse { UsedBy = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Item = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !, CanUse = Hook.CallOriginal(pCreature, pItem, bIgnoreIdentifiedFlag).ToBool(), });
private static int OnCanEquipItem(void *pCreature, void *pItem, uint *pEquipToSLot, int bEquipping, int bLoading, int bDisplayFeedback, void *pFeedbackPlayer) { OnItemValidateEquip eventData = ProcessEvent(new OnItemValidateEquip { UsedBy = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Item = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !, Slot = (InventorySlot)Math.Round(Math.Log2(*pEquipToSLot)), Result = (EquipValidationResult)Hook.CallOriginal(pCreature, pItem, pEquipToSLot, bEquipping, bLoading, bDisplayFeedback, pFeedbackPlayer), });
private int OnGetWeaponFinesse(void *pStats, void *pWeapon) { if (pStats == null) { return(false.ToInt()); } CNWSCreatureStats creatureStats = CNWSCreatureStats.FromPointer(pStats); if (!creatureStats.HasFeat((ushort)Feat.WeaponFinesse).ToBool()) { return(0); } return(IsWeaponLight(creatureStats, CNWSItem.FromPointer(pWeapon), true).ToInt()); }
private static int OnRemoveItem(void *pItemRepository, void *pItem) { CItemRepository itemRepository = CItemRepository.FromPointer(pItemRepository); NwGameObject? parent = itemRepository.m_oidParent.ToNwObject <NwGameObject>(); // Early out if parent isn't an item or placeable or Bad Things(tm) happen if (parent is null || parent is not NwItem && parent is not NwPlaceable) { return(Hook.CallOriginal(pItemRepository, pItem)); } ProcessEvent(new OnInventoryItemRemove { RemovedFrom = parent, Item = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !, });
private int OnGetEpicWeaponDevastatingCritical(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = CNWSItem.FromPointer(pWeapon); uint weaponType = weapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = epicWeaponDevastatingCriticalMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } bool canUseFeat = applicableFeatExists && hasApplicableFeat || getEpicWeaponDevastatingCriticalHook.CallOriginal(pStats, pWeapon).ToBool(); if (weapon != null && canUseFeat && OnDevastatingCriticalHit != null) { CNWSCreature creature = stats.m_pBaseCreature; CNWSCombatRound combatRound = creature.m_pcCombatRound; CNWSCombatAttackData attackData = combatRound.GetAttack(combatRound.m_nCurrentAttack); DevastatingCriticalData devastatingCriticalData = new DevastatingCriticalData { Weapon = weapon.ToNwObject <NwItem>() !, Target = creature.m_oidAttackTarget.ToNwObject <NwGameObject>() !, Damage = attackData.GetTotalDamage(1), }; OnDevastatingCriticalHit(devastatingCriticalData); if (devastatingCriticalData.Bypass) { attackData.m_bKillingBlow = 0; return(0); } } return(canUseFeat.ToInt()); }
private float OnMaxAttackRange(void *pCreature, uint oidTarget, int bBaseValue, int bPassiveRange) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); CNWSItem equippedItem = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (equippedItem != null) { uint baseItemType = equippedItem.m_nBaseItem; CNWBaseItem baseItem = NWNXLib.Rules().m_pBaseItemArray.GetBaseItem((int)baseItemType); if (baseItem != null && baseItem.m_nWeaponRanged > 0 && maxRangedAttackDistanceOverrideMap.TryGetValue(baseItemType, out MaxRangedAttackDistanceOverride distanceOverride)) { return(bPassiveRange.ToBool() ? distanceOverride.MaxRangedPassiveAttackDistance : distanceOverride.MaxRangedAttackDistance); } } return(creature.DesiredAttackRange(oidTarget, bBaseValue) + 1.5f); }
private int OnGetRangedAttackBonus(void *pStats, int bIncludeBase, int bTouchAttack) { int attackBonus = getRangedAttackBonusHook.CallOriginal(pStats, bIncludeBase, bTouchAttack); if (bTouchAttack.ToBool()) { return(attackBonus); } CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = stats.m_pBaseCreature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (weapon == null) { return(attackBonus); } uint baseItem = weapon.m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponFocusMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { attackBonus += GreaterWeaponFocusAttackBonus; } if (EnableSlingGoodAimFeat && baseItem == (uint)BaseItem.Sling && stats.m_nRace != (ushort)RacialType.Halfling && stats.HasFeat((ushort)Feat.GoodAim).ToBool()) { attackBonus += 1; } return(attackBonus); }
private int OnGetUseMonkAttackTables(void *pStats, int bForceUnarmed) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; int monkLevels = GetLevelByClass(stats, (uint)ClassType.Monk); if (monkLevels < 1 || !creature.GetUseMonkAbilities().ToBool()) { return(false.ToInt()); } CNWSItem mainWeapon = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (mainWeapon == null) { return(true.ToInt()); } if (bForceUnarmed.ToBool()) { return(false.ToInt()); } uint mainWeaponType = mainWeapon.m_nBaseItem; if (mainWeaponType != (uint)BaseItem.Kama && !monkWeaponSet.Contains(mainWeapon.m_nBaseItem)) { return(false.ToInt()); } CNWSItem secondWeapon = creature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.LeftHand); if (secondWeapon == null) { return(true.ToInt()); } uint secondWeaponType = secondWeapon.m_nBaseItem; return((secondWeaponType is (uint)BaseItem.Kama or(uint) BaseItem.Torch || monkWeaponSet.Contains(secondWeaponType)).ToInt()); }
private bool IsWeaponLight(CNWSCreatureStats stats, CNWSItem weapon, bool finesse) { if (IsUnarmedWeapon(weapon)) { return(true); } CNWSCreature creature = stats.m_pBaseCreature; if (creature == null) { return(false); } int creatureSize = creature.m_nCreatureSize; if (creatureSize is < (int)CreatureSize.Tiny or > (int)CreatureSize.Huge) { return(false); } if (finesse) { const byte defaultSize = (byte)CreatureSize.Huge + 1; byte size = weaponFinesseSizeMap.GetValueOrDefault(weapon.m_nBaseItem, defaultSize); if (creatureSize >= size) { return(true); } } int rel = stats.m_pBaseCreature.GetRelativeWeaponSize(weapon); if (finesse && creatureSize < (int)CreatureSize.Small) { return(rel <= 0); } return(rel < 0); }
private int OnGetWeaponImprovedCritical(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); uint weaponType = pWeapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = weaponImprovedCriticalMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } return(applicableFeatExists && hasApplicableFeat ? 1 : getWeaponImprovedCriticalHook.CallOriginal(pStats, pWeapon)); }
private int OnGetEpicWeaponFocus(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); uint weaponType = pWeapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = epicWeaponFocusMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool() || feat == (ushort)Feat.EpicWeaponFocus_Creature && stats.HasFeat((ushort)Feat.EpicWeaponFocus_Unarmed).ToBool(); if (hasApplicableFeat) { break; } } } return(applicableFeatExists && hasApplicableFeat ? 1 : getEpicWeaponFocusHook.CallOriginal(pStats, pWeapon)); }
private static int OnCheckProficiencies(void *pCreature, void *pItem, uint nEquipToSlot) { NwCreature?creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>(); NwItem? item = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>(); if (creature == null || item == null) { return(Hook.CallOriginal(pCreature, pItem, nEquipToSlot)); } OnCreatureCheckProficiencies eventData = ProcessEvent(new OnCreatureCheckProficiencies { Creature = creature, Item = item, TargetSlot = (EquipmentSlots)nEquipToSlot, }); return(eventData.ResultOverride switch { CheckProficiencyOverride.HasProficiency => true.ToInt(), CheckProficiencyOverride.NoProficiency => false.ToInt(), _ => Hook.CallOriginal(pCreature, pItem, nEquipToSlot), });
private int OnGetAttackModifierVersus(void *pStats, void *pCreature) { int attackMod = getAttackModifierVersusHook.CallOriginal(pStats, pCreature); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; CNWSCombatRound combatRound = creature.m_pcCombatRound; if (combatRound == null) { return(attackMod); } CNWSItem weapon = combatRound.GetCurrentAttackWeapon(combatRound.GetWeaponAttackType()); if (weapon == null) { return(attackMod); } uint baseItem = weapon.m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponFocusMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { attackMod += GreaterWeaponFocusAttackBonus; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = combatRound.GetAttack(combatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); debugMessage.Append(GreaterWeaponFocusAttackBonus); debugMessage.Append(" (Greater Weapon Focus Feat)"); currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } if (EnableSlingGoodAimFeat && baseItem == (uint)BaseItem.Sling && stats.m_nRace != (ushort)RacialType.Halfling && stats.HasFeat((ushort)Feat.GoodAim).ToBool()) { int goodAimModifier = NWNXLib.Rules().GetRulesetIntEntry("GOOD_AIM_MODIFIER".ToExoString(), 1); attackMod += goodAimModifier; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = combatRound.GetAttack(combatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); debugMessage.Append(goodAimModifier); debugMessage.Append(" (Good Aim Feat)"); currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } return(attackMod); }
internal NwItem(CNWSItem item) : base(item) { Item = item; Inventory = new Inventory(this, item.m_pItemRepository); Appearance = new ItemAppearance(this); }