Jump to content

Need script to get cursor target or prevent anim from running on player


Godschildgaming

Recommended Posts

So I've turned my eyes to the Khajiit race and noticed 2 spells that really make me upset 1) Eye of Fear and their night eye these upset me because they are cast like normal spells, So I have bound the eye of fear spell to a key but it still upsets me a lot that they still have to do the spell cast animation just to use their abilities. So what I want to do is either cut out the spell cast ability or find a way to shoot a scripted invisible projectile in the direction of the player looking. Down below is my current failure of a script it works in the fact is changes the spell to the racial ability to cast it then switch it to a spell of my choice.

Things I have tried:
Googling and forum searching for ways to get target ref from cursor/mouse position
Skipanim command - broke 1st person movement when I ran it
Playgroup command - seems to do nothing :/

scn keyscript

;canusemagic is a global variable
float fQuestDelayTime
int maxh
int damageresult
int waittillcasted
int castkey
int nomag
int keyheld
ref raceab01
ref raceab02
begin gamemode
set maxh to player.getmaxav health
if nomag == 1
if player.iscasting != (player == player)
set nomag to 0
endif
endif
set castkey to getcontrol 7
set fquestdelaytime to 0.01
set raceab01 to PwRaceKhajiitDemoralize
if (iskeypressed2 45) != (player == player)
set keyheld to 0
endif
if (iskeypressed2 45)
if (Player.cancastpower raceab01)
message "power used"
selectplayerspell raceab01
tapkey castkey
player.playgroup idle 1
set nomag to 1
else
message "that would hurt... but script has not been made yet... oh wait... now it is..."
set damageresult to maxh*.25
set damageresult to 0 - damageresult
if keyheld == 0
player.modav2 health damageresult
set keyheld to 1
endif
endif
endif
if nomag == 0
if canusemagic == 0
selectplayerspell uselessspell
endif
endif
end

 

Edited by Godschildgaming
Link to comment
Share on other sites

Yeah, it's a bit more difficult than that. You can't just call "PlayGroup idle" to abort a playing animation. Rather it will "schedule" the next animation to play. Even with the second parameter being "1" there's still no guarantee for an immediate switch back to idle.

Additionally, by using any other means to "disable" or prevent the casting animation from playing you'll only end up disabling your actor from "being able to" cast itself likewise. If the animation doesn't play, the actor will not cast.

Now you "could" devise means to "switch" the casting animation temporarily to one without any motion, or a different, more befitting one even, perhaps, by using ToggleSpecialAnim right before and after the cast... But there's also different means.

