--[[ Created by Warren Dawes : contact@warren2go.com ~ 1.0 - 09-05-2015 - Initial base with spawn/phase/tornados ]] require( "common" ) StatsData = { HP = 8377200, MaxHP = 8377200, HPRegen = 837720, AC = 4816, MR = 5274, TH = 1531, TB = 1020, MinWC = 549467, MaxWC = 824199, MinMA = 549467, MaxMA = 824199, RunSpeed = 300, MobExp = 174523050, ItemDrop = true, ItemDropIndex = "B_AHarp00", } SkillData = { HealIndex = nil, } SpawnData = { Tornado = { [1] = { MobIndex = "B_AHarp01", OnHitAbstate = { Target = ObjectType.Player,Index = "StaNortfBurn", Strength = 17, Duration = 5000, Rate = 1000 ,}, }, -- Burn [2] = { MobIndex = "B_AHarp02", OnHitAbstate = { Target = ObjectType.Player,Index = "StaIceBlastStun", Strength = 5, Duration = 15000, Rate = 1000 ,}, }, -- Slow [3] = { MobIndex = "B_AHarp03", OnHitAbstate = { Target = ObjectType.Player,Index = "StaKnockBackFly", Strength = 1, Duration = 1000, Rate = 1000 ,}, }, -- Knockback [4] = { MobIndex = "B_AHarp04", OnHitAbstate = { Target = ObjectType.Player,Index = "StaMultiBlood", Strength = 4, Duration = 5000, Rate = 1000 ,}, }, -- Bleed --[6] = { MobIndex = "B_AHarp06", OnHitAbstate = { Index = "", Strength = 1, Duration = 10000 }, }, -- Knockback & ? --[7] = { MobIndex = "B_AHarp07", OnHitAbstate = { Index = "", Strength = 1, Duration = 10000 }, }, -- Knockback & ? --[8] = { MobIndex = "B_AHarp08", OnHitAbstate = { Index = "", Strength = 1, Duration = 10000 }, }, -- Knockback & ? --[9] = { MobIndex = "B_AHarp09", OnHitAbstate = { Index = "", Strength = 1, Duration = 10000 }, }, -- Knockback & ? --[10] = { MobIndex = "B_AHarp10", OnHitAbstate = { Index = "", Strength = 1, Duration = 10000 }, }, -- Knockback & ? }, TornadoSpeed = 150, SpawnMax = 4, Pillars = { [1] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAngry", Strength = 1, Duration = 30000, OnSelf = true, HasStack = false, }, X = 786, Y = 1795, D = 297 }, [2] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAngry", Strength = 1, Duration = 30000, OnSelf = true, HasStack = false, }, X = 772, Y = 1392, D = 298 }, [3] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAngry", Strength = 1, Duration = 30000, OnSelf = true, HasStack = false, }, X = 997, Y = 1000, D = 297 }, [4] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAngry", Strength = 1, Duration = 30000, OnSelf = true, HasStack = false, }, X = 1373, Y = 769, D = 298 }, [5] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAdlFHCrazy",Strength = 1, Duration = 300000,OnSelf = true, HasStack = true, }, X = 1822, Y = 781, D = 297 }, [6] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAdlFHCrazy",Strength = 1, Duration = 300000,OnSelf = true, HasStack = true, }, X = 2210, Y = 1003, D = 298 }, [7] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAdlFHCrazy",Strength = 1, Duration = 300000,OnSelf = true, HasStack = true, }, X = 2412, Y = 1396, D = 297 }, [8] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaAdlFHCrazy",Strength = 1, Duration = 300000,OnSelf = true, HasStack = true, }, X = 2415, Y = 1807, D = 297 }, [9] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaBlind", Strength = 1, Duration = 5000, OnSelf = false,HasStack = false, }, X = 2185, Y = 2187, D = 297 }, [10] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaBlind", Strength = 1, Duration = 5000, OnSelf = false,HasStack = false, }, X = 1805, Y = 2398, D = 297 }, [11] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaBlind", Strength = 1, Duration = 5000, OnSelf = false,HasStack = false, }, X = 1374, Y = 2409, D = 297 }, [12] = { MobIndex = "B_AHarp_Pillar", ConsumeAbstate = { Index = "StaBlind", Strength = 1, Duration = 5000, OnSelf = false,HasStack = false, }, X = 997, Y = 2188, D = 297 }, }, TreasureChest = { [1] = { Rate = 15, MobIndex = "Box_AHarp", DropIndex = "Box_AHarp", }, --Weapon Skin }, TreasureChestCommon = { MobIndex = "Box_AHarp", DropIndex = "BH_Humar_X", }, } PhaseData = { [1] = { StepFunc = "AHarp_Natural", StepDuration = 60, SubDuration = 15, SubPhase = { [1] = { DamageFactor = 1.00, DefenseFactor = 1.00 }, [2] = { DamageFactor = 1.25, DefenseFactor = 1.25 }, [3] = { DamageFactor = 1.50, DefenseFactor = 1.50 }, [4] = { DamageFactor = 1.75, DefenseFactor = 1.75 }, }, }, [2] = { StepFunc = "AHarp_Berzerk", StepDuration = 30, SubDuration = 10, SubPhase = { [1] = { DamageFactor = 2.00, DefenseFactor = 1.00 }, [2] = { DamageFactor = 4.00, DefenseFactor = 0.75 }, [3] = { DamageFactor = 6.00, DefenseFactor = 0.50 }, }, }, [3] = { StepFunc = "AHarp_Defensive", StepDuration = 15, SubDuration = 5, SubPhase = { [1] = { DamageFactor = 1.00, DefenseFactor = 1.00 }, }, }, [4] = { StepFunc = "AHarp_Regenerate", StepDuration = 5, SubDuration = 5, SubPhase = { [1] = { DamageFactor = 1.00, DefenseFactor = 1.50 }, }, }, } -------------------------------------------------------------------------------- -------------- AHarp -------------- -------------------------------------------------------------------------------- MemBlock = {} --[[ ANGELIC HARPY SECTION TODO: - Initiate phase when damaged - Implement sub-phase system into phase system ]] --> Initiate function to handle all default function AHarp_Initiate( Var ) cExecCheck("AHarp_Initiate") --> Future calls to main-loop Var.StepFunc = PhaseData[1].StepFunc Var.Phase.Enabled = true Var.Phase.StepTick = cCurSec() + PhaseData[Var.Phase.Step].StepDuration Var.Phase.SubStepTick = cCurSec() + PhaseData[Var.Phase.Step].SubDuration return ReturnAI.CPP end --> Main function called from cpp/zone function B_AHarp00( Handle, MapIndex ) cExecCheck("B_AHarp00") if cIsObjectDead( Handle ) ~= nil then --cNoticeString( MapIndex, "ENTRACE AND HANDLE IS DEAD" ) return ReturnAI.CPP end local Var = MemBlock[Handle] if Var == nil then if MapIndex ~= "B_AHarp" then return ReturnAI.CPP end --cNoticeString( MapIndex, "REINIT VAR" ) MemBlock[Handle] = {} Var = MemBlock[Handle] Var.Handle = Handle Var.MapIndex = MapIndex Var.Type = "Boss" Var.AddsList = {} Var.Phase = {} Var.Phase.Enabled = false Var.Phase.Step = 1 Var.Phase.StepTick = cCurSec() Var.Phase.SubStep = 1 Var.Phase.SubStepTick = cCurSec() Var.Phase.SpawnStep = 0 Var.Phase.RunToConsume = false Var.Phase.RunToHandle = nil Var.Phase.PillarList = {} Var.Phase.UsedRegen = false --> Set stats cSetNPCParam( Var.Handle, "MaxHP", StatsData.MaxHP ) cSetNPCParam( Var.Handle, "HP", StatsData.HP ) cSetNPCParam( Var.Handle, "HPRegen", StatsData.HPRegen ) cSetNPCParam( Var.Handle, "TH", StatsData.TH ) cSetNPCParam( Var.Handle, "TB", StatsData.TB ) cSetNPCParam( Var.Handle, "AC", StatsData.AC ) cSetNPCParam( Var.Handle, "MR", StatsData.MR ) cSetNPCParam( Var.Handle, "MinWC", StatsData.MinWC ) cSetNPCParam( Var.Handle, "MaxWC", StatsData.MaxWC ) cSetNPCParam( Var.Handle, "MinMA", StatsData.MinMA ) cSetNPCParam( Var.Handle, "MaxMA", StatsData.MaxMA ) cSetNPCParam( Var.Handle, "RunSpeed", StatsData.RunSpeed ) cSetNPCParam( Var.Handle, "MobExp", StatsData.MobExp ) cSetItemDropMobID( Var.Handle, StatsData.ItemDropIndex ) for i=1, #SpawnData.Pillars do local Pillar = SpawnData.Pillars[i] local PillarHandle = cMobRegen_XY( Var.MapIndex, Pillar.MobIndex, Pillar.X, Pillar.Y, Pillar.D ) if PillarHandle ~= nil then MemBlock[PillarHandle] = {} MemBlock[PillarHandle].Handle = PillarHandle MemBlock[PillarHandle].MapIndex = Var.MapIndex MemBlock[PillarHandle].Type = "Pillar" MemBlock[PillarHandle].ID = i MemBlock[PillarHandle].PillarList = Var.Phase.PillarList table.insert(MemBlock[PillarHandle].PillarList, i, PillarHandle) cAIScriptSet( PillarHandle, Var.Handle ) cAIScriptFunc( PillarHandle, "Entrance", "AHarp_PillarAI" ) cAIScriptFunc( PillarHandle, "ObjectDied", "AHarp_ObjectDied" ) cSetAbstate( PillarHandle, "StaImmortal", 1, 2000000000 ) end end cVanishAll( Var.MapIndex, "InvisibleMan" ) local SpawnedInvisibleMan = cMobRegen_Obj( "InvisibleMan", Var.Handle ) if SpawnedInvisibleMan ~= nil then cAIScriptSet( SpawnedInvisibleMan, Var.Handle ) cSetAbstate( SpawnedInvisibleMan, "StaImmortal", 1, 2000000000 ) end cAIScriptFunc( Var.Handle, "ObjectDied", "AHarp_ObjectDied" ) cAIScriptFunc( Var.Handle, "MobDamaged", "AHarp_MobDamaged" ) Var.StepFunc = PhaseData[1].StepFunc end local InvisibleHandle = cGetNPCHandle( Var.MapIndex, "InvisibleMan" ) if InvisibleHandle ~= nil then local PlayerList = { cGetPlayerList( Var.MapIndex ) } for i=1, #PlayerList do end local DistBetween = cDistanceSquar( InvisibleHandle, Var.Handle ) if DistBetween > 700000 then cSetAbstate( Var.Handle, "StaMobImmortal", 1, 2000000000 ) else cResetAbstate( Var.Handle, "StaMobImmortal" ) end end return AHarp_MainLoop( Var ) end function InvisibleMan( Handle, MapIndex) return ReturnAI.END end --> Object damaged function AHarp_MobDamaged( MapIndex, AttackerHandle, MaxHP, CurHP, DefenderHandle ) cExecCheck("AHarp_MobDamaged") if MapIndex == nil or AttackerHandle == nil or MaxHP == nil or CurHP == nil or DefenderHandle == nil then AHarp_Debug( "AHarp_MobDamaged->MapIndex or AttackerHandle or MaxHP or CurHP or DefenderHandle is nil" ) return ReturnAI.CPP end local Var = MemBlock[DefenderHandle] if Var == nil then AHarp_Debug( "AHarp_MobDamaged->Var is nil" ) return ReturnAI.END end if Var.Type == "Boss" then if not Var.Phase.Enabled then --cNoticeString( MapIndex, "not Var.Phase.Enabled" ) AHarp_Initiate( Var ) else --cNoticeString( MapIndex, "Var.Phase.Enabled" ) AHarp_Step( Var ) end elseif Var.Type == "Pillar" then elseif Var.Type == "Add" then end return ReturnAI.CPP end --> Object died function AHarp_ObjectDied( MapIndex, KillerHandle, DeadHandle ) cExecCheck("AHarp_ObjectDied") if MapIndex == nil or KillerHandle == nil or DeadHandle == nil then AHarp_Debug( "AHarp_ObjectDied->MapIndex or KillerHandle or DeadHandle is nil" ) return ReturnAI.CPP end local Var = MemBlock[DeadHandle] if Var ~= nil then if Var.Type == "Boss" then AHarp_Reset( Var ) elseif Var.Type == "Pillar" then local PillarAbstate = SpawnData.Pillars[Var.ID].ConsumeAbstate if PillarAbstate ~= nil then if PillarAbstate.OnSelf then local ExistStr, ExistRemain = cGetAbstate( KillerHandle, PillarAbstate.Index ) if ExistStr ~= nil and PillarAbstate.HasStack then cSetAbstate( KillerHandle, PillarAbstate.Index, ExistStr + 1, PillarAbstate.Duration ) else cSetAbstate( KillerHandle, PillarAbstate.Index, PillarAbstate.Strength, PillarAbstate.Duration ) end else local PlayerList = { cGetPlayerList( Var.MapIndex ) } for i=1,#PlayerList do cSetAbstate( PlayerList[i], PillarAbstate.Index, PillarAbstate.Strength, PillarAbstate.Duration ) end end end Var.PillarList[Var.ID] = nil elseif Var.Type == "Add" then end end MemBlock[DeadHandle] = nil return ReturnAI.END end --> Reset variables for boss function AHarp_Reset( Var ) cExecCheck("AHarp_Reset") for i=1, #Var.AddsList do if Var.AddsList[i] ~= nil then cNPCVanish( Var.AddsList[i] ) MemBlock[Var.AddsList[i]] = nil end end Var.AddsList = {} local ChestRates = {} for i=1, #SpawnData.TreasureChest do table.insert(ChestRates, SpawnData.TreasureChest[math.random(#SpawnData.TreasureChest)]) end for i=1, #SpawnData.Pillars do if cIsObjectDead( Var.Handle ) ~= nil and Var.Phase.PillarList[i] ~= nil then local ChestRate = table.remove( ChestRates, 1 ) if ChestRate ~= nil then table.insert( ChestRates, ChestRate ) if math.random(1, 100) <= ChestRate.Rate then local RareChestHandle = cMobRegen_Obj( ChestRate.MobIndex, Var.Phase.PillarList[i] ) if RareChestHandle ~= nil then cSetItemDropMobID( RareChestHandle, ChestRate.DropIndex ) end else local CommonChestHandle = cMobRegen_Obj( SpawnData.TreasureChestCommon.MobIndex, Var.Phase.PillarList[i] ) if CommonChestHandle ~= nil then cSetItemDropMobID( CommonChestHandle, SpawnData.TreasureChestCommon.DropIndex ) end end end end if Var.Phase.PillarList[i] ~= nil then cNPCVanish( Var.Phase.PillarList[i] ) MemBlock[Var.Phase.PillarList[i]] = nil end end --cNoticeString( MapIndex, "B_AHARP RESET" ) Var.Phase.PillarList = {} Var.Phase.Enabled = false Var.Phase.Step = 1 Var.Phase.StepTick = cCurSec() Var.Phase.SubStep = 1 Var.Phase.SubStepTick = cCurSec() Var.Phase.SpawnStep = 0 Var.Phase.RunToConsume = false Var.Phase.RunToHandle = nil Var.Phase.UsedRegen = false MemBlock[Var.Handle] = nil return ReturnAI.CPP end --> Spawn Tornados function AHarp_SpawnTornado( Var, Max ) cExecCheck("AHarp_SpawnTornado") local BossX, BossY = cObjectLocate( Var.Handle ) if BossX ~= nil and BossY ~= nil then for i=1, Max do local TornadoID = math.random(#SpawnData.Tornado) local TornadoSpawn = SpawnData.Tornado[TornadoID] local TornadoHandle = cMobRegen_Circle( Var.MapIndex, TornadoSpawn.MobIndex, BossX, BossY, 500 ) if TornadoHandle ~= nil then table.insert( Var.AddsList, TornadoHandle ) MemBlock[TornadoHandle] = {} local TornadoVar = MemBlock[TornadoHandle] TornadoVar.Handle = TornadoHandle TornadoVar.MapIndex = Var.MapIndex TornadoVar.Type = "Add" TornadoVar.Speed = TornadoSpawn.Speed TornadoVar.NextMoveTick = cCurSec() TornadoVar.NextMoveX = 0 TornadoVar.NextMoveY = 0 TornadoVar.ID = TornadoID cAIScriptSet( TornadoHandle, Var.Handle ) cAIScriptFunc( TornadoHandle, "Entrance", "AHarp_TornadoAI" ) cAIScriptFunc( TornadoHandle, "NPCAction", "AHarp_TornadoNPCAction" ) cSetAbstate( TornadoHandle, "StaImmortal", 1, 2000000000 ) end end end end --> Step phase function AHarp_Step( Var ) cExecCheck("AHarp_Step") Var.Phase.UsedRegen = false local CurHP, MaxHP = cObjectHP( Var.Handle ) if CurHP == nil then return end local HPPercent = ((CurHP / MaxHP) * 1000) if HPPercent < 1000 then --> Step Tick if Var.Phase.StepTick <= cCurSec() then --cNoticeString( Var.MapIndex, "FromStep = " .. Var.Phase.Step .. ", FromStepFunc = " .. Var.StepFunc ) if (Var.Phase.Step + 1) <= #PhaseData then Var.Phase.Step = Var.Phase.Step + 1 else Var.Phase.Step = 1 end Var.StepFunc = PhaseData[Var.Phase.Step].StepFunc Var.Phase.SubStep = 1 Var.Phase.SubStepTick = cCurSec() + PhaseData[Var.Phase.Step].SubDuration --cNoticeString( Var.MapIndex, "ToStep = " .. Var.Phase.Step .. ", ToStepFunc = " .. Var.StepFunc ) Var.Phase.StepTick = cCurSec() + PhaseData[Var.Phase.Step].StepDuration end --> SubStep Tick if Var.Phase.SubStepTick <= cCurSec() then --cNoticeString( Var.MapIndex, "FromSubStep = " .. Var.Phase.SubStep ) if (Var.Phase.SubStep + 1) <= #PhaseData[Var.Phase.Step].SubPhase then Var.Phase.SubStep = Var.Phase.SubStep + 1 else Var.Phase.SubStep = 1 end local DamageFactor = PhaseData[Var.Phase.Step].SubPhase[Var.Phase.SubStep].DamageFactor local DefenseFactor = PhaseData[Var.Phase.Step].SubPhase[Var.Phase.SubStep].DefenseFactor cSetNPCParam( Var.Handle, "AC", StatsData.AC * DefenseFactor ) --cNoticeString( Var.MapIndex, "AC = " .. StatsData.AC * DefenseFactor ) cSetNPCParam( Var.Handle, "MR", StatsData.MR * DefenseFactor ) --cNoticeString( Var.MapIndex, "MR = " .. StatsData.MR * DefenseFactor ) cSetNPCParam( Var.Handle, "MinWC", StatsData.MinWC * DamageFactor ) --cNoticeString( Var.MapIndex, "MinWC = " .. StatsData.MinWC * DamageFactor ) cSetNPCParam( Var.Handle, "MaxWC", StatsData.MaxWC * DamageFactor ) --cNoticeString( Var.MapIndex, "MaxWC = " .. StatsData.MaxWC * DamageFactor ) cSetNPCParam( Var.Handle, "MinMA", StatsData.MinMA * DamageFactor ) --cNoticeString( Var.MapIndex, "MinMA = " .. StatsData.MinMA * DamageFactor ) cSetNPCParam( Var.Handle, "MaxMA", StatsData.MaxMA * DamageFactor ) --cNoticeString( Var.MapIndex, "MaxMA = " .. StatsData.MaxMA * DamageFactor ) --cNoticeString( Var.MapIndex, "ToSubStep = " .. Var.Phase.SubStep ) Var.Phase.SubStepTick = cCurSec() + PhaseData[Var.Phase.Step].SubDuration end --> Spawn Control if HPPercent >= 800 and HPPercent < 1000 then if Var.Phase.SpawnStep == 0 then AHarp_SpawnTornado( Var, SpawnData.SpawnMax ) Var.Phase.SpawnStep = 1 end elseif HPPercent >= 600 and HPPercent < 800 then if Var.Phase.SpawnStep == 1 then AHarp_SpawnTornado( Var, SpawnData.SpawnMax ) Var.Phase.SpawnStep = 2 end elseif HPPercent >= 400 and HPPercent < 600 then if Var.Phase.SpawnStep == 2 then AHarp_SpawnTornado( Var, SpawnData.SpawnMax ) Var.Phase.SpawnStep = 3 end elseif HPPercent >= 200 and HPPercent < 600 then if Var.Phase.SpawnStep == 3 then AHarp_SpawnTornado( Var, SpawnData.SpawnMax ) Var.Phase.SpawnStep = 4 end elseif HPPercent > 0 and HPPercent < 200 then if Var.Phase.SpawnStep == 4 then AHarp_SpawnTornado( Var, SpawnData.SpawnMax ) Var.Phase.SpawnStep = 5 end end end end --> Main-loop to handle future AI function AHarp_MainLoop( Var ) cExecCheck("AHarp_MainLoop") local CurHP, MaxHP = cObjectHP( Var.Handle ) if CurHP == nil then return ReturnAI.END end if CurHP == MaxHP then if Var.Phase.Enabled then return AHarp_Reset( Var ) end end return _G[Var.StepFunc]( Var ) end --> Natural Phase function AHarp_Natural( Var ) cExecCheck("AHarp_Natural") return ReturnAI.CPP end --> Berzerk Phase function AHarp_Berzerk( Var ) cExecCheck("AHarp_Berzerk") return ReturnAI.CPP end function AHarp_Regenerate( Var ) cExecCheck("AHarp_Regenerate") if not Var.Phase.UsedRegen then local HP, MaxHP = cObjectHP( Var.Handle ) if HP ~= nil and MaxHP ~= nil then local HPPercent = ((HP / MaxHP) * 1000) if HPPercent <= 250 then if SkillData.HealIndex ~= nil then cNPCSkillUse( Var.Handle, Var.Handle, SkillData.HealIndex ) end end end Var.Phase.UsedRegen = true end return ReturnAI.CPP end --> Defensive Phase function AHarp_Defensive( Var ) cExecCheck("AHarp_Defensive") local HasConsumed = false if not Var.Phase.RunToConsume then local ConsumePillar = nil local ConsumePillarAttempt = 0 while true do ConsumePillar = Var.Phase.PillarList[math.random(#SpawnData.Pillars)] if ConsumePillar ~= nil then break end ConsumePillarAttempt = ConsumePillarAttempt + 1 if ConsumePillarAttempt >= 50 then break end end if ConsumePillar ~= nil then Var.Phase.RunToHandle = ConsumePillar local RunX, RunY = cObjectLocate( Var.Phase.RunToHandle ) if RunX ~= nil and RunY ~= nil then Var.Phase.RunToConsume = true cAggroSet( Var.Handle, Var.Phase.RunToHandle ) cRunToUntilBlock( Var.Handle, RunX, RunY, 1000 ) end end else if Var.Phase.RunToHandle ~= nil then if cIsObjectDead( Var.Phase.RunToHandle ) == nil then local DistBetween = cDistanceSquar( Var.Handle, Var.Phase.RunToHandle ) if DistBetween <= 100 then cDamaged( Var.Phase.RunToHandle, 100, Var.Handle ) Var.Phase.StepTick = cCurSec() Var.Phase.RunToConsume = false Var.Phase.RunToHandle = nil AHarp_Step( Var ) end else Var.Phase.RunToHandle = nil end end end if Var.Phase.RunToHandle ~= nil then return ReturnAI.END else return ReturnAI.CPP end end --[[ PILLAR SECTION ]] function AHarp_PillarAI( Handle, MapIndex ) cExecCheck("AHarp_PillarAI") return ReturnAI.END end --[[ TORNADO SECTION TODO: - Spawn and insert base data in MemBlock for Handle (Index num) - Get data from MemBlock via Handle - ]] function AHarp_TornadoAI( Handle, MapIndex ) cExecCheck("AHarp_TornadoAI") local Var = MemBlock[Handle] if Var == nil then cAIScriptSet( Handle ) cNPCVanish( Handle ) return ReturnAI.END end local BossHandle = cGetNPCHandle( Var.MapIndex, "B_AHarp00" ) if BossHandle == nil then MemBlock[Handle] = nil cAIScriptSet( Handle ) cNPCVanish( Handle ) return ReturnAI.END end local X, Y = cObjectLocate( Var.Handle ) if X ~= nil and Y ~= nil then local DistBetween = cDistanceSquar( X, Y, Var.NextMoveX, Var.NextMoveY ) local RandX, RandY = cGetAroundCoord( BossHandle, math.random(1, 360), 1500 ) if Var.NextMoveTick <= cCurSec() then if RandX ~= nil and RandY ~= nil then Var.NextMoveTick = cCurSec() + math.random(2, 5) Var.NextMoveX = RandX Var.NextMoveY = RandY cRunToUntilBlock( Var.Handle, RandX, RandY, 1000 ) end elseif DistBetween <= 50 then if RandX ~= nil and RandY ~= nil then Var.NextMoveTick = cCurSec() + math.random(2, 5) Var.NextMoveX = RandX Var.NextMoveY = RandY cRunToUntilBlock( Var.Handle, RandX, RandY, 1000 ) end end end return ReturnAI.END end function AHarp_TornadoNPCAction( MapIndex, NPCHandle, PlyHandle, PlyCharNo ) cExecCheck( "AHarp_TornadoNPCAction" ) if MapIndex == nil or NPCHandle == nil or PlyHandle == nil or PlyCharNo == nil then return end local Var = MemBlock[ NPCHandle ] --> If var is nil then spawn is broken or boss is dead if Var == nil then cAIScriptSet( NPCHandle ) cNPCVanish( NPCHandle ) return end local IdleStr, IdleRemain = cGetAbstate( PlyHandle, "StaImmortal" ) if IdleStr == nil then local DistBetween = cDistanceSquar( NPCHandle, PlyHandle ) if DistBetween <= 15000 then local AbstateData = SpawnData.Tornado[Var.ID].OnHitAbstate local AbStr, AbRemain = cGetAbstate( PlyHandle, AbstateData.Index ) if AbStr == nil then local HandleObjectType = cObjectType( PlyHandle ) if HandleObjectType == ObjectType.Player then if cGetAdminLevel( PlyHandle ) > 0 then return end end if cPermileRate( AbstateData.Rate ) == 1 then if HandleObjectType == AbstateData.Target then cSetAbstate( PlyHandle, AbstateData.Index, AbstateData.Strength, 0, Var.Handle ) end end end end end end --[[ MISCELANIOUS SECTION ]] function AHarp_Debug( Message ) cExecCheck("AHarp_Debug") cAssertLog( string.format("%-20s : %s", cCurSec(), Message) ) end