Jump to content

[LE] Why is the script not working?


Masterofnet

Recommended Posts

Let me explain this script a little better.

Scriptname PlayerAliasScript extends ReferenceAlias

Int Count
Int NoPoison
Potion Property ThePotion Auto

ReferenceAlias Property PoisonedWeapon Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
AddInventoryEventFilter(ThePotion) ; The exact poison you are using on the weapon.

Count += 1
;-------------------------------------------------------------------------------------
; The Wait must be used here because this is the only way we can determine if the
Poison has been applied. The Event OnItemRemoved fires twice when you poison a weapon
or take a potion. 

Utility.Wait(0.7) 
;---------------------------------------------------------------------------------
If Count = 2
Weapon Poisoned = (PlayerRef.GetEquippedWeapon())

Int WeaponCount = PlayerRef.GetItemCount(Poisoned)
;----------------------------------------------------------------------------------------------
; This must be done to clear any other weapons of the same type from the players
inventory. The Drop function always drops the unequipped weapon first. If there are no
extras it will go right to the next function. If they exist I drop, count, and disable
them.  

While WeaponCount > 1 
(PlayerRef.DropObject(Poisoned)).Disable()
NoPoison += 1
EndWhile
;--------------------------------------------------------------------------------------------------
; Now I have the exact weapon that has been poisoned. I drop it and force it to a
ReferenceAlias that has a script on it to keep track of it. If it is equipped,
Un-eqipped etc.

PoisonedWeapon.ForceRefTo(PlayerRef.DropObject(Poisoned))
ObjectReference PWeaponRef = PoisonedWeapon.GetReference()

PlayerRef.AddItem(PWeaponRef, 1, True)
Utility.Wait(1) ;You must add Wait here or the weapon will not equip.
PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)
;------------------------------------------------------------------------------
After I equip the poisoned weapon the removed weapons are added back into the players
inventory.  

PlayerRef.AddItem(Poisoned,NoPoison,True) 
EndIf
endEvent

I see in your script you get the Form of the equipped weapon. Do you think that will work on drop? Do you think it will be able to separate it from the other exact weapons? (If any are in inventory) I have never used that or had a need to. I have always separated items by getting an object reference.

 

So this could be all I may need to do?

Scriptname PlayerAliasScript extends ReferenceAlias

Bool PropertiesGate
Int PotionCount
Potion Property ThePotion Auto

ReferenceAlias Property PoisonedWeaponRef Auto

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)
AddInventoryEventFilter(ThePotion) ; The exact poison you are using on the weapon.
Actor PlayerRef = Game.GetPlayer()
If AkBaseItem == ThePotion
PotionCount += 1
EndIf
;-------------------------------------------------------------------------------------
; The Wait must be used here because this is the only way we can determine if the

Utility.Wait(0.7) 
;---------------------------------------------------------------------------------
If PotionCount == 2

If PropertiesGate == False
Form Poisonedfm = PlayerRef.GetEquippedWeapon() as Form
PropertiesGate = True
EndIf
 PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisonedfm, 1))
 PlayerRef.AddItem(PoisonedWeaponRef.GetReference(),1,True)
 Utility.Wait(1)
 PlayerRef.EquipItem(Poisonedfm,False,True)

EndIf
EndEvent
Edited by Masterofnet
Link to comment
Share on other sites

Using form does not work. The game drops the unequipped weapons first.

This script is removing all of the weapons of which there are 5 and adding 14 I can not figure out why.

 

I have run some things down but they make no sense. The add items function is adding twice the amount of the INT even if I put in a #

 

PlayerRef.AddItem(Poisoned,2,True) It will add 4 Why????

Scriptname PlayerAliasPotion extends ReferenceAlias  


Bool PropertiesGate
Int PotionCount
Potion Property ThePotion Auto
Form Property PFM Auto
KeyWord Property VendorItemPoison Auto
Int NoPoison

ReferenceAlias Property PoisonedWeaponRef Auto


EVENT OnInit()
    self.AddInventoryEventFilter(ThePotion)     ; The exact poison you are using on the weapon.
Debug.Notification("Fired")
ENDEVENT

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

Debug.Notification("Event Fired")
Actor PlayerRef = Game.GetPlayer()

If AkBaseItem == ThePotion
PotionCount += 1
EndIf

Utility.Wait(0.7) 
If PotionCount == 1
PotionCount =0
ElseIf PotionCount == 2
Weapon Poisoned = (PlayerRef.GetEquippedWeapon())

Int WeaponCount = PlayerRef.GetItemCount(Poisoned)

If WeaponCount == 5
Debug.Notification("Got Five")
EndIf

While WeaponCount > 1  ;THIS IS NOT WORKING. IT IS NOT PRECISE ENOUGH TO COUNT THEM CORRECTLY EVEYTIME.  
(PlayerRef.DropObject(Poisoned)).Disable()
WeaponCount -=1
NoPoison += 1
EndWhile

PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
ObjectReference PWeaponRef = PoisonedWeaponRef.GetReference()

PlayerRef.AddItem(PWeaponRef, 1, True)
Utility.Wait(1)
PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)

PlayerRef.AddItem(Poisoned,NoPoison,True) ; This is adding twice as many times as the Int States, PlayerRef.AddItem(Poisoned,2,True) It adds 4 Why????
EndIf
endEvent
Edited by Masterofnet
Link to comment
Share on other sites

This section of the code is the reason for your extras. Because of the Wait both instances of the event will see a PotionCount of 2 and so all of that code runs twice (but not at exactly the same time leading to the strange numbers you're seeing.)

If AkBaseItem == ThePotion
PotionCount += 1
EndIf

Utility.Wait(0.7) 
If PotionCount == 1
PotionCount =0
ElseIf PotionCount == 2
;;;; do stuff 
EndIf

Try this instead because only the first event should be waiting. The second event needs to happen during the wait.

If AkBaseItem == ThePotion
    PotionCount += 1

    If PotionCount == 1
        Utility.Wait(0.7) 
        PotionCount = 0
    ElseIf PotionCount == 2
        ;;;; do stuff 
    EndIf

EndIf
Link to comment
Share on other sites

Thinking about this a little more, this should work:


Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

Debug.Notification("Event Fired")
Actor PlayerRef = Game.GetPlayer()

If AkBaseItem == ThePotion
    PotionCount += 1

    If PotionCount == 1
        Utility.Wait(0.7) 
        PotionCount =0
    Else
        Weapon Poisoned = (PlayerRef.GetEquippedWeapon())
        ObjectReference UnpoisonedStackRef
        ObjectReference PoisonedRef

        ; drop the stack of weapons that won't get poison
        Int UnpoisonedCount = PlayerRef.GetItemCount(Poisoned) - 1
        if UnpoisonedCount > 0
            UnpoisonedStackRef = PlayerRef.DropItem(Poisoned, UnpoisonedCount)
        endif

        ; now drop the equipped one so it can be poisoned       
        PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
        PoisonedRef = PoisonedWeaponRef.GetReference()

        ; give the poisoned item back and equip it
        PlayerRef.AddItem(PoisonedRef, 1, True)
        Utility.Wait(0.1) ; you shouldn't need to wait this long
        PlayerRef.EquipItem(PoisonedRef.GetBaseObject(), False, True)

        ; finally give back the stack of unpoisoned ones (if there are any)
        if UnpoisonedStackRef
            PlayerRef.AddItem(UnpoisonedStackRef, 1, true)
        endif
    EndIf
EndIf

endEvent
Link to comment
Share on other sites

Cooley you are a God Send. I just gated it and it works perfectly. I don't see how the functions can fire twice when the Count only reaches 2 in my testing once, but it is the problem. I am going to get some sleep and have a look when I wake up.

 

Ya and thanks again. I can just not get out of my own way on this. For some reason I though you could not drop # of items. That is I why I have been counting them down. That is exactly what I would have done. Get the count -1 and drop them.

 

I did read that they are dropped one at a time so you may not be able to get a stack of them.

Also can you disable them?? With your script the player would see the weapons fall and lay on the ground. This script does work very well now. You can not see the dropped items at all and the weapon just looks like it was unequipped and then re- equipped.

 

As far as the Wait(1) I have never had to use a wait at all between adding an item and equipping it. It may have something to do with the gating issue as well.

Scriptname PlayerAliasPotion extends ReferenceAlias  


Bool PropertiesGate
Int PotionCount
Potion Property ThePotion Auto
KeyWord Property VendorItemPoison Auto
Int NoPoison

ReferenceAlias Property PoisonedWeaponRef Auto


EVENT OnInit()
    self.AddInventoryEventFilter(ThePotion)     ; The exact poison you are using on the weapon.
Debug.Notification("Fired")
ENDEVENT



Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

Debug.Notification("Event Fired")
Actor PlayerRef = Self.GetReference() As Actor

If AkBaseItem == ThePotion
PotionCount += 1
EndIf

Utility.Wait(0.7) 
If PotionCount == 1
PotionCount =0
ElseIf PotionCount == 2
If PropertiesGate == False
PropertiesGate = True
Weapon Poisoned = (PlayerRef.GetEquippedWeapon())

Int WeaponCount = PlayerRef.GetItemCount(Poisoned)

While WeaponCount >1
(PlayerRef.DropObject(Poisoned)).Disable()
WeaponCount -=1
NoPoison +=1
EndWhile

PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
ObjectReference PWeaponRef = PoisonedWeaponRef.GetReference()

PlayerRef.AddItem(PWeaponRef, 1, True)
Utility.Wait(1)
PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)

