// Prototype actors that provide exclusively the flags to use projectile spawn funcs.
actor ProjSpawnFuncActor
{
    +USESPAWNEVENTSCRIPT
    var int user_UseProjSpawnFunc;
}

actor ProjSpawnFuncActorFast : FastProjectile
{
    +USESPAWNEVENTSCRIPT
    var int user_UseProjSpawnFunc;
}

// Used for basic barebones projectiles
actor BasicProjectile : ProjSpawnFuncActor
{
    PROJECTILE
    damagetype "Buster"
    Obituary "%o told %k they forgot the obituary. (BasicProjectile)"
    Speed 27
    Damage (5000)
    radius 5
    height 5
    scale 2.5
    States
    {
    Spawn:
        BUST A 1
        wait
    }
}

// Used for FastProjectiles (basic projectiles with 60+ speed)
actor BasicFastProjectile : ProjSpawnFuncActorFast
{
    PROJECTILE
    damagetype "Buster"
    Obituary "%o told %k they forgot the obituary. (BasicFastProjectile)"
    Speed 60
    Damage (5000)
    radius 5
    height 5
    scale 2.5
    States
    {
    Spawn:
        BUST A 1
        wait
    }
}

// Used for basic bouncing projectiles that bounce off of planes
actor BasicBouncer : BasicProjectile
{
    +BOUNCEONFLOORS
    +BOUNCEONWALLS
    +BOUNCEONCEILINGS
    +CANBOUNCEWATER
}

// Used for basic graphical effects (eg. GeminiLaser's trail)
actor BasicGraphicEffect
{
    +CLIENTSIDEONLY
    +NOINTERACTION
    +NOGRAVITY
    -SOLID
    +MISSILE
    +DONTBLAST
    renderstyle "Translucent"
    alpha 1.0
    radius 2
    height 2
    scale 2.5
    States
    {
    // Replace this state if you *do not* want ACS to run on these items...
    Spawn:
        TNT1 A 0
        TNT1 A 0 A_GiveInventory("MM8BDMProjSpawnFuncClient", 1)
        TNT1 A 1 A_JumpIf(true, "SpawnFrame")
        wait
    
    // Replace this state if you want ACS to run on these items...
    SpawnFrame:
        "----" "#" 0
        stop
    }
}

// Used for explosion effects like Top Spin
actor BasicExplosion : ProjSpawnFuncActor
{
    Obituary "%o told %k they forgot the obituary. (BasicExplosion)"
    DamageType "Normal"
    +MISSILE
    +NOTELEPORT
    -SOLID
    +NOCLIP
    +DONTBLAST
    +NOGRAVITY
    +RIPPER
    +SKYEXPLODE
    +NOINTERACTION
    +DONTSPLASH
    +THRUGHOST
    +THRUACTORS
    +DONTREFLECT
    Damage (0)
    radius 2
    height 2
    scale 2.5
    Speed 0
    States
    {
    Spawn:
        TNT1 A 0
        TNT1 A 1 A_Explode(5000,32,0)
        stop
    Death:
        TNT1 A 1
        stop
    }
}

// Used for props that can be triggered by players to reward credit for frags
actor BasicHazardExplosion : BasicExplosion
{
    States
    {
    // Replace this state if using custom sound or OilPitIgnite
    Spawn:
        TNT1 A 0
        TNT1 A 0 A_PlaySoundEx("misc/mm3explosion","Voice")
        TNT1 A 1 A_JumpIf(true, "Explode")
        wait

    Explode:
        TNT1 A 0 A_JumpIf(CallACS("core_checkservercvar", SVCVAR_HAZARD), "Credit")
		TNT1 A 0 A_RearrangePointers(AAPTR_NULL, AAPTR_NULL, AAPTR_NULL)
        TNT1 A 1 A_JumpIf(true, "NoCredit")
        wait
    
    // Replace these states for different animation and damage value
    Credit:
        TNT1 E 0 A_SpawnItemEx("OilCanisterExplodeFX")
        TNT1 A 35 ACS_NamedExecuteWithResult("core_propexplode", 20, 120, 120)
        stop
    NoCredit:
        TNT1 E 0 A_SpawnItemEx("OilCanisterExplodeFX")
        TNT1 A 35 A_Explode(20,120,XF_HURTSOURCE,0,120)
        stop
    }
}

