Author Topic: Questions about triggered animation  (Read 15557 times)

0 Members and 1 Guest are viewing this topic.

Questions about triggered animation
I must be missing some details/information...

The physical subsystem must also have a "$triggered:" but what's the value for it?

The table entry looks like this:
Code: [Select]
$Subsystem: PortMainGearDoorInner, 10, 1
$flags: ("untargetable")
$animation: triggered
$type: scripted
+sub_type: 0
+delay: 0
+relative_angle:0,0,90
+velocity: 0,0,10
+acceleration: 0,0,5
+time: 2000

and the sexp looks like this:
every-time
     key-pressed   q
    free-rotating-subsystem   Alpha 1    FrontLandingGear
    key-reset   q

but nothing happens, any ideas?
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
the submodel prop has no value. its just $triggered: (with the : ) at least thats what i get from my own nukemod models. i think the problem may be with the scripted type (which i think works from lua not through sexps, though im not totally sure).

you can try changing the type to something else, like afterburner and see if the animation plays, this will eliminate model/table configuration as an issue. animation code is a glitchy system when it does work.

e:

after looking at the scripting.html, it appears that the function to play an animation of type scripted is marked as being expiremental. so im writing a short script you should be able to test it with. two functions that can be called with a scrip eval to forward and reverse play an animation

Code: [Select]
#Conditional Hooks

$Application: FS2_Open
$On Game Init:
[
--do forward animations
function fanim(sname)
--not a string, bail
if type(sname) ~= "string" then
return false
end
--get a ship handle
local shp = mn.Ships[sname]
if shp:isValid() then
--play animation forward
shp:triggerAnimation("scripted",0,true)
return true
end
return false
end
--do backwords animation
function ranim(sname)
--not a string, bail
if type(sname) ~= "string" then
return false
end
--get a ship handle
local shp = mn.Ships[sname]
if shp:isValid() then
--play animation in reverse
shp:triggerAnimation("scripted",0,false)
return true
end
return false
end
]
#End

stick that in a somename-sct.tbm and then use a script-eval sexp to call functions fanim(shipname) and ranim(shipname) (the first plays an animation forward and the second plays it in reverse). shipname is a string, such as "Alpha 1". the full string for the sexp should be "[fanim("Alpha 2")]". this will play an animation of type scripted at subtype 0. thats assuming it works at all and doesnt crash.
« Last Edit: November 30, 2012, 12:21:31 am by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Axem

  • 211
Re: Questions about triggered animation
There's also a new sexp in nightlies I think, called trigger-subobject-animation. You specify which type (in this case scripted) and optionally the specific subobject and just call it. You can also specify if you want the animation to be reversed, or for the animation to snap to its end position (in effect ignoring the speeds and instantly rotating).

 
Re: Questions about triggered animation
Alright unless I'm doing something completely wrong, there's something wrong with the rotation.  I've been doing some checking to see if i can figure out what I'm doing.  I've done the simple cube ship with a rotation wheel.  Now when I setup the wheel to rotate on the z-axis, so it's like a helicopter blades, it works perfectly.  Then I rotated the wheel so it wouldn't spin vertically flat (tilted it), things broke.  Instead of continuing to rotate like helicopter blade, it wobbled back and forth, i.e. it was rotating on the world's Z axis and not the subobject's Z axis. 

Hmmm i wonder if uvec and fvec are needed... checking
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
YES!!!  That was the solution... 

if your subsystem is not on the classic top/bottom flat, you must use the uvec and fvec.  This includes everything, not just turrets! Someone should put a sticky note on the wiki about this.
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
There's also a new sexp in nightlies I think, called trigger-subobject-animation. You specify which type (in this case scripted) and optionally the specific subobject and just call it. You can also specify if you want the animation to be reversed, or for the animation to snap to its end position (in effect ignoring the speeds and instantly rotating).

Well until someone ports the tables from saga over i'm stuck with it.  The newer builds throw errors and quits.  I've looked at the tables and went ugh at the thought.

edit: Sorry nuke, not having luck with the scripts. I don't think it's actually starting, added a couple of gr.DrawString ("") messages and notta.  Is this how the event is suppose to look like?
Code: [Select]
$Formula: ( every-time
   ( key-pressed "Q" )
   ( script-eval "[fanim('Alpha 1')]" )
   ( send-message
      "#Command"
      "High"
      "testing"
   )
   ( key-reset "Q" )
)

