Jump to content

New modder, new Papyrus scripter, strange bug.


BellCube

Recommended Posts

So I'm a new modder working on a script to make the Wood Chopping Block much more convenient by searching around it for a Woodcutter's axe (or other compatible item), programmed in a way that it could be easily adapted for other objects using ResourceFurnitureScript. However, I've run into a few issues:

  • (Only in a vanilla setup) No matter what I set SearchRadius to in the CK, I have to be practically touching the item (axe) for it to work.
  • For some reason, even though I'm calling FailureMessage.Show(), the message still doesn't show.
  • Though I've added a workaround (Activate(Game.GetPlayer(), true)), it would reduce script lag if this could be forcibly run BEFORE ResourceFurnitureScript.
  • (Only in my semi-modded setup) Even though I set a variable multiple times, it always keeps its original value. In other words, I can pick up an axe once, put it in a chest in Markarth (on the other side of Skyrim), and my script will still choose this axe.

 

Can anyone tell me what I'm doing wrong, and possibly how to fix these? Any other advice would be great too.

 

Code:

 

 

Scriptname ConvenientAxe extends ObjectReference
{Grabs a required item from the surrounding area. Attach to the same object ResourceFurnitureScript is attached to.}

formlist Property requiredItemList Auto
{List of items for the attached ResourceFurnitureScript that the script will take if needed}
Formlist Property preferredItemList Auto
{List of items that the script will prefer to take}
Message Property TookItemMessage Auto
{Message to say that a required item was grabbed from somewhere nearby}
Message Property FailureMessage Auto
{Message to show when the script cannot find any required item. Make sure to use an empty message in ResourceFurnitureScript!}
Int Property SearchRadius Auto
{How far to search for a viable item}
ObjectReference ThatItem

Event OnActivate(ObjectReference akActionRef)
if Game.GetPlayer().GetItemCount(requiredItemList) == 0
ThatItem = None
ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(requiredItemList, Game.GetPlayer(), SearchRadius)
if preferredItemList
ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(preferredItemList, Game.GetPlayer(), SearchRadius)
endif
if ThatItem != Game.GetPlayer() && ThatItem != None
Game.GetPlayer().AddItem(ThatItem.GetBaseObject() as Weapon, 1, true)
TookItemMessage.Show()
ThatItem.Disable(True)
Activate(Game.GetPlayer(), true)
Else
FailureMessage.Show()
endif
endif
endEvent

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
;debug.trace(self + ": animation event received=" + asEventName)
if asEventName == "IdleFurnitureExit"
Game.GetPlayer().RemoveItem(ThatItem.GetBaseObject(), 1, True)
ThatItem.Enable(True)
ThatItem = None
;I accidentally uploaded some testing code here. Oops.
endif
endEvent

 

 

Edited by GamingZacharyC
Link to comment
Share on other sites

To what object or objects are you attaching this script?

 

It should be possible to use a custom key press (requires SKSE) when pointing at a wood chopping block to locate and pick up a nearby wood axe. And then activate the wood chopping block. I do something similar in one of my mods, but there I just transfer a pre-stored wood axe from a "container" carried in inventory rather than search the ground for one.

Link to comment
Share on other sites

I'm attaching the script to the Wood Chopping Block, and I'm trying to create as many modules of a suite I'm creating without using SKSE.

 

Also, after doing some more testing in an as-vanilla-as-it-gets environment (SKSE, Engine Fixes, and my mod only), I found some differences. Specifically, the axe system works as-intended now, but for some reason the range is reduces from 500 units (what I entered in CK) to about 5 units. Additionally, the message still fails to show. (I will be editing the original post as well to include this information)

 

As for searching the ground for an axe, I'm using a display rack for the axe. It'd be more complicated for me to target a specific script attached to a specific container and get the MountedItem variable. That was originally what I was going to do until I found Game.FindClosestReferenceOfAnyTypeInListFromRef().

Edited by GamingZacharyC
Link to comment
Share on other sites

I realize where the miscommunication is now. The script is only attached to one Wood Chopping Block (I only want one). However, (in my modded setup; As established, without these mods it has different quirks) this one Chopping Block will choose the same reference every time, no matter where it is.
Link to comment
Share on other sites

Slight tweak to your OnActivate event. If it solves the issue, great. But the other should have behaved properly too.

 

 

Event OnActivate(ObjectReference akActionRef)
  ThatItem = None
  If Game.GetPlayer() == akActionRef
    If akActionRef.GetItemCount(requiredItemList) == 0
      if preferredItemList
        ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(preferredItemList, akActionRef, SearchRadius)
      Else
        ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(requiredItemList, akActionRef, SearchRadius)
      endif
      if ThatItem ;filled with valid data
        akActionRef.AddItem(ThatItem, 1, true)
        TookItemMessage.Show()
        Activate(akActionRef, true)
      Else
        FailureMessage.Show()
      EndIf
    endif
  endif
