Get specific reference from a leveled list?

Post » Thu Jun 21, 2012 11:35 pm

So I have a simple magic effect I am testing where I basically cast a spell at a creature, and send their Actor value to a function in a quest script that gets their LeveledActorBase and uses that to spawn a duplicate at the player.

Here is how that looks:

Scriptname phitamecastS extends ActiveMagicEffectphitametrackerS Property phitametracker autoEvent OnEffectStart(Actor akTarget, Actor akCaster)	phitametracker.SetQuestValue(akTarget)EndEvent

Scriptname phitametrackerS extends QuestphitametrackerS Property phitametracker AutoFunction SetQuestValue(Actor akTarget)	Game.GetPlayer().PlaceAtMe(akTarget.GetLeveledActorBase())EndFunction

This works (after much helpful info on http://www.gamesas.com/topic/1378518-setting-a-quest-actor-reference-property-from-a-magic-effect-script/), however I am still having a problem.

The function does indeed spawn a duplicate, but not of the SPECIFIC creature type I cast it on, at least not always. What I get instead is a spawn from that LIST, so when cast on say a wolf, sometimes I will also get skeevers and lions, etc.

My whole purpose of using GetLeveledActorBase was to hopefully get the specific editor reference of the CURRENT spawned creature I actually cast the spell on.

So, is there a way to do that? Can I cast my spell on a random creature and get the specific reference of THAT type, to use with PlaceAtMe so my duplicate is ALWAYS the same type no matter what else is in the list?
User avatar
Mike Plumley
 
Posts: 3392
Joined: Wed Sep 05, 2007 10:45 pm

Post » Thu Jun 21, 2012 8:52 am

This did seem like a tricky one. I haven't been able to find a way yet.
User avatar
Khamaji Taylor
 
Posts: 3437
Joined: Sun Jul 29, 2007 6:15 am

Post » Thu Jun 21, 2012 3:22 pm

There are almost always ways, it just depends on how ugly you want to get. :wink:

For example, could you also get the race of the targeted actor, force that into a quest property as well, and then use a while loop in your quest script to create initially disabled copies until you get one with a matching race, and then enable that one? (Remembering to delete the invalid copies.)

That said--and realizing I've done absolutely nothing with leveled actors myself, so forgive me if this doesn't work for obvious reasons--if you're trying to create a copy of an actor, is it really the actor base you want, or could you not pass the targeted actor as your property instead?
User avatar
Johnny
 
Posts: 3390
Joined: Fri Jul 06, 2007 11:32 am

Post » Thu Jun 21, 2012 10:28 am

There are almost always ways, it just depends on how ugly you want to get. :wink:

For example, could you also get the race of the targeted actor, force that into a quest property as well, and then use a while loop in your quest script to create initially disabled copies until you get one with a matching race, and then enable that one? (Remembering to delete the invalid copies.)

Brilliant! I was thinking of exactly that sort of thing, using some sort of keyword, but Race is perfect since it's "built-in," at least in the sense it is easier to get at, having it's own command and all.

I was running some tests to see what different values looked like. For example running this:

phitametrackerS Property phitametracker AutoActorBase phiActorBaseint phiakTargetFormIDForm phiakTargetFormRace phiakTargetRaceFunction SetQuestValue(Actor akTarget)	phiActorBase = akTarget.GetLeveledActorBase()	phiakTargetFormID = akTarget.GetFormID()	phiakTargetForm = Game.GetForm(akTarget.GetFormID())	phiakTargetRace = akTarget.GetRace()	Debug.MessageBox("akTarget is " +akTarget)	Debug.MessageBox("phiActorBase is " +phiActorBase)	Debug.MessageBox("phiakTargetFormID is " +phiakTargetFormID)	Debug.MessageBox("phiakTargetForm is " +phiakTargetForm)	Debug.MessageBox("phiakTargetRace is " +phiakTargetRace)EndFunction

I determined:

akTarget =
[lvlpredatorscript <(0008453F)>]
akTarget.GetLeveledActorBase() =
[ActorBase <(FF000C97)>]
akTarget.GetFormID() =
542015
Game.GetForm(akTarget.GetFormID()) =
[lvlpredatorscript <(0008453F)>]
akTarget.GetRace() =
[Race ]

That said--if you're trying to create a copy of an actor, is it really the actor base you want, or could you not pass the targeted actor as your property instead?

For generic use purposes yes, because of the way the "akTarget" Actor value is passed from the OnEffectStart Event in the MagicEffect script I am using to call the function, because of how leveled list objects are referenced, and because of how http://www.creationkit.com/GetLeveledActorBase_-_Actor works.

If you look at the above results, you can see that akTarget (which is passed AS an Actor value from the OnEffectStart Event in the MagicEffect script) is actually the same as Game.GetForm(akTarget.GetFormID()) where GetFormID() returns an ID of a Form as an INT value and GetForm() the FORM of that ID.

Therefore one can reasonably conclude the MagicEffect Event OnEventStart passes the akTarget FORM value CAST AS an Actor, if I am saying that right.

The trouble seems to be that with Actors spawned from leveled lists this might not be an actual Actor but rather a list that spawned it, a script associated with it, etc. http://www.creationkit.com/Glossary#Form

Trying to use PlaceAtMe on such a reference frequently results in the generic "cannot be placed" error in debug traces.

However, by using GetLeveledActorBase() you can "search out" or resolve the actual ActorBase object this passed Form points to or was generated from. In the case of creatures spawned from a leveled list, this is the actual leveled list "object" or "container," however one refers to it, with a true ActorBase value, or "object reference" in old-paradigm terminology.

That is why GetLeveledActorBase() is such a useful command, because if it isn't a leveled list spawn it will return the same as GetActorBase(), and so provides a convenient filter that eliminates some extra scripting.

It is still a leveled list object mind you, so the spawn of PlaceAtMe on this ActorBase object still has whatever chance defined in that leveled list of spawning any other creature in the list instead of our target creature, which is where the race check comes in.

With a quick modification to the script it is now working as intended!

Scriptname phitametrackerS extends QuestphitametrackerS Property phitametracker AutoRace phiakTargetRaceActor phiSpawnTempRace phiSpawnRaceFunction SetQuestValue(Actor akTarget)	phiakTargetRace = akTarget.GetRace()	phiSpawnTemp = Game.GetPlayer().PlaceAtMe(akTarget.GetLeveledActorBase()) as Actor	phiSpawnRace = phiSpawnTemp.GetRace()	while phiSpawnRace != phiakTargetRace		phiSpawnTemp.Disable()		phiSpawnTemp.Delete()		phiSpawnTemp = Game.GetPlayer().PlaceAtMe(akTarget.GetLeveledActorBase()) as Actor		phiSpawnRace = phiSpawnTemp.GetRace()	endwhileEndFunction
User avatar
Scarlet Devil
 
Posts: 3410
Joined: Wed Aug 16, 2006 6:31 pm

Post » Thu Jun 21, 2012 11:55 am

Cool, glad you got it working! And thanks for the explanation, I appreciate you taking the time for that. Although given what you write, it does seem weird to me that akTarget.GetRace() works...makes me wonder if akTarget could be cast as an actor. I may investigate further, just to satisfy my own curiosity. Cheers!
User avatar
Nick Tyler
 
Posts: 3437
Joined: Thu Aug 30, 2007 8:57 am

Post » Thu Jun 21, 2012 11:51 am

Just re-tried casting akTarget as an Actor and using that directly with PlaceAtMe like this:
Game.GetPlayer().PlaceAtMe(akTarget) as Actor

This compiles however fails with the following in the log:
[06/04/2012 - 10:18:17AM] error: (0008453F): cannot be placed. stack: [ (00000014)].Actor.PlaceAtMe() - ""

So it seems that, for lack of better object-oriented verbiage, what akTarget WAS AT THE TIME qualified it to be passed through OnEffectStart on a MagicScript, being a FORM that is the target of a magic effect, but just because the game happens to code this function to cast the target of the spell as an Actor doesn't mean it will always BE an actor.

The MagicEffect script Event "OnEffectStart" may be coded to accept the full range of "forms" which magic effects can be applied to. Since magic effects won't only necessarily ever be used on actual actors, the passed "target" may be CAST as an actor, but really, it should be thought of more as a Form.

Because of how things spawned from leveled lists are referenced in the world however, what qualifies and is cast as Actor from OnEffectStart may not qualify as the explicit Actor type that PlaceAtMe requires. That is because the Form in this case seems to be the actual leveled list itself, not the specific object reference spawned from it, if I understand correctly.

Since GetLeveledActorBase() "gets the temporary http://www.creationkit.com/ActorBase_Script of a leveled http://www.creationkit.com/Actor_Script - the one generated by the game from the leveled list," this reference qualifies since it is the actual object reference generated FROM the Form list.
User avatar
Mr. Ray
 
Posts: 3459
Joined: Sun Jul 29, 2007 8:08 am

Post » Thu Jun 21, 2012 9:35 pm

There are almost always ways, it just depends on how ugly you want to get. :wink:

For example, could you also get the race of the targeted actor, force that into a quest property as well, and then use a while loop in your quest script to create initially disabled copies until you get one with a matching race, and then enable that one? (Remembering to delete the invalid copies.)

That said--and realizing I've done absolutely nothing with leveled actors myself, so forgive me if this doesn't work for obvious reasons--if you're trying to create a copy of an actor, is it really the actor base you want, or could you not pass the targeted actor as your property instead?

Brilliant! I was thinking of exactly that sort of thing, using some sort of keyword, but Race is perfect since it's "built-in," at least in the sense it is easier to get at, having it's own command and all.

Am I right in thinking this will only work for creatures? One wolf looks exactly like another, but if the levelled list contains NPCs then matching race won't be enough because different NPCs of the same race can have different facial characteristics and such.
User avatar
Leah
 
Posts: 3358
Joined: Wed Nov 01, 2006 3:11 pm


Return to V - Skyrim