meta data for this page
Vehicles/VehicleManager.lua
Together with Vehicle, VehicleManager is at the core of all scripts relating to vehicles. It is responsible for managing many features that are shared between all vehicles (such as switching vehicles using the Tab
key and the distribution of various events such as update(dt)
).
32 VehicleManager = VehicleManager or {};
VehicleManager:setup()
Is called upon initialisation of the game. This will also set up SnowmakingManager.
37 function VehicleManager:setup() 38 self.vehicles = {}; 39 self.vehiclesByOrder = {}; 40 self.vehicleTemplates = {}; 41 self.allowSwitchVehicle = true; 42 self.currentVehicle = nil; -- the vehicle this player is currently in 43 44 self.vehicleSpawnPositons = {}; 45 self.dummyFunction = function() end; 46 47 SnowmakingManager:setup(); 48 end;
VehicleManager:newFunction(functionName)
This function will return a new function which calls the function named functionName
(string) for all vehicle scripts of the vehicle it is called on. Check the load()
function of any vehicle script (e.g. RopeWinch) to see how it is used.
51 function VehicleManager:newFunction(functionName) 52 -- returns a function that calls all vehicle scripts 53 54 return function(self, ...) 55 -- call all vehicle scripts 56 57 for _, script in pairs(self.vehicleScripts) do 58 -- ensure its not nil 59 if script[functionName] ~= nil then 60 script[functionName](self, ...); 61 end; 62 end; 63 end; 64 end;
VehicleManager:dummyFunction()
This function will return a dummy function that does not perform any action at all. This is easier than checking the functions against nil in some cases.
68 function VehicleManager:dummyFunction() 69 return self.dummyFunction; 70 end;
VehicleManager:registerVehicleTemplate(typeName, template)
Registers a new vehicle template named typeName
(string). The data regarding this template are stored within template
(table).
75 function VehicleManager:registerVehicleTemplate(typeName, template) 76 self.vehicleTemplates[typeName] = template; 77 end;
VehicleManager:registerVehicle(vehicle)
Registers a new vehicle instance vehicle
(table of the instance).
80 function VehicleManager:registerVehicle(vehicle) 81 -- add this entry to vehicles list 82 -- note: key is actually the vehicle value 83 self.vehicles[vehicle.mainId or vehicle.id] = vehicle; 84 85 -- avoid double entries 86 for n, vhc in pairs(self.vehiclesByOrder) do 87 if vehicle == vhc then 88 return; 89 end; 90 end; 91 92 table.insert(self.vehiclesByOrder, vehicle); 93 end;
VehicleManager:unregisterVehicle(vehicle)
Unregisters the vehicle instance vehicle
(table of the instance). This is called in Vehicle:destroy()
(see Vehicle).
96 function VehicleManager:unregisterVehicle(vehicle) 97 -- delete this entry 98 if vehicle.mainId ~= nil then 99 self.vehicles[vehicle.mainId] = nil; 100 end; 101 if vehicle.id ~= nil then 102 self.vehicles[vehicle.id] = nil; 103 end; 104 105 for n, vhc in pairs(self.vehiclesByOrder) do 106 if vehicle == vhc then 107 table.remove(self.vehiclesByOrder, n); 108 break; 109 end; 110 end; 111 end;
VehicleManager:onEnterVehicle(vehicle)
Is called every time the player enters the vehicle vehicle
(table of the instance).
114 function VehicleManager:onEnterVehicle(vehicle) 115 self.currentVehicle = vehicle; 116 117 -- reset player controller's parent 118 PlayerController:setParent(0); 119 120 -- micro lag: call this every now and then 121 g_scenario:allowMicroLag(); 122 end;
VehicleManager:onLeaveVehicle(vehicle)
Is called every time the player leaves the vehicle vehicle
(table of the instance).
125 function VehicleManager:onLeaveVehicle(vehicle) 126 if self.currentVehicle == vehicle then 127 self.currentVehicle = nil; 128 end; 129 end;
VehicleManager:switchVehicle(delta)
Is called every time the player wants to switch vehicles, e.g. by pressing the Tab
key. delta
(eiter larger 0 or less than 0). The function walks through all available vehicles in the given order and activates the next possible one.
132 function VehicleManager:switchVehicle(delta) 133 if not self.allowSwitchVehicle or not g_scenario.freeplayMode or IngameEditorGui.isActive then 134 return; 135 end; 136 137 -- this is a bit slow, but simpler in programming 138 local currentIndex = 0; 139 local vehicleCount = 0; 140 141 for i, vehicle in pairs(self.vehiclesByOrder) do 142 143 -- count all vehicles that have driver seats 144 if vehicle.driverSeat ~= nil and not vehicle.nonTabbable then 145 vehicleCount = vehicleCount + 1; 146 end; 147 148 -- determine current vehicle number in that list 149 if vehicle == self.currentVehicle then 150 currentIndex = vehicleCount; 151 end; 152 end; 153 154 if self.currentVehicle ~= nil then 155 self.currentVehicle:leaveByTab(); 156 end; 157 VehicleSeat.leaveActiveSeat(); 158 159 local newIndex = 1; 160 -- determine the vehicle we want to jump into 161 if currentIndex == 0 then 162 newIndex = (delta > 0) and 1 or 0; 163 else 164 newIndex = currentIndex + delta; 165 end; 166 167 -- limit to bounds 168 if newIndex > vehicleCount then 169 newIndex = 1; 170 171 elseif newIndex < 1 then 172 newIndex = vehicleCount + newIndex; 173 end; 174 175 -- jump to that vehicle 176 local n = 1; 177 for i, vehicle in pairs(self.vehiclesByOrder) do 178 179 -- count all vehicles that have driver seats 180 if vehicle.driverSeat ~= nil and not vehicle.nonTabbable then 181 if n == newIndex then 182 -- jump into this vehicle, then quit 183 vehicle:enterByTab(); 184 return; 185 end; 186 187 n = n + 1; 188 end; 189 end; 190 end;
VehicleManager:update(...)
This is directly called by the game's update
function. It distributes the update(dt)
call to all vehicles.
193 function VehicleManager:update(...) 194 -- switch vehicle function 195 if InputMapper:getKeyDown(InputMapper.Vehicle_Switch_Inverse) then 196 -- switch with inverse order 197 self:switchVehicle(-1); 198 199 elseif InputMapper:getKeyDown(InputMapper.Vehicle_Switch) then 200 -- switch to next vehicle 201 self:switchVehicle(1); 202 end; 203 204 for n, vehicle in pairs(self.vehicles) do 205 if vehicle.update ~= nil then 206 vehicle:update(...); 207 end; 208 end; 209 for n, vehicle in pairs(self.vehicles) do 210 if vehicle.postUpdate ~= nil then 211 vehicle:postUpdate(...); 212 end; 213 end; 214 215 if g_currentVehicleSeat ~= nil and g_currentVehicleSeat.update ~= nil then 216 g_currentVehicleSeat:update(...); 217 end; 218 end;
VehicleManager:fixedUpdate(...)
This again is called directly by the game's fixedUpdate
function. For performance reasons, the fixedUpdate(dt)
function will only be distributed to the currently active vehicle.
221 function VehicleManager:fixedUpdate(...) 222 --[[for n, vehicle in pairs(self.vehicles) do 223 if vehicle.fixedUpdate ~= nil then 224 vehicle:fixedUpdate(...); 225 end; 226 end; 227 228 if self.currentVehicle ~= nil and self.currentVehicle.fixedUpdate ~= nil then 229 self.currentVehicle:fixedUpdate(...); 230 end; 231 232 if g_currentVehicleSeat ~= nil and g_currentVehicleSeat.fixedUpdate ~= nil then 233 g_currentVehicleSeat:fixedUpdate(...); 234 end; 235 end;
VehicleManager:onGUI(...)
One more time, the function is called directly by the game's onGUI
function.
238 function VehicleManager:onGUI(...) 239 for n, vehicle in pairs(self.vehicles) do 240 if vehicle.onGUI ~= nil then 241 vehicle:onGUI(...); 242 end; 243 end; 244 end;
VehicleManager:spawnVehicle(templateName, x,y,z, rx,ry,rz)
Spawns a new vehicle of template name templateName
(string) at position x,y,z
(all float) with rotation rx,ry,rz
(all float in degrees).
256 function VehicleManager:spawnVehicle(templateName, x,y,z, rx,ry,rz) 257 -- find the template 258 local template = self.vehicleTemplates[templateName]; 259 260 if template == nil then 261 print("Error VehicleManager: attempt to spawn non-existing vehicle with template name " .. tostring(templateName) .. ". Make sure you've installed all mods that are used in this savegame."); 262 return nil; 263 end; 264 265 -- load the configuration 266 local mod = ModLoader.mods[template.modName]; 267 local bundleId = 0; 268 if mod ~= nil and mod.modFilename ~= nil then 269 bundleId = Utils.loadAssetBundleFromFile(mod.modFilename); 270 end; 271 local dataTable = template.dataTable; 272 273 local customClass = dataTable.class or Vehicle; 274 local instance = customClass:new(bundleId, modName, templateName, dataTable, vehicleId); 275 276 instance:spawnAt(x,y,z, rx or 0, ry or 0, rz or 0) 277 return instance; 278 end;
VehicleManager:saveToTable()
Called directly by the scenario when the game is saved. The function passes the call on to each vehicle.
281 function VehicleManager:saveToTable() 282 local vehicles = {}; 283 for k, vehicle in pairs(VehicleManager.vehicles) do 284 table.insert(vehicles, vehicle:saveToTable()); 285 end; 286 return vehicles; 287 end;
VehicleManager:loadFromTable(tbl)
Also called directly by the scenario when the game is loaded. The function spawns a new vehicle for each table entry and calls Vehicle:loadFromTable()
on each vehicle.
290 function VehicleManager:loadFromTable(tbl) 291 if tbl == nil then return end; 292 293 for k, vehicle in pairs(tbl) do 294 local vehicleInstance = VehicleManager:spawnVehicle(vehicle.templateName, vehicle.px,vehicle.py,vehicle.pz, vehicle.rx,vehicle.ry,vehicle.rz); 295 296 -- check this against nil (nil will be returned if the template is invalid) 297 if vehicleInstance ~= nil then 298 vehicleInstance:loadFromTable(vehicle); 299 end; 300 end; 301 end;
VehicleManager:addSpawnPosition(id, customVehicleRotation)
Permanently adds a spawn position to the game. Any time vehicles are bought or resetted, they will be placed on the first available spawn position.
304 function VehicleManager:addSpawnPosition(id, customVehicleRotation) 305 local pos = {}; 306 pos.startPosition = VectorUtils.getWorldPosition(id); 307 pos.endPosition = VectorUtils.getWorldPosition(getChildAt(id, 0)); 308 pos.width = (pos.endPosition - pos.startPosition):magnitude(); 309 pos.direction = (pos.endPosition - pos.startPosition):normalized(); 310 311 x,y,z = getWorldRotation(id); 312 pos.ry = y; 313 314 pos.vehicleRotation = customVehicleRotation or y; 315 316 table.insert(self.vehicleSpawnPositons, pos); 317 end;
VehicleManager:newTempSpawnPosition(posBegin, posEnd, ry, customVehicleRotation)
Temporarily creates a new spawn position, e.g. if a tutorial mission is active.
320 function VehicleManager:newTempSpawnPosition(posBegin, posEnd, ry, customVehicleRotation) 321 local place = {}; 322 place.startPosition = posBegin; 323 place.endPosition = posEnd; 324 place.width = (posEnd - posBegin):magnitude(); 325 place.direction = (posEnd - posBegin):normalized(); 326 327 place.ry = ry or 0; 328 place.vehicleRotation = customVehicleRotation or place.ry; 329 330 return place; 331 end;
VehicleManager:addSpawnPositionOverride(place)
Temporarily adds a spawn position to the overrides. Any time a vehicle is bought or resetted, override spawn positions will be preferred over permanent spawn positions.
334 function VehicleManager:addSpawnPositionOverride(place) 335 if self.spawnPositionOverrides == nil then 336 self.spawnPositionOverrides = {}; 337 end; 338 339 table.insert(self.spawnPositionOverrides, place); 340 end;
VehicleManager:cleanupSpawnPositionOverrides()
Removes any temporary spawn position overrides.
343 function VehicleManager:cleanupSpawnPositionOverrides() 344 self.spawnPositionOverrides = nil; 345 end;
VehicleManager:findPosition(width, length)
Returns the first suitable spawn position (spawn position overrides first, then permanent spawn positions).
348 local copy = function(from, to) 349 for k, v in ipairs(from) do 350 table.insert(to, v); 351 end; 352 end; 353 354 function VehicleManager:findPosition(width, length) 355 local positions = {}; 356 357 if self.spawnPositionOverrides ~= nil then 358 copy(self.spawnPositionOverrides, positions); 359 end; 360 361 copy(self.vehicleSpawnPositons, positions); 362 363 364 local height = 5; 365 width, length = width+0.5, length+1; -- leave a minimum gap 366 367 for k, place in pairs(positions) do 368 -- do some box casts there 369 370 for i=width/2, place.width-width/2, 1 do 371 local p = place.startPosition + place.direction:multiply(i); 372 p.y = Utils.sampleTerrainHeight(p.x, p.z) + height/2; 373 374 local isFull = Utils.checkBox(Vector3:new(p.x, p.y, p.z), Vector3:new(width, height, length), place.ry); 375 376 if not isFull then 377 return p.x,p.y,p.z, place.vehicleRotation; 378 end; 379 end; 380 end; 381 382 if #positions <= 0 and PlayerController.isActive then 383 -- there are no spawn positions within the map! 384 -- therefore spawn at player position 385 local p = VectorUtils.getWorldPosition(PlayerController.transformId); 386 p.y = Utils.sampleTerrainHeight(p.x, p.z) + height/2; 387 388 local isFull = Utils.checkBox(Vector3:new(p.x, p.y, p.z), Vector3:new(width, height, length), 0, (2^32) - 1 - 2^19 - 2^2); 389 390 -- return this as backup position 391 if not isFull then 392 local rx,ry,rz = getWorldRotation(PlayerController.transformId); 393 return p.x,p.y,p.z, ry, true; 394 end; 395 end; 396 397 -- nothing found if we actually arrive here (so nothing is returned) 398 end;
VehicleManager:addMaintenanceExpenses(dayShare)
Charges maintenance expenses for all vehicles. The daily maintenance costs are multiplied by the factor dayShare
(float, share of the day passed since the last call).
401 function VehicleManager:addMaintenanceExpenses(dayShare) 402 -- add maintenance cost for each vehicle 403 for k, v in pairs(self.vehiclesByOrder) do 404 local cost = v:getMaintenanceCost() or 0; 405 g_scenario.accounting:addExpense("vehicles", -cost*dayShare); 406 end; 407 end;
Copyright
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.