//=============================================================================
// CreatureCarcass.
//=============================================================================
class CreatureCarcass expands Carcass;

#exec MESH IMPORT MESH=CowBody1 ANIVFILE=MODELS\g_cow2_a.3D DATAFILE=MODELS\g_cow2_d.3D X=0 Y=0 Z=0
#exec MESH ORIGIN MESH=CowBody1 X=0 Y=0 Z=0 YAW=64
#exec MESH SEQUENCE MESH=CowBody1 SEQ=All    STARTFRAME=0   NUMFRAMES=1
#exec MESH SEQUENCE MESH=CowBody1 SEQ=Still  STARTFRAME=0   NUMFRAMES=1
#exec TEXTURE IMPORT NAME=JGCow1  FILE=MODELS\Nc_1.PCX GROUP=Skins 
#exec MESHMAP SCALE MESHMAP=CowBody1 X=0.06 Y=0.06 Z=0.12
#exec MESHMAP SETTEXTURE MESHMAP=CowBody1 NUM=1 TEXTURE=JGCow1

#exec MESH IMPORT MESH=CowBody2 ANIVFILE=MODELS\g_cowb_a.3D DATAFILE=MODELS\g_cowb_d.3D X=0 Y=0 Z=0
#exec MESH ORIGIN MESH=CowBody2 X=0 Y=0 Z=0 YAW=64
#exec MESH SEQUENCE MESH=CowBody2 SEQ=All    STARTFRAME=0   NUMFRAMES=1
#exec MESH SEQUENCE MESH=CowBody2 SEQ=Still  STARTFRAME=0   NUMFRAMES=1
#exec TEXTURE IMPORT NAME=JGCow1  FILE=MODELS\Nc_1.PCX GROUP=Skins 
#exec MESHMAP SCALE MESHMAP=CowBody2 X=0.04 Y=0.04 Z=0.08
#exec MESHMAP SETTEXTURE MESHMAP=CowBody2 NUM=1 TEXTURE=JGCow1

#exec MESH IMPORT MESH=Liver ANIVFILE=MODELS\g_gut1_a.3D DATAFILE=MODELS\g_gut1_d.3D X=0 Y=0 Z=0
#exec MESH ORIGIN MESH=Liver X=0 Y=0 Z=0 YAW=64
#exec MESH SEQUENCE MESH=Liver SEQ=All    STARTFRAME=0   NUMFRAMES=1
#exec MESH SEQUENCE MESH=Liver SEQ=Still  STARTFRAME=0   NUMFRAMES=1
#exec TEXTURE IMPORT NAME=Jparts1  FILE=MODELS\g_parts.PCX GROUP=Skins
#exec MESHMAP SCALE MESHMAP=Liver X=0.02 Y=0.02 Z=0.04
#exec MESHMAP SETTEXTURE MESHMAP=Liver NUM=1 TEXTURE=Jparts1

#exec TEXTURE IMPORT NAME=RedBlood2 FILE=MODELS\Blood2.PCX GROUP=Skins FLAGS=2

#exec AUDIO IMPORT FILE="Sounds\Gibs\biggib1.WAV" NAME="Gib1" GROUP="Gibs"
#exec AUDIO IMPORT FILE="Sounds\Gibs\biggib2.WAV" NAME="Gib4" GROUP="Gibs"
#exec AUDIO IMPORT FILE="Sounds\Gibs\biggib3.WAV" NAME="Gib5" GROUP="Gibs"
#exec AUDIO IMPORT FILE="Sounds\Gibs\gib1.WAV" NAME="Gib2" GROUP="Gibs"
#exec AUDIO IMPORT FILE="Sounds\Gibs\gib3.WAV" NAME="Gib3" GROUP="Gibs"
#exec AUDIO IMPORT FILE="Sounds\Gibs\bthump1.WAV" NAME="Thump" GROUP="Gibs"

