Sylmir

Untitled

May 27th, 2021 (edited)
34
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.53 KB | None | 0 0
  1. -- The core function is computeEsauEndPosition which returns a point 2000 tiles away
  2. -- from Esau on the (Esau, Jacob) line. I did that because I wanted what I draw while
  3. -- Esau is held and what you draw when he breaks free to transition smoothly.
  4. --
  5. -- There is no valid TargetPosition while Esau is held in place by Anima Sola, so I
  6. -- have to compute manually a position at which the Marked target will appear. I
  7. -- chose to put it offscreen because it is similar to what happens when Esau breaks
  8. -- free. I don't know if it impacts performance or not. A better solution would be
  9. -- to put the marked target just offscreen, but I don't know how to compute if something
  10. -- is on screen or not.
  11.  
  12. local mod = RegisterMod("Dark Esau Helper", 1)                                
  13.                                                                                
  14. --approximate)                                                                  
  15. local ESAU_REGULAR_DASH_DISTANCE = 410                                          
  16. local ESAU_REGULAR_DASH_FRAME_COUNT = 40                                        
  17. local ESAU_ANIMA_DASH_DISTANCE = 1600                                          
  18. local ESAU_ANIMA_DASH_FRAME_COUNT = 70                                          
  19. local ESAU_ANIMA_FRAME_WARN = 80                                                
  20. local ESAU_ANIMA_FRAME_DANGER = 110                                            
  21. local ESAU_ANIMA_FRAME_CRITICAL = 120                                          
  22.                                                                                
  23. local isSpriteInitialized = false                                              
  24. local targetSprite = nil                                                        
  25.                                                                                
  26. local DASH_ATTACKING_FRAME = "dashAttackingFrame"                              
  27. local ANIMA_ATTACKING_FRAME = "animaAttackingFrame"                            
  28. local TARGET_POSITION = "targetPosition"                                        
  29. local ANIMA_SOLA_STATE = "animaSolaState"                                      
  30. local ANIMA_SOLA_APPLICATION = "animaSolaApplication"
  31.  
  32. local ANIMA_SOLA_STATE = "animaSolaState"                                      
  33. local ANIMA_SOLA_APPLICATION = "animaSolaApplication"
  34.  
  35. local AnimaSolaState = {                                                        
  36.    STATE_NONE = 0, -- No info yet                                              
  37.    STATE_APPLIED = 1, -- Anima Sola was applied                                
  38.    STATE_REMOVED = 2 -- Anima Sola was applied and is no longer active          
  39. }
  40.  
  41. local function getEsauTargetVector(esau)
  42.     return Vector.FromAngle(esau.TargetPosition:GetAngleDegrees())
  43. end
  44.  
  45. local function configureEsauData(esau, dashDistance, dataName)
  46.     local dashVector = getEsauTargetVector(esau)
  47.     esau:GetData()[TARGET_POSITION] = esau.Position + dashDistance * dashVector
  48.     esau:GetData()[dataName] = Game():GetFrameCount()
  49. end
  50.  
  51. local function updateAnimaSolaState(esau)                                      
  52.     local previousState = esau:GetData()[ANIMA_SOLA_STATE]                      
  53.     local newState = nil                                                        
  54.                                                                                
  55.     if previousState == nil then                                                
  56.         esau:GetData()[ANIMA_SOLA_STATE] = AnimaSolaState.STATE_NONE            
  57.         previousState = AnimaSolaState.STATE_NONE                              
  58.     end                                                                        
  59.                                                                                
  60.     if previousState == AnimaSolaState.STATE_NONE then                          
  61.         if esau.State == NpcState.STATE_SUICIDE then                            
  62.             esau:GetData()[ANIMA_SOLA_APPLICATION] = Game():GetFrameCount()    
  63.             newState = AnimaSolaState.STATE_APPLIED                            
  64.         else                                                                    
  65.         newState = previousState                                                
  66.     end                                                                        
  67.     elseif previousState == AnimaSolaState.STATE_APPLIED then                  
  68.         if esau.State == NpcState.STATE_SUICIDE then                            
  69.             newState = previousState                                            
  70.         else                                                                    
  71.             newState = AnimaSolaState.STATE_REMOVED                            
  72.         end                                                                    
  73.     else                                                                        
  74.         if esau.State == NpcState.STATE_SUICIDE then                            
  75.             esau:GetData()[ANIMA_SOLA_APPLICATION] = Game():GetFrameCount()    
  76.             newState = AnimaSolaState.STATE_APPLIED                            
  77.         else                                                                    
  78.             newState = previousState                                            
  79.         end                                                                    
  80.     end                                                                        
  81.                                                                                
  82.     esau:GetData()[ANIMA_SOLA_STATE] = newState                                
  83.     return previousState, newState                                              
  84. end
  85.  
  86. local function computeEsauEndPosition(esauStart, jacobPos)                      
  87.     -- Compute the vector between both                                          
  88.     local diff = jacobPos - esauStart -- This the vector from esauStart to jacobPos
  89.     local norm = diff:Normalized()                                              
  90.     local room = Game():GetRoom()                                              
  91.     local shape = room:GetRoomShape()                            
  92.     return esauStart + norm * 2000
  93. end
  94.  
  95. function mod:postNpcRender(npc, renderOffset)                                  
  96.     Isaac.DebugString("Begin post NPC render")                                  
  97.                                                                                
  98.     local npcData = npc:GetData()                                              
  99.     local currentFrameCount = Game():GetFrameCount();                          
  100.                                                                                
  101.     if npcData[DASH_ATTACKING_FRAME] == nil or npc.State == NpcState.STATE_SUICIDE then --when chained
  102.         npcData[DASH_ATTACKING_FRAME] = 0                                      
  103.         npcData[ANIMA_ATTACKING_FRAME] = 0                                      
  104.     end                                                                        
  105.                                                                                
  106.     --first frame where TargetPosition is initialized with valid value          
  107.     if npc.State == NpcState.STATE_ATTACK and npc.StateFrame == 15 then        
  108.         configureEsauData(npc, ESAU_REGULAR_DASH_DISTANCE, DASH_ATTACKING_FRAME)
  109.     elseif npc.State == NpcState.STATE_ATTACK2 and npc.StateFrame == 0 then    
  110.         configureEsauData(npc, ESAU_ANIMA_DASH_DISTANCE, ANIMA_ATTACKING_FRAME)
  111.     end                                                                        
  112.                                                                                
  113.     local previousState, newState = updateAnimaSolaState(npc)                  
  114.     local breakFree = npcData[ANIMA_ATTACKING_FRAME] + ESAU_ANIMA_DASH_FRAME_COUNT >= currentFrameCount
  115.                                                                                
  116.     if npcData[DASH_ATTACKING_FRAME] + ESAU_REGULAR_DASH_FRAME_COUNT >= currentFrameCount
  117.       or breakFree                                                              
  118.       or newState == AnimaSolaState.STATE_APPLIED then                          
  119.         if newState == AnimaSolaState.STATE_APPLIED and not breakFree then      
  120.             local target = npc:GetPlayerTarget()                                
  121.             if target == nil then                                              
  122.                 target = Isaac.GetPlayer(0)                                    
  123.             end                                                                
  124.                                                                                
  125.             local finalPosition = computeEsauEndPosition(npc.Position, target.Position)
  126.             mod:drawLine(npc.Position, finalPosition, true, currentFrameCount - npcData[ANIMA_SOLA_APPLICATION])
  127.         else                                                                    
  128.             mod:drawLine(npc.Position, npcData[TARGET_POSITION], false, 0, breakFree)
  129.         end                                                                    
  130.     end                                                                        
  131.                                                                                
  132.     Isaac.DebugString("End post NPC render")                                    
  133. end                                                                            
  134.                                                                                
  135. local function RGB(R, G, B)                                                    
  136.     return Color(R / 255, G / 255, B / 255)                                    
  137. end
  138.  
  139. local animaColorNormal = RGB(198, 232, 86) -- Color(0.65, 0.45, 0.3)            
  140. local animaColorWarn = RGB(232, 220, 86) -- Color(0.75, 0.33, 0.15)            
  141. local animaColorDanger = RGB(232, 164, 86) -- Color(0.85, 0.1, 0)              
  142. local animaColorCritical = Color(1, 0, 0)                                      
  143. local lastColor = animaColorNormal                                              
  144.                                                                                
  145. local function flickerSprite(sprite, frame)                                    
  146.     if frame >= ESAU_ANIMA_FRAME_WARN and frame < ESAU_ANIMA_FRAME_DANGER then  
  147.         if frame % 4 == 0 then                                                  
  148.             if frame % 8 == 0 then                                              
  149.                 sprite.Color = animaColorNormal                                
  150.             else                                                                
  151.                 sprite.Color = animaColorWarn                                  
  152.             end                                                                
  153.         end                                                                    
  154.     elseif frame >= ESAU_ANIMA_FRAME_DANGER and frame < ESAU_ANIMA_FRAME_CRITICAL then
  155.         if frame % 3 == 0 then                                                  
  156.             if frame % 6 == 0 then                                              
  157.                 sprite.Color = animaColorWarn                                  
  158.             else                                                                
  159.                 sprite.Color = animaColorDanger                                
  160.             end                                                                
  161.         end                                                                    
  162.     elseif frame >= ESAU_ANIMA_FRAME_CRITICAL then                              
  163.         if frame % 2 == 0 then                                                  
  164.             if frame % 4 == 2 then                                              
  165.                 sprite.Color = animaColorDanger                                
  166.             else                                                                
  167.                 sprite.Color = animaColorCritical                              
  168.             end                                                                
  169.         end                                                                    
  170.     else                                                                        
  171.         sprite.Color = animaColorNormal                                        
  172.     end                                                                        
  173.                                                                                
  174.     lastColor = sprite.Color                                                    
  175. end
  176.  
  177. function mod:drawLine(from, to, flicker, frame, breakFree)                      
  178.     --using edited fetus_target file, failed to make line visible otherwise    
  179.     if not isSpriteInitialized then                                            
  180.         targetSprite = Sprite()                                                
  181.         targetSprite:Load("gfx/esau_target.anm2", true)                        
  182.         targetSprite.Color = animaColorNormal                                  
  183.         isSpriteInitialized = true                                              
  184.     end                                                                        
  185.                                                                                
  186.     if targetSprite:IsLoaded() then                                            
  187.         if flicker then                                                        
  188.             flickerSprite(targetSprite, frame)                                  
  189.             -- colorSprite(targetSprite, frame)                                
  190.         else                                                                    
  191.             if breakFree then                                                  
  192.                 targetSprite.Color = lastColor                                  
  193.             else                                                                
  194.                 targetSprite.Color = animaColorNormal                          
  195.             end                                                                
  196.         end                                                                    
  197.                                                                                
  198.         local diffVector = to - from;                                          
  199.         local angle = diffVector:GetAngleDegrees();                            
  200.         local sectionCount = diffVector:Length()/16;                            
  201.                                                                                
  202.         targetSprite.Rotation = angle;                                          
  203.         targetSprite:SetFrame("Line", 0)                                        
  204.         for i=1, sectionCount do                                                
  205.             targetSprite:Render(Isaac.WorldToScreen(from))                      
  206.             from= from + Vector.One* 16 * Vector.FromAngle(angle)              
  207.         end                                                                    
  208.                                                                                
  209.         targetSprite.Rotation = 0                                              
  210.         targetSprite:SetFrame("Idle", 0)                                        
  211.         targetSprite:Render(Isaac.WorldToScreen(to))                            
  212.     end                                                                        
  213. end
  214.  
  215. mod:AddCallback(ModCallbacks.MC_POST_NPC_RENDER, mod.postNpcRender, EntityType.ENTITY_DARK_ESAU)
  216.  
Advertisement
Add Comment
Please, Sign In to add comment