LCountach Posted May 5 Share Posted May 5 (edited) EDIT: Updated 5/22/24 with bug fixed scripts. You can read about how I got there in the posts further down. I have been working hard on getting a randomized population cycle working on my map mod Underworld City. My other thread here: Link I think I may have have finally cracked it. With great pain I made two scripts. One that fires from the Actor OnDeath and spawns in a randomized (Level Listed) actor and. The other on a door that deletes the one who touched it. I am still very new to scripting and worry I may break something. If you wonderful scripters out there could check my work. It would be much appreciated. Door Script: Event OnActivate(ObjectReference akActionRef) (akActionRef as Actor).Kill() (akActionRef as Actor).Delete() Debug.MessageBox("Kill Triggered") EndEvent NPC Script: Actorbase Property MyActor Auto ObjectReference Property MyObject Auto Event OnDeath(Actor akKiller) Debug.MessageBox("NPC Died") Utility.wait(10) MyObject.PlaceActorAtMe(MyActor) self.delete() EndEvent These two scripts do seem to function HOWEVER I am uncertain if the Actor that gets deleted is truly gone. Other example scripts I referenced used "Disable, Delete, and DeleteWhenAble" in three lines of code. Was that overkill? Are my scripts safe in terms of memory filling up or save files being filled with garbage? It was mentioned in the other thread. That NPCs may pick up dropped items and the items get deleted when the NPCs do. I am not too worried about that at the moment. As stated above. If you wonderful scripters out there could check my work. It would be much appreciated. Edited May 22 by LCountach Link to comment Share on other sites More sharing options...
LCountach Posted May 19 Author Share Posted May 19 (edited) Progress update. I have run into a serious problem/bug!?!?! Those two scripts seem to function just fine while I am in the exterior cell part of the city. HOWEVER, when I spend any lengthy time in an interior cell. The AI continue to walk their rout and activate the door script that only half functions if the player is not in the cell with it when triggered. The "Self.PlaceActorAtMe(MyActor)" part works BUT "(akActionRef as Actor).Delete()" does not. This results in NPCs being created but NOT deleted. Creating an exponential run away effect of NPCs flooding the city. The effect is made even worse when the player uses the wait function to pass time quickly. The script can fire off many times while the player is waiting. I tried going another rout with a script I finally got functioning that spawns in NPCs every hour. But the same pitfalls plague that approach too. It's actually where I first noticed the cascading run away effect. Any help getting these scripts to work would be much appreciated. Or is there a better approach to making a continually refreshing NPC population? The guards in the Skyrim cities must have a refresh/respawn system right? Or are they too on the basic 10/30 day Skyrim reset cycle. I have never actually in my 1000+ hours in Skyrim wiped out a city. I always play a good guy. If the guards do have a faster refresh cycle. Is there a guide out there on setting one of those systems up? I was sooo close to releasing my next update to Underworld City when I noticed this game breaking issue. Sooo disappointing. Test script to Spawn On UpdateGameTime. I modified it then attached it to a quest with "Run Once and Start Game Enabled checked" as guided by the Tutorial. Import Game Actorbase Property MyNPC03 Auto Actorbase Property MyNPC04 Auto Actorbase Property MyNPC05 Auto ObjectReference Property MyObject03 Auto ObjectReference Property MyObject04 Auto ObjectReference Property MyObject05 Auto Event OnInit() RegisterForSingleUpdateGameTime(0.5) EndEvent Event OnUpdateGameTime() MyObject03.PlaceActorAtMe(MyNPC03) MyObject04.PlaceActorAtMe(MyNPC04) MyObject05.PlaceActorAtMe(MyNPC05) RegisterForSingleUpdateGameTime(0.5) Debug.MessageBox("Pop Cycle Triggered") EndEvent Not sure if "Import Game" was needed. It was in the example script I sourced. Edited May 19 by LCountach Link to comment Share on other sites More sharing options...
xkkmEl Posted May 20 Share Posted May 20 In the code sample provided, "import game" is not required. If you remove it, and the compiler complains, you just need to insert "Game." before some function calls. Your "Self.PlaceActorAtMe(MyActor)" does not need the "Self." part. It is implicitly assumed if you remove it. From what you posted, I note that the door's OnActivate contains the possibility of increasing the population, since the delete is conditional but the placeAtMe is not. Similarly, your OnUpdateGameTime add three new actors every 30mn game time. That's two actors per minute on the default time scale. You have not discussed how this gets balanced. I could suggest that the door does not need to add new actors, if you are using OnUpdateGameTime to do it. This will give you an easy way to control the population. Link to comment Share on other sites More sharing options...
LCountach Posted May 20 Author Share Posted May 20 (edited) Thank you very much for responding!!! I am very new to scripting so please bear with me. "In the code sample provided, "import game" is not required." You were correct. It compiled without error. "From what you posted, I note that the door's OnActivate contains the possibility of increasing the population, since the delete is conditional but the placeAtMe is not." The conditional part of the script was there because the example I followed had it. I did not know if it would work without it. I does indeed function without the condition. It however still does not seem to function without me being in the cell with the door. If I move to another cell. The delete part seems to stop working yet it still spawns NPCs. Will do more testing tomorrow. "Similarly, your OnUpdateGameTime add three new actors every 30mn game time. That's two actors per minute on the default time scale. You have not discussed how this gets balanced." The fast spawn rate was for testing. I normally would have it at one or two Skyrim hours. The fast rate unfortunately just showed another error. The NPC's AI does not activate until I enter the city at least once. I found that when I loaded a save from before I was in the city and took a while to get there. There was a pile of dormant NPCs that activated upon my arrival. I have no idea how to address this new issue. "I could suggest that the door does not need to add new actors, if you are using OnUpdateGameTime to do it. This will give you an easy way to control the population." You are correct. Sorry I wasn't clear enough. The Door Spawning and Time Based Spawning were two alternative methods I have tried to get a functioning population cycle. They were not running together at the same time. The Door Spawning works if I am in the cell. But does not delete any NPCs spawned when I am not there. The Time Based Spawning also seemed to work at first. Unfortunately, it too doesn't delete the NPCs if I am not in the cell. I now also found the second bug I mentioned above where it slowly spawns a pile of dormant NPCs if I haven't entered the city before. Sigh... Honestly this is quite frustrating. There are hundreds of games that have random generated populations in cities. I wish there was a tried and true method for Skyrim. I feel it is the single most important feature for my city to feel alive. If you or anyone knows of a better/functional way. Please let me know. Edited May 20 by LCountach Link to comment Share on other sites More sharing options...
xkkmEl Posted May 20 Share Posted May 20 (edited) Working with the Skyrim engine is frustrating, in large part because the documentation is insufficient. It is possible that your door.OnActivate does not fire, or fires with a None akActionRef, when it happens in a detached cell. In my testing, I found that the game engine is so enthusiastic about freeing memory when things get out of sight of the player, that some events (OnEffectFinish in my case) could not be received or processed reliably. The same thing could be happening with your OnActivate. If you set it up so that the spawned NPCs will continue to activate the door until they succeed at being deleted, I would suggest this: Event OnActivate(ObjectReference akActionRef) If akActionRef && akActionRef.getParentCell() && akActionRef.getParentCell().isAttached() akActionRef.Delete() PlaceActorAtMe(MyActor) EndIf EndEvent Edited May 20 by xkkmEl Link to comment Share on other sites More sharing options...
LCountach Posted May 20 Author Share Posted May 20 (edited) 6 hours ago, xkkmEl said: If you set it up so that the spawned NPCs will continue to activate the door until they succeed at being deleted, I would suggest this: Event OnActivate(ObjectReference akActionRef) If akActionRef && akActionRef.getParentCell() && akActionRef.getParentCell().isAttached() akActionRef.Delete() PlaceActorAtMe(MyActor) EndIf EndEvent Apologies. I can not fully read and understand your suggested script. It seems to be checking if that the actor that touched the door is in the same cell with the door? If Yes, perform those commands. If not, do nothing? I also am not aware of how to make a NPC stand at the door and try it over and over. OR are you suggesting that I simply attach your suggested script to the door. Then when the player is away in another cell and the NPC reaches the door. If it can not verify those conditions it will just end the event. Go around for another loop on it's patrol rout. Check again. Until at some point where the player is in the cell and the script can verify the conditions? I hope I have understood this correctly and that the solution is that simple. I will be trying this later today hopefully. Thankyou! Edited May 20 by LCountach Link to comment Share on other sites More sharing options...
LCountach Posted May 21 Author Share Posted May 21 (edited) Progress Update: I am sad to report xkkmEl that your suggested script only partially worked. It worked fine like my other attempts when I stayed near the exterior cell door. It would even sometimes work when I left and went inside an interior cell. However, after one or two passes through the door. The NPC would stop moving and just stand on the other side of the door. Never to return again. I eventually got frustrated and teleported with "coc" into the special spawn cell I created specifically for the NPCs to spawn in and have doors to use. Sure enough the NPCs were just standing there. After a second or two. When the game registered my presence there. They woke up and started on their rout again. Unfortunately, asking the player to periodically enter the spawn room to wake up the city. Just isn't acceptable. Thanks very much for the suggestion though!!! However... GOOD NEWS!!! I was able to come up with two scripts that do seem to work. My brain would not let me sleep last night and just kept churning on the problem and eventually came up with something. The two scripts both fire and debug report while I am inside and outside. New NPCs do seem to be spawning and randomizing. The old also seem to be deleting. I let several dozen cycles go. Checked the three test zones. No big pile of bodies. I do fear they may pile up on the other side of the door. I did teleport into the spawn room to see if I could catch the game deleting them as I spawned in. The room is very simple and teleport is almost instantaneous and I didn't see anything. I wish I had the know how to check the Save Game files to see if garbage is showing up in there. But fingers crossed. It seems to working properly. Door Script: Event OnActivate(ObjectReference akActionRef) (akActionRef as Actor).Kill() (akActionRef as Actor).Delete() Debug.MessageBox("Kill Triggered") EndEvent NPC Script: Actorbase Property MyActor Auto ObjectReference Property MyObject Auto Event OnDeath(Actor akKiller) Debug.MessageBox("NPC Died") Utility.wait(10) MyObject.PlaceActorAtMe(MyActor) self.delete() EndEvent I suspected the door was the culprit not working while the player was in a different cell than the door. So I shifted the bulk of the work to the NPC. Also I included the Kill command and there are Delete commands on both. I dont know if what I did was good practice. But It Worked!!! Hopefully I don't run into anymore unforeseen issues. Thanks again for the help xkkmEl Edited May 21 by LCountach Link to comment Share on other sites More sharing options...
Recommended Posts