Vehicles/VehicleScripts/AnimatedParts.lua

AnimatedParts allows to add doors or other animated parts to a vehicle. The player can then click onto these parts to open or close them (one animation per part allowed).

  25  AnimatedParts                       = AnimatedParts or {};

AnimatedParts:load(dataTable)

Initializes this vehicle script and fetches some data from the vehicle's configuration.

  29  function AnimatedParts:load(dataTable)
  30      -- currently only supports doors
  31      self.setAnimatedPartState       = VehicleManager:newFunction("setAnimatedPartState");
  32      self.getMayOpenDoors            = AnimatedParts.getMayOpenDoors;
  33  
  34      self.animatedParts              = {};
  35  
  36      if dataTable.animatedParts ~= nil then
  37          for k, v in pairs(dataTable.animatedParts) do
  38              local id                = getChild(self.id, v.index or "");
  39  
  40              if id ~= 0 then
  41                  local ap            = {};
  42                  local key           = #self.animatedParts + 1;
  43                  ap.id               = id;
  44                  ap.colId            = v.collision == nil and id or getChild(self.id, v.collision or "");
  45                  ap.animationLength  = Animation.getLength(ap.id);
  46  
  47                  ap.textOff          = l10n.getDollar(v.textOff  or "textOff");
  48                  ap.textOn           = l10n.getDollar(v.textOn   or "textOn");
  49                  ap.state            = v.defaultState or false;
  50                  ap.targetPosition   = ap.state and ap.animationLength or 0;
  51                  ap.position         = ap.targetPosition;
  52                  ap.onEnterState     = v.onEnterState;
  53                  ap.onLeaveState     = v.onLeaveState;
  54  
  55                  ap.isExteriorDoor   = v.isExteriorDoor or false;
  56  
  57                  Animation.sampleTime(ap.id, ap.position);
  58  
  59                  ControlElement.new(ap.colId);
  60                  ControlElement.setCallback(ap.colId, 1, function() self:setAnimatedPartState(key, not ap.state); end);
  61                  ControlElement.setName(ap.colId, ap.state and ap.textOff or ap.textOn);
  62  
  63                  -- exterior doors will always be closed when the vehicle starts moving
  64                  if ap.isExteriorDoor then
  65                      ControlElement.setActiveCallback(ap.colId, self, "getMayOpenDoors");
  66                  end;
  67  
  68                  table.insert(self.animatedParts, ap);
  69              end;
  70          end;
  71      end;
  72  end;

AnimatedParts:destroy()

Destroys all control elements.

  75  function AnimatedParts:destroy()
  76      for k, ap in pairs(self.animatedParts) do
  77          ControlElement.destroy(ap.colId);
  78      end;
  79  end;

AnimatedParts:saveToTable(tbl)

Writes the current states of all animated parts to the savegame.

  83  function AnimatedParts:saveToTable(tbl)
  84      if tbl == nil then return end;
  85  
  86      tbl.animatedParts               = {};
  87      for k, ap in pairs(self.animatedParts) do
  88          tbl.animatedParts[k]        = {
  89              state                   = ap.state or false,
  90              position                = ap.position,
  91          };
  92      end;
  93  end;

AnimatedParts:loadFromTable(tbl)

Reads the current states of our animated parts from the savegame.

  97  function AnimatedParts:loadFromTable(tbl)
  98      if tbl == nil then return end;
  99      if tbl.animatedParts == nil then return end;
 100  
 101      for k, ap in pairs(self.animatedParts) do
 102          local data                  = tbl.animatedParts[k];
 103  
 104          if data ~= nil then
 105              ap.state                = getNoNil(data.state,      ap.state);
 106              ap.position             = getNoNil(data.position,   ap.position);
 107  
 108              self:setAnimatedPartState(k, ap.state);
 109  
 110              -- force sample time
 111              Animation.sampleTime(ap.id, ap.position);
 112          end;
 113      end;
 114  end;

