From 9ff9b08a42a5615f9ce8fbe7cd01d3a6f4b1655a Mon Sep 17 00:00:00 2001 From: Nikita Kruglickiy Date: Sun, 6 Jun 2021 18:34:44 +0600 Subject: [PATCH] Racelogic, Mustang, Porsche, etc. --- koptilnya/engine_sounds/bmw_e30_exterior.txt | 1 + koptilnya/gui/elements/button.txt | 1 + koptilnya/gui/elements/panel.txt | 1 + koptilnya/gui/gui.txt | 3 +- koptilnya/libs/utils.txt | 46 ++- koptilnya/midi_player/constants.txt | 5 + koptilnya/midi_player/player.txt | 103 +++++++ koptilnya/midi_player/track.txt | 33 ++ koptilnya/models/ford mustang gt 2015.txt | 84 ++++++ koptilnya/models/jdm_wheels.txt | 1 + koptilnya/models/porsche 911 turbo s 2017.txt | 42 +++ koptilnya/models/toyota_altezza.txt | 14 +- koptilnya/racelogic.txt | 247 +++++++++++++++ koptilnya/suspension.txt | 43 +++ koptilnya/torque_editor.txt | 281 ++++++++++-------- koptilnya/vehicle_hud.txt | 4 + 16 files changed, 776 insertions(+), 133 deletions(-) create mode 100644 koptilnya/midi_player/constants.txt create mode 100644 koptilnya/midi_player/player.txt create mode 100644 koptilnya/midi_player/track.txt create mode 100644 koptilnya/models/ford mustang gt 2015.txt create mode 100644 koptilnya/models/porsche 911 turbo s 2017.txt create mode 100644 koptilnya/racelogic.txt create mode 100644 koptilnya/suspension.txt create mode 100644 koptilnya/vehicle_hud.txt diff --git a/koptilnya/engine_sounds/bmw_e30_exterior.txt b/koptilnya/engine_sounds/bmw_e30_exterior.txt index fa0dbed..53760b0 100644 --- a/koptilnya/engine_sounds/bmw_e30_exterior.txt +++ b/koptilnya/engine_sounds/bmw_e30_exterior.txt @@ -46,6 +46,7 @@ else fadeIn = Vector(6500, 7000) } }) + engineSound:setMasterVolume(1.3) net.receive("rpm", function(len) engineSound:setRPM(net.readFloat()) diff --git a/koptilnya/gui/elements/button.txt b/koptilnya/gui/elements/button.txt index ad8df3f..4c62d11 100644 --- a/koptilnya/gui/elements/button.txt +++ b/koptilnya/gui/elements/button.txt @@ -9,6 +9,7 @@ EButton:include(require("radius_mixin.txt")) function EButton:initialize() ELabel.initialize(self) + self:setFont(GUI.fonts.mainBold) self:setText("Button") self:setSize(100, 32) self:setRoundedCorners(true) diff --git a/koptilnya/gui/elements/panel.txt b/koptilnya/gui/elements/panel.txt index 2d9281f..7848532 100644 --- a/koptilnya/gui/elements/panel.txt +++ b/koptilnya/gui/elements/panel.txt @@ -24,6 +24,7 @@ function EPanel:initialize() self._lastHeight = 0 self.title = ELabel:new() + self.title:setFont(GUI.fonts.mainBold) self.title:setPos(12, 8) self:addChild(self.title) diff --git a/koptilnya/gui/gui.txt b/koptilnya/gui/gui.txt index 443931e..5838a1e 100644 --- a/koptilnya/gui/gui.txt +++ b/koptilnya/gui/gui.txt @@ -7,7 +7,8 @@ require("elements/root.txt") GUI = class("GUI") GUI.static.fonts = { - main = render.createFont("Roboto", 16, 700, true), + main = render.createFont("Roboto", 16, 400, true), + mainBold = render.createFont("Roboto", 16, 700, true), icons = render.createFont("Segoe MDL2 Assets", 16, 400, true, false, false, false, false, true) } diff --git a/koptilnya/libs/utils.txt b/koptilnya/libs/utils.txt index a4947b1..9d36f2d 100644 --- a/koptilnya/libs/utils.txt +++ b/koptilnya/libs/utils.txt @@ -1,5 +1,4 @@ -- @name koptilnya/libs/utils - function checkVarClass(var, class, message) if type(var) ~= "table" or var["class"] == nil or not var:isInstanceOf(class) then throw(message == nil and "Wrong variable class." or message, 1, true) @@ -24,3 +23,48 @@ function rotateAround(entity, pivot, angles) pos = pos + (pivot - entity:localToWorld(localPivotPos)) entity:setPos(pos) end + +function tobase(number, base) + local ret = "" + + if base < 2 or base > 36 or number == 0 then + return "0" + end + + if base == 10 then + return tostring(number) + end + + local chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + local loops = 0 + while number > 0 do + loops = loops + 1 + number, d = math.floor(number / base), (number % base) + 1 + ret = string.sub(chars, d, d) .. ret + if (loops > 32000) then + break + end + end + return ret +end + +function bytesToHex(bytes) + local hex = "0x" + + for _, v in pairs(bytes) do + hex = hex .. bit.tohex(v, 2) + end + + return hex +end + +function byteTable(str, start, length) + local result = {} + + for i = 1, length do + result[i] = string.byte(str, i + start - 1) + end + + return result +end + diff --git a/koptilnya/midi_player/constants.txt b/koptilnya/midi_player/constants.txt new file mode 100644 index 0000000..08d935f --- /dev/null +++ b/koptilnya/midi_player/constants.txt @@ -0,0 +1,5 @@ +local TABLE = { + HEADER_CHUNK_LENGTH = 14 +} + +return TABLE \ No newline at end of file diff --git a/koptilnya/midi_player/player.txt b/koptilnya/midi_player/player.txt new file mode 100644 index 0000000..faddb0b --- /dev/null +++ b/koptilnya/midi_player/player.txt @@ -0,0 +1,103 @@ +-- @include constants.txt +-- @include track.txt +-- @include /koptilnya/libs/utils.txt +require("track.txt") +require("/koptilnya/libs/utils.txt") + +local CONSTANTS = require("constants.txt") + +function byteToHex(byte) + return tostring(byte) +end + +MidiPlayer = class("MidiPlayer") + +function MidiPlayer:initialize() + self._startTime = 0 + self._buffer = nil + self._midiChunksByteLength = nil + self._division = 0 + self._format = nil + self._setIntervalId = false + self._tracks = {} + self._instruments = {} + self._defaultTempo = 120 + self._tempo = null + self._startTick = 0 + self._tick = 0 + self._lastTick = null + self._inLoop = false + self._totalTicks = 0 + self._events = {} + self._totalEvents = 0 + self._eventListeners = {} +end + +function MidiPlayer:loadURL(link) + if not http.canRequest() then + return + end + + http.get(link, function(data, len) + self._buffer = data + + self:_fileLoaded() + end) +end + +function MidiPlayer:_fileLoaded() + if not self:isValid() then + throw("Invalid MIDI file; should start with MThd") + end + + self:setTempo(self._defaultTempo) + self:_parseDivision() + self:_parseFormat() + self:_parseTracks() +end + +function MidiPlayer:isValid() + return string.char(unpack(byteTable(self._buffer, 1, 4))) == "MThd" +end + +function MidiPlayer:setTempo(tempo) + self._tempo = tempo +end + +function MidiPlayer:_parseDivision() + self._division = tonumber(bytesToHex(byteTable(self._buffer, 13, 2))) +end + +function MidiPlayer:_parseFormat() + self._format = tonumber(bytesToHex(byteTable(self._buffer, 9, 2))) +end + +function MidiPlayer:_parseTracks() + self._tracks = {} + + local offset = 1 + + while offset < #self._buffer do + local length = tonumber(bytesToHex(byteTable(self._buffer, offset + 4, 4))) + + if string.char(unpack(byteTable(self._buffer, offset, 4))) == "MTrk" then + table.insert(self._tracks, MidiTrack:new(#self._tracks + 1, string.sub(self._buffer, offset + 8, offset + 8 + length))) + end + + offset = offset + length + 8 + end +end + +function MidiPlayer:resetTracks() + for _, v in pairs(self._tracks) do + v:reset() + end +end + +function MidiPlayer:enableTrack(id) + self._tracks[id]:enable() +end + +function MidiPlayer:disableTrack(id) + self._tracks[id]:disable() +end \ No newline at end of file diff --git a/koptilnya/midi_player/track.txt b/koptilnya/midi_player/track.txt new file mode 100644 index 0000000..2c715ca --- /dev/null +++ b/koptilnya/midi_player/track.txt @@ -0,0 +1,33 @@ +MidiTrack = class("MidiTrack") + +function MidiTrack:initialize(index, data) + self._enabled = true; + self._eventIndex = 0; + self._pointer = 0; + self._lastTick = 0; + self._lastStatus = nil; + self._index = index; + self._data = data; + self._delta = 0; + self._runningDelta = 0; + self._events = {}; +end + +function MidiTrack:reset() + self._enabled = true; + self._eventIndex = 0; + self._pointer = 0; + self._lastTick = 0; + self._lastStatus = null; + self._delta = 0; + self._runningDelta = 0; +end + +function MidiTrack:enable() + self._enabled = true +end + +function MidiTrack:disable() + self._enabled = false +end + diff --git a/koptilnya/models/ford mustang gt 2015.txt b/koptilnya/models/ford mustang gt 2015.txt new file mode 100644 index 0000000..238de28 --- /dev/null +++ b/koptilnya/models/ford mustang gt 2015.txt @@ -0,0 +1,84 @@ +-- @shared +-- @name Ford Mustang GT 2015 +-- @author Opti1337, DarkSupah +-- @include /koptilnya/mesh_loader/builder.txt +require("/koptilnya/mesh_loader/builder.txt") + +DEBUG_MODE = true + +local LINK = "https://www.dropbox.com/s/mw882znuj8c83ek/mustang.obj?dl=1" +local SCALE = Vector(1) +local MATERIALS = { + Interior = "models/debug/debugwhite", + Torpedo = "models/debug/debugwhite", + Seats = "models/debug/debugwhite", + SteeringWheelAndDoors = "models/debug/debugwhite", + Stripes = "models/debug/debugwhite", + DashboardDetails = "models/debug/debugwhite", + SteeringWheelControls = "models/debug/debugwhite", + Bottom = "models/debug/debugwhite", + Bottom2 = "models/debug/debugwhite", + ExteriorDetails = "models/debug/debugwhite", + Body = "models/shiny", + MirrorsAndExhaust = "models/debug/debugwhite", + Lights = "models/debug/debugwhite", + Glass = "phoenix_storms/glass", + ExteriorDetails2 = "models/debug/debugwhite" +} +local COLORS = { + Interior = Color(40, 40, 40), + Torpedo = Color(50, 50, 50), + Seats = Color(50, 50, 50), + SteeringWheelAndDoors = Color(55, 55, 55), + Stripes = Color(10, 10, 10), + DashboardDetails = Color(130, 130, 130), + SteeringWheelControls = Color(25, 25, 25), + Bottom = Color(0, 0, 0), + Bottom2 = Color(0, 0, 0), + ExteriorDetails = Color(120, 120, 120), + Body = Color(245, 221, 31), + MirrorsAndExhaust = Color(255, 255, 255), + Lights = Color(255, 255, 255), + Glass = Color(255, 255, 255), + ExteriorDetails2 = Color(130, 130, 130) +} + +local builder = {} + +if SERVER then + builder = MeshBuilder:new(LINK) + + builder:build("Interior_body1_model0", Vector(0), Angle(0), SCALE, COLORS.Interior, MATERIALS.Interior, chip(), chip()) + builder:build("Torpedo_body1_model0.001", Vector(0), Angle(0), SCALE, COLORS.Torpedo, MATERIALS.Torpedo, chip(), chip()) + builder:build("Seats_body1_model0.002", Vector(0), Angle(0), SCALE, COLORS.Seats, MATERIALS.Seats, chip(), chip()) + builder:build("SteeringWheelAndDoors_body1_model0.003", Vector(0), Angle(0), SCALE, COLORS.SteeringWheelAndDoors, MATERIALS.SteeringWheelAndDoors, chip(), chip()) + builder:build("Stripes_body1_model0.004", Vector(0), Angle(0), SCALE, COLORS.Stripes, MATERIALS.Stripes, chip(), chip()) + builder:build("DashboardDetails_body1_model0.005", Vector(0), Angle(0), SCALE, COLORS.DashboardDetails, MATERIALS.DashboardDetails, chip(), chip()) + builder:build("SteeringWheelControls_body1_model0.006", Vector(0), Angle(0), SCALE, COLORS.SteeringWheelControls, MATERIALS.SteeringWheelControls, chip(), chip()) + builder:build("Bottom_body1_model0.007", Vector(0), Angle(0), SCALE, COLORS.Bottom, MATERIALS.Bottom, chip(), chip()) + builder:build("Bottom2_body1_model0.008", Vector(0), Angle(0), SCALE, COLORS.Bottom2, MATERIALS.Bottom2, chip(), chip()) + builder:build("ExteriorDetails2_body1_model0.009", Vector(0), Angle(0), SCALE, COLORS.ExteriorDetails2, MATERIALS.ExteriorDetails2, chip(), chip()) + builder:build("Body_body1_model0.010", Vector(0), Angle(0), SCALE, COLORS.Body, MATERIALS.Body, chip(), chip()) + builder:build("MirrorsAndExhaust_body1_model0.011", Vector(0), Angle(0), SCALE, COLORS.MirrorsAndExhaust, MATERIALS.MirrorsAndExhaust, chip(), chip()) + builder:build("Lights_body1_model0.012", Vector(0), Angle(0), SCALE, COLORS.Lights, MATERIALS.Lights, chip(), chip()) + builder:build("Glass_body1_model0.013", Vector(0), Angle(0), SCALE, COLORS.Glass, MATERIALS.Glass, chip(), chip()) + builder:build("ExteriorDetails_body1_model0.014", Vector(0), Angle(0), SCALE, COLORS.ExteriorDetails, MATERIALS.ExteriorDetails, chip(), chip()) + + local result = builder:getResult() +else + function init() + builder = MeshBuilder:new(LINK) + end + + if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then + init() + else + setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true) + + hook.add("permissionrequest", "_permissionrequest", function() + if permissionRequestSatisfied() then + init() + end + end) + end +end diff --git a/koptilnya/models/jdm_wheels.txt b/koptilnya/models/jdm_wheels.txt index 6a8f309..45afea5 100644 --- a/koptilnya/models/jdm_wheels.txt +++ b/koptilnya/models/jdm_wheels.txt @@ -25,6 +25,7 @@ local COLORS = { } local OFFSET = 1 + local builder = {} if SERVER then diff --git a/koptilnya/models/porsche 911 turbo s 2017.txt b/koptilnya/models/porsche 911 turbo s 2017.txt new file mode 100644 index 0000000..1de659c --- /dev/null +++ b/koptilnya/models/porsche 911 turbo s 2017.txt @@ -0,0 +1,42 @@ +-- @shared +-- @name Porsche 911 Turbo S 2017 +-- @author Opti1337, DarkSupah +-- @include /koptilnya/mesh_loader/builder.txt +require("/koptilnya/mesh_loader/builder.txt") + +DEBUG_MODE = true + +local LINK = "https://www.dropbox.com/s/bo7myjv0ekkcbf6/911.obj?dl=1" +local SCALE = Vector(0.9) + +local builder = {} + +if SERVER then + builder = MeshBuilder:new(LINK) + builder.onObjectParsed = function(builder, objectsNames) + timer.simple(3, function() + for k, v in pairs(objectsNames) do + + builder:build(v, Vector(0), Angle(0), SCALE, Color(360 / #objectsNames * k, 1, 1):hsvToRGB(), "models/debug/debugwhite", chip(), chip()) + end + + local result = builder:getResult() + end) + end +else + function init() + builder = MeshBuilder:new(LINK) + end + + if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then + init() + else + setupPermissionRequest({"http.get", "mesh", "entities.setRenderProperty"}, "", true) + + hook.add("permissionrequest", "_permissionrequest", function() + if permissionRequestSatisfied() then + init() + end + end) + end +end diff --git a/koptilnya/models/toyota_altezza.txt b/koptilnya/models/toyota_altezza.txt index eaa32c5..d5788e6 100644 --- a/koptilnya/models/toyota_altezza.txt +++ b/koptilnya/models/toyota_altezza.txt @@ -14,7 +14,7 @@ local builder = {} if SERVER then builder = MeshBuilder:new(LINK) - builder:build("body_Mesh_0", Vector(0), Angle(0), SCALE, Color(54, 225, 220), "models/debug/debugwhite", chip(), chip()) + builder:build("body_Mesh_0", Vector(0), Angle(0), SCALE, Color(40, 40, 40), "models/debug/debugwhite", chip(), chip()) builder:build("chrome_Mesh_1", Vector(0), Angle(0), SCALE, Color(255, 255, 255), "sprops/textures/sprops_chrome", chip(), chip()) builder:build("glass_Mesh_2", Vector(0), Angle(0), SCALE, Color(55, 55, 55, 200), "models/debug/debugwhite", chip(), chip()) builder:build("hood_Mesh_3", Vector(0), Angle(0), SCALE, Color(255, 255, 255, 255), "sprops/textures/sprops_cfiber2", chip(), chip()) @@ -28,6 +28,18 @@ if SERVER then else function init() builder = MeshBuilder:new(LINK) + builder.onHologramsReceived = function(builder, objects) + local mat = material.create("VertexLitGeneric") + mat:setTextureURL("$basetexture", "https://i.imgur.com/gw4kfYv.jpg", + function(m, url, w, h, layout) + layout(0, 0, 2048, 2048) + end, + function(m, url) + objects[1].holo:setMaterial("") + objects[1].holo:setMeshMaterial(m) + end + ) + end end if hasPermission("http.get") and hasPermission("mesh") and hasPermission("entities.setRenderProperty", chip()) then diff --git a/koptilnya/racelogic.txt b/koptilnya/racelogic.txt new file mode 100644 index 0000000..72f405e --- /dev/null +++ b/koptilnya/racelogic.txt @@ -0,0 +1,247 @@ +--@name RaceLogic +--@author Opti1337 +--@server +--@model models/sprops/cuboids/height06/size_1/cube_6x6x6.mdl + +local digitsColor = Color(255, 128, 0) +local backgroundColor = Color(0, 0, 0) +local bodyColor = Color(40, 40, 40) + +local holdDuration = 2 + +local reachSoundPath = "buttons/blip2.wav"--"garrysmod/ui_click.wav" +local resetSoundPath = "buttons/combine_button7.wav" + +local lastResultsCount = 3 +local printResultBeforeReset = true + +------------------------------------ + +local METER = 39.37 + +local speedometerNumbers = {} +local timerNumbers = {} +local timerDot = {} +local active = false +local hold = false +local startTime = 0 +local holdTime = 0 +local currentResult = { + triggers = { + [30] = { + reached = false, + reachTime = 0, + time = 0 + }, + [60] = { + reached = false, + reachTime = 0, + time = 0 + }, + [100] = { + reached = false, + reachTime = 0, + time = 0 + }, + [200] = { + reached = false, + reachTime = 0, + time = 0 + } + }, + maxSpeed = 0 +} +local results = {} + +function buildBody() + local background = holograms.create(chip():getPos(), chip():localToWorldAngles(Angle(90, 0, 0)), "models/holograms/plane.mdl") + background:setSize(Vector(METER * 0.04, METER * 0.2, 1)) + background:setMaterial("models/debug/debugwhite") + background:setColor(backgroundColor) + background:suppressEngineLighting(true) + background:setParent(chip()) + + local body = holograms.create(chip():getPos(), chip():localToWorldAngles(Angle(90, 0, 0)), "models/props_junk/PlasticCrate01a.mdl") + body:setSize(Vector(METER * 0.042, METER * 0.21, 1)) + body:setMaterial("models/debug/debugwhite") + body:setColor(bodyColor) + body:setParent(chip()) +end + +function buildSpeedometer() + local xOffset = -METER * 0.085 + for i = 0, 2 do + local number = holograms.create(chip():localToWorld(Vector(0, xOffset + i * METER * 0.03)), chip():localToWorldAngles(Angle(0, -90, 0)), "models/sprops/misc/alphanum/alphanum_0.mdl") + number:setSize(Vector(METER * 0.03, METER * 0.005, METER * 0.03)) + number:setBodygroup(0, 3) + number:setMaterial("models/debug/debugwhite") + number:setColor(digitsColor) + number:suppressEngineLighting(true) + number:setParent(chip()) + + table.insert(speedometerNumbers, number) + end +end + +function buildTimer() + local xOffset = METER * 0.025 + for i = 0, 2 do + local number = holograms.create(chip():localToWorld(Vector(0, xOffset + i * METER * 0.03)), chip():localToWorldAngles(Angle(0, -90, 0)), "models/sprops/misc/alphanum/alphanum_0.mdl") + number:setSize(Vector(METER * 0.03, METER * 0.005, METER * 0.03)) + number:setBodygroup(0, 3) + number:setMaterial("models/debug/debugwhite") + number:setColor(digitsColor) + number:suppressEngineLighting(true) + number:setParent(chip()) + + table.insert(timerNumbers, number) + + if i == 1 then + local dot = holograms.create(chip():localToWorld(Vector(0, xOffset + i * METER * 0.03 + METER * 0.012)), chip():localToWorldAngles(Angle(0, -90, 0)), "models/sprops/misc/alphanum/alphanum_prd.mdl") + dot:setSize(Vector(METER * 0.03, METER * 0.005, METER * 0.03)) + dot:setBodygroup(0, 3) + dot:setMaterial("models/debug/debugwhite") + dot:setColor(digitsColor) + dot:suppressEngineLighting(true) + dot:setParent(chip()) + + timerDot = dot + end + end +end + +function setSpeed(value) + value = math.clamp(value, 0, 999) + value = math.round(value) + + local str = string.rep("0", 3 - #tostring(value)) .. value + + for k, v in pairs(speedometerNumbers) do + v:setModel("models/sprops/misc/alphanum/alphanum_" .. string.sub(str, k, k) ..".mdl") + end +end + +function setTime(value) + value = math.clamp(value, 0, 99.9) + + local i, f = math.modf(value) + f = math.floor(f * 10) + + local str = string.rep("0", 2 - #tostring(i)) .. i .. f + + for k, v in pairs(timerNumbers) do + v:setModel("models/sprops/misc/alphanum/alphanum_" .. string.sub(str, k, k) ..".mdl") + end +end + +function hasResult() + return currentResult.triggers[math.min(unpack(table.getKeys(currentResult.triggers)))].reached +end + +function reset() + active = false + + if hasResult() then + chip():emitSound(resetSoundPath) + end + + for k, v in pairs(currentResult.triggers) do + v.reached = false + v.reachTime = 0 + v.time = 0 + end + + currentResult.maxSpeed = 0 + + setTime(0) + setSpeed(0) +end + +function saveResult() + table.remove(results, lastResultsCount) + table.insert(results, 1, table.copy(currentResult)) +end + +function printResult(result) + local format = "%d-%d km/h - %.02fs" + local orderedTriggerKeys = table.getKeys(result.triggers) + + table.sort(orderedTriggerKeys) + + for _, v in pairs(orderedTriggerKeys) do + local trigger = result.triggers[v] + + if trigger.reached then + print(Color(255, 255, 255), string.format(format, 0, v, trigger.time)) + end + end + + if result.triggers[200].reached then + print(Color(255, 255, 255), string.format(format, 100, 200, math.abs(result.triggers[200].time - result.triggers[100].time))) + end + + print(Color(200, 200, 200), string.format("Max speed: %.02f km/h", result.maxSpeed)) +end + +hook.add("tick", "_tick", function() + local weldedTo = chip():isWeldedTo() + + if isValid(weldedTo) and not weldedTo:isPlayerHolding() then + local localVelocity = weldedTo:worldToLocal(weldedTo:getVelocity() + weldedTo:getPos()) + local localVelocityLength = localVelocity:getLength() + local MPH = localVelocityLength * 3600 / 63360 + local KPH = MPH * 1.609 + + if KPH < 1 and active then + if hasResult() then + saveResult() + + if printResultBeforeReset then + print(Color(255, 128, 0), "Result:") + printResult(currentResult) + end + end + + reset() + elseif not active and MPH >= 1 then + active = true + startTime = timer.systime() + end + + if active then + currentResult.maxSpeed = math.max(currentResult.maxSpeed, KPH) + + for k, v in pairs(currentResult.triggers) do + if KPH >= k and not v.reached then + local time = timer.systime() + + v.reached = true + v.reachTime = time + v.time = time - startTime + hold = true + holdTime = time + + chip():emitSound(reachSoundPath) + + setSpeed(k) + setTime(time - startTime) + end + end + + if hold and holdTime + holdDuration <= timer.systime() then + hold = false + end + + if not hold then + setSpeed(KPH) + setTime(timer.systime() - startTime) + end + end + end +end) + +chip():setColor(Color(0, 0, 0, 0)) + +buildBody() +buildSpeedometer() +buildTimer() diff --git a/koptilnya/suspension.txt b/koptilnya/suspension.txt new file mode 100644 index 0000000..4695d55 --- /dev/null +++ b/koptilnya/suspension.txt @@ -0,0 +1,43 @@ +--@name Suspension +--@author Opti1337, .hemp +--@server + + +local lock = 70 +local caster = 0 +local camber = 0 +local accerman = 0 + +--------------------------- + +local base, steerWheels, otherWheels + +wire.adjustPorts( + { + Base = "ENTITY", + SteerWheels = "ARRAY", + OtherWheels = "ARRAY" + }, + {} +) + +hook.add("input", "_input", function(name, value) + + if name == "Base" then + base = value + elseif name == "SteerWheels" or name == "OtherWheels" then + if isValid(base) then + base:setAngles(Angle(0, 90, 0)) + end + + if name == "SteerWheels" then + steerWheels = value + else + otherWheels = value + end + end +end) + +hook.add("tick", "_tick", function() + +end) diff --git a/koptilnya/torque_editor.txt b/koptilnya/torque_editor.txt index 668f8cc..e523e32 100644 --- a/koptilnya/torque_editor.txt +++ b/koptilnya/torque_editor.txt @@ -9,7 +9,7 @@ -- @include /koptilnya/gui/elements/shape.txt -- @include /koptilnya/gui/elements/button.txt -- @include /koptilnya/gui/segoe_mdl2_assets_icons.txt -local points = {Vector(0, 0)} +local points = {Vector(0, 0), Vector(100, 0)} local zoom = 1 local zoomBase = 100 local scroll = 0 @@ -254,7 +254,7 @@ local function removePoint() end end -local function getTorqueAt(t) +local function getYAt(t) if #points == 0 then return 0 end @@ -281,23 +281,27 @@ local function getTorqueAt(t) end end -local function exportPoints() +local function exportPoints(asE2Array) if not hasPermission("file.write") then return end + + asE2Array = asE2Array or false local result = "" + local prefix = asE2Array and "array(" or "{" + local suffix = asE2Array and ")" or "}" + local vecSyntax = asE2Array and "vec2" or "Vector" for k, v in pairs(points) do - result = result .. "\tVector(" .. (v.x / 100) .. ", " .. v.y .. ")" + result = result .. "\t" .. vecSyntax .. "(" .. (v.x / 100) .. ", " .. v.y .. ")" if k ~= #points then result = result .. ",\n" end end - - result = "array(\n" .. result - result = result .. "\n)" + + result = string.format("%s\n%s\n%s", prefix, result, suffix) file.write("torque_export_result.txt", result) end @@ -310,7 +314,7 @@ local function exportTorqueMap() local result = "" for i = 0, 100 do - result = result .. "\t" .. getTorqueAt(i) + result = result .. "\t" .. getYAt(i) if i ~= 100 then result = result .. ",\n" @@ -323,74 +327,85 @@ local function exportTorqueMap() file.write("torque_export_result.txt", result) end -net.receive("setUser", function() - net.readEntity(function(ent) - user = ent - end) -end) +local renderDevice = RenderDeviceHUD:new() +local scrW, scrH = 1920, 1080 -net.receive("resetUser", function() - user = nil -end) +local gui = GUI:new(renderDevice) +local w, h = 190, 226 +local panel = EPanel:new() +panel:setTitle("Torque Editor") +panel:setDraggable(false) +panel:setMinimizable(false) +panel:setCloseable(false) +panel:setPos(scrW - w - 20, scrH - h - 20) +panel:setSize(w, h) +gui:add(panel) -net.receive("init", function() - zoom = net.readFloat() - scroll = net.readFloat() - points = net.readTable() -end) - -net.receive("settings", function() - zoom = net.readFloat() - scroll = net.readFloat() -end) - -net.receive("points", function() - points = net.readTable() -end) - -hook.add("hudconnected", "_hudconnected", function() - -- renderDevice:setPlayer() - if not hasPermission("file.write") or not hasPermission("file.read") then - sendPermissionRequest() +local importButton = EButton:new() +importButton:setPos(11, 43) +importButton:setSize(w - 22, 24) +importButton:setText("Import") +importButton.onMousePressed = function(_, x, y, key, keyName) + if keyName == "MOUSE1" then end -end) +end +panel:addChild(importButton) -hook.add("huddisconnected", "_huddisconnected", function() -end) +local dividerShape = EShape:new() +dividerShape:setPos(11, 82) +dividerShape:setSize(w - 22, 1) +dividerShape:setColor(Color(60, 60, 60)) +panel:addChild(dividerShape) -hook.add("inputPressed", "_inputPressed", function(button) - if not hasPermission("input") then - return +local exportLabel = ELabel:new() +exportLabel:setPos(11, 97) +exportLabel:setFont(GUI.fonts.mainBold) +exportLabel:setText("Export as") +panel:addChild(exportLabel) + +local pointsArrayLabel = ELabel:new() +pointsArrayLabel:setPos(11, 126) +pointsArrayLabel:setText("Points array") +pointsArrayLabel:setColorScheme(Color(200, 200, 200)) +panel:addChild(pointsArrayLabel) + +local exportE2ArrayButton = EButton:new() +exportE2ArrayButton:setPos(w - 91, 123) +exportE2ArrayButton:setText("E2") +exportE2ArrayButton:setSize(35, 24) +exportE2ArrayButton.onMousePressed = function(_, x, y, key, keyName) + if keyName == "MOUSE1" then + exportPoints(true) end +end +panel:addChild(exportE2ArrayButton) - if player() == user then - local keyName = input.getKeyName(button) - - if keyName == "t" then - input.enableCursor(input.getCursorVisible()) - elseif keyName == "MOUSE1" then - if not input.getCursorVisible() then - addPoint() - end - elseif keyName == "MOUSE2" then - if not input.getCursorVisible() then - removePoint() - end - elseif keyName == "MWHEELUP" then - if input.isShiftDown() then - zoomIn() - else - scrollUp() - end - elseif keyName == "MWHEELDOWN" then - if input.isShiftDown() then - zoomOut() - else - scrollDown() - end - end +local exportSFArrayButton = EButton:new() +exportSFArrayButton:setPos(w - 46, 123) +exportSFArrayButton:setText("SF") +exportSFArrayButton:setSize(35, 24) +exportSFArrayButton.onMousePressed = function(_, x, y, key, keyName) + if keyName == "MOUSE1" then + exportPoints() end -end) +end +panel:addChild(exportSFArrayButton) + +local exportMapButton = EButton:new() +exportMapButton:setPos(11, 157) +exportMapButton:setText("Torque map") +exportMapButton:setSize(w - 22, 24) +exportMapButton.onMousePressed = function(_, x, y, key, keyName) + if keyName == "MOUSE1" then + exportTorqueMap() + end +end +panel:addChild(exportMapButton) + +local pointsCountLabel = ELabel:new() +pointsCountLabel:setPos(11, 200) +pointsCountLabel:setText("Points count: " .. #points) +panel:addChild(pointsCountLabel) hook.add("render", "_render", function() local cursorX, cursorY @@ -497,84 +512,90 @@ hook.add("render", "_render", function() prevPointData = {point = point, x = x, y = y} end - --[[ + local t = (math.cos(timer.curtime() * 0.5) + 1) / 2 * 100 - x, y = fromWorkspacePos(cellSize.x * t, (workspace.h - 1) / (zoomBase / zoom) * getTorqueAt(t) - ((workspace.h - 1) / 10 * scroll)) + x, y = fromWorkspacePos(cellSize.x * t, (workspace.h - 1) / (zoomBase / zoom) * getYAt(t) - ((workspace.h - 1) / 10 * scroll)) render.setColor(Color(0, 0, 255, 180)) render.drawRect(x - 3, y - 3, 7, 7) render.drawRect(x, workspace.y, 1, workspace.h) - ]] end) -local renderDevice = RenderDeviceHUD:new() -local scrW, scrH = 1920, 1080 +net.receive("setUser", function() + net.readEntity(function(ent) + user = ent + end) +end) -local gui = GUI:new(renderDevice) +net.receive("resetUser", function() + user = nil +end) -local panel = EPanel:new() -panel:setTitle("Torque Editor") -panel:setDraggable(false) -panel:setMinimizable(false) -panel:setCloseable(false) -panel:setPos(scrW - 180 - 20, scrH - 226 - 20) -panel:setSize(180, 226) -gui:add(panel) +net.receive("init", function() + zoom = net.readFloat() + scroll = net.readFloat() + points = net.readTable() +end) -local importButton = EButton:new() -importButton:setPos(11, 43) -importButton:setSize(158, 24) -importButton:setText("Import") -importButton.onMousePressed = function(_, x, y, key, keyName) - if keyName == "MOUSE1" then +net.receive("settings", function() + zoom = math.round(net.readFloat() * 100) / 100 + scroll = math.round(net.readFloat() * 100) / 100 + + +end) + +net.receive("points", function() + points = net.readTable() + + pointsCountLabel:setText("Points count: " .. #points) +end) + +hook.add("hudconnected", "_hudconnected", function() + -- renderDevice:setPlayer() + if not hasPermission("file.write") or not hasPermission("file.read") then + sendPermissionRequest() end -end -panel:addChild(importButton) +end) -local dividerShape = EShape:new() -dividerShape:setPos(11, 82) -dividerShape:setSize(158, 1) -dividerShape:setColor(Color(60, 60, 60)) -panel:addChild(dividerShape) +hook.add("huddisconnected", "_huddisconnected", function() +end) -local exportLabel = ELabel:new() -exportLabel:setPos(11, 97) -exportLabel:setText("Export as") -panel:addChild(exportLabel) - ---[[ -local exportCurveButton = EButton:new() -exportCurveButton:setPos(11, 123) -exportCurveButton:setText("Points array") -exportCurveButton:setSize(158, 24) -exportCurveButton.onMousePressed = function(_, x, y, key, keyName) - if keyName == "MOUSE1" then - exportPoints() +hook.add("inputPressed", "_inputPressed", function(button) + if not hasPermission("input") then + return end -end -panel:addChild(exportCurveButton) -]] -local pointsArrayLabel = ELabel:new() -pointsArrayLabel:setPos(11, 123) -pointsArrayLabel:setText("Points array") -pointsArrayLabel:setColorScheme(Color(200, 200, 200)) -panel:addChild(pointsArrayLabel) + if player() == user then + local keyName = input.getKeyName(button) -local exportMapButton = EButton:new() -exportMapButton:setPos(11, 157) -exportMapButton:setText("Torque map") -exportMapButton:setSize(158, 24) -exportMapButton.onMousePressed = function(_, x, y, key, keyName) - if keyName == "MOUSE1" then - exportTorqueMap() + if keyName == "t" then + input.enableCursor(!input.getCursorVisible()) + elseif keyName == "MOUSE1" then + if not input.getCursorVisible() then + addPoint() + + pointsCountLabel:setText("Points count: " .. #points) + end + elseif keyName == "MOUSE2" then + if not input.getCursorVisible() then + removePoint() + + pointsCountLabel:setText("Points count: " .. #points) + end + elseif keyName == "MWHEELUP" then + if input.isShiftDown() then + zoomIn() + else + scrollUp() + end + elseif keyName == "MWHEELDOWN" then + if input.isShiftDown() then + zoomOut() + else + scrollDown() + end + end end -end -panel:addChild(exportMapButton) - -local pointsCountLabel = ELabel:new() -pointsCountLabel:setPos(11, 200) -pointsCountLabel:setText("Points count: " .. #points) -panel:addChild(pointsCountLabel) +end) diff --git a/koptilnya/vehicle_hud.txt b/koptilnya/vehicle_hud.txt new file mode 100644 index 0000000..4d48239 --- /dev/null +++ b/koptilnya/vehicle_hud.txt @@ -0,0 +1,4 @@ +--@name Vehicle HUD +--@author Opti1337 +--@shared +