Files
barotrauma-localmods/Real Sonar/Lua/sonarping.lua
2025-03-31 13:19:47 +02:00

230 lines
10 KiB
Lua

-- It would technically be faster to patch the Barotrauma.Items.Components.Sonar.Use method.
-- But doing so would not allow me to stop the default ping sound from playing.
Hook.Patch(
"Barotrauma.Item", "Use", function(instance, ptable)
if not RealSonar.Config.CustomSonar then
return
end
local instance_sonar = instance.GetComponentString("Sonar")
for terminal in RealSonar.sonarItems do
if terminal.GetComponentString("Sonar") == instance_sonar and tostring(instance_sonar.CurrentMode) == "Active" then
if instance_sonar.UseDirectionalPing then
Hook.Call("sonarPingDirectional", nil, nil, terminal)
else
Hook.Call("sonarPing", nil, nil, terminal)
end
-- Prevent default ping sound from playing.
ptable.PreventExecution = true
end
end
end, Hook.HookMethodType.Before)
Hook.Add("sonarPing", "sonarPing", function(effect, deltaTime, item, targets, worldPosition)
local terminal_id = item.Prefab.Identifier.Value
local sonar = item.GetComponentString("Sonar")
-- deltaTime being passed in means that the hook was called from XML
if RealSonar.Config.CustomSonar and deltaTime then
-- If the terminal is registered cancel the XML status effect.
if RealSonar.Config.SonarTerminals[terminal_id] then
return true
-- Otherwise, add the terminal to the config.
else
RealSonar.Config.SonarTerminals[terminal_id] = {}
RealSonar.Config.SonarTerminals[terminal_id]["damage"] = "high"
RealSonar.Config.SonarTerminals[terminal_id]["sounds"] = "default"
RealSonar.Config.SonarTerminals[terminal_id]["range"] = sonar.Range
table.insert(RealSonar.sonarItems, item)
print("Real Sonar: Automatically added '", terminal_id, "' to config with default values.")
end
end
local distance
local amount
local terminal_type
local sonarResistanceData
local damageMultiplier
local muffleSonar
-- Select correct sound-playing function.
local soundPreset = "default"
if RealSonar.Config.SonarTerminals[terminal_id] then
soundPreset = RealSonar.Config.SonarTerminals[terminal_id]["sounds"]
end
local airSounds = RealSonar.airSounds
local waterSounds = RealSonar.waterSounds
local suitSounds = RealSonar.suitSounds
if soundPreset == "shuttle" then
airSounds = RealSonar.airSoundsShuttle
waterSounds = RealSonar.waterSoundsShuttle
suitSounds = RealSonar.suitSoundsShuttle
end
terminal_type = RealSonar.getTerminalType(terminal_id)
for _, character in pairs(Character.CharacterList) do
distance = RealSonar.distanceBetween(item.worldPosition, character.worldPosition)
if distance < sonar.Range and not character.isDead then
amount = (1 - distance / sonar.Range) * 100
-- Air sounds.
if not character.InWater or not RealSonar.isEnabledForTerminal(terminal_id) or not RealSonar.pathToBreach(character) then
if character.isPlayer then
airSounds(character, amount)
end
elseif RealSonar.isEnabledForTerminal(terminal_id) and RealSonar.pathToBreach(character) then
sonarResistanceData = RealSonar.getSonarResistanceData(character)
damageMultiplier = sonarResistanceData[1]
muffleSonar = sonarResistanceData[2]
-- Damage.
RealSonar.GiveAffliction(character, string.format("activesonar%slua", terminal_type), (amount * damageMultiplier) * RealSonar.Config.SonarDamage)
-- Stun & slow.
if character.isHuman and not muffleSonar then
RealSonar.GiveAffliction(character, string.format("sonarshakestun%s", terminal_type), (amount * damageMultiplier) * RealSonar.Config.ImpactVisuals)
RealSonar.SetAffliction(character, string.format("sonarslow%s", terminal_type), (amount * damageMultiplier) * RealSonar.Config.SonarSlow)
end
-- Water sounds & impact visuals.
if not muffleSonar and character.isPlayer then
RealSonar.GiveAffliction(character, string.format("sonarvisuals%s", terminal_type), (amount * damageMultiplier) * RealSonar.Config.ImpactVisuals)
waterSounds(character, amount * damageMultiplier)
-- Suit sounds.
elseif character.isPlayer then
suitSounds(character, amount)
end
-- Bot messages.
if terminal_id ~= "sonarmonitor" and character.isBot and character.IsOnPlayerTeam and not character.IsUnconscious then
character.Speak(TextManager.Get("dialogturnoffsonar").Value, nil, 0.5, "dialogturnoffsonar", 5)
end
end
end
end
-- Cancel the rest of the Status Effect.
return true
end)
Hook.Add("sonarPingDirectional", "sonarPingDirectional", function(effect, deltaTime, item, targets, worldPosition)
local terminal_id = item.Prefab.Identifier.Value
local sonar = item.GetComponentString("Sonar")
-- deltaTime being passed in means that the hook was called from XML
if RealSonar.Config.CustomSonar and deltaTime then
-- If the terminal is registered cancel the XML status effect.
if RealSonar.Config.SonarTerminals[terminal_id] then
return true
-- Otherwise, add the terminal to the config.
else
RealSonar.Config.SonarTerminals[terminal_id] = {}
RealSonar.Config.SonarTerminals[terminal_id]["damage"] = "high"
RealSonar.Config.SonarTerminals[terminal_id]["sounds"] = "default"
RealSonar.Config.SonarTerminals[terminal_id]["range"] = sonar.Range
table.insert(RealSonar.sonarItems, item)
print("Real Sonar: Automatically added '", terminal_id, "' to config with default values.")
end
end
local distance
local amount
local terminal_type
local sonarResistanceData
local damageMultiplier
local muffleSonar
local soundRangeMultiplier = 2.0
local inConeDamageMultiplier = 1.5
local outConeDamageMultiplier = 0.6
-- Select correct sound-playing function.
local soundPreset = "default"
if RealSonar.Config.SonarTerminals[terminal_id] then
soundPreset = RealSonar.Config.SonarTerminals[terminal_id]["sounds"]
end
local airSoundsDirectional = RealSonar.airSoundsDirectional
local waterSoundsDirectional = RealSonar.waterSoundsDirectional
local suitSoundsDirectional = RealSonar.suitSoundsDirectional
local waterSounds = RealSonar.waterSounds
local suitSounds = RealSonar.suitSounds
if soundPreset == "shuttle" then
airSoundsDirectional = RealSonar.airSoundsShuttleDirectional
waterSoundsDirectional = RealSonar.waterSoundsShuttleDirectional
suitSoundsDirectional = RealSonar.suitSoundsShuttleDirectional
waterSounds = RealSonar.waterSoundsShuttle
suitSounds = RealSonar.suitSoundsShuttle
end
terminal_type = RealSonar.getTerminalType(terminal_id)
for _, character in pairs(Character.CharacterList) do
distance = RealSonar.distanceBetween(item.worldPosition, character.worldPosition)
if distance < sonar.Range and not character.isDead then
amount = (1 - distance / sonar.Range) * 100
-- Air sounds.
if (not character.InWater or not RealSonar.isEnabledForTerminal(terminal_id) or not RealSonar.pathToBreach(character)) and character.isPlayer then
airSoundsDirectional(character, amount)
elseif RealSonar.isEnabledForTerminal(terminal_id) and RealSonar.pathToBreach(character) then
sonarResistanceData = RealSonar.getSonarResistanceData(character)
damageMultiplier = sonarResistanceData[1]
muffleSonar = sonarResistanceData[2]
-- Being aimed at.
if RealSonar.inDirectionalSector(character, item) then
-- Damage.
RealSonar.GiveAffliction(character, string.format("activesonar%slua", terminal_type), ((amount * damageMultiplier) * inConeDamageMultiplier) * RealSonar.Config.SonarDamage)
-- Stun & slow.
if character.isHuman and not muffleSonar then
RealSonar.GiveAffliction(character, string.format("sonarshakestun%s", terminal_type), ((amount * damageMultiplier) * inConeDamageMultiplier) * RealSonar.Config.ImpactVisuals)
RealSonar.SetAffliction(character, string.format("sonarslow%s", terminal_type), ((amount * damageMultiplier) * inConeDamageMultiplier) * RealSonar.Config.SonarSlow)
end
-- Water sounds & impact visuals.
if not muffleSonar and character.isPlayer then
RealSonar.GiveAffliction(character, string.format("sonarvisuals%s", terminal_type), ((amount * damageMultiplier) * inConeDamageMultiplier) * RealSonar.Config.ImpactVisuals)
waterSounds(character, (amount * damageMultiplier) * soundRangeMultiplier)
-- Suit sounds.
elseif character.isPlayer then
suitSounds(character, (amount * damageMultiplier) * soundRangeMultiplier)
end
-- Bot messages.
if terminal_id ~= "sonarmonitor" and character.isBot and character.IsOnPlayerTeam and not character.IsUnconscious then
character.Speak(TextManager.Get("dialogturnoffsonar").Value, nil, 0.5, "dialogturnoffsonar", 5)
end
-- Not being aimed at.
else
-- Damage.
RealSonar.GiveAffliction(character, string.format("activesonar%slua", terminal_type), ((amount * damageMultiplier) * outConeDamageMultiplier) * RealSonar.Config.SonarDamage)
-- Water sounds.
if not muffleSonar and character.isPlayer then
waterSoundsDirectional(character, amount)
-- Suit sounds.
elseif character.isPlayer then
suitSoundsDirectional(character, amount)
end
end
end
end
end
-- Cancel the rest of the Status Effect.
return true
end)