double edit: ok found a extra quote but now its throwing this error  Fixed that one (quote in quotes)
triple edit:  ok it crashes when it tries to use the graphics.drawscreen, no biggie. I do know that the script is being called.  I removed them and nothing rotates.  Back to doing more checking.  :blah:
« Last Edit: December 02, 2012, 02:54:39 am by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Ya! Finally got it working.  Turns out I was rotating in the wrong direction, so the landing gears never appeared outside the hull.

Two lua questions, is it possible to see the angle that the subobject current is and is it possible to see subobject properties?  I'm thinking of something like this: 
$RotationDelta:0,90,0
$RotationDirection:0,1,0

$RotationLimit would stop the rotation when it reaches limit and $RotationDirection tells it clockwise/counterclockwise.  That way all you would have to do is call a function like DoAnimation("Alpha 1", "FrontLandingGear", true) to tell it to bring down the landing gear and DoAnimation ("Alpha 1", "FrontLandingGear" false) to raise it back up.
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
in script you just get the ship handle (ship = mn.Ships["shipname"]), and then the subsystem handle (subsys = ship["subsystemname"]). from that you can get the submodel orientation (subsys.Orientation). if you want to rotate it for example 90 degrees on the x axis, just multiply it orientation by a matrix that represents your change in rotation (subsys.Orientation = subsys.Orientation * ba.createOrientation(math.rad(90),0,0)) ). its slightly more complicated than that though, for example euler angles sometimes produce singularities and multiplication order matters.

way i would do it is id set up a begin matrix and an end matrix, and then interpolate between them (scripting has a function for that). you could map any data within a fixed range to the interpolation value and get an intermediate matrix. take this a step further you can make a keyframe based animation system, where each key in the time graph is a matrix, you can find the previous and next key for a given time graph, and get an interpolated matrix from that. mapping also need not be made linear. frankly even with the animation code, the submodel animation capabilities of the engine are archaic at best. im considering (eventually) writing such a script, because i need it for an animation heavy model im (sort of) working on.

im also not sure if scripted animations break collision detection or not, thats something that needs to be tested.
« Last Edit: December 03, 2012, 10:04:30 pm by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Hmmm well my lua knowledge is VERY limited.

I'm getting this error:
Code: [Select]
LUA ERROR: [string "animation-sct.tbm - On Game Init"]:18: attempt to index global 'base' (a nil value)
Code: [Select]
function DoAnimation(shipName, subsystemName)
--not a string, bail
if type(shipName) ~= "string" then
return false
end

if type (subsystemName) ~= "string" then
return false
end

--get a ship handle
local shp = mn.Ships[shipName]

if shp:isValid() then
subsystem = shp["FrontLandingGear"]

if subsystem:isValid () then
subsystem.Orientation = subsystem.Orientation * base.CreateOrientation (math.rad ((90),0,0))
--play animation forward
shp:triggerAnimation("scripted",0,true)

return true
end
end
return false
end
How do you import libaries ("base")?
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline zookeeper

  • *knock knock* Who's there? Poe. Poe who?
  • 210
Re: Questions about triggered animation
Quote
base.CreateOrientation (math.rad ((90),0,0))

I don't know if Lua is case-sensitive or not, but the function's name is createOrientation. Also, you got the argument parentheses mixed up.

Presumably this is what you want:

Quote
base.createOrientation(math.rad(90), 0, 0)

  

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
lua is case sensitive. im mostly quoting for memory so do look stuff up in the scripting.html to make sure. i alwayse got at the base library with ba.functionName(). most of the functions are lower case for the first word and upper case for all other words, there are some exceptions, things like mn.Ships (technically thats an indexer not a function) for example. all built in lua functions seem to be lower case. also any functions that return handles should be checked with handle:isValid() before use, which returns true if its good.
« Last Edit: December 04, 2012, 07:24:45 am by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Also it doesn't like base for some reason... ba is good though.  Making a lot of progress though!

Ok next question, is it possible to read properties from a subsystem?  For example $RotateX=0 $RotateY=90 $RotateZ=0  that way I can do something like this:

Code: [Select]
xAxis = readProperty (ship)
yAxis = readProperty (ship)
zAxis = readProperty (ship)

subsystem.Orientation = subsystem.Orientation * ba.createOrientation (math.rad (xAxis), math.rad (yAxis), math.rad (zAxis)) -- Whatever the actual formula is needed

