  --
  -- Foldable
 -- Class for vehicles which have folding parts
  --
  -- @author  Stefan Geiger
  -- @date  12/01/09
   
  --adaptation to ballewagen:ViC77 
   9  
  10  source("dataS/scripts/vehicles/specializations/FoldableSetFoldDirectionEvent.lua");
  11  Foldable = {};
  12  
  13  function Foldable.prerequisitesPresent(specializations)
  14      return true;
  15  end;
  16  
  17  function Foldable:load(xmlFile)
  18  
  19      self.setFoldDirection = SpecializationUtil.callSpecializationsFunction("setFoldDirection");
  20  
  21      self.getIsAreaActive = Utils.overwrittenFunction(self.getIsAreaActive, Foldable.getIsAreaActive);
  22  
  23      self.posDirectionText = Utils.getNoNil(getXMLString(xmlFile, "vehicle.foldingParts#posDirectionText"), "fold_OBJECT");
  24      self.negDirectionText = Utils.getNoNil(getXMLString(xmlFile, "vehicle.foldingParts#negDirectionText"), "unfold_OBJECT");
  25      local startMoveDirection = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.foldingParts#startMoveDirection"), 0);
  26      self.startAnimTime = 0;
  27      if startMoveDirection > 0.1 then
  28          self.startAnimTime = 1;
  29      end;
  30  
  31      local foldInputButtonStr = getXMLString(xmlFile, "vehicle.foldingParts#foldInputButton");
  32      if foldInputButtonStr ~= nil then
  33          self.foldInputButton = InputBinding[foldInputButtonStr];
  34      end;
  35      self.foldInputButton = Utils.getNoNil(self.foldInputButton, InputBinding.IMPLEMENT_EXTRA2);
  36  
  37      self.foldAnimTime = 0;
  38      self.maxFoldAnimDuration = 0.0001;
  39  
  40      local numCuttingAreas = Utils.getNoNil(getXMLInt(xmlFile, "vehicle.cuttingAreas#count"), 0);
  41      for i=1, numCuttingAreas do
  42          local areanamei = string.format("vehicle.cuttingAreas.cuttingArea%d", i);
  43          self.cuttingAreas[i].foldMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMinLimit"), 0);
  44          self.cuttingAreas[i].foldMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, areanamei .. "#foldMaxLimit"), 1);
  45      end;
  46  
  47      self.foldingParts = {};
  48      local i=0;
  49      while true do
Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de


  
  50          local baseName = string.format("vehicle.foldingParts.foldingPart(%d)", i);
  51          if not hasXMLProperty(xmlFile, baseName) then
  52              break;
  53          end;
  54  
  55          local isValid = false;
  56          local entry = {};
  57          entry.speedScale = Utils.getNoNil(getXMLFloat(xmlFile, baseName.."#speedScale"), 1);
  58          local componentJointIndex = getXMLInt(xmlFile, baseName.. "#componentJointIndex");
  59          if componentJointIndex ~= nil then
  60              local componentJoint = self.componentJoints[componentJointIndex+1];
  61              if componentJoint ~= nil then
  62                  entry.componentJoint = componentJoint;
  63                  entry.anchorActor = Utils.getNoNil(getXMLInt(xmlFile,  baseName.."#anchorActor"), 0);
  64  
  65                  entry.animCharSet = 0;
  66  
  67                  local rootNode = Utils.indexToObject(self.components, getXMLString(xmlFile, baseName.."#rootNode"));
  68                  if rootNode ~= nil then
  69                      local animCharSet = getAnimCharacterSet(rootNode);
  70                      if animCharSet ~= 0 then
  71                          local clip = getAnimClipIndex(animCharSet, getXMLString(xmlFile, baseName.."#animationClip"));
  72                          if clip >= 0 then
  73                              isValid = true;
  74  
  75                              entry.animCharSet = animCharSet;
  76                              assignAnimTrackClip(entry.animCharSet, 0, clip);
  77                              setAnimTrackLoopState(entry.animCharSet, 0, false);
  78                              entry.animDuration = getAnimClipDuration(entry.animCharSet, clip);
  79  
  80                          end;
  81                      end;
  82                  end;
  83                  -- try AnimatedVehicle specialization support
  84                  if not isValid and self.playAnimation ~= nil and self.animations ~= nil then
  85                      local animationName = getXMLString(xmlFile, baseName.."#animationName");
  86                      if animationName ~= nil then
  87                          if self.animations[animationName] ~= nil then
  88                              isValid = true;
  89                              entry.animDuration = self:getAnimationDuration(animationName);
  90                              entry.animationName = animationName;
  91                          end;
  92                      end;
  93                  end;
  94  
  95                  if isValid then
  96                      self.maxFoldAnimDuration = math.max(self.maxFoldAnimDuration, entry.animDuration);
  97                      local node = self.components[componentJoint.componentIndices[((entry.anchorActor+1)%2)+1] ].node;
  98                      entry.x,entry.y,entry.z = worldToLocal(componentJoint.jointNode, getWorldTranslation(node));
  99                      entry.upX,entry.upY,entry.upZ = worldDirectionToLocal(componentJoint.jointNode, localDirectionToWorld(node, 0, 1, 0));
Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de


  
 100                      entry.dirX,entry.dirY,entry.dirZ = worldDirectionToLocal(componentJoint.jointNode, localDirectionToWorld(node, 0, 0, 1));
 101  
 102                      table.insert(self.foldingParts, entry);
 103                  end;
 104  
 105              end;
 106          end;
 107          i = i+1;
 108      end;
 109  
 110      self.foldMoveDirection = startMoveDirection;
 111  
 112      Foldable.setAnimTime(self, self.startAnimTime)
 113  end;
 114  
 115  function Foldable:delete()
 116  end;
 117  
 118  function Foldable:readStream(streamId, connection)
 119      local direction = streamReadUIntN(streamId, 2)-1;
 120      local animTime = streamReadFloat32(streamId);
 121      Foldable.setAnimTime(self, animTime);
 122      self:setFoldDirection(direction, true);
 123  end;
 124  
 125  function Foldable:writeStream(streamId, connection)
 126      local direction = Utils.sign(self.foldMoveDirection)+1;
 127      streamWriteUIntN(streamId, direction, 2);
 128      streamWriteFloat32(streamId, self.foldAnimTime);
 129  end;
 130  
 131  function Foldable:readUpdateStream(streamId, timestamp, connection)
 132  end;
 133  
 134  function Foldable:writeUpdateStream(streamId, connection, dirtyMask)
 135  end;
 136  
 137  function Foldable:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
 138  
 139      Foldable.setAnimTime(self, self.startAnimTime)
 140      return BaseMission.VEHICLE_LOAD_OK;
 141  end;
 142  
 143  function Foldable:setRelativePosition(positionX, offsetY, positionZ, yRot)
 144      Foldable.setAnimTime(self, self.startAnimTime);
 145  end;
 146  
 147  function Foldable:mouseEvent(posX, posY, isDown, isUp, button)
 148  end;
 149  
Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de


  
 150  function Foldable:keyEvent(unicode, sym, modifier, isDown)
 151  end;
 152  
 153  function Foldable:update(dt)
 154  
 155      if self:getIsActive() then
 156  
 157          if math.abs(self.foldMoveDirection) > 0.1 then
 158              local isInvalid = false;
 159              local foldAnimTime = 0;
 160              if self.foldMoveDirection < -0.1 then
 161                  foldAnimTime = 1;
 162              end;
 163              for k,foldingPart in pairs(self.foldingParts) do
 164                  local charSet = foldingPart.animCharSet;
 165                  if self.foldMoveDirection > 0.1 then
 166                      local animTime = 0;
 167                      if charSet ~= 0 then
 168                          animTime = getAnimTrackTime(charSet, 0);
 169                      else
 170                          animTime = self:getRealAnimationTime(foldingPart.animationName);
 171                      end;
 172                      if animTime < foldingPart.animDuration then
 173                          isInvalid = true;
 174                      end;
 175                      foldAnimTime = math.max(foldAnimTime, animTime / self.maxFoldAnimDuration);
 176                  elseif self.foldMoveDirection < -0.1 then
 177                      local animTime = 0;
 178                      if charSet ~= 0 then
 179                          animTime = getAnimTrackTime(charSet, 0);
 180                      else
 181                          animTime = self:getRealAnimationTime(foldingPart.animationName);
 182                      end;
 183                      if animTime > 0 then
 184                          isInvalid = true;
 185                      end;
 186                      foldAnimTime = math.min(foldAnimTime, animTime / self.maxFoldAnimDuration);
 187                  end;
 188              end;
 189              self.foldAnimTime = Utils.clamp(foldAnimTime, 0, 1);
 190  
 191              if isInvalid and self.isServer then
 192                  for k,foldingPart in pairs(self.foldingParts) do
 193                      setJointFrame(foldingPart.componentJoint.jointIndex, foldingPart.anchorActor, foldingPart.componentJoint.jointNode);
 194                  end;
 195              end;
 196          end;
 197      end;
 198  
 199      if self.isClient and self:getIsActiveForInput() then
Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de


  
 200          if InputBinding.hasEvent(self.foldInputButton) then
 201              if self.foldMoveDirection > 0.1 or (self.foldMoveDirection == 0 and self.foldAnimTime > 0.5) then
 202                  self:setFoldDirection(-1)
 203              else
 204                  self:setFoldDirection(1)
 205              end;
 206          end;
 207      end;
 208  end;
 209  
 210  function Foldable:updateTick(dt)
 211  end;
 212  
 213  function Foldable:draw()
 214      if table.getn(self.foldingParts) > 0 then
 215          if self.foldMoveDirection > 0.1 or (self.foldMoveDirection == 0 and self.foldAnimTime > 0.5) then
 216              g_currentMission:addHelpButtonText(string.format(g_i18n:getText(self.negDirectionText), self.typeDesc), self.foldInputButton);
 217          else
 218              g_currentMission:addHelpButtonText(string.format(g_i18n:getText(self.posDirectionText), self.typeDesc), self.foldInputButton);
 219          end;
 220      end;
 221  end;
 222  
 223  function Foldable:onDetach()
 224      if self.deactivateOnDetach then
 225          Foldable.onDeactivate(self);
 226      end;
 227  end;
 228  
 229  function Foldable:onLeave()
 230      if self.deactivateOnLeave then
 231          Foldable.onDeactivate(self);
 232      end;
 233  end;
 234  
 235  function Foldable:onDeactivate()
 236      self:setFoldDirection(0, true);
 237  end;
 238  
 239  function Foldable:setFoldDirection(direction, noEventSend)
 240      if noEventSend == nil or noEventSend == false then
 241          if g_server ~= nil then
 242              g_server:broadcastEvent(FoldableSetFoldDirectionEvent:new(self, direction), nil, nil, self);
 243          else
 244              g_client:getServerConnection():sendEvent(FoldableSetFoldDirectionEvent:new(self, direction));
 245          end;
 246      end
 247      self.foldMoveDirection = direction;
 248  
 249      for k,foldingPart in pairs(self.foldingParts) do
Copyright (C) GIANTS Software GmbH, Confidential, All Rights Reserved.
This document is to be published solely by ls-mods.de


  
 250          local speedScale = nil;
 251          if self.foldMoveDirection > 0.1 then
 252              speedScale = foldingPart.speedScale;
 253          elseif self.foldMoveDirection < -0.1 then
 254              speedScale = -foldingPart.speedScale;
 255          end;
 256  
 257          local charSet = foldingPart.animCharSet;
 258          if charSet ~= 0 then
 259              if speedScale ~= nil then
 260                  if speedScale > 0 then
 261                      if getAnimTrackTime(charSet, 0) < 0.0 then
 262                          setAnimTrackTime(charSet, 0, 0.0);
 263                      end;
 264                  else
 265                      if getAnimTrackTime(charSet, 0) > foldingPart.animDuration then
 266                          setAnimTrackTime(charSet, 0, foldingPart.animDuration);
 267                      end;
 268                  end;
 269                  setAnimTrackSpeedScale(charSet, 0, speedScale);
 270                  enableAnimTrack(charSet, 0);
 271              else
 272                  disableAnimTrack(charSet, 0);
 273              end;
 274          else
 275              if speedScale ~= nil then
 276                  local animTime = (self.foldAnimTime*self.maxFoldAnimDuration)/self:getAnimationDuration(foldingPart.animationName);
 277                  self:playAnimation(foldingPart.animationName, speedScale, animTime, true);
 278              else
 279                  self:stopAnimation(foldingPart.animationName, true);
 280              end;
 281          end;
 282      end;
 283  end;
 284  
 285  function Foldable:getIsAreaActive(superFunc, area)
 286      if self.foldAnimTime > area.foldMaxLimit or self.foldAnimTime < area.foldMinLimit then
 287          return false;
 288      end;
 289      if superFunc ~= nil then
 290          return superFunc(self, area);
 291      end;
 292      return true;
   end;
   
   function Foldable.setAnimTime(self, animTime)
       self.foldAnimTime = animTime;
      for k,foldingPart in pairs(self.foldingParts) do
         if foldingPart.animCharSet ~= 0 then
              enableAnimTrack(foldingPart.animCharSet, 0);


              setAnimTrackTime(foldingPart.animCharSet, 0, animTime*foldingPart.animDuration, true);
              disableAnimTrack(foldingPart.animCharSet, 0);
           else
              local currentTime = self:getAnimationTime(foldingPart.animationName);
              local speed = 1;
               if currentTime > self.foldAnimTime then
                  speed = -1;
               end;
               self:playAnimation(foldingPart.animationName, speed, currentTime, true);
             self:setAnimationStopTime(foldingPart.animationName, self.foldAnimTime);
             AnimatedVehicle.updateAnimations(self, 99999999);
           end;
      end;
   
       if self.isServer then
           for k,foldingPart in pairs(self.foldingParts) do
              local componentJoint = foldingPart.componentJoint;
   
              local node = self.components[componentJoint.componentIndices[((foldingPart.anchorActor+1)%2)+1] ].node;
              local x,y,z = localToWorld(componentJoint.jointNode, foldingPart.x, foldingPart.y, foldingPart.z);
              local upX,upY,upZ = localDirectionToWorld(componentJoint.jointNode, foldingPart.upX,foldingPart.upY,foldingPart.upZ);
              local dirX,dirY,dirZ = localDirectionToWorld(componentJoint.jointNode, foldingPart.dirX,foldingPart.dirY,foldingPart.dirZ);
              Utils.setWorldTranslation(node, x,y,z);
              Utils.setWorldDirection(node, dirX,dirY,dirZ, upX,upY,upZ);
 
             setJointFrame(componentJoint.jointIndex, foldingPart.anchorActor, componentJoint.jointNode);
         end;
      end;
   end;