Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- The core function is computeEsauEndPosition which returns a point 2000 tiles away
- -- from Esau on the (Esau, Jacob) line. I did that because I wanted what I draw while
- -- Esau is held and what you draw when he breaks free to transition smoothly.
- --
- -- There is no valid TargetPosition while Esau is held in place by Anima Sola, so I
- -- have to compute manually a position at which the Marked target will appear. I
- -- chose to put it offscreen because it is similar to what happens when Esau breaks
- -- free. I don't know if it impacts performance or not. A better solution would be
- -- to put the marked target just offscreen, but I don't know how to compute if something
- -- is on screen or not.
- local mod = RegisterMod("Dark Esau Helper", 1)
- --approximate)
- local ESAU_REGULAR_DASH_DISTANCE = 410
- local ESAU_REGULAR_DASH_FRAME_COUNT = 40
- local ESAU_ANIMA_DASH_DISTANCE = 1600
- local ESAU_ANIMA_DASH_FRAME_COUNT = 70
- local ESAU_ANIMA_FRAME_WARN = 80
- local ESAU_ANIMA_FRAME_DANGER = 110
- local ESAU_ANIMA_FRAME_CRITICAL = 120
- local isSpriteInitialized = false
- local targetSprite = nil
- local DASH_ATTACKING_FRAME = "dashAttackingFrame"
- local ANIMA_ATTACKING_FRAME = "animaAttackingFrame"
- local TARGET_POSITION = "targetPosition"
- local ANIMA_SOLA_STATE = "animaSolaState"
- local ANIMA_SOLA_APPLICATION = "animaSolaApplication"
- local ANIMA_SOLA_STATE = "animaSolaState"
- local ANIMA_SOLA_APPLICATION = "animaSolaApplication"
- local AnimaSolaState = {
- STATE_NONE = 0, -- No info yet
- STATE_APPLIED = 1, -- Anima Sola was applied
- STATE_REMOVED = 2 -- Anima Sola was applied and is no longer active
- }
- local function getEsauTargetVector(esau)
- return Vector.FromAngle(esau.TargetPosition:GetAngleDegrees())
- end
- local function configureEsauData(esau, dashDistance, dataName)
- local dashVector = getEsauTargetVector(esau)
- esau:GetData()[TARGET_POSITION] = esau.Position + dashDistance * dashVector
- esau:GetData()[dataName] = Game():GetFrameCount()
- end
- local function updateAnimaSolaState(esau)
- local previousState = esau:GetData()[ANIMA_SOLA_STATE]
- local newState = nil
- if previousState == nil then
- esau:GetData()[ANIMA_SOLA_STATE] = AnimaSolaState.STATE_NONE
- previousState = AnimaSolaState.STATE_NONE
- end
- if previousState == AnimaSolaState.STATE_NONE then
- if esau.State == NpcState.STATE_SUICIDE then
- esau:GetData()[ANIMA_SOLA_APPLICATION] = Game():GetFrameCount()
- newState = AnimaSolaState.STATE_APPLIED
- else
- newState = previousState
- end
- elseif previousState == AnimaSolaState.STATE_APPLIED then
- if esau.State == NpcState.STATE_SUICIDE then
- newState = previousState
- else
- newState = AnimaSolaState.STATE_REMOVED
- end
- else
- if esau.State == NpcState.STATE_SUICIDE then
- esau:GetData()[ANIMA_SOLA_APPLICATION] = Game():GetFrameCount()
- newState = AnimaSolaState.STATE_APPLIED
- else
- newState = previousState
- end
- end
- esau:GetData()[ANIMA_SOLA_STATE] = newState
- return previousState, newState
- end
- local function computeEsauEndPosition(esauStart, jacobPos)
- -- Compute the vector between both
- local diff = jacobPos - esauStart -- This the vector from esauStart to jacobPos
- local norm = diff:Normalized()
- local room = Game():GetRoom()
- local shape = room:GetRoomShape()
- return esauStart + norm * 2000
- end
- function mod:postNpcRender(npc, renderOffset)
- Isaac.DebugString("Begin post NPC render")
- local npcData = npc:GetData()
- local currentFrameCount = Game():GetFrameCount();
- if npcData[DASH_ATTACKING_FRAME] == nil or npc.State == NpcState.STATE_SUICIDE then --when chained
- npcData[DASH_ATTACKING_FRAME] = 0
- npcData[ANIMA_ATTACKING_FRAME] = 0
- end
- --first frame where TargetPosition is initialized with valid value
- if npc.State == NpcState.STATE_ATTACK and npc.StateFrame == 15 then
- configureEsauData(npc, ESAU_REGULAR_DASH_DISTANCE, DASH_ATTACKING_FRAME)
- elseif npc.State == NpcState.STATE_ATTACK2 and npc.StateFrame == 0 then
- configureEsauData(npc, ESAU_ANIMA_DASH_DISTANCE, ANIMA_ATTACKING_FRAME)
- end
- local previousState, newState = updateAnimaSolaState(npc)
- local breakFree = npcData[ANIMA_ATTACKING_FRAME] + ESAU_ANIMA_DASH_FRAME_COUNT >= currentFrameCount
- if npcData[DASH_ATTACKING_FRAME] + ESAU_REGULAR_DASH_FRAME_COUNT >= currentFrameCount
- or breakFree
- or newState == AnimaSolaState.STATE_APPLIED then
- if newState == AnimaSolaState.STATE_APPLIED and not breakFree then
- local target = npc:GetPlayerTarget()
- if target == nil then
- target = Isaac.GetPlayer(0)
- end
- local finalPosition = computeEsauEndPosition(npc.Position, target.Position)
- mod:drawLine(npc.Position, finalPosition, true, currentFrameCount - npcData[ANIMA_SOLA_APPLICATION])
- else
- mod:drawLine(npc.Position, npcData[TARGET_POSITION], false, 0, breakFree)
- end
- end
- Isaac.DebugString("End post NPC render")
- end
- local function RGB(R, G, B)
- return Color(R / 255, G / 255, B / 255)
- end
- local animaColorNormal = RGB(198, 232, 86) -- Color(0.65, 0.45, 0.3)
- local animaColorWarn = RGB(232, 220, 86) -- Color(0.75, 0.33, 0.15)
- local animaColorDanger = RGB(232, 164, 86) -- Color(0.85, 0.1, 0)
- local animaColorCritical = Color(1, 0, 0)
- local lastColor = animaColorNormal
- local function flickerSprite(sprite, frame)
- if frame >= ESAU_ANIMA_FRAME_WARN and frame < ESAU_ANIMA_FRAME_DANGER then
- if frame % 4 == 0 then
- if frame % 8 == 0 then
- sprite.Color = animaColorNormal
- else
- sprite.Color = animaColorWarn
- end
- end
- elseif frame >= ESAU_ANIMA_FRAME_DANGER and frame < ESAU_ANIMA_FRAME_CRITICAL then
- if frame % 3 == 0 then
- if frame % 6 == 0 then
- sprite.Color = animaColorWarn
- else
- sprite.Color = animaColorDanger
- end
- end
- elseif frame >= ESAU_ANIMA_FRAME_CRITICAL then
- if frame % 2 == 0 then
- if frame % 4 == 2 then
- sprite.Color = animaColorDanger
- else
- sprite.Color = animaColorCritical
- end
- end
- else
- sprite.Color = animaColorNormal
- end
- lastColor = sprite.Color
- end
- function mod:drawLine(from, to, flicker, frame, breakFree)
- --using edited fetus_target file, failed to make line visible otherwise
- if not isSpriteInitialized then
- targetSprite = Sprite()
- targetSprite:Load("gfx/esau_target.anm2", true)
- targetSprite.Color = animaColorNormal
- isSpriteInitialized = true
- end
- if targetSprite:IsLoaded() then
- if flicker then
- flickerSprite(targetSprite, frame)
- -- colorSprite(targetSprite, frame)
- else
- if breakFree then
- targetSprite.Color = lastColor
- else
- targetSprite.Color = animaColorNormal
- end
- end
- local diffVector = to - from;
- local angle = diffVector:GetAngleDegrees();
- local sectionCount = diffVector:Length()/16;
- targetSprite.Rotation = angle;
- targetSprite:SetFrame("Line", 0)
- for i=1, sectionCount do
- targetSprite:Render(Isaac.WorldToScreen(from))
- from= from + Vector.One* 16 * Vector.FromAngle(angle)
- end
- targetSprite.Rotation = 0
- targetSprite:SetFrame("Idle", 0)
- targetSprite:Render(Isaac.WorldToScreen(to))
- end
- end
- mod:AddCallback(ModCallbacks.MC_POST_NPC_RENDER, mod.postNpcRender, EntityType.ENTITY_DARK_ESAU)
Advertisement
Add Comment
Please, Sign In to add comment