Vehicles/VehicleScripts/FuelTank.lua

FuelTank adds some features to vehicles regarding fuel. Without using this script, your vehicle will not use any fuel. It also handles refueling.

FuelTank is therefore also responsible for the sounds that are played while refueling. You can specify custom sounds for your vehicle using fuelTankRefillLoop, fuelTankRefillStart and fuelTankRefillStop within your vehicle's data table. The configuration will look similar to the usual configuration of vehicle sounds. In case you have no sounds specified, the game will fall back to the default sounds that are initialized below.

  29  FuelTank                            = FuelTank or {};
  30  
  31  FuelTank.loopSound                  = { prefab  = "$sounds/fuelStation/loop",   };
  32  FuelTank.startSound                 = { prefab  = "$sounds/fuelStation/start",  };
  33  FuelTank.stopSound                  = { prefab  = "$sounds/fuelStation/stop",   };

FuelTank:load(dataTable)

This will initialize the vehicle script. First, we set up some custom functions for our vehicle. Afterwards, we initialize some variables and finally we set up the actual sounds using the loadSingleSound function provided by the Vehicle class.

  38  function FuelTank:load(dataTable)
  39      self.addFuelUsage               = VehicleManager:newFunction("addFuelUsage");
  40      self.refillFuel                 = VehicleManager:newFunction("refillFuel");
  41      self.getHasRunOutOfFuel         = FuelTank.getHasRunOutOfFuel;
  42      self.getCanRefillFuel           = FuelTank.getCanRefillFuel;
  43      self.setIsFuelStationInRange    = FuelTank.setIsFuelStationInRange;
  44  
  45      self.fuelTankCapacity           = math.max(dataTable.fuelTankCapacity   or 50, 1);
  46      self.fuelUsagePerSecond         = (dataTable.fuelUsagePerHour           or 5) / 3600;
  47      self.fuelUsagePerMetre          = (dataTable.fuelUsagePer100Km          or 15.0) * 0.00001;
  48      self.refuelSpeed                = math.abs(dataTable.refuelSpeed        or 20);
  49  
  50      self.fuelStationInRange         = false;
  51  
  52      self.fuelTankCurrentAmount      = self.fuelTankCapacity;
  53  
  54      self.isRefuelling               = false;
  55  
  56      -- load sounds
  57      self.fuelTankRefillLoop         = self:loadSingleSound(dataTable.fuelTankRefillLoop     or FuelTank.loopSound);
  58      self.fuelTankRefillStart        = self:loadSingleSound(dataTable.fuelTankRefillStart    or FuelTank.startSound);
  59      self.fuelTankRefillStop         = self:loadSingleSound(dataTable.fuelTankRefillStop     or FuelTank.stopSound);
  60  
  61  end;
  62  --[[
  63  Loads the current fuel tank amount from the savegame.
 
  64  function FuelTank:loadFromTable(tbl)
  65      if tbl == nil then return end;
  66  
  67      self.fuelTankCurrentAmount      = getNoNil(tbl.fuelTankCurrentAmount, self.fuelTankCurrentAmount);
  68  end;

FuelTank:saveToTable(tbl)

Saves the current fuel tank amount to the savegame.

  73  function FuelTank:saveToTable(tbl)
  74      if tbl == nil then return end;
  75  
  76      tbl.fuelTankCurrentAmount       = self.fuelTankCurrentAmount;
  77  end;

FuelTank:addFuelUsage(dt, deltaWay)

Adds some amount of fuel usage (depending on the vehicle's configuration).

Fuel is consumed on a time basis. dt (float) is the time in seconds. Additionally, for each movement, some more fuel is consumed. deltaWay (float) specifies the way in metres.

We are aware that this method of determining fuel usage is not very accurate. However, it is sufficient for our use case, and saves performance compared to more verbose implementations.

  86  function FuelTank:addFuelUsage(dt, deltaWay)
  87      self.fuelTankCurrentAmount      = math.max(self.fuelTankCurrentAmount - self.fuelUsagePerSecond * dt - math.abs(self.fuelUsagePerMetre * deltaWay), 0);
  88  end;

FuelTank:setIsFuelStationInRange(inRange)

This is called by FuelStationTrigger every time the vehicle enters or leaves a fuel station trigger.

  92  function FuelTank:setIsFuelStationInRange(inRange)
  93      self.fuelStationInRange         = inRange;
  94  end;

FuelTank:getHasRunOutOfFuel()

Returns whether the vehicle has run out of fuel.

  98  function FuelTank:getHasRunOutOfFuel()
  99      return self.fuelTankCurrentAmount <= 0;
 100  end;

FuelTank:onReset()

Sometimes, vehicles may be resetted due to lack of fuel (e.g. if a player can't reach a fuel station in time). Therefore, we need to refuel the vehicle if its fuel tank is low.

Note that the price is considerably higher than for usual refueling.

 106  function FuelTank:onReset()
 107      if self.fuelTankCurrentAmount < 0.3 * self.fuelTankCapacity then
 108          -- we need to refill
 109          local delta                 = 0.3 * self.fuelTankCapacity - self.fuelTankCurrentAmount;
 110          local price                 = delta * g_scenario.ecoSystem.fuelPricePerLiterReset;
 111  
 112          -- always do this, even if the player couldn't pay this (otherwise his vehicle would be lost)
 113          g_scenario.accounting:addExpense("vehicles", -price);
 114  
 115          self.fuelTankCurrentAmount  = 0.3 * self.fuelTankCapacity;
 116      end;
 117  end;

FuelTank:update(dt)

We need to update fuel usage and refueling every frame, as well as sounds and GUI displays.

 121  function FuelTank:update(dt)
 122      if not self.isActive then return end;
 123      
 124      self.getHasRunOutOfFuel         = FuelTank.getHasRunOutOfFuel;
 125      local isRefuelling              = false;
 126  
 127      -- allow refilling
 128      if self:getIsInputActive() and self.fuelStationInRange then
 129          if self.fuelTankCurrentAmount <= self.fuelTankCapacity - 0.5 then
 130  
 131              g_GUI:addKeyHint(InputMapper.Vehicle_RefillFuel, l10n.get("Input_Vehicle_RefillFuel"));
 132  
 133              if g_scenario.tutorialAgent ~= nil then
 134                  g_scenario.tutorialAgent:callByScript("fuelStation");
 135              end;
 136  
 137              if InputMapper:getKey(InputMapper.Vehicle_RefillFuel) then
 138                  -- let's refuel
 139                  local delta         = math.min(self.refuelSpeed * dt, self.fuelTankCapacity - self.fuelTankCurrentAmount);
 140  
 141                  -- check if player can afford this
 142                  local price         = delta * g_scenario.ecoSystem.fuelPricePerLiter;
 143  
 144                  if g_scenario:canAffordExpense(price) then
 145                      -- refuel
 146                      self.fuelTankCurrentAmount  = math.min(self.fuelTankCurrentAmount + delta, self.fuelTankCapacity);
 147                      g_scenario.accounting:addExpense("vehicles", -price);
 148  
 149                      isRefuelling    = true;
 150                  end;
 151              end;
 152          end;
 153      end;
 154  
 155      if self.isRefuelling ~= isRefuelling then
 156          if isRefuelling then
 157              -- start playing sounds
 158              self:playSound(self.fuelTankRefillLoop);
 159              self:playSound(self.fuelTankRefillStart);
 160              self:stopSound(self.fuelTankRefillStop);
 161          else
 162              self:stopSound(self.fuelTankRefillStart);
 163              self:stopSound(self.fuelTankRefillLoop);
 164              self:playSound(self.fuelTankRefillStop);
 165          end;
 166          self.isRefuelling           = isRefuelling;
 167      end;
 168  
 169      if self:getIsGUIActive() then
 170          local fuelBar               = getChild(g_GUI.vehicleHUD,    "FuelBar/Filled");
 171          local fuelIcon              = getChild(g_GUI.vehicleHUD,    "FuelBarIcon");
 172          local fuelText              = getChild(g_GUI.vehicleHUD,    "FuelAmount");
 173  
 174          UI.setImageFillAmount(fuelBar,      0.25 * self.fuelTankCurrentAmount / self.fuelTankCapacity)
 175          UI.setLabelText(fuelText,           l10n.format("ui_hud_fuelAmount", self.fuelTankCurrentAmount));
 176  
 177          local relativeAmount        = self.fuelTankCurrentAmount / self.fuelTankCapacity;
 178  
 179          if relativeAmount < 0.2 then
 180              if g_scenario.tutorialAgent ~= nil then
 181                  g_scenario.tutorialAgent:callByScript("fuelAlmostEmpty");
 182              end;
 183          end;
 184  
 185          if (relativeAmount < 0.2 and relativeAmount >= 0.1) or (relativeAmount < 0.1 and (getTime()%1.5) < 0.75) then
 186              -- red
 187              UI.setImageColor(fuelIcon,  235,  20, 20);
 188              UI.setImageColor(fuelBar,   235,  20, 20);
 189              UI.setLabelColor(fuelText,  235,  20, 20);
 190          
 191          else
 192              -- orange
 193              UI.setImageColor(fuelIcon,  252, 182, 55);
 194              UI.setImageColor(fuelBar,   252, 182, 55);
 195              UI.setLabelColor(fuelText,  252, 182, 55);
 196          end;
 197      end;
 198  
 199  end;

FuelTank:onHUDActivate()

 202  function FuelTank:onHUDActivate()
 203      setActive(getChild(g_GUI.vehicleHUD,    "FuelBar"),         true);
 204      setActive(getChild(g_GUI.vehicleHUD,    "FuelBarIcon"),     true);
 205      setActive(getChild(g_GUI.vehicleHUD,    "FuelAmount"),      true);
 206  end;

FuelTank:onLeave()

 209  function FuelTank:onLeave()
 210      self:stopSound(self.fuelTankRefillStart);
 211      self:stopSound(self.fuelTankRefillLoop);
 212      self:stopSound(self.fuelTankRefillStop);
 213  end;

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

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