ACTOR BDPlayerRocket : Rocket
{
	var int user_damage;	// damage that will be caused by splash damage

	Damage 0	// damage is solely done by the explosion
	Decal Scorch
	Speed 40	// doubled from Doom

	SeeSound "rocket/fly"

	// some information possibly not in the wiki:
	// 1. Whenever a projectile gets spawned and immediately has collision (fired directly into a wall for example) then
	//    the Spawn state will never be executed! It directly goes to the Death state.
	// 2. There are three versions of ACS_Execute: ACS_Execute, ACS_ExecuteAlways and ACS_ExecuteWithResult.
	//    The first one executes a script. However only one instance of this script can run at any time.
	//    The second one allows multiple instances of a script to run in parallel.
	//    The third one does the same as the second but the script will be executed IMMEDIATELY! The other variants
	//    take one or more tics to actually execute. This is important with code depending on the execution of scripts.

	States
	{
		Spawn:
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("SetPlayerProjectileDamage",0)
		DoStuff:
			MISL A 1 Bright
			Loop
		Death:
			// set projectile damage AGAIN. This is important if the rocket was fired directly in front of something.
			// in that case the Spawn state will never have executed in the first place leaving the projectile without
			// a defined damage. has to use "ACS_NamedExecuteWithResult" as the other types of script calling take
			// one or more tics to actually execute!
			// the executed script has to check if the projectile's damage is still 0 and only then set the damage!
			// otherwise situations like these may occur: rocket gets fired and flies through level but player is killed in
			// the meantime. weapon values gotten after the player has died may be invalid.
			TNT1 A 0 ACS_NamedExecuteWithResult("SetPlayerProjectileDamage",0)
			TNT1 A 0 A_Quake (1, 5, 0, 1000)
			TNT1 A 0 A_Quake (1, 8, 0, 800)
			TNT1 A 0 A_Quake (2, 10, 0, 500)
			TNT1 A 0 A_Quake (4, 15, 0, 300)
			TNT1 A 0 A_Quake (7, 15, 0, 150)
			MISL B 8 Bright A_Explode(user_damage, 128, XF_HURTSOURCE, true, 32)
			MISL C 6 Bright
			MISL D 4 Bright
			Stop
	}
}

/////////////////////////////////////////////////

// rocket launcher pickup that creates random weapon values
ACTOR RandomRocketLauncherPickup : PickupBase
{
	States
	{
		Spawn:
			TNT1 A 0
			TNT1 A 0 A_SetUserVar("user_isBDPickupItem", 1)	// mark thing as BorderDoom pickup item
			TNT1 A 0 A_SetUserVar("user_pickupType", ItemType_RocketLauncher)	// set pickup type to weapon (rocket launcher)
			TNT1 A 0 ACS_NamedExecuteAlways("CreateRandomRocketLauncherData")
			TNT1 A 0 A_SetSpecial(ACS_ExecuteAlways,901,0,0,0,0)	// script for picking up the item
			goto Waiting
		Waiting:
			LAUN A -1
			stop
		// called by script. makes the pickup "useable" for a short amount of time so it can be picked up.
		IsUseable:
			LAUN A 0 A_ChangeFlag("USESPECIAL", TRUE)
			LAUN A 7
			LAUN A 0 A_ChangeFlag("USESPECIAL", FALSE)
			goto Waiting
	}
}

// rocket launcher pickup that uses pre-existing/pre-set weapon values
ACTOR FixedRocketLauncherPickup : RandomRocketLauncherPickup
{
	States
	{
		Spawn:
			TNT1 A 0
			TNT1 A 0 A_SetUserVar("user_isBDPickupItem", 1)	// mark thing as BorderDoom pickup item
			TNT1 A 0 A_SetUserVar("user_pickupType", ItemType_RocketLauncher)	// set pickup type to weapon (rocket launcher)
			TNT1 A 0 A_SetSpecial(ACS_ExecuteAlways,901,0,0,0,0)	// script for picking up the item
			LAUN A -1
			stop
	}
}

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

