Optimize this code, improve the code, structure the code, improve the interface in this lua code for teardown
```lua
-- options.lua

function DrawDynamicTextButtons(condition, text1, text2, w, h, font, size, R, G, B)
    local press = false
    UiPush()
        UiButtonPressDist(3)
        UiFont(font, size)
        UiButtonImageBox("ui/common/box-outline-6.png", 6, 6)
        if condition then
            UiColor(R, G, B)
            UiButtonHoverColor(R*10, G*0.6, B*0.2)
            if UiTextButton(text2, w, h) then
                condition = not condition
                press = true
            end
        else
            UiColor(1, 1, 1)
            UiButtonHoverColor(R*0.6, G, B*0.6)
            if UiTextButton(text1, w, h) then
                condition = not condition
                press = true
            end
        end
    UiPop()
    return press, condition
end

-- need to copy and paste this because the #include keyword stopped working
function KeyInit()
	setKey("savegame.mod.fire", true, true)
	setKey("savegame.mod.dca", true, true)
	setKey("savegame.mod.damage", true, true)
	setKey("savegame.mod.machinegun", true, true)
	setKey("savegame.mod.aircraft", true, true)
	setKey("savegame.mod.mortar", true, true)
	setKey("savegame.mod.music", true, true)
	setKey("savegame.mod.lowconfig", false, true)
	setKey("savegame.mod.start", false, true)
	setKey("savegame.mod.start.key", 'c', false)
	setKey("savegame.mod.flak", true, true)
end

function setKey(key, default, boolean, infinite)

	boolean = boolean or false
	infinite = infinite or false
	
	if not HasKey(key) then
		if boolean then
			SetBool(key, default)
		else
			SetString(key, default)
		end
	end
	if infinite then
		if not HasKey(key .. "_infinite") then
			SetBool(key .. "_infinite", false)
		end
	end
end

function init()
	KeyInit()
end


function draw()
	UiTranslate(UiCenter(), 0)
	UiAlign("center middle")

	--Draw buttons
	UiTranslate(0, 0)
	UiFont("regular.ttf", 26)
	UiButtonImageBox("ui/common/box-outline-6.png", 6, 6)
	
	local border = 80
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.fire", "Toggle this to randomnly spawn fire on start.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.dca", "Toggle this to have some DCA shots in the sky.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.damage", "Toggle this to randomnly destroy parts of the map on start (laggy during the first 30s of the simulation, as it progressively destroys the map).")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.lowconfig", "Toggle this if you have a small config and the previous feature make you crash or lag for too long.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.machinegun", "Toggle this to have machine gun sounds around you.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.aircraft", "Toggle this to make an aircraft pass sometimes in the sky.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.mortar", "Toggle this to add random mortar shots on the map.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.music", "Toggle this to activate the music.")
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.start", "Toggle this to activate the mod when you press any key you want instead of on-start. This allows you to freely set up your scene and also ending it.")
	UiTranslate(0, border)
	triggerkey = GetString("savegame.mod.start.key")
	if triggerkey ~= "" then
		keyDisplay = triggerkey
	else
		keyDisplay = "Not Assigned"
	end
	change, changeKey = DrawDynamicTextButtons(changeKey, keyDisplay, "Press A Key", 150, 35, "regular.ttf", 26, 1, 1, 1)
	if changeKey and not autoEQ then
		if InputLastPressedKey() == "tab" or InputLastPressedKey() == "esc" then
			changeKey = false
		else
			if InputPressed(",") then
				changeKey = false
				SetString("savegame.mod.start.key", ",")
			elseif InputPressed(".") then
				changeKey = false
				SetString("savegame.mod.start.key", ".")
			elseif InputLastPressedKey() ~= "" then
				changeKey = false
				SetString("savegame.mod.start.key", InputLastPressedKey())
			end
		end
	else
		changeKey = false
	end
	
	UiTranslate(0, border)
	DrawBoolButton("savegame.mod.flak", "Toggle this to activate the flak explosions in the sky.")
	
	UiTranslate(0, 100)
	if UiTextButton("Close", 200, 40) then
		Menu()
	end
end

local function bool_to_int(value)
	return value == true and 1 or value == false and 0
end

local function int_to_bool(value)
	return value > 0
end

function DrawIntSlider(key, lowerbound, upperbound, size, text, infinite)
	infinite = infinite or false
	UiPush()
		UiAlign("center middle")
		UiFont("regular.ttf", 22)
		UiColor(0.9,0.9,0.025,1)
		local value = GetInt(key)
		if GetBool(key .. "_infinite") then
			value = "Infinite"
		end
		UiText(text .. " " .. value, true)
		UiColor(1,1,1,1)
		UiFont("regular.ttf", 26)
		UiImageBox("box-solid-6.png", (upperbound * size) - (lowerbound * (size * 0.5)), 20, 5, 5)
		UiTranslate(-((upperbound * (size*0.5)) + (lowerbound * (size*0.5))), 0)
		SetInt(key, UiSlider("dot_small.png", "x", GetInt(key) * size, lowerbound * size, upperbound * size) / size)
		if infinite then
			SetBool(key .. "_infinite", GetInt(key) == upperbound)
		end
	UiPop()
end

function DrawBoolButton(key, text)
	UiPush()
		UiAlign("center middle")
		UiFont("regular.ttf", 22)
		UiColor(0.9,0.9,0.025,1)
		UiText(text, true)
		UiTranslate(0, 15)
		if GetBool(key) then
			UiColor(0,1,0,1)
		else
			UiColor(1,0,0,1)
		end
		UiFont("regular.ttf", 26)
		if UiTextButton("Toggled: " .. tostring(GetBool(key))) then
			SetBool(key, not GetBool(key))
		end
	UiPop()
end
```
```
-- library.lua

--[[01-17-2022 (mm-dd-yyyy) version 0.7]]--



version = "0.7"
date = "Jan 17 2022"

function progressBar(w, h, t, R, G, B)
    local bar = t or 0
	UiPush()
		UiAlign("left top")
		UiColor(0, 0, 0, 0.5)
		UiImageBox("ui/common/box-solid-10.png", w, h, 6, 6)
		if bar > 0 then
			UiTranslate(2, 2)
			w = (w-4)*bar
			if w < 12 then w = 12 end
			h = h-4
			UiColor(R,G,B,1)
			UiImageBox("ui/common/box-solid-6.png", w, h, 6, 6)
		end
	UiPop()
end

function DrawSlider(value, length, R, G, B, dotR, dotG, dotB)
    UiPush()
        UiAlign("left middle")
        UiColor(R, G, B)
        UiRect(length+20, 20)
        UiColor(dotR, dotG, dotB)
        slidValue, done = UiSlider("ui/common/box-solid-4.png", x, value, 0, length)
    UiPop()
    return slidValue, done
end

function DrawSliderVirtical(value, length, screenLength, R, G, B, dotR, dotG, dotB)
    UiPush()
        UiScale(1, screenLength/(length+20))
        UiRotate(-90)
        UiAlign("left middle")
        UiColor(R, G, B)
        UiRect(length+20, 20)
        UiColor(dotR, dotG, dotB)
        slidValue, done = UiSlider("pic/ui/slider-vertical.png", x, value, 0, length)
    UiPop()
    return slidValue, done
end

function DrawNormalText(text, font, size, R, G, B)
    local newFont = FontList(font)
    UiPush()
        UiColor(R, G, B)
        UiFont(newFont, size)
        UiText(text)
    UiPop()
end

function DrawValueText(value, text, font, size, R, G, B)
    UiPush()
        UiAlign("left")
        UiColor(R, G, B)
        UiFont(font, size)
        UiText(value)
        w, h = UiGetTextSize(value)
        UiTranslate(h+w-18, 0)
        UiText(text)
    UiPop()
end

function DrawColoredTextButtons(condition, text, w, h, font, size, R, G, B)
    local newFont = FontList(font)
    UiPush()
        if condition then
            UiColor(R, G, B)
            UiButtonHoverColor(R*10, G*0.6, B*0.2)
        else
            UiColor(1, 1, 1)
            UiButtonHoverColor(R*0.6, G, B*0.6)
        end
        UiButtonPressDist(3)
        UiFont(newFont, size)
        UiButtonImageBox("ui/common/box-outline-6.png", 6, 6)
        if UiTextButton(text, w, h) then
            condition = not condition
            press = true
        else
            press = false
        end
    UiPop()
    return press, condition
end

function DrawDynamicTextButtons(condition, text1, text2, w, h, font, size, R, G, B)
    local press = false
    UiPush()
        UiButtonPressDist(3)
        UiFont(font, size)
        UiButtonImageBox("ui/common/box-outline-6.png", 6, 6)
        if condition then
            UiColor(R, G, B)
            UiButtonHoverColor(R*10, G*0.6, B*0.2)
            if UiTextButton(text2, w, h) then
                condition = not condition
                press = true
            end
        else
            UiColor(1, 1, 1)
            UiButtonHoverColor(R*0.6, G, B*0.6)
            if UiTextButton(text1, w, h) then
                condition = not condition
                press = true
            end
        end
    UiPop()
    return press, condition
end

function DrawColorPreview(R, G, B)
    UiPush()
        UiColor(R, G, B)
        UiRect(50, 50)
        UiTranslate(130, 0)
    UiPop()
end

function DrawRGBselecter(RGBs, path, branch1, branch2, branch3)
    DrawColorPreview(RGBs[1], RGBs[2], RGBs[3])
    UiTranslate(80, -24)
    UiPush()
        DrawValueText(math.floor(RGBs[1]*256), "", 6, 26, 1, 1, 1)
        UiTranslate(70, 0)
        Rt, rst = DrawSlider(RGBs[1]*256, 256, 0.2, 0.2, 0.2, 1, 0, 0)
        SetFloat(path..branch1, (math.floor(Rt)/256))
    UiPop()
    UiTranslate(0, 40)
    UiPush()
        DrawValueText(math.floor(RGBs[2]*256), "", 6, 26, 1, 1, 1)
        UiTranslate(70, 0)
        Gt, gst = DrawSlider(RGBs[2]*256, 256, 0.2, 0.2, 0.2, 0, 1, 0)
        SetFloat(path..branch2, (math.floor(Gt)/256))
    UiPop()
    UiTranslate(0, 40)
    UiPush()
        DrawValueText(math.floor(RGBs[3]*256), "", 6, 26, 1, 1, 1)
        UiTranslate(70, 0)
        Bt, bst = DrawSlider(RGBs[3]*256, 256, 0.2, 0.2, 0.2, 0, 0, 1)
        SetFloat(path..branch3, (math.floor(Bt)/256))
    UiPop()
end

function scrollAndDrag(windowW, windowH, contentLength, scrollSpeed, adjustFactor, background)

    local length = contentLength or 1
    local inputScrollFactor = scrollSpeed or 1
    local adjust = adjustFactor or 1

    local wheelMove = false
    local wheelMoveTime = 0
    local tempWheel = 0

    UiWindow(windowW, windowH, true)
    UiPush()
        UiTranslate(-1, -1)
        local alpha = background[4]
        if background[4] == nil then alpha = 1 end
        if background[1] > 1 or background[2] > 1 or background[3] > 1 or alpha > 1 then
            if background[4] == nil then alpha = 100 end
            UiColor(background[1]/255, background[2]/255, background[3]/255, alpha/100)
        else
            if background[4] == nil then alpha = 1 end
            UiColor(background[1], background[2], background[3], alpha)
        end
        UiRect(windowW+2, windowH+2)
    UiPop()
    local factor = length*100/(windowH-20)
    if UiIsMouseInRect(windowW, windowH) then
        if InputValue("mousewheel") ~= 0 then
            wheelMove = true
            tempWheel = InputValue("mousewheel")
            wheelMoveTime = GetTime()
        else
            if (GetTime()-wheelMoveTime) > 0.5 then
                wheelMove = false
            end
        end
        if wheelMove then
            SetValue("wheel", tempWheel*inputScrollFactor)
        else
            SetValue("wheel", 0)
        end
    end
    if factor ~= 0 then
        local newslide = slide - wheel*0.3
        SetValue("slide", newslide, linear, 2)
        if slide >= ((windowH-20)/20)*factor then slide = ((windowH-20)/20)*factor end
        if slide <= 0 then slide = 0 end
        UiPush()
            UiTranslate(windowW-10, 0)
            newslide, dragDone = DrawSliderVirtical(slide, ((windowH-20)/20)*factor, windowH, 0.2, 0.2, 0.2, 1, 1, 1)
        UiPop()
        SetValue("slide", newslide, linear, 2)
        if slide >= ((windowH-20)/20)*factor then slide = ((windowH-20)/20)*factor end
        if slide <= 0 then slide = 0 end
    end
    local slideOutput = -slide*adjust
    if factor == 0 then slideOutput = 0 end
    return slideOutput
end
```
```lua
-- main.lua
--This script will run on all levels when mod is active.
--Modding documentation: http://teardowngame.com/modding
--API reference: http://teardowngame.com/modding/api.html

function setKey(key, default, boolean, infinite)

	boolean = boolean or false
	infinite = infinite or false
	
	if not HasKey(key) then
		if boolean then
			SetBool(key, default)
		else
			SetString(key, default)
		end
	end
	if infinite then
		if not HasKey(key .. "_infinite") then
			SetBool(key .. "_infinite", false)
		end
	end
end

function KeyInit()
	setKey("savegame.mod.fire", true, true)
	setKey("savegame.mod.dca", true, true)
	setKey("savegame.mod.damage", true, true)
	setKey("savegame.mod.machinegun", true, true)
	setKey("savegame.mod.aircraft", true, true)
	setKey("savegame.mod.mortar", true, true)
	setKey("savegame.mod.music", true, true)
	setKey("savegame.mod.lowconfig", false, true)
	setKey("savegame.mod.start", false, true)
	setKey("savegame.mod.start.key", 'c', false)
	setKey("savegame.mod.flak", true, true)
end

function init()
	
	KeyInit()
	
	FIRE = GetBool("savegame.mod.fire")
	DCA = GetBool("savegame.mod.dca")
	DAMAGE_MAP = GetBool("savegame.mod.damage")
	MACHINEGUN_SND = GetBool("savegame.mod.machinegun")
	AIRCRAFT = GetBool("savegame.mod.aircraft")
	MORTAR = GetBool("savegame.mod.mortar")
	MUSIC = GetBool("savegame.mod.music")
	LOWCONFIG = GetBool("savegame.mod.lowconfig")
	START = not GetBool("savegame.mod.start")
	STARTKEY = GetString("savegame.mod.start.key")
	FLAK = GetBool("savegame.mod.flak")
	
	world = {}
	world.aa, world.bb = GetBodyBounds(GetWorldBody())
	
	if FIRE then
		fire = {}
		fire.spots = {}
		fire.spots = initSpots(10000)
		fire.first = true
	end
	
	if DAMAGE_MAP then
		explosion = {}
		explosion.spots = {}
		explosion.amount = 500
		explosion.defaultIntervalCooldown = 1.0
		explosion.step = 1
		explosion.intervalCooldown = explosion.defaultIntervalCooldown
		explosion.stepCount = 10
		exploPerStep = explosion.amount / explosion.stepCount
		
	end
	
	if DCA then
		dca = {}
		dca.defaultIntervalCooldown = 0.1
		dca.angleRotationPerSec = 5 -- per sec
		dca.spread = 0.03
		dca.defaultCooldown = 5
		dca.defaultRandomSalvo = 10
		dca.defaultSalvo = 10
		dca.spots = {}
		dca.spots = initDCASpots(10)
	end
	
	if MACHINEGUN_SND then
		mg = {}
		mg.spots = {}
		mg.snd = {}
		mg.snd[#mg.snd + 1] = LoadSound("snd/dca.ogg")
		mg.snd[#mg.snd + 1] = LoadSound("snd/gun.ogg")
		mg.snd[#mg.snd + 1] = LoadSound("snd/assault_rifle.ogg")
		mg.count = 3
		mg.defaultIntervalCooldown = 0.1
		mg.defaultCooldown = 3
		mg.defaultRandomSalvo = 4
		mg.defaultSalvo = 1
		mg.soundDist = 20
		mg.spots = initMachinegunSound(mg.count)
	end
	
	if AIRCRAFT then
		ac = {}
		ac.height = 50 + world.bb[2]
		ac.cooldown = 3
		ac.defaultCooldown = 10
		ac.speed = 250
		ac.body = 0
		ac.snd = LoadSound("snd/flyby_a10.ogg")
		ac.transform = Transform(Vec(0, -100, 0))
		local entities = Spawn("MOD/prefabs/airstrike_a10.xml", ac.transform)
		for i=1, #entities do
			if GetEntityType(entities[i]) == "body" then
				ac.body = entities[i]
				break
			end
		end
	end
	
	if MORTAR then
		mortar = {}
		mortar.delay = {
			default = 1.5,
			value = 1.5
		}
		mortar.first = false
		mortar.snd = LoadSound("snd/mortar.ogg")
		mortar.pos = Vec(0, 0, 0)
		mortar.explosion = rand(0,2)
		mortar.cooldown = {
			default = 1,
			value = mortar.explosion*2
		}
	end
	
	if FLAK then
		flak = {
			height = world.bb[2] + 200,
			explosion = 2.0,
			cooldown = {
				default = 0.8,
				value = 0.0
			}
		}
	end
	
end

function tick(dt)
	if START then
		if DCA then
			DCAShoot(dca.spots, dt)
		end
		
		if MACHINEGUN_SND then
			MGShoot(mg.spots, dt)
		end
		
		if AIRCRAFT then
			updateAircraft(dt)
		end
		
		if MORTAR then
			if updateCooldown(mortar.cooldown, mortar.explosion/2) then
				mortar.pos = getMortarPos()
				mortar.first = true
				PlaySound(mortar.snd,mortar.pos , 1.5)
			end
			if updateCooldown(mortar.delay, 0, mortar.first) then
				Explosion(mortar.pos, mortar.explosion)
				mortar.first = false
				mortar.explosion = rand(0,2)
				mortar.cooldown.value = mortar.explosion*2
				getFirePos(mortar.pos)
			end
		end

		if (InputPressed(STARTKEY)) then
			DebugPrint('stop')
			START = false
			StopMusic()
		end
	else
		if InputPressed(STARTKEY) then
			START = true
			if MUSIC then
				PlayMusic("snd/music.ogg")
			end
		end
	end
	
end


function update(dt)

	if START then
		if FIRE and fire.first then
			ambiantFire(fire.spots)
			fire.first = false
		end
	
		if DAMAGE_MAP and explosion.step < explosion.stepCount then
			explosion.intervalCooldown = explosion.intervalCooldown - dt
			if explosion.intervalCooldown <= 0 then
				explosion.intervalCooldown = explosion.defaultIntervalCooldown
				explosion.step = explosion.step + 1
				explosion.spots = initSpots(exploPerStep)
				if LOWCONFIG then
					holes(explosion.spots)
				else
					explosions(explosion.spots)
				end
			end
			SetPlayerHealth(1.0)
			clearDebris(2000)
		end
		
		if FLAK then
			updateFlak(flak, dt)
		end
	end
end


function draw(dt)

end

--------------------------------------------------------------------------------

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, deepcopy(getmetatable(orig)))
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

function rand(minv, maxv)
	minv = minv or nil
	maxv = maxv or nil
	if minv == nil then
		return math.random()
	end
	if maxv == nil then
		return math.random(minv)
	end
	return math.random(minv, maxv)
end

function updateCooldown(cd, variation, additionalCondition)
	variation = variation or 0
	if additionalCondition == nil then
		additionalCondition = true
	end
	cd.value = cd.value - GetTimeStep()
	if cd.value <= 0 then
		if variation >= 1 then
			variation = rand(variation)
		end
		cd.value = cd.default + variation
		return additionalCondition
	end
	return false
end

function debugWatchTable(t, addonName)
	addonName = addonName or ""
	for k, v in pairs(t) do
		DebugWatch(addonName .. " " .. k, v)
	end
end

--------------------------------------------------------------------------------

function clearDebris(size)
	size = size or 500
	local GetAllShapes = FindShapes(nil, true)
	for i, shape in ipairs(GetAllShapes) do
		if GetShapeVoxelCount(shape) <= size  and  IsShapeBroken(shape) == true then
			Delete(shape) 
		end
	end
end

function initSpots(count)
	local x = 0
	local y = 0
	local z = 0
	
	local down = Vec(0, -1, 0)
	local maxDist = world.bb[2] - world.aa[2]
	
	local spots = {}
	
	for i=1, count do
		x = rand(world.aa[1], world.bb[1])
		y = world.bb[2]
		z = rand(world.aa[3], world.bb[3])
		local hit, dist, normal, shape = QueryRaycast(Vec(x, y, z), down, maxDist, 0, true)
		if hit then
			local pos = Vec(x, y - dist, z)
			if not IsPointInWater(VecAdd(pos, Vec(0, 0.1, 0))) then
				spots[#spots + 1] = {}
				spots[#spots].pos = deepcopy(pos)
			end
		end
	end
	
	return deepcopy(spots)
end

function getMortarPos()
	local down = Vec(0, -1, 0)
	local maxDist = 65536
	local pos = Vec(0, 0, 0)
	x = rand(world.aa[1], world.bb[1])
	y = world.bb[2]
	z = rand(world.aa[3], world.bb[3])
	local hit, dist, normal, shape = QueryRaycast(Vec(x, y, z), down, maxDist)
	while (not hit) do
		x = rand(world.aa[1], world.bb[1])
		y = world.bb[2]
		z = rand(world.aa[3], world.bb[3])
		hit, dist, normal, shape = QueryRaycast(Vec(x, y, z), down, maxDist)
	end
	pos = Vec(x, y - dist, z)

	return deepcopy(pos)
end

function getFirePos(oldPos)
	local maxDist = 1
	local hit, point, normal, shape = QueryClosestPoint(oldPos, maxDist)
	SpawnFire(point)
end

function updateFlak(f, dt)
	if updateCooldown(f.cooldown) then
		local pos = randomPos(world.aa, world.bb)
		pos[2] = flak.height + rand(30) - 15
		Explosion(pos, flak.explosion)
	end
end

function initDCASpots(count)
	local spots = {}
	
	for i=1, count do
		spots[#spots + 1] = {}
		local pos = randomPosBorder()
		--local orientation = GetQuatEuler(QuatLookAt(pos, Vec(randomInterpolate(world.aa[1], world.bb[1]), 0, randomInterpolate(world.aa[3], world.bb[3]))))
		local orientation = rand() * 360 - 180
		local angle = 45
		spots[#spots].t = Transform(deepcopy(pos), QuatEuler(angle, orientation, 0))
		
		spots[#spots].defaultCooldown = dca.defaultCooldown
		spots[#spots].cooldown = rand(spots[#spots].defaultCooldown)
		
		spots[#spots].defaultIntervalCooldown = dca.defaultIntervalCooldown
		spots[#spots].intervalCooldown = 0
		spots[#spots].defaultSalvo = dca.defaultSalvo
		spots[#spots].randomSalvo = dca.defaultRandomSalvo
		spots[#spots].salvo = 0
	end
	
	return deepcopy(spots)
end

function initMachinegunSound(count)
	local spots = {}
	
	local playerPos = GetPlayerCameraTransform().pos
	
	for i=1, count do
		spots[#spots + 1] = {}
		local pos = VecAdd(playerPos, Vec(rand(mg.soundDist) - mg.soundDist / 2, 0, rand(mg.soundDist) - mg.soundDist / 2))
		
		spots[#spots].pos = pos
		
		spots[#spots].snd = 0
		
		spots[#spots].defaultCooldown = mg.defaultCooldown
		spots[#spots].cooldown = rand(spots[#spots].defaultCooldown)
		
		spots[#spots].defaultIntervalCooldown = mg.defaultIntervalCooldown
		spots[#spots].intervalCooldown = 0
		spots[#spots].defaultSalvo = mg.defaultSalvo
		spots[#spots].randomSalvo = mg.defaultRandomSalvo
		spots[#spots].salvo = 0
	end
	
	return deepcopy(spots)
end

function randomInterpolate(a, b)
	return math.random() * (b - a) + a
end

function randomPos(aa, bb)
	return Vec(randomInterpolate(aa[1], bb[1]), randomInterpolate(aa[2], bb[2]), randomInterpolate(aa[3], bb[3]))
end

function randomPosBorder()
	local p = Vec(0, 0, 0)
	p[1] = randomInterpolate(world.aa[1], world.bb[1])
	p[3] = randomInterpolate(world.aa[3], world.bb[3])
	local rd = rand(4)
	if rd == 1 then
		p[1] = world.aa[1]
	elseif rd == 2 then
		p[3] = world.aa[3]
	elseif rd == 3 then
		p[1] = world.bb[1]
	else
		p[3] = world.bb[3]
	end
	return deepcopy(p)
end

function ambiantFire(spots)
	for i=1, #spots do
		SpawnFire(spots[i].pos)
	end
end

function explosions(spots)
	for i=1, #spots do
		Explosion(spots[i].pos, 2.0)
	end
end

function holes(spots)
	for i=1, #spots do
		MakeHole(spots[i].pos, 4.0, 3.0, 2.0, true)
	end
end

function DCAShoot(spots, dt)
	for i=1, #spots do
		spots[i].cooldown = spots[i].cooldown - dt
		--DrawLine(spots[i].t.pos, TransformToParentPoint(spots[i].t, VecScale(Vec(0, 0, -1), 600)), 1, 0, 0, 0.5)
		local forward = Vec(rand() * dca.spread - dca.spread / 2, rand() * dca.spread - dca.spread / 2, -1)
		
		if spots[i].cooldown <= 0 and spots[i].salvo <= 0 then
		
			spots[i].salvo = rand(spots[i].randomSalvo) + spots[i].defaultSalvo
			
		elseif spots[i].salvo > 0 then
		
			if spots[i].intervalCooldown <= 0 then
			
				spots[i].intervalCooldown = spots[i].defaultIntervalCooldown
				spots[i].salvo = spots[i].salvo - 1
				Shoot(spots[i].t.pos, QuatRotateVec(spots[i].t.rot, forward), "bullet", 1, 600)
				--PlaySound(DCASound, spots[i].t.pos, 1)
				if spots[i].salvo == 0 then
					spots[i].cooldown = spots[i].defaultCooldown + rand(2)
				end
				
			else
			
				spots[i].intervalCooldown = spots[i].intervalCooldown - dt
				
			end
			
		end
	end
end

function MGShoot(spots, dt)

	local playerPos = GetPlayerCameraTransform().pos
	--DebugPrint(#spots)
	for i=1, #spots do
		--DebugCross(spots[i].pos)
		--DebugLine(spots[i].pos, playerPos)
		spots[i].cooldown = spots[i].cooldown - dt
		
		if spots[i].cooldown <= 0 and spots[i].salvo <= 0 then
			
			spots[i].salvo = rand(spots[i].randomSalvo) + spots[i].defaultSalvo
			local offset = Vec(rand(mg.soundDist) - mg.soundDist / 2, 0, rand(mg.soundDist) - mg.soundDist / 2)
			spots[i].pos = VecAdd(playerPos, VecScale(offset, mg.soundDist / VecLength(offset)))
			spots[i].snd = mg.snd[rand(#mg.snd)]
			
		elseif spots[i].salvo > 0 then
		
			if spots[i].intervalCooldown <= 0 then
			
				spots[i].intervalCooldown = spots[i].defaultIntervalCooldown
				spots[i].salvo = spots[i].salvo - 1
				PlaySound(spots[i].snd, spots[i].pos, 1)
				if spots[i].salvo == 0 then
					spots[i].cooldown = 1 + rand(spots[i].defaultCooldown)
				end
				
			else
			
				spots[i].intervalCooldown = spots[i].intervalCooldown - dt
				
			end
			
		end
	end
end

function updateAircraft(dt)
	ac.cooldown = ac.cooldown - dt
	
	if ac.cooldown <= 0 then
		ac.cooldown = ac.defaultCooldown + rand(10)
		local pos = randomPosBorder()
		local playerPos = GetPlayerCameraTransform().pos
		local dir = QuatLookAt(pos, playerPos)
		local velocity = Vec(0, ac.height, -ac.speed)
		velocity = QuatRotateVec(dir, velocity)
		ac.transform = Transform(pos, dir)
		
		PlaySound(ac.snd, playerPos, 1)
		SetBodyTransform(ac.body, ac.transform)
		SetBodyVelocity(ac.body, velocity)
	end
	
end
```