Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
88 changes: 88 additions & 0 deletions amx/client/samp_chatbubbles.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
local g_Players = {}
local screenW, screenH = guiGetScreenSize()

local function getPlayerData(player)
if not g_Players[player] then
g_Players[player] = { pvars = {} }
end
return g_Players[player]
end

addEvent("onChatBubbleRequested", true)
addEventHandler("onChatBubbleRequested", root, function(player, text, colour, dist, exptime, cameraMatrix)
if not isElement(player) then return end

local data = getPlayerData(player)

data.pvars["_chtbbl" .. tostring(getElemID(player))] = {
text = text,
colour = colour,
expires = getTickCount() + (exptime or 5000),
zOffset = 0.7,
drawDist = dist,
targetPlayer = player,
camMatrix = cameraMatrix
}
end)

addEventHandler("onClientRender", root, function()
local function destroyDisplay(serverDisplay, dspText, targetPlayer, forPlayer)
textDisplayRemoveObserver(serverDisplay, forPlayer)
textDisplayRemoveText(serverDisplay, dspText)
textDestroyDisplay(serverDisplay)
g_Players[forPlayer].pvars["_chtbbl" .. tostring(getElemID(targetPlayer))].txtDisplay = nil
g_Players[forPlayer].pvars["_chtbbl" .. tostring(getElemID(targetPlayer))].serverText = nil
end

local text, colour, dist, exptime, zOffset
local data = getPlayerData(localPlayer)
for key, bubble in pairs(data.pvars) do
if type(bubble) == "table" then
if getTickCount() > bubble.expires then
data.pvars[key] = nil
else
local bx, by, bz = getPedBonePosition(bubble.targetPlayer, 8)
local worldPos = Vector3(bx, by, bz + (bubble.zOffset or 0.7))
local sx, sy = getScreenFromWorldPosition(worldPos.x, worldPos.y, worldPos.z)
local targetPos = Vector2(sx, sy)
local camPos = Vector3(camMatrix.x, camMatrix.y, camMatrix.z)

if targetPos.x and targetPos.y then
print("worldPos.x and worldPos.y : TRUE")
local distance = (camPos - worldPos).length
if distance <= bubble.drawDist and isLineOfSightClear(camPos.x, camPos.y, camPos.z, worldPos.x, worldPos.y, worldPos.z, true, true, true, true, true, false, false) then
if data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay == nil then
data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay = textCreateDisplay()
data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText = textCreateTextItem(bubble.text, 0.5, 0.5)
local r = bitAnd(bitRShift(bubble.colour, 24), 0xFF)
local g = bitAnd(bitRShift(bubble.colour, 16), 0xFF)
local b = bitAnd(bitRShift(bubble.colour), 0xFF)
local a = bitAnd(bubble.colour, 0xFF)
if a == 0 then a = 255 end
textItemSetColor(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText, r, g, b, a)
textDisplayAddText(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay, data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText)
end
print("distance <= bubble.drawDist : TRUE")

local normX = targetPos.x -- / screenW
local normY = targetPos.y -- / screenH
textItemSetPosition(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText, normX, normY)

local scale = math.max(0.6, (15 / distance * 1.0))
textItemSetScale(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText, scale)

if not textDisplayIsObserver(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay, localPlayer) then
textDisplayAddObserver(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay, localPlayer)
end
end
else
if textDisplayIsObserver(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay) then
destroyDisplay(data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay, data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText, localPlayer)
end
print("worldPos.x and worldPos.y : FALSE")
end
setTimer(destroyDisplay, bubble.expires, 1, data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].txtDisplay, data.pvars["_chtbbl" .. tostring(getElemID(bubble.targetPlayer))].serverText, localPlayer)
end
end
end
end)
2 changes: 2 additions & 0 deletions amx/meta.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<script src="client/samp_nametags.lua" type="client" />
<script src="client/map_waypoint.lua" type="client" />
<script src="client/garages.lua" type="client" />
<script src="client/samp_chatbubbles.lua" type="client" />

<!--
attachToBones: Credit to Tekken (also known as mihayy5)
Expand Down Expand Up @@ -59,3 +60,4 @@
<setting name="plugins" value="" />
</settings>
</meta>

34 changes: 22 additions & 12 deletions amx/server/natives/a_players.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function SetPlayerPosFindZ(amx, player, x, y, z)
end

function GetPlayerPos(amx, player, refX, refY, refZ)
if not player then
if not player then
return false
end

Expand All @@ -46,7 +46,7 @@ function SetPlayerFacingAngle(amx, player, angle)
end

function GetPlayerFacingAngle(amx, player, refAng)
if not player then
if not player then
return false
end
local rX, rY, rZ = getElementRotation(player)
Expand Down Expand Up @@ -115,7 +115,7 @@ function SetPlayerHealth(amx, player, health)
end

function GetPlayerHealth(amx, player, refHealth)
if not player then
if not player then
return false
end
writeMemFloat(amx, refHealth, getElementHealth(player))
Expand All @@ -127,7 +127,7 @@ function SetPlayerArmour(amx, player, armor)
end

function GetPlayerArmour(amx, player, refArmor)
if not player then
if not player then
return false
end
writeMemFloat(amx, refArmor, getPedArmor(player))
Expand Down Expand Up @@ -410,7 +410,7 @@ function SetPlayerVelocity(amx, player, vx, vy, vz)
end

function GetPlayerVelocity(amx, player, refVX, refVY, refVZ)
if not player then
if not player then
return false
end
local vx, vy, vz = getElementVelocity(player)
Expand Down Expand Up @@ -824,12 +824,22 @@ function GetPVarType(amx, player, varname)
end

function SetPlayerChatBubble(amx, player, text, color, dist, exptime)
notImplemented('SetPlayerChatBubble')
return false
if not player then
return false
end

if not text or string.len(text) == 0 then
return false
end

for _, plr in ipairs(getElementsByType('player')) do
triggerClientEvent(root, "onChatBubbleRequested", plr, player, text, color, dist, exptime, Vector3((plr)))
end
return true
end

function PutPlayerInVehicle(amx, player, vehicle, seat)
if not player then
if not player then
return false
end
warpPedIntoVehicle(player, vehicle, seat)
Expand Down Expand Up @@ -1037,7 +1047,7 @@ function SetPlayerDisabledWeapons(amx, player, ...)
end

function SetPlayerCameraPos(amx, player, x, y, z)
if not player then
if not player then
return false
end
fadeCamera(player, true)
Expand All @@ -1046,7 +1056,7 @@ function SetPlayerCameraPos(amx, player, x, y, z)
end

function SetPlayerCameraLookAt(amx, player, lx, ly, lz, cut)
if not player then
if not player then
return false
end
local x, y, z = getCameraMatrix(player)
Expand All @@ -1065,7 +1075,7 @@ function SetCameraBehindPlayer(amx, player)
end

function GetPlayerCameraPos(amx, player, refX, refY, refZ)
if not player then
if not player then
return false
end
local x, y, z = getCameraMatrix(player)
Expand All @@ -1076,7 +1086,7 @@ function GetPlayerCameraPos(amx, player, refX, refY, refZ)
end

function GetPlayerCameraFrontVector(amx, player, refX, refY, refZ)
if not player then
if not player then
return false
end

Expand Down