Guest User

PDA + AAI compatibility

a guest
Aug 26th, 2017
304
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 7.71 KB | None | 0 0
  1.  
  2.  
  3. -- **** BEGIN insert this function before "local function manage_drive_assistant(index)"
  4.  
  5. -- adjusts the orientation of the unit being controlled to follow paved tiles
  6. local function manage_drive_assistant_for_unit(unit, player)
  7.     local car = unit.vehicle
  8.  
  9.     if global.unit_data == nil then
  10.         global.unit_data = {}
  11.     end
  12.     if global.unit_data[unit.unit_id] == nil then
  13.         global.unit_data[unit.unit_id] = {}
  14.     end
  15.  
  16.     local car_data = global.unit_data[unit.unit_id]
  17.  
  18.     if car ~= nil and math.abs(unit.speed) > global.min_speed then
  19.         local dir = car.orientation
  20.         local newdir = 0
  21.  
  22.         local dirr = dir + lookangle
  23.         local dirl = dir - lookangle
  24.  
  25.         -- scores for straight, right and left (@sillyfly)
  26.         local ss,sr,sl = 0,0,0
  27.         local vs = {math.sin(2*math.pi*dir), -math.cos(2*math.pi*dir)}
  28.         local vr = {math.sin(2*math.pi*dirr), -math.cos(2*math.pi*dirr)}
  29.         local vl = {math.sin(2*math.pi*dirl), -math.cos(2*math.pi*dirl)}
  30.  
  31.         local px = car.position['x'] or car.position[1]
  32.         local py = car.position['y'] or car.position[2]
  33.  
  34.         -- notification("X " .. px ..  " Y " .. py)
  35.         local sign = (unit.speed >= 0 and 1) or -1
  36.  
  37.         local sts = {px, py}
  38.         local str = {px + sign*vs[2]*eccent, py - sign*vs[1]*eccent}
  39.         local stl = {px -sign*vs[2]*eccent, py + sign*vs[1]*eccent}
  40.  
  41.         -- linearly increases start and length of the scanned area if the car is very fast
  42.         local lookahead_start_hs = 0
  43.         local lookahead_length_hs = 0
  44.  
  45.         if car.speed > global.highspeed then
  46.             local speed_factor = car.speed / global.highspeed
  47.             lookahead_start_hs = math.floor (hs_start_extension * speed_factor + 0.5)
  48.             lookahead_length_hs = math.floor (hs_length_extension * speed_factor + 0.5)
  49.         end
  50.  
  51.         -- sign detection
  52.         if game.surfaces[car.surface.index].count_entities_filtered{area = {{px-1, py-1},{px+1, py+1}}, type="constant-combinator"} > 0 then
  53.             local sign_scanner = game.surfaces[car.surface.index].find_entities_filtered{area = {{px-1, py-1},{px+1, py+1}}, type="constant-combinator"}
  54.             for i = 1, #sign_scanner do
  55.                 -- speed limit sign
  56.                 if sign_scanner[i].name == "pda-road-sign-speed-limit" then
  57.                     local sign = sign_scanner[i].get_or_create_control_behavior().get_signal(1)
  58.                     local sign_value = 0
  59.                     if sign.signal ~= nil then sign_value = sign.count end
  60.                     -- read signal value only if a signal is set
  61.                     if sign_value ~= 0 then
  62.                         car_data.imposed_speed_limit = kmph_to_mpt(sign_value)
  63.                         if car.speed > car_data.imposed_speed_limit then
  64.                             -- activate brake to deccelerate the vehicle
  65.                             car_data.cruise_control_brake_active = true
  66.                         end
  67.                     end
  68.                     return
  69.                 -- unlimit sign
  70.                 elseif sign_scanner[i].name == "pda-road-sign-speed-unlimit" then
  71.                     car_data.imposed_speed_limit_car = nil
  72.                     return
  73.                 end
  74.             end
  75.         end
  76.  
  77.         --local last_scan = global.last_scan[player.index]
  78.         --local new_scan = {{},{}}
  79.         -- calculate scores within the scanning area in front of the vehicle (@sillyfly)
  80.         -- commented out areas: Intended to cache scanned tiles to avoid multiple scans. Downside: This is apparently 5%-10% slower than accessing the raw tile data on each tick.
  81.         for i=lookahead_start + lookahead_start_hs,lookahead_start + lookahead_length + lookahead_length_hs do
  82.             local d = i*sign
  83.             local rstx = str[1] + vs[1]*d
  84.             local rsty = str[2] + vs[2]*d
  85.             local lstx = stl[1] + vs[1]*d
  86.             local lsty = stl[2] + vs[2]*d
  87.             local rtx = px + vr[1]*d
  88.             local rty = py + vr[2]*d
  89.             local ltx = px + vl[1]*d
  90.             local lty = py + vl[2]*d
  91.             local rst = --[[(last_scan ~= nil and last_scan[rstx] ~= nil and last_scan[rstx][rsty]) or]] scores[car.surface.get_tile(rstx, rsty).name]
  92.             local lst = --[[(last_scan ~= nil and last_scan[lstx] ~= nil and last_scan[lstx][lsty]) or]] scores[car.surface.get_tile(lstx, lsty).name]
  93.             local rt = --[[(last_scan ~= nil and last_scan[rtx] ~= nil and last_scan[rtx][rty]) or]] scores[car.surface.get_tile(rtx, rty).name]
  94.             local lt = --[[(last_scan ~= nil and last_scan[ltx] ~= nil and last_scan[ltx][lty]) or]] scores[car.surface.get_tile(ltx, lty).name]
  95.  
  96.             ss = ss + (((rst or 0) + (lst or 0))/2.0)
  97.             sr = sr + (rt or 0)
  98.             sl = sl + (lt or 0)
  99.  
  100.             --[[
  101.             new_scan[rstx] = (new_scan ~= nil and new_scan[rstx]) or {}
  102.             new_scan[rstx][rsty] = rst
  103.             new_scan[lstx] = (new_scan ~= nil and new_scan[lstx]) or {}
  104.             new_scan[lstx][lsty] = lst
  105.             new_scan[rtx] = (new_scan ~= nil and new_scan[rtx]) or {}
  106.             new_scan[rtx][rty] = rt
  107.             new_scan[ltx] = (new_scan ~= nil and new_scan[ltx]) or {}
  108.             new_scan[ltx][lty] = lt
  109.             ]]
  110.         end
  111.         --global.last_scan[player.index] = new_scan
  112.         if debug and player then
  113.             player.print("x:" .. px .. "->" .. px+vs[1]*(lookahead_start + lookahead_length) .. ", y:" .. py .. "->" .. py+vs[2]*(lookahead_start + lookahead_length))
  114.             player.print("S: " .. ss .. " R: " .. sr .. " L: " .. sl)
  115.         end
  116.  
  117.         -- check if the score indicates that the vehicle leaved paved area
  118.         local ls = car_data.last_score or 0
  119.         local ts = ss+sr+sl
  120.  
  121.         if ts < ls and ts == 0 and not car_data.emergency_brake_active then
  122.             -- warn the player and activate emergency brake
  123.  
  124.             if player and player.mod_settings["PDA-setting-sound-alert"].value then
  125.                 player.surface.create_entity({name = "pda-warning-1", position = player.position})
  126.             elseif player and player.mod_settings["PDA-setting-verbose"].value then
  127.                 player.print({"DA-road-departure-warning"})
  128.             end
  129.             if player then
  130.                 player.riding_state = {acceleration = defines.riding.acceleration.braking, direction = player.riding_state.direction}
  131.             end
  132.             car_data.emergency_brake_active = true
  133.         end
  134.         car_data.last_score_car = ts
  135.  
  136.         -- set new direction depending on the scores (@sillyfly)
  137.         if sr > ss and sr > sl then
  138.             newdir = dir + (changeangle*sr*2)/(sr+ss)
  139.         elseif sl > ss and sl > sr then
  140.             newdir = dir - (changeangle*sl*2)/(sl+ss)
  141.         else
  142.            newdir = dir
  143.         end
  144.  
  145.         -- Snap car to nearest 1/64 to avoid oscillation (@GotLag)
  146.         car.orientation = math.floor(newdir * 64 + 0.5) / 64
  147.  
  148.     -- no score reset in curves -> allow the player to guide his vehicle off road manually
  149.     elseif player and player.riding_state.direction ~= defines.riding.direction.straight then
  150.         car_data.last_score = 0
  151.     end
  152.  
  153. end
  154.  
  155. -- **** END of function to insert
  156.  
  157.  
  158. -- **** BEGIN insert this section at the end of the "function pda.on_tick(event)" function right before "global.playertick = ptick"
  159.  
  160.     -- if aai mod is active, manage drive assistant for all units
  161.     -- TODO only manage drive assistant if a certain signal is active on the car to avoid performance issues and add flexibility
  162.     if remote.interfaces["aai-programmable-vehicles"]["get_units"] then
  163.         local units = remote.call("aai-programmable-vehicles", "get_units", entity)
  164.  
  165.         for key1, unit in pairs(units) do
  166.             if unit and unit.vehicle ~= nil and unit.vehicle.valid and not unit.vehicle.passenger then
  167.                 manage_drive_assistant_for_unit(unit)
  168.             end
  169.         end
  170.     end
  171.  
  172. -- **** END of section to insert
Advertisement
Add Comment
Please, Sign In to add comment