Files
2026-10-27 17:16:21 -04:00

122 lines
5.5 KiB
Lua

require "Vehicles/Papa_Chad_Tank_Cannon"
require "Vehicles/Papa_Chad_Tank_Aim"
MTKViewpointTurrets = MTKViewpointTurrets or {}
local M = MTKViewpointTurrets
local seats = { [0] = "SeatFrontLeft", [1] = "SeatGunner", [2] = "SeatFrontRight", [3] = "SeatRearRight" }
local scope = nil
local function enabled()
return MTKViewpointCamera and MTKViewpointCamera.enabled()
end
local function allowed(player, vehicle, weapon)
return player == getPlayer() and not player:isDead()
and MTKViewpointCamera.captured() and getGameSpeed() > 0
and not (UIManager and UIManager.isMouseOverInventory and UIManager.isMouseOverInventory())
and seats[vehicle:getSeat(player)] == weapon.requiredSeat
and player:getCharacterActions():isEmpty()
end
function M.install()
-- These local adapters register their own wrappers at boot/start. Install
-- them first, then wrap the completed chain, regardless of event order.
if KFTFerret and KFTFerret.installClient then KFTFerret.installClient() end
if KLTLAV and KLTLAV.installClient then KLTLAV.installClient() end
if not tankAimSystemPC or not chooseWeaponPC or not ISCoordConversion then return end
if ISCoordConversion.ToWorld ~= M.toWorld then
local previousToWorld = ISCoordConversion.ToWorld
M.toWorld = function(x, y, z)
-- Only override conversions inside this turret update. The Ferret
-- and LAV wrappers otherwise overwrite our camera heading with a
-- floor pick (or the screen-centre isometric fallback).
if scope and scope.x then return scope.x, scope.y end
return previousToWorld(x, y, z)
end
ISCoordConversion.ToWorld = M.toWorld
end
if chooseWeaponPC ~= M.choose then
local previousChoose = chooseWeaponPC
M.choose = function(vehicle)
-- MTK still advances existing projectiles when weapon input is
-- blocked; no simulation callback is removed or duplicated.
if scope and scope.blocked then return nil end
return previousChoose(vehicle)
end
chooseWeaponPC = M.choose
end
if tankAimSystemPC ~= M.aim then
local previousAim = tankAimSystemPC
Events.OnPlayerUpdate.Remove(previousAim)
M.aim = function(player)
local vehicle = player and player:getVehicle()
if not enabled() or not vehicle then return previousAim(player) end
local weapon = chooseWeaponPC(vehicle)
if not weapon then return previousAim(player) end
local oldScope = scope
scope = { blocked = not allowed(player, vehicle, weapon) }
local oldDirection = nil
if not scope.blocked and isMouseButtonDown(1) then
local heading = MTKViewpointCamera.heading()
if type(heading) == "number" and heading == heading and math.abs(heading) < math.huge then
oldDirection = player:getDirectionAngle()
local rad = math.rad(heading)
scope.x = player:getX() + math.cos(rad) * 100
scope.y = player:getY() + math.sin(rad) * 100
player:setDirectionAngle(heading)
else
scope.blocked = true
end
end
-- Restore temporary input even if a dependency raises an error.
local ok, err = pcall(previousAim, player)
scope = oldScope
if oldDirection ~= nil then player:setDirectionAngle(oldDirection) end
if not ok then error(err) end
end
tankAimSystemPC = M.aim
Events.OnPlayerUpdate.Add(M.aim)
print("[MTKViewpointTurrets] MTK camera aiming registered; Ferret/LAV wrappers retained.")
end
if TankCursor and TankCursor.prerender ~= M.cursor then
local previousCursor = TankCursor.prerender
M.cursor = function(self)
if not enabled() then return previousCursor(self) end
-- MTK's two iso-projected textures cannot represent the 3D view.
-- A centred cross marks camera bearing; green means the turret
-- has caught up in yaw, not that ammunition or a hit is guaranteed.
local player = getPlayer()
local vehicle = player and player:getVehicle()
local weapon = vehicle and chooseWeaponPC(vehicle)
if not weapon or not allowed(player, vehicle, weapon) or not isMouseButtonDown(1) then return end
local heading = MTKViewpointCamera.heading()
if not heading then return end
local turret = turretAngles and turretAngles[vehicle:getId()]
local aligned = turret and math.abs(((turret - heading + 540) % 360) - 180) <= 2
local r, g, b = 1, 0.75, 0.25
if aligned then r, g, b = 0.3, 1, 0.4 end
local x = getCore():getScreenWidth() / 2 - self.x
local y = getCore():getScreenHeight() / 2 - self.y
self:drawRect(x - 9, y, 5, 1, 0.9, r, g, b)
self:drawRect(x + 4, y, 5, 1, 0.9, r, g, b)
self:drawRect(x, y - 9, 1, 5, 0.9, r, g, b)
self:drawRect(x, y + 4, 1, 5, 0.9, r, g, b)
end
TankCursor.prerender = M.cursor
end
end
Events.OnGameBoot.Add(M.install)
Events.OnGameStart.Add(M.install)
Events.OnGameStart.Add(function()
if not MTKViewpointCamera then
print("[MTKViewpointTurrets] Camera bridge unavailable. Enable this mod and approve its local JAR in ZombieBuddy, then fully restart the game.")
end
end)