freeslot("S_PLAY_OVERDRIVECHARGE", "S_PLAY_OVERDRIVEATTACK", "S_OVERDRIVEFX", "S_OVERDRIVEAURA", "SPR2_CHRG", "SPR2_OVRD", "SPR_ODFX", "SPR_OCFX", "MT_OVERDRIVEFX", "MT_OVERDRIVEAURA", "sfx_movrdr", "sfx_mochrg", "sfx_moredy", "SKINCOLOR_SUPER_TOPAZ1", "SKINCOLOR_SUPER_TOPAZ2", "SKINCOLOR_SUPER_TOPAZ3", "SKINCOLOR_SUPER_TOPAZ4", "SKINCOLOR_SUPER_TOPAZ5") skincolors[SKINCOLOR_SUPER_TOPAZ1] = { name = "Super Topaz 1", ramp = {0,0,0,0,0,80,81,82,72,72,73,73,74,75,76,67}, invcolor = SKINCOLOR_ORANGE, invshade = 9, chatcolor = V_BLUEMAP, accessible = false } skincolors[SKINCOLOR_SUPER_TOPAZ2] = { name = "Super Topaz 2", ramp = {0,0,0,0,80,81,82,72,73,73,74,74,75,76,67,68}, invcolor = SKINCOLOR_ORANGE, invshade = 9, chatcolor = V_BLUEMAP, accessible = false } skincolors[SKINCOLOR_SUPER_TOPAZ3] = { name = "Super Topaz 3", ramp = {0,0,0,80,81,82,72,73,74,74,75,76,67,68,69,69}, invcolor = SKINCOLOR_ORANGE, invshade = 9, chatcolor = V_BLUEMAP, accessible = false } skincolors[SKINCOLOR_SUPER_TOPAZ4] = { name = "Super Topaz 4", ramp = {0,0,80,81,82,72,73,74,74,75,76,67,68,69,70,70}, invcolor = SKINCOLOR_ORANGE, invshade = 9, chatcolor = V_BLUEMAP, accessible = false } skincolors[SKINCOLOR_SUPER_TOPAZ5] = { name = "Super Topaz 5", ramp = {0,80,81,82,72,73,74,74,75,76,67,68,69,70,70,46}, invcolor = SKINCOLOR_ORANGE, invshade = 9, chatcolor = V_BLUEMAP, accessible = false } local charge = S_PLAY_OVERDRIVECHARGE states[charge].sprite = SPR_PLAY states[charge].frame = SPR2_CHRG states[charge].tics = -1 states[charge].nextstate = S_PLAY_OVERDRIVECHARGE local overdrive = S_PLAY_OVERDRIVEATTACK states[overdrive].sprite = SPR_PLAY states[overdrive].frame = SPR2_OVRD|FF_FULLBRIGHT|FF_ANIMATE states[overdrive].var1 = 1 states[overdrive].var2 = 1 states[overdrive].tics = -1 states[overdrive].nextstate = S_PLAY_OVERDRIVEATTACK mobjinfo[MT_OVERDRIVEFX] = { spawnstate = S_OVERDRIVEFX, spawnhealth = 1, deathstate = S_NULL, dispoffset = -1, speed = FRACUNIT, radius = FRACUNIT, height = FRACUNIT, flags = MF_SCENERY|MF_NOGRAVITY } local effect = S_OVERDRIVEFX states[effect].sprite = SPR_OCFX states[effect].frame = FF_FULLBRIGHT|FF_ANIMATE states[effect].var1 = 6 states[effect].var2 = 1 states[effect].tics = -1 states[effect].nextstate = S_OVERDRIVEFX mobjinfo[MT_OVERDRIVEAURA] = { spawnstate = S_OVERDRIVEAURA, spawnhealth = 1, deathstate = S_NULL, dispoffset = -1, speed = FRACUNIT, radius = FRACUNIT, height = FRACUNIT, flags = MF_SCENERY|MF_NOGRAVITY } local aura = S_OVERDRIVEAURA states[aura].sprite = SPR_ODFX states[aura].frame = FF_FULLBRIGHT|FF_ANIMATE states[aura].var1 = 1 states[aura].var2 = 1 states[aura].tics = -1 states[aura].nextstate = S_OVERDRIVEAURA sfxinfo[sfx_movrdr].caption = "Overdrive Attack" sfxinfo[sfx_mochrg].caption = "Overdrive Charging" sfxinfo[sfx_moredy].caption = "Overdrive Ready" local function FlipObjectFromObject(mo, master) mo.flags2 = ($ & ~MF2_OBJECTFLIP) | (master.flags2 & MF2_OBJECTFLIP) mo.eflags = ($ & ~MFE_VERTICALFLIP) | (master.eflags & MFE_VERTICALFLIP) end addHook("ThinkFrame", do for player in players.iterate if player.mo and player.mo.valid and player.mo.skin == "metalsonic" //print(player.resetod) if player.overdrivechargetimer == nil player.overdrivechargetimer = 0 end if player.overdrivepulsetimer == nil player.overdrivepulsetimer = 0 end if player.dooverdriveattack == nil player.dooverdriveattack = false end if player.overdriveattacktimer == nil player.overdriveattacktimer = 0 end if player.odstats == nil player.odstats = false end if player.resetod == nil player.resetod = false end if P_PlayerInPain(player) or (player.pflags & PF_SLIDING) or player.powers[pw_carry] or player.spectator or player.playerstate != PST_LIVE or not player.mo.health or player.panim == PA_PAIN or player.iseggrobo or (player.dirk_frozen) or (player.gotflag or player.gotcrystal) or player.powers[pw_nocontrol] or player.exiting player.resetod = true else player.resetod = false end local flip = (P_MobjFlip(player.mo) == 1) and 0 or player.mo.height+(20*FU) //Overdrive charge checks if P_IsObjectOnGround(player.mo) and player.resetod == false if player.cmd.buttons & BT_SPIN -- Is the player holding spin? and not player.dooverdriveattack and not ((player.mo.state == S_PLAY_SPINDASH) or (player.pflags & PF_SPINNING)) if ((player.overdrivechargetimer < 85) and not (player.powers[pw_sneakers] or player.powers[pw_super])) --Is the charge timer below 85 without shoes/super? or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super])) player.overdrivechargetimer = $ + 1 end if player.overdrivechargetimer >= 1 player.mo.momz = 0 end if not (leveltime & 3) and player.overdrivechargetimer >= 2 and player.mo.state == S_PLAY_OVERDRIVECHARGE S_StartSound(player.mo, sfx_s3k5c) end if not player.c2down and ((player.overdrivechargetimer < 85) or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))) and not player.dooverdriveattack player.c2down = true player.mo.state = S_PLAY_OVERDRIVECHARGE player.mo.momx = FixedMul($, FRACUNIT*88/100) player.mo.momy = FixedMul($, FRACUNIT*88/100) local effect = P_SpawnMobjFromMobj(player.mo, 0, 0, 17*FU, MT_OVERDRIVEFX) effect.source = player.mo S_StartSound(player.mo, sfx_mochrg) end player.pflags = $|PF_STASIS else player.c2down = false if player.mo.state == S_PLAY_OVERDRIVECHARGE and (((player.overdrivechargetimer < 85) and not (player.powers[pw_sneakers] or player.powers[pw_super])) or ((player.overdrivechargetimer < 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))) --Why does this conditional need to arbitrarily be a chungus? player.mo.state = S_PLAY_STND S_StopSoundByID(player.mo, sfx_mochrg) S_StartSound(player.mo, sfx_kc65) player.overdrivechargetimer = 0 elseif ((player.overdrivechargetimer >= 85) or ((player.overdrivechargetimer >= 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))) and player.dooverdriveattack == false player.dooverdriveattack = true S_StartSound(player.mo, sfx_movrdr) player.mo.state = S_PLAY_OVERDRIVEATTACK player.height = skins[player.mo.skin].spinheight player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_RUNONWATER|SF_CANBUSTWALLS player.normalspeed = 72*FRACUNIT player.jumpfactor = skins[player.mo.skin].jumpfactor*2 player.charability = CA_NONE player.charability2 = CA2_NONE P_InstaThrust(player.mo, player.mo.angle, 102*FRACUNIT) local aura = P_SpawnMobjFromMobj(player.mo, 0, 0, 17*FU, MT_OVERDRIVEAURA) aura.target = player.mo player.overdrivechargetimer = 0 player.odstats = true end end if player.c2down == true and player.mo.state ~= S_PLAY_OVERDRIVECHARGE player.overdrivechargetimer = 0 player.pflags = $ & ~PF_STASIS end if player.dooverdriveattack if player.overdriveattacktimer < 3 player.overdriveattacktimer = $ + 1 end end if ((player.overdrivechargetimer >= 85) or ((player.overdrivechargetimer >= 50) and (player.powers[pw_sneakers] or player.powers[pw_super]))) player.overdrivepulsetimer = $ + 1 player.mo.frame = B|FF_FULLBRIGHT end if player.overdrivepulsetimer >= 2 player.overdrivepulsetimer = 0 player.mo.frame = A end end if not P_IsObjectOnGround(player.mo) player.overdrivechargetimer = 0 end if player.dooverdriveattack and player.playerstate == PST_LIVE and not player.resetod player.mo.state = S_PLAY_OVERDRIVEATTACK player.mo.frame = (leveltime % 2)|FF_FULLBRIGHT end if ((player.overdrivechargetimer == 84) or ((player.overdrivechargetimer == 49) and (player.powers[pw_sneakers] or player.powers[pw_super]))) and player.mo.state == S_PLAY_OVERDRIVECHARGE S_StartSound(player.mo, sfx_moredy) end if (((player.overdriveattacktimer >= 3) and (player.speed < 20*FRACUNIT)) or ((player.overdriveattacktimer >= 3) and (player.mo.state ~= S_PLAY_OVERDRIVEATTACK))) and player.playerstate == PST_LIVE player.overdriveattacktimer = 0 player.dooverdriveattack = false S_StartSound(player.mo, sfx_kc65) player.normalspeed = 36*FRACUNIT player.jumpfactor = skins[player.mo.skin].jumpfactor player.height = skins[player.mo.skin].height player.charability = CA_FLOAT player.charability2 = CA2_SPINDASH player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_DASHMODE player.mo.state = S_PLAY_WALK player.odstats = false end if player.resetod --failsafe and (player.dooverdriveattack or player.odstats) player.overdriveattacktimer = 0 player.dooverdriveattack = false S_StartSound(player.mo, sfx_kc65) player.normalspeed = 36*FRACUNIT player.jumpfactor = skins[player.mo.skin].jumpfactor player.charability = CA_FLOAT player.charability2 = CA2_SPINDASH player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_DASHMODE player.panim = PA_RUN if player.powers[pw_carry] == CR_MACESPIN --mace swings are stupid. player.mo.state = S_PLAY_ROLL end player.odstats = false end end end end) addHook("MobjThinker", function(mo) if not mo.target return end mo.lifetime = $ or 0 mo.angle = mo.target.player.drawangle local ghost = P_SpawnGhostMobj(mo) ghost.rollangle = mo.rollangle FlipObjectFromObject(mo, mo.target) local flip = (P_MobjFlip(mo.target) == 1) and 0 or mo.target.height+(17*FU) local z = 17*mo.scale if mo.eflags & MFE_VERTICALFLIP z = -$ + mo.target.z + mo.target.height - mo.height else z = $ + mo.target.z end ghost.blendmode = AST_ADD P_TeleportMove(mo, mo.target.x + mo.lifetime * mo.momx, mo.target.y + mo.lifetime * mo.momy, z + mo.lifetime * mo.momz) mo.lifetime = $ + 1 if mo.target.player.dooverdriveattack == false or mo.target.player.playerstate != PST_LIVE P_RemoveMobj(mo) end end, MT_OVERDRIVEAURA) addHook("MobjThinker", function(mo) if not mo.source return end mo.lifetime = $ or 0 mo.angle = mo.source.player.drawangle mo.rollangle = $ + FixedAngle((FU*360)/9) FlipObjectFromObject(mo, mo.source) local flip = (P_MobjFlip(mo.source) == 1) and 0 or mo.source.height+(17*FU) local z = 17*mo.scale if mo.eflags & MFE_VERTICALFLIP z = -$ + mo.source.z + mo.source.height - mo.height else z = $ + mo.source.z end P_TeleportMove(mo, mo.source.x + mo.lifetime * mo.momx, mo.source.y + mo.lifetime * mo.momy, z + mo.lifetime * mo.momz) mo.lifetime = $ + 1 if not mo.source.player.overdrivechargetimer or mo.source.state ~= S_PLAY_OVERDRIVECHARGE or not P_IsObjectOnGround(mo.source) or mo.source.player.resetod P_RemoveMobj(mo) end end, MT_OVERDRIVEFX) addHook("ShouldDamage", function(target, inflictor, source, damage, damagetype) if target and target.valid and target.skin == "metalsonic" if (target.player.dooverdriveattack) and not (damagetype & DMG_DEATHMASK) return false end if ((target.state == S_PLAY_OVERDRIVECHARGE) or (target.player.dooverdriveattack)) and inflictor and inflictor.flags & MF_ENEMY|MF_BOSS return false end end end, MT_PLAYER) addHook("MobjCollide", function(spike, plmo) if not (plmo and plmo.valid and plmo.skin == "metalsonic") then return end if plmo.type ~= MT_PLAYER then return end if plmo.z + plmo.height < spike.z or spike.z + spike.height < plmo.z then return end local player = plmo.player if player.dooverdriveattack then P_KillMobj(spike, plmo, plmo) end end, MT_SPIKE) addHook("MobjCollide", function(spike, plmo) if not (plmo and plmo.valid and plmo.skin == "metalsonic") then return end if plmo.type ~= MT_PLAYER then return end if (plmo.z > spike.z+spike.height*4) or (spike.z > plmo.z+plmo.height*2) then return end local player = plmo.player if player.dooverdriveattack then P_KillMobj(spike, plmo, plmo) end end, MT_WALLSPIKE) addHook("PlayerCanDamage", function(player, mobj) if player.mo and player.mo.valid and player.mo.skin == "metalsonic" if mobj.type == MT_PLAYER return end if player.mo.state == S_PLAY_OVERDRIVECHARGE and P_IsObjectOnGround(player.mo) and not (player.powers[pw_super]) P_DamageMobj(mobj, player.mo, source, 1, damagetype) return true elseif player.dooverdriveattack or player.powers[pw_super] P_DamageMobj(mobj, player.mo, source, 2, damagetype) return true end end end) addHook("MobjMoveCollide", function(metal, enemy) if (metal and metal.valid and metal.health and metal.skin == "metalsonic") and (enemy and enemy.valid and enemy.health) and enemy.type == MT_PLAYER and not (metal == enemy) and not (maptol == TOL_CHAOS) and not (gametype == GT_COOP) and metal.z <= enemy.z + enemy.height*2 and metal.z + metal.height >= enemy.z if ((metal.state == S_PLAY_OVERDRIVECHARGE and P_IsObjectOnGround(metal)) or (metal.player.dooverdriveattack)) P_DamageMobj(enemy, metal, source, 1) end end end, MT_PLAYER) addHook("PlayerSpawn", function(player) if player.mo and player.mo.valid and player.mo.skin == "metalsonic" player.overdrivechargetimer = 0 player.overdrivepulsetimer = 0 player.dooverdriveattack = false player.overdriveattacktimer = 0 if player.odstats == true player.normalspeed = 36*FRACUNIT player.jumpfactor = skins[player.mo.skin].jumpfactor player.charability = CA_FLOAT player.charability2 = CA2_SPINDASH player.charflags = SF_MACHINE|SF_MULTIABILITY|SF_SUPER|SF_DASHMODE player.odstats = false end end end)