
/*
	ChebMaster's note:
	I strongly encourage re-using my code in other mods
	-- but, PRETTY PLEASE, invent your own prefix and search-and-replace "FBD_"
	   with that prefix of yours everywhere in the borrowed code.
	Because when someone *else* goes a step further building something
		even more awesome by cros-breeeding the mods they'd have a *colossal pain*
		if identifiers in those mods are the same.
	I encountered this problem when trying to run Franken Brutal Doom Monsters-only	
		on top of Project Brutality. It went pear-shaped because PB copies *tons*
		of BD code verbatim, with class names staying *the same* - and GZDoom 
		fucks class inheritance up *hard* when it tries resolving two PK3s
		that declare identical class names.
*/

//***Che This class implements methods common for all npc companions

// Does *not* #include MARINES_syn.txt 
//   because MARINES_evil.txt (invoked from EEEVILLL_mkII.txt) already did that. 
// Not to mention the regular marines are NOT included with monstersonly

// NPC code must *always* use A_LookEx(LOF_NOSOUNDCHECK) instead of A_Look !
//   Otherwise, he chooses a random monster he heard around two corners 
//     smack in the center of a hunmongous crowd, runs towards it
//     disregarding the rest of the crowd and gets himself killed.
//   Thus, NPCs *must* be deaf. Not +AMBUSH fake deaf but *really* deaf.
//   Sight only.

