Thanks!
While browsing the mod's discussion board, I've found
this thread where somebody provided some code for calculating the maximum speed. This was posted several weeks before I even started to collaborate on Autodrive, that's why I didn't see it before.
I adapted the code this way:
Code: Select all
-- Modded vehicles (e.g. the jet from "Aircraft") may have insane speeds, so we limit the top speed to a reasonable value
-- (anything faster will lead to strange quirks)
local SPEED_CAP = 300
-- state{} contains the entity state.car and additional data related to that entity
local vehicle = state.car -- entity
local p = vehicle.prototype -- entity.prototype
-- Setup defaults (to be replaced with real values later on, perhaps)
local fuel_speed_modifier = 1
local sticker_speed_modifiers = 1
local sticker_friction_modifier = 1
local tileUnderVehicle = vehicle.surface.get_tile(vehicle.position)
-- vehicle_friction_modifier of each tile will be stored in a local table in the future so we don't have to poll prototype data each time
local tile_friction_modifier = tileUnderVehicle.prototype.vehicle_friction_modifier
-- raw_acceleration_eng_per_tick can be stored because all values used in the calculation are constant prototype data
if not state.raw_acceleration_eng_per_tick then
state.raw_acceleration_eng_per_tick = (p.consumption * vehicle.consumption_modifier) *
(p.effectivity * vehicle.effectivity_modifier) *
p.burner_prototype.effectivity
end
-- Store constant values with vehicle so prototype data will have to be polled only once
state.terrain_friction_modifier = state.terrain_friction_modifier or p.terrain_friction_modifier
state.friction_force = state.friction_force or p.friction_force
state.friction_modifier = state.friction_modifier or vehicle.friction_modifier
state.weight = state.weight or p.weight
-- This can't be stored because tile_friction_modifier and (in the future) sticker_*_modifiers will vary
local friction_modifier = (1 - state.friction_force *
(1 + state.terrain_friction_modifier * (tile_friction_modifier - 1) ) *
state.friction_modifier * sticker_friction_modifier
)
local acceleration_eng_per_tick = state.raw_acceleration_eng_per_tick * fuel_speed_modifier * sticker_speed_modifiers
lcoal max_energy = acceleration_eng_per_tick * friction_modifier ^ 2 / (1-friction_modifier ^ 2)
local max_speed_tiles_sec = math.sqrt(max_energy/0.5/state.weight)
local max_speed_kph = max_speed_tiles_sec * 3.6
local max_speed = max(SPEED_CAP * -1, min(SPEED_CAP, max_speed_kph))
Using this, I can determine a vehicle's maximum speed on the terrain it's currently driving at, and accelerate if the current speed is lower, brake if it's higher, or coast if it's about the same. Now I need to find out when I have to start braking if a waypoint (final destination or turn of direction) is near.
Until now, this was used:
Code: Select all
local waypoint = state.path[1].position
local range = distance(waypoint, car.position)
-- Adjust speeds
if range > 8 or rails then
speed = 100
elseif range > 4 then
speed = 50
end
[…]
if range < 0.5 then
brake(state)
end
The same speeds were applied to all vehicles, so using constant values for range kind of worked. Now I'll need to calculate range based on a variable driving speed. This should be possible using information from the old thread darkfrei has linked to. However, there's one complication: I need to find a suitable minimum speed that won't slow down the vehicle to a crawI (some mods introduce incredibly fast vehicles, others vehicles that are very strong but have a rather low maximum speed) if there are several short path segments in a row, so the distance between two waypoints is less than the distance where vehicles start to slow down (with the old code: range <= 4). Applying an arbitrary limit like
may work with long, straight paths, but can result in an intolerably low traveling speed on a zigzag course. (Unfortunately, the pathing isn't optimal, so vehicles often make a detour although there would be a shorter straight path over better terrain. I haven't figured out yet how it works, so I'll have to make the best of the current situation.)
Any ideas how to deal with that?