AnimatedParts:setAnimatedPartState(key, value, noEvent)

Call this function to move the animated part to the specified position. key is the animated part's index, value (bool) is the target position (true or false). For doors, true usually represents open. noEvent (bool) specifies whether the multiplayer event shall be suppressed.

The corresponding network event is EventSetAnimatedPart.

 120  function AnimatedParts:setAnimatedPartState(key, value, noEvent)
 121      local ap                        = self.animatedParts[key];
 122  
 123      if ap == nil then return end;
 124  
 125      ap.state                        = value;
 126      ap.targetPosition               = ap.state and ap.animationLength or 0;
 127      ControlElement.setName(ap.colId, ap.state and ap.textOff or ap.textOn);
 128  
 129      if not noEvent then
 130          EventSetAnimatedPart:send(self, key, value);
 131      end;
 132  end;

AnimatedParts:onEnter(player)

For some vehicles, it makes sense to open or close doors (depending on the animated part's onEnterState) when the player enters the vehicle.

 136  function AnimatedParts:onEnter(player)
 137      if not isLocalPlayer or not GameplaySettings.autoCloseDoors then
 138          return;
 139      end;
 140  
 141      for key, ap in pairs(self.animatedParts) do
 142          if ap.onEnterState ~= nil then
 143              self:setAnimatedPartState(key, ap.onEnterState);
 144          end;
 145      end;
 146  end;

AnimatedParts:onLeave(player, isLocalPlayer)

For some vehicles, it can also make sense to open or close doors (depending on the animated part's onLeaveState) when the player leaves the vehicle.

 150  function AnimatedParts:onLeave(player, isLocalPlayer)
 151      if not isLocalPlayer or not GameplaySettings.autoCloseDoors then
 152          return;
 153      end;
 154      
 155      for key, ap in pairs(self.animatedParts) do
 156          if ap.onLeaveState ~= nil then
 157              self:setAnimatedPartState(key, ap.onLeaveState);
 158          end;
 159      end;
 160  end;

AnimatedParts:update(dt)

Updates the door positions every frame, and if necessary, resamples the animation.

 164  function AnimatedParts:update(dt)
 165      local closeDoors                = self:getIsLocalPlayerEntered() and not self:getMayOpenDoors();
 166      for key, ap in pairs(self.animatedParts) do
 167          if ap.isExteriorDoor and closeDoors then
 168              self:setAnimatedPartState(key, false);
 169          end;
 170          if ap.position ~= ap.targetPosition then
 171              ap.position             = Utils.moveTowards(ap.position, ap.targetPosition, dt);
 172              Animation.sampleTime(ap.id, ap.position);
 173          end;
 174      end;
 175  end;

AnimatedParts:getMayOpenDoors()

Returns true whenever the vehicle is hardly moving (which means that doors etc may be opened).

 179  function AnimatedParts:getMayOpenDoors()
 180      return self.currentSpeed == nil or math.abs(self.currentSpeed) < 3 or not self:getIsActive();
 181  end;
 182  

AnimatedParts:writeResync()

Resynchronizes all variables when a new player joins the game. The data sent by writeResync will be received by readResync.

 186  function AnimatedParts:writeResync()
 187      for k, v in ipairs(self.animatedParts) do
 188          streamWriteBool(v.targetPosition > 0.5 * v.animationLength);
 189      end;
 190  end;
 191  

AnimatedParts:readResync()

Resynchronizes all variables when a new player joins the game. The data sent by writeResync will be received by readResync.

 195  function AnimatedParts:readResync()
 196      for k, v in pairs(self.animatedParts) do
 197          local state                 = streamReadBool();
 198          self:setAnimatedPartState(k, state, true);
 199      end;
 200  end

All contents of this page may be used for modding use for Winter Resort Simulator - Season 2 only. Any use exceeding this regulation is not permitted.

Copyright (C) HR Innoways, 2021. All Rights Reserved.