adb3nj Posted January 23, 2023 Share Posted January 23, 2023 The two-shot effect is massively overpowered, so I've been trying to mod it so it costs the player twice as much ammo. The Fallout 3 engine had a built-in way of doing this, but as far as I can tell, the only way of doing it in Fallout 4 is with a script. Does anyone have any ideas for ways to do it elegantly and efficiently? Is there a way to script it so a weapon discharges two rounds simultaneously, or will it have to be a matter of removing the additional round from the player inventory? Link to comment Share on other sites More sharing options...
Fantafaust Posted January 23, 2023 Share Posted January 23, 2023 I don't see any way to do that, really. I mean scripting the ammo removal per shot, sure, but that's a bad solution really. You could reduce the ammo capacity in the gun by half but that's a bad solution too. Maybe, on equip you could silently halve the amount of ammo the player has altogether(saving the remainder) and then multiply the current ammo by two(and return the remainder) when unequipping? That technically would achieve the desired effect. Link to comment Share on other sites More sharing options...
LarannKiar Posted January 23, 2023 Share Posted January 23, 2023 (edited) Create a Quest >> add a new Quest Alias >> fill the Alias with the Player >> Save your plugin >> Open the Quest and the Alias >> attach this script to it >> fill the script property "MyAmmo". Scriptname YOURSCRIPTNAME extends ReferenceAlias Auto bool EventBlock ; if true, OnItemRemoved won't do anything Ammo Property MyAmmo Auto Const ; Ammo of the weapon Event OnAliasInit() AddInventoryEventFilter(MyAmmo) ; Event OnItemRemoved will be received only if akBaseItem (see event below) is MyAmmo RegisterForRemoteEvent(Game.GetPlayer(), "OnItemRemoved") ; listen to the event that's being received when MyAmmo gets removed from the Player's inventory (i.e., when shooting) EndEvent Event ObjectReference.OnItemRemoved(ObjectReference akSenderRef, Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) If EventBlock == False ; see below Actor PlayerRef = Game.GetPlayer() ; ask the native Game script to get the Player reference and temporarly store it as an actor variable for speed (using "Game.GetPlayer()" all the time makes the process a tiny bit slower) If akSenderRef == PlayerRef ; sender object reference is the Player ==> this line is not necessary if there are no other OnItemRemoved registrations (the script can receive OnItemRemoved only if it's sent by the Player) If akBaseItem == MyAmmo ; this line isn't necessary either due to the inventory event filter EventBlock = True ; to prevent the "infinite loop" of removing MyAmmo PlayerRef.RemoveItem(MyAmmo, 1, abSilent = True) ; remove 1 MyAmmo silently EventBlock = False EndIf EndIf EndIf EndEvent See the commented out lines ( the text after ';' ) for more info. The only limitation it is that it doesn't check if there's only one bullet left in the magazine. Edited January 23, 2023 by LarannKiar Link to comment Share on other sites More sharing options...
adb3nj Posted January 23, 2023 Author Share Posted January 23, 2023 (edited) Create a Quest >> add a new Quest Alias >> fill the Alias with the Player >> Save your plugin >> Open the Quest and the Alias >> attach this script to it >> fill the script property "MyAmmo". Scriptname YOURSCRIPTNAME extends ReferenceAlias Auto bool EventBlock ; if true, OnItemRemoved won't do anything Ammo Property MyAmmo Auto Const ; Ammo of the weapon Event OnAliasInit() AddInventoryEventFilter(MyAmmo) ; Event OnItemRemoved will be received only if akBaseItem (see event below) is MyAmmo RegisterForRemoteEvent(Game.GetPlayer(), "OnItemRemoved") ; listen to the event that's being received when MyAmmo gets removed from the Player's inventory (i.e., when shooting) EndEvent Event ObjectReference.OnItemRemoved(ObjectReference akSenderRef, Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer) If EventBlock == False ; see below Actor PlayerRef = Game.GetPlayer() ; ask the native Game script to get the Player reference and temporarly store it as an actor variable for speed (using "Game.GetPlayer()" all the time makes the process a tiny bit slower) If akSenderRef == PlayerRef ; sender object reference is the Player ==> this line is not necessary if there are no other OnItemRemoved registrations (the script can receive OnItemRemoved only if it's sent by the Player) If akBaseItem == MyAmmo ; this line isn't necessary either due to the inventory event filter EventBlock = True ; to prevent the "infinite loop" of removing MyAmmo PlayerRef.RemoveItem(MyAmmo, 1, abSilent = True) ; remove 1 MyAmmo silently EventBlock = False EndIf EndIf EndIf EndEvent See the commented out lines ( the text after ';' ) for more info. The only limitation it is that it doesn't check if there's only one bullet left in the magazine.Thanks! I'll give that a test later. Re the 'one bullet' problem: I figured I'd double the ammo capacity so it's always even, although I realised the game only doubles the base weapon capacity, i.e. it doesn't account for magazine mods, so I might have to find another solution for that :) Edited January 23, 2023 by adb3nj Link to comment Share on other sites More sharing options...
adb3nj Posted January 23, 2023 Author Share Posted January 23, 2023 I don't see any way to do that, really. I mean scripting the ammo removal per shot, sure, but that's a bad solution really. You could reduce the ammo capacity in the gun by half but that's a bad solution too. Maybe, on equip you could silently halve the amount of ammo the player has altogether(saving the remainder) and then multiply the current ammo by two(and return the remainder) when unequipping? That technically would achieve the desired effect.Yup, that could work! Or similarly, the mod could change the ammo type, but I'd then have to add different ammo types for every weapon in the game. Link to comment Share on other sites More sharing options...
LarannKiar Posted January 23, 2023 Share Posted January 23, 2023 (edited) Glad I could help :smile: Anyway, now that I think about it, registering the script for the Player's WeaponFire animation event seems to be a better option.. less exlude conditions needed (as MyAmmo can get removed when selling it, dropping it, etc.). Scriptname YOURSCRIPTNAME extends ReferenceAlias Const Ammo Property AmmoToBeRemoved Auto Const Weapon Property WeaponThatMustBeEquipped Auto Const Event OnAliasInit() RegisterForAnimationEvent(Game.GetPlayer(),"WeaponFire") EndEvent Event OnAnimationEvent(ObjectReference akSource, string asEventName) Actor PlayerRef = Game.GetPlayer() If akSource == PlayerRef && asEventName == "WeaponFire" Weapon PlayerEquippedWeapon = PlayerRef.GetEquippedWeapon() If PlayerEquippedWeapon && PlayerEquippedWeapon == WeaponThatMustBeEquipped PlayerRef.RemoveItem(AmmoToBeRemoved, 1, abSilent = True) EndIf EndIf EndEvent Edited January 23, 2023 by LarannKiar Link to comment Share on other sites More sharing options...
adb3nj Posted January 23, 2023 Author Share Posted January 23, 2023 Glad I could help :smile: Anyway, now that I think about it, registering the script for the Player's WeaponFire animation event seems to be a better option.. less exlude conditions needed (as MyAmmo can get removed when selling it, dropping it, etc.). Scriptname YOURSCRIPTNAME extends ReferenceAlias Const Ammo Property AmmoToBeRemoved Auto Const Weapon Property WeaponThatMustBeEquipped Auto Const Event OnAliasInit() RegisterForAnimationEvent(Game.GetPlayer(),"WeaponFire") EndEvent Event OnAnimationEvent(ObjectReference akSource, string asEventName) Actor PlayerRef = Game.GetPlayer() If akSource == PlayerRef && asEventName == "WeaponFire" Weapon PlayerEquippedWeapon = PlayerRef.GetEquippedWeapon() If PlayerEquippedWeapon && PlayerEquippedWeapon == WeaponThatMustBeEquipped PlayerRef.RemoveItem(AmmoToBeRemoved, 1, abSilent = True) EndIf EndIf EndEvent Thanks again! Is there a mistake at 'If PlayerEquippedWeapon' though? Is there supposed to be some condition other than PlayerEquippedWeapon && PlayerEquippedWeapon == WeaponThatMustBeEquipped? Or is that a check to see if the player has a weapon equipped at all? Link to comment Share on other sites More sharing options...
Fantafaust Posted January 23, 2023 Share Posted January 23, 2023 Larann, I see what you're going for, but the problem is that almost any random weapon in the game can get this effect, it's the vanilla Two-Shot Legendary weapon effect, you can't pre-define a specific weapon for it in properties. You could perhaps check for it in equipped keywords though.Also I'd keep in mind that if this effect ends up on an automatic rifle, that script will be firing(pun intended) a whole lot, like really often. Link to comment Share on other sites More sharing options...
adb3nj Posted January 23, 2023 Author Share Posted January 23, 2023 Larann, I see what you're going for, but the problem is that almost any random weapon in the game can get this effect, it's the vanilla Two-Shot Legendary weapon effect, you can't pre-define a specific weapon for it in properties. You could perhaps check for it in equipped keywords though.Also I'd keep in mind that if this effect ends up on an automatic rifle, that script will be firing(pun intended) a whole lot, like really often. I'm approaching it a different way and attaching the script to the object mod as an enchantment. So I think the script should literally just be: Scriptname LegendaryTwoShotScript extends ActiveMagicEffect Const Event OnEffectStart(Actor akTarget, Actor akCaster) akCaster.RemoveItem((akCaster.GetEquippedWeapon()).GetAmmo(), 1, abSilent = True) EndEventAlthough it's not firing at the moment, so I've probably set it up wrong. With regard to automatic weapons, that's true, but there are automatic weapons with script-based effects in the vanilla game, e.g. the Kneecapper effect. It's part of the reason I was trying to avoid this approach though. Link to comment Share on other sites More sharing options...
SKKmods Posted January 23, 2023 Share Posted January 23, 2023 Whilst papyrus is not good for high performance real time solutions like auto weapon fire, its all we got (without DLL injection) so WeaponFire animation event is the least worst option. It *is* better than OnPlayerFireWeapon used in FollowersScript tho. Since mod_legendary_weapon_twoShot is simply adding +1 uNumProjectiles it is unlikely to trigger OnEffectStart except maybe once when the OMOD is applied to the weapon. Link to comment Share on other sites More sharing options...
Recommended Posts