Quote: "Probably much better to use quaternions from the outset then you avoid strange behaviour later on."
ok so i got close but it's not quite working... can't figure out what i'm doing wrong, only appears to show the light in certain directions and i would expect only the Y euler value to change but it changes all 3... (i know the euler aren't wrapped at the end but it's only for prompt purposes, they're not actually used - only the quat values are
local U = require "scriptbank\\utillib"
local Q = require "scriptbank\\quatlib"
local lightNum = {}
local attachTo = {}
local offx,offy,offz,offax,offay,offaz = {},{},{},{},{},{}
attachLightToMe = {}
local rad = math.rad
local mode = {}
local offq = {}
function light_npc_init_name(e,name)
lightNum[e] = GetEntityLightNumber(e)--change 2 to the entity number of the light
--change 'nil' to the entity number of the npc
--or place the light next to entity for automatic assignment
--*make sure entity has 'attachLightToMe[e] = e' in the script*
attachTo[e] = nil
mode[e] = name
end
function light_npc_main(e)
if attachTo[e] == nil then
local x1,y1,z1 = GetLightPosition(lightNum[e])
local dist1 = 999999
for a,_ in pairs (attachLightToMe) do
local x2,y2,z2 = GetEntityPosAng(a)
local dist2 = sqrd(x1,z1,x2,z2)
if dist2 < dist1 then
attachTo[e] = a
dist1 = dist2
end
end
if attachTo[e] == nil then
attachTo[e] = -1
return
end
--get the entity pos & angles values we are attaching too
local x, y, z, Ax, Ay, Az = GetEntityPosAng(attachTo[e])
--get our own (light) values
local lx,ly,lz = GetLightPosition(lightNum[e])
local lax,lay,laz = GetEntityAngleX(e),GetEntityAngleY(e),GetEntityAngleZ(e)
--work out the offsets (done once at map start)
offx[e] = lx-x
offy[e] = ly-y
offz[e] = lz-z
--workout and store the angle offset as vector for later
local xA, yA, zA = rad( Ax ), rad( Ay ), rad( Az )
lax,lay,laz = rad(lax), rad(lay), rad(laz)
local q1 = Q.FromEuler(xA,yA,zA)
local q2 = Q.FromEuler(lax,lay,laz)
offq[e] = Q.Sub(q1,q2)
--q2 = Q.Normalise(q2)
else
--this part is run during the update
if attachTo[e] == -1 then
return
end
--get the new values for our attached entity
local x, y, z, Ax, Ay, Az = GetEntityPosAng(attachTo[e])
--place the light based on the new position + our offset
--place the light based on the new position + our offset
local xA, yA, zA = rad( Ax ), rad( Ay ), rad( Az )
local xo, yo, zo = U.Rotate3D( offx[e], offy[e], offz[e], xA, yA, zA )
SetLightPosition ( lightNum[e], x + xo, y + yo, z + zo )
--work out the angle of the entity + our angle offset
local q1 = Q.FromEuler(xA, yA, zA)
--q1 = Q.Normalise(q1)
local q3 = Q.Add(q1,offq[e])
--q3 = Q.Normalise(q3)
local fax, fay, faz = Q.ToEuler(q3)
--fax, fay, faz = rad(fax), rad(fay), rad(faz)
local xv, yv, zv = U.Rotate3D( 0, 0, 1, fax, fay, faz)
SetLightAngle( lightNum[e], xv, yv, zv )
--just to move the prompt
--SetPosition(e, GetLightPosition(lightNum[e]))
--ResetPosition(e, GetLightPosition(lightNum[e]))
--shows the light's angle vectors
TextCenterOnX(50,80,3,"quat3 = "..round(q3.x,2).." "..round(q3.y,2).." "..round(q3.z,2).." "..round(q3.w,2))
--or show the light angle values
TextCenterOnX(50,85,3,"final light angles = "..round(xv,2).." "..round(yv,2).." "..round(zv,2))
--or show the euler values
local deg = math.deg
fax,fay,faz = deg(fax),deg(fay),deg(faz)
TextCenterOnX(50,90,3,"euler X = "..round(fax,2).." , Y = "..round(fay,2).." , Z = "..round(faz,2))
end
end
function sqrd( x1, z1, x2, z2 )
local dx, dz = x1 - x2, z1 - z2
return dx*dx+dz*dz
end
function Q.Sub (q1, q2)
return { w = q1.w - q2.w, x = q1.x - q2.x, y = q1.y - q2.y, z = q1.z - q2.z }
end