Copy salient and essential scripts and models from Plane Building Roblox
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user