// Basic damager, spawned by core_damageactor
actor BasicACSDamager : BasicExplosion
{
    -USESPAWNEVENTSCRIPT
    var int user_damage;
    renderstyle "none"
    States
    {
    Spawn:
		TNT1 A 0 // $MISC
	Spawn1: // $MISC
        TNT1 A 0 A_Explode(user_damage, 8, 0, 0, 8) // $MISC
        TNT1 A 35
        stop
	Spawn2: // $MISC
        TNT1 A 0 A_Explode(user_damage, 8, XF_HURTSOURCE, 0, 8) // $MISC
        TNT1 A 35
        stop
    }
}

// Used for shield FX actors to constantly warp to the user
actor BasicShieldWarper
{
	Scale 2.5
	Height 0
	Radius 0
	+NOINTERACTION
	+CLIENTSIDEONLY
	-SOLID
	+NOGRAVITY
	+MISSILE
	+DONTBLAST
	States
	{
	Spawn:
		TNT1 A 0
		TNT1 A 0 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
		TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper", 0, 0)
		TNT1 A 0 A_Jump(256, "Shield")
		Goto Shield
	Shield:
		STAR AABBCCDD 1 A_Warp(AAPTR_TARGET, 0, 0, 16, 0, WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION)
		loop
	}
}
actor BaseShieldWarper : BasicShieldWarper {} // Proxy actor for backwards compatibility

// Used for projectile blocking shields ala Proto Shield
actor BasicShieldHitbox
{
    -SOLID
    +MISSILE
    +DONTSPLASH
    +DONTBLAST
    +DONTDRAIN
    +DONTREFLECT
    +DONTRIP
    +NOBLOOD
    +NOCLIP
    +NORADIUSDMG
    +GHOST
    +SHOOTABLE
    +NOTIMEFREEZE
    +NOGRAVITY
    +NOTARGETSWITCH
    +NOTAUTOAIMED
    +NODAMAGE
    //PainSound "item/protoreflect"
    RenderStyle "None"
    bloodtype ""
    damagefactor "Telefrag",0.0
    painchance 256
    health 99999

    Meleerange 28 // Warp X
    Accuracy 0 // Warp Y 
    Mass 8 // Warp Z

    Damage 0
    Height 42
    Radius 5
    Speed 0
    scale 2.5

    States
    {
    Spawn:
        TNT1 A 0
        TNT1 A 0 A_JumpIf(ACS_NamedExecuteWithResult("core_targetexists")==0,"Death2")
        TNT1 A 0 A_JumpIfInTargetInventory("StopShield",1,"SpawnStop")
        PLAY A 1 A_Warp(2,Meleerange,Accuracy,Mass,0,24)
        loop
    SpawnStop:
        TNT1 A 0 //A_Log("SpawnStop")
        PLAY H 1
        stop
    Pain:
        TNT1 A 0 A_PlaySound("item/protoreflect")//A_Pain
        TNT1 A 0 A_SpawnItemEx("ProtoShieldDeathFX")
        goto Spawn
    Death:
        TNT1 A 0 //A_PlaySound("item/protoreflect")
        PLAY H 1
        stop
    Death2:
        TNT1 A 0 //A_Log("Death2")
        PLAY H 1
        stop
    }
}

// Used for passive effects such as Concrete Shot's on-hit effect
actor BasicWatcher
{
    +MISSILE
    -SOLID
    +NOCLIP
    +NOINTERACTION
    +NOGRAVITY
    +DONTBLAST
    +DONTREFLECT
    +THRUACTORS
    +NOBLOCKMAP
    renderstyle none
    radius 2
    height 2
    States
    {
    Spawn:
        TNT1 A 1
        stop
    Death:
        TNT1 A 1
        stop
    }
}

// Used for map props to define basic flags
actor BasicMapProp
{
    //$Category MM8BDM-Props
    +SOLID
    -NOGRAVITY
    height 32
    radius 16
    scale 2.5
    States
    {
    Spawn:
        SKEJ AB 10
        loop
    }
}

// Used for AProp-modifying actors (Such as Gravity and JumpZ)
actor PowerApropGiver : CustomInventory
{
    +INVENTORY.AUTOACTIVATE
    States
    {
    Use:
        TNT1 A 0 ACS_NamedExecuteWithResult("core_aproppoweractivator")
		fail
    }
}

