mirror of
https://github.com/citizenfx/cfx-server-data.git
synced 2025-01-24 10:12:54 +08:00
initial
This commit is contained in:
commit
ee4dd89693
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
CitizenMP.Server.exe
|
||||
CitizenMP.Server.exe.config
|
||||
NLog.config
|
||||
/cache/
|
3
bin/README.txt
Normal file
3
bin/README.txt
Normal file
@ -0,0 +1,3 @@
|
||||
CitizenMP.Server.exe in bin/ is no longer use.
|
||||
|
||||
Please run the executable from the root directory.
|
40
citmp-server.yml
Normal file
40
citmp-server.yml
Normal file
@ -0,0 +1,40 @@
|
||||
ListenPort: 30120
|
||||
|
||||
PreParseResources:
|
||||
- mapmanager
|
||||
|
||||
AutoStartResources:
|
||||
- chat
|
||||
- spawnmanager
|
||||
- fivem-map-skater
|
||||
- baseevents
|
||||
- rconlog
|
||||
- hardcap # prevents too many players from joining
|
||||
- scoreboard
|
||||
|
||||
# do change
|
||||
RconPassword: lovely
|
||||
|
||||
# configure this, please
|
||||
Hostname: default FiveReborn server
|
||||
|
||||
# don't change this, it'll cause your server to be unlisted
|
||||
Game: GTA5
|
||||
|
||||
PlatformServer: updater.fivereborn.com
|
||||
|
||||
ScriptDebug: true
|
||||
|
||||
DebugLog: true
|
||||
|
||||
# set to false to hide from the online server list
|
||||
Announce: true
|
||||
|
||||
# set to false to require players to be signed in to Steam
|
||||
DisableAuth: true
|
||||
|
||||
# set to true to disable local script hook plugins
|
||||
DisableScriptHook: false
|
||||
|
||||
# set to the path of an icon to use in the server browser. it should be square.
|
||||
#ServerIcon: hello.png
|
BIN
mono/System.Runtime.InteropServices.RuntimeInformation.dll
Normal file
BIN
mono/System.Runtime.InteropServices.RuntimeInformation.dll
Normal file
Binary file not shown.
BIN
mono/libSystem.Native.so
Normal file
BIN
mono/libSystem.Native.so
Normal file
Binary file not shown.
3
resources/[gamemodes]/race-test/__resource.lua
Normal file
3
resources/[gamemodes]/race-test/__resource.lua
Normal file
@ -0,0 +1,3 @@
|
||||
resource_type 'map' { gameTypes = { race = true } }
|
||||
|
||||
map 'map.lua'
|
31
resources/[gamemodes]/race-test/map.lua
Normal file
31
resources/[gamemodes]/race-test/map.lua
Normal file
@ -0,0 +1,31 @@
|
||||
spawnpoint 'ig_brucie' { 1127.99, -569.018, 12.5918, heading = 270 }
|
||||
spawnpoint 'ig_brucie' { 1122.99, -569.018, 12.5918, heading = 270 }
|
||||
spawnpoint 'ig_brucie' { 1119.99, -569.018, 12.5918, heading = 270 }
|
||||
spawnpoint 'ig_brucie' { 1116.99, -569.018, 12.5918, heading = 270 }
|
||||
|
||||
checkpoint { pos = { 1175.38, -568.361, 12.9386 } }
|
||||
checkpoint { pos = { 1192.41, -484.373, 12.9902 } }
|
||||
checkpoint { pos = { 1370.24, -454.326, 16.1487 } }
|
||||
checkpoint { pos = { 1380.32, -319.673, 19.2937 } }
|
||||
checkpoint { pos = { 1153.19, -334.017, 17.6384 } }
|
||||
--[[checkpoint { pos = { 1120.66, -272.068, 19.6985 } }
|
||||
checkpoint { pos = { 1014.76, -270.757, 20.9716 } }
|
||||
checkpoint { pos = { 1018.3, -367.436, 18.9644 } }
|
||||
checkpoint { pos = { 634.072, -400.678, 40.1211 } }
|
||||
checkpoint { pos = { 218.425, -400.586, 14.506 } }
|
||||
checkpoint { pos = { 27.9617, -408.632, 13.7693 } }
|
||||
checkpoint { pos = { -0.9286, -625.767, 13.7056 } }
|
||||
checkpoint { pos = { -114.801, -646.633, 13.8117 } }
|
||||
checkpoint { pos = { -123.565, -785.028, 4.2556 } }
|
||||
checkpoint { pos = { 114.514, -730.95, 4.0023 } }
|
||||
checkpoint { pos = { 267.888, -668.781, 4.0181 } }
|
||||
checkpoint { pos = { 337.305, -509.17, 3.7381 } }
|
||||
checkpoint { pos = { 309.906, -407.719, 4.0468 } }
|
||||
checkpoint { pos = { 296.932, -253.16, 3.9989 } }
|
||||
checkpoint { pos = { 157.697, -234.079, 13.8108 } }
|
||||
checkpoint { pos = { 140.173, -389.505, 13.7984 } }
|
||||
checkpoint { pos = { 340.356, -415.681, 31.418 } }
|
||||
checkpoint { pos = { 566.093, -415.848, 39.5434 } }
|
||||
checkpoint { pos = { 909.641, -422.129, 36.4247 } }
|
||||
checkpoint { pos = { 1049.37, -416.408, 17.3975 } }
|
||||
checkpoint { pos = { 1091.72, -553.691, 12.5552 } }]]
|
9
resources/[gamemodes]/race/__resource.lua
Normal file
9
resources/[gamemodes]/race/__resource.lua
Normal file
@ -0,0 +1,9 @@
|
||||
resource_type 'gametype' { name = 'Race' }
|
||||
|
||||
dependencies {
|
||||
"spawnmanager",
|
||||
"mapmanager"
|
||||
}
|
||||
|
||||
client_script 'race_client.lua'
|
||||
server_script 'race_server.lua'
|
469
resources/[gamemodes]/race/race_client.lua
Normal file
469
resources/[gamemodes]/race/race_client.lua
Normal file
@ -0,0 +1,469 @@
|
||||
local curCheckpoint, nextCheckpoint
|
||||
local goGoGo
|
||||
|
||||
local playerCar
|
||||
local weFinished
|
||||
local resultsShown
|
||||
|
||||
local checkpoints = {}
|
||||
local playerScores = {}
|
||||
|
||||
local function initializeMap()
|
||||
echo("[RACE] initializeMap\n")
|
||||
|
||||
TriggerServerEvent('race:updateCheckpoints', checkpoints)
|
||||
end
|
||||
|
||||
local function resetGameMode()
|
||||
curCheckpoint = nil
|
||||
nextCheckpoint = nil
|
||||
|
||||
SetMultiplayerHudTime('')
|
||||
|
||||
checkpointCount = 0
|
||||
playerScores = {}
|
||||
|
||||
if IsThisMachineTheServer() then
|
||||
-- load the initial map
|
||||
initializeMap()
|
||||
end
|
||||
|
||||
goGoGo = false
|
||||
weFinished = false
|
||||
resultsShown = false
|
||||
end
|
||||
|
||||
local function updatePositions()
|
||||
local players = {}
|
||||
|
||||
for id, data in pairs(playerScores) do
|
||||
data.playerId = id
|
||||
|
||||
table.insert(players, data)
|
||||
end
|
||||
|
||||
table.sort(players, function(a, b)
|
||||
if a.finishPosition or b.finishPosition then
|
||||
if not b.finishPosition then
|
||||
return true
|
||||
end
|
||||
|
||||
if not a.finishPosition then
|
||||
return false
|
||||
end
|
||||
|
||||
return a.finishPosition < b.finishPosition
|
||||
end
|
||||
|
||||
if a.cp == b.cp then
|
||||
local aPed = a.ped
|
||||
local bPed = b.ped
|
||||
|
||||
local aPos
|
||||
local bPos
|
||||
|
||||
if not DoesCharExist(aPed) or not DoesCharExist(bPed) then
|
||||
aPos = { 0, 0 }
|
||||
bPos = { 0, 0 }
|
||||
else
|
||||
aPos = a.ped.position
|
||||
bPos = b.ped.position
|
||||
end
|
||||
|
||||
local nextCp = checkpoints[a.cp + 1]
|
||||
|
||||
if not nextCp then
|
||||
return a.cp > b.cp
|
||||
end
|
||||
|
||||
local aDist = GetDistanceBetweenCoords2d(aPos[1], aPos[2], nextCp.pos[1], nextCp.pos[2])
|
||||
local bDist = GetDistanceBetweenCoords2d(bPos[1], bPos[2], nextCp.pos[1], nextCp.pos[2])
|
||||
|
||||
return aDist < bDist
|
||||
end
|
||||
|
||||
return a.cp > b.cp
|
||||
end)
|
||||
|
||||
if not playerScores[GetPlayerId().serverId] then
|
||||
return
|
||||
end
|
||||
|
||||
local lastPosition = selfLastPosition
|
||||
|
||||
local i = 1
|
||||
|
||||
for _, v in ipairs(players) do
|
||||
playerScores[v.playerId].position = i
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
local selfPosition = playerScores[GetPlayerId().serverId].position
|
||||
selfLastPosition = selfPosition
|
||||
|
||||
if selfPosition ~= lastPosition then
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, 'position changed to ' .. tostring(selfPosition) .. ' from ' .. tostring(lastPosition))
|
||||
end
|
||||
|
||||
|
||||
-- positions updated, we hope
|
||||
end
|
||||
|
||||
AddEventHandler('race:onPlayerFinished', function(player, data)
|
||||
local selfId = GetPlayerId().serverId
|
||||
|
||||
if not playerScores[player] then
|
||||
local ped = sPlayer.ped
|
||||
|
||||
playerScores[player] = {
|
||||
cp = #checkpoints,
|
||||
ped = ped,
|
||||
vehicle = ped.vehicle
|
||||
}
|
||||
end
|
||||
|
||||
playerScores[player].finishPosition = data.position
|
||||
|
||||
if selfId == player then
|
||||
exports.obituary:printObituary('New world record!')
|
||||
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, 'you finished!')
|
||||
|
||||
weFinished = true
|
||||
|
||||
tearDownCheckpoint(curCheckpoint)
|
||||
tearDownCheckpoint(nextCheckpoint)
|
||||
|
||||
-- todo: spectate?
|
||||
|
||||
CreateThread(function()
|
||||
Wait(500)
|
||||
|
||||
if playerCar then
|
||||
FreezeCarPosition(playerCar, true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local sPlayer = GetPlayerByServerId(player)
|
||||
|
||||
if sPlayer then
|
||||
exports.obituary:printObituary('<b>%s</b> finished in %s seconds', sPlayer.name, tostring(data.finishSeconds))
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('onClientGameTypeStart', function()
|
||||
CreateThread(function()
|
||||
--[[while true do
|
||||
Wait(500)
|
||||
|
||||
local player = GetPlayerId()
|
||||
|
||||
TriggerServerEvent('race:updatePos', player.ped.position)
|
||||
end]]
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(250)
|
||||
|
||||
updatePositions()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
function GetPlayerInteger(i)
|
||||
local serverId = i.serverId
|
||||
local players = GetPlayers()
|
||||
|
||||
for k, v in ipairs(players) do
|
||||
if v.serverId == serverId then
|
||||
return k
|
||||
end
|
||||
end
|
||||
|
||||
return 1
|
||||
end
|
||||
|
||||
local function spawnVehicle(spawnPoint)
|
||||
local carModel
|
||||
|
||||
if not spawnPoint.carModel then
|
||||
carModel = 'admiral'
|
||||
else
|
||||
carModel = spawnPoint.carModel
|
||||
end
|
||||
|
||||
if not tonumber(carModel) then
|
||||
carModel = GetHashKey(carModel, _r)
|
||||
end
|
||||
|
||||
-- is the model actually a model?
|
||||
if not IsModelInCdimage(carModel) then
|
||||
error("invalid spawn model")
|
||||
end
|
||||
|
||||
-- is is even a vehicle?
|
||||
if not IsThisModelAVehicle(carModel) then
|
||||
error("this model ain't a vehicle!")
|
||||
end
|
||||
|
||||
-- spawn a vehicle for our lovely player
|
||||
RequestModel(carModel)
|
||||
LoadAllObjectsNow()
|
||||
|
||||
playerCar = CreateCar(carModel, spawnPoint.x, spawnPoint.y, spawnPoint.z, 0, 1)
|
||||
SetCarHeading(playerCar, spawnPoint.heading)
|
||||
SetCarOnGroundProperly(playerCar)
|
||||
|
||||
WarpCharIntoCar(GetPlayerId().ped, playerCar)
|
||||
|
||||
if not goGoGo then
|
||||
FreezeCarPosition(playerCar, true)
|
||||
end
|
||||
|
||||
LockCarDoors(playerCar, 4)
|
||||
|
||||
-- and done, hopefully.
|
||||
end
|
||||
|
||||
AddEventHandler('race:itsGoTime', function()
|
||||
if playerCar then
|
||||
-- let go of the brakes
|
||||
FreezeCarPosition(playerCar, false)
|
||||
end
|
||||
|
||||
-- gogogo
|
||||
goGoGo = true
|
||||
end)
|
||||
|
||||
string.lpad = function(str, len, char)
|
||||
if char == nil then char = ' ' end
|
||||
return string.rep(char, len - #str) .. str
|
||||
end
|
||||
|
||||
AddEventHandler('race:results', function(time)
|
||||
if playerCar then
|
||||
FreezeCarPosition(playerCar, true)
|
||||
end
|
||||
|
||||
tearDownCheckpoint(curCheckpoint)
|
||||
tearDownCheckpoint(nextCheckpoint)
|
||||
|
||||
SetMultiplayerHudTime('')
|
||||
|
||||
updatePositions()
|
||||
|
||||
local players = {}
|
||||
|
||||
for id, data in pairs(playerScores) do
|
||||
table.insert(players, data)
|
||||
end
|
||||
|
||||
table.sort(players, function(a, b) return a.position < b.position end)
|
||||
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, 'RESULTS')
|
||||
|
||||
for i, p in ipairs(players) do
|
||||
local name = '**INVALID**'
|
||||
local sp = GetPlayerByServerId(p.playerId)
|
||||
|
||||
if sp then
|
||||
name = sp.name
|
||||
end
|
||||
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, tostring(i) .. '. ' .. name)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('race:hurryUp', function(time)
|
||||
CreateThread(function()
|
||||
echo("resultsShown: " .. tostring(resultsShown) .. " , weF: " .. tostring(weFinished) .. "\n")
|
||||
|
||||
while not resultsShown and not weFinished do
|
||||
Wait(1000)
|
||||
|
||||
time = time - 1000
|
||||
|
||||
SetMultiplayerHudTime('00:' .. tostring(math.floor(time / 1000)):lpad(2, '0'))
|
||||
echo(tostring(math.floor(time / 1000)):lpad(2, '0') .. ':' .. tostring(math.floor((time % 1000) / 100)):lpad(2, '0') .. "\n")
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler('race:showGoMessage', function(message)
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, message)
|
||||
end)
|
||||
|
||||
AddEventHandler('onClientMapStart', function(res)
|
||||
resetGameMode()
|
||||
|
||||
requestedGo = true
|
||||
|
||||
TriggerServerEvent('race:requestGo')
|
||||
end)
|
||||
|
||||
AddEventHandler('onClientMapStop', function(res)
|
||||
DoScreenFadeOut(50)
|
||||
end)
|
||||
|
||||
AddEventHandler('race:weGotPorn', function()
|
||||
echo("[RACE] race:weGotPorn\n")
|
||||
|
||||
if not requestedGo then
|
||||
return
|
||||
end
|
||||
|
||||
requestedGo = false
|
||||
|
||||
exports.spawnmanager:setAutoSpawn(false)
|
||||
|
||||
exports.spawnmanager:spawnPlayer(GetPlayerInteger(GetPlayerId()), function(spawnPoint)
|
||||
spawnVehicle(spawnPoint)
|
||||
end)
|
||||
|
||||
TriggerServerEvent('race:requestCheckpoint', '1234')
|
||||
end)
|
||||
|
||||
local function setUpCheckpoint(cp, next)
|
||||
local nextPos, typeNum
|
||||
|
||||
if next then
|
||||
nextPos = next.pos
|
||||
typeNum = 2
|
||||
else
|
||||
nextPos = { 0.0, 0.0, 0.0 }
|
||||
typeNum = 3
|
||||
end
|
||||
|
||||
-- 2 = regular 'ground', 3 = finish 'ground', others are different 3dmarker types
|
||||
cp.handle = CreateCheckpoint(typeNum, cp.pos[1], cp.pos[2], cp.pos[3] + 2.5, nextPos[1], nextPos[2], nextPos[3], 1.0001, _r)
|
||||
cp.blip = AddBlipForCoord(cp.pos[1], cp.pos[2], cp.pos[3], _i)
|
||||
|
||||
if cp == nextCheckpoint then
|
||||
ChangeBlipScale(cp.blip, 0.8)
|
||||
end
|
||||
|
||||
ChangeBlipSprite(cp.blip, 3)
|
||||
end
|
||||
|
||||
function tearDownCheckpoint(cp)
|
||||
if not cp then
|
||||
return
|
||||
end
|
||||
|
||||
if cp.blip then
|
||||
RemoveBlip(cp.blip)
|
||||
cp.blip = nil
|
||||
end
|
||||
|
||||
if cp.handle then
|
||||
DeleteCheckpoint(cp.handle)
|
||||
cp.handle = nil
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler('race:setCheckpoint', function(cur, next, later)
|
||||
if curCheckpoint then
|
||||
tearDownCheckpoint(curCheckpoint)
|
||||
end
|
||||
|
||||
if nextCheckpoint then
|
||||
tearDownCheckpoint(nextCheckpoint)
|
||||
end
|
||||
|
||||
curCheckpoint = cur
|
||||
nextCheckpoint = next
|
||||
|
||||
if cur then
|
||||
setUpCheckpoint(curCheckpoint, nextCheckpoint)
|
||||
|
||||
-- make a background thread waiting for the checkpoint to be reached
|
||||
CreateThread(function()
|
||||
local localCur = curCheckpoint
|
||||
|
||||
-- so we exit if the checkpoint target is changed
|
||||
while curCheckpoint == localCur do
|
||||
Wait(25)
|
||||
|
||||
if playerCar then
|
||||
local px, py, pz = GetCarCoordinates(playerCar)
|
||||
local distance = GetDistanceBetweenCoords2d(px, py, localCur.pos[1], localCur.pos[2])
|
||||
|
||||
if distance < 10 then
|
||||
-- pass the fact we reached the checkpoint to the server
|
||||
TriggerServerEvent('race:gotCP', '1234')
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if next then
|
||||
setUpCheckpoint(nextCheckpoint, later)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('race:confirmCP', function()
|
||||
PlayAudioEvent('FRONTEND_GAME_PICKUP_CHECKPOINT')
|
||||
end)
|
||||
|
||||
AddEventHandler('race:updateStatus', function(player, curCP)
|
||||
if curCP == -1 then
|
||||
playerScores[player] = nil
|
||||
end
|
||||
|
||||
local sPlayer = GetPlayerByServerId(player)
|
||||
|
||||
if not sPlayer then
|
||||
return
|
||||
end
|
||||
|
||||
local ped = sPlayer.ped
|
||||
|
||||
playerScores[player] = {
|
||||
cp = curCP,
|
||||
ped = ped,
|
||||
vehicle = ped.vehicle
|
||||
}
|
||||
|
||||
TriggerEvent('chatMessage', '', { 0, 0, 0 }, sPlayer.name .. ' now has cp ' .. curCP)
|
||||
|
||||
updatePositions()
|
||||
end)
|
||||
|
||||
AddEventHandler('onClientMapStop', function()
|
||||
if playerCar then
|
||||
MarkCarAsNoLongerNeeded(playerCar)
|
||||
playerCar = nil
|
||||
end
|
||||
|
||||
if curCheckpoint and curCheckpoint.handle then
|
||||
DeleteCheckpoint(curCheckpoint.handle)
|
||||
end
|
||||
|
||||
if nextCheckpoint and nextCheckpoint.handle then
|
||||
DeleteCheckpoint(nextCheckpoint.handle)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('getMapDirectives', function(add)
|
||||
-- call the remote callback
|
||||
add('checkpoint', function(state, data)
|
||||
table.insert(checkpoints, data)
|
||||
|
||||
state.add('pos', data.pos)
|
||||
|
||||
-- delete callback follows on the next line
|
||||
end, function(state, arg)
|
||||
for i, sp in ipairs(checkpoints) do
|
||||
if sp.pos[1] == state.pos[1] and sp.pos[2] == state.pos[2] and sp.pos[3] == state.pos[3] then
|
||||
table.remove(checkpoints, i)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
209
resources/[gamemodes]/race/race_server.lua
Normal file
209
resources/[gamemodes]/race/race_server.lua
Normal file
@ -0,0 +1,209 @@
|
||||
local checkpoints = {}
|
||||
local raceId = 0
|
||||
|
||||
RegisterServerEvent('race:updateCheckpoints')
|
||||
|
||||
AddEventHandler('race:updateCheckpoints', function(cps)
|
||||
if #checkpoints > 0 then
|
||||
return
|
||||
end
|
||||
|
||||
checkpoints = cps
|
||||
|
||||
TriggerClientEvent('race:weGotPorn', -1)
|
||||
end)
|
||||
|
||||
local playerData = {}
|
||||
|
||||
local function ensurePlayerData(id)
|
||||
if playerData[id] then
|
||||
return
|
||||
end
|
||||
|
||||
playerData[id] = {
|
||||
curCheckpoint = 0
|
||||
}
|
||||
end
|
||||
|
||||
local raceStarted = false
|
||||
local playerCount = 0
|
||||
|
||||
local function startRace()
|
||||
raceStarted = true
|
||||
|
||||
print("really starting race")
|
||||
|
||||
local function raceCountdown(num)
|
||||
local time = (4000 - (num * 1000))
|
||||
|
||||
print("setting countdown for " .. tostring(time))
|
||||
|
||||
SetTimeout(time, function()
|
||||
print("trig'd countdown for " .. tostring(time))
|
||||
|
||||
if num == 0 then
|
||||
TriggerClientEvent('race:itsGoTime', -1, 0)
|
||||
TriggerClientEvent('race:showGoMessage', -1, 'GO')
|
||||
else
|
||||
TriggerClientEvent('race:showGoMessage', -1, tostring(num))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
raceCountdown(3) -- 3...
|
||||
raceCountdown(2) -- 2...
|
||||
raceCountdown(1) -- 1...
|
||||
raceCountdown(0) -- GOGOGO
|
||||
end
|
||||
|
||||
local function incrementPlayerCount()
|
||||
playerCount = playerCount + 1
|
||||
|
||||
if playerCount > 4 then
|
||||
startRace()
|
||||
end
|
||||
|
||||
if playerCount == 1 then
|
||||
SetTimeout(3000, function()
|
||||
if raceStarted then
|
||||
return
|
||||
end
|
||||
|
||||
print("starting race")
|
||||
|
||||
startRace()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local playersFinished
|
||||
local raceEnded
|
||||
|
||||
AddEventHandler('onMapStart', function()
|
||||
playerCount = 0
|
||||
playersFinished = 0
|
||||
raceId = raceId + 1
|
||||
raceStarted = false
|
||||
raceEnded = false
|
||||
|
||||
playerData = {}
|
||||
checkpoints = {}
|
||||
|
||||
print("mmmmmm race")
|
||||
end)
|
||||
|
||||
local function endRace()
|
||||
raceEnded = true
|
||||
|
||||
TriggerClientEvent('race:results', -1, '1234')
|
||||
|
||||
SetTimeout(7500, function()
|
||||
TriggerEvent('mapmanager:roundEnded')
|
||||
end)
|
||||
end
|
||||
|
||||
AddEventHandler('race:onPlayerFinished', function(player)
|
||||
print(GetPlayerName(player) .. ' finished')
|
||||
|
||||
local data = playerData[player]
|
||||
local finishSeconds = os.clock() - data.startTime
|
||||
|
||||
local position = playersFinished + 1
|
||||
data.position = position
|
||||
playersFinished = position
|
||||
|
||||
TriggerClientEvent('race:onPlayerFinished', -1, player, {
|
||||
finishSeconds = finishSeconds,
|
||||
position = position
|
||||
})
|
||||
|
||||
if playersFinished == playerCount then
|
||||
endRace()
|
||||
elseif playersFinished == 1 then
|
||||
local thisRaceId = raceId
|
||||
|
||||
TriggerClientEvent('race:hurryUp', -1, 30000)
|
||||
|
||||
SetTimeout(30000, function()
|
||||
if raceId ~= thisRaceId or raceEnded then
|
||||
return
|
||||
end
|
||||
|
||||
endRace()
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerActivated', function()
|
||||
if #checkpoints > 0 then
|
||||
TriggerClientEvent('race:weGotPorn', source)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterServerEvent('race:requestGo')
|
||||
|
||||
AddEventHandler('race:requestGo', function()
|
||||
if #checkpoints > 0 then
|
||||
TriggerClientEvent('race:weGotPorn', source)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function(player)
|
||||
if playerData[player] and playerData[player].curCheckpoint > 0 then
|
||||
TriggerClientEvent('race:updateStatus', -1, player, -1)
|
||||
|
||||
playerCount = playerCount - 1
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterServerEvent('race:gotCP')
|
||||
|
||||
AddEventHandler('race:gotCP', function()
|
||||
ensurePlayerData(source)
|
||||
|
||||
local data = playerData[source]
|
||||
|
||||
local next = data.curCheckpoint + 1
|
||||
|
||||
if next > #checkpoints then
|
||||
print("omg finished")
|
||||
|
||||
TriggerEvent('race:onPlayerFinished', source)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
data.curCheckpoint = next
|
||||
|
||||
TriggerClientEvent('race:confirmCP', source) -- for sound effects
|
||||
TriggerClientEvent('race:setCheckpoint', source, checkpoints[next], checkpoints[next + 1], checkpoints[next + 2])
|
||||
TriggerClientEvent('race:updateStatus', -1, source, next - 1)
|
||||
end)
|
||||
|
||||
RegisterServerEvent('race:requestCheckpoint')
|
||||
|
||||
AddEventHandler('race:requestCheckpoint', function()
|
||||
print('is it even in here')
|
||||
|
||||
ensurePlayerData(source)
|
||||
|
||||
print(source, 'requesting cp')
|
||||
|
||||
if playerData[source].curCheckpoint == 0 then
|
||||
incrementPlayerCount()
|
||||
|
||||
print(source, 'requesting cp 0')
|
||||
|
||||
local curCP = 1
|
||||
playerData[source].curCheckpoint = curCP
|
||||
playerData[source].startTime = os.clock()
|
||||
|
||||
TriggerClientEvent('race:setCheckpoint', source, checkpoints[curCP], checkpoints[curCP + 1], checkpoints[curCP + 2])
|
||||
TriggerClientEvent('race:updateStatus', -1, source, 0)
|
||||
|
||||
-- should have raceReallyStarted since 4-second countdown
|
||||
if raceStarted then
|
||||
TriggerClientEvent('race:itsGoTime', -1, 0)
|
||||
end
|
||||
end
|
||||
end)
|
18
resources/[gameplay]/channelfeed/__resource.lua
Normal file
18
resources/[gameplay]/channelfeed/__resource.lua
Normal file
@ -0,0 +1,18 @@
|
||||
description 'output lists for game content'
|
||||
|
||||
SetResourceInfo('uiPage', 'client/html/index.html')
|
||||
|
||||
client_script 'client/channelfeed.lua'
|
||||
|
||||
export 'printTo'
|
||||
export 'addChannel'
|
||||
export 'removeChannel'
|
||||
|
||||
files
|
||||
{
|
||||
'client/html/index.html',
|
||||
'client/html/feed.js',
|
||||
'client/html/feed.css',
|
||||
'client/fonts/roboto-regular.ttf',
|
||||
'client/fonts/roboto-condensed.ttf',
|
||||
}
|
40
resources/[gameplay]/channelfeed/client/channelfeed.lua
Normal file
40
resources/[gameplay]/channelfeed/client/channelfeed.lua
Normal file
@ -0,0 +1,40 @@
|
||||
local eventBuffer = {}
|
||||
|
||||
AddUIHandler('getNew', function(data, cb)
|
||||
local localBuf = eventBuffer
|
||||
eventBuffer = {}
|
||||
|
||||
cb(localBuf)
|
||||
end)
|
||||
|
||||
function printTo(channel, data)
|
||||
table.insert(eventBuffer, {
|
||||
meta = 'print',
|
||||
channel = channel,
|
||||
data = data
|
||||
})
|
||||
|
||||
PollUI()
|
||||
end
|
||||
|
||||
function addChannel(id, options)
|
||||
if not options.template then
|
||||
return
|
||||
end
|
||||
|
||||
options.id = id
|
||||
|
||||
table.insert(eventBuffer, {
|
||||
meta = 'addChannel',
|
||||
data = options
|
||||
})
|
||||
|
||||
PollUI()
|
||||
end
|
||||
|
||||
function removeChannel(id)
|
||||
table.insert(eventBuffer, {
|
||||
meta = 'removeChannel',
|
||||
data = id
|
||||
})
|
||||
end
|
Binary file not shown.
BIN
resources/[gameplay]/channelfeed/client/fonts/roboto-regular.ttf
Normal file
BIN
resources/[gameplay]/channelfeed/client/fonts/roboto-regular.ttf
Normal file
Binary file not shown.
118
resources/[gameplay]/channelfeed/client/html/feed.js
Normal file
118
resources/[gameplay]/channelfeed/client/html/feed.js
Normal file
@ -0,0 +1,118 @@
|
||||
(function() {
|
||||
var getLock = 0;
|
||||
|
||||
var channels = {};
|
||||
|
||||
var zoomLevel = '100%';
|
||||
|
||||
$(function()
|
||||
{
|
||||
zoomLevel = Math.round(($(window).height() / 720) * 100) + '%'; // yay dynamic typing
|
||||
});
|
||||
|
||||
function refetchData()
|
||||
{
|
||||
getLock = 0;
|
||||
|
||||
$.get('http://channelfeed/getNew', function(data)
|
||||
{
|
||||
if (getLock > 1)
|
||||
{
|
||||
setTimeout(refetchData, 50);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getLock++;
|
||||
|
||||
data.forEach(function(item)
|
||||
{
|
||||
switch (item.meta)
|
||||
{
|
||||
case 'print':
|
||||
var channel = item.channel;
|
||||
|
||||
if (!(channel in channels))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel = channels[channel];
|
||||
|
||||
var elem = $($.Mustache.render(item.channel, item.data, { method: channel.method })).appendTo(channel.$elem);
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
elem.fadeOut(400, function()
|
||||
{
|
||||
elem.remove();
|
||||
});
|
||||
}, 7500);
|
||||
|
||||
break;
|
||||
|
||||
case 'addChannel':
|
||||
var channel = item.data;
|
||||
|
||||
if (channel.id in channels)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel.$elem = $('<div></div>').attr('id', 'channel-' + channel.id).appendTo('#channels');
|
||||
|
||||
if (channel.styles !== undefined)
|
||||
{
|
||||
channel.$elem.css(channel.styles);
|
||||
}
|
||||
|
||||
channel.$elem = $('<div></div>').css('zoom', zoomLevel).appendTo(channel.$elem);
|
||||
|
||||
if (channel.styleUrl !== undefined)
|
||||
{
|
||||
$('<link>').appendTo('head').attr({ type: 'text/css', rel: 'stylesheet' }).attr('href', channel.styleUrl);
|
||||
}
|
||||
|
||||
$.Mustache.add(channel.id, channel.template);
|
||||
|
||||
channels[channel.id] = channel;
|
||||
|
||||
break;
|
||||
case 'removeChannel':
|
||||
var channelId = item.data;
|
||||
|
||||
if (channelId in channels)
|
||||
{
|
||||
channel.$elem.parent().remove();
|
||||
|
||||
delete channels[channelId];
|
||||
}
|
||||
|
||||
break;
|
||||
case 'clear':
|
||||
var channel = item.channel;
|
||||
|
||||
if (!(channel in channels))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
channel = channels[channel];
|
||||
|
||||
channel.$elem.html();
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('message', function(event)
|
||||
{
|
||||
if (event.data.type != 'poll')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
refetchData();
|
||||
});
|
||||
})();
|
13
resources/[gameplay]/channelfeed/client/html/index.html
Normal file
13
resources/[gameplay]/channelfeed/client/html/index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
|
||||
<script src="nui://game/ui/mustache.js" type="text/javascript"></script>
|
||||
<script src="nui://game/ui/jquery.mustache.js" type="text/javascript"></script>
|
||||
<script src="feed.js" type="text/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="channels">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
BIN
resources/[gameplay]/irc/ChatSharp.dll
Normal file
BIN
resources/[gameplay]/irc/ChatSharp.dll
Normal file
Binary file not shown.
1
resources/[gameplay]/irc/__resource.lua
Normal file
1
resources/[gameplay]/irc/__resource.lua
Normal file
@ -0,0 +1 @@
|
||||
server_script 'irc.lua'
|
4
resources/[gameplay]/irc/irc.lua
Normal file
4
resources/[gameplay]/irc/irc.lua
Normal file
@ -0,0 +1,4 @@
|
||||
local reflection = clr.System.Reflection
|
||||
local assembly = reflection.Assembly.LoadFrom('resources/[gameplay]/irc/ChatSharp.dll')
|
||||
|
||||
dofile('resources/[gameplay]/irc/irc_run.lua')
|
91
resources/[gameplay]/irc/irc_run.lua
Normal file
91
resources/[gameplay]/irc/irc_run.lua
Normal file
@ -0,0 +1,91 @@
|
||||
local chatSharp = clr.ChatSharp
|
||||
|
||||
local client = chatSharp.IrcClient('irc.rizon.net', chatSharp.IrcUser('citimate', 'mateyate'), false)
|
||||
|
||||
-- temporary workaround for connections that never triggered playerActivated but triggered playerDropped
|
||||
local activatedPlayers = {}
|
||||
|
||||
client.ConnectionComplete:add(function(s : object, e : System.EventArgs) : void
|
||||
client:JoinChannel('#meow')
|
||||
end)
|
||||
|
||||
-- why is 'received' even misspelled here?
|
||||
client.ChannelMessageRecieved:add(function(s : object, e : ChatSharp.Events.PrivateMessageEventArgs) : void
|
||||
local msg = e.PrivateMessage
|
||||
|
||||
TriggerClientEvent('chatMessage', -1, msg.User.Nick, { 0, 0x99, 255 }, msg.Message)
|
||||
end)
|
||||
|
||||
AddEventHandler('playerActivated', function()
|
||||
client:SendMessage('* ' .. GetPlayerName(source) .. '(' .. GetPlayerGuid(source) .. '@' .. GetPlayerEP(source) .. ') joined the server', '#fourdeltaone')
|
||||
table.insert(activatedPlayers, GetPlayerGuid(source))
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function()
|
||||
-- find out if this connection ever triggered playerActivated
|
||||
for index,guid in pairs(activatedPlayers) do
|
||||
if guid == playerGuid then
|
||||
-- show player dropping connection in chat
|
||||
client:SendMessage('* ' .. GetPlayerName(source) .. '(' .. GetPlayerGuid(source) .. '@' .. GetPlayerEP(source) .. ') left the server', '#fourdeltaone')
|
||||
table.remove(activatedPlayers, index)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('chatMessage', function(source, name, message)
|
||||
print('hey there ' .. name)
|
||||
|
||||
local displayMessage = gsub(message, '^%d', '')
|
||||
|
||||
-- ignore zero-length messages
|
||||
if string.len(displayMessage) == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- ignore chat messages that are actually commands
|
||||
if string.sub(displayMessage, 1, 1) == "/" then
|
||||
return
|
||||
end
|
||||
|
||||
client:SendMessage('[' .. tostring(GetPlayerName(source)) .. ']: ' .. displayMessage, '#fourdeltaone')
|
||||
end)
|
||||
|
||||
AddEventHandler('onPlayerKilled', function(playerId, attackerId, reason, position)
|
||||
local player = GetPlayerByServerId(playerId)
|
||||
local attacker = GetPlayerByServerId(attackerId)
|
||||
|
||||
local reasonString = 'killed'
|
||||
|
||||
if reason == 0 or reason == 56 or reason == 1 or reason == 2 then
|
||||
reasonString = 'meleed'
|
||||
elseif reason == 3 then
|
||||
reasonString = 'knifed'
|
||||
elseif reason == 4 or reason == 6 or reason == 18 or reason == 51 then
|
||||
reasonString = 'bombed'
|
||||
elseif reason == 5 or reason == 19 then
|
||||
reasonString = 'burned'
|
||||
elseif reason == 7 or reason == 9 then
|
||||
reasonString = 'pistoled'
|
||||
elseif reason == 10 or reason == 11 then
|
||||
reasonString = 'shotgunned'
|
||||
elseif reason == 12 or reason == 13 or reason == 52 then
|
||||
reasonString = 'SMGd'
|
||||
elseif reason == 14 or reason == 15 or reason == 20 then
|
||||
reasonString = 'assaulted'
|
||||
elseif reason == 16 or reason == 17 then
|
||||
reasonString = 'sniped'
|
||||
elseif reason == 49 or reason == 50 then
|
||||
reasonString = 'ran over'
|
||||
end
|
||||
|
||||
client:SendMessage('* ' .. attacker.name .. ' ' .. reasonString .. ' ' .. player.name, '#fourdeltaone')
|
||||
end)
|
||||
|
||||
client:ConnectAsync()
|
||||
|
||||
AddEventHandler('onResourceStop', function(name)
|
||||
if name == GetInvokingResource() then
|
||||
client:Quit('Resource stopping.')
|
||||
end
|
||||
end)
|
5
resources/[gameplay]/obituary-deaths/__resource.lua
Normal file
5
resources/[gameplay]/obituary-deaths/__resource.lua
Normal file
@ -0,0 +1,5 @@
|
||||
dependency 'obituary'
|
||||
|
||||
description 'death messages using the obituary resource'
|
||||
|
||||
client_script 'deathmessages.lua'
|
42
resources/[gameplay]/obituary-deaths/deathmessages.lua
Normal file
42
resources/[gameplay]/obituary-deaths/deathmessages.lua
Normal file
@ -0,0 +1,42 @@
|
||||
AddEventHandler('onPlayerDied', function(playerId, reason, position)
|
||||
local player = GetPlayerByServerId(playerId)
|
||||
|
||||
if player then
|
||||
exports.obituary:printObituary('<b>%s</b> died.', player.name)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('onPlayerKilled', function(playerId, attackerId, reason, position)
|
||||
local player = GetPlayerByServerId(playerId)
|
||||
local attacker = GetPlayerByServerId(attackerId)
|
||||
|
||||
local reasonString = 'killed'
|
||||
|
||||
if reason == 0 or reason == 56 or reason == 1 or reason == 2 then
|
||||
reasonString = 'meleed'
|
||||
elseif reason == 3 then
|
||||
reasonString = 'knifed'
|
||||
elseif reason == 4 or reason == 6 or reason == 18 or reason == 51 then
|
||||
reasonString = 'bombed'
|
||||
elseif reason == 5 or reason == 19 then
|
||||
reasonString = 'burned'
|
||||
elseif reason == 7 or reason == 9 then
|
||||
reasonString = 'pistoled'
|
||||
elseif reason == 10 or reason == 11 then
|
||||
reasonString = 'shotgunned'
|
||||
elseif reason == 12 or reason == 13 or reason == 52 then
|
||||
reasonString = 'SMGd'
|
||||
elseif reason == 14 or reason == 15 or reason == 20 then
|
||||
reasonString = 'assaulted'
|
||||
elseif reason == 16 or reason == 17 then
|
||||
reasonString = 'sniped'
|
||||
elseif reason == 49 or reason == 50 then
|
||||
reasonString = 'ran over'
|
||||
end
|
||||
|
||||
echo("obituary-deaths: onPlayerKilled\n")
|
||||
|
||||
if player and attacker then
|
||||
exports.obituary:printObituary('<b>%s</b> %s <b>%s</b>.', attacker.name, reasonString, player.name)
|
||||
end
|
||||
end)
|
7
resources/[gameplay]/obituary/__resource.lua
Normal file
7
resources/[gameplay]/obituary/__resource.lua
Normal file
@ -0,0 +1,7 @@
|
||||
dependency 'channelfeed'
|
||||
|
||||
client_script 'obituary.lua'
|
||||
|
||||
export 'printObituary'
|
||||
|
||||
files 'obituary.css'
|
46
resources/[gameplay]/obituary/obituary.css
Normal file
46
resources/[gameplay]/obituary/obituary.css
Normal file
@ -0,0 +1,46 @@
|
||||
@font-face {
|
||||
font-family: 'Roboto Condensed';
|
||||
src: url('nui://channelfeed/client/fonts/roboto-condensed.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
src: url('nui://channelfeed/client/fonts/roboto-regular.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#channel-obituary
|
||||
{
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#channel-obituary > div
|
||||
{
|
||||
width: 100%;
|
||||
|
||||
font-family: 'Roboto';
|
||||
}
|
||||
|
||||
#channel-obituary div.item
|
||||
{
|
||||
background-color: rgba(50, 50, 50, .6);
|
||||
padding: 4px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
border-radius: 4px;
|
||||
color: #eee;
|
||||
margin-bottom: 3px;
|
||||
|
||||
font-size: 65%;
|
||||
}
|
||||
|
||||
#channel-obituary div.item b
|
||||
{
|
||||
font-family: 'Roboto Condensed';
|
||||
font-size: 125%;
|
||||
font-weight: normal;
|
||||
color: #09f;
|
||||
}
|
51
resources/[gameplay]/obituary/obituary.lua
Normal file
51
resources/[gameplay]/obituary/obituary.lua
Normal file
@ -0,0 +1,51 @@
|
||||
AddEventHandler('onClientResourceStart', function(name)
|
||||
if name == GetCurrentResource() then
|
||||
local x, y = GetHudPosition('HUD_RADAR')
|
||||
local w, h = GetHudSize('HUD_RADAR')
|
||||
|
||||
x = x - 0.01
|
||||
w = w + 0.02
|
||||
|
||||
if GetIsWidescreen() then
|
||||
x = x / 1.333
|
||||
w = w / 1.333
|
||||
end
|
||||
|
||||
exports.channelfeed:addChannel('obituary', {
|
||||
method = 'append',
|
||||
styleUrl = 'nui://obituary/obituary.css',
|
||||
styles = { -- temporary
|
||||
left = tostring(x * 100) .. '%',
|
||||
bottom = 'calc(' .. tostring((1 - y) * 100) .. '% + 10px)',
|
||||
width = tostring(w * 100) .. '%'
|
||||
},
|
||||
template = '<div class="item">{{{text}}}</div>'
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
function printObituary(format, ...)
|
||||
local args = table.pack(...)
|
||||
|
||||
for i = 1, args.n do
|
||||
if type(args[i]) == 'string' then
|
||||
args[i] = args[i]:gsub('<', '<')
|
||||
end
|
||||
end
|
||||
|
||||
echo("obituary: printObituary\n")
|
||||
|
||||
exports.channelfeed:printTo('obituary', {
|
||||
text = string.format(format, table.unpack(args))
|
||||
})
|
||||
end
|
||||
|
||||
--[[AddEventHandler('chatMessage', function(name, color, message)
|
||||
exports.channelfeed:printTo('obituary', {
|
||||
text = message:gsub('<', '<')
|
||||
})
|
||||
end)]]
|
||||
|
||||
AddEventHandler('onClientResourceStop', function()
|
||||
-- todo: remove channel
|
||||
end)
|
9
resources/[managers]/mapmanager/__resource.lua
Normal file
9
resources/[managers]/mapmanager/__resource.lua
Normal file
@ -0,0 +1,9 @@
|
||||
client_scripts {
|
||||
"mapmanager_client.lua",
|
||||
"mapmanager_shared.lua"
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
"mapmanager_server.lua",
|
||||
"mapmanager_shared.lua"
|
||||
}
|
200
resources/[managers]/mapmanager/mapmanager_client.lua
Normal file
200
resources/[managers]/mapmanager/mapmanager_client.lua
Normal file
@ -0,0 +1,200 @@
|
||||
maps = {}
|
||||
gametypes = {}
|
||||
|
||||
AddEventHandler('getResourceInitFuncs', function(isPreParse, add)
|
||||
if not isPreParse then
|
||||
add('map', function(file)
|
||||
addMap(file, GetInvokingResource())
|
||||
end)
|
||||
|
||||
add('resource_type', function(type)
|
||||
return function(params)
|
||||
local resourceName = GetInvokingResource()
|
||||
|
||||
if type == 'map' then
|
||||
maps[resourceName] = params
|
||||
elseif type == 'gametype' then
|
||||
gametypes[resourceName] = params
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
mapFiles = {}
|
||||
|
||||
function addMap(file, owningResource)
|
||||
if not mapFiles[owningResource] then
|
||||
mapFiles[owningResource] = {}
|
||||
end
|
||||
|
||||
table.insert(mapFiles[owningResource], file)
|
||||
end
|
||||
|
||||
AddEventHandler('onClientResourceStart', function(res)
|
||||
-- parse metadata for this resource
|
||||
|
||||
-- map files
|
||||
local num = GetNumResourceMetadata(res, 'map')
|
||||
|
||||
if num then
|
||||
for i = 0, num-1 do
|
||||
local file = GetResourceMetadata(res, 'map', i)
|
||||
|
||||
if file then
|
||||
addMap(file, res)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- resource type data
|
||||
local type = GetResourceMetadata(res, 'resource_type', 0)
|
||||
|
||||
if type then
|
||||
Citizen.Trace("type " .. res .. " " .. type .. "\n")
|
||||
|
||||
local extraData = GetResourceMetadata(res, 'resource_type_extra', 0)
|
||||
|
||||
if extraData then
|
||||
extraData = json.decode(extraData)
|
||||
else
|
||||
extraData = {}
|
||||
end
|
||||
|
||||
if type == 'map' then
|
||||
maps[res] = extraData
|
||||
elseif type == 'gametype' then
|
||||
gametypes[res] = extraData
|
||||
end
|
||||
end
|
||||
|
||||
-- handle starting
|
||||
if mapFiles[res] then
|
||||
for _, file in ipairs(mapFiles[res]) do
|
||||
parseMap(file, res)
|
||||
end
|
||||
end
|
||||
|
||||
-- defer this to the next game tick to work around a lack of dependencies
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(15)
|
||||
|
||||
if maps[res] then
|
||||
TriggerEvent('onClientMapStart', res)
|
||||
elseif gametypes[res] then
|
||||
TriggerEvent('onClientGameTypeStart', res)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler('onClientResourceStop', function(res)
|
||||
if maps[res] then
|
||||
TriggerEvent('onClientMapStop', res)
|
||||
elseif gametypes[res] then
|
||||
TriggerEvent('onClientGameTypeStop', res)
|
||||
end
|
||||
|
||||
if undoCallbacks[res] then
|
||||
for _, cb in ipairs(undoCallbacks[res]) do
|
||||
cb()
|
||||
end
|
||||
|
||||
undoCallbacks[res] = nil
|
||||
mapFiles[res] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
undoCallbacks = {}
|
||||
|
||||
function parseMap(file, owningResource)
|
||||
if not undoCallbacks[owningResource] then
|
||||
undoCallbacks[owningResource] = {}
|
||||
end
|
||||
|
||||
local env = {
|
||||
math = math, pairs = pairs, ipairs = ipairs, next = next, tonumber = tonumber, tostring = tostring,
|
||||
type = type, table = table, string = string, _G = env
|
||||
}
|
||||
|
||||
TriggerEvent('getMapDirectives', function(key, cb, undocb)
|
||||
env[key] = function(...)
|
||||
local state = {}
|
||||
|
||||
state.add = function(k, v)
|
||||
state[k] = v
|
||||
end
|
||||
|
||||
local result = cb(state, ...)
|
||||
local args = table.pack(...)
|
||||
|
||||
table.insert(undoCallbacks[owningResource], function()
|
||||
undocb(state)
|
||||
end)
|
||||
|
||||
return result
|
||||
end
|
||||
end)
|
||||
|
||||
local mt = {
|
||||
__index = function(t, k)
|
||||
if rawget(t, k) ~= nil then return rawget(t, k) end
|
||||
|
||||
-- as we're not going to return nothing here (to allow unknown directives to be ignored)
|
||||
local f = function()
|
||||
return f
|
||||
end
|
||||
|
||||
return function() return f end
|
||||
end
|
||||
}
|
||||
|
||||
setmetatable(env, mt)
|
||||
|
||||
local fileData = LoadResourceFile(owningResource, file)
|
||||
local mapFunction, err = load(fileData, file, 't', env)
|
||||
|
||||
if not mapFunction then
|
||||
Citizen.Trace("Couldn't load map " .. file .. ": " .. err .. " (type of fileData: " .. type(fileData) .. ")\n")
|
||||
return
|
||||
end
|
||||
|
||||
mapFunction()
|
||||
end
|
||||
|
||||
AddEventHandler('getMapDirectives', function(add)
|
||||
add('vehicle_generator', function(state, name)
|
||||
return function(opts)
|
||||
local x, y, z, heading
|
||||
local color1, color2
|
||||
|
||||
if opts.x then
|
||||
x = opts.x
|
||||
y = opts.y
|
||||
z = opts.z
|
||||
else
|
||||
x = opts[1]
|
||||
y = opts[2]
|
||||
z = opts[3]
|
||||
end
|
||||
|
||||
heading = opts.heading or 1.0
|
||||
color1 = opts.color1 or -1
|
||||
color2 = opts.color2 or -1
|
||||
|
||||
local hash = GetHashKey(name)
|
||||
RequestModel(hash)
|
||||
|
||||
LoadAllObjectsNow()
|
||||
|
||||
local carGen = CreateScriptVehicleGenerator(x, y, z, heading, 5.0, 3.0, hash, color1, color2, -1, -1, true, false, false, true, true, -1)
|
||||
SetScriptVehicleGenerator(carGen, true)
|
||||
SetAllVehicleGeneratorsActive(true)
|
||||
|
||||
state.add('cargen', carGen)
|
||||
end
|
||||
end, function(state, arg)
|
||||
Citizen.Trace("deleting car gen " .. tostring(state.cargen) .. "\n")
|
||||
|
||||
DeleteScriptVehicleGenerator(state.cargen)
|
||||
end)
|
||||
end)
|
273
resources/[managers]/mapmanager/mapmanager_server.lua
Normal file
273
resources/[managers]/mapmanager/mapmanager_server.lua
Normal file
@ -0,0 +1,273 @@
|
||||
-- loosely based on MTA's https://code.google.com/p/mtasa-resources/source/browse/trunk/%5Bmanagers%5D/mapmanager/mapmanager_main.lua
|
||||
|
||||
maps = {}
|
||||
gametypes = {}
|
||||
|
||||
AddEventHandler('getResourceInitFuncs', function(isPreParse, add)
|
||||
add('resource_type', function(type)
|
||||
return function(params)
|
||||
local resourceName = GetInvokingResource()
|
||||
|
||||
if type == 'map' then
|
||||
maps[resourceName] = params
|
||||
elseif type == 'gametype' then
|
||||
gametypes[resourceName] = params
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
add('map', function(file)
|
||||
AddAuxFile(file)
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStarting', function(resource)
|
||||
if maps[resource] then
|
||||
if getCurrentMap() and getCurrentMap() ~= resource then
|
||||
if doesMapSupportGameType(getCurrentGameType(), resource) then
|
||||
print("Changing map from " .. getCurrentMap() .. " to " .. resource)
|
||||
|
||||
changeMap(resource)
|
||||
else
|
||||
-- check if there's only one possible game type for the map
|
||||
local map = maps[resource]
|
||||
local count = 0
|
||||
local gt
|
||||
|
||||
for type, flag in pairs(map.gameTypes) do
|
||||
if flag then
|
||||
count = count + 1
|
||||
gt = type
|
||||
end
|
||||
end
|
||||
|
||||
if count == 1 then
|
||||
print("Changing map from " .. getCurrentMap() .. " to " .. resource .. " (gt " .. gt .. ")")
|
||||
|
||||
changeGameType(gt)
|
||||
changeMap(resource)
|
||||
end
|
||||
end
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
elseif gametypes[resource] then
|
||||
if getCurrentGameType() and getCurrentGameType() ~= resource then
|
||||
print("Changing gametype from " .. getCurrentGameType() .. " to " .. resource)
|
||||
|
||||
changeGameType(resource)
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
math.randomseed(GetInstanceId())
|
||||
|
||||
local currentGameType = nil
|
||||
local currentMap = nil
|
||||
|
||||
AddEventHandler('onResourceStart', function(resource)
|
||||
if maps[resource] then
|
||||
if not getCurrentGameType() then
|
||||
for gt, _ in pairs(maps[resource].gameTypes) do
|
||||
changeGameType(gt)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if getCurrentGameType() and not getCurrentMap() then
|
||||
if doesMapSupportGameType(currentGameType, resource) then
|
||||
if TriggerEvent('onMapStart', resource, maps[resource]) then
|
||||
if maps[resource].name then
|
||||
SetMapName(maps[resource].name)
|
||||
else
|
||||
SetMapName(resource)
|
||||
end
|
||||
|
||||
currentMap = resource
|
||||
else
|
||||
currentMap = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif gametypes[resource] then
|
||||
if not getCurrentGameType() then
|
||||
if TriggerEvent('onGameTypeStart', resource, gametypes[resource]) then
|
||||
currentGameType = resource
|
||||
|
||||
local gtName = gametypes[resource].name or resource
|
||||
|
||||
SetGameType(gtName)
|
||||
|
||||
print('Started gametype ' .. gtName)
|
||||
TriggerClientEvent('onClientGameTypeStart', -1, getCurrentGameType())
|
||||
|
||||
SetTimeout(50, function()
|
||||
if not currentMap then
|
||||
local possibleMaps = {}
|
||||
|
||||
for map, data in pairs(maps) do
|
||||
if data.gameTypes[currentGameType] then
|
||||
table.insert(possibleMaps, map)
|
||||
end
|
||||
end
|
||||
|
||||
if #possibleMaps > 0 then
|
||||
local rnd = math.random(#possibleMaps)
|
||||
changeMap(possibleMaps[rnd])
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
currentGameType = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function handleRoundEnd()
|
||||
local possibleMaps = {}
|
||||
|
||||
for map, data in pairs(maps) do
|
||||
if data.gameTypes[currentGameType] then
|
||||
table.insert(possibleMaps, map)
|
||||
end
|
||||
end
|
||||
|
||||
if #possibleMaps > 0 then
|
||||
local rnd = math.random(#possibleMaps)
|
||||
changeMap(possibleMaps[rnd])
|
||||
end
|
||||
end
|
||||
|
||||
AddEventHandler('mapmanager:roundEnded', function()
|
||||
-- set a timeout as we don't want to return to a dead environment
|
||||
SetTimeout(50, handleRoundEnd) -- not a closure as to work around some issue in neolua?
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
if resource == currentGameType then
|
||||
TriggerEvent('onGameTypeStop', resource)
|
||||
|
||||
currentGameType = nil
|
||||
|
||||
if currentMap then
|
||||
StopResource(currentMap)
|
||||
end
|
||||
elseif resource == currentMap then
|
||||
TriggerEvent('onMapStop', resource)
|
||||
|
||||
currentMap = nil
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == 'map' then
|
||||
if #args ~= 1 then
|
||||
RconPrint("usage: map [mapname]\n")
|
||||
end
|
||||
|
||||
if not maps[args[1]] then
|
||||
RconPrint('no such map ' .. args[1] .. "\n")
|
||||
CancelEvent()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if currentGameType == nil or not doesMapSupportGameType(currentGameType, args[1]) then
|
||||
local map = maps[args[1]]
|
||||
local count = 0
|
||||
local gt
|
||||
|
||||
for type, flag in pairs(map.gameTypes) do
|
||||
if flag then
|
||||
count = count + 1
|
||||
gt = type
|
||||
end
|
||||
end
|
||||
|
||||
if count == 1 then
|
||||
print("Changing map from " .. getCurrentMap() .. " to " .. args[1] .. " (gt " .. gt .. ")")
|
||||
|
||||
changeGameType(gt)
|
||||
changeMap(args[1])
|
||||
|
||||
RconPrint('map ' .. args[1] .. "\n")
|
||||
else
|
||||
RconPrint('map ' .. args[1] .. ' does not support ' .. currentGameType .. "\n")
|
||||
end
|
||||
|
||||
CancelEvent()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
changeMap(args[1])
|
||||
|
||||
RconPrint('map ' .. args[1] .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
elseif commandName == 'gametype' then
|
||||
if #args ~= 1 then
|
||||
RconPrint("usage: gametype [name]\n")
|
||||
end
|
||||
|
||||
if not gametypes[args[1]] then
|
||||
RconPrint('no such gametype ' .. args[1] .. "\n")
|
||||
CancelEvent()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
changeGameType(args[1])
|
||||
|
||||
RconPrint('gametype ' .. args[1] .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
||||
|
||||
function getCurrentGameType()
|
||||
return currentGameType
|
||||
end
|
||||
|
||||
function getCurrentMap()
|
||||
return currentMap
|
||||
end
|
||||
|
||||
function changeGameType(gameType)
|
||||
if currentMap and not doesMapSupportGameType(gameType, currentMap) then
|
||||
StopResource(currentMap)
|
||||
end
|
||||
|
||||
if currentGameType then
|
||||
StopResource(currentGameType)
|
||||
end
|
||||
|
||||
StartResource(gameType)
|
||||
end
|
||||
|
||||
function changeMap(map)
|
||||
if currentMap then
|
||||
StopResource(currentMap)
|
||||
end
|
||||
|
||||
StartResource(map)
|
||||
end
|
||||
|
||||
function doesMapSupportGameType(gameType, map)
|
||||
if not gametypes[gameType] then
|
||||
return false
|
||||
end
|
||||
|
||||
if not maps[map] then
|
||||
return false
|
||||
end
|
||||
|
||||
if not maps[map].gameTypes then
|
||||
return true
|
||||
end
|
||||
|
||||
return maps[map].gameTypes[gameType]
|
||||
end
|
1
resources/[managers]/mapmanager/mapmanager_shared.lua
Normal file
1
resources/[managers]/mapmanager/mapmanager_shared.lua
Normal file
@ -0,0 +1 @@
|
||||
-- shared logic file for map manager - don't call any subsystem-specific functions here
|
2
resources/[system]/baseevents/__resource.lua
Normal file
2
resources/[system]/baseevents/__resource.lua
Normal file
@ -0,0 +1,2 @@
|
||||
client_script 'deathevents.lua'
|
||||
client_script 'vehiclechecker.lua'
|
73
resources/[system]/baseevents/deathevents.lua
Normal file
73
resources/[system]/baseevents/deathevents.lua
Normal file
@ -0,0 +1,73 @@
|
||||
Citizen.CreateThread(function()
|
||||
local isDead = false
|
||||
local hasBeenDead = false
|
||||
local diedAt
|
||||
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
local player = PlayerId()
|
||||
|
||||
if NetworkIsPlayerActive(player) then
|
||||
local ped = PlayerPedId()
|
||||
|
||||
if IsPedFatallyInjured(ped) and not isDead then
|
||||
isDead = true
|
||||
if not diedAt then
|
||||
diedAt = GetGameTimer()
|
||||
end
|
||||
|
||||
local killer = NetworkGetEntityKillerOfPlayer(player)
|
||||
local killerentitytype = GetEntityType(killer)
|
||||
local killertype = -1
|
||||
local killerinvehicle = false
|
||||
local killervehiclename = ''
|
||||
local killervehicleseat = 0
|
||||
if killerentitytype == 1 then
|
||||
killertype = GetPedType(killer)
|
||||
if IsPedInAnyVehicle(killer, false) == 1 then
|
||||
killerinvehicle = true
|
||||
killervehiclename = GetDisplayNameFromVehicleModel(GetEntityModel(GetVehiclePedIsUsing(killer)))
|
||||
killervehicleseat = GetPedVehicleSeat(killer)
|
||||
else killerinvehicle = false
|
||||
end
|
||||
end
|
||||
|
||||
local killerid = GetPlayerByEntityID(killer)
|
||||
if killer ~= ped and killerid ~= nil and NetworkIsPlayerActive(killerid) then killerid = GetPlayerServerId(killerid)
|
||||
else killerid = -1
|
||||
end
|
||||
|
||||
if killer == ped then
|
||||
TriggerEvent('baseevents:onPlayerDied', killertype, { table.unpack(GetEntityCoords(ped)) })
|
||||
TriggerServerEvent('baseevents:onPlayerDied', killertype, { table.unpack(GetEntityCoords(ped)) })
|
||||
hasBeenDead = true
|
||||
else
|
||||
TriggerEvent('baseevents:onPlayerKilled', killerid, {killertype=killertype, killerinveh=killerinvehicle, killervehseat=killervehicleseat, killervehname=killervehiclename, killerpos=table.unpack(GetEntityCoords(ped))})
|
||||
TriggerServerEvent('baseevents:onPlayerKilled', killerid, {killertype=killertype, killerinveh=killerinvehicle, killervehseat=killervehicleseat, killervehname=killervehiclename, killerpos=table.unpack(GetEntityCoords(ped))})
|
||||
hasBeenDead = true
|
||||
end
|
||||
elseif not IsPedFatallyInjured(ped) then
|
||||
isDead = false
|
||||
diedAt = nil
|
||||
end
|
||||
|
||||
-- check if the player has to respawn in order to trigger an event
|
||||
if not hasBeenDead and diedAt ~= nil and diedAt > 0 then
|
||||
TriggerEvent('baseevents:onPlayerWasted', { table.unpack(GetEntityCoords(ped)) })
|
||||
TriggerServerEvent('baseevents:onPlayerWasted', { table.unpack(GetEntityCoords(ped)) })
|
||||
|
||||
hasBeenDead = true
|
||||
elseif hasBeenDead and diedAt ~= nil and diedAt <= 0 then
|
||||
hasBeenDead = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function GetPlayerByEntityID(id)
|
||||
for i=0,32 do
|
||||
if(NetworkIsPlayerActive(i) and GetPlayerPed(i) == id) then return i end
|
||||
end
|
||||
return nil
|
||||
end
|
54
resources/[system]/baseevents/vehiclechecker.lua
Normal file
54
resources/[system]/baseevents/vehiclechecker.lua
Normal file
@ -0,0 +1,54 @@
|
||||
local isInVehicle = false
|
||||
local isEnteringVehicle = false
|
||||
local currentVehicle = 0
|
||||
local currentSeat = 0
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Citizen.Wait(0)
|
||||
|
||||
local ped = PlayerPedId()
|
||||
|
||||
if not isInVehicle and not IsPlayerDead(PlayerId()) then
|
||||
if DoesEntityExist(GetVehiclePedIsTryingToEnter(ped)) and not isEnteringVehicle then
|
||||
-- trying to enter a vehicle!
|
||||
local vehicle = GetVehiclePedIsTryingToEnter(ped)
|
||||
local seat = GetSeatPedIsTryingToEnter(ped)
|
||||
isEnteringVehicle = true
|
||||
TriggerServerEvent('baseevents:enteringVehicle', vehicle, seat, GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)))
|
||||
elseif not DoesEntityExist(GetVehiclePedIsTryingToEnter(ped)) and not IsPedInAnyVehicle(ped, true) and isEnteringVehicle then
|
||||
-- vehicle entering aborted
|
||||
TriggerServerEvent('baseevents:enteringAborted')
|
||||
isEnteringVehicle = false
|
||||
elseif IsPedInAnyVehicle(ped, false) then
|
||||
-- suddenly appeared in a vehicle, possible teleport
|
||||
isEnteringVehicle = false
|
||||
isInVehicle = true
|
||||
currentVehicle = GetVehiclePedIsUsing(ped)
|
||||
currentSeat = GetPedVehicleSeat(ped)
|
||||
local model = GetEntityModel(currentVehicle)
|
||||
local name = GetDisplayNameFromVehicleModel()
|
||||
TriggerServerEvent('baseevents:enteredVehicle', currentVehicle, currentSeat, GetDisplayNameFromVehicleModel(GetEntityModel(currentVehicle)))
|
||||
end
|
||||
elseif isInVehicle then
|
||||
if not IsPedInAnyVehicle(ped, false) or IsPlayerDead(PlayerId()) then
|
||||
-- bye, vehicle
|
||||
local model = GetEntityModel(currentVehicle)
|
||||
local name = GetDisplayNameFromVehicleModel()
|
||||
TriggerServerEvent('baseevents:leftVehicle', currentVehicle, currentSeat, GetDisplayNameFromVehicleModel(GetEntityModel(currentVehicle)))
|
||||
isInVehicle = false
|
||||
currentVehicle = 0
|
||||
currentSeat = 0
|
||||
end
|
||||
end
|
||||
Citizen.Wait(50)
|
||||
end
|
||||
end)
|
||||
|
||||
function GetPedVehicleSeat(ped)
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
for i=-2,GetVehicleMaxNumberOfPassengers(vehicle) do
|
||||
if(GetPedInVehicleSeat(vehicle, i) == ped) then return i end
|
||||
end
|
||||
return -2
|
||||
end
|
15
resources/[system]/chat/__resource.lua
Normal file
15
resources/[system]/chat/__resource.lua
Normal file
@ -0,0 +1,15 @@
|
||||
description 'chat management stuff'
|
||||
|
||||
ui_page 'html/chat.html'
|
||||
|
||||
client_script 'chat_client.lua'
|
||||
server_script 'chat_server.lua'
|
||||
|
||||
export 'printChatLine'
|
||||
|
||||
files {
|
||||
'html/chat.html',
|
||||
'html/chat.css',
|
||||
'html/chat.js',
|
||||
'html/jquery.faketextbox.js'
|
||||
}
|
56
resources/[system]/chat/chat_client.lua
Normal file
56
resources/[system]/chat/chat_client.lua
Normal file
@ -0,0 +1,56 @@
|
||||
local chatInputActive = false
|
||||
local chatInputActivating = false
|
||||
|
||||
RegisterNetEvent('chatMessage')
|
||||
|
||||
AddEventHandler('chatMessage', function(name, color, message)
|
||||
SendNUIMessage({
|
||||
name = name,
|
||||
color = color,
|
||||
message = message
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNUICallback('chatResult', function(data, cb)
|
||||
chatInputActive = false
|
||||
|
||||
SetNuiFocus(false)
|
||||
|
||||
if data.message then
|
||||
local id = PlayerId()
|
||||
|
||||
--local r, g, b = GetPlayerRgbColour(id, _i, _i, _i)
|
||||
local r, g, b = 0, 0x99, 255
|
||||
|
||||
TriggerServerEvent('chatMessageEntered', GetPlayerName(id), { r, g, b }, data.message)
|
||||
end
|
||||
|
||||
cb('ok')
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
SetTextChatEnabled(false)
|
||||
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
if not chatInputActive then
|
||||
if IsControlPressed(0, 245) --[[ INPUT_MP_TEXT_CHAT_ALL ]] then
|
||||
chatInputActive = true
|
||||
chatInputActivating = true
|
||||
|
||||
SendNUIMessage({
|
||||
meta = 'openChatBox'
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if chatInputActivating then
|
||||
if not IsControlPressed(0, 245) then
|
||||
SetNuiFocus(true)
|
||||
|
||||
chatInputActivating = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
50
resources/[system]/chat/chat_server.lua
Normal file
50
resources/[system]/chat/chat_server.lua
Normal file
@ -0,0 +1,50 @@
|
||||
RegisterServerEvent('chatCommandEntered')
|
||||
RegisterServerEvent('chatMessageEntered')
|
||||
|
||||
AddEventHandler('chatMessageEntered', function(name, color, message)
|
||||
if not name or not color or not message or #color ~= 3 then
|
||||
return
|
||||
end
|
||||
|
||||
TriggerEvent('chatMessage', source, name, message)
|
||||
|
||||
if not WasEventCanceled() then
|
||||
TriggerClientEvent('chatMessage', -1, name, color, message)
|
||||
end
|
||||
|
||||
print(name .. ': ' .. message)
|
||||
end)
|
||||
|
||||
-- player join messages
|
||||
AddEventHandler('playerActivated', function()
|
||||
TriggerClientEvent('chatMessage', -1, '', { 0, 0, 0 }, '^2* ' .. GetPlayerName(source) .. ' joined.')
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function(reason)
|
||||
TriggerClientEvent('chatMessage', -1, '', { 0, 0, 0 }, '^2* ' .. GetPlayerName(source) ..' left (' .. reason .. ')')
|
||||
end)
|
||||
|
||||
-- say command handler
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == "say" then
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
TriggerClientEvent('chatMessage', -1, 'console', { 0, 0x99, 255 }, msg)
|
||||
RconPrint('console: ' .. msg .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
||||
|
||||
-- tell command handler
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == "tell" then
|
||||
local target = table.remove(args, 1)
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
TriggerClientEvent('chatMessage', tonumber(target), 'console', { 0, 0x99, 255 }, msg)
|
||||
RconPrint('console: ' .. msg .. "\n")
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
102
resources/[system]/chat/html/chat.css
Normal file
102
resources/[system]/chat/html/chat.css
Normal file
@ -0,0 +1,102 @@
|
||||
body
|
||||
{
|
||||
background-color: transparent;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
list-style-type: none; /* hii */
|
||||
}
|
||||
|
||||
#chat
|
||||
{
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 30px;
|
||||
padding: 7px;
|
||||
width: 30%;
|
||||
font-size: 20px;
|
||||
font-family: "Segoe UI", "Segoe UI Symbol", "Segoe UI Emoji", Arial, sans-serif;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
text-shadow: 0px 0px 1px #333;
|
||||
}
|
||||
|
||||
input.fake
|
||||
{
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
}
|
||||
|
||||
#chatInputHas
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
#chatInputHas strong
|
||||
{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-transform: uppercase;
|
||||
height: 29px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
#chatInput
|
||||
{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none !important;
|
||||
padding: 3px;
|
||||
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
margin: 0px;
|
||||
color: #fff;
|
||||
text-shadow: 0px 0px 1px #333;
|
||||
|
||||
font: inherit;
|
||||
|
||||
white-space: pre;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#chatInput > div:first-child
|
||||
{
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 23px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#chatInput .caret
|
||||
{
|
||||
display: inline-block;
|
||||
min-width: 1px;
|
||||
height: 22px;
|
||||
margin-left: 1px;
|
||||
vertical-align: bottom;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 0px 1px #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#chatBuffer
|
||||
{
|
||||
height: 240px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.color-1{color: #ff4444;}
|
||||
.color-2{color: #99cc00;}
|
||||
.color-3{color: #ffbb33;}
|
||||
.color-4{color: #0099cc;}
|
||||
.color-5{color: #33b5e5;}
|
||||
.color-6{color: #aa66cc;}
|
||||
.color-8{color: #cc0000;}
|
||||
.color-9{color: #cc0000;}
|
20
resources/[system]/chat/html/chat.html
Normal file
20
resources/[system]/chat/html/chat.html
Normal file
@ -0,0 +1,20 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
|
||||
<script src="jquery.faketextbox.js" type="text/javascript"></script>
|
||||
<script src="chat.js" type="text/javascript"></script>
|
||||
<link href="chat.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="chat">
|
||||
<div id="chatBuffer">
|
||||
<ul>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="chatInputHas">
|
||||
<strong>Chat</strong>
|
||||
<div id="chatInput" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
166
resources/[system]/chat/html/chat.js
Normal file
166
resources/[system]/chat/html/chat.js
Normal file
@ -0,0 +1,166 @@
|
||||
function colorize(string)
|
||||
{
|
||||
var newString = '';
|
||||
var inSpan = false;
|
||||
|
||||
for (i = 0; i < string.length; i++)
|
||||
{
|
||||
if (string[i] == '^')
|
||||
{
|
||||
if (string[i + 1] == '7' || string[i + 1] == '0')
|
||||
{
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
|
||||
inSpan = false;
|
||||
}
|
||||
|
||||
i += 2;
|
||||
}
|
||||
else if (string[i + 1] >= '0' && string[i + 1] <= '9')
|
||||
{
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
}
|
||||
|
||||
i += 2;
|
||||
newString += '<span class="color-' + string[i - 1] + '">';
|
||||
|
||||
inSpan = true;
|
||||
}
|
||||
}
|
||||
|
||||
newString += string[i];
|
||||
}
|
||||
|
||||
if (inSpan)
|
||||
{
|
||||
newString += '</span>';
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
$(function()
|
||||
{
|
||||
var chatHideTimeout;
|
||||
var inputShown = false;
|
||||
|
||||
function startHideChat()
|
||||
{
|
||||
if (chatHideTimeout)
|
||||
{
|
||||
clearTimeout(chatHideTimeout);
|
||||
}
|
||||
|
||||
if (inputShown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chatHideTimeout = setTimeout(function()
|
||||
{
|
||||
if (inputShown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$('#chat').animate({ opacity: 0 }, 300);
|
||||
}, 7000);
|
||||
}
|
||||
|
||||
handleResult = function(elem, wasEnter)
|
||||
{
|
||||
inputShown = false;
|
||||
|
||||
$('#chatInputHas').hide();
|
||||
|
||||
startHideChat();
|
||||
|
||||
var obj = {};
|
||||
|
||||
if (wasEnter)
|
||||
{
|
||||
obj = { message: $(elem).val() };
|
||||
}
|
||||
|
||||
$(elem).val('');
|
||||
|
||||
$.post('http://chat/chatResult', JSON.stringify(obj), function(data)
|
||||
{
|
||||
console.log(data);
|
||||
});
|
||||
};
|
||||
|
||||
$('#chatInput').fakeTextbox(); // //
|
||||
|
||||
$('#chatInput')[0].onPress(function(e)
|
||||
{
|
||||
if (e.which == 13)
|
||||
{
|
||||
handleResult(this, true);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).keyup(function(e)
|
||||
{
|
||||
if (e.keyCode == 27)
|
||||
{
|
||||
handleResult($('#chatInput')[0].getTextBox(), false);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).keypress(function(e)
|
||||
{
|
||||
if (e.keyCode == 9)
|
||||
{
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('message', function(event)
|
||||
{
|
||||
var item = event.data;
|
||||
|
||||
if (item.meta && item.meta == 'openChatBox')
|
||||
{
|
||||
inputShown = true;
|
||||
|
||||
$('#chat').css('opacity', '1');
|
||||
|
||||
$('#chatInputHas').show();
|
||||
$('#chatInput')[0].doFocus();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: use some templating stuff for this
|
||||
var colorR = parseInt(item.color[0]);
|
||||
var colorG = parseInt(item.color[1]);
|
||||
var colorB = parseInt(item.color[2]);
|
||||
|
||||
var name = item.name.replace('<', '<');
|
||||
var message = item.message.replace('<', '<');
|
||||
|
||||
message = colorize(message);
|
||||
|
||||
var buf = $('#chatBuffer');
|
||||
|
||||
var nameStr = '';
|
||||
|
||||
if (name != '')
|
||||
{
|
||||
nameStr = '<strong style="color: rgb(' + colorR + ', ' + colorG + ', ' + colorB + ')">' + name + ': </strong>';
|
||||
}
|
||||
|
||||
buf.find('ul').append('<li>' + nameStr + message + '</li>');
|
||||
buf.scrollTop(buf[0].scrollHeight - buf.height());
|
||||
|
||||
$('#chat').css('opacity', '1');
|
||||
|
||||
startHideChat();
|
||||
}, false);
|
||||
});
|
103
resources/[system]/chat/html/jquery.faketextbox.js
Normal file
103
resources/[system]/chat/html/jquery.faketextbox.js
Normal file
@ -0,0 +1,103 @@
|
||||
(function ($) {
|
||||
$.fn.fakeTextbox = function () {
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
var $me = $(this),
|
||||
cursorTimer,
|
||||
$tb = $('<input type="text" class="fake" />');
|
||||
|
||||
if ($me.data('ftbftw')) {
|
||||
console.log('already initialized');
|
||||
return;
|
||||
}
|
||||
|
||||
$me.data('ftbftw', 1);
|
||||
|
||||
$tb.insertAfter($me);
|
||||
|
||||
function appendCaret(toHere, position, selStart, selEnd) {
|
||||
if (position === selStart) {
|
||||
toHere += "</div><div class='caret'>";
|
||||
}
|
||||
if (position === selEnd) {
|
||||
toHere += "</div><div>";
|
||||
}
|
||||
return toHere;
|
||||
}
|
||||
|
||||
function syncTextbox() {
|
||||
var tbVal = $tb.val().replace('<', '<');
|
||||
var tbLen = tbVal.length;
|
||||
var selStart = $tb.get(0).selectionStart;
|
||||
var selEnd = $tb.get(0).selectionEnd;
|
||||
var newOut = '<div>';
|
||||
|
||||
for (var i = 0; i < tbLen; i++) {
|
||||
newOut = appendCaret(newOut, i, selStart, selEnd);
|
||||
newOut += tbVal[i];
|
||||
}
|
||||
|
||||
$me.html(colorize(appendCaret(newOut, i, selStart, selEnd) + '</div>'));
|
||||
if (selStart != selEnd) {
|
||||
$('.caret', $me).addClass('selection');
|
||||
}
|
||||
}
|
||||
|
||||
$me.click(function () {
|
||||
$tb.focus();
|
||||
});
|
||||
|
||||
$tb.bind("change keypress keyup", function()
|
||||
{
|
||||
setTimeout(syncTextbox, 1); //
|
||||
})
|
||||
.blur(function () {
|
||||
clearInterval(cursorTimer);
|
||||
cursorTimer = null;
|
||||
var $cursor = $('.caret', $me);
|
||||
$cursor.css({
|
||||
visibility: 'visible'
|
||||
});
|
||||
$me.removeClass('focused');
|
||||
}).focus(function () {
|
||||
if (!cursorTimer) {
|
||||
$me.addClass('focused');
|
||||
cursorTimer = window.setInterval(function () {
|
||||
var $cursor = $('.caret', $me);
|
||||
if ($cursor.hasClass('selection') || $cursor.css('visibility') === 'hidden') {
|
||||
$cursor.css({
|
||||
visibility: 'visible'
|
||||
});
|
||||
} else {
|
||||
$cursor.css({
|
||||
visibility: 'hidden'
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
this.doFocus = function()
|
||||
{
|
||||
$tb.focus();
|
||||
};
|
||||
|
||||
this.onPress = function(f)
|
||||
{
|
||||
$tb.bind('keypress', f);
|
||||
};
|
||||
|
||||
this.getTextBox = function()
|
||||
{
|
||||
return $tb;
|
||||
};
|
||||
|
||||
syncTextbox();
|
||||
|
||||
if ($me.hasClass('initFocus')) {
|
||||
$tb.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
}(jQuery));
|
2
resources/[system]/hardcap/__resource.lua
Normal file
2
resources/[system]/hardcap/__resource.lua
Normal file
@ -0,0 +1,2 @@
|
||||
client_script 'client.lua'
|
||||
server_script 'server.lua'
|
11
resources/[system]/hardcap/client.lua
Normal file
11
resources/[system]/hardcap/client.lua
Normal file
@ -0,0 +1,11 @@
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
if NetworkIsSessionStarted() then
|
||||
TriggerServerEvent('hardcap:playerActivated')
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
29
resources/[system]/hardcap/server.lua
Normal file
29
resources/[system]/hardcap/server.lua
Normal file
@ -0,0 +1,29 @@
|
||||
local playerCount = 0
|
||||
local list = {}
|
||||
|
||||
RegisterServerEvent('hardcap:playerActivated')
|
||||
|
||||
AddEventHandler('hardcap:playerActivated', function()
|
||||
if not list[source] then
|
||||
playerCount = playerCount + 1
|
||||
list[source] = true
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function()
|
||||
if list[source] then
|
||||
playerCount = playerCount - 1
|
||||
list[source] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerConnecting', function(name, setReason)
|
||||
print('Connecting: ' .. name)
|
||||
|
||||
if playerCount >= 24 then
|
||||
print('Full. :(')
|
||||
|
||||
setReason('This server is full (past 24 players).')
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
2
resources/[system]/rconlog/__resource.lua
Normal file
2
resources/[system]/rconlog/__resource.lua
Normal file
@ -0,0 +1,2 @@
|
||||
client_script 'rconlog_client.lua'
|
||||
server_script 'rconlog_server.lua'
|
25
resources/[system]/rconlog/rconlog_client.lua
Normal file
25
resources/[system]/rconlog/rconlog_client.lua
Normal file
@ -0,0 +1,25 @@
|
||||
RegisterNetEvent('rlUpdateNames')
|
||||
|
||||
AddEventHandler('rlUpdateNames', function()
|
||||
local names = {}
|
||||
|
||||
for i = 0, 31 do
|
||||
if NetworkIsPlayerActive(i) then
|
||||
names[GetPlayerServerId(i)] = { id = i, name = GetPlayerName(i) }
|
||||
end
|
||||
end
|
||||
|
||||
TriggerServerEvent('rlUpdateNamesResult', names)
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
if NetworkIsSessionStarted() then
|
||||
TriggerServerEvent('rlPlayerActivated')
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
80
resources/[system]/rconlog/rconlog_server.lua
Normal file
80
resources/[system]/rconlog/rconlog_server.lua
Normal file
@ -0,0 +1,80 @@
|
||||
RconLog({ msgType = 'serverStart', hostname = 'lovely', maxplayers = 32 })
|
||||
|
||||
RegisterServerEvent('rlPlayerActivated')
|
||||
|
||||
local names = {}
|
||||
|
||||
AddEventHandler('rlPlayerActivated', function()
|
||||
RconLog({ msgType = 'playerActivated', netID = source, name = GetPlayerName(source), guid = GetPlayerIdentifiers(source)[1], ip = GetPlayerEP(source) })
|
||||
|
||||
names[source] = { name = GetPlayerName(source), id = source }
|
||||
|
||||
TriggerClientEvent('rlUpdateNames', GetHostId())
|
||||
end)
|
||||
|
||||
RegisterServerEvent('rlUpdateNamesResult')
|
||||
|
||||
AddEventHandler('rlUpdateNamesResult', function(res)
|
||||
if source ~= GetHostId() then
|
||||
print('bad guy')
|
||||
return
|
||||
end
|
||||
|
||||
for id, data in pairs(res) do
|
||||
if data then
|
||||
if data.name then
|
||||
if not names[id] then
|
||||
names[id] = data
|
||||
end
|
||||
|
||||
if names[id].name ~= data.name or names[id].id ~= data.id then
|
||||
names[id] = data
|
||||
|
||||
RconLog({ msgType = 'playerRenamed', netID = id, name = data.name })
|
||||
end
|
||||
end
|
||||
else
|
||||
names[id] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('playerDropped', function()
|
||||
RconLog({ msgType = 'playerDropped', netID = source, name = GetPlayerName(source) })
|
||||
|
||||
names[source] = nil
|
||||
end)
|
||||
|
||||
AddEventHandler('chatMessage', function(netID, name, message)
|
||||
RconLog({ msgType = 'chatMessage', netID = netID, name = name, message = message, guid = GetPlayerIdentifiers(netID)[1] })
|
||||
end)
|
||||
|
||||
AddEventHandler('rconCommand', function(commandName, args)
|
||||
if commandName == 'status' then
|
||||
for netid, data in pairs(names) do
|
||||
local guid = GetPlayerIdentifiers(netid)
|
||||
|
||||
if guid and guid[1] and data then
|
||||
local ping = GetPlayerPing(netid)
|
||||
|
||||
RconPrint(netid .. ' ' .. guid[1] .. ' ' .. data.name .. ' ' .. GetPlayerEP(netid) .. ' ' .. ping .. "\n")
|
||||
end
|
||||
end
|
||||
|
||||
CancelEvent()
|
||||
elseif commandName:lower() == 'clientkick' then
|
||||
local playerId = table.remove(args, 1)
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
DropPlayer(playerId, msg)
|
||||
|
||||
CancelEvent()
|
||||
elseif commandName:lower() == 'tempbanclient' then
|
||||
local playerId = table.remove(args, 1)
|
||||
local msg = table.concat(args, ' ')
|
||||
|
||||
TempBanPlayer(playerId, msg)
|
||||
|
||||
CancelEvent()
|
||||
end
|
||||
end)
|
18
resources/[system]/scoreboard/__resource.lua
Normal file
18
resources/[system]/scoreboard/__resource.lua
Normal file
@ -0,0 +1,18 @@
|
||||
description 'Scoreboard'
|
||||
|
||||
-- temporary!
|
||||
ui_page 'html/scoreboard.html'
|
||||
|
||||
client_script 'scoreboard.lua'
|
||||
|
||||
files {
|
||||
'html/scoreboard.html',
|
||||
'html/style.css',
|
||||
'html/reset.css',
|
||||
'html/listener.js',
|
||||
'html/res/futurastd-medium.css',
|
||||
'html/res/futurastd-medium.eot',
|
||||
'html/res/futurastd-medium.woff',
|
||||
'html/res/futurastd-medium.ttf',
|
||||
'html/res/futurastd-medium.svg',
|
||||
}
|
17
resources/[system]/scoreboard/html/listener.js
Normal file
17
resources/[system]/scoreboard/html/listener.js
Normal file
@ -0,0 +1,17 @@
|
||||
$(function()
|
||||
{
|
||||
window.addEventListener('message', function(event)
|
||||
{
|
||||
var item = event.data;
|
||||
var buf = $('#wrap');
|
||||
buf.find('table').append("<tr class=\"heading\"><th>ID</th><th>Name</th><th>Wanted level</th></tr>");
|
||||
if (item.meta && item.meta == 'close')
|
||||
{
|
||||
document.getElementById("ptbl").innerHTML = "";
|
||||
$('#wrap').hide();
|
||||
return;
|
||||
}
|
||||
buf.find('table').append(item.text);
|
||||
$('#wrap').show();
|
||||
}, false);
|
||||
});
|
@ -0,0 +1,8 @@
|
||||
@font-face {
|
||||
font-family: 'FuturaStdMedium';
|
||||
src: url('futurastd-medium.eot');
|
||||
src: url('futurastd-medium.eot') format('embedded-opentype'),
|
||||
url('futurastd-medium.woff') format('woff'),
|
||||
url('futurastd-medium.ttf') format('truetype'),
|
||||
url('futurastd-medium.svg#FuturaStdMedium') format('svg');
|
||||
}
|
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.eot
Normal file
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.eot
Normal file
Binary file not shown.
913
resources/[system]/scoreboard/html/res/futurastd-medium.svg
Normal file
913
resources/[system]/scoreboard/html/res/futurastd-medium.svg
Normal file
@ -0,0 +1,913 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by FontForge 20110222 at Mon Aug 4 15:25:24 2014
|
||||
By Orthosie Webhosting
|
||||
Copyright (c) 1987, 1991, 1993, 2002 Adobe Systems Incorporated. All Rights Reserved.
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="FuturaStdMedium" horiz-adv-x="578" >
|
||||
<font-face
|
||||
font-family="FuturaStdMedium"
|
||||
font-weight="500"
|
||||
font-stretch="normal"
|
||||
units-per-em="1000"
|
||||
panose-1="2 11 5 2 2 2 4 2 3 3"
|
||||
ascent="825"
|
||||
descent="-175"
|
||||
x-height="468"
|
||||
cap-height="754"
|
||||
bbox="-163 -268 1113 995"
|
||||
underline-thickness="50"
|
||||
underline-position="-50"
|
||||
unicode-range="U+0020-FB02"
|
||||
/>
|
||||
<missing-glyph horiz-adv-x="500"
|
||||
d="M0 0v700h500v-700h-500zM250 395l170 255h-340zM280 350l170 -255v510zM80 50h340l-170 255zM50 605v-510l170 255z" />
|
||||
<glyph glyph-name="fi" unicode="fi" horiz-adv-x="512"
|
||||
d="M430 468v-468h-90v468h90zM385 745q26 0 44 -18.5t18 -44.5q0 -25 -18 -43t-44 -18t-44 18t-18 43q0 26 18 44.5t44 18.5zM294 868v-91q-43 19 -60 19q-18 0 -31 -9.5t-19 -21.5t-9.5 -32.5t-4 -32t-0.5 -31.5v-201h124v-84h-124v-384h-90v384h-41v84h41v228
|
||||
q0 184 151 184q33 0 63 -12z" />
|
||||
<glyph glyph-name="fl" unicode="fl" horiz-adv-x="497"
|
||||
d="M431 868v-868h-90v868h90zM294 868v-91q-43 19 -60 19q-18 0 -31 -9.5t-19 -21.5t-9.5 -32.5t-4 -32t-0.5 -31.5v-201h124v-84h-124v-384h-90v384h-41v84h41v228q0 184 151 184q33 0 63 -12z" />
|
||||
<glyph glyph-name=".notdef" horiz-adv-x="500"
|
||||
d="M0 0v700h500v-700h-500zM250 395l170 255h-340zM280 350l170 -255v510zM80 50h340l-170 255zM50 605v-510l170 255z" />
|
||||
<glyph glyph-name=".null" horiz-adv-x="0"
|
||||
/>
|
||||
<glyph glyph-name="nonmarkingreturn" horiz-adv-x="333"
|
||||
/>
|
||||
<glyph glyph-name="space" unicode=" " horiz-adv-x="289"
|
||||
/>
|
||||
<glyph glyph-name="exclam" unicode="!" horiz-adv-x="321"
|
||||
d="M161 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5zM116 174v580h90v-580h-90z" />
|
||||
<glyph glyph-name="quotedbl" unicode=""" horiz-adv-x="439"
|
||||
d="M90 754h98l-18 -328h-62zM251 754h98l-18 -328h-62z" />
|
||||
<glyph glyph-name="numbersign" unicode="#"
|
||||
d="M217 718h77l-36 -194h124l35 194h79l-35 -194h92v-80h-107l-27 -154h101v-80h-117l-38 -210h-76l37 210h-123l-40 -210h-75l37 210h-100v80h115l27 154h-105v80h119zM245 444l-27 -154h123l27 154h-123z" />
|
||||
<glyph glyph-name="dollar" unicode="$"
|
||||
d="M333 349v-271q46 10 75.5 49t29.5 87q0 80 -105 135zM283 770v90h50v-90q114 -11 171 -116l-79 -45q-29 55 -92 74v-235q90 -39 142.5 -92.5t52.5 -137.5q0 -82 -57.5 -152.5t-137.5 -81.5v-95h-50v95q-87 1 -153 62t-80 148l90 19q13 -66 46 -99.5t97 -41.5v300l-36 18
|
||||
q-70 36 -107 76t-37 107q0 75 52.5 133t127.5 64zM283 472v211q-40 -6 -66.5 -35t-26.5 -68q0 -71 93 -108z" />
|
||||
<glyph glyph-name="percent" unicode="%" horiz-adv-x="708"
|
||||
d="M193 710q-47 0 -81.5 -33t-34.5 -79q0 -45 34.5 -78t81.5 -33t81.5 33t34.5 78q0 46 -34.5 79t-81.5 33zM552 770l45 -26l-440 -760l-46 25zM516 267q-47 0 -81.5 -33t-34.5 -79q0 -45 34.5 -78t81.5 -33t81.5 33t34.5 78q0 46 -34.5 79t-81.5 33zM193 770
|
||||
q72 0 124 -50.5t52 -121.5t-52.5 -121t-123.5 -50t-123.5 50t-52.5 121t52 121.5t124 50.5zM516 327q72 0 124 -50.5t52 -121.5t-52.5 -121t-123.5 -50t-123.5 50t-52.5 121t52 121.5t124 50.5z" />
|
||||
<glyph glyph-name="ampersand" unicode="&" horiz-adv-x="692"
|
||||
d="M287 372l-9 -6q-1 -1 -20 -14t-24 -16.5t-21.5 -16.5t-23 -19.5t-18.5 -19.5t-16.5 -23t-9 -23.5t-4.5 -26.5q0 -54 43 -96.5t97 -42.5q33 0 67 17t55 35t51 48zM307 490l12 8q4 3 19.5 14.5t21.5 17t17.5 17t17 20t10 21.5t4.5 26q0 39 -24.5 60.5t-63.5 21.5
|
||||
q-35 0 -59.5 -22.5t-24.5 -57.5q0 -18 8 -36.5t14.5 -28t22.5 -29.5zM592 0l-82 102q-100 -118 -226 -118q-96 0 -163.5 63t-67.5 159q0 65 33.5 109t98.5 91l47 34q-83 87 -83 165q0 76 49 120.5t125 44.5q72 0 123 -42.5t51 -114.5q0 -30 -11.5 -57.5t-34.5 -52t-42 -40.5
|
||||
t-49 -38l157 -190l88 102l60 -62l-92 -108l135 -167h-116z" />
|
||||
<glyph glyph-name="quotesingle" unicode="'" horiz-adv-x="277"
|
||||
d="M90 754h98l-18 -328h-62z" />
|
||||
<glyph glyph-name="parenleft" unicode="(" horiz-adv-x="292"
|
||||
d="M161 809l74 -55q-86 -180 -86 -446t86 -446l-74 -55q-52 103 -78 236.5t-26 264.5t26 265t78 236z" />
|
||||
<glyph glyph-name="parenright" unicode=")" horiz-adv-x="292"
|
||||
d="M57 754l74 55q52 -102 78 -236t26 -265t-26 -264.5t-78 -236.5l-74 55q86 180 86 446t-86 446z" />
|
||||
<glyph glyph-name="asterisk" unicode="*" horiz-adv-x="432"
|
||||
d="M184 754h69v-95l81 48l35 -59l-85 -50l85 -50l-35 -58l-81 50v-96h-69v97l-87 -49l-34 57l85 49l-84 50l31 57l89 -49v98z" />
|
||||
<glyph glyph-name="plus" unicode="+"
|
||||
d="M246 512h86v-213h213v-86h-213v-213h-86v213h-213v86h213v213z" />
|
||||
<glyph glyph-name="comma" unicode="," horiz-adv-x="289"
|
||||
d="M164 119l78 -31l-133 -267l-55 23z" />
|
||||
<glyph glyph-name="hyphen" unicode="-" horiz-adv-x="332"
|
||||
d="M57 358h219v-75h-219v75z" />
|
||||
<glyph glyph-name="period" unicode="." horiz-adv-x="289"
|
||||
d="M145 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="slash" unicode="/" horiz-adv-x="551"
|
||||
d="M448 868l72 -32l-417 -962l-71 32z" />
|
||||
<glyph glyph-name="zero" unicode="0"
|
||||
d="M289 -16q-56 0 -101.5 26.5t-75 67.5t-49.5 94t-28.5 104.5t-8.5 100.5q0 63 14.5 127.5t43.5 126t82.5 100.5t122.5 39t122.5 -39t82.5 -100.5t43.5 -126t14.5 -127.5q0 -49 -8.5 -100.5t-28.5 -104.5t-49.5 -94t-75 -67.5t-101.5 -26.5zM289 690q-48 0 -83.5 -33.5
|
||||
t-54 -84.5t-27 -100.5t-8.5 -93.5t8.5 -93t27 -100t54 -84t83.5 -33t83.5 33t54 84t27 100t8.5 93t-8.5 93.5t-27 100.5t-54 84.5t-83.5 33.5z" />
|
||||
<glyph glyph-name="one" unicode="1"
|
||||
d="M254 668h-131l52 86h169v-754h-90v668z" />
|
||||
<glyph glyph-name="two" unicode="2"
|
||||
d="M228 86h304v-86h-487l330 405q67 82 67 135q0 59 -44.5 101.5t-103.5 42.5q-57 0 -99 -40.5t-46 -97.5h-94q11 102 74.5 163t164.5 61q98 0 168 -64.5t70 -161.5q0 -86 -56 -155z" />
|
||||
<glyph glyph-name="three" unicode="3"
|
||||
d="M275 360v78q148 0 148 121q0 57 -37 93t-94 36q-51 0 -84 -29.5t-41 -78.5h-93q13 93 70.5 141.5t150.5 48.5t155.5 -55.5t62.5 -147.5q0 -116 -96 -170q107 -51 107 -187q0 -103 -68.5 -164.5t-172.5 -61.5q-92 0 -159 56t-71 146h91q7 -54 48.5 -87t97.5 -33
|
||||
q62 0 103 43t41 105q0 71 -44.5 111t-114.5 35z" />
|
||||
<glyph glyph-name="four" unicode="4"
|
||||
d="M469 192h86v-82h-86v-110h-90v110h-372l462 676v-594zM379 192v311h-2l-212 -311h214z" />
|
||||
<glyph glyph-name="five" unicode="5"
|
||||
d="M528 668h-237l-47 -155l53 3q106 0 174 -78t68 -186q0 -118 -80.5 -193t-198.5 -75q-71 0 -134.5 35.5t-95.5 96.5l70 66q17 -47 66.5 -79.5t100.5 -32.5q76 0 129 54.5t53 130.5q0 73 -53.5 126t-126.5 53q-40 0 -78.5 -18t-62.5 -49h-18l116 387h302v-86z" />
|
||||
<glyph glyph-name="six" unicode="6"
|
||||
d="M379 770l68 -46l-201 -272l2 -2q36 18 74 18q91 0 154.5 -71.5t63.5 -164.5q0 -103 -73 -175.5t-176 -72.5q-99 0 -175 71.5t-76 169.5q0 89 82 199zM290 68q64 0 112 46t48 108q0 68 -49 115t-111 47t-111 -48t-49 -109q0 -65 47.5 -112t112.5 -47z" />
|
||||
<glyph glyph-name="seven" unicode="7"
|
||||
d="M437 668h-390v86h543l-470 -770l-73 45z" />
|
||||
<glyph glyph-name="eight" unicode="8"
|
||||
d="M289 352q-58 0 -102 -41.5t-44 -100.5q0 -56 45 -99t101 -43t101 43t45 99q0 59 -44 100.5t-102 41.5zM53 210q0 63 31 112t88 69q-99 56 -99 169q0 91 62.5 150.5t153.5 59.5t153.5 -59.5t62.5 -150.5q0 -113 -99 -169q57 -20 88 -69t31 -112q0 -102 -68.5 -164
|
||||
t-167.5 -62t-167.5 62t-68.5 164zM289 690q-51 0 -89.5 -38t-38.5 -92q0 -45 40.5 -86.5t87.5 -41.5t87.5 41.5t40.5 86.5q0 54 -38.5 92t-89.5 38z" />
|
||||
<glyph glyph-name="nine" unicode="9"
|
||||
d="M213 -16l-68 47l201 271l-2 2q-28 -14 -73 -14q-92 0 -155.5 70t-63.5 162q0 103 73 175.5t176 72.5q99 0 175 -71.5t76 -169.5q0 -89 -82 -199zM302 370q70 0 115 47t45 111q0 61 -46.5 109.5t-107.5 48.5q-68 0 -117 -47t-49 -111q0 -65 49.5 -111.5t110.5 -46.5z" />
|
||||
<glyph glyph-name="colon" unicode=":" horiz-adv-x="289"
|
||||
d="M145 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5zM145 482q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="289"
|
||||
d="M156 119l78 -31l-133 -267l-55 23zM192 482q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="less" unicode="<"
|
||||
d="M545 498v-94l-384 -148l384 -148v-94l-512 207v70z" />
|
||||
<glyph glyph-name="equal" unicode="="
|
||||
d="M33 385h512v-86h-512v86zM33 213h512v-86h-512v86z" />
|
||||
<glyph glyph-name="greater" unicode=">"
|
||||
d="M33 404v94l512 -207v-70l-512 -207v94l384 148z" />
|
||||
<glyph glyph-name="question" unicode="?" horiz-adv-x="453"
|
||||
d="M301 345h91q3 -64 -47 -112.5t-115 -48.5q-67 0 -114 46.5t-47 113.5q0 64 33 94.5t93 52.5q5 2 20 7.5t21 7.5t19 7.5t18 9t15 10t14 12.5t9 14t7 17t2 20q0 41 -26 65t-66 24q-35 0 -60.5 -25.5t-25.5 -60.5q0 -10 6 -32h-94l-2 33q-4 71 51 120.5t128 49.5
|
||||
q76 0 128 -51t52 -126q0 -78 -54 -124q-31 -27 -124 -56q-73 -22 -73 -73q0 -30 20 -51t50 -21q32 0 52 22.5t19 54.5zM230 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="at" unicode="@" horiz-adv-x="800"
|
||||
d="M503 372q7 60 -21 93.5t-81 33.5q-58 0 -95 -47t-37 -106q0 -46 27.5 -80t72.5 -34q62 0 94 39.5t40 100.5zM528 506l14 62h71l-50 -257q-9 -25 -8.5 -55.5t22.5 -30.5q36 0 72 60t36 132q0 124 -76.5 198.5t-193.5 74.5q-126 0 -212.5 -91.5t-86.5 -221.5
|
||||
q0 -135 92.5 -224t223.5 -89q129 0 186 48l75 -60q-64 -34 -122 -51t-147 -17q-163 0 -275.5 112t-112.5 281q0 167 110.5 280t271.5 113q139 0 235 -87q112 -97 112 -230q0 -131 -62 -212q-34 -45 -75 -67t-79 -20q-44 2 -54 62q-62 -62 -136 -62q-67 0 -117.5 54.5
|
||||
t-50.5 130.5q0 95 57 166.5t147 71.5q78 0 133 -71z" />
|
||||
<glyph glyph-name="A" unicode="A" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268z" />
|
||||
<glyph glyph-name="B" unicode="B" horiz-adv-x="535"
|
||||
d="M158 670v-250h24q78 0 120 26t42 100q0 73 -41.5 98.5t-118.5 25.5h-26zM158 345v-261h72q178 0 178 133q0 38 -17.5 64.5t-47.5 39.5t-61 18.5t-66 5.5h-58zM64 0v754h92q58 0 104 -9t86.5 -30.5t63 -64t22.5 -103.5q0 -43 -22 -84.5t-59 -58.5v-2q65 -12 108 -67.5
|
||||
t43 -123.5q0 -106 -76 -158.5t-186 -52.5h-176z" />
|
||||
<glyph glyph-name="C" unicode="C" horiz-adv-x="661"
|
||||
d="M621 719v-109q-83 74 -199 74q-125 0 -211.5 -90.5t-86.5 -217.5q0 -125 85.5 -215.5t210.5 -90.5q114 0 201 78v-111q-90 -53 -198 -53q-162 0 -277.5 113t-115.5 276q0 167 117 282t284 115q107 0 190 -51z" />
|
||||
<glyph glyph-name="D" unicode="D" horiz-adv-x="665"
|
||||
d="M64 0v754h156q183 0 303 -96.5t120 -276.5q0 -185 -119 -283t-307 -98h-153zM158 668v-582h33q76 0 138 15t112.5 48t79 91t28.5 137q0 80 -28.5 138t-79.5 90.5t-112.5 47.5t-137.5 15h-33z" />
|
||||
<glyph glyph-name="E" unicode="E" horiz-adv-x="521"
|
||||
d="M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405z" />
|
||||
<glyph glyph-name="F" unicode="F" horiz-adv-x="474"
|
||||
d="M436 668h-271v-212h262v-86h-262v-370h-94v754h365v-86z" />
|
||||
<glyph glyph-name="G" unicode="G" horiz-adv-x="780"
|
||||
d="M460 380h299v-30q0 -157 -100 -261.5t-257 -104.5t-269 116.5t-112 274.5q0 163 114.5 279t276.5 116q89 0 170.5 -38.5t136.5 -107.5l-66 -63q-41 56 -105 89.5t-132 33.5q-126 0 -213.5 -89.5t-87.5 -216.5q0 -121 86.5 -214.5t206.5 -93.5q90 0 167 67t80 157h-195v86
|
||||
z" />
|
||||
<glyph glyph-name="H" unicode="H" horiz-adv-x="675"
|
||||
d="M158 450h359v304h94v-754h-94v362h-359v-362h-94v754h94v-304z" />
|
||||
<glyph glyph-name="I" unicode="I" horiz-adv-x="232"
|
||||
d="M163 754v-754h-94v754h94z" />
|
||||
<glyph glyph-name="J" unicode="J" horiz-adv-x="362"
|
||||
d="M209 754h94v-479q0 -61 -7.5 -107.5t-28 -91t-63 -68.5t-105.5 -24t-118 33l47 80q33 -25 75 -25q22 0 39.5 8t28.5 18t19 30t11.5 34t5.5 40t2 37v36v479z" />
|
||||
<glyph glyph-name="K" unicode="K" horiz-adv-x="600"
|
||||
d="M166 427l320 327h123l-339 -339l345 -415h-127l-284 351l-38 -36v-315h-94v754h94v-327z" />
|
||||
<glyph glyph-name="L" unicode="L" horiz-adv-x="385"
|
||||
d="M166 754v-668h229v-86h-323v754h94z" />
|
||||
<glyph glyph-name="M" unicode="M" horiz-adv-x="851"
|
||||
d="M426 -16l-226 514h-2l-88 -498h-97l154 786l259 -594l259 594l154 -786h-97l-88 498h-2z" />
|
||||
<glyph glyph-name="N" unicode="N" horiz-adv-x="785"
|
||||
d="M63 0v790l566 -593v557h94v-785l-566 593v-562h-94z" />
|
||||
<glyph glyph-name="O" unicode="O" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5z" />
|
||||
<glyph glyph-name="P" unicode="P" horiz-adv-x="495"
|
||||
d="M166 316v-316h-94v754h108q167 0 235.5 -54.5t68.5 -163.5q0 -112 -73.5 -166t-190.5 -54h-54zM166 670v-270h30q41 0 72.5 5t62.5 18.5t48 42.5t17 72q0 42 -18 70t-51 40.5t-64 17t-72 4.5h-25z" />
|
||||
<glyph glyph-name="Q" unicode="Q" horiz-adv-x="828"
|
||||
d="M808 -16h-114l-65 67q-97 -67 -215 -67q-165 0 -280 113t-115 280q0 162 116.5 277.5t278.5 115.5t278.5 -115.5t116.5 -277.5q0 -80 -31 -152.5t-87 -125.5zM508 284l119 -118q42 37 65 95.5t23 115.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216
|
||||
q0 -128 89 -216.5t212 -88.5q82 0 150 43l-173 169h117z" />
|
||||
<glyph glyph-name="R" unicode="R" horiz-adv-x="543"
|
||||
d="M303 328l238 -328h-114l-222 319h-39v-319h-94v754h114q43 0 69.5 -1.5t64 -9.5t65.5 -24q46 -27 72.5 -76t26.5 -104q0 -82 -50 -141.5t-131 -69.5zM166 670v-273h30q41 0 72.5 5t62.5 18.5t48 42.5t17 72q0 135 -205 135h-25z" />
|
||||
<glyph glyph-name="S" unicode="S" horiz-adv-x="537"
|
||||
d="M482 656l-75 -45q-42 71 -121 71q-48 0 -87 -30t-39 -77q0 -68 105 -108l54 -21q90 -35 138.5 -87t48.5 -140q0 -102 -69.5 -168.5t-171.5 -66.5q-91 0 -156 59.5t-77 151.5l95 20q-1 -61 41.5 -102t104.5 -41q60 0 99.5 43.5t39.5 103.5q0 55 -34.5 86.5t-95.5 56.5
|
||||
l-52 22q-77 33 -120.5 76t-43.5 115q0 88 66 141.5t156 53.5q130 0 194 -114z" />
|
||||
<glyph glyph-name="T" unicode="T" horiz-adv-x="456"
|
||||
d="M275 668v-668h-94v668h-179v86h452v-86h-179z" />
|
||||
<glyph glyph-name="U" unicode="U" horiz-adv-x="669"
|
||||
d="M59 754h94v-445q0 -237 182 -237t182 237v445h94v-477q0 -128 -74.5 -210.5t-201.5 -82.5t-201.5 82.5t-74.5 210.5v477z" />
|
||||
<glyph glyph-name="V" unicode="V" horiz-adv-x="640"
|
||||
d="M96 754l225 -558l224 558h103l-327 -794l-328 794h103z" />
|
||||
<glyph glyph-name="W" unicode="W" horiz-adv-x="1027"
|
||||
d="M90 754l211 -540l213 556l213 -556l211 540h102l-313 -784l-213 553l-213 -553l-313 784h102z" />
|
||||
<glyph glyph-name="X" unicode="X" horiz-adv-x="574"
|
||||
d="M237 395l-208 359h107l154 -275l164 275h107l-217 -359l229 -395h-105l-178 309l-185 -309h-105z" />
|
||||
<glyph glyph-name="Y" unicode="Y" horiz-adv-x="573"
|
||||
d="M240 328l-246 426h108l185 -322l185 322h108l-246 -426v-328h-94v328z" />
|
||||
<glyph glyph-name="Z" unicode="Z" horiz-adv-x="552"
|
||||
d="M162 86h382v-86h-535l382 668h-328v86h481z" />
|
||||
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="311"
|
||||
d="M153 725v-834h98v-84h-190v1002h190v-84h-98z" />
|
||||
<glyph glyph-name="backslash" unicode="\" horiz-adv-x="551"
|
||||
d="M31 868h84l404 -868h-84z" />
|
||||
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="311"
|
||||
d="M158 -109v834h-98v84h190v-1002h-190v84h98z" />
|
||||
<glyph glyph-name="asciicircum" unicode="^"
|
||||
d="M33 308l200 446h112l200 -446h-94l-162 362l-163 -362h-93z" />
|
||||
<glyph glyph-name="underscore" unicode="_" horiz-adv-x="500"
|
||||
d="M500 -75v-50h-500v50h500z" />
|
||||
<glyph glyph-name="grave" unicode="`" horiz-adv-x="360"
|
||||
d="M76 690l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="a" unicode="a" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90z" />
|
||||
<glyph glyph-name="b" unicode="b" horiz-adv-x="556"
|
||||
d="M288 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM55 0v868h90v-478h2q61 92 163 92q98 0 159 -72.5t61 -172.5q0 -106 -60 -179.5t-164 -73.5q-48 0 -89.5 24t-69.5 65h-2v-73h-90z" />
|
||||
<glyph glyph-name="c" unicode="c" horiz-adv-x="441"
|
||||
d="M406 451v-116q-55 63 -134 63q-65 0 -110.5 -49t-45.5 -115q0 -72 45.5 -119t116.5 -47q73 0 128 62v-115q-58 -31 -129 -31q-104 0 -177.5 71t-73.5 175q0 108 73.5 180t182.5 72q71 0 124 -31z" />
|
||||
<glyph glyph-name="d" unicode="d" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM411 0v73h-2q-28 -41 -69.5 -65t-89.5 -24q-104 0 -164 73.5t-60 179.5q0 100 61 172.5t159 72.5q102 0 163 -92h2v478h90v-868h-90z" />
|
||||
<glyph glyph-name="e" unicode="e" horiz-adv-x="488"
|
||||
d="M473 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94t-126.5 -34q-105 0 -167.5 70t-62.5 176q0 112 59 182t169 70q107 0 163 -69.5t56 -179.5v-14zM121 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84z" />
|
||||
<glyph glyph-name="f" unicode="f" horiz-adv-x="275"
|
||||
d="M294 868v-91q-43 19 -60 19q-18 0 -31 -9.5t-19 -21.5t-9.5 -32.5t-4 -32t-0.5 -31.5v-201h124v-84h-124v-384h-90v384h-41v84h41v228q0 184 151 184q33 0 63 -12z" />
|
||||
<glyph glyph-name="g" unicode="g" horiz-adv-x="555"
|
||||
d="M263 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM500 468v-459q0 -133 -50 -205t-178 -72q-99 0 -162 57t-64 155h90q0 -62 38.5 -97t101.5 -35q77 0 105.5 45t28.5 127v89h-2q-28 -41 -69.5 -65
|
||||
t-89.5 -24q-104 0 -164 73.5t-60 179.5q0 100 61 172.5t159 72.5q103 0 163 -94h2v80h90z" />
|
||||
<glyph glyph-name="h" unicode="h" horiz-adv-x="523"
|
||||
d="M62 868h90v-463h2q20 37 58.5 57t82.5 20q92 0 129 -54t37 -149v-279h-90v268q0 69 -19.5 101.5t-83.5 32.5q-28 0 -49 -7t-33 -23t-19.5 -30.5t-10.5 -41t-3.5 -41.5t-0.5 -44v-215h-90v868z" />
|
||||
<glyph glyph-name="i" unicode="i" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90zM127 745q26 0 44 -18.5t18 -44.5q0 -25 -18 -43t-44 -18t-44 18t-18 43q0 26 18 44.5t44 18.5z" />
|
||||
<glyph glyph-name="j" unicode="j" horiz-adv-x="254"
|
||||
d="M172 468v-736h-90v736h90zM127 745q26 0 44 -18.5t18 -44.5q0 -25 -18 -43t-44 -18t-44 18t-18 43q0 26 18 44.5t44 18.5z" />
|
||||
<glyph glyph-name="k" unicode="k" horiz-adv-x="462"
|
||||
d="M158 868v-576l176 176h119l-200 -194l220 -274h-117l-167 213l-31 -31v-182h-90v868h90z" />
|
||||
<glyph glyph-name="l" unicode="l" horiz-adv-x="222"
|
||||
d="M156 868v-868h-90v868h90z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="767"
|
||||
d="M149 468v-59h2q20 32 53.5 52.5t70.5 20.5q87 0 135 -83q22 38 61 60.5t83 22.5q155 0 155 -202v-280h-90v265q0 27 -2.5 47.5t-11 43t-27 34.5t-46.5 12t-47.5 -11.5t-30 -28t-16.5 -41.5t-7.5 -45t-1.5 -46v-230h-90v248q0 24 -1 40t-5.5 40t-13 38t-25.5 25t-41 11
|
||||
q-34 0 -56.5 -15.5t-32 -44t-12.5 -53.5t-3 -59v-230h-90v468h90z" />
|
||||
<glyph glyph-name="n" unicode="n" horiz-adv-x="523"
|
||||
d="M152 468v-63h2q20 37 58.5 57t82.5 20q92 0 129 -54t37 -149v-279h-90v268q0 69 -19.5 101.5t-83.5 32.5q-28 0 -49 -7t-33 -23t-19.5 -30.5t-10.5 -41t-3.5 -41.5t-0.5 -44v-215h-90v468h90z" />
|
||||
<glyph glyph-name="o" unicode="o" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48z" />
|
||||
<glyph glyph-name="p" unicode="p" horiz-adv-x="556"
|
||||
d="M288 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM145 468v-78h2q61 92 163 92q98 0 159 -72.5t61 -172.5q0 -106 -60 -179.5t-164 -73.5q-48 0 -89.5 24t-69.5 65h-2v-341h-90v736h90z" />
|
||||
<glyph glyph-name="q" unicode="q" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-736h-90v341h-2q-28 -41 -69.5 -65t-89.5 -24q-104 0 -164 73.5t-60 179.5q0 100 61 172.5t159 72.5q102 0 163 -92h2v78h90z" />
|
||||
<glyph glyph-name="r" unicode="r" horiz-adv-x="351"
|
||||
d="M158 468v-76h3q17 42 50.5 66t77.5 24q38 0 74 -23l-41 -82q-22 19 -55 19q-35 0 -58 -14.5t-33.5 -41t-14 -52t-3.5 -58.5v-230h-90v468h90z" />
|
||||
<glyph glyph-name="s" unicode="s" horiz-adv-x="384"
|
||||
d="M323 400l-73 -39q-20 41 -60 41q-19 0 -34 -13.5t-15 -32.5q0 -9 2.5 -16.5t10 -14t13 -11.5t18 -11.5t19.5 -10t23.5 -10.5t22.5 -10q50 -23 79 -53t29 -80q0 -66 -47.5 -110.5t-113.5 -44.5q-53 0 -98.5 28.5t-63.5 76.5l77 35q33 -60 85 -60q29 0 50 18.5t21 47.5
|
||||
t-33 51l-88 47q-46 25 -68 49.5t-22 68.5q0 57 40.5 96.5t97.5 39.5q88 0 128 -82z" />
|
||||
<glyph glyph-name="t" unicode="t" horiz-adv-x="240"
|
||||
d="M165 384v-384h-90v384h-49v84h49v179h90v-179h88v-84h-88z" />
|
||||
<glyph glyph-name="u" unicode="u" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5t-149 57.5t-49 157.5v269z" />
|
||||
<glyph glyph-name="v" unicode="v" horiz-adv-x="445"
|
||||
d="M88 468l134 -292l135 292h101l-236 -484l-235 484h101z" />
|
||||
<glyph glyph-name="w" unicode="w" horiz-adv-x="718"
|
||||
d="M86 468l136 -298l138 324l137 -324l136 298h102l-238 -484l-137 313l-138 -313l-238 484h102z" />
|
||||
<glyph glyph-name="x" unicode="x" horiz-adv-x="489"
|
||||
d="M195 254l-168 214h106l111 -151l121 151h109l-172 -214l201 -254h-105l-154 190l-149 -190h-109z" />
|
||||
<glyph glyph-name="y" unicode="y" horiz-adv-x="484"
|
||||
d="M201 80l-214 388h105l158 -297l147 297h101l-379 -736h-102z" />
|
||||
<glyph glyph-name="z" unicode="z" horiz-adv-x="495"
|
||||
d="M177 84h304v-84h-479l317 384h-263v84h438z" />
|
||||
<glyph glyph-name="braceleft" unicode="{" horiz-adv-x="334"
|
||||
d="M48 271v73q75 33 75 151v182q0 55 29.5 93.5t55.5 38.5h78v-84h-40q-15 0 -22 -10t-8 -20t-1 -32v-184q0 -52 -18 -93.5t-31.5 -55.5t-26.5 -23q8 -5 18 -15t24.5 -29.5t24 -53t9.5 -73.5v-184q0 -22 1 -32t8 -20t22 -10h40v-84h-78q-26 0 -55.5 38.5t-29.5 93.5v182
|
||||
q0 118 -75 151z" />
|
||||
<glyph glyph-name="bar" unicode="|" horiz-adv-x="570"
|
||||
d="M328 786v-1000h-86v1000h86z" />
|
||||
<glyph glyph-name="braceright" unicode="}" horiz-adv-x="334"
|
||||
d="M286 344v-73q-75 -33 -75 -151v-182q0 -55 -29.5 -93.5t-55.5 -38.5h-78v84h40q15 0 22 10t8 20t1 32v184q0 40 9.5 73.5t24 53t24.5 29.5t18 15q-13 9 -26.5 23t-31.5 55.5t-18 93.5v184q0 22 -1 32t-8 20t-22 10h-40v84h78q26 0 55.5 -38.5t29.5 -93.5v-182
|
||||
q0 -118 75 -151z" />
|
||||
<glyph glyph-name="asciitilde" unicode="~"
|
||||
d="M478 334l67 -50q-67 -122 -152 -122q-40 0 -115 51q-7 5 -21 14.5t-21 14.5t-17 11t-17.5 8.5t-13.5 2.5q-24 0 -45 -20t-47 -62l-63 45q22 32 30.5 43t30.5 35.5t44.5 34.5t47.5 10q55 0 122 -51q6 -5 18.5 -14.5t19 -14.5t15.5 -11t16.5 -8.5t14.5 -2.5q24 0 39.5 17
|
||||
t39.5 57q5 8 7 12z" />
|
||||
<glyph glyph-name="uni00A0" unicode=" " horiz-adv-x="289"
|
||||
/>
|
||||
<glyph glyph-name="exclamdown" unicode="¡" horiz-adv-x="321"
|
||||
d="M161 508q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5zM116 323h90v-581h-90v581z" />
|
||||
<glyph glyph-name="cent" unicode="¢"
|
||||
d="M356 704v-76q74 -4 122 -31v-115h-2q-47 61 -120 63v-328q73 10 122 62v-117q-50 -24 -105 -28l-17 -1v-85h-48v89q-91 14 -149.5 81t-58.5 159q0 94 58 164.5t150 84.5v78h48zM308 220v319q-51 -6 -85.5 -56t-34.5 -102q0 -56 33 -103t87 -58z" />
|
||||
<glyph glyph-name="sterling" unicode="£"
|
||||
d="M90 -16l-79 40q31 54 65.5 82.5t88.5 30.5q30 100 -8 164h-129v58h100q-58 110 -58 180q0 95 75.5 163t171.5 68q105 0 170 -64.5t70 -169.5l-90 -34v28q0 63 -41.5 107.5t-104.5 44.5q-61 0 -111 -47.5t-50 -103.5q0 -24 8 -50t16.5 -42t24.5 -42.5t22 -37.5h148v-58
|
||||
h-124q26 -84 0 -172l74 -26q6 -2 27.5 -11t37 -13.5t29.5 -4.5q19 0 36.5 13.5t26 26t20.5 34.5l75 -46q-23 -53 -62.5 -85.5t-93.5 -32.5q-48 0 -131 33q-79 32 -116 32q-62 0 -88 -65z" />
|
||||
<glyph glyph-name="currency" unicode="¤"
|
||||
d="M483 546l60 -60l-41 -44q42 -66 42 -142t-42 -142l41 -44l-60 -60l-46 44q-63 -48 -148 -48t-148 48l-46 -44l-60 60l41 44q-42 66 -42 142t42 142l-41 44l60 60l46 -44q63 48 148 48t148 -48zM289 130q72 0 123 50t52 120q1 74 -49 122t-126 48t-126 -48t-49 -122
|
||||
q2 -70 52.5 -120t122.5 -50z" />
|
||||
<glyph glyph-name="yen" unicode="¥"
|
||||
d="M336 260v-260h-94v260h-236v58h236v10l-54 94h-182v58h148l-158 274h108l185 -322l185 322h108l-158 -274h148v-58h-181l-55 -94v-10h236v-58h-236z" />
|
||||
<glyph glyph-name="brokenbar" unicode="¦" horiz-adv-x="570"
|
||||
d="M328 161v-250h-86v250h86zM328 661v-250h-86v250h86z" />
|
||||
<glyph glyph-name="section" unicode="§"
|
||||
d="M214 335l175 -87q27 17 43.5 46t16.5 59q0 32 -19.5 51t-56.5 37l-184 93q-27 -17 -43.5 -46t-16.5 -60q0 -18 6.5 -32.5t22 -26t25.5 -18t31 -16.5zM310 192l-141 69q-34 17 -51.5 27.5t-38.5 29.5t-30 43t-9 57q0 90 96 162q-44 50 -44 111q0 75 57.5 126t133.5 51
|
||||
q80 0 137 -45t62 -123h-87q-2 41 -35.5 65t-76.5 24q-42 0 -71.5 -29t-29.5 -71q0 -36 22.5 -59t62.5 -42l133 -67q31 -16 49 -26.5t42 -29t35.5 -42t11.5 -51.5q0 -49 -24.5 -94t-64.5 -75q53 -50 53 -122q0 -86 -63 -139.5t-150 -53.5q-99 0 -162.5 58t-63.5 157v15h89
|
||||
q-2 -62 36 -105t100 -43q49 0 86.5 32t37.5 81q0 21 -8.5 38t-26.5 31t-30 21t-37 19z" />
|
||||
<glyph glyph-name="dieresis" unicode="¨" horiz-adv-x="470"
|
||||
d="M130 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5zM341 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="copyright" unicode="©" horiz-adv-x="800"
|
||||
d="M400 -16q-165 0 -279.5 114.5t-114.5 278.5t114.5 278.5t279.5 114.5t279.5 -114.5t114.5 -278.5t-114.5 -278.5t-279.5 -114.5zM400 706q-136 0 -233 -95.5t-97 -233.5t97 -233.5t233 -95.5t233 95.5t97 233.5t-97 233.5t-233 95.5zM600 458h-61q-9 41 -42 63t-83 22
|
||||
q-76 0 -114.5 -47.5t-38.5 -113.5q0 -72 41 -118t114 -46q102 0 123 89h61q-9 -69 -61.5 -111t-122.5 -42q-98 0 -158.5 65t-60.5 161q0 100 59 163.5t159 63.5q71 0 121.5 -40t63.5 -109z" />
|
||||
<glyph glyph-name="ordfeminine" unicode="ª" horiz-adv-x="334"
|
||||
d="M167 519q46 0 72.5 29.5t26.5 72.5t-26.5 72t-72.5 29q-43 0 -69.5 -30t-26.5 -71q0 -42 26 -72t70 -30zM322 761v-280h-59v43h-2q-39 -53 -103 -53q-67 0 -106.5 44t-39.5 108q0 60 40 103.5t104 43.5t106 -55h1v46h59z" />
|
||||
<glyph glyph-name="guillemotleft" unicode="«" horiz-adv-x="523"
|
||||
d="M311 320l149 -191l-56 -41l-182 232l182 240l56 -41zM119 320l149 -191l-56 -41l-182 232l182 240l56 -41z" />
|
||||
<glyph glyph-name="logicalnot" unicode="¬"
|
||||
d="M459 115v184h-426v86h512v-270h-86z" />
|
||||
<glyph glyph-name="uni00AD" unicode="­" horiz-adv-x="332"
|
||||
d="M57 358h219v-75h-219v75z" />
|
||||
<glyph glyph-name="registered" unicode="®" horiz-adv-x="800"
|
||||
d="M400 -16q-165 0 -279.5 114.5t-114.5 278.5t114.5 278.5t279.5 114.5t279.5 -114.5t114.5 -278.5t-114.5 -278.5t-279.5 -114.5zM400 706q-136 0 -233 -95.5t-97 -233.5t97 -233.5t233 -95.5t233 95.5t97 233.5t-97 233.5t-233 95.5zM468 357l112 -204h-73l-113 204h-82
|
||||
v-204h-64v442h186q152 0 152 -117q0 -60 -34 -89.5t-84 -31.5zM422 531h-110v-110h68q7 0 26.5 -0.5t28.5 0t25.5 1.5t25 4t18.5 8.5t14 15t4 21.5q0 20 -7.5 33t-23 18.5t-30.5 7t-39 1.5z" />
|
||||
<glyph glyph-name="macron" unicode="¯" horiz-adv-x="500"
|
||||
d="M70 694h361v-68h-361v68z" />
|
||||
<glyph glyph-name="degree" unicode="°" horiz-adv-x="400"
|
||||
d="M350 620q0 -62 -44 -106t-106 -44t-106 44t-44 106q-1 62 43.5 106t106.5 44t106 -44t44 -106zM199 720q-42 0 -71 -29t-28 -71q0 -43 28.5 -71.5t71.5 -28.5q42 0 71 28.5t29 71.5q0 42 -29 71t-72 29z" />
|
||||
<glyph glyph-name="plusminus" unicode="±"
|
||||
d="M33 0v86h512v-86h-512zM246 562h86v-173h213v-86h-213v-173h-86v173h-213v86h213v173z" />
|
||||
<glyph glyph-name="twosuperior" unicode="²" horiz-adv-x="346"
|
||||
d="M144 360h188v-58h-317l215 243q38 44 38 81q0 33 -29 56.5t-62 23.5q-37 0 -61.5 -21t-26.5 -55h-67q7 61 48 97.5t107 36.5q63 0 109 -39t46 -97q0 -55 -33 -93z" />
|
||||
<glyph glyph-name="threesuperior" unicode="³" horiz-adv-x="346"
|
||||
d="M163 518v58q43 0 68.5 17t25.5 50t-25 51t-58 18q-32 0 -53.5 -14t-21.5 -42h-67q9 55 46 84.5t98 29.5t103 -33.5t42 -88.5q0 -67 -66 -102q73 -32 73 -112q0 -62 -46 -99t-114 -37q-59 0 -102.5 33.5t-46.5 88.5h64q10 -64 90 -64q37 0 64 22t27 58q0 38 -29 61t-72 21
|
||||
z" />
|
||||
<glyph glyph-name="acute" unicode="´" horiz-adv-x="360"
|
||||
d="M201 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="mu" unicode="µ" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5q-56 0 -108 44v-296h-90v736z" />
|
||||
<glyph glyph-name="paragraph" unicode="¶"
|
||||
d="M538 754v-84h-61v-823h-84v823h-62v-823h-84v436q-86 0 -142.5 57t-63.5 157q-7 95 56.5 176t158.5 81h282z" />
|
||||
<glyph glyph-name="periodcentered" unicode="·" horiz-adv-x="289"
|
||||
d="M145 314q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="cedilla" unicode="¸" horiz-adv-x="330"
|
||||
d="M244 -46l-105 -135l-53 27l87 137z" />
|
||||
<glyph glyph-name="onesuperior" unicode="¹" horiz-adv-x="346"
|
||||
d="M151 696h-86l34 58h116v-452h-64v394z" />
|
||||
<glyph glyph-name="ordmasculine" unicode="º" horiz-adv-x="324"
|
||||
d="M162 770q68 0 115.5 -43t47.5 -107q0 -63 -47.5 -106t-115.5 -43t-115 43t-47 106q0 64 47 107t115 43zM162 718q-43 0 -73 -28.5t-30 -69.5q0 -39 30 -68t73 -29t73.5 29t30.5 68q0 41 -30.5 69.5t-73.5 28.5z" />
|
||||
<glyph glyph-name="guillemotright" unicode="»" horiz-adv-x="523"
|
||||
d="M63 129l149 191l-149 199l56 41l182 -240l-182 -232zM255 129l149 191l-149 199l56 41l182 -240l-182 -232z" />
|
||||
<glyph glyph-name="onequarter" unicode="¼" horiz-adv-x="867"
|
||||
d="M778 124h49v-58h-49v-66h-64v66h-243l307 407v-349zM714 124v164h-3l-123 -164h126zM126 696h-86l34 58h116v-452h-64v394zM631 770l51 -26l-440 -760l-51 28z" />
|
||||
<glyph glyph-name="onehalf" unicode="½" horiz-adv-x="867"
|
||||
d="M126 302v394h-86l34 58h116v-452h-64zM639 58h188v-58h-317l215 243q38 44 38 81q0 33 -29 56.5t-62 23.5q-37 0 -61.5 -21t-26.5 -55h-67q7 61 48 97.5t107 36.5q63 0 109 -39t46 -97q0 -55 -33 -93zM579 770l51 -26l-440 -760l-51 28z" />
|
||||
<glyph glyph-name="threequarters" unicode="¾" horiz-adv-x="867"
|
||||
d="M778 124h49v-58h-49v-66h-64v66h-243l307 407v-349zM714 124v164h-3l-123 -164h126zM184 518v58q43 0 68.5 17t25.5 50t-25 51t-58 18q-32 0 -53.5 -14t-21.5 -42h-67q9 55 46 84.5t98 29.5t103 -33.5t42 -88.5q0 -67 -66 -102q73 -32 73 -112q0 -62 -46 -99t-114 -37
|
||||
q-59 0 -102.5 33.5t-46.5 88.5h64q10 -64 90 -64q37 0 64 22t27 58q0 38 -29 61t-72 21zM687 770l51 -26l-440 -760l-51 28z" />
|
||||
<glyph glyph-name="questiondown" unicode="¿" horiz-adv-x="453"
|
||||
d="M152 157h-91q-3 64 47 112.5t115 48.5q67 0 114 -46.5t47 -113.5q0 -64 -33 -94.5t-93 -52.5q-5 -2 -20 -7.5t-21 -7.5t-19 -7.5t-18 -9t-15 -10t-14 -12.5t-9 -14t-7 -17t-2 -20q0 -41 26 -65t66 -24q35 0 60.5 25.5t25.5 60.5q0 10 -6 32h94l2 -33q4 -71 -51 -120.5
|
||||
t-128 -49.5q-76 0 -128 51t-52 126q0 78 54 124q31 27 124 56q73 22 73 73q0 30 -20 51t-50 21q-32 0 -52 -22.5t-19 -54.5zM223 508q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="Agrave" unicode="À" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM208 951l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="Aacute" unicode="Á" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM413 995l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="Acircumflex" unicode="Â" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM192 850l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="Atilde" unicode="Ã" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM208 834l-47 40l3 5q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="Adieresis" unicode="Ä" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM247 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5zM458 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43
|
||||
t18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="Aring" unicode="Å" horiz-adv-x="703"
|
||||
d="M525 189h-346l-86 -189h-101l360 786l360 -786h-101zM486 275l-134 305l-134 -305h268zM352 985q38 0 64.5 -26.5t26.5 -64.5t-26.5 -64t-64.5 -26t-64 26t-26 64t26.5 64.5t63.5 26.5zM352 849q19 0 32.5 13t13.5 32t-13.5 32.5t-32.5 13.5q-18 0 -31.5 -13.5
|
||||
t-13.5 -32.5t13.5 -32t31.5 -13z" />
|
||||
<glyph glyph-name="AE" unicode="Æ" horiz-adv-x="997"
|
||||
d="M532 189h-343l-86 -189h-103l362 754h330l38 -86h-309l91 -211h301l40 -86h-302l121 -285h311l38 -86h-406zM497 275l-130 292l-138 -292h268z" />
|
||||
<glyph glyph-name="Ccedilla" unicode="Ç" horiz-adv-x="661"
|
||||
d="M621 719v-109q-83 74 -199 74q-125 0 -211.5 -90.5t-86.5 -217.5q0 -125 85.5 -215.5t210.5 -90.5q114 0 201 78v-111q-90 -53 -198 -53q-162 0 -277.5 113t-115.5 276q0 167 117 282t284 115q107 0 190 -51zM410 -46l-105 -135l-53 27l87 137z" />
|
||||
<glyph glyph-name="Egrave" unicode="È" horiz-adv-x="521"
|
||||
d="M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405zM137 951l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="Eacute" unicode="É" horiz-adv-x="521"
|
||||
d="M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405zM322 995l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="Ecircumflex" unicode="Ê" horiz-adv-x="521"
|
||||
d="M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405zM113 850l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="Edieresis" unicode="Ë" horiz-adv-x="521"
|
||||
d="M72 0v754h405v-86h-311v-211h302v-86h-302v-285h311v-86h-405zM168 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43t18 42.5t43 17.5zM379 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="Igrave" unicode="Ì" horiz-adv-x="232"
|
||||
d="M163 754v-754h-94v754h94zM-18 951l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="Iacute" unicode="Í" horiz-adv-x="232"
|
||||
d="M163 754v-754h-94v754h94zM167 995l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="Icircumflex" unicode="Î" horiz-adv-x="232"
|
||||
d="M163 754v-754h-94v754h94zM-44 850l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="Idieresis" unicode="Ï" horiz-adv-x="232"
|
||||
d="M163 754v-754h-94v754h94zM11 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5zM222 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43t18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="Eth" unicode="Ð" horiz-adv-x="665"
|
||||
d="M64 442v312h156q183 0 303 -96.5t120 -276.5q0 -185 -119 -283t-307 -98h-153v362h-64v80h64zM158 668v-226h134v-80h-134v-276h33q76 0 138 15t112.5 48t79 91t28.5 137q0 80 -28.5 138t-79.5 90.5t-112.5 47.5t-137.5 15h-33z" />
|
||||
<glyph glyph-name="Ntilde" unicode="Ñ" horiz-adv-x="785"
|
||||
d="M63 0v790l566 -593v557h94v-785l-566 593v-562h-94zM249 834l-47 40l3 5q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="Ograve" unicode="Ò" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5zM280 951l83 44l125 -166
|
||||
l-44 -27z" />
|
||||
<glyph glyph-name="Oacute" unicode="Ó" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5zM465 995l83 -44l-164 -149
|
||||
l-44 27z" />
|
||||
<glyph glyph-name="Ocircumflex" unicode="Ô" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5zM254 850l159 145l161 -145
|
||||
l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="Otilde" unicode="Õ" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5zM270 834l-47 40l3 5
|
||||
q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="Odieresis" unicode="Ö" horiz-adv-x="828"
|
||||
d="M414 770q162 0 278.5 -115.5t116.5 -277.5q0 -167 -115 -280t-280 -113t-280 113t-115 280q0 162 116.5 277.5t278.5 115.5zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89t-85.5 -216q0 -128 89 -216.5t212 -88.5zM309 955q25 0 42.5 -17.5
|
||||
t17.5 -42.5t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5zM520 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43t18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="multiply" unicode="×"
|
||||
d="M33 451l60 61l196 -195l196 195l60 -61l-195 -195l195 -195l-60 -61l-196 195l-196 -195l-60 61l195 195z" />
|
||||
<glyph glyph-name="Oslash" unicode="Ø" horiz-adv-x="828"
|
||||
d="M659 557l-428 -422q81 -63 183 -63q123 0 212 88.5t89 216.5q0 102 -56 180zM178 189l430 423q-80 70 -194 70q-130 0 -215.5 -89t-85.5 -216q0 -107 65 -188zM7 21l104 102q-92 108 -92 254q0 162 116.5 277.5t278.5 115.5q146 0 257 -96l96 95l54 -53l-98 -96
|
||||
q86 -108 86 -243q0 -167 -115 -280t-280 -113q-141 0 -249 86l-104 -102z" />
|
||||
<glyph glyph-name="Ugrave" unicode="Ù" horiz-adv-x="669"
|
||||
d="M59 754h94v-445q0 -237 182 -237t182 237v445h94v-477q0 -128 -74.5 -210.5t-201.5 -82.5t-201.5 82.5t-74.5 210.5v477zM201 951l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="Uacute" unicode="Ú" horiz-adv-x="669"
|
||||
d="M59 754h94v-445q0 -237 182 -237t182 237v445h94v-477q0 -128 -74.5 -210.5t-201.5 -82.5t-201.5 82.5t-74.5 210.5v477zM386 995l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="Ucircumflex" unicode="Û" horiz-adv-x="669"
|
||||
d="M59 754h94v-445q0 -237 182 -237t182 237v445h94v-477q0 -128 -74.5 -210.5t-201.5 -82.5t-201.5 82.5t-74.5 210.5v477zM175 850l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="Udieresis" unicode="Ü" horiz-adv-x="669"
|
||||
d="M59 754h94v-445q0 -237 182 -237t182 237v445h94v-477q0 -128 -74.5 -210.5t-201.5 -82.5t-201.5 82.5t-74.5 210.5v477zM230 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43t18 42.5t43 17.5zM441 955q25 0 42.5 -17.5t17.5 -42.5
|
||||
t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="Yacute" unicode="Ý" horiz-adv-x="573"
|
||||
d="M240 328l-246 426h108l185 -322l185 322h108l-246 -426v-328h-94v328zM368 995l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="Thorn" unicode="Þ" horiz-adv-x="495"
|
||||
d="M166 176v-176h-94v754h94v-140h14q167 0 235.5 -54.5t68.5 -163.5q0 -112 -73.5 -166t-190.5 -54h-54zM166 530v-270h30q41 0 72.5 5t62.5 18.5t48 42.5t17 72q0 42 -18 70t-51 40.5t-64 17t-72 4.5h-25z" />
|
||||
<glyph glyph-name="germandbls" unicode="ß" horiz-adv-x="580"
|
||||
d="M282 -16v84q78 0 136.5 56t58.5 134q0 84 -54.5 131.5t-140.5 53.5v88q57 -1 96 39.5t39 98.5q0 55 -38 91t-92 36q-27 0 -48.5 -9t-35 -20.5t-22.5 -34.5t-13.5 -38.5t-7 -46.5t-2.5 -43.5v-44.5v-559h-90v386h-40v84h40v148q0 262 222 262q93 0 155 -61t62 -155
|
||||
q0 -111 -96 -167q72 -23 114 -91.5t42 -147.5q0 -117 -84.5 -198t-200.5 -76z" />
|
||||
<glyph glyph-name="agrave" unicode="à" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM159 690l83 44l125 -166
|
||||
l-44 -27z" />
|
||||
<glyph glyph-name="aacute" unicode="á" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM339 734l83 -44
|
||||
l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="acircumflex" unicode="â" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM118 589l159 145
|
||||
l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="atilde" unicode="ã" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM134 573l-47 40l3 5
|
||||
q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="adieresis" unicode="ä" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM173 694
|
||||
q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5zM384 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="aring" unicode="å" horiz-adv-x="556"
|
||||
d="M264 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50zM501 468v-468h-90v73h-2q-60 -89 -159 -89q-103 0 -163.5 73.5t-60.5 179.5q0 100 61 172.5t160 72.5q101 0 162 -92h2v78h90zM278 734
|
||||
q38 0 64.5 -26.5t26.5 -64.5t-26.5 -64t-64.5 -26t-64 26.5t-26 63.5q0 38 26.5 64.5t63.5 26.5zM278 598q19 0 32.5 13t13.5 32t-13.5 32.5t-32.5 13.5q-18 0 -31.5 -13.5t-13.5 -32.5t13.5 -32t31.5 -13z" />
|
||||
<glyph glyph-name="ae" unicode="æ" horiz-adv-x="807"
|
||||
d="M442 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM221 218q-41 0 -76 -20.5t-35 -58.5t36 -56.5t78 -18.5q43 0 79.5 19.5t36.5 58.5q0 38 -38 57t-81 19zM792 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94
|
||||
t-126.5 -34q-105 0 -180 87q-28 -42 -76.5 -64.5t-102.5 -22.5q-76 0 -133 39.5t-57 113.5q0 73 51 115t126 42q90 0 142 -43v32q0 121 -123 121q-81 0 -128 -15v80q66 13 141 13q48 0 93.5 -19.5t66.5 -57.5q62 77 178 77q107 0 163 -69.5t56 -179.5v-14z" />
|
||||
<glyph glyph-name="ccedilla" unicode="ç" horiz-adv-x="441"
|
||||
d="M406 451v-116q-55 63 -134 63q-65 0 -110.5 -49t-45.5 -115q0 -72 45.5 -119t116.5 -47q73 0 128 62v-115q-58 -31 -129 -31q-104 0 -177.5 71t-73.5 175q0 108 73.5 180t182.5 72q71 0 124 -31zM300 -46l-105 -135l-53 27l87 137z" />
|
||||
<glyph glyph-name="egrave" unicode="è" horiz-adv-x="488"
|
||||
d="M473 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94t-126.5 -34q-105 0 -167.5 70t-62.5 176q0 112 59 182t169 70q107 0 163 -69.5t56 -179.5v-14zM121 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM125 690l83 44
|
||||
l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="eacute" unicode="é" horiz-adv-x="488"
|
||||
d="M473 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94t-126.5 -34q-105 0 -167.5 70t-62.5 176q0 112 59 182t169 70q107 0 163 -69.5t56 -179.5v-14zM121 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM305 734
|
||||
l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="ecircumflex" unicode="ê" horiz-adv-x="488"
|
||||
d="M473 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94t-126.5 -34q-105 0 -167.5 70t-62.5 176q0 112 59 182t169 70q107 0 163 -69.5t56 -179.5v-14zM121 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM84 589
|
||||
l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="edieresis" unicode="ë" horiz-adv-x="488"
|
||||
d="M473 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94t-126.5 -34q-105 0 -167.5 70t-62.5 176q0 112 59 182t169 70q107 0 163 -69.5t56 -179.5v-14zM121 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM139 694
|
||||
q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5zM350 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="igrave" unicode="ì" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90zM-7 690l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="iacute" unicode="í" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90zM178 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90zM-33 589l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="idieresis" unicode="ï" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90zM22 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5zM233 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="eth" unicode="ð" horiz-adv-x="540"
|
||||
d="M270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM46 638l145 83q-54 60 -111 105l57 51q62 -43 129 -113l145 83l42 -55l-141 -81q91 -107 149.5 -229.5t58.5 -229.5q0 -124 -71 -196t-179 -72q-105 0 -177.5 72
|
||||
t-72.5 177t72.5 177t177.5 72q10 0 19.5 -1t17 -2.5t15.5 -4t13 -4.5t12.5 -6t10 -5.5t10 -5.5t8.5 -5q-58 119 -139 220l-147 -84z" />
|
||||
<glyph glyph-name="ntilde" unicode="ñ" horiz-adv-x="523"
|
||||
d="M152 468v-63h2q20 37 58.5 57t82.5 20q92 0 129 -54t37 -149v-279h-90v268q0 69 -19.5 101.5t-83.5 32.5q-28 0 -49 -7t-33 -23t-19.5 -30.5t-10.5 -41t-3.5 -41.5t-0.5 -44v-215h-90v468h90zM118 573l-47 40l3 5q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27
|
||||
q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="ograve" unicode="ò" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM126 690l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="oacute" unicode="ó" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM331 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="ocircumflex" unicode="ô" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM110 589l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="otilde" unicode="õ" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM126 573l-47 40l3 5q17 24 29 38t33 26t46 12q41 0 89 -26
|
||||
q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="odieresis" unicode="ö" horiz-adv-x="540"
|
||||
d="M270 482q105 0 177.5 -72t72.5 -177t-72.5 -177t-177.5 -72t-177.5 72t-72.5 177t72.5 177t177.5 72zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM165 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18
|
||||
t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5zM376 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="divide" unicode="÷"
|
||||
d="M33 213v86h512v-86h-512zM289 124q26 0 44 -18.5t18 -44.5q0 -25 -18 -43t-44 -18t-44 18t-18 43q0 26 18 44.5t44 18.5zM289 512q26 0 44 -18.5t18 -44.5q0 -25 -18 -43t-44 -18t-44 18t-18 43q0 26 18 44.5t44 18.5z" />
|
||||
<glyph glyph-name="oslash" unicode="ø" horiz-adv-x="540"
|
||||
d="M139 141l223 225q-42 30 -92 30q-66 0 -113 -48t-47 -115q0 -50 29 -92zM405 319l-221 -223q38 -26 86 -26q66 0 113 48.5t47 114.5q0 49 -25 86zM8 9l67 67q-55 66 -55 157q0 105 72.5 177t177.5 72q87 0 155 -52l61 61l46 -43l-62 -63q50 -66 50 -152
|
||||
q0 -105 -72.5 -177t-177.5 -72q-85 0 -149 48l-69 -70z" />
|
||||
<glyph glyph-name="ugrave" unicode="ù" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5t-149 57.5t-49 157.5v269zM112 690l83 44l125 -166l-44 -27z" />
|
||||
<glyph glyph-name="uacute" unicode="ú" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5t-149 57.5t-49 157.5v269zM317 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="ucircumflex" unicode="û" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5t-149 57.5t-49 157.5v269zM96 589l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="udieresis" unicode="ü" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5t-149 57.5t-49 157.5v269zM151 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5zM362 694q25 0 42.5 -17.5
|
||||
t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="yacute" unicode="ý" horiz-adv-x="484"
|
||||
d="M201 80l-214 388h105l158 -297l147 297h101l-379 -736h-102zM323 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="thorn" unicode="þ" horiz-adv-x="556"
|
||||
d="M145 868v-478h2q61 92 163 92q98 0 159 -72.5t61 -172.5q0 -106 -60 -179.5t-164 -73.5q-48 0 -89.5 24t-69.5 65h-2v-341h-90v1136h90zM288 64q71 0 111.5 49t40.5 121q0 71 -41 119.5t-111 48.5q-67 0 -107.5 -49.5t-40.5 -118.5q0 -70 40 -120t108 -50z" />
|
||||
<glyph glyph-name="ydieresis" unicode="ÿ" horiz-adv-x="484"
|
||||
d="M201 80l-214 388h105l158 -297l147 297h101l-379 -736h-102zM147 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5zM358 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 17.5t-17.5 43.5q0 25 18 42.5
|
||||
t43 17.5z" />
|
||||
<glyph glyph-name="dotlessi" unicode="ı" horiz-adv-x="254"
|
||||
d="M172 468v-468h-90v468h90z" />
|
||||
<glyph glyph-name="Lslash" unicode="Ł" horiz-adv-x="385"
|
||||
d="M166 754v-288l118 83v-90l-118 -79v-294h229v-86h-323v322l-81 -58v91l81 54v345h94z" />
|
||||
<glyph glyph-name="lslash" unicode="ł" horiz-adv-x="255"
|
||||
d="M82 0v412l-81 -55v81l81 55v375h90v-314l82 56v-82l-82 -55v-473h-90z" />
|
||||
<glyph glyph-name="OE" unicode="Œ" horiz-adv-x="1143"
|
||||
d="M718 0v126h-2q-51 -68 -130.5 -105.5t-171.5 -36.5q-165 0 -280 113t-115 280q0 162 116.5 277.5t278.5 115.5q90 -3 172 -41t130 -107h2v132h395v-86h-310v-211h301v-86h-301v-285h310v-86h-395zM414 72q123 0 212 88.5t89 216.5q0 127 -85.5 216t-215.5 89t-215.5 -89
|
||||
t-85.5 -216q0 -128 89 -216.5t212 -88.5z" />
|
||||
<glyph glyph-name="oe" unicode="œ" horiz-adv-x="897"
|
||||
d="M529 287h262q-8 54 -42 85.5t-87 31.5q-52 0 -88.5 -33t-44.5 -84zM270 396q-66 0 -113 -48t-47 -115q0 -66 47 -114.5t113 -48.5t113 48.5t47 114.5q0 67 -47 115t-113 48zM882 219h-357q1 -63 40 -109t101 -46q49 0 80.5 22.5t59.5 68.5l76 -43q-33 -60 -90.5 -94
|
||||
t-126.5 -34q-60 -1 -113 26.5t-82 76.5q-33 -49 -87 -76.5t-113 -26.5q-105 0 -177.5 72t-72.5 177t72.5 177t177.5 72q58 -2 113 -30t87 -75q64 101 193 105q107 0 163 -69.5t56 -179.5v-14z" />
|
||||
<glyph glyph-name="Scaron" unicode="Š" horiz-adv-x="537"
|
||||
d="M482 656l-75 -45q-42 71 -121 71q-48 0 -87 -30t-39 -77q0 -68 105 -108l54 -21q90 -35 138.5 -87t48.5 -140q0 -102 -69.5 -168.5t-171.5 -66.5q-91 0 -156 59.5t-77 151.5l95 20q-1 -61 41.5 -102t104.5 -41q60 0 99.5 43.5t39.5 103.5q0 55 -34.5 86.5t-95.5 56.5
|
||||
l-52 22q-77 33 -120.5 76t-43.5 115q0 88 66 141.5t156 53.5q130 0 194 -114zM119 949l58 46l101 -96l102 96l59 -46l-161 -145z" />
|
||||
<glyph glyph-name="scaron" unicode="š" horiz-adv-x="384"
|
||||
d="M323 400l-73 -39q-20 41 -60 41q-19 0 -34 -13.5t-15 -32.5q0 -9 2.5 -16.5t10 -14t13 -11.5t18 -11.5t19.5 -10t23.5 -10.5t22.5 -10q50 -23 79 -53t29 -80q0 -66 -47.5 -110.5t-113.5 -44.5q-53 0 -98.5 28.5t-63.5 76.5l77 35q33 -60 85 -60q29 0 50 18.5t21 47.5
|
||||
t-33 51l-88 47q-46 25 -68 49.5t-22 68.5q0 57 40.5 96.5t97.5 39.5q88 0 128 -82zM32 688l58 46l101 -96l102 96l59 -46l-161 -145z" />
|
||||
<glyph glyph-name="Ydieresis" unicode="Ÿ" horiz-adv-x="573"
|
||||
d="M240 328l-246 426h108l185 -322l185 322h108l-246 -426v-328h-94v328zM194 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18q-26 0 -43.5 18t-17.5 43t18 42.5t43 17.5zM405 955q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 18t-18 43t18 42.5t43 17.5z
|
||||
" />
|
||||
<glyph glyph-name="Zcaron" unicode="Ž" horiz-adv-x="552"
|
||||
d="M162 86h382v-86h-535l382 668h-328v86h481zM131 949l58 46l101 -96l102 96l59 -46l-161 -145z" />
|
||||
<glyph glyph-name="zcaron" unicode="ž" horiz-adv-x="495"
|
||||
d="M177 84h304v-84h-479l317 384h-263v84h438zM103 688l58 46l101 -96l102 96l59 -46l-161 -145z" />
|
||||
<glyph glyph-name="florin" unicode="ƒ"
|
||||
d="M355 505h129l-9 -68h-131l-55 -303q-7 -42 -12.5 -67.5t-16 -59t-22 -53.5t-30 -42t-41.5 -34t-55.5 -19.5t-73.5 -7.5h-24l15 86h19q28 0 49.5 6.5t36.5 22t24.5 29t17 41.5t10.5 43t9 50l53 308h-65l9 68h70l21 124q17 100 60 153.5t137 53.5q33 0 60 -7l-16 -84
|
||||
q-18 7 -41 7t-41 -8.5t-27.5 -18.5t-18 -32t-11.5 -34.5t-8 -40.5z" />
|
||||
<glyph glyph-name="circumflex" unicode="ˆ" horiz-adv-x="470"
|
||||
d="M75 589l159 145l161 -145l-59 -46l-102 96l-101 -96z" />
|
||||
<glyph glyph-name="caron" unicode="ˇ" horiz-adv-x="472"
|
||||
d="M76 688l58 46l101 -96l102 96l59 -46l-161 -145z" />
|
||||
<glyph glyph-name="uni02C9" unicode="ˉ" horiz-adv-x="500"
|
||||
d="M70 694h361v-68h-361v68z" />
|
||||
<glyph glyph-name="breve" unicode="˘" horiz-adv-x="490"
|
||||
d="M71 694h72q32 -75 102 -75q39 0 62.5 18.5t40.5 56.5h71q-11 -62 -60.5 -101.5t-113.5 -39.5q-63 0 -112.5 39.5t-61.5 101.5z" />
|
||||
<glyph glyph-name="dotaccent" unicode="˙" horiz-adv-x="360"
|
||||
d="M181 694q25 0 42.5 -17.5t17.5 -42.5t-17.5 -43t-42.5 -18t-43 17.5t-18 43.5q0 25 18 42.5t43 17.5z" />
|
||||
<glyph glyph-name="ring" unicode="˚" horiz-adv-x="360"
|
||||
d="M180 734q38 0 64.5 -26.5t26.5 -64.5t-26.5 -64t-64.5 -26t-64 26.5t-26 63.5q0 38 26.5 64.5t63.5 26.5zM180 598q19 0 32.5 13t13.5 32t-13.5 32.5t-32.5 13.5q-18 0 -31.5 -13.5t-13.5 -32.5t13.5 -32t31.5 -13z" />
|
||||
<glyph glyph-name="ogonek" unicode="˛" horiz-adv-x="340"
|
||||
d="M165 -16h46v-2q-61 -41 -61 -85q0 -47 56 -47q30 0 50 13l-7 -58q-27 -17 -64 -17q-40 0 -70.5 22t-30.5 60q0 65 81 114z" />
|
||||
<glyph glyph-name="tilde" unicode="˜" horiz-adv-x="510"
|
||||
d="M111 573l-47 40l3 5q17 24 29 38t33 26t46 12q41 0 89 -26q50 -27 72 -27q35 0 64 48l47 -39q-40 -82 -118 -82q-29 0 -83 26q-54 25 -78 25q-17 0 -32.5 -14t-24.5 -32z" />
|
||||
<glyph glyph-name="hungarumlaut" unicode="˝" horiz-adv-x="470"
|
||||
d="M349 725l83 -44l-164 -149l-44 27zM163 734l83 -44l-164 -149l-44 27z" />
|
||||
<glyph glyph-name="uni03A9" unicode="Ω" horiz-adv-x="745"
|
||||
d="M204 70v3q-61 57 -100.5 144t-39.5 192q0 158 88.5 259t223.5 101q136 0 220 -105t84 -250q0 -109 -41 -198.5t-100 -142.5v-3h155v-70h-252v51q65 46 109 136t44 211q0 74 -23.5 140.5t-75.5 113t-121 46.5q-102 0 -164 -86.5t-62 -216.5q0 -114 44.5 -207.5
|
||||
t107.5 -136.5v-51h-251v70h154z" />
|
||||
<glyph glyph-name="uni03BC" unicode="μ" horiz-adv-x="512"
|
||||
d="M58 468h90v-259q0 -65 23.5 -103t84.5 -38t84.5 38t23.5 103v259h90v-269q0 -100 -49 -157.5t-149 -57.5q-56 0 -108 44v-296h-90v736z" />
|
||||
<glyph glyph-name="pi" unicode="π" horiz-adv-x="598"
|
||||
d="M570 491h-83v-333q0 -104 15 -158h-81q-17 31 -17 151v340h-185q-4 -114 -26 -265t-49 -226h-82q29 85 50 230.5t25 260.5q-79 0 -115 -13l-12 57q44 29 152 29h415z" />
|
||||
<glyph glyph-name="endash" unicode="–" horiz-adv-x="500"
|
||||
d="M0 358h500v-75h-500v75z" />
|
||||
<glyph glyph-name="emdash" unicode="—" horiz-adv-x="1000"
|
||||
d="M130 358h740v-75h-740v75z" />
|
||||
<glyph glyph-name="quoteleft" unicode="‘" horiz-adv-x="277"
|
||||
d="M139 472l-79 31l133 267l56 -23z" />
|
||||
<glyph glyph-name="quoteright" unicode="’" horiz-adv-x="277"
|
||||
d="M138 770l79 -31l-133 -267l-56 23z" />
|
||||
<glyph glyph-name="quotesinglbase" unicode="‚" horiz-adv-x="277"
|
||||
d="M164 119l78 -31l-133 -267l-55 23z" />
|
||||
<glyph glyph-name="quotedblleft" unicode="“" horiz-adv-x="439"
|
||||
d="M305 472l-79 31l133 267l56 -23zM139 472l-79 31l133 267l56 -23z" />
|
||||
<glyph glyph-name="quotedblright" unicode="”" horiz-adv-x="439"
|
||||
d="M134 770l79 -31l-133 -267l-56 23zM300 770l79 -31l-133 -267l-56 23z" />
|
||||
<glyph glyph-name="quotedblbase" unicode="„" horiz-adv-x="439"
|
||||
d="M160 119l78 -31l-133 -267l-55 23zM326 119l78 -31l-133 -267l-55 23z" />
|
||||
<glyph glyph-name="dagger" unicode="†"
|
||||
d="M244 868h90v-275h181v-86h-181v-595h-90v595h-181v86h181v275z" />
|
||||
<glyph glyph-name="daggerdbl" unicode="‡"
|
||||
d="M244 868h90v-239h181v-86h-181v-122h181v-86h-181v-422h-90v422h-181v86h181v122h-181v86h181v239z" />
|
||||
<glyph glyph-name="bullet" unicode="•"
|
||||
d="M289 189q-78 0 -133 55t-55 133q-1 79 54 134t134 55t134 -55t55 -134q0 -78 -55.5 -133t-133.5 -55z" />
|
||||
<glyph glyph-name="ellipsis" unicode="…" horiz-adv-x="1000"
|
||||
d="M500 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5zM834 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5zM166 100q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41
|
||||
q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="perthousand" unicode="‰" horiz-adv-x="1110"
|
||||
d="M198 710q-47 0 -81.5 -33t-34.5 -79q0 -45 34.5 -78t81.5 -33t81.5 33t34.5 78q0 46 -34.5 79t-81.5 33zM557 770l45 -26l-440 -760l-46 25zM521 267q-47 0 -81.5 -33t-34.5 -79q0 -45 34.5 -78t81.5 -33t81.5 33t34.5 78q0 46 -34.5 79t-81.5 33zM198 770
|
||||
q72 0 124 -50.5t52 -121.5t-52.5 -121t-123.5 -50t-123.5 50t-52.5 121t52 121.5t124 50.5zM521 327q72 0 124 -50.5t52 -121.5t-52.5 -121t-123.5 -50t-123.5 50t-52.5 121t52 121.5t124 50.5zM913 327q72 0 124 -50.5t52 -121.5t-52.5 -121t-123.5 -50t-123.5 50
|
||||
t-52.5 121t52 121.5t124 50.5zM913 267q-47 0 -81.5 -33t-34.5 -79q0 -45 34.5 -78t81.5 -33t81.5 33t34.5 78q0 46 -34.5 79t-81.5 33z" />
|
||||
<glyph glyph-name="guilsinglleft" unicode="‹" horiz-adv-x="336"
|
||||
d="M111 320l149 -191l-56 -41l-182 232l182 240l56 -41z" />
|
||||
<glyph glyph-name="guilsinglright" unicode="›" horiz-adv-x="336"
|
||||
d="M76 129l149 191l-149 199l56 41l182 -240l-182 -232z" />
|
||||
<glyph glyph-name="fraction" unicode="⁄" horiz-adv-x="165"
|
||||
d="M277 770l51 -26l-440 -760l-51 28z" />
|
||||
<glyph glyph-name="Euro" unicode="€"
|
||||
d="M532 723v-87q-57 53 -154 53q-83 0 -129.5 -55t-55.5 -147h295l-23 -69h-281q0 -5 -0.5 -19t-0.5 -20q0 -8 0.5 -22.5t0.5 -18.5h253l-23 -69h-221q11 -101 58.5 -153t127.5 -52q95 0 153 53v-89q-51 -43 -165 -43q-227 0 -262 284h-78l23 69h48q-2 20 -2 41
|
||||
q0 7 0.5 20.5t0.5 18.5h-70l23 69h53q17 132 81.5 207t182.5 75q109 0 165 -46z" />
|
||||
<glyph glyph-name="afii61289" unicode="ℓ" horiz-adv-x="509"
|
||||
d="M446 159l39 -36q-68 -134 -196 -134q-86 0 -128.5 56t-45.5 144v14q-10 -8 -30.5 -25t-29.5 -24l-25 48q71 62 84 75v295q0 136 47 198t116 62q64 0 97 -49t33 -127q0 -179 -213 -395v-39q1 -84 32 -125t80 -41q45 0 81 30.5t59 72.5zM194 576v-231q157 180 157 311
|
||||
q0 112 -73 112q-34 0 -59 -46t-25 -146z" />
|
||||
<glyph glyph-name="trademark" unicode="™" horiz-adv-x="940"
|
||||
d="M906 754v-421h-64v357h-2l-144 -357h-39l-140 357h-2v-357h-64v421h105l121 -297l125 297h104zM374 754v-64h-138v-357h-64v357h-138v64h340z" />
|
||||
<glyph glyph-name="Omega" unicode="Ω" horiz-adv-x="745"
|
||||
d="M204 70v3q-61 57 -100.5 144t-39.5 192q0 158 88.5 259t223.5 101q136 0 220 -105t84 -250q0 -109 -41 -198.5t-100 -142.5v-3h155v-70h-252v51q65 46 109 136t44 211q0 74 -23.5 140.5t-75.5 113t-121 46.5q-102 0 -164 -86.5t-62 -216.5q0 -114 44.5 -207.5
|
||||
t107.5 -136.5v-51h-251v70h154z" />
|
||||
<glyph glyph-name="estimated" unicode="℮" horiz-adv-x="948"
|
||||
d="M910 366h-707q-6 0 -6 -5v-214q0 -11 9 -24q113 -116 268 -116q83 0 156 34.5t125 95.5h63q-60 -70 -151 -111t-194 -41q-181 0 -308.5 114.5t-127.5 277.5t127.5 278t308.5 115t309 -115t128 -278v-11zM749 394v215q0 16 -10 26q-114 111 -265 111q-154 0 -266 -115
|
||||
q-11 -11 -11 -27v-210q0 -7 6 -7h542q4 0 4 7z" />
|
||||
<glyph glyph-name="partialdiff" unicode="∂" horiz-adv-x="573"
|
||||
d="M107 725l-28 63q73 60 175 60q111 0 188.5 -105.5t77.5 -304.5q0 -201 -71.5 -325t-202.5 -124q-96 0 -148.5 74t-52.5 176q0 124 65.5 201t157.5 77q62 0 106.5 -32.5t61.5 -66.5h2q1 12 1 46q0 137 -56 225t-138 88q-78 0 -138 -52zM253 60h2q69 0 116 80.5t57 194.5
|
||||
q-13 41 -53 77t-94 36q-63 0 -108 -61.5t-45 -147.5q0 -79 34.5 -129t90.5 -50z" />
|
||||
<glyph glyph-name="Delta" unicode="∆" horiz-adv-x="676"
|
||||
d="M33 0v57l258 720h97l254 -719v-58h-609zM117 69h436l-147 407q-8 26 -34.5 99.5t-33.5 100.5h-4q-5 -22 -29 -90.5t-32 -93.5z" />
|
||||
<glyph glyph-name="product" unicode="∏" horiz-adv-x="731"
|
||||
d="M703 680h-113v-785h-82v785h-286v-785h-82v785h-112v77h675v-77z" />
|
||||
<glyph glyph-name="summation" unicode="∑"
|
||||
d="M555 -105h-531v57l279 373l-267 373v59h502v-72h-387v-4l247 -343l-269 -359v-4h426v-80z" />
|
||||
<glyph glyph-name="minus" unicode="−"
|
||||
d="M33 213v86h512v-86h-512z" />
|
||||
<glyph glyph-name="uni2215" unicode="∕" horiz-adv-x="165"
|
||||
d="M277 770l51 -26l-440 -760l-51 28z" />
|
||||
<glyph glyph-name="uni2219" unicode="∙" horiz-adv-x="289"
|
||||
d="M145 314q24 0 41 -17.5t17 -40.5q0 -24 -17 -41t-41 -17t-41 17t-17 41q0 23 17 40.5t41 17.5z" />
|
||||
<glyph glyph-name="radical" unicode="√" horiz-adv-x="601"
|
||||
d="M601 901l-232 -1062h-73l-166 501l-78 -29l-16 51l146 57l131 -395q2 -11 9 -40t9 -41l2 -1q7 50 14 82l193 877h61z" />
|
||||
<glyph glyph-name="infinity" unicode="∞" horiz-adv-x="821"
|
||||
d="M768 315v-1q0 -75 -48.5 -122.5t-114.5 -47.5q-48 0 -91.5 29.5t-101.5 96.5q-53 -61 -97.5 -93.5t-102.5 -32.5q-65 0 -112 48t-47 118q0 73 47.5 121t119.5 48q54 0 99 -32.5t96 -92.5q3 4 10 11q34 38 54 57t57.5 38t76.5 19q69 0 112 -45.5t43 -118.5zM219 196h2
|
||||
q14 0 27.5 3t27 11.5t23 14.5t24 19.5t20.5 20t21 23t19 20.5q-26 32 -37.5 45t-35.5 35.5t-47 31.5t-50 9q-48 0 -76.5 -35t-28.5 -85q1 -48 32 -80.5t79 -32.5zM607 429h-1q-25 0 -52 -15t-40.5 -27t-41 -42t-29.5 -32q58 -65 92 -91t74 -26q47 0 75.5 35t28.5 79
|
||||
q0 55 -29.5 87t-76.5 32z" />
|
||||
<glyph glyph-name="integral" unicode="∫" horiz-adv-x="381"
|
||||
d="M362 912l-13 -59q-17 11 -38 11q-33 0 -53 -26q-35 -43 -35 -193q0 -84 7 -269t7 -275q0 -151 -45 -219q-34 -57 -107 -57q-41 0 -69 17l14 61q27 -12 47 -12q31 0 49 25q34 46 34 185q0 91 -7 278.5t-7 273.5q0 91 13 144t44 86q39 43 101 43q36 0 58 -14z" />
|
||||
<glyph glyph-name="approxequal" unicode="≈" horiz-adv-x="588"
|
||||
d="M506 465l34 -29q-50 -102 -136 -102q-29 0 -53.5 9.5t-68.5 34.5q-61 36 -97 36q-33 0 -56 -20.5t-47 -58.5l-35 29q24 48 62 75.5t83 27.5q15 0 28.5 -2.5t27.5 -9t21.5 -10t22.5 -12.5t17 -10q3 -2 19.5 -11t21 -11t16.5 -7t21 -6.5t20 -1.5q31 0 53.5 19.5t45.5 59.5z
|
||||
M506 284l34 -30q-50 -101 -136 -101q-29 0 -53.5 9.5t-68.5 34.5q-63 36 -97 36q-33 0 -56 -20.5t-47 -58.5l-35 29q24 47 62 74.5t83 27.5q18 0 37 -5t29 -9.5t29 -15t22 -12.5t14 -8t14.5 -8t12.5 -7t14.5 -6.5t13 -4t15 -3.5t15.5 -1q30 0 52.5 19t45.5 60z" />
|
||||
<glyph glyph-name="notequal" unicode="≠" horiz-adv-x="588"
|
||||
d="M419 541l-47 -103h162v-54h-183l-70 -153h253v-54h-274l-56 -123l-43 19l48 104h-156v54h178l69 153h-247v54h268l55 122z" />
|
||||
<glyph glyph-name="lessequal" unicode="≤" horiz-adv-x="588"
|
||||
d="M531 107l-472 240v57l472 239v-65l-415 -201v-2l415 -203v-65zM535 8h-481v56h481v-56z" />
|
||||
<glyph glyph-name="greaterequal" unicode="≥" horiz-adv-x="588"
|
||||
d="M60 643l472 -240v-56l-471 -240v65l414 202v2l-415 202v65zM534 8h-479v56h479v-56z" />
|
||||
<glyph glyph-name="lozenge" unicode="◊" horiz-adv-x="602"
|
||||
d="M544 378l-211 -426h-68l-208 426l211 427h68zM468 376l-146 298q-13 31 -20 59h-3q-10 -35 -20 -59l-146 -294l147 -300q13 -33 19 -57h4q6 28 18 56z" />
|
||||
<hkern u1="T" u2="š" k="25" />
|
||||
<hkern u1="T" u2="ü" k="50" />
|
||||
<hkern u1="T" u2="ö" k="50" />
|
||||
<hkern u1="T" u2="ò" k="50" />
|
||||
<hkern u1="T" u2="î" k="-3" />
|
||||
<hkern u1="T" u2="í" k="8" />
|
||||
<hkern u1="T" u2="ì" k="-8" />
|
||||
<hkern u1="T" u2="ë" k="50" />
|
||||
<hkern u1="T" u2="ê" k="75" />
|
||||
<hkern u1="T" u2="è" k="75" />
|
||||
<hkern u1="T" u2="å" k="50" />
|
||||
<hkern u1="T" u2="ä" k="25" />
|
||||
<hkern u1="T" u2="ã" k="50" />
|
||||
<hkern u1="T" u2="â" k="50" />
|
||||
<hkern u1="T" u2="à" k="50" />
|
||||
<hkern u1="V" u2="ö" k="40" />
|
||||
<hkern u1="V" u2="ô" k="60" />
|
||||
<hkern u1="V" u2="î" k="-4" />
|
||||
<hkern u1="V" u2="ë" k="40" />
|
||||
<hkern u1="V" u2="ê" k="40" />
|
||||
<hkern u1="V" u2="è" k="40" />
|
||||
<hkern u1="V" u2="å" k="40" />
|
||||
<hkern u1="V" u2="ä" k="40" />
|
||||
<hkern u1="V" u2="ã" k="40" />
|
||||
<hkern u1="V" u2="â" k="40" />
|
||||
<hkern u1="V" u2="à" k="40" />
|
||||
<hkern u1="W" u2="ü" k="30" />
|
||||
<hkern u1="W" u2="ö" k="45" />
|
||||
<hkern u1="W" u2="ê" k="45" />
|
||||
<hkern u1="W" u2="ä" k="45" />
|
||||
<hkern u1="Y" u2="ü" k="45" />
|
||||
<hkern u1="Y" u2="ö" k="75" />
|
||||
<hkern u1="‘" u2="‘" k="111" />
|
||||
<hkern u1="’" u2="’" k="111" />
|
||||
<hkern g1="f,fi,fl"
|
||||
g2="quoteright"
|
||||
k="-20" />
|
||||
<hkern g1="f,fi,fl"
|
||||
g2="f,germandbls,fi,fl"
|
||||
k="-20" />
|
||||
<hkern g1="F"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="60" />
|
||||
<hkern g1="F"
|
||||
g2="comma"
|
||||
k="150" />
|
||||
<hkern g1="F"
|
||||
g2="period"
|
||||
k="150" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="T"
|
||||
k="30" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="V"
|
||||
k="40" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="W"
|
||||
k="30" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="y,yacute,ydieresis"
|
||||
k="20" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="Y,Yacute,Ydieresis"
|
||||
k="40" />
|
||||
<hkern g1="L,Lslash"
|
||||
g2="quoteright"
|
||||
k="80" />
|
||||
<hkern g1="P"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="80" />
|
||||
<hkern g1="P"
|
||||
g2="comma"
|
||||
k="135" />
|
||||
<hkern g1="P"
|
||||
g2="period"
|
||||
k="135" />
|
||||
<hkern g1="r"
|
||||
g2="v"
|
||||
k="-40" />
|
||||
<hkern g1="r"
|
||||
g2="w"
|
||||
k="-40" />
|
||||
<hkern g1="r"
|
||||
g2="y,yacute,ydieresis"
|
||||
k="-40" />
|
||||
<hkern g1="r"
|
||||
g2="f,germandbls,fi,fl"
|
||||
k="-20" />
|
||||
<hkern g1="r"
|
||||
g2="comma"
|
||||
k="100" />
|
||||
<hkern g1="r"
|
||||
g2="period"
|
||||
k="100" />
|
||||
<hkern g1="r"
|
||||
g2="m"
|
||||
k="-8" />
|
||||
<hkern g1="r"
|
||||
g2="n,ntilde"
|
||||
k="-8" />
|
||||
<hkern g1="r"
|
||||
g2="q"
|
||||
k="20" />
|
||||
<hkern g1="r"
|
||||
g2="t"
|
||||
k="-20" />
|
||||
<hkern g1="r"
|
||||
g2="x"
|
||||
k="-40" />
|
||||
<hkern g1="R"
|
||||
g2="T"
|
||||
k="20" />
|
||||
<hkern g1="R"
|
||||
g2="Y,Yacute,Ydieresis"
|
||||
k="20" />
|
||||
<hkern g1="T"
|
||||
g2="w"
|
||||
k="80" />
|
||||
<hkern g1="T"
|
||||
g2="y,yacute,ydieresis"
|
||||
k="80" />
|
||||
<hkern g1="T"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="80" />
|
||||
<hkern g1="T"
|
||||
g2="comma"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="period"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="a,agrave,aacute,acircumflex,atilde,adieresis,aring,ae"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="c,ccedilla"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="e,egrave,eacute,ecircumflex,edieresis"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="i,igrave,iacute,icircumflex,idieresis"
|
||||
k="15" />
|
||||
<hkern g1="T"
|
||||
g2="o,ograve,oacute,ocircumflex,otilde,odieresis,oslash,oe"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="r"
|
||||
k="80" />
|
||||
<hkern g1="T"
|
||||
g2="s,scaron"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="u,ugrave,uacute,ucircumflex,udieresis"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="colon"
|
||||
k="100" />
|
||||
<hkern g1="T"
|
||||
g2="hyphen"
|
||||
k="80" />
|
||||
<hkern g1="T"
|
||||
g2="semicolon"
|
||||
k="100" />
|
||||
<hkern g1="v"
|
||||
g2="comma"
|
||||
k="80" />
|
||||
<hkern g1="v"
|
||||
g2="period"
|
||||
k="80" />
|
||||
<hkern g1="V"
|
||||
g2="y,yacute,ydieresis"
|
||||
k="20" />
|
||||
<hkern g1="V"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="100" />
|
||||
<hkern g1="V"
|
||||
g2="comma"
|
||||
k="120" />
|
||||
<hkern g1="V"
|
||||
g2="period"
|
||||
k="120" />
|
||||
<hkern g1="V"
|
||||
g2="a,agrave,aacute,acircumflex,atilde,adieresis,aring,ae"
|
||||
k="80" />
|
||||
<hkern g1="V"
|
||||
g2="e,egrave,eacute,ecircumflex,edieresis"
|
||||
k="80" />
|
||||
<hkern g1="V"
|
||||
g2="i,igrave,iacute,icircumflex,idieresis"
|
||||
k="20" />
|
||||
<hkern g1="V"
|
||||
g2="o,ograve,oacute,ocircumflex,otilde,odieresis,oslash,oe"
|
||||
k="80" />
|
||||
<hkern g1="V"
|
||||
g2="r"
|
||||
k="40" />
|
||||
<hkern g1="V"
|
||||
g2="u,ugrave,uacute,ucircumflex,udieresis"
|
||||
k="60" />
|
||||
<hkern g1="V"
|
||||
g2="colon"
|
||||
k="80" />
|
||||
<hkern g1="V"
|
||||
g2="hyphen"
|
||||
k="30" />
|
||||
<hkern g1="V"
|
||||
g2="semicolon"
|
||||
k="80" />
|
||||
<hkern g1="w"
|
||||
g2="comma"
|
||||
k="60" />
|
||||
<hkern g1="w"
|
||||
g2="period"
|
||||
k="60" />
|
||||
<hkern g1="W"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="100" />
|
||||
<hkern g1="W"
|
||||
g2="comma"
|
||||
k="80" />
|
||||
<hkern g1="W"
|
||||
g2="period"
|
||||
k="80" />
|
||||
<hkern g1="W"
|
||||
g2="a,agrave,aacute,acircumflex,atilde,adieresis,aring,ae"
|
||||
k="60" />
|
||||
<hkern g1="W"
|
||||
g2="e,egrave,eacute,ecircumflex,edieresis"
|
||||
k="60" />
|
||||
<hkern g1="W"
|
||||
g2="o,ograve,oacute,ocircumflex,otilde,odieresis,oslash,oe"
|
||||
k="60" />
|
||||
<hkern g1="W"
|
||||
g2="r"
|
||||
k="20" />
|
||||
<hkern g1="W"
|
||||
g2="u,ugrave,uacute,ucircumflex,udieresis"
|
||||
k="40" />
|
||||
<hkern g1="W"
|
||||
g2="colon"
|
||||
k="80" />
|
||||
<hkern g1="W"
|
||||
g2="semicolon"
|
||||
k="80" />
|
||||
<hkern g1="y,yacute,ydieresis"
|
||||
g2="comma"
|
||||
k="80" />
|
||||
<hkern g1="y,yacute,ydieresis"
|
||||
g2="period"
|
||||
k="80" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="v"
|
||||
k="40" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="A,Agrave,Aacute,Acircumflex,Atilde,Adieresis,Aring,AE"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="comma"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="period"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="q"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="a,agrave,aacute,acircumflex,atilde,adieresis,aring,ae"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="e,egrave,eacute,ecircumflex,edieresis"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="i,igrave,iacute,icircumflex,idieresis"
|
||||
k="20" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="o,ograve,oacute,ocircumflex,otilde,odieresis,oslash,oe"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="u,ugrave,uacute,ucircumflex,udieresis"
|
||||
k="60" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="colon"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="hyphen"
|
||||
k="60" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="semicolon"
|
||||
k="100" />
|
||||
<hkern g1="Y,Yacute,Ydieresis"
|
||||
g2="p"
|
||||
k="80" />
|
||||
<hkern g1="quoteright"
|
||||
g2="t"
|
||||
k="20" />
|
||||
<hkern g1="quoteright"
|
||||
g2="s,scaron"
|
||||
k="100" />
|
||||
</font>
|
||||
</defs></svg>
|
After Width: | Height: | Size: 68 KiB |
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.ttf
Normal file
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.ttf
Normal file
Binary file not shown.
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.woff
Normal file
BIN
resources/[system]/scoreboard/html/res/futurastd-medium.woff
Normal file
Binary file not shown.
48
resources/[system]/scoreboard/html/reset.css
Normal file
48
resources/[system]/scoreboard/html/reset.css
Normal file
@ -0,0 +1,48 @@
|
||||
/* http://meyerweb.com/eric/tools/css/reset/
|
||||
v2.0 | 20110126
|
||||
License: none (public domain)
|
||||
*/
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
body {
|
||||
line-height: 1;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
14
resources/[system]/scoreboard/html/scoreboard.html
Normal file
14
resources/[system]/scoreboard/html/scoreboard.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="nui://game/ui/jquery.js" type="text/javascript"></script>
|
||||
<script src="listener.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="nui://scoreboard/html/reset.css">
|
||||
<link rel="stylesheet" href="nui://scoreboard/html/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: none;" id="wrap">
|
||||
<table id="ptbl" width="100%">
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
40
resources/[system]/scoreboard/html/style.css
Normal file
40
resources/[system]/scoreboard/html/style.css
Normal file
@ -0,0 +1,40 @@
|
||||
@import url('res/futurastd-medium.css');
|
||||
|
||||
html {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
width: 500px;
|
||||
min-height: 185px;
|
||||
margin-top: 10%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.16), 0px 2px 10px 0px rgba(0, 0, 0, 0.12);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
table {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
th {
|
||||
padding-top: 10px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
tr {
|
||||
font-size: 120%;
|
||||
font-family: 'Segoe UI';
|
||||
/*text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.9);*/
|
||||
}
|
||||
|
||||
tr.heading {
|
||||
background-color: #43A047;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
48
resources/[system]/scoreboard/scoreboard.lua
Normal file
48
resources/[system]/scoreboard/scoreboard.lua
Normal file
@ -0,0 +1,48 @@
|
||||
local listOn = false
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
listOn = false
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
if IsControlPressed(0, 27)--[[ INPUT_PHONE ]] then
|
||||
if not listOn then
|
||||
local players = {}
|
||||
ptable = GetPlayers()
|
||||
for _, i in ipairs(ptable) do
|
||||
local wantedLevel = GetPlayerWantedLevel(i)
|
||||
r, g, b = GetPlayerRgbColour(i)
|
||||
table.insert(players,
|
||||
'<tr style=\"color: rgb(' .. r .. ', ' .. g .. ', ' .. b .. ')\"><td>' .. GetPlayerServerId(i) .. '</td><td>' .. GetPlayerName(i) .. '</td><td>' .. (wantedLevel and wantedLevel or tostring(0)) .. '</td></tr>'
|
||||
)
|
||||
end
|
||||
|
||||
SendNUIMessage({ text = table.concat(players) })
|
||||
|
||||
listOn = true
|
||||
while listOn do
|
||||
Wait(0)
|
||||
if(IsControlPressed(0, 27) == false) then
|
||||
listOn = false
|
||||
SendNUIMessage({
|
||||
meta = 'close'
|
||||
})
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function GetPlayers()
|
||||
local players = {}
|
||||
|
||||
for i = 0, 31 do
|
||||
if NetworkIsPlayerActive(i) then
|
||||
table.insert(players, i)
|
||||
end
|
||||
end
|
||||
|
||||
return players
|
||||
end
|
11
resources/[system]/sessionmanager/__resource.lua
Normal file
11
resources/[system]/sessionmanager/__resource.lua
Normal file
@ -0,0 +1,11 @@
|
||||
client_scripts {
|
||||
'client/initial.lua',
|
||||
'client/leavehandler.lua',
|
||||
'client/activationhandler.lua',
|
||||
'client/hostservice.lua',
|
||||
'client/sessionstarter.lua'
|
||||
}
|
||||
|
||||
server_script 'server/host_lock.lua'
|
||||
|
||||
export 'serviceHostStuff'
|
@ -0,0 +1,27 @@
|
||||
-- triggers an event when the local network player becomes active
|
||||
AddEventHandler('sessionInitialized', function()
|
||||
local playerId = GetPlayerId()
|
||||
|
||||
-- create a looping thread
|
||||
CreateThread(function()
|
||||
-- wait until the player becomes active
|
||||
while not IsNetworkPlayerActive(playerId) do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- set some defaults
|
||||
AllowGameToPauseForStreaming(true)
|
||||
|
||||
SetMaxWantedLevel(6)
|
||||
SetWantedMultiplier(0.9999999)
|
||||
SetCreateRandomCops(true)
|
||||
SetDitchPoliceModels(false)
|
||||
|
||||
DisplayPlayerNames(true)
|
||||
NetworkSetHealthReticuleOption(true)
|
||||
|
||||
-- trigger an event on both the local client and the server
|
||||
TriggerEvent('playerActivated')
|
||||
TriggerServerEvent('playerActivated')
|
||||
end)
|
||||
end)
|
55
resources/[system]/sessionmanager/client/hostservice.lua
Normal file
55
resources/[system]/sessionmanager/client/hostservice.lua
Normal file
@ -0,0 +1,55 @@
|
||||
-- serving the duties of the office of the host
|
||||
|
||||
-- two functions from GTA script; they do 'something lock-ish'
|
||||
local function acquireHostLock()
|
||||
if IsThisMachineTheServer() then
|
||||
SetThisMachineRunningServerScript(true)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function releaseHostLock()
|
||||
SetThisMachineRunningServerScript(false)
|
||||
end
|
||||
|
||||
-- handle msgGetReadyToStartPlaying sending
|
||||
function serviceHostStuff()
|
||||
-- acquire the host lock
|
||||
if acquireHostLock() then
|
||||
-- check if players want to join
|
||||
for i = 0, 31 do
|
||||
-- does this index?
|
||||
if PlayerWantsToJoinNetworkGame(i) then
|
||||
-- well, get ready to start playing!
|
||||
TellNetPlayerToStartPlaying(i, 0)
|
||||
|
||||
TriggerServerEvent('playerJoining', i)
|
||||
end
|
||||
end
|
||||
|
||||
-- release the host lock
|
||||
releaseHostLock()
|
||||
end
|
||||
end
|
||||
|
||||
-- host service loop
|
||||
CreateThread(function()
|
||||
NetworkSetScriptLobbyState(false)
|
||||
SwitchArrowAboveBlippedPickups(true)
|
||||
UsePlayerColourInsteadOfTeamColour(true)
|
||||
LoadAllPathNodes(true)
|
||||
SetSyncWeatherAndGameTime(true)
|
||||
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
serviceHostStuff()
|
||||
|
||||
-- launch the local player, for the initial host scenario
|
||||
if LocalPlayerIsReadyToStartPlaying() then
|
||||
LaunchLocalPlayerInNetworkGame()
|
||||
end
|
||||
end
|
||||
end)
|
124
resources/[system]/sessionmanager/client/initial.lua
Normal file
124
resources/[system]/sessionmanager/client/initial.lua
Normal file
@ -0,0 +1,124 @@
|
||||
-- state variable for session host lock
|
||||
local sessionHostPending = false
|
||||
local sessionHostResult
|
||||
|
||||
AddEventHandler('sessionHostResult', function(result)
|
||||
if not sessionHostPending then
|
||||
return
|
||||
end
|
||||
|
||||
sessionHostResult = result
|
||||
sessionHostPending = false
|
||||
end)
|
||||
|
||||
local attempts = 0
|
||||
|
||||
-- allow early script to create the player
|
||||
AddEventHandler('playerInfoCreated', function()
|
||||
CreateThread(function()
|
||||
-- so that the game won't trigger the citizen disconnect handler
|
||||
SafeguardDisconnect(true)
|
||||
|
||||
-- loop for 3 times
|
||||
while attempts < 3 do
|
||||
-- 'find' games (this will store the host session in memory, or if no host exists, tell us later)
|
||||
NetworkFindGame(16, false, 0, 0)
|
||||
|
||||
-- we don't have to wait for the finding to complete; TestSessionFind.cpp in hooks_ny will instantly return
|
||||
local gamesFound = NetworkGetNumberOfGames(_r)
|
||||
|
||||
-- if we found at least one game (if the game isn't hooked, this can be any amount; but
|
||||
-- we can't trust the implementation in that case anyway)
|
||||
local needsToHost = true -- whether we need to host after completing a possible join
|
||||
|
||||
if gamesFound > 0 then
|
||||
-- join the game
|
||||
NetworkJoinGame(0)
|
||||
|
||||
SetLoadingText('Entering session') -- status text
|
||||
|
||||
-- wait for the join to complete
|
||||
while NetworkJoinGamePending() do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- if we succeeded, we're now a session member, and will not need to host
|
||||
if NetworkJoinGameSucceeded() then
|
||||
needsToHost = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- if we didn't find any games, or a join timed out, we'll *consider* hosting
|
||||
if needsToHost then
|
||||
-- make sure we don't have an actual other host waiting for us
|
||||
sessionHostPending = true -- to trigger a wait loop below
|
||||
|
||||
TriggerServerEvent('hostingSession')
|
||||
|
||||
SetLoadingText('Initializing session') -- some vague status text
|
||||
|
||||
-- wait for the server to respond to our request
|
||||
while sessionHostPending do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if sessionHostResult == 'wait' then
|
||||
-- TODO: not implemented yet: wait for a message from the server, then attempt finding a game/joining a game again
|
||||
sessionHostPending = true
|
||||
|
||||
while sessionHostPending do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if sessionHostResult == 'free' then
|
||||
goto endLoop
|
||||
end
|
||||
end
|
||||
|
||||
if sessionHostResult == 'conflict' and gamesFound > 0 then
|
||||
-- there's already a host which is working perfectly fine; show a message to the player
|
||||
--error('session creation conflict: could not connect to original host')
|
||||
echo("session creation conflict\n")
|
||||
goto endLoop
|
||||
end
|
||||
|
||||
-- we got a green light to host; start hosting
|
||||
if not NetworkHostGameE1(16, false, 32, false, 0, 0) then
|
||||
echo("session creation failure from NetworkHostGameE1\n")
|
||||
error('failed to initialize session')
|
||||
end
|
||||
|
||||
-- wait for internal processing to complete
|
||||
while NetworkHostGamePending() do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- another failure check
|
||||
if not NetworkHostGameSucceeded() then
|
||||
echo("session creation failure from NetworkHostGameSucceeded\n")
|
||||
error('failed to initialize session')
|
||||
end
|
||||
|
||||
TriggerServerEvent('hostedSession')
|
||||
|
||||
break
|
||||
end
|
||||
|
||||
::endLoop::
|
||||
attempts = attempts + 1
|
||||
end
|
||||
|
||||
SafeguardDisconnect(false)
|
||||
|
||||
if attempts >= 3 then
|
||||
error("Could not connect to session provider.")
|
||||
end
|
||||
|
||||
SetLoadingText('Look at that!')
|
||||
|
||||
-- signal local game-specific resources to start
|
||||
TriggerEvent('sessionInitialized')
|
||||
TriggerServerEvent('sessionInitialized')
|
||||
end)
|
||||
end)
|
31
resources/[system]/sessionmanager/client/leavehandler.lua
Normal file
31
resources/[system]/sessionmanager/client/leavehandler.lua
Normal file
@ -0,0 +1,31 @@
|
||||
-- handles the script end of the flag the 'leave game' option in the pause menu sets
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(0)
|
||||
|
||||
-- if the flag is set
|
||||
if DoesGameCodeWantToLeaveNetworkSession() then
|
||||
-- if we're part of a started session; end it first (FIXME: will this break others when we're host?)
|
||||
if NetworkIsSessionStarted() then
|
||||
NetworkEndSession()
|
||||
|
||||
-- wait for the session to be ended
|
||||
while NetworkEndSessionPending() do
|
||||
Wait(0)
|
||||
end
|
||||
end
|
||||
|
||||
-- attempt to leave the game
|
||||
NetworkLeaveGame()
|
||||
|
||||
-- while we're waiting to leave...
|
||||
while NetworkLeaveGamePending() do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- reinitialize the game as a network game (TODO: call into citigame for UI/NetLibrary leaving)
|
||||
--ShutdownAndLaunchNetworkGame(0) -- episode id is arg
|
||||
ShutdownNetworkCit('Left');
|
||||
end
|
||||
end
|
||||
end)
|
26
resources/[system]/sessionmanager/client/sessionstarter.lua
Normal file
26
resources/[system]/sessionmanager/client/sessionstarter.lua
Normal file
@ -0,0 +1,26 @@
|
||||
-- more rline stuff, this does some late-term session management (which I think has some race condition with launching the network player?)
|
||||
AddEventHandler('sessionInitialized', function()
|
||||
if IsThisMachineTheServer() then
|
||||
-- unknown stuff, seems needed though
|
||||
NetworkChangeExtendedGameConfigCit()
|
||||
|
||||
CreateThread(function()
|
||||
Wait(1500)
|
||||
|
||||
if not NetworkIsSessionStarted() then
|
||||
NetworkStartSession()
|
||||
|
||||
while NetworkStartSessionPending() do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
if not NetworkStartSessionSucceeded() then
|
||||
ForceLoadingScreen(0)
|
||||
SetMsgForLoadingScreen("MO_SNI")
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
67
resources/[system]/sessionmanager/server/host_lock.lua
Normal file
67
resources/[system]/sessionmanager/server/host_lock.lua
Normal file
@ -0,0 +1,67 @@
|
||||
-- whitelist c2s events
|
||||
RegisterServerEvent('hostingSession')
|
||||
RegisterServerEvent('hostedSession')
|
||||
|
||||
-- event handler for pre-session 'acquire'
|
||||
local currentHosting
|
||||
local hostReleaseCallbacks = {}
|
||||
|
||||
-- TODO: add a timeout for the hosting lock to be held
|
||||
-- TODO: add checks for 'fraudulent' conflict cases of hosting attempts (typically whenever the host can not be reached)
|
||||
AddEventHandler('hostingSession', function()
|
||||
-- if the lock is currently held, tell the client to await further instruction
|
||||
if currentHosting then
|
||||
TriggerClientEvent('sessionHostResult', source, 'wait')
|
||||
|
||||
-- register a callback for when the lock is freed
|
||||
table.insert(hostReleaseCallbacks, function()
|
||||
TriggerClientEvent('sessionHostResult', source, 'free')
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- if the current host was last contacted less than a second ago
|
||||
if GetHostId() >= 1 then
|
||||
if GetPlayerLastMsg(GetHostId()) < 1000 then
|
||||
TriggerClientEvent('sessionHostResult', source, 'conflict')
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
hostReleaseCallbacks = {}
|
||||
|
||||
currentHosting = source
|
||||
|
||||
TriggerClientEvent('sessionHostResult', source, 'go')
|
||||
|
||||
-- set a timeout of 5 seconds
|
||||
SetTimeout(5000, function()
|
||||
if not currentHosting then
|
||||
return
|
||||
end
|
||||
|
||||
currentHosting = nil
|
||||
|
||||
for _, cb in ipairs(hostReleaseCallbacks) do
|
||||
cb()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
AddEventHandler('hostedSession', function()
|
||||
-- check if the client is the original locker
|
||||
if currentHosting ~= source then
|
||||
-- TODO: drop client as they're clearly lying
|
||||
print(currentHosting, '~=', source)
|
||||
return
|
||||
end
|
||||
|
||||
-- free the host lock (call callbacks and remove the lock value)
|
||||
for _, cb in ipairs(hostReleaseCallbacks) do
|
||||
cb()
|
||||
end
|
||||
|
||||
currentHosting = nil
|
||||
end)
|
9
resources/[system]/spawnmanager/__resource.lua
Normal file
9
resources/[system]/spawnmanager/__resource.lua
Normal file
@ -0,0 +1,9 @@
|
||||
client_script 'spawnmanager.lua'
|
||||
|
||||
export 'getRandomSpawnPoint'
|
||||
export 'spawnPlayer'
|
||||
export 'addSpawnPoint'
|
||||
export 'loadSpawns'
|
||||
export 'setAutoSpawn'
|
||||
export 'setAutoSpawnCallback'
|
||||
export 'forceRespawn'
|
350
resources/[system]/spawnmanager/spawnmanager.lua
Normal file
350
resources/[system]/spawnmanager/spawnmanager.lua
Normal file
@ -0,0 +1,350 @@
|
||||
-- in-memory spawnpoint array for this script execution instance
|
||||
local spawnPoints = {}
|
||||
|
||||
-- auto-spawn enabled flag
|
||||
local autoSpawnEnabled = false
|
||||
local autoSpawnCallback
|
||||
|
||||
-- support for mapmanager maps
|
||||
AddEventHandler('getMapDirectives', function(add)
|
||||
-- call the remote callback
|
||||
add('spawnpoint', function(state, model)
|
||||
-- return another callback to pass coordinates and so on (as such syntax would be [spawnpoint 'model' { options/coords }])
|
||||
return function(opts)
|
||||
local x, y, z, heading
|
||||
|
||||
local s, e = pcall(function()
|
||||
-- is this a map or an array?
|
||||
if opts.x then
|
||||
x = opts.x
|
||||
y = opts.y
|
||||
z = opts.z
|
||||
else
|
||||
x = opts[1]
|
||||
y = opts[2]
|
||||
z = opts[3]
|
||||
end
|
||||
|
||||
x = x + 0.0001
|
||||
y = y + 0.0001
|
||||
z = z + 0.0001
|
||||
|
||||
-- get a heading and force it to a float, or just default to null
|
||||
heading = opts.heading and (opts.heading + 0.01) or 0
|
||||
|
||||
-- add the spawnpoint
|
||||
addSpawnPoint({
|
||||
x = x, y = y, z = z,
|
||||
heading = heading,
|
||||
model = model
|
||||
})
|
||||
|
||||
-- recalculate the model for storage
|
||||
if not tonumber(model) then
|
||||
model = GetHashKey(model, _r)
|
||||
end
|
||||
|
||||
-- store the spawn data in the state so we can erase it later on
|
||||
state.add('xyz', { x, y, z })
|
||||
state.add('model', model)
|
||||
end)
|
||||
|
||||
if not s then
|
||||
Citizen.Trace(e .. "\n")
|
||||
end
|
||||
end
|
||||
-- delete callback follows on the next line
|
||||
end, function(state, arg)
|
||||
-- loop through all spawn points to find one with our state
|
||||
for i, sp in ipairs(spawnPoints) do
|
||||
-- if it matches...
|
||||
if sp.x == state.xyz[1] and sp.y == state.xyz[2] and sp.z == state.xyz[3] and sp.model == state.model then
|
||||
-- remove it.
|
||||
table.remove(spawnPoints, i)
|
||||
return
|
||||
end
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
-- loads a set of spawn points from a JSON string
|
||||
function loadSpawns(spawnString)
|
||||
-- decode the JSON string
|
||||
local data = json.decode(spawnString)
|
||||
|
||||
-- do we have a 'spawns' field?
|
||||
if not data.spawns then
|
||||
error("no 'spawns' in JSON data")
|
||||
end
|
||||
|
||||
-- loop through the spawns
|
||||
for i, spawn in ipairs(data.spawns) do
|
||||
-- and add it to the list (validating as we go)
|
||||
addSpawnPoint(spawn)
|
||||
end
|
||||
end
|
||||
|
||||
function addSpawnPoint(spawn)
|
||||
-- validate the spawn (position)
|
||||
if not tonumber(spawn.x) or not tonumber(spawn.y) or not tonumber(spawn.z) then
|
||||
error("invalid spawn position")
|
||||
end
|
||||
|
||||
-- heading
|
||||
if not tonumber(spawn.heading) then
|
||||
error("invalid spawn heading")
|
||||
end
|
||||
|
||||
-- model (try integer first, if not, hash it)
|
||||
local model = spawn.model
|
||||
|
||||
if not tonumber(spawn.model) then
|
||||
model = GetHashKey(spawn.model)
|
||||
end
|
||||
|
||||
-- is the model actually a model?
|
||||
if not IsModelInCdimage(model) then
|
||||
error("invalid spawn model")
|
||||
end
|
||||
|
||||
-- is is even a ped?
|
||||
-- not in V?
|
||||
--[[if not IsThisModelAPed(model) then
|
||||
error("this model ain't a ped!")
|
||||
end]]
|
||||
|
||||
-- overwrite the model in case we hashed it
|
||||
spawn.model = model
|
||||
|
||||
-- all OK, add the spawn entry to the list
|
||||
table.insert(spawnPoints, spawn)
|
||||
end
|
||||
|
||||
-- changes the auto-spawn flag
|
||||
function setAutoSpawn(enabled)
|
||||
autoSpawnEnabled = enabled
|
||||
end
|
||||
|
||||
-- sets a callback to execute instead of 'native' spawning when trying to auto-spawn
|
||||
function setAutoSpawnCallback(cb)
|
||||
autoSpawnCallback = cb
|
||||
autoSpawnEnabled = true
|
||||
end
|
||||
|
||||
-- function as existing in original R* scripts
|
||||
local function freezePlayer(id, freeze)
|
||||
local player = id
|
||||
SetPlayerControl(player, not freeze, false)
|
||||
|
||||
local ped = GetPlayerPed(player)
|
||||
|
||||
if not freeze then
|
||||
if not IsEntityVisible(ped) then
|
||||
SetEntityVisible(ped, true)
|
||||
end
|
||||
|
||||
if not IsPedInAnyVehicle(ped) then
|
||||
SetEntityCollision(ped, true)
|
||||
end
|
||||
|
||||
FreezeEntityPosition(ped, false)
|
||||
--SetCharNeverTargetted(ped, false)
|
||||
SetPlayerInvincible(player, false)
|
||||
else
|
||||
if IsEntityVisible(ped) then
|
||||
SetEntityVisible(ped, false)
|
||||
end
|
||||
|
||||
SetEntityCollision(ped, false)
|
||||
FreezeEntityPosition(ped, true)
|
||||
--SetCharNeverTargetted(ped, true)
|
||||
SetPlayerInvincible(player, true)
|
||||
--RemovePtfxFromPed(ped)
|
||||
|
||||
if not IsPedFatallyInjured(ped) then
|
||||
ClearPedTasksImmediately(ped)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function loadScene(x, y, z)
|
||||
NewLoadSceneStart(x, y, z, 0.0, 0.0, 0.0, 20.0, 0)
|
||||
|
||||
while IsNewLoadSceneActive() do
|
||||
networkTimer = GetNetworkTimer()
|
||||
|
||||
NetworkUpdateLoadScene()
|
||||
end
|
||||
end
|
||||
|
||||
-- to prevent trying to spawn multiple times
|
||||
local spawnLock = false
|
||||
|
||||
-- spawns the current player at a certain spawn point index (or a random one, for that matter)
|
||||
function spawnPlayer(spawnIdx, cb)
|
||||
if spawnLock then
|
||||
return
|
||||
end
|
||||
|
||||
spawnLock = true
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
DoScreenFadeOut(500)
|
||||
|
||||
while IsScreenFadingOut() do
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
|
||||
-- if the spawn isn't set, select a random one
|
||||
if not spawnIdx then
|
||||
spawnIdx = GetRandomIntInRange(1, #spawnPoints + 1)
|
||||
end
|
||||
|
||||
-- get the spawn from the array
|
||||
local spawn
|
||||
|
||||
if type(spawnIdx) == 'table' then
|
||||
spawn = spawnIdx
|
||||
else
|
||||
spawn = spawnPoints[spawnIdx]
|
||||
end
|
||||
|
||||
-- validate the index
|
||||
if not spawn then
|
||||
Citizen.Trace("tried to spawn at an invalid spawn index\n")
|
||||
|
||||
spawnLock = false
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- freeze the local player
|
||||
freezePlayer(PlayerId(), true)
|
||||
|
||||
-- if the spawn has a model set
|
||||
if spawn.model then
|
||||
RequestModel(spawn.model)
|
||||
|
||||
-- load the model for this spawn
|
||||
while not HasModelLoaded(spawn.model) do
|
||||
RequestModel(spawn.model)
|
||||
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
-- change the player model
|
||||
SetPlayerModel(PlayerId(), spawn.model)
|
||||
|
||||
-- release the player model
|
||||
SetModelAsNoLongerNeeded(spawn.model)
|
||||
end
|
||||
|
||||
-- preload collisions for the spawnpoint
|
||||
RequestCollisionAtCoord(spawn.x, spawn.y, spawn.z)
|
||||
|
||||
-- spawn the player
|
||||
--ResurrectNetworkPlayer(GetPlayerId(), spawn.x, spawn.y, spawn.z, spawn.heading)
|
||||
local ped = GetPlayerPed(-1)
|
||||
|
||||
-- V requires setting coords as well
|
||||
SetEntityCoordsNoOffset(ped, spawn.x, spawn.y, spawn.z, false, false, false, true)
|
||||
|
||||
NetworkResurrectLocalPlayer(spawn.x, spawn.y, spawn.z, spawn.heading, true, true, false)
|
||||
|
||||
-- gamelogic-style cleanup stuff
|
||||
ClearPedTasksImmediately(ped)
|
||||
--SetEntityHealth(ped, 300) -- TODO: allow configuration of this?
|
||||
RemoveAllPedWeapons(ped) -- TODO: make configurable (V behavior?)
|
||||
ClearPlayerWantedLevel(PlayerId())
|
||||
|
||||
-- why is this even a flag?
|
||||
--SetCharWillFlyThroughWindscreen(ped, false)
|
||||
|
||||
-- set primary camera heading
|
||||
--SetGameCamHeading(spawn.heading)
|
||||
--CamRestoreJumpcut(GetGameCam())
|
||||
|
||||
-- load the scene; streaming expects us to do it
|
||||
--ForceLoadingScreen(true)
|
||||
--loadScene(spawn.x, spawn.y, spawn.z)
|
||||
--ForceLoadingScreen(false)
|
||||
|
||||
ShutdownLoadingScreen()
|
||||
|
||||
DoScreenFadeIn(500)
|
||||
|
||||
while IsScreenFadingIn() do
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
|
||||
-- and unfreeze the player
|
||||
freezePlayer(PlayerId(), false)
|
||||
|
||||
TriggerEvent('playerSpawned', spawn)
|
||||
|
||||
if cb then
|
||||
cb(spawn)
|
||||
end
|
||||
|
||||
spawnLock = false
|
||||
end)
|
||||
end
|
||||
|
||||
-- automatic spawning monitor thread, too
|
||||
local respawnForced
|
||||
local diedAt
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
-- main loop thing
|
||||
while true do
|
||||
Citizen.Wait(50)
|
||||
|
||||
local playerPed = GetPlayerPed(-1)
|
||||
|
||||
if playerPed and playerPed ~= -1 then
|
||||
-- check if we want to autospawn
|
||||
if autoSpawnEnabled then
|
||||
if NetworkIsPlayerActive(PlayerId()) then
|
||||
if (diedAt and (GetTimeDifference(GetGameTimer(), diedAt) > 2000)) or respawnForced then
|
||||
Citizen.Trace("forcin' respawn\n")
|
||||
|
||||
if autoSpawnCallback then
|
||||
autoSpawnCallback()
|
||||
else
|
||||
spawnPlayer()
|
||||
end
|
||||
|
||||
respawnForced = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if IsEntityDead(playerPed) then
|
||||
if not diedAt then
|
||||
diedAt = GetGameTimer()
|
||||
end
|
||||
else
|
||||
diedAt = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function forceRespawn()
|
||||
spawnLock = false
|
||||
respawnForced = true
|
||||
end
|
||||
|
||||
--[[AddEventHandler('playerInfoCreated', function()
|
||||
loadSpawns(json.encode({
|
||||
spawns = {
|
||||
{ x = -238.511, y = 954.025, z = 11.0803, heading = 90.0, model = 'ig_brucie' },
|
||||
{ x = -310.001, y = 945.603, z = 14.3728, heading = 90.0, model = 'ig_bulgarin' },
|
||||
}
|
||||
}))
|
||||
end)
|
||||
|
||||
AddEventHandler('playerActivated', function()
|
||||
respawnForced = true
|
||||
end)]]
|
2
resources/[test]/betaguns/__resource.lua
Normal file
2
resources/[test]/betaguns/__resource.lua
Normal file
@ -0,0 +1,2 @@
|
||||
client_script 'client.lua'
|
||||
server_script 'server.lua'
|
208
resources/[test]/betaguns/client.lua
Normal file
208
resources/[test]/betaguns/client.lua
Normal file
@ -0,0 +1,208 @@
|
||||
local function getPickupType(i)
|
||||
if i == 2 then
|
||||
return 30
|
||||
elseif i == 1 then
|
||||
return 31
|
||||
end
|
||||
|
||||
local w = GenerateRandomIntInRange(5, 17, _i)
|
||||
|
||||
if w == 8 or w == 6 then
|
||||
w = 4
|
||||
end
|
||||
|
||||
return w
|
||||
end
|
||||
|
||||
local function createPickup(ptype, etype, unk, x, y, z)
|
||||
if ptype == 30 then
|
||||
CreatePickupWithAmmo(0x972daa10, etype, 0, x, y, z, _i)
|
||||
elseif ptype == 31 then
|
||||
CreatePickupWithAmmo(0x3fc62578, etype, 0, x, y, z, _i)
|
||||
else
|
||||
CreatePickupWithAmmo(GetWeapontypeModel(ptype, _i), etype, 60, x, y, z, _i)
|
||||
end
|
||||
end
|
||||
|
||||
local pickupSeed
|
||||
|
||||
local function createPickups()
|
||||
echo("creating algo pickups\n")
|
||||
|
||||
SetRandomSeed(pickupSeed)
|
||||
|
||||
createPickup( getPickupType( 2 ), 23, 200, -563.10640000, 293.52680000, 5.65930000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 79.41570000, -839.53680000, 3.99560000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -277.35550000, -533.76340000, 3.92420000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -491.51540000, -173.97790000, 6.90340000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -235.68930000, 739.30850000, 6.12510000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -539.49120000, 1362.38800000, 16.47050000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -180.02360000, -823.41240000, 4.11750000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 173.60920000, 236.49170000, 13.76010000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 89.24590000, 1152.34900000, 13.57080000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 63.60470000, -439.60590000, 13.75830000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -226.95040000, 1714.70300000, 14.75500000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 130.44570000, 467.39240000, 13.91780000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -529.52310000, -339.29980000, 5.04460000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -477.98870000, 1707.35300000, 7.46380000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -636.54130000, -45.71210000, 3.81230000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 140.68720000, -857.79680000, 3.77320000 )
|
||||
--createPickup( getPickupType( 2 ), 23, 200, -108.89000000, 64499, 4.11910000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 348.54010000, -431.52940000, 3.54320000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 166.63900000, 1080.60900000, 13.62470000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -145.57280000, 1694.71300000, 15.72350000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 64.54370000, 261.20720000, 14.53200000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -507.19360000, 533.97330000, 5.67160000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -410.23560000, -141.84080000, 11.61790000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, -248.26890000, -589.95000000, 3.78540000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 115.38710000, 741.87240000, 13.56160000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 49.21290000, 1350.85200000, 15.25260000 )
|
||||
createPickup( getPickupType( 2 ), 23, 200, 332.02520000, -158.35070000, 8.06910000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -462.60650000, 775.56370000, 8.98430000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -66.39730000, 1550.17700000, 17.64730000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -47.94850000, 35.91300000, 13.84780000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -210.80500000, 1410.40400000, 19.35510000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 136.81580000, 387.45690000, 14.02680000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -604.36200000, 339.06450000, 3.67190000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -135.90700000, 819.94900000, 17.62560000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -437.64390000, 430.90700000, 8.93740000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -522.79810000, 1018.30500000, 8.79210000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -593.54960000, 1165.60900000, 8.94090000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 89.78390000, 1251.53900000, 14.86610000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -108.15450000, 1271.20900000, 19.43000000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -5.26000000, -447.87000000, 13.75820000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 171.83730000, -807.45750000, 3.97040000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 0.32430000, -761.24270000, 4.08570000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -526.37620000, 593.51290000, 12.12300000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -554.97370000, 806.93090000, 8.05520000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 13.89740000, 1147.71300000, 13.24760000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 179.53490000, 691.26530000, 7.18630000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -463.63800000, 899.77910000, 8.96270000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -467.32180000, 1556.19000000, 17.47570000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -284.66330000, 1600.64600000, 19.41570000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -311.56230000, 1733.49700000, 12.12580000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -99.43640000, 1350.29900000, 19.41500000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -534.05160000, 1610.99600000, 8.39809000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 91.99830000, -318.91000000, 13.61250000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -619.61000000, -115.38000000, 5.59590000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, 361.06920000, -477.77790000, 4.81800000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -404.86420000, 1487.26800000, 17.86060000 )
|
||||
createPickup( getPickupType( 1 ), 23, 200, -572.86970000, 227.56950000, 3.66220000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 150.65500000, 913.75690000, 7.35240000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -151.58120000, 1004.30900000, 5.22660000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -126.16370000, 554.53360000, 13.76430000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -389.27630000, 1763.59200000, 8.23320000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -414.94510000, 376.06220000, 11.07520000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -348.11940000, 631.42010000, 13.58580000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -561.26700000, 1457.39500000, 16.53680000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -656.75510000, 1140.68700000, 8.81430000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 286.89990000, -392.37890000, 3.97690000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 267.28000000, -686.88580000, 3.87500000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 185.85650000, 801.42330000, 7.45320000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -33.85220000, 772.73390000, 13.64890000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -658.17000000, 809.31000000, 3.10420000 )
|
||||
--createPickup( getPickupType( 0 ), 23, 200, 65123, 1658.10000000, 20.08190000 )
|
||||
--createPickup( getPickupType( 0 ), 23, 200, 65307, 1445.20000000, 19.45000000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -579.01340000, 1414.69400000, 14.47110000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -570.93210000, 158.32300000, 3.66220000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -641.65510000, -195.11170000, 3.94450000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -373.43770000, 1563.55700000, 19.15690000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -242.26720000, -515.22510000, 3.93780000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 83.27290000, 128.63830000, 13.74580000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 100.85700000, -751.07600000, 3.95820000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 148.27850000, -520.31800000, 13.76100000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -145.85800000, -436.54300000, 13.71600000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 30.52840000, -319.98200000, 13.72060000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -121.35400000, -765.42500000, 4.20210000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -301.78400000, -408.61900000, 3.82400000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -221.12500000, -244.63100000, 13.55080000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 345.52040000, -409.60800000, 3.69260000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -187.78400000, -104.23300000, 13.59230000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 23.03970000, -41.08220000, 13.81190000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -105.90000000, 129.42250000, 13.72260000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -470.49600000, 190.20460000, 8.85820000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -108.92700000, 371.07960000, 13.80730000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -308.23960000, 455.43910000, 13.69960000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 113.34910000, 650.53870000, 13.71280000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -69.89160000, 1147.73100000, 13.76710000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 29.31370000, 761.22520000, 13.50620000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 52.12710000, 889.81030000, 13.65160000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -616.57000000, 1001.96400000, 8.91920000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -491.81600000, 949.22980000, 8.96670000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 5.79550000, 1028.96500000, 13.72000000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -542.94400000, 1303.59300000, 16.25890000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -273.10860000, 1211.38200000, 17.78520000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -292.14300000, 1331.30300000, 23.60140000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -364.25800000, 1371.32500000, 14.19140000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -34.57900000, 1410.33300000, 19.42230000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -161.42200000, 1555.53300000, 17.37360000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 210.82320000, -105.36900000, 13.76120000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -124.28630000, -530.18220000, 13.76020000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -220.20000000, -883.72000000, 3.67810000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -107.78000000, -821.86000000, 4.12670000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 78.03000000, -670.74000000, 13.76770000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 151.18900000, -613.04700000, 9.63030000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -27.54000000, -823.69000000, 4.45430000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 200.28920000, -698.77010000, 3.95350000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -195.15000000, -711.21000000, 3.96790000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 100.96000000, -512.62000000, 15.08830000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 306.47000000, -623.30000000, 4.19430000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -79.41310000, 614.20590000, 13.76610000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -385.48000000, 738.49000000, 13.76610000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -434.99950000, 1101.79400000, 9.24650000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -31.37680000, 959.19130000, 13.92130000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -268.25000000, 751.37000000, 10.86610000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -199.04800000, 880.55260000, 5.15900000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -330.31000000, 1134.31000000, 12.49350000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -174.81230000, 938.15850000, 10.64700000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -115.90590000, 1043.57100000, 5.15920000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -315.16000000, 867.71000000, 8.89900000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -564.60000000, 1183.60000000, 9.01900000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -498.02150000, 1183.31100000, 13.21080000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -414.29530000, 1365.34600000, 15.55880000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -468.98060000, 1468.96400000, 17.86100000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -112.28410000, 1672.74500000, 17.61140000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -219.91810000, 1277.23200000, 22.09290000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 2.40000000, 1197.70000000, 16.47760000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -25.70000000, 1250.90000000, 19.43250000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -65.74770000, 1498.05800000, 17.44880000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -383.30600000, 319.06300000, 13.75090000 )
|
||||
--createPickup( getPickupType( 0 ), 23, 200, 65250, 344.20000000, 13.66590000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -212.60000000, 346.70000000, 14.03540000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -66.26470000, 278.22370000, 13.76360000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -181.14000000, 491.28420000, 13.71490000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -24.70000000, 405.20000000, 14.76350000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 51.61110000, 464.46720000, 13.69600000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 27.60000000, 374.20000000, 13.70190000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -603.98900000, 612.11540000, 3.85550000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -337.70000000, 215.40000000, 13.74920000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -383.50000000, 556.30000000, 13.77870000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -442.96920000, 590.37180000, 10.25190000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 141.80000000, 211.20000000, 13.76310000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -192.30000000, 162.40000000, 13.98940000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -348.60300000, -188.71300000, 13.64900000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -273.48200000, -157.81400000, 13.88300000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -117.97000000, -335.54000000, 13.73490000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -12.45000000, -218.40000000, 13.63990000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 179.94720000, -254.52090000, 11.85560000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 264.98180000, -302.83180000, 5.59270000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 162.58500000, -158.31150000, 13.92630000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 113.02140000, -39.66420000, 13.76250000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -126.60700000, -117.37200000, 13.81500000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 207.01740000, 20.70740000, 13.71320000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -254.45000000, -43.88000000, 13.76330000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -347.84500000, 105.27390000, 13.81310000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -345.03400000, -100.46700000, 13.70210000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -445.05100000, 131.98950000, 8.83120000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -490.37520000, 25.33320000, 6.86600000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -572.51200000, 86.31020000, 3.81230000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, 29.85000000, -601.28000000, 13.69580000 )
|
||||
createPickup( getPickupType( 0 ), 23, 200, -184.29000000, 102.09000000, 13.76770000 )
|
||||
end
|
||||
|
||||
AddEventHandler('createGunPickups', function(seed)
|
||||
pickupSeed = seed
|
||||
|
||||
RemoveAllPickupsOfType(23)
|
||||
createPickups()
|
||||
end)
|
9
resources/[test]/betaguns/server.lua
Normal file
9
resources/[test]/betaguns/server.lua
Normal file
@ -0,0 +1,9 @@
|
||||
math.randomseed(GetInstanceId())
|
||||
|
||||
local randomBase = math.random()
|
||||
|
||||
RegisterServerEvent('playerActivated')
|
||||
|
||||
AddEventHandler('playerActivated', function()
|
||||
TriggerClientEvent('createGunPickups', source, randomBase)
|
||||
end)
|
4
resources/[test]/gameInit/__resource.lua
Normal file
4
resources/[test]/gameInit/__resource.lua
Normal file
@ -0,0 +1,4 @@
|
||||
description 'early init for game script'
|
||||
|
||||
client_script 'init.lua'
|
||||
server_script 'server.lua'
|
42
resources/[test]/gameInit/init.lua
Normal file
42
resources/[test]/gameInit/init.lua
Normal file
@ -0,0 +1,42 @@
|
||||
CreateThread(function()
|
||||
local bit = function()
|
||||
return math.random()
|
||||
end
|
||||
|
||||
local function freezePlayer(id, freeze)
|
||||
local player = ConvertIntToPlayerindex(id)
|
||||
SetPlayerControlForNetwork(player, not freeze, false)
|
||||
|
||||
local ped = GetPlayerChar(player, _i)
|
||||
|
||||
if not freeze then
|
||||
if not IsCharVisible(ped) then
|
||||
SetCharVisible(ped, true)
|
||||
end
|
||||
|
||||
if not IsCharInAnyCar(ped) then
|
||||
SetCharCollision(ped, true)
|
||||
end
|
||||
|
||||
FreezeCharPosition(ped, false)
|
||||
SetCharNeverTargetted(ped, false)
|
||||
SetPlayerInvincible(player, false)
|
||||
else
|
||||
FreezeCharPosition(ped, true)
|
||||
SetCharNeverTargetted(ped, true)
|
||||
SetPlayerInvincible(player, true)
|
||||
|
||||
if not IsCharFatallyInjured(ped) then
|
||||
--ClearCharTasksImmediately(ped)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local player = CreatePlayer(0, -2000.5 + bit(), -2000.5 + bit(), 240.5 + bit(), _i)
|
||||
|
||||
freezePlayer(GetPlayerId(), true)
|
||||
|
||||
SetLoadingText("this is too lovely")
|
||||
|
||||
TriggerEvent('playerInfoCreated')
|
||||
end)
|
4
resources/[test]/gameInit/server.lua
Normal file
4
resources/[test]/gameInit/server.lua
Normal file
@ -0,0 +1,4 @@
|
||||
-- prevent stopping gameInit on the server
|
||||
AddEventHandler('onResourceStop', function(name)
|
||||
if name == 'gameInit' then CancelEvent() end
|
||||
end)
|
6
resources/[test]/keks/__resource.lua
Normal file
6
resources/[test]/keks/__resource.lua
Normal file
@ -0,0 +1,6 @@
|
||||
files {
|
||||
'index.html',
|
||||
'keks.css',
|
||||
'bankgothic.ttf',
|
||||
'loadscreen.jpg'
|
||||
}
|
BIN
resources/[test]/keks/bankgothic.ttf
Normal file
BIN
resources/[test]/keks/bankgothic.ttf
Normal file
Binary file not shown.
41
resources/[test]/keks/index.html
Normal file
41
resources/[test]/keks/index.html
Normal file
@ -0,0 +1,41 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="keks.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="backdrop">
|
||||
<div class="top">
|
||||
<h1 title="Free Mode">Free Mode</h1>
|
||||
<h2 title="Algonquin">Algonquin</h2>
|
||||
</div>
|
||||
|
||||
<div class="letni">
|
||||
<h2 title="INTEL">Intel</h2>
|
||||
<div class="loadbar"><div class="thingy"></div></div>
|
||||
<p>The Statue of Happiness has a heart. Have one too!</p>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div id="gradient">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var left = -10;
|
||||
|
||||
var self = function()
|
||||
{
|
||||
var elem = document.querySelector('.thingy');
|
||||
left += (0.15 / 60) * 100;
|
||||
if (left >= 100)
|
||||
{
|
||||
left = -10;
|
||||
}
|
||||
|
||||
elem.style.left = left + '%';
|
||||
requestAnimationFrame(self);
|
||||
};
|
||||
requestAnimationFrame(self);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
147
resources/[test]/keks/keks.css
Normal file
147
resources/[test]/keks/keks.css
Normal file
@ -0,0 +1,147 @@
|
||||
body
|
||||
{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.backdrop
|
||||
{
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background-image: url(loadscreen.jpg);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.bottom
|
||||
{
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#gradient
|
||||
{
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
|
||||
height: 25%;
|
||||
|
||||
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'BankGothic';
|
||||
src: url('bankgothic.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
position: relative;
|
||||
background: transparent;
|
||||
z-index: 0;
|
||||
}
|
||||
/* add a single stroke */
|
||||
h1:before, h2:before {
|
||||
content: attr(title);
|
||||
position: absolute;
|
||||
-webkit-text-stroke: 0.1em #000;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
.letni
|
||||
{
|
||||
position: absolute;
|
||||
left: 5%;
|
||||
right: 5%;
|
||||
bottom: 10%;
|
||||
|
||||
z-index: 5;
|
||||
|
||||
color: #fff;
|
||||
|
||||
font-family: "Segoe UI";
|
||||
}
|
||||
|
||||
.letni p
|
||||
{
|
||||
font-size: 22px;
|
||||
|
||||
margin-left: 3px;
|
||||
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.letni h2
|
||||
{
|
||||
font-family: BankGothic;
|
||||
|
||||
text-transform: uppercase;
|
||||
|
||||
font-size: 50px;
|
||||
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.top
|
||||
{
|
||||
color: #fff;
|
||||
|
||||
position: absolute;
|
||||
top: 7%;
|
||||
left: 5%;
|
||||
right: 5%;
|
||||
}
|
||||
|
||||
.top h1
|
||||
{
|
||||
font-family: BankGothic;
|
||||
font-size: 60px;
|
||||
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.top h2
|
||||
{
|
||||
font-family: BankGothic;
|
||||
font-size: 40px;
|
||||
|
||||
margin: 0px;
|
||||
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.loadbar
|
||||
{
|
||||
width: 100%;
|
||||
background-color: rgba(140, 140, 140, .9);
|
||||
height: 20px;
|
||||
|
||||
margin-left: 2px;
|
||||
margin-right: 3px;
|
||||
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.thingy
|
||||
{
|
||||
width: 10%;
|
||||
background-color: #eee;
|
||||
height: 20px;
|
||||
|
||||
position: absolute;
|
||||
left: 10%;
|
||||
}
|
BIN
resources/[test]/keks/loadscreen.jpg
Normal file
BIN
resources/[test]/keks/loadscreen.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 283 KiB |
2
resources/fivem-awesome1501/__resource.lua
Normal file
2
resources/fivem-awesome1501/__resource.lua
Normal file
@ -0,0 +1,2 @@
|
||||
client_script 'omg.lua'
|
||||
server_script 'srv.lua'
|
78
resources/fivem-awesome1501/omg.lua
Normal file
78
resources/fivem-awesome1501/omg.lua
Normal file
@ -0,0 +1,78 @@
|
||||
Citizen.Trace("OMG FINALLY FIVEM SCRIPTING FROM SERVER-SIDE STUFF WOWOWOWOWOW-zers\n")
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Citizen.Wait(0)
|
||||
|
||||
local playerPed = GetPlayerPed(-1)
|
||||
|
||||
if playerPed and playerPed ~= -1 then
|
||||
--local pos = GetEntityCoords(playerPed)
|
||||
|
||||
local is, pos = GetPedLastWeaponImpactCoord(playerPed)
|
||||
|
||||
if is then
|
||||
SetNotificationTextEntry('STRING')
|
||||
AddTextComponentString(tostring(pos))
|
||||
DrawNotification(false, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Citizen.Wait(50)
|
||||
|
||||
local playerPed = GetPlayerPed(-1)
|
||||
|
||||
if playerPed and playerPed ~= -1 then
|
||||
if IsControlPressed(2, 18) then
|
||||
SetEntityHeading(playerPed, GetEntityHeading(playerPed) + 15.0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
Citizen.Wait(250)
|
||||
|
||||
local playerPed = GetPlayerPed(-1)
|
||||
|
||||
if playerPed and playerPed ~= -1 then
|
||||
if IsControlPressed(0, 11) then
|
||||
RequestModel(0x2B6DC64A)
|
||||
|
||||
while not HasModelLoaded(0x2B6DC64A) do
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
|
||||
local playerCoords = GetEntityCoords(playerPed)
|
||||
playerCoords = playerCoords + vector3(0, 2, 0)
|
||||
|
||||
local car = CreateVehicle(0x2B6DC64A, playerCoords, 0.0, true, false)
|
||||
|
||||
SetNotificationTextEntry('STRING')
|
||||
AddTextComponentString('car: ' .. tostring(car))
|
||||
DrawNotification(false, false)
|
||||
|
||||
TriggerEvent('isogram', 'a', function(b)
|
||||
Citizen.Trace('in isogram ' .. tostring(b.a) .. "\n")
|
||||
|
||||
return b.a + 2
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('isogram', function(i, s)
|
||||
Citizen.Trace('in isogram_0 ' .. tostring(i) .. "\n")
|
||||
|
||||
Citizen.Trace('out of isogram_0 ' .. tostring(s({ a = 50 })) .. "\n")
|
||||
end)
|
||||
|
||||
AddEventHandler('onPlayerJoining', function(netId, name)
|
||||
TriggerServerEvent('yepThatsMe', netId, name, { a = 'b' })
|
||||
end)
|
5
resources/fivem-awesome1501/srv.lua
Normal file
5
resources/fivem-awesome1501/srv.lua
Normal file
@ -0,0 +1,5 @@
|
||||
RegisterServerEvent('yepThatsMe')
|
||||
|
||||
AddEventHandler('yepThatsMe', function(id, name, tab)
|
||||
print('ytm ', id, name, tab.a)
|
||||
end)
|
3
resources/fivem-map-hipster/__resource.lua
Normal file
3
resources/fivem-map-hipster/__resource.lua
Normal file
@ -0,0 +1,3 @@
|
||||
resource_type 'map' { gameTypes = { fivem = true } }
|
||||
|
||||
map 'map.lua'
|
64
resources/fivem-map-hipster/map.lua
Normal file
64
resources/fivem-map-hipster/map.lua
Normal file
@ -0,0 +1,64 @@
|
||||
vehicle_generator "airtug" { -54.26639938354492, -1679.548828125, 28.4414, heading = 228.2736053466797 }
|
||||
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -802.311, y = 175.056, z = 72.8446 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -9.96562, y = -1438.54, z = 31.1015 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 0.916756, y = 528.485, z = 174.628 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 1975.86, y = 3821.03, z = 33.4501 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -181.615, y = 852.8, z = 232.701 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 657.723, y = 457.342, z = 144.641 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 134.387, y = 1150.31, z = 231.594 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 726.14, y = 1196.91, z = 326.262 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 740.792, y = 1283.62, z = 360.297 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -437.009, y = 1059.59, z = 327.331 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -428.771, y = 1596.8, z = 356.338 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1348.78, y = 723.87, z = 186.45 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1543.24, y = 830.069, z = 182.132 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -2150.48, y = 222.019, z = 184.602 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -3032.13, y = 22.2157, z = 10.1184 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 3063.97, y = 5608.88, z = 209.245 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -2614.35, y = 1872.49, z = 167.32 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1873.94, y = 2088.73, z = 140.994 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -597.177, y = 2092.16, z = 131.413 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 967.126, y = 2226.99, z = 54.0588 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -338.043, y = 2829, z = 56.0871 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 1082.25, y = -696.921, z = 58.0099 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 1658.31, y = -13.9234, z = 169.992 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 2522.98, y = -384.436, z = 92.9928 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 2826.27, y = -656.489, z = 1.87841 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 2851.12, y = 1467.5, z = 24.5554 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 2336.33, y = 2535.39, z = 46.5177 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 2410.46, y = 3077.88, z = 48.1529 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 2451.15, y = 3768.37, z = 41.3477 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 3337.78, y = 5174.8, z = 18.2108 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1119.33, y = 4978.52, z = 186.26 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 2877.3, y = 5911.57, z = 369.618 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 2942.1, y = 5306.73, z = 101.52 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 2211.29, y = 5577.94, z = 53.872 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 1602.39, y = 6623.02, z = 15.8417 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 66.0113, y = 7203.58, z = 3.16 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -219.201, y = 6562.82, z = 10.9706 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -45.1562, y = 6301.64, z = 31.6114 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1004.77, y = 4854.32, z = 274.606 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1580.01, y = 5173.3, z = 19.5813 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1467.95, y = 5416.2, z = 23.5959 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -2359.31, y = 3243.83, z = 92.9037 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -2612.96, y = 3555.03, z = 4.85649 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -2083.27, y = 2616.94, z = 3.08396 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -524.471, y = 4195, z = 193.731 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -840.713, y = 4183.18, z = 215.29 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1576.24, y = 2103.87, z = 67.576 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1634.37, y = 209.816, z = 60.6413 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1495.07, y = 142.697, z = 55.6527 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1715.41, y = -197.722, z = 57.698 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1181.07, y = -505.544, z = 35.5661 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1712.37, y = -1082.91, z = 13.0801 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -1352.43, y = -1542.75, z = 4.42268 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -1756.89, y = 427.531, z = 127.685 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 3060.2, y = 2113.2, z = 1.6613 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 501.646, y = 5604.53, z = 797.91 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = 714.109, y = 4151.15, z = 35.7792 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = -103.651, y = -967.93, z = 296.52 }
|
||||
spawnpoint 'a_m_y_hipster_01' { x = -265.333, y = -2419.35, z = 122.366 }
|
||||
spawnpoint 'a_m_y_hipster_02' { x = 1788.25, y = 3890.34, z = 34.3849 }
|
||||
|
||||
--
|
3
resources/fivem-map-skater/__resource.lua
Normal file
3
resources/fivem-map-skater/__resource.lua
Normal file
@ -0,0 +1,3 @@
|
||||
resource_type 'map' { gameTypes = { fivem = true } }
|
||||
|
||||
map 'map.lua'
|
62
resources/fivem-map-skater/map.lua
Normal file
62
resources/fivem-map-skater/map.lua
Normal file
@ -0,0 +1,62 @@
|
||||
spawnpoint 'a_m_y_skater_01' { x = -802.311, y = 175.056, z = 72.8446 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -9.96562, y = -1438.54, z = 31.1015 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 0.916756, y = 528.485, z = 174.628 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 1975.86, y = 3821.03, z = 33.4501 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -181.615, y = 852.8, z = 232.701 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 657.723, y = 457.342, z = 144.641 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 134.387, y = 1150.31, z = 231.594 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 726.14, y = 1196.91, z = 326.262 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 740.792, y = 1283.62, z = 360.297 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -437.009, y = 1059.59, z = 327.331 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -428.771, y = 1596.8, z = 356.338 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1348.78, y = 723.87, z = 186.45 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1543.24, y = 830.069, z = 182.132 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -2150.48, y = 222.019, z = 184.602 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -3032.13, y = 22.2157, z = 10.1184 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 3063.97, y = 5608.88, z = 209.245 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -2614.35, y = 1872.49, z = 167.32 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1873.94, y = 2088.73, z = 140.994 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -597.177, y = 2092.16, z = 131.413 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 967.126, y = 2226.99, z = 54.0588 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -338.043, y = 2829, z = 56.0871 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 1082.25, y = -696.921, z = 58.0099 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 1658.31, y = -13.9234, z = 169.992 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 2522.98, y = -384.436, z = 92.9928 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 2826.27, y = -656.489, z = 1.87841 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 2851.12, y = 1467.5, z = 24.5554 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 2336.33, y = 2535.39, z = 46.5177 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 2410.46, y = 3077.88, z = 48.1529 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 2451.15, y = 3768.37, z = 41.3477 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 3337.78, y = 5174.8, z = 18.2108 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1119.33, y = 4978.52, z = 186.26 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 2877.3, y = 5911.57, z = 369.618 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 2942.1, y = 5306.73, z = 101.52 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 2211.29, y = 5577.94, z = 53.872 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 1602.39, y = 6623.02, z = 15.8417 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 66.0113, y = 7203.58, z = 3.16 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -219.201, y = 6562.82, z = 10.9706 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -45.1562, y = 6301.64, z = 31.6114 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1004.77, y = 4854.32, z = 274.606 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1580.01, y = 5173.3, z = 19.5813 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1467.95, y = 5416.2, z = 23.5959 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -2359.31, y = 3243.83, z = 92.9037 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -2612.96, y = 3555.03, z = 4.85649 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -2083.27, y = 2616.94, z = 3.08396 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -524.471, y = 4195, z = 193.731 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -840.713, y = 4183.18, z = 215.29 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1576.24, y = 2103.87, z = 67.576 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1634.37, y = 209.816, z = 60.6413 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1495.07, y = 142.697, z = 55.6527 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1715.41, y = -197.722, z = 57.698 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1181.07, y = -505.544, z = 35.5661 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1712.37, y = -1082.91, z = 13.0801 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -1352.43, y = -1542.75, z = 4.42268 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -1756.89, y = 427.531, z = 127.685 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 3060.2, y = 2113.2, z = 1.6613 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 501.646, y = 5604.53, z = 797.91 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = 714.109, y = 4151.15, z = 35.7792 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = -103.651, y = -967.93, z = 296.52 }
|
||||
spawnpoint 'a_m_y_skater_01' { x = -265.333, y = -2419.35, z = 122.366 }
|
||||
spawnpoint 'a_m_y_skater_02' { x = 1788.25, y = 3890.34, z = 34.3849 }
|
||||
|
||||
--
|
3
resources/fivem/__resource.lua
Normal file
3
resources/fivem/__resource.lua
Normal file
@ -0,0 +1,3 @@
|
||||
resource_type 'gametype' { name = 'Freeroam' }
|
||||
|
||||
client_script 'fivem_client.lua'
|
9
resources/fivem/fivem_client.lua
Normal file
9
resources/fivem/fivem_client.lua
Normal file
@ -0,0 +1,9 @@
|
||||
AddEventHandler('onClientMapStart', function()
|
||||
Citizen.Trace("ocms fivem\n")
|
||||
|
||||
exports.spawnmanager:setAutoSpawn(true)
|
||||
exports.spawnmanager:forceRespawn()
|
||||
SetClockTime(24, 0, 0)
|
||||
PauseClock(true)
|
||||
Citizen.Trace("ocms fivem end\n")
|
||||
end)
|
85
resources/initial/net_init.lua
Normal file
85
resources/initial/net_init.lua
Normal file
@ -0,0 +1,85 @@
|
||||
local function launchGame()
|
||||
-- TODO: replace with the actual game mode the joined session is running
|
||||
--StartResource('citizen')
|
||||
TriggerEvent('gameModeStarted')
|
||||
|
||||
--StopResource('initial')
|
||||
end
|
||||
|
||||
local function showError(err)
|
||||
ForceLoadingScreen(0)
|
||||
SetMsgForLoadingScreen(err)
|
||||
|
||||
echo(err .. "\n")
|
||||
|
||||
return "exit"
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
Wait(50)
|
||||
|
||||
AllowThisScriptToBePaused(false)
|
||||
SetNoResprays(false)
|
||||
ThisScriptIsSafeForNetworkGame()
|
||||
|
||||
if IsPlayerPlaying(GetPlayerIndex()) then
|
||||
SetPlayerControl(GetPlayerIndex(), false)
|
||||
end
|
||||
|
||||
-- setup default callbacks
|
||||
exports.session:reset()
|
||||
|
||||
AddEventHandler('sessionStateChanged', function(state)
|
||||
if state == 'find' then
|
||||
SetLoadingText('Finding games...')
|
||||
elseif state == 'host' then
|
||||
SetLoadingText('Creating game...')
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('sessionJoining', function(cur, max, hostName)
|
||||
SetLoadingText('Joining game ' .. cur .. ' of ' .. max .. '... (' .. hostName .. ')')
|
||||
end)
|
||||
|
||||
AddEventHandler('sessionJoined', launchGame)
|
||||
AddEventHandler('sessionHosted', launchGame)
|
||||
|
||||
AddEventHandler('sessionHostFailed', function(err)
|
||||
echo("hosting game failed: " .. err .. "\n")
|
||||
showError("NICON_MT")
|
||||
|
||||
ShutdownAndLaunchSinglePlayerGame()
|
||||
end)
|
||||
|
||||
local sessionList
|
||||
local curJoinSession = 0
|
||||
|
||||
local joinFailed = function()
|
||||
exports.session:hostSession(16, 32)
|
||||
end
|
||||
|
||||
AddEventHandler('sessionJoinFailed', function()
|
||||
curJoinSession = curJoinSession + 1
|
||||
|
||||
if curJoinSession > #sessionList then
|
||||
joinFailed()
|
||||
return
|
||||
end
|
||||
|
||||
exports.session:joinSession(sessionList[curJoinSession])
|
||||
end)
|
||||
|
||||
AddEventHandler('sessionsFound', function(sessions)
|
||||
if #sessions == 0 then
|
||||
joinFailed()
|
||||
return
|
||||
end
|
||||
|
||||
sessionList = sessions
|
||||
|
||||
curJoinSession = 1
|
||||
exports.session:joinSession(sessionList[curJoinSession])
|
||||
end)
|
||||
|
||||
exports.session:findSessions(16)
|
||||
end)
|
4
run.sh
Normal file
4
run.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
fx_root=`dirname "$(readlink -f "$0")"`
|
||||
|
||||
MONO_PATH=$fx_root/mono/ mono $fx_root/CitizenMP.Server.exe $*
|
1205
system/MessagePack.lua
Normal file
1205
system/MessagePack.lua
Normal file
File diff suppressed because it is too large
Load Diff
709
system/dkjson.lua
Normal file
709
system/dkjson.lua
Normal file
@ -0,0 +1,709 @@
|
||||
-- Module options:
|
||||
local always_try_using_lpeg = true
|
||||
local register_global_module_table = true
|
||||
local global_module_name = 'json'
|
||||
|
||||
--[==[
|
||||
|
||||
David Kolf's JSON module for Lua 5.1/5.2
|
||||
|
||||
Version 2.5
|
||||
|
||||
|
||||
For the documentation see the corresponding readme.txt or visit
|
||||
<http://dkolf.de/src/dkjson-lua.fsl/>.
|
||||
|
||||
You can contact the author by sending an e-mail to 'david' at the
|
||||
domain 'dkolf.de'.
|
||||
|
||||
|
||||
Copyright (C) 2010-2013 David Heiko Kolf
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
--]==]
|
||||
|
||||
-- global dependencies:
|
||||
--local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
|
||||
-- pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
|
||||
--local error, require, pcall, select = error, require, pcall, select
|
||||
local floor, huge = math.floor, math.huge
|
||||
local strrep, gsub, gsubf, strsub, strbyte, strchar, strfind, strlen, strformat =
|
||||
string.rep, gsub, gsubf, ssub, string.byte, string.char,
|
||||
sfind, string.len, string.format
|
||||
local strmatch = string.match
|
||||
local concat = table.concat
|
||||
|
||||
local json = { version = "dkjson 2.5" }
|
||||
|
||||
if register_global_module_table then
|
||||
_G[global_module_name] = json
|
||||
end
|
||||
|
||||
local _ENV = nil -- blocking globals in Lua 5.2
|
||||
|
||||
pcall (function()
|
||||
-- Enable access to blocked metatables.
|
||||
-- Don't worry, this module doesn't change anything in them.
|
||||
local debmeta = require "debug".getmetatable
|
||||
if debmeta then getmetatable = debmeta end
|
||||
end)
|
||||
|
||||
json.null = setmetatable ({}, {
|
||||
__tojson = function () return "null" end
|
||||
})
|
||||
|
||||
local function isarray (tbl)
|
||||
local max, n, arraylen = 0, 0, 0
|
||||
for k,v in pairs (tbl) do
|
||||
if k == 'n' and type(v) == 'number' then
|
||||
arraylen = v
|
||||
if v > max then
|
||||
max = v
|
||||
end
|
||||
else
|
||||
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
|
||||
return false
|
||||
end
|
||||
if k > max then
|
||||
max = k
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
if max > 10 and max > arraylen and max > n * 2 then
|
||||
return false -- don't create an array with too many holes
|
||||
end
|
||||
return true, max
|
||||
end
|
||||
|
||||
local escapecodes = {
|
||||
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
|
||||
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
|
||||
}
|
||||
|
||||
local function escapeutf8 (uchar)
|
||||
local value = escapecodes[uchar]
|
||||
if value then
|
||||
return value
|
||||
end
|
||||
local a, b, c, d = strbyte (uchar, 1, 4)
|
||||
a, b, c, d = a or 0, b or 0, c or 0, d or 0
|
||||
if a <= 0x7f then
|
||||
value = a
|
||||
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
|
||||
value = (a - 0xc0) * 0x40 + b - 0x80
|
||||
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
|
||||
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
|
||||
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
|
||||
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
|
||||
else
|
||||
return ""
|
||||
end
|
||||
if value <= 0xffff then
|
||||
return strformat ("\\u%.4x", value)
|
||||
elseif value <= 0x10ffff then
|
||||
-- encode as UTF-16 surrogate pair
|
||||
value = value - 0x10000
|
||||
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
|
||||
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
local function fsub (str, pattern, repl)
|
||||
-- gsub always builds a new string in a buffer, even when no match
|
||||
-- exists. First using find should be more efficient when most strings
|
||||
-- don't contain the pattern.
|
||||
if strfind (str, pattern) then
|
||||
if type(repl) == 'function' then
|
||||
return gsubf(str, pattern, repl)
|
||||
else
|
||||
return gsub (str, pattern, repl)
|
||||
end
|
||||
else
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
local function quotestring (value)
|
||||
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
|
||||
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
|
||||
if strfind (value, "[\194\216\220\225\226\239]") then
|
||||
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
|
||||
value = fsub (value, "\216[\128-\132]", escapeutf8)
|
||||
value = fsub (value, "\220\143", escapeutf8)
|
||||
value = fsub (value, "\225\158[\180\181]", escapeutf8)
|
||||
value = fsub (value, "\226\128[\140-\143\168-\175]", escapeutf8)
|
||||
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
|
||||
value = fsub (value, "\239\187\191", escapeutf8)
|
||||
value = fsub (value, "\239\191[\176-\191]", escapeutf8)
|
||||
end
|
||||
return "\"" .. value .. "\""
|
||||
end
|
||||
json.quotestring = quotestring
|
||||
|
||||
local function replace(str, o, n)
|
||||
local i, j = strfind (str, o, 1, true)
|
||||
if i then
|
||||
return strsub(str, 1, i-1) .. n .. strsub(str, j+1, -1)
|
||||
else
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
-- locale independent num2str and str2num functions
|
||||
local decpoint, numfilter
|
||||
|
||||
local function updatedecpoint ()
|
||||
decpoint = strmatch(tostring(0.5), "([^05+])")
|
||||
-- build a filter that can be used to remove group separators
|
||||
numfilter = "[^0-9%-%+eE" .. gsub(decpoint, "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%0") .. "]+"
|
||||
end
|
||||
|
||||
updatedecpoint()
|
||||
|
||||
local function num2str (num)
|
||||
return replace(fsub(tostring(num), numfilter, ""), decpoint, ".")
|
||||
end
|
||||
|
||||
local function str2num (str)
|
||||
local num = tonumber(replace(str, ".", decpoint))
|
||||
if not num then
|
||||
updatedecpoint()
|
||||
num = tonumber(replace(str, ".", decpoint))
|
||||
end
|
||||
return num
|
||||
end
|
||||
|
||||
local function addnewline2 (level, buffer, buflen)
|
||||
buffer[buflen+1] = "\n"
|
||||
buffer[buflen+2] = strrep (" ", level)
|
||||
buflen = buflen + 2
|
||||
return buflen
|
||||
end
|
||||
|
||||
function json.addnewline (state)
|
||||
if state.indent then
|
||||
state.bufferlen = addnewline2 (state.level or 0,
|
||||
state.buffer, state.bufferlen or #(state.buffer))
|
||||
end
|
||||
end
|
||||
|
||||
local encode2 -- forward declaration
|
||||
|
||||
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||
local kt = type (key)
|
||||
if kt ~= 'string' and kt ~= 'number' then
|
||||
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
|
||||
end
|
||||
if prev then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = ","
|
||||
end
|
||||
if indent then
|
||||
buflen = addnewline2 (level, buffer, buflen)
|
||||
end
|
||||
buffer[buflen+1] = quotestring (key)
|
||||
buffer[buflen+2] = ":"
|
||||
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder, state)
|
||||
end
|
||||
|
||||
local function appendcustom(res, buffer, state)
|
||||
local buflen = state.bufferlen
|
||||
if type (res) == 'string' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = res
|
||||
end
|
||||
return buflen
|
||||
end
|
||||
|
||||
local function exception(reason, value, state, buffer, buflen, defaultmessage)
|
||||
defaultmessage = defaultmessage or reason
|
||||
local handler = state.exception
|
||||
if not handler then
|
||||
return nil, defaultmessage
|
||||
else
|
||||
state.bufferlen = buflen
|
||||
local ret, msg = handler (reason, value, state, defaultmessage)
|
||||
if not ret then return nil, msg or defaultmessage end
|
||||
return appendcustom(ret, buffer, state)
|
||||
end
|
||||
end
|
||||
|
||||
function json.encodeexception(reason, value, state, defaultmessage)
|
||||
return quotestring("<" .. defaultmessage .. ">")
|
||||
end
|
||||
|
||||
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder, state)
|
||||
local valtype = type (value)
|
||||
local valmeta = getmetatable (value)
|
||||
valmeta = type (valmeta) == 'table' and valmeta -- only tables
|
||||
local valtojson = valmeta and valmeta.__tojson
|
||||
if valtojson then
|
||||
if tables[value] then
|
||||
return exception('reference cycle', value, state, buffer, buflen)
|
||||
end
|
||||
tables[value] = true
|
||||
state.bufferlen = buflen
|
||||
local ret, msg = valtojson (value, state)
|
||||
if not ret then return exception('custom encoder failed', value, state, buffer, buflen, msg) end
|
||||
tables[value] = nil
|
||||
buflen = appendcustom(ret, buffer, state)
|
||||
elseif valtype == 'nil' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "null"
|
||||
elseif valtype == 'number' then
|
||||
local s
|
||||
if value ~= value or value >= huge or -value >= huge then
|
||||
-- This is the behaviour of the original JSON implementation.
|
||||
s = "null"
|
||||
else
|
||||
s = num2str (value)
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = s
|
||||
elseif valtype == 'boolean' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = value and "true" or "false"
|
||||
elseif valtype == 'string' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = quotestring (value)
|
||||
elseif valtype == 'table' then
|
||||
--[[if tables[value] then
|
||||
return exception('reference cycle', value, state, buffer, buflen)
|
||||
end
|
||||
tables[value] = true]]
|
||||
level = level + 1
|
||||
local isa, n = isarray (value)
|
||||
if n == 0 and valmeta and valmeta.__jsontype == 'object' then
|
||||
isa = false
|
||||
end
|
||||
local msg
|
||||
if isa then -- JSON array
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "["
|
||||
for i = 1, n do
|
||||
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder, state)
|
||||
if not buflen then return nil, msg end
|
||||
if i < n then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = ","
|
||||
end
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "]"
|
||||
else -- JSON object
|
||||
local prev = false
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "{"
|
||||
local order = valmeta and valmeta.__jsonorder or globalorder
|
||||
if order then
|
||||
local used = {}
|
||||
n = #order
|
||||
for i = 1, n do
|
||||
local k = order[i]
|
||||
local v = value[k]
|
||||
if v then
|
||||
used[k] = true
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
for k,v in pairs (value) do
|
||||
if not used[k] then
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||
if not buflen then return nil, msg end
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
else -- unordered
|
||||
for k,v in pairs (value) do
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder, state)
|
||||
if not buflen then return nil, msg end
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
if indent then
|
||||
buflen = addnewline2 (level - 1, buffer, buflen)
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "}"
|
||||
end
|
||||
--tables[value] = nil
|
||||
else
|
||||
return exception ('unsupported type', value, state, buffer, buflen,
|
||||
"type '" .. valtype .. "' is not supported by JSON.")
|
||||
end
|
||||
return buflen
|
||||
end
|
||||
|
||||
function json.encode (value, state)
|
||||
state = state or {}
|
||||
local oldbuffer = state.buffer
|
||||
local buffer = oldbuffer or {}
|
||||
state.buffer = buffer
|
||||
updatedecpoint()
|
||||
local ret, msg = encode2 (value, state.indent, state.level or 0,
|
||||
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder, state)
|
||||
if not ret then
|
||||
error (msg, 2)
|
||||
elseif oldbuffer == buffer then
|
||||
state.bufferlen = ret
|
||||
return true
|
||||
else
|
||||
state.bufferlen = nil
|
||||
state.buffer = nil
|
||||
return concat (buffer)
|
||||
end
|
||||
end
|
||||
|
||||
local function loc (str, where)
|
||||
local line, pos, linepos = 1, 1, 0
|
||||
while true do
|
||||
pos = strfind (str, "\n", pos, true)
|
||||
if pos and pos < where then
|
||||
line = line + 1
|
||||
linepos = pos
|
||||
pos = pos + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return "line " .. line .. ", column " .. (where - linepos)
|
||||
end
|
||||
|
||||
local function unterminated (str, what, where)
|
||||
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
|
||||
end
|
||||
|
||||
local function scanwhite (str, pos)
|
||||
while true do
|
||||
pos = strfind (str, "%S", pos)
|
||||
if not pos then return nil end
|
||||
local sub2 = strsub (str, pos, pos + 1)
|
||||
if sub2 == "\239\187" and strsub (str, pos + 2, pos + 2) == "\191" then
|
||||
-- UTF-8 Byte Order Mark
|
||||
pos = pos + 3
|
||||
elseif sub2 == "//" then
|
||||
pos = strfind (str, "[\n\r]", pos + 2)
|
||||
if not pos then return nil end
|
||||
elseif sub2 == "/*" then
|
||||
pos = strfind (str, "*/", pos + 2)
|
||||
if not pos then return nil end
|
||||
pos = pos + 2
|
||||
else
|
||||
return pos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local escapechars = {
|
||||
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
|
||||
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
|
||||
}
|
||||
|
||||
local function unichar (value)
|
||||
if value < 0 then
|
||||
return nil
|
||||
elseif value <= 0x007f then
|
||||
return strchar (value)
|
||||
elseif value <= 0x07ff then
|
||||
return strchar (0xc0 + floor(value/0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
elseif value <= 0xffff then
|
||||
return strchar (0xe0 + floor(value/0x1000),
|
||||
0x80 + (floor(value/0x40) % 0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
elseif value <= 0x10ffff then
|
||||
return strchar (0xf0 + floor(value/0x40000),
|
||||
0x80 + (floor(value/0x1000) % 0x40),
|
||||
0x80 + (floor(value/0x40) % 0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function scanstring (str, pos)
|
||||
local lastpos = pos + 1
|
||||
local buffer, n = {}, 0
|
||||
while true do
|
||||
local nextpos = strfind (str, "[\"\\]", lastpos)
|
||||
if not nextpos then
|
||||
return unterminated (str, "string", pos)
|
||||
end
|
||||
if nextpos > lastpos then
|
||||
n = n + 1
|
||||
buffer[n] = strsub (str, lastpos, nextpos - 1)
|
||||
end
|
||||
if strsub (str, nextpos, nextpos) == "\"" then
|
||||
lastpos = nextpos + 1
|
||||
break
|
||||
else
|
||||
local escchar = strsub (str, nextpos + 1, nextpos + 1)
|
||||
local value
|
||||
if escchar == "u" then
|
||||
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
|
||||
if value then
|
||||
local value2
|
||||
if 0xD800 <= value and value <= 0xDBff then
|
||||
-- we have the high surrogate of UTF-16. Check if there is a
|
||||
-- low surrogate escaped nearby to combine them.
|
||||
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
|
||||
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
|
||||
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
|
||||
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
|
||||
else
|
||||
value2 = nil -- in case it was out of range for a low surrogate
|
||||
end
|
||||
end
|
||||
end
|
||||
value = value and unichar (value)
|
||||
if value then
|
||||
if value2 then
|
||||
lastpos = nextpos + 12
|
||||
else
|
||||
lastpos = nextpos + 6
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not value then
|
||||
value = escapechars[escchar] or escchar
|
||||
lastpos = nextpos + 2
|
||||
end
|
||||
n = n + 1
|
||||
buffer[n] = value
|
||||
end
|
||||
end
|
||||
if n == 1 then
|
||||
return buffer[1], lastpos
|
||||
elseif n > 1 then
|
||||
return concat (buffer), lastpos
|
||||
else
|
||||
return "", lastpos
|
||||
end
|
||||
end
|
||||
|
||||
local scanvalue -- forward declaration
|
||||
|
||||
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
|
||||
local len = strlen (str)
|
||||
local tbl, n = {}, 0
|
||||
local pos = startpos + 1
|
||||
if what == 'object' then
|
||||
setmetatable (tbl, objectmeta)
|
||||
else
|
||||
setmetatable (tbl, arraymeta)
|
||||
end
|
||||
while true do
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
local char = strsub (str, pos, pos)
|
||||
if char == closechar then
|
||||
return tbl, pos + 1
|
||||
end
|
||||
local val1, err
|
||||
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
if err then return nil, pos, err end
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
char = strsub (str, pos, pos)
|
||||
if char == ":" then
|
||||
if val1 == nil then
|
||||
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
|
||||
end
|
||||
pos = scanwhite (str, pos + 1)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
local val2
|
||||
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
if err then return nil, pos, err end
|
||||
tbl[val1] = val2
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
char = strsub (str, pos, pos)
|
||||
else
|
||||
n = n + 1
|
||||
tbl[n] = val1
|
||||
end
|
||||
if char == "," then
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local level = 0
|
||||
|
||||
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
|
||||
pos = pos or 1
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then
|
||||
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
|
||||
end
|
||||
local char = strsub (str, pos, pos)
|
||||
if char == "{" then
|
||||
level = level + 1
|
||||
|
||||
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
|
||||
elseif char == "[" then
|
||||
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
|
||||
elseif char == "\"" then
|
||||
return scanstring (str, pos)
|
||||
else
|
||||
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
|
||||
if pstart then
|
||||
local number = str2num (strsub (str, pstart, pend))
|
||||
if type(number) == 'number' then -- FIXME: change to 'if number then' when neolua bug is fixed
|
||||
return number, pend + 1
|
||||
end
|
||||
end
|
||||
pstart, pend = strfind (str, "^%a%w*", pos)
|
||||
if pstart then
|
||||
local name = strsub (str, pstart, pend)
|
||||
if name == "true" then
|
||||
return true, pend + 1
|
||||
elseif name == "false" then
|
||||
return false, pend + 1
|
||||
elseif name == "null" then
|
||||
return nullval, pend + 1
|
||||
end
|
||||
end
|
||||
return nil, pos, "no valid JSON value at " .. loc (str, pos)
|
||||
end
|
||||
end
|
||||
|
||||
function json.decode (str, pos, nullval, ...)
|
||||
local objectmeta, arraymeta = {__jsontype = 'object'}, {__jsontype = 'array'}
|
||||
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
end
|
||||
|
||||
function json.use_lpeg ()
|
||||
local g = require ("lpeg")
|
||||
|
||||
if g.version() == "0.11" then
|
||||
error "due to a bug in LPeg 0.11, it cannot be used for JSON matching"
|
||||
end
|
||||
|
||||
local pegmatch = g.match
|
||||
local P, S, R = g.P, g.S, g.R
|
||||
|
||||
local function ErrorCall (str, pos, msg, state)
|
||||
if not state.msg then
|
||||
state.msg = msg .. " at " .. loc (str, pos)
|
||||
state.pos = pos
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function Err (msg)
|
||||
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
|
||||
end
|
||||
|
||||
local SingleLineComment = P"//" * (1 - S"\n\r")^0
|
||||
local MultiLineComment = P"/*" * (1 - P"*/")^0 * P"*/"
|
||||
local Space = (S" \n\r\t" + P"\239\187\191" + SingleLineComment + MultiLineComment)^0
|
||||
|
||||
local PlainChar = 1 - S"\"\\\n\r"
|
||||
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
|
||||
local HexDigit = R("09", "af", "AF")
|
||||
local function UTF16Surrogate (match, pos, high, low)
|
||||
high, low = tonumber (high, 16), tonumber (low, 16)
|
||||
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
|
||||
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local function UTF16BMP (hex)
|
||||
return unichar (tonumber (hex, 16))
|
||||
end
|
||||
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
|
||||
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
|
||||
local Char = UnicodeEscape + EscapeSequence + PlainChar
|
||||
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
|
||||
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
|
||||
local Fractal = P"." * R"09"^0
|
||||
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
|
||||
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/str2num
|
||||
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
|
||||
local SimpleValue = Number + String + Constant
|
||||
local ArrayContent, ObjectContent
|
||||
|
||||
-- The functions parsearray and parseobject parse only a single value/pair
|
||||
-- at a time and store them directly to avoid hitting the LPeg limits.
|
||||
local function parsearray (str, pos, nullval, state)
|
||||
local obj, cont
|
||||
local npos
|
||||
local t, nt = {}, 0
|
||||
repeat
|
||||
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
|
||||
if not npos then break end
|
||||
pos = npos
|
||||
nt = nt + 1
|
||||
t[nt] = obj
|
||||
until cont == 'last'
|
||||
return pos, setmetatable (t, state.arraymeta)
|
||||
end
|
||||
|
||||
local function parseobject (str, pos, nullval, state)
|
||||
local obj, key, cont
|
||||
local npos
|
||||
local t = {}
|
||||
repeat
|
||||
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
|
||||
if not npos then break end
|
||||
pos = npos
|
||||
t[key] = obj
|
||||
until cont == 'last'
|
||||
return pos, setmetatable (t, state.objectmeta)
|
||||
end
|
||||
|
||||
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
|
||||
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
|
||||
local Value = Space * (Array + Object + SimpleValue)
|
||||
local ExpectedValue = Value + Space * Err "value expected"
|
||||
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
|
||||
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
|
||||
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
|
||||
local DecodeValue = ExpectedValue * g.Cp ()
|
||||
|
||||
function json.decode (str, pos, nullval, ...)
|
||||
local state = {}
|
||||
state.objectmeta, state.arraymeta = optionalmetatables(...)
|
||||
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
|
||||
if state.msg then
|
||||
return nil, state.pos, state.msg
|
||||
else
|
||||
return obj, retpos
|
||||
end
|
||||
end
|
||||
|
||||
-- use this function only once:
|
||||
json.use_lpeg = function () return json end
|
||||
|
||||
json.using_lpeg = true
|
||||
|
||||
return json -- so you can get the module using json = require "dkjson".use_lpeg()
|
||||
end
|
||||
|
||||
return json
|
289
system/resource_init.lua
Normal file
289
system/resource_init.lua
Normal file
@ -0,0 +1,289 @@
|
||||
-- local resource init stuff (similar to client resource_init)
|
||||
RegisterInitHandler(function(initScript, isPreParse)
|
||||
local env = {
|
||||
_VERSION = _VERSION,
|
||||
assert = assert,
|
||||
error = error,
|
||||
getmetatable = getmetatable,
|
||||
ipairs = ipairs,
|
||||
next = next,
|
||||
pairs = pairs,
|
||||
pcall = pcall,
|
||||
print = print,
|
||||
rawequal = rawequal,
|
||||
rawget = rawget,
|
||||
rawlen = rawlen,
|
||||
rawset = rawset,
|
||||
select = select,
|
||||
setmetatable = setmetatable,
|
||||
tonumber = tonumber,
|
||||
tostring = tostring,
|
||||
type = type,
|
||||
xpcall = xpcall,
|
||||
bit32 = {
|
||||
arshift = bit32.arshift,
|
||||
band = bit32.band,
|
||||
bnot = bit32.bnot,
|
||||
bor = bit32.bor,
|
||||
btest = bit32.btest,
|
||||
bxor = bit32.bxor,
|
||||
extract = bit32.extract,
|
||||
lrotate = bit32.lrotate,
|
||||
lshift = bit32.lshift,
|
||||
replace = bit32.replace,
|
||||
rrotate = bit32.rrotate,
|
||||
rshift = bit32.rshift
|
||||
},
|
||||
coroutine = {
|
||||
create = coroutine.create,
|
||||
resume = coroutine.resume,
|
||||
running = coroutine.running,
|
||||
status = coroutine.status,
|
||||
wrap = coroutine.wrap,
|
||||
yield = coroutine.yield
|
||||
},
|
||||
math = {
|
||||
abs = math.abs,
|
||||
acos = math.acos,
|
||||
asin = math.asin,
|
||||
atan = math.atan,
|
||||
atan2 = math.atan2,
|
||||
ceil = math.ceil,
|
||||
cos = math.cos,
|
||||
cosh = math.cosh,
|
||||
deg = math.deg,
|
||||
exp = math.exp,
|
||||
floor = math.floor,
|
||||
fmod = math.fmod,
|
||||
frexp = math.frexp,
|
||||
huge = math.huge,
|
||||
ldexp = math.ldexp,
|
||||
log = math.log,
|
||||
max = math.max,
|
||||
min = math.min,
|
||||
modf = math.modf,
|
||||
pi = math.pi,
|
||||
pow = math.pow,
|
||||
rad = math.rad,
|
||||
random = math.random,
|
||||
randomseed = math.randomseed,
|
||||
sin = math.sin,
|
||||
sinh = math.sinh,
|
||||
sqrt = math.sqrt,
|
||||
tan = math.tan,
|
||||
tanh = math.tanh
|
||||
},
|
||||
string = {
|
||||
byte = string.byte,
|
||||
char = string.char,
|
||||
dump = string.dump,
|
||||
find = string.find,
|
||||
format = string.format,
|
||||
gmatch = string.gmatch,
|
||||
gsub = string.gsub,
|
||||
len = string.len,
|
||||
lower = string.lower,
|
||||
match = string.match,
|
||||
rep = string.rep,
|
||||
reverse = string.reverse,
|
||||
sub = string.sub,
|
||||
upper = string.upper
|
||||
},
|
||||
table = {
|
||||
concat = table.concat,
|
||||
insert = table.insert,
|
||||
pack = table.pack,
|
||||
remove = table.remove,
|
||||
sort = table.sort,
|
||||
unpack = table.unpack
|
||||
}
|
||||
}
|
||||
|
||||
TriggerEvent('getResourceInitFuncs', isPreParse, function(key, cb)
|
||||
env[key] = cb
|
||||
end)
|
||||
|
||||
local pr = print
|
||||
|
||||
if not isPreParse then
|
||||
env.server_scripts = function(n)
|
||||
if type(n) == 'string' then
|
||||
n = { n }
|
||||
end
|
||||
|
||||
for _, d in ipairs(n) do
|
||||
AddServerScript(d)
|
||||
end
|
||||
end
|
||||
|
||||
env.server_script = env.server_scripts
|
||||
else
|
||||
-- and add our native items
|
||||
env.solution = function(n)
|
||||
SetResourceInfo('clr_solution', n)
|
||||
end
|
||||
|
||||
env.description = function(n)
|
||||
SetResourceInfo('description', n)
|
||||
end
|
||||
|
||||
env.version = function(n)
|
||||
SetResourceInfo('version', n)
|
||||
end
|
||||
|
||||
env.client_scripts = function(n)
|
||||
if type(n) == 'string' then
|
||||
n = { n }
|
||||
end
|
||||
|
||||
for _, d in ipairs(n) do
|
||||
AddClientScript(d)
|
||||
end
|
||||
end
|
||||
|
||||
env.client_script = env.client_scripts
|
||||
|
||||
env.files = function(n)
|
||||
if type(n) == 'string' then
|
||||
n = { n }
|
||||
end
|
||||
|
||||
for _, d in ipairs(n) do
|
||||
AddAuxFile(d)
|
||||
end
|
||||
end
|
||||
|
||||
env.file = env.files
|
||||
|
||||
env.dependencies = function(n)
|
||||
if type(n) == 'string' then
|
||||
n = { n }
|
||||
end
|
||||
|
||||
for _, d in ipairs(n) do
|
||||
AddResourceDependency(d)
|
||||
end
|
||||
end
|
||||
|
||||
env.dependency = env.dependencies
|
||||
end
|
||||
|
||||
local rawget_ = rawget
|
||||
local print_ = print
|
||||
|
||||
local mt = {
|
||||
__index = function(t, k) : object
|
||||
if env[k] ~= nil then
|
||||
return env[k]
|
||||
end
|
||||
|
||||
if rawget_(t, k) ~= nil then
|
||||
return rawget_(t, k)
|
||||
end
|
||||
|
||||
-- as we're not going to return nothing here (to allow unknown directives to be ignored)
|
||||
local f = function()
|
||||
return f
|
||||
end
|
||||
|
||||
return function() return f end
|
||||
end
|
||||
}
|
||||
|
||||
for k, v in pairs(env) do
|
||||
if type(v) == 'function' then
|
||||
env[k] = function(...)
|
||||
_G.__metatable = nil
|
||||
|
||||
local rv = v(...)
|
||||
|
||||
_G.__metatable = mt
|
||||
|
||||
return rv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
_G.__metatable = mt
|
||||
--setmetatable(env, mt)
|
||||
--setfenv(initScript, env)
|
||||
|
||||
initScript()
|
||||
|
||||
--env = nil
|
||||
|
||||
--setfenv(initScript, _G)
|
||||
|
||||
_G.__metatable = nil
|
||||
|
||||
-- print('rc', findallpaths(rt))
|
||||
end)
|
||||
|
||||
-- nothing, yet
|
||||
|
||||
-- TODO: cleanup RPC environment stuff on coroutine end/error
|
||||
local function RunRPCFunction(f, env)
|
||||
local co = coroutine.create(f)
|
||||
env.__co = client
|
||||
|
||||
local success, err = coroutine.resume(co)
|
||||
|
||||
if success then
|
||||
env.SendEvents()
|
||||
else
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
|
||||
local rpcIdx = 1
|
||||
local rpcEnvironments = {}
|
||||
|
||||
function CreateRPCContext(cl, f)
|
||||
local idx = rpcIdx
|
||||
rpcIdx = rpcIdx + 1
|
||||
|
||||
local key = cl .. '_' .. idx
|
||||
|
||||
local env = {
|
||||
getIdx = function()
|
||||
return idx
|
||||
end,
|
||||
getSource = function()
|
||||
return cl
|
||||
end
|
||||
}
|
||||
|
||||
local lastEnv = _ENV
|
||||
|
||||
setmetatable(env, {__index = _G})
|
||||
|
||||
local _ENV = env
|
||||
rpcEnvironments[key] = env
|
||||
|
||||
setfenv(f, env)
|
||||
|
||||
local fRun = f()
|
||||
|
||||
local virtenv_init = loadfile('system/virtenv_init.lua', 't', env)
|
||||
virtenv_init()
|
||||
|
||||
_ENV = lastEnv
|
||||
|
||||
RunRPCFunction(fRun, env)
|
||||
end
|
||||
|
||||
RegisterServerEvent('svRpc:results')
|
||||
|
||||
AddEventHandler('svRpc:results', function(results)
|
||||
if not results.idx then
|
||||
return
|
||||
end
|
||||
|
||||
local key = source .. '_' .. results.idx
|
||||
|
||||
if not rpcEnvironments[key] then
|
||||
return
|
||||
end
|
||||
|
||||
rpcEnvironments[key].HandleResults(results)
|
||||
end)
|
99
system/virtenv_init.lua
Normal file
99
system/virtenv_init.lua
Normal file
@ -0,0 +1,99 @@
|
||||
local execQueue = {}
|
||||
local execQueueArgNum = 1
|
||||
local execResults = {}
|
||||
local curRoutine
|
||||
|
||||
_i = { _a = '_i' }
|
||||
_f = { _a = '_f' }
|
||||
|
||||
function GetResult(argNum)
|
||||
if not execResults[argNum] then
|
||||
if #execQueue > 0 then
|
||||
execQueue.idx = getIdx()
|
||||
|
||||
curRoutine = coroutine.running()
|
||||
coroutine.yield()
|
||||
|
||||
execQueue = {}
|
||||
end
|
||||
end
|
||||
|
||||
local r = execResults[argNum]
|
||||
execResults[argNum] = nil
|
||||
|
||||
return r
|
||||
end
|
||||
|
||||
function HandleResults(results)
|
||||
for k, v in pairs(results) do
|
||||
execResults[k] = v
|
||||
end
|
||||
|
||||
if coroutine.status(curRoutine) == 'dead' then
|
||||
return
|
||||
end
|
||||
|
||||
local success, err = coroutine.resume(curRoutine)
|
||||
|
||||
if success then
|
||||
SendEvents({ getSource = getSource })
|
||||
else
|
||||
print(err)
|
||||
end
|
||||
end
|
||||
|
||||
function SendEvents(env)
|
||||
TriggerClientEvent('svRpc:run', getSource(), 10, execQueue)
|
||||
end
|
||||
|
||||
function CallNative(hash, ...)
|
||||
local arguments = {}
|
||||
local returns = {}
|
||||
|
||||
local arg = {...}
|
||||
|
||||
for i, v in ipairs(arg) do
|
||||
local a = v
|
||||
|
||||
if type(v) == 'table' then
|
||||
if v._a then
|
||||
if v._a == '_i' or v._a == '_f' then
|
||||
a._i = execQueueArgNum
|
||||
execQueueArgNum = execQueueArgNum + 1
|
||||
|
||||
local fakeRetVal = {
|
||||
_a = '_z',
|
||||
_i = a._i
|
||||
}
|
||||
|
||||
-- this will only work in Lua 5.2+; as metamethod yielding got added there
|
||||
setmetatable(fakeRetVal, {
|
||||
__call = function()
|
||||
if not fakeRetVal._value then
|
||||
fakeRetVal._value = GetResult(fakeRetVal._i)
|
||||
end
|
||||
|
||||
return fakeRetVal._value
|
||||
end
|
||||
})
|
||||
|
||||
table.insert(returns, fakeRetVal)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(arguments, a)
|
||||
end
|
||||
|
||||
table.insert(execQueue, {
|
||||
h = hash,
|
||||
a = arguments
|
||||
})
|
||||
|
||||
return table.unpack(returns)
|
||||
end
|
||||
|
||||
function PrintStringWithLiteralString(...) return CallNative(0x3F89280B, ...) end
|
||||
function PrintStringWithLiteralStringNow(...) return CallNative(0xCA539D6, ...) end
|
||||
function GetCharCoordinates(...) return CallNative(0x2B5C06E6, ...) end
|
||||
function GetPlayerChar(...) return CallNative(0x511454A9, ...) end
|
Loading…
Reference in New Issue
Block a user