Jump to content

New to papyrus - need some help


lasere200

Recommended Posts

Hi, I'm looking to create an Auto Loot mod based on my previous version for FNV. I learned the scripting in the FNV geck as I went along and now I just can't get started with Papyrus.

 

The way it worked in FNV is a quest enabled to run at start that would add a non-playable armor to my char that would continously run a script.

 

This was the quest Script:

scn ALEnhSInit

short DoOnce

Begin GameMode
    if DoOnce != 1
        set DoOnce to 1

        Player.AddItem ALEnh 1 1
        ShowMessage ALEnhMInit
        StopQuest ALEnhQInit

    endif
end

This is my new "code" and it's not working. Any help would be greatly appreciated

Scriptname AutoLootQuestScript extends Quest

Armor Property AutoLootArmor Auto
Quest Property AutoLootQuest Auto
Message Property AutoLootMessage Auto
Event OnQuestInit()
  Game.GetPlayer().AddItem(AutoLootArmor, 1, true)    AutoLootMessage.Show()
    AutoLootQuest.Stop()
endEvent

I get this error in the debug log: error: Unable to bind script AutoLootQuestScript to AutoLootQuest (01000F9A) because their base types do not match

Edited by lasere200
Link to comment
Share on other sites

I'm not really sure what your mod is completely doing but why not just create a quest that is attached to the player at all times. You can then attach a script to the player via ReferenceAlias and then they have a script attached to them at all times.

 

But either way I don't know exactly what the armor will do but you'd should probably do something like that anyway. I'm not really sure about your error but to create a quest that Shows a message, Adds and item then ends you'd do the following:

  1. Create a new quest via CK (just 'right-click', 'new' over any other quests).
  2. Give it whatever ID you want and make sure "Start Game Enabled" and "Run Once" are checked then click "OK".
  3. Reopen the script (you needed to do that to auto-generate some properties) and go to Quest Stages.
  4. Right-click on the left, create a new Index then right-click in the top Log-Entry portion (with the index you created highlighted) and click "new". You can leave both the index and log empty you just need it to place a fragment.

Now for the scripting part.

 

While highlighting both the index and entry you created go to the Papyrus Fragment portion and you can put the following:

Utility.wait(5) ;Bethesda's wait onLoad trigger from the SM comes up a little to fast so we put a wait
Game.getPlayer().addItem(AutoLootArmor, 1, true)
AutoLootMessage.show()
Stop() ;you can choose to stop the quest or not. It doesn't really matter

Now for the important bit. After you've put the above in the Papyrus Fragment click Properties right below it. You're going to create TWO properties. One with Type: Armor and Name: AutoLootArmor and another with Type: Message and Name: AutoLootMessage . Leave there initial values default.

 

Now click on each one individually and pick a value, a little drop down menu will appear, then select the AutoLootArmor you created. Same for the Message. Viola run it and it should happen as soon as the player spawns into the game. If you want it to start on some specific event or prerequisite you can just add that condition in the first tab on the lower left.

 

Before you click okay and exit out be sure that "Run on Start" is checked in the Quest Stages tab.

Link to comment
Share on other sites

Thank you very much for your response. I am still trying to get it to work.

 

The armor would run a script made of bits like this:

    if ALEnhGKey
        set KeyR to GetFirstRef 46 1 0
        Label 46
        if IsFormValid KeyR
            if (Player.GetDistance KeyR < 201) && (KeyR.GetDisabled == 0)
                set OREvl to 0
                set OCEvl to 0
                set ORe to KeyR.GetOwner
                set OCe to KeyR.GetParentCellOwner
                if ORe && (ORe != Player.GetBaseObject) && (ORe != PlayerFaction)
                    if GetType ORe == 8
                        set OREvl to (ListGetFormIndex ALEnhLEvilFact ORe >= 0)
                    endif
                endif
                if OCe && (OCe != Player.GetBaseObject) && (OCe != PlayerFaction)
                    if GetType OCe == 8
                        set OCEvl to (ListGetFormIndex ALEnhLEvilFact OCe >= 0)
                    endif
                endif
                if ((ORe == 0) && (OCe == 0)) || (ORe == Player.GetBaseObject) || (ORe == PlayerFaction) || (OCe == Player.GetBaseObject) || (OCe == PlayerFaction) || ((Seen == 0) && (OREvl || OCEvl || ALEnhGSteal))
                    KeyR.Activate Player 1
                endif
            endif
            set KeyR to Pencil01
            set KeyR to GetNextRef
            Goto 46
        endif
    endif

It would cycle through refs and loot based on certain conditions. Here's the link to it http://www.nexusmods.com/newvegas/mods/42631/?

 

I am initially looking to create a mod that automatically loots and instantly scraps to your inventory the items looted. Junk only of course, for starters. I'd be interested in seeing the script for that magnifying class used to track components. Maybe I could use that but I don't know if that's possible. Ref walking was done with NVSE so again I'm at a loss on how to move from one object to another.

 

I feel like the scavenging is too much for anything else but the first 1-2 runs. I wish to make it more efficiet. The NV version had more features but I'm just looking to get started.

Edited by lasere200
Link to comment
Share on other sites

Yea I've been playing with it a bit. It's not really my mod but I'll give you the code I came up with.

Scriptname ScavengeItems extends Actor

Form property TYPETOFIND auto mandatory
float property distanceToLook = 50.0 auto
Form property ScavangerArmor auto const
bool property isEquipped = false auto

Event  OnItemEquipped(Form akBaseObject, ObjectReference akReference)
	if ScavangerArmor == akBaseObject
		isEquipped = true
		checkForJunk()
	endif
endEvent

