Copy salient and essential scripts and models from Plane Building Roblox

This commit is contained in:
2026-06-10 02:53:40 +01:00
commit 891781366d
76 changed files with 10904 additions and 0 deletions
+126
View File
@@ -0,0 +1,126 @@
local module = {}
local debugWings = game.Workspace.DebugWings.Value
local space = game.Workspace.Objects
local dens = game.Workspace.AirDensity * -game.Workspace.CompensateDensity.Value
local ndelta = 1/60
local function drag(v,r)
return v * r
end
local rnd = function(vec) return Vector3.new(math.round(vec.X),math.round(vec.Y),math.round(vec.Z)) end
local a = math.abs
local ln = math.log
local debwings = {}
local function deb(wing,force)
local part = debwings[wing]
if not part then
part = Instance.new("Part")
part.Name = "WingDebug"
part.Parent = game.Workspace.Hidden
part.Color = Color3.new(0.152941, 0.764706, 0.0588235)
part.Material = Enum.Material.Neon
part.Anchored = true
part.CanCollide = false
part.Transparency = 0.8
part.Size = Vector3.new(0.25,0.25,2) -- we determine the wing's strength and do math by its size, the bigger, the more lift
debwings[wing] = part
end
part.Transparency = 0.5
part.CFrame = CFrame.lookAt(wing.Position,wing.Position+force)
part.Size = Vector3.new(0.25,0.25,force.Magnitude)
part.CFrame = part.CFrame + part.CFrame.LookVector * part.Size.Z * 0.5
end
require(game.ReplicatedFirst.ReadyModule)("WingCommands")
local process = true
game.Workspace.DebugWings.Changed:Connect(function()
debugWings = game.Workspace.DebugWings.Value
if not debugWings then
for _,item in pairs(debwings) do
item:Destroy()
end
debwings = {}
end
end)
game.Workspace.CompensateDensity.Changed:Connect(function()
dens = game.Workspace.AirDensity * -game.Workspace.CompensateDensity.Value
end)
function module.new(this,wing,context)
--local mul = wing:GetAttribute("AeroMultiplier") or 1
this.bounds = {}
this.volume = {}
if wing:IsA("Model") then
this.aero = {}
for _,part in pairs(wing:GetChildren()) do
if part:HasTag("IsAerodynamic") then
table.insert(this.aero,part)
end
end
else
this.aero = {wing}
end
for _,part in pairs(this.aero) do
local s = part.Size
this.bounds[part] = Vector3.new(s.Y*s.Z,s.X*s.Z,s.Y*s.X)-- * mul
this.volume[part] = s.X*s.Y*s.Z
end
return this
end
local visc = 0.75
local commands = require(_G.Modules.CommandsModule)
commands.new("viscosity (.+)","viscosity <number>: change air viscosity coefficient",function(n)
visc = tonumber(n)
end)
module.run = @native
function(this,wing,context)
local bounds = this.bounds
local volume = this.volume
if not process then return true end
if not this.aero then print(this,wing) end -- BECAUSE WHAT THE BLOODY HELL IS THIS!?!??
for _,wing in pairs(this.aero) do
--if not (wing.Parent == space or wing.Parent.Parent == space) and v.player then return end
local s = bounds[wing]
if not s then print(this.aero,bounds,wing,s) end
local p = wing.Position
local v = wing:GetVelocityAtPosition(p) -- velocity of wing
local d = dens * 20
local fmass = 2 -- mass of air generally
--[[if p.Y < 0 then
d = d * 5
fmass = 100 -- mass of water
end]]
v = v - Vector3.new(0,
0--0.15 * v.Magnitude -- implement upthrust due to pressure difference across an airfoil (lift)
,0)
local lv = wing.CFrame.Rotation:PointToObjectSpace(v) -- velocity for each wing face
--mv = lv.Magnitude + 0.0001 -- small number to stop zero error
-- "math", YEAH REALLY? i didnt REALISE! I don't even know what this does...
--lp = Vector3.new(lv.X/(a(scale.X*d*lv.X)+1)-lv.X,lv.Y/(a(scale.Y*d*lv.Y)+1)-lv.Y,lv.Z/(a(scale.Z*d*lv.Z)+1)-lv.Z) -- math
local drag = Vector3.new(lv.X*s.X,lv.Y*s.Y,lv.Z*s.Z)
-- implement anti-viscosity (may the riemann sum gods be with the low end machines
local lp = (drag) * context.delta*d*math.tanh(v.Magnitude*0.0075)
local r = (wing.CFrame.Rotation:PointToWorldSpace(lp))
r = r + Vector3.yAxis * fmass * volume[wing] * 2 * context.delta -- implement upthrust due to pressure difference in a fluid column (floating)
wing:ApplyImpulseAtPosition(r,wing.Position)
if debugWings then deb(wing,r) end
end
return true
end
module.manifest = {
predicate = function(instance)
return instance:HasTag("IsAerodynamic") or instance.Name:match("Sheet") -- LAST CONDITION IS NOT NEEDED
end,
}
return module
+34
View File
@@ -0,0 +1,34 @@
local module = {}
local cool_rate = 0.25
function module.new(this,balloon,context)
this.heat = 0
end
function module.run(this,balloon,context)
this.heat = this.heat * (1 - cool_rate * context.delta) -- wrong but idc
local force = Vector3.new(0,1,0) * (1-(1/(1+this.heat))) * 1000 * context.delta * balloon.Size.Magnitude
balloon:ApplyImpulseAtPosition(force,balloon.Position)
context.replicate(this,balloon,module,this.heat)
return true
end
function module.replicate(this,balloon,context,heat)
this.heat = heat
end
module.update = module.new
module.messages = {
flux = function(this,balloon,context,heat)
this.heat = this.heat + heat
end,
}
module.messages.default = nil
module.manifest = {
"LongBalloon",
"RoundBalloon"
}
return module
+54
View File
@@ -0,0 +1,54 @@
local module = {}
local function burn_effect(this,boiler,context,burn)
for index,item in pairs(this.burning) do
item.Color = Color3.fromRGB(255, 137, 73):Lerp(Color3.fromRGB(115, 61, 33),1-math.abs(burn))
end
end
function module.new(this,boiler,context)
this.burning = {}
this.scale = boiler:GetExtentsSize().Magnitude
this.exhaust = _G.GetInstance(boiler,"Exhaust")
for index,item in pairs(boiler:GetChildren()) do
if item.Name == "Fire" then
table.insert(this.burning,item)
end
end
return this
end
function module.idle(this,boiler) return true end
local begin = tick()
module.run = function(this,boiler,context)
local throttle = this.throttle or context.controls[_G.GetValue(boiler,"Binding","throttle")] or this.Throttle or 0
context.replicate(this,boiler,module,throttle)
local objects = {}
context.connected("ConnectorFume","Exhaust",this.exhaust,function(object)
table.insert(objects,object)
end)
for index,object in pairs(objects) do
context.message(object,"flux",this.scale * math.abs(throttle) * context.delta * (1/#objects))
end
return true
end
module.replication_delta = 0.25
function module.replicate(this,boiler,context,burn)
burn_effect(this,boiler,context,burn)
end
module.messages = {
control = function(this,object,context,value)
this.throttle = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"Boiler1",
"Boiler2"
}
return module
+26
View File
@@ -0,0 +1,26 @@
local module = {}
function module.new(this,boombox,context)
this.sound = _G.GetInstance(_G.GetInstance(boombox,"Plank"),"Sound")
end
module.messages = {
source = function(this,speaker,context,value)
this.sound.SoundId = "rbxassetid://"..(tostring(value or "") or "")
end,
default = function(this,speaker,context,value)
if value > 0.5 then
this.sound:Play()
elseif value == 0 then
this.sound:Pause()
elseif value < -0.5 then
this.sound:Stop()
end
end,
}
module.manifest = {
"Boombox"
}
return module
+19
View File
@@ -0,0 +1,19 @@
local module = {}
local partStateModule = require(_G.Modules.PartStateModule)
function module.new(this,cable,context)
end
function module.run(this,cable,context)
if context.frequency(this,"cable_material",1) then cable.Material = Enum.Material.Fabric end
return true
end
module.update = module.new
module.manifest = {
"DataCable"
}
return module
+59
View File
@@ -0,0 +1,59 @@
local module = {}
local programModule = require(_G.Modules.ProgramModule)
function module.new(this,computer,context)
this.value = _G.GetInstance(computer,"Program")
this.led = _G.GetInstance(computer,"LED")
this.program = programModule.open_program(this.value,nil)
this.program:load()
this.inputs = {}
this.output = function(pin,name,value)
context.connected("ConnectorData","ConnectorEnd",computer[pin],function(object)
context.message(object,name,value)
end)
end
this.input = function(name)
return this.inputs[name]
end
this.control = function(name)
return context.controls[name]
end
this.message = function(title,value)
if context.queue(this,"notification",3) then _G.Events.Notification:Fire(title,value) end
end
this.led.Color = Color3.fromRGB(255,255,255)
return this
end
local begin = tick()
module.run = _G.Protect(function(this,computer,context)
if not this.program then this.led.Color = Color3.fromRGB(255,0,0) return true end
this.led.Color = Color3.fromRGB(0,255,0)
this.program.variables = this.variables or {}
this.program:run(this)
context.replicate(this,computer,module,this.program.variables)
return true
end)
function module.remove(this,computer,context)
end
module.replication_delta = 0.25
function module.replicate(this,computer,context,variables)
this.variables = variables
end
module.messages = {
default = function(this,object,context,value)
local pin = object.Name
this.inputs[pin] = value
end
}
module.manifest = {
"Microcontroller"
}
return module
+44
View File
@@ -0,0 +1,44 @@
local module = {}
function module.new(this,disconnector,context)
this.grip = _G.GetInstance(disconnector,"Grip")
this.binding = _G.GetInstance(disconnector,"Binding")
return this
end
module.run = _G.Protect(function(this,disconnector,context)
if this.control or 0 < 0.5 and context.queue(this,module.name,0.4) then
context.replicate(this,disconnector,module)
elseif context.controls[this.binding.Value] or 0 < 0.5 then
context.replicate(this,disconnector,module)
end
return true
end)
module.replication_delta = 0.25
function module.replicate(this,disconnector,context)
if _G.IsClient then return end
for _,weld in pairs(this.grip:GetJoints()) do
if
weld:IsA("WeldConstraint") and
weld.Name == "BuiltWeldConstraint" and
weld.Parent
then
weld:Destroy()
end
end
this.grip.Transparency = 1
task.delay(0.3,function() this.grip.Transparency = 0 end)
end
module.messages = {
control = function(this,disconnector,context,value)
this.control = tonumber(value)
end,
}
module.manifest = {
"Disconnector"
}
return module
+23
View File
@@ -0,0 +1,23 @@
local module = {}
function module.new(this,display,context)
this.screen = _G.GetInstance(display,"Screen")
this.gui = _G.GetInstance(this.screen,"Gui")
this.text = _G.GetInstance(this.gui,"Label")
this.text.Text = "<b>PSx Display Driver 1.0</b>\nStandby for message..."
end
module.messages = {
default = function(this,display,context,value)
this.text.Text = tostring(value)
end,
color = function(this,display,context,value)
pcall(function() this.text.TextColor3 = value end)
end,
}
module.manifest = {
"Display"
}
return module
+41
View File
@@ -0,0 +1,41 @@
local module = {}
function module.new(this,emitter,context)
return this
end
function module.idle(this,engine) return true end
local begin = tick()
module.run = _G.Protect(function(this,emitter,context)
return true
end)
module.replication_delta = 0.25
function module.replicate(this,emitter,context,details)
end
module.messages = {
control = function(this,object,context,value)
this.throttle = value
end,
starter = function(this,object,context,value)
this.starter = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"Engine",
"Engine2",
"BigEngine",
"BigRadial",
"Radial",
"Boiler1",
"Boiler2"
}
return module
+121
View File
@@ -0,0 +1,121 @@
local module = {}
local function rpm(rot)
return (rot/(math.pi*2))*60
end
local function rot(hinge)
return hinge.CFrame.Rotation:PointToObjectSpace(hinge.AssemblyAngularVelocity).Magnitude
end
function module.new(this,engine,context)
this.powered = _G.GetValue(engine,"Powered",true)
this.inverted = _G.GetInstance(engine,"Inverted")
this.speed = _G.GetInstance(engine,"Speed")
this.rotor = _G.GetInstance(engine,"Hinge")
this.hinge = _G.GetInstance(engine,"HingeConstraint")
this.rotor_sound = this.rotor:FindFirstChild("RotorSound")
this.starter_sound = this.rotor:FindFirstChild("Starter")
this.starter_ratio = engine:GetAttribute("StarterRatio") or 1
if this.powered then
this.hinge.ActuatorType = Enum.ActuatorType.Motor
else
this.hinge.ActuatorType = Enum.ActuatorType.None
end
this.hinge.LimitsEnabled = false
this.torque = engine:GetScale() * 100000
return this
end
function module.idle(this,engine) return true end
local begin = tick()
module.run = _G.Protect(function(this,engine,context)
local throttle = this.throttle or context.controls[_G.GetValue(engine,"Binding","throttle")] or this.Throttle or 0
if this.inverted.Value then throttle = throttle * -1 end
local starter = math.abs(throttle) > 0.1
local target_speed = this.speed.Value * throttle
local current_speed = rot(this.rotor)
local accel
if math.abs(current_speed) > this.speed.Value * 0.1 then
-- Running
starter = false
accel = 40
else
-- Starting
accel = 40 * this.starter_ratio --this.torque * (math.clamp(math.noise(0.123,0.456,(begin-tick())*0.5),0,1) + 0.5) * 0.2
end
this.hinge.MotorMaxAcceleration = accel
if math.abs(throttle) > 0.05 then
this.hinge.AngularVelocity = target_speed
else
this.hinge.AngularVelocity = 0
end
if not this.torque then print(this) return false end
this.hinge.MotorMaxTorque = this.torque * ((engine:GetAttribute("Health") or 1) / (engine:GetAttribute("MaxHealth") or 1)) * (1/(this.speed.Value + 1)) * 60
context.replicate(this,engine,module,{Throttle = throttle, Starter = starter})
return true
end)
local legal_detail = {
Throttle = true,
Mixture = true,
Temperature = true,
Oil = true,
Air = true,
Fuel = true,
Coolant = true,
Power = true
}
module.replication_delta = 0.25
function module.replicate(this,engine,context,details)
for index,item in pairs(details) do
if legal_detail[index] then
this[index] = item
engine:SetAttribute(index,item)
end
end
local speed = math.abs(rot(this.rotor))
if details.Starter then
-- Starter on
if this.starter_sound then if not this.starter_sound.Playing then this.starter_sound:Play() end end
if this.rotor_sound then if this.rotor_sound.Playing then this.rotor_sound:Pause() end end
elseif speed > this.speed.Value * 0.1 then
-- Running
if this.rotor_sound then
if not this.rotor_sound.Playing then this.rotor_sound:Play() end
_G.Print(engine,this.rotor_sound.PlaybackSpeed,speed,this.speed.Value/60)
this.rotor_sound.PlaybackSpeed = math.clamp(math.abs(speed/150) * 1.5,0.5,1.5)
this.rotor_sound.Volume = math.clamp(math.abs(speed/150) * 0.05 + 0.05,0,0.1)
end
if this.starter_sound then if this.starter_sound.Playing then this.starter_sound:Stop() end end
else
if this.rotor_sound then if this.rotor_sound.Playing then this.rotor_sound:Stop() end end
if this.starter_sound then if this.starter_sound.Playing then this.starter_sound:Stop() end end
end
end
module.messages = {
control = function(this,object,context,value)
this.throttle = value
end,
starter = function(this,object,context,value)
this.starter = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"Engine",
"Engine2",
"BigEngine",
"BigRadial",
"Radial",
"Jet",
"Motor",
"Motor1",
"BigSpinWheel",
"SpinWheel"
}
return module
+37
View File
@@ -0,0 +1,37 @@
local module = {}
local limit = 4
local bullet = require(_G.Modules.BulletModule)
function module.new(this,gun,context)
this.barrel = _G.GetInstance(gun,"Barrel")
this.binding = _G.GetInstance(gun,"Binding")
this.rate = _G.GetValue(gun,"Rate",0.15)
this.last = tick()
end
module.run = _G.Protect(function(this,gun,context)
if (this.control or context.controls[this.binding.Value] or 0) < 0.5 then return true end
if tick() - this.last < this.rate then return true end
-- Fire
bullet.fire(this.barrel)
this.last = tick()
this.barrel:ApplyImpulse(this.barrel.CFrame.RightVector * -500)
return true
end)
module.fire_rate = 0.05
module.messages = {
control = function(this,gun,context,value)
this.control = value
end,
}
module.manifest = {
"Gun",
"Cannon"
}
return module
+34
View File
@@ -0,0 +1,34 @@
local module = {}
function module.new(this,hinge,context)
this.hinge = _G.GetInstance(hinge,"HingeConstraint")
local function update()
if this.limited then this.hinge.LimitsEnabled = this.limited.Value end
if this.lower then this.hinge.LowerAngle = this.lower.Value end
if this.upper then this.hinge.UpperAngle = this.upper.Value end
end
if _G.IsServer then
this.limited = hinge:FindFirstChild("Limited")
this.upper = hinge:FindFirstChild("Upper")
this.lower = hinge:FindFirstChild("Lower")
if this.limited then this.limited.Changed:Connect(update) end
if this.lower then this.lower.Changed:Connect(update) end
if this.upper then this.upper.Changed:Connect(update) end
end
return this
end
module.manifest = {
"FlatServoRoll",
"FlatServoPitch",
"Servo",
"ControlSheet",
"NanoControlSheet",
"MetalServo",
"Spinner",
"Hinge",
"Rotator",
"RotatorPlate"
}
return module
+45
View File
@@ -0,0 +1,45 @@
local module = {}
function position(motor,phase,phases,target,origin)
motor.C0 = origin
local alpha = (phase)/(phases-1)
motor.C1 = CFrame.new():Lerp(target,alpha)
end
function module.new(this,lever,context)
this.motor = _G.GetInstance(lever,"Motor")
this.phase = _G.GetInstance(lever,"Phase")
this.phases = _G.GetInstance(lever,"Phases")
this.hold = _G.GetInstance(lever,"Hold")
this.click = _G.GetInstance(this.hold,"ClickDetector")
this.target = lever:GetAttribute("Target") or error("Needs target attribute.")
this.origin = lever:GetAttribute("Origin") or error("Needs target attribute.")
if _G.IsServer then
module.update(this,lever,context)
this.click.MouseClick:Connect(function()
if this.phase.Value == this.phases.Value - 1 then
this.phase.Value = 0
else
this.phase.Value += 1
end
print(this.phase.Value)
module.update(this,lever,context)
context.connected("ConnectorData",nil,lever.PrimaryPart,function(object)
print("firing",this.phase.Value)
context.message(object,nil,this.phase.Value/(this.phases.Value-1))
end)
end)
end
end
function module.update(this,lever,context)
if _G.IsServer then
position(this.motor,this.phase.Value,this.phases.Value,this.target,this.origin)
end
end
module.manifest = {
"Lever"
}
return module
+26
View File
@@ -0,0 +1,26 @@
local module = {}
local function setup(this,mesh,context)
this.mesh.MeshId = string.format("rbxassetid://%i",this.meshid.Value)
this.mesh.TextureId = string.format("rbxassetid://%i",this.textureid.Value)
this.mesh.Scale = mesh.Size * this.scale.Value
end
function module.new(this,mesh,context)
this.meshid = _G.GetInstance(mesh,"MeshId")
this.textureid = _G.GetInstance(mesh,"TextureId")
this.scale = _G.GetInstance(mesh,"Scale")
this.mesh = _G.GetInstance(mesh,"Mesh")
setup(this,mesh,context)
return this
end
function module.update(this,mesh,context)
setup(this,mesh,context)
end
module.manifest = {
"Prop"
}
return module
+40
View File
@@ -0,0 +1,40 @@
local module = {}
function module.new(this,piston,context)
this.servo = _G.GetInstance(piston,"Servo")
this.extension = _G.GetInstance(piston,"Extension")
this.binding = _G.GetInstance(piston,"Binding")
this.inverted = _G.GetInstance(piston,"Inverted")
this.force = _G.GetInstance(piston,"Force")
return this
end
local begin = tick()
module.run = _G.Protect(function(this,servo,context)
local control = (this.control or context.controls[this.binding.Value] or 0)
if this.inverted.Value then control = 1 - control end
this.servo.TargetPosition = servo.Extension.Value * control * servo:GetScale() + (this.offset or 0)
context.replicate(this,servo,module,this.servo.TargetPosition)
end)
module.replication_delta = 0.25
function module.replicate(this,servo,context,value)
servo.ServoMaxForce = this.force.Value * servo:GetScale() ^ 2
servo.TargetPosition = value
end
module.messages = {
control = function(this,object,context,value)
this.control = value
end,
offset = function(this,object,context,value)
this.offset = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"Piston"
}
return module
+126
View File
@@ -0,0 +1,126 @@
local module = {}
local dens = game.Workspace.AirDensity * -game.Workspace.CompensateDensity.Value
local bias = 0.2
local propeller_power_mod = 0.1
local propeller_cut_mod = 5/2
local propeller_reaction_mod = 0.05
game.Workspace.CompensateDensity.Changed:Connect(function()
dens = game.Workspace.AirDensity * -game.Workspace.CompensateDensity.Value
end)
_G.Events.Command.Event:Connect(function(message)
local value = message:match("setprop%((.-)%)")
if not value then return end
if tonumber(value) then
game.Workspace.CompensateDensity = tonumber(value)
_G.Events.Notification:Fire("Set Prop Density","PropBias.Value = "..value)
else
_G.Events.Notification:Fire("Set Prop Density","Invalid number.")
end
end)
local function setup(this,propeller,context)
local angle = _G.GetValue(propeller,"Trim",30)
for _,child in pairs(propeller:GetChildren()) do
if child.Name == "Blade" then
local welds = child:GetJoints()
local joint = child:FindFirstChild("Weld")
if not child:FindFirstChild("Weld") then
local c0 = propeller.PrimaryPart.CFrame:ToObjectSpace(child.CFrame)
joint = Instance.new("Motor6D")
joint.Name = "Weld"
joint.Parent = child
joint.Part0 = propeller.PrimaryPart
joint.Part1 = child
joint.C0 = c0
end
local flip = 0
if angle < 0 then flip = 180 end
local axis = (propeller:GetAttribute("Axis") or Vector3.new(0,0,1)) * (math.rad(-angle+flip))
local rotation = CFrame.Angles(axis.X,axis.Y,axis.Z)
joint.C1 = rotation
for _,weld in pairs(welds) do if weld:IsA("WeldConstraint") then weld:Destroy() end end
end
end
end
function module.new(this,propeller,context)
local size = propeller:GetExtentsSize()
this.scale = size.X * size.Z * 1.5
this.length = size.X
this.power = _G.GetValue(propeller,"Force",1000) * this.scale * 0.01
this.direction = _G.GetValue(propeller,"Direction",CFrame.identity)
this.rotor = propeller:FindFirstChild("Spin") or propeller:FindFirstChild("Hinge")
this.trim = _G.GetValue(propeller,"Trim",30)
this.blur = propeller:FindFirstChild("Blur")
if not this.rotor then error("Missing rotor") end
this.force = _G.GetInstance(propeller,"VectorForce")
this.sound = _G.GetInstance(this.rotor,"PropSound")
this.sound:Play()
setup(this,propeller,context)
return this
end
function module.update(this,propeller,context)
print("upd")
setup(this,propeller,context)
end
function module.idle(this,engine) return true end
local a = 300
local function limit(f)
return math.tanh(f/a)*a
end
local begin = tick()
module.run = _G.Protect(function(this,propeller,context)
local angular_velocity = ((this.rotor.CFrame.Rotation * this.direction):PointToObjectSpace(this.rotor.AssemblyAngularVelocity)).X
local linear_velocity = angular_velocity * math.sin(math.rad(this.trim))
local air_velocity = this.rotor.CFrame.Rotation:PointToObjectSpace(this.rotor.AssemblyLinearVelocity).X
local real_velocity = limit((linear_velocity * propeller_cut_mod * this.length) - air_velocity)
local rpm = (angular_velocity/(math.pi*2))*60
local multiplier = (this.sound:GetAttribute("Multiplier") or 1) * 0.01
this.force.Force = Vector3.new(0,0,-real_velocity*this.power*propeller_power_mod*dens)
this.rotor:ApplyAngularImpulse(
(this.rotor.CFrame.Rotation * this.direction).RightVector
* -angular_velocity
* math.cos(math.rad(this.trim))
* propeller_reaction_mod)
context.replicate(this,propeller,module,math.abs(rpm*dens*multiplier))
return true
end)
module.replication_delta = 0.1
function module.replicate(this,propeller,context,value)
this.sound.PlaybackSpeed = math.clamp(value,0.1,1.5)
this.sound.Volume = math.clamp(value,0,this.sound:GetAttribute("Max") or 1)
if this.blur then
this.blur.Transparency = math.clamp(1-value,0.3,1)
end
for _,blade in pairs(propeller:GetChildren()) do
if blade.Name == "Blade" then
blade.Transparency = math.clamp(value,0,0.7)
end
end
end
module.messages = {
trim = function(this,object,context,value)
end
}
module.messages.default = module.messages.trim
module.manifest = {
"Propeller",
"Turbine",
"LargePropeller",
"BiPropeller",
"Jet"
}
return module
+46
View File
@@ -0,0 +1,46 @@
local module = {}
function module.new(this,rocket,context)
this.scale = rocket:GetExtentsSize().Magnitude -- same as with the equivalent statement on the wing! BRRRRRRRRRRR
this.binding = _G.GetInstance(rocket,"Binding")
this.exhaust = _G.GetInstance(rocket,"Exhaust")
this.sound = _G.GetInstance(this.exhaust,"Sound")
this.force = _G.GetInstance(rocket,"Force")
this.inverted = _G.GetInstance(rocket,"Inverted")
return this
end
function module.idle(this,engine) return true end
local begin = tick()
module.run = _G.Protect(function(this,engine,context)
local throttle = this.throttle or context.controls[_G.GetValue(engine,"Binding","throttle")] or this.Throttle or 0
if this.inverted.Value then throttle = -throttle end
context.replicate(this,engine,module,math.clamp(throttle,0,1))
return true
end)
module.replication_delta = 0.25
function module.replicate(this,rocket,context,throttle)
this.exhaust:ApplyImpulseAtPosition(this.exhaust.CFrame.RightVector * throttle * this.scale * this.force.Value * context.delta * -1000, this.exhaust.Position)
this.exhaust.Flame.Rate = throttle * 1000
this.sound.Volume = math.clamp(throttle,0,1)
if _G.IsServer and this.sound.Volume > 0 then this.sound:Play() else this.sound:Pause() end
end
module.messages = {
control = function(this,object,context,value)
this.throttle = value
end,
starter = function(this,object,context,value)
this.starter = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"Rocket",
"BigRocket"
}
return module
+91
View File
@@ -0,0 +1,91 @@
local module = {}
local partStateModule = require(_G.Modules.PartStateModule)
function setup(this,rope,context)
local function new(name,tab)
local part = Instance.new(name)
_G.Union(part,tab)
return part
end
local node1 = rope["1"]
local node2 = rope["2"]
if rope.Name == "Shaft" then -- Make two universal constraints
local constraint1 = new("UniversalConstraint",{
Parent = node1,
Attachment0 = new("Attachment",{
Parent = node1
}),
Attachment1 = new("Attachment",{
Parent = rope,
WorldCFrame = node1.CFrame
})
})
local constraint2 = new("UniversalConstraint",{
Parent = node2,
Attachment0 = new("Attachment",{
Parent = node2
}),
Attachment1 = new("Attachment",{
Parent = rope,
WorldCFrame = node2.CFrame
})
})
elseif rope.Name == "Rope" or rope.Name == "Rod2" then
rope.Transparency = 1
rope.CanCollide = false
rope.Massless = true
local name
if rope.name == "Rope" then name = "RopeConstraint" end
if rope.Name == "Rod2" then name = "RodConstraint" end
local constraint = new(name,{
Parent = rope,
Attachment0 = new("Attachment",{
Parent = node1
}),
Attachment1 = new("Attachment",{
Parent = node2
}),
Visible = true,
Thickness = rope.Size.Y
})
if rope.Length.Value == 0 then rope.Length.Value = constraint.CurrentDistance end
constraint.Length = rope.Length.Value
end
node1.CanCollide = true -- Resize and make nodes non-collide
node2.CanCollide = true
node1.Size = Vector3.one * rope.Size.Y
node2.Size = node1.Size
for index,joint in pairs(rope:GetJoints()) do -- Fix welds in new version
if joint:IsA("WeldConstraint") then
local other = joint.Part0
if joint.Part0 == rope then other = joint.Part1 end
local closest = node1
if (node2.Position-other.Position).Magnitude < (node1.Position-other.Position).Magnitude then closest = node2 end
new("WeldConstraint",{
Parent = rope,
Part0 = closest,
Part1 = other,
Name = "BuiltWeldConstraint"
})
if index > 1 then joint:Destroy() end
end
end
end
function module.new(this,rope,context)
if _G.IsServer then setup(this,rope,context) end
return this
end
module.manifest = {
"Rod2",
"Rope",
"Shaft"
}
return module
+99
View File
@@ -0,0 +1,99 @@
local module = {}
local function targetHinge(target,hinge,stationary,angle,negative)
local attachment = stationary:FindFirstChildWhichIsA("Attachment")
local o = attachment.WorldCFrame:PointToObjectSpace(target)
local x,y,z = CFrame.lookAlong(attachment.WorldCFrame.Position,attachment.WorldCFrame.UpVector,attachment.WorldCFrame.RightVector):ToObjectSpace(
CFrame.lookAt(
attachment.WorldCFrame.Position,
attachment.WorldCFrame:PointToWorldSpace(Vector3.new(0,o.Y,o.Z)*negative)
)):ToEulerAnglesYXZ()
hinge.TargetAngle = -math.deg(y) + angle
end
function module.new(this,servo,context)
this.scale = servo:GetExtentsSize().Magnitude
this.hinge = _G.GetInstance(servo,"HingeConstraint")
this.binding = _G.GetInstance(servo,"Binding")
this.inverted = servo:FindFirstChild("Inverted")
this.offset = servo:FindFirstChild("Offset")
this.range = servo:FindFirstChild("Angle")
this.target = servo:FindFirstChild("Target")
this.torque = servo:FindFirstChild("Torque")
return this
end
local begin = tick()
module.run = _G.Protect(function(this,servo,context)
local shouldInvert = 1
local shouldOffset = 0
local pitchTrim = 0
local angle = 30
if context.seat and context.seat:FindFirstChild("PitchTrim") then pitchTrim = context.seat.PitchTrim.Value end
if this.inverted and this.inverted.Value then shouldInvert = -1 end
if this.offset and this.offset.Value then shouldOffset = this.offset.Value + (this.starter or 0) end
if this.range and this.range.Value then angle = this.range.Value end
if this.torque and this.torque.Value then this.hinge.MotorMaxTorque = this.torque.Value * ((servo:GetAttribute("Health") or 1) / (servo:GetAttribute("MaxHealth") or 1)) end
local control = (this.control or context.controls[this.binding.Value])
if this.target and this.target.Value then
this.hinge.LimitsEnabled = false
if context.cursor then
targetHinge(context.cursor,this.hinge,this.hinge.Attachment1.Parent,this.offset.Value,shouldInvert)
end
elseif this.binding.Value == "auto" and context.seat then
local pos = context.seat:GetPivot():ToObjectSpace(this.hinge.Attachment1.WorldCFrame)
local dir = pos.RightVector
pos = pos.Position.Unit
this.hinge.LimitsEnabled = false
this.hinge.TargetAngle = ( (
-context.controls.pitch*dir.x*pos.Z
-context.controls.yaw*dir.y*pos.Z
+context.controls.roll*dir.x*pos.X
) * angle + pitchTrim*dir.x*pos.Z
) * shouldInvert + shouldOffset
elseif control then
if this.binding.Value == "pitch" then shouldOffset = shouldOffset + pitchTrim end
this.hinge.LimitsEnabled = true
this.hinge.TargetAngle = control * angle * shouldInvert + shouldOffset
end
local distance = (this.hinge.Attachment1.WorldCFrame.Position - this.hinge.Attachment1.WorldCFrame.Position).Magnitude
if distance < 2 then
context.replicate(this,servo,module,this.hinge.TargetAngle,this.hinge.LimitsEnabled)
return true
else
context.replicate(this,servo,module,nil,nil)
return false
end
end)
module.replication_delta = 0.25
function module.replicate(this,servo,context,angle)
if not angle then
this.hinge:Destroy()
else
this.hinge.TargetAngle = angle
end
end
module.messages = {
control = function(this,object,context,value)
this.control = value
end,
offset = function(this,object,context,value)
this.starter = value
end,
}
module.messages.default = module.messages.control
module.manifest = {
"FlatServoRoll",
"FlatServoPitch",
"Servo",
"ControlSheet",
"NanoControlSheet",
"MetalServo"
}
return module
+26
View File
@@ -0,0 +1,26 @@
local module = {}
function module.new(this,speaker,context)
this.main = _G.GetInstance(speaker,"Main")
this.tts = _G.GetInstance(this.main,"AudioTextToSpeech")
end
function module.replicate(this,speaker,context,value)
this.tts.Text = tostring(value or "") or ""
if _G.IsClient then
if this.tts.IsPlaying then return end
this.tts:Play()
end
end
module.messages = {
default = function(this,speaker,context,value)
context.replicate(this,speaker,module,value)
end
}
module.manifest = {
"Speaker"
}
return module
+27
View File
@@ -0,0 +1,27 @@
local module = {}
local spring_modifier = 1
local function setup(this,spring,context)
this.spring.Damping = _G.GetValue(spring,"Dampness",this.spring.Damping)
this.spring.Stiffness = _G.GetValue(spring,"Stiffness",this.spring.Stiffness) * spring_modifier * spring:GetScale()^3
this.spring.Visible = this.spring.Stiffness > 0
end
function module.new(this,spring,context)
this.spring = _G.GetInstance(spring,"SpringConstraint")
setup(this,spring,context)
end
function module.update(this,spring,context)
print("setup")
setup(this,spring,context)
end
module.update = module.new
module.manifest = {
"Coilover",
"Wheel"
}
return module
+38
View File
@@ -0,0 +1,38 @@
local module = {}
local cool_rate = 0.5
function module.new(this,turbine,context)
this.heat = 0
this.hinge = _G.GetInstance(turbine,"HingeConstraint")
this.speed = _G.GetInstance(turbine,"Speed")
this.inverted = _G.GetInstance(turbine,"Inverted")
end
function module.run(this,turbine,context)
this.heat = this.heat * (1 - cool_rate * context.delta) -- wrong but idc
local mul = 1
if this.inverted.Value then mul = -1 end
this.hinge.AngularVelocity = (1-(1/(1 + this.heat))) * this.speed.Value * mul
this.hinge.MotorMaxTorque = 10000 * this.speed.Value
context.replicate(this,turbine,module,this.heat)
return true
end
function module.replicate(this,turbine,context,heat)
this.heat = heat
end
module.update = module.new
module.messages = {
flux = function(this,turbine,context,heat)
this.heat = this.heat + heat
end,
}
module.messages.default = nil
module.manifest = {
"Turbine1"
}
return module