Jump to content

Trying to script spell effect to target an area, not an object or actor.


Recommended Posts

Been trying for a few hours to figure out how to script a spell to affect a specific area of the environment (wall, ground, rock, etc...) that the player can target. Think along the lines of the Target Location delivery type in Magic Effects that summon and rune spells use. Runes can stick to walls, summons can be cast on the ground in a place the player targets with the crosshair. But I'm looking to place an activator object this way and the summon creature and hazard Effect archetypes only let you choose those specific types of objects to add to your magic effect. And from the scripting side, OnEffectStart wants specific actor references to apply the script's functions to, not an actual targetable area on the ground (like with the aforementioned summon effect).

 

I'd rather not use the Ref.MoveTo() or TranslateTo() functions with invisible markers to do this. I've tried those before and there are drawbacks to going that route. The targeting is not as flexible and collision isn't updated very effectively (if at all) and you could fire off your spell and watch it float right through the games geometry and out into limbo if you're not careful.

 

I tried the Light magic effect (like in MageLight) where it's shot with a projectile that sticks to the environment set with impact data properties. It uses a Light base object, so I tired making one with a script attached to the light using OnLoad() but the script never fires when the Light spell hits something. Another work around I've thought of is using an invisible NPC with the summon effect and an OnLoad/PlaceAtMe script snippet attached to said NPC, but now we're just getting ridiculous. I think there should be an easier way to do this that I'm not thinking of.

 

I've also seen an option in Explosions to place an object reference at the point of impact of the explosion. I tried that using my activator object on an explosion that I placed on a magic effect with a projectile, but couldn't successfully get the activator ref to generate when the projectile hit something and triggered the explosion.

 

Anyway that's how far I've gotten with this. I'm starting to run out of ideas. I hope someone else can point me in the right direction. Thanks.

Edited by SamHe11
Link to comment
Share on other sites

I've had success with what I wanted to do. Maybe this is common knowledge by now (the game is nearly 10 years old), or maybe a better way to do it has been discovered, but hits on searches for this kind of topic were non existant, and maybe some other poor soul another 10 years from now will be trying to solve this same issue and stumble across this old post. Oh and none of this requires SKSE (in case you also like to mod and play on Xbox like me :thumbsup: )

 

The invisible NPC route was the way to go. There is already an Invisible NPC race in the vanilla resources. Just duplicate that one and give it a unique ID, then make sure the form is as blank as possible. No traits, voices, packages, etc. Make sure its Summonable box is checked. Then attach a script to it with whatever you want to happen when this "spell" is cast. I suggest putting your code inside an OnLoad() event so it fires as soon as it's summoned. Next is to make the custom Magic Effect. The easiest way is to just duplicate a vanilla summon effect like SummonFlameAtronach. This effect will already come with the Summon archetype and Target Location delivery types plus a few extra settings required of summon spells that may not be immediately evident. Anyway, select your Invisible NPC in the Assoc. Item 1 dropdown box and give this edited magic effect a new ID. Now attach the magic effect to a spell and go in game and try it out. There, you now have a targetable invisible marker that respects the environment that you can attach some scripted effects to.

 

One drawback is the campy groans and grunts the invisible NPC makes when he/she dies after the spell wears off. There's an easy fix for this: Under the traits tab of your invisible NPC's Actor window, there is a box labeled Voice Type. You need to make a new Voice Type (found under Character in the Object Window) with a unique ID, then reopen the NPC window and select that empty Voice Type in the box. Now all the zombie impersonations are a thing of the past.

 

You may also notice right away that the sounds and visuals of the Magic Effect itself aren't what you're looking for. At this point, you can change any FX you want when the spell is cast, but (as I mentioned above) there is one caveat to changing a Summon effect's visuals and that is linked to the Hit Effect Art setting under Visual Effects. If you change that to anything else that doesn't use the SummonTargetFX.nif file in its Art Object, your invisible NPC won't be summoned. The actual code that spawns NPCs with the "summonable" flag is baked into the nif file. This may not bother you, but remember, we're not making a legit summon spell here, we just want this particular magic effect for the Target Location delivery type that comes with it. Therefore, the visual FX that come with the required Hit Effect Art may be a major turnoff to you. We can fix this with nifskope.

 

