Add BindAid
This commit is contained in:
322
BindAid/Contents/mods/BindAid/media/lua/client/ClientKeys.lua
Normal file
322
BindAid/Contents/mods/BindAid/media/lua/client/ClientKeys.lua
Normal file
@@ -0,0 +1,322 @@
|
||||
local keyman = require("KeybindManager")
|
||||
local conf = require("BindAidConfig")
|
||||
------------------------------------------
|
||||
-- ModKey Overrides -- Client
|
||||
--- All of the override functions ModKey Supports
|
||||
------------------------------------------
|
||||
|
||||
local overrides = {}
|
||||
|
||||
-- We want the LAST references to all of this
|
||||
overrides.onStart = function()
|
||||
-- Don't do this if disabled
|
||||
if not conf.Local.keyinputOptimize then return end
|
||||
------------------------------------------
|
||||
-- ISHotbar
|
||||
---- "All hotbar keys"
|
||||
------------------------------------------
|
||||
local _ISHotbar_onKeyStartPressed = ISHotbar.onKeyStartPressed
|
||||
local _ISHotbar_onKeyPressed = ISHotbar.onKeyPressed
|
||||
local _ISHotbar_onKeyKeepPressed = ISHotbar.onKeyKeepPressed
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISHotbar_onKeyStartPressed)
|
||||
Events.OnKeyKeepPressed.Remove(_ISHotbar_onKeyKeepPressed)
|
||||
Events.OnKeyPressed.Remove(_ISHotbar_onKeyPressed)
|
||||
|
||||
-- we need to get all of the keys that start with "Hotbar"
|
||||
local hotbars = {}
|
||||
for _,v in ipairs(keyBinding) do
|
||||
if luautils.stringStarts(v.value, "Hotbar ") then
|
||||
hotbars[#hotbars+1] = v.value
|
||||
end
|
||||
end
|
||||
for _,v in ipairs(hotbars) do
|
||||
keyman.addKeyEvents(v, {
|
||||
["OnKeyStartPressed"] = _ISHotbar_onKeyStartPressed,
|
||||
["OnKeyKeepPressed"] = _ISHotbar_onKeyKeepPressed,
|
||||
["OnKeyPressed"] = _ISHotbar_onKeyPressed
|
||||
})
|
||||
end
|
||||
hotbars = nil
|
||||
|
||||
------------------------------------------
|
||||
-- ISVehicleMenu
|
||||
---- "VehicleMechanics"
|
||||
---- "StartVehicleEngine"
|
||||
---- "VehicleHeater"
|
||||
---- "VehicleHorn"
|
||||
---- "VehicleSwitchSeat"
|
||||
------------------------------------------
|
||||
local _ISVehicleMenu_onKeyPressed = ISVehicleMenu.onKeyPressed
|
||||
local _ISVehicleMenu_onKeyStartPressed = ISVehicleMenu.onKeyStartPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISVehicleMenu_onKeyPressed)
|
||||
Events.OnKeyStartPressed.Remove(_ISVehicleMenu_onKeyStartPressed)
|
||||
|
||||
keyman.addKeyEvents("VehicleMechanics", {
|
||||
["OnKeyPressed"] = _ISVehicleMenu_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("StartVehicleEngine", {
|
||||
["OnKeyPressed"] = _ISVehicleMenu_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("VehicleHeater", {
|
||||
["OnKeyPressed"] = _ISVehicleMenu_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("VehicleHorn", {
|
||||
["OnKeyPressed"] = _ISVehicleMenu_onKeyPressed,
|
||||
["OnKeyStartPressed"] = _ISVehicleMenu_onKeyStartPressed
|
||||
})
|
||||
keyman.addKeyEvents("VehicleSwitchSeat", {
|
||||
["OnKeyStartPressed"] = _ISVehicleMenu_onKeyStartPressed
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISWorldMap
|
||||
---- "Map"
|
||||
------------------------------------------
|
||||
local _ISWorldMap_onKeyStartPressed = ISWorldMap.onKeyStartPressed
|
||||
local _ISWorldMap_onKeyKeepPressed = ISWorldMap.onKeyKeepPressed
|
||||
local _ISWorldMap_onKeyReleased = ISWorldMap.onKeyReleased
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISWorldMap_onKeyStartPressed)
|
||||
Events.OnKeyKeepPressed.Remove(_ISWorldMap_onKeyKeepPressed)
|
||||
Events.OnKeyPressed.Remove(_ISWorldMap_onKeyReleased)
|
||||
|
||||
keyman.addKeyEvents("Map", {
|
||||
["OnKeyStartPressed"] = _ISWorldMap_onKeyStartPressed,
|
||||
["OnKeyKeepPressed"] = _ISWorldMap_onKeyKeepPressed,
|
||||
["OnKeyPressed"] = _ISWorldMap_onKeyReleased
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISLightSourceRadialMenu
|
||||
---- "Equip/Turn On/Off Light Source"
|
||||
------------------------------------------
|
||||
local _ISLightSourceRadialMenu_onKeyPressed = ISLightSourceRadialMenu.onKeyPressed
|
||||
local _ISLightSourceRadialMenu_onKeyRepeat = ISLightSourceRadialMenu.onKeyRepeat
|
||||
local _ISLightSourceRadialMenu_onKeyReleased = ISLightSourceRadialMenu.onKeyReleased
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISLightSourceRadialMenu_onKeyPressed)
|
||||
Events.OnKeyKeepPressed.Remove(_ISLightSourceRadialMenu_onKeyRepeat)
|
||||
Events.OnKeyPressed.Remove(_ISLightSourceRadialMenu_onKeyReleased)
|
||||
|
||||
keyman.addKeyEvents("Equip/Turn On/Off Light Source", {
|
||||
["OnKeyStartPressed"] = _ISLightSourceRadialMenu_onKeyPressed,
|
||||
["OnKeyKeepPressed"] = _ISLightSourceRadialMenu_onKeyRepeat,
|
||||
["OnKeyPressed"] = _ISLightSourceRadialMenu_onKeyReleased
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISInventoryPage
|
||||
---- "Toggle Inventory"
|
||||
------------------------------------------
|
||||
local _ISInventoryPage_onKeyPressed = ISInventoryPage.onKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISInventoryPage_onKeyPressed)
|
||||
|
||||
keyman.addKeyEvents("Toggle Inventory", {
|
||||
["OnKeyPressed"] = _ISInventoryPage_onKeyPressed
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISFPS
|
||||
---- "Display FPS"
|
||||
------------------------------------------
|
||||
local _ISFPS_onKeyPressed = ISFPS.onKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISFPS_onKeyPressed)
|
||||
|
||||
keyman.addKeyEvents("Display FPS", {
|
||||
["OnKeyPressed"] = _ISFPS_onKeyPressed
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISUIHandler
|
||||
---- "VehicleRadialMenu"
|
||||
---- "Toggle UI"
|
||||
---- "Show Ping"
|
||||
------------------------------------------
|
||||
local _ISUIHandler_onKeyStartPressed = ISUIHandler.onKeyStartPressed
|
||||
local _ISUIHandler_onKeyPressed = ISUIHandler.onKeyPressed
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISUIHandler_onKeyStartPressed)
|
||||
Events.OnKeyPressed.Remove(_ISUIHandler_onKeyPressed)
|
||||
|
||||
keyman.addKeyEvents("Toggle UI", {
|
||||
["OnKeyStartPressed"] = _ISUIHandler_onKeyStartPressed,
|
||||
["OnKeyPressed"] = _ISUIHandler_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("VehicleRadialMenu", {
|
||||
["OnKeyStartPressed"] = _ISUIHandler_onKeyStartPressed,
|
||||
["OnKeyPressed"] = _ISUIHandler_onKeyPressed
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISCraftingUI
|
||||
---- "Crafting UI"
|
||||
------------------------------------------
|
||||
local _ISCraftingUI_onPressKey = ISCraftingUI.onPressKey
|
||||
|
||||
Events.OnCustomUIKey.Remove(_ISCraftingUI_onPressKey)
|
||||
|
||||
keyman.addKeyEvents("Crafting UI", {
|
||||
["OnCustomUIKey"] = _ISCraftingUI_onPressKey
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISSafetyUI
|
||||
---- "Toggle Safety"
|
||||
------------------------------------------
|
||||
local _ISSafetyUI_onKeyPressed = ISSafetyUI.onKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISSafetyUI_onKeyPressed)
|
||||
|
||||
if isClient() and getServerOptions():getBoolean("SafetySystem") then
|
||||
keyman.addKeyEvents("Toggle Safety", {
|
||||
["OnKeyPressed"] = _ISSafetyUI_onKeyPressed
|
||||
})
|
||||
end
|
||||
|
||||
------------------------------------------
|
||||
-- ISFirearmRadialMenu
|
||||
---- "ReloadWeapon"
|
||||
------------------------------------------
|
||||
local _ISFirearmRadialMenu_onKeyPressed = ISFirearmRadialMenu.onKeyPressed
|
||||
local _ISFirearmRadialMenu_onKeyRepeat = ISFirearmRadialMenu.onKeyRepeat
|
||||
local _ISFirearmRadialMenu_onKeyReleased = ISFirearmRadialMenu.onKeyReleased
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISFirearmRadialMenu_onKeyPressed)
|
||||
Events.OnKeyKeepPressed.Remove(_ISFirearmRadialMenu_onKeyRepeat)
|
||||
Events.OnKeyPressed.Remove(_ISFirearmRadialMenu_onKeyReleased)
|
||||
|
||||
keyman.addKeyEvents("ReloadWeapon", {
|
||||
["OnKeyStartPressed"] = _ISFirearmRadialMenu_onKeyPressed,
|
||||
["OnKeyKeepPressed"] = _ISFirearmRadialMenu_onKeyRepeat,
|
||||
["OnKeyPressed"] = _ISFirearmRadialMenu_onKeyReleased
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISMoveableInfoWindow
|
||||
---- "Toggle Moveable Panel Mode"
|
||||
------------------------------------------
|
||||
local _ISMoveableInfoWindow_moveablePanelModeKey = ISMoveableInfoWindow.moveablePanelModeKey
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISMoveableInfoWindow_moveablePanelModeKey)
|
||||
|
||||
keyman.addKeyEvents("Toggle Moveable Panel Mode", {
|
||||
["OnKeyPressed"] = _ISMoveableInfoWindow_moveablePanelModeKey
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISEmoteRadialMenu
|
||||
---- "Emote"
|
||||
---- "Shout"
|
||||
------------------------------------------
|
||||
local _ISEmoteRadialMenu_onKeyReleased = ISEmoteRadialMenu.onKeyReleased
|
||||
local _ISEmoteRadialMenu_onKeyPressed = ISEmoteRadialMenu.onKeyPressed
|
||||
local _ISEmoteRadialMenu_onKeyRepeat = ISEmoteRadialMenu.onKeyRepeat
|
||||
|
||||
Events.OnKeyStartPressed.Remove(_ISEmoteRadialMenu_onKeyPressed)
|
||||
Events.OnKeyKeepPressed.Remove(_ISEmoteRadialMenu_onKeyRepeat)
|
||||
Events.OnKeyPressed.Remove(_ISEmoteRadialMenu_onKeyReleased)
|
||||
|
||||
keyman.addKeyEvents("Emote", {
|
||||
["OnKeyStartPressed"] = _ISEmoteRadialMenu_onKeyPressed,
|
||||
["OnKeyKeepPressed"] = _ISEmoteRadialMenu_onKeyRepeat,
|
||||
["OnKeyPressed"] = _ISEmoteRadialMenu_onKeyReleased
|
||||
})
|
||||
keyman.addKeyEvents("Shout", {
|
||||
["OnKeyStartPressed"] = _ISEmoteRadialMenu_onKeyPressed,
|
||||
["OnKeyKeepPressed"] = _ISEmoteRadialMenu_onKeyRepeat,
|
||||
["OnKeyPressed"] = _ISEmoteRadialMenu_onKeyReleased
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISSearchManager
|
||||
---- "Toggle Search Mode"
|
||||
------------------------------------------
|
||||
local _ISSearchManager_handleKeyPressed = ISSearchManager.handleKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISSearchManager_handleKeyPressed)
|
||||
|
||||
keyman.addKeyEvents("Toggle Search Mode", {
|
||||
["OnKeyPressed"] = _ISSearchManager_handleKeyPressed
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISChat
|
||||
---- "Toggle chat"
|
||||
---- "Alt toggle chat"
|
||||
------------------------------------------
|
||||
local _ISChat_onToggleChatBox = ISChat.onToggleChatBox
|
||||
--local _ISChat_onKeyKeepPressed = ISChat.onKeyKeepPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISChat_onToggleChatBox)
|
||||
|
||||
keyman.addKeyEvents("Toggle chat", {
|
||||
["OnKeyPressed"] = _ISChat_onToggleChatBox
|
||||
})
|
||||
keyman.addKeyEvents("Alt toggle chat", {
|
||||
["OnKeyPressed"] = _ISChat_onToggleChatBox
|
||||
})
|
||||
keyman.addKeyEvents("Switch chat stream", {
|
||||
["OnKeyPressed"] = _ISChat_onToggleChatBox
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- Escape!
|
||||
---- "Main Menu"
|
||||
------------------------------------------
|
||||
local _ToggleEscapeMenu = ToggleEscapeMenu
|
||||
|
||||
Events.OnKeyPressed.Remove(_ToggleEscapeMenu)
|
||||
|
||||
keyman.addKeyEvents("Main Menu", {
|
||||
["OnKeyPressed"] = _ToggleEscapeMenu
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- SpeedControlsHandler
|
||||
---- "Pause"
|
||||
---- "Normal Speed"
|
||||
---- "Fast Forward x1"
|
||||
---- "Fast Forward x2"
|
||||
---- "Fast Forward x3"
|
||||
------------------------------------------
|
||||
local _SpeedControlsHandler_onKeyPressed = SpeedControlsHandler.onKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_SpeedControlsHandler_onKeyPressed)
|
||||
|
||||
if not isClient() then
|
||||
keyman.addKeyEvents("Pause", {
|
||||
["OnKeyPressed"] = _SpeedControlsHandler_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("Normal Speed", {
|
||||
["OnKeyPressed"] = _SpeedControlsHandler_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("Fast Forward x1", {
|
||||
["OnKeyPressed"] = _SpeedControlsHandler_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("Fast Forward x2", {
|
||||
["OnKeyPressed"] = _SpeedControlsHandler_onKeyPressed
|
||||
})
|
||||
keyman.addKeyEvents("Fast Forward x3", {
|
||||
["OnKeyPressed"] = _SpeedControlsHandler_onKeyPressed
|
||||
})
|
||||
end
|
||||
|
||||
------------------------------------------
|
||||
-- SurvivalGuideManager
|
||||
---- "Toggle Survival Guide"
|
||||
------------------------------------------
|
||||
local _SurvivalGuideManager_onKeyPressed = SurvivalGuideManager.onKeyPressed
|
||||
|
||||
Events.OnKeyPressed.Remove(_SurvivalGuideManager_onKeyPressed)
|
||||
|
||||
keyman.addKeyEvents("Toggle Survival Guide", {
|
||||
["OnKeyPressed"] = _SurvivalGuideManager_onKeyPressed
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
return overrides
|
||||
260
BindAid/Contents/mods/BindAid/media/lua/client/Mouse.lua
Normal file
260
BindAid/Contents/mods/BindAid/media/lua/client/Mouse.lua
Normal file
@@ -0,0 +1,260 @@
|
||||
local conf = require('BindAidConfig')
|
||||
|
||||
local mouse = {
|
||||
curMouseX = 0,
|
||||
curMouseY = 0,
|
||||
prevMouseX = 0,
|
||||
prevMouseY = 0,
|
||||
hideDelta = 1,
|
||||
hiding = false,
|
||||
shouldHide = true,
|
||||
hideDelay = 10, -- seconds
|
||||
mouseButtons = 3,
|
||||
buttonState = {},
|
||||
buttonData = {}
|
||||
}
|
||||
|
||||
mouse._onTickMouseHide = function()
|
||||
-- Get our position
|
||||
mouse.curMouseX = mouse.getX()
|
||||
mouse.curMouseY = mouse.getY()
|
||||
|
||||
-- if our position is the same as last frame
|
||||
---- Since we want this to work on everthing; we have to check this manually
|
||||
if (mouse.curMouseX == mouse.prevMouseX and mouse.curMouseY == mouse.prevMouseY) then
|
||||
-- if we are already hiding, do
|
||||
if mouse.hiding then
|
||||
mouse.setCursorVisible(false)
|
||||
else
|
||||
-- otherwise, increment
|
||||
mouse.hideDelta = mouse.hideDelta + 1
|
||||
-- We changed hideDelay on start to be in seconds
|
||||
if mouse.hideDelta >= mouse.hideDelay then
|
||||
mouse.hiding = true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Reset
|
||||
mouse.hiding = false
|
||||
mouse.hideDelta = 1
|
||||
mouse.prevMouseX = mouse.curMouseX
|
||||
mouse.prevMouseY = mouse.curMouseY
|
||||
end
|
||||
end
|
||||
|
||||
mouse.buttonEvents = {
|
||||
["OnMouseMiddleDown"] = {},
|
||||
["OnMouse4Down"] = {},
|
||||
["OnMouse5Down"] = {},
|
||||
["OnMouse6Down"] = {},
|
||||
["OnMouse7Down"] = {},
|
||||
["OnMouse8Down"] = {},
|
||||
["OnMouse9Down"] = {},
|
||||
["OnMouse10Down"] = {},
|
||||
["OnMouse11Down"] = {},
|
||||
["OnMouse12Down"] = {},
|
||||
|
||||
["OnMouseMiddleHold"] = {},
|
||||
["OnMouse4Hold"] = {},
|
||||
["OnMouse5Hold"] = {},
|
||||
["OnMouse6Hold"] = {},
|
||||
["OnMouse7Hold"] = {},
|
||||
["OnMouse8Hold"] = {},
|
||||
["OnMouse9Hold"] = {},
|
||||
["OnMouse10Hold"] = {},
|
||||
["OnMouse11Hold"] = {},
|
||||
["OnMouse12Hold"] = {},
|
||||
|
||||
["OnMouseMiddleUp"] = {},
|
||||
["OnMouse4Up"] = {},
|
||||
["OnMouse5Up"] = {},
|
||||
["OnMouse6Up"] = {},
|
||||
["OnMouse7Up"] = {},
|
||||
["OnMouse8Up"] = {},
|
||||
["OnMouse9Up"] = {},
|
||||
["OnMouse10Up"] = {},
|
||||
["OnMouse11Up"] = {},
|
||||
["OnMouse12Up"] = {},
|
||||
}
|
||||
|
||||
local _mouseDownEvents = {
|
||||
-- 0
|
||||
false, --1
|
||||
"OnMouseMiddleDown",
|
||||
"OnMouse4Down",
|
||||
"OnMouse5Down",
|
||||
"OnMouse6Down",
|
||||
"OnMouse7Down",
|
||||
"OnMouse8Down",
|
||||
"OnMouse9Down",
|
||||
"OnMouse10Down",
|
||||
"OnMouse11Down",
|
||||
"OnMouse12Down"
|
||||
}
|
||||
|
||||
local _mouseHoldEvents = {
|
||||
-- 0
|
||||
false, --1
|
||||
"OnMouseMiddleHold",
|
||||
"OnMouse4Hold",
|
||||
"OnMouse5Hold",
|
||||
"OnMouse6Hold",
|
||||
"OnMouse7Hold",
|
||||
"OnMouse8Hold",
|
||||
"OnMouse9Hold",
|
||||
"OnMouse10Hold",
|
||||
"OnMouse11Hold",
|
||||
"OnMouse12Hold"
|
||||
}
|
||||
|
||||
local _mouseUpEvents = {
|
||||
-- 0
|
||||
false, --1
|
||||
"OnMouseMiddleUp",
|
||||
"OnMouse4Up",
|
||||
"OnMouse5Up",
|
||||
"OnMouse6Up",
|
||||
"OnMouse7Up",
|
||||
"OnMouse8Up",
|
||||
"OnMouse9Up",
|
||||
"OnMouse10Up",
|
||||
"OnMouse11Up",
|
||||
"OnMouse12Up"
|
||||
}
|
||||
|
||||
local addTo = function(key, data, input)
|
||||
local o = data[key] or {}
|
||||
o[#o+1] = input
|
||||
data[key] = o
|
||||
return data
|
||||
end
|
||||
|
||||
mouse.Add = function(data)
|
||||
for i,v in pairs(data) do
|
||||
mouse.buttonEvents = addTo(i, mouse.buttonEvents, v)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local _event -- cache
|
||||
local mouseEvent = function(button, go)
|
||||
_event = mouse.buttonData[button]
|
||||
if not _event then return end
|
||||
if _event.press then
|
||||
if go then
|
||||
_event = mouse.buttonEvents[_mouseHoldEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
else
|
||||
_event.press = false
|
||||
_event = mouse.buttonEvents[_mouseUpEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
end
|
||||
else
|
||||
if go then
|
||||
_event.press = true
|
||||
_event = mouse.buttonEvents[_mouseDownEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mouseEmulate = function(button, go)
|
||||
_event = mouse.buttonData[button]
|
||||
if not _event then return end
|
||||
if _event.press then
|
||||
if go then
|
||||
-- hold
|
||||
triggerEvent("OnKeyKeepPressed", _event.key)
|
||||
else
|
||||
-- up
|
||||
triggerEvent("OnKeyPressed", _event.key)
|
||||
_event.press = false
|
||||
end
|
||||
else
|
||||
if go then
|
||||
-- down
|
||||
triggerEvent("OnKeyStartPressed", _event.key)
|
||||
_event.press = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mouseBoth = function(button, go)
|
||||
_event = mouse.buttonData[button]
|
||||
if not _event then return end
|
||||
if _event.press then
|
||||
if go then
|
||||
-- hold
|
||||
triggerEvent("OnKeyKeepPressed", _event.key)
|
||||
_event = mouse.buttonEvents[_mouseHoldEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
else
|
||||
-- up
|
||||
triggerEvent("OnKeyPressed", _event.key)
|
||||
_event.press = false
|
||||
_event = mouse.buttonEvents[_mouseUpEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
end
|
||||
else
|
||||
if go then
|
||||
-- down
|
||||
triggerEvent("OnKeyStartPressed", _event.key)
|
||||
_event.press = true
|
||||
_event = mouse.buttonEvents[_mouseDownEvents[button]]
|
||||
for i=1, #_event do
|
||||
_event[i](mouse.getX(), mouse.getY())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mouse.buildButtonData = function()
|
||||
mouse.buttonData = {}
|
||||
local buttons = { false, } -- 1
|
||||
for _,v in ipairs(keyBinding) do
|
||||
if luautils.stringStarts(v.value, "Bindaid_MouseKey") then
|
||||
buttons[#buttons+1] = getCore():getKey(v.value)
|
||||
end
|
||||
end
|
||||
for i=2, mouse.mouseButtons do
|
||||
local key = (buttons[i] and buttons[i] ~= 0 and buttons[i]) or nil
|
||||
mouse.buttonData[i] = {
|
||||
func = (key and conf.Conf.emulateAndEvent and mouseBoth) or (key and mouseEmulate) or mouseEvent,
|
||||
key = key
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
mouse._onClickButtonHandler = function()
|
||||
for i=2, mouse.mouseButtons do
|
||||
mouse.buttonData[i].func(i, mouse.isButtonDown(i))
|
||||
end
|
||||
end
|
||||
|
||||
mouse._onStart = function()
|
||||
mouse.buildButtonData()
|
||||
if conf.Local.mouseButtonSupport then
|
||||
Events.OnTick.Add(mouse._onClickButtonHandler)
|
||||
end
|
||||
end
|
||||
|
||||
mouse._onBoot = function()
|
||||
-- Since these are static functions, let's cache them
|
||||
mouse.getX = Mouse.getX
|
||||
mouse.getY = Mouse.getY
|
||||
mouse.setCursorVisible = Mouse.setCursorVisible
|
||||
mouse.isButtonDown = Mouse.isButtonDown
|
||||
mouse.isButtonDownUICheck = Mouse.isButtonDownUICheck
|
||||
end
|
||||
|
||||
return mouse
|
||||
@@ -0,0 +1,25 @@
|
||||
-- These fixes are included in other mods, so this prevents from multiple runnings
|
||||
if not Exterminator then
|
||||
Exterminator = {}
|
||||
end
|
||||
|
||||
if not Exterminator.onEnterFromGame then
|
||||
-- Protects Against a Known Options Bug
|
||||
-- Thanks Burryaga!
|
||||
Exterminator.onEnterFromGame = MainScreen.onEnterFromGame
|
||||
function MainScreen:onEnterFromGame()
|
||||
Exterminator.onEnterFromGame(self)
|
||||
-- Guarantee that when you ENTER the options menu, the game does not think you've already changed your damn options.
|
||||
MainOptions.instance.gameOptions.changed = false
|
||||
end
|
||||
end
|
||||
|
||||
if not Exterminator.MainOptions_apply then
|
||||
-- Adds an event when Game Options are changed
|
||||
LuaEventManager.AddEvent("OnSettingsApply")
|
||||
Exterminator.MainOptions_apply = MainOptions.apply
|
||||
function MainOptions:apply(closeAfter)
|
||||
Exterminator.MainOptions_apply(self, closeAfter)
|
||||
triggerEvent("OnSettingsApply")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,83 @@
|
||||
------------------------------------------
|
||||
-- BindAid Overrides -- Server
|
||||
--- All of the override functions BindAid Supports
|
||||
------------------------------------------
|
||||
if not (isClient() or not isServer()) then return end
|
||||
|
||||
local keyman = require('KeybindManager')
|
||||
local conf = require("BindAidConfig")
|
||||
|
||||
local overrides = {}
|
||||
|
||||
-- We want the LAST references to all of this
|
||||
overrides.onStart = function()
|
||||
-- Don't do this if disabled
|
||||
if not conf.Local.keyinputOptimize then return end
|
||||
------------------------------------------
|
||||
-- ItemBindingHandler
|
||||
---- "Equip/Turn On/Off Light Source"
|
||||
---- "ToggleVehicleHeadlights"
|
||||
------- This one is not actually an Event, but is called by ISLightSourceRadialMenu
|
||||
------- This is here to catch the headlights mostly
|
||||
------------------------------------------
|
||||
-- local _ItemBindingHandler_onKeyPressed = ItemBindingHandler.onKeyPressed
|
||||
-- ItemBindingHandler.onKeyPressed = function(key)
|
||||
-- if not keyman.isModKeyDown() then
|
||||
-- _ItemBindingHandler_onKeyPressed(key)
|
||||
-- end
|
||||
-- end
|
||||
|
||||
------------------------------------------
|
||||
-- xpUpdate
|
||||
---- "Toggle Skill Panel"
|
||||
---- "Toggle Health Panel"
|
||||
---- "Toggle Info Panel"
|
||||
---- "Toggle Clothing Protection Panel"
|
||||
------------------------------------------
|
||||
local _xpUpdate_displayCharacterInfo = xpUpdate.displayCharacterInfo
|
||||
|
||||
Events.OnKeyPressed.Remove(_xpUpdate_displayCharacterInfo)
|
||||
|
||||
keyman.addKeyEvents("Toggle Skill Panel", {
|
||||
["OnKeyPressed"] = _xpUpdate_displayCharacterInfo
|
||||
})
|
||||
keyman.addKeyEvents("Toggle Health Panel", {
|
||||
["OnKeyPressed"] = _xpUpdate_displayCharacterInfo
|
||||
})
|
||||
keyman.addKeyEvents("Toggle Info Panel", {
|
||||
["OnKeyPressed"] = _xpUpdate_displayCharacterInfo
|
||||
})
|
||||
keyman.addKeyEvents("Toggle Clothing Protection Panel", {
|
||||
["OnKeyPressed"] = _xpUpdate_displayCharacterInfo
|
||||
})
|
||||
|
||||
------------------------------------------
|
||||
-- ISMoveableCursor
|
||||
---- "Run"
|
||||
---- "Interact"
|
||||
---- "Toggle mode"
|
||||
------------------------------------------
|
||||
local _ISMoveableCursor_exitCursorKey = ISMoveableCursor.exitCursorKey
|
||||
local _ISMoveableCursor_changeModeKey = ISMoveableCursor.changeModeKey
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISMoveableCursor_exitCursorKey)
|
||||
Events.OnKeyKeepPressed.Remove(_ISMoveableCursor_exitCursorKey)
|
||||
|
||||
keyman.addKeyEvents("Run", {
|
||||
["OnKeyPressed"] = _ISMoveableCursor_exitCursorKey,
|
||||
["OnKeyKeepPressed"] = _ISMoveableCursor_exitCursorKey,
|
||||
})
|
||||
keyman.addKeyEvents("Interact", {
|
||||
["OnKeyPressed"] = _ISMoveableCursor_exitCursorKey,
|
||||
["OnKeyKeepPressed"] = _ISMoveableCursor_exitCursorKey,
|
||||
})
|
||||
|
||||
Events.OnKeyPressed.Remove(_ISMoveableCursor_changeModeKey)
|
||||
|
||||
keyman.addKeyEvents("Toggle mode", {
|
||||
["OnKeyPressed"] = _ISMoveableCursor_changeModeKey
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
return overrides
|
||||
84
BindAid/Contents/mods/BindAid/media/lua/shared/BindAid.lua
Normal file
84
BindAid/Contents/mods/BindAid/media/lua/shared/BindAid.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
-- Only load in Single Player or if a Multiplayer client
|
||||
if not (isClient() or not isServer()) then return end
|
||||
|
||||
local conf = require('BindAidConfig')
|
||||
local keyman = require('KeybindManager')
|
||||
|
||||
local mouse -- client, loaded onBoot
|
||||
|
||||
local localOverrides -- client, loaded onStart
|
||||
local serverOverrides -- server, loaded onStart
|
||||
|
||||
local autoHideTimes = {
|
||||
1,2,5,10,30,60
|
||||
}
|
||||
|
||||
local onBoot = function()
|
||||
mouse = require('Mouse')
|
||||
|
||||
-- Added to Sync the options
|
||||
conf.OnApplyOptions = function()
|
||||
mouse.hideDelay = (autoHideTimes[conf.Local.autohideMouseTime] or 5) * getPerformance():getFramerate()
|
||||
mouse.mouseButtons = conf.Local.mouseButtonCount + 1
|
||||
|
||||
Events.OnTickEvenPaused.Remove(mouse._onTickMouseHide)
|
||||
Events.OnFETick.Remove(mouse._onTickMouseHide)
|
||||
|
||||
if conf.Local.autohideMouse then
|
||||
-- Do the game and the Pause
|
||||
Events.OnTickEvenPaused.Add(mouse._onTickMouseHide)
|
||||
-- Do the Main Menu
|
||||
Events.OnFETick.Add(mouse._onTickMouseHide)
|
||||
end
|
||||
end
|
||||
|
||||
conf._onBoot()
|
||||
mouse._onBoot()
|
||||
keyman._onBoot()
|
||||
|
||||
keyman.addKeybind("[Bindaid]", 'Bindaid_Modkey', Keyboard.KEY_LCONTROL)
|
||||
|
||||
if conf.Local.mouseButtonSupport then
|
||||
for i=2, mouse.mouseButtons do
|
||||
keyman.addKeybind("[Bindaid]", 'Bindaid_MouseKey_' .. tostring(i), 0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local onSettings = function()
|
||||
if conf.Local.keyinputOptimize then
|
||||
keyman.buildKeymap()
|
||||
end
|
||||
if conf.Local.mouseButtonSupport then
|
||||
mouse.buildButtonData()
|
||||
end
|
||||
end
|
||||
|
||||
-- The postStart is the last OnGameStart function that is called
|
||||
---- Will run all of the other `starts` for keys to get the latest key events
|
||||
local postStart = function()
|
||||
localOverrides.onStart()
|
||||
if serverOverrides then serverOverrides.onStart() end
|
||||
|
||||
keyman._onStart()
|
||||
mouse._onStart()
|
||||
end
|
||||
|
||||
local onStart = function()
|
||||
localOverrides = require('ClientKeys')
|
||||
serverOverrides = require('ServerKeys')
|
||||
Events.OnSettingsApply.Add(onSettings)
|
||||
-- Add the postStart function to the OnGameStart stack now
|
||||
---- This ENSURES that it is last. :)
|
||||
Events.OnGameStart.Add(postStart)
|
||||
end
|
||||
|
||||
local function BindAid()
|
||||
print(getText("UI_Init_Bindaid"))
|
||||
|
||||
Events.OnGameBoot.Add(onBoot)
|
||||
Events.OnGameStart.Add(onStart)
|
||||
end
|
||||
|
||||
BindAid()
|
||||
309
BindAid/Contents/mods/BindAid/media/lua/shared/BindAidConfig.lua
Normal file
309
BindAid/Contents/mods/BindAid/media/lua/shared/BindAidConfig.lua
Normal file
@@ -0,0 +1,309 @@
|
||||
-- Configuration Manager
|
||||
---- Made by dhert, use this however you want. :)
|
||||
-- NOTE: GIVE THIS FILE A UNIQUE SANDNAME IN YOUR MOD TO NOT OVERWRITE OTHER USES OF THIS SCRIPT!
|
||||
|
||||
---------------------
|
||||
-- Edit the "options_data" array for your settings using Mod Options syntax.
|
||||
--- Comment out the OPTIONS table in full to disable ModOptions support
|
||||
--- Do not change the OPTIONS, options_data, mod_id, mod_shortname, and mod_fullname variable names, but fill them in with your own values
|
||||
--- The options OnApplyMainMenu and OnApplyInGame will be added/overwritten later, do not use them.
|
||||
|
||||
local OPTIONS = {
|
||||
options_data = {
|
||||
autohideMouse = {
|
||||
name = "UI_ModOptions_Bindaid_autohideMouse",
|
||||
default = true,
|
||||
},
|
||||
autohideMouseTime = {
|
||||
"1", "2", "5", "10", "30", "60",
|
||||
|
||||
name = "UI_ModOptions_Bindaid_autohideMouseTime",
|
||||
default = 4,
|
||||
},
|
||||
mouseButtonSupport = {
|
||||
name = "UI_ModOptions_Bindaid_mouseButtonSupport",
|
||||
default = true,
|
||||
},
|
||||
mouseButtonCount = {
|
||||
"1", "2", "3", "4", "5", "6", "7", "8", "9", "10",
|
||||
|
||||
name = "UI_ModOptions_Bindaid_mouseButtonCount",
|
||||
default = 3
|
||||
},
|
||||
emulateAndEvent = {
|
||||
name = "UI_ModOptions_Bindaid_emulateAndEvent",
|
||||
default = false,
|
||||
},
|
||||
keyinputOptimize = {
|
||||
name = "UI_ModOptions_Bindaid_keyinputOptimize",
|
||||
default = true,
|
||||
},
|
||||
},
|
||||
mod_id = "BindAid",
|
||||
mod_shortname = "BindAid",
|
||||
mod_fullname = getText("UI_optionscreen_binding_Bindaid")
|
||||
}
|
||||
|
||||
-- Controls whether ModOptions will overwrite Sandbox Options with the same name by default.
|
||||
--- To allow Server Owners to control this, keep this as "TRUE" add the IgnoreLocalOptions option to your Sandbox Namespace (see above)
|
||||
local OVERWRITE = true
|
||||
|
||||
-- Set the name of your SandboxVariable Namespace.
|
||||
--- The "Namespace" is the group of Sandbox Variables for your mod: "SanboxVars.Namespace.Variable"
|
||||
--- You build Sanbox Variables as: "option Namespace.Variable"
|
||||
---- If you have only one Namespace:
|
||||
----- local SANDNAME = "Namespace"
|
||||
---- If you have more than one, then build a table:
|
||||
----- local SANDNAME = {"One", "Two", "etc"}
|
||||
----- Comment out to disable Sandbox Support
|
||||
--local SANDNAME = "Bindaid"
|
||||
|
||||
---------------------
|
||||
-- Additional Documentation
|
||||
---------------------
|
||||
-- This module can be used as a cache for your Sandbox Options and ModOptions
|
||||
--- Simply modify the variables above to setup your mod's Config cache.
|
||||
--- This can be placed anywhere; client, server, or shared
|
||||
--- Include this in your mod and use as:
|
||||
---- local config = require('YourConfigManagerFileNameName') -- no .lua at the end
|
||||
---- Can use this as:
|
||||
----- if config.Get("Option") then
|
||||
----- -- do something
|
||||
----- end
|
||||
----
|
||||
---- You also have access to the raw data using:
|
||||
---- config.Conf["Option"] OR config.Conf.Option
|
||||
---
|
||||
--- Defined ModOptions are made available in the config.Conf table.
|
||||
---- ModOptions that have the same name as a Sandbox options will overwrite.
|
||||
----- In your Sandbox namespace, add the option 'IgnoreLocalOptions' to allow server owners to force sync options
|
||||
----- Example:
|
||||
------ option Namespace.IgnoreLocalOptions
|
||||
------ {
|
||||
------ type = boolean, default = false,
|
||||
------ page = Namespace,
|
||||
------ translation = Namespace_IgnoreLocalOptions,
|
||||
------ }
|
||||
----- Alternatively, set the OVERWRITE option to false to only sync ModOptions and not overwrite Sandbox options
|
||||
---------------------
|
||||
----------- Don't edit below here, unless you know what you're doing. :)
|
||||
---------------------
|
||||
local Conf = {
|
||||
-- This is our main object for configuration; read from this.
|
||||
Conf = {},
|
||||
-- This is the user's configuration, only defined if Mod Options exists. Used internally, not intended to be used but left here; already synced with Conf.
|
||||
Local = nil,
|
||||
-- A function that can be defined to run when Sandbox Settings are read
|
||||
OnSandboxConfig = nil,
|
||||
-- A function that can be defined to run when settings are applied. Called ANY time that Mod Options are changed
|
||||
OnApplyOptions = nil,
|
||||
-- A function that can be defined to run when settings are applied in game
|
||||
OnApplyOptionsInGame = nil
|
||||
}
|
||||
|
||||
-- Print the available Configuration
|
||||
--- Useful for debugging
|
||||
Conf.Print = function()
|
||||
for i,v in pairs(Conf.Conf) do
|
||||
print(" " .. tostring(i) .. " = " .. tostring(v))
|
||||
end
|
||||
end
|
||||
|
||||
-- Sync Sandbox Configuration from given Namespace
|
||||
local syncSandboxConfig = function(nmspce)
|
||||
local vars = SandboxVars[nmspce]
|
||||
if not vars then
|
||||
print("Unable to find namespace: " .. nmspce)
|
||||
return false
|
||||
end
|
||||
for i,v in pairs(vars) do
|
||||
Conf.Conf[i] = v
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Sync Sandbox Configuration from Multiple Namespaces
|
||||
local syncSandboxConfigMulti = function(nmspces)
|
||||
for _,n in ipairs(nmspces) do
|
||||
syncSandboxConfig(n)
|
||||
end
|
||||
end
|
||||
|
||||
-- Syncs Sandbox and available ModOptions
|
||||
Conf.SyncConfig = function()
|
||||
-- Reset our conf object
|
||||
Conf.Conf = {}
|
||||
if SANDNAME then
|
||||
if type(SANDNAME) == "string" then
|
||||
syncSandboxConfig(SANDNAME)
|
||||
else
|
||||
syncSandboxConfigMulti(SANDNAME)
|
||||
end
|
||||
end
|
||||
|
||||
if not Conf.Conf.IgnoreLocalOptions and Conf.Local and OVERWRITE then
|
||||
-- Sync our Local configuration into our Conf data, overriding any Sandbox Options
|
||||
for i,v in pairs(Conf.Local) do
|
||||
Conf.Conf[i] = v
|
||||
end
|
||||
elseif Conf.Local then
|
||||
-- only sync options that do not exist
|
||||
for i, v in pairs(Conf.Local) do
|
||||
if Conf.Conf[i] == nil then
|
||||
Conf.Conf[i] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get configuration value from given `key`
|
||||
-- Returns default, nil if no default given
|
||||
--- @param key string
|
||||
--- @param default number|boolean|string -- optional
|
||||
--- @return number|boolean|string|nil
|
||||
Conf.Get = function(key, default)
|
||||
return (Conf.Conf[key] == nil and default) or Conf.Conf[key]
|
||||
end
|
||||
|
||||
-- Apply Mod Options in general, run the OnApplyOptions function if available
|
||||
---- ALWAYS called when ModOptions are changed
|
||||
local function applyModOptions(data)
|
||||
Conf.Local = {}
|
||||
for i,v in pairs(data.settings.options) do
|
||||
Conf.Local[i] = v
|
||||
end
|
||||
if Conf.OnApplyOptions then
|
||||
Conf.OnApplyOptions(Conf.Local)
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply Mod Options in game, run the OnApplyOptionsInGame function if available
|
||||
local function applyModOptionsGame(data)
|
||||
applyModOptions(data)
|
||||
Conf.SyncConfig()
|
||||
if Conf.OnApplyOptionsInGame then
|
||||
Conf.OnApplyOptionsInGame(Conf.Conf)
|
||||
end
|
||||
end
|
||||
|
||||
-- Function that handles ModOptions
|
||||
local modOptions = function()
|
||||
-- Add our apply event functions to the settings
|
||||
for i,_ in pairs(OPTIONS.options_data) do
|
||||
if not OPTIONS.options_data[i].tooltip then
|
||||
local name = OPTIONS.options_data[i].name
|
||||
if name then
|
||||
name = name .. "_tooltip"
|
||||
local tt = getText(name)
|
||||
if tt ~= name then -- getText returns the same string if no translation exists, so just check for that
|
||||
OPTIONS.options_data[i].tooltip = tt
|
||||
end
|
||||
end
|
||||
end
|
||||
OPTIONS.options_data[i].OnApplyMainMenu = applyModOptions
|
||||
OPTIONS.options_data[i].OnApplyInGame = applyModOptionsGame
|
||||
end
|
||||
|
||||
-- Load our stuff
|
||||
ModOptions:getInstance(OPTIONS)
|
||||
ModOptions:loadFile()
|
||||
|
||||
applyModOptions({settings = OPTIONS})
|
||||
|
||||
-- Build our Configuration
|
||||
Events.OnInitGlobalModData.Add(function()
|
||||
applyModOptionsGame({settings = OPTIONS})
|
||||
end)
|
||||
end
|
||||
|
||||
-- Add support for loading the ModOptions config file, even if ModOptions is not currently active
|
||||
local forceModOptionsConfig = function()
|
||||
-- Set our defaults
|
||||
local config = {}
|
||||
for i,v in pairs(OPTIONS.options_data) do
|
||||
config[i] = v.default
|
||||
end
|
||||
|
||||
-- Read and apply configuration from the local ini file
|
||||
local function Load()
|
||||
local file = getFileReader("mods_options.ini", false)
|
||||
local line = ""
|
||||
local found = false
|
||||
if file then
|
||||
while true do
|
||||
line = file:readLine()
|
||||
if not line then
|
||||
break
|
||||
end
|
||||
line = line:trim()
|
||||
if line ~= "" then
|
||||
local next = false
|
||||
local k = line:match('^%[([^%[%]]+)%]$')
|
||||
if k and k == OPTIONS.mod_id then
|
||||
found = true
|
||||
next = true
|
||||
elseif k and k ~= OPTIONS.mod_id then
|
||||
if found then break end -- we found the next one, so we're done
|
||||
end
|
||||
if found and not next then
|
||||
local i, v = line:match('^([%w|_]+)%s-=%s-(.+)$')
|
||||
if(i and v)then
|
||||
v = v:trim()
|
||||
i = i:trim()
|
||||
if(tonumber(v))then
|
||||
v = tonumber(v)
|
||||
elseif(v:lower() == 'true')then
|
||||
v = true
|
||||
elseif(v:lower() == 'false')then
|
||||
v = false
|
||||
else -- we only want the above
|
||||
v = nil
|
||||
end
|
||||
|
||||
config = config or {}
|
||||
-- if we failed to read from config, then keep the default
|
||||
config[i] = (v == nil and config[i]) or v
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
end
|
||||
|
||||
Load()
|
||||
|
||||
if isDebugEnabled() then
|
||||
print("Force Loading Mod Options")
|
||||
for i,v in pairs(config) do
|
||||
print(" Loaded: " .. i .. " = " .. tostring(v))
|
||||
end
|
||||
end
|
||||
|
||||
-- add condition to not do this?
|
||||
Conf.Local = config
|
||||
|
||||
Conf.SyncConfig()
|
||||
|
||||
if Conf.OnApplyOptions then
|
||||
Conf.OnApplyOptions(Conf.Local)
|
||||
end
|
||||
end
|
||||
|
||||
Conf._onBoot = function()
|
||||
-- Runs on the local client, or in singleplayer
|
||||
if isClient() or not isServer() then
|
||||
-- Add ModOptions if installed, sync Sandbox and ModOptions
|
||||
if OPTIONS and ModOptions and ModOptions.getInstance then
|
||||
modOptions()
|
||||
else
|
||||
-- No ModOptions? That's fine, just sync our defined Mod Options and Sandbox options anyways
|
||||
Events.OnInitGlobalModData.Add(forceModOptionsConfig)
|
||||
end
|
||||
else
|
||||
-- If its a server, just sync our Sandbox config
|
||||
Events.OnInitGlobalModData.Add(Conf.SyncConfig)
|
||||
end
|
||||
end
|
||||
|
||||
return Conf
|
||||
@@ -0,0 +1,234 @@
|
||||
-- Only load in Single Player or if a Multiplayer client
|
||||
if not (isClient() or not isServer()) then return end
|
||||
|
||||
-- Storage module for defining keybinds used in the game.
|
||||
local keyman = {
|
||||
-- -- keys = {
|
||||
-- [key] = {
|
||||
-- ["OnKeyPressed"] = {}
|
||||
-- ["OnKeyStartPressed"] = {},
|
||||
|
||||
-- },
|
||||
-- }
|
||||
keys = {},
|
||||
-- Functions, indexed by their keybinds
|
||||
funcs = {},
|
||||
addKeys = {}
|
||||
}
|
||||
|
||||
local conf
|
||||
|
||||
local addTo = function(key, data, input)
|
||||
local o = data[key] or {}
|
||||
o[#o+1] = input
|
||||
data[key] = o
|
||||
return data
|
||||
end
|
||||
|
||||
-- Add a function to the map by event
|
||||
--- @param keyName string
|
||||
--- @param events table
|
||||
---- events should be a table of functions, indexed by event | { ["event"]=function, ["event"]=function }
|
||||
---- valid events are "OnKeyStartPressed", "OnModKeyStartPressed", "OnKeyKeepPressed", "OnModKeyKeepPressed", "OnKeyPressed", "OnModKeyPressed"
|
||||
keyman.addKeyEvents = function(keyName, events)
|
||||
keyman.funcs = addTo(keyName, keyman.funcs, events)
|
||||
end
|
||||
|
||||
-- Add a function to the map by event
|
||||
--- @param section string
|
||||
--- @param keyName string
|
||||
--- @param default integer
|
||||
--- @param events table
|
||||
---- events should be a table of functions, indexed by event | { ["event"]=function, ["event"]=function }
|
||||
---- valid events are "OnKeyStartPressed", "OnModKeyStartPressed", "OnKeyKeepPressed", "OnModKeyKeepPressed", "OnKeyPressed", "OnModKeyPressed"
|
||||
keyman.addKeybind = function(section, keyName, default, events)
|
||||
keyman.addKeys = addTo(section, keyman.addKeys, {value=keyName, key=default or 0})
|
||||
if events then
|
||||
keyman.addKeyEvents(keyName, events)
|
||||
end
|
||||
end
|
||||
|
||||
local isMKdown = false
|
||||
|
||||
-- Returns if the Modkey is down
|
||||
--- @return boolean
|
||||
keyman.isModkeyDown = function()
|
||||
return isMKdown
|
||||
end
|
||||
|
||||
-- Prints keys in the `funcs` table, pre-cache
|
||||
--- Used for Debug
|
||||
keyman.PrintFuncs = function()
|
||||
print("Functions: ")
|
||||
for i,v in pairs(keyman.funcs) do
|
||||
print("Key: " .. i)
|
||||
for j,k in ipairs(v) do
|
||||
print(" Index: " .. tostring(j))
|
||||
for name,func in pairs(k) do
|
||||
print(" Has Event: " .. name .. " | Function: " .. tostring(func))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Prints keys in the `keys` table, the cache
|
||||
--- Used for Debug, only available in game
|
||||
keyman.PrintKeys = function()
|
||||
print("Keys: ")
|
||||
for i,v in pairs(keyman.keys) do
|
||||
print("Key: " .. i)
|
||||
for j,event in pairs(v) do
|
||||
print(" Event: " .. tostring(j) .. " | Total: " .. tostring(event and #event))
|
||||
for index,func in ipairs(event) do
|
||||
print(" Index: " .. index .. " | Function: " .. tostring(func))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local handleInput = function(key, mevent, event)
|
||||
local temp = keyman.keys[key] and (keyman.keys[key][mevent] or keyman.keys[key][event])
|
||||
if not temp then return end
|
||||
for i=1, #temp do
|
||||
temp[i](key)
|
||||
end
|
||||
end
|
||||
|
||||
local _onKeyPressed = function(key)
|
||||
handleInput(key, (isMKdown and "OnModKeyPressed"), "OnKeyPressed")
|
||||
end
|
||||
|
||||
local _onKeyStartPressed = function(key)
|
||||
handleInput(key, (isMKdown and "OnModKeyStartPressed"), "OnKeyStartPressed")
|
||||
end
|
||||
|
||||
local _onKeyKeepPressed = function(key)
|
||||
handleInput(key, (isMKdown and "OnModKeyKeepPressed"), "OnKeyKeepPressed")
|
||||
end
|
||||
|
||||
local _onCustomUIKey = function(key)
|
||||
handleInput(key, (isMKdown and "OnCustomUIModKey"), "OnCustomUIKey")
|
||||
end
|
||||
|
||||
-- Check if our given function has been already added to the current key/event
|
||||
---- this could be better, but most of the time this should be a relatively small check
|
||||
local checkIfExists = function(obj, data)
|
||||
if not obj then return false end
|
||||
for _,v in ipairs(obj) do
|
||||
if v == data then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
keyman.buildKeymap = function()
|
||||
keyman.keys = {}
|
||||
for i,v in pairs(keyman.funcs) do
|
||||
-- get the key for the bind we have stored
|
||||
local key = getCore():getKey(i)
|
||||
-- check if we didn't get a key for some reason...
|
||||
if key then
|
||||
-- get the index for this key in our object
|
||||
local obj = keyman.keys[key] or {}
|
||||
for _,k in ipairs(v) do
|
||||
for event, func in pairs(k) do
|
||||
if not checkIfExists(obj[event], func) then
|
||||
obj = addTo(event, obj, func)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- reassign
|
||||
keyman.keys[key] = obj
|
||||
end
|
||||
end
|
||||
--keyman.PrintKeys()
|
||||
end
|
||||
|
||||
local _isKeyDown = isKeyDown
|
||||
local function modkey(key)
|
||||
isMKdown = _isKeyDown(key)
|
||||
end
|
||||
|
||||
-- this is for when we disable the event, need to prevent those modkeys from being added; they're not events
|
||||
local modkeyevents = {
|
||||
["OnModKeyPressed"] = true,
|
||||
["OnModKeyStartPressed"] = true,
|
||||
["OnModKeyKeepPressed"] = true,
|
||||
["OnCustomUIModKey"] = true,
|
||||
}
|
||||
|
||||
-- Build our Keymap and setup our events
|
||||
keyman._onStart = function()
|
||||
keyman.addKeyEvents('Bindaid_Modkey', {
|
||||
["OnKeyStartPressed"] = modkey,
|
||||
["OnKeyPressed"] = modkey,
|
||||
})
|
||||
|
||||
if conf.Local.keyinputOptimize then
|
||||
keyman.buildKeymap()
|
||||
Events.OnKeyPressed.Add(_onKeyPressed)
|
||||
Events.OnKeyStartPressed.Add(_onKeyStartPressed)
|
||||
Events.OnKeyKeepPressed.Add(_onKeyKeepPressed)
|
||||
Events.OnCustomUIKey.Add(_onCustomUIKey)
|
||||
else
|
||||
-- If the keyinput optimizer is disabled, this will only contain functions added by other mods
|
||||
---- Add those keys to the event stack
|
||||
for _,v in pairs(keyman.funcs) do
|
||||
for _,k in ipairs(v) do
|
||||
for event, func in pairs(k) do
|
||||
-- skip modkey events
|
||||
if not modkeyevents[event] then
|
||||
Events[event].Add(func)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local postBoot = function()
|
||||
conf = require('BindAidConfig')
|
||||
|
||||
local keys = {}
|
||||
local headers = {}
|
||||
local index
|
||||
-- index the current keyBinding variable
|
||||
for _,v in ipairs(keyBinding) do
|
||||
if luautils.stringStarts(v.value, "[") then
|
||||
index = v.value
|
||||
keys[index] = {}
|
||||
headers[#headers+1] = v.value
|
||||
else
|
||||
keys[index][#keys[index]+1] = v
|
||||
end
|
||||
end
|
||||
-- Add our functions to the appropriate section
|
||||
for section,binds in pairs(keyman.addKeys) do
|
||||
--print("Section: " .. tostring(section))
|
||||
if not keys[section] then
|
||||
headers[#headers+1] = section
|
||||
keys[section] = {}
|
||||
end
|
||||
for _,k in ipairs(binds) do
|
||||
--print(" Key: " .. tostring(k.value) .. " = " .. tostring(k.key))
|
||||
keys[section][#keys[section]+1] = k
|
||||
end
|
||||
end
|
||||
-- re-add our bindings back into the keyBinding variable
|
||||
keyBinding = {}
|
||||
for _,v in ipairs(headers) do
|
||||
--print("Index: " .. tostring(i) .. " | Header: " .. v)
|
||||
keyBinding[#keyBinding+1] = {value = v, key = nil} -- header
|
||||
for _,k in ipairs(keys[v]) do
|
||||
--print(" Value: " .. k.value .. " | Key: " .. k.key)
|
||||
keyBinding[#keyBinding+1] = {value = k.value, key = k.key} -- let's make a deep copy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
keyman._onBoot = function()
|
||||
Events.OnGameBoot.Add(postBoot)
|
||||
end
|
||||
|
||||
return keyman
|
||||
@@ -0,0 +1,34 @@
|
||||
UI_EN = {
|
||||
UI_Init_Bindaid = "Hello: BindAid!",
|
||||
UI_optionscreen_binding_Bindaid = "BindAid",
|
||||
UI_optionscreen_binding_Bindaid_Modkey = "Modifier Key",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_2 = "Middle Mouse Button",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_3 = "Mouse Button 3",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_4 = "Mouse Button 4",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_5 = "Mouse Button 5",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_6 = "Mouse Button 6",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_7 = "Mouse Button 7",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_8 = "Mouse Button 8",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_9 = "Mouse Button 9",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_10 ="Mouse Button 10",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_11 ="Mouse Button 11",
|
||||
UI_optionscreen_binding_Bindaid_MouseKey_12 ="Mouse Button 12",
|
||||
|
||||
UI_ModOptions_Bindaid_autohideMouse = "AutoHide Mouse",
|
||||
UI_ModOptions_Bindaid_autohideMouse_tooltip = "Hide the mouse after it has not been moved.",
|
||||
|
||||
UI_ModOptions_Bindaid_autohideMouseTime = "AutoHide Mouse Delay",
|
||||
UI_ModOptions_Bindaid_UI_ModOptions_Bindaid_autohideMouseTime_tooltip = "AutoHide the Mouse after this many Seconds",
|
||||
|
||||
UI_ModOptions_Bindaid_mouseButtonSupport = "Enable Additional Mouse Button Support",
|
||||
UI_ModOptions_Bindaid_mouseButtonSupport_tooltip = "NOTE: You MUST restart the game if this is changed.",
|
||||
|
||||
UI_ModOptions_Bindaid_mouseButtonCount = "Additional Mouse Buttons",
|
||||
UI_ModOptions_Bindaid_mouseButtonCount_tooltip = "Number of additional Mouse Buttons to support. <LINE> NOTE: You MUST restart the game if this is changed.",
|
||||
|
||||
UI_ModOptions_Bindaid_emulateAndEvent = "Run Mouse and Emulated Events",
|
||||
UI_ModOptions_Bindaid_emulateAndEvent_tooltip = "When a Mouse Button is pressed, run both the Mouse Event functions and the Emulated Key if set. If disabled, only the assigned Emulated Key is performed. If no Emulated Key, then Mouse Events are used.",
|
||||
|
||||
UI_ModOptions_Bindaid_keyinputOptimize = "Enable Keyboard Input Optimization",
|
||||
UI_ModOptions_Bindaid_keyinputOptimize_tooltip = "Enables the Keyboard Input Optimization, please read the Mod's Description for full information on this. <LINE> If you receive any issues with input, please disable this. <LINE> NOTE: You MUST restart the game if this is changed while in-game.",
|
||||
}
|
||||
11
BindAid/Contents/mods/BindAid/mod.info
Normal file
11
BindAid/Contents/mods/BindAid/mod.info
Normal file
@@ -0,0 +1,11 @@
|
||||
name=BindAid
|
||||
id=BindAid
|
||||
authors=dhert
|
||||
|
||||
description=
|
||||
description=Optimizes keyboard input, adds native mousebutton emulation, and more!
|
||||
|
||||
pzversion=41
|
||||
tags=Interface;Framework;Misc
|
||||
|
||||
poster=poster.png
|
||||
BIN
BindAid/Contents/mods/BindAid/poster.png
Normal file
BIN
BindAid/Contents/mods/BindAid/poster.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
353
BindAid/README.md
Normal file
353
BindAid/README.md
Normal file
@@ -0,0 +1,353 @@
|
||||
Supports B41+ and Multiplayer.
|
||||
|
||||
A new save is not required.
|
||||
|
||||
# BindAid
|
||||
|
||||
Input Binding Manager for Project Zomboid which provides optimizations for keyboard input events and additional Mouse button support with optional keybaord emulation.
|
||||
|
||||
# Features
|
||||
- Keyboard Input Optimization
|
||||
- Modkey Support
|
||||
- Additional Mouse Button Support
|
||||
- Mouse Button Keyboard Emulation
|
||||
- Autohide the Mouse Cursor
|
||||
- Easy API for Modders!
|
||||
|
||||
## Mod Options
|
||||
|
||||
Mod Options is **REQUIRED** to configure this mod; however, it is not a requirement for its operation. When your first install this mod, please take some time to set up its configuration based on your own needs using Mod Options. Further information on the available options is available below.
|
||||
|
||||
When Mod Options is **NOT** enabled for a save, your configuration will still be read and applied. **THIS MEANS** Server Owners can safely include this mod without also requiring Mod Options, and user configuration will still be used.
|
||||
|
||||
## Keyboard Input Optimization
|
||||
|
||||
A full breakdown is available here: BindAid's Keyboard Input Optimization - What It Be, and How It Do
|
||||
|
||||
In summary, there are 4 general events that are triggered for input handling, and each event will call multiple functions for each key press.
|
||||
| Event | Trigger | # of Functions |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| OnKeyStartPressed | When a key is pressed | 10 |
|
||||
| OnKeyKeepPressed | When a key is held, every frame | 9 |
|
||||
| OnKeyPressed | When a key is released | 26 |
|
||||
| OnCustomUIKey | When a key is released | 1 |
|
||||
|
||||
This occurs for **ALL** key presses, whether they have actions bound or not. Multiple key presses multiply the number of functions called per frame. This is not an issue for most people, but I have organized and optimized how this is handled so only 1 function is called during the event, which then calls the key press if applicable.
|
||||
|
||||
This feature can be disabled in the Mod Options configuration. If changed while in-game, a restart is required.
|
||||
|
||||
### Compatibility
|
||||
|
||||
I have created this in a way that should have maximum compatibility. If you have any issues with a vanilla key not being triggered, I would recommend disabling this optimization and letting me know. I cannot fix all mod compatibility, and some may require changes by the Modders. For Modders, please see: BindAid - Modder's Resource
|
||||
|
||||
- Mods that add their own **NEW** keys are not affected.
|
||||
- Mods that modify vanilla functions for key presses will be compatible as long as their changes are made no later than OnGameStart, and any modifications are forwarded.
|
||||
|
||||
## Mouse Buttons
|
||||
|
||||
That's right, BindAid provides support for additional Mouse Buttons! Currently supports up to 10 additional Mouse Buttons, configurable in the Mod Options!
|
||||
|
||||
You will need to select the number of Mouse Buttons that you would like to have support for in the Mod Options. A restart of the game is required after you have made this change.
|
||||
|
||||
The Mouse Buttons have 2 different modes: Mouse Button Events (default) and Keyboard Emulation. An option is available to enable both methods to run as well.
|
||||
|
||||
### Mouse Button Events
|
||||
|
||||
When Mouse Button Events are in use, the additional Mouse Buttons are handled similarly to key bind events. Modders can hook into these events to allow additional actions to be done on a Mouse Button Press/Hold/Release. Please see: BindAid - Modder's Resource
|
||||
|
||||
**THIS MEANS, BY DEFAULT, MOUSE BUTTONS PERFORM NO NEW ACTIONS! MODDERS MUST ADD SUPPORT FOR THIS!**
|
||||
|
||||
### Keyboard Emulation
|
||||
|
||||
New in the "Keybinds" Options Tab will be the Mouse Buttons that are supported under the "BindAid" section, each set to a key bind of "None". Setting a Key here on a Mouse Button will instead cause an emulated key press to be done instead of the Mouse Event! For example, you can bind "Reload" to the Middle Mouse Button.
|
||||
|
||||
**NOTE!!!** The Emulated key press is ONLY done in Lua, so it will not trigger functions defined in Java. This means you cannot assign a key to "Move Forward" or something like that; it won't work. Actions such as Reloading, Shout/Emote, and many others are available, as well as new key binds added by other mods (the main target).
|
||||
|
||||
# BindAid's Keyboard Input Optimization - What It Be, and How It Do
|
||||
|
||||
There are 4 general events that are triggered for input handling, and each event will call multiple functions for each key press.
|
||||
| Event | Trigger | # of Functions |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| OnKeyStartPressed | When a key is pressed | 10 |
|
||||
| OnKeyKeepPressed | When a key is held, every frame | 9 |
|
||||
| OnKeyPressed | When a key is released | 26 |
|
||||
| OnCustomUIKey | When a key is released | 1 |
|
||||
|
||||
This occurs for **ALL** key presses, whether they have actions bound or not. Multiple key presses multiply the number of functions called per frame.
|
||||
|
||||
Most of the time, this has minimal impact on performance for keyboard input in Project Zomboid as most of the functions called will immediately check for their key first and end. However, there are some that do not and may also perform additional checks; this is redundant when there is no action to perform on a key press and unnecessary overhead. On low-end machines, or when the game/device is undergoing stress, this can can cause be brief input delays.
|
||||
|
||||
Instead, the key binds, events, and functions that are being called have been organized into an array with the key and event as its index. All vanilla events are then removed from the event stack, and a single event is added for each to trigger the appropriate key and function per event given. This reduces the overhead for each of the Events to only call ONE function, and if the key is not found in the array then no further action is done.
|
||||
|
||||
## How it works
|
||||
|
||||
The key bind/event cache is built last during the `OnGameStart` event, so any other mods should have already made their changes at this point. I also have not experienced any mods that change key binds after `OnGameStart`, and am not sure why you would do this anyway. The cache is rebuilt when settings are updated.
|
||||
|
||||
The cache is built in the following manner:
|
||||
```lua
|
||||
cache[key] = {
|
||||
["OnKeyStartPressed"] = { func1, func2 },
|
||||
["OnKeyKeepPressed"] = { func1 }
|
||||
}
|
||||
```
|
||||
|
||||
The `key` is the numerical value of all key binds. When a key is pressed it is used to access the list of events, if any, bound to the key. The event then contains an indexed array of functions to run on this key press.
|
||||
|
||||
```lua
|
||||
local handleInput = function(key, event)
|
||||
local temp = cache[key] and cache[key][event]
|
||||
if not temp then return end
|
||||
for i=1, #temp do
|
||||
temp[i](key)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Why do this?
|
||||
|
||||
Most games engines I have found handles key presses in this way: where operations are indexed or there is some sort of additional control to prevent all functions from being run like this. While this may provide limited improvements, it is an improvement nonetheless.
|
||||
|
||||
## Benchmark
|
||||
|
||||
NOTE: This requires a change to the Lua in the base game by adding a new file, and may produce a lot of noise in your log. I don't recommend doing this unless you're curious, and if you do, you should be sure to delete this file or verify your game's files with Steam.
|
||||
|
||||
### Disclaimer
|
||||
|
||||
To be completely honest, we're not looking at substantial improvements for most players. The Event functions are already optimized, in that most simply end when the key doesn't match. In my testing, the current key bind input event stack takes on average 1 Millisecond (Ms) to complete; any delays come from the action being performed by the key and not from the number of functions being run. When there was a lot onscreen, and in a dedicated server, I could receive occasional delays of up to about 10Ms.
|
||||
|
||||
With this mod enabled, I consistently receive no more than 1Ms for each Event loop; unless an action is performed on the key, such as opening the crafting window.
|
||||
|
||||
Let's take the following code as our benchmark. In the base game folder, create the following file: `media/lua/shared/!a_KeyTimer.lua`
|
||||
```lua
|
||||
-- control for time.
|
||||
--- this is reset on each call of the keystack for each key
|
||||
local time = 0
|
||||
|
||||
-- event start functions, store the times
|
||||
local onKeyDownStart = function(key)
|
||||
time = getTimestampMs()
|
||||
end
|
||||
|
||||
local onKeyHoldStart = function(key)
|
||||
time = getTimestampMs()
|
||||
end
|
||||
|
||||
local onKeyUpStart = function(key)
|
||||
time = getTimestampMs()
|
||||
end
|
||||
|
||||
-- Add our Events to the stack.
|
||||
--- Due to how Project Zomboid loads files, this will be first on the Lua-side
|
||||
Events.OnKeyStartPressed.Add(onKeyDownStart)
|
||||
Events.OnKeyKeepPressed.Add(onKeyHoldStart)
|
||||
Events.OnKeyPressed.Add(onKeyUpStart)
|
||||
|
||||
-- event end functions. subtract the current from the start, and print if greater than 1
|
||||
local onKeyDownEnd = function(key)
|
||||
time = getTimestampMs() - time
|
||||
if time > 1 then
|
||||
print("onKeyDownEnd: " .. tostring(key) .. " | Time: " .. tostring(time))
|
||||
end
|
||||
end
|
||||
|
||||
local onKeyHoldEnd = function(key)
|
||||
time = getTimestampMs() - time
|
||||
if time > 1 then
|
||||
print("onKeyHoldEnd: " .. tostring(key) .. " | Time: " .. tostring(time))
|
||||
end
|
||||
end
|
||||
|
||||
local onKeyUpEnd = function(key)
|
||||
time = getTimestampMs() - time
|
||||
if time > 1 then
|
||||
print("onKeyUpEnd: " .. tostring(key) .. " | Time: " .. tostring(time))
|
||||
end
|
||||
end
|
||||
|
||||
-- Add our key events when creating the player; most key events should be assigned by now.
|
||||
local postStart = function()
|
||||
Events.OnKeyStartPressed.Add(onKeyDownEnd)
|
||||
Events.OnKeyKeepPressed.Add(onKeyHoldEnd)
|
||||
Events.OnKeyPressed.Add(onKeyUpEnd)
|
||||
end
|
||||
|
||||
Events.OnCreatePlayer.Add(postStart)
|
||||
```
|
||||
|
||||
This will save the current Millisecond timestamp in the `time` variable at the start of each event. The `OnCreatePlayer` function adds our other functions to the end of the Event stacks, and so at the end of the Event the current Millisecond timestamp is subtracted from the start's to give us our delta time. If this takes over 1Ms, then it will print the key and the delta time.
|
||||
|
||||
This most commonly will begin to give results after there are a bunch of zombies on screen, and mostly during `onKeyUpEnd()` due to the number of functions called.
|
||||
|
||||
As mentioned previously, I always get good performance on my machine. I would love to hear any reports (positive or negative) if you tried this yourself!
|
||||
|
||||
# BindAid - Modder's Resource
|
||||
|
||||
Do you or a loved one want to add your own input events, or be sure to not conflict with BindAid? Then look no further!
|
||||
|
||||
BindAid does require that it be supported by modders. I cannot create a solution that would make this work for everything. As long as nothing too weird is being done, there should already be compatibility. But to take advantage of the new input handling method, support must be added.
|
||||
|
||||
The good news is, this can be done easily and in a way that doesn't make BindAid a hard requirement!
|
||||
|
||||
## Keyboard Compatibility
|
||||
|
||||
**DO:**
|
||||
Feel free to make changes to Vanilla functions during `OnGameStart` or before, and be sure to forward your changes!
|
||||
```lua
|
||||
local _ItemBindingHandler_onKeyPressed = ItemBindingHandler.onKeyPressed
|
||||
ItemBindingHandler.onKeyPressed = function(key)
|
||||
_ItemBindingHandler_onKeyPressed(key)
|
||||
end
|
||||
```
|
||||
Here, I have replaced the `ItemBindingHandler.onKeyPressed` with my own version of the function, and my change is now forwarded as the new `ItemBindingHandler.onKeyPressed` going forward.
|
||||
|
||||
**DON'T:** Make changes to Vanilla functions locally, and not forward your changes.
|
||||
```lua
|
||||
local _ItemBindingHandler_onKeyPressed = ItemBindingHandler.onKeyPressed
|
||||
Events.OnKeyPressed.Remove(ItemBindingHandler.onKeyPressed)
|
||||
local myNewCoolFunc = function(key)
|
||||
_ItemBindingHandler_onKeyPressed(key)
|
||||
end
|
||||
Events.OnKeyPressed.Add(myNewCoolFunc)
|
||||
```
|
||||
This also prevents other functions from accessing any of your changes, as they will only get the vanilla version of the function and also would not be used at all. This is a sure-fire way to introduce incompatibilities!
|
||||
|
||||
The Key Event cache is built at the END of `OnGameStart`, so make any changes that you need before then!
|
||||
|
||||
That's basically it as far as compatibility: just make sure you forward your changes made to vanilla functions and be sure to make your changes when it makes sense to, and you're all set!
|
||||
|
||||
## Mod Load Order
|
||||
|
||||
There seems to be some confusion on this topic, likely due to how other games handle mods. But to be clear: Mod Load Order will never change the order that Lua files are loaded. If there is a code conflict, changing the Mod Load Order will not resolve this.
|
||||
|
||||
# How to use
|
||||
|
||||
Support for this mod can be added with just a few additional lines of code! First: get the module, if available. These will be referenced later.
|
||||
|
||||
- For Keyboard Input:
|
||||
```lua
|
||||
local keyman = (getActivatedMods():contains("BindAid") and require("KeybindManager"))
|
||||
```
|
||||
- For Mouse Input:
|
||||
```lua
|
||||
local mouse = (getActivatedMods():contains("BindAid") and require("Mouse"))
|
||||
```
|
||||
|
||||
## Adding a New Key
|
||||
|
||||
You can add a new key to the game with the following function:
|
||||
```lua
|
||||
keyman.addKeybind("[SECTION]", "Key_Name", 0)
|
||||
```
|
||||
`[SECTION]` can be any of the available sections, or a new one! This will add the key to the appropriate section on the Keybind Options Tab.
|
||||
|
||||
At this point, even if you have already added the key another way, you would typically add a function to an Event to handle your key as well. Instead, we're going to add our key this way:
|
||||
```lua
|
||||
keyman.addKeyEvents("Key_Name", {
|
||||
["OnKeyStartPressed"] = myDownFunction,
|
||||
["OnKeyKeepPressed"] = myHoldFunction,
|
||||
["OnKeyPressed"] = myUpFunction,
|
||||
})
|
||||
```
|
||||
You **ONLY** need to add the events that you intend to support!
|
||||
|
||||
You can do this in all one go, too!
|
||||
```lua
|
||||
keyman.addKeybind("[SECTION]", "Key_Name", 0, {
|
||||
["OnKeyStartPressed"] = myDownFunction,
|
||||
["OnKeyKeepPressed"] = myHoldFunction,
|
||||
["OnKeyPressed"] = myUpFunction,
|
||||
})
|
||||
```
|
||||
|
||||
If you are **ADDING** a new key bind, it MUST be done during or before `OnGameBoot` to ensure that the game receives this!
|
||||
|
||||
**NOTE:** If a user has the Keyboard Optimize disabled, then your keys will be added as normal events. You will need to plan for this in your function, by first checking the key pressed.
|
||||
|
||||
A full example:
|
||||
```lua
|
||||
-- Demonstrates adding Optional support for BindAid
|
||||
local keyman = (getActivatedMods():contains("BindAid") and require("KeybindManager"))
|
||||
|
||||
local myKeyFunction = function(key)
|
||||
if key == getCore():getKey("My_Key") then
|
||||
getPlayer():Say("Test Pressed!")
|
||||
elseif key == getCore():getKey("My_Key2") then
|
||||
getPlayer():Say("Test2 Pressed!")
|
||||
end
|
||||
end
|
||||
|
||||
local onGameBoot = function()
|
||||
-- This is just our Header for the keybinds
|
||||
table.insert(keyBinding, { value = "[Testing]" })
|
||||
|
||||
if keyman then
|
||||
-- Add our very own key, in full!
|
||||
keyman.addKeybind("[Testing]", "My_Key", 82, {
|
||||
["OnKeyPressed"] = myKeyFunction
|
||||
})
|
||||
|
||||
-- Let's say we add our key another way...
|
||||
table.insert(keyBinding, { value = "My_Key2", key = 83 })
|
||||
-- Then we add our "Event" this way:
|
||||
keyman.addKeyEvents("My_Key2", {
|
||||
["OnKeyPressed"] = myKeyFunction
|
||||
})
|
||||
else
|
||||
-- Add our keys and our events
|
||||
table.insert(keyBinding, { value = "My_Key", key = 82 })
|
||||
table.insert(keyBinding, { value = "My_Key2", key = 83 })
|
||||
-- Add our Event
|
||||
Events.OnKeyPressed.Add(myKeyFunction)
|
||||
end
|
||||
end
|
||||
|
||||
Events.OnGameBoot.Add(onGameBoot)
|
||||
```
|
||||
|
||||
## Mouse Buttons
|
||||
|
||||
Mouse Button Events are still be developed, in that I am trying to make it easier to handle when a Mouse Button is not available.
|
||||
|
||||
For now, you have access to the following variable to tell you how many Mouse Buttons are enabled:
|
||||
```lua
|
||||
mouse.mouseButtons
|
||||
```
|
||||
|
||||
Mouse Events work similarly to key bind events.
|
||||
|
||||
### Events
|
||||
| Down | Hold | Release |
|
||||
| ----------- | ----------- | ----------- |
|
||||
| OnMouseMiddleDown | OnMouseMiddleHold | OnMouseMiddleUp |
|
||||
| OnMouse4Down | OnMouse4Hold | OnMouse4Up |
|
||||
| OnMouse5Down | OnMouse5Hold | OnMouse5Up |
|
||||
| OnMouse6Down | OnMouse6Hold | OnMouse6Up |
|
||||
| OnMouse7Down | OnMouse7Hold | OnMouse7Up |
|
||||
| OnMouse8Down | OnMouse8Hold | OnMouse8Up |
|
||||
| OnMouse9Down | OnMouse9Hold | OnMouse9Up |
|
||||
| OnMouse10Down | OnMouse10Hold | OnMouse10Up |
|
||||
| OnMouse11Down | OnMouse11Hold | OnMouse11Up |
|
||||
| OnMouse12Down | OnMouse12Hold | OnMouse12Up |
|
||||
|
||||
The default Left and Right Click actions are defined in Java, and cannot be overwritten easily. It is beyond the scope of this mod to attempt this as well.
|
||||
|
||||
An example:
|
||||
```lua
|
||||
local mouse = (getActivatedMods():contains("BindAid") and require("Mouse"))
|
||||
|
||||
local myMouseButton = function(mouseX, mouseY)
|
||||
getPlayer():Say("Middle Mouse!")
|
||||
end
|
||||
|
||||
local onGameBoot = function()
|
||||
if mouse then
|
||||
mouse.Add({
|
||||
["OnMouseMiddleUp"] = myMouseButton,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
Events.OnGameBoot.Add(onGameBoot)
|
||||
```
|
||||
|
||||
I also would like to add support for detecting when these Mouse Buttons are clicked on a UI, but it seems the base game only performs these checks on the main Mouse Buttons. So, stay tuned!
|
||||
BIN
BindAid/preview.png
Normal file
BIN
BindAid/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
93
BindAid/workshop.txt
Normal file
93
BindAid/workshop.txt
Normal file
@@ -0,0 +1,93 @@
|
||||
version=1
|
||||
id=2945066057
|
||||
title=BindAid
|
||||
description=[h1]Supports B41+. Works in Multiplayer[/h1]
|
||||
description=[h3]A new save is not required[/h3]
|
||||
description=
|
||||
description=[img]https://i.imgur.com/p7Fv1Z6.gif[/img]
|
||||
description=
|
||||
description=Input Binding Manager for Project Zomboid which provides optimizations for keyboard input events and additional Mouse button support with optional keybaord emulation.
|
||||
description=
|
||||
description=[h2]Features[/h2]
|
||||
description=[list]
|
||||
description=[*] Keyboard Input Optimization
|
||||
description=[*] Modkey Support
|
||||
description=[*] Additional Mouse Button Support
|
||||
description=[*] Mouse Button Keyboard Emulation
|
||||
description=[*] Autohide the Mouse Cursor
|
||||
description=[*] Easy API for Modders!
|
||||
description=[/list]
|
||||
description=
|
||||
description=[h2]Mod Options[/h2]
|
||||
description=
|
||||
description=Mod Options is [b]REQUIRED[/b] to configure this mod; however, it is not a requirement for its operation. When your first install this mod, please take some time to set up its configuration based on your own needs using Mod Options. Further information on the available options is available below.
|
||||
description=
|
||||
description=When Mod Options is [b]NOT[/b] enabled for a save, your configuration will still be read and applied. [b]THIS MEANS[/b] Server Owners can safely include this mod without also requiring Mod Options, and user configuration will still be used.
|
||||
description=
|
||||
description=[h2]Keyboard Input Optimization[/h2]
|
||||
description=
|
||||
description=A full breakdown is available here: BindAid's Keyboard Input Optimization - What It Be, and How It Do
|
||||
description=
|
||||
description=In summary, there are 4 general events that are triggered for input handling, and each event will call multiple functions for each keypress.
|
||||
description=[table]
|
||||
description=[tr]
|
||||
description=[th]Event[/th]
|
||||
description=[th]Trigger[/th]
|
||||
description=[th]# of Functions[/th]
|
||||
description=[/tr]
|
||||
description=[tr]
|
||||
description=[td]OnKeyStartPressed[/td]
|
||||
description=[td]When a key is pressed[/td]
|
||||
description=[td]10[/td]
|
||||
description=[/tr]
|
||||
description=[tr]
|
||||
description=[td]OnKeyKeepPressed[/td]
|
||||
description=[td]When a key is held, every frame[/td]
|
||||
description=[td]9[/td]
|
||||
description=[/tr]
|
||||
description=[tr]
|
||||
description=[td]OnKeyPressed[/td]
|
||||
description=[td]When a key is released[/td]
|
||||
description=[td]26[/td]
|
||||
description=[/tr]
|
||||
description=[tr]
|
||||
description=[td]OnCustomUIKey[/td]
|
||||
description=[td]When a key is released[/td]
|
||||
description=[td]1[/td]
|
||||
description=[/tr]
|
||||
description=[/table]
|
||||
description=
|
||||
description=This occurs for [b]ALL[/b] keypresses, whether they have actions bound or not. Multiple keypresses multiply the number of functions called per frame. This is not an issue for most people, but I have organized and optimized how this is handled so only 1 function is called during the event, which then calls the keypress if applicable.
|
||||
description=
|
||||
description=This feature can be disabled in the Mod Options configuration. If changed while in-game, a restart is required.
|
||||
description=
|
||||
description=[h3]Compatibility[/h3]
|
||||
description=
|
||||
description=I have created this in a way that should have maximum compatibility. If you have any issues with a vanilla key not being triggered, I would recommend disabling this optimization and letting me know. I cannot fix all mod compatibility, and some may require changes by the Modders. For Modders, please see: BindAid - Modder's Resource
|
||||
description=
|
||||
description=[list]
|
||||
description=[*] Mods that add their own [b]NEW[/b] keys are not affected.
|
||||
description=[*] Mods that modify vanilla functions for keypresses will be compatible as long as their changes are made no later than OnGameStart, and any modifications are forwarded.
|
||||
description=[/list]
|
||||
description=
|
||||
description=[h2]Mouse Buttons[/h2]
|
||||
description=
|
||||
description=That's right, BindAid provides support for additional Mouse Buttons! Currently supports up to 10 additional Mouse Buttons, configurable in the Mod Options!
|
||||
description=
|
||||
description=You will need to select the number of Mouse Buttons that you would like to have support for in the Mod Options. A restart of the game is required after you have made this change.
|
||||
description=
|
||||
description=The Mouse Buttons have 2 different modes: Mouse Button Events (default) and Keyboard Emulation. An option is available to enable both methods to run as well.
|
||||
description=
|
||||
description=[h3]Mouse Button Events[/h3]
|
||||
description=
|
||||
description=When Mouse Button Events are in use, the additional Mouse Buttons are handled similarly to keybind events. Modders can hook into these events to allow additional actions to be done on a Mouse Button Press/Hold/Release. Please see: BindAid - Modder's Resource
|
||||
description=
|
||||
description=[b]THIS MEANS, BY DEFAULT, MOUSE BUTTONS PERFORM NO NEW ACTIONS! MODDERS MUST ADD SUPPORT FOR THIS![/b]
|
||||
description=
|
||||
description=[h3]Keyboard Emulation[/h3]
|
||||
description=
|
||||
description=New in the "Keybinds" Options Tab will be the Mouse Buttons that are supported under the "BindAid" section, each set to a keybind of "None". Setting a Key here on a Mouse Button will instead cause an emulated Keypress to be done instead of the Mouse Event! For example, you can bind "Reload" to the Middle Mouse Button.
|
||||
description=
|
||||
description=[b]NOTE!!![/b] The Emulated Keypress is ONLY done in Lua, so it will not trigger functions defined in Java. This means you cannot assign a key to "Move Forward" or something like that; it won't work. Actions such as Reloading, Shout/Emote, and many others are available, as well as new keybinds added by other mods (the main target).
|
||||
tags=Build 41;Interface;Misc
|
||||
visibility=private
|
||||
BIN
like_fav.gif
Normal file
BIN
like_fav.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 434 KiB |
Reference in New Issue
Block a user