meta data for this page
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 FuelTank.consumptionCoeff = 1; 31 32 FuelTank.loopSound = { prefab = "$sounds/fuelStation/loop", }; 33 FuelTank.startSound = { prefab = "$sounds/fuelStation/start", }; 34 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.
39 function FuelTank:load(dataTable) 40 self.addFuelUsage = VehicleManager:newFunction("addFuelUsage"); 41 self.setIsRefuelling = VehicleManager:newFunction("setIsRefuelling"); 42 self.getHasRunOutOfFuel = FuelTank.getHasRunOutOfFuel; 43 self.getCanRefillFuel = FuelTank.getCanRefillFuel; 44 self.setIsFuelStationInRange = FuelTank.setIsFuelStationInRange; 45 46 self.fuelTankCapacity = math.max(dataTable.fuelTankCapacity or 50, 1); 47 self.fuelUsagePerSecond = (dataTable.fuelUsagePerHour or 5) / 3600; 48 self.fuelUsagePerMetre = (dataTable.fuelUsagePer100Km or 15.0) * 0.00001; 49 self.refuelSpeed = math.abs(dataTable.refuelSpeed or 20); 50 51 self.fuelStationInRange = false; 52 self.fuelStationInRangeById = {}; 53 54 self.fuelTankCurrentAmount = self.fuelTankCapacity; 55 self.lastFuelTankAmount = self.fuelTankCapacity; 56 self.refuelSoundActiveUntil = -1; 57 58 self.isRefuelling = false; 59 self.refuelSoundPlaying = false; 60 61 -- load sounds 62 self.fuelTankRefillLoop = self:loadSingleSound(dataTable.fuelTankRefillLoop or FuelTank.loopSound); 63 self.fuelTankRefillStart = self:loadSingleSound(dataTable.fuelTankRefillStart or FuelTank.startSound); 64 self.fuelTankRefillStop = self:loadSingleSound(dataTable.fuelTankRefillStop or FuelTank.stopSound); 65 66 end;
FuelTank:loadFromTable(tbl)
Loads the current fuel tank amount from the savegame.
70 function FuelTank:loadFromTable(tbl) 71 if tbl == nil then return end; 72 73 self.fuelTankCurrentAmount = getNoNil(tbl.fuelTankCurrentAmount, self.fuelTankCurrentAmount); 74 end;
FuelTank:saveToTable(tbl)
Saves the current fuel tank amount to the savegame.
78 function FuelTank:saveToTable(tbl) 79 if tbl == nil then return end; 80 81 tbl.fuelTankCurrentAmount = self.fuelTankCurrentAmount; 82 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.
Note that calling this function only has an effect if done on the server or in singleplayer. Clients cannot influence the fuel level of their vehicle.
93 function FuelTank:addFuelUsage(dt, deltaWay) 94 if g_isClient then 95 return; 96 end; 97 self.fuelTankCurrentAmount = math.max(self.fuelTankCurrentAmount - (self.fuelUsagePerSecond * dt + math.abs(self.fuelUsagePerMetre * deltaWay)) * FuelTank.consumptionCoeff, 0); 98 end;
FuelTank:setIsFuelStationInRange(fuelStationId, colliderId, inRange)
This is called by FuelStationTrigger every time the vehicle enters or leaves a fuel station trigger.
102 function FuelTank:setIsFuelStationInRange(fuelStationId, colliderId, inRange) 103 self.fuelStationInRangeById[colliderId] = self.fuelStationInRangeById[colliderId] or {}; 104 local stationsInRange = self.fuelStationInRangeById[colliderId]; 105 stationsInRange[fuelStationId] = ifelse(inRange, true, nil); 106 107 if count(stationsInRange) == 0 then 108 self.fuelStationInRangeById[colliderId] = nil; 109 end; 110 111 self.fuelStationInRange = count(self.fuelStationInRangeById) > 0; 112 end;
FuelTank:getHasRunOutOfFuel()
Returns whether the vehicle has run out of fuel.
116 function FuelTank:getHasRunOutOfFuel() 117 return self.fuelTankCurrentAmount <= 0; 118 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.
124 function FuelTank:onReset() 125 if self.fuelTankCurrentAmount < 0.3 * self.fuelTankCapacity then 126 -- we need to refill 127 local delta = 0.3 * self.fuelTankCapacity - self.fuelTankCurrentAmount; 128 local price = delta * g_scenario.ecoSystem.fuelPricePerLiterReset; 129 130 -- always do this, even if the player couldn't pay this (otherwise his vehicle would be lost) 131 g_scenario.accounting:addExpense("vehicles", -price); 132 133 self.fuelTankCurrentAmount = 0.3 * self.fuelTankCapacity; 134 end; 135 end;
FuelTank:setIsRefuelling(isRefuelling, noEvent)
Is called whenever the vehicle shall be refuelled.
138 function FuelTank:setIsRefuelling(isRefuelling, noEvent) 139 if self.isRefuelling == isRefuelling then 140 return; 141 end; 142 143 self.isRefuelling = isRefuelling; 144 145 if g_isClient and not noEvent then 146 EventRefuelVehicle:send(self, isRefuelling); 147 end; 148 end;
FuelTank:update(dt)
We need to update fuel usage and refueling every frame, as well as sounds and GUI displays.
152 function FuelTank:update(dt) 153 if not self.isActive and not self.refuelSoundPlaying then return end; 154 155 local isRefuelling = false; 156 157 -- client side code 158 if self:getIsInputActive() then 159 -- allow refuelling even if we are not close to a fuel station, for there might be client-side errors 160 -- and we always keep server authority 161 self:setIsRefuelling(InputMapper:getKey(InputMapper.Vehicle_RefillFuel)); 162 163 if self.fuelStationInRange and self.fuelTankCurrentAmount <= self.fuelTankCapacity - 0.5 then 164 165 g_GUI:addKeyHint(InputMapper.Vehicle_RefillFuel, l10n.get("Input_Vehicle_RefillFuel")); 166 167 if g_scenario.tutorialAgent ~= nil then 168 g_scenario.tutorialAgent:callByScript("fuelStation"); 169 end; 170 end; 171 end; 172 173 if g_isClient then 174 isRefuelling = self.lastFuelTankAmount < self.fuelTankCurrentAmount; 175 self.lastFuelTankAmount = self.fuelTankCurrentAmount; 176 177 -- above detection will only trigger directly after the frame in which packets are received from server 178 -- hence wait 1sec for the falling edge 179 if isRefuelling then 180 -- activate sound for 1 second (if not already full) 181 if self.fuelTankCurrentAmount >= self.fuelTankCapacity - 0.25 then 182 self.refuelSoundActiveUntil = -1; 183 else 184 self.refuelSoundActiveUntil = getTime() + 1; 185 end; 186 else 187 -- keep active for some time 188 isRefuelling = self.refuelSoundActiveUntil > getTime(); 189 end; 190 191 -- check on non-clients (=> server or singleplayer) whether we need to refill 192 elseif self.isRefuelling then 193 194 if self.fuelTankCurrentAmount <= self.fuelTankCapacity - 0.5 and self:getIsActive() and self.fuelStationInRange then 195 -- let's refuel 196 local delta = math.min(self.refuelSpeed * dt, self.fuelTankCapacity - self.fuelTankCurrentAmount); 197 198 -- check if player can afford this 199 local price = delta * g_scenario.ecoSystem.fuelPricePerLiter; 200 201 if g_scenario:canAffordExpense(price) then 202 -- refuel 203 self.fuelTankCurrentAmount = math.min(self.fuelTankCurrentAmount + delta, self.fuelTankCapacity); 204 g_scenario.accounting:addExpense("vehicles", -price); 205 206 isRefuelling = true; 207 end; 208 end; 209 end; 210 211 isRefuelling = isRefuelling and self:getIsLocalPlayerEntered(); 212 213 if self.refuelSoundPlaying ~= isRefuelling then 214 if isRefuelling then 215 -- start playing sounds 216 self:playSound(self.fuelTankRefillLoop); 217 self:playSound(self.fuelTankRefillStart); 218 self:stopSound(self.fuelTankRefillStop); 219 else 220 self:stopSound(self.fuelTankRefillStart); 221 self:stopSound(self.fuelTankRefillLoop); 222 self:playSound(self.fuelTankRefillStop); 223 end; 224 self.refuelSoundPlaying = isRefuelling; 225 end; 226 227 if self:getIsGUIActive() then 228 self.vehicleHUD:showFuelAmount(self.fuelTankCurrentAmount, self.fuelTankCapacity); 229 end; 230 231 end;
FuelTank:onHUDActivate()
Activates the fuel-related UI elements in the vehicle HUD.
235 function FuelTank:onHUDActivate() 236 self.vehicleHUD:activateFuelDisplay(); 237 end;
FuelTank:onLeave(player, isLocalPlayer)
Stops all sounds when leaving a vehicle.
241 function FuelTank:onLeave(player, isLocalPlayer) 242 self.isRefuelling = false; 243 244 if isLocalPlayer then 245 self:stopSound(self.fuelTankRefillStart); 246 self:stopSound(self.fuelTankRefillLoop); 247 self:stopSound(self.fuelTankRefillStop); 248 self.refuelSoundPlaying = false; 249 end; 250 end;
FuelTank:writeUpdate(isLocalPlayerEntered)
Sends the current fuel level from the server to the client.
254 function FuelTank:writeUpdate(isLocalPlayerEntered) 255 if g_isServer then 256 streamBeginWriteBitwise(); 257 Utils.streamWriteFloatN(self.fuelTankCurrentAmount, 16, 0, self.fuelTankCapacity); 258 streamEndWriteBitwise(); 259 end; 260 end;
FuelTank:readUpdate()
Reads the current fuel level. Will be displayed by the UI in the next frame's update
call.
264 function FuelTank:readUpdate() 265 if g_isClient then 266 streamBeginReadBitwise(); 267 self.fuelTankCurrentAmount = Utils.streamReadFloatN(16, 0, self.fuelTankCapacity); 268 streamEndReadBitwise(); 269 end; 270 end;
Copyright
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.