// Author: cvet
// Client and mapper script
#include "_defines.fos"
#include "_animation.fos"


string@ critter_animation(int animType, uint crType, uint anim1, uint anim2, uint& pass, uint& flags, int& ox, int& oy)
{
	if(animType == ANIM_TYPE_TACTICS) return ProcessTactics(crType, anim1, anim2, pass, flags, ox, oy);
	if(animType == ANIM_TYPE_ARCANUM) return ProcessArcanum(crType, anim1, anim2, pass, flags, ox, oy);
	return null;
}

string@ ProcessTactics(uint crType, uint anim1, uint anim2, uint& pass, uint& flags, int& ox, int& oy)
{
	// Todo: Implement overlays

	string@ crTypeName = GetCritterTypeName(crType);
	string animName;

	// Some specific types
	bool isTurret = false;
	bool isVehicle = false;
	bool isMutantFreak = false;
	bool isBrain = false;

	switch(crTypeName[0])
	{
	case 'C': // Characters
		animName = "sprites/characters/";
		isMutantFreak = (crTypeName == "CMutantFreak");
		isBrain = (crTypeName == "CBrain");
		break;
	case 'A': // Animals
		animName = "sprites/critters/";
		break;
	case 'R': // Robots
		animName = "sprites/robots/";
		break;
	case 'T': // Turrets
		animName = "sprites/robots/RobotTurrets/";
		isTurret = true;
		break;
	case 'V': // Vehicles
		if(crTypeName == "VTankTurret") crTypeName = "VTank Turret";
		animName = "sprites/vehicles/";
		isVehicle = true;
		break;
	default: return null;
	}
	animName += substring(crTypeName, 1, crTypeName.length() - 1);
	animName += "$";

	// Color offsets
	// 0 - other
	// 1 - skin
	// 2 - hair
	// 3 - armor
	// Format: [index,R,G,B]
	const string[] colorOffsets =
	{
	//   R   G   B      Index
		"0,0,0"      , // 0  None
		"30,-30,-30" , // 1  Red
		"-30,30,-30" , // 2  Green
		"-30,-30,30" , // 3  Blue
		"-30,30,30"  , // 4  Turquoise
		"30,-30,30"  , // 5  Purple
		"30,30,-30"  , // 6  Yellow
		"30,30,30"   , // 7  Light
		"60,60,60"   , // 8  White
		"-30,-30,-30", // 9  Dark
		"-60,-60,-60", // 10 Black
		"0,0,0"      , // 11 ...
		"0,0,0"      , // 12 ...
		"0,0,0"      , // 13 ...
		"0,0,0"      , // 14 ...
		"0,0,0"        // 15 ...
	};
	uint skinColor  = (anim1 >> 20) & 0xF;
	uint hairColor  = (anim1 >> 24) & 0xF;
	uint armorColor = (anim1 >> 28) & 0xF;
	if(skinColor  != 0) animName += "[1," + colorOffsets[skinColor]  + "]";
	if(hairColor  != 0) animName += "[2," + colorOffsets[hairColor]  + "]";
	if(armorColor != 0) animName += "[3," + colorOffsets[armorColor] + "]";

	// Check flags
	bool isDead   = (anim2 >= ANIM2_DEAD_BEGIN && anim2 <= ANIM2_DEAD_END);
	bool isCrouch = (!isDead && (anim1 & ANIM1_CROUCH) != 0);
	bool isProne  = (!isDead && !isCrouch && (anim1 & ANIM1_PRONE) != 0);

	// Keep only weapon
	anim1 &= ANIM1_WEAPON_MASK;

	// Turret
	if(isTurret)
	{
		// Todo:
		animName += "StandArmed.spr";
		return animName;
	}

	// Vehicle
	if(isVehicle)
	{
		// Todo:
		animName += "Idle.spr";
		return animName;
	}

	// Mutant Freak
	if(isMutantFreak)
	{
		if(isDead) animName += "Death.spr";
		else if(anim2 >= ANIM2_PUNCH_RIGHT && anim2 <= ANIM2_KICK_COMBO) animName += "Attack.spr";
		else animName += "Breathe.spr";
		return animName;
	}

	// Generic critter
	if(!isDead)
	{
		// Some critters not have Breathe, use Default instead
		if(pass == 10)
		{
			animName += "Default.spr";
			return animName;
		}

		// Position
		if(isCrouch)
			animName += "Crouch";
		else if(isProne)
			animName += "Prone";
		else
			animName += "Stand";

		switch(anim2)
		{
		// Todo: Climb, Climbdown, Climbup
		case ANIM2_WALK:             animName += "Walk";          break;
		case ANIM2_LIMP:             animName += "Walk";          break;
		case ANIM2_SNEAK_WALK:       animName += "Walk";          break;
		case ANIM2_RUN:              animName += "Run";           break;
		case ANIM2_PANIC_RUN:        animName += "Run";           break;
		case ANIM2_SNEAK_RUN:        animName += "Run";           break;
		case ANIM2_DODGE_FRONT:      animName += "DodgeOne";      break;
		case ANIM2_DODGE_BACK:       animName += "DodgeTwo";      break;
		case ANIM2_DAMAGE_FRONT:     animName += "Recoil";        break;
		case ANIM2_DAMAGE_BACK:      animName += "Recoil";        break;
		case ANIM2_KNOCK_FRONT:      animName += "Fallback";      break;
		case ANIM2_KNOCK_BACK:       animName += "Fallforward";   break;
		case ANIM2_STANDUP_FRONT:    animName += "Getupback";     break;
		case ANIM2_STANDUP_BACK:     animName += "Getupforward";  break;
		case ANIM2_IDLE_PRONE_FRONT: animName += "Fallenback";    break;
		case ANIM2_IDLE_PRONE_BACK:  animName += "Fallenforward"; break;
		case ANIM2_PICKUP:           animName += "Pickup";        break;
		case ANIM2_LOOT:             animName += "Pickup";        break;
		case ANIM2_PUSH:             animName += "Attack";        break;
		case ANIM2_PUNCH_RIGHT:      animName += "Attack";        break;
		case ANIM2_KICK_HI:          animName += "Attack";        break;
		case ANIM2_THRUST_1H:        animName += "Attack";        break;
		case ANIM2_SWING_1H:         animName += "Attack";        break;
		case ANIM2_SINGLE:           animName += "Attack";        break;
		case ANIM2_BURST:            animName += "Attack";        break;
		case ANIM2_SWEEP:            animName += "Attack";        break;
		case ANIM2_FLAME:            animName += "Attack";        break;
		case ANIM2_THROW:            animName += "Attack";        break;
		case ANIM2_FIDGET:           animName += "Fidget";        break;
		case ANIM2_STAND:            animName += "Stand";         break;
		case ANIM2_CROUCH:           animName += "Crouch";        break;
		case ANIM2_PRONE:            animName += "Prone";         break;

		case ANIM2_IDLE:
			animName += "Breathe";
			if(anim1 == ANIM1_UNARMED) pass = 10; // Allow another call, see upper
			break;

		case ANIM2_SHOW_WEAPON:
		case ANIM2_HIDE_WEAPON:
		case ANIM2_USE:
		case ANIM2_SWITCH_ITEMS:
		case ANIM2_STEAL:
			if(pass == 0)
			{
				animName += "Magic";
				pass++; // Allow another call, see below
			}
			else
			{
				animName += "Magichigh";
			}
			break;

		default: return null;
		}

		switch(anim1)
		{
		case ANIM1_UNARMED:         animName += "";        break;
		case ANIM1_KNIFE:           animName += "Knife";   break;
		case ANIM1_CLUB:            animName += "Club";    break;
		case ANIM1_HAMMER:          animName += "Club";    break; // N/A
		case ANIM1_SPEAR:           animName += "Spear";   break;
		case ANIM1_PISTOL:          animName += "Pistol";  break;
		case ANIM1_SMG:             animName += "SMG";     break;
		case ANIM1_SHOOTGUN:        animName += "Rifle";   break; // N/A
		case ANIM1_HEAVY_RIFLE:     animName += "Heavy";   break;
		case ANIM1_MINIGUN:         animName += "Minigun"; break;
		case ANIM1_ROCKET_LAUNCHER: animName += "Rocket";  break;
		case ANIM1_FLAMER:          animName += "Heavy";   break; // N/A
		case ANIM1_RIFLE:           animName += "Rifle";   break;
		case ANIM1_SWORD:           animName += "Knife";   break; // N/A
		case ANIM1_LONG_SWORD:      animName += "Knife";   break; // N/A
		case ANIM1_AXE:             animName += "Club";    break; // N/A
		case ANIM1_BOW:             animName += "Spear";   break; // N/A
		default: break;
		}

		// Attack
		switch(anim2)
		{
		case ANIM2_PUNCH_RIGHT:
		case ANIM2_PUNCH_LEFT:
		case ANIM2_PUNCH_COMBO:
			if(isBrain)
				animName += "HeadButt";
			else
				animName += "UnarmedOne";
			break;
		case ANIM2_KICK_HI:
		case ANIM2_KICK_LO:
		case ANIM2_KICK_COMBO:
			if(isBrain)
				animName += "Whip";
			else
				animName += "UnarmedTwo";
			break;

		case ANIM2_SINGLE:      animName += "Single";     break; // RocketSingleOverlay
		case ANIM2_BURST:       animName += "Burst";      break;
		case ANIM2_SWEEP:       animName += "Burst";      break;
		case ANIM2_FLAME:       animName += "Single";     break;
		case ANIM2_THROW:       animName += "Throw";      break;

		case ANIM2_THRUST_1H:
		case ANIM2_THRUST_2H:
		case ANIM2_SWING_1H:
		case ANIM2_SWING_2H:
			if(anim1 == ANIM1_KNIFE || anim1 == ANIM1_SWORD || anim1 == ANIM1_LONG_SWORD)
				animName += "Slash";
			else if(anim1 == ANIM1_CLUB || anim1 == ANIM1_HAMMER || anim1 == ANIM1_AXE)
				animName += "Swing";
			else // Spear
				animName += "Thrust";
			break;

		default: break;
		}
	}
	else
	{
		animName += "";
		switch(anim2)
		{
		case ANIM2_DEAD_PRONE_FRONT:   animName += "StandFallenback";    break;
		case ANIM2_DEAD_PRONE_BACK:    animName += "StandFallenforward"; break;
		case ANIM2_DEAD_FRONT:         animName += "Death";              break;
		case ANIM2_DEAD_BACK:          animName += "Death";              break;
		case ANIM2_DEAD_BLOODY_SINGLE: animName += "DeathBighole";       break;
		case ANIM2_DEAD_BLOODY_BURST:  animName += "DeathFire";          break;
		case ANIM2_DEAD_BURST:         animName += "DeathRiddled";       break;
		case ANIM2_DEAD_PULSE:         animName += "DeathRiddled";       break;
		case ANIM2_DEAD_PULSE_DUST:    animName += "DeathElectrify";     break; // ElectrifyOverlay
		case ANIM2_DEAD_LASER:         animName += "DeathCutinhalf";     break;
		case ANIM2_DEAD_FUSED:         animName += "DeathFire";          break; // FireOverlay
		case ANIM2_DEAD_EXPLODE:       animName += "DeathMelt";          break; // MeltOverlay
		case ANIM2_DEAD_BURN:          animName += "DeathExplode";       break;
		case ANIM2_DEAD_BURN_RUN:      animName += "DeathElectrify";     break;
		default: return null;
		}
	}

	animName += ".spr";
	return animName;
}

