--@server --@include ./enums/powertrain_component.txt --@include ./factories/powertrain_component.txt --@include /koptilnya/libs/table.txt --@include /koptilnya/libs/constants.txt local PowertrainComponentFactory = require('./factories/powertrain_component.txt') local CustomWheel = require('./wheel/wheel.txt') local POWERTRAIN_COMPONENT = require('./enums/powertrain_component.txt') require('/koptilnya/libs/table.txt') require('/koptilnya/libs/constants.txt') local Vehicle = class('Vehicle') function Vehicle:initialize(config) if not Vehicle:validateConfig(config) then throw('Please check your vehicle configuration!') end self.config = config self.components = {} self.independentComponents = {} self:createComponents() self:linkComponents() self:createIO() self.rootComponent = self:getRootComponent() self.steer = 0 self.brake = 0 self.handbrake = 0 hook.add('input', 'vehicle_wire_input', function(name, value) self:handleWireInput(name, value) end) hook.add('tick', 'vehicle_update', function() self:update() end) end function Vehicle.static:validateConfig(config) return type(config) == 'table' end function Vehicle:getComponentByName(name) return table.find(self.components, function(component) return component.name == name end) end function Vehicle:createComponents() for _, componentConfig in pairs(self.config) do local component = PowertrainComponentFactory:create(self, componentConfig.Type, componentConfig.Name, componentConfig.Config) table.insert(self.components, component) end end function Vehicle:linkComponents() for _, componentConfig in pairs(self.config) do local component = self:getComponentByName(componentConfig.Name) if componentConfig.Type == POWERTRAIN_COMPONENT.Wheel and componentConfig.Input == nil then table.insert(self.independentComponents, component) else local inputComponent = self:getComponentByName(componentConfig.Input) if inputComponent ~= nil then inputComponent:linkComponent(component) end end end end function Vehicle:createIO() local inputs = { Base = 'entity', Steer = 'number', Brake = 'number', Handbrake = 'number' } local outputs = {} for _, component in ipairs(self.components) do inputs = table.merge(inputs, component.wireInputs) outputs = table.merge(outputs, component.wireOutputs) end wire.adjustPorts(inputs, outputs) end function Vehicle:getRootComponent() return table.find(self.components, function(component) return component.input == nil end) end function Vehicle:handleWireInput(name, value) if name == 'Base' then self.base = value self.basePhysObject = isValid(value) and value:getPhysicsObject() or nil elseif name == 'Steer' then self.steer = value elseif name == 'Brake' then self.brake = value elseif name == 'Handbrake' then self.handbrake = value end end function Vehicle:update() local base = wire.ports.Base self.rootComponent:forwardStep() for _, component in pairs(self.independentComponents) do component:forwardStep(0, component:queryInertia()) end for _, component in pairs(self.components) do component:updateWireOutputs() end --if isValid(base) and (self.clutch:getPress() == 1 or self.gearbox.ratio == 0) then -- local tiltForce = self.engine.torque * (-1 + self.engine.masterThrottle * 2) -- -- base:applyForceOffset(base:getUp() * tiltForce, base:getMassCenter() + base:getRight() * UNITS_PER_METER) -- base:applyForceOffset(-base:getUp() * tiltForce, base:getMassCenter() - base:getRight() * UNITS_PER_METER) --end end return { Vehicle, POWERTRAIN_COMPONENT }