actor Once : Inventory
{
    inventory.amount 1
    inventory.maxamount 1
}

actor ChildCount : Inventory
{
inventory.amount 1
inventory.maxamount 999
}

actor CountChildrenFunc : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_TakeInventory("ChildCount",999)
TNT1 A 0 A_GiveToChildren("CountChildrenFunc2",1)
stop
}
}

actor CountChildrenFunc2 : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_GiveInventory("ChildCount",1,AAPTR_MASTER)
stop
}
}

//Rolling Cutter, Grab Buster, etc.
actor HeadTowardsTarget_arg0 : CustomInventory
{
    states
    {
    Pickup:
        TNT1 A 0 ACS_NamedExecuteWithResult("core_lookatptr", AAPTR_TARGET)
        TNT1 A 0 A_ChangeVelocity(cos(-pitch)*args[0],0,sin(-pitch)*args[0],CVF_RELATIVE|CVF_REPLACE)
        stop
    }
}

actor AliveCheck : CustomInventory
{
    states
    {
    Pickup:
        TNT1 A 0 A_JumpIfHealthLower(1,"Pickup2")
		TNT1 A 0 A_GiveInventory("AliveCheckFlag",1)
		stop
	Pickup2:
        TNT1 A 0 A_TakeInventory("AliveCheckFlag",1)
        stop
    }
}

actor AliveCheckFlag : Once {}

//Bouncers get reflected by jewel satellite
//requires +HITTRACER
actor BouncerReflectedCheck : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_CheckFlag("REFLECTIVE","Pickup2",AAPTR_TRACER)
TNT1 A 0 A_RearrangePointers(AAPTR_DEFAULT,AAPTR_DEFAULT,AAPTR_NULL)
stop
Pickup2:
TNT1 A 0 A_RearrangePointers(AAPTR_TRACER,AAPTR_DEFAULT,AAPTR_NULL)
stop
}
}

// Various actors used to make wall crawling actors work better. See searchsnake.txt
actor WarpMasterHere : CustomInventory //uses master's tracer
{
states
{
Pickup:
TNT1 A 0 A_TransferPointer(AAPTR_DEFAULT,AAPTR_MASTER,AAPTR_DEFAULT,AAPTR_TRACER) //this thing's master's tracer -> this thing
TNT1 A 0 A_GiveInventory("WarpToTracer_ClearTracer",1,AAPTR_MASTER)
stop
}
}

actor WarpToTracer_ClearTracer : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_Warp(AAPTR_TRACER,0,0,0,0,WARPF_INTERPOLATE)
TNT1 A 0 A_RearrangePointers(AAPTR_DEFAULT,AAPTR_DEFAULT,AAPTR_NULL)
stop
}
}

actor CustomStateFlag : Inventory
{
inventory.amount 1
inventory.maxamount 999
}

// Not used by Search Snake, but can be used to limit a wall crawler's duration.
actor CrawlContingencyPower : PowerUp { Powerup.duration 2 }
actor CrawlContingencyCount : Inventory
{
inventory.amount 1
inventory.maxamount 999
}

actor CrawlContingencyFlag : Once {}

actor CrawlContingency : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_JumpIfInventory("CrawlContingencyPower",1,"Pickup2")
TNT1 A 0 A_TakeInventory("CrawlContingencyCount",999)
TNT1 A 0 A_GiveInventory("CrawlContingencyPower",1)
Pickup1:
TNT1 A 0 A_TakeInventory("CrawlContingencyFlag",1)
stop
Pickup2:
TNT1 A 0 A_GiveInventory("CrawlContingencyCount",1)
TNT1 A 0 A_JumpIfInventory("CrawlContingencyCount",4,"Pickup3")
goto Pickup1
Pickup3:
TNT1 A 0 A_GiveInventory("CrawlContingencyFlag",1)
stop
}
}

// Basic SBAR actors
// To add a normal bar to your weapon, create an actor called <weapon name>_NormalBar, inherit from this
// then set the args to the colors cyan, blue
actor NormalBar
{
    renderstyle "none"
    +NOINTERACTION
    +CLIENTSIDEONLY
    args 192, 198
    States
    {
    Spawn:
        TNT1 AA 0
        stop
    }
}