ACTOR RealRocketLauncher : RocketLauncher
{
	Weapon.AmmoGive 0
	Weapon.BobSpeed 2.0

	+INVENTORY.UNDROPPABLE	// should only be dropped by script
	+Weapon.CHEATNOTWEAPON	// don't give this weapon when using cheats
	+Weapon.Ammo_Optional
	Tag "Rocket Launcher"

	States
	{
		Ready:
			MISG A 1 A_WeaponReady(WRF_ALLOWRELOAD)
			TNT1 A 0 A_JumpIfNoAmmo("Reload")	// auto-reload if player has more ammo
			Loop
		Select:
			TNT1 A 0 ACS_NamedExecuteAlways("SetWeaponDamageMultiplier")
//			TNT1 A 0 ACS_NamedExecute("PrintEquippedWeaponInfo", 0, CallACS("GetWeaponIndex"))
			MISG A 1 A_Raise
			Loop
		Fire:
			TNT1 A 0 A_JumpIfNoAmmo("NoAmmo")
			goto DoFire
			NoAmmo:
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "Reload")
			TNT1 A 0 A_PlaySound("player/noammo", CHAN_AUTO)
			NoAmmoHold:
			MISG A 1 A_WeaponReady(WRF_NOFIRE)
			TNT1 A 0 A_Refire("NoAmmoHold")
			goto Ready
			DoFire:
			//TNT1 A 0 A_Quake (4, 4, 0, 1)
			MISG B 0 A_GunFlash
			TNT1 A 0 A_PlaySound("rocketlauncher/fire", CHAN_AUTO)
			MISG B 2 A_FireCustomMissile("BDPlayerRocket", frandom(-(CallACS("GetCurrentSpread")/65536.0),CallACS("GetCurrentSpread")/65536.0), true, 0, 0, false, frandom(-(CallACS("GetCurrentSpread")/65536.0),(CallACS("GetCurrentSpread")/65536.0))/2)
			TNT1 A 0 ACS_NamedExecuteAlways("WeaponRecoil", 0, CallACS("GetCurrentRecoil"), 50, 10)
			MISG B 1 Offset(0,62)
			MISG B 1 Offset(0,57)
			MISG B 1 Offset(0,52)

			TNT1 A 0 A_JumpIf(CallACS("GetCurrentFirerate") == 1, "FireSpeed1")
			TNT1 A 0 A_JumpIf(CallACS("GetCurrentFirerate") == 2, "FireSpeed2")
			TNT1 A 0 A_JumpIf(CallACS("GetCurrentFirerate") == 3, "FireSpeed3")
			TNT1 A 0 A_JumpIf(CallACS("GetCurrentFirerate") == 4, "FireSpeed4")
			TNT1 A 0 A_JumpIf(CallACS("GetCurrentFirerate") == 5, "FireSpeed5")
			Goto Ready
		// fire speeds: very fast: -2, fast: -1, normal: +0, slow: +1, very slow: +2
		FireSpeed1:
			MISG B 0
			Goto FireFinish
		FireSpeed2:
			MISG B 4
			Goto FireFinish
		FireSpeed3:
			MISG B 9
			Goto FireFinish
		FireSpeed4:
			MISG B 19
			Goto FireFinish
		FireSpeed5:
			MISG B 29
			Goto FireFinish
		FireFinish:
			MISG B 1 Offset(0,48)
			MISG B 1 Offset(0,44)
			MISG B 1 Offset(0,40)
			MISG B 1 Offset(0,36)
			MISG B 1 Offset(0,32)
			MISG B 0 A_ReFire
			Goto Ready

		ReloadWork:
			MISG A 0 A_ZoomFactor(1.0)
			MISG B 1 Offset(0,36)
			MISG B 1 Offset(0,40)
			MISG B 1 Offset(0,44)
			MISG B 1 Offset(0,48)
			TNT1 A 0 A_PlaySound("rocketlauncher/reload_down", CHAN_WEAPON)
			MISG A 30	// wait for reload
			TNT1 A 0 A_PlaySound("rocketlauncher/reload_unclip", CHAN_WEAPON)
			MISG A 30	// wait for reload
			TNT1 A 0 A_PlaySound("rocketlauncher/reload_lock", CHAN_WEAPON)
			MISG A 0 A_Jump(256, "ReloadLoop")	// A_Jump jumps are virtual, "goto" is not
			//Goto ReloadLoop
		ReloadFinish:
//			MISG B 1 Offset(0,48)
			MISG B 1 Offset(0,44)
			MISG B 1 Offset(0,40)
			MISG B 1 Offset(0,36)
			Goto Ready
	}
}


///////////////////////////////
// EQUIPPABLE ROCKET LAUNCHERS
///////////////////////////////

ACTOR RealRocketLauncher0 : RealRocketLauncher
{
	Weapon.SlotNumber 1
	Weapon.AmmoType "LoadedAmmoSlot0"

	States
	{
		Reload:
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot0", CallACS("GetCurrentClipSize"), "Ready")	// ignore if fully loaded
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadWork")	// do real reload
			Goto Ready
		ReloadLoop:
			TNT1 A 0 A_TakeInventory("RocketAmmo", 1)
			TNT1 A 0 A_GiveInventory("LoadedAmmoSlot0", 1)
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot0", CallACS("GetCurrentClipSize"), "ReloadFinish")
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadLoop")
			Goto ReloadFinish
	}
}

ACTOR RealRocketLauncher1 : RealRocketLauncher
{
	Weapon.SlotNumber 2
	Weapon.AmmoType "LoadedAmmoSlot1"

	States
	{
		Reload:
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot1", CallACS("GetCurrentClipSize"), "Ready")	// ignore if fully loaded
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadWork")	// do real reload
			Goto Ready
		ReloadLoop:
			TNT1 A 0 A_TakeInventory("RocketAmmo", 1)
			TNT1 A 0 A_GiveInventory("LoadedAmmoSlot1", 1)
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot1", CallACS("GetCurrentClipSize"), "ReloadFinish")
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadLoop")
			Goto ReloadFinish
	}
}

ACTOR RealRocketLauncher2 : RealRocketLauncher
{
	Weapon.SlotNumber 3
	Weapon.AmmoType "LoadedAmmoSlot2"

	States
	{
		Reload:
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot2", CallACS("GetCurrentClipSize"), "Ready")	// ignore if fully loaded
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadWork")	// do real reload
			Goto Ready
		ReloadLoop:
			TNT1 A 0 A_TakeInventory("RocketAmmo", 1)
			TNT1 A 0 A_GiveInventory("LoadedAmmoSlot2", 1)
			TNT1 A 0 A_JumpIfInventory("LoadedAmmoSlot2", CallACS("GetCurrentClipSize"), "ReloadFinish")
			TNT1 A 0 A_JumpIfInventory("RocketAmmo", 1, "ReloadLoop")
			Goto ReloadFinish
	}
}
