---------------------------------------- -- BASE script on the ninjago spinner -- Generic Server Spinner Traps -- -- updated by mrb... 6/16/11 - refactored --------------------------------------------- -- current objIDs: -- Imagination: 16155 or 16154 or 16153 or 16152 or 14385 or 14384 or 14383 or 14382 -- Earth: 16203 or 16213 or 16214 or 16215 or 16216 or 16217 or 16218 or 16219 -- Fire: 16220 or 16221 or 16222 or 16223 or 16224 or 16225 or 16226 or 16227 -- Ice: 16228 or 16229 or 16230 or 16231 or 16232 or 16233 or 16234 or 16235 -- Lightning: 16236 or 16237 or 16238 or 16239 or 16240 or 16241 or 16242 or 16243 --------------------------------------------- -- config data variables for HF; defaults listed. ** if nothing is set the spinner defaults to a toggle elevator spinner ** -- type -> 0:elevator -- other types; blade, arrow -- spin_distance -> 1:3.5 -- setting this will change the distance the player has to be from the object to cast the skill -- damage_radius -> 1:7 -- this changes the radius of the damage proximity -- damage_height -> 1:-4 -- this changes the height of the damage proximity, it's negative cause the pivot point of these objects are at the top of the object -- skill_pulse_time -> 1:1 -- this is how long to wait to pulse a skill -- reset_time -> 1:0 -- this is how long to wait before putting the spinner back to it's initial state, 0 means the spinner toggles on skill cast with no reset time -- once_only -> 7:1 -- if this is set it will move once and lock in place and will never be able to be triggered again -- static -> 7:0 -- if this is set to 1 then the spinner will be locked in it's starting position unless triggered from an event -- element_type -> 0:imagination -- other types; fire, earth, ice, lightning, collision, imagination -- spawner_network -> 0:networkName -- spawner network to activate/deactivate with the spinner. -- noninteract -> 7:0 -- if this is set to 1 it will make the spinner not interactive, interact can be turned on by fire event --- cinematics -- on_cinematic -> 0:spinner1on -- animation to play when the spinner is put into the active state -- off_cinematic -> 0:spinner1off -- animation to play when the spinner is put into the inactive state --- audio -- audioMovementBeginGUID -> 0:{5c30c263-00ae-42a2-80a3-2ae33c8f13fe} -- audio oneshot to play when the spinner starts moving -- audioMovementEndGUID -> 0:{5c30c263-00ae-42a2-80a3-2ae33c8f13fe} -- audio oneshot to play when the spinner stops moving -- audioMovementGUID -> 0:{7f770ade-b84c-46ad-b3ae-bdbace5985d4} -- audio loop to play while the spinner moves -- audioSpinningGUID -> 0:{8dcf670f-9fe9-4f14-b5ba-0a8e0943c2f6} -- audio loop to play while the spinner spins in the active state --- spawners -- NoSpawnerFX -> 7:0 -- set to 7:1 if you do not want the spawner spinner fx to play when activated -- spawnNw1 -> 0:spawnerName -- first spawner network to activate/deactivate -- spawnNw# -> 0:spawnerName# -- consecutive spawner networks to activate/deactivate, should be spawnNw2, spawnNw3, etc... --- fire events -- name_activated_event --> 0:event1 -- event name to fire when the spinner is put into the active state -- group_activated_event --> 0:group1 -- group name to fire the on_event_name to, this has to be set to fire the on event -- name_deactivated_event --> 0:event2 -- event name to fire when the spinner is put into the inactive state -- group_deactivated_event --> 0:group1 -- group name to fire the off_event_name to, this has to be set to fire the off event --- types of events: this is set on the object configData in HF for the receiving the event. ---- -- FORMAT: this is for the name_activated_event sent to the group_activated_event from above -- event1 --> 0:activate ---- -- activate -- use this variable name to put the spinner into the active state -- deactivate -- use this variable name to put the spinner into the inactive state -- toggle_active -- use this variable name to put the spinner into it's other active state -- interact -- use this variable name to put the spinner into the interactive state -- noninteract -- use this variable name to put the spinner into the noninactive state -- toggle_interact -- use this variable name to put the spinner into it's other interactive state --------------------------------------------- -- green switch: 16195 -- red switch: 16196 --------------------------------------------- -- default variables incase there is no HF configdata; defaults listed local defaultSpinDistance = 3.5 -- config data variable = spin_distance -> 1:3.5 local defaultDamageRadius = 8 -- config data variable = damage_radius -> 1:10 local defaultDamageHeight = -4 -- config data variable = damage_height -> 1:-4 local defaultDamageVertOffset = -2 -- config data variable = damage_offset -> 1:-2 local defaultPulseTime = 1 -- config data variable = skill_pulse_time -> 1:1 local defaultResetTime = 0 -- config data variable = reset_time -> 1:1 local defaultSpawnFXType = "spawner_activate" -- animations on use for player local startAnim = "spinjitzu-staff-windup" local runAnim = "spinjitzu-staff-loop" local endAnim = "spinjitzu-staff-end" local downAnimModifier = "-down" -- spinner animation names local upAnim = "up" local downAnim = "down" local idleDownAnim = "idle" local idleUpAnim = "idle-up" -- audio GUIDs local audioMovementBeginGUID = "{5c30c263-00ae-42a2-80a3-2ae33c8f13fe}" local audioMovementEndGUID = "{40e86d71-084c-4149-884e-ab9b45b694dc}" local audioMovementGUID = "{b91d2f01-1998-4ca3-bb5c-c25cf36c7a24}" local audioSpinningGUID = "{8dcf670f-9fe9-4f14-b5ba-0a8e0943c2f6}" --------------------------------------------- -- type skills local skills = { blade = 971, arrow = 972, } --------------------------------------------- -- element settings --TODO: make sure the staff lots are correct local elements = --fire, earth, ice, lightning, collision, imagination { imagination = {capFX = "spinner_interaction", precondition = 143, staffLOT = 11195}, --default fire = {capFX = "spinner_interaction", precondition = 144, staffLOT = 12656}, earth = {capFX = "spinner_interaction", precondition = 145, staffLOT = 12657}, ice = {capFX = "spinner_interaction", precondition = 146, staffLOT = 12658}, lightning = {capFX = "spinner_interaction", precondition = 147, staffLOT = 12659}, collision = {capFX = "green-switch", precondition = 143, staffLOT = 11195}, collision_off = {capFX = "red-switch", precondition = 143, staffLOT = 11195}, } local damageStartDelay = 1.0 -- how long to wait after the spinner reaches the active position to start the damage proximity --------------------------------------------- -- print function that only works in an internal build function debugPrint(self, text) if self:GetVersioningInfo().bIsInternal then print(text) end end function onStartup(self, msg) spinStartup(self, msg) end function spinStartup(self, msg) -- get the path attached to this object local pathName = self:GetVar("attached_path") -- if we dont have a path print a message to the log if (not pathName) and (not self:GetVar("platformIsSimpleMover")) then local pos = self:GetPosition().pos debugPrint(self, self:GetName().name .. " located at x:" .. pos.x .. " y:" .. pos.y .. " z:" .. pos.z .. " is missing an attached_path") return end -- get the spin_distance from the config data or use the default local spinDist = self:GetVar("spin_distance") or defaultSpinDistance -- set up the prox radius for where the player needs to be to use the skill self:SetProximityRadius{radius = spinDist, shapeType = "CYLINDER", height = 5, name = "spin_distance"} -- stop the mover self:StopPathing() -- get the initial start node for the path local startNode = self:GetVar("attached_path_start") self:SetVar("stoppedNode", startNode) if self:GetVar("element_type") ~= "collision" and not self:GetVar("static") and not self:GetVar("noninteract") then self:SetNetworkVar("bInteractive", true) setCapFX(self, true) elseif not self:GetNetworkVar("bInteractive") or self:GetVar("noninteract") then self:SetNetworkVar("bInteractive", false) setCapFX(self, false) end self:SetNetworkVar("element_precondition_ID", getElementData(self).precondition) if self:GetVar("spawnNw1") then local tSpawners = {} local count = 1 while self:GetVar("spawnNw"..count) do table.insert(tSpawners, self:GetVar("spawnNw"..count)) count = count + 1 end self:SetVar("tSpawners", tSpawners) end -- based on the start node set if it's active or not, set the spinNode (where it moves to when the skill is cast) if startNode == 1 then -- activate spinner toggleActive(self) -- play the up idle anim self:SetNetworkVar("current_anim", idleUpAnim) -- start the damage proximity toggleDamageProx(self, true) -- check for spawner network toggleSpawnerNetwork(self, true) self:SetVar("movingUp", false) else self:SetVar("movingUp", true) end end function getElementData(self) local elementType = self:GetVar("element_type") or false if elementType then if elements[elementType] then return elements[elementType] end end return elements.imagination end function setCapFX(self, bTurnOn) if self:GetVar("static") then return end local cap = getElementData(self) if bTurnOn then self:PlayFXEffect{name = "element_" .. cap.capFX, effectType = cap.capFX} self:SetVar("bCapShown", true) else self:StopFXEffect{name = "element_" .. cap.capFX} self:SetVar("bCapShown", false) end end function playAnim(self, player, animName) -- see if this object has an animation on it by getting the time local animTime = player:GetAnimationTime{animationID = animName}.time if not animTime then return end -- if the time isn't more than 0 we dont want to do anything if animTime > 0 then local tempAnimName = animName if not self:GetVar("movingUp") then tempAnimName = animName .. downAnimModifier end -- play the interact animation player:PlayAnimation{ animationID = tempAnimName, fPriority = 2.0} -- start up the anim done timer self:ActivityTimerSet{name = "AnimDone_" .. animName, duration = animTime} end end function onCheckUseRequirements(self, msg) spinCheckUseRequirements(self, msg) end function spinCheckUseRequirements(self, msg) if self:GetNetworkVar('bIsInUse') then msg.bCanUse = false return msg end local preConVar = self:GetVar("CheckPrecondition") if preConVar and preConVar ~= "" then local check = msg.objIDUser:CheckListOfPreconditionsFromLua{PreconditionsToCheck = preConVar, requestingID = self} if not check.bPass then msg.bCanUse = false return msg end end local preconID = getElementData(self).precondition if preconID ~= -1 then local check = msg.objIDUser:CheckPrecondition{PreconditionID = preconID} if not check.bPass then msg.bCanUse = false end end return msg end function onUse(self, msg) spinUse(self, msg) end function spinUse(self, msg) if not self:GetVar("bCapShown") or self:GetNetworkVar("bIsInUse") then return end self:SetNetworkVar("bFreezePlayer_" .. msg.user:GetID(), true) self:SetNetworkVar("bIsInUse", true) -- start playing the effects for the staff interaction msg.user:PlayFXEffect{name = "tornado", effectType = "on-anim", effectID = 5499} msg.user:PlayFXEffect{name = "staff", effectType = "on-anim", effectID = 5502} self:SetVar("userID", msg.user:GetID()) playAnim(self, msg.user, startAnim) end -- custom function that toggles the active state of the spinner based on it's current state function setActiveState(self, bActive, bPlayerTriggered) self:SetVar("bActive", bActive) --debugPrint(self, '2 ' .. tostring(bActive)) if bPlayerTriggered then playCinematic(self, bActive) end if bActive then -- what is the type of the spinner, default = elevator local type = self:GetVar("type") -- if arrow then start pulsing skill if type == "arrow" then local pulseTime = self:GetVar("skill_pulse_time") or defaultPulseTime -- start activity timer with update time and no duration to pulse the skill self:ActivityTimerSet{name = "Pulse_Skill", updateInterval = pulseTime} end self:SetVar("movingUp", true) -- play the up animation --self:PlayAnimation{ animationID = upAnim, fPriority = 2.0} self:SetNetworkVar("current_anim", upAnim) else self:SetVar("movingUp", false) -- play the down animation --self:PlayAnimation{ animationID = downAnim, fPriority = 2.0} self:SetNetworkVar("current_anim", downAnim) end end -- custom function that toggles the active state of the spinner based on it's current state function toggleActive(self, bPlayerTriggered) local bActive = self:GetVar("bActive") or false --debugPrint(self, '1 ' .. tostring(bActive)) -- get the inverse bool value bActive = not bActive setActiveState(self, bActive, bPlayerTriggered) end function toggleSpawnerNetwork(self, bActive) local tSpawners = self:GetVar("tSpawners") or false if not tSpawners then return end if bActive and not self:GetVar("NoSpawnerFX") then local spawnFXType = self:GetVar("spawnFXType") or defaultSpawnFXType self:PlayFXEffect{name = "spawnFX", effectType = spawnFXType} end for k, spawnerNetworkName in ipairs(tSpawners) do local spawner = LEVEL:GetSpawnerByName(spawnerNetworkName) if spawner and spawner:Exists() then if bActive then spawner:SpawnerActivate() local totalToSpawn = self:GetVar("TotalSpawnedAlive") or 0 totalToSpawn = totalToSpawn + spawner:SpawnerGetMaxToSpawn().iNum self:SetVar("TotalSpawnedAlive",totalToSpawn) self:SendLuaNotificationRequest{requestTarget = spawner, messageName = "NotifySpawnerOfDeath"} else spawner:SpawnerDestroyObjects{bDieSilent = false} spawner:SpawnerDeactivate() end else local loc = self:GetPosition().pos debugPrint(self, "Warning!! Spawner Network " .. spawnerNetworkName .. " doesn't exist on spinner at location " .. tostring(loc.x) .. ", " .. tostring(loc.y) .. ", " .. tostring(loc.z)) end end end function notifyNotifySpawnerOfDeath(self,spawner,msg) local totalStillAlive = self:GetVar("TotalSpawnedAlive") if not totalStillAlive then return end totalStillAlive = totalStillAlive - 1 if totalStillAlive < 0 then debugPrint(self, "Warning!! More enemies killed on Spawner Network " .. spawner:GetName().name .. " than were spawned. Probably something wrong with the script") return end self:SetVar("TotalSpawnedAlive",totalStillAlive) if spawner:SpawnerGetCurrentSpawned().iSpawned == 0 then self:SendLuaNotificationCancel{requestTarget = spawner, messageName = "NotifySpawnerOfDeath"} spawner:SpawnerDeactivate() spawner:SpawnerReset() end if totalStillAlive > 0 then return end -- fire deactivated event --sendEvent(self, false) activateSpinner(self, false) end -- custom function to playCinematic function playCinematic(self, bPlayOn) local player = GAMEOBJ:GetObjectByID(self:GetVar("userID")) if not player:Exists() then return end local cine = nil if bPlayOn then cine = self:GetVar("on_cinematic") else cine = self:GetVar("off_cinematic") end if not cine then return end player:RemoveBuff{uiBuffID = 60} player:PlayCinematic{pathName = cine} end -- custom function to find the skill type and cast it function spinCastSkill(self) local type = self:GetVar("type") -- return out if we dont want to cast the skill if not type or type == "elevator" or not self:GetVar("bActive") then return end local skill = skills[type] self:CastSkill{skillID = skill} end function toggleSpinner(self, bPlayerTriggered) local bActivate = true if self:GetVar("stoppedNode") == 1 then bActivate = false end activateSpinner(self, bActivate, bPlayerTriggered) end function activateSpinner(self, bActivate, bPlayerTriggered) -- get the node to move to local gotoNode = 0 local newSpinNode = 1 if bActivate then gotoNode = 1 newSpinNode = 0 end if gotoNode == self:GetVar("stoppedNode") then return end -- stop all timers self:ActivityTimerStopAllTimers() -- set flag to true so this wont happen twice self:SetNetworkVar("bIsInUse", true) -- set to true because we dont want to castSkill while moving self:SetVar("bTraveling", true) if bPlayerTriggered then -- get the time to reset, 0 means not to reset local resetTime = self:GetVar("reset_time") or defaultResetTime if self:GetVar("once_only") then setCapFX(self, false) elseif resetTime > 0 then self:SetVar("startResetOnArrived", true) else -- this will put the spinner in a waiting state when it arrives self:SetVar("resetOnArrived", true) end else -- this will put the spinner in a waiting state when it arrives self:SetVar("resetOnArrived", true) end if self:GetVar("element_type") == "collision" and self:GetVar("bCapShown") then setCapFX(self, false) self:SetVar("element_type", "collision_off") setCapFX(self, true) end -- move the spinner self:GoToWaypoint{ iPathIndex = gotoNode, bStopAtWaypoint = true } self:SetVar("stoppedNode", gotoNode) -- Play the movement oneshot audio. local audioMovementOneshotGUID = self:GetVar("audioMovementBeginGUID") or audioMovementBeginGUID self:PlayNDAudioEmitter{m_NDAudioEventGUID = audioMovementOneshotGUID} -- Play the movement loop audio. Use a network var so that state is communicated upon ghosting. local audioMovementLoopGUID = self:GetVar("audioMovementGUID") or audioMovementGUID self:SetNetworkVar("StopAudio", nil) self:SetNetworkVar("PlayAudio", audioMovementLoopGUID) -- toggleActive based on current state setActiveState(self, bActivate, bPlayerTriggered) end function toggleDamageProx(self, bOn) -- what is the type of the spinner, default = elevator local type = self:GetVar("type") -- blade uses a proximity radius for casting the skill, so set it if type ~= "blade" then return end -- set the default up audio local audioGUID = self:GetVar("audioSpinningGUID") or audioSpinningGUID if bOn then -- get config data or use defaults local damageRaduis = self:GetVar("damage_radius") or defaultDamageRadius local damageHeight = self:GetVar("damage_height") or defaultDamageHeight local heightOffset = self:GetVar("damage_offset") or defaultDamageVertOffset self:SetProximityRadius{name = "damage", radius = damageRaduis, height = damageHeight, shapeType = "CYLINDER", heightOffset = defaultDamageVertOffset} self:SetNetworkVar("StopAudio2", nil) self:SetNetworkVar("PlayAudio2", audioGUID) else self:UnsetProximityRadius{name = "damage"} self:SetNetworkVar("PlayAudio2", nil) self:SetNetworkVar("StopAudio2", audioGUID) end end --function onFireEventServerSide(self, msg) -- spinFireEventServerSide(self, msg) --end ---- TODO: Change this to setnetworkvar and play animations on the client --function spinFireEventServerSide(self, msg) -- if msg.args ~= "startAnim" then return end -- local node = self:GetVar("stoppedNode") or 0 -- -- based on the start node set if it's active or not, set the spinNode (where it moves to when the skill is cast) -- if node == 0 then return end -- -- play the up animation -- self:PlayAnimation{ animationID = idleUpAnim, fPriority = 2.0} --end function onFireEvent(self, msg) spinFireEvent(self, msg) end function spinFireEvent(self, msg) --- types of events: this is set on the object configData in HF for the receiving the event. ---- -- FORMAT: this is for the name_activated_event sent to the group_activated_event from above -- event1 --> 0:activate ---- -- activate -- use this variable name to put the spinner into the active state -- deactivate -- use this variable name to put the spinner into the inactive state -- toggle_activate -- use this variable name to put the spinner into it's other active state -- interact -- use this variable name to put the spinner into the interactive state -- noninteract -- use this variable name to put the spinner into the noninactive state -- toggle_interact -- use this variable name to put the spinner into it's other interactive state local eventType = self:GetVar(msg.args) if not eventType then return end if eventType == "activate" then activateSpinner(self, true) elseif eventType == "deactivate" then activateSpinner(self, false) elseif eventType == "toggle_activate" then toggleSpinner(self) elseif eventType == "interact" then if self:GetVar("element_type") ~= "collision" and not self:GetVar("static") then self:SetNetworkVar("bInteractive", true) end setCapFX(self, true) elseif eventType == "noninteract" then if self:GetVar("element_type") ~= "collision" and not self:GetVar("static") then self:SetNetworkVar("bInteractive", false) end setCapFX(self, false) elseif eventType == "toggle_interact" then local bInteractive = true if self:GetNetworkVar("bInteractive") then bInteractive = false end if self:GetVar("element_type") ~= "collision" and not self:GetVar("static") then self:SetNetworkVar("bInteractive", bInteractive) end setCapFX(self, bInteractive) end local playerID = self:GetVar("userID") or 0 if playerID ~= 0 then local player = self:GetObjectByID(playerID) if player:Exists() then playAnim(self, player, endAnim) end end end function sendEvent(self, bFireOn) local eventName = false local eventGroup = false if bFireOn then eventName = self:GetVar("name_activated_event") or false eventGroup = self:GetVar("group_activated_event") or false else eventName = self:GetVar("name_deactivated_event") or false eventGroup = self:GetVar("group_deactivated_event") or false end if not eventName or not eventGroup then return end --debugPrint(self, 'name = ' .. eventName .. " group = " .. eventGroup) local groupObjs = self:GetObjectsInGroup{group = eventGroup, ignoreSpawners = true}.objects for k,obj in ipairs(groupObjs) do if obj:Exists() then obj:FireEvent{args = eventName, senderID = self} end end end function onArrived(self, msg) spinArrived(self, msg) end function spinArrived(self, msg) -- done traveleing so set this to false self:SetVar("bTraveling", false) if msg.wayPoint == self:GetVar("stoppedNode") and self:GetNetworkVar("bIsInUse") then if self:GetVar("resetOnArrived") then -- toggle to waiting state self:SetNetworkVar("bIsInUse", false) self:SetVar("resetOnArrived", false) -- TODO: collision cap not working correctly if self:GetVar("element_type") == "collision_off" then setCapFX(self,false) self:SetVar("element_type", "collision") end setCapFX(self, true) elseif self:GetVar("startResetOnArrived") then -- get the time to reset, 0 means not to reset local resetTime = self:GetVar("reset_time") or defaultResetTime -- set the reset activity timer, no update only duration self:ActivityTimerSet{name = "Reset", duration = resetTime} end end local activeState = self:GetVar("bActive") or false if activeState then -- start a timer to delay when the player can be hit by the proximity, -- this should prevent players getting hit when the move time is really short self:ActivityTimerSet{name = "Start_Damage", duration = damageStartDelay} -- check to see if we need to activate the spanwer network toggleSpawnerNetwork(self, true) -- play the animation self:SetNetworkVar("current_anim", idleUpAnim) else -- turn off the damage proximity toggleDamageProx(self, false) -- check to see if we need to deactivate the spanwer network toggleSpawnerNetwork(self, false) -- play the animation self:SetNetworkVar("current_anim", idleDownAnim) end -- Play the movement oneshot audio. local audioMovementOneshotGUID = self:GetVar("audioMovementEndGUID") or audioMovementEndGUID self:PlayNDAudioEmitter{m_NDAudioEventGUID = audioMovementOneshotGUID} -- Stop the movement loop audio. Use a network var so that state is communicated upon ghosting. local audioMovementLoopGUID = self:GetVar("audioMovementGUID") or audioMovementGUID self:SetNetworkVar("PlayAudio", nil) self:SetNetworkVar("StopAudio", audioMovementLoopGUID) local player = GAMEOBJ:GetObjectByID(self:GetVar("userID")) if player:Exists() then playAnim(self, player, endAnim) end sendEvent(self, activeState) --debugPrint(self, 'Arrived @ ' .. msg.wayPoint) end function onProximityUpdate(self, msg) spinProximityUpdate(self, msg) end function spinProximityUpdate(self, msg) -- cast skill if the player entered into the damage radius if msg.name == "damage" and self:GetVar("bActive") then if msg.status == "ENTER" then -- if we're inUse then cast the skill local type = self:GetVar("type") if type == "blade" then spinCastSkill(self) self:ActivityTimerSet{name = "Pulse_Skill", updateInterval = 0.5} end elseif msg.status == "LEAVE" then -- get the number of players in the damage radus local numPlayers = #self:GetProximityObjects{name = "damage"}.objects or 0 if numPlayers < 1 then self:ActivityTimerStop{name = "Pulse_Skill"} end end elseif msg.name == "spin_distance" then if msg.status == "LEAVE" then local playerID = self:GetVar("userID") or 0 if playerID ~= 0 then if playerID == msg.objId:GetID() then local player = GAMEOBJ:GetObjectByID(self:GetVar("userID")) if player:Exists() then playAnim(self, player, endAnim) if self:GetNetworkVar('bIsInUse') and not self:GetVar("bTraveling") then self:SetNetworkVar("bIsInUse", false) end end end end elseif (msg.status == "ENTER" and self:GetVar("element_type") == "collision" and not self:GetVar("bTraveling") and self:GetVar("bCapShown")) then toggleSpinner(self, true) end end end function onActivityTimerUpdate(self, msg) spinActivityTimerUpdate(self, msg) end function spinActivityTimerUpdate(self, msg) -- if we are supposed to be pulsing the skill thnen do it if msg.name == "Pulse_Skill" and self:GetVar("bActive") and not self:GetVar("bTraveling") then -- if not arrow pulse the skill spinCastSkill(self) end end function onActivityTimerDone(self, msg) spinActivityTimerDone(self,msg) end function spinActivityTimerDone(self, msg) if msg.name == "Reset" then toggleSpinner(self) elseif string.starts(msg.name, "AnimDone") then local msgData = split(msg.name, "_") local animName = msgData[2] or false local player = GAMEOBJ:GetObjectByID(self:GetVar("userID")) if player:Exists() and animName then if animName == startAnim then toggleSpinner(self, true) -- triggerSpinner(self, player) -- set inuse to false and update pick type player:PlayAnimation{ animationID = runAnim, fPriority = 2.0} elseif animName == runAnim then -- set inuse to false and update pick type playAnim(self, player, endAnim) elseif animName == endAnim then self:SetNetworkVar("bFreezePlayer_" .. self:GetVar("userID"), false) -- clear the user and reequip any items that need it self:SetVar("userID", 0) -- stop the staff interaction fx player:StopFXEffect{name = "tornado"} player:StopFXEffect{name = "staff"} local movingUp = not self:GetVar("movingUp") self:SetVar("movingUp", movingUp) end end elseif msg.name == "Start_Damage" then toggleDamageProx(self, 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 function string.starts(String,Start) -- finds if a string starts with a giving string. return string.sub(String,1,string.len(Start))==Start end