string@ ProcessArcanum(uint crType, uint anim1, uint anim2, uint& pass, uint& flags, int& ox, int& oy)
{
	string@ crTypeName = GetCritterTypeName(crType);
	string animName;

	// Critter
	if(crTypeName[0] == 'C')
	{
		animName += "art/critter/";
		animName += substring(crTypeName, 1, 3) + "/" + substring(crTypeName, 1, 5);
	}
	// Monster
	else if(crTypeName[0] == 'M')
	{
		animName += "art/monster/";
		animName += substring(crTypeName, 1, 3) + "/" + substring(crTypeName, 1, 5);
	}
	// Unique NPC
	else // 'U'
	{
		animName += "art/unique_npc/";
		animName += substring(crTypeName, 1, 5) + "/" + substring(crTypeName, 1, 5);
	}

	// Check palette index
	uint palette = anim1 >> (ANIM1_FLAGS_BITS + 8);
	palette &= 3; // Clamp to 0..3

	// Check Shield flag
	if(anim1 & ANIM1_SHIELD != 0)
		animName += "s";
	else
		animName += "x";

	// Keep only weapon
	anim1 &= ANIM1_WEAPON_MASK;

	// Weapon
	switch(anim1)
	{
	case ANIM1_UNARMED:
		// Some critters not have AA, use BA instead
		if(pass == 0)
		{
			animName += "a";
			pass++; // Allow another call
		}
		else
		{
			animName += "b";
		}
		break;

	case ANIM1_KNIFE:           animName += "c"; break;
	case ANIM1_CLUB:            animName += "f"; break; // N/A
	case ANIM1_HAMMER:          animName += "f"; break;
	case ANIM1_SPEAR:           animName += "n"; break;
	case ANIM1_PISTOL:          animName += "g"; break;
	case ANIM1_SMG:             animName += "g"; break; // N/A
	case ANIM1_SHOOTGUN:        animName += "k"; break; // N/A
	case ANIM1_HEAVY_RIFLE:     animName += "k"; break; // N/A
	case ANIM1_MINIGUN:         animName += "k"; break; // N/A
	case ANIM1_ROCKET_LAUNCHER: animName += "k"; break; // N/A
	case ANIM1_FLAMER:          animName += "k"; break; // N/A
	case ANIM1_RIFLE:           animName += "k"; break;
	case ANIM1_SWORD:           animName += "d"; break;
	case ANIM1_LONG_SWORD:      animName += "h"; break;
	case ANIM1_AXE:             animName += "e"; break;
	case ANIM1_BOW:             animName += "i"; break;
	default: break;
	}

	// Action
	bool changeAtoB = false;
	switch(anim2)
	{
	case ANIM2_IDLE:
		animName += "a";
		if(crType < CRTYPE_ARCANUM_GEN_CR_BEGIN || crType > CRTYPE_ARCANUM_GEN_CR_END) changeAtoB = true;
		break;
	case ANIM2_IDLE_COMBAT:      animName += "a"; changeAtoB = true; break;
	case ANIM2_IDLE_STUNNED:     animName += "x"; changeAtoB = true; break;
	case ANIM2_WALK:             animName += "b"; break;
	case ANIM2_RUN:              animName += "g"; break;
	case ANIM2_SNEAK_WALK:       animName += "d"; break;
	case ANIM2_SNEAK_RUN:        animName += "d"; break;
	case ANIM2_KNOCK_FRONT:      animName += "h"; break;
	case ANIM2_KNOCK_BACK:       animName += "h"; break;
	case ANIM2_STANDUP_FRONT:    animName += "i"; break;
	case ANIM2_STANDUP_BACK:     animName += "i"; break;
	case ANIM2_IDLE_PRONE_FRONT: animName += "i"; flags |= ANIM_FLAG_FIRST_FRAME; break;
	case ANIM2_IDLE_PRONE_BACK:  animName += "i"; flags |= ANIM_FLAG_FIRST_FRAME; break;
	case ANIM2_PICKUP:           animName += "k"; break;
	case ANIM2_LOOT:             animName += "k"; break;
	case ANIM2_SHOW_WEAPON:      animName += "m"; break;
	case ANIM2_HIDE_WEAPON:      animName += "m"; break;
	case ANIM2_USE:              animName += "m"; break;
	case ANIM2_RELOAD:           animName += "m"; break;
	case ANIM2_REPAIR:           animName += "m"; break;
	case ANIM2_SWITCH_ITEMS:     animName += "m"; break;
	case ANIM2_STEAL:            animName += "m"; break;
	case ANIM2_PUSH:             animName += "u"; changeAtoB = true; break;
	case ANIM2_PUNCH_RIGHT:      animName += "u"; changeAtoB = true; break;
	case ANIM2_KICK_HI:          animName += "v"; changeAtoB = true; break;
	case ANIM2_THRUST_1H:        animName += "u"; changeAtoB = true; break;
	case ANIM2_SWING_1H:         animName += "v"; changeAtoB = true; break;
	case ANIM2_SINGLE:           animName += "u"; changeAtoB = true; break;
	case ANIM2_BURST:            animName += "u"; changeAtoB = true; break;
	case ANIM2_SWEEP:            animName += "u"; changeAtoB = true; break;
	case ANIM2_FLAME:            animName += "u"; changeAtoB = true; break;
	case ANIM2_THROW:            animName += "o"; break;
	case ANIM2_FIDGET:           animName += "a"; break;

	case ANIM2_DEAD_PRONE_FRONT:
	case ANIM2_DEAD_PRONE_BACK:    animName += "h"; flags |= ANIM_FLAG_LAST_FRAME; break;
	case ANIM2_DEAD_FRONT:
	case ANIM2_DEAD_BACK:          animName += "h"; break;
	case ANIM2_DEAD_BLOODY_SINGLE:
	case ANIM2_DEAD_BLOODY_BURST:  animName += "r"; break;
	case ANIM2_DEAD_BURST:
	case ANIM2_DEAD_PULSE:
	case ANIM2_DEAD_PULSE_DUST:
	case ANIM2_DEAD_LASER:         animName += "s"; break;
	case ANIM2_DEAD_FUSED:
	case ANIM2_DEAD_EXPLODE:
	case ANIM2_DEAD_BURN:
	case ANIM2_DEAD_BURN_RUN:      animName += "t"; break;
	default: return null;
	}

	if(anim1 != ANIM1_UNARMED && anim2 == ANIM2_IDLE) flags |= ANIM_FLAG_FIRST_FRAME;
	if(anim1 == ANIM1_UNARMED && changeAtoB) animName[animName.length() - 2] = 'b';

//a - standing
//b - walking
//c - kick low? (only one file found, ghmv2xac.ART)
//d - walking, stealth
///e - disassemble? (only one file found, ls1uwxae.ART)
///f - conceal fidget
//g - running
//h - fall down
//i - get up
///j - crouch
///k - pickpocket, crouch
//m - pickpocket
///n - vault
//o - throw
//r - decapitation (get killed, search for head)
//s - blown out (get killed, left arm massacred)
//t - severed leg (get killed, left leg massacred)
//u - attack (hit somebody, primary, punch, hammer etc.)
//v - attack low (hit somebody, secondary, kick to lying)
//x - stunned
///y - explode (get killed, exploded!)
///z - crafting (only one file found, hmmbsxaz.ART)

	// Append palette
	if(palette != 0) animName += "$" + palette;

	animName += ".art";
	return animName;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Call on animation substitute seeking.
bool critter_animation_substitute(int animType, uint crTypeBase, uint anim1Base, uint anim2Base, uint& crType, uint& anim1, uint& anim2)
{
	// Unset shield (Arcanum animations)
	if((anim1 & ANIM1_SHIELD) != 0)
	{
		anim1 ^= ANIM1_SHIELD;
		return true;
	}

	// Check crType alias
	if(crTypeBase != 0) // Zero for 3d animations
	{
		uint crTypeAlias = GetCritterAlias(crTypeBase);
		if(crType == crTypeBase && crType != crTypeAlias)
		{
			switch(anim2)
			{
			case ANIM2_DEAD_PULSE:
			case ANIM2_DEAD_PULSE_DUST:
			case ANIM2_DEAD_BURN:
			case ANIM2_DEAD_BURN_RUN:
				crType = crTypeAlias;
				return true;
			default: break;
			}
		}
	}
	crType = crTypeBase;

	// Check Unarmed specific substitute
	if((anim1 & ANIM1_WEAPON_MASK) == ANIM1_UNARMED)
	{
		bool swapped = true;
		switch(anim2)
		{
		case ANIM2_LIMP:         anim2 = ANIM2_WALK;       break;
		case ANIM2_RUN:          anim2 = ANIM2_WALK;       break;
		case ANIM2_PANIC_RUN:    anim2 = ANIM2_RUN;        break;
		case ANIM2_SNEAK_WALK:   anim2 = ANIM2_WALK;       break;
		case ANIM2_SNEAK_RUN:    anim2 = ANIM2_SNEAK_WALK; break;
		case ANIM2_PICKUP:       anim2 = ANIM2_USE;        break;
		case ANIM2_SWITCH_ITEMS: anim2 = ANIM2_USE;        break;
		default: swapped = false; break;
		}
		if(swapped) return true;
	}

	// Check anim2 substitute
	bool swapped = true;
	switch(anim2)
	{
	case ANIM2_IDLE_STUNNED:     anim2 = ANIM2_IDLE;              break;
	case ANIM2_IDLE_COMBAT:      anim2 = ANIM2_IDLE;              break;
	case ANIM2_CLIMBING:         anim2 = ANIM2_USE;               break;
	case ANIM2_PUNCH_LEFT:       anim2 = ANIM2_PUNCH_RIGHT;       break;
	case ANIM2_PUNCH_COMBO:      anim2 = ANIM2_PUNCH_LEFT;        break;
	case ANIM2_KICK_HI:          anim2 = ANIM2_PUNCH_RIGHT;       break;
	case ANIM2_KICK_LO:          anim2 = ANIM2_KICK_HI;           break;
	case ANIM2_KICK_COMBO:       anim2 = ANIM2_KICK_HI;           break;
	case ANIM2_SWING_1H:         anim2 = ANIM2_THRUST_1H;         break;
	case ANIM2_THRUST_2H:        anim2 = ANIM2_THRUST_1H;         break;
	case ANIM2_SWING_2H:         anim2 = ANIM2_SWING_1H;          break;
	case ANIM2_SWEEP:            anim2 = ANIM2_BURST;             break;
	case ANIM2_BURST:            anim2 = ANIM2_SINGLE;            break;
	case ANIM2_BUTT:             anim2 = ANIM2_PUNCH_RIGHT;       break;
	case ANIM2_FLAME:            anim2 = ANIM2_SINGLE;            break;
	case ANIM2_NO_RECOIL:        anim2 = ANIM2_USE;               break;
	case ANIM2_THROW:            anim2 = ANIM2_PUNCH_RIGHT;       break;
	case ANIM2_RELOAD:           anim2 = ANIM2_USE;               break;
	case ANIM2_REPAIR:           anim2 = ANIM2_RELOAD;            break;
	case ANIM2_DODGE_BACK:       anim2 = ANIM2_DODGE_FRONT;       break;
	case ANIM2_DAMAGE_BACK:      anim2 = ANIM2_DAMAGE_FRONT;      break;
	case ANIM2_DAMAGE_MUL_BACK:  anim2 = ANIM2_DAMAGE_MUL_FRONT;  break;
	case ANIM2_WALK_DAMAGE_BACK: anim2 = ANIM2_WALK_DAMAGE_FRONT; break;
	case ANIM2_LIMP_DAMAGE_BACK: anim2 = ANIM2_LIMP_DAMAGE_FRONT; break;
	case ANIM2_RUN_DAMAGE_BACK:  anim2 = ANIM2_RUN_DAMAGE_FRONT;  break;
	case ANIM2_LOOT:             anim2 = ANIM2_PICKUP;            break;
	case ANIM2_STEAL:            anim2 = ANIM2_USE;               break;
	case ANIM2_PUSH:             anim2 = ANIM2_PUNCH_RIGHT;       break;
	case ANIM2_SHOW_WEAPON:      anim2 = ANIM2_USE;               break;
	case ANIM2_HIDE_WEAPON:      anim2 = ANIM2_USE;               break;

	case ANIM2_KNOCK_BACK:            anim2 = ANIM2_KNOCK_FRONT;            break;
	case ANIM2_LAYDOWN_BACK:          anim2 = ANIM2_LAYDOWN_FRONT;          break;
	case ANIM2_IDLE_PRONE_BACK:       anim2 = ANIM2_IDLE_PRONE_FRONT;       break;
	case ANIM2_STANDUP_BACK:          anim2 = ANIM2_STANDUP_FRONT;          break;
	case ANIM2_DEAD_PRONE_BACK:       anim2 = ANIM2_DEAD_PRONE_FRONT;       break;
	case ANIM2_DAMAGE_PRONE_BACK:     anim2 = ANIM2_DAMAGE_PRONE_FRONT;     break;
	case ANIM2_DAMAGE_MUL_PRONE_BACK: anim2 = ANIM2_DAMAGE_MUL_PRONE_FRONT; break;
	case ANIM2_TWITCH_PRONE_BACK:     anim2 = ANIM2_TWITCH_PRONE_FRONT;     break;

	case ANIM2_DEAD_FRONT:         anim2 = ANIM2_KNOCK_FRONT; break;
	case ANIM2_DEAD_BACK:          anim2 = ANIM2_KNOCK_BACK;  break;
	case ANIM2_DEAD_BLOODY_SINGLE:
	case ANIM2_DEAD_BLOODY_BURST:
	case ANIM2_DEAD_BURST:
	case ANIM2_DEAD_PULSE:
	case ANIM2_DEAD_PULSE_DUST:
	case ANIM2_DEAD_LASER:
	case ANIM2_DEAD_FUSED:
	case ANIM2_DEAD_EXPLODE:
	case ANIM2_DEAD_BURN:
	case ANIM2_DEAD_BURN_RUN:      anim2 = ANIM2_DEAD_FRONT;       break;

	default: swapped = false; break;
	}
	if(swapped) return true;

	// Restore anim2
	anim2 = anim2Base;

	// Find anim1 substitute
	uint flags = anim1 & ANIM1_FLAGS_MASK; // Store flags
	anim1 &= ANIM1_WEAPON_MASK; // Keep only weapon
	switch(anim1)
	{
	case ANIM1_KNIFE:           anim1 = ANIM1_UNARMED;         break;
	case ANIM1_CLUB:            anim1 = ANIM1_KNIFE;           break;
	case ANIM1_HAMMER:          anim1 = ANIM1_CLUB;            break;
	case ANIM1_SPEAR:           anim1 = ANIM1_KNIFE;           break;
	case ANIM1_PISTOL:          anim1 = ANIM1_UNARMED;         break;
	case ANIM1_SMG:             anim1 = ANIM1_PISTOL;          break;
	case ANIM1_SHOOTGUN:        anim1 = ANIM1_SMG;             break;
	case ANIM1_RIFLE:           anim1 = ANIM1_SHOOTGUN;        break;
	case ANIM1_MINIGUN:         anim1 = ANIM1_RIFLE;           break;
	case ANIM1_ROCKET_LAUNCHER: anim1 = ANIM1_MINIGUN;         break;
	case ANIM1_FLAMER:          anim1 = ANIM1_ROCKET_LAUNCHER; break;
	case ANIM1_HEAVY_RIFLE:     anim1 = ANIM1_RIFLE;           break;
	case ANIM1_SWORD:           anim1 = ANIM1_KNIFE;           break;
	case ANIM1_LONG_SWORD:      anim1 = ANIM1_KNIFE;           break;
	case ANIM1_AXE:             anim1 = ANIM1_HAMMER;          break;
	case ANIM1_BOW:             anim1 = ANIM1_KNIFE;           break;
	default: return false;
	}
	anim1 |= flags; // Merge weapon and flags

	return true;
}

// Fallout animations
#define ANIM1_FALLOUT_UNARMED            (1)
#define ANIM1_FALLOUT_DEAD               (2)
#define ANIM1_FALLOUT_KNOCKOUT           (3)
#define ANIM1_FALLOUT_KNIFE              (4)
#define ANIM1_FALLOUT_CLUB               (5)
#define ANIM1_FALLOUT_HAMMER             (6)
#define ANIM1_FALLOUT_SPEAR              (7)
#define ANIM1_FALLOUT_PISTOL             (8)
#define ANIM1_FALLOUT_UZI                (9)
#define ANIM1_FALLOUT_SHOOTGUN           (10)
#define ANIM1_FALLOUT_RIFLE              (11)
#define ANIM1_FALLOUT_MINIGUN            (12)
#define ANIM1_FALLOUT_ROCKET_LAUNCHER    (13)
#define ANIM1_FALLOUT_AIM                (14)
#define ANIM2_FALLOUT_STAY               (1)
#define ANIM2_FALLOUT_WALK               (2)
#define ANIM2_FALLOUT_SHOW               (3)
#define ANIM2_FALLOUT_HIDE               (4)
#define ANIM2_FALLOUT_DODGE_WEAPON       (5)
#define ANIM2_FALLOUT_THRUST             (6)
#define ANIM2_FALLOUT_SWING              (7)
#define ANIM2_FALLOUT_PREPARE_WEAPON     (8)
#define ANIM2_FALLOUT_TURNOFF_WEAPON     (9)
#define ANIM2_FALLOUT_SHOOT              (10)
#define ANIM2_FALLOUT_BURST              (11)
#define ANIM2_FALLOUT_FLAME              (12)
#define ANIM2_FALLOUT_THROW_WEAPON       (13)
#define ANIM2_FALLOUT_DAMAGE_FRONT       (15)
#define ANIM2_FALLOUT_DAMAGE_BACK        (16)
#define ANIM2_FALLOUT_KNOCK_FRONT        (1)  // Only with ANIM1_FALLOUT_DEAD
#define ANIM2_FALLOUT_KNOCK_BACK         (2)
#define ANIM2_FALLOUT_STANDUP_BACK       (8)  // Only with ANIM1_FALLOUT_KNOCKOUT
#define ANIM2_FALLOUT_STANDUP_FRONT      (10)
#define ANIM2_FALLOUT_PICKUP             (11) // Only with ANIM1_FALLOUT_UNARMED
#define ANIM2_FALLOUT_USE                (12)
#define ANIM2_FALLOUT_DODGE_EMPTY        (14)
#define ANIM2_FALLOUT_PUNCH              (17)
#define ANIM2_FALLOUT_KICK               (18)
#define ANIM2_FALLOUT_THROW_EMPTY        (19)
#define ANIM2_FALLOUT_RUN                (20)
#define ANIM2_FALLOUT_DEAD_FRONT         (1)  // Only with ANIM1_FALLOUT_DEAD
#define ANIM2_FALLOUT_DEAD_BACK          (2)
#define ANIM2_FALLOUT_DEAD_BLOODY_SINGLE (4)
#define ANIM2_FALLOUT_DEAD_BURN          (5)
#define ANIM2_FALLOUT_DEAD_BLOODY_BURST  (6)
#define ANIM2_FALLOUT_DEAD_BURST         (7)
#define ANIM2_FALLOUT_DEAD_PULSE         (8)
#define ANIM2_FALLOUT_DEAD_LASER         (9)
#define ANIM2_FALLOUT_DEAD_BURN2         (10)
#define ANIM2_FALLOUT_DEAD_PULSE_DUST    (11)
#define ANIM2_FALLOUT_DEAD_EXPLODE       (12)
#define ANIM2_FALLOUT_DEAD_FUSED         (13)
#define ANIM2_FALLOUT_DEAD_BURN_RUN      (14)
#define ANIM2_FALLOUT_DEAD_FRONT2        (15)
#define ANIM2_FALLOUT_DEAD_BACK2         (16)
////////////////////////////////////////////////////////////////////////////////////////////////////
// Convert from common to fallout specific
bool critter_animation_fallout(uint crType, uint& anim1, uint& anim2, uint& anim1ex, uint& anim2ex, uint& flags)
{
	// Still only weapon
	anim1 &= ANIM1_WEAPON_MASK;

	// Weapon
	switch(anim1)
	{
	case ANIM1_UNARMED:         anim1 = ANIM1_FALLOUT_UNARMED;         break;
	case ANIM1_KNIFE:           anim1 = ANIM1_FALLOUT_KNIFE;           break;
	case ANIM1_CLUB:            anim1 = ANIM1_FALLOUT_CLUB;            break;
	case ANIM1_HAMMER:          anim1 = ANIM1_FALLOUT_HAMMER;          break;
	case ANIM1_SPEAR:           anim1 = ANIM1_FALLOUT_SPEAR;           break;
	case ANIM1_PISTOL:          anim1 = ANIM1_FALLOUT_PISTOL;          break;
	case ANIM1_SMG:             anim1 = ANIM1_FALLOUT_UZI;             break;
	case ANIM1_SHOOTGUN:        anim1 = ANIM1_FALLOUT_SHOOTGUN;        break;
	case ANIM1_HEAVY_RIFLE:     anim1 = ANIM1_FALLOUT_RIFLE;           break;
	case ANIM1_MINIGUN:         anim1 = ANIM1_FALLOUT_MINIGUN;         break;
	case ANIM1_ROCKET_LAUNCHER: anim1 = ANIM1_FALLOUT_ROCKET_LAUNCHER; break;
	case ANIM1_FLAMER:          anim1 = ANIM1_FALLOUT_RIFLE;           break;
	case ANIM1_RIFLE:           anim1 = ANIM1_FALLOUT_RIFLE;           break;
	case ANIM1_SWORD:           anim1 = ANIM1_FALLOUT_KNIFE;           break;
	case ANIM1_LONG_SWORD:      anim1 = ANIM1_FALLOUT_KNIFE;           break;
	case ANIM1_AXE:             anim1 = ANIM1_FALLOUT_CLUB;            break;
	case ANIM1_BOW:             anim1 = ANIM1_FALLOUT_UNARMED;         break;
	default:                    anim1 = ANIM1_FALLOUT_UNARMED;         break;
	}

	// Action
	switch(anim2)
	{
	case ANIM2_IDLE:               anim2 = ANIM2_FALLOUT_STAY; flags |= ANIM_FLAG_FIRST_FRAME;   break;
	case ANIM2_IDLE_STUNNED:       anim2 = ANIM2_FALLOUT_STAY; flags |= ANIM_FLAG_FIRST_FRAME;   break;
	case ANIM2_WALK:               anim2 = ANIM2_FALLOUT_WALK;                                   break;
	case ANIM2_LIMP:               anim2 = ANIM2_FALLOUT_WALK;                                   break;
	case ANIM2_RUN:                anim2 = ANIM2_FALLOUT_RUN;  anim1 = ANIM1_FALLOUT_UNARMED;    break;
	case ANIM2_PANIC_RUN:          anim2 = ANIM2_FALLOUT_RUN;  anim1 = ANIM1_FALLOUT_UNARMED;    break;
	case ANIM2_SHOW_WEAPON:        anim2 = ANIM2_FALLOUT_SHOW;                                   break;
	case ANIM2_HIDE_WEAPON:        anim2 = ANIM2_FALLOUT_HIDE;                                   break;
	case ANIM2_PREPARE_WEAPON:     anim2 = ANIM2_FALLOUT_PREPARE_WEAPON;                         break;
	case ANIM2_TURNOFF_WEAPON:     anim2 = ANIM2_FALLOUT_TURNOFF_WEAPON;                         break;
	case ANIM2_FIDGET:             anim2 = ANIM2_FALLOUT_STAY;                                   break;
//	case ANIM2_CLIMBING:           anim2 = ;                                                     break;
	case ANIM2_PICKUP:             anim2 = ANIM2_FALLOUT_PICKUP; anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_USE:                anim2 = ANIM2_FALLOUT_USE;    anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_SWITCH_ITEMS:       anim2 = ANIM2_FALLOUT_USE;    anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_LOOT:               anim2 = ANIM2_FALLOUT_PICKUP; anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_STEAL:              anim2 = ANIM2_FALLOUT_USE;    anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_PUSH:               anim2 = ANIM2_FALLOUT_PUNCH;  anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_IDLE_COMBAT:        anim2 = ANIM2_FALLOUT_STAY;   flags |= ANIM_FLAG_FIRST_FRAME; break;
	case ANIM2_PUNCH_RIGHT:        anim2 = ANIM2_FALLOUT_PUNCH;  anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_KICK_HI:            anim2 = ANIM2_FALLOUT_KICK;   anim1 = ANIM1_FALLOUT_UNARMED;  break;
	case ANIM2_THRUST_1H:          anim2 = ANIM2_FALLOUT_THRUST;                                 break;
	case ANIM2_THRUST_2H:          anim2 = ANIM2_FALLOUT_THRUST;                                 break;
	case ANIM2_SWING_1H:           anim2 = ANIM2_FALLOUT_SWING;                                  break;
	case ANIM2_SWING_2H:           anim2 = ANIM2_FALLOUT_SWING;                                  break;
	case ANIM2_SINGLE:             anim2 = ANIM2_FALLOUT_SHOOT;                                  break;
	case ANIM2_BURST:              anim2 = ANIM2_FALLOUT_BURST;                                  break;
	case ANIM2_SWEEP:              anim2 = ANIM2_FALLOUT_BURST;                                  break;
	case ANIM2_FLAME:              anim2 = ANIM2_FALLOUT_FLAME;                                  break;
	case ANIM2_BUTT:               anim2 = ANIM2_FALLOUT_PUNCH; anim1 = ANIM1_FALLOUT_UNARMED;   break;
	case ANIM2_THROW:              anim2 = (anim1 == ANIM1_FALLOUT_UNARMED ? ANIM2_FALLOUT_THROW_EMPTY : ANIM2_FALLOUT_THROW_WEAPON); break;
	case ANIM2_DODGE_FRONT:        anim2 = (anim1 == ANIM1_FALLOUT_UNARMED ? ANIM2_FALLOUT_DODGE_EMPTY : ANIM2_FALLOUT_DODGE_WEAPON); break;
	case ANIM2_DODGE_BACK:         anim2 = (anim1 == ANIM1_FALLOUT_UNARMED ? ANIM2_FALLOUT_DODGE_EMPTY : ANIM2_FALLOUT_DODGE_WEAPON); break;
	case ANIM2_DAMAGE_FRONT:       anim2 = ANIM2_FALLOUT_DAMAGE_FRONT;                                       break;
	case ANIM2_DAMAGE_BACK:        anim2 = ANIM2_FALLOUT_DAMAGE_BACK;                                        break;
	case ANIM2_DAMAGE_MUL_FRONT:   anim2 = ANIM2_FALLOUT_DAMAGE_FRONT;                                       break;
	case ANIM2_DAMAGE_MUL_BACK:    anim2 = ANIM2_FALLOUT_DAMAGE_BACK;                                        break;
	case ANIM2_KNOCK_FRONT:        anim2 = ANIM2_FALLOUT_KNOCK_FRONT;        anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_KNOCK_BACK:         anim2 = ANIM2_FALLOUT_KNOCK_BACK;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_STANDUP_FRONT:      anim2 = ANIM2_FALLOUT_STANDUP_FRONT;      anim1 = ANIM1_FALLOUT_KNOCKOUT; break;
	case ANIM2_STANDUP_BACK:       anim2 = ANIM2_FALLOUT_STANDUP_BACK;       anim1 = ANIM1_FALLOUT_KNOCKOUT; break;
	case ANIM2_DEAD_PRONE_FRONT:   anim2 = ANIM2_FALLOUT_DEAD_FRONT2;        anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_PRONE_BACK:    anim2 = ANIM2_FALLOUT_DEAD_BACK2;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_BLOODY_SINGLE: anim2 = ANIM2_FALLOUT_DEAD_BLOODY_SINGLE; anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_BLOODY_BURST:  anim2 = ANIM2_FALLOUT_DEAD_BLOODY_BURST;  anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_BURST:         anim2 = ANIM2_FALLOUT_DEAD_BURST;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_PULSE:         anim2 = ANIM2_FALLOUT_DEAD_PULSE;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_PULSE_DUST:    anim2 = ANIM2_FALLOUT_DEAD_PULSE_DUST;    anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_LASER:         anim2 = ANIM2_FALLOUT_DEAD_LASER;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_FUSED:         anim2 = ANIM2_FALLOUT_DEAD_FUSED;         anim1 = ANIM1_FALLOUT_DEAD;     break;
	case ANIM2_DEAD_EXPLODE:       anim2 = ANIM2_FALLOUT_DEAD_EXPLODE;       anim1 = ANIM1_FALLOUT_DEAD;     break;

	case ANIM2_IDLE_PRONE_FRONT:   anim2 = ANIM2_FALLOUT_KNOCK_FRONT;        anim1 = ANIM1_FALLOUT_DEAD; flags |= ANIM_FLAG_LAST_FRAME; break;
	case ANIM2_IDLE_PRONE_BACK:    anim2 = ANIM2_FALLOUT_KNOCK_BACK;         anim1 = ANIM1_FALLOUT_DEAD; flags |= ANIM_FLAG_LAST_FRAME; break;

	case ANIM2_DEAD_BURN:          anim2 = ANIM2_FALLOUT_DEAD_BURN;          anim1 = ANIM1_FALLOUT_DEAD;     break; // ANIM2_FALLOUT_DEAD_BURN2
	case ANIM2_DEAD_BURN_RUN:
		anim2   = ANIM2_FALLOUT_DEAD_BURN_RUN; anim1   = ANIM1_FALLOUT_DEAD;
		anim2ex = ANIM2_FALLOUT_DEAD_BURN;     anim1ex = ANIM1_FALLOUT_DEAD;
		break;

	case ANIM2_DEAD_FRONT:
		anim1 = ANIM1_FALLOUT_DEAD;        anim1ex = ANIM1_FALLOUT_DEAD;
		anim2 = ANIM2_FALLOUT_KNOCK_FRONT; anim2ex = ANIM2_FALLOUT_DEAD_FRONT2;
		break;
	case ANIM2_DEAD_BACK:
		anim1 = ANIM1_FALLOUT_DEAD;       anim1ex = ANIM1_FALLOUT_DEAD;
		anim2 = ANIM2_FALLOUT_KNOCK_BACK; anim2ex = ANIM2_FALLOUT_DEAD_BACK2;
		break;
	case ANIM2_NO_RECOIL:
	case ANIM2_RELOAD:
	case ANIM2_REPAIR:
		anim1ex = anim1;
		anim2 = ANIM2_FALLOUT_PREPARE_WEAPON; anim2ex = ANIM2_FALLOUT_TURNOFF_WEAPON;
		break;

	// ANIM2_BEGIN_COMBAT
	// ANIM2_END_COMBAT
	// ANIM2_PUNCH_LEFT
	// ANIM2_PUNCH_COMBO
	// ANIM2_KICK_LO
	// ANIM2_KICK_COMBO
	// ANIM2_WALK_DAMAGE_FRONT
	// ANIM2_WALK_DAMAGE_BACK
	// ANIM2_LIMP_DAMAGE_FRONT
	// ANIM2_LIMP_DAMAGE_BACK
	// ANIM2_RUN_DAMAGE_FRONT
	// ANIM2_RUN_DAMAGE_BACK
	// ANIM2_LAYDOWN_FRONT
	// ANIM2_LAYDOWN_BACK
	// ANIM2_DAMAGE_PRONE_FRONT
	// ANIM2_DAMAGE_PRONE_BACK
	// ANIM2_DAMAGE_MUL_PRONE_FRONT
	// ANIM2_DAMAGE_MUL_PRONE_BACK
	// ANIM2_TWITCH_PRONE_FRONT
	// ANIM2_TWITCH_PRONE_BACK
	default: return false;
	}
	return true;
}

#ifdef __CLIENT
void PlayAnimSound(uint crType, int gender, uint anim1, uint anim2)
{
	if(anim2 == ANIM2_WALK || anim2 == ANIM2_LIMP || anim2 == ANIM2_RUN ||
		anim2 == ANIM2_PANIC_RUN || anim2 == ANIM2_SNEAK_WALK || anim2 == ANIM2_SNEAK_RUN) return;

	bool isFemale = gender == GENDER_FEMALE;
	int animType = GetCritterAnimType(crType);
	string crTypeSound = GetCritterSoundName(crType);

	// Keep only weapon
	anim1 &= ANIM1_WEAPON_MASK;

	if(animType == ANIM_TYPE_FALLOUT)
	{
		// Convert indicies to fallout specific
		uint fAnim1 = anim1, fAnim2 = anim2, fAnim1ex = 0, fAnim2ex = 0, fFlags = 0;
		if(!critter_animation_fallout(crType, fAnim1, fAnim2, fAnim1ex, fAnim2ex, fFlags) || fFlags != 0) return;

		// Make name
		const string abc = "_abcdefghijklmnopqrstuvwxyz0123456789";
		string sound = crTypeSound;
		sound.resize(sound.length() + 1); sound[sound.length() - 1] = abc[fAnim1];
		sound.resize(sound.length() + 1); sound[sound.length() - 1] = abc[fAnim2];
		sound += ".acm";

		// Convert 'ha' to 'hm' / 'hf'
		if(sound[0] == 'h' && sound[1] == 'a') sound[1] = (isFemale ? 'f' : 'm');

		// Try play
		if(PlaySound(sound)) return;

		// Find substitutes for humans
		if(sound[0] == 'h')
		{
			// Try find by mask (hmxxxxab)
			for(uint i = 2, j = crTypeSound.length(); i < j; i++) sound[i] = 'x';
			if(PlaySound(sound)) return;

			// Convert 'hf' to 'hm'
			if(sound[1] == 'f')
			{
				sound[1] = 'm';
				if(PlaySound(sound)) return;
			}
		}
	}
	else
	{
		uint sexPos = crTypeSound.length() - 1;
		if(crTypeSound[sexPos] == 'U') crTypeSound[sexPos] = (isFemale ? 'F' : 'M');

		for(uint pass = 0; pass < 4; pass++)
		{
			if(pass == 2)
			{
				if(crTypeSound[sexPos] == 'I') break;
				crTypeSound[sexPos] = 'U';
			}

			string sound = crTypeSound + "_";

			if(pass == 0 || pass == 2)
			{
				switch(anim1)
				{
				case ANIM1_UNARMED:         sound += "Unarmed";        break;
				case ANIM1_KNIFE:           sound += "Knife";          break;
				case ANIM1_CLUB:            sound += "Club";           break;
				case ANIM1_HAMMER:          sound += "Hammer";         break;
				case ANIM1_SPEAR:           sound += "Spear";          break;
				case ANIM1_PISTOL:          sound += "Pistol";         break;
				case ANIM1_SMG:             sound += "SMG";            break;
				case ANIM1_SHOOTGUN:        sound += "Shootgun";       break;
				case ANIM1_HEAVY_RIFLE:     sound += "HeavyRifle";     break;
				case ANIM1_MINIGUN:         sound += "Minigun";        break;
				case ANIM1_ROCKET_LAUNCHER: sound += "RocketLauncher"; break;
				case ANIM1_FLAMER:          sound += "Flamer";         break;
				case ANIM1_RIFLE:           sound += "Rifle";          break;
				case ANIM1_SWORD:           sound += "Sword";          break;
				case ANIM1_LONG_SWORD:      sound += "LongSword";      break;
				case ANIM1_AXE:             sound += "Axe";            break;
				case ANIM1_BOW:             sound += "Bow";            break;
				default: break;
				}
			}

			switch(anim2)
			{
			case ANIM2_IDLE:                   sound += "Idle";                break;
			case ANIM2_IDLE_STUNNED:           sound += "IdleStunned";         break;
			case ANIM2_WALK:                   sound += "Walk";                break;
			case ANIM2_LIMP:                   sound += "Limp";                break;
			case ANIM2_RUN:                    sound += "Run";                 break;
			case ANIM2_PANIC_RUN:              sound += "PanicRun";            break;
			case ANIM2_SNEAK_WALK:             sound += "SneakWalk";           break;
			case ANIM2_SNEAK_RUN:              sound += "SneakRun";            break;
			case ANIM2_STAND:                  sound += "Stand";               break;
			case ANIM2_CROUCH:                 sound += "Crouch";              break;
			case ANIM2_PRONE:                  sound += "Prone";               break;
			case ANIM2_SHOW_WEAPON:            sound += "ShowWeapon";          break;
			case ANIM2_HIDE_WEAPON:            sound += "HideWeapon";          break;
			case ANIM2_PREPARE_WEAPON:         sound += "PrepareWeapon";       break;
			case ANIM2_TURNOFF_WEAPON:         sound += "TurnoffWeapon";       break;
			case ANIM2_FIDGET:                 sound += "Fidget";              break;
			case ANIM2_CLIMBING:               sound += "Climbing";            break;
			case ANIM2_PICKUP:                 sound += "Pickup";              break;
			case ANIM2_USE:                    sound += "Use";                 break;
			case ANIM2_SWITCH_ITEMS:           sound += "SwitchItems";         break;
			case ANIM2_RELOAD:                 sound += "Reload";              break;
			case ANIM2_REPAIR:                 sound += "Repair";              break;
			case ANIM2_LOOT:                   sound += "Loot";                break;
			case ANIM2_STEAL:                  sound += "Steal";               break;
			case ANIM2_PUSH:                   sound += "Push";                break;
			case ANIM2_BEGIN_COMBAT:           sound += "BeginCombat";         break;
			case ANIM2_IDLE_COMBAT:            sound += "IdleCombat";          break;
			case ANIM2_END_COMBAT:             sound += "EndCombat";           break;
			case ANIM2_PUNCH_RIGHT:            sound += "PunchRight";          break;
			case ANIM2_PUNCH_LEFT:             sound += "PunchLeft";           break;
			case ANIM2_PUNCH_COMBO:            sound += "PunchCombo";          break;
			case ANIM2_KICK_HI:                sound += "KickHi";              break;
			case ANIM2_KICK_LO:                sound += "KickLo";              break;
			case ANIM2_KICK_COMBO:             sound += "KickCombo";           break;
			case ANIM2_THRUST_1H:              sound += "Thrust1H";            break;
			case ANIM2_THRUST_2H:              sound += "Thrust2H";            break;
			case ANIM2_SWING_1H:               sound += "Swing1H";             break;
			case ANIM2_SWING_2H:               sound += "Swing2H";             break;
			case ANIM2_THROW:                  sound += "Throw";               break;
			case ANIM2_SINGLE:                 sound += "Single";              break;
			case ANIM2_BURST:                  sound += "Burst";               break;
			case ANIM2_SWEEP:                  sound += "Sweep";               break;
			case ANIM2_BUTT:                   sound += "Butt";                break;
			case ANIM2_FLAME:                  sound += "Flame";               break;
			case ANIM2_NO_RECOIL:              sound += "NoRecoil";            break;
			case ANIM2_DODGE_FRONT:            sound += "DodgeFront";          break;
			case ANIM2_DODGE_BACK:             sound += "DodgeBack";           break;
			case ANIM2_DAMAGE_FRONT:           sound += "DamageFront";         break;
			case ANIM2_DAMAGE_BACK:            sound += "DamageBack";          break;
			case ANIM2_DAMAGE_MUL_FRONT:       sound += "DamageMulFront";      break;
			case ANIM2_DAMAGE_MUL_BACK:        sound += "DamageMulBack";       break;
			case ANIM2_WALK_DAMAGE_FRONT:      sound += "WalkDamageFront";     break;
			case ANIM2_WALK_DAMAGE_BACK:       sound += "WalkDamageBack";      break;
			case ANIM2_LIMP_DAMAGE_FRONT:      sound += "LimpDamageFront";     break;
			case ANIM2_LIMP_DAMAGE_BACK:       sound += "LimpDamageBack";      break;
			case ANIM2_RUN_DAMAGE_FRONT:       sound += "RunDamageFront";      break;
			case ANIM2_RUN_DAMAGE_BACK:        sound += "RunDamageBack";       break;
			case ANIM2_KNOCK_FRONT:            sound += "KnockFront";          break;
			case ANIM2_KNOCK_BACK:             sound += "KnockBack";           break;
			case ANIM2_LAYDOWN_FRONT:          sound += "LaydownFront";        break;
			case ANIM2_LAYDOWN_BACK:           sound += "LaydownBack";         break;
			case ANIM2_IDLE_PRONE_FRONT:       sound += "IdleProneFront";      break;
			case ANIM2_IDLE_PRONE_BACK:        sound += "IdleProneBack";       break;
			case ANIM2_STANDUP_FRONT:          sound += "StandupFront";        break;
			case ANIM2_STANDUP_BACK:           sound += "StandupBack";         break;
			case ANIM2_DAMAGE_PRONE_FRONT:     sound += "DamageProneFront";    break;
			case ANIM2_DAMAGE_PRONE_BACK:      sound += "DamageProneBack";     break;
			case ANIM2_DAMAGE_MUL_PRONE_FRONT: sound += "DamageMulProneFront"; break;
			case ANIM2_DAMAGE_MUL_PRONE_BACK:  sound += "DamageMulProneBack";  break;
			case ANIM2_TWITCH_PRONE_FRONT:     sound += "TwitchProneFront";    break;
			case ANIM2_TWITCH_PRONE_BACK:      sound += "TwitchProneBack";     break;
			case ANIM2_DEAD_PRONE_FRONT:       sound += "DeadProneFront";      break;
			case ANIM2_DEAD_PRONE_BACK:        sound += "DeadProneBack";       break;
			case ANIM2_DEAD_FRONT:             sound += "DeadFront";           break;
			case ANIM2_DEAD_BACK:              sound += "DeadBack";            break;
			case ANIM2_DEAD_BLOODY_SINGLE:     sound += "DeadBloodySingle";    break;
			case ANIM2_DEAD_BLOODY_BURST:      sound += "DeadBloodyBack";      break;
			case ANIM2_DEAD_BURST:             sound += "DeadBurst";           break;
			case ANIM2_DEAD_PULSE:             sound += "DeadPulse";           break;
			case ANIM2_DEAD_PULSE_DUST:        sound += "DeadPulseDust";       break;
			case ANIM2_DEAD_LASER:             sound += "DeadLaser";           break;
			case ANIM2_DEAD_FUSED:             sound += "DeadFused";           break;
			case ANIM2_DEAD_EXPLODE:           sound += "DeadExplode";         break;
			case ANIM2_DEAD_BURN:              sound += "DeadBurn";            break;
			case ANIM2_DEAD_BURN_RUN:          sound += "DeadBurnRun";         break;
			default: break;
			}

			// Try play
			if(PlaySound(sound + ".wav")) return;

			// Try erase 'Front' / 'Back'
			uint len = 0;
			int pos = findLast(sound, "Front");
			if(pos != -1) len = 5;
			else
			{
				pos = findLast(sound, "Back");
				if(pos != -1) len = 4;
				else continue;
			}
			sound.resize(sound.length() - len);

			if(PlaySound(sound + ".wav")) return;
		}
	}
}
#endif