An invisible casting activator doing the casting for you comes to mind, because inanimate objects don't need to play no animations to cast. Just spawn it above yourself, or in front of you, then let "it" cast instead, and move it away (or leave it where it is until next cast, I've seen both solutions used). (https://cs.elderscrolls.com/index.php?title=Casting_Spells_From_An_Activator)
You could use GetCrosshairRef to obtain the target you're looking at, but it only finds targets within activation range.

A different approach to "aiming" targeted spells at targets outside of activation range would be to make one activator shoot a spell towards another but miss it (I think the key is the NIF file doesn't have collision to hit).
Maybe you can make some use of my code in understanding this (however, there's some vector math magic by myself inside for easing my work. It definitely works without vector math and just simple geometric, too, though):

DrakeDragonTransformCaster01.MoveTo player
let fPosX := 0
let fPosY := 55 * GetScale
let fPosZ := 60 * GetScale
let vTemp := rSelf.Call DrakeDragonGetVectorGlobal fPosX fPosY fPosZ
let fPosX := vTemp[0] + rSelf.GetPos X
let fPosY := vTemp[1] + rSelf.GetPos Y
let fPosZ := vTemp[2] + rSelf.GetPos Z
DrakeDragonTransformCaster01.SetPos X fPosX
DrakeDragonTransformCaster01.SetPos Y fPosY
DrakeDragonTransformCaster01.SetPos Z fPosZ
PrintToConsole "caster at %.02f %.02f %.02f" fPosX fPosY fPosZ
DrakeDragonTransformCaster02.MoveTo player
let fPosX := 0
let fPosY := 1000
let fPosZ := 60 * GetScale
let vTemp := rSelf.Call DrakeDragonGetVectorGlobal fPosX fPosY fPosZ
let fPosX := vTemp[0] + rSelf.GetPos X
let fPosY := vTemp[1] + rSelf.GetPos Y
let fPosZ := vTemp[2] + rSelf.GetPos Z
DrakeDragonTransformCaster02.SetPos X fPosX
DrakeDragonTransformCaster02.SetPos Y fPosY
DrakeDragonTransformCaster02.SetPos Z fPosZ
PrintToConsole "dummy target at %.02f %.02f %.02f" fPosX fPosY fPosZ

Basically the caster is moved into my cell, gets positioned at a little offset to me relatively (60 above, 55 in front, to not hit myself accidentally, and relative to my scale, which you can neglect in your case),
then I use my vector math function to get absolute world coordinates from the player-relative ones I defined (rSelf is the player in your case) and SetPos the caster into its place.
The same goes for the target, it's just 1000 units forward away.
Then have the caster cast a targeted spell at the target and the projectile will fly into the desired direction you're looking at.

If you need it, here's my vector math magic for reference (I consider it common knowledge at this point):

scn DrakeDragonGetVectorGlobal
 
float fVecLocX
float fVecLocY
float fVecLocZ
float fAngleX
float fAngleY
float fAngleZ
array_var vVecLoc
array_var vVec
array_var mRotationX
array_var mRotationY
array_var mRotationZ
array_var mRotationYXZ
 
Begin Function {fVecLocX fVecLocY fVecLocZ}
    let vVecLoc := ar_Construct Array
    let vVecLoc[0] := fVecLocX
    let vVecLoc[1] := fVecLocY
    let vVecLoc[2] := fVecLocZ
    let vVecLoc := ForceColumnVector vVecLoc
    let fAngleX := -GetAngle X
    let fAngleY := GetAngle Y
    let fAngleZ := -GetAngle Z
    let mRotationX := GenerateRotationMatrix X fAngleX
    let mRotationY := GenerateRotationMatrix Y fAngleY
    let mRotationZ := GenerateRotationMatrix Z fAngleZ
    let mRotationYXZ := MatrixMultiply mRotationX mRotationY
    let mRotationYXZ := MatrixMultiply mRotationZ mRotationYXZ
    let vVecLoc := MatrixMultiply mRotationYXZ vVecLoc
    let vVec := ar_Construct Array
    let vVec[0] := vVecLoc[0][0]
    let vVec[1] := vVecLoc[1][0]
    let vVec[2] := vVecLoc[2][0]
    SetFunctionValue vVec
End

It's pretty much just basic vector math like we all learned it in school put into ObScript/OBSE terms... well, plus fixing some game engine oddities with their coordinate systems, so don't be surprised the resulting matrix isn't looking like what you expected. It works regardless, in this game. :sweat:

Link to comment
Share on other sites

Yeah, it's a bit more difficult than that. You can't just call "PlayGroup idle" to abort a playing animation. Rather it will "schedule" the next animation to play. Even with the second parameter being "1" there's still no guarantee for an immediate switch back to idle.

 

Additionally, by using any other means to "disable" or prevent the casting animation from playing you'll only end up disabling your actor from "being able to" cast itself likewise. If the animation doesn't play, the actor will not cast.

 

Now you "could" devise means to "switch" the casting animation temporarily to one without any motion, or a different, more befitting one even, perhaps, by using ToggleSpecialAnim right before and after the cast... But there's also different means.

 

An invisible casting activator doing the casting for you comes to mind, because inanimate objects don't need to play no animations to cast. Just spawn it above yourself, or in front of you, then let "it" cast instead, and move it away (or leave it where it is until next cast, I've seen both solutions used). (https://cs.elderscrolls.com/index.php?title=Casting_Spells_From_An_Activator)

You could use GetCrosshairRef to obtain the target you're looking at, but it only finds targets within activation range.

 

A different approach to "aiming" targeted spells at targets outside of activation range would be to make one activator shoot a spell towards another but miss it (I think the key is the NIF file doesn't have collision to hit).

Maybe you can make some use of my code in understanding this (however, there's some vector math magic by myself inside for easing my work. It definitely works without vector math and just simple geometric, too, though):

DrakeDragonTransformCaster01.MoveTo player
let fPosX := 0
let fPosY := 55 * GetScale
let fPosZ := 60 * GetScale
let vTemp := rSelf.Call DrakeDragonGetVectorGlobal fPosX fPosY fPosZ
let fPosX := vTemp[0] + rSelf.GetPos X
let fPosY := vTemp[1] + rSelf.GetPos Y
let fPosZ := vTemp[2] + rSelf.GetPos Z
DrakeDragonTransformCaster01.SetPos X fPosX
DrakeDragonTransformCaster01.SetPos Y fPosY
DrakeDragonTransformCaster01.SetPos Z fPosZ
PrintToConsole "caster at %.02f %.02f %.02f" fPosX fPosY fPosZ
DrakeDragonTransformCaster02.MoveTo player
let fPosX := 0
let fPosY := 1000
let fPosZ := 60 * GetScale
let vTemp := rSelf.Call DrakeDragonGetVectorGlobal fPosX fPosY fPosZ
let fPosX := vTemp[0] + rSelf.GetPos X
let fPosY := vTemp[1] + rSelf.GetPos Y
let fPosZ := vTemp[2] + rSelf.GetPos Z
DrakeDragonTransformCaster02.SetPos X fPosX
DrakeDragonTransformCaster02.SetPos Y fPosY
DrakeDragonTransformCaster02.SetPos Z fPosZ
PrintToConsole "dummy target at %.02f %.02f %.02f" fPosX fPosY fPosZ

Basically the caster is moved into my cell, gets positioned at a little offset to me relatively (60 above, 55 in front, to not hit myself accidentally, and relative to my scale, which you can neglect in your case),

then I use my vector math function to get absolute world coordinates from the player-relative ones I defined (rSelf is the player in your case) and SetPos the caster into its place.

The same goes for the target, it's just 1000 units forward away.

Then have the caster cast a targeted spell at the target and the projectile will fly into the desired direction you're looking at.

 

If you need it, here's my vector math magic for reference (I consider it common knowledge at this point):

scn DrakeDragonGetVectorGlobal
 
float fVecLocX
float fVecLocY
float fVecLocZ
float fAngleX
float fAngleY
float fAngleZ
array_var vVecLoc
array_var vVec
array_var mRotationX
array_var mRotationY
array_var mRotationZ
array_var mRotationYXZ
 
Begin Function {fVecLocX fVecLocY fVecLocZ}
    let vVecLoc := ar_Construct Array
    let vVecLoc[0] := fVecLocX
    let vVecLoc[1] := fVecLocY
    let vVecLoc[2] := fVecLocZ
    let vVecLoc := ForceColumnVector vVecLoc
    let fAngleX := -GetAngle X
    let fAngleY := GetAngle Y
    let fAngleZ := -GetAngle Z
    let mRotationX := GenerateRotationMatrix X fAngleX
    let mRotationY := GenerateRotationMatrix Y fAngleY
    let mRotationZ := GenerateRotationMatrix Z fAngleZ
    let mRotationYXZ := MatrixMultiply mRotationX mRotationY
    let mRotationYXZ := MatrixMultiply mRotationZ mRotationYXZ
    let vVecLoc := MatrixMultiply mRotationYXZ vVecLoc
    let vVec := ar_Construct Array
    let vVec[0] := vVecLoc[0][0]
    let vVec[1] := vVecLoc[1][0]
    let vVec[2] := vVecLoc[2][0]
    SetFunctionValue vVec
End

It's pretty much just basic vector math like we all learned it in school put into ObScript/OBSE terms... well, plus fixing some game engine oddities with their coordinate systems, so don't be surprised the resulting matrix isn't looking like what you expected. It works regardless, in this game. :sweat:

wow thats a lot of detail and sure it will come in handy, now I just gotta figure out how to dismantle the code and rescript it for my script Thanks for the help will reply with either a failed or successful attempt in like a few hours

Link to comment
Share on other sites

Ok now I have a new problem.... I have a activator going to the target and it is right on the target and hits them perfectly with any spell... but I need it to use a demoralize spell... which it refuses to do... It'll shoot fireballs and lighting but gets shy when I try to have it fire a projectile demoralize

Link to comment
Share on other sites

  • Recently Browsing   0 members

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