SameOldBard Posted April 11 Author Share Posted April 11 6 hours ago, HeyYou said: Drop a marker first? Place it fairly high, then drop it to the ground. Spawn your npc at the marker. (I used to do this in morrowind, used a dead rat as the marker. :D) What if the marker is not dead when dropped and I register to it's OnDeath event before moving it to a high position? I'm guessing the position it will have by the time I get the event will be precise enough hehe. So, the solution is a bit dead rat hehehe Link to comment Share on other sites More sharing options...
HeyYou Posted April 12 Share Posted April 12 That *should* work..... unless the rat doesn't die on impact. (short fall height.) Link to comment Share on other sites More sharing options...
SameOldBard Posted April 20 Author Share Posted April 20 (edited) On 4/12/2024 at 11:21 PM, HeyYou said: That *should* work..... unless the rat doesn't die on impact. (short fall height.) In the end, it did work. But even with a high fall height it still had a success rate of 76%. I tried it a 1000 times to get a proper valid percentage. I am not interely sure why that is so. I was at 1 side of the Outpost and had them being dropped at random places around the Outpost, basically at the border area. I also set their HP to 1 before dropping. Maybe those that did not die where at an area that maybe was not fully loaded or something? Does anyone know?  Anyway, with a couple of retries I could have a 100% success rate, so, it worked for my mod needs. I should have replied before, but I've been playtesting it while working on my other mod which I'm planning to release together with the one using this system.  Here's a snippet with how I have it set up here. Maybe someone can spot why I have the 24% failure to die rate (Sorry, I don't follow Bethesda's scripting coding pattern):  ScriptName SomeScript ; Using the player as the spawner Actor Property PlayerRef Auto Const mandatory ; A minibot, specifically: 0x000C1F4F Form Property MarkerRef Auto Const mandatory ; Field set by the OnDeath event Form _deadMarker ; Amount of time we want to wait for the Marker to die int _timesToTryAgain = 15 Actor function SpawnActor() ; I am not stashing the Beacon as the player may want to remove it while this script is running. So we can have a way to fail if that happens ObjectReference workshop = GetWorkshop() if(workshop == NONE) Trace("SpawnActor: Could not get a Workshop") return endIf float buildRadius = workshop.GetValue(OutpostBuildAreaRadius) ; We ask for a Marker to be placed at the same Height as the Outpost Radius, should be 150 by default Actor marker = GetSpawnMarker(buildRadius) ; Waits for a few seconds to allow it to bounce Utility.Wait(10) ; Creates an actor at the Marker position disabled so we don't see it beside the player Actor actorSpawned = PlayerRef.PlaceActorAtMe(actorToSpawn as ActorBase, 4, None, true, true, false, NONE, false) ; Moves to the Marker position and enables it actorSpawned.SetPosition(marker.GetPositionX(), marker.GetPositionY(), marker.GetPositionZ()) actorSpawned.Enable(true) ; Get's rid of the Marker marker.DisableNoWait(false) marker.Delete() return actorSpawned endFunction Actor function GetSpawnMarker(float height) int timesAwaited = 0 int retries = 0 ; Tries to get a marker right away Actor spawnMarker = GetDeadDrop(height) ; Repeats until we have a marker dying while(_deadMarker != spawnMarker) ; Checking every second Utility.Wait(1) timesAwaited += 1 ; If we waited for more than the maximum amount of time (15 seconds) if(timesAwaited >= _timesToTryAgain) timesAwaited = 0 ; Clear the data of the marker that failed to die and delete it ClearRegisteredEvents(spawnMarker) spawnMarker.DisableNoWait(false) spawnMarker.Delete() ; Drop a new marker and retry spawnMarker = GetDeadDrop(height) retries += 1 endIf endWhile ; We got a marker, let's clean up and return the object _deadMarker = NONE ClearRegisteredEvents(spawnMarker) return spawnMarker endFunction Actor function GetDeadDrop(float height) ObjectReference workshop = GetWorkshop() if(workshop == NONE) Trace("SpawnActor: Could not get a Workshop") return endIf float xPos = workshop.GetPositionX() float yPos = workshop.GetPositionY() float zPos = workshop.GetPositionZ() float buildRadius = workshop.GetValue(OutpostBuildAreaRadius) ; Let's get a random point in the circle of the outpost border float angle = Utility.RandomFloat(0.0, 359.999) float newX = xPos + (buildRadius * Math.cos(angle)) float newY = yPos + (buildRadius * Math.sin(angle)) float newZ = zPos + height ; Create the marker, wait for it to load and set it's alpha to 0. Not exactly transparent but good enough Actor spawnMarker = PlayerRef.PlaceActorAtMe(MarkerRef as ActorBase, 0, workshop.GetCurrentLocation(), true, false, false, NONE, false) spawnMarker.WaitFor3DLoad() spawnMarker.SetAlpha(0, False) if(!spawnMarker.Is3DLoaded()) Trace("3D is not loaded!") endIf ; Get ready for it's death RegisterForRemoteEvent(spawnMarker, "OnDeath") ; Set's health to 1 and drop it from the wanted position! spawnMarker.SetValue(Game.GetHealthAV(), 1) spawnMarker.SetPosition(newX, newY, newZ) ; Waiting again, in case there is some loading to be done at the other side of the map. spawnMarker.WaitFor3DLoad() return spawnMarker endFunction function ClearRegisteredEvents(Actor actorRef) ; Clean up! UnregisterForRemoteEvent(actorRef, "OnDeath") endFunction event Actor.OnDeath(Actor deadActor, Actor akKiller) UnregisterForRemoteEvent(deadActor, "OnDeath") ObjectReference workshop = GetWorkshop() if(workshop == NONE) Trace("OnDeath: Could not get a Workshop") return endIf if(deadActor.HasKeyword(MarkerKeyword)) ; Yay! We got a dead one! _deadMarker = deadActor return endIf endEvent  Cheers, OldBard Edited April 20 by SameOldBard Link to comment Share on other sites More sharing options...
SameOldBard Posted April 30 Author Share Posted April 30 (edited) I just found something quite odd happening when using a similar solution in another mod I am working on. I tried dropping the bots and although I was dropping 16 of them at once, only 1 of them was dying. The others were not. For some reason. Some further investigation (tracing + searching for them) showed me that they were actually being spawned right at a safe place in the ground at the right position I wanted them to. Some more tests and I had was something like this: float xPos = _workshop.GetPositionX() float yPos = _workshop.GetPositionY() float zPos = _workshop.GetPositionZ() float buildRadius = _workshop.GetValue(OutpostBuildAreaRadius) float newX = xPos + (buildRadius * Math.cos(angle)) float newY = yPos + (buildRadius * Math.sin(angle)) float newZ = zPos + buildRadius * 2 Actor spawnMarker = _workshop.PlaceActorAtMe(MarkerRef as ActorBase, 0, NONE, true, true, false, NONE, false) spawnMarker.SetValue(Game.GetHealthAV(), 1) spawnMarker.SetPosition(newX, newY, newZ) Trace("Placing Marker at: " + spawnMarker.GetPositionX() + ", " + spawnMarker.GetPositionY() + ", " + spawnMarker.GetPositionZ() + ". Initial Z: " + zPos + ", new Z: " + newZ) spawnMarker.Enable(false) spawnMarker.WaitFor3DLoad() Trace("Placing Marker at: " + spawnMarker.GetPositionX() + ", " + spawnMarker.GetPositionY() + ", " + spawnMarker.GetPositionZ() + ". Initial Z: " + zPos + ", new Z: " + newZ) With the output being... Before enabling: Placing Marker at: 504.698944, -284.563171, 305.337381. Initial Z: 5.337381, new Z: 305.337372 After enabling: Placing Marker at: 504.698944, -284.563171, 2.863391. Initial Z: 5.337381, new Z: 305.337372 I ran it again and again and it seems consistent. It is as if when the actors are enabled they are auto moved to the ground safely. Does anyone know if that is reliable? Has anyone had similar results? OldBard. Edited April 30 by SameOldBard Link to comment Share on other sites More sharing options...
aurreth Posted April 30 Share Posted April 30 1 hour ago, SameOldBard said: It is as if when the actors are enabled they are auto moved to the ground safely. Does anyone know if that is reliable? Has anyone had similar results? Sometimes fast travel glitches and you zone into a planet before creatures spawn. When that happens you see them placed in the air, fairly high up, and then drop to the ground. So apparently yes, things get spawned above the possible terrain height and then auto moved down. Link to comment Share on other sites More sharing options...
SameOldBard Posted May 2 Author Share Posted May 2 Indeed I saw that happening every now and them. My concern though is about reliability as I need those for setting up solo level positions. I guess I can check the Z after enabling. If it is about the same as the high one I set before enabling then I would know that it was not automatically placed at ground level. Link to comment Share on other sites More sharing options...
Recommended Posts