Extract the SummonTargetFX.nif file from the Skyrim - Meshes1.bsa in your data folder and open it in Nifskope (I'm using Nifskope 2.0 Dev 7, that's probably an old one but it's what works for me atm). What you're looking for in the node tree on the left side of the screen are the BSTriShape blocks found under the NiBillboardNode. When you click on the individual BSTriShape blocks, their corresponding wireframes should highlight in the render window. Give each one a look over and consider if you want to save any of them or not. To remove one, simply right click it and select Block -> Remove. Doing this to every BSTriShape block will remove the visual 3D portion of the nif file while leaving the important code intact that the summon effect from the game wants to see. This is found over several entries in the Sting block under the Header tab (also on the left side of the screen). After you've removed the BSTriShape blocks, save the nif with a new file name, drop it in your Data/Magic/ folder and load it into a new Art Object with a new ID in the Creation Kit. Now go back to your custom Magic Effect and select your new Art Object in the Hit Effect Art box. Load up a game and try it out again and voila, a nice new blank slate for your own scripted AoE spells with stable, reliable targeting on any part of the environment without any accidental ghosting through walls or other unpredictable collision issues.

Edited by SamHe11
Link to comment
Share on other sites

This can easily be done with a simple script instead of doing all that...

Here you can find the 'script base' and the 'base idea' to adjust it to your needs.



PS: This has been done thousands of times over the years, in one way or the other.


Have a nice weekend.

Link to comment
Share on other sites

Hi thanks for the info. As I mentioned in the first post, I've used that method before and wasn't happy with the results b/c of the collision issues and rigid pre-defined distancing from the player in the code. You even said so yourself in the thread you referenced...

 

Your issue is cause by the fact that the whole setup doesn't care or detects if there is an object or void in front of the player, the script only cares about the player's position (The Player's BSFadeNode), so that it can place the "Shrine's BSFadeNode" where the script calls.

The functions:

GetPosition

SetPosition

GetAngle

SetAngle

MoveTo

Cannot detect obstacles or the void, if the player is facing a wall or a big rock, and so on....

 

If this is for a public mod, then you need to inform the downloaders how to use the 'Shrine', like what not to do ( standing in front of a wall

I'd like to point again that my way, while certainly not perfect, avoids issues like these in that uses the Summon spell mechanic to let you drop anything right onto any object in the environment (walls, rocks, rooftops, etc..) from any distance and all with the flexibility of pointing and clicking with your mouse where you want it, not relying on pre-defined values in the code and risking the activator (in my case, or shrine in the case you mentioned) getting stuck out in the "void". By doing it this way, I've put the decision of where to place the object dynamically in the hands of the player, not the code.

 

Hope that clarifies. Thanks.

Edited by SamHe11
Link to comment
Share on other sites

I admit that i didn't read carefully all your post..., i tend to zoom out easily and fast when i'm too tired, so... i just assumed this is what you wanted to do.


* You may want to use "SetCriticalStage()" on the invisible actor to delete them and to not end up with a game full with invisible corpses, which also occupy space in your save file.


Have a happy modding.

Link to comment
Share on other sites

 

I admit that i didn't read carefully all your post..., i tend to zoom out easily and fast when i'm too tired, so... i just assumed this is what you wanted to do.
* You may want to use "SetCriticalStage()" on the invisible actor to delete them and to not end up with a game full with invisible corpses, which also occupy space in your save file.
Have a happy modding.

 

 

That's a good point and is another reason I like this method. The Summon effect cleans itself up after the spell wears off so there aren't any corpses lying around. The way I have it setup now is with a duration of 1 second on the spell. This is more than enough time to spawn in the invisible NPC and execute its OnLoad() event with the contained script. Then the spell ends and the invisible NPC unloads.

 

The most glaring problem I can see with this right now is that it (ever so briefly) ties up one of the player's summon "slots", which I believe in vanilla Skyrim is just 1 creature until you obtain the summon perk that allows more "slots". And if the player already has their maximum allowed summons active when this spell is cast, this would unintentionally interrupt one of those summons. Of course the easy fix would just be to download a mod that increases this cap, but I don't want to paint players into a corner like that. What I'm thinking of trying is to circumvent this as un-intrusively as possible by adding a conditional somewhere that checks if the player has the spell readied and quietly grants them an additional summon slot, then removes said extra slot after the spell wears off. This way, simply using the spell won't unsummon any other creatures the player had active if they were already at their max summons when the spell was cast.

 

It's been fun to play around with so far.

Edited by SamHe11
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...