Jump to content

Understanding dynamic array correctly


SMB92

Recommended Posts

Hi folks.

 

I'm doing some study into using arrays with Papyrus, currently I'm looking at how I can use a dynamic array to do what I want. I've got a bout 6 or so wiki pages up that I've been reading through, as well as various example code I've looked at in War of the Commonwealth. I was hoping to get some advice on what I've learnt so far.

 

First I'll say what I want to do with this and then I'll post the example code I just made. What we want to do is, dynamically create a list of Actors that spawn at a spawn point (that I've made) so I can do things with them later, such as disable them/delete them when they have been unloaded for some time. And I also want to destroy the array in that particular case so it's not making my spawnpoint persistent forever. You might say I can do that with PlaceAtMe function, but I need to use PlaceActorAtMe function, so I need to do this instead.

 

Here is example/test code I wrote, with commentary:

Event OnCellAttach
	;Do what I need to do to get to Function Spawn(), if we do
	Spawn()
EndEvent

Function Spawn()
	if (WhoToSpawn == 1)  && (1S_Allowed_Raiders_R1.GetValueInt() == 1)   ;1 = Raiders, and are we allowed to spawn Raiders according to user settings
		SpawnCounter = 1S_Max_Allowed_Raiders_R1.GetValueInt()            ;Maximum allowed units to spawn
			while (SpawnCounter > 0)
				if (Utility.RandomInt(1,100) >= 1S_Chance_Raiders_R1.GetValueInt())      ;Chance of a unit actually spawning (makes the spawn amounts a bit more dynamic)
					Actor[] SpawnList = new Actor[0]              ;The list of Actors that will be controlled, maybe I should make this straight after the function call instead of in this block
					Spawn = Self.PlaceActorAtMe(LvlRaider, Utility.RandomInt(1,Difficulty), R1_EZ)    ;Place the spawn
					Spawn.SetLinkedRef(PatrolMarker)			;Set the NPC to use the Patrol marker network I've created, there is a starting marker next to each point (we use GetClosest function rather than property)
					SpawnList[GroupMembers].Add(Spawn as Actor)		;Add the spawnpoint to the array, GroupMarkers is a declared Int starting at 0. Not sure if this is correct method but for example only
					GroupMembers = GroupMembers + 1				;Increment the index number + 1 
					SpawnCounter = SpawnCounter - 1                         ;Lower spawn count remaining
					Spawn = None						;Ready for next actor	
					SpawnSuccess = True					;This value is used for another function
				else
					SpawnCounter = SpawnCounter - 1				;Lower spawn count on unsuccessful dice roll for dynamic group size
				endif
			endwhile
	endif
EndFunction
				
				
				
Event OnCellDetach
	SpawnPointLoaded = false
	Utility.Wait(10)
	if (SpawnPointLoaded = true) && (Player.IsInCombat == true)
		;I'll figure out how to loop this efficiently eventually
	elseif (SpawnPointLoaded == false) && Player.IsInCombat == false)  ;We can disable/delete or do stuff to the Actors in array if true)
		while GroupMemebers > -1      ;Not sure if this is what you do here
			SpawnList[GroupMembers].Remove()   ;Remove the highest index actor from the list
			GroupMembers = GroupMembers - 1	   ;And count down until the list is empty
		endwhile
		; Whats the best way to destroy the array here so it's not saved
	endif
EndEvent
Link to comment
Share on other sites

  • Replies 111
  • Created
  • Last Reply

Top Posters In This Topic

@smbNineTwo-er

Howdy!

there are some interesting ideas in this snippet, so, thanks for sharing!

 

I hope you posted this in the Creation Kit and Modders section also, as it tends to get read in a quicker turnaround time there too.

I'd also recommend cross-forum posting, to say, ThisWeekInTech, CodeStack, Github and moddb. (and, TheGameCreators too).

 

Shavkacagarikia, ChuckSteel and Steve40 are go-to mod-fu masters in just these such areas,

so I will await their pro guidances.

see, I would do a dual - hard override to a blank, and throw back to the default placement routine,

with an if no spawn counter increment per |time interval|, then throwback to default.

 

 

 

basically, we want to use as few Papyrus arrays, structSorts or EigenSorts as possible.

this is all related to that Optimization thread

https://forums.nexusmods.com/index.php?/topic/5522717-fallout-4-optimization-and-performance-systems-explained/

