-- LUA Script - precede every function and global member with lowercase name of script + '_main' -- Default script - does nothing. local bubbles = {} local bubbleNames = {} local SB_Database = {} local deg = math.deg local sin = math.sin local cos = math.cos local atan = math.atan2 function SpeechBubbleRegister(e, speeches) SB_Database[e] = speeches end local function Rotate3D (x, y, z, xrot, yrot, zrot) function RotatePoint2D (x, y, Ang) -- Ang in radians local Sa, Ca = sin(Ang), cos(Ang) return x*Ca - y*Sa, x*Sa + y*Ca end local NX, NY, NZ = x, y, z -- X NZ, NY = RotatePoint2D (NZ, NY, -xrot) -- Y NX, NZ = RotatePoint2D (NX, NZ, -yrot) -- Z NY, NX = RotatePoint2D (NY, NX, -zrot) return NX, NY, NZ end local function ShowBubble(name, character, speech, bxo, byo, tyo, px, pz) local bubble = bubbles[name] if bubble then local charEnt = g_Entity[character] local x, y, z = charEnt.x, charEnt.y, charEnt.z --PromptLocal(bubble.Ent, bubble.speech or 'nil') CollisionOff(bubble.Ent) -- rotate to face player local dx, dz = x - px, z - pz local ang = atan(dx, dz) ResetRotation(bubble.Ent, 0, deg(ang), 0) CollisionOff(bubble.Ent) -- position bubble wrt character -- first work out horizontal offset local xo, yo, zo = Rotate3D(bxo, 0, 0, 0, ang, 0) ResetPosition(bubble.Ent, x + xo, y + byo, z + zo) if not bubble.showing then Show(bubble.Ent) bubble.showing = true end if ShowSpeech ~= nil then ShowSpeech(speech, x + xo, y + byo + tyo, z + zo, px, pz, ang) bubble.speech = speech end bubble.hideNextFrame = false end end local function HideBubble(name) local bubble = bubbles[name] if bubble.showing then Hide(bubble.Ent) bubble.showing = false bubble.hideNextFrame = false if HideSpeech ~= nil then HideSpeech(bubble.speech) end end end function SpeechBubbleShow(e, num) local speechBubble = SB_Database[e] if speechBubble ~= nil and speechBubble[num] ~= nil then local sB = speechBubble[num] ShowBubble(sB[1], e, sB[2], sB[3], sB[4], sB[5], g_PlayerPosX, g_PlayerPosZ) end end function bubbles_init_name(e, name) bubbleNames[e] = name if bubbles[name] == nil then bubbles[name] = {Ent = e, showing = false, speech = nil, hideNextFrame = false} Hide(e) end end function bubbles_main(e) local bubble = bubbles[bubbleNames[e]] if bubble.Ent ~= e then PromptLocal(e, "Duplicate Bubble") return end if bubble.showing and not bubble.hideNextFrame then bubble.hideNextFrame = true return end if bubble.hideNextFrame then HideBubble(bubbleNames[e]) end end