Files
2026-07-23 16:35:06 +05:00

224 lines
7.6 KiB
Lua
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 脚本位置 "{命名空间}:{路径}"require 格式 "{命名空间}_{路径}"
local default = require("tacz_manual_action_state_machine")
local STATIC_TRACK_LINE = default.STATIC_TRACK_LINE
local MAIN_TRACK = default.MAIN_TRACK
local main_track_states = default.main_track_states
-- override idle state
local idle_state = setmetatable({}, {__index = main_track_states.idle})
-- custom reload state
local reload_state = {
need_ammo = 0,
loaded_ammo = 0
}
-- override start state so we control the draw animation
local start_state = setmetatable({}, { __index = main_track_states.start })
local end_state = setmetatable({}, { __index = main_track_states["end"] })
function end_state.transition(this, context, input)
if input == INPUT_PUT_AWAY then
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
local ammo = context:getAmmoCount() or 0
local hasBarrel = context:hasBulletInBarrel()
if ammo <= 0 and not hasBarrel then
context:runAnimation("put_away_empty", track, false, PLAY_ONCE_STOP, 0.15)
else
context:runAnimation("put_away", track, false, PLAY_ONCE_STOP, 0.15)
end
return nil
end
if main_track_states["end"] and main_track_states["end"].transition then
return main_track_states["end"].transition(this, context, input)
end
return nil
end
-------------------------------------------------------
-- UTILITY
-------------------------------------------------------
local function get_ejection_time(context)
local ejection_time = context:getStateMachineParams().intro_shell_ejecting_time
if (ejection_time) then
ejection_time = ejection_time * 1000
else
ejection_time = 0
end
return ejection_time
end
-------------------------------------------------------
-- INSPECT ANIM
-------------------------------------------------------
local function runInspectAnimation(context)
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
local ammo = context:getAmmoCount()
local hasBarrel = context:hasBulletInBarrel()
if (ammo <= 0 and not hasBarrel) then
context:runAnimation("inspect_empty", track, false, PLAY_ONCE_STOP, 0.2)
elseif (ammo <= 0) then
context:runAnimation("inspect_01", track, false, PLAY_ONCE_STOP, 0.2)
else
context:runAnimation("inspect", track, false, PLAY_ONCE_STOP, 0.2)
end
end
-------------------------------------------------------
-- START (DRAW) OVERRIDE — plays draw_empty when ammo == 0
-------------------------------------------------------
function start_state.transition(this, context, input)
-- when weapon is drawn the state machine sends INPUT_DRAW
if input == INPUT_DRAW then
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
local ammo = context:getAmmoCount() or 0
-- check chambered bullet too if you want fully empty detection:
local hasBarrel = context:hasBulletInBarrel()
if ammo <= 0 and not hasBarrel then
-- completely empty: draw_empty
context:runAnimation("draw_empty", track, false, PLAY_ONCE_STOP, 0.15)
else
-- has ammo somewhere: normal draw
context:runAnimation("draw", track, false, PLAY_ONCE_STOP, 0.15)
end
-- after draw, go to idle
return this.main_track_states.idle
end
-- any other inputs: delegate to default start transition
if main_track_states.start and main_track_states.start.transition then
return main_track_states.start.transition(this, context, input)
end
return nil
end
-------------------------------------------------------
-- IDLE TRANSITION OVERRIDE (reload + inspect)
-------------------------------------------------------
function idle_state.transition(this, context, input)
if input == INPUT_PUT_AWAY then
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
local ammo = context:getAmmoCount() or 0
local hasBarrel = context:hasBulletInBarrel()
if ammo <= 0 and not hasBarrel then
context:runAnimation("put_away_empty", track, false, PLAY_ONCE_HOLD, 0.15)
else
context:runAnimation("put_away", track, false, PLAY_ONCE_HOLD, 0.15)
end
-- let default machine go to end state
return this.main_track_states["end"]
end
if input == INPUT_RELOAD then
return this.main_track_states.reload
end
if input == INPUT_INSPECT then
runInspectAnimation(context)
return this.main_track_states.inspect
end
return main_track_states.idle.transition(this, context, input)
end
-------------------------------------------------------
-- RELOAD ENTRY
-------------------------------------------------------
function reload_state.entry(this, context)
local state = this.main_track_states.reload
local ammo = context:getAmmoCount() or 0
local hasBarrel = context:hasBulletInBarrel()
local empty = (ammo <= 0 and not hasBarrel)
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
if empty then
state.timestamp = context:getCurrentTimestamp()
state.ejection_time = get_ejection_time(context)
context:runAnimation("reload_intro_empty", track, false, PLAY_ONCE_HOLD, 0.2)
else
state.timestamp = -1
state.ejection_time = 0
context:runAnimation("reload_intro", track, false, PLAY_ONCE_HOLD, 0.2)
end
state.need_ammo = context:getMaxAmmoCount() - context:getAmmoCount()
state.loaded_ammo = 0
end
-------------------------------------------------------
-- RELOAD UPDATE
-------------------------------------------------------
function reload_state.update(this, context)
local state = this.main_track_states.reload
-- empty intro shell eject
if (state.timestamp ~= -1 and context:getCurrentTimestamp() - state.timestamp > state.ejection_time) then
context:popShellFrom(0)
state.timestamp = -1
end
if (state.loaded_ammo > state.need_ammo or not context:hasAmmoToConsume()) then
context:trigger(this.INPUT_RELOAD_RETREAT)
return
end
local track = context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK)
if (context:isHolding(track)) then
context:runAnimation("reload_loop", track, false, PLAY_ONCE_HOLD, 0)
state.loaded_ammo = state.loaded_ammo + 1
end
end
-------------------------------------------------------
-- RELOAD TRANSITION END
-------------------------------------------------------
function reload_state.transition(this, context, input)
if (input == this.INPUT_RELOAD_RETREAT or input == INPUT_CANCEL_RELOAD) then
context:runAnimation("reload_end", context:getTrack(STATIC_TRACK_LINE, MAIN_TRACK), false, PLAY_ONCE_STOP, 0.2)
return this.main_track_states.idle
end
return this.main_track_states.idle.transition(this, context, input)
end
-------------------------------------------------------
-- EXPORT MACHINE
-------------------------------------------------------
local M = setmetatable({
main_track_states = setmetatable({
start = start_state,
idle = idle_state,
reload = reload_state,
["end"] = end_state,
}, { __index = main_track_states }),
INPUT_RELOAD_RETREAT = "reload_retreat",
}, { __index = default })
function M:initialize(context)
default.initialize(self, context)
self.main_track_states.reload.need_ammo = 0
self.main_track_states.reload.loaded_ammo = 0
end
return M