/* * Simple Lua script to allow TASes of the game. * Simply define the order of your inputs at the top of the file using either * the input names or the shorthands below. * The script will associate that order with the inputs in the following lines * executing them frame by frame. * * The script is capable of either loading a TAS/TAS_MAPXX-skinname.csv for * every level or a TAS/TAS_MAPXX.csv for every level or a TAS/TAS-skinname.csv * or a TAS/TAS.csv for the entire run. The run has to be started manually as * the TAS is currently unable to navigate the menu. * * Attack -> "Attack", "A" * Spin -> "Spin", "S" * Camera Left -> "CamLeft", "CL" * Camera Right -> "CamRight", "CR" * Toss Flag -> "TossFlag", "TF" * Jump -> "Jump", "J" * Fire -> "Fire", "FireNormal", "F" * Custom 1 -> "Custom1", "C1" * Custom 2 -> "Custom2", "C2" * Custom 3 -> "Custom3", "C3" * Strafe -> "X" * Move Forwards/Backwards -> "Y" * Analog -> "Analog","Manual" which one is used determines expected start mode * Autobrake -> "Brake" */ local file local lines local filename = "" //https://stackoverflow.com/questions/1426954/split-string-in-lua local function split (inputstr, sep) if sep == nil then sep = "%s" end local t={} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do table.insert(t, str) end return t end local expected_analog = false local invalid = false local mappings = {} local function get_mappings() expected_analog = false local first = lines() local buttons = split(first, ",") mappings = {} for i, b in pairs(buttons) if b == "S" or b == "Spin" mappings[BT_SPIN] = i elseif b == "A" or b == "Attack" mappings[BT_ATTACK] = i elseif b == "CL" or b == "CamLeft" mappings[BT_CAMLEFT] = i elseif b == "CR" or b == "CamRight" mappings[BT_CAMRIGHT] = i elseif b == "TF" or b == "TossFlag" mappings[BT_TOSSFLAG] = i elseif b == "J" or b == "Jump" mappings[BT_JUMP] = i elseif b == "F" or b == "Fire" or b == "FireNormal" mappings[BT_FIRENORMAL] = i elseif b == "C1" or b == "Custom1" mappings[BT_CUSTOM1] = i elseif b == "C2" or b == "Custom2" mappings[BT_CUSTOM2] = i elseif b == "C3" or b == "Custom3" mappings[BT_CUSTOM3] = i elseif b == "X" or b == "Y" or b == "Brake" mappings[b] = i elseif b == "Analog" expected_analog = true mappings["Analog"] = i elseif b == "Manual" mappings["Analog"] = i end end end local done = false local counter = 0 local checked = false local function frame() counter = $ + 1 if not invalid and not done and consoleplayer != nil if not checked and counter > 1 // Annoying fix for pflags being incorrect the first frame print("Checking Analog " + expected_analog + " - " + (consoleplayer.pflags & PF_ANALOGMODE)) if expected_analog if consoleplayer.pflags & PF_ANALOGMODE == 0 print("Replay won't work in Manual mode!") invalid = true done = true end elseif consoleplayer.pflags & PF_ANALOGMODE != 0 print("Replay won't work in Analog mode!") invalid = true done = true end checked = true end if invalid return end local frame_input = lines() // Skip comments while frame_input != nil and frame_input:sub(1,1) == "#" frame_input = lines() end consoleplayer.cmd.buttons = 0 if frame_input == nil print("End of TAS reached! GG!") done = true return nil end local inputs = split(frame_input, ",") for b,v in pairs(mappings) if type(b) == "string" if b == "Y" consoleplayer.cmd.forwardmove = tonumber(inputs[v]) elseif b == "X" consoleplayer.cmd.sidemove = tonumber(inputs[v]) elseif b == "Analog" local analog = tonumber(inputs[v]) != 0 if analog consoleplayer.pflags = $ | PF_ANALOGMODE else consoleplayer.pflags = $ & ~PF_ANALOGMODE end elseif b == "Brake" local brake = tonumber(inputs[v]) != 0 if brake consoleplayer.pflags = $ | PF_AUTOBRAKE else consoleplayer.pflags = $ & ~PF_AUTOBRAKE end end elseif inputs[v] == "1" consoleplayer.cmd.buttons = $ | b end end end end addHook("PreThinkFrame", frame) local function on_map_changed(/*int*/ mapnum) invalid = false checked = false counter = 0 local skinname = skins[consoleplayer.skin].name if filename != "client/TAS/TAS.csv" and filename != "client/TAS/TAS-"..skinname..".csv" if file != nil file:close() end local mapname = G_BuildMapName(mapnum) filename = "client/TAS/TAS_"..mapname.."-"..skinname..".csv" file = io.openlocal(filename, "r") if file == nil filename = "client/TAS/TAS_"..mapname..".csv" file = io.openlocal(filename, "r") end if file == nil filename = "client/TAS/TAS-"..skinname..".csv" file = io.openlocal(filename, "r") end if file == nil filename = "client/TAS/TAS.csv" file = io.openlocal(filename, "r") end if file == nil print("Unable to load TAS replay! Aborting!") done = true return nil end print("Loaded TAS replay "..filename.."!") lines = file:lines() get_mappings() done = false end end addHook("MapChange", on_map_changed)