Skip to content
Snippets Groups Projects
Commit d4580b76 authored by Indev's avatar Indev
Browse files

Add booststack-compatible slipstream modification

parent 5deab05d
No related branches found
No related tags found
No related merge requests found
Addons that vere modified for compatibility with booststack.
-- 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)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment