local allowed_latters = {[" "] = true, ["q"] = true, ["w"] = true, ["e"] = true, ["r"] = true, ["t"] = true, ["y"] = true, ["u"] = true, ["i"] = true, ["o"] = true, ["p"] = true, ["a"] = true, ["s"] = true, ["d"] = true, ["f"] = true, ["g"] = true, ["h"] = true, ["j"] = true, ["k"] = true, ["l"] = true, ["z"] = true, ["x"] = true, ["c"] = true, ["v"] = true, ["b"] = true, ["n"] = true, ["m"] = true}
local function format_name(str)
local formated = ""
for i = 1, string.len(str) do
local latter = string.sub( str, i, i )
formated = /*i == 1 and string.upper(latter) or*/ formated .. latter--string.lower(latter)
end
return formated
end
local function contains_unallowed_latter(str)
local toret = false
for i = 1, string.len(str) do
local latter = string.lower(string.sub( str, i, i ))
if not allowed_latters[latter] then toret = true break end
end
return toret
end
function rp.LoadPlayer(ply, cback)
MySQLite.query(("SELECT * FROM rp_players WHERE steamid = %s;"):format(MySQLite.SQLStr(ply:SteamID64())), function(data)
if not IsValid(ply) then return end
local _data = data and data[1] or {}
if not data then
MySQLite.query(([[
INSERT INTO rp_players(
steamid,
name,
gang,
gang_rank,
inventory,
inventory_bank,
accessories,
money_held,
money_bank,
last_seen,
total_time,
statistics
) VALUES (
%s, %s, NULL, NULL, %s, %s, %s, %d, %d, %d, %d, %s
);
]]):format(
ply:SteamID64(),
MySQLite.SQLStr(ply:SteamName()),
MySQLite.SQLStr("[]"),
MySQLite.SQLStr("[]"),
MySQLite.SQLStr("[]"),
rp.config.default_money,
rp.config.default_bank_money,
0,
0,
MySQLite.SQLStr("[]")
), nil, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
_data = {
steamid = ply:SteamID64(),
name = ply:SteamName(),
inventory = {},
inventory_bank = {},
accessories = {},
money_held = rp.config.default_money,
money_bank = rp.config.default_bank_money,
last_seen = 0,
total_time = 0,
statistics = {}
}
if rp.config.random_name then
local random_name = rp.names.Random()
ply:SetName(random_name)
_data.name = random_name
end
else
_data.inventory = util.JSONToTable(_data.inventory) or {}
_data.inventory_bank = util.JSONToTable(_data.inventory_bank) or {}
_data.accessories = util.JSONToTable(_data.accessories) or {}
end
if not _data.name then
local random_name = rp.names.Random()
ply:SetName(random_name)
_data.name = random_name
else
if #_data.name < 4 or #_data.name > 16 or contains_unallowed_latter(_data.name) then
local random_name = rp.names.Random()
ply:SetName(random_name)
_data.name = random_name
end
end
_data.money_held = tonumber(_data.money_held)
_data.money_bank = tonumber(_data.money_bank)
_data.last_seen = tonumber(_data.last_seen)
_data.total_time = tonumber(_data.total_time)
ply.inventory = _data.inventory
ply.bank = _data.inventory_bank
if not istable(_data.statistics) then
_data.statistics = util.JSONToTable(_data.statistics)
end
ply.statistics = _data.statistics
local inv_w = 0
for k,v in pairs(ply.inventory) do
inv_w = inv_w + v.weight
end
ply.items_weight = inv_w
local bank_w = 0
for k,v in pairs(ply.bank) do
bank_w = bank_w + v.weight
end
ply.banks_weight = bank_w
nw.WaitForPlayer(ply, function()
if _data.name and (_data.name ~= ply:SteamName()) then
ply:SetNetVar("rp.Name", _data.name)
end
ply:SetNetVar("rp.Money", _data.money_held or rp.config.default_money)
ply:SetNetVar("rp.BankMoney", _data.money_bank or rp.config.default_bank_money)
if _data.vk then
ply:SetNetVar("rp.VK", _data.vk)
end
if _data.discord then
ply:SetNetVar("rp.Discord", _data.discord)
end
if _data.gang then
ply:SetNetVar("rp.Gang", _data.gang)
end
ply:SetNetVar("rp.StartPlay", CurTime())
ply:SetNetVar("rp.TotalPlayed", _data.total_time)
ply:SetNetVar("rp.ItemsWeight", ply.items_weight)
ply:SetNetVar("rp.BankItemsWeight", ply.banks_weight)
ply:SetNetVar("rp.Accessories", _data.accessories)
ply:SetNetVar("rp.Name", _data.name)
ply.DataLoaded = true
ply:SetTeam(1)
ply:SetModel(team.GetModel(1))
hook.Call("PlayerLoadout", GAMEMODE, ply)
hook.Call("PlayerDataLoaded", GAMEMODE, ply, _data)
end)
end, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
MySQLite.query(("UPDATE rp_players SET money_held = %d WHERE money_held < 0;"):format(rp.config.default_money), nil, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
end
function rp.is_name_taken(name, func)
MySQLite.query(("SELECT * FROM rp_players WHERE name = %s LIMIT 1;"):format(
MySQLite.SQLStr(name)
), function(data)
func(istable(data))
end, function(e) rp.print_debug("MYSQL", e) end)
end
function GM:PlayerAuthed(ply)
rp.LoadPlayer(ply)
end
function PLAYER:SetName(name)
self:SetNetVar("rp.Name", name)
MySQLite.query(("UPDATE rp_players SET name = %s WHERE steamid = %s;"):format(MySQLite.SQLStr(name), self:SteamID64()), nil, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
end
function PLAYER:UpdateTime()
if not rp.IsLoaded(self) then return end
MySQLite.query(("UPDATE rp_players SET total_time = %d, last_seen = %d WHERE steamid = %s;"):format(self:GetTotalTime(), os.time(), self:SteamID64()), nil, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
end
function PLAYER:CanDropWeapon(weapon)
return GAMEMODE:CanDropWeapon(self, weapon)
end
function PLAYER:SetMaxArmor(v)
self:SetNetVar("rp.MaxArmor", v)
end
function PLAYER:GetStatistic(id)
return self.statistics[id]
end
function PLAYER:GetStatistics()
return self.statistics or {}
end
function PLAYER:SetStatistic(id, val)
self.statistics[id] = val
end
function PLAYER:UpdateStatistics()
if not rp.IsLoaded(self) then return end
MySQLite.query(("UPDATE rp_players SET statistics = %s WHERE steamid = %s;"):format(MySQLite.SQLStr(util.TableToJSON(self.statistics)), self:SteamID64()), nil, function(e) rp.print_debug(RED, "[MYSQL] ", e) end)
end
function rp.IsLoaded(ply)
if IsValid(ply) and (ply.DataLoaded ~= true) then
return false
end
return true
end
function PLAYER:DropRPWeapon(weapon)
local ammo = self:GetAmmoCount(weapon:GetPrimaryAmmoType())
self:DropWeapon(weapon) -- Drop it so the model isn't the viewmodel
local ent = ents.Create("spawned_weapon")
local model = (weapon:GetModel() == "models/weapons/v_physcannon.mdl" and "models/weapons/w_physics.mdl") or weapon:GetModel()
ent.ShareGravgun = true
ent:SetPos(self:GetShootPos() + self:GetAimVector() * 30)
ent:SetModel(model)
ent:SetSkin(weapon:GetSkin())
ent.weaponclass = weapon:GetClass()
ent.nodupe = true
ent.clip1 = weapon:Clip1()
ent.clip2 = weapon:Clip2() or -1
ent.ammoadd = ammo
self:RemoveAmmo(ammo, weapon:GetPrimaryAmmoType())
ent:Spawn()
weapon:Remove()
end
timer.Create("PlayerThink", 5, 0, function()
for k,v in ipairs(player.GetAll()) do
if not IsValid(v) then continue end
hook.Call("PlayerThink", GAMEMODE, v)
end
end)
hook.Add("PlayerShouldTaunt", "rp.player.PlayerShouldTaunt", function(ply, act)
if not ply:OnGround() then return false end
if ply:InVehicle() then return false end
if ply:GetMoveType() == MOVETYPE_NOCLIP then return false end
end)
function GM:PlayerStartTaunt(ply, act, l)
local last_move_type = ply:GetMoveType()
ply:SetMoveType(MOVETYPE_NONE)
ply:Timer("rp.player.Taunt", l, 1, function(p)
p:SetMoveType(last_move_type or MOVETYPE_WALK)
end)
end
rp.commands.register("rpname", USER_ACCESS, function(ply, args)
if ply.next_rpname_change and ply.next_rpname_change > CurTime() then
rp.notify(ply, NOTIFY_ERROR, 4, "Подождите немного перед повторной сменой имени!")
return
end
ply.next_rpname_change = CurTime() + 10
if not args[1] then
rp.notify(ply, NOTIFY_ERROR, 4, "Вы должны написать рп имя!")
return
end
local text = format_name(args[1])
if args[2] then
text = text .. " " .. format_name(args[2])
end
text = string.Trim( text )
if #text < 4 then
rp.notify(ply, NOTIFY_ERROR, 4, "RP имя не может быть меньше 4 символов!")
return
end
if #text > 16 then
rp.notify(ply, NOTIFY_ERROR, 4, "RP имя не может быть больше 16 символов!")
return
end
if contains_unallowed_latter(text) then
rp.notify(ply, NOTIFY_ERROR, 4, "RP имя может содержать только буквы английского алфавита!")
return
end
rp.is_name_taken(text, function(is_taken)
if not IsValid(ply) then return end
if is_taken then
rp.notify(ply, NOTIFY_ERROR, 4, "Это рп имя занято!")
return
end
rp.notify_all(NOTIFY_GENERIC, 4, ply:Name() .. " изменил имя на " .. text)
hook.Call("playerChangedRPName", nil, ply, ply:GetName(), text)
ply:SetName(text)
end)
end, {"name"})