cypher2012 Posted August 22, 2017 Share Posted August 22, 2017 Hey guys, any idea why my array length is still 0 after using array Add() function? Actor Property spawned_actor Auto Actor[] Property enemy_actor_pool Auto spawned_actor = spawn_points[random_spawn].PlaceActorAtMe(LvlFeralGhoul,1) enemy_actor_pool.Add(spawned_actor) Function ResetActorPool() Debug.MessageBox("Array len: " + enemy_actor_pool.length) ;Displays zero Int iElement = enemy_actor_pool.Length While iElement Debug.MessageBox("iElement found") ;Doesn't display. So nothing looping iElement -= 1 enemy_actor_pool[iElement].SetCriticalStage(enemy_actor_pool[iElement].CritStage_DisintegrateEnd) enemy_actor_pool.Remove(iElement) EndWhile EndFunction Link to comment Share on other sites More sharing options...
JonathanOstrus Posted August 22, 2017 Share Posted August 22, 2017 Did you ever initialize the array? Link to comment Share on other sites More sharing options...
cypher2012 Posted August 22, 2017 Author Share Posted August 22, 2017 Did you ever initialize the array?Does it not just make an empty array when I declare it? Link to comment Share on other sites More sharing options...
scrivener07 Posted August 22, 2017 Share Posted August 22, 2017 Something seemed weird about your loop so I just went about it how I would. I faked the parts of the script I dont have with some guess work. Scriptname Example extends Quest Actor[] Pool int random_spawn = 0 ; whatever random thing ActorBase Property LvlFeralGhoul Auto Const Mandatory ObjectReference[] Property spawn_points Auto Const Mandatory Event OnInit() Pool = new Actor[0] ; Array.Add will auto-expand size EndEvent Event OnQuestInit() SpawnGhoul() SpawnGhoul() SpawnGhoul() SpawnGhoul() SpawnGhoul() EndEvent Event OnQuestShutdown() ResetActors(Pool) EndEvent Function SpawnGhoul() Actor Spawned = spawn_points[random_spawn].PlaceActorAtMe(LvlFeralGhoul, 1) Pool.Add(Spawned) EndFunction Function ResetActors(Actor[] actors) Global If (actors) int size = actors.Length int index = 0 Debug.MessageBox("Size:"+size+"\n\nDo not change the size of your array while perform iterations.") While (index < size) Actor element = actors[index] If (element) Debug.MessageBox("Found\n"+element+"\nSetting critical stage to disintegrate end.") element.SetCriticalStage(element.CritStage_DisintegrateEnd) Else Debug.MessageBox("The element at index "+index+" was none, skipping..") EndIf index += 1 ; move to the next index EndWhile actors.Clear() Debug.MessageBox("Iteration Complete\nClearing the actor pool.\nSize:"+actors.Length) Else Debug.MessageBox("The actor pool is empty or none, skipping reset.") EndIf EndFunction Link to comment Share on other sites More sharing options...
JonathanOstrus Posted August 22, 2017 Share Posted August 22, 2017 (edited) Did you ever initialize the array?Does it not just make an empty array when I declare it? When you declare it as you did it's set to a None value. So the entire array = None. You need to initialize it to a zero entity array like Scrivner exampled with Actor[] Pool ; Pool currently = None. You cannot initialize it here. It must be done in a function or event. Event OnInit() Pool = new Actor[0] ; Array.Add will auto-expand size EndEvent I suspect if you had papyrus logging turned on and check you'll see some message like, cannot add to a none array, or something like that. Edited August 22, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
cypher2012 Posted August 23, 2017 Author Share Posted August 23, 2017 Hey guys, thanks for the replies! Unfortunately, i tried initializing the array and it still isn't working. I used the OnInit event to add the following code: Event OnInit() enemy_actor_pool = new Actor[0] EndEvent Here is the script in it's full: Scriptname CMA:CMA_ArenaManagerScript extends ObjectReference {Main script for controlling the waves of enemy.} Float Property cool_down_time = 10.0 Auto const {How long the cool down period is inbetween each round.} ActorBase Property LvlFeralGhoul Auto Const {Standard actor used that will be spawned.} ActorBase Property LvlGlowLegGhoul Auto Const {Hard actor that will be used in hard rounds.} Float Property spawn_interval_time = 2.0 Auto const {Delay between each actual spawn.} Sound Property snd_new_round Auto Const {Sound to be played at the start of a new round.} Sound Property snd_round_end Auto Const {Sound to be played at the end of a round.} Sound Property snd_hard_round_wrn Auto Const {Sound to be played at the start of a hard round.} Message Property new_round_notification Auto Const {Message displayed when a new round begins. Shows the actual round number} Int Property kill_complete_caps Auto Const {Number of caps to reward the player for killing an enemy.} Int Property round_complete_caps Auto Const {Number of caps rewarded to player for completing a round.} ;End of const properties Int Property round_counter = 1 Auto {Counter to keep track of what round it is.} Int Property hard_round_counter = 0 Auto {Counter to see when the next hard round will be.} Int Property hard_rounds_completed = 1 Auto {Used to multiply the number of hard enemies for every hard round} Int Property enemies_remaining = 0 Auto {Keeps track of how many enemies remain to be killed.} Bool Property game_started Auto {Used to check if the game has already been setup and started.} ObjectReference[] Property spawn_points Auto {Where the enemies will spawn} Bool Property finished_spawning Auto {Used to check if there are still enemies spawning. Used to stop premature end of round} Bool Property in_cool_down = true Auto {Used to check if the game is currently in it's cool down state} Actor Property spawned_actor Auto Actor[] Property enemy_actor_pool Auto {Used to keep track of enemies spawned in the last round so they can be deleted at the end of cool down.} Event OnInit() enemy_actor_pool = new Actor[0] EndEvent Event OnLoad() Self.Reset() GetParentCell().Reset() Reset() ResetGame() EndEvent Event OnActivate(ObjectReference akActionRef) StartGame() EndEvent Event Actor.OnDeath(Actor akSender, Actor akKiller) if(akSender != Game.GetPlayer()) enemies_remaining -= 1 Game.GivePlayerCaps(kill_complete_caps) if(CheckEndOfRound()) int instanceID = snd_round_end.play(Game.GetPlayer()) Sound.SetInstanceVolume(instanceID,1.0) StartCoolDown() endIf UnregisterForRemoteEvent(akSender, "OnDeath") endif EndEvent Function StartGame() if(!game_started) Debug.MessageBox("Game starting. Get ready!") RegisterForRemoteEvent(Game.GetPlayer(), "OnDeath") StartRound(1) in_cool_down = false game_started = true else Debug.MessageBox("Game has already started!") endIf EndFunction Function StartRound(Int num_round) new_round_notification.Show(round_counter) int instanceID = snd_new_round.play(Game.GetPlayer()) Sound.SetInstanceVolume(instanceID,1.0) finished_spawning = false Int counter = 0 Int random_spawn Int num_enemies_to_spawn = num_round + 5 while(counter < num_enemies_to_spawn) random_spawn = Utility.RandomInt(0, spawn_points.Length - 1) spawned_actor = spawn_points[random_spawn].PlaceActorAtMe(LvlFeralGhoul,1) enemy_actor_pool.Add(spawned_actor) RegisterForRemoteEvent(spawned_actor, "OnDeath") enemies_remaining += 1 counter += 1 Utility.Wait(spawn_interval_time) endWhile hard_round_counter += 1 if(hard_round_counter == 5) int snd_inst = snd_hard_round_wrn.play(Game.GetPlayer()) Sound.SetInstanceVolume(snd_inst, 4.0) Int hard_counter = 0 while(hard_counter < hard_rounds_completed) random_spawn = Utility.RandomInt(0, spawn_points.Length - 1) spawned_actor = spawn_points[random_spawn].PlaceActorAtMe(LvlGlowLegGhoul, 1) enemy_actor_pool.Add(spawned_actor) RegisterForRemoteEvent(spawned_actor, "OnDeath") enemies_remaining += 1 hard_counter += 1 endWhile hard_round_counter = 0 hard_rounds_completed += 1 endif finished_spawning = true EndFunction Function StartCoolDown() in_cool_down = true StartTimer(cool_down_time, 10) EndFunction Function EndOfCooldown() in_cool_down = false ResetActorPool() round_counter += 1 StartRound(round_counter) EndFunction Event OnTimer(int iTimerID) if( iTimerID == 10) EndOfCooldown() endIf EndEvent Bool Function CheckEndOfRound() if(enemies_remaining <= 0 && finished_spawning) Game.GivePlayerCaps(round_complete_caps) return true else return false endIf EndFunction Function ResetGame() CancelTimer(10) round_counter = 1 hard_round_counter = 0 hard_rounds_completed = 1 enemies_remaining = 0 game_started = false finished_spawning = true in_cool_down = true EndFunction Function ResetActorPool() Debug.MessageBox("Array len: " + enemy_actor_pool.Length) Int iElement = enemy_actor_pool.Length While iElement Debug.MessageBox("iElement found") iElement -= 1 enemy_actor_pool[iElement].SetCriticalStage(enemy_actor_pool[iElement].CritStage_DisintegrateEnd) enemy_actor_pool.Remove(iElement) EndWhile EndFunction Link to comment Share on other sites More sharing options...
JonathanOstrus Posted August 23, 2017 Share Posted August 23, 2017 (edited) Hey guys, thanks for the replies! Unfortunately, i tried initializing the array and it still isn't working.ÃÂ ÃÂ I used the OnInit event to add the following code: Event OnInit() enemy_actor_pool = new Actor[0] EndEvent Here is the script in it's full:ÃÂ ÃÂ Scriptname CMA:CMA_ArenaManagerScript extends ObjectReference {Main script for controlling the waves of enemy.} Float Property cool_down_time = 10.0 Auto const {How long the cool down period is inbetween each round.} ActorBase Property LvlFeralGhoul Auto Const {Standard actor used that will be spawned.} ActorBase Property LvlGlowLegGhoul Auto Const {Hard actor that will be used in hard rounds.} Float Property spawn_interval_time = 2.0 Auto const {Delay between each actual spawn.} Sound Property snd_new_round Auto Const {Sound to be played at the start of a new round.} Sound Property snd_round_end Auto Const {Sound to be played at the end of a round.} Sound Property snd_hard_round_wrn Auto Const {Sound to be played at the start of a hard round.} Message Property new_round_notification Auto Const {Message displayed when a new round begins. Shows the actual round number} Int Property kill_complete_caps Auto Const {Number of caps to reward the player for killing an enemy.} Int Property round_complete_caps Auto Const {Number of caps rewarded to player for completing a round.} ;End of const properties Int Property round_counter = 1 Auto {Counter to keep track of what round it is.} Int Property hard_round_counter = 0 Auto {Counter to see when the next hard round will be.} Int Property hard_rounds_completed = 1 Auto {Used to multiply the number of hard enemies for every hard round} Int Property enemies_remaining = 0 Auto {Keeps track of how many enemies remain to be killed.} Bool Property game_started Auto {Used to check if the game has already been setup and started.} ObjectReference[] Property spawn_points Auto {Where the enemies will spawn} Bool Property finished_spawning Auto {Used to check if there are still enemies spawning. Used to stop premature end of round} Bool Property in_cool_down = true Auto {Used to check if the game is currently in it's cool down state} Actor Property spawned_actor Auto Actor[] Property enemy_actor_pool Auto {Used to keep track of enemies spawned in the last round so they can be deleted at the end of cool down.} Event OnInit() enemy_actor_pool = new Actor[0] EndEvent Event OnLoad() Self.Reset() GetParentCell().Reset() Reset() ResetGame() EndEvent Event OnActivate(ObjectReference akActionRef) StartGame() EndEvent Event Actor.OnDeath(Actor akSender, Actor akKiller) if(akSender != Game.GetPlayer()) enemies_remaining -= 1 Game.GivePlayerCaps(kill_complete_caps) if(CheckEndOfRound()) int instanceID = snd_round_end.play(Game.GetPlayer()) Sound.SetInstanceVolume(instanceID,1.0) StartCoolDown() endIf UnregisterForRemoteEvent(akSender, "OnDeath") endif EndEvent Function StartGame() if(!game_started) Debug.MessageBox("Game starting. Get ready!") RegisterForRemoteEvent(Game.GetPlayer(), "OnDeath") StartRound(1) in_cool_down = false game_started = true else Debug.MessageBox("Game has already started!") endIf EndFunction Function StartRound(Int num_round) new_round_notification.Show(round_counter) int instanceID = snd_new_round.play(Game.GetPlayer()) Sound.SetInstanceVolume(instanceID,1.0) finished_spawning = false Int counter = 0 Int random_spawn Int num_enemies_to_spawn = num_round + 5 while(counter < num_enemies_to_spawn) random_spawn = Utility.RandomInt(0, spawn_points.Length - 1) spawned_actor = spawn_points[random_spawn].PlaceActorAtMe(LvlFeralGhoul,1) enemy_actor_pool.Add(spawned_actor) RegisterForRemoteEvent(spawned_actor, "OnDeath") enemies_remaining += 1 counter += 1 Utility.Wait(spawn_interval_time) endWhile hard_round_counter += 1 if(hard_round_counter == 5) int snd_inst = snd_hard_round_wrn.play(Game.GetPlayer()) Sound.SetInstanceVolume(snd_inst, 4.0) Int hard_counter = 0 while(hard_counter < hard_rounds_completed) random_spawn = Utility.RandomInt(0, spawn_points.Length - 1) spawned_actor = spawn_points[random_spawn].PlaceActorAtMe(LvlGlowLegGhoul, 1) enemy_actor_pool.Add(spawned_actor) RegisterForRemoteEvent(spawned_actor, "OnDeath") enemies_remaining += 1 hard_counter += 1 endWhile hard_round_counter = 0 hard_rounds_completed += 1 endif finished_spawning = true EndFunction Function StartCoolDown() in_cool_down = true StartTimer(cool_down_time, 10) EndFunction Function EndOfCooldown() in_cool_down = false ResetActorPool() round_counter += 1 StartRound(round_counter) EndFunction Event OnTimer(int iTimerID) if( iTimerID == 10) EndOfCooldown() endIf EndEvent Bool Function CheckEndOfRound() if(enemies_remaining <= 0 && finished_spawning) Game.GivePlayerCaps(round_complete_caps) return true else return false endIf EndFunction Function ResetGame() CancelTimer(10) round_counter = 1 hard_round_counter = 0 hard_rounds_completed = 1 enemies_remaining = 0 game_started = false finished_spawning = true in_cool_down = true EndFunction Function ResetActorPool() Debug.MessageBox("Array len: " + enemy_actor_pool.Length) Int iElement = enemy_actor_pool.Length While iElement Debug.MessageBox("iElement found") iElement -= 1 enemy_actor_pool[iElement].SetCriticalStage(enemy_actor_pool[iElement].CritStage_DisintegrateEnd) enemy_actor_pool.Remove(iElement) EndWhile EndFunction That should work unless the object was already created. I would move the initializer to the start game function personally if it would be applicable there. It would mean you start with a fresh array each time your object is activated. I'm not sure if you want that behavior or not. You could try that and see how it goes. Edited August 24, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
cypher2012 Posted August 23, 2017 Author Share Posted August 23, 2017 Woohoo, finally it's working. Moved to the StartGame function as suggested. Went back to a different cell and completely reloaded the cell. Now it's working. Thank you! :) Link to comment Share on other sites More sharing options...
scrivener07 Posted August 23, 2017 Share Posted August 23, 2017 Yay! Happy endings are nice. Link to comment Share on other sites More sharing options...
JonathanOstrus Posted August 24, 2017 Share Posted August 24, 2017 (edited) Glad to hear it's working. Now that I'm home it's easier to type. The issue you probably were running in to is that the OnInit wasn't firing because you were loading a save that already had a spawned object containing the script. It would be worth reading the wiki page for OnInit https://www.creationkit.com/fallout4/index.php?title=OnInit_-_ScriptObject specifically the circumstances of when it is called. I just realized I have a few scripts on a mod to go update now. Something else to be aware of. If the player was to leave the cell which causes the 3D to unload for the actors, your resetactors function may fail. Also the OnLoad having the 3 resets is redundant. The cell reset alone should do it. Unless the cell is in an encounter zone that is marked as no reset. Then the script will fail and halt. Calling self.Reset() and just Reset() is the same thing. Not including Self makes it implied vs explicit. Another thing that's more of a nit picky thing. There's really no point in registering for Player OnDeath and then checking for != Player in the event. If the player triggers it, the game will force a reload before anything else would fire up anyway and the whole crap resets to the save. So it's pretty pointless. Edited August 24, 2017 by BigAndFlabby Link to comment Share on other sites More sharing options...
Recommended Posts