Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

superman: more initial improvements #577

Merged
merged 17 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local Superman = {}

-- Settings

local ZERO_TOLERANCE = 0.00001
local MAX_ANGLE_SPEED = 6 -- In degrees per frame
local MAX_SPEED = 2.5
Expand All @@ -21,37 +22,21 @@ local IDLE_ANIMATION = "Coplook_loop"
local IDLE_ANIM_LOOP = true
local MAX_Y_ROTATION = 70
local ROTATION_Y_SPEED = 3.8
local warningTextColor = tocolor(255, 0, 0, 255)

-- Static variables

-- Static global variables
local thisResource = getThisResource()
local serverGravity = getGravity()
ds1-e marked this conversation as resolved.
Show resolved Hide resolved

--
-- 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 isPlayerFlying(playerElement)
local playerFlying = getSupermanData(playerElement, SUPERMAN_FLY_DATA_KEY)

local function setPlayerFlying(player, state)
if not player then return end

if state == true then
state = true
else
state = false
end

setElementData(player, "superman:flying", state)
return playerFlying
end
addEvent("setPlayerFlyingC", true)
addEventHandler("setPlayerFlyingC", root, setPlayerFlying)

local function iterateFlyingPlayers()
local current = 1
Expand All @@ -70,14 +55,14 @@ local function iterateFlyingPlayers()
end
end

function Superman:restorePlayer(player)
setPlayerFlying(player, false)
setPedAnimation(player, false)
setElementVelocity(player, 0, 0, 0)
setElementRotation(player, 0, 0, 0)
setElementCollisionsEnabled(player, true)
self.rotations[player] = nil
self.previousVelocity[player] = nil
function Superman:restorePlayer(playerElement)
setSupermanData(playerElement, SUPERMAN_FLY_DATA_KEY, false)
setPedAnimation(playerElement, false)
setElementVelocity(playerElement, 0, 0, 0)
setElementRotation(playerElement, 0, 0, 0)
setElementCollisionsEnabled(playerElement, true)
self.rotations[playerElement] = nil
self.previousVelocity[playerElement] = nil
end

function angleDiff(angle1, angle2)
ds1-e marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -91,22 +76,6 @@ function angleDiff(angle1, angle2)
end
end

