--Red Rings v1 - Made by Nightwolf --Inspired by "OMG THE RED RINGS" Sonic 1 hack made by Fiz freeslot("MT_EVILRING","S_ERNG") local rrenable = CV_RegisterVar({ name = "redrings_enable", defaultvalue = "Yes", flags = CV_NETVAR, PossibleValue = CV_YesNo, func = function() end }) local supermode = CV_RegisterVar({ name = "redrings_difficulty", defaultvalue = tostring(0), flags = CV_NETVAR, PossibleValue = {MIN = 0, MAX = 6}, func = function() end }) //Difficulty settings //0 - rings only bounce up and down //1 - rings can bounce horizontally //2 - rings will fall in a weird way and they can bounce horizontally //3 - rings WILL always bounce horizontally and will fall in a weird way //4 - nearby rings will change their horizontal speed to try to face you //5 - nearby rings will change their both speeds to try to face you //6 - like 5 but rings can turn into any enemy they touch (1/16 chance) local function ringtargeting(actor,maxdist) if not actor.target then P_LookForPlayers(actor,maxdist,true) actor.momx = P_RandomRange(-64,64)*FRACUNIT actor.momy = P_RandomRange(-64,64)*FRACUNIT else local dist = R_PointToDist2(actor.x,actor.y,actor.target.x,actor.target.y) if dist < maxdist and P_CheckSight(actor,actor.target) then local angle = R_PointToAngle2(actor.x,actor.y,actor.target.x,actor.target.y) actor.momx = P_RandomRange(32,64)*cos(angle) actor.momy = P_RandomRange(32,64)*sin(angle) if supermode.value > 4 then actor.momz = FixedDiv(actor.target.z-actor.z,dist) end else actor.target = nil end end end addHook("MobjCollide",function(thing,tmthing) if not tmthing.redrset or supermode.value < 6 then return nil end if not (thing.flags & MF_ENEMY) or thing.type == MT_PLAYER then return nil end if P_RandomChance(FRACUNIT/16) then P_SpawnMobj(tmthing.x,tmthing.y,tmthing.z,thing.type) tmthing.state = S_NULL return nil end end) --Red Ring Action function A_EvilRedRing(actor) --Remove red rings in special stages if G_IsSpecialStage(gamemap) then actor.state = S_NULL return end --Red ring setup (only once) if not actor.redrset then actor.flags = MF_SLIDEME|MF_RUNSPAWNFUNC|MF_PAIN actor.speed = 38*FRACUNIT actor.radius = 16*FRACUNIT actor.height = 24*FRACUNIT actor.deathstate = S_SPRK1 actor.redrset = true actor.color = SKINCOLOR_RED actor.momz = -1*FRACUNIT if actor.ceilingz - actor.floorz < 96*FRACUNIT actor.state = S_NULL return end end if supermode.value == 6 then ringtargeting(actor,1024*FRACUNIT) elseif supermode.value > 1 then if actor.z == actor.floorz A_ZThrust(actor,20,(1<<16)+0) if supermode.value == 3 then actor.momx = P_RandomRange(-64,64)*FRACUNIT actor.momy = P_RandomRange(-64,64)*FRACUNIT elseif supermode.value > 3 then ringtargeting(actor,512*FRACUNIT) end end if actor.momz < 0 actor.momz = P_RandomRange(-50,0)*FRACUNIT end if supermode.value > 2 and actor.momx == 0 and actor.momy == 0 then actor.momx = P_RandomRange(-64,64)*FRACUNIT actor.momy = P_RandomRange(-64,64)*FRACUNIT end else --Push rings upwards if they're on the floor if actor.z == actor.floorz A_ZThrust(actor,20,(1<<16)+1) end --Set Z Momentum to -5*FRACUNIT if rings are falling down if actor.momz < 0 actor.momz = -5*FRACUNIT end if supermode.value == 1 or supermode.value == 2 then return end --Remove horizontal momentum if actor.momx != 0 or actor.momy != 0 actor.momx = 0 actor.momy = 0 end end end --Red ring (MT_EVILRING) definition mobjinfo[MT_EVILRING] = { doomednum = 300, spawnstate = S_ERNG, spawnhealth = 1000, seestate = S_NULL, seesound = sfx_None, reactiontime = MT_FLINGRING, attacksound = sfx_None, painstate = S_NULL, painchance = 0, painsound = sfx_None, meleestate = S_NULL, missilestate = S_NULL, deathstate = S_SPRK1, xdeathstate = S_NULL, deathsound = sfx_itemup, speed = 38*FRACUNIT, radius = 16*FRACUNIT, height = 24*FRACUNIT, dispoffset = 0, mass = 100, damage = 0, activesound = sfx_None, flags = MF_SLIDEME|MF_RUNSPAWNFUNC|MF_PAIN, raisestate = S_NULL } --Red ring main state (S_ERNG) states[S_ERNG] = { sprite = SPR_RRNG, frame = 0, tics = 1, action = A_EvilRedRing, var1 = 0, var2 = 0, nextstate = S_ERNG } addHook("PlayerThink", function(p) if rrenable.value == 0 then return end if gamemap != nil --Bonus type > 0 --> Boss (bonustype == 1) or ERZ3 Boss (bonustype == 2) if mapheaderinfo[gamemap].bonustype > 0 --If on boss level, limit ring count to 1 if p.rings > 1 p.rings = 1 end return end end --If not on boss level, take all rings from player if p.rings > 0 p.rings = 0 end end) --If not in netgame give player 1 second of invincibility after (re)spawn --This was added to prevent rings from killing you constantly after respawn addHook("PlayerSpawn", function(p) if rrenable.value == 1 and netgame == false then p.powers[pw_flashing] = TICRATE end end) addHook("MobjThinker",function(mo) if mo.redringdeletelater then P_SpawnMobj(mo.x,mo.y,mo.z,MT_EVILRING) mo.state = S_NULL end end) addHook("MobjSpawn",function(mo) if rrenable.value == 0 then return nil end if mo.type == MT_RING or mo.flags & MF_MONITOR then mo.redringdeletelater = true elseif mo.type == MT_FLINGRING then mo.state = S_SPRK1 end end)