//=====================================================================
// NemesisWINGSvX.
//      ""(§)FrÅgÊd(§)""
//               **Monarch**
//
//              555 ---===CrAzYBoNeS===--- 555
//          Boppolis_The_Dog
//
//
// Thank you Al McElrath for SLV2.
//=====================================================================

/** Fuel core pickup. It floats in the air and provides extra fuel.

	Here's how it works. When spawned, it determines if it's in air or
	not. If it is, it will loop the hovering anim and sit there. If not,
	it will spawn a fuel pod on the client side. When a player approaches,
	it will pop up out of the pod and hover. When they walk away it falls
	down. The complication of network play is that when the core is
	picked up, the client doesn't know, except via bHidden. So all our
	behavior is client side. The client core monitors bHidden to find out
	when it's sleeping and when it's picked up, via tick() in the Pickup
	state and timer() in the ClientSleep state, respectively.

	This scheme may need to be revised, either by making pickedUp() or
	start/stopHover() replicated calls from the server, depending on how
	badly it's possible for this scheme to get desynced.
*/
class Fuelcore extends SLAmmo config (NemesisWINGSvX);


var Fuelpod pod;

var() float hoverDist;          // Distance off the ground we hover.
var() float hoverRadius;        // Range we inititate hovering.
var() float hoverRate;          // Speed we rise at.
var() float hoverTimer;         // Timer lapse in Fuelpod.uc.

//var() Sound sndExplode;

var vector hoverLoc;
var bool bHover;
var bool bInAir;
var bool bRising;

var BlastMark bm;
var Fuelglow glow;
var() Class<Fuelglow> glowClass;
var Sound casingSound, riseSound;

var Util u;


/** Initialize. Set bInAir and hoverLoc. On client, too.
*/
simulated function postBeginPlay() {
	local Actor a;
	local vector hl, hn, end;

	u = spawn(Class'Util', self);
	u.setDebugLevel(DL_Verbose);

	// Always level us out. We hover.
	setRotation(rot(0, 0, 0));

	// If we have an owner, we are an inventory spawn copy.
	if (owner == none) {
		// Establish how high off the ground we are.
		end = location;
		end.z -= hoverDist;
		a = trace(hl, hn, end, location, false);


		bInAir = (a == none);

		// Only used if not hanging in the air all the time.
		if (!bInAir) {
			hoverLoc = hl + vect(0, 0, 1) * hoverDist;
			pod = spawn(class'Fuelpod', self,, hl + hn, rotator(hn) + rot(-16384, 0, 0));

			u.debug("postBeginPlay(): hover loc: " $ u.sv(hl));
		}
	}

	super.postBeginPlay();
}


simulated function spawnGlow() {
	if (glow != none)
		glow.destroy();
	glow = spawn(glowClass, self);
}


auto state Pickup {
	simulated function beginState() {
		// Inventory copy.
		if (owner == none) {
			u.debug("Pickup:beginState()");

			if (bInAir) {
				loopAnim('hover');
				spawnGlow();

			} else {
				if (bHover)
					stopHover();
				else
					// This starts the core hidden.
					landed(vect(0, 0, 1));

				// Anyone in the pod radius?
				pod.touchCheck();
			}
		}

		super.beginState();
	}


	/** This is not inventory that can be tossed out and what not, so
		skip the super call. Once we've hit the ground (after stopHover()),
		hide us. We can't use bHidden because that will screw other stuff up.
	*/
	simulated function landed(vector hn) {
		u.debug("Pickup:landed()");

		// Hidden, sorta.
		drawScale = 0.001;

		// Not sure this is necessary.
		setLocation(pod.location);

		//super.landed(hn);
	}


	/** Enabled so we know when to stop the pod's rising. Also used to
		detect pickups on net clients.
	*/
	simulated function tick(float delta) {
		local float d;

		if (bRising) {
			d = hoverLoc.z - location.z;
			if (abs(d) < 5.0) {
				u.debug("Pickup:tick(): v set to 0");
				velocity = vect(0, 0, 0);

				// See destroyed().
				setPhysics(PHYS_None);
				playSound(casingSound, SLOT_None, 0.85);
				bRising = false;
			} else if (abs(d) < (hoverDist * 0.5)) {
				velocity = vect(0, 0, 1) * hoverRate * (d / (hoverDist * 0.5));
			}
		}


		// On the client, register pickups via bHidden.
		if (role < ROLE_Authority) {
			if (bHidden) {
				disable('tick');
				pickedUp();
				gotoState('ClientSleep');
			}
		} else {
			// No need to keep tick running.
			if (!bRising) {
				disable('tick');
			}
		}
	}


	/** Once we're done the rising animation, just hover.
	*/
	simulated function animEnd() {
		if (animSequence == 'rise') {
			loopAnim('hover');
		}
	}


	simulated function startHover() {
		u.debug("Pickup:startHover()");

		bHover = true;

		playAnim('rise');
		playSound(riseSound, SLOT_Misc, 1.0);

		velocity = vect(0, 0, 1) * hoverRate;
		setPhysics(PHYS_Projectile);
		bRising = true;
		enable('tick');

		lightEffect = LE_FastWave;

		// Damnit. un/touch() get called too fast.
		spawnGlow();

		// Restore its scale from landed().
		drawScale = 1.0;
	}


	simulated function stopHover() {
		u.debug("Pickup:stopHover(): v: " $ vsize(velocity));

		bHover = false;

		// Keeps it from popping up in net games where stop and start
		// get called too closely. Need to figure out why and FIX that.
		velocity = vect(0, 0, 0);

		disable('tick');
		playAnim('drop');
		bCollideWorld = true;
		setPhysics(PHYS_Falling);

		lightEffect = LE_None;

		if (glow != none)
			glow.fade();
	}


	/** The pod protects us when we're not hovering. You can't shoot
		the core while it's falling, but I can live with that. FIX?
	*/
	function takeDamage(int dam, Pawn inst, vector hl, vector mom, name dt) {
		u.debug("Pickup:takeDamage(): dam: " $ dam $ " instigator: " $ u.sname(inst));

		if (bHover || bInAir) {
			instigator = inst;
			gotoState('Explode');
		}
	}

begin:
	// Nothing. Why does Inventory call becomePickup() twice?

} // End pickup state.


