Heres what I have right now. My current problem lies in ProcessContinuousAnimation, the deltaOrientation.p
#Conditional Hooks
$Application: FS2_Open
$On Game Init:
[
--shipAnimationList:
-- Ship - the ship data
-- ShipPreviousOrientation - orientation of the ship during the last frame (used to get the delta angle)
-- PreviousDelta
-- DeltaSignage
-- SubsystemList
-- Name - name of subsystem
-- Offset - offset orientation
-- CurrentOrientation - current orientation of subsystem
-- Active - if subsystem is currently being rotated
-- Type - type of animation, see below:
-- OpenTime - Time for animation to preform for opening landing gear and missile bays
-- CloseTime - Time for animation to preform for closing landing gear and missile bays
-- Closed - Closed position for landing gear and missile bays
-- Opened - Open position for landing gear and missile bays
-- VectorFactor - Vector direction for thrust vectoring
-- MinPosition - Minimum position for thrust vectoring
-- MaxPosition - Max position for thrust vectoring
-- Animation Types:
-- 0 - Landing gears
-- 1 - Missile Bays
-- 2 - Sweeping motion
-- 3 - Thrust Vectoring
-- 4 - Thrust Nozzles
LANDING_GEAR = 0
MISSILE_BAY = 1
SWEEPING = 2
THRUST_VECTOR = 3
THRUST_NOZZLE = 4
--animationQueue:
-- ship - Actual ship
-- subsystem - Actual subsystem
-- destOrientation - Destination orientation
-- runtime - Time to do the rotation
-- originalOrientation - Original orientation of subsystem before rotation begins
-- startTime - When the rotation started
-- endTime - When the rotation will end
--Variable Prefixes:
-- g_ = global
-- p_ = private (don't touch unless absolutely necessary!) Also should only be "p_" when
-- using public functions
--Variable PostFixes:
-- List = list/array
-- Data = Physical data (passed to via game engine)
-- Record = Table record (lua table)
g_b = 666
g_h = 666
g_p = 666
g_time = 0
g_percent = 666
g_deltaH = 666
g_deltaB = 666
g_lenp = 0
g_lenb = 0
g_lenh = 0
g_orientNow = {}
g_pp = 0
debugtest = 0
g_test1 = 0
g_test2 = 0
g_prep = false
g_doOnce = false
g_lastFrameTime = 0
animationQueue = {}
shipAnimationList = {}
-----------------------------------------------------------------------------------------------
-- Your ship registeration function goes here aka pure virtual functions
-----------------------------------------------------------------------------------------------
-- Just call one of the Register subsystem functions with p_subsystemList, name of the subsystem
-- and it's necessary info
-- Params:
-- p_subsystemList - List of all subsystems on that ship,
-- do not modify just forward to RegisterSystems
-----------------------------------------------------------------------------------------------
function RegisterBearcat (p_subsystemList)
--RegisterLandingGearSubsystem (p_subsystemList, "MissileBayPortDoor01", CreateOrientation (math.rad (8.62),0,0), CreateOrientation (0,0,0), CreateOrientation (0, math.rad (-90), 0), 2, 2)
--RegisterLandingGearSubsystem (p_subsystemList, "MissileBayStarDoor01", CreateOrientation (math.rad (8.62),0,0), CreateOrientation (0,0,0), CreateOrientation (0, math.rad (90), 0), 2, 2)
local Closed = CreateOrientation (0,0,0)
local ZeroOffset = Closed
local OpenPort = CreateOrientation (0, math.rad (-90), 0)
local OpenStar = CreateOrientation (0, math.rad ( 90), 0)
--RegisterLandingGearSubsystem (p_subsystemList, "FrontLandingGear", ZeroOffset, Closed, CreateOrientation (math.rad(-90), 0, 0), 1.5, 1.5 )
--RegisterLandingGearSubsystem (p_subsystemList, "PortMainLandingGear", ZeroOffset, Closed, OpenPort, 1.5, 1.5)
--RegisterLandingGearSubsystem (p_subsystemList, "StarMainLandingGear", ZeroOffset, Closed, OpenStar, 1.5, 1.5)
--RegisterLandingGearSubsystem (p_subsystemList, "PortDoor01", ZeroOffset, Closed, OpenPort, .5, 2.5)
--RegisterLandingGearSubsystem (p_subsystemList, "PortDoor02", ZeroOffset, Closed, OpenPort, .5, 2.5)
--RegisterLandingGearSubsystem (p_subsystemList, "PortDoor03", ZeroOffset, Closed, OpenPort, .5, 4.5)
--RegisterLandingGearSubsystem (p_subsystemList, "StarDoor01", ZeroOffset, Closed, OpenStar, .5, 2.5)
--RegisterLandingGearSubsystem (p_subsystemList, "StarDoor02", ZeroOffset, Closed, OpenStar, .5, 2.5)
--RegisterLandingGearSubsystem (p_subsystemList, "StarDoor03", ZeroOffset, Closed, OpenStar, .5, 4.5)
RegisterThrustVectorGearSubsystem (p_subsystemList, "PortEngine", CreateOrientation (0,0,0), CreateOrientation (-10,0,0), CreateOrientation (math.rad (-90),0,0), CreateOrientation (math.rad (90),0,0))
end
-----------------------------------------------------------------------------------------------
-- Protected Methods, Update as needed (aka override functions)
-----------------------------------------------------------------------------------------------
-- Intializes all of the ship classes rotations
-- Update this function when adding new ship classes
-- Params: shipData - Ship to be initialized
-- Returns: New ship data ready to be added to the list
function InitializeShipRotation (shipData)
local newShipRecord = {}
newShipRecord.Ship = shipData
newShipRecord.SubsystemList = {}
newShipRecord.ShipPreviousOrientation = shipData.Orientation
newShipRecord.PreviousDelta = CreateOrientation (0,0,0)
newShipRecord.DeltaSignage = 1
if (shipData.Class.Name == "F-104D Bearcat") then
RegisterBearcat (newShipRecord.SubsystemList)
end
--*************************************************
-- Add different ship classes as needed here
--*************************************************
-- Any subsystem that wasn't defined gets the simple (0,0,0) world rotation
SetRestAsSimple (newShipRecord.SubsystemList, shipData)
SetInitialOrientation (newShipRecord)
return newShipRecord
end
-----------------------------------------------------------------------------------------------
-- Public functions that should be called by FRED
-----------------------------------------------------------------------------------------------
function OpenLandGear(shipData)
OpenLandingGear (shipData)
end
function CloseLandGear(ship)
CloseLandingGear (ship)
end
-----------------------------------------------------------------------------------------------
-- Functions that should be called (aka public) but not modified (aka final)
-----------------------------------------------------------------------------------------------
-- Registers a subsystem into the ship's subsystem table
-- Params: subsystemList - list of all subsystems for that ship
-- name - Name for new subsystem
-- offsetOrientation - Orientation that subsystem should initialy have
function RegisterSubsystem (subsystemList, name, offsetOrientation)
local newEntryRecord = {}
newEntryRecord.Name = name
newEntryRecord.Offset = offsetOrientation
newEntryRecord.CurrentOrientation = CreateOrientation (0,0,0)
newEntryRecord.Active = false
table.insert (subsystemList, newEntryRecord)
end
-- Registers a subsystem as a landing gear into the ship's subsystem table
-- Params: subsystemList - list of all subsystems for that ship
-- name - Name for new subsystem
-- offsetOrientation - Orientation that subsystem should initialy have
-- closedPosition - Closed position for the landing gear
-- openPosition - Opened position for the landing gear
-- openTime - Time it takes to open
-- closeTime - Time it takes to close
function RegisterLandingGearSubsystem (subsystemList, name, offsetOrientation, closedPosition, openPosition, openTime, closeTime)
local newEntryRecord = {}
newEntryRecord.Name = name
newEntryRecord.Offset = offsetOrientation
newEntryRecord.CurrentOrientation = CreateOrientation (0,0,0)
newEntryRecord.Active = false
newEntryRecord.Type = LANDING_GEAR
newEntryRecord.Closed = closedPosition
newEntryRecord.Open = openPosition
newEntryRecord.OpenTime = openTime
newEntryRecord.CloseTime = closeTime
table.insert (subsystemList, newEntryRecord)
end
-- Registers a subsystem as a thrust vectoring into the ship's subsystem table
-- Params: subsystemList - list of all subsystems for that ship
-- name - Name for new subsystem
-- offsetOrientation - Orientation that subsystem should initialy have
-- closedPosition - Closed position for the landing gear
-- openPosition - Opened position for the landing gear
-- openTime - Time it takes to open
-- closeTime - Time it takes to close
function RegisterThrustVectorGearSubsystem (subsystemList, name, offsetOrientation, shipDeltaFactor, minPosition, maxPosition)
local newEntryRecord = {}
newEntryRecord.Name = name
newEntryRecord.Offset = offsetOrientation
newEntryRecord.CurrentOrientation = CreateOrientation (0,0,0)
newEntryRecord.Active = false
newEntryRecord.Type = THRUST_VECTOR
newEntryRecord.VectorFactor = shipDeltaFactor
newEntryRecord.MinPosition = minPosition
newEntryRecord.MaxPosition = maxPosition
table.insert (subsystemList, newEntryRecord)
end
-- Create the orientation matrix, just to create cleaner code
-- Params: X - X Coordinate
-- Y - Y Coordinate
-- Z - Z Coordinate
-- Returns: Orientation matrix
function CreateOrientation (x, y, z)
return ba.createOrientation (x,y,z)
end
-----------------------------------------------------------------------------------------------
-- Private functions pertaining to the animationShipList table and children
-----------------------------------------------------------------------------------------------
-- Retrieves the ship's subsystem animation list, note this is not the actual subsystems, but
-- rather the animation orientation list
-- Returns: List of subsystem's orientations (look at shipAnimationList for details)
function GetShipSubsystems (shipName)
for loop = 1, #shipAnimationList do
if (shipAnimationList[loop].Ship.Name == shipName) then
return shipAnimationList[loop].SubsystemList
end
end
end
-- Retrieves the subsystem's information about orientation
-- Returns: List of subsystem's orientation information (look at shipAnimationList->SubsystemList for details)
function GetSubsystemData (subsystems, subsystemName)
for loop = 1, #subsystems do
if (subsystems[loop].Name == subsystemName) then
return subsystems[loop]
end
end
end
-- Retrieves the ships's animation/orientation information
-- Returns: Ship's orientation information (look at shipAnimationList->SubsystemList for details)
function GetShipData (shipName)
for loop = 1, #shipAnimationList do
if (shipAnimationList[loop].Ship.Name == shipName) then
return shipAnimationList[loop]
end
end
end
-- Ship no longer exists , remove it from the tables,
-- needs testing
function RemoveLostShips ()
gr.drawString ("ship left", 10, 10)
for loop = 1, #shipAnimationList do
local stillExists = false
local storedShip = shipAnimationList[loop]
for innerLoop = 1, #mn.Ships do
if (storedShip.Ship.Name == mn.Ships[innerLoop].Name) then
stillExists = true
break
end
end
if (stillExists == false) then
table.remove (shipAnimationList, loop)
return
end
end
end
-- Adds any new ships to the animation list
function AddNewShip ()
-- Go through all the ships currently in the mission
for loop = 1, #mn.Ships do
local existingName = mn.Ships[loop].Name
local found = false
if (#shipAnimationList ~= 0) then
-- Now go through all the ships currently in the animation list
for innerLoop = 1, #shipAnimationList do
local recordName = shipAnimationList[innerLoop].Ship.Name
if (existingName == recordName) then
-- This ship already exists in the list, skip it
found = true
break
end
end
end
if (found == false) then
-- Found one that doesn't exist in the orientation list, let's add it
local shipRecord = InitializeShipRotation (mn.Ships[loop])
table.insert (shipAnimationList, shipRecord)
end
end
end
-- Updates the orientation table/list to reflect any changes in the ships in the mission
function UpdateShipList ()
if (#shipAnimationList > #mn.Ships) then
-- Something got destroyed
RemoveLostShips ()
else
-- Something new was added/arrived
AddNewShip ()
end
end
-- When a subsystem has an orientation rotation, we must save the ending orientation for future use
-- Params: subsystemRecord - Current animation info about the subsystem, look at animationQueue for details
function FinishedSubsystemAnimation (subsystemRecord)
local subsystems = GetShipSubsystems (subsystemRecord.shipData.Name)
local subsystemData = GetSubsystemData (subsystems, subsystemRecord.subsystem.Name)
subsystemData.CurrentOrientation = subsystemRecord.destOrientation
subsystemData.Active = false
end
-- When a subsystem's offset orientation isn't registered, use (0,0,0) as a default value
function SetRestAsSimple (subsystemList, shipData)
for loop = 1, #shipData do
local subsystem = shipData[loop]
local found = false
-- Run through all the ships subsystems
for innerloop = 1, #subsystemList do
local recordedSubsystem = subsystemList[innerloop]
if (recordedSubsystem.Name == subsystem.Name) then
-- Found one that wasn't registered
found = true
break
end
end
if (found == false) then
RegisterSubsystem (subsystemList, subsystem.Name, CreateOrientation (0,0,0))
end
end
end
-- Sets the subsystems initial orientation, based on was it was registered with
-- Params: shipRecord - ship to have it's subsystems initialized
function SetInitialOrientation (shipRecord)
for loop = 1, #shipRecord.SubsystemList do
local offset = shipRecord.SubsystemList[loop].Offset
local subsystemName = shipRecord.SubsystemList[loop].Name
shipRecord.Ship[subsystemName].Orientation = offset
shipRecord.SubsystemList[loop].CurrentOrientation = offset
end
end
-- Open the landing gear(s)
-- Params: shipName - name of ship
function OpenLandingGear (shipName)
local shipSubsystemList = GetShipSubsystems (shipName)
for loop = 1, #shipSubsystemList do
local currentSubsystem = shipSubsystemList[loop]
if (currentSubsystem.Type == LANDING_GEAR) then
AddAnimationToQueue (mn.Ships[shipName],
currentSubsystem.Name,
currentSubsystem.Open,
currentSubsystem.OpenTime)
end
end
end
-- Close the landing gear(s)
-- Params: shipName - name of ship
function CloseLandingGear (shipName)
local shipSubsystemList = GetShipSubsystems (shipName)
for loop = 1, #shipSubsystemList do
local currentSubsystem = shipSubsystemList[loop]
if (currentSubsystem.Type == LANDING_GEAR) then
AddAnimationToQueue (mn.Ships[shipName],
currentSubsystem.Name,
currentSubsystem.Closed,
currentSubsystem.CloseTime)
end
end
end
-- Creates a new animation entry and adds it to the animation queue
-- Params: shipName - Name of ship in the mission
-- subsystemName - Name of subsystem found on shipName that needs to be rotated
-- originalOrientation - Orientation the object starts in (if opening a bay door, usually is (0,0,0))
-- destOrientation - Orientation of the subsystem once the animation is finished
-- rotationTime - Total time for the animation
function StartAnimation(shipName, subsystemName, originalOrientation, destOrientation, rotationTime)
AddAnimationToQueue (mn.Ships[shipName], subsystemName, originalOrientation, destOrientation, rotationTime)
end
-- Adds an animation to the animation queue
-- Params: shipData - ship that has the subsystem to animation
-- subsystemName - Subsystem that needs to be rotated
-- originalOrientation - Orientation the object starts in (if opening a bay door, usually is (0,0,0))
-- destOrientation - Orientation of the subsystem once the animation is finished
-- timeForAnimation - Total time for the animation
function AddAnimationToQueue (shipData, subsystemName, destOrientation, timeForAnimation)
local subsystems = GetShipSubsystems (shipData.Name)
local subsystem = GetSubsystemData (subsystems, subsystemName)
subsystem.Active = true
-- Grab the subsystem's current orientation
local subsystemOffset = CreateOrientation (0,0,0)
local subsystemCurrentOrientation = CreateOrientation (0,0,0)
subsystemOffset = subsystem.Offset
subsystemCurrentOrientation = subsystem.CurrentOrientation
local updatedestOrientation = CreateOrientation (0,0,0)
updatedestOrientation.p = destOrientation.p + subsystemOffset.p
updatedestOrientation.h = destOrientation.h + subsystemOffset.h
updatedestOrientation.b = destOrientation.b + subsystemOffset.b
local newShipRecord = {}
newShipRecord.shipData = shipData
newShipRecord.subsystem = shipData[subsystemName]
newShipRecord.destOrientation = updatedestOrientation
newShipRecord.runtime = timeForAnimation
newShipRecord.originalOrientation = subsystemCurrentOrientation
newShipRecord.startTime = mn.getMissionTime ()
newShipRecord.endTime = mn.getMissionTime () + timeForAnimation
table.insert (animationQueue, newShipRecord)
end
-- Process one piece of the animation
-- Params: animation - animation Step to process
function ProcessAnimation (animation)
local currentTime = (mn.getMissionTime () - animation.startTime) / animation.runtime
local test1 = animation.originalOrientation:getInterpolated (animation.destOrientation, currentTime)
animation.subsystem.Orientation = test1
end
function ProcessContinuousAnimationForShips ()
for loop = 1, #mn.Ships do
ProcessContinuousAnimation (mn.Ships[loop])
end
end
function Sign (x)
if (x < 0) then
return -1
else
return 1
end
end
g_laptime = 0
function ProcessContinuousAnimation (shipData)
local subsystemList = GetShipSubsystems (shipData.Name)
local animationShipData = GetShipData (shipData.Name)
for loop = 1, #subsystemList do
local subsystem = subsystemList[loop]
if (subsystem.Type == THRUST_VECTOR) then
if (mn.getMissionTime () > g_laptime + 1) then
local vectorFactor = subsystem.VectorFactor
local newOrientation = shipData.Orientation
local deltaOrientation = CreateOrientation (0,0,0)
local previousOrientation = animationShipData.ShipPreviousOrientation
local previousDelta = animationShipData.PreviousDelta
deltaOrientation.p = (newOrientation.p - previousOrientation.p)
if (Sign (deltaOrientation.p) ~= Sign (previousDelta.p)) then
debugtest = "sign change"
local temp = math.abs (deltaOrientation.p) - math.abs (previousDelta.p)
temp = math.abs (temp)
if (temp > math.rad (5)) then
debugtest = "sign changed, very big"
else
debugtest = "signed changed, small"
end
else
debugtest = ""
end
deltaOrientation.b = (newOrientation.b - previousOrientation.b)
deltaOrientation.h = (newOrientation.h - previousOrientation.h)
deltaOrientation.p = deltaOrientation.p * vectorFactor.p
deltaOrientation.b = deltaOrientation.b * vectorFactor.b
deltaOrientation.h = deltaOrientation.h * vectorFactor.h
AddAnimationToQueue (shipData, subsystem.Name, deltaOrientation, 1)
g_deltaP = math.deg(animationShipData.PreviousDelta.p)
g_deltaH = math.deg(deltaOrientation.p)
g_p = math.deg(previousOrientation.p)
g_h = math.deg(newOrientation.p)
animationShipData.PreviousDelta = deltaOrientation
g_laptime = mn.getMissionTime () + .1
end
end
end
animationShipData.ShipPreviousOrientation = shipData.Orientation
end
-----------------------------------------------------------------------------------------------
-- General purpose private functions
-----------------------------------------------------------------------------------------------
-- Nuke's Matrix Creation tool
function arbitraryAxisMatrix(w,x,y,z)
local cosi = math.cos(w)
local sine = math.sin(w)
local tang = 1 - cosi
local aarot = ba.createOrientation( tang * x^2 + cosi, tang * x * y + sine * z, tang * x * z - sine * y,
tang * x * y - sine * z, tang * y^2 + cosi, tang * y * z + sine * x,
tang * x * z + sine * y, tang * y * z - sine * x, tang * z^2 + cosi )
return aarot
end
function DebugSpew ()
gr.drawString ("p", 950, 10)
gr.drawString (g_p, 1000, 10)
gr.drawString ("h", 950, 50)
gr.drawString (g_h, 1000, 50)
gr.drawString ("b", 950, 100)
gr.drawString (g_b, 1000, 100)
--gr.drawString (g_time, 1000, 150)
gr.drawString ("deltaP", 1200, 10)
gr.drawString ((g_deltaP), 1250, 10)
gr.drawString ("deltah", 1200, 50)
gr.drawString ((g_deltaH), 1250, 50)
gr.drawString ("deltab", 1200, 100)
gr.drawString ((g_deltaB), 1250, 100)
gr.drawString ("len p", 1400, 10)
gr.drawString (g_lenP, 1450, 10)
gr.drawString ("len h", 1400, 50)
gr.drawString (g_lenH, 1450, 50)
gr.drawString ("len b", 1400, 100)
gr.drawString (g_lenB, 1450, 100)
gr.drawString ("orient.p", 1600, 10)
gr.drawString (g_pp, 1650, 10)
--gr.drawString ("orient.h", 1600, 50)
--gr.drawString (g_orientNow.h, 1650, 50)
--gr.drawString ("orient.b", 1600, 100)
--gr.drawString (g_orientNow.b, 1650, 100)
gr.drawString (debugtest, 100, 100)
end
]
$State: GS_STATE_GAME_PLAY
$On Frame:
[
DebugSpew ()
if (#shipAnimationList ~= #mn.Ships) then
UpdateShipList ()
end
if (doOnce == false) then
doOnce = true
g_lastFrameTime = mn.getMissionTime ()
end
ProcessContinuousAnimationForShips ()
-- Make sure animationQueue exists and isn't empty (no sense in processing nothing)
if (animationQueue == nil) then
return false
end
if (#animationQueue == 0) then
return
end
for loop = 1, #animationQueue do
local anim = animationQueue [loop]
-- Make sure the subsystem still exists
if not (anim.subsystem:isValid ()) then
table.remove (animationQueue, loop)
break
end
if (mn.getMissionTime () < anim.endTime) then
ProcessAnimation (anim)
end
if (mn.getMissionTime () > anim.endTime) then
-- Animation must be done by now.. deleting it
FinishedSubsystemAnimation (anim)
table.remove (animationQueue, loop)
break
end
end
g_lastFrameTime = mn.getMissionTime ()
]
#End