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 int OnLearnScroll(void *pCreature, uint oidScrollToLearn) { OnItemScrollLearn eventData = ProcessEvent(new OnItemScrollLearn { Creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Scroll = oidScrollToLearn.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 static OnCreatureAttack[] GetAttackEvents(void *pCreature, void *pTarget, int nAttacks) { CNWSCreature?creature = CNWSCreature.FromPointer(pCreature); NwGameObject?target = CNWSObject.FromPointer(pTarget).ToNwObject <NwGameObject>(); if (creature == null || target == null) { return(Array.Empty <OnCreatureAttack>()); } NwCreature nwCreature = creature.ToNwObject <NwCreature>() !; // m_nCurrentAttack points to the attack after this flurry. int attackNumberOffset = creature.m_pcCombatRound.m_nCurrentAttack - nAttacks; CNWSCombatRound combatRound = creature.m_pcCombatRound; // Create an event for each attack in the flurry OnCreatureAttack[] attackEvents = new OnCreatureAttack[nAttacks]; for (int i = 0; i < nAttacks; i++) { attackEvents[i] = GetEventData(nwCreature, target, combatRound, attackNumberOffset + i); } return(attackEvents); }
private static int OnRequestSell(void *pCreature, uint oidItemToSell, uint oidStore) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); NwItem? item = oidItemToSell.ToNwObject <NwItem>(); NwStore? store = oidStore.ToNwObject <NwStore>(); int price = 0; if (store != null && item != null) { price = store.Store.CalculateItemBuyPrice(item, creature.m_idSelf); } OnStoreRequestSell eventData = new OnStoreRequestSell { Creature = creature.ToNwObject <NwCreature>() !, Item = item, Store = store, Price = price, }; eventData.Result = new Lazy <bool>(() => !eventData.PreventSell && Hook.CallOriginal(pCreature, oidItemToSell, oidStore).ToBool()); ProcessEvent(eventData); return(eventData.Result.Value.ToInt()); }
private static void OnRemoveAssociate(void *pCreature, uint oidAssociate) { ProcessEvent(new OnAssociateRemove { Owner = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Associate = oidAssociate.ToNwObject <NwCreature>() !, });
public void SetAlwaysWalk(NwCreature creature, bool forceWalk) { CNWSCreature nativeCreature = creature.Creature; InternalVariableBool alwaysWalk = InternalVariables.AlwaysWalk(creature); if (forceWalk) { nativeCreature.m_bForcedWalk = true.ToInt(); alwaysWalk.Value = true; } else { alwaysWalk.Delete(); if (creature.ActiveEffects.Any(activeEffect => activeEffect.EffectType == EffectType.MovementSpeedDecrease)) { return; } if (!nativeCreature.m_bForcedWalk.ToBool()) { nativeCreature.UpdateEncumbranceState(false.ToInt()); nativeCreature.m_bForcedWalk = (nativeCreature.m_nEncumbranceState != 0).ToInt(); } nativeCreature.m_bForcedWalk = false.ToInt(); } }
private static int OnUnequipItem(void *pCreature, uint oidItemToUnequip, uint oidTargetRepository, byte x, byte y, int bMergeIntoRepository, uint oidFeedbackPlayer) { OnItemUnequip eventData = ProcessEvent(new OnItemUnequip { Creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Item = oidItemToUnequip.ToNwObject <NwItem>() !, });
private static void HandleEnter(CNWSCreature creature, byte nDetectMode) { OnDetectModeUpdate eventData = ProcessEvent(new OnDetectModeUpdate { Creature = creature.ToNwObject <NwCreature>() !, EventType = ToggleModeEventType.Enter, });
private static int OnAddCastSpellActions(void *pCreature, uint nSpellId, int nMultiClass, int nDomainLevel, int nMetaType, int bSpontaneousCast, Vector3 vTargetLocation, uint oidTarget, int bAreaTarget, int bAddToFront, int bFake, byte nProjectilePathType, int bInstant, int bAllowPolymorphedCast, int nFeat, byte nCasterLevel) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); OnSpellAction eventData = new OnSpellAction { Caster = creature.ToNwObject <NwCreature>() !, Spell = NwSpell.FromSpellId((int)nSpellId) !, ClassIndex = nMultiClass, Domain = (Domain)nDomainLevel, MetaMagic = (MetaMagic)nMetaType, IsSpontaneous = bSpontaneousCast.ToBool(), TargetPosition = vTargetLocation, TargetObject = oidTarget.ToNwObject <NwGameObject>() !, IsAreaTarget = bAreaTarget.ToBool(), IsFake = bFake.ToBool(), ProjectilePath = (ProjectilePathType)nProjectilePathType, IsInstant = bInstant.ToBool(), Feat = NwFeat.FromFeatId(nFeat) !, CasterLevel = nCasterLevel, }; eventData.Result = new Lazy <bool>(() => !eventData.PreventSpellCast && Hook.CallOriginal(pCreature, nSpellId, nMultiClass, nDomainLevel, nMetaType, bSpontaneousCast, vTargetLocation, oidTarget, bAreaTarget, bAddToFront, bFake, nProjectilePathType, bInstant, bAllowPolymorphedCast, nFeat, nCasterLevel).ToBool()); ProcessEvent(eventData); return(eventData.Result.Value.ToInt()); }
private static void OnSendFeedbackMessage(void *pCreature, ushort nFeedbackId, void *pMessageData, void *pFeedbackPlayer) { const ushort resistanceId = 66; const ushort reductionId = 67; const int remainingDRIndex = 2; if (pMessageData == null) { Hook.CallOriginal(pCreature, nFeedbackId, null, pFeedbackPlayer); return; } CNWSCreature creature = CNWSCreature.FromPointer(pCreature); CNWCCMessageData messageData = CNWCCMessageData.FromPointer(pMessageData); if (nFeedbackId != resistanceId && nFeedbackId != reductionId || creature.m_idSelf != messageData.GetObjectID(0) || messageData.GetInteger(remainingDRIndex) != 0) { Hook.CallOriginal(pCreature, nFeedbackId, pMessageData, pFeedbackPlayer); return; } ProcessEvent(new OnCombatDRBroken { Creature = creature.ToNwObject <NwCreature>() !, Type = nFeedbackId == resistanceId ? DRType.DamageResistance : DRType.DamageReduction, });
private static void OnAddAssociate(void *pCreature, uint oidAssociate, ushort associateType) { ProcessEvent(new OnAssociateAdd { Owner = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Associate = oidAssociate.ToNwObject <NwCreature>() !, AssociateType = (AssociateType)associateType, });
private static void OnPayToIdentifyItem(void *pCreature, uint oidItem, uint oidStore) { OnItemPayToIdentify eventData = ProcessEvent(new OnItemPayToIdentify { Creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Item = oidItem.ToNwObject <NwItem>() !, Store = oidStore.ToNwObject <NwStore>() !, });
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 void OnAddGold(void *pCreature, int nGold, int bDisplayFeedback) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); OnInventoryGoldAdd eventData = ProcessEvent(new OnInventoryGoldAdd { Creature = creature.ToNwObject <NwCreature>() !, Gold = nGold, });
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 static void OnPossessFamiliar(void *pCreature) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); ProcessEvent(new OnFamiliarPossess { Owner = creature.ToNwObject <NwCreature>() !, Familiar = creature.GetAssociateId((ushort)AssociateType.Familiar).ToNwObject <NwCreature>() !, });
private static void OnBroadcastSpellCast(void *pCreature, uint nSpellId, byte nMultiClass, ushort nFeat) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); OnSpellBroadcast eventData = ProcessEvent(new OnSpellBroadcast { Caster = creature.ToNwObject <NwCreature>() !, Spell = NwSpell.FromSpellId((int)nSpellId) !, ClassIndex = nMultiClass, Feat = NwFeat.FromFeatId(nFeat) !, });
private int OnGetDamageBonus(void *pStats, void *pCreature, int bOffHand) { int damageBonus = getDamageBonusHook.CallOriginal(pStats, pCreature, bOffHand); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; bool offHand = bOffHand.ToBool(); CNWSItem?weapon = GetEquippedWeapon(creature, offHand); uint baseItem = weapon != null ? weapon.m_nBaseItem : (uint)BaseItem.Gloves; 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) { damageBonus += GreaterWeaponSpecializationDamageBonus; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = creature.m_pcCombatRound.GetAttack(creature.m_pcCombatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); if (currentAttack.m_nAttackResult == 3) { int criticalThreat = stats.GetCriticalHitMultiplier(bOffHand); debugMessage.Append(GreaterWeaponSpecializationDamageBonus * criticalThreat); debugMessage.Append(" (Greater Weapon Specialization Feat) (Critical x"); debugMessage.Append(criticalThreat); debugMessage.Append(")"); } else { debugMessage.Append(GreaterWeaponSpecializationDamageBonus); debugMessage.Append(" (Greater Weapon Specialization Feat) "); } currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } return(damageBonus); }
private static int OnUseSkill(void *pCreature, byte nSkill, byte nSubSkill, uint oidTarget, Vector3 vTargetPosition, uint oidArea, uint oidUsedItem, int nActivePropertyIndex) { OnUseSkill eventData = ProcessEvent(new OnUseSkill { Creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Skill = NwSkill.FromSkillId(nSkill) !, SubSkill = (SubSkill)nSubSkill, Target = oidTarget.ToNwObject <NwGameObject>() !, Area = oidArea.ToNwObject <NwArea>() !, UsedItem = oidUsedItem.ToNwObject <NwItem>() !, TargetPosition = vTargetPosition, });
private static int OnCreatureUseFeat(void *pCreature, ushort nFeat, ushort nSubFeat, uint oidTarget, uint oidArea, void *pTargetPos) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); OnUseFeat eventData = ProcessEvent(new OnUseFeat { Creature = creature.ToNwObject <NwCreature>() !, Feat = NwFeat.FromFeatId(nFeat) !, SubFeatId = nSubFeat, TargetObject = oidTarget.ToNwObject <NwGameObject>() !, TargetArea = oidArea.ToNwObject <NwArea>() !, TargetPosition = pTargetPos != null ? Marshal.PtrToStructure <Vector3>((IntPtr)pTargetPos) : Vector3.Zero, });
private static int OnUseItem(void *pCreature, uint oidItem, byte nActivePropertyIndex, byte nSubPropertyIndex, uint oidTarget, Vector3 vTargetPosition, uint oidArea, int bUseCharges) { OnItemUse eventData = ProcessEvent(new OnItemUse { UsedBy = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Item = oidItem.ToNwObject <NwItem>() !, TargetObject = oidTarget.ToNwObject <NwGameObject>() !, ItemPropertyIndex = nActivePropertyIndex, ItemSubPropertyIndex = nSubPropertyIndex, TargetPosition = vTargetPosition, TargetArea = oidArea.ToNwObject <NwArea>() !, UseCharges = bUseCharges.ToBool(), });
private float OnGetWalkRate(void *pCreature) { NwCreature?creature = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>(); if (creature == null) { return(walkRateHook.CallOriginal(pCreature)); } InternalVariableFloat rateCap = InternalVariables.WalkRateCap(creature); return(rateCap.HasValue ? rateCap.Value : walkRateHook.CallOriginal(pCreature)); }
private static int OnDoListenDetection(void *pCreature, void *pTarget, int bTargetInvisible) { CNWSCreature target = CNWSCreature.FromPointer(pTarget); if (target.m_nStealthMode == 0 && !bTargetInvisible.ToBool()) { return(true.ToInt()); } CNWSCreature creature = CNWSCreature.FromPointer(pCreature); OnDoListenDetection eventData = ProcessEvent(new OnDoListenDetection { Creature = creature.ToNwObject <NwCreature>() !, Target = target.ToNwObject <NwCreature>() !, });
private static void OnSetCombatMode(void *pCreature, byte nNewMode, int bForceNewMode) { CNWSCreature creature = CNWSCreature.FromPointer(pCreature); if (creature == null) { Hook.CallOriginal(pCreature, nNewMode, bForceNewMode); return; } OnCombatModeToggle eventData = ProcessEvent(new OnCombatModeToggle { Creature = creature.ToNwObject <NwCreature>() !, NewMode = (CombatMode)nNewMode, ForceNewMode = bForceNewMode.ToBool(), });
private static void ForceEnterStealth(CNWSCreature creature, byte nStealthMode) { bool noHIPS = false; if (!creature.m_pStats.HasFeat((ushort)Feat.HideInPlainSight).ToBool()) { creature.m_pStats.AddFeat((ushort)Feat.HideInPlainSight); noHIPS = true; } Hook.CallOriginal(creature, nStealthMode); if (noHIPS) { creature.m_pStats.RemoveFeat((ushort)Feat.HideInPlainSight); } }
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 static uint OnAIActionHeal(void *pCreature, void *pNode) { CNWSObjectActionNode actionNode = CNWSObjectActionNode.FromPointer(pNode); OnHealKitUse eventData = new OnHealKitUse { UsedBy = CNWSCreature.FromPointer(pCreature).ToNwObject <NwCreature>() !, Target = ((uint)actionNode.m_pParameter[0].AsULong()).ToNwObject <NwGameObject>() !, ItemUsed = ((uint)actionNode.m_pParameter[1].AsULong()).ToNwObject <NwItem>() !, ItemPropertyIndex = (int)actionNode.m_pParameter[2], MoveToTarget = ((int)actionNode.m_pParameter[2]).ToBool(), }; eventData.Result = new Lazy <ActionState>(() => !eventData.PreventUse ? (ActionState)Hook.CallOriginal(pCreature, pNode) : ActionState.Failed); ProcessEvent(eventData); return((uint)eventData.Result.Value); }
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()); }