as presently written, there's no catchback to do that "else IFXOR function" you're wanting,

which reminds me more of an MCMC approach (and hence, sieve of eratosthenes).

to check on the time of the placement of the node.

that could be an overflow waiting to happen hehe.

 

that cleaning function of the hashingstring is almost a "perfect compression" problem,

with an " is A* in A" hyperdefinition problem too...

 

we need to bring some old-school 2D-3D approaches to the node placement for spawning,

moreso a 'table edge in' type deal; relative to a screenshot or other topology fetch command,

or relative to a fixed distance from the center of the cell...

to deal with the variable topology of each settlement. unless, we wanted to place the spawnpoint inside the settlement,

as for the Bounty Boards or Ambient Quest nodes.

 

It's like I was saying about War of the Wasteland v1;

enemies would spawn inside walls,

it was checking at peak prior to CTD, over 600 times across all cells hehe.

don't get me wrong though - it was an awesome ambitious project,

and I'm pumped to see where v2 is headed.

 

 

 

I'm looking forward to the answers here,

as they'll be directly applicable to the 'floatingpoint ambient quests" too

Link to comment
Share on other sites

Maybe you can simplify it a bit by using " DeleteWhenAble()" function. I have not used it myself yet, but according to the description it should mark the reference as temorary and delete it when the cell is detached. Spawn.DeleteWhenAble()

Link to comment
Share on other sites

@smbNineTwo-er

Howdy!

there are some interesting ideas in this snippet, so, thanks for sharing!

 

I hope you posted this in the Creation Kit and Modders section also, as it tends to get read in a quicker turnaround time there too.

I'd also recommend cross-forum posting, to say, ThisWeekInTech, CodeStack, Github and moddb. (and, TheGameCreators too).

 

Shavkacagarikia, ChuckSteel and Steve40 are go-to mod-fu masters in just these such areas,

so I will await their pro guidances.

see, I would do a dual - hard override to a blank, and throw back to the default placement routine,

with an if no spawn counter increment per |time interval|, then throwback to default.

 

 

 

basically, we want to use as few Papyrus arrays, structSorts or EigenSorts as possible.

this is all related to that Optimization thread

https://forums.nexusmods.com/index.php?/topic/5522717-fallout-4-optimization-and-performance-systems-explained/

as presently written, there's no catchback to do that "else IFXOR function" you're wanting,

which reminds me more of an MCMC approach (and hence, sieve of eratosthenes).

to check on the time of the placement of the node.

that could be an overflow waiting to happen hehe.

 

that cleaning function of the hashingstring is almost a "perfect compression" problem,

with an " is A* in A" hyperdefinition problem too...

 

we need to bring some old-school 2D-3D approaches to the node placement for spawning,

moreso a 'table edge in' type deal; relative to a screenshot or other topology fetch command,

or relative to a fixed distance from the center of the cell...

to deal with the variable topology of each settlement. unless, we wanted to place the spawnpoint inside the settlement,

as for the Bounty Boards or Ambient Quest nodes.

 

It's like I was saying about War of the Wasteland v1;

enemies would spawn inside walls,

it was checking at peak prior to CTD, over 600 times across all cells hehe.

don't get me wrong though - it was an awesome ambitious project,

and I'm pumped to see where v2 is headed.

 

 

 

I'm looking forward to the answers here,

as they'll be directly applicable to the 'floatingpoint ambient quests" too

