Client: 
   -- Copyright (c) 2008, Alberto Alonso  --  -- All rights reserved.  --  -- Redistribution and use in source and binary forms, with or without modification,  -- are permitted provided that the following conditions are met:  --  --     * Redistributions of source code must retain the above copyright notice, this  --       list of conditions and the following disclaimer.  --     * Redistributions in binary form must reproduce the above copyright notice, this  --       list of conditions and the following disclaimer in the documentation and/or other  --       materials provided with the distribution.  --     * Neither the name of the superman script nor the names of its contributors may be used  --       to endorse or promote products derived from this software without specific prior  --       written permission.  --  -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  -- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  -- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR  -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  -- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  -- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  local Superman = {}     -- Settings  local ZERO_TOLERANCE = 0.00001  local MAX_ANGLE_SPEED = 6 -- In degrees per frame  local MAX_SPEED = 1.0  local EXTRA_SPEED_FACTOR = 1.85  local LOW_SPEED_FACTOR = 0.40  local ACCELERATION = 0.025  local EXTRA_ACCELERATION_FACTOR = 1.8  local LOW_ACCELERATION_FACTOR = 0.85  local TAKEOFF_VELOCITY = 1.75  local TAKEOFF_FLIGHT_DELAY = 750  local SMOKING_SPEED = 1.25  local GROUND_ZERO_TOLERANCE = 0.18  local LANDING_DISTANCE = 3.2  local FLIGHT_ANIMLIB = "swim"  local FLIGHT_ANIMATION = "Swim_Dive_Under"  local FLIGHT_ANIM_LOOP = false  local IDLE_ANIMLIB = "cop_ambient"  local IDLE_ANIMATION = "Coplook_loop"  local IDLE_ANIM_LOOP = true  local MAX_Y_ROTATION = 55  local ROTATION_Y_SPEED = 3.8     -- Static global variables  local thisResource = getThisResource()  local rootElement = getRootElement()  local localPlayer = getLocalPlayer()  local serverGravity = getGravity()        --  -- Utility functions  --  local function isPlayerFlying(player)    local data = getElementData(player, "superman:flying")    if not data or data == false then return false    else return true end  end     local function setPlayerFlying(player, state)    if state == true then state = true    else state = false end       setElementData(player, "superman:flying", state)  end     local function iterateFlyingPlayers()    local current = 1    local allPlayers = getElementsByType("player")       return function()      local player           repeat        player = allPlayers[current]        current = current + 1      until not player or (isPlayerFlying(player) and isElementStreamedIn(player))         return player    end  end     function Superman:restorePlayer(player)    setPlayerFlying(player, false)    setPedAnimation(player, false)    setElementVelocity(player, 0, 0, 0)    setElementRotation(player, 0, 0, 0)    --setPedRotation(player, getPedRotation(player))    setElementCollisionsEnabled(player, true)    self:destroySmokeGenerators(player)    self.rotations[player] = nil    self.previousVelocity[player] = nil  end     function Superman:createSmokeGenerator(player)    local generator = createObject(2780, getElementPosition(player))    setElementCollisionsEnabled(generator, false)    setObjectScale(generator, 0)    return generator  end     function Superman:createSmokeGenerators(player)    if not self.smokeGenerators[player] then      local smokeGenerators = {}         smokeGenerators[1] = self:createSmokeGenerator(player)      attachElementToElement(smokeGenerators[1], player, 0.75, -0.2, -0.4, -40, 0, 60)      smokeGenerators[2] = self:createSmokeGenerator(player)      attachElementToElement(smokeGenerators[2], player, -0.75, -0.2, -0.4, -40, 0, -60)         self.smokeGenerators[player] = smokeGenerators    end  end     function Superman:destroySmokeGenerators(player)    if self.smokeGenerators[player] then      for k, v in ipairs(self.smokeGenerators[player]) do        destroyElement(v)      end      self.smokeGenerators[player] = nil    end  end     function angleDiff(angle1, angle2)    angle1, angle2 = angle1 % 360, angle2 % 360    local diff = (angle1 - angle2) % 360    if diff <= 180 then      return diff    else      return -(360 - diff)    end  end     local function isPedInWater(ped)    local pedPosition = Vector3D:new(getElementPosition(ped))    if pedPosition.z <= 0 then return true end       local waterLevel = getWaterLevel(pedPosition.x, pedPosition.y, pedPosition.z)    if not isElementStreamedIn(ped) or not waterLevel or waterLevel < pedPosition.z then      return false    else      return true    end  end     local function isnan(x)      math.inf = 1/0      if x == math.inf or x == -math.inf or x ~= x then          return true      end      return false  end     local function getVector2DAngle(vec)    if vec.x == 0 and vec.y == 0 then return 0 end    local angle = math.deg(math.atan(vec.x / vec.y)) + 90    if vec.y < 0 then      angle = angle + 180    end    return angle  end     --  -- Initialization and shutdown functions  --  function Superman.Start()    local self = Superman       -- Register events    addEventHandler("onClientResourceStop", getResourceRootElement(thisResource), Superman.Stop, false)    addEventHandler("onPlayerJoin", rootElement, Superman.onJoin)    addEventHandler("onPlayerQuit", rootElement, Superman.onQuit)    addEventHandler("onClientRender", rootElement, Superman.processControls)    addEventHandler("onClientRender", rootElement, Superman.processFlight)    addEventHandler("onClientPlayerDamage", localPlayer, Superman.onDamage, false)    addEventHandler("onClientElementDataChange", rootElement, Superman.onDataChange)    addEventHandler("onClientElementStreamIn", rootElement, Superman.onStreamIn)    addEventHandler("onClientElementStreamOut", rootElement, Superman.onStreamOut)       -- Bind keys          -- Register commands  --  addCommandHandler("mansuper", Superman.cmdSuperman)       -- Initializate attributes    self.smokeGenerators = {}    self.rotations = {}    self.previousVelocity = {}  end  addEventHandler("onClientResourceStart", getResourceRootElement(thisResource), Superman.Start, false)     function Superman.Stop()    local self = Superman       setGravity(serverGravity)       -- Restore all players animations, collisions, etc    for player in iterateFlyingPlayers() do      self:restorePlayer(player)    end  end           --  -- Join/Quit  --  function Superman.onJoin(player)    local self = Superman    local player = player or source       setPlayerFlying(player, false)  end     function Superman.onQuit(reason, player)    local self = Superman    local player = player or source       if isPlayerFlying(player) then      self:restorePlayer(player)    end  end        --  -- onDamage: superman is invulnerable  --  function Superman.onDamage()    local self = Superman       if isPlayerFlying(localPlayer) then      cancelEvent()    end  end        --  -- onStreamIn: Reset rotation attribute for player  --  function Superman.onStreamIn()