[READ-ONLY] Mirror of https://github.com/thoda-dev/du-elevator. a generic elevator script for Dual Universe
0

Configure Feed

Select the types of activity you want to include in your feed.

version 1.0.0

Thomas (Jul 22, 2023, 3:49 PM +0200) 58a1f080 cf612a19

+470
+12
.github/FUNDING.yml
··· 1 + # These are supported funding model platforms 2 + 3 + github: Jericho1060 4 + patreon: # Replace with a single Patreon username 5 + open_collective: # Replace with a single Open Collective username 6 + ko_fi: jericho1060 7 + tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 + community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 + liberapay: # Replace with a single Liberapay username 10 + issuehunt: # Replace with a single IssueHunt username 11 + otechie: # Replace with a single Otechie username 12 + custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+57
README.MD
··· 1 + # DU-ELEVATOR 2 + 3 + A Generic Elevator script for Dual universe 4 + 5 + # Guilded Server (better than Discord) 6 + 7 + You can join me on Guilded for help or suggestions or requests by following that link : https://guilded.jericho.dev 8 + 9 + # Discord Server 10 + 11 + You can join me on Discord for help or suggestions or requests by following that link : https://discord.gg/qkdjyqDZQZ 12 + 13 + # Instalation 14 + 15 + ### Important notice 16 + 17 + - the script was only tested on a remote control 18 + 19 + ### Links 20 + 21 + You must link the following elements to the remote control (order doesn't matter, the script will detect them automatically): 22 + - Link the core to the remote control 23 + - Link the fuel tank to the remote control (only if you want to see the fuel gauge) 24 + 25 + ### Setup 26 + 27 + - you need at least a vertical engine pointing the bottom 28 + - you need at least one engine on each horizontal direction (forward, right, left, backward) 29 + - you need at least 3 adjustors on each angles of the construct : (see picture below) 30 + - one pointing up (this one is used for autoroll and autopitch) 31 + - one pointing on one side (this one is used for autoyaw) 32 + - one pointing on the orther side of the angle (this one is used for autoyaw) 33 + - ![Adustors Positioning](./images/adjustors.png) 34 + 35 + ### Installation of the script 36 + 37 + - copy the content of the config.json file and paste it on the remote control (right click on the remote control -> advanced -> paste lua configuration from clipboard) 38 + 39 + ### Lua parameters 40 + 41 + - `DEBUG` : if set to true, the script will print debug messages in the chat 42 + - `BaseAltitude` : the default altitude of the elevator when landed on the floor 43 + - `StrafeSpeedFactor` : the speed multiplier when strafing. adjust it depending on how many engines you have on the sides 44 + 45 + ### Usage 46 + 47 + - open the "lua" chat channel and type `goto:<altitude>` to go to the specified altitude with `<altitude>` the altitude in meters, if the altitude is missing or invalid, it will send you the `BaseAltitude` 48 + 49 + # Coming Soon 50 + 51 + - Bookmark system: you will be able to name and store your favorite floors and go to them with a key press 52 + - support for emitter to be able to send a signal to a specific channel to close a door to lock the elevator in position 53 + - dedicated HUD with more informations and with some customizations possible (AR View of the position of the elevator, custom fuel gauge, etc...) 54 + 55 + # Support or donation 56 + 57 + if you like it, [<img src="https://github.com/Jericho1060/DU-Industry-HUD/blob/main/ressources/images/ko-fi.png?raw=true" width="150">](https://ko-fi.com/jericho1060)
+1
Source/Construct/OnConstructDocked.lua
··· 1 + Script.construct:constructDocked(id)
+1
Source/Construct/OnPlayerBoarded.lua
··· 1 + Script.construct:playerBoarded(id)
+1
Source/Construct/OnUndocked.lua
··· 1 + Script.construct:undocked(id)
+1
Source/Construct/OnVRStationEntered.lua
··· 1 + Script.construct:VRStationEntered(id)
+1
Source/Construct/onPvPTimer.lua
··· 1 + Script.construct:PvPTimer(active)
+1
Source/Player/OnParentChanged.lua
··· 1 + Script.player:parentChanged(oldId, newId)
+1
Source/System/OnActionLoop.lua
··· 1 + Script.system:actionLoop(action)
+1
Source/System/OnActionStart.lua
··· 1 + Script.system:actionStart(action)
+1
Source/System/OnActionStop.lua
··· 1 + Script.system:actionStop(action)
+1
Source/System/OnFlush.lua
··· 1 + Script.system:flush()
+1
Source/System/OnInputText.lua
··· 1 + Script.system:inputText(text)
+1
Source/System/OnUpdate.lua
··· 1 + Script.system:update()
+386
Source/Unit/OnStart.lua
··· 1 + --[[ 2 + DU-ELEVATOR by Jericho 3 + ]] 4 + 5 + __DEBUG = false --export: Debug mode, will print more information in the console 6 + 7 + --[[ 8 + Version Management 9 + ]] 10 + 11 + local version = "V 1.0.0" 12 + local log_split = "=================================================" 13 + --printing version in lua chat 14 + system.print(log_split)local a=""local b=math.ceil((50-#version-2)/2)for c=1,b,1 do a=a..'='end;a=a.." "..version.." "for c=1,b,1 do a=a..'='end;system.print(a)system.print(log_split) 15 + 16 + --[[ 17 + Detecting elements linked 18 + ]] 19 + core = nil 20 + fuelTanks = {} 21 + 22 + for slot_name, slot in pairs(unit) do 23 + if 24 + type(slot) == "table" 25 + and type(slot.export) == "table" 26 + and slot.getClass 27 + then 28 + local class = slot.getClass():lower() 29 + if class:find("coreunit") then 30 + core = slot 31 + elseif class:find("fuelcontainer") then 32 + table.insert(fuelTanks, slot) 33 + end 34 + end 35 + end 36 + 37 + --[[ 38 + stopping the script if required elements are not linked 39 + ]] 40 + if core == nil then 41 + system.print('Core unit is not linked, exiting the script') 42 + unit.exit() 43 + end 44 + 45 + --[[ 46 + Default Unit Start Mechanics 47 + ]] 48 + pitchInput = 0 49 + pitchInputFromDevice = 0 50 + rollInput = 0 51 + yawInput = 0 52 + verticalStrafeInput = 0 53 + lateralStrafeInput = 0 54 + brakeInput = 1 --braking by default 55 + goingBack = false 56 + goingForward = false 57 + shiftPressed = false 58 + jumpDelta = 0 59 + baseAcceleration = 0.8 60 + 61 + Nav = Navigator.new(system, core, unit) 62 + Nav.axisCommandManager:setupCustomTargetSpeedRanges(axisCommandId.longitudinal, {100, 500, 1000, 2000,3000, 5000}) 63 + Nav.axisCommandManager:setTargetGroundAltitude(0) 64 + unit.deactivateGroundEngineAltitudeStabilization() 65 + 66 + -- Parenting widget 67 + parentingPanelId = system.createWidgetPanel("Docking") 68 + parentingWidgetId = system.createWidget(parentingPanelId,"parenting") 69 + system.addDataToWidget(unit.getWidgetDataId(),parentingWidgetId) 70 + 71 + -- Fuel widget generation (Updated code By Jericho) 72 + --TODO: replace by custom HUD 73 + if (#fuelTanks > 0) then 74 + fuelTankPanelId = system.createWidgetPanel("Fuel Tanks") 75 + fuelTankWidgetId = system.createWidget(fuelTankPanelId,"fuel_container") 76 + for _,tank in pairs(fuelTanks) do 77 + system.addDataToWidget(tank.getWidgetDataId(),fuelTankWidgetId) 78 + end 79 + end 80 + 81 + --[[ 82 + Storing base position and orientation of the elevator 83 + ]] 84 + ConstructInitPos = construct.getWorldPosition() 85 + --replace that pos by a hand written value to be sure the construct will always realign the same position 86 + --ConstructInitPos = {-1231538.185042, 1201297.6879598, -2617220.2766464} 87 + if __DEBUG then system.print('ConstructInitPos: ' .. json.encode(ConstructInitPos)) end 88 + BaseForward = vec3(construct.getWorldForward()) 89 + if __DEBUG then system.print('BaseForward: ' .. json.encode(BaseForward)) end 90 + BaseAltitute = 285 --export: the start altitude of the elevator (lower position altitude) 91 + 92 + --TODO: to replace with a computing in flush from the current acceleration and the friction acceleration (construct.getWorldAirFrictionAcceleration) 93 + MaxSpeed = construct.getFrictionBurnSpeed() -- for security to avoid burning if going too fast 94 + if __DEBUG then system.print('MaxSpeed: ' .. MaxSpeed) end 95 + 96 + --init a value to store the target altitude 97 + TargetAltitude = core.getAltitude() --by default to the start altitude to avoid falling down if in the air 98 + 99 + --[[ 100 + Kinematics functions by Jaylebreak 101 + Source available at https://gitlab.com/JayleBreak/dualuniverse/-/blob/master/DUflightfiles/autoconf/custom/kinematics.lua 102 + ]] 103 + function computeAccelerationTime(initial, acceleration, final) return (final - initial)/acceleration end 104 + function computeDistanceAndTime(initial, final, mass, thrust, t50, brakeThrust) 105 + t50 = t50 or 0 106 + brakeThrust = brakeThrust or 0 107 + local speedUp = initial < final 108 + local a0 = thrust / (speedUp and mass or -mass) 109 + local b0 = -brakeThrust/mass 110 + local totA = a0+b0 111 + if initial == final then 112 + return 0, 0 113 + elseif speedUp and totA <= 0 or not speedUp and totA >= 0 then 114 + return -1, -1 115 + end 116 + local distanceToMax, timeToMax = 0, 0 117 + if a0 ~= 0 and t50 > 0 then 118 + local c1 = math.pi/t50/2 119 + local v = function(t) 120 + return a0*(t/2 - t50*math.sin(c1*t)/math.pi) + b0*t + initial 121 + end 122 + local speedchk = speedUp and function(s) return s >= final end or function(s) return s <= final end 123 + timeToMax = 2*t50 124 + if speedchk(v(timeToMax)) then 125 + local lasttime = 0 126 + while math.abs(timeToMax - lasttime) > 0.25 do 127 + local t = (timeToMax + lasttime)/2 128 + if speedchk(v(t)) then 129 + timeToMax = t 130 + else 131 + lasttime = t 132 + end 133 + end 134 + end 135 + local K = 2*a0*t50^2/math.pi^2 136 + distanceToMax = K*(math.cos(c1*timeToMax) - 1) + (a0+2*b0)*timeToMax^2/4 + initial*timeToMax 137 + if timeToMax < 2*t50 then 138 + return distanceToMax, timeToMax 139 + end 140 + initial = v(timeToMax) 141 + end 142 + local a = a0+b0 143 + local t = computeAccelerationTime(initial, a, final) 144 + local d = initial*t + a*t*t/2 145 + return distanceToMax+d, timeToMax+t 146 + end 147 + 148 + --[[ 149 + Commpute angle betwwen vectors by Jericho 150 + ]] 151 + function signedAngleBetween(vec1, vec2, planeNormal) 152 + local normVec1 = vec1:project_on_plane(planeNormal):normalize() 153 + local normVec2 = vec2:normalize() 154 + local v1v2dot = normVec1:dot(normVec2) 155 + local angle = math.acos(utils.clamp(v1v2dot,-1,1)) 156 + local crossProduct = vec1:cross(vec2) 157 + if crossProduct:dot(planeNormal) < 0 then 158 + return -angle 159 + end 160 + return angle 161 + end 162 + 163 + --[[ 164 + DU-LUA-Framework by Jericho 165 + Permit to code easier by grouping most of the code in a single event Unit > Start 166 + Unminified Source available here: https://github.com/Jericho1060/du-lua-framework 167 + ]]-- 168 + local a=system.print;local b=error;local c=pcall;local d=assert;local e=coroutine;local f=e.create;local g=e.status;local h=e.resume;local i="dead"local j="suspended"function runFunction(k,l,...)local m,n=c(k,...)if not m then b(l..n)end end;local o={__index={cos={update={},flush={}},fns={update={},flush={},action={start={},stop={},loop={}},inputText=nil,start=nil,stop=nil},ACTIONS={FORWARD="forward",BACKWARD="backward",YAW_LEFT="yawleft",YAW_RIGHT="yawright",STRAFE_LEFT="strafeleft",STRAFE_RIGHT="straferight",LEFT="left",RIGHT="right",UP="up",DOWN="down",GROUND_ALTITUDE_UP="groundaltitudeup",GROUND_ALTITUDE_DOWN="groundaltitudedown",LEFT_ALT="lalt",LEFT_SHIFT="lshift",GEAR="gear",LIGHT="light",BRAKE="brake",OPTION_1="option1",OPTION_2="option2",OPTION_3="option3",OPTION_4="option4",OPTION_5="option5",OPTION_6="option6",OPTION_7="option7",OPTION_8="option8",OPTION_9="option9",OPTION_10="option10",OPTION_11="option11",OPTION_12="option12",OPTION_13="option13",OPTION_14="option14",OPTION_15="option15",OPTION_16="option16",OPTION_17="option17",OPTION_18="option18",OPTION_19="option19",OPTION_20="option20",OPTION_21="option21",OPTION_22="option22",OPTION_23="option23",OPTION_24="option24",OPTION_25="option25",OPTION_26="option26",OPTION_27="option27",OPTION_28="option28",OPTION_29="option29",LEFT_MOUSE="leftmouse",STOP_ENGINES="stopengines",SPEED_UP="speedup",SPEED_DOWN="speeddown",ANTIGRAVITY="antigravity",BOOSTER="booster"},main={update=f(function()end),flush=f(function()end)},update=function(self)local p=g(self.main.update)if p==i then self.main.update=f(function()self:runUpdate()end)elseif p==j then d(h(self.main.update))end end,flush=function(self)local p=g(self.main.flush)if p==i then self.main.flush=f(function()self:runFlush()end)elseif p==j then d(h(self.main.flush))end end,action=function(self,q,r)if self.fns.action[q][r]then runFunction(self.fns.action[q][r],"System Action "..q.." Error: ")end end,actionStart=function(self,r)self:action('start',r)end,actionStop=function(self,r)self:action('stop',r)end,actionLoop=function(self,r)self:action('loop',r)end,inputText=function(self,s)if self.fns.inputText then runFunction(self.fns.inputText,"System Input Text Error: ",s)end end,runUpdate=function(self)for t,u in pairs(self.cos.update)do local m=g(u)if m==i then self.cos.update[t]=f(self.fns.update[t])elseif m==j then d(h(u))end end end,runFlush=function(self)for t,u in pairs(self.cos.flush)do local m=g(u)if m==i then self.cos.flush[t]=f(self.fns.flush[t])elseif m==j then d(h(u))end end end,onUpdate=function(self,v)for t,w in pairs(v)do self.fns.update[t]=w;self.cos.update[t]=f(w)end end,onFlush=function(self,v)for t,w in pairs(v)do self.fns.flush[t]=w;self.cos.flush[t]=f(w)end end,onAction=function(self,q,v)for t,w in pairs(v)do self.fns.action[q][t]=w end end,onActionStart=function(self,v)self:onAction("start",v)end,onActionStop=function(self,v)self:onAction("stop",v)end,onActionLoop=function(self,v)self:onAction("loop",v)end,onInputText=function(self,k)self.fns.inputText=k end}}local x={__index={timers={},stopFn=function()end,timer=function(self,y)if self.timers[y]then runFunction(self.timers[y],"Unit Timer "..y.." Error: ")end end,setTimer=function(self,y,z,k)self.timers[y]=k;unit.setTimer(y,z)end,stopTimer=function(self,y)unit.stopTimer(y)self.timers[y]=nil end,onStop=function(self,k)self.stopFn=k end,stop=function(self)if self.stopFn then runFunction(self.stopFn,"Unit Stop Error: ")end end}}local A={__index={parentChangedFn=function(B,C)end,onParentChange=function(self,k)self.parentChangedFn=k end,parentChanged=function(self,B,C)if self.parentChangedFn then runFunction(self.parentChangedFn,"Player Parent Changed Error: ",B,C)end end}}local D={__index={dockedFn=function(E)end,onDocked=function(self,k)self.dockedFn=k end,docked=function(self,E)if self.dockedFn then runFunction(self.dockedFn,"Construct Docked Error: ",E)end end,undockedFn=function(E)end,onUndocked=function(self,k)self.undockedFn=k end,undocked=function(self,E)if self.undockedFn then runFunction(self.undockedFn,"Construct Undocked Error: ",E)end end,playerBoardedFn=function(E)end,onPlayerBoarded=function(self,k)self.playerBoardedFn=k end,playerBoarded=function(self,E)if self.playerBoardedFn then runFunction(self.playerBoardedFn,"Construct Player Boarded Error: ",E)end end,VRStationEnteredFn=function(E)end,onVRStationEntered=function(self,k)self.VRStationEnteredFn=k end,VRStationEntered=function(self,E)if self.VRStationEnteredFn then runFunction(self.VRStationEnteredFn,"Construct VR Station Entered Error: ",E)end end,constructDockedFn=function(E)end,onConstructDocked=function(self,k)self.constructDockedFn=k end,constructDocked=function(self,E)if self.constructDockedFn then runFunction(self.constructDockedFn,"Construct Construct Docked Error: ",E)end end,PvPTimerFn=function(F)end,onPvPTimer=function(self,k)self.PvPTimerFn=k end,PvPTimer=function(self,F)if self.PvPTimerFn then runFunction(self.PvPTimerFn,"Construct PvP Timer Error: ",F)end end}}DU_Framework={__index={system=setmetatable({},o),unit=setmetatable({},x),player=setmetatable({},A),construct=setmetatable({},D)}} 169 + 170 + Script = {} 171 + setmetatable(Script, DU_Framework) 172 + 173 + --[[ 174 + String Helpers For Lua By Jericho 175 + ]] 176 + String = { 177 + __index = { 178 + split = function(self, delimiter) 179 + local result = {} 180 + for match in (self..delimiter):gmatch("(.-)"..delimiter) do 181 + table.insert(result, match) 182 + end 183 + return result 184 + end 185 + } 186 + } 187 + string = setmetatable(string, String) 188 + string.__index = string 189 + 190 + local systemOnUpdate = { 191 + function () 192 + Nav:update() 193 + end 194 + } 195 + 196 + local systemOnFlush = { 197 + function() 198 + local yawSpeedFactor = 1.5 199 + local yawAccelerationFactor = 3 200 + local lateralAntiDriftFactor = 1 201 + local lateralStrafeFactor = 5 202 + local brakeSpeedFactor = 1 203 + local brakeFlatFactor = 4 204 + local autoBrakeSpeed = 15 205 + -- validate params 206 + brakeSpeedFactor = math.max(brakeSpeedFactor, 0.01) 207 + brakeFlatFactor = math.max(brakeFlatFactor, 0.01) 208 + yawSpeedFactor = math.max(yawSpeedFactor, 0.01) 209 + yawAccelerationFactor = math.max(yawAccelerationFactor, 0.01) 210 + --init all the PIDs as global if first flush 211 + if (rollPID == nil) then rollPID = pid.new(0.2, 0, 10) end 212 + if (pitchPID == nil) then pitchPID = pid.new(0.2, 0, 10) end 213 + if (yawPID == nil) then yawPID = pid.new(0.2, 0, 10) end 214 + if (lateralPID == nil) then lateralPID = pid.new(0.2, 0, 10) end 215 + if (longitudinalPID == nil) then longitudinalPID = pid.new(0.2, 0, 10) end 216 + if (distancePID == nil) then distancePID = pid.new(0.2, 0, 10) end 217 + 218 + -- final inputs 219 + if unit.isMouseDirectControlActivated() then 220 + -- in direct control, we tweak the pitch to behave inbetween virtual joystick and direct control 221 + -- this helps a lot for ground construct control 222 + pitchInputFromDevice = utils.clamp(pitchInputFromDevice + system.getControlDeviceForwardInput() * system.getActionUpdateDeltaTime(), -1.0, 1.0) 223 + else 224 + pitchInputFromDevice = system.getControlDeviceForwardInput() 225 + end 226 + local finalPitchInput = pitchInput + pitchInputFromDevice 227 + local finalRollInput = rollInput + system.getControlDeviceYawInput() 228 + local finalYawInput = yawInput - system.getControlDeviceLeftRightInput() 229 + local combinedRollYawInput = utils.clamp(finalRollInput - finalYawInput, -1.0, 1.0); 230 + local finalVerticalStrafeInput = verticalStrafeInput 231 + local finalLateralStrafeInput = lateralStrafeInput; 232 + local finalBrakeInput = brakeInput 233 + 234 + -- Axis 235 + local worldVertical = vec3(core.getWorldVertical()) 236 + local constructUp = vec3(construct.getWorldOrientationUp()) 237 + local constructForward = vec3(construct.getWorldOrientationForward()) 238 + local constructRight = vec3(construct.getWorldOrientationRight()) 239 + local constructVelocity = vec3(construct.getWorldVelocity()) 240 + local constructVelocityDir = vec3(construct.getWorldVelocity()):normalize() 241 + local constructAngularVelocity = vec3(construct.getWorldAngularVelocity()) 242 + local constructYawVelocity = constructAngularVelocity:dot(constructUp) 243 + local constructWorldPosition = vec3(construct.getWorldPosition()) 244 + local constructTargetPosition = vec3(ConstructInitPos) 245 + 246 + -- Engine commands 247 + local keepCollinearity = 0 -- for easier reading 248 + local dontKeepCollinearity = 1 -- for easier reading 249 + local tolerancePercentToSkipOtherPriorities = 1 -- if we are within this tolerance (in%), we don't go to the next priorities 250 + 251 + -- keeping the start position alignement 252 + local StrafeSpeedFactor = 50 --export: useg to increase the force of the alignement, decrease the value if the alignement is too strong or increase it if it's too slow 253 + local positionDifference = constructTargetPosition - constructWorldPosition 254 + local lateralOffset = positionDifference:project_on(constructRight):len() * utils.sign(positionDifference:dot(constructRight)) 255 + local longitudinalOffset = positionDifference:project_on(constructForward):len() * utils.sign(positionDifference:dot(constructForward)) 256 + lateralPID:inject(lateralOffset) 257 + Nav.axisCommandManager:setThrottleCommand(axisCommandId.lateral, lateralPID:get() * StrafeSpeedFactor) 258 + longitudinalPID:inject(longitudinalOffset) 259 + Nav.axisCommandManager:setThrottleCommand(axisCommandId.longitudinal, longitudinalPID:get() * StrafeSpeedFactor) 260 + 261 + -- Rotation 262 + local currentRollDeg = getRoll(worldVertical, constructForward, constructRight) 263 + local currentPitchDeg = -math.asin(constructForward:dot(worldVertical)) * constants.rad2deg 264 + local targetRollDeg = 0 265 + local targetPitchDeg = 0 266 + local targetYawDeg = signedAngleBetween(BaseForward,constructForward,constructUp)*180/math.pi 267 + rollPID:inject(targetRollDeg - currentRollDeg) 268 + pitchPID:inject(targetPitchDeg - currentPitchDeg) 269 + yawPID:inject(-targetYawDeg*yawSpeedFactor) 270 + 271 + local constructYawTargetVelocity = -combinedRollYawInput * yawSpeedFactor 272 + local constructYawTargetAcceleration = yawAccelerationFactor * (constructYawTargetVelocity - constructYawVelocity) 273 + local constructTargetAngularVelocity = rollPID:get() * constructForward + pitchPID:get() * constructRight + constructYawTargetAcceleration * constructUp 274 + 275 + Nav:setEngineTorqueCommand('torque', constructTargetAngularVelocity, keepCollinearity, 'airfoil', '', '', tolerancePercentToSkipOtherPriorities) 276 + 277 + -- moving up or down from TargetAltitude 278 + local verticalSpeed = constructVelocity:project_on(worldVertical):len() 279 + local verticalSpeedSigned = verticalSpeed * -utils.sign(constructVelocity:dot(worldVertical)) 280 + local brakeDistance = 0 281 + local maxBrake = construct.getMaxBrake() 282 + if maxBrake ~= nil then 283 + brakeDistance, _ = computeDistanceAndTime(verticalSpeed, 0, construct.getInertialMass(), 0, 0, maxBrake - (core.getGravityIntensity() * construct.getInertialMass()) * utils.sign(verticalSpeedSigned)) 284 + end 285 + local coreAltitude = core.getAltitude() 286 + local distance = TargetAltitude - coreAltitude 287 + local targetDistance = utils.sign(distance) * (math.abs(distance)-brakeDistance) 288 + distancePID:inject(targetDistance) 289 + if distancePID:get() > 0.5 or verticalSpeedSigned < -MaxSpeed then --using a 0.5 meter deadband for stabilizing 290 + Nav.axisCommandManager:setThrottleCommand(axisCommandId.vertical, 1) 291 + elseif distancePID:get() < -0.5 or verticalSpeedSigned > MaxSpeed then 292 + Nav.axisCommandManager:setThrottleCommand(axisCommandId.vertical, -1) 293 + else 294 + Nav.axisCommandManager:resetCommand(axisCommandId.vertical) 295 + end 296 + 297 + --Brakes 298 + if 299 + (math.abs(distance) < verticalSpeed) 300 + or verticalSpeed > MaxSpeed 301 + or (brakeDistance > math.abs(distance)) 302 + or (finalBrakeInput == 0 and autoBrakeSpeed > 0 and Nav.axisCommandManager.throttle == 0 and constructVelocity:len() < autoBrakeSpeed) 303 + then 304 + finalBrakeInput = 1 305 + end 306 + local brakeAcceleration = -finalBrakeInput * (brakeSpeedFactor * constructVelocity + brakeFlatFactor * constructVelocityDir) 307 + 308 + Nav:setEngineForceCommand('brake', brakeAcceleration) 309 + 310 + -- AutoNavigation regroups all the axis command by 'TargetSpeed' 311 + local autoNavigationEngineTags = '' 312 + local autoNavigationAcceleration = vec3() 313 + local autoNavigationUseBrake = false 314 + 315 + -- Longitudinal Translation 316 + local longitudinalEngineTags = 'thrust analog longitudinal' 317 + local longitudinalCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.longitudinal) 318 + if (longitudinalCommandType == axisCommandType.byThrottle) then 319 + local longitudinalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(longitudinalEngineTags,axisCommandId.longitudinal) 320 + Nav:setEngineForceCommand(longitudinalEngineTags, longitudinalAcceleration, keepCollinearity) 321 + elseif (longitudinalCommandType == axisCommandType.byTargetSpeed) then 322 + local longitudinalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.longitudinal) 323 + autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. longitudinalEngineTags 324 + autoNavigationAcceleration = autoNavigationAcceleration + longitudinalAcceleration 325 + if (Nav.axisCommandManager:getTargetSpeed(axisCommandId.longitudinal) == 0 or -- we want to stop 326 + Nav.axisCommandManager:getCurrentToTargetDeltaSpeed(axisCommandId.longitudinal) < - Nav.axisCommandManager:getTargetSpeedCurrentStep(axisCommandId.longitudinal) * 0.5) -- if the longitudinal velocity would need some braking 327 + then 328 + autoNavigationUseBrake = true 329 + end 330 + end 331 + 332 + -- Lateral Translation 333 + local lateralStrafeEngineTags = 'thrust analog lateral' 334 + local lateralCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.lateral) 335 + if (lateralCommandType == axisCommandType.byThrottle) then 336 + local lateralStrafeAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(lateralStrafeEngineTags,axisCommandId.lateral) 337 + Nav:setEngineForceCommand(lateralStrafeEngineTags, lateralStrafeAcceleration, keepCollinearity) 338 + elseif (lateralCommandType == axisCommandType.byTargetSpeed) then 339 + local lateralAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.lateral) 340 + autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. lateralStrafeEngineTags 341 + autoNavigationAcceleration = autoNavigationAcceleration + lateralAcceleration 342 + end 343 + 344 + -- Vertical Translation 345 + local verticalStrafeEngineTags = 'thrust analog vertical' 346 + local verticalCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.vertical) 347 + if (verticalCommandType == axisCommandType.byThrottle) then 348 + local verticalStrafeAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(verticalStrafeEngineTags,axisCommandId.vertical) 349 + Nav:setEngineForceCommand(verticalStrafeEngineTags, verticalStrafeAcceleration, keepCollinearity, 'airfoil', 'ground', '', tolerancePercentToSkipOtherPriorities) 350 + elseif (verticalCommandType == axisCommandType.byTargetSpeed) then 351 + local verticalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.vertical) 352 + autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. verticalStrafeEngineTags 353 + autoNavigationAcceleration = autoNavigationAcceleration + verticalAcceleration 354 + end 355 + 356 + -- Auto Navigation (Cruise Control) 357 + if (autoNavigationAcceleration:len() > constants.epsilon) then 358 + if (brakeInput ~= 0 or autoNavigationUseBrake or math.abs(constructVelocityDir:dot(constructForward)) < 0.95) -- if the velocity is not properly aligned with the forward 359 + then 360 + autoNavigationEngineTags = autoNavigationEngineTags .. ', brake' 361 + end 362 + Nav:setEngineForceCommand(autoNavigationEngineTags, autoNavigationAcceleration, dontKeepCollinearity, '', '', '', tolerancePercentToSkipOtherPriorities) 363 + end 364 + 365 + -- Rockets 366 + Nav:setBoosterCommand('rocket_engine') 367 + end 368 + } 369 + 370 + 371 + Script.system:onUpdate(systemOnUpdate) 372 + Script.system:onFlush(systemOnFlush) 373 + 374 + --[[ 375 + Chat Commands 376 + ]] 377 + 378 + Script.system:onInputText(function (text) 379 + if text:lower():find('goto:') then 380 + TargetAltitude = tonumber(text:split(':')[2]) or BaseAltitute 381 + brakeInput = 0 382 + system.print('Target Altitude set to ' .. TargetAltitude .. 'm') 383 + else 384 + system.print('Unknown command') 385 + end 386 + end)
+1
Source/Unit/OnStop.lua
··· 1 + Script.unit:stop()
+1
Source/Unit/OnTimer.Lua
··· 1 + Script.unit:timer(tag)
+1
config.json
··· 1 + {"events":[],"handlers":[{"code":"Script.system:update()","filter":{"args":[],"signature":"onUpdate()","slotKey":"-4"},"key":"9"},{"code":"Script.system:inputText(text)","filter":{"args":[{"variable":"*"}],"signature":"onInputText(text)","slotKey":"-4"},"key":"10"},{"code":"Script.system:flush()","filter":{"args":[],"signature":"onFlush()","slotKey":"-4"},"key":"11"},{"code":"Script.system:actionStop(action)","filter":{"args":[{"variable":"*"}],"signature":"onActionStop(action)","slotKey":"-4"},"key":"12"},{"code":"Script.system:actionStart(action)","filter":{"args":[{"variable":"*"}],"signature":"onActionStart(action)","slotKey":"-4"},"key":"13"},{"code":"Script.system:actionLoop(action)","filter":{"args":[{"variable":"*"}],"signature":"onActionLoop(action)","slotKey":"-4"},"key":"14"},{"code":"Script.player:parentChanged(oldId, newId)","filter":{"args":[{"variable":"*"},{"variable":"*"}],"signature":"onParentChanged(oldId,newId)","slotKey":"-3"},"key":"3"},{"code":"Script.construct:VRStationEntered(id)","filter":{"args":[{"variable":"*"}],"signature":"onVRStationEntered(id)","slotKey":"-2"},"key":"4"},{"code":"Script.construct:undocked(id)","filter":{"args":[{"variable":"*"}],"signature":"onUndocked(id)","slotKey":"-2"},"key":"5"},{"code":"Script.construct:PvPTimer(active)","filter":{"args":[{"variable":"*"}],"signature":"onPvPTimer(active)","slotKey":"-2"},"key":"6"},{"code":"Script.construct:playerBoarded(id)","filter":{"args":[{"variable":"*"}],"signature":"onPlayerBoarded(id)","slotKey":"-2"},"key":"7"},{"code":"Script.construct:constructDocked(id)","filter":{"args":[{"variable":"*"}],"signature":"onConstructDocked(id)","slotKey":"-2"},"key":"8"},{"code":"Script.unit:timer(tag)","filter":{"args":[{"variable":"*"}],"signature":"onTimer(tag)","slotKey":"-1"},"key":"0"},{"code":"Script.unit:stop()","filter":{"args":[],"signature":"onStop()","slotKey":"-1"},"key":"1"},{"code":"--[[\r\n DU-ELEVATOR by Jericho\r\n]]\r\n\r\n__DEBUG = false --export: Debug mode, will print more information in the console\r\n\r\n--[[\r\n Version Management\r\n]]\r\n\r\nlocal version = \"V 1.0.0\"\r\nlocal log_split = \"=================================================\"\r\n--printing version in lua chat\r\nsystem.print(log_split)local a=\"\"local b=math.ceil((50-#version-2)/2)for c=1,b,1 do a=a..'='end;a=a..\" \"..version..\" \"for c=1,b,1 do a=a..'='end;system.print(a)system.print(log_split)\r\n\r\n--[[\r\n Detecting elements linked\r\n]]\r\ncore = nil\r\nfuelTanks = {}\r\n\r\nfor slot_name, slot in pairs(unit) do\r\n if\r\n type(slot) == \"table\"\r\n and type(slot.export) == \"table\"\r\n and slot.getClass\r\n then\r\n local class = slot.getClass():lower()\r\n if class:find(\"coreunit\") then\r\n core = slot\r\n elseif class:find(\"fuelcontainer\") then\r\n table.insert(fuelTanks, slot)\r\n end\r\n end\r\nend\r\n\r\n--[[\r\n stopping the script if required elements are not linked\r\n]]\r\nif core == nil then\r\n system.print('Core unit is not linked, exiting the script')\r\n unit.exit()\r\nend\r\n\r\n--[[\r\n Default Unit Start Mechanics\r\n]]\r\npitchInput = 0\r\npitchInputFromDevice = 0\r\nrollInput = 0\r\nyawInput = 0\r\nverticalStrafeInput = 0\r\nlateralStrafeInput = 0\r\nbrakeInput = 1 --braking by default\r\ngoingBack = false\r\ngoingForward = false\r\nshiftPressed = false\r\njumpDelta = 0\r\nbaseAcceleration = 0.8\r\n\r\nNav = Navigator.new(system, core, unit)\r\nNav.axisCommandManager:setupCustomTargetSpeedRanges(axisCommandId.longitudinal, {100, 500, 1000, 2000,3000, 5000})\r\nNav.axisCommandManager:setTargetGroundAltitude(0)\r\nunit.deactivateGroundEngineAltitudeStabilization()\r\n\r\n-- Parenting widget\r\nparentingPanelId = system.createWidgetPanel(\"Docking\")\r\nparentingWidgetId = system.createWidget(parentingPanelId,\"parenting\")\r\nsystem.addDataToWidget(unit.getWidgetDataId(),parentingWidgetId)\r\n\r\n-- Fuel widget generation (Updated code By Jericho)\r\n--TODO: replace by custom HUD\r\nif (#fuelTanks > 0) then\r\n fuelTankPanelId = system.createWidgetPanel(\"Fuel Tanks\")\r\n fuelTankWidgetId = system.createWidget(fuelTankPanelId,\"fuel_container\")\r\n for _,tank in pairs(fuelTanks) do\r\n system.addDataToWidget(tank.getWidgetDataId(),fuelTankWidgetId)\r\n end\r\nend\r\n\r\n--[[\r\n Storing base position and orientation of the elevator\r\n]]\r\nConstructInitPos = construct.getWorldPosition()\r\n--replace that pos by a hand written value to be sure the construct will always realign the same position\r\n--ConstructInitPos = {-1231538.185042, 1201297.6879598, -2617220.2766464}\r\nif __DEBUG then system.print('ConstructInitPos: ' .. json.encode(ConstructInitPos)) end\r\nBaseForward = vec3(construct.getWorldForward())\r\nif __DEBUG then system.print('BaseForward: ' .. json.encode(BaseForward)) end\r\nBaseAltitute = 285 --export: the start altitude of the elevator (lower position altitude)\r\n\r\n--TODO: to replace with a computing in flush from the current acceleration and the friction acceleration (construct.getWorldAirFrictionAcceleration)\r\nMaxSpeed = construct.getFrictionBurnSpeed() -- for security to avoid burning if going too fast\r\nif __DEBUG then system.print('MaxSpeed: ' .. MaxSpeed) end\r\n\r\n--init a value to store the target altitude\r\nTargetAltitude = core.getAltitude() --by default to the start altitude to avoid falling down if in the air\r\n\r\n--[[\r\n Kinematics functions by Jaylebreak\r\n Source available at https://gitlab.com/JayleBreak/dualuniverse/-/blob/master/DUflightfiles/autoconf/custom/kinematics.lua\r\n]] \r\nfunction computeAccelerationTime(initial, acceleration, final) return (final - initial)/acceleration end\r\nfunction computeDistanceAndTime(initial, final, mass, thrust, t50, brakeThrust)\r\n t50 = t50 or 0\r\n brakeThrust = brakeThrust or 0\r\n local speedUp = initial < final\r\n local a0 = thrust / (speedUp and mass or -mass)\r\n local b0 = -brakeThrust/mass\r\n local totA = a0+b0\r\n if initial == final then\r\n return 0, 0\r\n elseif speedUp and totA <= 0 or not speedUp and totA >= 0 then\r\n return -1, -1\r\n end\r\n local distanceToMax, timeToMax = 0, 0\r\n if a0 ~= 0 and t50 > 0 then\r\n local c1 = math.pi/t50/2\r\n local v = function(t)\r\n return a0*(t/2 - t50*math.sin(c1*t)/math.pi) + b0*t + initial\r\n end\r\n local speedchk = speedUp and function(s) return s >= final end or function(s) return s <= final end\r\n timeToMax = 2*t50\r\n if speedchk(v(timeToMax)) then\r\n local lasttime = 0\r\n while math.abs(timeToMax - lasttime) > 0.25 do\r\n local t = (timeToMax + lasttime)/2\r\n if speedchk(v(t)) then\r\n timeToMax = t \r\n else\r\n lasttime = t\r\n end\r\n end\r\n end\r\n local K = 2*a0*t50^2/math.pi^2\r\n distanceToMax = K*(math.cos(c1*timeToMax) - 1) + (a0+2*b0)*timeToMax^2/4 + initial*timeToMax\r\n if timeToMax < 2*t50 then\r\n return distanceToMax, timeToMax\r\n end\r\n initial = v(timeToMax)\r\n end\r\n local a = a0+b0\r\n local t = computeAccelerationTime(initial, a, final)\r\n local d = initial*t + a*t*t/2\r\n return distanceToMax+d, timeToMax+t\r\nend\r\n\r\n--[[\r\n Commpute angle betwwen vectors by Jericho\r\n]]\r\nfunction signedAngleBetween(vec1, vec2, planeNormal)\r\n local normVec1 = vec1:project_on_plane(planeNormal):normalize()\r\n local normVec2 = vec2:normalize()\r\n local v1v2dot = normVec1:dot(normVec2)\r\n local angle = math.acos(utils.clamp(v1v2dot,-1,1))\r\n local crossProduct = vec1:cross(vec2)\r\n if crossProduct:dot(planeNormal) < 0 then\r\n return -angle\r\n end\r\n return angle\r\nend\r\n\r\n--[[\r\n DU-LUA-Framework by Jericho\r\n Permit to code easier by grouping most of the code in a single event Unit > Start\r\n Unminified Source available here: https://github.com/Jericho1060/du-lua-framework\r\n]]--\r\nlocal a=system.print;local b=error;local c=pcall;local d=assert;local e=coroutine;local f=e.create;local g=e.status;local h=e.resume;local i=\"dead\"local j=\"suspended\"function runFunction(k,l,...)local m,n=c(k,...)if not m then b(l..n)end end;local o={__index={cos={update={},flush={}},fns={update={},flush={},action={start={},stop={},loop={}},inputText=nil,start=nil,stop=nil},ACTIONS={FORWARD=\"forward\",BACKWARD=\"backward\",YAW_LEFT=\"yawleft\",YAW_RIGHT=\"yawright\",STRAFE_LEFT=\"strafeleft\",STRAFE_RIGHT=\"straferight\",LEFT=\"left\",RIGHT=\"right\",UP=\"up\",DOWN=\"down\",GROUND_ALTITUDE_UP=\"groundaltitudeup\",GROUND_ALTITUDE_DOWN=\"groundaltitudedown\",LEFT_ALT=\"lalt\",LEFT_SHIFT=\"lshift\",GEAR=\"gear\",LIGHT=\"light\",BRAKE=\"brake\",OPTION_1=\"option1\",OPTION_2=\"option2\",OPTION_3=\"option3\",OPTION_4=\"option4\",OPTION_5=\"option5\",OPTION_6=\"option6\",OPTION_7=\"option7\",OPTION_8=\"option8\",OPTION_9=\"option9\",OPTION_10=\"option10\",OPTION_11=\"option11\",OPTION_12=\"option12\",OPTION_13=\"option13\",OPTION_14=\"option14\",OPTION_15=\"option15\",OPTION_16=\"option16\",OPTION_17=\"option17\",OPTION_18=\"option18\",OPTION_19=\"option19\",OPTION_20=\"option20\",OPTION_21=\"option21\",OPTION_22=\"option22\",OPTION_23=\"option23\",OPTION_24=\"option24\",OPTION_25=\"option25\",OPTION_26=\"option26\",OPTION_27=\"option27\",OPTION_28=\"option28\",OPTION_29=\"option29\",LEFT_MOUSE=\"leftmouse\",STOP_ENGINES=\"stopengines\",SPEED_UP=\"speedup\",SPEED_DOWN=\"speeddown\",ANTIGRAVITY=\"antigravity\",BOOSTER=\"booster\"},main={update=f(function()end),flush=f(function()end)},update=function(self)local p=g(self.main.update)if p==i then self.main.update=f(function()self:runUpdate()end)elseif p==j then d(h(self.main.update))end end,flush=function(self)local p=g(self.main.flush)if p==i then self.main.flush=f(function()self:runFlush()end)elseif p==j then d(h(self.main.flush))end end,action=function(self,q,r)if self.fns.action[q][r]then runFunction(self.fns.action[q][r],\"System Action \"..q..\" Error: \")end end,actionStart=function(self,r)self:action('start',r)end,actionStop=function(self,r)self:action('stop',r)end,actionLoop=function(self,r)self:action('loop',r)end,inputText=function(self,s)if self.fns.inputText then runFunction(self.fns.inputText,\"System Input Text Error: \",s)end end,runUpdate=function(self)for t,u in pairs(self.cos.update)do local m=g(u)if m==i then self.cos.update[t]=f(self.fns.update[t])elseif m==j then d(h(u))end end end,runFlush=function(self)for t,u in pairs(self.cos.flush)do local m=g(u)if m==i then self.cos.flush[t]=f(self.fns.flush[t])elseif m==j then d(h(u))end end end,onUpdate=function(self,v)for t,w in pairs(v)do self.fns.update[t]=w;self.cos.update[t]=f(w)end end,onFlush=function(self,v)for t,w in pairs(v)do self.fns.flush[t]=w;self.cos.flush[t]=f(w)end end,onAction=function(self,q,v)for t,w in pairs(v)do self.fns.action[q][t]=w end end,onActionStart=function(self,v)self:onAction(\"start\",v)end,onActionStop=function(self,v)self:onAction(\"stop\",v)end,onActionLoop=function(self,v)self:onAction(\"loop\",v)end,onInputText=function(self,k)self.fns.inputText=k end}}local x={__index={timers={},stopFn=function()end,timer=function(self,y)if self.timers[y]then runFunction(self.timers[y],\"Unit Timer \"..y..\" Error: \")end end,setTimer=function(self,y,z,k)self.timers[y]=k;unit.setTimer(y,z)end,stopTimer=function(self,y)unit.stopTimer(y)self.timers[y]=nil end,onStop=function(self,k)self.stopFn=k end,stop=function(self)if self.stopFn then runFunction(self.stopFn,\"Unit Stop Error: \")end end}}local A={__index={parentChangedFn=function(B,C)end,onParentChange=function(self,k)self.parentChangedFn=k end,parentChanged=function(self,B,C)if self.parentChangedFn then runFunction(self.parentChangedFn,\"Player Parent Changed Error: \",B,C)end end}}local D={__index={dockedFn=function(E)end,onDocked=function(self,k)self.dockedFn=k end,docked=function(self,E)if self.dockedFn then runFunction(self.dockedFn,\"Construct Docked Error: \",E)end end,undockedFn=function(E)end,onUndocked=function(self,k)self.undockedFn=k end,undocked=function(self,E)if self.undockedFn then runFunction(self.undockedFn,\"Construct Undocked Error: \",E)end end,playerBoardedFn=function(E)end,onPlayerBoarded=function(self,k)self.playerBoardedFn=k end,playerBoarded=function(self,E)if self.playerBoardedFn then runFunction(self.playerBoardedFn,\"Construct Player Boarded Error: \",E)end end,VRStationEnteredFn=function(E)end,onVRStationEntered=function(self,k)self.VRStationEnteredFn=k end,VRStationEntered=function(self,E)if self.VRStationEnteredFn then runFunction(self.VRStationEnteredFn,\"Construct VR Station Entered Error: \",E)end end,constructDockedFn=function(E)end,onConstructDocked=function(self,k)self.constructDockedFn=k end,constructDocked=function(self,E)if self.constructDockedFn then runFunction(self.constructDockedFn,\"Construct Construct Docked Error: \",E)end end,PvPTimerFn=function(F)end,onPvPTimer=function(self,k)self.PvPTimerFn=k end,PvPTimer=function(self,F)if self.PvPTimerFn then runFunction(self.PvPTimerFn,\"Construct PvP Timer Error: \",F)end end}}DU_Framework={__index={system=setmetatable({},o),unit=setmetatable({},x),player=setmetatable({},A),construct=setmetatable({},D)}}\r\n\r\nScript = {}\r\nsetmetatable(Script, DU_Framework)\r\n\r\n--[[\r\n String Helpers For Lua By Jericho\r\n]]\r\nString = {\r\n __index = {\r\n split = function(self, delimiter)\r\n local result = {}\r\n for match in (self..delimiter):gmatch(\"(.-)\"..delimiter) do\r\n table.insert(result, match)\r\n end\r\n return result\r\n end\r\n }\r\n}\r\nstring = setmetatable(string, String)\r\nstring.__index = string\r\n\r\nlocal systemOnUpdate = {\r\n function ()\r\n Nav:update()\r\n end\r\n}\r\n\r\nlocal systemOnFlush = {\r\n function()\r\n local yawSpeedFactor = 1.5\r\n local yawAccelerationFactor = 3\r\n local lateralAntiDriftFactor = 1\r\n local lateralStrafeFactor = 5\r\n local brakeSpeedFactor = 1\r\n local brakeFlatFactor = 4 \r\n local autoBrakeSpeed = 15\r\n -- validate params\r\n brakeSpeedFactor = math.max(brakeSpeedFactor, 0.01)\r\n brakeFlatFactor = math.max(brakeFlatFactor, 0.01)\r\n yawSpeedFactor = math.max(yawSpeedFactor, 0.01)\r\n yawAccelerationFactor = math.max(yawAccelerationFactor, 0.01)\r\n --init all the PIDs as global if first flush\r\n if (rollPID == nil) then rollPID = pid.new(0.2, 0, 10) end\r\n if (pitchPID == nil) then pitchPID = pid.new(0.2, 0, 10) end\r\n if (yawPID == nil) then yawPID = pid.new(0.2, 0, 10) end\r\n if (lateralPID == nil) then lateralPID = pid.new(0.2, 0, 10) end\r\n if (longitudinalPID == nil) then longitudinalPID = pid.new(0.2, 0, 10) end\r\n if (distancePID == nil) then distancePID = pid.new(0.2, 0, 10) end\r\n\r\n -- final inputs\r\n if unit.isMouseDirectControlActivated() then\r\n -- in direct control, we tweak the pitch to behave inbetween virtual joystick and direct control\r\n -- this helps a lot for ground construct control\r\n pitchInputFromDevice = utils.clamp(pitchInputFromDevice + system.getControlDeviceForwardInput() * system.getActionUpdateDeltaTime(), -1.0, 1.0)\r\n else\r\n pitchInputFromDevice = system.getControlDeviceForwardInput()\r\n end\r\n local finalPitchInput = pitchInput + pitchInputFromDevice\r\n local finalRollInput = rollInput + system.getControlDeviceYawInput()\r\n local finalYawInput = yawInput - system.getControlDeviceLeftRightInput()\r\n local combinedRollYawInput = utils.clamp(finalRollInput - finalYawInput, -1.0, 1.0);\r\n local finalVerticalStrafeInput = verticalStrafeInput\r\n local finalLateralStrafeInput = lateralStrafeInput;\r\n local finalBrakeInput = brakeInput\r\n\r\n -- Axis\r\n local worldVertical = vec3(core.getWorldVertical())\r\n local constructUp = vec3(construct.getWorldOrientationUp())\r\n local constructForward = vec3(construct.getWorldOrientationForward())\r\n local constructRight = vec3(construct.getWorldOrientationRight())\r\n local constructVelocity = vec3(construct.getWorldVelocity())\r\n local constructVelocityDir = vec3(construct.getWorldVelocity()):normalize()\r\n local constructAngularVelocity = vec3(construct.getWorldAngularVelocity())\r\n local constructYawVelocity = constructAngularVelocity:dot(constructUp)\r\n local constructWorldPosition = vec3(construct.getWorldPosition())\r\n local constructTargetPosition = vec3(ConstructInitPos)\r\n\r\n -- Engine commands\r\n local keepCollinearity = 0 -- for easier reading\r\n local dontKeepCollinearity = 1 -- for easier reading\r\n local tolerancePercentToSkipOtherPriorities = 1 -- if we are within this tolerance (in%), we don't go to the next priorities\r\n\r\n -- keeping the start position alignement\r\n local StrafeSpeedFactor = 50 --export: useg to increase the force of the alignement, decrease the value if the alignement is too strong or increase it if it's too slow\r\n local positionDifference = constructTargetPosition - constructWorldPosition\r\n local lateralOffset = positionDifference:project_on(constructRight):len() * utils.sign(positionDifference:dot(constructRight))\r\n local longitudinalOffset = positionDifference:project_on(constructForward):len() * utils.sign(positionDifference:dot(constructForward))\r\n lateralPID:inject(lateralOffset)\r\n Nav.axisCommandManager:setThrottleCommand(axisCommandId.lateral, lateralPID:get() * StrafeSpeedFactor)\r\n longitudinalPID:inject(longitudinalOffset)\r\n Nav.axisCommandManager:setThrottleCommand(axisCommandId.longitudinal, longitudinalPID:get() * StrafeSpeedFactor)\r\n\r\n -- Rotation\r\n local currentRollDeg = getRoll(worldVertical, constructForward, constructRight)\r\n local currentPitchDeg = -math.asin(constructForward:dot(worldVertical)) * constants.rad2deg\r\n local targetRollDeg = 0\r\n local targetPitchDeg = 0\r\n local targetYawDeg = signedAngleBetween(BaseForward,constructForward,constructUp)*180/math.pi\r\n rollPID:inject(targetRollDeg - currentRollDeg)\r\n pitchPID:inject(targetPitchDeg - currentPitchDeg)\r\n yawPID:inject(-targetYawDeg*yawSpeedFactor)\r\n\r\n local constructYawTargetVelocity = -combinedRollYawInput * yawSpeedFactor\r\n local constructYawTargetAcceleration = yawAccelerationFactor * (constructYawTargetVelocity - constructYawVelocity)\r\n local constructTargetAngularVelocity = rollPID:get() * constructForward + pitchPID:get() * constructRight + constructYawTargetAcceleration * constructUp\r\n\r\n Nav:setEngineTorqueCommand('torque', constructTargetAngularVelocity, keepCollinearity, 'airfoil', '', '', tolerancePercentToSkipOtherPriorities)\r\n\r\n -- moving up or down from TargetAltitude\r\n local verticalSpeed = constructVelocity:project_on(worldVertical):len()\r\n local verticalSpeedSigned = verticalSpeed * -utils.sign(constructVelocity:dot(worldVertical))\r\n local brakeDistance = 0\r\n local maxBrake = construct.getMaxBrake()\r\n if maxBrake ~= nil then\r\n brakeDistance, _ = computeDistanceAndTime(verticalSpeed, 0, construct.getInertialMass(), 0, 0, maxBrake - (core.getGravityIntensity() * construct.getInertialMass()) * utils.sign(verticalSpeedSigned))\r\n end\r\n local coreAltitude = core.getAltitude()\r\n local distance = TargetAltitude - coreAltitude\r\n local targetDistance = utils.sign(distance) * (math.abs(distance)-brakeDistance)\r\n distancePID:inject(targetDistance)\r\n if distancePID:get() > 0.5 or verticalSpeedSigned < -MaxSpeed then --using a 0.5 meter deadband for stabilizing\r\n Nav.axisCommandManager:setThrottleCommand(axisCommandId.vertical, 1)\r\n elseif distancePID:get() < -0.5 or verticalSpeedSigned > MaxSpeed then\r\n Nav.axisCommandManager:setThrottleCommand(axisCommandId.vertical, -1)\r\n else\r\n Nav.axisCommandManager:resetCommand(axisCommandId.vertical)\r\n end\r\n\r\n --Brakes\r\n if\r\n (math.abs(distance) < verticalSpeed)\r\n or verticalSpeed > MaxSpeed\r\n or (brakeDistance > math.abs(distance))\r\n or (finalBrakeInput == 0 and autoBrakeSpeed > 0 and Nav.axisCommandManager.throttle == 0 and constructVelocity:len() < autoBrakeSpeed)\r\n then\r\n finalBrakeInput = 1\r\n end\r\n local brakeAcceleration = -finalBrakeInput * (brakeSpeedFactor * constructVelocity + brakeFlatFactor * constructVelocityDir)\r\n \r\n Nav:setEngineForceCommand('brake', brakeAcceleration)\r\n\r\n -- AutoNavigation regroups all the axis command by 'TargetSpeed'\r\n local autoNavigationEngineTags = ''\r\n local autoNavigationAcceleration = vec3()\r\n local autoNavigationUseBrake = false\r\n\r\n -- Longitudinal Translation\r\n local longitudinalEngineTags = 'thrust analog longitudinal'\r\n local longitudinalCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.longitudinal)\r\n if (longitudinalCommandType == axisCommandType.byThrottle) then\r\n local longitudinalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(longitudinalEngineTags,axisCommandId.longitudinal)\r\n Nav:setEngineForceCommand(longitudinalEngineTags, longitudinalAcceleration, keepCollinearity)\r\n elseif (longitudinalCommandType == axisCommandType.byTargetSpeed) then\r\n local longitudinalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.longitudinal)\r\n autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. longitudinalEngineTags\r\n autoNavigationAcceleration = autoNavigationAcceleration + longitudinalAcceleration\r\n if (Nav.axisCommandManager:getTargetSpeed(axisCommandId.longitudinal) == 0 or -- we want to stop\r\n Nav.axisCommandManager:getCurrentToTargetDeltaSpeed(axisCommandId.longitudinal) < - Nav.axisCommandManager:getTargetSpeedCurrentStep(axisCommandId.longitudinal) * 0.5) -- if the longitudinal velocity would need some braking\r\n then\r\n autoNavigationUseBrake = true\r\n end\r\n end\r\n\r\n -- Lateral Translation\r\n local lateralStrafeEngineTags = 'thrust analog lateral'\r\n local lateralCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.lateral)\r\n if (lateralCommandType == axisCommandType.byThrottle) then\r\n local lateralStrafeAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(lateralStrafeEngineTags,axisCommandId.lateral)\r\n Nav:setEngineForceCommand(lateralStrafeEngineTags, lateralStrafeAcceleration, keepCollinearity)\r\n elseif (lateralCommandType == axisCommandType.byTargetSpeed) then\r\n local lateralAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.lateral)\r\n autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. lateralStrafeEngineTags\r\n autoNavigationAcceleration = autoNavigationAcceleration + lateralAcceleration\r\n end\r\n\r\n -- Vertical Translation\r\n local verticalStrafeEngineTags = 'thrust analog vertical'\r\n local verticalCommandType = Nav.axisCommandManager:getAxisCommandType(axisCommandId.vertical)\r\n if (verticalCommandType == axisCommandType.byThrottle) then\r\n local verticalStrafeAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromThrottle(verticalStrafeEngineTags,axisCommandId.vertical)\r\n Nav:setEngineForceCommand(verticalStrafeEngineTags, verticalStrafeAcceleration, keepCollinearity, 'airfoil', 'ground', '', tolerancePercentToSkipOtherPriorities)\r\n elseif (verticalCommandType == axisCommandType.byTargetSpeed) then\r\n local verticalAcceleration = Nav.axisCommandManager:composeAxisAccelerationFromTargetSpeed(axisCommandId.vertical)\r\n autoNavigationEngineTags = autoNavigationEngineTags .. ' , ' .. verticalStrafeEngineTags\r\n autoNavigationAcceleration = autoNavigationAcceleration + verticalAcceleration\r\n end\r\n\r\n -- Auto Navigation (Cruise Control)\r\n if (autoNavigationAcceleration:len() > constants.epsilon) then\r\n if (brakeInput ~= 0 or autoNavigationUseBrake or math.abs(constructVelocityDir:dot(constructForward)) < 0.95) -- if the velocity is not properly aligned with the forward\r\n then\r\n autoNavigationEngineTags = autoNavigationEngineTags .. ', brake'\r\n end\r\n Nav:setEngineForceCommand(autoNavigationEngineTags, autoNavigationAcceleration, dontKeepCollinearity, '', '', '', tolerancePercentToSkipOtherPriorities)\r\n end\r\n\r\n -- Rockets\r\n Nav:setBoosterCommand('rocket_engine')\r\n end\r\n}\r\n\r\n\r\nScript.system:onUpdate(systemOnUpdate)\r\nScript.system:onFlush(systemOnFlush)\r\n\r\n--[[\r\n Chat Commands\r\n]]\r\n\r\nScript.system:onInputText(function (text)\r\n if text:lower():find('goto:') then\r\n TargetAltitude = tonumber(text:split(':')[2]) or BaseAltitute\r\n brakeInput = 0\r\n system.print('Target Altitude set to ' .. TargetAltitude .. 'm')\r\n else\r\n system.print('Unknown command')\r\n end\r\nend)","filter":{"args":[],"signature":"onStart()","slotKey":"-1"},"key":"2"}],"methods":[],"slots":{"0":{"name":"slot1","type":{"events":[],"methods":[]}},"1":{"name":"slot2","type":{"events":[],"methods":[]}},"2":{"name":"slot3","type":{"events":[],"methods":[]}},"3":{"name":"slot4","type":{"events":[],"methods":[]}},"4":{"name":"slot5","type":{"events":[],"methods":[]}},"5":{"name":"slot6","type":{"events":[],"methods":[]}},"6":{"name":"slot7","type":{"events":[],"methods":[]}},"7":{"name":"slot8","type":{"events":[],"methods":[]}},"8":{"name":"slot9","type":{"events":[],"methods":[]}},"9":{"name":"slot10","type":{"events":[],"methods":[]}},"-5":{"name":"library","type":{"events":[],"methods":[]}},"-4":{"name":"system","type":{"events":[],"methods":[]}},"-3":{"name":"player","type":{"events":[],"methods":[]}},"-2":{"name":"construct","type":{"events":[],"methods":[]}},"-1":{"name":"unit","type":{"events":[],"methods":[]}}}}
images/adjustors.png

This is a binary file and will not be displayed.