PlayerRef.AddItem(PWeaponRef.GetBaseObject(),NoPoison,True) 
EndIf
EndIf
endEvent

Edited by Masterofnet
Link to comment
Share on other sites

One last thing about the Wait at the beginning. You must have it above the PotionCount == 1 because you need to use that to put the potion back in the players inventory if it is dropped. That is the only way to distinguish between it being dropped and being used. By the time the wait is done if the potion was used it will be at 2. If the potion is dropped the wait does not matter because it will always be one. You check the inventory and if it is not there you put it back.

 

 

 

I was unable to add the stack back into the players inventory because it gave all of the weapons one objectreference. If the player were to drop them into the environment they would all disappear until only one was left.

 

UPDATE: This was a really good attempt. However it does not function up to my standards. If you drop the potion enough times etc. it can sometimes fail. Thanks for the help. If anyone has any ideas on how this could be "fool prof" I am happy to hear them, but unfortunately I doubt it.

Scriptname PlayerAliasPotion extends ReferenceAlias  

Int PotionCount
Int UnpoisonedCount
Potion Property ThePotion Auto
ObjectReference UnpoisonedStackRef
ObjectReference PWeaponRef
ObjectReference PotionRef
ReferenceAlias Property PotionAlias Auto
ReferenceAlias Property PoisonedWeaponRef Auto
Bool Gate


EVENT OnInit()
    self.AddInventoryEventFilter(ThePotion)     ; The exact poison you are using on the weapon.
Debug.Notification("Fired")
ENDEVENT



Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

Actor PlayerRef = Self.GetReference() As Actor
PotionRef = PotionAlias.GetReference()

If AkBaseItem == ThePotion
  PotionCount += 1
EndIf

Utility.Wait(0.1) 

If PotionCount == 2

If Gate == False
   Gate = True

Weapon Poisoned = (PlayerRef.GetEquippedWeapon())

  UnpoisonedCount = PlayerRef.GetItemCount(Poisoned) - 1
  If UnpoisonedCount > 0
    UnpoisonedStackRef = PlayerRef.DropObject(Poisoned, UnpoisonedCount).Disable()
  EndIf

PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
PWeaponRef = PoisonedWeaponRef.GetReference()

PlayerRef.AddItem(PWeaponRef, 1, True)
PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)

PlayerRef.AddItem(Poisoned, UnpoisonedCount, True) 
EndIf

ElseIf PotionCount == 1
  If !PlayerRef.GetItemCount(PotionRef)
    If akDestContainer
       akDestContainer.RemoveItem(PotionRef, 1 , False, PlayerRef )
    Else
    PlayerRef.AddItem(PotionRef, Absilent = 1)
    EndIf
    Debug.Notification("You can not drop this!")
    PotionCount = 0
  EndIf
EndIf
EndEvent

Edited by Masterofnet
Link to comment
Share on other sites

You've added new features and that means you'll need a different structure. Timing issues are best handled with states. I spent many weeks exploring how the inventory functions interact for my Storage Helpers mod and states were the only way I was able to get things to work reliably. And in this case I think it makes the code easier to read. (I've also never needed a wait between the additem and equip but you're original code had one so I left it not knowing if you had a specific reason for using it.)

Scriptname PlayerAliasPotion extends ReferenceAlias  

Int UnpoisonedCount
Potion Property ThePotion Auto
ObjectReference UnpoisonedStackRef
ObjectReference PWeaponRef
ObjectReference PotionRef
ReferenceAlias Property PotionAlias Auto
ReferenceAlias Property PoisonedWeaponRef Auto


EVENT OnInit()
    self.AddInventoryEventFilter(ThePotion)     ; The exact poison you are using on the weapon.
Debug.Notification("Fired")
ENDEVENT


Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

    GoToState("Watching") ; watch for the poison confirmation choice

    Utility.Wait(0.2) ; give plenty of time for the other event instance to be processed

    if GetState("Watching") ; return the poison potion if it wasn't used

        GoToState("") ; prepare for next time

        Actor PlayerRef = Self.GetReference() As Actor
        PotionRef = PotionAlias.GetReference()
        If !PlayerRef.GetItemCount(PotionRef)
            If akDestContainer
               akDestContainer.RemoveItem(PotionRef, 1 , False, PlayerRef )
            Else
                PlayerRef.AddItem(PotionRef, Absilent = True)
            EndIf
            Debug.Notification("You can not drop this!")
        EndIf
     endif
  EndIf
