diff --git a/compat/README.txt b/compat/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..82453f74ac5d841a1108e92d30c62c654d70b3ac
--- /dev/null
+++ b/compat/README.txt
@@ -0,0 +1 @@
+Addons that vere modified for compatibility with booststack.
diff --git a/compat/slipstream.lua b/compat/slipstream.lua
new file mode 100644
index 0000000000000000000000000000000000000000..a75d24147ef564ce89e33e18244eb6bb7d5ac90a
--- /dev/null
+++ b/compat/slipstream.lua
@@ -0,0 +1,424 @@
+-- Based on KL_Slipstream-v3
+-- Added booststack support
+
+-- Author: Ashnal
+-- Adds slipstreaming aka drafting like the later Mario Kart games
+-- Youll see small gray speed lines when you're charging a slipstream boost
+-- Theres a subtle woosh sound when it activates, and the gray speed lines will become normal size and more frequent
+-- You need to have another racer within the maxangle of your heading, and be within the maxdistiance range to charge it
+-- the closer you are to them, the faster it will charge
+-- KNOWN BUG: the fast lines have some wierd angles on OpenGL rendering. No idea why.
+
+local cv_slipstream = CV_RegisterVar({
+    name = "slipstream_enabled",
+    defaultvalue = "Off",
+    flags = CV_NETVAR,
+    PossibleValue = CV_OnOff
+})
+local ss_running = cv_slipstream.value
+
+local cv_anglefix = CV_RegisterVar({
+    name = "slipstream_anglefix",
+    defaultvalue = "On",
+    flags = CV_NETVAR,
+    PossibleValue = CV_OnOff,
+})
+
+local cv_colorized = CV_RegisterVar({
+    name = "slipstream_colorized",
+    defaultvalue = "On",
+    flags = NULL,
+    PossibleValue = CV_OnOff
+})
+
+local cv_reminder = CV_RegisterVar({
+    name = "slipstream_reminder",
+    defaultvalue = "Off",
+    flags = NULL,
+    PossibleValue = CV_OnOff
+})
+
+local cv_maxdistance = CV_RegisterVar({
+    name = "slipstream_maxdistance",
+    defaultvalue = 2400, -- enough room to charge slowly, and dodge
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+local cv_t2chargedist = CV_RegisterVar({
+    name = "slipstream_t2chargedist",
+    defaultvalue = 1400,
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+local cv_t3chargedist = CV_RegisterVar({
+    name = "slipstream_t3chargedist",
+    defaultvalue = 300, -- danger close, woudln't be able to dodge an aimed item
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+local cv_maxangle = CV_RegisterVar({
+    name = "slipstream_maxangle",
+    defaultvalue = "10", --11 degrees
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = CV_Unsigned
+})
+
+-- This is measured in tics
+local cv_chargetoboost = CV_RegisterVar({
+    name = "slipstream_chargetoboost",
+    defaultvalue = 5*TICRATE/2,
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+local cv_boosttime = CV_RegisterVar({
+    name = "slipstream_boosttime",
+    defaultvalue = 2*TICRATE,
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+local cv_minimumspeed = CV_RegisterVar({
+    name = "slipstream_minimumspeed",
+    defaultvalue = 28,
+    flags = CV_NETVAR,
+    PossibleValue = CV_Unsigned
+})
+
+-- Boost youll get if you're a 1 kartspeed
+local cv_maxspeedboostpercent = CV_RegisterVar({
+    name = "slipstream_maxspeedboostpercent",
+    defaultvalue = "0.27",
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = {MIN = 0, MAX = INT32_MAX}
+})
+
+-- Boost youll get if you're a 9 or higher kartspeed
+local cv_minspeedboostpercent = CV_RegisterVar({
+    name = "slipstream_minspeedboostpercent",
+    defaultvalue = "0.17",
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = {MIN = 0, MAX = INT32_MAX}
+})
+
+local cv_accelboostpercent = CV_RegisterVar({
+    name = "slipstream_accelboostpercent",
+    defaultvalue = "0.50",
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = {MIN = 0, MAX = INT32_MAX}
+})
+
+local cv_maxdraftspeedboostpercent = CV_RegisterVar({
+    name = "slipstream_maxdraftspeedboostpercent",
+    defaultvalue = "0.12",
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = {MIN = 0, MAX = INT32_MAX}
+})
+
+local cv_mindraftspeedboostpercent = CV_RegisterVar({
+    name = "slipstream_mindraftspeedboostpercent",
+    defaultvalue = "0.01",
+    flags = CV_NETVAR|CV_FLOAT,
+    PossibleValue = {MIN = 0, MAX = INT32_MAX}
+})
+
+
+local soundcooldown = 3*TICRATE
+local starttime = 6*TICRATE + (3*TICRATE/4)
+local slipstreamsfx = sfx_s3k82
+
+local function IntPercentToFixed(int)
+	return FixedDiv(int*FRACUNIT, 100*FRACUNIT)
+end
+
+-- prefer to input all fixed values
+-- https://en.wikipedia.org/wiki/Feature_scaling
+local function Rescale(value, oldmin, oldmax, newmin, newmax)
+	return newmin +  FixedMul(FixedDiv( value-oldmin , oldmax-oldmin), newmax-newmin)
+end
+
+local function SpawnFastLines(p, tier, color)
+    if p.fastlinestimer == 1 or tier == 1 then
+        local fast = P_SpawnMobj(p.mo.x + (P_RandomRange(-36,36) * p.mo.scale),
+            p.mo.y + (P_RandomRange(-36,36) * p.mo.scale),
+            p.mo.z + (p.mo.height/2) + (P_RandomRange(-20,20) * p.mo.scale),
+            MT_FASTLINE)
+        fast.angle = R_PointToAngle2(0, 0, p.mo.momx, p.mo.momy)
+        fast.momx = 3*p.mo.momx/4
+        fast.momy = 3*p.mo.momy/4
+        fast.momz = 3*p.mo.momz/4
+        fast.color = color
+        fast.colorized = true
+        K_MatchGenericExtraFlags(fast, p.mo)
+
+        fast.scale = $/tier
+        p.fastlinestimer = tier
+    end
+    p.fastlinestimer = max($-1, 1)
+end
+
+local function FSonicRunDust(mo)
+	local angle = mo.angle
+	local newx
+	local newy
+	local parts
+	local i
+	if leveltime%2 then
+		for i = 0,1 do
+			newx = mo.x + P_ReturnThrustX(mo, angle + ((i == 0) and -1 or 1)*ANGLE_90, FixedMul(16*FRACUNIT, mo.scale))
+			newy = mo.y + P_ReturnThrustY(mo, angle + ((i == 0) and -1 or 1)*ANGLE_90, FixedMul(16*FRACUNIT, mo.scale))
+			parts = P_SpawnMobj(newx, newy, (verticalflip and (mo.ceilingz or -1) or mo.floorz), MT_PARTICLE)
+			parts.target = mo
+			parts.angle = angle - ((i == 0) and -1 or 1)*ANGLE_45
+			parts.scale = mo.scale
+			parts.destscale = mo.scale*3
+			parts.scalespeed = mo.scale/6
+			parts.momx = 3*mo.momx/5
+			parts.momy = 3*mo.momy/5
+			parts.fuse = 5
+		end
+	end
+end
+
+--hud.add(function(v, p, c)
+--    if p.spectator then return end
+--    v.drawString(12,145,FixedMul(p.kartstuff[k_speedboost], 100*FRACUNIT)>>FRACBITS,V_SNAPTOLEFT,"left")
+--end)
+
+booststack.registerBoostType("slipstreamboost", {
+    stacktics = false,
+    dynamic = true,
+
+    getBoostPower = function(pmo)
+		local clampedkartspeed = max(min(pmo.player.kartspeed, 9), 1)
+
+        local speedboost = Rescale(clampedkartspeed*FRACUNIT, 9*FRACUNIT, FRACUNIT, cv_minspeedboostpercent.value, cv_maxspeedboostpercent.value)
+        local accelboost = cv_accelboostpercent.value
+
+        return speedboost, accelboost
+    end,
+})
+
+booststack.registerBoostType("draftingboost", {
+    stackable = false,
+    dynamic = true,
+
+    getBoostPower = function(pmo)
+        local clampedkartspeed = max(min(pmo.player.kartspeed, 9), 1)
+		local draftingboost = Rescale(clampedkartspeed*FRACUNIT, 9*FRACUNIT, FRACUNIT, cv_mindraftspeedboostpercent.value, cv_maxdraftspeedboostpercent.value)
+
+        return draftingboost, 0
+    end
+})
+
+local T3_DISTANCE
+local T2_DISTANCE
+local MAX_DISTANCE
+
+addHook("NetVars", function(net)
+    T3_DISTANCE = net(T3_DISTANCE)
+    T2_DISTANCE = net(T2_DISTANCE)
+    MAX_DISTANCE = net(MAX_DISTANCE)
+    ss_running = net(ss_running)
+end)
+
+addHook("ThinkFrame", function()
+    if leveltime <= 1 then
+        ss_running = cv_slipstream.value
+
+        T3_DISTANCE = cv_t3chargedist.value * mapobjectscale
+        T2_DISTANCE = cv_t2chargedist.value * mapobjectscale
+        MAX_DISTANCE = cv_maxdistance.value * mapobjectscale
+    end
+
+    if not ss_running then return end -- Has to be turned on
+
+    -- Key - player_t, value - bool
+    -- Used for optimizing out redundant checks
+    local nocheck = {}
+
+    -- Key - player_t (slipstreaming), value - player_t (target)
+    -- Table for slipstream targets found on this frame
+    local targets = {}
+
+    -- Key - player_t, value - table
+    -- Yes i had to name it like that
+    -- It actually stands for "per player"
+    local nocheck_pp = {}
+
+    for p in players.iterate do
+
+        if leveltime == 3*TICRATE and cv_reminder.value then
+            chatprintf(p, "\131* Don't forget you can \130draft\131 behind another player to charge a \130slipstream speed boost!", true)
+        end
+
+        if p.mo and p.mo.valid then  -- must have valid player mapobject
+            local pmo = p.mo
+            local ks = p.kartstuff
+
+            nocheck_pp[p] = {}
+
+            if ks[k_spinouttimer] and ks[k_wipeoutslow] == 1 then -- no slipstreaming if you've bumped or spun out
+                p.slipstreamboost = 0
+                p.slipstreamcharge = 0
+            else
+
+                if p.slipstreamcharge == nil then
+                    p.slipstreamcharge = 0
+                    p.slipstreamboost = 0
+                    p.fastlinestimer = 0
+                    p.slipstreamsoundtimer = false
+                end
+
+                -- reset until we find a valid slipstreamtarget this frame
+                local slipstreamtarget
+                local angletotarget
+                local mindisttotarget
+                local disttotarget
+                local charge = 0
+                local speedboost = ks[k_speedboost]
+                local accelboost = ks[k_accelboost]
+
+                if P_IsObjectOnGround(pmo)
+                   and FixedDiv(p.speed, mapobjectscale)/FRACUNIT >= cv_minimumspeed.value then -- must be moving decently on the ground
+
+                    for potentialtarget in players.iterate do
+                        if nocheck[potentialtarget] -- They are too slow, don't even bother to check
+                            or (nocheck_pp[potentialtarget] and nocheck_pp[potentialtarget][p]) -- Bad angle/distance, checked on some previous iteration
+                            or targets[potentialtarget] == p -- If we are their slipstream target, we can't use them as target ourself obviously
+                            or not (potentialtarget.mo and potentialtarget.mo.valid and potentialtarget.mo ~= pmo) then continue end
+
+                        local tmo = potentialtarget.mo
+
+                        if not potentialtarget.kartstuff[k_hyudorotimer] -- or ghosts
+                           and P_IsObjectOnGround(tmo) -- or airbourne karts
+                           and FixedDiv(potentialtarget.speed, mapobjectscale)/FRACUNIT >= cv_minimumspeed.value then -- or slowpokes
+
+                            local checkangle = pmo.angle - (cv_anglefix.value and ((ANG1*11)*ks[k_drift]) or 0)
+                            angletotarget = abs(checkangle - R_PointToAngle2(pmo.x, pmo.y, tmo.x, tmo.y))
+                            disttotarget = FixedHypot(pmo.x - tmo.x, pmo.y - tmo.y)
+
+                            if ks[k_drift] then
+                                if angletotarget > FixedAngle(cv_maxangle.value*2) then
+                                    continue
+                                end
+
+                                if disttotarget > 3*MAX_DISTANCE/5 then
+                                    continue
+                                end -- max slipstream distance while drifting
+                            else
+                                if angletotarget > FixedAngle(cv_maxangle.value) then
+                                    continue
+                                end
+
+                                if disttotarget > MAX_DISTANCE then
+                                    nocheck_pp[p][potentialtarget] = true
+                                    continue
+                                end -- max slipstream distance
+                            end -- Narrow angle for following to slipstream
+
+                            if mindisttotarget == nil or mindisttotarget > disttotarget then
+                                mindisttotarget = disttotarget
+                                slipstreamtarget = potentialtarget
+                            end
+                        end
+                    end
+                else
+                    nocheck[p] = true
+                end
+
+                -- add/remove slipstream charge
+                if slipstreamtarget then
+                    targets[p] = slipstreamtarget
+                    disttotarget = mindisttotarget
+
+                    if disttotarget > T2_DISTANCE then
+                        charge = 1
+                    elseif disttotarget > T3_DISTANCE then
+                        charge = 2
+                    else
+                        charge = 3
+                    end
+
+                    p.slipstreamcharge = min($+charge, cv_chargetoboost.value)
+                    -- print(p.mo.skin + " " +slipstreamtarget.mo.skin + " angletotarget: " + angletotarget + " disttotarget: " + disttotarget + " charging slipstream: " + p.slipstreamcharge)
+
+                    -- also spawn mini lines if charging to teach/show player the charging area
+                    if p.slipstreamboost == 0 then
+
+                        SpawnFastLines(p, 2, SKINCOLOR_WHITE)
+
+						local clampedkartspeed = max(min(p.kartspeed, 9), 1)
+						local draftingboost = Rescale(clampedkartspeed*FRACUNIT, 9*FRACUNIT, FRACUNIT, cv_mindraftspeedboostpercent.value, cv_maxdraftspeedboostpercent.value)
+                        speedboost = max(speedboost, draftingboost)
+                        p.slipstreamsoundtimer = false
+
+                    end
+
+                else
+                    -- if p.slipstreamcharge then print(p.mo.skin + " losing  slipstream " + p.slipstreamcharge) end
+                    p.slipstreamcharge = max($-1, 0)
+                end
+
+                if p.slipstreamcharge >= cv_chargetoboost.value then
+
+                    -- print(p.mo.skin + " slipstreaming!")
+                    p.slipstreamboost = cv_boosttime.value
+
+                    if p.slipstreamsoundtimer == false then
+                        S_StartSound(p.mo, slipstreamsfx)
+                        p.slipstreamsoundtimer = true
+                    end
+
+                end
+
+                if p.slipstreamboost then
+					if cv_colorized.value then
+						SpawnFastLines(p, 1, p.skincolor)
+					else
+						SpawnFastLines(p, 1, SKINCOLOR_WHITE)
+					end
+
+                    if P_IsObjectOnGround(pmo) then
+						FSonicRunDust(pmo)
+					end
+
+                end
+
+                if not booststack.running then
+                    if p.slipstreamboost then
+                        local clampedkartspeed = max(min(p.kartspeed, 9), 1)
+                        local slipstreamspeedboost = Rescale(clampedkartspeed*FRACUNIT, 9*FRACUNIT, FRACUNIT, cv_minspeedboostpercent.value, cv_maxspeedboostpercent.value)
+
+                        speedboost = max(speedboost, slipstreamspeedboost)
+                        accelboost = max(accelboost, cv_accelboostpercent.value)
+                    end
+
+                    -- value smoothing
+                    if (speedboost > p.kartstuff[k_speedboost]) then
+                        p.kartstuff[k_speedboost] = speedboost
+                    else
+                        p.kartstuff[k_speedboost] = p.kartstuff[k_speedboost] + (speedboost - p.kartstuff[k_speedboost])/(TICRATE/2)
+                    end
+
+                    p.kartstuff[k_accelboost] = accelboost
+                else
+                    if p.slipstreamboost then
+                        booststack.doBoost(pmo, "slipstreamboost", 1)
+                    elseif charge then
+                        booststack.doBoost(pmo, "draftingboost", 1)
+                    end
+                end
+
+                -- if p.slipstreamboost then print(p.mo.skin + " slipstreamboost: " + p.slipstreamboost) end
+                p.slipstreamboost = max($-1, 0)
+                --p.slipstreamsoundtimer = max($-1, 0)
+            end
+        else
+            nocheck[p] = true
+        end
+    end
+end)