added support for touchscreen

This commit is contained in:
FatalErr42O 2024-03-29 22:39:20 -07:00
parent 9922a37206
commit 30bd8d9528
8 changed files with 114 additions and 50 deletions

View File

@ -1,15 +0,0 @@
Bullet = Instantiatable_class:inherit({
registered = {},
range = 100,
force_mmRHA = 1,
dropoff_mmRHA = 0,
damage = 0,
itemstring = "",
construct = function(def)
assert(not def.instance, "attempt to create instance of a template")
assert(rawget(def, "itemstring"), "no string provided to new bullet template")
assert(minetest.registered_items[def.itemstring], "bullet item is not registered. Check dependencies?")
end
})

View File

@ -1,6 +1,6 @@
Guns4d.control_handler = { Guns4d.control_handler = {
--[[example: --[[example:
controls = { actions_pc = {
reload = { reload = {
conditions = { --the list of controls (see lua_api.txt) to call conditions = { --the list of controls (see lua_api.txt) to call
"shift", "shift",
@ -15,6 +15,7 @@ Guns4d.control_handler = {
} }
]] ]]
ads = false, ads = false,
touchscreen = false
} }
--data table: --data table:
--[[ --[[
@ -32,6 +33,10 @@ end]]
--this function always ends up a mess. I rewrote it here 2 times, --this function always ends up a mess. I rewrote it here 2 times,
--and in 3dguns I rewrote it at least 3 times. It's always just... --and in 3dguns I rewrote it at least 3 times. It's always just...
--impossible to understand. So if you see ALOT of comments, that's why. --impossible to understand. So if you see ALOT of comments, that's why.
function controls:get_actions()
assert(self.instance, "attempt to call object method on a class")
return (self.touchscreen and self.actions_touch) or self.actions_pc
end
function controls:update(dt) function controls:update(dt)
assert(self.instance, "attempt to call object method on a class") assert(self.instance, "attempt to call object method on a class")
self.player_pressed = self.player:get_player_control() self.player_pressed = self.player:get_player_control()
@ -39,7 +44,7 @@ function controls:update(dt)
local call_queue = {} --so I need to have a "call" queue so I can tell the functions the names of other active controls (busy_list) local call_queue = {} --so I need to have a "call" queue so I can tell the functions the names of other active controls (busy_list)
local busy_list = self.busy_list or {} --list of controls that have their conditions met. Has to be reset at END of update, so on_use and on_secondary_use can be marked local busy_list = self.busy_list or {} --list of controls that have their conditions met. Has to be reset at END of update, so on_use and on_secondary_use can be marked
if not (self.gun.rechamber_time > 0 and self.gun.ammo_handler.ammo.next_bullet == "empty") then --check if the gun is being charged. if not (self.gun.rechamber_time > 0 and self.gun.ammo_handler.ammo.next_bullet == "empty") then --check if the gun is being charged.
for i, control in pairs(self.actions) do for i, control in pairs(self:get_actions()) do
if not (i=="on_use") and not (i=="on_secondary_use") then if not (i=="on_use") and not (i=="on_secondary_use") then
local def = control local def = control
local data = control.data local data = control.data
@ -104,37 +109,53 @@ function controls:update(dt)
end end
function controls:on_use(itemstack, pointed_thing) function controls:on_use(itemstack, pointed_thing)
assert(self.instance, "attempt to call object method on a class") assert(self.instance, "attempt to call object method on a class")
if self.actions.on_use then local actions = self:get_actions()
self.actions.on_use(itemstack, self.handler, pointed_thing) if actions.on_use then
actions.on_use(itemstack, self.handler, pointed_thing)
end end
end end
function controls:on_secondary_use(itemstack, pointed_thing) function controls:on_secondary_use(itemstack, pointed_thing)
assert(self.instance, "attempt to call object method on a class") assert(self.instance, "attempt to call object method on a class")
if self.actions.on_secondary_use then local actions = self:get_actions()
self.actions.on_secondary_use(itemstack, self.handler, pointed_thing) if actions.on_secondary_use then
actions.on_secondary_use(itemstack, self.handler, pointed_thing)
end end
end end
---@diagnostic disable-next-line: duplicate-set-field ---@diagnostic disable-next-line: duplicate-set-field
function controls.construct(def) function controls:toggle_touchscreen_mode(active)
if def.instance then if active~=nil then self.touchscreen=active else self.touchscreen = not self.touchscreen end
assert(def.actions, "no actions provided") self.handler.touchscreen = self.touchscreen
assert(def.player, "no player provided") for i, action in pairs((self.touchscreen and self.actions_pc) or self.actions_touch) do
def.actions = Guns4d.table.deep_copy(def.actions) if not (i=="on_use") and not (i=="on_secondary_use") then
def.busy_list = {} action.timer = action.timer or 0
def.handler = Guns4d.players[def.player:get_player_name()] action.data = nil --no need to store excess data
def.mode = def.mode or "hold" end
for i, action in pairs(def.actions) do end
for i, action in pairs((self.touchscreen and self.actions_touch) or self.actions_pc) do
if not (i=="on_use") and not (i=="on_secondary_use") then if not (i=="on_use") and not (i=="on_secondary_use") then
action.timer = action.timer or 0 action.timer = action.timer or 0
action.data = { action.data = {
timer = action.timer, timer = action.timer,
continue = false, continue = false,
time_held = 0, time_held = 0,
current_mode = (def.mode=="hybrid" and "toggle") or def.mode current_mode = (action.mode=="hybrid" and "toggle") or action.mode or "hold"
} }
end end
end end
table.sort(def.actions, function(a,b) end
function controls.construct(def)
if def.instance then
assert(def.gun.properties.pc_control_actions, "no actions for pc controls provided")
assert(def.gun.properties.touch_control_actions, "no actions for touchscreen controls provided")
assert(def.player, "no player provided")
--instantiate controls (as we will be adding to the table)
def.actions_pc = Guns4d.table.deep_copy(def.gun.properties.pc_control_actions)
def.actions_touch = Guns4d.table.deep_copy(def.gun.properties.touch_control_actions)
def.busy_list = {}
def.handler = Guns4d.players[def.player:get_player_name()]
def:toggle_touchscreen_mode(def.touchscreen)
table.sort(def.actions_pc, function(a,b)
return #a.conditions > #b.conditions return #a.conditions > #b.conditions
end) end)
end end

View File

@ -106,7 +106,7 @@ local gun_default = {
gun_axial = {x=1, y=-1}, gun_axial = {x=1, y=-1},
player_axial = {x=1,y=1}, player_axial = {x=1,y=1},
}, },
control_actions = { --used by control_handler pc_control_actions = { --used by control_handler
__overfill=true, --this table will not be filled in. __overfill=true, --this table will not be filled in.
aim = Guns4d.default_controls.aim, aim = Guns4d.default_controls.aim,
auto = Guns4d.default_controls.auto, auto = Guns4d.default_controls.auto,
@ -114,8 +114,13 @@ local gun_default = {
on_use = Guns4d.default_controls.on_use, on_use = Guns4d.default_controls.on_use,
firemode = Guns4d.default_controls.firemode firemode = Guns4d.default_controls.firemode
}, },
mobile_control_actions = { touch_control_actions = {
__overfill=true,
aim = Guns4d.default_touch_controls.aim,
auto = Guns4d.default_touch_controls.auto,
reload = Guns4d.default_touch_controls.reload,
on_secondary_use = Guns4d.default_touch_controls.on_secondary_use,
firemode = Guns4d.default_touch_controls.firemode
}, },
charging = { --how the gun "cocks" charging = { --how the gun "cocks"
require_draw_on_swap = true, require_draw_on_swap = true,
@ -223,10 +228,10 @@ local gun_default = {
player_axial = Vec.new(), player_axial = Vec.new(),
}, },
}, },
spread = { --[[spread = {
recoil = vector.new(), recoil = vector.new(),
walking = vector.new() walking = vector.new()
}, },]]
animation_rotation = vector.new(), animation_rotation = vector.new(),
--[[total_offset_rotation = { --can't be in offsets, as they're added automatically. --[[total_offset_rotation = { --can't be in offsets, as they're added automatically.
gun_axial = Vec.new(), gun_axial = Vec.new(),
@ -263,7 +268,7 @@ local gun_default = {
ANIMATIONS_OFFSET_AIM = false, ANIMATIONS_OFFSET_AIM = false,
LOOP_IDLE_ANIM = false LOOP_IDLE_ANIM = false
}, },
animation_data = { --where animations data is stored. --[[animation_data = { --where animations data is stored.
anim_runtime = 0, anim_runtime = 0,
length = 0, length = 0,
fps = 0, fps = 0,
@ -272,8 +277,7 @@ local gun_default = {
--[[animations = { --[[animations = {
} }
]] },]]
},
bolt_charged = false, bolt_charged = false,
particle_spawners = {}, particle_spawners = {},
current_firemode = 1, current_firemode = 1,

View File

@ -40,7 +40,7 @@ function player_handler:update(dt)
self.player_model_handler = nil self.player_model_handler = nil
end end
self.player_model_handler = Guns4d.player_model_handler.get_handler(self:get_properties().mesh):new({player=self.player}) self.player_model_handler = Guns4d.player_model_handler.get_handler(self:get_properties().mesh):new({player=self.player})
self.control_handler = Guns4d.control_handler:new({player=player, actions=self.gun.properties.control_actions, gun=self.gun}) self.control_handler = Guns4d.control_handler:new({player=player, gun=self.gun, touchscreen=self.touchscreen})
--this needs to be stored for when the gun is unset! --this needs to be stored for when the gun is unset!
self.horizontal_offset = self.gun.properties.ads.horizontal_offset self.horizontal_offset = self.gun.properties.ads.horizontal_offset

View File

@ -35,7 +35,7 @@ Guns4d.default_controls.firemode = {
end end
end end
} }
Guns4d.default_controls.toggle_safety = { --[[Guns4d.default_controls.toggle_safety = {
conditions = {"sneak", "zoom"}, conditions = {"sneak", "zoom"},
loop = false, loop = false,
timer = 2, timer = 2,
@ -48,8 +48,8 @@ Guns4d.default_controls.toggle_safety = {
end end
end end
} }]]
Guns4d.default_controls.on_use = function(itemstack, handler, pointed_thing) Guns4d.default_controls.on_use = function(itemstack, handler, pointed_thing, busy_list)
local gun = handler.gun local gun = handler.gun
local fmode = gun.properties.firemodes[gun.current_firemode] local fmode = gun.properties.firemodes[gun.current_firemode]
if fmode ~= "safe" and not (gun.burst_queue > 0) then if fmode ~= "safe" and not (gun.burst_queue > 0) then

View File

@ -20,7 +20,8 @@ Guns4d.config = {
simple_headshot = true, --holdover feature before a more complex system is implemented simple_headshot = true, --holdover feature before a more complex system is implemented
simple_headshot_body_ratio = .75, --percentage of hitbox height that is body. simple_headshot_body_ratio = .75, --percentage of hitbox height that is body.
default_fov = 80, default_fov = 80,
headshot_damage_factor = 1.75 headshot_damage_factor = 1.75,
enable_touchscreen_command_name = "guns4d_enable_touchmode",
--`["official_content.replace_ads_with_bloom"] = false, --`["official_content.replace_ads_with_bloom"] = false,
--`["official_content.uses_magazines"] = true --`["official_content.uses_magazines"] = true
} }
@ -45,6 +46,7 @@ dofile(path.."/item_entities.lua")
dofile(path.."/play_sound.lua") dofile(path.."/play_sound.lua")
dofile(path.."/visual_effects.lua") dofile(path.."/visual_effects.lua")
dofile(path.."/default_controls.lua") dofile(path.."/default_controls.lua")
dofile(path.."/touch_support.lua")
dofile(path.."/block_values.lua") dofile(path.."/block_values.lua")
dofile(path.."/ammo_api.lua") dofile(path.."/ammo_api.lua")
path = path .. "/classes" path = path .. "/classes"
@ -54,7 +56,7 @@ dofile(path.."/Control_handler.lua")
dofile(path.."/Ammo_handler.lua") dofile(path.."/Ammo_handler.lua")
dofile(path.."/Sprite_scope.lua") dofile(path.."/Sprite_scope.lua")
dofile(path.."/Dynamic_crosshair.lua") dofile(path.."/Dynamic_crosshair.lua")
dofile(path.."/Gun.lua") dofile(path.."/Gun.lua") --> loads /classes/gun_construct.lua
dofile(path.."/Player_model_handler.lua") dofile(path.."/Player_model_handler.lua")
dofile(path.."/Player_handler.lua") dofile(path.."/Player_handler.lua")
dofile(path.."/Proxy_table.lua") dofile(path.."/Proxy_table.lua")

52
touch_support.lua Normal file
View File

@ -0,0 +1,52 @@
minetest.register_chatcommand(Guns4d.config.enable_touchscreen_command_name, {
parameters = "player",
description = "toggle wether the user is using a mobile device so controls can be adjusted for an optimal mobile experience",
privs = {privs=true},
func = function(caller, arg)
local handler = Guns4d.players[caller]
if handler and handler.control_handler then
handler.control_handler:toggle_touchscreen_mode()
minetest.chat_send_player(caller, "mobile mode "..((handler.control_handler.touchscreen and "enabled") or "disabled"))
if handler.control_handler.touchscreen then
minetest.chat_send_player(caller, "shift+tap to aim, shift+hold to switch fire modes, tap to fire, hold to fire full auto (when wielding a full auto weapon)")
end
end
end
})
Guns4d.default_touch_controls = {}
local touch = Guns4d.default_touch_controls
local pc = Guns4d.default_controls
--aiming
touch.aim = table.copy(pc.aim)
touch.aim.conditions = {"RMB", "sneak"}
--switching firemode
touch.firemode = table.copy(pc.firemode)
touch.firemode.conditions = {"LMB", "sneak"}
touch.firemode.func = function(active, interrupted, data, busy_list, gun, handler)
if active then
gun:cycle_firemodes()
end
end
--reloading
touch.reload = table.copy(pc.reload)
touch.reload.mode = "toggle"
--firing semi
touch.on_secondary_use = function(itemstack, handler, pointed_thing)
if not handler.control_handler.player_pressed.sneak then
pc.on_use(itemstack, handler, pointed_thing)
end
end
--full auto
touch.auto = table.copy(pc.auto)
touch.auto.conditions = {"LMB"}
touch.auto.func = function(active, interrupted, data, busy_list, gun, handler)
if (not handler.control_handler.player_pressed.sneak) and gun.properties.firemodes[gun.current_firemode] == "auto" then
gun:attempt_fire()
end
end