Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local LilLarry = {}
- LilLarry.item = PassiveItem("Lil Larry")
- LilLarry.head = Isaac.GetEntityVariantByName("Lil Larry's Head")
- LilLarry.body = Isaac.GetEntityVariantByName("Lil Larry's Body")
- LilLarry.guideType = Isaac.GetEntityTypeByName("Lil Larry's Head's Guide")
- LilLarry.guideVariant = Isaac.GetEntityVariantByName("Lil Larry's Head's Guide")
- -- parameters for the familiar's characteristics
- LilLarry.maxSegmentDistance = 30
- LilLarry.maxTargetDistanceForTracking = 400
- LilLarry.minTargetDistanceForTracking = 60
- LilLarry.minTargetDistance = 0.1
- LilLarry.maxTargetDistance = 500
- LilLarry.segmentFollowingSpeed = 7
- LilLarry.HeadSpeed = 5
- LilLarry.baseDamage = 0.1
- LilLarry.baseDamageIncrement = 0.1
- LilLarry.baseSize = 14
- --why does it behave oddly around portals?
- --External Item Description text
- __eidItemDescriptions[LilLarry.item.ID] = "Chases enemies #Gains 1 segment for each floor you progress"
- --creating a saved table for tracking the length of each larry Jr. even if you leave the game
- if IpecacCM.SaveData.LilLarryFamiliarData == nil then
- IpecacCM.SaveData.LilLarryFamiliarData = {}
- end
- function LilLarry.RecoverFamilarLength (_,save) -- recalling the saved values of each larry's length
- if save then
- for i,npc in pairs(Isaac.FindByType(3,LilLarry.head,-1,false,false)) do
- if IpecacCM.SaveData.LilLarryFamiliarData[i] ~= nil then
- npc:GetData().LilLarrySegmentCount = IpecacCM.SaveData.LilLarryFamiliarData[i]
- else
- npc:GetData().LilLarrySegmentCount = 1
- end
- end
- else
- IpecacCM.SaveData.LilLarryFamiliarData = {}
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_POST_GAME_STARTED,LilLarry.RecoverFamilarLength)
- function LilLarry.UpdateFamiliarCount (_) -- gives you a nex head for each instance of the item or of its effect you have
- local player = Isaac.GetPlayer(0)
- if player:GetEffects():GetCollectibleEffectNum( LilLarry.item.ID) >= 1 then
- player:CheckFamiliar(LilLarry.head,player:GetCollectibleNum(LilLarry.item.ID)+ player:GetEffects():GetCollectibleEffectNum( LilLarry.item.ID),player:GetCollectibleRNG(LilLarry.item.ID))
- else
- player:CheckFamiliar(LilLarry.head,player:GetCollectibleNum(LilLarry.item.ID),player:GetCollectibleRNG(LilLarry.item.ID))
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_EVALUATE_CACHE,LilLarry.UpdateFamiliarCount)
- IpecacMod:AddCallback(ModCallbacks.MC_USE_ITEM,LilLarry.UpdateFamiliarCount,CollectibleType.COLLECTIBLE_BOX_OF_FRIENDS)
- IpecacMod:AddCallback(ModCallbacks.MC_POST_NEW_ROOM,LilLarry.UpdateFamiliarCount)
- function LilLarry.Behaviour (_,npc) --determines how the head behaves
- local sprite = npc:GetSprite()
- local angle = npc.Velocity:GetAngleDegrees()%360
- npc.FlipX = false
- if angle < 45 or ( angle >= 315 ) then -- gives a different sprite depending on the direction it's facing
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_head_side.png")
- elseif angle < 135 then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_head_front.png")
- elseif angle < 225 then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_head_side.png")
- npc.FlipX = true
- else
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_head_back.png")
- end
- sprite:LoadGraphics()
- local room = IpecacCM.Game:GetLevel():GetCurrentRoom()
- local gridentity = room:GetGridEntityFromPos(npc.Position + (npc.Velocity):Normalized() * 30)
- if gridentity ~= nil and gridentity:GetType() == GridEntityType.GRID_POOP and math.random() <= 0.8 then --makes it destroy poop. Just like its parents!
- gridentity:Destroy(false)
- end
- sprite:SetFrame("Idle",npc.FrameCount%12 + 1)
- npc.CollisionDamage = LilLarry.baseDamage
- LilLarry.RecoverFamilarLength(_,true)
- npc.CollisionDamage = math.min(LilLarry.baseDamage + LilLarry.baseDamageIncrement * npc:GetData().LilLarrySegmentCount,LilLarry.baseDamage + 5 * LilLarry.baseDamageIncrement)
- -- if npc:GetData().LilLarrySegmentCount > 1 then
- local entity = npc
- for i = 1,npc:GetData().LilLarrySegmentCount do -- creates a train of familiar parts connected to each other!
- entity:GetData().LilLarryHead = npc
- entity:GetData().LilLarrySegmentNumber = i
- entity:GetData().LilLarryParentSegmentCount = npc:GetData().LilLarrySegmentCount
- if Isaac.GetPlayer(0):HasCollectible(CollectibleType.COLLECTIBLE_BFFS) or Isaac.GetPlayer(0):GetEffects():HasCollectibleEffect(CollectibleType.COLLECTIBLE_BFFS) then
- entity.CollisionDamage = LilLarry.baseSize * 1.3
- entity.CollisionDamage = math.min(LilLarry.baseDamage + LilLarry.baseDamageIncrement * npc:GetData().LilLarrySegmentCount,5 * LilLarry.baseDamageIncrement + LilLarry.baseDamage) * 2
- else
- entity.CollisionDamage = math.min(LilLarry.baseDamage + LilLarry.baseDamageIncrement * npc:GetData().LilLarrySegmentCount,5 * LilLarry.baseDamageIncrement + LilLarry.baseDamage)
- end
- if entity:GetData().LilLarryChild ~= nil and entity:GetData().LilLarryChild:Exists() then
- entity = entity:GetData().LilLarryChild
- entity:GetData().LilLarrySegmentNumber = i + 1
- else
- local child = Isaac.Spawn(EntityType.ENTITY_FAMILIAR,LilLarry.body,0,entity.Position,Vector(0,0),entity)
- entity:GetData().LilLarryChild = child
- entity:GetData().LilLarrySegmentNumber = i
- child:GetData().LilLarryParent = entity
- if Isaac.GetPlayer(0):HasCollectible(CollectibleType.COLLECTIBLE_BFFS) or Isaac.GetPlayer(0):GetEffects():HasCollectibleEffect(CollectibleType.COLLECTIBLE_BFFS) then
- child.CollisionDamage = LilLarry.baseSize * 1.3
- child.CollisionDamage = math.min(LilLarry.baseDamage + LilLarry.baseDamageIncrement * npc:GetData().LilLarrySegmentCount,5 * LilLarry.baseDamageIncrement + LilLarry.baseDamage) * 2
- else
- child.CollisionDamage = math.min(LilLarry.baseDamage + LilLarry.baseDamageIncrement * npc:GetData().LilLarrySegmentCount,5 * LilLarry.baseDamageIncrement + LilLarry.baseDamage)
- end
- entity = child
- entity:GetData().LilLarryParentSegmentCount = npc:GetData().LilLarrySegmentCount
- entity:GetData().LilLarrySegmentNumber = i + 1
- end
- end
- -- end
- if Isaac.GetPlayer(0):HasCollectible(CollectibleType.COLLECTIBLE_BFFS) or Isaac.GetPlayer(0):GetEffects():HasCollectibleEffect(CollectibleType.COLLECTIBLE_BFFS) then
- npc.Size = LilLarry.baseSize * 1.3
- end
- if npc:GetData().LilLarryHeadGuide == nil or not (npc:GetData().LilLarryHeadGuide:Exists()) then -- creates an entity to guide the head. Piber advised me against it, but it is way simpler than creating our own pathfinder. If someone else does for me, I can remove this. Oherwise, don't expect me to do so
- npc:GetData().LilLarryHeadGuide = Isaac.Spawn(LilLarry.guideType,LilLarry.guideVariant, 0, npc.Position,Vector(0,0),npc)
- npc:GetData().LilLarryHeadGuide.GridCollisionClass = GridCollisionClass.COLLISION_OBJECT
- npc:GetData().LilLarryHeadGuide.EntityCollisionClass = EntityCollisionClass.ENTCOLL_NONE
- npc:GetData().LilLarryHeadGuide:GetData().LilLarrysHead = npc
- npc:GetData().LilLarryHeadGuide:AddEntityFlags(EntityFlag.FLAG_FRIENDLY,EntityFlag.FLAG_CHARM)
- else
- npc.Position = npc:GetData().LilLarryHeadGuide.Position
- npc.Velocity = npc:GetData().LilLarryHeadGuide.Velocity
- end
- if npc.Target == nil or not npc.Target:Exists() then -- if the familiar doesn't yet have a target, it should seek one
- local selectedentity = nil
- local distance = LilLarry.maxTargetDistanceForTracking
- for m,n in pairs(Isaac.GetRoomEntities()) do
- currentdistance = ( n.Position - npc.Position ):Length()
- if currentdistance < distance and n:IsActiveEnemy() and n:IsVulnerableEnemy() and n:HasEntityFlags(EntityFlag.FLAG_FRIENDLY) == false and LilLarry.guideType ~= n.Type and currentdistance > LilLarry.minTargetDistanceForTracking then
- distance = currentdistance
- selectedentity = n
- end
- end
- if selectedentity ~= nil then
- npc.Target = selectedentity
- end
- else
- if npc.Target ~= nil and ((npc.Target.Position - npc.Position):Length() > LilLarry.maxTargetDistance or (npc.Target.Position - npc.Position):Length() < LilLarry.minTargetDistance ) then
- npc.Target = nil
- end
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_FAMILIAR_UPDATE,LilLarry.Behaviour,LilLarry.head)
- --[[function LilLarry.OnBoxOfFriends(_)
- local player = Isaac.GetPlayer(0)
- if player:HasCollectible(LilLarry.item.ID) then
- player:GetEffects():AddCollectibleEffect(LilLarry.item.ID)
- LilLarry.UpdateFamiliarCount()
- player:GetEffects():RemoveCollectibleEffect(CollectibleType.COLLECTIBLE_DEMON_BABY)
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_USE_ITEM,LilLarry.OnBoxOfFriends,CollectibleType.COLLECTIBLE_BOX_OF_FRIENDS)]]
- function LilLarry.GuideLilLarrysHead(_,npc)
- if npc.Variant == LilLarry.guideVariant and npc:GetData().LilLarrysHead and npc:GetData().LilLarrysHead:Exists() then
- npc.GridCollisionClass = GridCollisionClass.COLLISION_OBJECT
- if npc:GetData().LilLarrysHead.Target ~= nil then
- if not npc.Pathfinder:HasPathToPos(npc:GetData().LilLarrysHead.Target.Position,true) then
- npc:GetData().LilLarrysHead.Target = nil
- end
- end
- if npc:GetData().LilLarrysHead.Target ~= nil then
- if (npc.Position - npc:GetData().LilLarrysHead.Target.Position):Length() > 30 then
- npc.Pathfinder:FindGridPath(npc:GetData().LilLarrysHead.Target.Position,1,0,true)
- elseif npc.Pathfinder:HasPathToPos(npc:GetData().LilLarrysHead.Target.Position,true) then
- npc.Velocity = (npc:GetData().LilLarrysHead.Target.Position - npc.Position):Normalized() * math.min(LilLarry.HeadSpeed,(npc.Position - npc:GetData().LilLarrysHead.Target.Position):Length())
- end
- else
- if npc:GetData().LilLarryGuideTemporaryTarget ~= nil and (npc:GetData().LilLarryGuideTemporaryTarget - npc.Position):Length() > 70 and npc.Pathfinder:HasPathToPos(npc:GetData().LilLarryGuideTemporaryTarget,true) then
- npc.Pathfinder:FindGridPath(npc:GetData().LilLarryGuideTemporaryTarget,1,0,true)
- else
- npc:GetData().LilLarryGuideTemporaryTarget = IpecacCM.Game:GetLevel():GetCurrentRoom():GetClampedPosition(Isaac.GetRandomPosition(),5)
- end
- end
- elseif npc.Variant == LilLarry.guideVariant then
- npc:Remove()
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_NPC_UPDATE,LilLarry.GuideLilLarrysHead,LilLarry.guideType)
- function IpecacMod:IncreaseLilLarrysSize (_)
- for i,npc in pairs(Isaac.FindByType(3,LilLarry.head,-1,false,false)) do
- if npc:GetData().LilLarrySegmentCount == nil then
- if IpecacCM.SaveData.LilLarryFamiliarData[i] ~= nil then
- npc:GetData().LilLarrySegmentCount = IpecacCM.SaveData.LilLarryFamiliarData[i] + 1
- else
- npc:GetData().LilLarrySegmentCount = 1
- end
- else
- npc:GetData().LilLarrySegmentCount = npc:GetData().LilLarrySegmentCount +1
- end
- local level = IpecacCM.Game:GetLevel()
- if level:GetCurses() & LevelCurse.CURSE_OF_LABYRINTH == LevelCurse.CURSE_OF_LABYRINTH then
- npc:GetData().LilLarrySegmentCount = npc:GetData().LilLarrySegmentCount + 1
- end
- IpecacCM.SaveData.LilLarryFamiliarData[i] = npc:GetData().LilLarrySegmentCount
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_POST_NEW_LEVEL,IpecacMod.IncreaseLilLarrysSize)
- function LilLarry.BodyFollowsParent (_,npc)
- npc.GridCollisionClass = GridCollisionClass.COLLISION_OBJECT
- local sprite = npc:GetSprite()
- sprite:SetFrame("Idle",npc.FrameCount%12 + 1)
- local angle = npc.Velocity:GetAngleDegrees()%360
- npc.FlipX = false
- if npc.Velocity:Length() > 0.5 then
- if angle < 45 or ( angle >= 315 ) then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_body_side.png")
- elseif angle < 135 then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_body_front.png")
- elseif angle < 225 then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_body_side.png")
- npc.FlipX = true
- else
- if npc:GetData().LilLarryChild and npc:GetData().LilLarryChild:Exists() then
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_body_front.png")
- else
- sprite:ReplaceSpritesheet(0,"gfx/familiar/familiar_lil_larry_body_back.png")
- end
- end
- end
- sprite:LoadGraphics()
- if npc:GetData().LilLarryParent and npc:GetData().LilLarryParent:Exists() then
- local parent = npc:GetData().LilLarryParent
- npc:GetData().LilLarryParentSegmentCount = parent:GetData().LilLarryParentSegmentCount
- if type(npc:GetData().LilLarryParentSegmentCount) ~= "number" or npc:GetData().LilLarryParentSegmentCount + 1 < npc:GetData().LilLarrySegmentNumber then
- npc:Remove()
- end
- if (parent.Position - npc.Position ):Length() > LilLarry.maxSegmentDistance then
- npc.Velocity = (parent.Position - npc.Position):Normalized() * LilLarry.segmentFollowingSpeed
- elseif npc.Velocity:Length() > LilLarry.segmentFollowingSpeed / 6 then
- npc.Velocity = npc.Velocity - (npc.Velocity):Normalized() * LilLarry.segmentFollowingSpeed /6
- else
- npc.Velocity = npc.Velocity * 0.9
- end
- else
- npc:Remove()
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_FAMILIAR_UPDATE,LilLarry.BodyFollowsParent,LilLarry.body)
- -- Idea: Make a function for Lil larry pooping when it kills an enemy
- function IpecacMod:LilLarryLock ( collectible, pool, decrease, seed) -- can't find the item if you haven't unlocked it
- if collectible == LilLarry.item.ID and (not ( IpecacCM.SaveData.Unlocks ~= nil and IpecacCM.SaveData.Unlocks.LilLarry ~= nil and IpecacCM.SaveData.Unlocks.LilLarry.unlocked )) then
- local returnid = IpecacCM.Game:GetItemPool():GetCollectible(pool,true,seed)
- if returnid ~= LilLarry.item.ID then
- return returnid
- else
- return IpecacCM.Game:GetItemPool():GetCollectible(pool,true,seed)
- end
- end
- end
- IpecacMod:AddCallback(ModCallbacks.MC_POST_GET_COLLECTIBLE,IpecacMod.LilLarryLock)
Advertisement
Add Comment
Please, Sign In to add comment