I couldn't find anything about properties in the scripting.html file.
« Last Edit: December 04, 2012, 04:44:55 pm by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
i dont think those are in. problem is you need to add a function to lua.cpp for every little piece of data you need access to. this makes lua.cpp a very big pile of code. its usually trivial for someone to go in and add one, but code freeze. i usually just put the data in another file and parse it with lua, and that works fine for any unchanging piece of data. 
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
i dont think those are in. problem is you need to add a function to lua.cpp for every little piece of data you need access to.
Actually it should have looked more like this:
Code: [Select]
xAxis = readProperty (ship, subsystemName, "$RotateX")
yAxis = readProperty (ship, subsystemName, "$RotateY")
zAxis = readProperty (ship, subsystemName, "$RotateZ")


That way you don't need a tons of extra functions to read data, just one function that takes the ship/object, the subsystem to use and the property in quesetion.


Alternatively, I can always do this:
Code: [Select]
DropBearcatLandingGear (shipName)
        DoAnimation (shipName, "FrontLandingGear", 0, 90, 9) -- Front Gear
        DoAnimation (shipName, "PortLandingGear", 90,0,0) -- Port landing gear
        DoAnimation (shipName, "StarLandingGear", -90, 0, 0) -- starboard landing gear
end

RaiseBearcatLandingGear (shipName)
        DoAnimation (shipName, "FrontLandingGear", 0,- 90, 0) -- Front Gear
        DoAnimation (shipName, "PortLandingGear", -90,0,0) -- Port landing gear
        DoAnimation (shipName, "StarLandingGear", 90, 0, 0) -- starboard landing gear
end
Have one for each ship type that needs animation.
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Ya! This is working great... actually I kinda like having the rotation info in the script file over the pof file, far easier to fix and update.

Ok now how would I go about making it actual rotate to the destination angle rather than just snap?
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
use getInterpolated(). you need to call it like this

orientA:getInterpolated(orientB, v)

where orientA is your base orientation, and orientB is your destination orient. v is a value between 0 and 1. if the value is 0 you get orientA, and if its 1 you get orientB, or any intermediate orientation if its in the middle somewhere. in your case you need to figure out how long the animation will run, say 5 seconds. set a timestamp, and then while its good compute the current time and map it to the range of 0 to 1.

init code, call once when you want to start an animation
Code: [Select]
--create start and end orientations
orientA = ba.createOrientation(0,0,0)
orientB = ba.createOrientation(math.rad(90),0,0)
--how long the animation will run
animTime = 5
--setup timing info
startTime = mn.getMissionTime()
timeStamp = starttime + animTime

then call this every frame, this will animate the submodel up till the point that the timestamp expires, and wont work anymore (you can always re-run the init if you want to run another animation).
Code: [Select]
--animate while we still have time left
if mn.getMissionTime() < timestamp then
  local animT = (mn.getMissionTime() - startTime) / animTime
  local orientNew = orientA:getInterpolated(orientB, animT)
  --apply to subystem now (note that subsystem needs to be a valid subsystem handle)
  subsystem.Orientation = orientNew
end

