예제 #1
0
        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,
            });
예제 #2
0
 private static void OnOpenInventory(void *pItem, uint oidOpener)
 {
     OnItemInventoryOpen eventData = ProcessEvent(new OnItemInventoryOpen
     {
         OpenedBy  = oidOpener.ToNwObject <NwCreature>() !,
         Container = CNWSItem.FromPointer(pItem).ToNwObject <NwItem>() !,
     });
예제 #3
0
 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>() !,
     });
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
            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());
            }
        }
예제 #7
0
 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(),
     });
예제 #8
0
 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),
     });
예제 #9
0
        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());
        }
예제 #10
0
            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>() !,
                });
예제 #11
0
        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());
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
        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());
        }
예제 #15
0
        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);
        }
예제 #16
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));
        }
예제 #17
0
        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),
                });
예제 #19
0
        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);
        }
예제 #20
0
파일: NwItem.cs 프로젝트: nwn-dotnet/Anvil
 internal NwItem(CNWSItem item) : base(item)
 {
     Item       = item;
     Inventory  = new Inventory(this, item.m_pItemRepository);
     Appearance = new ItemAppearance(this);
 }