state ClientSleep {
	ignores touch, takeDamage;

	simulated function timer() {
		if (!bHidden) {
			gotoState('Pickup');
		} else {
			setTimer(0.1, false);
		}
	}


	simulated function beginState() {
		setTimer(0.1, false);
	}
}


simulated function pickedUp() {
	u.debug("pickedUp()");

	if (glow != none)
		glow.destroy();

	// This calls back stopHover().
	if (pod != none) {
		setLocation(pod.location);

		if (pod.bOpen)
			pod.close();
	}
}


/** So the fuel pod compiles.
*/
simulated function startHover() {
	// Not in pickup mode? Ignore.
}


/** So the fuel pod compiles.
*/
simulated function stopHover() {
	// Not in pickup mode? Ignore.
}


state Sleeping {
	ignores touch, takeDamage;

	function beginState() {
		// Stick it back in the pod.
		pickedUp();

		super.beginState();
	}

begin:
	sleep(respawnTime);
	playSound(respawnSound);
	// Looks stupid coming from inside the pod.
	//spawn(class'RespawnEffect', self,, location);
	sleep(0.3);
	gotoState('Pickup');
}


state Explode {
	ignores touch, takeDamage;

	begin:
	u.debug("Explode:begin");
	bHidden = true;

	spawn(class'StrangeExpl',,, location);
	//playSound(effectSound1,, 12.0,, 3000);

	hurtRadius(165, 250, 'exploded', 140000, location);
	sleep(0.05);

	// If we're close to the ground, spawn a blast mark. GAH. FIX.
	/*
	if (level.netmode != NM_DedicatedServer && !bInAir) {
		bm = spawn(class'Botpack.BlastMark',,, location, rot(-16384, 0, 0));
		if (bm == none) {
			u.debug("Explode:begin: failed to spawn blast");
		}
	}
	*/

	setRespawn();
}


/** Need to notify the controller that we've pickup up our first pod
	so the HUD will reflect it.
*/
function inventory spawnCopy(Pawn p) {
	local inventory copy;
	local StrangeShell sl;

	copy = super.spawnCopy(p);
	foreach p.TouchingActors(class'StrangeShell', sl) {
		if (sl.getPilot() == p) {
			sl.fc = Fuelcore(copy);
		}
	}

	return copy;
}


/** Note that if we're PHYS_Projectile, the StrangeWave destroys us
	somehow. It is a mystery to me. So it's possible we will be destroyed,
	which we shouldn't be unless there's no respawns (unlikely). Watch
	for it. May need to get bProjTarget to false while rising. FIX?
*/
simulated function destroyed() {
	u.debug("destroyed(): state: " $ getStateName() $ " phys: " $ physics);

	if (glow != none)
		glow.destroy();

	if (pod != none)
		pod.destroy();

	super.destroyed();
}



// end

defaultproperties
{
     hoverDist=60.000000
     hoverRadius=800.000000
     hoverRate=180.000000
     hoverTimer=1.000000
     casingSound=Sound'SLV2Sounds.Fuelcore.casing'
     riseSound=Sound'Botpack.ASMD.Vapour'
     MaxAmmo=5
     PickupMessage="You picked up a fuel core."
     ItemName="Fuelcore"
     PickupViewMesh=SkeletalMesh'SLV2Models.fcore'
     MaxDesireability=0.320000
     PickupSound=Sound'SLV2Sounds.Fuelcore.Pickup'
     Physics=PHYS_None
     Mesh=SkeletalMesh'SLV2Models.fcore'
     SoundRadius=64
     CollisionRadius=20.000000
     CollisionHeight=6.000000
     bProjTarget=True
     LightBrightness=255
     LightRadius=6
     RotationRate=(Yaw=0)
}