I was looking at a way to dynamically get my spawn node but the functions involved aren't all that great in terms of performance (at least I get the impression). This script is actually attached to the node so I don't need to find it, nor does the node need to be persistent (an earlier error on my part lead me to believe they were permanently persistent but that's not the case)

 

The spawncounter has an absolute limit defined before the counter starts, so that's fine too. It's the count backwards on the array, removing and destroying it upon completion is what I'm unsure about at this point. Few articles I have seen have good examples on that, unless I'm just not understanding them well.

 

I got the impression the CK thread wasn't looekd at so much, so I just posted in here for the time being. I'm still at work too so one is all I can handle right now :D. Especially now the login system for all the employees for one of our companies just crashed, right in time for knock off D:

Link to comment
Share on other sites

Maybe you can simplify it a bit by using " DeleteWhenAble()" function. I have not used it myself yet, but according to the description it should mark the reference as temorary and delete it when the cell is detached. Spawn.DeleteWhenAble()

Suppose that would be the easier way if it works :D

 

Still wouldn't mind having the array around though, this is handy for the Vertibird tracking script that is currently implemented in WOTC by Engager. It sorta rolls the dice on a group and possibly has a Vertibird intercept them (I think vanilla is like this too in some RETrigger spawns)

Link to comment
Share on other sites

You`ll still need the array to spawn them and to run this function on each spawn. It just allows you to spawn and forget about them. Your script looks fine , but as everything in this game it requires testing :D . I`m not sure what was the question. Is something not working as expected?

Edited by kitcat81
Link to comment
Share on other sites

You`ll still need the arrayÃÂ to spawnÃÂ them and to run this function on each spawn. It just allows youÃÂ toÃÂ spawn and forgetÃÂ about them.ÃÂ ÃÂ Your script looks fine , butÃÂ ÃÂ as everything in this game it requires testing :D . I`m not sure what was the question. Is something not working as expected?ÃÂ

Just wanted to see if anyone with experience was around to maybe make some suggestions. I wrote the array part of the code today at work ;) (damn its hard life, IT, lol).

 

Gonna give it a test soon, just got home after the TimeTarget crisis made me work late.

 

Edit - from my experience, I wouldn't need the array if I mark the DeleteWhenAble before I reset spawn to None. Or maybe it doesn't work that way like SetLinkedRef does (they patrol even after I've dumped the NPC as a variable and got another).

Link to comment
Share on other sites

To destroy an array, you clear the array by calling clear() on it. Alternatively and depending on its type, you can assign 0, 0.0, "", none to each index. Int, Float, String, objectreference/actor/etc respectively.

http://www.creationkit.com/fallout4/index.php?title=Clear_-_Array

But arrays are one good way to keep track of created refs for later clean up.

I'm not very sure about using PlaceActorAtMe myself, so you may want to check if they are temp refs or made permanent by that function.

Edited by TheDungeonDweller
Link to comment
Share on other sites

You don`t need to keep anyone as a variable unless you are going to run some other functions on them later. And you need to run the function on each spawned actor ( because you can have more than 1 spawned actors, ). Just a question, why do you need a linked ref? Actors usually have a default package to stay near editor location. ( the location where they were spawned in this case)

  While SpawnCounter > 0
           If  ; your  conditions for spawning  here
              Actor  MyActor = Self.PlaceActorAtMe(your  data here, but the quantity  should be 1)  
              MyActor.DeleteWhenAble() ; mark the actor  as temporary so the game deletes him when the cell is detached
           EndIf
           SpawnCounter = SpawnCounter - 1 ; doing this outside the "if" block  allows to shorten the script
  EndWhile       
Edited by kitcat81
Link to comment
Share on other sites

To destroy an array, you clear the array by calling clear() on it. Alternatively and depending on its type, you can assign 0, 0.0, "", none to each index. Int, Float, String, objectreference/actor/etc respectively.

 

http://www.creationkit.com/fallout4/index.php?title=Clear_-_Array

 

But arrays are one good way to keep track of created refs for later clean up.

 

I'm not very sure about using PlaceActorAtMe myself, so you may want to check if they are temp refs or made permanent by that function.

Cool so my method of destroying (assigning none) to each member of the index will destroy it in the end, but I could make it faster by addressing them all. That's great news (I was a bit worried it would hang around and keep everything persistent)

 

Another thing I might find useful in this method of using an Array later, is tracking who killed who between groups, and devise some sort of "score" system for the "civil war/regional control" type of feature that users are asking for.

 

Regarding the PlaceActorAtme, according to this Talk on the Wiki they do not become persistent. The reason I want to use this function is 1. I plan Encounter Zone features, and 2. It seems more reliable at placing the spawn than PlaceAtMe (I am sure I read somewhere that you have to put your spawnpoint in the air because it is possible for actors to end up half in the ground, falling through the map, which might explain some CTDs I saw with it ages ago).

 

However worth noting, if I select one of my spawned NPCs in game, I get the "ff" formID, but with the [PP][T] flag on all of them. I assume this means Permanently Persistent, Temporary. I don't really know what the [EP] tag is some other things found in game means and this sorta doesn't make any sense to say Permanently and then Temporary, I just thought maybe thats how it flags it or something. Maybe it means something else entirely, never found a good explanation on Google.

 

Thanks for the post, clarification is a great thing some times.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...