var() mesh	bodyparts[8];
var() float Trails[8];
var() float ZOffset[8];
var() texture BloodColor;
var() sound GibOne;
var() sound GibTwo;
var() sound Landed;
var	  bool bThumped;

	function PreBeginPlay()
	{
		if ( !bDecorative )
			Region.Zone.NumCarcasses++;
		CallParent.PreBeginPlay();
	}

	function Destroyed()
	{
		if ( !bDecorative )
			Region.Zone.NumCarcasses--;
		CallParent.Destroyed();
	}
	
	function Initfor(actor Other)
	{
		local Rotation carcRotation;

		if ( bDecorative )
			Region.Zone.NumCarcasses++;
		bDecorative = false;
		bMeshCurvy = Other.bMeshCurvy;		
		Mesh = Other.Mesh;
		Skin = Other.Skin;
		Fatness = Other.Fatness;
		DrawScale = Other.DrawScale;
		SetCollisionSize(Other.CollisionRadius + 4, Other.CollisionHeight);
		if ( !SetLocation(Location) )
			SetCollisionSize(CollisionRadius - 4, CollisionHeight);

		DesiredRotation = other.Rotation;
		DesiredRotation.Roll = 0;
		DesiredRotation.Pitch = 0;
		AnimFrame = Other.AnimFrame;
		AnimSequence = Other.AnimSequence;  
		AnimRate = Other.AnimRate;      
		TweenRate = Other.TweenRate; 
		AnimLast = Other.AnimLast;
		AnimMinRate = Other.AnimMinRate; 
		bAnimFinished = Other.bAnimFinished;
		bAnimLoop = Other.bAnimLoop;
		bAnimNotify = Other.bAnimNotify;
		Velocity = other.Velocity;
		Mass = Other.Mass;
	}

	function Damage( int Damage, Pawn InstigatedBy, Vector Hitlocation, 
							Vector Momentum, name DamageType)
	{
		Spawn(class'BloodSpurt',,,HitLocation);
		CallParent.Damage(Damage, instigatedBy, HitLocation, Momentum, DamageType);
	}

	function CreateReplacement()
	{
		local CreatureChunks carc;
		
		if (bHidden)
			return;
		if ( bodyparts[0] != None )
			carc = Spawn(class 'CreatureChunks',,, Location + ZOffset[0] * CollisionHeight * vect(0,0,1)); 
		if (carc != None)
		{
			carc.TrailSize = Trails[0];
			carc.Mesh = bodyparts[0];
			carc.Initfor(self);
			carc.Velocity = velocity; //no rand
			carc.Bugs = Bugs;
			if ( Bugs != None )
				Bugs.SetBase(carc);
			Bugs = None;
		}
		else if ( Bugs != None )
			Bugs.Destroy();
	}

	function ChunkUp(int Damage)
	{
		CreateReplacement();
		ClientExtraChunks();
		SetPhysics(PHYS_None);
		bHidden = true;
		SetCollision(false,false,false);
		bProjTarget = false;
		GotoState('Gibbing');
	}

	function ClientExtraChunks()
	{
		local CreatureChunks carc;
		local bloodspurt Blood;
		local int n;
		
		n = 1;
		while ( (n<8) && (bodyparts[n] != none) )
		{
			carc = Spawn(class 'CreatureChunks',,, Location + ZOffset[n] * CollisionHeight * vect(0,0,1));
			if (carc != None)
			{
				carc.TrailSize = Trails[n];
				carc.Mesh = bodyparts[n];
				carc.Initfor(self);
			}
			n++;
		}
		Blood = Spawn(class 'Bloodspurt');
	}

	function Landed(vector HitNormal)
	{
		local rotation finalRot;
		local float OldHeight;

		finalRot = Rotation;
		finalRot.Roll = 0;
		finalRot.Pitch = 0;
		setRotation(finalRot);
		if ( !bDecorative )
			Spawn(class 'Bloodspurt');
		SetPhysics(PHYS_None);
		SetCollision(bCollideActors, false, false);
		if ( !IsAnimating() )
			LieStill();
	}

	function AnimEnd()
	{
		if ( Physics == PHYS_None )
			LieStill();
	}

	function LieStill()
	{
		if ( !bThumped && !bDecorative )
			LandThump();
		if ( !bReducedHeight )
			ReduceCylinder();
	}

	function ThrowOthers()
	{
		local float dist, shake;
		local pawn Thrown;
		local PlayerPawn aPlayer;
		local vector Momentum;

		Thrown = Level.PawnList;
		While ( Thrown != None )
		{
			aPlayer = PlayerPawn(Thrown);
			if ( aPlayer != None )
			{	
				dist = Size(Location - aPlayer.Location);
				shake = FMax(500, 1500 - dist);
				aPlayer.ShakeView( FMax(0, 0.35 - dist/20000),shake, 0.015 * shake );
				if ( (aPlayer.Physics == PHYS_Walking) && (dist < 1500) )
				{
					Momentum = -0.5 * aPlayer.Velocity + 100 * VRand();
					Momentum.Z =  7000000.0/((0.4 * dist + 350) * aPlayer.Mass);
					aPlayer.ClientAddVelocity(Momentum);
				}
			}
		Thrown = Thrown.nextPawn;
		}
	}

	function LandThump()
	{
		local float impact;

		if ( Physics == PHYS_None)
		{
			bThumped = true;
			if ( Role == ROLE_Authority )
			{
				impact = 0.75 + Velocity.Z * 0.004;
				impact = Mass * impact * impact * 0.01;
				PlaySound(Landed,, impact);
				if ( Mass >= 500 )
					ThrowOthers();
			}
		}
	}

	function ReduceCylinder()
	{
		local float OldHeight;

		bReducedHeight = true;
		SetCollision(bCollideActors,False,False);
		OldHeight = CollisionHeight;
		SetCollisionSize(CollisionRadius + 4, CollisionHeight * 0.3);
		PrePivot = vect(0,0,1) * (OldHeight - CollisionHeight); 
		if ( !SetLocation(Location - PrePivot) )
		{
			SetCollisionSize(CollisionRadius - 4, CollisionHeight);
			if ( !SetLocation(Location - PrePivot) )
			{
				SetCollisionSize(CollisionRadius, OldHeight);
				SetCollision(false, false, false);
				PrePivot = vect(0,0,0);
			}
		}
		PrePivot = PrePivot + vect(0,0,2);
		Mass = Mass * 0.8;
	}

	function HitWall(vector HitNormal, actor Wall)
	{
		Spawn(class 'Bloodspurt');
		Velocity = 0.7 * (Velocity - 2 * HitNormal * (Velocity Dot HitNormal));
		Velocity.Z *= 0.9;
		if ( Abs(Velocity.Z) < 120 )
		{
			bBounce = false;
			Disable('HitWall');
		}
	}

