Created
April 7, 2022 01:30
-
-
Save Elmuti/cd31468d074f5e6c0a71eb3c71455ab7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pcall(function() | |
game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.All, false) | |
game:GetService("StarterGui"):SetCore("TopbarEnabled", false) | |
end) | |
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter | |
local plabel = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("HUD"):WaitForChild("PingLabel") | |
local pingremote = game.ReplicatedStorage.Ping | |
local UseWeaponViewmodel = true | |
local ConsoleVisible = false | |
local hrpOffsetFromGround = 3 | |
local MOUSE_MIN, MOUSE_MAX = math.rad(-80), math.rad(80) --down angle, up angle | |
local mouseAngles = Vector2.new() | |
local bobtimer = 0 | |
local PlayerLatencies = {} | |
local PlayerData = {} | |
--contents really dont matter, list is replicated from server, its just nice to have this here on initialization if for some reason the replication does not happen before client cvar initialization | |
local ConVars = { | |
sv_cheats = {false, true, "Turns cheats on"}; | |
sv_gravity = {196.200, true, "World gravity", {-math.huge, math.huge}}; | |
sv_accelerate = {200, true, "Acceleration rate", {-math.huge, math.huge}}; | |
sv_airaccelerate = {5, true, "Air acceleration rate", {-math.huge, math.huge}}; | |
sv_max_velocity_ground = {200, true, "Maximum velocity on the ground", {-math.huge, math.huge}}; | |
sv_max_velocity_air = {1350, true, "Maximum velocity in the air", {-math.huge, math.huge}}; | |
sv_friction = {7.5, true, "Amount of friction on surfaces", {-math.huge, math.huge}}; | |
sv_motd = {"", true, "Server message of the day"}; | |
sv_currentmap = {"", true, ""}; | |
mp_startingweapon = {"Machinegun", true, ""}; | |
mp_damagemult = {1, true, "Global damage multiplier", {0, 1000}}; | |
mp_gamemode = {"Deathmatch", true, "The current gamemode"}; | |
mp_dm_fraglimit = {10, true, "The frag limit to win the game", {1, math.huge}}; | |
mp_dm_timelimit = {300, true, "The time limit of the game", {1, math.huge}}; | |
mp_ctf_capturelimit = {5, true, "Flag capture limit", {1, math.huge}}; | |
cl_thirdperson = {false, true, "Third person camera toggle"}; | |
cl_autoswitch = {true, false, "Toggles auto-switching to picked up weapons"}; | |
cl_violence = {true, false, "Toggles blood and gore"}; | |
cl_shellfadetime = {0.75, false, "", {0, 10}}; | |
cl_chat_message_displaytime = {4.5, false, "Seconds to display a new chat message for", {0, 60}}; | |
cl_chathistorylength = {5, false, "", {1, 20}}; | |
cl_crosshairsize = {10, false, "", {-100, 100}}; | |
cl_crosshairgap = {2.5, false, "", {-100, 100}}; | |
cl_crosshairalpha = {255, false, "", {0, 255}}; | |
cl_footsteps = {true, false, "Toggles footstep sounds"}; | |
cl_drawping = {false, false, "Toggles ping counter"}; | |
cl_muzzleflash = {true, false, ""}; | |
cl_weaponbob_rate = {1, false, "Weapon bob animation frequency multiplier", {0, 2}}; | |
cl_weaponbob_amt = {1, false, "Weapon bob animation range multiplier", {0, 2}}; | |
cl_fov = {75, false, "", {20, 90}}; | |
cl_zoomfov = {20, false, "", {20, 90}}; | |
cl_sensitivity = {0.15, false, "Mouse sensitivity multiplier", {0, 100}}; | |
cl_zoomsensitivity = {0.85, false, "Mouse sensitivity multiplier", {0, 100}}; | |
cl_camera_orbit = {false, true, ""}; | |
cl_camera_orbit_offset = {6, true, ""}; | |
} | |
local Developers = {"StealthKing95", "Player1"} | |
function IsDeveloper(plr) | |
for _, dev in pairs(Developers) do | |
if plr == dev then | |
return true | |
end | |
end | |
return false | |
end | |
local StopTweens = false | |
local scoreboardCanBeToggled = true | |
local currentCmdIndex = 0 | |
local thirdpersonangle = 0 | |
local thirdpersonRotSpeed = 45 | |
local thirdperson = false | |
local prevCamCF = CFrame.new() | |
local actualMouseHit = Vector3.new() | |
local accelDir = Vector3.new() | |
local playerVelocity = Vector3.new() | |
local prevVelocity = Vector3.new() | |
local pushVector = Vector3.new() | |
local movementKeysDown = {W = false; A = false; S = false; D = false; Space = false;} | |
local RAYMDL | |
local jumpedOnPrevFrame = false | |
local barrierUp = false | |
local charInvisible = false | |
local respawning = false | |
local events = game.ReplicatedStorage | |
local player = game.Players.LocalPlayer | |
local char = player.Character or player.CharacterAdded:wait() | |
local torso = char:WaitForChild("HumanoidRootPart") | |
local cam = workspace.CurrentCamera | |
local mouse = player:GetMouse() | |
mouse.Icon = "rbxassetid://810062788"--http://www.roblox.com/asset/?id=810062788 | |
local pickups = workspace.ItemPickups:GetChildren() | |
local clouds | |
local latency = 0 | |
local CurrentSituation = "" | |
local PrevSituation = "" | |
local Orakel = require(game.ReplicatedStorage.Orakel.Main) | |
local mathLib = Orakel.LoadModule("MathLib") | |
local sndLib = Orakel.LoadModule("SoundLib") | |
local assetLib = Orakel.LoadModule("AssetLib") | |
local npcLib = Orakel.LoadModule("NpcLib") | |
local tLib = Orakel.LoadModule("CFrameLib") | |
local weaponData = {} | |
local lastHurtSound = tick() | |
local ClientTime = 0 | |
local canwalk = true | |
local VelOffset = Vector3.new() | |
local PlayerModels = {} | |
local canfire = true | |
local itemFloatHeight = 0.01 | |
local equippedWeapon | |
local weaponCode | |
local firingWeapon = false | |
local lastShotFired = tick() | |
local chatlog = {} | |
local chatVisible = false | |
local AbilityIsInCooldown = false | |
local PlayerStats = { | |
Weapons = { | |
Machinegun = {Ammo = 150; MaxAmmo = 150; Owned = true;}; | |
Shotgun = {Ammo = 25; MaxAmmo = 25; Owned = false;}; | |
Grenade = {Ammo = 25; MaxAmmo = 25; Owned = false;}; | |
RocketLauncher = {Ammo = 25; MaxAmmo = 25; Owned = false;}; | |
LightningGun = {Ammo = 150; MaxAmmo = 150; Owned = false;}; | |
Railgun = {Ammo = 25; MaxAmmo = 25; Owned = false;}; | |
PlasmaGun = {Ammo = 150; MaxAmmo = 150; Owned = false;}; | |
}; | |
Health = 100; | |
MaxHealth = 100; | |
Armor = 15; | |
MaxArmor = 100; | |
} | |
local WeaponIndexes = { | |
"Machinegun"; | |
"Shotgun"; | |
"Grenade"; | |
"RocketLauncher"; | |
"LightningGun"; | |
"Railgun"; | |
"PlasmaGun"; | |
} | |
local PreviousCmds = {} | |
local conMsg = {} | |
local conMsgYMax = 2 | |
local conMsgY = 0 | |
local Aliases = { | |
clr = "clear"; | |
quti = "quit"; | |
qq = "quit"; | |
cls = "close"; | |
exit = "close"; | |
cleardecals = "r_cleardecals"; | |
suicide = "kill"; | |
memory = "memory_details"; | |
getmem = "memory_details"; | |
cl_mem = "memory_details"; | |
} | |
local ConCmd = { | |
clear = {"Clears the console window", function() | |
player.PlayerGui.HUD.Console.Output:ClearAllChildren() | |
conMsgY = 0 | |
conMsg = {} | |
end}; | |
quit = {"Exits the game", function() | |
Orakel.Log("Please remind the developer to finish this command", "Warning") | |
end}; | |
kill = {"Commit suicide", function() | |
TakeDamage(90000, "Server") | |
Orakel.Log(player.Name.. " killed by server.") | |
end}; | |
close = {"Closes the console", function() | |
ConsoleVisible = false | |
player.PlayerGui.HUD.Console.Visible = false | |
end}; | |
endgame = {"End the current round", function() | |
Orakel.Log("Not currently functional!") | |
end}; | |
players = {"Lists current players", function() | |
for i, plr in pairs(game.Players:GetPlayers()) do | |
Orakel.Log("#"..i..": "..plr.Name.." "..plr.UserId) | |
end | |
end}; | |
r_cleardecals = {"Clear world decals", function() | |
npcLib.ClearDecals() | |
end}; | |
convars = {"Lists all convars", function() | |
for convar, data in pairs(ConVars) do | |
if data[3] ~= nil and data[3] ~= "" then | |
Orakel.Log(convar.." = "..tostring(data[1]).." -> "..data[3]) | |
else | |
Orakel.Log(convar.." = "..tostring(data[1])) | |
end | |
end | |
end}; | |
help = {"Gives you instructions", function() | |
Orakel.Log('To change ConVars(console variables) or call console commands, the syntax is as follows:\n\nChanging a ConVar:\n<convar> <value>\n\nCalling a command:\n<command> <value>\n^ where value might be optional depending on the command.\n\nTo get a list of ConVars, type "convars"\nTo get a list of commands, type "commands"\n\nTo get information about a specific ConVar or command,\njust type the name of the it.\nYou can write multiple commands in one go by separating them with a semicolon(;)') | |
end}; | |
aliases = {"Lists all set aliases", function() | |
for alias, cmd in pairs(Aliases) do | |
Orakel.Log(alias .. " -> alias for " .. cmd) | |
end | |
end}; | |
memory_details = {"Get detailed information on memory usage", function() | |
local memoryReportFormat = "\t%s - %.3f MBs" | |
for i,memoryTag in ipairs(Enum.DeveloperMemoryTag:GetEnumItems()) do | |
local consumption = game:GetService("Stats"):GetMemoryUsageMbForTag(memoryTag) | |
if consumption > 10 then | |
Orakel.Log(memoryReportFormat:format(memoryTag.Name, consumption), "Error") | |
else | |
Orakel.Log(memoryReportFormat:format(memoryTag.Name, consumption), "Warning") | |
end | |
end | |
end}; | |
status = {"", function() | |
Orakel.Log("hostname : "..ConVars["sv_motd"][1]) | |
Orakel.Log("version : "..Orakel.Configuration.Version) | |
Orakel.Log("type : ".."community_public") | |
Orakel.Log("map : "..ConVars["sv_currentmap"][1]) | |
Orakel.Log("players : "..(#game.Players:GetPlayers()).." / "..game.Players.MaxPlayers.."\n\n") | |
Orakel.Log("# userid name ping state") | |
for i, plr in pairs(game.Players:GetPlayers()) do | |
Orakel.Log("# "..plr.UserId.." "..plr.Name.." "..PlayerLatencies[plr.UserId].."ms ".."active") | |
end | |
Orakel.Log("#end players") | |
end}; | |
} | |
function IsConvar(str) | |
for cvar, data in pairs(ConVars) do | |
if cvar == str then | |
return true | |
end | |
end | |
return false | |
end | |
function IsCmd(str) | |
for cmd, data in pairs(ConCmd) do | |
if cmd == str then | |
return true | |
end | |
end | |
return false | |
end | |
function IsAlias(str) | |
for alias, cmd in pairs(Aliases) do | |
if str == alias then | |
return true | |
end | |
end | |
return false | |
end | |
function TweenCallback() | |
return StopTweens | |
end | |
function ParseConvar(cmd, val) | |
--Orakel.Log("Parsing convar '"..cmd.."' '"..val.."'") | |
if (ConVars[cmd] == nil) and (val == nil or val == "") then | |
Orakel.Log('Unknown command "'..cmd..'"', "Warning") | |
return | |
else | |
if ConVars[cmd] ~= nil then | |
--GAVE CONVAR BUT NO VALUE | |
if val == nil or val == "" then | |
--Specify range if defined | |
if ConVars[cmd][4] ~= nil then | |
Orakel.Log(cmd.." = '"..tostring(ConVars[cmd][1]).."' - "..ConVars[cmd][3]..', Usage: "'..cmd..' <'..type(ConVars[cmd][1])..'>", Range: ['..ConVars[cmd][4][1]..' - '..ConVars[cmd][4][2]..']') | |
else | |
Orakel.Log(cmd.." = '"..tostring(ConVars[cmd][1]).."' - "..ConVars[cmd][3]..', Usage: "'..cmd..' <'..type(ConVars[cmd][1])..'>"') | |
end | |
else | |
local isServerCvar = (cmd:sub(1, 2) == "sv") or (cmd:sub(1, 2) == "mp") | |
local valn = tonumber(val) | |
--VALUE IS BOOLEAN | |
if type(ConVars[cmd][1]) == "bool" and valn == 1 or valn == 0 then | |
if valn == 1 then | |
--Orakel.Log(">"..cmd.." "..valn) | |
if isServerCvar then | |
local wasValid = events.AttemptCommandServer:InvokeServer(cmd, 1) | |
if not wasValid then | |
Orakel.Log("Can't change replicated ConVar "..cmd.." from console of client, only server operator can change its value", "Warning") | |
end | |
else | |
ConVars[cmd][1] = true | |
end | |
elseif valn == 0 then | |
--Orakel.Log(">"..cmd.." "..valn) | |
if isServerCvar then | |
local wasValid = events.AttemptCommandServer:InvokeServer(cmd, 0) | |
if not wasValid then | |
Orakel.Log("Can't change replicated ConVar "..cmd.." from console of client, only server operator can change its value", "Warning") | |
end | |
else | |
ConVars[cmd][1] = false | |
end | |
else | |
Orakel.Log("'"..cmd.."' is not a boolean", "Error") | |
end | |
--VALUE IS STRING | |
elseif type(ConVars[cmd][1]) == "string" then | |
--Orakel.Log(">"..cmd.." "..val) | |
if isServerCvar then | |
local wasValid = events.AttemptCommandServer:InvokeServer(cmd, val) | |
if not wasValid then | |
Orakel.Log("Can't change replicated ConVar "..cmd.." from console of client, only server operator can change its value", "Warning") | |
end | |
else | |
ConVars[cmd][1] = val | |
end | |
--VALUE IS NUMBER | |
else | |
if valn ~= nil then | |
--Orakel.Log(">"..cmd.." "..valn) | |
if isServerCvar then | |
if ConVars[cmd][4] ~= nil then | |
valn = math.clamp(val, ConVars[cmd][4][1], ConVars[cmd][4][2]) | |
end | |
local wasValid = events.AttemptCommandServer:InvokeServer(cmd, valn) | |
if not wasValid then | |
Orakel.Log("Can't change replicated ConVar "..cmd.." from console of client, only server operator can change its value", "Warning") | |
end | |
else | |
if ConVars[cmd][4] ~= nil then | |
val = math.clamp(valn, ConVars[cmd][4][1], ConVars[cmd][4][2]) | |
end | |
ConVars[cmd][1] = valn | |
end | |
else | |
Orakel.Log("'"..tostring(val).."' is an invalid parameter for "..cmd, "Error") | |
end | |
end | |
end | |
else | |
--CONVAR DOESNT EXIST | |
Orakel.Log("Unknown convar '"..cmd.."'", "Warning") | |
end | |
end | |
end | |
function ParseCommandLine(line) | |
Orakel.Log(">"..line, "Deprecated") | |
local pattern = "" | |
local patternLine = '([%w%p]+)%s*;*(%-*%w*%.*%w*);*%s*' | |
local patternAlias = '([%w%p]+)%s*;*(%-*%w*%.*%w*);*%s*"*([%w%p]*)"*;*%s*' | |
local currentPattern = patternLine | |
if line:find("alias") then | |
currentPattern = patternAlias | |
end | |
for cmd, val, val2 in line:gmatch(currentPattern) do | |
if cmd == "alias" and type(val) == "string" and val ~= "" and val2 ~= nil then | |
local alias = val | |
local aliasCmd = val2 | |
if IsConvar(aliasCmd) or IsCmd(aliasCmd) then | |
Orakel.Log("Created alias '"..alias.."' for '"..aliasCmd.."'", "Deprecated") | |
Aliases[alias] = aliasCmd | |
else | |
Orakel.Log("No such command or convar as '"..aliasCmd.."' exists!", "Warning") | |
end | |
return | |
elseif cmd == "alias" and (type(val) ~= "string" or val == "") then | |
Orakel.Log("Cannot create an alias for an invalid command/convar", "Warning") | |
return | |
end | |
--List commands | |
if cmd == "commands" then | |
for cmd, data in pairs(ConCmd) do | |
Orakel.Log(cmd.." = "..data[1]) | |
end | |
return | |
--ConCmd | |
elseif IsCmd(cmd) then | |
ConCmd[cmd][2]() | |
return | |
--Alias | |
elseif IsAlias(cmd) then | |
local cmd = Aliases[cmd] | |
if IsCmd(cmd) then | |
ConCmd[cmd][2]() | |
return | |
--elseif IsConvar(cmd) then | |
--ParseConvar(cmd, val) | |
end | |
end | |
--ConVar | |
ParseConvar(cmd, val) | |
end | |
end | |
function GetNewlineAmt(str) | |
local _, count = str:gsub('\n', '\n') | |
return count | |
end | |
function GetOldestConMsg() | |
local oldest = conMsg[1] | |
local lasti = 0 | |
if #conMsg > 1 then | |
for i = 2, #conMsg do | |
local current = conMsg[i] | |
if current.Time < oldest.Time then | |
oldest = current | |
lasti = i | |
end | |
end | |
end | |
return oldest, lasti | |
end | |
function AddConMessage(msg, color) | |
local m = Instance.new("TextLabel") | |
m.BackgroundTransparency = 1 | |
m.TextColor3 = color | |
m.TextXAlignment = Enum.TextXAlignment.Left | |
m.TextYAlignment = Enum.TextYAlignment.Top | |
m.TextSize = 14 | |
m.Font = Enum.Font.Code | |
m.Size = UDim2.new(1, 0, 0.015, 0) | |
m.Position = UDim2.new(0, 0, conMsgY, 0) | |
m.Text = msg | |
m.TextWrapped = true | |
--m.Rotation = 180 | |
m.Parent = player.PlayerGui.HUD.Console.Output | |
table.insert(conMsg, {Label = m, Time = ClientTime}) | |
while not m.TextFits do | |
m.Size = m.Size + UDim2.new(0, 0, 0.015, 0) | |
end | |
conMsgY = conMsgY + m.Size.Y.Scale | |
--print(msg.."\nconMsgY: "..conMsgY.." SizeY: "..m.Size.Y.Scale.."\n"..string.rep("-", 36)) | |
end | |
function AddConMessaged(msg, color) | |
local m = Instance.new("TextLabel") | |
m.BackgroundTransparency = 1 | |
m.TextColor3 = color | |
m.TextXAlignment = Enum.TextXAlignment.Left | |
m.TextYAlignment = Enum.TextYAlignment.Top | |
m.TextSize = 14 | |
m.Font = Enum.Font.Code | |
m.Size = UDim2.new(1, 0, 0.015, 0) | |
m.Position = UDim2.new(0, 0, conMsgY, 0) | |
m.Text = msg | |
m.Parent = player.PlayerGui.HUD.Console.Output | |
table.insert(conMsg, {Label = m, Time = ClientTime}) | |
local textSize = game:GetService("TextService"):GetTextSize(msg, m.TextSize, m.Font, m.AbsoluteSize) | |
local textWidth = textSize.X | |
local textHeight = textSize.Y | |
--The Y-axis message size multiplier, takes into account if text doesnt fit: | |
local numNewlines = (textWidth / (player.PlayerGui.HUD.Console.Output.AbsoluteSize.X - 10)) + GetNewlineAmt(msg) -- + (textHeight / m.TextSize) | |
print("textWidth: "..textWidth.." numNewlines: "..numNewlines.. " conMsgY: "..conMsgY) | |
if numNewlines >= 1 then | |
m.TextWrapped = true | |
--If this new message exceeds the Y-limit of the ScrollingFrame, cut old entries | |
if conMsgY + (0.015 * math.floor(numNewlines)) >= conMsgYMax then | |
print("new message exceeds the Y-limit of the ScrollingFrame, cutting old entries") | |
local overkill = (0.015 * math.floor(numNewlines)) | |
--remove oldest messages by overkill | |
local overkillYAchieved = 0 | |
while overkillYAchieved < overkill do | |
local oldest, index = GetOldestConMsg() | |
overkillYAchieved = overkillYAchieved + oldest.Label.AbsoluteSize.Y | |
end | |
--move all current messages up by overkillYAchieved | |
for i, msg in pairs(conMsg) do | |
msg.Label.Position = msg.Label.Position - UDim2.new(0, 0, 0, overkillYAchieved) | |
end | |
end | |
conMsgY = conMsgY + 0.015 * math.floor(numNewlines) | |
m.Size = UDim2.new(1, 0, conMsgY, 0) | |
else | |
conMsgY = conMsgY + 0.015 | |
end | |
end | |
function DrawLineDebug(a, b) | |
local beam = Instance.new("Part") | |
beam.Name = "BEAM" | |
beam.BrickColor = BrickColor.new("Bright red") | |
beam.Material = Enum.Material.Neon | |
beam.Transparency = 0 | |
beam.Anchored = true | |
beam.CanCollide = false | |
local distance = (a - b).magnitude | |
beam.Size = Vector3.new(0.3, 0.3, distance) | |
beam.CFrame = CFrame.new(a, b) * CFrame.new(0, 0, -distance / 2) | |
beam.Parent = workspace.Ignore | |
--game:GetService("Debris"):AddItem(beam, 0.08) | |
return beam | |
end | |
function GetWeaponIndex(wepname) | |
for i = 1, #WeaponIndexes do | |
if WeaponIndexes[i] == wepname then | |
return i | |
end | |
end | |
return 1 | |
end | |
function GetWeaponName(index) | |
if index > 7 then | |
return "Machinegun" | |
elseif index < 1 then | |
return "PlasmaGun" | |
end | |
for i = 1, #WeaponIndexes do | |
if i == index then | |
return WeaponIndexes[i] | |
end | |
end | |
return "Machinegun" | |
end | |
local CooldownReduction = 0 | |
function UseAbility() | |
local curAbility = "Ghostwalk" | |
local ability = require(game.ReplicatedStorage.Abilities[curAbility]) | |
if not AbilityIsInCooldown then | |
AbilityIsInCooldown = true | |
local frame = player.PlayerGui.HUD.SpecialAbility | |
frame.AbilityFrame.Image = "http://www.roblox.com/asset/?id=847342696" | |
frame.SkillIcon.Visible = false | |
frame.AbilityUseLabel.Visible = false | |
spawn(function() | |
ability.FireClient(player, equippedWeapon, cam.CFrame.p, mouse.Hit.p) | |
events.FireAbilityServer:FireServer(player, equippedWeapon.Name, cam.CFrame.p, mouse.Hit.p, curAbility) | |
end) | |
if ability.Duration then | |
local t = ability.Duration | |
frame.AbilityTimer.Text = mathLib.Round(t) | |
frame.AbilityTimer.Visible = true | |
while t > 0 do | |
local dt = wait() | |
t = t - dt | |
frame.AbilityTimer.Text = mathLib.Round(t, 1) | |
end | |
end | |
local t = ability.Cooldown | |
frame.AbilityTimer.Text = mathLib.Round(t) | |
frame.AbilityTimer.Visible = true | |
while t > 0 do | |
local dt = wait() | |
t = t - dt - CooldownReduction | |
CooldownReduction = 0 | |
if t < 10 then | |
frame.AbilityTimer.Text = mathLib.Round(t, 1) | |
else | |
frame.AbilityTimer.Text = mathLib.Round(t) | |
end | |
end | |
frame.AbilityFrame.Image = "rbxassetid://847342692" | |
frame.AbilityTimer.Visible = false | |
frame.SkillIcon.Visible = true | |
frame.AbilityUseLabel.Visible = true | |
AbilityIsInCooldown = false | |
CooldownReduction = 0 | |
end | |
end | |
function OtherPlayerDied(plr, killerweapon) | |
if ConVars["cl_violence"][1] then | |
--if killerweapon == "Railgun" or killerweapon == "RocketLauncher" or killerweapon == "Grenade" or killerweapon == "PlasmaGun" then | |
local char = workspace.Characters:FindFirstChild(plr.Name) | |
if char then | |
npcLib.CreateGoryCorpse(char:GetPrimaryPartCFrame(), playerVelocity, {char, workspace.Ignore, workspace.PlayerSpawns, workspace.ItemPickups, workspace.ItemSpawns, workspace.Nodes}) | |
end | |
--end | |
end | |
end | |
function UpdateJumpPadLogic(dt) | |
local vel = Vector3.new() | |
for _, pad in pairs(workspace.JumpPads:GetChildren()) do | |
if (pad.JumpPad.Position - char.PrimaryPart.Position).magnitude < 5 then | |
--playerVelocity = Vector3.new() | |
vel = pad.JumpPad.JumpVelocity.Value | |
sndLib.PlaySoundClient("global", "jumpPAD", "http://www.roblox.com/asset/?id=81116553", 0.3, 1, false, 1) | |
sndLib.PlaySoundOtherClients("3d", "jumpPAD", "http://www.roblox.com/asset/?id=81116553", 0.3, 1, false, pad.JumpPad) | |
end | |
end | |
VelOffset = vel | |
end | |
local lastFallDamage = tick() | |
local lastFallSound = tick() | |
function Grounded(dt) | |
local ray = Ray.new(char.PrimaryPart.Position, Vector3.new(0, -(math.max(hrpOffsetFromGround + 0.1, math.abs(playerVelocity.Y * dt))), 0)) | |
local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, {char, workspace.Ignore, workspace.PlayerSpawns, workspace.ItemPickups, workspace.ItemSpawns, workspace.Nodes}) | |
if hit then | |
char:SetPrimaryPartCFrame(CFrame.new(pos + Vector3.new(0, hrpOffsetFromGround, 0))) | |
--print(hit:GetFullName()) | |
local downvel = math.abs(playerVelocity.Y) | |
--print(downvel) | |
if downvel >= 20 and math.abs(tick() - lastFallSound) > 0.5 then | |
sndLib.PlaySoundClient("global", "fall", "rbxassetid://821077662", 0.3, 1, false, 1) | |
lastFallSound = tick() | |
end | |
if downvel >= 60 and math.abs(tick() - lastFallDamage) > 1 then | |
local falldmg = (downvel - 60) * 1.5 | |
TakeDamage(falldmg, "World") | |
if PlayerStats.Health <= 0 then | |
Orakel.Log(player.Name.. " got rekt by the cruel hard floor.") | |
end | |
lastFallDamage = tick() | |
end | |
return true | |
end | |
return false | |
end | |
function Accelerate(accelDir, prevVelocity, accelerate, max_velocity, dt, grounded) | |
local projVel = prevVelocity:Dot(accelDir) | |
local accelVel = accelerate * dt | |
--If necessary, truncate the accelerated velocity so the vector projection does not exceed max_velocity | |
if projVel + accelVel > max_velocity then | |
accelVel = max_velocity - projVel | |
end | |
return prevVelocity + accelDir * accelVel | |
end | |
function MoveGround(accelDir, prevVelocity, dt, grounded) | |
local speed = prevVelocity.magnitude | |
if speed ~= 0 then | |
local drop = speed * ConVars.sv_friction[1] * dt --calculate friction | |
prevVelocity = prevVelocity * math.max(speed - drop, 0) / speed --friction affects velocity | |
end | |
return Accelerate(accelDir, prevVelocity, ConVars.sv_accelerate[1], ConVars.sv_max_velocity_ground[1], dt, grounded) | |
end | |
function MoveAir(accelDir, prevVelocity, dt, grounded) | |
return Accelerate(accelDir, prevVelocity, ConVars.sv_airaccelerate[1], ConVars.sv_max_velocity_air[1], dt, grounded) | |
end | |
function SwitchWeapon(curwep, direction, indexOverride, playSound) | |
local playSound = playSound or true | |
if playSound then | |
sndLib.PlaySoundClient("global", "wep_switch", "rbxassetid://823816849", 0.15, 1, false, 2) | |
end | |
equippedWeapon:Destroy() | |
local curi = GetWeaponIndex(equippedWeapon.Name) | |
local newname = GetWeaponName(indexOverride or (curi + -(direction))) | |
local newGun = game.ReplicatedStorage.Models[newname]:Clone() | |
newGun.Parent = char | |
equippedWeapon = newGun | |
if weaponCode.StopFire ~= nil then | |
weaponCode.StopFire() | |
end | |
weaponCode.UnEquip() | |
weaponCode = weaponData[equippedWeapon.Name] | |
weaponCode.Equip() | |
for _, frame in pairs(player.PlayerGui.HUD.WeaponsFrame:GetChildren()) do | |
if frame.Name ~= newname then | |
frame.BackgroundTransparency = 1 | |
end | |
end | |
player.PlayerGui.HUD.WeaponsFrame[newname].BackgroundTransparency = 0.45 | |
end | |
function CreateViewmodel(char, mdl) | |
local mdl = mdl:Clone() | |
mdl.Name = "Viewmodel" | |
mdl.Parent = char | |
return mdl | |
end | |
function UpdatePlayerData(dt) | |
for _, plr in pairs(game.Players:GetPlayers()) do | |
spawn(function() | |
local s, e = pcall(function() | |
--local pos, mpos, yrot = events.GetPlayerLocation:InvokeServer(plr) | |
--local cwep = events.GetCurrentWeapon:InvokeServer(plr) | |
--local ghosting = events.GetPlayerGhosting:InvokeServer(plr) | |
--local bup = events.GetPlayerBarrier:InvokeServer(plr) | |
PlayerData[plr.Name] = events.GetPlayerData:InvokeServer(plr) | |
end) | |
if not s then | |
warn(e) | |
PlayerData[plr.Name] = {Position = Vector3.new(), MousePosition = Vector3.new(), YRot = CFrame.new(), Invisible = false, Barrier = false, CurrentWeapon = "Machinegun"} | |
end | |
end) | |
end | |
end | |
function CreatePlayerModel(originalPlayer) | |
local dir = workspace:FindFirstChild("Characters") or Instance.new("Model", workspace) | |
if dir.Name ~= "Characters" then dir.Name = "Characters" end | |
local char = game.ReplicatedStorage.Characters.PlayerModel:Clone() | |
char.Name = originalPlayer.Name | |
char["Left Arm"].Transparency = 1 | |
char["Right Arm"].Transparency = 1 | |
local charmdl = "Circuit" | |
for _, msh in pairs(game.ReplicatedStorage.Characters[charmdl]:GetChildren()) do | |
if msh.Name ~= "Head" then | |
local mc = msh:Clone() | |
mc.Parent = char | |
end | |
end | |
local arms = game.ReplicatedStorage.Characters.ArmsViewmodel:Clone() | |
arms.Parent = char | |
if player == originalPlayer then | |
for _, p in pairs(arms:GetChildren()) do | |
if p:IsA("BasePart") then | |
p.Transparency = 1 | |
end | |
end | |
end | |
char.Parent = dir | |
char:MakeJoints() | |
return char | |
end | |
function UpdatePlayermodels(dt) | |
--debug.profilebegin("UpdatePlayermodels") | |
--create default values if InvokeServer fails for some reason | |
local pos, mpos, yrot, ghosting, bup = Vector3.new(156, 3.5, -115), Vector3.new(265, 3.5, -115), CFrame.new(), false, false | |
local cwep = "Machinegun" | |
local dir = workspace:FindFirstChild("Characters") or Instance.new("Model", workspace) | |
if dir.Name ~= "Characters" then dir.Name = "Characters" end | |
for _, plr in pairs(game.Players:GetPlayers()) do | |
spawn(function() | |
local mdl = dir:FindFirstChild(plr.Name) --Get the custom character of plr | |
if mdl and mdl.PrimaryPart ~= nil then | |
if mdl ~= nil and plr.Name ~= player.Name then | |
--pcall(function() | |
local pd = PlayerData[plr.Name] | |
if pd ~= nil then | |
pos = pd.Position | |
mpos = pd.MousePosition | |
yrot = pd.YRot | |
ghosting = pd.Invisible | |
bup = pd.Barrier | |
cwep = pd.CurrentWeapon | |
end | |
--pos, mpos, yrot = events.GetPlayerLocation:InvokeServer(plr) | |
--cwep = events.GetCurrentWeapon:InvokeServer(plr) | |
--ghosting = events.GetPlayerGhosting:InvokeServer(plr) | |
--bup = events.GetPlayerBarrier:InvokeServer(plr) | |
--end) | |
if mdl.PrimaryPart ~= nil then | |
local plrcf = CFrame.new(pos) * yrot --set player CFrame | |
--mdl:SetPrimaryPartCFrame(plrcf) | |
tLib.TweenModelLinearAsync(mdl, plrcf, dt, TweenCallback) | |
end | |
local wmdl = mdl:FindFirstChild(cwep) | |
if not wmdl then --3rd person weapon model doesnt exist, create one | |
wmdl = game.ReplicatedStorage.Models[cwep]:Clone() | |
wmdl.Parent = mdl | |
wmdl:MakeJoints() | |
end | |
local weaponCode = weaponData[cwep] | |
--Delete any weapon viewmodels that arent the currently selected weapon | |
for _, wm in pairs(mdl:GetChildren()) do | |
if wm.ClassName == "Model" then | |
for _, wname in pairs(WeaponIndexes) do | |
if wm.Name == wname and wm.Name ~= cwep then | |
wm:Destroy() | |
end | |
end | |
end | |
end | |
--Set 3rd person weapon model's CFrame | |
local wmdlcf = CFrame.new(pos, mpos) | |
* CFrame.new(weaponCode.ViewModel_3rdPerson.Offset.X or 0.4, weaponCode.ViewModel_3rdPerson.Offset.Y or 0.7, weaponCode.ViewModel_3rdPerson.Offset.Z or -2.15) | |
* CFrame.Angles(math.rad(weaponCode.ViewModel.Angle.X), math.rad(weaponCode.ViewModel.Angle.Y), math.rad(weaponCode.ViewModel.Angle.Z)) | |
--wmdl:SetPrimaryPartCFrame(wmdlcf) | |
if wmdl.PrimaryPart ~= nil then | |
tLib.TweenModelLinearAsync(wmdl, wmdlcf, dt, TweenCallback) | |
end | |
local armsCf = CFrame.new(pos, mpos) * CFrame.new(0.4, 0.7, -2.15) | |
if mdl:FindFirstChild("ArmsViewmodel") then | |
--mdl.ArmsViewmodel:SetPrimaryPartCFrame(armsCf) | |
if mdl.ArmsViewmodel.PrimaryPart ~= nil then | |
tLib.TweenModelLinearAsync(mdl.ArmsViewmodel, armsCf, dt, TweenCallback) | |
end | |
end | |
local arms = mdl:FindFirstChild("ArmsViewmodel") | |
if ghosting then | |
Orakel.RecursiveSearch(mdl.Head, function(obj) return (obj.ClassName == "Decal") end, function(obj) obj.Transparency = 1 end) | |
Orakel.ToggleVisible(mdl, 1, false) | |
Orakel.ToggleVisible(arms, 1, false, {"Part"}) | |
if not equippedWeapon.Name == "Machinegun" then | |
Orakel.ToggleVisible(wmdl, 1, false, {"Muzzle", "Barrel"}) | |
else | |
Orakel.ToggleVisible(wmdl, 1, false, {"Muzzle"}) | |
end | |
else | |
Orakel.RecursiveSearch(mdl.Head, function(obj) return (obj.ClassName == "Decal") end, function(obj) obj.Transparency = 0 end) | |
Orakel.ToggleVisible(mdl, 0, false) | |
Orakel.ToggleVisible(arms, 0, false, {"Part"}) | |
Orakel.ToggleVisible(wmdl, 0, false, {"Muzzle", "Barrel"}) | |
end | |
if bup and not mdl:FindFirstChild("Barrier") then | |
local barrier = game.ReplicatedStorage.Particles.Barrier:Clone() | |
barrier.Parent = mdl | |
elseif not bup then | |
local barrier = mdl:FindFirstChild("Barrier") | |
if barrier then | |
barrier:Destroy() | |
end | |
end | |
local barrier = mdl:FindFirstChild("Barrier") | |
if barrier then | |
barrier:SetPrimaryPartCFrame(CFrame.new(mdl:GetPrimaryPartCFrame().p, mpos)) | |
end | |
elseif mdl == nil and plr.Name ~= player.Name then --Character model doesnt exist, create one | |
PlayerModels[plr.Name] = CreatePlayerModel(plr) | |
end | |
else | |
--print("playermodel doesnt exist or hrp died") | |
if PlayerModels[plr.Name] then | |
PlayerModels[plr.Name]:Destroy() | |
end | |
PlayerModels[plr.Name] = CreatePlayerModel(plr) | |
end | |
end) | |
end | |
--debug.profileend() | |
end | |
function SendCurrentBody() | |
if string.len(player.PlayerGui.HUD.Chat.InputFrame.TextBox.Text) > 0 then | |
events.SendMessage:FireServer(player.PlayerGui.HUD.Chat.InputFrame.TextBox.Text) | |
--print("sending: "..player.PlayerGui.HUD.Chat.InputFrame.TextBox.Text) | |
end | |
end | |
function GetOldestMessage() | |
local messages = player.PlayerGui.HUD.Chat.Messages:GetChildren() | |
local oldest | |
for i = 1, #messages do | |
local curmsg = messages[i] | |
if curmsg.Name == "ChatMessage" or curmsg.Name == "SystemChatMessage" then | |
if oldest == nil then | |
oldest = curmsg | |
else | |
if curmsg.Time.Value < oldest.Time.Value then | |
oldest = curmsg | |
end | |
end | |
end | |
end | |
return oldest | |
end | |
function ToggleChatWindow() | |
chatVisible = not chatVisible | |
player.PlayerGui.HUD.Chat.HelpFrame.Visible = not player.PlayerGui.HUD.Chat.HelpFrame.Visible | |
player.PlayerGui.HUD.Chat.InputFrame.Visible = not player.PlayerGui.HUD.Chat.InputFrame.Visible | |
if chatVisible then | |
player.PlayerGui.HUD.Chat.InputFrame.TextBox:CaptureFocus() | |
else | |
--player.PlayerGui.HUD.Chat.InputFrame.TextBox:ReleaseFocus() | |
player.PlayerGui.HUD.Chat.InputFrame.TextBox.Text = "" | |
end | |
end | |
function ToggleScoreboard() | |
if scoreboardCanBeToggled then | |
player.PlayerGui.HUD.Scoreboard.Visible = not player.PlayerGui.HUD.Scoreboard.Visible | |
end | |
end | |
function GetMyPlacing(sortedNames) | |
for i = 1, #sortedNames do | |
if sortedNames[i] == player.Name then | |
return i | |
end | |
end | |
end | |
function UpdateScoreboard(dt) | |
spawn(function() | |
--debug.profilebegin("UpdateScoreboard") | |
local playerframes = player.PlayerGui.HUD.Scoreboard.Main.PlayerList:GetChildren() | |
local scoreboard = {} | |
pcall(function() | |
scoreboard = events.GetPlayerScores:InvokeServer() | |
end) | |
local sortedNames = mathLib.SortScoreboardBy(scoreboard, "Score") | |
local p1, p2 | |
PrevSituation = CurrentSituation | |
--print("prev sit: "..PrevSituation.." cur sit: "..CurrentSituation) | |
if sortedNames ~= nil then | |
p1 = sortedNames[1] or "Player1" | |
p2 = sortedNames[2] or "Player2" | |
if #sortedNames > 1 then | |
if p1 == player.Name and not (scoreboard[p1].Score == scoreboard[p2].Score) then | |
CurrentSituation = "LEAD" | |
elseif p1 ~= player.Name and not (p2 == player.Name and scoreboard[p1].Score == scoreboard[p2].Score) then | |
CurrentSituation = "NOT_LEADING_OR_TIED" | |
elseif scoreboard[p1].Score == scoreboard[p2].Score and (p1 == player.Name or p2 == player.Name) then | |
CurrentSituation = "TIED" | |
end | |
else | |
CurrentSituation = "LEAD" | |
end | |
if CurrentSituation ~= PrevSituation then | |
if CurrentSituation == "TIED" then | |
sndLib.PlaySoundClient("global", "tied_for_the_lead", "rbxassetid://822279510", 0.3, 1, false, 4) | |
elseif CurrentSituation == "LEAD" then | |
sndLib.PlaySoundClient("global", "taken_the_lead", "rbxassetid://822279334", 0.3, 1, false, 4) | |
elseif CurrentSituation == "NOT_LEADING_OR_TIED" then | |
sndLib.PlaySoundClient("global", "lost_the_lead", "rbxassetid://822279169", 0.3, 1, false, 4) | |
end | |
end | |
end | |
if sortedNames ~= nil then | |
for i, plrname in pairs(sortedNames) do | |
local scores = scoreboard[plrname] | |
local plr = game.Players:FindFirstChild(plrname) | |
if plr then | |
spawn(function() | |
local f = player.PlayerGui.HUD.Scoreboard.Main.PlayerList:FindFirstChild(plr.Name) | |
if not f then | |
f = game.ReplicatedStorage.PlayerFrame:Clone() | |
f.Size = UDim2.new(1, 0, 0.1, 0) | |
f.Name = plr.Name | |
f.Position = UDim2.new(0, 0, 0.1 * i, 0) | |
f.BackgroundTransparency = 1 | |
f.Parent = player.PlayerGui.HUD.Scoreboard.Main.PlayerList | |
f.Icon.Image = game:GetService("Players"):GetUserThumbnailAsync(plr.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48) | |
end | |
player.PlayerGui.HUD.Scoreboard.Placing.Text = mathLib.IntegerToNumeral(GetMyPlacing(sortedNames)) | |
if CurrentSituation == "TIED" then | |
player.PlayerGui.HUD.Scoreboard.PlacingFrags.Text = " place with "..tostring(scores.Kills).." (TIED)" | |
else | |
player.PlayerGui.HUD.Scoreboard.PlacingFrags.Text = " place with "..tostring(scores.Kills) | |
end | |
f.Position = UDim2.new(0, 0, 0.1 * i, 0) | |
local suffix = "" | |
if IsDeveloper(plr.Name) then | |
suffix = " (DEV)" | |
end | |
f.PlayerName.Text = plr.Name .. suffix | |
f.Score.Text = scores.Score | |
f.Time.Text = mathLib.SecondsToTimerFormat(ClientTime) | |
f.Ping.Text = (PlayerLatencies[plr.UserId] or 0).."ms" | |
f.KD.Text = scores.Kills.." / "..scores.Deaths | |
f.DMG.Text = scores.Damage | |
end) | |
end | |
end | |
end | |
--debug.profileend() | |
end) | |
end | |
function CreateChatMessage(sender, msg, ypos, isSystemMessage) | |
local f = game.ReplicatedStorage.ChatMessage:Clone() | |
local suffix = "" | |
if IsDeveloper(sender) then | |
suffix = " (DEV)" | |
f.Sender.TextColor3 = Color3.new(0.8, 0.05, 0.05) | |
end | |
f.Sender.Text = sender..suffix..":" | |
f.Body.Text = msg | |
if isSystemMessage then | |
f:Destroy() | |
f = game.ReplicatedStorage.SystemChatMessage:Clone() | |
f.Body.Text = msg | |
f.Sender.Text = "" | |
end | |
print(f.Sender.Text .. f.Body.Text) | |
for _, msg in pairs(player.PlayerGui.HUD.Chat.Messages:GetChildren()) do | |
if msg.Name == "ChatMessage" or msg.Name == "SystemChatMessage" then | |
msg.Position = UDim2.new(msg.Position.X.Scale, msg.Position.X.Offset, msg.Position.Y.Scale - 0.1, 0) | |
end | |
end | |
if #player.PlayerGui.HUD.Chat.Messages:GetChildren() >= 7 then | |
local o = GetOldestMessage() | |
o:Destroy() | |
end | |
f.Position = UDim2.new(0, 0, 0.7, 0) | |
local x = game:GetService("TextService"):GetTextSize(f.Sender.Text, f.Sender.TextSize, f.Sender.Font, f.Sender.AbsoluteSize).X | |
f.Body.Position = UDim2.new(0, x + 18, 0, 0) | |
f.Parent = player.PlayerGui.HUD.Chat.Messages | |
sndLib.PlaySoundClient("global", "chatnotification", "rbxassetid://821076180", 0.4, 1, false, 2) | |
f.Time.Value = ClientTime | |
end | |
function UpdateChat(dt) | |
spawn(function() | |
--debug.profilebegin("UpdateChat") | |
local newchatlog = {} | |
pcall(function() | |
newchatlog = events.GetServerChat:InvokeServer() | |
end) | |
if #newchatlog > #chatlog then | |
--print("new messages found") | |
local numNewMessages = #newchatlog - #chatlog | |
--print(numNewMessages.." new messages") | |
if numNewMessages > 0 then | |
for i = #newchatlog, 1, -1 do | |
if i <= #newchatlog - numNewMessages then | |
break | |
end | |
--print("working on message #"..i) | |
local msg = newchatlog[i] | |
if msg.GameInfo == true then | |
CreateChatMessage(msg.Sender, msg.Body, 0.7 - (0.1 * #newchatlog), true) | |
else | |
--print("creating the message") | |
CreateChatMessage(msg.Sender, msg.Body, 0.7 - (0.1 * #newchatlog), false) | |
end | |
end | |
--print("done fetching") | |
chatlog = newchatlog | |
--local msg = newchatlog[#newchatlog] | |
--CreateChatMessage(msg.Sender, msg.Body, 0.7 - (0.1 * #newchatlog)) | |
--chatlog = newchatlog | |
end | |
end | |
for _, msg in pairs(player.PlayerGui.HUD.Chat.Messages:GetChildren()) do | |
if msg.Name == "ChatMessage" or msg.Name == "SystemChatMessage" then | |
if math.abs(ClientTime - msg.Time.Value) > ConVars["cl_chat_message_displaytime"][1] and chatVisible then | |
msg.Body.TextTransparency = 0 | |
msg.Sender.TextTransparency = 0 | |
elseif math.abs(ClientTime - msg.Time.Value) > ConVars["cl_chat_message_displaytime"][1] and not chatVisible then | |
msg.Body.TextTransparency = 1 | |
msg.Sender.TextTransparency = 1 | |
else | |
msg.Body.TextTransparency = 0 | |
msg.Sender.TextTransparency = 0 | |
end | |
end | |
end | |
--debug.profileend() | |
end) | |
end | |
function UpdateCamera(dt) | |
--debug.profilebegin("UpdateCamera") | |
if thirdperson then | |
cam.CFrame = CFrame.new(char:GetPrimaryPartCFrame().p) * CFrame.Angles(0, thirdpersonangle, 0) * CFrame.new(0, 0, 5) | |
thirdpersonangle = thirdpersonangle + math.rad(thirdpersonRotSpeed * dt) | |
else | |
do | |
if char.PrimaryPart ~= nil and PlayerStats.Health > 0 then | |
local xRot = CFrame.Angles(-mouseAngles.Y, 0, 0) | |
local yRot = CFrame.Angles(0, -mouseAngles.X, 0) | |
local pos = char.PrimaryPart.Position + Vector3.new(0, 2, 0) | |
cam.CFrame = CFrame.new(pos) * yRot * xRot | |
cam.Focus = cam.CFrame | |
prevCamCF = cam.CFrame | |
else | |
cam.CFrame = prevCamCF | |
cam.Focus = cam.CFrame | |
end | |
end | |
end | |
--debug.profileend() | |
end | |
local grounded = true | |
local timeGrounded = 0 | |
function GetWeaponBob() | |
local a = (math.sin(bobtimer) / 7.5) * ConVars["cl_weaponbob_amt"][1] | |
local b = (math.sin(2 * bobtimer) / 7.5) * ConVars["cl_weaponbob_amt"][1] | |
if movementKeysDown.W or movementKeysDown.A or movementKeysDown.S or movementKeysDown.D then | |
return weaponCode.ViewModel_Bob(a, b) | |
else | |
return CFrame.new() | |
end | |
end | |
function UpdateRender(dt) | |
--debug.profilebegin("UpdateRender") | |
UpdateCamera(dt) | |
bobtimer = bobtimer + (5 * dt * ConVars["cl_weaponbob_rate"][1]) | |
local chars = workspace.Characters:GetChildren() | |
for _, mdl in pairs(chars) do | |
local rarm = mdl:FindFirstChild("Right Arm") | |
local larm = mdl:FindFirstChild("Left Arm") | |
local hrp = mdl:FindFirstChild("HumanoidRootPart") | |
local arms = mdl:FindFirstChild("ArmsViewmodel") | |
if rarm and larm then | |
rarm.Transparency = 1 | |
larm.Transparency = 1 | |
rarm.LocalTransparencyModifier = 1 | |
larm.LocalTransparencyModifier = 1 | |
end | |
if arms then | |
for _, p in pairs(arms:GetChildren()) do | |
p.Transparency = 1 | |
p.LocalTransparencyModifier = 1 | |
end | |
end | |
if hrp then | |
hrp.Transparency = 1 | |
hrp.LocalTransparencyModifier = 1 | |
end | |
end | |
local actualMouseRay = Ray.new(mouse.UnitRay.Origin, mouse.UnitRay.Direction * 999) | |
local hit, pos, norm = workspace:FindPartOnRayWithWhitelist(actualMouseRay, {}) | |
actualMouseHit = pos | |
local hitwall = false | |
for _, p in pairs(char:GetChildren()) do | |
if p:IsA("BasePart") then | |
p.Transparency = 1 | |
end | |
end | |
if RAYMDL ~= nil then | |
RAYMDL:Destroy() | |
end | |
--RAYMDL = DrawLineDebug(char:GetPrimaryPartCFrame().p, char:GetPrimaryPartCFrame().p + char:GetPrimaryPartCFrame().lookVector * 5) | |
if grounded then | |
timeGrounded = timeGrounded + dt | |
else | |
timeGrounded = 0 | |
end | |
grounded = Grounded(dt) | |
accelDir = Vector3.new() | |
if PlayerStats.Health > 0 and not player.PlayerGui.HUD.Chat.InputFrame.Visible and canwalk then | |
if movementKeysDown.W then | |
accelDir = accelDir + CFrame.Angles(0, math.rad(0), 0) * (cam.CFrame.lookVector * Vector3.new(1,0,1)).unit | |
end | |
if movementKeysDown.S then | |
accelDir = accelDir + CFrame.Angles(0, math.rad(-180), 0) * (cam.CFrame.lookVector * Vector3.new(1,0,1)).unit | |
end | |
if movementKeysDown.A then | |
accelDir = accelDir + CFrame.Angles(0, math.rad(90), 0) * (cam.CFrame.lookVector * Vector3.new(1,0,1)).unit | |
end | |
if movementKeysDown.D then | |
accelDir = accelDir + CFrame.Angles(0, math.rad(-90), 0) * (cam.CFrame.lookVector * Vector3.new(1,0,1)).unit | |
end | |
end | |
if (grounded and timeGrounded > 0.15) and not jumping then | |
player.PlayerGui.HUD.SpeedTypeLabel.Text = "MoveGround" | |
playerVelocity = MoveGround(accelDir, playerVelocity, dt, grounded) + VelOffset + pushVector | |
else | |
if jumpedOnPrevFrame then | |
jumpedOnPrevFrame = false | |
end | |
player.PlayerGui.HUD.SpeedTypeLabel.Text = "MoveAir" | |
playerVelocity = MoveAir(accelDir, playerVelocity, dt, grounded) | |
playerVelocity = playerVelocity + (Vector3.new(0, -workspace.Gravity / 2, 0) * dt) + pushVector | |
end | |
if movementKeysDown.Space and not jumping and PlayerStats.Health > 0 and grounded and not player.PlayerGui.HUD.Chat.InputFrame.Visible then | |
jumpedOnPrevFrame = true | |
jumping = true | |
sndLib.PlaySoundClient("global", "jump", "rbxassetid://821077345", 0.3, 1, false, 1) | |
spawn(function() | |
while true do | |
local dt = game:GetService("RunService").RenderStepped:wait() | |
local grounded = Grounded(dt) | |
if grounded then | |
break | |
end | |
end | |
wait() | |
jumping = false | |
end) | |
playerVelocity = playerVelocity + Vector3.new(0, 32.5, 0) | |
end | |
player.PlayerGui.HUD.SpeedLabel.Text = math.abs(math.floor(playerVelocity.magnitude)) | |
prevVelocity = playerVelocity | |
--print(playerVelocity) | |
local function raycast(orig, dir) | |
return workspace:FindPartOnRayWithIgnoreList(Ray.new(orig, dir), {char, workspace.Ignore, workspace.PlayerSpawns, workspace.ItemPickups, workspace.ItemSpawns, workspace.Nodes}) | |
end | |
-- Radius of player's hitbox: | |
local playerRadius = 2.95 | |
-- STEP 1: cast forward into movement direction to find initial collision with wall: | |
-- (i.e. so you dont teleport the player into wall to begin with) | |
local origin = char:GetPrimaryPartCFrame().p -- player's current position | |
local movement = playerVelocity * dt -- player's movement vector | |
local movement_xz_unit = (playerVelocity * Vector3.new(1,0,1)).unit | |
local hitboxadjust = movement_xz_unit * playerRadius -- offset to be applied to take into account hitbox as well | |
-- Check for hit within movement vector: | |
local hit, hitpos = raycast(origin, movement) | |
if hit then | |
-- Hit found, so move to the wall position and move back from wall by hitboxadjust: | |
hitwall = true | |
origin = hitpos - hitboxadjust | |
playerVelocity = Vector3.new(0, playerVelocity.Y, 0) | |
else | |
-- No hit, simply move to the position: | |
origin = origin + movement | |
end | |
-- STEP 2: cast in a fan to check for collisions: | |
-- (i.e. making sure a player is approximately playerRadius away from any objects in any direction) | |
-- Precalculate direction vectors for angle-pairs: | |
local directionVector = {} | |
for i = -180, -0.1, 22.5 do | |
directionVector[i] = CFrame.Angles(0,math.rad(i),0) * hitboxadjust | |
end | |
-- Which angle-pairs have been done: | |
local done = {} | |
-- Do 8 rounds of correction (one for each angle-pair): | |
for _ = 1,8 do | |
-- Running variables: | |
local m = .001 -- Magnitude of maximum displacement | |
local n = nil -- Maximum displacement | |
local o = nil -- Angle of maximum displacement | |
-- Loop over all angle-pairs: | |
for i = -180, -0.1, 22.5 do | |
-- If we have corrected at this angle-pair already then we won't correct again this frame: | |
if not done[i] then | |
-- Raycast positive/negative angle (these rays are opposite): | |
local hit1, pos1 = raycast(origin, directionVector[i]) | |
local hit2, pos2 = raycast(origin, -directionVector[i]) | |
-- Determine offset in this angle-pair: | |
local off = Vector3.new(0,0,0) | |
if hit1 then | |
-- For negative angle: | |
hitwall = true | |
off = (directionVector[i] - (pos1 - origin)) | |
end | |
if hit2 then | |
-- For positive angle: | |
hitwall = true | |
off = off + (-directionVector[i] - (pos2 - origin)) | |
end | |
-- Check if displacement is greater than the tracked displacement: | |
if off.magnitude > m then | |
-- It's bigger, so update running variables: | |
m = off.magnitude | |
n = off | |
o = i | |
end | |
end | |
end | |
-- Check if a maximum displacement was found: | |
if o then | |
-- Apply the displacement for angle-pair 'o': | |
origin = origin - n | |
-- This angle-pair is now done: | |
done[o] = true | |
else | |
-- No displacement in any direction, so just stop: | |
break | |
end | |
end | |
char:SetPrimaryPartCFrame(CFrame.new(origin) * CFrame.Angles(0, -mouseAngles.X, 0)) | |
if hitwall and not grounded then | |
--playerVelocity = Vector3.new(0, playerVelocity.Y, 0) | |
end | |
if char.PrimaryPart.Position.Y < -900 and not falldeath then | |
TakeDamage(9000, "World") | |
Orakel.Log(player.Name.. " could not fly.") | |
falldeath = true | |
playerVelocity = Vector3.new() | |
spawn(function() | |
wait(4) | |
falldeath = false | |
end) | |
elseif char.PrimaryPart.Position.Y < -900 and falldeath then | |
playerVelocity = Vector3.new() | |
end | |
pushVector = Vector3.new() | |
clouds.CFrame = CFrame.new(char.Torso.Position.X, 67, char.Torso.Position.Z) * CFrame.Angles(math.rad(180), 0, 0) | |
for _, tex in pairs(clouds.SurfaceGui:GetChildren()) do | |
tex.Position = tex.Position + UDim2.new(0.05 * dt, 0, 0, 0) | |
if tex.Position.X.Scale > 2 then | |
tex.Position = UDim2.new(-2, 0, 0, 0) | |
end | |
end | |
if equippedWeapon then | |
--if UseWeaponViewmodel then | |
local a = (math.sin(bobtimer) / 7.5) * ConVars["cl_weaponbob_amt"][1] | |
local b = (math.sin(2 * bobtimer) / 7.5) * ConVars["cl_weaponbob_amt"][1] | |
--if weaponCode.ViewModel_Bob then | |
equippedWeapon:SetPrimaryPartCFrame( | |
CFrame.new(cam.CFrame.p, mouse.Hit.p) | |
* CFrame.new(weaponCode.ViewModel.Offset.X, weaponCode.ViewModel.Offset.Y, weaponCode.ViewModel.Offset.Z) | |
* CFrame.Angles(math.rad(weaponCode.ViewModel.Angle.X), math.rad(weaponCode.ViewModel.Angle.Y), math.rad(weaponCode.ViewModel.Angle.Z)) | |
* GetWeaponBob() --CFrame.new(a, b, 0) | |
) | |
--end | |
--else | |
--equippedWeapon:SetPrimaryPartCFrame( | |
--CFrame.new(cam.CFrame.p, mouse.Hit.p) | |
--* CFrame.new(script.Offset.Value.X, script.Offset.Value.Y, script.Offset.Value.Z) | |
--* CFrame.Angles(math.rad(script.Angle.Value.X), math.rad(script.Angle.Value.Y), math.rad(script.Angle.Value.Z)) | |
--) | |
--end | |
end | |
if barrierUp and not workspace.Ignore:FindFirstChild("Barrier") then | |
local barrier = game.ReplicatedStorage.Particles.Barrier:Clone() | |
barrier.Parent = workspace.Ignore | |
elseif not barrierUp then | |
local barrier = workspace.Ignore:FindFirstChild("Barrier") | |
if barrier then | |
barrier:Destroy() | |
end | |
end | |
local barrier = workspace.Ignore:FindFirstChild("Barrier") | |
if barrier then | |
--barrier:SetPrimaryPartCFrame(equippedWeapon:GetPrimaryPartCFrame() * CFrame.Angles(math.rad(script.Angle.Value.X), math.rad(script.Angle.Value.Y), math.rad(script.Angle.Value.Z))) | |
barrier:SetPrimaryPartCFrame(CFrame.new(char:GetPrimaryPartCFrame().p, actualMouseHit)) | |
end | |
--debug.profileend() | |
end | |
local falldeath = false | |
function TakeDamage(damage, damageGiver) | |
if not falldeath then | |
local dmg = damage | |
if PlayerStats.Armor > 0 then | |
local armourCanAbsorb = math.min(math.floor(dmg*(2/3)), PlayerStats.Armor) | |
dmg = dmg - armourCanAbsorb | |
PlayerStats.Armor = math.clamp(PlayerStats.Armor - armourCanAbsorb, 0, 9000) | |
end | |
PlayerStats.Health = math.clamp(PlayerStats.Health - dmg, 0, 9000) | |
--spawn blood on screen | |
if ConVars["cl_violence"][1] then | |
local blood = Instance.new("ImageLabel") | |
blood.BackgroundTransparency = 1 | |
blood.Size = UDim2.new(0.259, 0, 0.5, 0) | |
blood.Position = UDim2.new(math.random(), 0, math.random(), 0) | |
blood.Image = "rbxassetid://313082863" | |
blood.Rotation = math.random() * 360 | |
blood.Parent = player.PlayerGui.HUD.HurtFrame | |
spawn(function() | |
wait(3) | |
local t = 0 | |
while t <= 2 do | |
local dt = game:GetService("RunService").RenderStepped:wait() | |
t = t + dt | |
blood.ImageTransparency = blood.ImageTransparency + (dt * 2) | |
end | |
blood:Destroy() | |
end) | |
end | |
--hurt sounds | |
if PlayerStats.Health <= 0 then | |
--death sound | |
sndLib.PlaySoundClient("global", "die", Orakel.TRand(assetLib.HurtSounds.DieHuman), 0.4, 1, false, 2) | |
lastHurtSound = tick() + 20 | |
player.PlayerGui.HUD.Scoreboard.Visible = true | |
player.PlayerGui.HUD.Scoreboard.Fraggedby.Text = "Fragged by "..tostring(damageGiver) | |
player.PlayerGui.HUD.Scoreboard.Fraggedby.Visible = true | |
elseif PlayerStats.Health > 0 and math.abs(tick() - lastHurtSound) > 1 then | |
--hurt sound | |
sndLib.PlaySoundClient("global", "hurt", Orakel.TRand(assetLib.HurtSounds.HurtHuman), 0.4, 1, false, 2) | |
lastHurtSound = tick() | |
end | |
end | |
end | |
local jumping = false | |
function UpdateHeartbeat(dt) | |
--debug.profilebegin("UpdateHeartbeat") | |
ClientTime = ClientTime + dt | |
for _, plr in pairs(game.Players:GetPlayers()) do | |
local mdl = workspace.Characters:FindFirstChild(plr.Name) | |
if mdl then | |
local hrp = mdl:FindFirstChild("HumanoidRootPart") | |
if hrp then | |
if hrp.Position.Y <= -30 then | |
--print("HRP FALLIN OUT OF MAP") | |
end | |
end | |
end | |
end | |
--Update ui health labels and health bars | |
player.PlayerGui.HUD.VitalsFrame.Health.TextLabel.Text = math.ceil(PlayerStats.Health).."/"..PlayerStats.MaxHealth | |
player.PlayerGui.HUD.VitalsFrame.Health.Bar.Filler.Size = UDim2.new(PlayerStats.Health / PlayerStats.MaxHealth, 0, 1, 0) | |
player.PlayerGui.HUD.VitalsFrame.Armor.TextLabel.Text = math.ceil(PlayerStats.Armor).."/"..PlayerStats.MaxArmor | |
player.PlayerGui.HUD.VitalsFrame.Armor.Bar.Filler.Size = UDim2.new(PlayerStats.Armor / PlayerStats.MaxArmor, 0, 1, 0) | |
--adjust ui health bar colours | |
if PlayerStats.Health > PlayerStats.MaxHealth then | |
player.PlayerGui.HUD.VitalsFrame.Health.Bar.Filler.BackgroundColor3 = Color3.new(0, 243/255, 1) | |
else | |
player.PlayerGui.HUD.VitalsFrame.Health.Bar.Filler.BackgroundColor3 = Color3.new(0, 1, 93/255) | |
end | |
if PlayerStats.Armor > PlayerStats.MaxArmor then | |
player.PlayerGui.HUD.VitalsFrame.Armor.Bar.Filler.BackgroundColor3 = Color3.new(0, 243/255, 1) | |
else | |
player.PlayerGui.HUD.VitalsFrame.Armor.Bar.Filler.BackgroundColor3 = Color3.new(0, 1, 93/255) | |
end | |
--Update ammo values and weapon icons on UI | |
for _, frame in pairs(player.PlayerGui.HUD.WeaponsFrame:GetChildren()) do | |
frame.Ammo.Text = tostring(PlayerStats.Weapons[frame.Name].Ammo) | |
end | |
player.PlayerGui.HUD.AmmoFrame.ImageLabel.Image = player.PlayerGui.HUD.WeaponsFrame[equippedWeapon.Name].Icon.Image | |
player.PlayerGui.HUD.AmmoFrame.TextLabel.Text = tostring(PlayerStats.Weapons[equippedWeapon.Name].Ammo) | |
--Lose health and armor constantly if n > 100 | |
if PlayerStats.Health > PlayerStats.MaxHealth then | |
PlayerStats.Health = PlayerStats.Health - 0.6 * dt | |
end | |
if PlayerStats.Armor > PlayerStats.MaxArmor then | |
PlayerStats.Armor = PlayerStats.Armor - 0.6 * dt | |
end | |
--Die in roblox | |
if PlayerStats.Health <= 0 and not respawning then | |
respawning = true | |
spawn(function() | |
canfire = false | |
local dspawns = workspace.PlayerDebugSpawns:GetChildren() | |
local dspawn = dspawns[math.random(1, #dspawns)] | |
char:SetPrimaryPartCFrame(dspawn.CFrame) | |
wait(4) | |
playerVelocity = Vector3.new() | |
SwitchWeapon(equippedWeapon, 1, 1, false) | |
canfire = true | |
char.Humanoid.WalkSpeed = 32 | |
player.PlayerGui.HUD.Scoreboard.Visible = false | |
player.PlayerGui.HUD.Scoreboard.Fraggedby.Visible = false | |
--char.Humanoid.Health = 0 | |
PlayerStats.Health = 100 | |
PlayerStats.Armor = 15 | |
PlayerStats.Weapons.Machinegun.Ammo = 100 | |
local spawns = workspace.PlayerSpawns:GetChildren() | |
local cspawn = spawns[math.random(1, #spawns)] | |
char:SetPrimaryPartCFrame(cspawn.CFrame) | |
respawning = false | |
end) | |
end | |
--Fire weapon, TODO: implement single-fire instead of always-auto? | |
if m1down and PlayerStats.Weapons[equippedWeapon.Name].Ammo > 0 then | |
local ps = weaponCode.RateOfFire / 60 | |
local rof = 1 / ps | |
if tick() - lastShotFired >= rof and canfire then | |
game.ReplicatedStorage.WeaponFiredClient:Fire() | |
PlayerStats.Weapons[equippedWeapon.Name].Ammo = PlayerStats.Weapons[equippedWeapon.Name].Ammo - 1 | |
weaponCode.Fire(player, equippedWeapon, cam.CFrame.p, mouse.Hit.p, char) | |
events.FireWeaponServer:FireServer(player, equippedWeapon.Name, cam.CFrame.p, mouse.Hit.p) | |
if weaponCode.Fired ~= nil then | |
if not weaponCode.Fired then | |
weaponCode.FireOnce(player) | |
weaponCode.Fired = true | |
end | |
end | |
lastShotFired = tick() | |
end | |
weaponCode.Update(dt, equippedWeapon, true) | |
else | |
weaponCode.Update(dt, equippedWeapon, false) --only necessary for the machinegun's barrel spin | |
if weaponCode.StopFire ~= nil then | |
weaponCode.StopFire() | |
end | |
end | |
for _, item in pairs(pickups) do | |
if item.ClassName == "Model" then | |
item:SetPrimaryPartCFrame(item:GetPrimaryPartCFrame() * CFrame.new(0, 0, itemFloatHeight * math.sin(tick() % 10000)) * CFrame.Angles(0, 0, math.rad(180 * dt))) | |
else | |
--item.CFrame = item.CFrame * CFrame.Angles(0, 0, math.rad(180 * dt)) | |
item.CFrame = item.CFrame * CFrame.new(0, 0, itemFloatHeight * math.sin(tick() % 10000)) * CFrame.Angles(0, 0, math.rad(180 * dt)) | |
--local ypos = itemFloatHeight * math.sin(tick() % 10000) | |
end | |
end | |
local arms = char:FindFirstChild("ArmsViewmodel") | |
if charInvisible then | |
Orakel.RecursiveSearch(char.Head, function(obj) return (obj.ClassName == "Decal") end, function(obj) obj.Transparency = 1 end) | |
Orakel.ToggleVisible(char, 1, false) | |
Orakel.ToggleVisible(arms, 1, false, {"Part"}) | |
if not equippedWeapon.Name == "Machinegun" then | |
Orakel.ToggleVisible(equippedWeapon, 1, false, {"Muzzle", "Barrel"}) | |
else | |
Orakel.ToggleVisible(equippedWeapon, 1, false, {"Muzzle"}) | |
end | |
else | |
Orakel.RecursiveSearch(char.Head, function(obj) return (obj.ClassName == "Decal") end, function(obj) obj.Transparency = 0 end) | |
Orakel.ToggleVisible(char, 0, false) | |
Orakel.ToggleVisible(arms, 0, false, {"Part"}) | |
Orakel.ToggleVisible(equippedWeapon, 0, false, {"Muzzle", "Barrel"}) | |
end | |
player.PlayerGui.HUD.ScoreFrame.RoundTimer.Text = mathLib.SecondsToTimerFormat(game.ReplicatedStorage.GetServerRoundTime:InvokeServer()) | |
--debug.profileend() | |
end | |
function InputBegan(io) | |
if io.UserInputType == Enum.UserInputType.MouseButton1 then | |
if not ConsoleVisible then | |
m1down = true | |
end | |
--elseif io.UserInputType == Enum.UserInputType.MouseWheel then | |
--print("mwheel") | |
--SwitchWeapon(equippedWeapon, io.Position.Z) | |
elseif io.UserInputType == Enum.UserInputType.MouseButton2 then | |
cam.FieldOfView = ConVars["cl_zoomfov"][1] | |
elseif io.UserInputType == Enum.UserInputType.Keyboard then | |
if not ConsoleVisible then | |
for key,_ in pairs(movementKeysDown) do | |
if key == io.KeyCode.Name then | |
movementKeysDown[key] = true | |
end | |
end | |
end | |
if ConsoleInputFocused then | |
if io.KeyCode == Enum.KeyCode.Up then | |
currentCmdIndex = math.clamp(currentCmdIndex - 1, 0, #PreviousCmds) | |
if currentCmdIndex ~= nil then | |
player.PlayerGui.HUD.Console.InputBox.Text = PreviousCmds[currentCmdIndex] | |
end | |
elseif io.KeyCode == Enum.KeyCode.Down then | |
currentCmdIndex = math.clamp(currentCmdIndex + 1, 0, #PreviousCmds) | |
if currentCmdIndex ~= nil then | |
player.PlayerGui.HUD.Console.InputBox.Text = PreviousCmds[currentCmdIndex] | |
end | |
end | |
end | |
--print(io.KeyCode.Name) | |
if io.KeyCode == Enum.KeyCode.T and not chatVisible and not ConsoleVisible then | |
ToggleChatWindow() | |
end | |
if io.KeyCode == Enum.KeyCode.Backquote or io.KeyCode == Enum.KeyCode.Tilde and not chatVisible and not ConsoleVisible then | |
player.PlayerGui.HUD.Console.InputBox:CaptureFocus() | |
player.PlayerGui.HUD.Console.InputBox.Text = "" | |
player.PlayerGui.HUD.Console.Visible = true | |
ConsoleVisible = true | |
elseif io.KeyCode == Enum.KeyCode.Backquote or io.KeyCode == Enum.KeyCode.Tilde and ConsoleVisible then | |
player.PlayerGui.HUD.Console.InputBox.Text = "" | |
player.PlayerGui.HUD.Console.Visible = false | |
ConsoleVisible = false | |
end | |
if io.KeyCode == Enum.KeyCode.F and PlayerStats.Health > 0 and not ConsoleVisible then | |
UseAbility() | |
end | |
if io.KeyCode == Enum.KeyCode.Return and chatVisible then | |
SendCurrentBody() | |
ToggleChatWindow() | |
end | |
if io.KeyCode == Enum.KeyCode.Tab and PlayerStats.Health > 0 then | |
ToggleScoreboard() | |
end | |
elseif io.UserInputType == Enum.UserInputType.MouseMovement then | |
local SENSITIVITY = Vector3.new(ConVars["cl_sensitivity"][1], ConVars["cl_sensitivity"][1], 0) --horizontal, vertical, zoom? | |
local delta = math.rad(1) * io.Delta * SENSITIVITY | |
local clampedY = math.clamp(mouseAngles.Y + delta.Y, MOUSE_MIN, MOUSE_MAX) | |
mouseAngles = Vector2.new(mouseAngles.X + delta.X, clampedY) | |
end | |
end | |
function InputChanged(io) | |
if io.UserInputType == Enum.UserInputType.MouseWheel and not ConsoleVisible then | |
SwitchWeapon(equippedWeapon, io.Position.Z) | |
end | |
if io.UserInputType == Enum.UserInputType.MouseMovement then | |
local SENSITIVITY = Vector3.new(ConVars["cl_sensitivity"][1], ConVars["cl_sensitivity"][1], 0) --horizontal, vertical, zoom? | |
local delta = math.rad(1) * io.Delta * SENSITIVITY | |
local clampedY = math.clamp(mouseAngles.Y + delta.Y, MOUSE_MIN, MOUSE_MAX) | |
--print(math.deg(clampedY)) | |
mouseAngles = Vector2.new(mouseAngles.X + delta.X, clampedY) | |
end | |
end | |
function InputEnded(io) | |
if io.UserInputType == Enum.UserInputType.MouseButton1 then | |
m1down = false | |
elseif io.UserInputType == Enum.UserInputType.MouseButton2 then | |
cam.FieldOfView = ConVars["cl_fov"][1] | |
elseif io.UserInputType == Enum.UserInputType.Keyboard then | |
for key,_ in pairs(movementKeysDown) do | |
if key == io.KeyCode.Name then | |
movementKeysDown[key] = false | |
end | |
end | |
if io.KeyCode == Enum.KeyCode.Tab and PlayerStats.Health > 0 then | |
ToggleScoreboard() | |
end | |
elseif io.UserInputType == Enum.UserInputType.MouseMovement then | |
local SENSITIVITY = Vector3.new(ConVars["cl_sensitivity"][1], ConVars["cl_sensitivity"][1], 0) --horizontal, vertical, zoom? | |
local delta = math.rad(1) * io.Delta * SENSITIVITY | |
local clampedY = math.clamp(mouseAngles.Y + delta.Y, MOUSE_MIN, MOUSE_MAX) | |
mouseAngles = Vector2.new(mouseAngles.X + delta.X, clampedY) | |
end | |
end | |
function ToggleGameUI(enabled) | |
player.PlayerGui.HUD.PingLabel.Visible = enabled | |
player.PlayerGui.HUD.SpeedLabel.Visible = enabled | |
player.PlayerGui.HUD.SpeedTypeLabel.Visible = enabled | |
player.PlayerGui.HUD.WeaponsFrame.Visible = enabled | |
player.PlayerGui.HUD.VitalsFrame.Visible = enabled | |
player.PlayerGui.HUD.Killfeed.Visible = enabled | |
player.PlayerGui.HUD.AmmoFrame.Visible = enabled | |
player.PlayerGui.HUD.HurtFrame.Visible = enabled | |
player.PlayerGui.HUD.SpecialAbility.Visible = enabled | |
end | |
function Init() | |
for _, plr in pairs(game.Players:GetPlayers()) do | |
PlayerLatencies[plr.UserId] = 0 | |
end | |
UpdatePlayerData(0) | |
local hud = player.PlayerGui:WaitForChild("HUD") | |
local con = hud:WaitForChild("Console") | |
local ibox = con:WaitForChild("InputBox") | |
local btn = con:WaitForChild("Button") | |
local ebtn = con:WaitForChild("ExitButton") | |
ebtn.MouseButton1Click:connect(function() | |
ConsoleInputFocused = false | |
con.Visible = false | |
ConsoleVisible = false | |
end) | |
btn.MouseButton1Click:connect(function() | |
local txt = ibox.Text | |
table.insert(PreviousCmds, txt) | |
ParseCommandLine(txt) | |
ibox.Text = "" | |
end) | |
ibox.FocusLost:connect(function(enterpressed, input) | |
ConsoleInputFocused = false | |
if enterpressed then | |
local txt = ibox.Text | |
table.insert(PreviousCmds, txt) | |
ParseCommandLine(txt) | |
ibox.Text = "" | |
player.PlayerGui.HUD.Console.InputBox:CaptureFocus() | |
end | |
end) | |
ibox.Focused:connect(function(enterpressed, input) | |
ConsoleInputFocused = true | |
end) | |
Orakel.Log("initializing client...") | |
wait(.5) | |
mouse.TargetFilter = workspace.Ignore | |
cam.CameraType = Enum.CameraType.Scriptable | |
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter | |
wait() | |
for _, wmodule in pairs(game.ReplicatedStorage.Weapons:GetChildren()) do | |
weaponData[wmodule.Name] = require(wmodule) | |
end | |
local dir = workspace:FindFirstChild("Characters") or Instance.new("Model", workspace) | |
if dir.Name ~= "Characters" then dir.Name = "Characters" end | |
dir.ChildAdded:connect(function(c) | |
c.ChildRemoved:connect(function(c) | |
--print(tostring(c)) | |
end) | |
end) | |
local mychar = CreatePlayerModel(player) | |
char = mychar | |
PlayerModels[player.Name] = mychar | |
wait() | |
player.PlayerGui:WaitForChild("Music"):Play() | |
clouds = game.ReplicatedStorage.Clouds:Clone() | |
clouds.CFrame = CFrame.new(char.Torso.Position.X, 67, char.Torso.Position.Z) | |
clouds.Parent = workspace.Ignore | |
local wna = ConVars["mp_startingweapon"][1] | |
local mg = game.ReplicatedStorage.Models[wna]:Clone() | |
mg.Parent = char | |
equippedWeapon = mg | |
weaponCode = require(game.ReplicatedStorage.Weapons[equippedWeapon.Name]) | |
weaponCode.Equip() | |
--[[ | |
local la = mg:FindFirstChild("Left Arm") | |
local ra = mg:FindFirstChild("Right Arm") | |
if la and ra then | |
la.Transparency = 1 | |
ra.Transparency = 1 | |
end]] | |
game:GetService("RunService").Heartbeat:connect(UpdateHeartbeat) | |
game:GetService("RunService").RenderStepped:connect(UpdateRender) | |
--game:GetService("RunService").RenderStepped:connect(UpdateCamera) | |
game:GetService("UserInputService").InputBegan:connect(InputBegan) | |
game:GetService("UserInputService").InputEnded:connect(InputEnded) | |
game:GetService("UserInputService").InputChanged:connect(InputChanged) | |
game.ReplicatedStorage.PlaySoundClient.OnClientEvent:connect(sndLib.PlaySoundClient) | |
game.ReplicatedStorage.TakeDamage.OnClientEvent:connect(TakeDamage) | |
game.ReplicatedStorage.GiveAmmo.OnClientEvent:connect(function(wname, amt) | |
--print("taking "..amt.." ammo for "..wname) | |
PlayerStats.Weapons[wname].Ammo = math.clamp(PlayerStats.Weapons[wname].Ammo + amt, 0, PlayerStats.Weapons[wname].MaxAmmo) | |
end) | |
game.ReplicatedStorage.GiveHealth.OnClientEvent:connect(function(amt) | |
--print("taking "..amt.." health") | |
if amt >= 100 then | |
PlayerStats.Health = math.clamp(PlayerStats.Health + amt, 0, 200) | |
else | |
if PlayerStats.Health + amt < 100 then | |
PlayerStats.Health = math.clamp(PlayerStats.Health + amt, 0, PlayerStats.MaxHealth) | |
else | |
PlayerStats.Health = math.clamp(PlayerStats.Health + amt, 0, 200) | |
end | |
end | |
end) | |
game.ReplicatedStorage.GiveArmor.OnClientEvent:connect(function(amt) | |
--print("taking "..amt.." armor") | |
if amt >= 100 then | |
PlayerStats.Armor = math.clamp(PlayerStats.Armor + amt, 0, 200) | |
else | |
if PlayerStats.Armor + amt < 100 then | |
PlayerStats.Armor = math.clamp(PlayerStats.Armor + amt, 0, PlayerStats.MaxArmor) | |
else | |
PlayerStats.Armor = math.clamp(PlayerStats.Armor + amt, 0, 200) | |
end | |
end | |
end) | |
game.ReplicatedStorage.GiveTime.OnClientEvent:connect(function(amt) | |
CooldownReduction = CooldownReduction + amt | |
end) | |
game.ReplicatedStorage.PlayerRemoving.OnClientEvent:connect(function(plrname) | |
print(plrname.. "left the game") | |
PlayerModels[plrname]:Destroy() | |
for _, frame in pairs(player.PlayerGui.HUD.Scoreboard.Main.PlayerList:GetChildren()) do | |
if frame.Name == plrname then | |
frame:Destroy() | |
end | |
end | |
end) | |
game.ReplicatedStorage.PlayerAdded.OnClientEvent:connect(function(plr) | |
if plr ~= nil then | |
if plr.Name ~= player.Name then | |
PlayerModels[plr.Name] = CreatePlayerModel(plr) | |
end | |
end | |
end) | |
game.ReplicatedStorage.SetPlayerLocation.OnClientEvent:connect(function(cframe) | |
local cf = CFrame.new(cframe.p + Vector3.new(0, 3.5, 0)) | |
playerVelocity = Vector3.new() | |
StopTweens = true | |
char:SetPrimaryPartCFrame(cf) | |
StopTweens = false | |
playerVelocity = Vector3.new() | |
end) | |
game.ReplicatedStorage.CreateKillfeedEntry.OnClientEvent:connect(function(killer, weapon, victim) | |
print(killer.." killed "..victim.." with "..weapon) | |
Orakel.Log(killer.." killed "..victim.." with "..weapon) | |
local kf = game.ReplicatedStorage.Killframe:Clone() | |
kf.Icon.Image = player.PlayerGui.HUD.WeaponsFrame[weapon].Icon.Image | |
kf.Killer.Text = killer | |
kf.Victim.Text = victim | |
local existingEntries = player.PlayerGui.HUD.Killfeed:GetChildren() | |
kf.Position = kf.Position + UDim2.new(0, 0, 0.15 * #existingEntries, 0) | |
spawn(function() | |
wait(3.5) | |
local t = 0 | |
while t <= 1 do | |
local dt = game:GetService("RunService").RenderStepped:wait() | |
t = t + dt | |
kf.Killer.TextTransparency = kf.Killer.TextTransparency + dt | |
kf.Victim.TextTransparency = kf.Victim.TextTransparency + dt | |
kf.Icon.ImageTransparency = kf.Icon.ImageTransparency + dt | |
kf.Icon.BackgroundTransparency = kf.Icon.BackgroundTransparency + dt | |
end | |
kf:Destroy() | |
end) | |
kf.Parent = player.PlayerGui.HUD.Killfeed | |
end) | |
game.ReplicatedStorage.AwardFrag.OnClientEvent:connect(function(killedplayer) | |
--print("awarded frag of "..killedplayer) | |
player.PlayerGui.HUD.FragLabel.Text = "You Fragged "..killedplayer | |
player.PlayerGui.HUD.FragLabel.Visible = true | |
wait(3) | |
player.PlayerGui.HUD.FragLabel.Visible = false | |
end) | |
game.ReplicatedStorage.FireWeaponClient.OnClientEvent:connect(function(shooter, wname, campos, mpos, runserverfire) | |
local w = weaponData[wname] | |
local pm = workspace.Characters:FindFirstChild(shooter.Name) | |
local wm = pm:FindFirstChild(wname) | |
if w and pm and wm then | |
if w.ShootEffect ~= nil and shooter.Name ~= player.Name then | |
w.ShootEffect(wm, mpos) | |
end | |
if w.FireServer ~= nil then | |
w.FireServer(shooter, wm, campos, mpos, player) | |
end | |
end | |
end) | |
game.ReplicatedStorage.AddConMessage.Event:connect(AddConMessage) | |
game.ReplicatedStorage.FireAbilityClient.OnClientEvent:connect(function(shooter, wname, campos, mpos, ability) | |
local ab = require(game.ReplicatedStorage.Abilities[ability]) | |
ab.FireServer(shooter, wname, campos, mpos, player) | |
end) | |
game.ReplicatedStorage.Push.OnClientEvent:connect(function(pushorigin, pushforce) | |
pushVector = (char.PrimaryPart.Position - pushorigin).unit * pushforce | |
end) | |
game.ReplicatedStorage.ToggleInvisibilityClient.Event:connect(function(enabled) | |
charInvisible = enabled | |
end) | |
game.ReplicatedStorage.ToggleBarrierClient.Event:connect(function(enabled) | |
barrierUp = enabled | |
end) | |
game.ReplicatedStorage.PlayerDied.OnClientEvent:connect(OtherPlayerDied) | |
game.ReplicatedStorage.ClearDecals.OnClientEvent:connect(function() | |
npcLib.ClearDecals() | |
end) | |
game.ReplicatedStorage.GameEnded.OnClientEvent:connect(function(scoreboardShowtime, winner) | |
local endMusic | |
canfire = false | |
canwalk = false | |
charInvisible = true | |
scoreboardCanBeToggled = false | |
thirdperson = true | |
player.PlayerGui.HUD.WinLabel.Visible = true | |
player.PlayerGui.HUD.Scoreboard.Visible = true | |
ToggleGameUI(false) | |
if winner then | |
sndLib.PlaySoundClient("global", "winspeech", "rbxassetid://1058507658", 1, 1, false, 4) | |
wait(0.5) | |
endMusic = sndLib.PlaySoundClient("global", "winmusic", "rbxassetid://1040473875", 0.5, 1, true, -1) | |
player.PlayerGui.HUD.WinLabel.Text = "Victory" | |
else | |
endMusic = sndLib.PlaySoundClient("global", "lossmusic", "rbxassetid://1040474024", 0.5, 1, true, -1) | |
player.PlayerGui.HUD.WinLabel.Text = "Defeat" | |
end | |
wait(scoreboardShowtime) | |
charInvisible = false | |
canfire = true | |
canwalk = true | |
endMusic:Stop() | |
endMusic:Destroy() | |
thirdperson = false | |
ToggleGameUI(true) | |
scoreboardCanBeToggled = true | |
player.PlayerGui.HUD.WinLabel.Visible = false | |
player.PlayerGui.HUD.Scoreboard.Visible = false | |
end) | |
events.ToggleConsole.OnClientEvent:connect(function() | |
player.PlayerGui.HUD.Console.Visible = true | |
ConsoleVisible = true | |
player.PlayerGui.HUD.Console.InputBox:CaptureFocus() | |
player.PlayerGui.HUD.Console.InputBox.Text = "" | |
end) | |
Orakel.Log("done initializing client") | |
end | |
function events.GetCurrentWeapon.OnClientInvoke(player, playerToGetFrom) | |
if equippedWeapon ~= nil then | |
return equippedWeapon.Name | |
end | |
return "Machinegun" | |
end | |
function events.GetPlayerHealth.OnClientInvoke() | |
return PlayerStats.Health | |
end | |
function events.GetMouseHit.OnClientInvoke(player, playerToGetFrom) | |
return mouse.Hit.p | |
end | |
function events.GetClientPing.OnClientInvoke() | |
return latency | |
end | |
function events.GetPlayerLocation.OnClientInvoke() | |
return char.Torso.Position, actualMouseHit, CFrame.Angles(0, -mouseAngles.X, 0) | |
end | |
function events.GetPlayerGhosting.OnClientInvoke() | |
return charInvisible | |
end | |
function events.GetPlayerBarrier.OnClientInvoke() | |
return barrierUp | |
end | |
Init() | |
spawn(function() | |
while true do | |
local dt = wait(1/2) | |
local now = ClientTime | |
--Only update SERVER convars | |
local cvars = events.GetSCVars:InvokeServer() | |
for cvar, data in pairs(cvars) do | |
if cvar:sub(1,2) == "sv" or cvar:sub(1,2) == "mp" then | |
ConVars[cvar] = data | |
end | |
end | |
latency = math.abs(mathLib.Round((now - ClientTime) * 1000, 0)) | |
plabel.Visible = ConVars["cl_drawping"][1] | |
plabel.Text = "Ping: "..latency.."ms" | |
if latency >= 110 then | |
plabel.TextColor3 = Color3.new(1, 0, 0) | |
else | |
plabel.TextColor3 = Color3.new(1, 1, 1) | |
end | |
UpdateChat(dt) | |
for _, plr in pairs(game.Players:GetPlayers()) do | |
if plr ~= player then | |
local s,e = pcall(function() | |
PlayerLatencies[plr.UserId] = events.GetClientPing:InvokeServer(plr) | |
end) | |
if not s then | |
Orakel.Log("Failed to ping "..tostring(plr.Name).." "..tostring(plr.UserId), "Error") | |
end | |
else | |
PlayerLatencies[plr.UserId] = latency | |
end | |
end | |
end | |
end) | |
while true do | |
local dt = wait(1/20) | |
--ClientTime = ClientTime + dt | |
--UpdateChat(dt) | |
events.SendPlayerData:FireServer(char.Torso.Position, actualMouseHit, CFrame.Angles(0, -mouseAngles.X, 0), charInvisible, barrierUp, equippedWeapon.Name) | |
UpdateScoreboard(dt) | |
UpdateJumpPadLogic(dt) | |
UpdatePlayerData(dt) | |
UpdatePlayermodels(dt) | |
end | |
Orakel.Log("FATAL WARNING: CLIENT HAS EXITED MAIN LOOP !!!!!!!!!", "Error") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment