Last active
February 4, 2021 09:31
-
-
Save Toliak/e65a4b3f7e7f6f7d81a98e4cda092298 to your computer and use it in GitHub Desktop.
MTASA has some interesting caveats with NPC damage synchronization and processLineOfSight function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SERVER_SIDE = guiGetScreenSize == nil | |
CLIENT_SIDE = guiGetScreenSize ~= nil | |
--------------- | |
-- LIFECYCLE -- | |
--------------- | |
if SERVER_SIDE then | |
addEventHandler('onResourceStart', resourceRoot, function() | |
SERVER_PED_A = Ped(17, -1316, -59,15) | |
SERVER_PED_C = Ped(19, -1320, -59,15) | |
SERVER_PED_C:setRotation(0,0,270) | |
SERVER_PED_C:giveWeapon(25, 9999, true) | |
end) | |
addEvent('syncPed', true) | |
addEventHandler('syncPed', resourceRoot, function() | |
triggerClientEvent(root, 'syncPed', resourceRoot, SERVER_PED_A, SERVER_PED_C) | |
SYNCER_HOST = getPlayerFromName('toliak') | |
SYNCER_HELPER = getPlayerFromName('toliak_helper') | |
if SERVER_PED_A:getSyncer() ~= SYNCER_HOST then | |
SERVER_PED_A:setSyncer(SYNCER_HOST) | |
end | |
-- | |
if SERVER_PED_C:getSyncer() ~= SYNCER_HELPER then | |
SERVER_PED_C:setSyncer(SYNCER_HELPER) | |
end | |
end) | |
end | |
if CLIENT_SIDE then | |
addEventHandler('onClientResourceStart', resourceRoot, function() | |
triggerServerEvent('syncPed', resourceRoot) | |
end) | |
addEvent('syncPed', true) | |
addEventHandler('syncPed', resourceRoot, function(b,c) | |
CLIENT_PED_A = b | |
CLIENT_PED_C = c | |
local marker = Marker(0,0,0,'arrow',.5,0,255,0,200) | |
marker:attach(CLIENT_PED_A, 0, 0, 1.6) | |
end) | |
end | |
------------------- | |
-- LINE OF SIGHT -- | |
------------------- | |
if CLIENT_SIDE then | |
LOS_POSITION = {} | |
for i=1,10 do --100 | |
for j=1,5 do --50 | |
table.insert(LOS_POSITION, { | |
Vector3(-1331 + i/10, 23 - j*1.01,14.3), | |
Vector3(-1331 + i/10, 22 - j*1.01,14.3) | |
}) | |
end | |
end | |
lineOfSightElement = nil | |
addEventHandler('onClientPreRender', root, function() | |
if localPlayer.name ~= 'toliak' then | |
return | |
end | |
local hitElemenAccum = nil | |
for _,v in ipairs(LOS_POSITION) do | |
-- or isLineOfSightClear | |
local hit, x,y,z, hitElement = isLineOfSightClear( | |
v[1], | |
v[2]) | |
-- `not hit`, if `isLineOfSightClear` selected | |
hitElemenAccum = hitElemenAccum or not hit | |
end | |
lineOfSightElement = hitElemenAccum | |
end) | |
addEventHandler('onClientRender', root, function() | |
for _,v in ipairs(LOS_POSITION) do | |
dxDrawLine3D(v[1], v[2]) | |
end | |
end) | |
end | |
--------------- | |
-- STATISTIC -- | |
--------------- | |
if CLIENT_SIDE then | |
SCREEN_W, SCREEN_H = guiGetScreenSize() | |
addEventHandler('onClientPedDamage', root, function() | |
if source ~= CLIENT_PED_A then | |
return | |
end | |
outputChatBox(tostring(getRealTime().timestamp) .. ' damaged (client) ') | |
end) | |
addEventHandler('onClientRender', root, function() | |
if localPlayer.name ~= 'toliak' then | |
return | |
end | |
if not CLIENT_PED_A then | |
return | |
end | |
local syncerText = 'Not syncer' | |
if CLIENT_PED_A:isSyncer() then | |
syncerText = 'Syncer' | |
end | |
local streamedInText = 'Not streamed in' | |
if CLIENT_PED_A:isStreamedIn() then | |
streamedInText = 'Streamed in' | |
end | |
local streamableText = 'Always streamable' | |
if CLIENT_PED_A:isStreamable() then | |
streamableText = 'Streamable' | |
end | |
local position = ('%d %d %d'):format( | |
CLIENT_PED_A.position.x, | |
CLIENT_PED_A.position.y, | |
CLIENT_PED_A.position.z | |
) | |
dxDrawText( | |
tostring(math.floor(CLIENT_PED_A.health)) | |
.. '\n' .. syncerText | |
.. '\n'.. streamedInText | |
.. '\n' .. streamableText | |
.. '\n' .. position | |
.. '\n', | |
SCREEN_W - 600, | |
SCREEN_H - 500, | |
SCREEN_W, | |
SCREEN_H, | |
0xFFFFFFFF, | |
3.5 | |
) | |
end) | |
end | |
----------- | |
-- BINDS -- | |
----------- | |
if CLIENT_SIDE then | |
bindKey('num_2', 'down', function() | |
CLIENT_PED_C:setAimTarget(CLIENT_PED_A.position) | |
CLIENT_PED_C:setControlState('aim_weapon', true) | |
end) | |
bindKey('num_3', 'down', function() | |
CLIENT_PED_C:setControlState('fire', true) | |
end) | |
bindKey('num_3', 'up', function() | |
CLIENT_PED_C:setControlState('fire', false) | |
end) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment