Difference between revisions of "Script - Zoom"
From FreeSpace Wiki
m (A bit of cleanup.) |
(New Config options and FRED interface) |
||
Line 1: | Line 1: | ||
This script enables you to zoom your view so precise aiming is easier. | This script enables you to zoom your view so precise aiming is easier. | ||
+ | It includes a config file that specifies the values the script will use. It also features a FRED SEXP interface so A FREDer can force a zoom-in (or -out) as needed. | ||
+ | For more documentation check out [http://www.hard-light.net/forums/index.php?topic=70411.0 this thread]. | ||
== Table Entry == | == Table Entry == | ||
− | * To use create an file called '''zoom-sct.tbm''' in your date/tables directory and paste the following code into it: | + | * To use create an file called '''zoom-sct.tbm''' in your ''date/tables'' directory and paste the following code into it: |
<pre> | <pre> | ||
#Conditional Hooks | #Conditional Hooks | ||
$Application: FS2_Open | $Application: FS2_Open | ||
− | $On | + | $On Game Init: |
[ | [ | ||
− | -- | + | ------------------------------------------------------------- |
− | + | -------- utility functions -------- | |
− | + | ------------------------------------------------------------- | |
− | + | function trim(s) | |
− | transitionTime = | + | return (s:gsub("^%s*(.-)%s*$", "%1")) |
− | + | end | |
− | + | ||
− | + | function isAllIdent(check) | |
+ | check = check:lower() | ||
+ | if check == "**all**" then | ||
+ | return true | ||
+ | else | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function indexOf(t,val) | ||
+ | for k,v in ipairs(t) do | ||
+ | if v == val then | ||
+ | return k | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | ------------------------------------------------------------- | ||
+ | ---- defining functions used for parsing the config file ---- | ||
+ | ------------------------------------------------------------- | ||
+ | |||
+ | -- gets the next line out of the file | ||
+ | local function getNextLine(file) | ||
+ | if file:isValid() then | ||
+ | local line = file:read("*l") | ||
+ | return line | ||
+ | else | ||
+ | ba.warning("Invalid file handle pased to readLine function") | ||
+ | return nil | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- looks up the set function which is connected to the specified keyword | ||
+ | local function getSetFunc(keyword) | ||
+ | keyword = keyword:lower() | ||
+ | for i,v in pairs(setTable) do | ||
+ | index = i:lower() | ||
+ | if index == keyword then | ||
+ | return v | ||
+ | end | ||
+ | end | ||
+ | return nil | ||
+ | end | ||
+ | |||
+ | local function addAllowedShipClass(value) | ||
+ | if isAllIdent(value) then | ||
+ | allowedShips = {} | ||
+ | allowedShips[1] = value | ||
+ | return false | ||
+ | end | ||
+ | if allowedShips[1] == nil or not isAllIdent(allowedShips[1]) then | ||
+ | |||
+ | if indexOf(allowedShips,value) ~= nil then | ||
+ | ba.warning("Ship " .. value .. " was specified more than once. Skipping...") | ||
+ | return false | ||
+ | end | ||
+ | |||
+ | local ship = tb.ShipClasses[value] | ||
+ | if ship ~= nil and ship:isValid() then | ||
+ | table.insert(allowedShips, value) | ||
+ | return true | ||
+ | else | ||
+ | ba.warning("Specified ship class '" .. value .. "' does not exist.") | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function addRestrictedShipClass(value) | ||
+ | if isAllIdent(value) then | ||
+ | restrictedShips = {} | ||
+ | restrictedShips[1] = value | ||
+ | return | ||
+ | end | ||
+ | if restrictedShips[1] == nil or not isAllIdent(restrictedShips[1]) then | ||
+ | |||
+ | if indexOf(restrictedShips,value) ~= nil then | ||
+ | ba.warning("Ship " .. value .. " was specified more than once. Skipping...") | ||
+ | return false | ||
+ | end | ||
+ | |||
+ | local ship = tb.ShipClasses[value] | ||
+ | if ship ~= nil and ship:isValid() then | ||
+ | table.insert(restrictedShips, value) | ||
+ | return true | ||
+ | else | ||
+ | ba.warning("Specified ship class '" .. value .. "' does not exist.") | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function addAllowedWeaponClass(value) | ||
+ | if isAllIdent(value) then | ||
+ | allowedWeapons = {} | ||
+ | allowedWeapons[1] = value | ||
+ | return false | ||
+ | end | ||
+ | |||
+ | if allowedWeapons[1] == nil or not isAllIdent(allowedWeapons[1]) then | ||
+ | |||
+ | if indexOf(allowedWeapons,value) ~= nil then | ||
+ | ba.warning("Weapon " .. value .. " was specified more than once. Skipping...") | ||
+ | return false | ||
+ | end | ||
+ | |||
+ | local weapon = tb.WeaponClasses[value] | ||
+ | if weapon ~= nil and weapon:isValid() then | ||
+ | table.insert(allowedWeapons, value) | ||
+ | return true | ||
+ | else | ||
+ | ba.warning("Specified weapon class '" .. value .. "' does not exist.") | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function addRestrictedWeaponClass(value) | ||
+ | if isAllIdent(value) then | ||
+ | restrictedWeapons = {} | ||
+ | restrictedWeapons[1] = value | ||
+ | return false | ||
+ | end | ||
+ | if restrictedWeapons[1] == nil or not isAllIdent(restrictedWeapons[1]) then | ||
+ | |||
+ | if indexOf(restrictedWeapons,value) ~= nil then | ||
+ | ba.warning("Weapon " .. value .. " was specified more than once. Skipping...") | ||
+ | return false | ||
+ | end | ||
+ | |||
+ | local weapon = tb.WeaponClasses[value] | ||
+ | if weapon ~= nil and weapon:isValid() then | ||
+ | table.insert(restrictedWeapons, value) | ||
+ | return true | ||
+ | else | ||
+ | ba.warning("Specified weapon class '" .. value .. "' does not exist.") | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function parseLine(line) | ||
+ | if line == nil or line == "" then -- Check if this line needs to be parsed | ||
+ | return | ||
+ | end | ||
+ | |||
+ | local comm_s, comm_e = line:find("--",1,true) | ||
+ | if comm_s ~= nil then | ||
+ | line = line:sub(1,(comm_s - 1)) | ||
+ | end | ||
+ | if line == "" then -- was the line fully commented away? | ||
+ | return -- Nothing to be done... | ||
+ | end | ||
+ | local key_s, key_e = line:find(":",1,true) | ||
+ | local val_s, val_e = line:find("%a",key_e) | ||
+ | |||
+ | if key_s == nil then -- malformatted line | ||
+ | ba.warning("Malformatted line: " .. line .. "\nSkipping...") | ||
+ | return | ||
+ | end | ||
+ | |||
+ | local keyword = line:sub(1,(key_e - 1)) | ||
+ | |||
+ | if val_s == nil then -- Maybe we_ve got a digit value | ||
+ | val_s, val_e = line:find("%d",key_e) -- search for them | ||
+ | if val_s == nil then | ||
+ | -- We have no value | ||
+ | ba.warning("Keyword '" .. keyword .. "' hasn't specified a value. Skipping...") | ||
+ | return | ||
+ | end | ||
+ | end | ||
+ | |||
+ | keyword = keyword:lower() -- make the keyword lowercase | ||
+ | |||
+ | local val = line:sub(val_s, line:len()) | ||
+ | |||
+ | if val ~= nil then | ||
+ | val = trim(val) | ||
+ | local setFunc = getSetFunc(keyword) | ||
+ | if setFunc == nil then | ||
+ | ba.warning("Unknown keyword: " .. keyword) | ||
+ | return | ||
+ | end | ||
+ | setFunc(val) | ||
+ | else | ||
+ | return | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function initSetTable() | ||
+ | setTable = {} | ||
+ | setTable["Zoom Factor"]= | ||
+ | function(value) | ||
+ | local val = tonumber(value) | ||
+ | if val == nil then | ||
+ | return | ||
+ | ba.warning("Non numeric value given to 'Zoom Factor'. Skipping...") | ||
+ | end | ||
+ | zoomValue = val | ||
+ | end | ||
+ | |||
+ | setTable["Transition Time"]= | ||
+ | function(value) | ||
+ | local val = tonumber(value) | ||
+ | if val == nil then | ||
+ | ba.warning("Non numeric value given to 'Transition Time'. Skipping...") | ||
+ | return | ||
+ | end | ||
+ | transitionTime = val | ||
+ | end | ||
+ | |||
+ | setTable["Sensitivity"]= | ||
+ | function(value) | ||
+ | local val = tonumber(value) | ||
+ | if val == nil then | ||
+ | ba.warning("Non numeric value given to 'Sensitivity'. Skipping...") | ||
+ | return | ||
+ | end | ||
+ | sensitivity = val | ||
+ | end | ||
+ | |||
+ | setTable["Allowed Ship Class"]=addAllowedShipClass | ||
+ | |||
+ | setTable["Restricted Ship Class"]=addRestrictedShipClass | ||
+ | |||
+ | setTable["Allowed Weapon Class"]=addWeaponClass | ||
+ | |||
+ | setTable["Restricted Weapon Class"]=addRestrictedWeaponClass | ||
+ | |||
+ | setTable["Linked Zoom"]= | ||
+ | function(value) | ||
+ | local yesKey = "yes" | ||
+ | value = value:lower() | ||
+ | if value == yesKey then | ||
+ | linkedZoom = true | ||
+ | else | ||
+ | linkedZoom = false | ||
+ | end | ||
+ | end | ||
+ | |||
+ | setTable["Key"]= | ||
+ | function(key) | ||
+ | if key == nil then | ||
+ | ba.warning("Invalid value given for 'Key'. Skipping...") | ||
+ | return | ||
+ | end | ||
+ | zoomKey=key | ||
+ | end | ||
+ | |||
+ | setTable["Zoom Lock Key"]= | ||
+ | function(key) | ||
+ | if key == nil then | ||
+ | ba.warning("Invalid value given for 'Zoom Lock Key'. Skipping...") | ||
+ | return | ||
+ | end | ||
+ | zoomLockKey=key | ||
+ | end | ||
+ | end | ||
− | -- | + | local function readConfig() |
− | + | if cf.fileExists(configFile) then | |
− | + | local config = cf.openFile(configFile) | |
+ | if config:isValid() then | ||
+ | initSetTable() | ||
+ | local parse = true | ||
+ | while parse do | ||
+ | local line = getNextLine(config) | ||
+ | if line == nil then | ||
+ | parse = false | ||
+ | break | ||
+ | end | ||
+ | parseLine(line) -- parse the found line | ||
+ | end | ||
+ | else | ||
+ | ba.warning("Handle to config file is invalid. Is the file readable?") | ||
+ | end | ||
+ | else | ||
+ | ba.warning("No config file found. Returning to default") | ||
+ | end | ||
+ | end | ||
− | |||
− | |||
− | + | ------------------------------------------------------------- | |
− | + | ------these functions will be use for the FRED interface----- | |
+ | ------------------------------------------------------------- | ||
− | -- | + | function zoom_zoomIn() |
− | + | if defaultZoomSet and cam:isValid() then | |
− | + | cam:setFOV(normalFOV) -- Resetting the FOV in case we have not zoomed out completely | |
− | + | end | |
− | + | fredOverride = true | |
+ | zoomIn() | ||
+ | end | ||
− | + | function zoom_zoomOut() | |
+ | fredOverride = false | ||
+ | zoomOut() | ||
+ | end | ||
+ | |||
+ | function zoom_alS(ship) | ||
+ | if addAllowedShipClass(ship) then | ||
+ | table.insert(tempAllowedShip, ship) | ||
+ | end | ||
+ | end | ||
− | + | function zoom_alW(weapon) | |
− | + | if addAllowedWeaponClass(weapon) then | |
+ | table.insert(tempAllowedWeapon, weapon) | ||
+ | end | ||
+ | end | ||
− | -- | + | function zoom_reS(ship) |
− | + | if addRestrictedShipClass(ship) then | |
+ | table.insert(tempRestrictedShip, ship) | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function zoom_reW(weapon) | ||
+ | if addRestrictedWeaponClass(weapon) then | ||
+ | table.insert(tempRestrictedWeapon, weapon) | ||
+ | end | ||
+ | end | ||
+ | |||
+ | |||
+ | ------------------------------------------------------------- | ||
+ | ------ defining functions used in the script ------ | ||
+ | ------------------------------------------------------------- | ||
+ | function removeTemps() | ||
+ | for i,v in ipairs(tempAllowedShip) do | ||
+ | index = indexOf(allowedShips,v) | ||
+ | if index ~= nil then | ||
+ | allowedShips[index]=nil | ||
+ | end | ||
+ | end | ||
+ | |||
+ | for i,v in ipairs(tempRestrictedShip) do | ||
+ | index = indexOf(restrictedShips,v) | ||
+ | if index ~= nil then | ||
+ | restrictedShips[index]=nil | ||
+ | end | ||
+ | end | ||
+ | |||
+ | for i,v in ipairs(tempAllowedWeapon) do | ||
+ | index = indexOf(allowedWeapons,v) | ||
+ | if index ~= nil then | ||
+ | allowedWeapons[index]=nil | ||
+ | end | ||
+ | end | ||
+ | |||
+ | for i,v in ipairs(tempRestrictedWeapon) do | ||
+ | index = indexOf(restrictedWeapons,v) | ||
+ | if index ~= nil then | ||
+ | restrictedWeapons[index]=nil | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function checkTables(allTbl,restrTbl, checkHandle) | ||
+ | if checkHandle == nil then | ||
+ | return false | ||
+ | end | ||
+ | if allTbl ~= nil and restrTbl ~= nil then | ||
+ | if #allTbl > 0 then | ||
+ | if isAllIdent(allTbl[1]) then | ||
+ | if #restrTbl > 0 then | ||
+ | if isAllIdent(restrTbl[1]) then | ||
+ | return true | ||
+ | end | ||
+ | end | ||
+ | for i,v in ipairs(restrTbl) do | ||
+ | if checkHandle.Name == v then | ||
+ | return false | ||
+ | end | ||
+ | end | ||
+ | return true | ||
+ | elseif isAllIdent(restrTbl[1]) then | ||
+ | if #allTbl > 0 then | ||
+ | if isAllIdent(allTbl[1]) then | ||
+ | return true | ||
+ | end | ||
+ | end | ||
+ | for i,v in ipairs(allTbl) do | ||
+ | if checkHandle.Name == v then | ||
+ | return true | ||
+ | end | ||
+ | end | ||
+ | return false | ||
+ | else | ||
+ | local allowed = false | ||
+ | for i,v in ipairs(allTbl) do | ||
+ | if checkHandle.Name == v then | ||
+ | allowed = true | ||
+ | break | ||
+ | end | ||
+ | end | ||
+ | for i,v in ipairs(restrTbl) do | ||
+ | if checkHandle.Name == v then | ||
+ | allowed = false | ||
+ | break | ||
+ | end | ||
+ | end | ||
+ | return allowed | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | return true | ||
+ | end | ||
+ | |||
+ | function isAllowedShip(shipClass) | ||
+ | return checkTables(allowedShips,restrictedShips,shipClass) | ||
+ | end | ||
+ | |||
+ | function isAllowedWeapon(weaponClass) | ||
+ | return checkTables(allowedWeapons,restrictedWeapons,weaponClass) | ||
+ | end | ||
function getProgressString() | function getProgressString() | ||
Line 59: | Line 450: | ||
function handleControls() | function handleControls() | ||
if zoomingIn or zoomedIn then | if zoomingIn or zoomedIn then | ||
− | local ci = ba.getControlInfo() | + | if currentProgr > 0 then |
− | + | local tempSensValue = sensitivity * 100 / currentProgr | |
− | + | ||
− | + | if tempSensValue <= 1 then | |
+ | local ci = ba.getControlInfo() | ||
+ | ci.Pitch = ci.Pitch * tempSensValue | ||
+ | ci.Heading = ci.Heading * tempSensValue | ||
+ | ci.Bank = ci.Bank * tempSensValue | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function isAllowedToZoom() | ||
+ | local allowedShip = isAllowedShip(hv.Player.Class) | ||
+ | |||
+ | local allowedWeapon = true | ||
+ | local primWeaponBank = hv.Player.PrimaryBanks | ||
+ | if not linkedZoom and primWeaponBank.Linked then | ||
+ | allowedWeapon = false | ||
+ | else | ||
+ | for i=0, #primWeaponBank do | ||
+ | local v = primWeaponBank[i] | ||
+ | if v.Armed then | ||
+ | if isAllowedWeapon(tb.WeaponClasses[v.WeaponClass.Name]) then | ||
+ | allowedWeapon = true | ||
+ | break | ||
+ | else | ||
+ | allowedWeapon = false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | if allowedWeapon then | ||
+ | local secWeaponBank = hv.Player.SecondaryBanks | ||
+ | for i=0, #secWeaponBank do | ||
+ | local v = secWeaponBank[i] | ||
+ | if v.Armed then | ||
+ | if isAllowedWeapon(tb.WeaponClasses[v.WeaponClass.Name]) then | ||
+ | allowedWeapon = true | ||
+ | break | ||
+ | else | ||
+ | allowedWeapon = false | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | return allowedShip and allowedWeapon | ||
+ | end | ||
+ | |||
+ | function zoomIn() | ||
+ | if not cameraSet then | ||
+ | if #gr.Cameras > 0 then | ||
+ | cam = gr.Cameras[1] | ||
+ | end | ||
+ | end | ||
+ | if not zooming then | ||
+ | if hv.Player:isValid() then | ||
+ | if cam:isValid() then | ||
+ | |||
+ | if isAllowedToZoom() then | ||
+ | if currentProgr > 0 and currentProgr < 100 then | ||
+ | stepWidth = width / currentProgr -- Setting the stepWidth in case the zoom may not have been completed | ||
+ | end | ||
+ | |||
+ | zoomEndProgress = 100 | ||
+ | |||
+ | zooming = true | ||
+ | |||
+ | zoomingIn = true | ||
+ | zoomedIn = false | ||
+ | zoomedOut = false | ||
+ | zoomingOut = false | ||
+ | |||
+ | if not defaultZoomSet then | ||
+ | normalFOV = cam.FOV | ||
+ | defaultZoomSet = true | ||
+ | end | ||
+ | zoom = normalFOV * zoomValue | ||
+ | |||
+ | ba.setControlMode(LUA_FULL_CONTROLS) | ||
+ | |||
+ | cam:setFOV(zoom,transitionTime,transitionTime / 2,transitionTime / 4) | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | |||
+ | function zoomOut() | ||
+ | if zooming and not zoomOutOverride then | ||
+ | if hv.Player:isValid() then | ||
+ | if cam:isValid() then | ||
+ | |||
+ | stepWidth = width / 100 | ||
+ | |||
+ | zoomingIn = false | ||
+ | zoomingOut = true | ||
+ | zoomedIn = false | ||
+ | zoomedOut = false | ||
+ | |||
+ | if currentProgr > 0 then | ||
+ | zoomEndProgress = currentProgr -- Save the progress we made as we begin to zoom back | ||
+ | end | ||
+ | |||
+ | cam:setFOV(normalFOV,transitionTime,transitionTime / 2,transitionTime / 4) | ||
+ | |||
+ | ba.setControlMode(NORMAL_CONTROLS) | ||
+ | |||
+ | fredOverride = false | ||
+ | end | ||
+ | end | ||
end | end | ||
end | end | ||
Line 77: | Line 576: | ||
local progressLineOffset_x = realOffset_x + stepWidth * currentProgr | local progressLineOffset_x = realOffset_x + stepWidth * currentProgr | ||
gr.drawLine(progressLineOffset_x, offset_y, progressLineOffset_x, offset_y + heigth) | gr.drawLine(progressLineOffset_x, offset_y, progressLineOffset_x, offset_y + heigth) | ||
+ | |||
+ | if not isAllowedToZoom() and not zoomOutOverride then | ||
+ | if zoomingIn or zoomedIn then | ||
+ | zoomOut() | ||
+ | zoomOutOverride = true | ||
+ | end | ||
+ | end | ||
local thisFrameProg = (frameTime / transitionTime) * zoomEndProgress | local thisFrameProg = (frameTime / transitionTime) * zoomEndProgress | ||
Line 83: | Line 589: | ||
if currentProgr >= 100 then | if currentProgr >= 100 then | ||
currentProgr = 100 | currentProgr = 100 | ||
− | + | zoomingIn = false | |
− | + | zoomedIn = true | |
end | end | ||
elseif zoomingOut then | elseif zoomingOut then | ||
Line 90: | Line 596: | ||
if currentProgr <= 0 then | if currentProgr <= 0 then | ||
currentProgr = 0 | currentProgr = 0 | ||
+ | zoomOutOverride = false | ||
zoomedOut = true | zoomedOut = true | ||
zoomingOut = false | zoomingOut = false | ||
Line 95: | Line 602: | ||
end | end | ||
end | end | ||
+ | end | ||
+ | |||
+ | local function init() | ||
+ | if useConfig then | ||
+ | readConfig() -- read the config file if exists | ||
+ | end | ||
+ | end | ||
+ | |||
+ | local function initVars() | ||
+ | -- Some things to tell the script to do something and some default values | ||
+ | runZoomScript = false | ||
+ | useConfig = true | ||
+ | |||
+ | zoomValue = 0.1 | ||
+ | normalFOV = 0.75 | ||
+ | transitionTime = 2 | ||
+ | zooming = false | ||
+ | defaultZoomSet = false | ||
+ | cameraSet = false | ||
+ | configFile = "data/config/zoom_config.cfg" | ||
+ | zoomOutOverride = false | ||
+ | linkedZoom = true | ||
+ | zoomKey = "d" | ||
+ | zoomLockKey = nil | ||
+ | |||
+ | fredOverride=false | ||
+ | |||
+ | lockedZoom = false | ||
+ | |||
+ | -- Setting the values to be used in the $On Frame: hook | ||
+ | currentProgr = 0 | ||
+ | zoomEndProgress = 100 | ||
+ | |||
+ | zoomingIn = false | ||
+ | zoomedIn = false | ||
+ | |||
+ | zoomingOut = false | ||
+ | zoomedOut = true | ||
+ | |||
+ | -- Constants for drawing the progress | ||
+ | offset_x = 30 | ||
+ | offset_y = 70 | ||
+ | heigth = 8 | ||
+ | width = 80 | ||
+ | |||
+ | stepWidth = width / 100 | ||
+ | |||
+ | -- Settings for the sensitivity | ||
+ | sensitivity = 0.25 | ||
+ | |||
+ | -- The camera which is used for zooming (is initialized in the first $Key Pressed: hook) | ||
+ | cam = nil | ||
+ | |||
+ | -- Tables that hold the allowe/restricted informations | ||
+ | -- Ships | ||
+ | allowedShips = {"**all**"} | ||
+ | tempAllowedShip = {} | ||
+ | |||
+ | restrictedShips = {} | ||
+ | tempRestrictedShip = {} | ||
+ | |||
+ | -- Weapons | ||
+ | allowedWeapons = {"**all**"} | ||
+ | tempAllowedWeapon = {} | ||
+ | |||
+ | restrictedWeapons = {} | ||
+ | tempRestrictedWeapon = {} | ||
+ | end | ||
+ | |||
+ | -- Initialize the global variables | ||
+ | initVars() | ||
+ | |||
+ | -- Initialize the rest | ||
+ | init() | ||
+ | ] | ||
+ | |||
+ | $Application: FS2_Open | ||
+ | $On Mission Start: | ||
+ | [ | ||
+ | if not runZoomScript then | ||
+ | runZoomScript = true | ||
end | end | ||
] | ] | ||
Line 102: | Line 690: | ||
if runZoomScript then | if runZoomScript then | ||
runZoomScript = false | runZoomScript = false | ||
− | if defaultZoomSet then | + | if defaultZoomSet and cam:isValid() then |
cam:setFOV(normalFOV) -- Resetting the FOV in case we have not zoomed out completely | cam:setFOV(normalFOV) -- Resetting the FOV in case we have not zoomed out completely | ||
end | end | ||
+ | removeTemps() | ||
end | end | ||
] | ] | ||
Line 119: | Line 708: | ||
] | ] | ||
− | $ | + | $On Key Pressed: [[zoom_KeyDn.lua]] |
− | + | $On Key Released: [[zoom_KeyUp.lua]] | |
− | $On Key | + | |
− | [ | + | |
− | + | #End | |
− | + | </pre> | |
− | + | ||
− | + | Then create the file '''zoom_KeyDn.lua''' and '''zoom_KeyUp.lua''' in your ''data/scripts'' directory and paste the following into then: | |
− | + | ||
− | + | '''zoom_KeyDn.lua:''' | |
− | + | <pre> | |
− | + | if runZoomScript and not fredOverride then | |
− | + | if hv.Key:lower() == zoomLockKey:lower() then | |
− | + | if lockedZoom then | |
− | + | lockedZoom = false | |
− | + | zoomOut() | |
− | + | else | |
− | + | lockedZoom = true | |
− | + | zoomIn() | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
+ | elseif hv.Key:lower() == zoomKey:lower() then | ||
+ | zoomIn() | ||
end | end | ||
end | end | ||
− | + | </pre> | |
− | + | '''zoom_KeyUp.lua:''' | |
− | + | <pre> | |
− | if runZoomScript then | + | if runZoomScript and not fredOverride then |
− | if | + | if not lockedZoom then |
− | + | if hv.Key:lower() == zoomKey:lower() then | |
− | + | zoomOut() | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
end | end | ||
end | end | ||
− | + | </pre> | |
+ | |||
+ | After this create a file named '''zoom_config.cfg''' in your ''data/config'' directory and paste the following text into it: | ||
+ | <pre> | ||
+ | -- Setting standart values | ||
+ | Zoom Factor: 0.1 | ||
+ | Transition Time: 2 | ||
+ | Sensitivity: 0.25 | ||
+ | Linked Zoom: YES | ||
+ | Key: d | ||
+ | Zoom Lock Key: Alt-d | ||
+ | |||
+ | -- Setting ship class options | ||
+ | Allowed Ship Class: **all** | ||
− | + | -- Setting weapon class options | |
+ | Allowed Weapon Class: **all** | ||
</pre> | </pre> | ||
[[Category:Scripting Examples|Zoom]] | [[Category:Scripting Examples|Zoom]] |
Revision as of 13:46, 12 September 2010
This script enables you to zoom your view so precise aiming is easier. It includes a config file that specifies the values the script will use. It also features a FRED SEXP interface so A FREDer can force a zoom-in (or -out) as needed. For more documentation check out this thread.
Table Entry
- To use create an file called zoom-sct.tbm in your date/tables directory and paste the following code into it:
#Conditional Hooks $Application: FS2_Open $On Game Init: [ ------------------------------------------------------------- -------- utility functions -------- ------------------------------------------------------------- function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end function isAllIdent(check) check = check:lower() if check == "**all**" then return true else return false end end function indexOf(t,val) for k,v in ipairs(t) do if v == val then return k end end end ------------------------------------------------------------- ---- defining functions used for parsing the config file ---- ------------------------------------------------------------- -- gets the next line out of the file local function getNextLine(file) if file:isValid() then local line = file:read("*l") return line else ba.warning("Invalid file handle pased to readLine function") return nil end end -- looks up the set function which is connected to the specified keyword local function getSetFunc(keyword) keyword = keyword:lower() for i,v in pairs(setTable) do index = i:lower() if index == keyword then return v end end return nil end local function addAllowedShipClass(value) if isAllIdent(value) then allowedShips = {} allowedShips[1] = value return false end if allowedShips[1] == nil or not isAllIdent(allowedShips[1]) then if indexOf(allowedShips,value) ~= nil then ba.warning("Ship " .. value .. " was specified more than once. Skipping...") return false end local ship = tb.ShipClasses[value] if ship ~= nil and ship:isValid() then table.insert(allowedShips, value) return true else ba.warning("Specified ship class '" .. value .. "' does not exist.") return false end end end local function addRestrictedShipClass(value) if isAllIdent(value) then restrictedShips = {} restrictedShips[1] = value return end if restrictedShips[1] == nil or not isAllIdent(restrictedShips[1]) then if indexOf(restrictedShips,value) ~= nil then ba.warning("Ship " .. value .. " was specified more than once. Skipping...") return false end local ship = tb.ShipClasses[value] if ship ~= nil and ship:isValid() then table.insert(restrictedShips, value) return true else ba.warning("Specified ship class '" .. value .. "' does not exist.") return false end end end local function addAllowedWeaponClass(value) if isAllIdent(value) then allowedWeapons = {} allowedWeapons[1] = value return false end if allowedWeapons[1] == nil or not isAllIdent(allowedWeapons[1]) then if indexOf(allowedWeapons,value) ~= nil then ba.warning("Weapon " .. value .. " was specified more than once. Skipping...") return false end local weapon = tb.WeaponClasses[value] if weapon ~= nil and weapon:isValid() then table.insert(allowedWeapons, value) return true else ba.warning("Specified weapon class '" .. value .. "' does not exist.") return false end end end local function addRestrictedWeaponClass(value) if isAllIdent(value) then restrictedWeapons = {} restrictedWeapons[1] = value return false end if restrictedWeapons[1] == nil or not isAllIdent(restrictedWeapons[1]) then if indexOf(restrictedWeapons,value) ~= nil then ba.warning("Weapon " .. value .. " was specified more than once. Skipping...") return false end local weapon = tb.WeaponClasses[value] if weapon ~= nil and weapon:isValid() then table.insert(restrictedWeapons, value) return true else ba.warning("Specified weapon class '" .. value .. "' does not exist.") return false end end end local function parseLine(line) if line == nil or line == "" then -- Check if this line needs to be parsed return end local comm_s, comm_e = line:find("--",1,true) if comm_s ~= nil then line = line:sub(1,(comm_s - 1)) end if line == "" then -- was the line fully commented away? return -- Nothing to be done... end local key_s, key_e = line:find(":",1,true) local val_s, val_e = line:find("%a",key_e) if key_s == nil then -- malformatted line ba.warning("Malformatted line: " .. line .. "\nSkipping...") return end local keyword = line:sub(1,(key_e - 1)) if val_s == nil then -- Maybe we_ve got a digit value val_s, val_e = line:find("%d",key_e) -- search for them if val_s == nil then -- We have no value ba.warning("Keyword '" .. keyword .. "' hasn't specified a value. Skipping...") return end end keyword = keyword:lower() -- make the keyword lowercase local val = line:sub(val_s, line:len()) if val ~= nil then val = trim(val) local setFunc = getSetFunc(keyword) if setFunc == nil then ba.warning("Unknown keyword: " .. keyword) return end setFunc(val) else return end end local function initSetTable() setTable = {} setTable["Zoom Factor"]= function(value) local val = tonumber(value) if val == nil then return ba.warning("Non numeric value given to 'Zoom Factor'. Skipping...") end zoomValue = val end setTable["Transition Time"]= function(value) local val = tonumber(value) if val == nil then ba.warning("Non numeric value given to 'Transition Time'. Skipping...") return end transitionTime = val end setTable["Sensitivity"]= function(value) local val = tonumber(value) if val == nil then ba.warning("Non numeric value given to 'Sensitivity'. Skipping...") return end sensitivity = val end setTable["Allowed Ship Class"]=addAllowedShipClass setTable["Restricted Ship Class"]=addRestrictedShipClass setTable["Allowed Weapon Class"]=addWeaponClass setTable["Restricted Weapon Class"]=addRestrictedWeaponClass setTable["Linked Zoom"]= function(value) local yesKey = "yes" value = value:lower() if value == yesKey then linkedZoom = true else linkedZoom = false end end setTable["Key"]= function(key) if key == nil then ba.warning("Invalid value given for 'Key'. Skipping...") return end zoomKey=key end setTable["Zoom Lock Key"]= function(key) if key == nil then ba.warning("Invalid value given for 'Zoom Lock Key'. Skipping...") return end zoomLockKey=key end end local function readConfig() if cf.fileExists(configFile) then local config = cf.openFile(configFile) if config:isValid() then initSetTable() local parse = true while parse do local line = getNextLine(config) if line == nil then parse = false break end parseLine(line) -- parse the found line end else ba.warning("Handle to config file is invalid. Is the file readable?") end else ba.warning("No config file found. Returning to default") end end ------------------------------------------------------------- ------these functions will be use for the FRED interface----- ------------------------------------------------------------- function zoom_zoomIn() if defaultZoomSet and cam:isValid() then cam:setFOV(normalFOV) -- Resetting the FOV in case we have not zoomed out completely end fredOverride = true zoomIn() end function zoom_zoomOut() fredOverride = false zoomOut() end function zoom_alS(ship) if addAllowedShipClass(ship) then table.insert(tempAllowedShip, ship) end end function zoom_alW(weapon) if addAllowedWeaponClass(weapon) then table.insert(tempAllowedWeapon, weapon) end end function zoom_reS(ship) if addRestrictedShipClass(ship) then table.insert(tempRestrictedShip, ship) end end function zoom_reW(weapon) if addRestrictedWeaponClass(weapon) then table.insert(tempRestrictedWeapon, weapon) end end ------------------------------------------------------------- ------ defining functions used in the script ------ ------------------------------------------------------------- function removeTemps() for i,v in ipairs(tempAllowedShip) do index = indexOf(allowedShips,v) if index ~= nil then allowedShips[index]=nil end end for i,v in ipairs(tempRestrictedShip) do index = indexOf(restrictedShips,v) if index ~= nil then restrictedShips[index]=nil end end for i,v in ipairs(tempAllowedWeapon) do index = indexOf(allowedWeapons,v) if index ~= nil then allowedWeapons[index]=nil end end for i,v in ipairs(tempRestrictedWeapon) do index = indexOf(restrictedWeapons,v) if index ~= nil then restrictedWeapons[index]=nil end end end local function checkTables(allTbl,restrTbl, checkHandle) if checkHandle == nil then return false end if allTbl ~= nil and restrTbl ~= nil then if #allTbl > 0 then if isAllIdent(allTbl[1]) then if #restrTbl > 0 then if isAllIdent(restrTbl[1]) then return true end end for i,v in ipairs(restrTbl) do if checkHandle.Name == v then return false end end return true elseif isAllIdent(restrTbl[1]) then if #allTbl > 0 then if isAllIdent(allTbl[1]) then return true end end for i,v in ipairs(allTbl) do if checkHandle.Name == v then return true end end return false else local allowed = false for i,v in ipairs(allTbl) do if checkHandle.Name == v then allowed = true break end end for i,v in ipairs(restrTbl) do if checkHandle.Name == v then allowed = false break end end return allowed end end end return true end function isAllowedShip(shipClass) return checkTables(allowedShips,restrictedShips,shipClass) end function isAllowedWeapon(weaponClass) return checkTables(allowedWeapons,restrictedWeapons,weaponClass) end function getProgressString() local progressString = "Zooming" if zoomingIn then progressString = progressString .. " in:" elseif zoomingOut then progressString = progressString .. " out:" elseif zoomedIn then progressString = "Zoomed in:" elseif zoomedOut then progressString = "Zoomed out:" else progressString = "Zoomed:" end return progressString end function handleControls() if zoomingIn or zoomedIn then if currentProgr > 0 then local tempSensValue = sensitivity * 100 / currentProgr if tempSensValue <= 1 then local ci = ba.getControlInfo() ci.Pitch = ci.Pitch * tempSensValue ci.Heading = ci.Heading * tempSensValue ci.Bank = ci.Bank * tempSensValue end end end end function isAllowedToZoom() local allowedShip = isAllowedShip(hv.Player.Class) local allowedWeapon = true local primWeaponBank = hv.Player.PrimaryBanks if not linkedZoom and primWeaponBank.Linked then allowedWeapon = false else for i=0, #primWeaponBank do local v = primWeaponBank[i] if v.Armed then if isAllowedWeapon(tb.WeaponClasses[v.WeaponClass.Name]) then allowedWeapon = true break else allowedWeapon = false end end end if allowedWeapon then local secWeaponBank = hv.Player.SecondaryBanks for i=0, #secWeaponBank do local v = secWeaponBank[i] if v.Armed then if isAllowedWeapon(tb.WeaponClasses[v.WeaponClass.Name]) then allowedWeapon = true break else allowedWeapon = false end end end end end return allowedShip and allowedWeapon end function zoomIn() if not cameraSet then if #gr.Cameras > 0 then cam = gr.Cameras[1] end end if not zooming then if hv.Player:isValid() then if cam:isValid() then if isAllowedToZoom() then if currentProgr > 0 and currentProgr < 100 then stepWidth = width / currentProgr -- Setting the stepWidth in case the zoom may not have been completed end zoomEndProgress = 100 zooming = true zoomingIn = true zoomedIn = false zoomedOut = false zoomingOut = false if not defaultZoomSet then normalFOV = cam.FOV defaultZoomSet = true end zoom = normalFOV * zoomValue ba.setControlMode(LUA_FULL_CONTROLS) cam:setFOV(zoom,transitionTime,transitionTime / 2,transitionTime / 4) end end end end end function zoomOut() if zooming and not zoomOutOverride then if hv.Player:isValid() then if cam:isValid() then stepWidth = width / 100 zoomingIn = false zoomingOut = true zoomedIn = false zoomedOut = false if currentProgr > 0 then zoomEndProgress = currentProgr -- Save the progress we made as we begin to zoom back end cam:setFOV(normalFOV,transitionTime,transitionTime / 2,transitionTime / 4) ba.setControlMode(NORMAL_CONTROLS) fredOverride = false end end end end function drawProgress() progressString = getProgressString() local stringWidth = gr.getStringWidth(progressString); gr.drawString(progressString,30,70) local realOffset_x = offset_x + stringWidth + 10 gr.drawRectangle(realOffset_x, offset_y,realOffset_x + width, offset_y + heigth, zoomedIn) local frameTime = ba.getFrametime() local progressLineOffset_x = realOffset_x + stepWidth * currentProgr gr.drawLine(progressLineOffset_x, offset_y, progressLineOffset_x, offset_y + heigth) if not isAllowedToZoom() and not zoomOutOverride then if zoomingIn or zoomedIn then zoomOut() zoomOutOverride = true end end local thisFrameProg = (frameTime / transitionTime) * zoomEndProgress if zoomingIn then currentProgr = currentProgr + thisFrameProg if currentProgr >= 100 then currentProgr = 100 zoomingIn = false zoomedIn = true end elseif zoomingOut then currentProgr = currentProgr - thisFrameProg if currentProgr <= 0 then currentProgr = 0 zoomOutOverride = false zoomedOut = true zoomingOut = false zooming = false end end end local function init() if useConfig then readConfig() -- read the config file if exists end end local function initVars() -- Some things to tell the script to do something and some default values runZoomScript = false useConfig = true zoomValue = 0.1 normalFOV = 0.75 transitionTime = 2 zooming = false defaultZoomSet = false cameraSet = false configFile = "data/config/zoom_config.cfg" zoomOutOverride = false linkedZoom = true zoomKey = "d" zoomLockKey = nil fredOverride=false lockedZoom = false -- Setting the values to be used in the $On Frame: hook currentProgr = 0 zoomEndProgress = 100 zoomingIn = false zoomedIn = false zoomingOut = false zoomedOut = true -- Constants for drawing the progress offset_x = 30 offset_y = 70 heigth = 8 width = 80 stepWidth = width / 100 -- Settings for the sensitivity sensitivity = 0.25 -- The camera which is used for zooming (is initialized in the first $Key Pressed: hook) cam = nil -- Tables that hold the allowe/restricted informations -- Ships allowedShips = {"**all**"} tempAllowedShip = {} restrictedShips = {} tempRestrictedShip = {} -- Weapons allowedWeapons = {"**all**"} tempAllowedWeapon = {} restrictedWeapons = {} tempRestrictedWeapon = {} end -- Initialize the global variables initVars() -- Initialize the rest init() ] $Application: FS2_Open $On Mission Start: [ if not runZoomScript then runZoomScript = true end ] $On Mission End: [ if runZoomScript then runZoomScript = false if defaultZoomSet and cam:isValid() then cam:setFOV(normalFOV) -- Resetting the FOV in case we have not zoomed out completely end removeTemps() end ] $On Frame: [ if runZoomScript then if zooming then handleControls() drawProgress() end end ] $On Key Pressed: [[zoom_KeyDn.lua]] $On Key Released: [[zoom_KeyUp.lua]] #End
Then create the file zoom_KeyDn.lua and zoom_KeyUp.lua in your data/scripts directory and paste the following into then:
zoom_KeyDn.lua:
if runZoomScript and not fredOverride then if hv.Key:lower() == zoomLockKey:lower() then if lockedZoom then lockedZoom = false zoomOut() else lockedZoom = true zoomIn() end elseif hv.Key:lower() == zoomKey:lower() then zoomIn() end end
zoom_KeyUp.lua:
if runZoomScript and not fredOverride then if not lockedZoom then if hv.Key:lower() == zoomKey:lower() then zoomOut() end end end
After this create a file named zoom_config.cfg in your data/config directory and paste the following text into it:
-- Setting standart values Zoom Factor: 0.1 Transition Time: 2 Sensitivity: 0.25 Linked Zoom: YES Key: d Zoom Lock Key: Alt-d -- Setting ship class options Allowed Ship Class: **all** -- Setting weapon class options Allowed Weapon Class: **all**