local function isElementInWater(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

Expand Down Expand Up @@ -136,26 +105,24 @@ function Superman.Start()
local self = Superman

-- Register events
addEventHandler("onClientResourceStop", getResourceRootElement(thisResource), Superman.Stop, false)
addEventHandler("onPlayerJoin", root, Superman.onJoin)
addEventHandler("onPlayerQuit", root, Superman.onQuit)

addEventHandler("onClientResourceStop", resourceRoot, Superman.Stop, false)
addEventHandler("onClientRender", root, Superman.processControls)
addEventHandler("onClientRender", root, Superman.processFlight)
addEventHandler("onClientPlayerDamage", localPlayer, Superman.onDamage, false)
addEventHandler("onClientPlayerVehicleEnter", localPlayer, Superman.onEnter)
addEventHandler("onClientElementDataChange", root, Superman.onDataChange)
addEventHandler("onClientElementStreamIn", root, Superman.onStreamIn)
addEventHandler("onClientElementStreamOut", root, Superman.onStreamOut)

bindKey("jump", "down", Superman.onJump)

addCommandHandler("superman", Superman.cmdSuperman)

-- Initializate attributes

self.rotations = {}
self.previousVelocity = {}
end
addEventHandler("onClientResourceStart", getResourceRootElement(thisResource), Superman.Start, false)
addEventHandler("onClientResourceStart", resourceRoot, Superman.Start, false)

function Superman.Stop()
local self = Superman
ds1-e marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -168,30 +135,14 @@ function Superman.Stop()
end
end

function Superman.onJoin(player)
local self = Superman
local playerElement = player or source

setPlayerFlying(playerElement, false)
end

function Superman.onQuit(reason, player)
local self = Superman
local playerElement = player or source

if isPlayerFlying(playerElement) then
self:restorePlayer(playerElement)
end
end

-- onEnter: superman cant enter vehicles
-- There's a fix (serverside) for players glitching other players' vehicles by warping into them while superman is active, causing them to flinch into air and get stuck.
function showWarning()
ds1-e marked this conversation as resolved.
Show resolved Hide resolved
local x, y, z = getPedBonePosition(localPlayer, 6)
local sx, sy, dist = getScreenFromWorldPosition(x, y, z + 0.3)

if sx and sy and dist and dist < 100 then
dxDrawText("You can not warp into a vehicle when superman is activated.", sx, sy, sx, sy, tocolor(255, 0, 0, 255), 1.1, "default-bold", "center")
dxDrawText("You can not warp into a vehicle when superman is activated.", sx, sy, sx, sy, warningTextColor, 1.1, "default-bold", "center")
end
end

Expand All @@ -200,46 +151,44 @@ function hideWarning()
end

function Superman.onEnter()
if (isPlayerFlying(localPlayer) or getElementData(localPlayer, "superman:takingOff")) and not isTimer(warningTimer) then
if (isPlayerFlying(localPlayer) or getSupermanData(localPlayer, SUPERMAN_TAKE_OFF_DATA_KEY)) and not isTimer(warningTimer) then
addEventHandler("onClientRender", root, showWarning)
warningTimer = setTimer(hideWarning, 5000, 1)
end
end

function Superman.onDamage()
local self = Superman

if isPlayerFlying(localPlayer) then
cancelEvent()
end
end

-- onStreamIn: Reset rotation attribute for player
function Superman.onStreamIn()
local self = Superman
end

function Superman.onStreamOut()
local self = Superman

if source and isElement(source) and getElementType(source) == "player" and isPlayerFlying(source) then
if isPlayerFlying(source) then
self.rotations[source] = nil
self.previousVelocity[source] = nil
end
end

-- onDataChange: Check if somebody who is out of stream stops being superman
function Superman.onDataChange(dataName, oldValue)
local self = Superman
function onClientSupermanDataChange(dataKey, _, newValue)
local flyDataKey = (dataKey == SUPERMAN_FLY_DATA_KEY)

if (not flyDataKey) then
return false
end

if dataName == "superman:flying" and isElement(source) and getElementType(source) == "player" and oldValue ~= getElementData(source, dataName) and oldValue == true and getElementData(source, dataName) == false then
self:restorePlayer(source)
if (not newValue) then
Superman:restorePlayer(source)
end
end
if (not SUPERMAN_USE_ELEMENT_DATA) then addEvent("onClientSupermanDataChange", false) end
addEventHandler(SUPERMAN_USE_ELEMENT_DATA and "onClientElementDataChange" or "onClientSupermanDataChange", root, onClientSupermanDataChange)

-- onJump: Combo to start flight without any command
function Superman.onJump(key, keyState)
local self = Superman

function Superman.onJump()
local task = getPedSimplestTask(localPlayer)

if not isPlayerFlying(localPlayer) then
Expand All @@ -251,34 +200,32 @@ function Superman.onJump(key, keyState)
end

function Superman.cmdSuperman()
local self = Superman

if isPedInVehicle(localPlayer) or isPlayerFlying(localPlayer) then
return
end

setElementVelocity(localPlayer, 0, 0, TAKEOFF_VELOCITY)
setTimer(Superman.startFlight, TAKEOFF_FLIGHT_DELAY, 1)
setElementData(localPlayer, "superman:takingOff", true)
setSupermanData(localPlayer, SUPERMAN_TAKE_OFF_DATA_KEY, true)
end

function Superman.startFlight()
local self = Superman

setElementData(localPlayer, "superman:takingOff", false)
setSupermanData(localPlayer, SUPERMAN_TAKE_OFF_DATA_KEY, false)

if isPlayerFlying(localPlayer) then
return
end

triggerServerEvent("superman:start", localPlayer)
setPlayerFlying(localPlayer, true)
setSupermanData(localPlayer, SUPERMAN_FLY_DATA_KEY, true)
setElementVelocity(localPlayer, 0, 0, 0)
self.currentSpeed = 0
self.extraVelocity = {x = 0, y = 0, z = 0}
end

-- Controls processing

local jump, oldJump = false, false

function Superman.processControls()
Expand Down Expand Up @@ -449,7 +396,7 @@ function Superman.processFlight()
self:restorePlayer(player)
if player == localPlayer then
setGravity(serverGravity)
triggerServerEvent("superman:stop", localPlayer)
setSupermanData(localPlayer, SUPERMAN_FLY_DATA_KEY, false)
end
elseif distanceToGround and distanceToGround < LANDING_DISTANCE then
self:processLanding(player, Velocity, distanceToGround)
Expand Down Expand Up @@ -488,11 +435,10 @@ function Superman:processIdleFlight(player)

Sight.z = math.deg(Sight.z) + 180

setPedRotation(localPlayer, Sight.z)
setElementRotation(localPlayer, 0, 0, Sight.z)
else
local Zangle = getPedCameraRotation(player)
setPedRotation(player, Zangle)

setElementRotation(player, 0, 0, Zangle)
end
end
Expand All @@ -515,7 +461,7 @@ function Superman:processMovingFlight(player, Velocity)
local Rotation = Vector3D:new(0, 0, 0)

if Velocity.x == 0 and Velocity.y == 0 then
Rotation.z = getPedRotation(player)
Rotation.z = getElementRotation(player)
else
Rotation.z = math.deg(math.atan(Velocity.x / Velocity.y))

Expand Down Expand Up @@ -574,7 +520,7 @@ function Superman:processMovingFlight(player, Velocity)
Rotation.y = self.rotations[player]

-- Apply the calculated rotation
setPedRotation(player, Rotation.z)

setElementRotation(player, Rotation.x, Rotation.y, Rotation.z)

-- Save the current velocity
Expand All @@ -600,7 +546,7 @@ function Superman:processLanding(player, Velocity, distanceToGround)
local Rotation = Vector3D:new(0, 0, 0)

if Velocity.x == 0 and Velocity.y == 0 then
Rotation.z = getPedRotation(player)
Rotation.z = getElementRotation(player)
else
Rotation.z = math.deg(math.atan(Velocity.x / Velocity.y))
if Velocity.y > 0 then
Expand All @@ -614,7 +560,7 @@ function Superman:processLanding(player, Velocity, distanceToGround)
Rotation.x = Rotation.x - 40

-- Apply the calculated rotation
setPedRotation(player, Rotation.z)

setElementRotation(player, Rotation.x, Rotation.y, Rotation.z)
end

Expand Down
29 changes: 29 additions & 0 deletions [gameplay]/superman/SHandleSuperman.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
local function supermanCancelAirKill()
local supermanFlying = getSupermanData(source, SUPERMAN_FLY_DATA_KEY)
local supermanTakingOff = getSupermanData(source, SUPERMAN_TAKE_OFF_DATA_KEY)

if (not supermanFlying and not supermanTakingOff) then
return false
end

cancelEvent()
end
addEventHandler("onPlayerStealthKill", root, supermanCancelAirKill)

-- Fix for players glitching other players' vehicles by warping into them while superman is active, causing them to flinch into air and get stuck.

local function supermanEnterVehicle()
local supermanFlying = getSupermanData(source, SUPERMAN_FLY_DATA_KEY)
local supermanTakingOff = getSupermanData(source, SUPERMAN_TAKE_OFF_DATA_KEY)

if (not supermanFlying and not supermanTakingOff) then
return false
end

removePedFromVehicle(source)

local playerX, playerY, playerZ = getElementPosition(source)

setElementPosition(source, playerX, playerY, playerZ)
end
addEventHandler("onPlayerVehicleEnter", root, supermanEnterVehicle)
2 changes: 2 additions & 0 deletions [gameplay]/superman/config/ShSupermanConfig.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SUPERMAN_FLY_DATA_KEY = "superman:flying"
SUPERMAN_TAKE_OFF_DATA_KEY = "superman:takingOff"
15 changes: 15 additions & 0 deletions [gameplay]/superman/data/CData.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
local function onClientSupermanSync(supermanServerData)
syncSupermansData(supermanServerData)
end
if (not SUPERMAN_USE_ELEMENT_DATA) then
addEvent("onClientSupermanSync", true)
addEventHandler("onClientSupermanSync", localPlayer, onClientSupermanSync)
end

local function onClientSupermanSetData(dataKey, dataValue)
setSupermanData(source, dataKey, dataValue)
end
if (not SUPERMAN_USE_ELEMENT_DATA) then
addEvent("onClientSupermanSetData", true)
addEventHandler("onClientSupermanSetData", root, onClientSupermanSetData)
end
Loading