Files
FunctionalTurrets/Contents/mods/FunctionalTurretsLAV300/42.20/media/lua/client/KLT_LAVClient.lua
T
2026-10-27 17:27:44 -04:00

124 lines
5.3 KiB
Lua

require "KLT_LAV"
require "TimedActions/KLT_ReloadLAV"
require "Vehicles/Papa_Chad_Tank_Cannon"
local F = KLTLAV
local characterVariables = {
"M2_idle", "M2_360Anim", "M2_045Anim", "M2_090Anim", "M2_135Anim",
"M2_180Anim", "M2_225Anim", "M2_270Anim", "M2_315Anim",
}
function F.installClient()
if F.clientInstalled then return end
if not weaponConfig or not weaponConfig.M41_76mm
or not chooseWeaponPC or not tankAimSystemPC then
print("[KI5LAVTurret] MTK turret API unavailable; controls not installed.")
return
end
local profile = {}
for key, value in pairs(weaponConfig.M41_76mm) do profile[key] = value end
profile.requiredPart = F.weaponPart
profile.requiredSeat = "SeatGunner" -- MTK's label for index 1, not a renamed seat.
profile.requiredItem = F.ammoType
profile.requiredItemHE = F.heAmmoType
profile.coax = false
profile.sound = "HRSys_LAV300_90mm_Fire"
profile.soundEnd = "HRSys_LAV300_90mm_End"
profile.rotationTime = 10
profile.shotsPerMinute = 12
profile.startHeight = 0.7
profile.penetrationMM = 150
profile.soundTurret = "Turret_Electre"
profile.soundTurretCooldown = 0.25
weaponConfig[F.weaponPart] = profile
F.profile = profile
-- Keep AP damage unchanged. HE uses precisely the tank profile's explosion
-- radius, flash radius and damage, with MTK's existing explosion code.
local heProfile = {}
for key, value in pairs(profile) do heProfile[key] = value end
heProfile.penetrationMM = weaponConfig.M41_76mm.penetrationMM
F.heProfile = heProfile
local originalChoose = chooseWeaponPC
chooseWeaponPC = function(vehicle)
if F.isLAV(vehicle) then
if not F.inputBlocked and F.weaponReady(vehicle) and not F.pendingReload[getPlayer()] then
local part = vehicle:getPartById(F.weaponPart)
local container = part and part:getItemContainer()
if container and container:containsType(F.heAmmoType) then return heProfile end
return profile
end
return nil
end
return originalChoose(vehicle)
end
local originalAim = tankAimSystemPC
Events.OnPlayerUpdate.Remove(originalAim)
tankAimSystemPC = function(player)
local vehicle = player and player:getVehicle()
if not F.isLAV(vehicle) then return originalAim(player) end
local gunner = F.isGunner(vehicle, player) and player == getPlayer() and not player:isDead()
local overInventory = UIManager and UIManager.isMouseOverInventory
and UIManager.isMouseOverInventory()
-- Still call MTK so its existing projectiles continue to advance. A nil
-- weapon prevents input/state changes from driver or non-local updates.
F.inputBlocked = not gunner or overInventory or getGameSpeed() == 0
if F.inputBlocked then
originalAim(player)
F.inputBlocked = false
return
end
local oldDirection = player:getDirectionAngle()
local oldSneaking = player:isSneaking()
local oldVariables = {}
for _, name in ipairs(characterVariables) do oldVariables[name] = player:getVariableString(name) end
local aiming = isMouseButtonDown(1) and player:getCharacterActions():isEmpty()
if aiming then
-- ToWorld also uses the installed Viewpoint mouse bridge when active.
-- Scaled mouse coordinates are required by the base-game conversion.
local x, y = ISCoordConversion.ToWorld(getMouseXScaled(), getMouseYScaled(), player:getZ() + profile.startHeight)
if x and y then
local dx, dy = x - player:getX(), y - player:getY()
if dx * dx + dy * dy > 0.0001 then
player:setDirectionAngle(math.deg(math.atan2(dy, dx)))
end
end
end
local weapon = vehicle:getPartById(F.weaponPart)
local container = weapon and weapon:getItemContainer()
local round = aiming and isMouseButtonDown(0) and container and (container:FindAndReturn(F.heAmmoType) or container:FindAndReturn(F.ammoType))
originalAim(player)
if round and isClient() and not container:contains(round) then
sendRemoveItemFromContainer(container, round)
end
-- Keep DAMN's existing seated pose instead of MTK's exposed M2 gunner pose.
player:setDirectionAngle(oldDirection)
player:setSneaking(oldSneaking)
for _, name in ipairs(characterVariables) do
if oldVariables[name] and oldVariables[name] ~= "" then
player:setVariable(name, oldVariables[name])
else
player:clearVariable(name)
end
end
if aiming and turretAngles[vehicle:getId()] and not isClient() then
local hull = calculateVehicleRotation(vehicle:getAngleX(), vehicle:getAngleY(), vehicle:getAngleZ())
local relative = (hull - turretAngles[vehicle:getId()] + 360) % 360
F.savePose(vehicle, F.poseForAngle(relative))
end
end
Events.OnPlayerUpdate.Add(tankAimSystemPC)
F.clientInstalled = true
print("[KI5LAVTurret] Gunner controls registered with Military Tool Kit.")
end
Events.OnGameBoot.Add(F.installClient)
Events.OnGameStart.Add(F.installClient)