Jump to content

Specific Scripting Help


LordSerathDarklands

Recommended Posts

I'm trying to make a minor spell mod that I plan on calling either "Flicker" or "Blink" or something similar, with the idea of the spell being to blink the spell's target out of existence for the spell's duration. I've got the basics down (using the "disable" and "enable" commands to blink the target in and out of existence), but I don't know how to create a timer within scripts.

 

For example, I'd like to have the script be something like:

 

 

scn FlickerSpell
begin ScriptEffectStart
disable
end
(Timer Script Command)
enable
end
begin ScriptEffectFinish
end
Also, anyone who knows scripts well, if I've made a mistake in the syntax of the script, please correct me.
The overall goal of the effect is to make it into a script effect for a spell so that when it's cast, it will remove the targeted item (like the "disable" console command) for the duration of the timer script command, then restore it (like the "enable" console command does on something that has had "disable" used on it if you've not clicked on anything else once you used "disable"), effectively temporarily "blinking" the object out of existence for a set amount of time.
Link to comment
Share on other sites

Is there a reason you're not just using the Oblivion-internal spell duration timer to achieve this? You can disable the target in the ScriptEffectStart block and enable it again in the corresponding ScriptEffectFinish block, which will automatically be called once your spell duration "runs out".

 

You can also use a GameMode block, running about every frame, and GetSecondsPassed to reduce a timer variable each frame and only enable once it's <= 0 again. Have the ScriptEffectStart block set the variable to the amount of seconds you want to have it run down, and use a trigger flag variable so it only runs down and enables once the timer was set. But as it's a spell already, the spell's duration should do the trick.

float timeout
short docount
 
Begin ScriptEffectStart
    disable ;or whatever
    set timeout to 10 ;seconds
    set docount to 1
End
 
Begin GameMode
    if 1 == docount
        if 0 < timeout
            set timeout to timeout - GetSecondsPassed
        else
            enable ;or whatever
            set docount to 0
        endif
    endif
End

There's one thing to keep in mind though. I don't know if "disable" doesn't actually cancel all spells or stops all scripts on the object disabled as well. In that case it'd be no use to even try anything of the above.

But if that is the case, you can always create a "holding cell" instead where you "moveto" the objects hit by the spell and "moveto" them back to where they were before they got removed. I think a placeholder XMarker can be spawned in their place, and that'll be where they'll be transported back to then. But that's just a very basic idea of a different approach in case the above fails due to mentioned game engine limitations.

 

Oh, and the above will also not work, when your spell runs out before the script has ended, of course. But that's to be expected I think.

Link to comment
Share on other sites

The reason I wasn't using the existing spell duration was because I thought that would time the entire script - disable AND enable. So I thought it would effectively run a script of disable, then enable over the course of a few seconds, with no actual visible effect.

 

This is much more advanced than I thought it was going to be. Perhaps I should put it in the mod request forum instead.

 

Morrowind had the capacity to shrink objects to 0% scale, as opposed to Oblivion's minimum of 50%, which could have been rather useful for this kind of effect. Instead of disabling it, it could have simply been reduced to zero size, then resized to normal. Sadly, Morrowind didn't have script effect enchanting.

Link to comment
Share on other sites

For what it's worth, if you use this spell script:

 

Begin ScriptEffectStart
    disable
End
 
Begin ScriptEffectFinish
    enable
End

and give your spell a duration, it might just do what you want already, given the "disable" does not kill the script. Both blocks will only run once, one at the start of the spell's duration, one when it ran out, and the spell duration will be your timer. I'd say give it a try and see what it does.

Link to comment
Share on other sites

So I tried the script you provided, with a five second duration for testing purposes. It has no effect on inanimate objects (shelves, staircases, etc) or things that you can pick up (I tried it on a silver pitcher and a silver bowl). However, it makes objects that can be interacted with (NPCs, chairs, gates [i tried the ones at the Arcane University], benches, and so on) vanish - permanently.

Link to comment
Share on other sites

Spell effects in general did not work on statics last I checked. They do seem to work on containers, activators, actors and all that. As for permanent disabling, chances are that - as Drake mentioned:

 

-- it might just do what you want already, given the "disable" does not kill the script. --

 

So it sounds like, when the reference is disabled, all script processing on it might also be disabled (like actors have their AI disabled with the actor), and the script probably stops processing after the Disable command has been called on it.

 

For actors, you could use GetActorAlpha and SetActorAlpha, with an AI toggle, and maybe something to stop combat (just an example, I have not yet managed to stop any combat at all this far... so go figure):

float fOldAlpha

Begin ScriptEffectStart
    StopCombatAlarmOnActor ; to stop others' combat, maybe?
    SetActorsAI 0
    let fOldAlpha := GetActorAlpha
    SetActorAlpha 0
End

