--
-- KuhnGMD4010
-- Specialization for KuhnGMD4010
--
-- @author Michael-76
-- @date 10/02/12
--
KuhnGMD4010 = {};
function KuhnGMD4010.prerequisitesPresent(specializations)
return SpecializationUtil.hasSpecialization(Attachable, specializations);
end;
function KuhnGMD4010:load(xmlFile)
local hydraulicsCount = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.hydraulics#count"), 0);
self.hydraulics = {};
for i=1, hydraulicsCount do
local hydraulicName = string.format("vehicle.hydraulics.hydraulic%d", i);
self.hydraulics = {};
self.hydraulics.node = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#index"));
self.hydraulics.punch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punch"));
self.hydraulics.translationPunch = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#punchFixpoint"));
self.hydraulics.fenderFixPoint = Utils.indexToObject(self.components, getXMLString(xmlFile, hydraulicName .. "#fixpoint"));
local ax, ay, az = getWorldTranslation(self.hydraulics.punch);
local bx, by, bz = getWorldTranslation(self.hydraulics.translationPunch);
self.hydraulics.punchDistance = Utils.vector3Length(ax-bx, ay-by, az-bz);
end;
self.arm = {};
self.arm.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.arm#index"));
local y = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#minRot"), 0));
self.arm.minRot = {0,y,0};
y = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#maxRot"), 0));
self.arm.maxRot = {0,y,0};
self.arm.rotTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#rotTime"), 3) * 1000;
self.arm.liftTime = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.arm#liftTime"), 3) * 1000;
self.arm.currentRotLimit = {0};
self.supportArm = {};
self.supportArm.node = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.supportArm#index"));
self.supportArm.node2 = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.supportArm#index2"));
x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#minRot"), 0));
self.supportArm.minRot = {x,0,0};
x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#maxRot"), 0));
self.supportArm.maxRot = {x,0,0};
x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#minRot2"), 0));
self.supportArm.minRot2 = {x,0,0};
x = Utils.degToRad(Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.supportArm#maxRot2"), 0));
self.supportArm.maxRot2 = {x,0,0};
self.arm.isDown = false;
self.arm.isExpanded = false;
self.groundReferenceThreshold = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.groundReferenceNode#threshold"), 0.2);
self.groundReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.groundReferenceNode#index"));
if self.groundReferenceNode == nil then
self.groundReferenceNode = self.components[1].node;
end;
local mowerSound = getXMLString(xmlFile, "vehicle.mowerSound#file");
if mowerSound ~= nil and mowerSound ~= "" then
mowerSound = Utils.getFilename(mowerSound, self.baseDirectory);
self.mowerSound = createSample("mowerSound");
self.mowerSoundEnabled = false;
loadSample(self.mowerSound, mowerSound, false);
self.mowerSoundPitchOffset = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#pitchOffset"), 1);
self.mowerSoundVolume = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.mowerSound#volume"), 1);
end;
local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0);
for i=1, numCuttingAreas do
local areanamei = string.format("vehicle.cuttingAreas.cuttingArea%d", i);
self.cuttingAreas.foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMinLimit"), 0);
self.cuttingAreas.foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMaxLimit"), 1);
self.cuttingAreas[i].grassParticleSystemIndex = getXMLInt(xmlFile, areanamei .. "#particleSystemIndex");
end;
self.isTurnedOn = false;
self.wasToFast = false;
self.grassParticleSystems = {};
local i=0;
while true do
local baseName = string.format("vehicle.grassParticleSystems.grassParticleSystem(%d)", i);
local particleSystem = {};
particleSystem.ps = {};
local ps = Utils.loadParticleSystem(xmlFile, particleSystem.ps, baseName, self.components, false, nil, self.baseDirectory)
if ps == nil then
break;
end;
particleSystem.disableTime = 0;
table.insert(self.grassParticleSystems, particleSystem);
i = i+1;
end;
self.runOnlyOnce = true;
self.attacherVehicleJoint = nil;
self.mowerIsAttached = false;
self.isExpanded = false;
self.isLowered = false;
end;
function KuhnGMD4010:delete()
if self.mowerSound ~= nil then
delete(self.mowerSound);
end;
end;
function KuhnGMD4010:mouseEvent(posX, posY, isDown, isUp, button)
end;
function KuhnGMD4010:keyEvent(unicode, sym, modifier, isDown)
end;
function KuhnGMD4010:update(dt)
if self.runOnlyOnce then
setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(0), Utils.degToRad(0));
self.runOnlyOnce = false;
end;
if self.mowerIsAttached then
for i=1, table.getn(self.attacherVehicle.attachedImplements) do
if self.attacherVehicle.attachedImplements[i].object == self then
local index = self.attacherVehicle.attachedImplements[i].jointDescIndex;
self.attacherVehicleJoint = self.attacherVehicle.attacherJoints[index];
break;
end;
end;
self.mowerIsAttached = false;
end;
if self:getIsActive() then
self.wasToFast = false;
self.isExpanded = false;
self.isLowered = false;
local x, y, z = getRotation(self.arm.node);
if y > Utils.degToRad(85) then
self.isExpanded = true;
end;
if self.arm.currentRotLimit[1] > 1 then
self.isLowered = true;
end;
end;
if self:getIsActiveForInput(true) then
if self.isExpanded then
if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA) then
self.isTurnedOn = not self.isTurnedOn;
end;
if InputBinding.hasEvent(InputBinding.LOWER_IMPLEMENT) then
self.arm.isDown = not self.arm.isDown;
end;
end;
if InputBinding.hasEvent(InputBinding.IMPLEMENT_EXTRA2) and not self.isLowered and not self.isTurnedOn then
self.arm.isExpanded = not self.arm.isExpanded;
end;
end;
if self:getIsActive() then
if self.attacherVehicleJoint ~= nil and self.isExpanded then
self.attacherVehicleJoint.moveDown = false;
end;
for k,v in pairs(self.grassParticleSystems) do
if self.time > v.disableTime then
Utils.setEmittingState(v.ps, false);
end;
end;
if self.isTurnedOn then
local toFast = self:doCheckSpeedLimit() and self.lastSpeed*3600 > 31;
if not toFast and self.arm.currentRotLimit[1] > 15 then
local x,y,z = getWorldTranslation(self.groundReferenceNode);
local foldAnimTime = self.foldAnimTime;
local area = 0;
local areaWheat = 0;
local areaBarley = 0;
for k, cuttingArea in pairs(self.cuttingAreas) do
local x,y,z = getWorldTranslation(cuttingArea.start);
local x1,y1,z1 = getWorldTranslation(cuttingArea.width);
local x2,y2,z2 = getWorldTranslation(cuttingArea.height);
if k == 1 then
area = Utils.updateMeadowArea(x, z, x1, z1, x2, z2, false);
areaWheat = Utils.cutFruitArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, true, true);
areaBarley = Utils.cutFruitArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, true, true);
if self.attacherVehicle.movingDirection ~= -1 then
local area = Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0);
area = area + Utils.updateFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0);
else
if areaWheat > 0 then
local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2);
local value = (areaWheat+old) / total;
value = math.floor(value+0.001);
if value >= 1 then
value = math.min(value, g_currentMission.maxWindrowValue);
areaWheat = math.min(math.max(areaWheat+old - value*total, 0), 2*g_currentMission.maxWindrowValue);
areaWheat = value;
local areaWheat = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, true, true);
areaWheat = areaWheat + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, value, true);
end;
end;
if areaBarley > 0 then
local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2);
local value = (areaBarley+old) / total;
value = math.floor(value+0.001);
if value >= 1 then
value = math.min(value, g_currentMission.maxWindrowValue);
areaBarley = math.min(math.max(areaBarley+old - value*total, 0), 2*g_currentMission.maxWindrowValue);
areaBarley = value;
local areaBarley = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, true, true);
areaBarley = areaBarley + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, value, true);
end;
end;
end;
if g_currentMission.environment.lastRainScale <= 0.1 and g_currentMission.environment.timeSinceLastRain > 30 then
if area > 0 or areaWheat > 0 or areaBarley > 0 then
if cuttingArea.particleSystemIndex ~= nil then
ps = self.particleSystems[cuttingArea.particleSystemIndex+1];
if ps ~= nil then
ps.disableTime = self.time + 20;
Utils.setEmittingState(ps.ps, true);
end;
end;
end;
end;
else
if self.attacherVehicle.movingDirection ~= -1 then
local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2);
local value = (area+old) / total;
value = math.floor(value+0.001);
if value >= 1 then
value = math.min(value, g_currentMission.maxWindrowValue);
area = math.min(math.max(area+old - value*total, 0), 2*g_currentMission.maxWindrowValue);
area = value;
local area = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, 0);
area = area + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_GRASS, x, z, x1, z1, x2, z2, value, true, false);
end;
if areaWheat > 0 then
local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2);
local value = (areaWheat+old) / total;
value = math.floor(value+0.001);
if value >= 1 then
value = math.min(value, g_currentMission.maxWindrowValue);
areaWheat = math.min(math.max(areaWheat+old - value*total, 0), 2*g_currentMission.maxWindrowValue);
areaWheat = value;
local areaWheat = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, true, true);
areaWheat = areaWheat + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_WHEAT, x, z, x1, z1, x2, z2, value, true);
end;
end;
if areaBarley > 0 then
local old, total = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2);
local value = (areaBarley+old) / total;
value = math.floor(value+0.001);
if value >= 1 then
value = math.min(value, g_currentMission.maxWindrowValue);
areaBarley = math.min(math.max(areaBarley+old - value*total, 0), 2*g_currentMission.maxWindrowValue);
areaBarley = value;
local areaBarley = Utils.getFruitCutLongArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, true, true);
areaBarley = areaBarley + Utils.updateFruitWindrowArea(FruitUtil.FRUITTYPE_BARLEY, x, z, x1, z1, x2, z2, value, true);
end;
end;
end;
end;
end;
end;
if not self.mowerSoundEnabled and self:getIsActiveForSound() then
setSamplePitch(self.mowerSound, self.mowerSoundPitchOffset);
playSample(self.mowerSound, 0, self.mowerSoundVolume, 0);
self.mowerSoundEnabled = true;
end;
self.wasToFast = toFast;
else
if self.mowerSoundEnabled then
stopSample(self.mowerSound);
self.mowerSoundEnabled = false;
end;
end;
for i=1, table.getn(self.hydraulics) do
local ax, ay, az = getWorldTranslation(self.hydraulics[i].node);
local bx, by, bz = getWorldTranslation(self.hydraulics[i].fenderFixPoint);
local x, y, z = worldDirectionToLocal(getParent(self.hydraulics[i].node), bx-ax, by-ay, bz-az);
setDirection(self.hydraulics[i].node, x, y, z, 0, 1, 0);
if self.hydraulics[i].punch ~= nil then
local distance = Utils.vector3Length(ax-bx, ay-by, az-bz);
setTranslation(self.hydraulics[i].punch, 0, 0, distance-self.hydraulics[i].punchDistance);
end;
end;
local x, y, z = getRotation(self.arm.node);
local rot = {x,y,z};
self.arm.maxRot[1] = x;
self.arm.minRot[1] = x;
local newRot = Utils.getMovedLimitedValues(rot, self.arm.maxRot, self.arm.minRot, 3, self.arm.rotTime, dt, not self.arm.isExpanded);
setRotation(self.arm.node, unpack(newRot));
--if math.abs(newRot[2] - y) > 0.001 then
setJointFrame(self.componentJoints[1].jointIndex, 0, self.componentJoints[1].jointNode);
if not self.isExpanded then
setJointFrame(self.componentJoints[2].jointIndex, 0, self.componentJoints[2].jointNode);
setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(0), Utils.degToRad(0));
else
setJointRotationLimit(self.componentJoints[2].jointIndex, 2, true, Utils.degToRad(-19), Utils.degToRad(19));
end;
--end;
x, y, z = getRotation(self.arm.node);
rot = {x,y,z};
local newRotLimit = {0,0,0};
newRotLimit = Utils.getMovedLimitedValues(self.arm.currentRotLimit, {30}, {0}, 1, self.arm.liftTime * 2, dt, not self.arm.isDown);
if math.abs(newRotLimit[1] - self.arm.currentRotLimit[1]) > 0.001 then
setJointRotationLimit(self.componentJoints[1].jointIndex, 0, true, Utils.degToRad(-newRotLimit[1]), Utils.degToRad(newRotLimit[1]));
end;
self.arm.currentRotLimit = newRotLimit;
end;
end;
function KuhnGMD4010:draw()
if self.isActive then
if self.isExpanded then
if self.isTurnedOn then
g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_off_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
else
g_currentMission:addHelpButtonText(string.format(g_i18n:getText("turn_on_OBJECT"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA);
end;
if self.wasToFast then
g_currentMission:addWarning(g_i18n:getText("Dont_drive_to_fast") .. "\n" .. string.format(g_i18n:getText("Cruise_control_levelN"), "2", InputBinding.getButtonKeyName(InputBinding.SPEED_LEVEL2)), 0.07+0.022, 0.019+0.029);
end;
end;
if not self.isLowered and not self.isTurnedOn then
if self.arm.isExpanded then
g_currentMission:addHelpButtonText(string.format(g_i18n:getText("arm_fold"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
else
g_currentMission:addHelpButtonText(string.format(g_i18n:getText("arm_expand"), self.typeDesc), InputBinding.IMPLEMENT_EXTRA2);
end;
end;
end;
end;
function KuhnGMD4010:onAttach(attacherVehicle)
setRotation(self.supportArm.node, unpack(self.supportArm.maxRot));
setRotation(self.supportArm.node2, unpack(self.supportArm.maxRot2));
self.mowerIsAttached = true;
end;
function KuhnGMD4010:onDetach()
if self.deactivateOnDetach then
KuhnGMD4010.onDeactivate(self);
else
KuhnGMD4010.onDeactivateSounds(self)
end;
setRotation(self.supportArm.node, unpack(self.supportArm.minRot));
setRotation(self.supportArm.node2, unpack(self.supportArm.minRot2));
self.attacherVehicleJoint = nil;
end;
function KuhnGMD4010:onLeave()
if self.deactivateOnLeave then
KuhnGMD4010.onDeactivate(self);
else
KuhnGMD4010.onDeactivateSounds(self)
end;
end;
function KuhnGMD4010:onDeactivate()
KuhnGMD4010.onDeactivateSounds(self)
for k,v in pairs(self.grassParticleSystems) do
Utils.setEmittingState(v.ps, false);
end;
self.isTurnedOn = false;
end;
function KuhnGMD4010:onDeactivateSounds()
if self.mowerSoundEnabled then
stopSample(self.mowerSound);
self.mowerSoundEnabled = false;
end;
end;