--[[--------------------------------------------------------------------------- Functions ---------------------------------------------------------------------------]] local meta = FindMetaTable("Player") function meta:changeTeam(t, force, suppressNotification, ignoreMaxMembers) local prevTeam = self:Team() local notify = suppressNotification and fn.Id or DarkRP.notify local notifyAll = suppressNotification and fn.Id or DarkRP.notifyAll if self:isArrested() and not force then notify(self, 1, 4, DarkRP.getPhrase("unable", team.GetName(t), "")) return false end local allowed, time = self:changeAllowed(t) if t ~= GAMEMODE.DefaultTeam and not allowed and not force then local notif = time and DarkRP.getPhrase("have_to_wait", math.ceil(time), "/job, " .. DarkRP.getPhrase("banned_or_demoted")) or DarkRP.getPhrase("unable", team.GetName(t), DarkRP.getPhrase("banned_or_demoted")) notify(self, 1, 4, notif) return false end if self.LastJob and GAMEMODE.Config.changejobtime - (CurTime() - self.LastJob) >= 0 and not force then notify(self, 1, 4, DarkRP.getPhrase("have_to_wait", math.ceil(GAMEMODE.Config.changejobtime - (CurTime() - self.LastJob)), "/job")) return false end if self.IsBeingDemoted then self:teamBan() self.IsBeingDemoted = false self:changeTeam(GAMEMODE.DefaultTeam, true) DarkRP.destroyVotesWithEnt(self) notify(self, 1, 4, DarkRP.getPhrase("tried_to_avoid_demotion")) return false end if prevTeam == t then notify(self, 1, 4, DarkRP.getPhrase("unable", team.GetName(t), "")) return false end local TEAM = RPExtraTeams[t] if not TEAM then return false end if TEAM.customCheck and not TEAM.customCheck(self) and (not force or force and not GAMEMODE.Config.adminBypassJobRestrictions) then local message = isfunction(TEAM.CustomCheckFailMsg) and TEAM.CustomCheckFailMsg(self, TEAM) or TEAM.CustomCheckFailMsg or DarkRP.getPhrase("unable", team.GetName(t), "") notify(self, 1, 4, message) return false end if not force then if isnumber(TEAM.NeedToChangeFrom) and prevTeam ~= TEAM.NeedToChangeFrom then notify(self, 1,4, DarkRP.getPhrase("need_to_be_before", team.GetName(TEAM.NeedToChangeFrom), TEAM.name)) return false elseif istable(TEAM.NeedToChangeFrom) and not table.HasValue(TEAM.NeedToChangeFrom, prevTeam) then local teamnames = "" for _, b in pairs(TEAM.NeedToChangeFrom) do teamnames = teamnames .. " or " .. team.GetName(b) end notify(self, 1, 8, DarkRP.getPhrase("need_to_be_before", string.sub(teamnames, 5), TEAM.name)) return false end local max = TEAM.max local numPlayers = team.NumPlayers(t) if not ignoreMaxMembers and max ~= 0 and -- No limit (max >= 1 and numPlayers >= max or -- absolute maximum max < 1 and (numPlayers + 1) / player.GetCount() > max) then -- fractional limit (in percentages) notify(self, 1, 4, DarkRP.getPhrase("team_limit_reached", TEAM.name)) return false end end if TEAM.PlayerChangeTeam then local val = TEAM.PlayerChangeTeam(self, prevTeam, t) if val ~= nil then return val end end local hookValue, reason = hook.Call("playerCanChangeTeam", nil, self, t, force) if hookValue == false then if reason then notify(self, 1, 4, reason) end return false end local isMayor = RPExtraTeams[prevTeam] and RPExtraTeams[prevTeam].mayor if isMayor and GetGlobalBool("DarkRP_LockDown") then DarkRP.unLockdown(self) end self:updateJob(TEAM.name) self:setSelfDarkRPVar("salary", TEAM.salary) notifyAll(0, 4, DarkRP.getPhrase("job_has_become", self:Nick(), TEAM.name)) if self:getDarkRPVar("HasGunlicense") and GAMEMODE.Config.revokeLicenseOnJobChange then self:setDarkRPVar("HasGunlicense", nil) end if TEAM.hasLicense then self:setDarkRPVar("HasGunlicense", true) end self.LastJob = CurTime() if GAMEMODE.Config.removeclassitems then -- Must not be ipairs, DarkRPEntities might have missing keys when -- DarkRP.removeEntity is called. for _, v in pairs(DarkRPEntities) do if GAMEMODE.Config.preventClassItemRemoval[v.ent] then continue end if not v.allowed then continue end if istable(v.allowed) and (table.HasValue(v.allowed, t) or not table.HasValue(v.allowed, prevTeam)) then continue end for _, e in ipairs(ents.FindByClass(v.ent)) do if e.SID == self.SID then e:Remove() end end end if not GAMEMODE.Config.preventClassItemRemoval["spawned_shipment"] then for _, v in ipairs(ents.FindByClass("spawned_shipment")) do if v.allowed and istable(v.allowed) and table.HasValue(v.allowed, t) then continue end if v.SID == self.SID then v:Remove() end end end end if isMayor then for _, ent in ipairs(self.lawboards or {}) do if IsValid(ent) then ent:Remove() end end self.lawboards = {} end if isMayor and GAMEMODE.Config.shouldResetLaws then DarkRP.resetLaws() end local DoEffect = false self:SetTeam(t) hook.Call("OnPlayerChangedTeam", GAMEMODE, self, prevTeam, t) DarkRP.log(self:Nick() .. " (" .. self:SteamID() .. ") changed to " .. team.GetName(t), nil, Color(100, 0, 255)) if self:InVehicle() then self:ExitVehicle() end if GAMEMODE.Config.norespawn and self:Alive() then if GAMEMODE.Config.keepPickedUp then for k, v in ipairs(RPExtraTeams[prevTeam].weapons) do self:StripWeapon(v) end else self:StripWeapons() self:RemoveAllAmmo() end DoEffect = true player_manager.SetPlayerClass(self, TEAM.playerClass or "player_darkrp") self:applyPlayerClassVars(false) gamemode.Call("PlayerSetModel", self) gamemode.Call("PlayerLoadout", self) else if GAMEMODE.Config.instantjob then DoEffect = true self:StripWeapons() self:RemoveAllAmmo() self:Spawn() else self:KillSilent() end end if DoEffect then local vPoint = self:GetShootPos() + Vector(0,0,50) local effectdata = EffectData() effectdata:SetEntity(self) effectdata:SetStart(vPoint) -- Not sure if we need a start and origin (endpoint) for this effect, but whatever effectdata:SetOrigin(vPoint) effectdata:SetScale(1) util.Effect("entity_remove", effectdata) end umsg.Start("OnChangedTeam", self) umsg.Short(prevTeam) umsg.Short(t) umsg.End() return true end function meta:updateJob(job) self:setDarkRPVar("job", job) self.LastJob = CurTime() local timerid = self:SteamID64() .. "jobtimer" timer.Create(timerid, GAMEMODE.Config.paydelay, 0, function() if not IsValid(self) then timer.Remove(timerid) return end self:payDay() end) end function meta:teamUnBan(Team) self.bannedfrom = self.bannedfrom or {} local group = DarkRP.getDemoteGroup(Team) self.bannedfrom[group] = nil end function meta:teamBan(t, time) if not self.bannedfrom then self.bannedfrom = {} end t = t or self:Team() local group = DarkRP.getDemoteGroup(t) self.bannedfrom[group] = true local timerid = "teamban" .. self:UserID() .. "," .. group.value timer.Remove(timerid) if time == 0 then return end timer.Create(timerid, time or GAMEMODE.Config.demotetime, 1, function() if not IsValid(self) then return end self:teamUnBan(t) end) end function meta:teamBanTimeLeft(t) local group = DarkRP.getDemoteGroup(t or self:Team()) return timer.TimeLeft("teamban" .. self:UserID() .. "," .. (group and group.value or "")) end function meta:changeAllowed(t) local group = DarkRP.getDemoteGroup(t) if self.bannedfrom and self.bannedfrom[group] then return false, self:teamBanTimeLeft(t) end return true end function GM:canChangeJob(ply, args) if ply:isArrested() then return false end if ply.LastJob and 10 - (CurTime() - ply.LastJob) >= 0 then return false, DarkRP.getPhrase("have_to_wait", math.ceil(10 - (CurTime() - ply.LastJob)), "/job") end if not ply:Alive() then return false end local len = string.len(args) if len < 3 then return false, DarkRP.getPhrase("unable", "/job", ">2") end if len > 25 then return false, DarkRP.getPhrase("unable", "/job", "<26") end return true end --[[--------------------------------------------------------------------------- Commands ---------------------------------------------------------------------------]] local function ChangeJob(ply, args) if args == "" then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), "")) return "" end if not GAMEMODE.Config.customjobs then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("disabled", "/job", "")) return "" end local canChangeJob, message, replace = gamemode.Call("canChangeJob", ply, args) if canChangeJob == false then DarkRP.notify(ply, 1, 4, message or DarkRP.getPhrase("unable", "/job", "")) return "" end local job = replace or args DarkRP.notifyAll(2, 4, DarkRP.getPhrase("job_has_become", ply:Nick(), job)) ply:updateJob(job) return "" end DarkRP.defineChatCommand("job", ChangeJob) local function FinishDemote(vote, choice) local target = vote.target target.IsBeingDemoted = nil if choice == 1 then target:teamBan() if target:Alive() then local demoteTeam = hook.Call("demoteTeam", nil, target) or GAMEMODE.DefaultTeam target:changeTeam(demoteTeam, true) if target:isArrested() then target:arrest() end else target.demotedWhileDead = true end hook.Call("onPlayerDemoted", nil, vote.info.source, target, vote.info.reason) DarkRP.notifyAll(0, 4, DarkRP.getPhrase("demoted", target:Nick())) else DarkRP.notifyAll(1, 4, DarkRP.getPhrase("demoted_not", target:Nick())) end end local function Demote(ply, args) if #args == 0 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", "/demote", "")) return "" end if #args == 1 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("vote_specify_reason")) return "" end local reason = table.concat(args, ' ', 2) if string.len(reason) > 99 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", "/demote", "<100")) return "" end local p = DarkRP.findPlayer(args[1]) if p == ply then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("cant_demote_self")) return "" end local canDemote, message = hook.Call("canDemote", GAMEMODE, ply, p, reason) if canDemote == false then DarkRP.notify(ply, 1, 4, message or DarkRP.getPhrase("unable", "/demote", "")) return "" end if not p then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", args and args[1])) return "" end if CurTime() - ply.LastVoteCop < 80 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("have_to_wait", math.ceil(80 - (CurTime() - ply:GetTable().LastVoteCop)), "/demote")) return "" end local Team = p:Team() if not RPExtraTeams[Team] or RPExtraTeams[Team].candemote == false then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", "/demote", "")) else DarkRP.talkToPerson(p, team.GetColor(ply:Team()), DarkRP.getPhrase("demote") .. " " .. ply:Nick(), Color(255, 0, 0, 255), DarkRP.getPhrase("i_want_to_demote_you", reason), p) local voteInfo = DarkRP.createVote(p:Nick() .. ":\n" .. DarkRP.getPhrase("demote_vote_text", reason), DarkRP.getPhrase("demote_vote"), p, 20, FinishDemote, { [p] = true, [ply] = true }, function(vote) if not IsValid(vote.target) then return end vote.target.IsBeingDemoted = nil end, { source = ply, reason = reason }) if voteInfo then -- Vote has started DarkRP.notifyAll(0, 4, DarkRP.getPhrase("demote_vote_started", ply:Nick(), p:Nick())) DarkRP.log(DarkRP.getPhrase("demote_vote_started", string.format("%s(%s)[%s]", ply:Nick(), ply:SteamID(), team.GetName(ply:Team())), string.format("%s(%s)[%s] for %s", p:Nick(), p:SteamID(), team.GetName(p:Team()), reason)), Color(255, 128, 255, 255)) p.IsBeingDemoted = true end ply.LastVoteCop = CurTime() end return "" end DarkRP.defineChatCommand("demote", Demote) local function ExecSwitchJob(answer, ent, ply, target) if not IsValid(ply) or not IsValid(target) then return end ply.RequestedJobSwitch = nil if not tobool(answer) then return end local Pteam = ply:Team() local Tteam = target:Team() if not ply:changeTeam(Tteam, nil, nil, true) then return end if not target:changeTeam(Pteam, nil, nil, true) then ply:changeTeam(Pteam, true) -- revert job change return end DarkRP.notify(ply, 2, 4, DarkRP.getPhrase("job_switch")) DarkRP.notify(target, 2, 4, DarkRP.getPhrase("job_switch")) end local function SwitchJob(ply) --Idea by Godness. if not GAMEMODE.Config.allowjobswitch then return "" end if ply.RequestedJobSwitch then return end local eyetrace = ply:GetEyeTrace() local ent = eyetrace.Entity if not IsValid(ent) or not ent:IsPlayer() then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", DarkRP.getPhrase("switch_jobs"), "")) return "" end local team1 = RPExtraTeams[ply:Team()] local team2 = RPExtraTeams[ent:Team()] if not team1 or not team2 then return "" end if team1 == team2 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", DarkRP.getPhrase("switch_jobs"), "")) return "" end if team1.customCheck and not team1.customCheck(ent) or team2.customCheck and not team2.customCheck(ply) then -- notify only the player trying to switch DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", DarkRP.getPhrase("switch_jobs"), "")) return "" end ply.RequestedJobSwitch = true DarkRP.createQuestion(DarkRP.getPhrase("job_switch_question", ply:Nick()), "switchjob" .. tostring(ply:EntIndex()), ent, 30, ExecSwitchJob, ply, ent) DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("job_switch_requested")) return "" end DarkRP.defineChatCommand("switchjob", SwitchJob) DarkRP.defineChatCommand("switchjobs", SwitchJob) DarkRP.defineChatCommand("jobswitch", SwitchJob) local function DoTeamBan(ply, args) local ent = args[1] local Team = args[2] if not Team then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), "")) return end local target = DarkRP.findPlayer(ent) if not target or not IsValid(target) then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", ent or "")) return end local found = false for k, v in pairs(RPExtraTeams) do if string.lower(v.name) == string.lower(Team) or string.lower(v.command) == string.lower(Team) or k == tonumber(Team or -1) then Team = k found = true break end end if not found then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", Team or "")) return end local time = tonumber(args[3] or 0) target:teamBan(tonumber(Team), time) local nick if ply:EntIndex() == 0 then nick = "Console" else nick = ply:Nick() end DarkRP.notifyAll(0, 5, DarkRP.getPhrase("x_teambanned_y_for_z", nick, target:Nick(), team.GetName(tonumber(Team)), time / 60)) end DarkRP.definePrivilegedChatCommand("teamban", "DarkRP_AdminCommands", DoTeamBan) local function DoTeamUnBan(ply, args) if #args < 2 then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), "")) return end local ent = args[1] local Team = args[2] local target = DarkRP.findPlayer(ent) if not target then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", ent or "")) return end local found = false for k, v in pairs(RPExtraTeams) do if string.lower(v.name) == string.lower(Team) or string.lower(v.command) == string.lower(Team) then Team = k found = true break end if k == tonumber(Team or -1) then found = true break end end if not found then DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", Team or "")) return end target:teamUnBan(tonumber(Team)) local nick if ply:EntIndex() == 0 then nick = "Console" else nick = ply:Nick() end DarkRP.notifyAll(0, 5, DarkRP.getPhrase("x_teamunbanned_y", nick, target:Nick(), team.GetName(tonumber(Team)))) end DarkRP.definePrivilegedChatCommand("teamunban", "DarkRP_AdminCommands", DoTeamUnBan)