Begin ScriptEffectFinish
    SetActorAlpha fOldAlpha
    SetActorsAI 1
End

For activators and all that, I am not sure what would work, exactly. It is a bit tricky, SetActorAlpha does not work on something that is not an actor. Temporarily replacing model with an invisible one might be one option, assuming you can find a command that does not modify the base object - and those ones are probably pretty rare, from what I have noticed, since each reference is an instance of its base object, and modifying the base object will usually see the changes reflected in all instances of it. Hopefully that helps a little. And hopefully someone knows how to hide statics. :smile:

 

Edit: Whoops. Added the missing SetActorAlpha, to hide the actor. Of sorts. Update3D works if the changes are not instantly reflected.

 

Edit 2: One solution would be to use an array of StringMaps, with the ref ID and a timer, on a quest script, that could run each second, for example. This is just an idea, untested, I am writing it here directly, to give you an overall idea.

 

The looping, in a quest script, for example:

float fQuestDelayTime
Array_var aRefs
int iTemp
ref rTemp

Begin _GameMode

    let iTemp := ar_Size aRefs
    let fQuestDelayTime := 1.0 ; or otherwise set this

    While ( iTemp > 0 )
        let iTemp -= 1
        let aRefs[iTemp]["time"] -= fQuestDelayTime
        If Eval ( aRefs[iTemp]["time"] < 0 )
            let rTemp := aRefs[iTemp]["ref"]
            rTemp.Enable
            ar_Erase aRefs iTemp
        EndIf
    Loop

End

And the adding on a magic effect script:

Begin _ScriptEffectStart

    If Eval ( YourQuestID.aRefs == ar_Null )
        let YourQuestID.aRefs := ar_Construct "Array"
    EndIf

    ar_Append YourQuestID.aRefs ( ar_Map "ref"::GetSelf "time"::5.0 )

    Disable
    
End

Or something like that. Assuming GetSelf returns a reference and not a base object. Cannot remember at the moment.

Edited by Contrathetix
Link to comment
Share on other sites

I'm getting an issue on the script you provided. It's not recognizing the term "let".

 

Script 'SDFlickerSpell', line 8:
Script command "let" not found.
Continue Playing?
"Yes to all" will disable all Warnings this session.
"SDFlickerSpell" is the script name I'm using.
Also, if this works, awesome, but the main focus of the spell was for activators like locked gates. It's for a kind of "pathmage" like character, the kind of character that can open doors that aren't even there.
Link to comment
Share on other sites

Oh yes, that is an OBSE command. The second suggestion (I edited when you posted, it seems, whoops) will not even get that far without it. However, the second one should work for statics, assuming they do not have an enable parent. If a reference has an enable parent, it will refuse to abide by the Disable command.

 

I would recommend using the Construction Set Extender: http://www.nexusmods.com/oblivion/mods/36370/?

 

Hopefully that helps a little. As for how to achieve it without OBSE, no idea. Interesting idea tha project of yours, though. Be sure to check that the door is not a load door. You can use the IsLoadDoor and invert it http://cs.elderscrolls.com/index.php?title=IsLoadDoor

If Eval !( IsLoadDoor )

Or, the more usual notation, equivalent to that one

If ( IsLoadDoor == 0 )

This is a handy place: http://cs.elderscrolls.com/index.php?title=List_of_Functions

 

Edit: Using GetParentRef will help you check if it has an enable parent. You can invert it to check if it does not have one:

If Eval !( GetParentRef )

Edit 2: Like this, with the quest script mentioned earlier (remember to se the duration to at least 2 seconds if you use the visuals (which look nice)

Begin _ScriptEffectStart

    If Eval ( IsDoor ) || ( IsActivator )
        PlayMagicShaderVisuals effectEnchantAlteration 0.5
        ; having duration of something like > 1 will allow for the effect to finish
    EndIf

End

Begin _ScriptEffectFinish

    If Eval ( !( IsDoor ) && !( IsActivator ) ) || ( GetParentRef ) || ( IsLoadDoor )
        Message "The target resisted the spell!"
        Return
    EndIf

    If Eval ( YourQuestID.aRefs == ar_Null )
        let YourQuestID.aRefs := ar_Construct "Array"
    EndIf

    ar_Append YourQuestID.aRefs ( ar_Map "ref"::GetSelf "time"::5.0 )

    Disable
    
End

Edit 3: I need to go get some sleep. If someone has better solutions, feel free to chime in. I will check back tomorrow. Happy modding. :)

Edited by Contrathetix
Link to comment
Share on other sites

Contrathetix, I really like that Quest Script driven Array storage solution of your's to get around "disable" killing scripts and other processes running on the target. Very elegant. :thumbsup:

 

Juts in case the limitation to only things a spell can affect bothers you too much, there's also another nifty OBSE function called GetCrosshairRef which used from inside a GameMode block instead of a spell script might turn out quite useful.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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