Merge branch 'canc_reload' into 'main'
Cancel reloading when switching to another weapon and start to reload again when re-grabbing the previous weapon Closes #2 See merge request zughy-friends-minetest/weapons_lib!3
This commit is contained in:
commit
60af7e3a81
4
DOCS.md
4
DOCS.md
@ -34,6 +34,7 @@ Then there are the built-in weapons_lib parameters:
|
||||
* `slow_down_user`: (boolean) whether the player should be slowed down when attacking and reloading. Default is `false`.
|
||||
* **Beware**: changing player's velocity whilst slowed down will break their speed if a fixed value is used. Weapons_lib *cannot* know if there are any external mods interfering, so either rely on multipliers or be very careful when you perform such changes (meaning don't do it if you think they might have a weapon). Related: `wl_slowed_down` metadata
|
||||
* `can_use_weapon`: (function(player, \<action>)) additional checks about whether the weapon can be used (reloading included). Return `true` to proceed
|
||||
* Not called with `"zoom"` actions. Zoom is always allowed (TODO remove it?)
|
||||
* reloading doesn't pass any action
|
||||
* actions with `continuous_fire` run the check before every bullet/hit
|
||||
* `can_alter_speed`: (function(player)) additional checks about whether to prevent slowing down/speeding up again the player
|
||||
@ -47,7 +48,8 @@ Then there are the built-in weapons_lib parameters:
|
||||
* `total_damage`: the sum of the damage that should have been inflicted to all the targets. weapons_lib cannot know if an external mod altered the damage of the weapon (e.g. via `minetest.register_on_punchplayer(..)`)
|
||||
* `on_recovery_end`: (function(player, weapon, action)) additional behaviour for when the weapon is ready to be used again
|
||||
* `on_reload`: (function(player, weapon)) additional behaviour when reloading
|
||||
* `on_reload_end`: (function(player, weapon)) additional behaviour when the weapon has successfully finished reloading
|
||||
* `on_reload_end`: (function(player, weapon, skip_refill)) additional behaviour when the weapon has finished reloading
|
||||
* `skip_refill` is a boolean passed when reloading is interrupted (e.g. when switching to another weapon)
|
||||
* `action1`: (table) action on left click
|
||||
* `action2`: (table) action on right click
|
||||
* `action1_hold`: (table, melee only) action on left click if kept pressed for 0.3s. NOT YET IMPLEMENTED, [waiting for MT](https://gitlab.com/zughy-friends-minetest/weapons_lib/-/issues/7)
|
||||
|
@ -16,6 +16,7 @@ local function attack_end() end
|
||||
local function recovery_end() end
|
||||
local function zoom() end
|
||||
local function reload() end
|
||||
local function reload_cancel() end
|
||||
local function reload_end() end
|
||||
local function draw_particles() end
|
||||
local function wl_debug() end
|
||||
@ -32,8 +33,9 @@ local debug_p_list = weapons_lib.settings.DEBUG_PLAYERS_LIST
|
||||
local slow_down_func = {} -- KEY: p_name; VALUE: timer func
|
||||
local reload_func = {} -- KEY: p_name; VALUE: reload func
|
||||
local recovery_func = {} -- KEY: p_name; VALUE: recover_func
|
||||
local data = {} -- KEY: p_name; VALUE: {current_weapon, action_in_progress_weapon = {(string) w_name, (string) actn_name},
|
||||
-- magazine = {w_name1 = amount, w_name2 = amount}, last_physics = {MT physics params, _was_slowed_down}}
|
||||
local data = {} -- KEY: p_name; VALUE: {current_weapon, current_stack, action_in_progress_weapon = {(string) w_name, (string) actn_name},
|
||||
-- magazine = {w_name1 = amount, w_name2 = amount}, last_physics = {MT physics params, _was_slowed_down},
|
||||
-- reload_timestamp = {time, prev_state, prev_actn}}
|
||||
local registered_weaps = {} -- KEY: w_name; VALUE: {(int) magazine}
|
||||
|
||||
|
||||
@ -84,7 +86,17 @@ minetest.register_globalstep(function(dtime)
|
||||
weapons_lib.deactivate_zoom(player, minetest.registered_nodes[prev_w_name])
|
||||
end
|
||||
|
||||
-- (da implementare) se stava caricando o si stava parando, annulla l'azione
|
||||
-- interrompo eventuale ricarica
|
||||
if weap_state == 4 then
|
||||
reload_cancel(pl_name, minetest.registered_nodes[prev_w_name], pl_data.current_stack)
|
||||
end
|
||||
|
||||
-- se il nuovo oggetto è un'arma e sta a secco, comincio la ricarica
|
||||
if is_weapon and registered_weaps[w_name].magazine and data[pl_name].magazine[w_name] == 0 then
|
||||
reload(player, minetest.registered_nodes[w_name], wld_item)
|
||||
end
|
||||
|
||||
-- se stava caricando o si stava parando, annulla l'azione
|
||||
-- TODO: probabilmente meglio far questi controlli sulle funzioni corrispettive,
|
||||
-- una volta che queste funzionalità saranno presenti. Qua attack_end rischia
|
||||
-- di far danni come già faceva con weap_state == 2 (con controllo infatti
|
||||
@ -92,10 +104,17 @@ minetest.register_globalstep(function(dtime)
|
||||
if weap_state == 1 or weap_state == 5 then
|
||||
local prev_weap_def = minetest.registered_nodes[prev_w_name]
|
||||
local actn_name = pl_data.action_in_progress_weapon.actn_name
|
||||
attack_end(player, prev_weap_def, weapon, prev_weap_def[actn_name]) -- TODO non esiste weapon e non so manco se possa ottenerlo in qualche modo
|
||||
attack_end(player, prev_weap_def, pl_data.current_stack, prev_weap_def[actn_name])
|
||||
end
|
||||
|
||||
if not is_weapon then
|
||||
pl_data.current_weapon = nil
|
||||
pl_data.current_stack = nil
|
||||
else
|
||||
pl_data.current_weapon = w_name
|
||||
pl_data.current_stack = wld_item
|
||||
end
|
||||
|
||||
pl_data.current_weapon = is_weapon and w_name or nil
|
||||
weapons_lib.HUD_crosshair_update(pl_name, w_name)
|
||||
end
|
||||
|
||||
@ -103,6 +122,12 @@ minetest.register_globalstep(function(dtime)
|
||||
else
|
||||
if is_weapon then
|
||||
pl_data.current_weapon = w_name
|
||||
pl_data.current_stack = wld_item
|
||||
|
||||
-- se la nuova arma sta a secco, comincio la ricarica
|
||||
if registered_weaps[w_name].magazine and data[pl_name].magazine[w_name] == 0 then
|
||||
reload(player, minetest.registered_nodes[w_name], wld_item)
|
||||
end
|
||||
|
||||
-- se un'arma stava caricando, il mirino mostralo rosso
|
||||
weapons_lib.HUD_crosshair_update(pl_name, w_name)
|
||||
@ -237,17 +262,12 @@ end
|
||||
|
||||
|
||||
|
||||
function weapons_lib.refill(p_name, weap_def)
|
||||
function weapons_lib.refill(p_name, weapon)
|
||||
local weap_def = minetest.registered_nodes[weapon:get_name()]
|
||||
local p_meta = minetest.get_player_by_name(p_name):get_meta()
|
||||
|
||||
if p_meta:get_int("wl_weapon_state") == 4 then
|
||||
reload_func[p_name]:cancel()
|
||||
|
||||
if weap_def.sound_reload then
|
||||
weapons_lib.stop_sound(weap_def.sound_reload, p_name)
|
||||
end
|
||||
|
||||
reload_end(minetest.get_player_by_name(p_name), weap_def)
|
||||
reload_cancel(p_name, weap_def, weapon, true)
|
||||
end
|
||||
|
||||
data[p_name].magazine[weap_def.name] = weap_def.magazine
|
||||
@ -859,8 +879,15 @@ function reload(player, weap_def, weapon) -- TODO: prob da esporre in futuro
|
||||
weapons_lib.play_sound(weap_def.sound_reload, p_name)
|
||||
end
|
||||
|
||||
local p_data = data[p_name]
|
||||
local prev_actn = p_data.action_in_progress_weapon and p_data.action_in_progress_weapon.actn_name
|
||||
|
||||
-- il marcatore temporale serve in caso la ricarica venga annullata, per capire
|
||||
-- se delay di prev_actn è finito o meno (e capire se si possono eseguire già altre azioni)
|
||||
p_data.reload_timestamp = {time = minetest.get_us_time(), prev_state = p_meta:get_int("wl_weapon_state"), prev_actn = prev_actn}
|
||||
p_data.action_in_progress_weapon = {w_name = weap_def.name, actn_name = nil}
|
||||
|
||||
p_meta:set_int("wl_weapon_state", 4)
|
||||
data[p_name].action_in_progress_weapon = {w_name = weap_def.name, actn_name = nil}
|
||||
|
||||
-- rimuovo eventuale zoom
|
||||
if p_meta:get_int("wl_zooming", 1) then
|
||||
@ -885,40 +912,98 @@ function reload(player, weap_def, weapon) -- TODO: prob da esporre in futuro
|
||||
reload_func[p_name] = minetest.after(reload_time, function()
|
||||
if not minetest.get_player_by_name(p_name) or p_meta:get_int("wl_weapon_state") == 0 then return end -- se è morto nel mentre (meta), annullo
|
||||
|
||||
reload_end(player, weap_def)
|
||||
reload_end(player, weap_def, weapon)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function reload_end(player, weap_def)
|
||||
function reload_cancel(p_name, weap_def, weapon, refill_weapon)
|
||||
wl_debug(p_name, "Cancel reloading | (" .. weap_def.description .. ")")
|
||||
|
||||
reload_func[p_name]:cancel()
|
||||
|
||||
if weap_def.sound_reload then
|
||||
weapons_lib.stop_sound(weap_def.sound_reload, p_name)
|
||||
end
|
||||
|
||||
reload_end(minetest.get_player_by_name(p_name), weap_def, weapon, not refill_weapon)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function reload_end(player, weap_def, weapon, skip_refill)
|
||||
local p_meta = player:get_meta()
|
||||
local p_name = player:get_player_name()
|
||||
|
||||
p_meta:set_int("wl_weapon_state", 0)
|
||||
|
||||
wl_debug(p_name, "Terminate reloading | (" .. weap_def.description .. ")")
|
||||
|
||||
if weap_def.slow_down_user
|
||||
and (not weap_def.can_alter_speed or weap_def.can_alter_speed(player))
|
||||
and p_meta:get_int("wl_is_speed_locked") == 0 then
|
||||
speed_up(player, weap_def.mod)
|
||||
local p_data = data[p_name]
|
||||
|
||||
-- se stava ricaricando subito dopo lo sparo e cambia subito arma (quindi ricarica
|
||||
-- annullata), deve rimanere in fase di recupero così da non permettere alle altre
|
||||
-- armi di sparare immediatamente, oltre che a mantenere la velocità rallentata
|
||||
if skip_refill and p_data.reload_timestamp.prev_actn then
|
||||
local timestamp = p_data.reload_timestamp
|
||||
local time_passed = (minetest.get_us_time() - timestamp.time) / 1000000
|
||||
local action = weap_def[timestamp.prev_actn]
|
||||
-- TODO: in verità se prev_state è 1 o 3 bisogna sottrarre il tempo già trascorso
|
||||
-- per vedere quanto ritardo rimane ancora. Per farlo serve prendere dal processo
|
||||
-- il tempo già passato tramite https://github.com/minetest/minetest/issues/15047.
|
||||
-- Al momento, invece, parte sempre da 0, creando un ritardo leggermente maggiore
|
||||
-- se x es. si ricarica, si aspetta qualche decimo e si cambia arma (si andrà
|
||||
-- lentɜ di quei decimi in più). Preferisco questo ritardo maggiorato al non fare
|
||||
-- affatto il controllo, che porterebbe lə giocante a velocizzarsi subito appena
|
||||
-- cambia arma, anche se stava in fase di caricamento/recupero
|
||||
local delay = get_val(weapon, action, "delay") -- Non considero un math.max(delay, 0.5) perché sono tempistiche irrisorie che complicherebbero soltanto il codice
|
||||
|
||||
-- passo in fase di recupero
|
||||
if time_passed < delay then
|
||||
p_meta:set_int("wl_weapon_state", 3)
|
||||
|
||||
minetest.after(delay-time_passed, function()
|
||||
if not minetest.get_player_by_name(p_name) then return end
|
||||
recovery_end(player, weap_def, action)
|
||||
end)
|
||||
|
||||
else
|
||||
-- TODO: semplifica qui in modo da non ripetere anche in basso
|
||||
p_meta:set_int("wl_weapon_state", 0)
|
||||
|
||||
if weap_def.slow_down_user
|
||||
and (not weap_def.can_alter_speed or weap_def.can_alter_speed(player))
|
||||
and p_meta:get_int("wl_is_speed_locked") == 0 then
|
||||
speed_up(player, weap_def.mod)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
p_meta:set_int("wl_weapon_state", 0)
|
||||
|
||||
if weap_def.slow_down_user
|
||||
and (not weap_def.can_alter_speed or weap_def.can_alter_speed(player))
|
||||
and p_meta:get_int("wl_is_speed_locked") == 0 then
|
||||
speed_up(player, weap_def.mod)
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: bisognerebbe controllare e disattivare durante la rimozione dell'arma,
|
||||
-- ma questa può avvenire in più modi (via codice, spostamento inventario, Q)
|
||||
if not player:get_inventory():contains_item("main", weap_def.name) then return end
|
||||
|
||||
local curr_weap = data[p_name].current_weapon
|
||||
if not skip_refill then
|
||||
p_data.magazine[weap_def.name] = weap_def.magazine
|
||||
end
|
||||
|
||||
local curr_weap = p_data.current_weapon
|
||||
|
||||
data[p_name].magazine[weap_def.name] = weap_def.magazine
|
||||
weapons_lib.HUD_crosshair_update(p_name, curr_weap, false)
|
||||
|
||||
if weap_def.on_reload_end then
|
||||
weap_def.on_reload_end(player, weap_def)
|
||||
weap_def.on_reload_end(player, weap_def, skip_refill)
|
||||
end
|
||||
|
||||
data[p_name].action_in_progress_weapon = nil
|
||||
p_data.action_in_progress_weapon = nil
|
||||
end
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user