// Same procedure for these. Each of these UI types can stack with one another.
// Ammo1 number, implied by NormalBar
actor NormalAmmo : NormalBar {}
// SecondBar for a weapon with 2 bars.
actor SecondBar : NormalBar { args 198, 199 }
// Ammo2 number, implied by SecondBar
actor SecondAmmo : NormalBar {}
// Mugshot if the body color doesn't match the bar.
actor MugshotColor : NormalBar {}
// Script bar for special effects on the bar (eg, flashing while active, gray while inactive, charging animations...)
actor ScriptBar : NormalBar {}


// GetActorArg functions
actor GetArg0 : CustomInventory { states { Pickup: TNT1 A 0 ACS_NamedExecuteWithResult("core_SetArgHold",args[0]) stop } }
actor GetArg1 : CustomInventory { states { Pickup: TNT1 A 0 ACS_NamedExecuteWithResult("core_SetArgHold",args[1]) stop } }
actor GetArg2 : CustomInventory { states { Pickup: TNT1 A 0 ACS_NamedExecuteWithResult("core_SetArgHold",args[2]) stop } }
actor GetArg3 : CustomInventory { states { Pickup: TNT1 A 0 ACS_NamedExecuteWithResult("core_SetArgHold",args[3]) stop } }
actor GetArg4 : CustomInventory { states { Pickup: TNT1 A 0 ACS_NamedExecuteWithResult("core_SetArgHold",args[4]) stop } }

actor WeaponChargeLevel : Inventory
{
    inventory.amount 1
    inventory.maxamount 10
}

actor BasicCooldowner : BasicWatcher
{
reactiontime 1
}

actor BasicCooldownerFunc : CustomInventory
{
States
{
Pickup:
TNT1 A 0
PickupBasic:
TNT1 A 0 A_JumpIfInTargetInventory("PowerDoubleFiringSpeedRune",1,"PickupRage")
TNT1 A 0 A_CountDown
stop
PickupRage:
TNT1 AA 0 A_CountDown
stop
PickupRemove:
TNT1 A 0 Thing_Remove(0)
stop
}
}

// Ripper cap functions
actor RemoveIfNoMaster : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_GiveInventory("CheckMasterFlag",1,AAPTR_MASTER)
TNT1 A 0 A_JumpIfInventory("CheckMasterFlag",1,"Pickup2",AAPTR_MASTER)
TNT1 A 0 // A_SpawnItemEx("ExplosionEffect1")
TNT1 A 0 Thing_Remove(0)
stop
Pickup2:
TNT1 A 0
stop
}
}

actor CheckMasterFlag : Once {}

actor CopyMastersMaster : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_TransferPointer(AAPTR_MASTER,AAPTR_DEFAULT,AAPTR_MASTER,AAPTR_MASTER)
stop
}
}

actor PierceRipperLimit : Inventory
{
inventory.amount 1
inventory.maxamount 999
}

actor RipperHit
{
PROJECTILE
Height 0
Radius 0
+NOCLIP
+NOINTERACTION
+SERVERSIDEONLY
renderstyle "None"
//+INVISIBLE
states
{
Spawn:
TNT1 A 0
Spawn2:
METL A 1 A_GiveInventory("RemoveIfNoMaster",1)
loop
}
}

//

actor CurrentRipperVictim : Once {}

actor RipperHitCount : Inventory
{
inventory.amount 1
inventory.maxamount 999
}

actor CountVictimRipperHit : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_TakeInventory("RipperHitCount",999)
TNT1 A 0 A_GiveToChildren("CountVictimRipperHitC",1)
stop
}
}

actor CountVictimRipperHitC : CustomInventory
{
states
{
Pickup:
TNT1 A 0 A_JumpIf(CheckClass("RipperHit",AAPTR_DEFAULT,true),"Pickup2")
stop
Pickup2:
TNT1 A 0 A_JumpIfInTargetInventory("CurrentRipperVictim",1,"Pickup3")
stop
Pickup3:
TNT1 A 0 A_GiveInventory("RipperHitCount",1,AAPTR_MASTER)
stop
}
}

actor DamageKillCountdowner : CustomInventory
{
    States
    {
    Pickup:
        TNT1 A 0 A_Countdown
        TNT1 A 0 A_JumpIf(reactiontime > 0, "TakeBlocker")
        stop
    TakeBlocker:
        TNT1 A 0 A_TakeInventory("DamageKillFlag", 1)
        stop
    }
}

actor DamageKillFlag : Once {}

actor ProjectileFadeFlag : Once {}