Function checkForJunk()
	while isEquipped
		ObjectReference[] junkNearme = FindAllReferencesWithKeyword(TYPETOFIND, distanceToLook)
                ;The line above is pretty much just what you need to figure out.
		debug.MessageBox(""+junkNearme)
		if junkNearme.length !=0 || junkNearme != none
			int i = 0
			while i < junkNearme.length
				if junkNearme[i].GetBaseObject() == TYPETOFIND
					AddItem(junkNearMe, 1, false)
					junkNearme[i].delete()
				endif
				i = i +1
			endWhile
		endif
		Utility.wait(1)
	endwhile
endFunction

Event  OnItemUnEquipped(Form akBaseObject, ObjectReference akReference)
	if ScavangerArmor == akReference
		isEquipped = false
	endif
endEvent
 

I have this script running off the player (which is a BIG nono for compatibility issues) but you can figure out how to manipulate it through ReferenceAlias'.

 

With more time looking at it I could probably get it but this should probably get you on your way. (It's a little messy since it was only meant to just debug a bit).

Link to comment
Share on other sites

Thank you very much.

 

Seems to me that the variants of FindClosestReference and FindAllReferences only return "none".

Function checkForJunk()
    while isEquipped
        ObjectReference junkNearme = Game.FindClosestReferenceOfType (TYPETOFIND, 0.0, 0.0, 0.0, distanceToLook)
        if junkNearme != None
                debug.MessageBox(""+junkNearme)
        Utility.wait(1)
        endif
    endwhile
endFunction

set TYPETOFIND to a MiscObject like OilCan01 and no messages around Oil Cans

 

Maybe I'm not using them correctly.

 

EDIT: I got it to work :D I was wrong about FindAllReferences because I did it with FindAllReferencesOfType and a form list. Looking into using the keyword variant now to keep lists small.

 

Thank you so much.

Edited by lasere200
Link to comment
Share on other sites

I just can't understand this no matter how much I google:

Function AutoLoot()
	while isEquipped
		ObjectReference[] junkNearme = FindAllReferencesWithKeyword(AutoLootKeyword, AutoLootRange)
		if junkNearme.length != 0 || junkNearme != none
			int i = 0
			while i < junkNearme.length
                                AddItem(junkNearMe[i], 1, false)
				junkNearMe[i].Delete()
				debug.MessageBox(""+i +junkNearme.length)
				Utility.wait(1)
				i = i + 1
			endWhile
		endif
	endwhile
endFunction

FindAllReferencesWithKeyword continues to find the deleted references. So the objects are removed from the game world but as far as FindAllReferencesWithKeyword is concerned the references are still there. If junkNearme is in a container it will add the item to my inventory but it will not remove it from the container. I guess this is normal since i'm not using RemoveItem but what I don't understand is why is it doing this only once. I mean the object is still in the container and is still found by FindAllReferencesWithKeyword. Shouldn't it spam me with the object? Does junkNearMe.Delete() somehow work if the ref is in a container without removing the item? I just don't get it.

 

I've tried junkNearMe.Activate(Game.GetPlayer()) instead of Add and Remove but it continuously adds the items to my Inventory. The references are still there after activation even though the item is not and get continuously activated.

Edited by lasere200
Link to comment
Share on other sites

A couple of guesses here, could be spot on or hideously wrong:

 

- The found reference after the first loop is the item in your inventory, not the one you deleted from the crate. If you're just getting a list of nearby ObjectRefs, how do you know for sure what container they are in? Or that the Widget in loop 2+ is the same instance from the first loop?

 

- The crate popup shows the item listed because it's showing available forms in addition to references. Items "may or may not exist" when inside a crate. I think I read that in OnItemAdded page for a similar project (my Scavver NPC, who loots via find/acquire procedures).

 

- Or... the crate popup list is some kind of swf menu that doesn't update (shows cached view) because the swf (if that's even what it is) doesn't know you "reached in" and plucked the item by script.

 

I'm still in the process of exploring the "items in a crate may be forms or references" angle. Something about persistent items, but not sure what that term really means yet.

 

You should list the FindAllReferencesWithKeyword results in a debug trace and check your log to see if the loop is finding/editing your inventory in addition to your surroundings.

 

Edit:

 

Also, the wiki examples prefix the array with Game.GetPlayer() : http://www.creationkit.com/fallout4/index.php?title=FindAllReferencesWithKeyword_-_ObjectReference

Link to comment
Share on other sites

Thank you for your answer. I realized that the Item in the Container isn't added at all so at least that's consistent in the sense that my script does not affect containers for now, at all.

 

Basically I've added my keyword to 3 items Oil can, Duct Tape and Coffee Pot. So these are the only items that get found. In Sanctuary, near the workshop and in the house where the workshop is are 2 Oil Cans, 1 Coffee Pot and 1 Duct Tape. There's another Duct Tape in the Toolbox by the weapons bench.

 

I do not think it's finding items in my Inventory because of the "debug.MessageBox(""+junkNearme.length)". The length of the array generated by the FindAllReferencesWithKeyword is always the summed up value of how many references USED to be in range where you are standing. This is what's so crazy. If I use Activate instead of Add the item spam happens only in range of where the reference used to be. If I step away, the spamming of activate on the invisible/ghost reference stops. I hope that made sense.

 

Something else strange to a beginner like me: If I use JunkNearme.Delete() after Add like in my code above, even though the reference still gets detected where the item used to be, it works. If I use it after Activate it doesn't and the Activate spams continues at the ref's last location filling my inventory up.

 

So I guess the ObjectReferences persist somehow, but I don't get it.

 

EDIT: Also it seems that FindAllReferencesWithKeyword does not detect refs in containers.

Edited by lasere200
Link to comment
Share on other sites

  • Recently Browsing   0 members

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