ACTOR MarineNPCAbstract: Marine_AbstractSynth
{
	//$category "FBD NPC Marines"
	
	//***Che radius, height and maxdropoffheight (n/a for flying ones) MUST be kept consistent with FBD_TrySpawn in FBD_CORE.acs!
	
	Radius 12 // where chaos marine's radius is 14, I keep this to avoid breaking the throroughly tested EDAY maps
	Height 56 // NPCs have no headbox so their height is 56, compared to chaos marines' 42
	
	+FRIENDLY // And, unlike Mark-sensei's implementation, this flag stays set permanently
	
	// unlike the earlier implementations this translation applies to *all* npc marines
	Translation "112:127=[148,183,117]:[10,15,9]" // muted green
	
	//***Che I have a burning desire to find the people 
	//  who wrote the wiki off of their wild fantasies
	//  and shove that text up theirs >:(
	//+STANDSTILL //  A_LookEx: just like with A_Look, if you set this on a friendly monster, it will make the monster enter the specified state even if it does not have a target. The STANDSTILL actor flag can be used (and is pretty much required) with this function to prevent this behavior.
	// IT FUCKING DOESN'T! IT CHANGES A CRAPTON OF *OTHER* BEHAVIOUS BUT DOES *NOT* prevent entering the state.

	// The movement of this class is based on A_Wander and ThrustThing, 
	//  implementing custom movement logic instead of the game engine's default.

   // Speed 3
//	FastSpeed 22
	Speed 4
	FastSpeed 4
    Health 100
	PainChance 200
	PainChance "Kick", 255
	Monster
	Species "Marines"
	Scale 0.95

	-NORADIUSDMG

    +DONTHURTSPECIES
    +FIXMAPTHINGPOS // wiki says: Move thing out of walls. For torches and similar things that tend to be placed directly on a wall.
	// Lo. And behold. It works *exactly* as advertised - e.g. affects map things -- basically correcting after the map editor. It does NOT fix things in runtime, it only fixes the map when first parsed from a WAD.
	
	+LOOKALLAROUND // 360 degree vision
	
	+MISSILEEVENMORE
	
	
	+PUSHABLE
	+SLIDESONWALLS
	-CANNOTPUSH
	-COUNTKILL
	+DONTSPLASH
	+FIXMAPTHINGPOS
	+NORADIUSDMG
	+USESPECIAL
	+MTHRUSPECIES
	//+THRUSPECIES
	-THRUSPECIES
	
	+DONTHURTSPECIES
	+NOTAUTOAIMED
	+SHOOTABLE
	+NOBLOCKMONST // Actor can walk through monster blocking lines.
	Activation THINGSPEC_Activate
	DamageFactor "CauseSplash", 0.0 DamageFactor "CauseObjectsToSplashSlime", 0.0 DamageFactor "CauseSplashNukage", 0.0 DamageFactor "CauseSplashBlood", 0.0 DamageFactor "CauseSplashLava", 0.0
	
	damagefactor "TeleportRemover", 0.0
	damagefactor "GibRemoving", 0.0

	damagefactor "Leg", 0.0
	damagefactor "Shotgun", 0.0
	damagefactor "Minigun", 0.0
	damagefactor "SSG", 0.45 // assuming it is evil ssg marine/maradeur
	damagefactor "Slide", 0
	damagefactor "Trample", 0.0
	damagefactor "bullet", 0.0
	//damagefactor "Minigun", 0.0 //***Che this damage type is used by spider masterminds now
	damagefactor "shotgun", 0.0
	damagefactor "InstakillMarines", 40.0
	damagefactor "Desintegrate", 0.0
	damagefactor "ExplosiveImpact", 0.0
	
	damagefactor "IOS_Frost", 0.0 // immune to Icon of Sin's capital attacks

	//***Che
	// this insidious bug ONLY affects interaction between friendly monsters and player
	+DONTHARMSPECIES
	DamageFactor "FriendlyExplosion", 0.0
	
	damagefactor "Fatality", 0.0
	AttackSound "none"
	ActiveSound "none"
	damagefactor "Cut", 0.1
    BloodType "FBD_Blood", "BloodSPlatterReplacer", "FBD_SawBlood"
	damagefactor "FriendBullet", 0.0
    damagefactor "Blood", 0.0    damagefactor "GreenBlood", 0.0    damagefactor "BlueBlood", 0.0    damagefactor "Taunt", 0.0
    damagefactor "KillMe", 0.0 // they ignore captured marines
	DeathSound "DSMADTH"
	PainSound "*pain"
    damagefactor "Blood", 0.0 damagefactor "BlueBlood", 0.0 damagefactor "GreenBlood", 0.0
    damagefactor "Shrapnel", 0.0
	damagefactor "SpawnMarine", 0.0
	DamageFactor "Stealth", 0.0
	
	DamageFactor "UseNPC", 1.0 // inflicted by BD player pressing Use (implemented through weapons), along UseAttack
	PainChance "UseNPC", 255	
	
	damagefactor "HelperMarineFatallity", 0.0
	SeeSound "None"
	Obituary "%o has been gunned down by a Marine." // wtf, should not happen
	Mass 50
	
	var int user_target_friend; // a combined check fills this if our target is a player, an npc or has the FRIENDLY flag.	
	var int user_rnd_steer_cd; // random angle added to steering cooldown. Adds randomness Every 6 calls, about 3 seconds.
	
//	+NOTELEFRAG // they block teleports...
//	damagefactor "TeleportRemover", 0.3 
//	PainChance "TeleportRemover", 255 // ...but standing near any teleport destination causes them to dodge-roll!
	

	+NOPAIN // temporary, cleared after init

	var int user_non_commandable; // cannot be made to follow
	var int user_rifle_nerf; // for special occasions in EDAY where you need them only doing scratch damage to monsters
	
	var int user_standing_angle;
	
	States
	{
		SetupDefaults:
			"----" A 0 A_GiveInventory("TargetIsAMarine", 1)
			"----" A 0 A_SetUserVar("user_ddgrll_chance", 192) // chance to dodge-roll on pain. 0 = always
			"----" A 0 A_SetUserVar("user_head_type", 0) // various parts in the code use this to detect this is an npc rather than a chaos marine
			"----" A 0 A_SetUserVar("user_nag_cooldown", 300)
			"----" A 0 A_SetUserVar("user_nag_period", 60 * 35) // one minute. Note that it sets cooldown 
				// as a random from half of this to this!
				// So, actually, 30..60 seconds.
			"----" A 0 A_SetUserVar("user_forgetfulness", 35 * 8) // forget current enemy in 8 seconds of no sight 
			"----" A 0 A_SetUserVar("user_speed_limit", 14)
			
			"----" A 0 ACS_NamedExecuteAlways("FBD_AssignUniqueTidIfZero")

			"----" A 2
			"----" A 0 A_SetUserVar("user_jump_power", CallAcs("AdjustJumpPowerForEDAYMarsChapter", 50))
			"----" A 0 A_ChangeFlag("NOPAIN", 0)
			"----" A 0 A_SetUserVar("user_awakened", 1) //  go to See after weapon switch
			"----" A 0 A_SetUserVar("user_see_after_wp_sw", 1)
			"----" A 0 A_SetUserVar("user_standing_angle", angle)
			"----" A 0 A_SetUserVar("user_onspawn", user_npc_mode == 1 ? 0 : 1) // dont set if spawned by the script in CVARS.acs
			Goto WeaponSwitch // will proceed to See
			
		NpcFollowPlayer: // a just-in-case emergency reset. Would likely never get called.
			"----" A 0 A_SetUserVar("user_syn_mode", 0)
			"----" A 1 A_ChangeFlag("FRIENDLY", 1)
			Goto See			
		
		OnDeath: // see MARINES_deth.txt
			"----" A 0 ACS_NamedExecuteAlways("FBD_RegisterNPCCompanionDying")
			"----" A 1
			"----" A -1
			Stop
			
		Triumph:
			// "eat shit and die", "gotcha, bitch", "die, motherfucker" and the like:
			// (don't stop to gloat, keeps moving)
			"----" A 0 ACS_NamedExecuteWithResult("FBD_SynthMarineVoice", CHE_NAG)
			//"----" A 0 A_PlaySound("npcmarine/triumph", CHAN_VOICE)
			"----" A 0 A_SetUserVar("user_nag_cooldown", 1000)
			Goto Idle
			
		Pain.UseNPC:	
			"----" A 0 HealThing(1)
			Goto OnBeingUsed
		OnBeingUsed:
			"----" A 0 A_JumpIf(user_non_commandable, "StandLoop")
			"----" A 0 A_SetUserVar("user_onspawn", 0) // unlocks changing their standing angle
			"----" A 0 A_JumpIf(user_guarding || !user_npc_mode, "StopGuardingAndFollow")
		StopFollowingAndGuard: // this is invoked from a pain state so the target is the player who pressed Use
			"----" A 0 HealThing(100) // emulating BD21's behavior 
										// with NPCs respawning as another class 
										// every time you make them guard or follow
			
			// some of them may be girls now, requires ACS scripting
			"----" A 0 ACS_NamedExecuteWithResult("FBD_SynthMarineVoice", CHE_STAYING)
			//"----" A 0 A_PlaySound("MarineGuard", CHAN_VOICE)
			"----" A 0 A_CustomMissile ("OrderTitle2", 50, 0, 0, 2, 90)
			
			"----" A 0 A_SetUserVar("user_guarding", 1)
			"----" A 0 A_SetUserVar("user_standing_angle", angle)
			"----" A 0 A_SetUserVar("user_guard_x", x)
			"----" A 0 A_SetUserVar("user_guard_y", y)
			"----" A 0 A_SetUserVar("user_npc_mode", 0)
		
			// This only happens on the server
			"----" A 0 ACS_NamedExecuteWithResult("FBD_ChangeNpcGuardState", 1, user_guard_x, user_guard_y)
			Goto StandLoop
			
		StopGuardingAndFollow: // this is invoked from a pain state so the target is the player who pressed Use
			"----" A 0 A_SetUserVar("user_syn_mode", 0)
			"----" A 0 HealThing(100) // emulating BD21's behavior 
										// with NPCs respawning as another class 
										// every time you make them guard or follow
			"----" A 0 ACS_NamedExecuteWithResult("FBD_SynthMarineVoice", CHE_FOLLOWING)
			//"----" A 0 A_PlaySound("MarineFollow", 2)
			"----" A 0 A_CustomMissile ("OrderTitle1", 50, 0, 0, 2, 90)	
			"----" A 0 A_SetUserVar("user_guarding", 0)
			"----" A 0 A_SetUserVar("user_npc_mode", 1)
			
			// This only happens on the server
			"----" A 0 ACS_NamedExecuteWithResult("FBD_ChangeNpcGuardState", 0, 0, 0) 

			Goto See
			
		CancelMissileTargetInvalid: // NPC base class overrides
			"----" A 1
			"----" A 1 A_JumpIf(user_onspawn, "StandingLoop")

			// the NPCs turn facing that direction when their "random shuffling wile standing" next triggers
			// the function rounds the float down to integer
			"----" A 0 A_SetUserVar("user_standing_angle", 360.0 * FIXED_TO_FLOAT * CallAcs("GetAngleToTarget"))

			"----" A 1 A_JumpIf(user_guarding, "StandingLoop")
			Goto ChaseLoopWanderInstead				
		
		XDeath.Telefrag:
		Death.Telefrag:
			"----" A 0
			"----" A 0 A_Log("An NPC got telefragged. Pretend this did not happen and respawn.")
			"----" A 0 A_ChangeFlag("NOBLOCKMAP", 1)
			"----" A 0 A_ChangeFlag("SOLID", 0)
			"----" A 0 A_ChangeFlag("SHOOTABLE", 0)
			"----" A 0 ACS_NamedExecuteAlways("FBD_RespawnTrlefraggedNPC",0,user_player_num,0,0)
			"----" A -1 // the respawn script will set our state to "Vanish" when it succeeds
			
		Death.Extreme: // actor MechStompLand: MechStomp { DamageType Extreme
		XDeath:
			"----" A 0
			"----" A 0 A_JumpIfInTargetInventory("IsPlayer", 1, "PretentWasntCrushed")
			Goto DefaultXDeath
			
		XDeath.Stomp:
		Death.Stomp:
			"----" A 0
			"----" A 0 A_JumpIfInTargetInventory("IsPlayer", 1, "PretentWasntCrushed")
			Goto DefaultDeathStomp
			
		PretentWasntCrushed:	
			"----" A 0
			"----" A 0 A_Log("An NPC got crushed by player's tank. Pretend this did not happen and respawn.")
			"----" A 0 A_ChangeFlag("NOBLOCKMAP", 1)
			"----" A 0 A_ChangeFlag("SOLID", 0)
			"----" A 0 A_ChangeFlag("SHOOTABLE", 0)
			"----" A 0 ACS_NamedExecuteAlways("FBD_RespawnTrlefraggedNPC",0,user_player_num,1,0)
		FakeDodgeRoll:
			PROL ABCDE 4 // the respawn script will set our state to "Vanish" when it succeeds
			Loop
			
		Vanish:
			TNT1 A 30
			Stop
			
			
/*			
		Pain.TeleportRemover:
			"----" A 0
			"----" A 0 A_SetUserVar("user_aggro_cooldown", 0)
			"----" A 0 HealThing(100)
			Goto DodgeRoll
*/
		

/*			
	P.S. DID NOT FUCKING WORK AT ALL!!!!	
	Found another way.
	
	//***Che: WHY A_CHASE SUCKS HAIRY BALLS

	A_Chase auto-clears the target pointer if said target is dead or a friend (actor->IsFriend(actor->target))

	A_Chase on friendly monsters, on null target, always auto-sets their target to their FriendPlayer->attacker if it is not friendly and is SHOOTABLE and has Health > 0
	(where attacker is the last actor to harm him)

	THEREFORE, uising A_ClearTarget to make a friendly monster stop chasing the unreachable target
	and follow the player is *USELES* if you use A_Chase: he will re-aggro at the player's attacker immediately!
	
	THE SOLUTION:
	Use A_Wander + A_LookEx LOF_NOSOUNDCHECK and a custom state label

	A_LookEx, when no tid to hate is set, no goal is set and LOF_NOSOUNDCHECK is passed, works as a dumb wrapper for P_LookForPlayers -- which, for friendly monsters when it is not DM and not a team game, works as a dumb wrapper for P_LookForEnemies -- which will use lastenemy if it does not find an enemy, clearing lastenemy in the process. So checking LOS afterwards *is* necessary. P_LookForEnemies calls P_BlockmapSearch with blockmap distance of 10 - so, presumably, the maximum distance the friendly can aggro at a monster is around 1152..1280 (discretized to nearest 128).
	

*/			
		
		SeeGuarding:
			// return to position
			"----" A 0 A_JumpIf((x - user_guard_x) * (x - user_guard_x) + (y - user_guard_y) * (y - user_guard_y) > 100 * 100, "ChaseLoop")

			Goto StandLoop		
		
		SeeEnemy: // only A_LookEx jumps here -- *only* from the Idle state and its associated Wander substates
		
			"----" A 0 A_JumpIfTargetInLOS(1, 0, JLOSF_DEADNOJUMP)
			Goto See_FalsePositive
			
			"----" A 0 A_JumpIfInventory("IsPlayer", 1, "See_FalsePositive", AAPTR_TARGET)
			
			// Spectres are exception.
			//   (no support for invisible players since NPCs are disabled in DM!)
			"----" A 0 A_JumpIf(!CheckClass("FBD_Spectro", AAPTR_TARGET, true), 4)
			"----" A 0 A_JumpIfCloser(120, 3) // only see them reliably up close
			"----" A 0 A_JumpIfCloser(400, 1) // they don't see spectres at al at ranges over 400 map units
			Goto See_FalsePositive // no chance of seeing them past 400 map units
			"----" A 0 A_Jump(256 - 2, "See_FalsePositive") // a tiny chance, 2/256 every 2 tics, between 120 and 400 map units
			Goto See_FalsePositive
			
			"----" A 0 A_FaceTarget
			"----" A 0 A_SetUserVar("user_has_los", 1)
			Goto See
			
		See_FalsePositive:
			//"----" A 0 A_Log("False positive")
			"----" A 0 A_ClearTarget
			"----" A 0 A_SetUserVar("user_has_los", 0)
			"----" A 0 A_SetUserVar("user_aggro_cooldown", 8)
			Goto NothingToSeeHere
			
		NothingToSeeHere:
			// There is no use returning back to Idle: this NPC did acquire a target
			//	  and would do it again, breaking the idle animation.
			// Go either stand or chase.
			"----" A 0 A_JumpIf(user_guarding || !user_npc_mode || user_npc_mode == 4, "StandLoop")
			Goto ChasePlayer

		StandAfterAnim:

//***Che wtf is this supposed to do? Maybe this was the reason they kept firing at dead bodies if no player was around to follow?
//			"----" A 0 A_JumpIf(user_target_friend, 2)
//			"----" A 0 A_JumpIfTargetInLOS("Missile", 0, JLOSF_DEADNOJUMP, user_too_close_range * 2)
		
			"----" A 0 A_JumpIf(user_aggro_cooldown, "StandAfterOnAggroCooldown")
			
			// P.S. Epic Fail.
			// the looking is performed *after* animation, assuring at least one frame
			// also, can simply return to StandLoop without any intermediate jump points
			//"----" A 0 A_LookEx(LOF_NOSOUNDCHECK | LOF_NOSEESOUND | LOF_DONTCHASEGOAL, 0,0,0,0, "SeeEnemy")
			
			"----" A 0 A_SetUserVar("user_angle", angle * 100.0) 
			"----" AAAA 0 A_Chase("Missile", "Missile", CHF_DONTMOVE) // who could've thought this thing fucks the angle up resetting it to zero?
			"----" A 0 A_SetAngle(user_angle / 100.0) 
			
			Goto StandLoop

		StandAfterOnAggroCooldown:
			"----" A 0 A_SetUserVar("user_aggro_cooldown", user_aggro_cooldown > 2 ? user_aggro_cooldown - 2 : 0)
			Goto StandLoop
			
		FollowPatrolPoint:
			"----" A 0 A_SetUserVar("user_syn_mode", 0)
			"----" A 0 A_SetUserVar("user_target_friend", 0)
			"----" A 0 A_SetUserVar("user_has_los", 1)
			"----" A 0 A_SetUserVar("user_npc_mode", 5) // follow patrol point
			"----" A 0 A_SetUserVar("user_awakened", 1) // without this, a crash-to-desktop due to infinite loop!
			"----" A 1 A_SetUserVar("user_nag_cooldown", user_nag_cooldown > 16 ? user_nag_cooldown - 16 : 0)
			Goto ChaseLoop
		
		Stand:	// a stub, in case synth logic tries it	
		StandLoop:	
			// Initial position as set in the map editor (e.g. EDAY10)
			//   -- do not turn around
			"----" A 0 A_JumpIf(CheckClass("PatrolPoint", AAPTR_TARGET, true), "FollowPatrolPoint")
			
			"----" A 0 A_JumpIfInventory("IsPlayer", 1, 5, AAPTR_TARGET)
			"----" A 0 A_JumpIfInventory("TargetIsAMarine", 1, 4, AAPTR_TARGET)
			"----" A 0 A_CheckFlag("FRIENDLY", 3, AAPTR_TARGET)
			"----" A 0 A_SetUserVar("user_target_friend", 0)
			"----" A 0 A_JumpIf(true, 2)
			"----" A 0 A_SetUserVar("user_target_friend", 1)	

						
			//this line wasn't working, replaced with user_standing_angle and its management
			//"----" A 0 A_JumpIf(!user_npc_mode && !user_player_num && !user_guarding, "StandNoRandomizeNoTurn")
			
			
			//"----" A 0 A_JumpIf(!user_npc_mode || (!user_guarding && !user_player_num), "StandRandomizeNoTurn")
			
			"----" A 0 A_JumpIf(user_npc_mode == 4, "NPCStandingNearPlayer")
			
			//"----" A 0 A_JumpIf(!user_guarding && (user_npc_mode == 2 || user_npc_mode == 3) && IsPointerEqual(AAPTR_TARGET, AAPTR_NULL), "ResumeFollowing")
			
			"----" A 0 A_JumpIfInventory("evmarinenoway", 1, "TurnMoreOften")
			"----" A 0 A_Jump(2, "StandTurn")
			
			// at times, fire a probe -- in case the environment changes. 
			// Will keep turning around randomly until there is a large open space in front.
			"----" A 0 A_Jump(8, "StandProbe")
			Goto StandAnim

		NPCStandingNearPlayer:	
			"----" A 0 A_Stop
			"----" A 0 A_SetUserVar("user_noplayercansee", 0)
			
			// if pushed more than 7 map units away from the intial standing position, resume walking!
			"----" A 0 A_JumpIf(((x - user_guard_x) * (x - user_guard_x) + (y - user_guard_y) * (y - user_guard_y)) > 49, "ResumeFollowing")
			
			// When near the player, be on high alert. 
			// We don't need to suppress aggroing anymore, our goal is achieved:
			//  we are near the player!
			"----" A 0 A_SetUserVar("user_aggro_cooldown", 0) 

				
			"----" A 0 ACS_NamedExecuteWithResult("FBD_NpcGetDistanceToPlayer")
			// user_dist_to_player *may* be zero if never set!
			// takes z difference into consideration!
			"----" A 0 A_JumpIf(user_dist_to_player && user_dist_to_player < 90, "NpcPayAttentionToPlayer")
			
			"----" A 0 A_JumpIf(user_dist_to_player > 350, "ResumeFollowing")
			"----" A 0 A_JumpIf(user_dist_to_player > 250, "NpcHighlyLikelyResumeFollowing")
			"----" A 0 A_JumpIf(user_dist_to_player > 150, "NpcMaybeResumeFollowing")
			
			"----" A 0 A_SetUserVar("user_nag_cooldown", user_nag_cooldown > 4 ? user_nag_cooldown - 4 : 0)
			"----" A 0 A_JumpIf(!user_nag_cooldown && user_dist_to_player < 150, "NagNPCStanding")
			
			
			Goto StandAnim
			
		NagNPCStanding:
			"----" A 0 A_SetUserVar("user_nag_cooldown", Random(user_nag_period / 2, user_nag_period))
			"----" A 0 ACS_NamedExecuteWithResult("FBD_SynthMarineVoice", CHE_NAG)
			//"----" A 0 A_PlaySound("MRNWC", CHAN_VOICE)
			Goto StandAnim
			
		NpcHighlyLikelyResumeFollowing:
			"----" A 0 A_Jump(256 - 24, "StandAnim")
			Goto ResumeFollowing	
			
		NpcMaybeResumeFollowing:
			"----" A 0 A_Jump(256 - 4, "StandAnim")
			"----" A 0 A_SetAngle(angle + Random(-90, 90))
			Goto ResumeFollowing
			
		ResumeFollowing:

			// zero duration of this frame => game crashes
			"----" A 1 A_SetUserVar("user_npc_mode", 1) 
			Goto ChaseLoop			
			
		NpcPayAttentionToPlayer:
			
			// switch to non-aggressive standing animation
			"----" A 0 A_JumpIf(!user_npc_sas, 3)
			"----" A 0 A_SetUserVar("user_npc_sas", 0)
			"----" A 0 ACS_NamedExecuteWithResult("SkulltagTransmitNPCStateToClient")
			
			"----" A 0 ACS_NamedExecuteWithResult("FBD_NpcForceSteer") // face the player
			Goto StandAnim
			
		StandNoRandomizeNoTurn:
			"----" A 0 A_SetUserVar("user_npc_sas", 0) // the relaxed non-aggressive stance
			"----" A 0 ACS_NamedExecuteWithResult("SkulltagTransmitNPCStateToClient")
			Goto StandAnim
			
		StandRandomizeNoTurn:
			"----" A 0 A_Jump(4, 1)
			Goto StandAnim
			"----" A 0 A_SetUserVar("user_npc_sas", Random(0,3))
			"----" A 0 ACS_NamedExecuteWithResult("SkulltagTransmitNPCStateToClient")
			Goto StandAnim			
			
		TurnMoreOften:
			"----" A 0 A_Jump(48, "StandTurn")
			Goto StandAnim
			
		StandProbe:
			"----" A 0 A_CustomMissile("EvilMarineCheckFront", 46, 0, 0, 2, 0) // at the head height, not the normal half body height
			Goto StandAnim
	
		StandKeepAngle:
			"----" A 0 A_SetAngle(1.0 * (user_standing_angle + Random(-15,15)))
//"----" A 0 ACS_NamedExecuteWithResult("DEBUG_Log_Standing_Angle")			
			Goto StandTurnContinue
			
		StandTurn:
			"----" A 0 A_JumpIf(user_onspawn, "StandKeepAngle")
			"----" A 0 A_JumpIf(16, "StandKeepAngle") // the angle gets updated with their target (and friendly monsters target each other and player a lot) so this should result in life-like behavior to turning to face someone occasionally
			"----" A 0 A_SetAngle(angle + 1.0 * (Random(0,1) ? random(-90, -45) : Random(45, 90)))
			
		StandTurnContinue:	
			"----" A 0 A_SetUserVar("user_npc_sas", Random(0,3))
			"----" A 0 ACS_NamedExecuteWithResult("SkulltagTransmitNPCStateToClient")
			
			// now fire a probe to avoid standing facing a wall. 
			// Will keep turning around randomly until there is a large open space in front.
			"----" A 0 A_CustomMissile("EvilMarineCheckFront", 46, 0, 0, 2, 0) // at the head height, not the normal half body height			
			
			"----" A 0 A_JumpIf(user_weapon == 3, "StandTurn_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "StandTurn_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "StandTurn_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "StandTurn_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "StandTurn_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "StandTurn_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "StandTurn_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "StandTurn_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "StandTurn_BFG") 
			Goto StandTurn_Fists
			
			
		SwitchToStand:
			// use guard x,y to mark initial standing position so that if pushed, start walking!
			"----" A 0 A_SetUserVar("user_guard_x", x)
			"----" A 0 A_SetUserVar("user_guard_y", y)
			Goto StandLoop
			
		ChaseLoopNPCLogic:
//"----" A 0 ACS_NamedExecuteAlways("DrawDebugLineToTarget")
		
			"----" A 0 ACS_NamedExecuteWithResult("FBD_NpcGetDistanceToPlayer") // updates user_dist_to_player
		
			"----" A 0 A_JumpIf(user_npc_mode != 5 && CheckClass("PatrolPoint", AAPTR_TARGET, true), "FollowPatrolPoint")
			"----" A 0 A_JumpIf(user_npc_mode == 5, "ChaseLoopMovement") // when following patrol points, disregard NPC specific algos and revert back to ancestor's logic
			"----" A 0 A_JumpIf(!user_npc_mode || user_npc_mode == 4, "SwitchToStand") //"StandLoop")
			
			"----" A 0 A_JumpIfInventory("IsPlayer", 1, "NpcChaseTargetIsFriend", AAPTR_TARGET)
			"----" A 0 A_JumpIfInventory("TargetIsAMarine", 1, "NpcChaseTargetIsFriend", AAPTR_TARGET)
			"----" A 0 A_CheckFlag("FRIENDLY", "NpcChaseTargetIsFriend", AAPTR_TARGET)
			
			"----" A 0 A_SetUserVar("user_target_friend", 0)
		
			// Line of sight is cached in a variable to avoid spamming it (the threat evaluation phase 
			//   calls it on its own anyway, but it is throttled by doing the evaluation once in 5 tics)
			"----" A 0 A_JumpIfTargetInLOS("NpcChaseHasLOS", 0, JLOSF_DEADNOJUMP)
			Goto NpcChaseNoLOS
			
		NpcChaseTargetIsFriend:
		
			// The game engine WILL. FORCE. having a friendly as a target
			//   (either a nearby player or an another NPC)
			//   if there are no monsters in reach.
			// This behavior is not avoidable and not bypasseable.
			// We can only force-steer the NPC after the target we have in mind.
		
			//"----" A 1 A_ClearTarget
			"----" A 0 A_SetUserVar("user_npc_mode", 1) // follow the designated player
			"----" A 0 A_SetUserVar("user_target_friend", 1)
			"----" A 0 A_SetUserVar("user_npc_tgt_valid", 0)
			  // (not the player we auto-acquired as our target but our designated party leader)
			Goto NpcChaseNoLOS			
			
		NpcChaseNoLOS:
			"----" A 0 A_JumpIf(user_has_los, "NpcChaseLostLOS")
			"----" A 0 A_SetUserVar("user_enemy_memory", user_enemy_memory + 2)
			"----" A 0 A_JumpIf(user_enemy_memory > 35 * 4, "NpcChaseForgetTarget")
//"----" A 0 ACS_NamedExecuteWithResult("DebugLog01")		
			Goto NpcChaseStep2
		
		NpcChaseHasLOS:	
			"----"  A 0 A_JumpIf(!user_has_los, "NpcChaseRegainedLOS")
			"----"  A 0 A_JumpIf(user_target_friend || !CallAcs("IsSynthMarineTargetValid"), 2)
			// note melee attacks are exempt from this throttling
			//"----"  A 0 A_JumpIf(user_weapon <= 3 || CallAcs("NPC_CanOpenFireFilter"), "Missile") // NPCs are subject to the Ninjustsu Conservation Law
			"----"  A 0 A_Jump(64, "Missile") 
			
			"----" A 0 A_JumpIf(user_anim_frame_time > 0, "NpcChaseStep2") 
			
			// these below execute every second pass, or every 4 tics:
			"----" A 0 A_SetUserVar("user_enemy_memory", user_enemy_memory + 4)
			"----" A 0 A_JumpIf(user_enemy_memory > 35 * 8, "NpcChaseForgetTarget") // will just re-aggro
			
			"----" A 0 A_JumpIf(user_target_friend, "NpcChaseStep2")
			"----" A 0 ACS_NAmedExecuteAlways("FBD_NpcRememberTargetLastSeen")
			
			Goto NpcChaseStep2
			
		NpcChaseRegainedLOS:
			"----" A 0 A_SetUserVar("user_has_los", 1)
			"----" A 0 A_SetUserVar("user_npc_mode", user_target_friend ? 1 : 2) //(user_npc_mode == 3 ? 2 : user_npc_mode))
			Goto NpcChaseStep2
			
		NpcChaseLostLOS:
			"----" A 0 A_SetUserVar("user_has_los", 0)
			"----" A 0 A_SetUserVar("user_npc_mode", user_target_friend ? 1 : 3) //(user_npc_mode == 2 ? 3 : user_npc_mode))
			Goto NpcChaseStep2

		NpcChaseForgetTarget:
//"----" A 0 A_Log("NPC forget target")
			"----" A 0 A_ClearTarget
			"----" A 0 A_SetUserVar("user_has_los", 0)
			"----" A 0 A_SetUserVar("user_enemy_memory", 1)
			"----" A 0 A_SetUserVar("user_target_friend", 0)
			"----" A 0 A_SetUserVar("user_aggro_cooldown", 35)
			"----" A 0 A_SetUserVar("user_npc_mode", user_npc_mode >= 2 ? 1 : user_npc_mode)
			"----" A 0 A_JumpIf(CheckClass("PatrolPoint", AAPTR_TARGET, true), "FollowPatrolPoint")
			Goto NpcChaseReturn
			
		NpcChaseStep2:
			
			// Forget monsters after a short while!
			// This shit is FUCKING VITAL, otherwise they keep running along a wall behind which their enemy stays unreachable.
			//  Then they turn a fucking corner... And you can kiss them goodbye.
		
			// NPC *doessn't* see the monster he targets
			//"----" A 0 A_JumpIf(user_forgetfulness < 2, "NpcChaseReturn") // 0 means never
			
			
			
			// THE BLESSED FORCE-STEERING, THE CORNERSONE OF IT ALL! -------------------------------------------------------------
			
			// Work around the game engine's mulish stubbornness, not against it
			
			"----" A 0 A_JumpIf(user_anim_frame > 0 && user_anim_frame_time > 0, 4) // one in 8 (2*4) x 2 tics per step = every 16 tics
			// (, 0, max turn angle,  random deviation to add on top of steering, 0)
			
			"----" A 0 A_SetUserVar("user_rnd_steer_cd", user_rnd_steer_cd <= 0 ? 5 : (user_rnd_steer_cd > 1 ? user_rnd_steer_cd - 1 : 0))
			
			"----" A 0 ACS_NamedExecuteWithResult("FBD_NpcForceSteer", Random(0,100) < 10 ? Random(20,60) : Random(0, 15), user_rnd_steer_cd ? 0 : (user_dist_to_player < 200 ? 120 : (Random(0,100) < 5 ? 90 : 25)), 0)
			"----" A 0 A_JumpIf(true, 2)
			
			// otherwise, use a simple script that monitors distance to player
			"----" A 0 ACS_NamedExecuteWithResult("FBD_NpcGetDistanceToPlayer")
			
			// -------------------------------------------------------------------------------------------------------------------
			
			
			
			"----" A 0 A_JumpIf(!user_target_friend, "ChaseLoopNPCChasePlayer") 
			
			
			Goto NpcChaseReturn
			
			
		ChaseLoopNPCChasePlayer:
			
			//"----" A 0 A_SetUserVar("user_enemy_memory", 0) // this is for monsters
			
			// hopefully stop while near the player
			//"----" A 0 A_JumpIfInTargetLOS("NPCStandingNearPlayer", 90, JLOSF_DEADNOJUMP | JLOSF_CLOSENOSIGHT, 200, 120)
			//"----" A 0 A_JumpIfCloser(150, "NPCStandingNearPlayer")
			//P.S. delegated that to the ACS script "FBD_NpcForceSteer"
			
			"----" A 0 A_JumpIf(user_npc_mode == 4, "StandLoop")
			
			"----" A 0 A_CheckSight("NPCNoPlayerCanSee") // if out of sight of *all* players, try teleporting
			
			"----" A 0 A_JumpIf(CallAcs("FBD_NPCCheckIfShouldGetClear"), "SynthNPCGetClear") // check if
			// player is in a tank (crush npcs easily) or is currently shooting -- and we are in the way!
			
			
			"----" A 0 A_JumpIf(user_dist_to_player < 300 && (user_dang_to_player > 40 || (!CallAcs("GetIsPartyLeaderFighting") && user_dist_to_player > 96)), "NPCSlowDownNearPlayer") // halve the walking speed if closer than 300
			"----" A 0 A_JumpIf(user_dist_to_player < 600, 3)
			"----" AA 0 A_Wander // *double* walking speed if farther than 600
			"----" A 0 A_JumpIf(user_dist_to_player < 800, 5)
			"----" AAAA 0 A_Wander // *quadruple* walking speed if farther than 800
			"----" AAA 0 // an obligatory empty frame to jump to

			Goto NpcChaseReturn
			
		NPCSlowDownNearPlayer:
			
			// Note: using A_Look here would be a stupid idea because it'd jump to See immediately, 
			//  which would return here in zero time resulting in an infinite loop and a crash to desktop
			// The only way to stand still and yet react to enemies is A_Chase with the CHF_DONTMOVE flag.
			"----" A 0 A_Stop // kill his inertia
			"----" A 2 // also halves the speed of various cooldowns
			// but manage the weapon cooldown properly
			"----" A 0 A_JumpIf(!user_wp_cooldown, 2)
			"----" A 0 A_SetUserVar("user_wp_cooldown", (user_wp_cooldown < 2 ? 0 : user_wp_cooldown - 2))
			"----" A 0 // an obligatory empty frame to jump to
			
			// When near the player, be on high alert. 
			// We don't need to suppress aggroing anymore, our goal is achieved:
			//  we are near the player!
			"----" A 0 A_SetUserVar("user_aggro_cooldown", 0) 

				
			// do NOT check for teleport, assume we're in players sight	
				
			Goto NpcChaseReturnSkipRecoil // slower movement bypassing A_Recoil(-2)
		
		
		NpcChaseReturn:
			"----" A 0 
			// manage warping back to player
			"----" A 0 A_CheckSight("NPCNoPlayerCanSee")
			"----" A 0 A_SetUserVar("user_noplayercansee", 0)			
		NpcChaseReturnContinue:	
			"----" A 0 
			Goto ChaseLoopMovement	
			
		NpcChaseReturnSkipRecoil:
			"----" A 0 
			Goto ChaseLoopMoveSkipRecoil			
	
		NPCNoPlayerCanSee:
			"----" A 0 A_SetUserVar("user_noplayercansee", user_noplayercansee + 2)
			"----" A 0 A_JumpIf(user_dist_to_player < 400, "NpcChaseReturnContinue") // don't, if too close
			"----" A 0 A_JumpIf(user_noplayercansee > 350, "Pathfind")
			Goto NpcChaseReturnContinue
			
		Pathfind:
			"----" A 0
			"----" A 0 A_Log("DEBUG: an NPC is trying to warp behind their party leader")
			"----" A 0 ACS_NamedExecuteAlways("FBD_NPCCompanionGetPlayerPos")
				// writes a position 41 map units *behind* the player we are a companion of
				// into our user variables user_x, user_y and user_z
			"----" A 8 // wait for the script to execute
			"----" A 0 A_JumpIf(user_pathfind_fail, "ChaseLoopContinue")
		
			// Warp may fail. If it succeeds, it jumps to the provided success state
	
			"----" A 0 A_Warp(AAPTR_DEFAULT,user_x - x,user_y - y,user_z - z,user_angle,WARPF_ABSOLUTEOFFSET | WARPF_ABSOLUTEANGLE, "PathfindSuccess")
			
			// warp failed
			"----" A 0 A_Log("DEBUG: NPC warping failed!")
			"----" A 0 A_SetUserVar("user_noplayercansee", 350 - 35) // only try once per second
			Goto NpcChaseReturnContinue 
			
		PathfindSuccess:
			"----" A 0 HealThing(100) // emulate their old behavior with respawning to catch up with you
			"----" A 0 A_Log("DEBUG: an NPC warped behind their party leader")
			"----" A 0 A_SetUserVar("user_nag_cooldown", user_nag_cooldown > 200 ? user_nag_cooldown - 200 : 0)
			"----" A 0 A_SetUserVar("user_noplayercansee", 0)
			Goto SynthNPCGetClear // fix the awkward teleport spot by backpedaling behind player's back			
			
			
			
			
			
			
			
			
			
			
			
			
			

			

		StandAnim:
			"----" A 0 A_JumpIf(user_npc_sas == 2, "StandAnim2")
			"----" A 0 A_JumpIf(user_npc_sas == 3, "StandAnim3")
			"----" A 0 A_JumpIf(user_npc_sas == 4, "StandAnim4")
		
			"----" A 0 A_JumpIf(user_weapon == 3, "StandAnim1_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "StandAnim1_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "StandAnim1_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "StandAnim1_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "StandAnim1_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "StandAnim1_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "StandAnim1_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "StandAnim1_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "StandAnim1_BFG") 
			Goto StandAnim1_Fists			
		
		StandAnim2:
			"----" A 0 A_JumpIf(user_weapon == 3, "StandAnim2_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "StandAnim2_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "StandAnim2_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "StandAnim2_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "StandAnim2_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "StandAnim2_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "StandAnim2_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "StandAnim2_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "StandAnim2_BFG") 
			Goto StandAnim2_Fists			
		
		StandAnim3:
			"----" A 0 A_JumpIf(user_weapon == 3, "StandAnim3_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "StandAnim3_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "StandAnim3_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "StandAnim3_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "StandAnim3_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "StandAnim3_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "StandAnim3_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "StandAnim3_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "StandAnim3_BFG") 
			Goto StandAnim3_Fists	
			
		StandAnim4:
			"----" A 0 A_JumpIf(user_weapon == 3, "StandAnim4_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "StandAnim4_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "StandAnim4_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "StandAnim4_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "StandAnim4_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "StandAnim4_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "StandAnim4_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "StandAnim4_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "StandAnim4_BFG") 
			Goto StandAnim4_Fists			

		// Anim 1 should be non-aggressive (not aiming), used for facing the player up close
		// (and for NPCs pre-placed in the map editor)

		StandAnim1_Fists:
			PLA1 D 2
			Goto StandAfterAnim
		StandAnim2_Fists:
			PLA1 C 2
			Goto StandAfterAnim
		StandAnim3_Fists:
		StandAnim4_Fists:
			PLA1 A 2
			Goto StandAfterAnim	
		StandTurn_Fists:
			PKIK B 2
			Goto StandAfterAnim
			
		StandAnim1_Chainsaw:
			MAR1 P 2
			Goto StandAfterAnim
		StandAnim2_Chainsaw:
			MAR1 D 2
			Goto StandAfterAnim
		StandAnim3_Chainsaw:
			MAR1 A 2
			Goto StandAfterAnim
		StandAnim4_Chainsaw:
			MAR1 R 2
			Goto StandAfterAnim	
		StandTurn_Chainsaw:
			MAR1 QRS 1
			Goto StandAfterAnim
			
		StandAnim1_Rifle:
			SGUA A 2 // this is fom formerly EDAY only frames, backported to FBD
			Goto StandAfterAnim
		StandAnim2_Rifle:
			PLAY E 2
			Goto StandAfterAnim
		StandAnim3_Rifle:
			MAR2 A 2
			Goto StandAfterAnim
		StandAnim4_Rifle:
			MTRF B 2
			Goto StandAfterAnim			
		StandTurn_Rifle:
			MAR2 BCD 1
			Goto StandAfterAnim
			
		StandAnim1_Shotgun:
			PLA3 J 2
			Goto StandAfterAnim
		StandAnim2_Shotgun:
			PLA3 A 2
			Goto StandAfterAnim
		StandAnim3_Shotgun:
			PLA3 E 2
			Goto StandAfterAnim
		StandAnim4_Shotgun:
			PLA3 K 2
			Goto StandAfterAnim
		StandTurn_Shotgun:
			MAR3 BCD 1
			Goto StandAfterAnim			
			
		StandAnim1_SSG:
			PLA9 C 2
			Goto StandAfterAnim
		StandAnim2_SSG:
			PLA9 E 2
			Goto StandAfterAnim
		StandAnim3_SSG:
		StandAnim4_SSG:
			PLA9 A 2
			Goto StandAfterAnim
		StandTurn_SSG:
			MSSG BCD 1
			Goto StandAfterAnim			

		StandAnim1_Minugun:
			PL42 A 2
			Goto StandAfterAnim
		StandAnim2_Minugun:
			PL42 H 2
			Goto StandAfterAnim
		StandAnim3_Minugun:
			PL42 E 2
			Goto StandAfterAnim
		StandAnim4_Minugun:
			PL42 B 2
			Goto StandAfterAnim
		StandTurn_Minugun:
			MAR4 BCD 1
			Goto StandAfterAnim			
			
		StandAnim1_RL:
		StandAnim2_RL:
			MAR5 T 2 // a custom standing at ease frame frankensteined by ChebMaster for this.	
			Goto StandAfterAnim
		StandAnim3_RL:
			PL5S A 2
			Goto StandAfterAnim
		StandAnim4_RL:
			PL5S E 2
			Goto StandAfterAnim
		StandTurn_RL:
			PL5S BCD 1
			Goto StandAfterAnim
			
		StandAnim1_Plasma:
			MAR6 D 2
			Goto StandAfterAnim
		StandAnim2_Plasma:
			PLA6 A 2
			Goto StandAfterAnim
		StandAnim3_Plasma:
			PLA6 C 2
			Goto StandAfterAnim
		StandAnim4_Plasma:
			PLA6 E 2
			Goto StandAfterAnim
		StandTurn_Plasma:
			MAR6 BCD 1
			Goto StandAfterAnim			
			
		StandAnim1_Railgun:
			MRRG T 2 // a custom frame frankensteined by ChebMaster for this.
			Goto StandAfterAnim
		StandAnim2_Railgun:
			MRGA D 2
			Goto StandAfterAnim
		StandAnim3_Railgun:
			MRRG A 2
			Goto StandAfterAnim
		StandAnim4_Railgun:
			MRRG D 2
			Goto StandAfterAnim
		StandTurn_Railgun:
			MRGA BCD 1
			Goto StandAfterAnim			
			
		StandAnim1_BFG:
			MAR7 A 2
			Goto StandAfterAnim			
		StandAnim2_BFG:
			MAR7 D 2
			Goto StandAfterAnim	
		StandAnim3_BFG:
			PLA7 A 2
			Goto StandAfterAnim	
		StandAnim4_BFG:
			PLA7 E 2
			Goto StandAfterAnim				
		StandTurn_BFG:
			PLA7 BCD 1
			Goto StandAfterAnim




			
		
		// Unlike my first version, the synth machine itself takes care of dodge-rolling
		//  because all melee attacks have a small weapon cooldown and return to the synth loop afterwards.
		MeleeAttack: // weapon phase jumps here if tries firing a melee weapon
			"----" A 0 A_JumpIfTargetInLOS(1, 130, JLOSF_DEADNOJUMP, user_melee_range)
			Goto WeaponFinish
			"----" A 0 A_SetUserVar("user_wp_cooldown", user_weapon_cooldown_time)
			"----" A 0 A_JumpIf(user_weapon == 3, "AttackChainsaw") 
			"----" A 0 A_JumpIfCloser(100, "AttackPunch")
			Goto AttackKick
			// incongruously, berserk and normal inflict *identical* damage, only differing in attack cooldown and initiating range! 
		AttackKick:
			"----" A 0 A_JumpIf(user_in_air, "KickContinue")
			//"----" A 0 A_CustomMissile("FBD_CheckIfTargetIsAbove40")
			PKIK A 6 
			//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
			PLA1 J 3 ThrustThingZ(0,10,0,1)
			"----" A 0 A_Recoil(-6)
			//"----" A 0 A_JumpIfInventory("TargetIsAbove", 1, 2)
			"----" A 0 A_JumpIf(CallAcs("GetZDeltaToTarget") > 40, 2)
			"----" A 0 A_JumpIf(true, 2)
			PLA1 J 3 ThrustThingZ(0,20,0,1) // stronger updraft
			"----" A 0 //A_TakeInventory("TargetIsAbove", 1)
			
		KickContinue:	
			"----" A 0
			//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_JumpIf(true, 2)
				"----" A 0 A_FaceTarget
			"----" A 0 A_TakeInventory("MeleeMiss", 10)	
			"----" A 0
			"----" A 0 A_SetUserVar("user_loiter_count", 0)
		KickFly:	
			"----" A 0 A_Recoil(-2)
			"----" A 0 A_JumpIfTargetInLOS("AttackPunch", 0, JLOSF_DEADNOJUMP, 110)
			PLA1 J 1 A_CheckFloor("DodgeRoll") // will jump to MissileAfterDodgeRoll after rolling because we came here from syn mode 1
			"----" A 0 A_SetUserVar("user_loiter_count", user_loiter_count + 1)
			"----" A 0 A_JumpIf(user_loiter_count > 35, "See")
			Loop

		MeleeAttackPunch:
		AttackPunch: 
			"----" A 0
			PLA1 H 4 A_FaceTarget
			"----" A 0 A_Recoil(-4)
			PLA1 H 4 A_FaceTarget
			"----" A 0
			PLA1 E 4 A_CustomMissile("NpcMarinePunch",40,0,0,0)
			PLA1 E 4		
			Goto CheckForFatality	
		AttackChainsaw: // uses a mighty leap attack, even up close!
			"----" A 0 A_PlaySound("weapons/chainsaw/start", CHAN_WEAPON, 1, 0)	
			"----" A 0 A_JumpIf(user_in_air, "ChainsawContinue")
			//***Che: adjust aim *early* if target is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 2)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_FaceTarget
			// use attack frame (chainsaw forward)
			MAR1 A 6
			//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
		ChainsawContinue: 
			"----" A 0 A_Recoil(-8)
			//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
			MAR1 X 3
			"----" A 0 A_SetUserVar("user_prev_x", x)
			"----" A 0 A_SetUserVar("user_prev_y", y)
			MAR1 X 1 			
			"----" A 0 A_TakeInventory("MeleeMiss", 10)
			MAR1 XXXX 1 A_JumpIf(!CallAcs("SynthMarine_ChainsawContinueCheck"), "ChainsawCollided")
			MAR1 YYYYYYYYYYYYYYYYYYYYY 1 A_JumpIf(!CallAcs("SynthMarine_ChainsawContinueCheck"), "ChainsawCollided")			
		ChainsawCollided:
			MAR1 Y 0 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			MAR1 YY 1 A_Recoil(-2)
			MAR1 Y 0 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			MAR1 YY 1 A_Recoil(-2)
			MAR1 Y 0 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			MAR1 YY 1 A_Recoil(-2)			
			"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, "KeepSawing")
			Goto WeaponFinish
		KeepSawing:
			"----" A 0 A_TakeInventory("MeleeHitSuccess", 10)
			"----" A 0 A_Recoil(-2)
			"----" A 0 A_M_Saw("weapons/chainsaw/loop", "CSAWCUT", 1, "SSawPuff2") 
			MAR1 A 1 
			MAR1 AA 1 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			"----" A 0 A_JumpIfInventory("MeleeMiss", 5, "See")
			
				"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 4) // if we hit, your invisibility doesn't count. We SAW.
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
				"----" A 0 A_TakeInventory("MeleeHitSuccess", 1) // while successful sawing gives +2
				
			"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 1)
			Goto WeaponFinish	
			
			"----" A 0 A_Recoil(-2)
			"----" A 0 A_M_Saw("weapons/chainsaw/loop", "CSAWCUT", 1, "SSawPuff2") 
			MAR1 B 1 
			MAR1 BB 1 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			"----" A 0 A_JumpIfInventory("MeleeMiss", 5, "See")
			
				"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 4) // if we hit, your invisibility doesn't count. We SAW.
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
				"----" A 0 A_TakeInventory("MeleeHitSuccess", 1) // while successful sawing gives +2			
				
			"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 1)
			Goto WeaponFinish	
			
			"----" A 0 A_Recoil(-2)
			"----" A 0 A_M_Saw("weapons/chainsaw/loop", "CSAWCUT", 1, "SSawPuff2") 
			MAR1 C 1 
			MAR1 CC 1 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			"----" A 0 A_JumpIfInventory("MeleeMiss", 5, "See")
			
				"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 4) // if we hit, your invisibility doesn't count. We SAW.
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
				"----" A 0 A_TakeInventory("MeleeHitSuccess", 1) // while successful sawing gives +2
				
			"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 1)
			Goto WeaponFinish	
			
			"----" A 0 A_Recoil(-2)
			"----" A 0 A_M_Saw("weapons/chainsaw/loop", "CSAWCUT", 1, "SSawPuff2") 
			MAR1 D 1 
			MAR1 DD 1 A_CustomMissile("NpcMarineSawDamageVertical",35,0,angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			"----" A 0 A_JumpIfInventory("MeleeMiss", 5, "See")
			
				"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 4) // if we hit, your invisibility doesn't count. We SAW.
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				"----" A 0 A_JumpIfTargetInLOS(2)
				"----" A 0 A_Jump(256, 2)
				"----" A 0 A_FaceTarget
				"----" A 0 A_TakeInventory("MeleeHitSuccess", 1) // while successful sawing gives +2			
			
			"----" A 0 A_JumpIfInventory("MeleeHitSuccess", 1, 1)
			Goto WeaponFinish
			
			"----" A 0 A_Jump(24, "WeaponFinish") // caannot saw indefinitely!
			
			// must check if target is dead! Otherwise gets stuck sawing indestructible corpses that bleed :(
			// also breaks cycle if target moves aways
			MAR1 D 0 A_JumpIfTargetInLOS("KeepSawing",0,JLOSF_DEADNOJUMP,96)
			Goto WeaponFinish
			
		SummonAttack: // A stub to prevent parser-induced state errors. Maradeurs only.
			"----" A 0
			Goto WeaponFinish

		AnimFrameJ:
			"----" A 0 A_JumpIf(user_weapon == 3, "AnimFrameJ_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "AnimFrameJ_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "AnimFrameJ_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "AnimFrameJ_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "AnimFrameJ_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "AnimFrameJ_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "AnimFrameJ_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "AnimFrameJ_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "AnimFrameJ_BFG") 
		AnimFrameJ_Fists:
			PLA1 J 1
			Goto WeaponPhase
		AnimFrameJ_Chainsaw:
			// not actually a jump frame, using one ofthhe attack frames (leap attack)
			MAR1 Y 1
			Goto WeaponPhase
		AnimFrameJ_Rifle:
			//***Che: a *second* circumstance, beside SSG, where jumping animation exists 
			// and has radically different muzzle z
			// Sorry only noticed it when began porting the rifle marine from the original BD code
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 31)
			MARJ A 1
			Goto WeaponPhase
		AnimFrameJ_Shotgun:
			// no jumping frame
			MAR3 A 1
			Goto WeaponPhase
		AnimFrameJ_SSG:
			//***Che: a reminder: this jumping stuff *only* appears here in the SSG marine (also in Maradeur)
			// because only the SSG marine has a jumping frame that doesn't look like a walking frame
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 36) // unique circumstance of the animation phase affecting the weapon phase
			MSSG J 1
			Goto WeaponPhase
		AnimFrameJ_Minugun:
			// no jumping frame, using the standing frame
			MAR4 A 1
			Goto WeaponPhase
		AnimFrameJ_RL:
            // no jumping frame, using the standing frame
			PL5S A 1
			Goto WeaponPhase
		AnimFrameJ_Plasma:
			MAR6 J 1
			Goto WeaponPhase
		AnimFrameJ_Railgun:
			MRGA A 1
			Goto WeaponPhase
		AnimFrameJ_BFG:
			// no jumping frame, using the standing frame
			PLA7 A 1
			Goto WeaponPhase
		

		AnimFrame1:
			"----" A 0 A_JumpIf(user_weapon == 3, "AnimFrame1_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "AnimFrame1_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "AnimFrame1_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "AnimFrame1_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "AnimFrame1_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "AnimFrame1_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "AnimFrame1_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "AnimFrame1_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "AnimFrame1_BFG") 
		AnimFrame1_Fists:
			PLA1 A 1
			Goto WeaponPhase
		AnimFrame1_Chainsaw:
			MAR1 P 1
			Goto WeaponPhase
		AnimFrame1_Rifle:
			//***Che: a *second* circumstance, beside SSG, where jumping animation exists 
			// and has radically different muzzle z
			// Sorry only noticed it when began porting the rifle marine from the original BD code
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 39)
			MAR2 A 1
			Goto WeaponPhase
		AnimFrame1_Shotgun:
			MAR3 A 1
			Goto WeaponPhase
		AnimFrame1_SSG:
			//***Che: a reminder: this jumping stuff *only* appears here in the SSG marine (also in Maradeur)
			// because only the SSG marine has a jumping frame that doesn't look like a walking frame
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 31) // unique circumstance of the animation phase affecting the weapon phase
			MSSG A 1
			Goto WeaponPhase
		AnimFrame1_Minugun:
			MAR4 A 1
			Goto WeaponPhase
		AnimFrame1_RL:
			PL5S A 1
			Goto WeaponPhase
		AnimFrame1_Plasma:
			MAR6 A 1
			Goto WeaponPhase
		AnimFrame1_Railgun:
			MRGA A 1
			Goto WeaponPhase
		AnimFrame1_BFG:
			PLA7 A 1
			Goto WeaponPhase
			
		AnimFrame2:
			"----" A 0 A_JumpIf(user_weapon == 3, "AnimFrame2_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "AnimFrame2_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "AnimFrame2_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "AnimFrame2_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "AnimFrame2_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "AnimFrame2_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "AnimFrame2_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "AnimFrame2_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "AnimFrame2_BFG") 
		AnimFrame2_Fists:
			PLA1 B 1
			Goto WeaponPhase
		AnimFrame2_Chainsaw:
			MAR1 Q 1
			Goto WeaponPhase
		AnimFrame2_Rifle:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 39)
			MAR2 B 1
			Goto WeaponPhase
		AnimFrame2_Shotgun:
			MAR3 B 1
			Goto WeaponPhase
		AnimFrame2_SSG:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 31)
			MSSG B 1
			Goto WeaponPhase
		AnimFrame2_Minugun:
			MAR4 B 1
			Goto WeaponPhase
		AnimFrame2_RL:
			PL5S B 1
			Goto WeaponPhase
		AnimFrame2_Plasma:
			MAR6 B 1
			Goto WeaponPhase
		AnimFrame2_Railgun:
			MRGA B 1
			Goto WeaponPhase
		AnimFrame2_BFG:
			PLA7 B 1
			Goto WeaponPhase

		AnimFrame3:
			"----" A 0 A_JumpIf(user_weapon == 3, "AnimFrame3_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "AnimFrame3_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "AnimFrame3_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "AnimFrame3_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "AnimFrame3_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "AnimFrame3_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "AnimFrame3_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "AnimFrame3_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "AnimFrame3_BFG") 
		AnimFrame3_Fists:
			PLA1 C 1
			Goto WeaponPhase
		AnimFrame3_Chainsaw:
			MAR1 R 1
			Goto WeaponPhase
		AnimFrame3_Rifle:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 39)
			MAR2 C 1
			Goto WeaponPhase
		AnimFrame3_Shotgun:
			MAR3 C 1
			Goto WeaponPhase
		AnimFrame3_SSG:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 31)
			MSSG C 1
			Goto WeaponPhase
		AnimFrame3_Minugun:
			MAR4 C 1
			Goto WeaponPhase
		AnimFrame3_RL:
			PL5S C 1
			Goto WeaponPhase
		AnimFrame3_Plasma:
			MAR6 C 1
			Goto WeaponPhase
		AnimFrame3_Railgun:
			MRGA C 1
			Goto WeaponPhase
		AnimFrame3_BFG:
			PLA7 C 1
			Goto WeaponPhase
			
		AnimFrame4:
			"----" A 0 A_JumpIf(user_weapon == 3, "AnimFrame4_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "AnimFrame4_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "AnimFrame4_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "AnimFrame4_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "AnimFrame4_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "AnimFrame4_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "AnimFrame4_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "AnimFrame4_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "AnimFrame4_BFG") 
		AnimFrame4_Fists:
			PLA1 D 1
			Goto WeaponPhase
		AnimFrame4_Chainsaw:
			MAR1 S 1
			Goto WeaponPhase
		AnimFrame4_Rifle:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 42)
			MAR2 D 1
			Goto WeaponPhase
		AnimFrame4_Shotgun:
			MAR3 D 1
			Goto WeaponPhase
		AnimFrame4_SSG:
			TNT1 A 0 A_SetUserVar("user_muzzle_z", 31)
			MSSG D 1
			Goto WeaponPhase
		AnimFrame4_Minugun:
			MAR4 D 1
			Goto WeaponPhase
		AnimFrame4_RL:
			PL5S D 1
			Goto WeaponPhase
		AnimFrame4_Plasma:
			MAR6 D 1
			Goto WeaponPhase
		AnimFrame4_Railgun:
			MRGA D 1
			Goto WeaponPhase
		AnimFrame4_BFG:
			PLA7 D 1
			Goto WeaponPhase	
			
			
			
		Pain_Fists:
			PLA1 G 3 A_Pain
			PLA1 G 0 A_Jump(192, "DodgeRoll")
			PLA1 G 3
			Goto ShuffleFromPain
		Pain_Chainsaw:
			"----" A 0
			"----" A 0 A_ChangeFlag("NODROPOFF", 0)
			MAR1 E 3 A_Pain
			Goto PainContinue	
		Pain_Rifle:
			PLAY G 3 A_Pain
			Goto PainContinue
		Pain_Shotgun:
			"----" A 0 A_ChangeFlag("NODROPOFF", 0)
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			MAR3 E 3 A_Pain
			// pain interrupts his "charge" (merely a pre-firing pause) allowing him dodge-rolling
			//"----" A 0 A_JumpIf(user_charge && user_shots, "ShuffleFromPain") // don't interrupt charging, this jumps back into the synth loop
			"----" A 0 A_SetUserVar("user_charge", 0)
			"----" A 0 A_SetUserVar("user_shots", 0) // interrupt the firing burst
			Goto PainContinue
		Pain_SSG:
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			MSSG E 3 A_Pain
			"----" A 0 A_SetUserVar("user_shots", 0) // interrupt the firing burst
			"----" A 0 A_SetUserVar("user_notarget_cooldown", user_ambush_duration) // make the synth loop end as soon as weapon cooldown ends
			"----" A 0 A_JumpIf(user_charge && user_shots, "ShuffleFromPain") // don't interrupt charging, this jumps back into the synth loop
			"----" A 0 A_Jump(192, "DodgeRoll")
			Goto PainContinue
		Pain_Minugun:
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			MAR4 E 3 A_Pain
			"----" A 0 A_JumpIf(user_charge && user_shots > 3, "ShuffleFromPain") // don't interrupt charging, this jumps back into the synth loop
			"----" A 0 A_SetUserVar("user_shots", 0) // interrupt the firing burst
			Goto PainContinue
		Pain_RL:
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			PL5S G 3 A_Pain
			// pain interrupts his "charge" (merely a pre-firing pause) allowing him dodge-rolling
			"----" A 0 A_SetUserVar("user_charge", 0)
			"----" A 0 A_SetUserVar("user_shots", 0) // interrupt the firing burst
			Goto PainContinue
		Pain_Plasma:
			PLA6 G 3 A_Pain
			Goto PainContinue
		Pain_Railgun:
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			MRRG E 3 A_Pain
			// pain interrupts his "charge" (merely a pre-firing pause) allowing him dodge-rolling
			//"----" A 0 A_JumpIf(user_charge && user_shots, "ShuffleFromPain") // don't interrupt charging, this jumps back into the synth loop
			"----" A 0 A_SetUserVar("user_charge", 0)
			"----" A 0 A_SetUserVar("user_shots", 0) // interrupt the firing burst
			Goto PainContinue
		Pain_BFG:
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			PLA7 G 3 A_Pain
			// do NOT interrupt charging
			"----" A 0 A_JumpIf(user_charge && user_charge < user_charge_time, "ShuffleFromPain") // don't interrupt charging, this jumps back into the synth loop
			Goto PainContinue
			
			
		
		WpnFire_Rifle:
			"----" A 0 A_PlaySound("weapons/rifle") // not on the weapon channel, allowing them to overlap
			"----" A 0 A_SpawnItem ("RifleCaseSpawn", 0, 30,0)
			"----" A 0 A_SpawnItemEx("PlayerMuzzle1",27,6,user_muzzle_z, 0,0,0, 0,SXF_NOCHECKPOSITION)
			
			"----" A 0 A_JumpIf(user_rifle_nerf, "WpnFireRifleNerf1")
			
			"----" A 0 A_CustomMissile("MarineTracer",user_muzzle_z,0,angle + 0.01 * random(-50, 50), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.01 * random(-50, 50))
			// CMF_AIMDIRECTION's effect is auto-setting CMF_ABSOLUTEPITCH internally! -- meaning you have to provide the pitch yourself
			
		WpnFireRifleContinue:
			// while can seee target, randomly increase burst length -- just a little bit:
			"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "WeaponAfterFiring")
			"----" A 0 A_JumpIfTargetInLOS(1, 0, JLOSF_DEADNOJUMP) 
			Goto WeaponAfterFiring
			"----" A 0 A_Jump(24, "OneMoreShot")
			Goto WeaponAfterFiring
			
		WpnFireRifleNerf1:
			"----" A 0 A_JumpIf(user_rifle_nerf > 1, "WpnFireRifleNerf2")
			"----" A 0 A_CustomMissile("NerfedMarineTracer",user_muzzle_z,0,angle + 0.01 * random(-50, 50), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.01 * random(-50, 50))
			Goto WpnFireRifleContinue
			
		WpnFireRifleNerf2:
			// allows dispensing with specialized actors like SlaughterlambNPC in EDAY cutscenes
			"----" A 0 A_CustomMissile("SlaughterlambTracer",user_muzzle_z,0,angle + 0.01 * random(-50, 50), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.01 * random(-50, 50))
			Goto WpnFireRifleContinue
			
			
			
		WpnFire_Shotgun:
			"----" A 0 A_CustomMissile("DistantFireSoundShotgun", user_muzzle_z, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, 0)
			"----" A 0 A_PlaySound("weapons/sg", CHAN_WEAPON)
			"----" A 0 A_PlaySound("weapons/sgpump", 5)

			
			// visual effects:
			"----" AAAAAAAA 0 A_CustomMissile("ShotgunParticles", user_muzzle_z, 0, angle + random(-12, 12), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + random(-9, 9))	
			"----" A 0 A_SpawnItemEx("PlayerMuzzle2",24,10,user_muzzle_z, 0,0,0, 0,SXF_NOCHECKPOSITION)
			
			// perfectly mimic the spread of player's weapon with only half the pellet number (5 vs 9):
			"----" AA 0 A_CustomMissile("MarineShotgunTracer", 36, 0, 0.05 * random(-50, 50) + angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.05 * random(-10, 10))
			"----" AAA 0 A_CustomMissile("MarineShotgunTracer", 36, 0, 0.05 * random(-25, 25) + angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.05 * random(-25, 25))
			
			// player's:
			// SHTN A 0 A_FireBullets (5, 1, 4, 13, "ShotgunPuff", FBF_NORANDOM)
			// SHTN A 0 A_FireBullets (2.5, 2.5, 5, 13, "ShotgunPuff2", FBF_NORANDOM)
			
			// CMF_ABSOLUTEANGLE is required for shotguns to avoid extra spread
			//    at invisible targets adding to shotgun's spread.
			// Otherwise, CMF_AIMDIRECTION would be preferrable

			Goto WeaponAfterFiring		
			
		WpnFire_SSG:
			"----" A 0 A_CustomMissile("DistantFireSoundSSG", user_muzzle_z, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, 0)
			"----" A 0 A_PlaySound("SSHFIRE", CHAN_WEAPON)
			// visual effects:
			"----" AAAAAAAA 0 A_CustomMissile("ShotgunParticles", user_muzzle_z, 0, angle + random(-12, 12), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + random(-9, 9))	
			"----" A 0 A_SpawnItemEx("PlayerMuzzle3",30,8,user_muzzle_z, 0,0,0, 0,SXF_NOCHECKPOSITION)

			
			// just like regular shotgun guy, fires *half* the number of tracers compared to player's SSG
			// with each tracer doing nearly as much damage (12 vs 13)
			"----" A 0 A_CustomMissile("NpcMarineShotpuff", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0)
			
			// perfectly mimic the spread of player's weapon with only half the pellet number
			"----" AAAA 0 A_CustomMissile("MarineShotgunTracer", user_muzzle_z, 0, angle + 0.1 * random(-50, 50), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.1 * random(-5, 5))
			"----" AAAAA 0 A_CustomMissile("MarineShotgunTracer", user_muzzle_z, 0,angle +  0.1 * random(-30, 30), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.1 * random(-15, 15))
			
			// CMF_ABSOLUTEANGLE is required for sotguns to avoid extra spread at invisible adding to shotgun's spread.
			// Otherwise, CMF_AIMDIRECTION would be preferrable
			
			Goto WeaponAfterFiring

		WpnFire_Minugun:
			//***Che: poor thing doen't know what a division remainder is, got confused by '%' in (user_shots % 2)
			//***Che: it *does* -- the problem is you CANNOT use trinary operators to swap strings
			//  Obviously, unlike ACS, in DECORATE strings aren't integer indices.
			//"----" A 0 A_SpawnItemEx((user_shots - (user_shots / 2) * 2 > 0) ? "PlayerMuzzle2" : "PlayerMuzzle1", user_muzzle_z,9,27, 0,0,0, 0,SXF_NOCHECKPOSITION)
			//Execution could not continue.
			//Script error, "chebskies-EDAY-2.pk3:marines_evil.txt" line 818:
			//Expected ',', got 'user_shots'.

			"----" A 0 A_JumpIf(user_shots % 2, 3)
			"----" A 0 A_SpawnItemEx("PlayerMuzzle1", user_muzzle_z,9,27, 0,0,0, 0,SXF_NOCHECKPOSITION)
			"----" A 0 A_JumpIf(true, 2)
			"----" A 0 A_SpawnItemEx("PlayerMuzzle2", user_muzzle_z,9,27, 0,0,0, 0,SXF_NOCHECKPOSITION)
			
			"----" A 0 A_PlaySound ("CHGNSHOT", CHAN_WEAPON)
			"----" A 0 A_PlaySound("FARMGN", 5)
			"----" A 0 A_SpawnItem ("RifleCaseSpawn", 0, 30,0)

			"----" A 0 A_CustomMissile("NPCMarineMinigunTracer", user_muzzle_z, 0, angle + 0.1 * Random(-25, 25), CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, (user_best_d ? user_best_p * 0.005493164 : 0) + 0.1 * Random(-25, 25)) 

			"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "WeaponAfterFiring")
			"----" A 0 A_JumpIfTargetInLOS(1, 0, JLOSF_DEADNOJUMP) 
			Goto WeaponAfterFiring
			"----" A 0 A_Jump(96, "OneMoreShot")
			Goto WeaponAfterFiring

		WpnFire_RL:
			// no muzzle flash
			"----" A 0 A_PlaySound ("DSRFIRE", CHAN_WEAPON)
			
			// makes cacoes dodge the incoming rocket
			"----" A 0 A_CustomMissile("Alerter", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0) 
			
			"----" A 0 A_CustomMissile("NpcMarineRocket", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0) 
			"----" A 0 A_CustomMissile("RocketGlassBreaker", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0) 
			Goto WeaponAfterFiring
			
		WpnFire_Plasma:
			"----" A 0 A_CustomMissile("NPCPlasmaBall",user_muzzle_z,0,angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0)
			
			// while can seee target, randomly increase burst length:
			"----" A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "WeaponAfterFiring")
			"----" A 0 A_JumpIfTargetInLOS(1, 0, JLOSF_DEADNOJUMP) 
			Goto WeaponAfterFiring
			"----" A 0 A_Jump(96, "OneMoreShot")
			Goto WeaponAfterFiring
			
		WpnFire_Railgun:
			// no muzzle flash
			
			"----" A 0 A_PlaySound("RAILF1", CHAN_WEAPON)
			"----" A 0 A_CustomMissile("NpcMarineRailgunHACK", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | (user_best_d ? CMF_AIMDIRECTION : CMF_OFFSETPITCH) | CMF_SAVEPITCH, user_best_d ? user_best_p * 0.005493164 : 0) 
			Goto WeaponAfterFiring

		WpnFire_10K: // stubs to prevent ancestor's jump function spamming the log with error messages
		WpnFire_Unmaker:
		WpnFire_MG42:
			// only evil marines and maradeurs support these two weapons.
			
		WpnFire_BFG:
			"----" A 0 A_PlaySound("misc/supermaster_bfg_fir", CHAN_WEAPON)  // much larger roloff dist
			"----" A 0 A_SpawnItemEx("BFGMuzzle3",30,7,30, momx,momy,momz, 0,SXF_NOCHECKPOSITION | SXF_ABSOLUTEVELOCITY)
			"----" A 0 A_CustomMissile("MarineBFGBall", user_muzzle_z, 0, angle, CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			Goto WeaponAfterFiring
			
/*
		// NPCs cannot rely on A_Chase (see comment above) so the states are overridden with A_Wander
			
		ChaseFrame1:
			"----" A 0 A_JumpIf(user_weapon == 3, "ChaseFrame1_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "ChaseFrame1_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "ChaseFrame1_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "ChaseFrame1_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "ChaseFrame1_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "ChaseFrame1_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "ChaseFrame1_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "ChaseFrame1_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "ChaseFrame1_BFG") 			
		ChaseFrame1_Fists:
			"----" A 0 A_JumpIf(user_weapon != 2, 2)
			"----" A 0 A_Wander //200% speed with berserk
			PLA1 D 1 A_Wander
			"----" A 0 A_Wander //150% speed with fists			
			PLA1 D 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Chainsaw:
			"----" A 0 A_PlaySound("weapons/chainsaw/idle", CHAN_WEAPON)
			"----" A 0 A_Wander //150% speed with chainsaw
			MAR1 SS 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Rifle:
			PLAY DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Shotgun:
			PLA3 DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_SSG:
			PLA9 DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Minugun:
			PL42 DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_RL:
			PL5S DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Plasma:
			PLA6 DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_Railgun:
			MRRG DD 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame1_BFG:
			PLA7 DD 1 A_Wander
			Goto ChaseLoopContinue	



		ChaseFrame2:
			"----" A 0 A_JumpIf(user_weapon == 3, "ChaseFrame2_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "ChaseFrame2_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "ChaseFrame2_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "ChaseFrame2_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "ChaseFrame2_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "ChaseFrame2_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "ChaseFrame2_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "ChaseFrame2_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "ChaseFrame2_BFG") 
		ChaseFrame2_Fists:
			"----" A 0 A_JumpIf(user_weapon != 2, 2)
			"----" A 0 A_Wander //200% speed with berserk
			PLA1 A 1 A_Wander
			"----" A 0 A_Wander //150% speed with fists			
			PLA1 A 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Chainsaw:
			"----" A 0 A_Wander //150% speed with chainsaw
			MAR1 PP 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Rifle:
			PLAY AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Shotgun:
			PLA3 AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_SSG:
			PLA9 AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Minugun:
			PL42 AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_RL:
			PL5S AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Plasma:
			PLA6 AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_Railgun:
			MRRG AA 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame2_BFG:
			PLA7 AA 1 A_Wander
			Goto ChaseLoopContinue			



		
		ChaseFrame3:
			"----" A 0 A_JumpIf(user_weapon == 3, "ChaseFrame3_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "ChaseFrame3_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "ChaseFrame3_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "ChaseFrame3_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "ChaseFrame3_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "ChaseFrame3_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "ChaseFrame3_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "ChaseFrame3_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "ChaseFrame3_BFG") 
		ChaseFrame3_Fists:
			"----" A 0 A_JumpIf(user_weapon != 2, 2)
			"----" A 0 A_Wander //200% speed with berserk
			PLA1 B 1 A_Wander
			"----" A 0 A_Wander //150% speed with fists			
			PLA1 B 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Chainsaw:
			"----" A 0 A_Wander //150% speed with chainsaw
			MAR1 QQ 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Rifle:
			PLAY BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Shotgun:
			PLA3 BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_SSG:
			PLA9 BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Minugun:
			PL42 BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_RL:
			PL5S BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Plasma:
			PLA6 BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_Railgun:
			MRRG BB 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame3_BFG:
			PLA7 BB 1 A_Wander
			Goto ChaseLoopContinue	




		ChaseFrame4:
			"----" A 0 A_JumpIf(user_weapon == 3, "ChaseFrame4_Chainsaw")
			"----" A 0 A_JumpIf(user_weapon == 4, "ChaseFrame4_Rifle")
			"----" A 0 A_JumpIf(user_weapon == 5, "ChaseFrame4_Shotgun")
			"----" A 0 A_JumpIf(user_weapon == 6, "ChaseFrame4_SSG")
			"----" A 0 A_JumpIf(user_weapon == 7, "ChaseFrame4_Minugun")
			"----" A 0 A_JumpIf(user_weapon == 8, "ChaseFrame4_RL")
			"----" A 0 A_JumpIf(user_weapon == 9, "ChaseFrame4_Plasma")
			"----" A 0 A_JumpIf(user_weapon == 10, "ChaseFrame4_Railgun")
			"----" A 0 A_JumpIf(user_weapon == 11, "ChaseFrame4_BFG") 
		ChaseFrame4_Fists:
			"----" A 0 A_JumpIf(user_weapon != 2, 2)
			"----" A 0 A_Wander //200% speed with berserk
			PLA1 C 1 A_Wander
			"----" A 0 A_Wander //150% speed with fists			
			PLA1 C 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Chainsaw:
			"----" A 0 A_Wander //150% speed with chainsaw
			MAR1 RR 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Rifle:
			PLAY CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Shotgun:
			PLA3 CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_SSG:
			PLA9 CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Minugun:
			PL42 CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_RL:
			PL5S CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Plasma:
			PLA6 CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_Railgun:
			MRRG CC 1 A_Wander
			Goto ChaseLoopContinue
		ChaseFrame4_BFG:
			PLA7 CC 1 A_Wander
			Goto ChaseLoopContinue			
*/			
			
	}

}