auto state Dying
{
	ignores Damage;

Begin:
	if ( bDecorative && !bReducedHeight )
	{
		ReduceCylinder();
		SetPhysics(PHYS_None);
	}
	Sleep(0.2);
	GotoState('Dead');
}

state Dead 
{
	function AddFliesAndRats()
	{
		if ( (flies > 0) && (Bugs == None) && (Level.NetMode == NM_Standalone) )
		{
			Bugs = Spawn(class 'DeadBodySwarm');
			if (Bugs != None)
			{
				Bugs.SetBase(Self);
				DeadBodySwarm(Bugs).swarmsize = flies * (FRand() + 0.5);
				DeadBodySwarm(Bugs).swarmradius = collisionradius;
			}
		}
	}

	function CheckZoneCarcasses()
	{
		local CreatureCarcass C, Best;

		if ( !bDecorative && (Region.Zone.NumCarcasses > Region.Zone.MaxCarcasses) )
		{
			Best = self;
			ForEach AllActors(class'CreatureCarcass', C)
				if ( (C != Self) && !C.bDecorative && (C.Region.Zone == Region.Zone) && !C.IsAnimating() )
				{
					if ( Best == self )
						Best = C;
					else if ( !C.PlayerCanSeeMe() )
					{
						Best = C;
						break;
					}
				}
			Best.Destroy();
		}
	}

	function BeginState()
	{
		if ( bDecorative )
			lifespan = 0.0;
		else
			SetTimer(30.0 - 2 * Region.Zone.NumCarcasses, false); 
	}

}

state Gibbing
{
	ignores Landed, HitWall, AnimEnd, Damage;

	function GibSound()
	{
		local float decision;

		decision = FRand();
		if (decision < 0.2)
			PlaySound(GibOne, SLOT_Interact, 0.05 * Mass);
		else if ( decision < 0.4 )
			PlaySound(GibTwo, SLOT_Interact, 0.05 * Mass);
		else if ( decision < 0.6 )
			PlaySound(sound'Gib3', SLOT_Interact, 0.05 * Mass);
		else if ( decision < 0.8 )
			PlaySound(sound'Gib4', SLOT_Interact, 0.05 * Mass);
		else 
			PlaySound(sound'Gib5', SLOT_Interact, 0.05 * Mass);
	}

Begin:
	Sleep(0.2);
	GibSound();
	if ( !bPlayerCarcass )
		Destroy();
}