endEvent

 

 

Link to comment
Share on other sites

It's been a while, but I haven't come up with anything myself. I tried your fix, but it, for some reason, still doesn't resolve the issues. I can't think of any reason for these bugs to occur.

 

A few things I noticed with your modified event:

  • The modified script completely removes the item from the world, whereas mine disables and enables it, giving the illusion of taking and replacing the axe.
  • The modified script uses preferredItemList in a confusing manner. Basically, if it is present, don't check for requiredItemList. The original script checks for something from preferredItemList and uses requiredItemList as a last retort.

I did test with the modified version you gave me. Then, to address these, I've made some changes to the script (see below script). Oddly enough, neither the event you gave me or the modified version I made doesn't seem to work. The range still defaults to (I think) 10 somehow (even though it is set to something crazy like 10,000 in CK) and I wasn't able to properly fix the replace-the-axe functionality (the axe is disabled, but is never enabled)

 

I also noticed some Papyrus practices along the way, like using 1 instead of True

I also noticed a bug in the original that would cause followers to remove an item if ThatItem was still somehow set.

 

 

 

Scriptname CLWATakeAxe extends ObjectReference
{Grabs a required item from the surrounding area. Attach to the same object ResourceFurnitureScript is attached to.}

formlist Property requiredItemList Auto
{List of items for the attached ResourceFurnitureScript that the script will take if needed}
Formlist Property preferredItemList Auto
{List of items that the script will prefer to take}
Message Property TookItemMessage Auto
{Message to say that a required item was grabbed from somewhere nearby}
Message Property FailureMessage Auto
{Message to show when the script cannot find any required item. Make sure to use an empty message in ResourceFurnitureScript!}
Int Property SearchRadius Auto
{How far to search for a viable item}
ObjectReference ThatItem

Event OnActivate(ObjectReference akActionRef)
ThatItem = None
If Game.GetPlayer() == akActionRef
If akActionRef.GetItemCount(requiredItemList) == 0
if preferredItemList
ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(preferredItemList, akActionRef, SearchRadius)
endif
if ThatItem
ThatItem = Game.FindClosestReferenceOfAnyTypeInListFromRef(requiredItemList, akActionRef, SearchRadius)
EndIf
if ThatItem
ThatItem.Disable(1)
TookItemMessage.Show()
akActionRef.AddItem(ThatItem.GetBaseObject(), 1)
Activate(akActionRef, 1)
Else
FailureMessage.Show()
EndIf
endif
endif
endEvent

Event OnAnimationEvent(ObjectReference akSource, string asEventName)
if asEventName == "IdleFurnitureExit" && Game.GetPlayer() == akSource
ThatItem.Enable(1)
akSource.RemoveItem(ThatItem.GetBaseObject(), 1)
ThatItem = None
endif
endEvent

 

 

Edited by GamingZacharyC
Link to comment
Share on other sites

You want the illusion of taking the item instead of actually taking it? Use the method you initially came up with for that. I was hoping to resolve the issues in #2 and #4 of your first post. By actually taking the item from the world and not just disabling it, it was hoped that the script would pick up a different item the next time rather than finding the disabled instance again. And the general restructure was hoped to allow the failure message to show when appropriate. I guess none of that was resolved?

 

Regarding the lists. The way you had it setup, it would fill the item with something from the "main" list and then if the "secondary" list was present override it with something else. I figured why waste that processing, look first for the secondary list and use that otherwise use the main list. The end result would have been the same only difference being an imperceptible reduction in processing time.

 

Yes, you can use 1 for true and 0 for false because a bool is nothing more than a binary on / off switch. But for some of us, using true and false helps with understanding what is intended.

 

As far as search radius, I have no idea what is happening there.

Link to comment
Share on other sites

Further trying to debug my issue, I moved my existing Skyrim SE install (i.e. added a 1 onto the folder name), installed Skyrim again from Steam, and installed the CK again from the Bethesda.net launcher. I then entered the CK, compiled my script again, then attached it to ref 00083dad, a Wood Chopping Block in Ivarstead (IvarsteadExterior04). Properties list looks as follows.

download%20(1).png

When I load into the game (NOTHING but the Axe01 mod I just pulled together and Skyrim SE), ENTIRELY complete the intro sequence, and interact with the Wood Chopping Block, it does nothing (except give me the error message). Mind you, I'm literally standing on top of an axe.

 

Side note: You know that bear Harvar and Ralof are so afraid of? Yeah, dual-wield Imperial Swords (optionally with Frostbite Venom poisoning) and that bear is as good as dead.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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