EndEvent

    
State Watching  ; for the poison confirmation

Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

    GoToState("") ; this lets the first event instance know that the poison is being applied

    Actor PlayerRef = Self.GetReference() As Actor
    PotionRef = PotionAlias.GetReference()
    Weapon Poisoned = (PlayerRef.GetEquippedWeapon())

    UnpoisonedCount = PlayerRef.GetItemCount(Poisoned) - 1
    If UnpoisonedCount > 0
        UnpoisonedStackRef = PlayerRef.DropObject(Poisoned, UnpoisonedCount)
        UnpoisonedStackRef.Disable()
    EndIf

    PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
    PWeaponRef = PoisonedWeaponRef.GetReference()

    PlayerRef.AddItem(PWeaponRef, 1, True)
    PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)

    PlayerRef.AddItem(Poisoned, UnpoisonedCount, True) 

EndEvent

EndState
Link to comment
Share on other sites

I got. I can use get distance to 100% tell if a potion has been placed on a weapon.

 

I will update with the script when I get a chance. I did not think this was going to work. Thanks for your help CdCooley and everyone else.

 

Please feel free to comment on the new script if you feel it can be improved.

 

 

I can't believe it. This script is flawless. You know I keep my threads up to date so that may change but I beat the S*** out of this script and is just laughed at me.

 

100% perfect every time.

 

Now I need to run down the couple of weapons that may have an issue with Drop.

Scriptname PlayerAliasPotion extends ReferenceAlias  

Potion Property ThePotion Auto
ObjectReference Property UnpoisonedStackRef Auto Hidden
ObjectReference Property PWeaponRef Auto Hidden
ObjectReference Property PotionRef Auto Hidden
ReferenceAlias Property PotionAlias Auto
ReferenceAlias Property PoisonedWeaponRef Auto
Bool Gate
Int Distance
Weapon Poisoned
Actor PlayerRef

EVENT OnInit()
    self.AddInventoryEventFilter(ThePotion)     ; The exact poison you are using on the weapon.
Debug.Notification("Fired")
ENDEVENT



Event OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)

PlayerRef = Self.GetReference() As Actor
PotionRef = PotionAlias.GetReference()

If PlayerRef.GetItemCount(ThePotion)
Return
Else 
Distance = PlayerRef.GetDistance(PotionRef) as Int
  If akDestContainer 
    akDestContainer.RemoveItem(PotionRef, 1 , False, PlayerRef )
    Debug.Notification("You can not drop this!")
  Else  
    If Distance <  4000
      PlayerRef.AddItem(PotionRef,1,True)
      Debug.Notification("You can not drop this!")
    Else
      WeaponPoisoned()
    EndIf
  EndIf
EndIf
EndEvent  

Function WeaponPoisoned()
Poisoned = (PlayerRef.GetEquippedWeapon())

Int  UnpoisonedCount = PlayerRef.GetItemCount(Poisoned) - 1
  If UnpoisonedCount > 0
    UnpoisonedStackRef = PlayerRef.DropObject(Poisoned, UnpoisonedCount).Disable()
  EndIf

PoisonedWeaponRef.ForceRefTo(PlayerRef.DropObject(Poisoned))
PWeaponRef = PoisonedWeaponRef.GetReference()

PlayerRef.AddItem(PWeaponRef, 1, True)
PlayerRef.EquipItem(PWeaponRef.GetBaseObject(), False, True)

PlayerRef.AddItem(Poisoned, UnpoisonedCount, True) 

EndFunction

Edited by Masterofnet
Link to comment
Share on other sites

There's a fairly simple way around the drop bug too but until you had everything else working I didn't want to mention it because it makes the script even messier.

 

You need to use AddInventoryEventFilter on the weapon you're about to drop. You change to a new state watching for the weapon (as a separate but similar state to the one watching for the poison confirmation), then use the OnItemRemoved event in that state to get the reference. You'll only get a reference if the item was persistent and sometimes you'll get the exact same reference you're already getting from DropObject. With careful use of Wait and switching the state (and resetting the inventory event filter) you can get those pesky references for every item.

 

Your code is also not putting back the actual items taken from the player for the unpoisoned ones. In 99.9% of the cases that's fine, but if you're going for absolute safety you need return the items that were dropped UnpoisonedStackRef instead of Poisoned as the first parameter. (And the Disable call has to be done on a separate line.)

 

If the player has a collection of a particular weapon but some have player enchantments, improvements, or are somehow persistent the game may choose to only drop some of them despite the number you pass to DropObject. (The ordinary items get dropped as a group but customized ones may need to be dropped individually.) The fix for that is to make UnpoisonedStackRef an array and simply loop as long as the player has more than one left and store all of the resulting references into the array (including using the trick above to get the reference for any tricky persistent ones) then put back those references using additem on the reference id not the base formid. For this purpose you would certainly be safe just allocating it with 128 elements and keeping your own size variable to know how many you used. Generally it would be just 1 but it could be dozens, especially if the player had just gone on a crafting spree. The game doesn't always stack even ordinary weapons just after they've been crafted or improved.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...