-------------------------------------------------------------- -- L_NT_ASSEMBLYTUBE_SERVER.lua -- Handles processing of Assembly Teleporter events -- including player teleports and mission updatess -- updated abeechler ... 3/7/11 - refactored scripts and simplified functionality -- updated abeechler ... 4/14/11 - removed flag setting for scripted mission updates -- updated mrb... 5/5/11 - added interact sound option -- updated abeechler ... 5/17/11 - fixed teleport locking bug for logging out players -- updated abeechler ... 10/5/11 - fixed teleport ignore bug for character switch players -------------------------------------------------------------- -- -- add configData on the object in HF to play audio on interact -- sound1 -> 0:{GUID} -- -------------------------------------------------------------- local defaultTransportSendAnim = "tube-sucker" -- Transport send animation local transportReceiveAnim = "tube-resurrect" -- Transport receive animation local missionsToUpdate = {1047, 1330, 1331, 1332} -- MissionID's to update when the tube is used ---------------------------------------------- -- Process start-up events ---------------------------------------------- function onStartup(self,msg) -- Subscribe to a zone control object notification alerting the script -- when a local player is loaded self:SendLuaNotificationRequest{requestTarget = GAMEOBJ:GetZoneControlID(), messageName="PlayerLoaded"} end ---------------------------------------------- -- The zone control object says when the player is loaded ---------------------------------------------- function notifyPlayerLoaded(self, zoneObj, msg) -- Get the player ID local player = msg.playerID local playerID = player:GetID() -- A data structure containing players being teleported local teleportingPlayerTable = self:GetVar("teleportingPlayerTable") or {} -- Is the player a holdover from a previous failed teleport? if(teleportingPlayerTable[playerID] == true) then teleportingPlayerTable[playerID] = nil self:SetVar("teleportingPlayerTable", teleportingPlayerTable) end -- Is the player currently inside the teleport volume? local playersInMe = self:GetObjectsInPhysicsBounds().objects -- Iterate through the players in the volume for i, pRef in ipairs(playersInMe) do if(playerID == pRef:GetID()) then -- The loaded player is currently inside the teleporter -- run the teleporter runAssemblyTube(self, player) end end end ---------------------------------------------- -- Catch player teleporter collisions and process -- functions when applicable ---------------------------------------------- function onCollisionPhantom(self, msg) local player = msg.senderID runAssemblyTube(self, player) end ---------------------------------------------- -- Initiates assembly tube functionality ---------------------------------------------- function runAssemblyTube(self, player) local playerID = player:GetID() -- A data structure containing players being teleported local teleportingPlayerTable = self:GetVar("teleportingPlayerTable") or {} -- Process the colliding player against the teleporting table to see if they are eligible for teleport local bPlayerBeingTeleported = teleportingPlayerTable[playerID] -- Do we have a valid player? if((player:IsCharacter().isChar) and (not bPlayerBeingTeleported)) then -- Check HF object config data for a cinematic path to play on teleport local teleCinematic = self:GetVar("Cinematic") or false if(teleCinematic) then -- Mark the currently colliding player as -- being teleported teleportingPlayerTable[playerID] = true self:SetVar("teleportingPlayerTable", teleportingPlayerTable) -- Lock player interaction player:SetStunned{StateChangeType = "PUSH", bCantMove = true, bCantTurn = true, bCantAttack = true, bCantUseItem = true, bCantEquip = true, bCantInteract = true} local transportSendAnim = self:GetVar("OverrideAnim") or defaultTransportSendAnim -- Determine the length of the player transport send anim local sendAnimTime = player:GetAnimationTime{animationID = transportSendAnim}.time or 3 -- Play the transmission cinematic player:PlayCinematic{pathName = teleCinematic, lockPlayer = false, bSendServerNotify = true} -- Play the transmission anim player:PlayAnimation{animationID = transportSendAnim, bPlayImmediate = true, fPriority = 4.0} -- play custom audio sound local useSound = self:GetVar("sound1") or false if useSound then -- play the start audio player:PlayNDAudioEmitter{m_NDAudioEventGUID = useSound} end -- Request for notification upon cinematic conclusion for player reception and interaction unlocking self:SendLuaNotificationRequest{requestTarget = player, messageName = "CinematicUpdate"} -- Set a timer for player teleportation GAMEOBJ:GetTimer():AddTimerWithCancel(sendAnimTime, "TeleportPlayer_" .. playerID, self) -- Update the missions for the user for k,missionID in ipairs(missionsToUpdate) do -- Update the task player:UpdateMissionTask{taskType = "complete", value = missionID, value2 = 1, target = self} end else -- Generate warning about missing necessary config data local tubePos = self:GetPosition().pos WarningPrint(self, "WARNING: No Cinematic found for NT Assembly Tube located at: X = " .. tubePos.x .. ", Y = " .. tubePos.y .. ", Z = " .. tubePos.z) end end end ---------------------------------------------- -- Receive cinematic update events to initiate -- teleportation upon transition cinematic conclusion ---------------------------------------------- function notifyCinematicUpdate(self, player, msg) local eventType = msg.event local playerID = player:GetID() -- Our player exists and is ready for transport reception? if(not player:Exists()) then return end -- Process the nature of the update and process -- on cinematic conclusions if(eventType == "ENDED") then -- Teleport the player -- teleportPlayerToDest(self, player) -- Play the player reception anim player:PlayAnimation{animationID = transportReceiveAnim, bPlayImmediate = true, fPriority = 4.0} -- Prepare to unlock the Player ability to interact after we -- pause for the animation local animTime = player:GetAnimationTime{animationID = transportReceiveAnim}.time or 4 GAMEOBJ:GetTimer():AddTimerWithCancel(animTime, "UnlockPlayer_" .. playerID, self) self:SendLuaNotificationCancel{requestTarget = player, messageName = "CinematicUpdate"} end end ---------------------------------------------- -- Determine teleport destination location and rotation -- and orient a target accordingly ---------------------------------------------- function teleportPlayerToDest(self, player) -- Determine where to send the player local destinationGroup = self:GetVar("teleGroup") or false local destination = self if destinationGroup then -- We have a target destination group within the object config data local groupObjs = self:GetObjectsInGroup{group = destinationGroup, ignoreSpawners = true}.objects -- Iterate through the destination group and catch the first valid destination object for k,obj in ipairs(groupObjs) do if obj:Exists() then destination = obj break end end end -- Take the determined destination object and process its -- location/rotation values local destPosition = destination:GetPosition().pos local destRotation = destination:GetRotation() -- Teleport the player player:Teleport {pos = destPosition, x = destRotation.x, y = destRotation.y, z = destRotation.z, w = destRotation.w, bIgnoreY = false, bSetRotation = true} end ---------------------------------------------- -- Process timer events to finalize triggered teleports ---------------------------------------------- function onTimerDone(self, msg) -- Split out the timer local tTimer = split(msg.name, "_") -- Is our player timer for a teleportation event? if tTimer[1] == "TeleportPlayer" then local playerID = tTimer[2] or 0 local player = GAMEOBJ:GetObjectByID(playerID) -- Our player exists and is ready for transport reception? if(not player:Exists()) then return end -- Teleport the player teleportPlayerToDest(self, player) -- Time to unlock the player? elseif tTimer[1] == "UnlockPlayer" then local playerID = tTimer[2] or 0 local player = GAMEOBJ:GetObjectByID(playerID) local teleportingPlayerTable = self:GetVar("teleportingPlayerTable") if(teleportingPlayerTable) then -- Remove the target player from the teleporting table and process teleportingPlayerTable[playerID] = nil self:SetVar("teleportingPlayerTable", teleportingPlayerTable) end -- Our player exists and is ready for interact unlock? if(not player:Exists()) then return end --Return interact control to the player player:SetStunned{StateChangeType = "POP", bCantMove = true, bCantTurn = true, bCantAttack = true, bCantUseItem = true, bCantEquip = true, bCantInteract = true} end end function split(str, pat) local t = {} -- Creates a table of strings based on the passed in pattern string.gsub(str .. pat, "(.-)" .. pat, function(result) table.insert(t, result) end) return t end ---------------------------------------------------------------- -- print custom function to keep prints from showing up externally ---------------------------------------------------------------- function WarningPrint(self, msg) if(self:GetVersioningInfo().bIsInternal) then print(self,msg) end end