Newer
Older
-- TE4 - T-Engine 4
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
--- Handles player hotkey interface
-- This provides methods to bind and manage hotkeys as well as using them<br/>
-- This interface is designed to work with the engine.HotkeysDisplay class to display current hotkeys to the player
-- @classmod engine.generator.interface.PlayerHotkeys
module(..., package.seeall, class.make)
_M.quickhotkeys = {}
_M.quickhotkeys_specifics = {}
function _M:init(t)
self.hotkey = self.hotkey or {}
self.hotkey_page = self.hotkey_page or 1
end
print("[SORTING HOTKEYS] actor = " .. ("%q"):format(self.name))
self.hotkeys_sorted = true -- It's only important that we attempted to sort the hotkeys.
local quickhotkeys_type_table
if self == game:getPlayer(true) then
quickhotkeys_type_table = self:get_qhk_hotkeys(_M.quickhotkeys["Player: Specific"])
if not quickhotkeys_type_table then
quickhotkeys_type_table = _M.quickhotkeys["Player: Global"]
end
else
quickhotkeys_type_table = self:get_qhk_hotkeys(_M.quickhotkeys[self.name])
end
if not quickhotkeys_type_table then return end
local sorted = {}
local function sort_hotkeys(arg)
if arg then
for hotkey_type, hotkey_position_table in pairs(arg) do
sorted[hotkey_type] = sorted[hotkey_type] or {}
for hotkey_name, position in pairs(hotkey_position_table) do
local success = false
if not self.hotkey[position] then
if hotkey_type == "talent" and self.talents[hotkey_name] then success = true
elseif hotkey_type == "inventory" and self:findInAllInventories(hotkey_name) then success = true
end
end
if success and not sorted[hotkey_type][hotkey_name] then
print("[SORTING HOTKEYS]" .. " actor = " .. ("%q"):format(self.name) .. " - pairing",hotkey_name,i)
self.hotkey[position] = {hotkey_type, hotkey_name}
sorted[hotkey_type][hotkey_name] = true
-- Remove from old
for z = 1, 12 * self.nb_hotkey_pages do if old[z] and old[z][1] == hotkey_type and old[z][2] == hotkey_name then old[z] = nil break end end
end
end
sort_hotkeys(quickhotkeys_type_table)
-- Even if we have a "Player: Specific" entry for the player, make sure to
-- check "Player: Global" for any hotkeys the player might want sorted.
if self == game:getPlayer(true) then sort_hotkeys(_M.quickhotkeys["Player: Global"]) end
for j = 1, 12 * self.nb_hotkey_pages do
for i = 1, 12 * self.nb_hotkey_pages do if not self.hotkey[i] then
print("[SORTING HOTKEYS]" .. " actor = " .. ("%q"):format(self.name) .. " - added back", old[j][2], i)
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
-- Adds a new hotkey
function _M:addNewHotkey(kind, name)
if kind == "inventory" then
if self.player then
if self == game:getPlayer(true) then
position = self:findQuickHotkey("Player: Specific", "inventory", name)
if not position then
local global_hotkeys = engine.interface.PlayerHotkeys.quickhotkeys["Player: Global"]
if global_hotkeys and global_hotkeys["inventory"] then position = global_hotkeys["inventory"][name] end
end
else
position = self:findQuickHotkey(self.name, "inventory", name)
end
end
if position and not self.hotkey[position] then
self.hotkey[position] = {"inventory", name}
else
for i = 1, 12 * (self.nb_hotkey_pages or 5) do
if not self.hotkey[i] then
self.hotkey[i] = {"inventory", name}
break
end
end
end
elseif kind == "talent" then
if self.player then
if self == game:getPlayer(true) then
position = self:findQuickHotkey("Player: Specific", "talent", name)
if not position then
local global_hotkeys = engine.interface.PlayerHotkeys.quickhotkeys["Player: Global"]
if global_hotkeys and global_hotkeys["talent"] then position = global_hotkeys["talent"][name] end
end
else
position = self:findQuickHotkey(self.name, "talent", name)
end
end
if position and not self.hotkey[position] then
self.hotkey[position] = {"talent", name}
else
for i = 1, 12 * (self.nb_hotkey_pages or 5) do
if not self.hotkey[i] then
self.hotkey[i] = {"talent", name}
break
end
end
end
end
end
--- Uses an hotkeyed talent
-- This requires the ActorTalents interface to use talents and a method player:playerUseItem(o, item, inven) to use inventory objects
function _M:activateHotkey(id)
if self.hotkey[id] then
Dialog:simplePopup(_t"Hotkey not defined", _t"You may define a hotkey by pressing 'm' and following the instructions there.")
end
end
--- Activates a hotkey with a type "talent"
function _M:hotkeyTalent(tid)
self:useTalent(tid)
end
--- Activates a hotkey with a type "inventory"
function _M:hotkeyInventory(name)
local o, item, inven = self:findInAllInventories(name)
if not o then
Dialog:simplePopup(_t"Item not found", ("You do not have any %s ."):tformat(name))
--- Check if something is bound, and return the spot if it is
function _M:isHotkeyBound(kind, id)
for position, hotkey_info in pairs(self.hotkey) do
if hotkey_info[1] == kind and hotkey_info[2] == id then return position end
end
end
--- Switch to previous hotkey page
function _M:prevHotkeyPage()
self.hotkey_page = util.boundWrap(self.hotkey_page - 1, 1, self.nb_hotkey_pages)
self.changed = true
end
--- Switch to next hotkey page
function _M:nextHotkeyPage()
self.hotkey_page = util.boundWrap(self.hotkey_page + 1, 1, self.nb_hotkey_pages)
self.changed = true
end
--- Switch to hotkey page
function _M:setHotkeyPage(v)
self.hotkey_page = v
self.changed = true
end
function _M:hotkeyAutoTalents()
local already_hotkeyed = {}
-- Ensure we don't have endless duplicates of hotkeys on the bar
for position, hotkey_info in pairs(self.hotkey) do if hotkey_info[1] == "talent" then already_hotkeyed[hotkey_info[2]] = true end end
for tid, _ in pairs(self.talents) do
local t = self:getTalentFromId(tid)
if (t.mode == "activated" or t.mode == "sustained") and not already_hotkeyed[tid] and not t.ignored_by_hotkeyautotalents then
for i = 1, 12 * self.nb_hotkey_pages do
if not self.hotkey[i] then
self.hotkey[i] = {"talent", tid}
break
end
end
end
end
end
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
-- TODO: Replace this with loading quickhotkeys from the profile.
function _M:loadQuickHotkeys(module_short_name, file)
local f = loadfile(file)
print("[QUICK HOTKEYS] Loading quick hotkey settings for module " .. ("%q"):format(module_short_name) .. " from " .. file .. "...")
if f then
setfenv(f, _M)
if pcall(f) then
print("[QUICK HOTKEYS] Successfully loaded quick hotkey settings.")
return true
end
end
print("[QUICK HOTKEYS] Failed to load quick hotkey settings.")
return false
end
function _M:get_qhk_hotkeys(src, hotkey_type)
local ret = src
if ret and (not hotkey_type or (hotkey_type and not ret[hotkey_type])) then for i, f in ipairs(_M.quickhotkeys_specifics) do ret = ret[f(self)] if not ret then break end end end
if ret then if hotkey_type then return ret[hotkey_type] else return ret end end
end
function _M:findQuickHotkey(owner, hotkey_type, hotkey)
if _M.quickhotkeys[owner] then
local hotkey_table = self:get_qhk_hotkeys(_M.quickhotkeys[owner], hotkey_type)
if hotkey_table then return hotkey_table[hotkey] end
end
end
function _M:updateQuickHotkey(actor, hotkey_position)
local hotkey = actor and (actor.hotkey and actor.hotkey[hotkey_position] or nil) or nil
if hotkey then
local is_main_player = (actor == game:getPlayer(true))
local ownerString = is_main_player and "Player: Specific" or actor.name
_M.quickhotkeys[ownerString] = _M.quickhotkeys[ownerString] or {}
_M.quickhotkeys["Player: Global"] = _M.quickhotkeys["Player: Global"] or {}
local qhk_global = _M.quickhotkeys["Player: Global"]
local qhk_current = _M.quickhotkeys[ownerString]
for i, f in ipairs(_M.quickhotkeys_specifics) do
local key = f(actor)
qhk_current[key] = qhk_current[key] or {}
qhk_current = qhk_current[key]
end
qhk_current[hotkey[1]] = qhk_current[hotkey[1]] or {}
qhk_current[hotkey[1]][hotkey[2]] = hotkey_position
-- Only save global hotkeys for the main character.
if is_main_player then
qhk_global[hotkey[1]] = qhk_global[hotkey[1]] or {}
qhk_global[hotkey[1]][hotkey[2]] = hotkey_position
end
end
end
function _M:updateQuickHotkeys(actor)
-- Make sure the actor's hotkeys have been sorted at least once so we
-- don't overwrite the player's preferred hotkey order with defaults.
if actor.hotkeys_sorted then
if actor == game:getPlayer(true) or actor.save_hotkeys then
for position, hotkey in pairs(actor.hotkey) do
local save_quickhotkey = false
if hotkey[1] == "talent" then
save_quickhotkey = true
elseif hotkey[1] == "inventory" then
local item = actor:findInAllInventories(hotkey[2])
dg
committed
if item and item.save_hotkey then save_quickhotkey = true end
end
if save_quickhotkey then self:updateQuickHotkey(actor, position) end
end
end
end
end
local page_to_hotkey = {"", "SECOND_", "THIRD_", "FOURTH_", "FIFTH_", "SIX_", "SEVEN_"}
function _M:bindAllHotkeys(key, fct)
for page = 1, self.nb_hotkey_pages do for x = 1, 12 do
local i = x + (page - 1) * 12
local k = "HOTKEY_"..page_to_hotkey[page]..x
key:addBind(k, function() fct(i) end)
end end
end