--[[ Specialization to increase the RPM while tipping Author: Ifko[nator] Date: 22.12.2015 Version: 1.9 History: V 1.0 @ 28.10.2015 - intial release V 1.1 @ 29.10.2015 - added support for the gear box addon by mogli V 1.5 @ 01.11.2015 - added support for vehicles wich have no standard indoor hud added support for vehicles wich have no standard exhaust effect added support for the exhaust flap V 1.8 @ 06.12.2015 - the RPM will now increase for the whole tipping duration if the body is not moving upwards V 1.9 @ 22.12.2015 - added support for the it runner hook lift trailer Big Thanks to Marhu for helping me out with some issues !! ]] IncreaseRPMWhileTipping = {}; local increaseRPMWhileTippingDirectory = g_currentModDirectory; function IncreaseRPMWhileTipping.prerequisitesPresent(specializations) return true; end; function IncreaseRPMWhileTipping:load(savegame) local modDesc = loadXMLFile("modDesc", increaseRPMWhileTippingDirectory .. "modDesc.xml"); if SpecializationUtil.hasSpecialization(Drivable, self.specializations) then --## modDesc file self.maxRpmGlobal = Utils.getNoNil(getXMLInt(modDesc, "modDesc.increaseRPMWhileTipping#maxRpm"), self.motor.maxRpm); self.exhaustColorGlobal = Utils.getVectorNFromString(Utils.getNoNil(getXMLString(modDesc, "modDesc.increaseRPMWhileTipping#exhaustColor"), "0 0 0 3"), 4); --## vehicle xml file self.maxRpm = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.increaseRPMWhileTipping#maxRpm"), self.maxRpmGlobal); self.exhaustColorLocal = Utils.getVectorNFromString(getXMLString(self.xmlFile, "vehicle.increaseRPMWhileTipping#exhaustColor"), 4); --## check if value in the vehicle xml file exist, else took modDesc value if self.exhaustColorLocal ~= nil then self.exhaustColor = self.exhaustColorLocal; else self.exhaustColor = self.exhaustColorGlobal; end; self.colorRed = self.exhaustColor[1]; self.colorGreen = self.exhaustColor[2]; self.colorBlue = self.exhaustColor[3]; self.colorAlphaMax = self.exhaustColor[4]; self.colorAlpha = 1; self.increaseRPM = SpecializationUtil.callSpecializationsFunction("increaseRPM"); self.minRpmStart = Utils.getNoNil(getXMLInt(self.xmlFile, "vehicle.motor#minRpm"), 1000); self.rpm = self.minRpmStart; --#IndoorHud.updateTick = Utils.overwrittenFunction(IndoorHud.updateTick, IncreaseRPMWhileTipping.updateTickIndoorHud); Motorized.updateTick = Utils.overwrittenFunction(Motorized.updateTick, IncreaseRPMWhileTipping.updateTickMotorized); self.hasChangedGearBoxAddon = false; end; self.isTestModeGlobal = Utils.getNoNil(getXMLBool(modDesc, "modDesc.increaseRPMWhileTipping#isTestMode"), false); self.isTestMode = Utils.getNoNil(getXMLBool(self.xmlFile, "vehicle.increaseRPMWhileTipping#isTestMode"), self.isTestModeGlobal); self.doIncrease = false; self.isSelectable = true; --## make ANY vehicle selectable! self.isTipScrollerVehicle = hasXMLProperty(self.xmlFile, "vehicle.tipScrollerNodes"); local filename = getXMLString(self.xmlFile, "vehicle.filename"); if string.find(self.configFileName, "pdlc/itRunnerPack") and g_modNameToDirectory["pdlc_itRunnerPack"] then self.isItRunnerHookLiftTrailerModul = filename == "itRunner/containerSilage.i3d" or filename == "itRunner/containerDumper.i3d"; self.isItRunnerHookLiftTrailer = filename == "itRunner/itRunner2633HD.i3d"; else self.isItRunnerHookLiftTrailerModul = false; self.isItRunnerHookLiftTrailer = false; end; self.isOverloadVehicle = SpecializationUtil.hasSpecialization(Overloading, self.specializations) or string.find(filename, "flieglOverloadStation") or false; if self.isTestMode then print(" loaded IncreaseRPMWhileTipping in: '" .. self.configFileName .. "'."); print(" 'isTipScrollerVehicle' is '" .. tostring(self.isTipScrollerVehicle) .. "'."); print(" 'isItRunnerHookLiftTrailerModul' is '" .. tostring(self.isItRunnerHookLiftTrailerModul) .. "'."); print(" 'isItRunnerHookLiftTrailer' is '" .. tostring(self.isItRunnerHookLiftTrailer) .. "'."); print(" 'isOverloadVehicle' is '" .. tostring(self.isOverloadVehicle) .. "'."); end; delete(modDesc); end; function IncreaseRPMWhileTipping:update(dt) if self.isClient and self:getIsActive() then local trailer; for _, attachedTrailer in pairs(self.attachedImplements) do if attachedTrailer.object ~= nil then --## one or more trailer attached trailer = attachedTrailer.object; if trailer.isTipScrollerVehicle or trailer.isItRunnerHookLiftTrailerModul then self.doIncrease = trailer.tipState == Trailer.TIPSTATE_OPENING or trailer.tipState == Trailer.TIPSTATE_OPEN or trailer.doIncrease; elseif trailer.isItRunnerHookLiftTrailer then self.doIncrease = trailer:getIsAnimationPlaying("unfoldHand") or trailer.doIncrease; elseif trailer.isOverloadVehicle then self.doIncrease = trailer.pipeIsUnloading; else self.doIncrease = trailer.tipState == Trailer.TIPSTATE_OPENING or trailer.doIncrease; end; end; end; if SpecializationUtil.hasSpecialization(Drivable, self.specializations) and self.isMotorStarted then --## drivable vehicle if trailer ~= nil then --## one or more trailer attached if trailer.isTipScrollerVehicle or trailer.isItRunnerHookLiftTrailerModul then if self.isTipScrollerVehicle then self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN or trailer.tipState == Trailer.TIPSTATE_OPENING or trailer.tipState == Trailer.TIPSTATE_OPEN or trailer.doIncrease; else self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or trailer.tipState == Trailer.TIPSTATE_OPENING or trailer.tipState == Trailer.TIPSTATE_OPEN or trailer.doIncrease; end; elseif trailer.isItRunnerHookLiftTrailer then if self.isTipScrollerVehicle then self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN or trailer:getIsAnimationPlaying("unfoldHand") or trailer.doIncrease; else self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or trailer:getIsAnimationPlaying("unfoldHand") or trailer.doIncrease; end; elseif trailer.isOverloadVehicle then if self.isTipScrollerVehicle then self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN or self.pipeIsUnloading or trailer.pipeIsUnloading or trailer.doIncrease; else self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or self.pipeIsUnloading or trailer.pipeIsUnloading or trailer.doIncrease; end; elseif self.isOverloadVehicle then --## combine with cutter attached --self.doIncrease = self.pipeIsUnloading; else self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or trailer.tipState == Trailer.TIPSTATE_OPENING or trailer.doIncrease; end; else --## no trailer attached if self.tipState ~= nil then if self.isTipScrollerVehicle then self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING or self.tipState == Trailer.TIPSTATE_OPEN; else self.doIncrease = self.tipState == Trailer.TIPSTATE_OPENING; end; elseif self.isOverloadVehicle then --## combine --self.doIncrease = self.pipeIsUnloading; else self.doIncrease = false; end; end; self:increaseRPM(dt, self.doIncrease); end; end; end; function IncreaseRPMWhileTipping:updateTickIndoorHud(updateTick, dt) if self:getIsActive() then --## overwrite the whole 'IndoorHud:updateTick' function to stop update the rpm hud value while tipping if self.indoorHud.speed ~= nil then local maxSpeed = 30; if self.cruiseControl ~= nil then maxSpeed = self.cruiseControl.maxSpeed; end; self:setHudValue(self.indoorHud.speed, g_i18n:getSpeed(self:getLastSpeed() * self.speedDisplayScale), g_i18n:getSpeed(maxSpeed)); end; if self.indoorHud.rpm ~= nil and self.rpm == self.minRpmStart then self:setHudValue(self.indoorHud.rpm, self.motor.lastMotorRpm, self.motor.maxRpm); end; if self.indoorHud.fuel ~= nil then self:setHudValue(self.indoorHud.fuel, self.fuelFillLevel, self.fuelCapacity); end; if self.indoorHud.fuel ~= nil then self:setHudValue(self.indoorHud.fuel, self.fuelFillLevel, self.fuelCapacity); end; if self.indoorHud.fillLevel ~= nil and self.fillLevel ~= nil and self.getCapacity ~= (nil and 0) then self:setHudValue(self.indoorHud.fillLevel, self.fillLevel, self:getCapacity()); end; if self.indoorHud.operatingTime ~= nil and self.operatingTime ~= nil then local minutes = self.operatingTime / (1000 * 60); local hours = math.floor(minutes / 60); minutes = math.floor(minutes - hours * 60); local minutesString = string.format("%02d", minutes); self:setHudValue(self.indoorHud.operatingTime, tonumber(hours .. "." .. minutesString), self.maxOperatingTime); end; if self.indoorHud.workedHectars ~= nil and self.workedHectars ~= nil then self:setHudValue(self.indoorHud.workedHectars, self.workedHectars, 9999); end; if self.indoorHud.diameter ~= nil and self.lastDiameter ~= nil then self:setHudValue(self.indoorHud.diameter, self.lastDiameter*1000, 9999); end; if self.indoorHud.cutLength ~= nil and self.currentCutLength ~= nil then self:setHudValue(self.indoorHud.cutLength, self.currentCutLength*100, 9999); end; if self.indoorHud.time ~= nil then local minutes = g_currentMission.environment.currentMinute; local hours = g_currentMission.environment.currentHour; local minutesString = string.format("%02d", minutes); self:setHudValue(self.indoorHud.time, tonumber(hours .. "." .. minutesString), 9999); end; if self.indoorHud.cruiseControl ~= nil and self.cruiseControl ~= nil then self:setHudValue(self.indoorHud.cruiseControl, self.cruiseControl.speed, 9999); end; end; end; function IncreaseRPMWhileTipping:updateTickMotorized(updateTick, dt) --## overwrite the whole 'Motorized:updateTick' function to stop update the exhaust effect and flap while tipping if self.isServer then if math.abs(self.fuelFillLevel - self.sentFuelFillLevel) > 0.001 then self:raiseDirtyFlags(self.motorizedDirtyFlag); self.sentFuelFillLevel = self.fuelFillLevel; end; --## needed for refillig fuel if self.isFuelFilling then local delta = 0; if self.fuelFillTrigger ~= nil then delta = self.fuelFillLitersPerSecond * dt * 0.001; delta = self.fuelFillTrigger:fillFuel(self, delta); end; if delta <= 0.001 then self:setIsFuelFilling(false); end; end; end; if self.isClient then if self.isMotorStarted then if self.exhaustParticleSystems.minScale ~= nil and self.exhaustParticleSystems.maxScale ~= nil then local scale = Utils.lerp(self.exhaustParticleSystems.minScale, self.exhaustParticleSystems.maxScale, self.motor.lastMotorRpm / self.motor.maxRpm); Utils.setEmitCountScale(self.exhaustParticleSystems, scale); for _, ps in ipairs(self.exhaustParticleSystems) do setParticleSystemLifespan(ps.geometry, ps.originalLifespan * scale, true); end; end; if self.exhaustFlap ~= nil and self.rpm == self.minRpmStart then local minRandom = -0.1; local maxRandom = 0.1; local angle = Utils.lerp(minRandom, maxRandom, math.random()) + self.exhaustFlap.maxRot * (self.motor.lastMotorRpm / self.motor.maxRpm); angle = Utils.clamp(angle, 0, self.exhaustFlap.maxRot); setRotation(self.exhaustFlap.node, angle, 0, 0); end; if self.exhaustEffects ~= nil then local lastSpeed = self:getLastSpeed(); self.currentDirection = {localDirectionToWorld(self.rootNode, 0, 0, 1)}; if self.lastDirection == nil then self.lastDirection = self.currentDirection; end; local x,y,z = worldDirectionToLocal(self.rootNode, self.lastDirection[1], self.lastDirection[2], self.lastDirection[3]); local dot = z; dot = dot / Utils.vector2Length(x,z); local angle = math.acos(dot); if x < 0 then angle = -angle; end; local steeringPercent = math.abs((angle / dt) / self.exhaustEffectMaxSteeringSpeed); self.lastDirection = self.currentDirection; for _, effect in pairs(self.exhaustEffects) do local rpmScale = self.motor.lastMotorRpm / self.motor.maxRpm; local scale = Utils.lerp(effect.minRpmScale, effect.maxRpmScale, rpmScale); local forwardXRot = effect.forwardXRotations[2]; local forwardZRot = effect.forwardZRotations[2]; local steerXRot = effect.steerXRotations[2]; local steerZRot = effect.steerZRotations[2]; local r = Utils.lerp(effect.minRpmColor[1], effect.maxRpmColor[1], rpmScale); local g = Utils.lerp(effect.minRpmColor[2], effect.maxRpmColor[2], rpmScale); local b = Utils.lerp(effect.minRpmColor[3], effect.maxRpmColor[3], rpmScale); local a = Utils.lerp(effect.minRpmColor[4], effect.maxRpmColor[4], rpmScale); if self.rpm == self.minRpmStart then setShaderParameter(effect.effectNode, "exhaustColor", r, g, b, a, false); end; -- speed rotation if self.movingDirection == 1 then local percent = Utils.clamp(lastSpeed/effect.maxForwardSpeed, 0, 1); forwardXRot = effect.forwardXRotations[1] * percent; forwardZRot = effect.forwardZRotations[1] * percent; elseif self.movingDirection == -1 then local percent = Utils.clamp(lastSpeed/effect.maxBackwardSpeed, 0, 1); forwardXRot = effect.forwardXRotations[3] * percent; forwardZRot = effect.forwardZRotations[3] * percent; end; -- steering rotation if angle > 0 then steerXRot = effect.steerXRotations[1] * steeringPercent; steerZRot = effect.steerZRotations[1] * steeringPercent; elseif angle < 0 then steerXRot = effect.steerXRotations[3] * steeringPercent; steerZRot = effect.steerZRotations[3] * steeringPercent; end; -- target rotations local targetXRot = forwardXRot + steerXRot; local targetZRot = forwardZRot + steerZRot; -- damping if targetXRot > effect.xRot then effect.xRot = math.min(effect.xRot + 0.003*dt, targetXRot); else effect.xRot = math.max(effect.xRot - 0.003*dt, targetXRot); end; if targetZRot > effect.xRot then effect.zRot = math.min(effect.zRot + 0.003*dt, targetZRot); else effect.zRot = math.max(effect.zRot - 0.003*dt, targetZRot); end; setShaderParameter(effect.effectNode, "param", effect.xRot, effect.zRot, 0, scale, false); end; end; end; end; end; function IncreaseRPMWhileTipping:delete() end; function IncreaseRPMWhileTipping:increaseRPM(dt, isActive) if dt ~= nil then if isActive then if self.mrGbMS ~= nil then --## gearBoxAddon by mogli found if self:mrGbMGetIsOn(true) and not self.hasChangedGearBoxAddon then self:mrGbMSetIsOnOff(false); self.hasChangedGearBoxAddon = true; end; end; if self.rpm < self.maxRpm then if self.indoorHud ~= nil and self.indoorHud.rpm ~= nil then self.rpm = self.rpm + 8; self:setHudValue(self.indoorHud.rpm, self.rpm, self.maxRpm); end; if self.colorAlpha < (self.colorAlphaMax - 0.05) then self.colorAlpha = self.colorAlpha + 0.05; end; if self.exhaustEffects ~= nil then for _, effect in pairs(self.exhaustEffects) do setShaderParameter(effect.effectNode, "exhaustColor", self.colorRed, self.colorGreen, self.colorBlue, self.colorAlpha, false); end; end; if self.exhaustFlap ~= nil then local minRandom = -0.1; local maxRandom = 0.1; local angle = Utils.lerp(minRandom, maxRandom, math.random()) + self.exhaustFlap.maxRot * (self.rpm / self.maxRpm); angle = Utils.clamp(angle, 0, self.exhaustFlap.maxRot); setRotation(self.exhaustFlap.node, angle, 0, 0); end; end; if self.rpm > self.maxRpm then self.rpm = self.maxRpm; end; self.motor.lastMotorRpm = math.min(self.minRpmStart + dt, self.maxRpm); self.motor.minRpm = math.max(self.motor.minRpm - dt, - self.maxRpm); else if self.mrGbMS ~= nil then --## gearBoxAddon by mogli found if self.hasChangedGearBoxAddon and self.rpm == self.minRpmStart then self:mrGbMSetIsOnOff(true); self.hasChangedGearBoxAddon = false; end; end; if self.rpm > self.minRpmStart then if self.indoorHud ~= nil and self.indoorHud.rpm ~= nil then self.rpm = self.rpm - 12; self:setHudValue(self.indoorHud.rpm, self.rpm, self.maxRpm); end; if self.colorAlpha > 1 then self.colorAlpha = self.colorAlpha - 0.05; end; if self.exhaustEffects ~= nil then for _, effect in pairs(self.exhaustEffects) do setShaderParameter(effect.effectNode, "exhaustColor", self.colorRed, self.colorGreen, self.colorBlue, self.colorAlpha, false); end; end; if self.exhaustFlap ~= nil then local minRandom = -0.1; local maxRandom = 0.1; local angle = Utils.lerp(minRandom, maxRandom, math.random()) + self.exhaustFlap.maxRot * (self.rpm / self.maxRpm); angle = Utils.clamp(angle, 0, self.exhaustFlap.maxRot); setRotation(self.exhaustFlap.node, angle, 0, 0); end; end; if self.rpm < self.minRpmStart then self.rpm = self.minRpmStart; end; self.motor.minRpm = math.min(self.motor.minRpm + dt * 2, self.minRpmStart); end; else self.motor.minRpm = self.minRpmStart; end; end; function IncreaseRPMWhileTipping:draw() if SpecializationUtil.hasSpecialization(Drivable, self.specializations) and self.isTestMode then setTextAlignment(RenderText.ALIGN_CENTER) setTextBold(true); renderText(0.5, 0.53, 0.03, "Test Mode of the Increase RPM While Tipping Script is on!"); setTextBold(false); renderText(0.5, 0.5, 0.025, "min rpm = " .. self.motor.minRpm .. "."); renderText(0.5, 0.475, 0.025, "do rpm increase = " .. tostring(self.doIncrease) .. "."); renderText(0.5, 0.45, 0.025, "tipping rpm = " .. self.rpm .. "."); renderText(0.5, 0.425, 0.025, "exhaust colors = r: " .. self.colorRed .. " g: " .. self.colorGreen .. " b: " .. self.colorBlue .. " a: " .. self.colorAlpha .. "."); renderText(0.5, 0.4, 0.025, "exhaust color alpha max = " .. self.colorAlphaMax .. "."); if self.pipeIsUnloading ~= nil then --renderText(0.5, 0.375, 0.025, "pipe is unloading = " .. tostring(self.pipeIsUnloading) .. "."); end; end; end; function IncreaseRPMWhileTipping:mouseEvent(posX, posY, isDown, isUp, button)end; function IncreaseRPMWhileTipping:keyEvent(unicode, sym, modifier, isDown)end;