there are probibly neater ways to do this though. but thats the basicly how timing is done.  if you want to start the animation some times later, use another timestamp, wait for it to expire, then init the animation and run the on frame code. if you want to animate backwars, swap orientA and orientB. you also arent limited to time based animation, you can say link things like control surfaces to angular velocity or control input and the like and make those animate based on user input. you are also not limited to simple 90 degree on one axis rotations. you can rotate on multiple axes with this method as well.
« Last Edit: December 05, 2012, 09:07:42 am by Nuke »
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Perfect, but there's one question, multiple instances.  For example someone starts the animation sequence for a ship then starts it for another one.  What do you think would be the best solution for that?  I was thinking of an array of structs { sourceAngle, destAngle, ship } I assume the $On Game Init function (which the sexp calls) handles adding entries to the list while the $On Frame handles the actual processing the animation and removal of finished animations.
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: Questions about triggered animation
in that case make it both of these code snippets functions. i didnt do that because i just wanted to show how timing works. instead of using globals as i had done, stick all the parameters into a table, and return it from the function. this can be passed to the frame function. you can also include in the table the subsystem handle so you dont have to look it up later.
Code: [Select]
--takes subystem handle, orientation a, oritentation b, and animation length, returns a table or nil on failure
function initAnimation(subSys, oriA, oriB, animT)
--make sure handle is valid
if not subSys:isValid() then
return nil
end
--create a table
local t = {}
--subsystem handle
t.subsys = subSys
--create start and end orientations
t.orientA = oriA
t.orientB = oriB
--how long the animation will run
t.animTime = animT
--setup timing info
t.startTime = mn.getMissionTime()
t.timeStamp = t.startTime + t.animTime
return t --now contains everything we need to know for our animation
end
--now we just call it with the table, returns true when an animation frame is done, false when the the animation fails or is over
function doAnimation(t)
--first make sure the subsystem is still around (it could have been destroyed since the animation started
if not t.subsys:isValid() then
return false
end
--animate while we still have time left
if mn.getMissionTime() < t.timeStamp then
  local animT = (mn.getMissionTime() - t.startTime) / t.animTime
  local orientNew = t.orientA:getInterpolated(t.orientB, animT)
  --apply to subystem now (note that subsystem needs to be a valid subsystem handle)
  t.subsys.Orientation = orientNew
else --timestamp expired
return false
end
return true
end

you just stick that code in $OnGameInit: and you can call it from any other hook (in theory). now there is another problem, and that is keeping track of all the animation tables when you have a dozen animating subsystems running all at the same time. this is lua so we can just stick em all into another table then just iterate over it every frame so that all animations can be processed.

Code: [Select]
--all animations go here
animationList = {}
--same arguments as initAnimation, it just uses a global table instead
function addAnimation(sub, oa, ob, at)
--create an animation
local t = initAnimation(sub, oa, ob, at)
--t may be nil
if t then
--add it to the animation list
table.insert(animationList, t)
end
end
--no arguments, no return, just call once every frame
function runAnimations()
for i=1, #animationList do
local b = doAnimation(animationList[i])
--remove items from the list when they fail or are completed
if not b then
table.remove(animationList, i)
end
end
end

that can go in $onGameInit as well. then you can call addAnimation() at any time during a mission to create an animation for a subsystem. then call runAnimations() once every frame. these functions automatically maintain the animationList table. yo may need to re-init the animationList table in $OnMissionStart: (animationList  = {}).
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 
Re: Questions about triggered animation
Success!  It's not quite what you coded and it may not be the prettiest, but it does the job.  Give it the destination angle and the time to do it and it'll do the animation  :yes:

I need to fix a few things before I'll release it.  Also I'm looking for the best way to include a "#include<>" so people wouldn't have to modify the table that much.


Also I just had a brilliant idea, capture the ships change in x/y/z axis and I can develop a thrust vectoring subsystems!
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"

 
Re: Questions about triggered animation
Do you know where the default locations that lua looks for files [using the require ()]

I'm getting this list
Code: [Select]
LUA ERROR: [string "animation-sct.tbm - On Game Init"]:77: module '.\scripts\Bearcat.lua' not found:
no field package.preload['.\scripts\Bearcat.lua']
no file '.\\\scripts\Bearcat\lua.lua'
no file 'D:\Wing Commander Saga\lua\\\scripts\Bearcat\lua.lua'
no file 'D:\Wing Commander Saga\lua\\\scripts\Bearcat\lua\init.lua'
no file 'D:\Wing Commander Saga\\\scripts\Bearcat\lua.lua'
no file 'D:\Wing Commander Saga\\\scripts\Bearcat\lua\init.lua'
no file '.\\\scripts\Bearcat\lua.dll'
no file 'D:\Wing Commander Saga\\\scripts\Bearcat\lua.dll'
no file 'D:\Wing Commander Saga\loadall.dll'
no file '.\.dll'
no file 'D:\Wing Commander Saga\.dll'
no file 'D:\Wing Commander Saga\loadall.dll'


Also I assume you can't have code spread out on two seperate table files, global variables and stuff won't be seen I'm guessing.

Edit: shot... spoke to soon.. major problem.
Rotations you give are done to the world axis, not the subobjects local axis.  There should be a way of converting one to another (at least one i can wrap my brain around)
« Last Edit: December 06, 2012, 10:55:29 pm by Scooby_Doo »
That's cool and ....disturbing at the same time o_o  - Vasudan Admiral

"Don't play games with me. You just killed someone I like, that is not a safe place to stand. I'm the Doctor. And you're in the biggest library in the universe. Look me up."

"Quick everyone out of the universe now!"