// ============================ NPC WEAPON PROJECTILES =======================

// NOTE: as per convention they do half the player's damage on UV, because NPCs are friendly monsters
//   so their damage scales with difficulty setting the same way it does for regular monsters.


//MarineTracer - use as is. 

// super shotgun's central short-range hitscan

ACTOR NPCMarineShotpuff: FastProjectile
{
	Species "Marines"
	+THRUGHOST
	+DONTSPLASH
	+THRUSPECIES
	+MTHRUSPECIES
	Radius 4
	Height 2
	Speed 300 // unlike evil marines', whose takes 3 tics to travel those 300 map units, we do it in one.
	DamageType SSG
	Damage (random(20,20)) // player's central hitscan does 40, we do 50% of that 
		// -- see above about monsters on UV doing half player's damage
	States
	{
		Spawn:
			TNT1 A 1 // travel 300 map units
			TNT1 A 0 A_Stop
			Stop
		Death:
			TNT1 A 1
			Stop
	}
}


// minigun -----------------------------------------------------

ACTOR NPCMarineMinigunTracer: MarineTracer
{
	damagetype Minigun
}


// plasma -----------------------------------------------------



// see FBD_Plasma_ball.txt



// rocket -----------------------------------------------------

ACTOR NPCMarineRocket: FBD_Rocket2
{
	+DONTHARMSPECIES
	+THRUSPECIES
	+MTHRUSPECIES
	Species "Marines"
	Damage (random (150, 150)) // half the player's by default
	
	States
	{
		//***Che: supporting same-species infighting
		KinslayerAdjust:
			TNT1 A 0 A_ChangeFlag("MTHRUSPECIES", 0)
			TNT1 A 0 A_ChangeFlag("THRUSPECIES", 0)
			Goto Live		
		
		Spawn:
		
			MISL A 0
			TNT1 A 0 A_PlaySound("DSRLAUN")
			//***Che: so much fucking effort put into finding this one that works -- because wiki is crap!
			// the only one that works without a target is CMF_AIMDIRECTION, and it takes *relative* angle :(
			
			//***Che: For backblast to work properly, use the CMF_SAVEPITCH flag *every* time you fire a rocket 
			// (unless you are a player avatar calling A_FireCustomMissile)
			// Otherwise rocket's pitch is zero on spawn and any secondary projectiles, 
			// like the backblast here, fly straight horizontal!
			
			// This one is for hitting monsters extra hard with Shotgun damage type,
			//   does no self-harm by design
			TNT1 A 0 BRIGHT A_CustomMissile("RocketBackblast", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)

			// this one I had to modify to avoid self-harm
			TNT1 A 0 BRIGHT A_CustomMissile("NPCMarineRocketBackblast2", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			
			// This one is again to splatter monsters, a *huge* Shrapnel damage
			//   with self-harm disabled	
			TNT1 A 0 BRIGHT A_CustomMissile("RocketBackblast3", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			TNT1 A 0 BRIGHT A_CustomMissile("BackblastFlames1", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			TNT1 A 0 BRIGHT A_CustomMissile("BackblastFlames2", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			TNT1 A 0 BRIGHT A_CustomMissile("BackblastFlames3", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			TNT1 A 0 BRIGHT A_CustomMissile("BackblastFlames4", 0, 0, 180, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, 0-pitch)
			
			MISL AA 1 Bright // wait to leave the spawner 
			
			//***Che
			TNT1 A 0 A_JumpIfInventory("IsAKinSlayer", 1, "KinslayerAdjust", AAPTR_TARGET)
			
			Goto Live
		Death:
			EXPL A 0 Radius_Quake (3, 8, 0, 15, 0)//(intensity, duration, damrad, tremrad, tid)
			TNT1 A 0 A_CustomMissile("ExplosionSplashSpawner")
			TNT1 A 0 A_SpawnItemEx ("DetectFloorCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_SpawnItemEx ("DetectCeilCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_SpawnItemEx ("UnderwaterExplosion",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_SpawnItemEx ("ExplosionFlareSpawner",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 AAAAAA 0 A_CustomMissile ("BDExplosionparticles", 0, 0, random (0, 360), 2, random (0, 360))
			TNT1 AAAA 0 A_CustomMissile ("BDExplosionparticles2", 0, 0, random (0, 360), 2, random (0, 90))
			TNT1 AAAA 0 A_CustomMissile ("MediumExplosionFlames", 0, 0, random (0, 360), 2, random (0, 360))
			
			// half the player's damage -- and more cheating, self harm greatly reduced
			TNT1 A 0 A_SpawnItemEx ("NPCMarineRocketExplosion",0,0,13,0,0,0,0,SXF_NOCHECKPOSITION,0)
			
			TNT1 A 0
			TNT1 A 2
			TNT1 A 0 A_SpawnItemEx ("LiquidExplosionEffectSpawner",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_PlaySound("FAREXPL", 3)
			TNT1 A 15
			TNT1 A 0 A_PlaySound("distantexp", 5)
			Stop	
	
	}
}

ACTOR NPCMarineRocketExplosion: RocketExplosion
{
	DamageType "FriendlyExplosion" // do NOT hurt players
	States {
		Spawn:
			Goto Death
		Death:
			TNT1 A 0
			TNT1 A 0 A_SpawnItem("WhiteShockwave")
			TNT1 A 3
			// 50 instead of 100 (half the player's) plus self harm reduced to near cosmetic value of 20
			TNT1 A 0 A_Explode(20,150)
			TNT1 A 0 A_Explode(30,150, 0)
			Stop	
	}
}

ACTOR NPCMarineRocketBackblast2: RocketBackblast2
{
	DamageType "FriendlyExplosion"
	States
	{
		Death:
			TNT1 A 3
			TNT1 A 0 A_Explode(11, 2, 0) // NO self-damage!
			TNT1 A 0 A_SpawnItemEx ("LiquidExplosionEffectSpawner",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_CustomMissile("ExplosionSmokeHD", 2, 0, random(0, 360), 2, random(0, 90))
			Stop	
	}
}





// railgun CTHULHACKERY --------------------------------------------------------------------


/*
I RAN OUT OF CUSS WORDS at the game engine's implementation of rail attack (the inflexible autoaim options of it).
In the end, making them fire true railgun was impossible. Had to create a horrible hackaround.


The railgun beams work properly, going thjrough several monsters in a row then causing explosion and spalling at a wall that penetrates thin walls (hellooo, closing doors?)
Had to invent projectile that every time it hits someone it relaunches itself behind them to emulate a beam penetrating all. At arbitrary distance of 64 map units, so hopefully won't ever hit the same monster twice. Of two monsters close together, one could survive unscathed, though.
The spalling effects are identical to *your* railgun, simply doing 50% damage. 

To render as a rail attack, with the spiral particle effect, I had to invent an even more sanity-melting hack. When the rail attack (a very fast projectile, not a hitscan) finally hits map geometry it turns itself into a monster, which makes the one who fired it its enemy, and fires a sfx missile at the evil marine who fired it. The sfx missile immediately teleports to the evil marine's muzzle position, turns *itself* into a monster -- which makes the first former missile its enemy -- and fires a purely decorative, fully autoaimed railgun shot at it.

Works like a charm, makes the rail beam render between the points *I* dictate, not where the game engine's iffy and inflexible autoaiming wants it to go :) 

*/

Actor NPCMarineRailgunHACK: FastProjectile 
{
	Radius 2
	Height 2
	Speed 900
	Damage (random(200, 200))
	
	DamageType Railgun
	Decal None //"Scorch"
	
	+THRUSPECIES
	+MTHRUSPECIES
	Species "Marines"

	Speed 999
	+SKYEXPLODE
	+THRUGHOST
	DeathSound None //"weapons/plasmax"
    SeeSound None
	MissileType None //"NPCMarineRailgunFlameTrailsBlue" //"RailgunTrailEffect" not visible in gzdoom ??? :( 
	Missileheight 12
	
	+HITMASTER // to receive someone we hit in our master pointer on hit
	
	States
	{
		Spawn:
			TNT1 A 1
			Loop
		Crash:
		XDeath: // hit an actor
			TNT1 A 0
			
			// some monsters cause the same effect as if we hit a wall
			TNT1 A 0 A_JumpIf(CheckClass("TheCyberdemon", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("CyberdemonChad", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("FBD_Mastermind", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("MightyMastermind", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("FBD_EnemyMBT", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("PlayerTank", AAPTR_MASTER, true), "Death")
			TNT1 A 0 A_JumpIf(CheckClass("Tank", AAPTR_MASTER, true), "Death")
		
			// fire a daughter missile that would re-launch us 1 tic and 64 map units later
			// (repeater because it can hit map geometry before it has a chance to relaunch
			//  - so repeater acts identical way to us in relation to wall hits:
			//  spawns spalling, spawns railgun spiral effect
			TNT1 A 0 A_CustomMissile ("NPCMarineRailgunHACKRepeater", 0, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH | CMF_TRACKOWNER, pitch)
			TNT1 A 0 A_Stop
			
			// make some noise
			TNT1 A 0 A_PlaySound("weapons/plasmax")
			TNT1 A 0 A_SpawnItemEx("RailgunTrailEffect",0,0,0, 0,0,0, 0,SXF_NOCHECKPOSITION,0)
			
			TNT1 A 1
			Stop
		Death: // hit map geometry
			
			// This one makes the explosion and generates spall -- UNLESS we hit sky
			// We delegate that task (including telling if it was a sky hit) to it.
			TNT1 A 0 A_CustomMissile ("NPCMarineRgWallHit", 0, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH | CMF_TRACKOWNER, pitch)
			
			// ..while we employ a horrible, sanity-melting cthulhack
			// to make the game engine draw a rail spiral where WE need,
			// not where the game engine's moronic autoaim options want it to go!
			TNT1 A 0 A_RearrangePointers(AAPTR_DEFAULT, AAPTR_NULL, AAPTR_NULL, 0) // clear our master pointer
			TNT1 A 0 A_ChangeFlag("MISSILE", 0) // should be cleared by our death state anyway but let's make sure
			TNT1 A 0 A_ChangeFlag("ISMONSTER", 1) // by making ourselves a monster 
				// we change the meaning of our target pointer: the evil marine who fired us
				// is now our enemy
			
			
			// The direction doesn't affect anything because the projectile is intangible.
			// would fail to fire if we don't have a target
			// Since this is a seeker missile it receives the evil marine who fired us as its tracer
			TNT1 A 0 A_CustomMissile ("NPCMarineRgBeamSfx")
			TNT1 A 30
			Stop
			
	}
}

ACTOR NPCMarineRgBeamSfx
{
	PROJECTILE
	+SEEKERMISSILE
	+NOINTERACTION
	+CLIENTSIDEONLY
	Speed 0
	Height 1
	Radius 2
	States
	{
		Spawn:
			// warp to his muzzle position and hope he did not move far since the original projectile was fired
			TNT1 A 0 NODELAY A_Warp(AAPTR_TRACER,29,4,44,0,WARPF_STOP,"WarpedOk")
			TNT1 A 1
			Stop
		WarpedOk:
			// cheat again making us a monster and thus the actor who fired us our enamy
			TNT1 A 0 A_ChangeFlag("ISMONSTER", 1)
			
			// fire an autoaimed, purely decorative railgun beam at our enemy
			TNT1 A 0 A_CustomRailgun(0, 0, "95b2fc", "4b61ff", RGF_FULLBRIGHT | RGF_CENTERZ, 1, 0, "RailgunAlerterPuff")
			TNT1 A 30
			Stop
	}
}

ACTOR NPCMarineRgWallHit
{
	Speed 1
	Radius 1 // vs radius 2 height 2 of the projectile who fired us -- 
		// so hopefuully we'd travel that one map unit before hitting map geometry.
	Height 1
	PROJECTILE
	-SKYEXPLODE
	+THRUACTORS
	+THRUGHOST
	Decal "Scorch"
	States
	{
		Spawn:
			TNT1 AAAAA 1
			Stop
		Death:
// act as the penetrator
			TNT1 A 0
			
			//half the number of player's, each one doing the same damage
			TNT1 AAAAAAAAAAAAAA 0 A_CustomMissile("NPCMarineRailgunSpallTracker1", 0, 0, random(-30,30), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, pitch + random(-30, 30))
			

			TNT1 A 0 A_SpawnItemEx ("Footstep91",0,0, 40,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 
			RAIL A 0 A_SpawnItemEx ("ExplosionSplashSpawner", 0, 0, 0)
			RAIL A 0 A_SpawnItemEx ("DetectFloorCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			RAIL A 0 A_SpawnItemEx ("DetectCeilCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 AA 0 A_CustomMissile ("SparkXNoModel", 2, 0, random (0, 360), 2, random (0, 360))
			RAIL A 0 A_SpawnItem("RailgunFlameTrails")
			
			EXPL A 0 Radius_Quake (3, 8, 0, 15, 0)
			RAIL A 0 A_SpawnItemEx ("UnderwaterExplosion",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			RAIL A 0 A_SpawnItemEx ("ExplosionFlareSpawner",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 AAA 0 A_CustomMissile ("BDExplosionparticles", 0, 0, random (0, 360), 2, random (40, 90))
			TNT1 AA 0 A_CustomMissile ("BDExplosionparticles2", 0, 0, random (0, 360), 2, random (40, 90))
			TNT1 AA 0 A_CustomMissile ("BDExplosionparticles3", 10, 0, random (0, 360), 2, random (40, 90))
			TNT1 AAA 0 A_CustomMissile ("ExplosionFlames", 0, 0, random (0, 360), 2, random (0, 360))
			
			
			//inflict damage
			RAIL A 0 A_SpawnItemEx ("NPCMarineRocketExplosion",0,0,13,0,0,0,0,SXF_NOCHECKPOSITION,0)
			
			
			TNT1 A 2
			RAIL A 0 A_SpawnItemEx ("LiquidExplosionEffectSpawner",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			RAIL A 0 A_PlaySound("FAREXPL", 3)
			TNT1 A 15
			RAIL A 0 A_PlaySound("distantexp", 5)
			Stop		
		
	
	}

}

ACTOR NPCMarineRailgunHACKRepeater: NPCMarineRailgunHACK // shares its Death state to make BOOM on walls!
{
	Speed 64
	+THRUACTORS
	MissileType None
	States 
	{
		Spawn:
			TNT1 A 1 // travel for one tic, through everything, 64 map units
			
			// restart the railgun projectile (hopefully *behind* the actor the previous one hit).
			// woe to thicc d00ds like masterminds or tanks
			TNT1 A 0 A_CustomMissile ("NPCMarineRailgunHACK", 0, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH | CMF_TRACKOWNER, pitch)
			TNT1 A 1 A_Stop
			Stop
			
	}
}


//***Che Spalling, Step one: fire a bunch of missiles 
// with collision TOTALLY OFF that go through walls, *floors* and everything.

ACTOR NPCMarineRailgunSpallTracker1 {
	//PROJECTILE
	+NOINTERACTION // ignore *ALL* collision
	-CLIENTSIDEONLY
	Decal None
	Radius 1
	Height 1
	Speed 50
	Scale 1
	States {
		Spawn:
			TNT1 A 1
			
			//***Che Step two: fire, straight backwards, 
			//  	projectiles tasked with finding the other side of the wall.
			//  Must pass through everything but walls.
			
			TNT1 A 0 A_Stop
			TNT1 A 10 A_CustomMissile("NPCMarineRailgunSpallTracker2", 0, 0, 180, CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, -pitch)
			TNT1 A 0
			Stop
	
	}
}


ACTOR NPCMarineRailgunSpallTracker2: FastProjectile
{
	damage (random(0, 0))
	Decal "Scorch"
	DamageType Railgun
	+NODAMAGETHRUST
	Radius 2
	Height 1
	Scale 0.2
	Speed 64
	-SKYEXPLODE
	+THRUGHOST
	+THRUACTORS
	States {
		Spawn:
			TNT1 A 1
			//KYDB G 30 A_Stop
			Stop
		Death:
			TNT1 A 0
			
			//***Che Step three: we found the wall surface! Fire damaging tracers forward.
			// (also causes shrapnel from the floor and ceiling when hit at a shallow angle)			
			
			
			TNT1 A 0 A_Stop
			TNT1 A 0 A_CustomMissile("MarineTracer", 0, 0, random(150,210), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, - pitch + random(-30, 30))
			//SPRK AAAAAA 1 A_FadeOut(0.2)
			TNT1 A 0 A_Jump(140, 2)
			TNT1 A 0 A_CustomMissile ("Spark_BD13", 0, 0, random(150,210), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, - pitch + random(-30, 30))
			TNT1 A 0 A_Jump(140, 2)
			TNT1 A 0 A_CustomMissile ("Spark_BD16", 0, 0, random(150,210), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH | CMF_SAVEPITCH, - pitch + random(-30, 30))
			TNT1 A 10
			//KYDB J 30
		Crash:
		XDeath:
			// this should never happen
			TNT1 A 0
			Stop
	}
}








// ---------- bfg ------------------------------------------------

// muzzle flashes are defined in MARINES_evil.txt


ACTOR MarineBFGBall: Quake2AndDoom2016LikeBFGBall {
	Species "Marines" // because it is otherwise designed not to hurt player
	
	// half the player's
	Damage (random(150, 150)) //Damage (random(300, 300))
	
	States
	{
		Spawn:
			BFGN A 0
			BFGN A 0 A_GiveInventory("BfgBallRaysCount", 20)
			BFGN A 0 A_SpawnItemEx("BFGFOG", 0, 0)
			BFS1 ABABABABAB 1 BRIGHT // first 10 tics, no spam
		FlyOnwards:
			// after that, start spamming lightning
			BFS1 AB 1 BRIGHT A_CustomMissile("MarineBFGBallLazerProjectile", 0.0, 0.0, Random(-180,180), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH, Random(-70,70))
			
			// continued hugging the floor, annoyingly, if fired at very shallow angles
			// (e.g. always when the mastermind is concerned -- his firing origin
			//  is above Doomguy's head
			TNT1 A 0 A_JumpIf((z - floorz) < 20, "Death")
			Loop
		 
		Death:
			BFGN A 0
			BFGN A 0 A_Stop // in case we are "died" manually
			BFGN A 0 Radius_Quake(4,34,0,12,0)
			BFGN A 0 Radius_Quake(1,34,0,32,0)
			BFGN A 0 A_SpawnItemEx ("ExplosionSplashSpawner", 0, 0, -20)
			BFGN A 0 A_SpawnItemEx ("UnderwaterExplosion",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 AA 0 A_SpawnItemEx ("DetectFloorCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			BFGN A 0 A_SpawnItemEx ("DetectCeilCrater",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_PlaySOund("BFGEXPL2", 1)
			BFGN A 0 Bright A_SpawnItem("GreenShockWave",0,0,0)
			//BFE1 A 0 A_SpawnItemEx("BFGDeathParticleSpawner", 0, 0, 0, 0, 0, 0, 0, 128)
			//BFE1 A 0 A_SpawnItemEx("BFGSuperParticleSpawner", 0, 0, 0, 0, 0, 0, 0, 128)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 0, 0, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 50, 0, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", -50, 0, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 0, 50, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 0, -50, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 50, 50, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", 50, -50, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", -50, 50, 0)
			EXPL A 0 A_SpawnItemEx("BFGBigFlare", -50, -50, 0)
			EXPL AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("BFGDeathParticleFast", 0, 0, random (0, 360), 2, random (0, 360))
			EXPL AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("BFGDeathParticleSuperFast", 0, 0, random (0, 360), 2, random (0, 360))
			EXPL AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("BFGDeathParticleFast", 0, 0, random (0, 360), 2, random (0, 360))
			EXPL AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("BFGDeathParticleFast", 0, 0, random (0, 360), 2, random (0, 360))

// >>> ====== SUPER IMPORTANT!!! ====== <<<<<
			//***Che The ONLY fucking way not to off the player with AOE is to use a custom damage type he is made immune to!
			TNT1 A 0 A_SetDamageType("FriendlyExplosion")
			
			BFGN A 0 A_Explode(200,400,0)
			
		DeathAdvanced:
			
			// The flash is a separate entity, purely cosmetic. 
			BFGN A 0 A_SPawnItemEx("SuperBFGExtraGiantChe", 0,0,0, 0,0,0, 0, SXF_NOCHECKPOSITION, 0, 0)
			
			// We go invisibal and spam beams!
			TNT1 A 0 A_CheckFloor("DeathFloor")
			TNT1 A 0 A_JumpIf((z - floorz) < 21, "DeathFloor")
			TNT1 A 0 A_CheckCeiling("DeathCeiling")
		
		DeathSpam:
			// projectiles are launched *backwards*, so they curve back towards the target
			TNT1 A 0
			TNT1 A 1 A_CustomMissile("MarineBFGBallLongReachFastTurning", 0.0, 0.0, Random(135,225), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_SAVEPITCH, - pitch + Random(-45,45)) // angle = 180 +/-45
			TNT1 A 0 A_TakeInventory("BfgBallRaysCount", 1)
			TNT1 A 0 A_JumpIfInventory("BfgBallRaysCount", 1, "DeathSpam")
			TNT1 A 12
			Stop
		DeathFloor:
			TNT1 A 0
			TNT1 A 1 A_CustomMissile("MarineBFGBallLongReachFastTurning", 24.0, 0.0, Random(-180,180), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_SAVEPITCH, Random(5, 70))
			TNT1 A 0 A_TakeInventory("BfgBallRaysCount", 1)
			TNT1 A 0 A_JumpIfInventory("BfgBallRaysCount", 1, "DeathFloor")
			TNT1 A 12
			Stop
		DeathCeiling:
			TNT1 A 0
			TNT1 A 0 A_Stop
			TNT1 A 1 A_CustomMissile("MarineBFGBallLongReachFastTurning", -24.0, 0.0, Random(-180,180), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_SAVEPITCH, Random(-70,-5))
			TNT1 A 0 A_TakeInventory("BfgBallRaysCount", 1)
			TNT1 A 0 A_JumpIfInventory("BfgBallRaysCount", 1, "DeathCeiling")
			TNT1 A 12
			Stop
		DeathPointBlank:
			TNT1 A 0
			Goto DeathAdvanced
	}	
}

Actor MarineBfgBallLazerProjectile: BfgBallLazerProjectile
{
	Species "Marines"
	// half the player's
	Damage (Random(40,40)) //Damage (Random(80,80))
	States	{
		Spawn:
			TNT1 AAAAA 1 A_SeekerMissile(32, 64, SMF_LOOK | SMF_PRECISE, 256, 3)
			TNT1 A 1 A_Jump (256, "Airburst")
			Wait
		Airburst: // no flash
			TNT1 AAA 0 A_CustomMissile("MarineBfgBallAirExpiration", 0.0, 0.0, Random(-90,90), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH, pitch + Random(-45,45))
			TNT1 A 0
			Stop
		Death:
		XDeath:
			TNT1 A 0
			TNT1 A 0 A_SpawnItemEx("BFGBallFlash", 0,0,0, 0,0,0, 0, SXF_NOCHECKPOSITION, 0,0)
			TNT1 A 0 A_CheckFloor("DeathFloor")
			TNT1 A 0 A_CheckCeiling("DeathCeiling")
			TNT1 AAA 0 A_CustomMissile("MarineBfgBallRipper", 0.0, 0.0, Random(-45,45), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_ABSOLUTEPITCH, pitch + Random(-35,35))
			TNT1 A 0
			Stop
		DeathFloor:
			TNT1 AAA 0 A_CustomMissile("MarineBfgBallAirExpiration", 33.0, 0.0, Random(-180,180), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_SAVEPITCH, Random(-70,-15))
			TNT1 A 0
			Stop
		DeathCeiling:	
			TNT1 AAA 0 A_CustomMissile("MarineBfgBallAirExpiration", -33.0, 0.0, Random(-180,180), CMF_AIMDIRECTION | CMF_TRACKOWNER | CMF_SAVEPITCH, Random(15,70))
			TNT1 A 0
			Stop
	}
}

Actor MarineBfgBallLongReachProjectile: MarineBfgBallLazerProjectile
{
	States	{
		Spawn:
			TNT1 AA 1 A_SeekerMissile(16, 32, SMF_LOOK | SMF_PRECISE, 256, 4)
			TNT1 AAAAAAAA 1 A_SeekerMissile(32, 64, SMF_LOOK | SMF_PRECISE, 256, 4)
			TNT1 A 1 A_Jump (256, "Airburst")
			Wait
	}
}

Actor MarineBfgBallLongReachFastTurning: MarineBfgBallLazerProjectile
{
	States	{
		Spawn:
			TNT1 AAAAAAAA 1 A_SeekerMissile(32, 64, SMF_LOOK | SMF_PRECISE, 256, 3)
			TNT1 A 1 A_Jump (256, "Airburst")
			Wait
	}
}



Actor MarineBfgBallAirExpiration: MarineBfgBallLazerProjectile
{
	//-RIPPER
	+RIPPER
	+BLOODLESSIMPACT // without this, framerate dies a horrible stuttering death every time you hit a big crowd
	+NOBOSSRIP // only tickle the bosses
	Missiletype "BFGBallLazerTrailSecondary"
	// half the player's
	Damage (Random(1,1)) //Damage (Random(2,2))
	// ripper rips 8 times per tic (i.e. 8..11 times per imp or baron (if horizontally).
	Radius 3
	Height 3	
	//Speed 25
	Speed 32
	States {
		Spawn:
			TNT1 A 1 BRIGHT
			TNT1 AA 1 BRIGHT A_SeekerMissile(64, 90, SMF_LOOK | SMF_PRECISE, 256, 2)
			TNT1 A 0 A_Jump (256, "Airburst")
			Stop
		Airburst:
			TNT1 A 0 // no flash
			Stop
		Death:
		XDeath:
			TNT1 A 0
			TNT1 A 0 A_SpawnItemEx("BFGBallFlash", 0,0,0, 0,0,0, 0, SXF_NOCHECKPOSITION, 0,0) //"BFGBallFlashNoScream"
			Stop			
	}
}

Actor MarineBfgBallRipper:  MarineBfgBallAirExpiration
{
	+RIPPER
	+BLOODLESSIMPACT // without this, framerate dies a horrible stuttering death every time you hit a big crowd
	+NOBOSSRIP // only tickle the bosses
	Speed 64
	// half the player's
	Damage (Random(2,2)) //Damage (Random(4,4))
	// ripper rips 8 times per tic (i.e. 8 times per 64 -- i.e. 4..5 times per imp or baron (if horizontally). Must splatter any imp.
	
	States {
		Airburst:
			TNT1 A 0
			TNT1 A 0 A_SpawnItemEx("BFGBallFlashNoScream", 0,0,0, 0,0,0, 0, SXF_NOCHECKPOSITION, 0,0) //"BFGBallFlashNoScream"
			Stop
		Death:
		XDeath:
			TNT1 A 0 // no flash
			Stop			
	}
}


ACTOR SlaughterlambTracer: MarineTracer {
	damage (random(0,1))
}

ACTOR NerfedMarineTracer: MarineTracer {
	damage (random(5,5)) // vs normal 12 12
}