addDamageType( "Fire", '<bitmap:Add-Ons/___/CI_Fire> %1', '%2 <bitmap:Add-Ons/___/CI_Fire> %1', 1, 1 );

datablock particleData( burningParticle )
{
	textureName = "base/data/particles/cloud";
	dragCoefficient = 0.0;
	gravityCoefficient = -1.0;
	inheritedVelFactor = 0.0;
	windCoefficient = 0;
	constantAcceleration = 3.0;
	lifetimeMS = 1000;
	lifetimeVarianceMS = 100;
	spinSpeed = 0;
	spinRandomMin = -90.0;
	spinRandomMax =  90.0;
	useInvAlpha = false;
	
	colors[ 0 ] = "1.0 1.0 0.3 0.0";
	colors[ 1 ] = "1.0 1.0 0.3 1.0";
	colors[ 2 ] = "0.6 0.0 0.0 0.0";
	
	sizes[ 0 ] = 0.0;
	sizes[ 1 ] = 0.75;
	sizes[ 2 ] = 1.5;
	
	times[ 0 ] = 0.0;
	times[ 1 ] = 0.2;
	times[ 2 ] = 0.9;
};


datablock particleEmitterData( burningEmitter )
{
	ejectionPeriodMS = 5;
	periodVarianceMS = 4;
	ejectionVelocity = 0;
	ejectionOffset = 1.00;
	velocityVariance = 0.0;
	thetaMin = 30;
	thetaMax = 90;
	phiReferenceVel = 0;
	phiVariance = 360;
	overrideAdvance = false;
	
	particles = burningParticle;  
};

datablock shapeBaseImageData( burningImage )
{
	shapeFile = "base/data/shapes/empty.dts";
	emap = false;
	
	mountPoint = $HeadSlot;
	offset = "0 -0.5 -1";
	// offset = "0 -0.5 0";
	
	stateName[0] = "Ready";
	stateTimeoutValue[0] = 0.01;
	stateTransitionOnTimeout[0] = "FireA";
	
	stateName[1] = "FireA";
	// stateEmitter[1] = burningEmitter;
	stateEmitter[1] = sFireExplosionEmitter;
	stateEmitterTime[1] = 0.9;
	stateTimeoutValue[1] = 0.9;
	stateTransitionOnTimeout[1] = "Done";
	stateWaitForTimeout[1] = true;
	
	stateName[2] = "Done";
	stateTimeoutValue[2] = 0.01;
	stateTransitionOnTimeout[2] = "FireA";
};

function burningImage::onMount( %this, %obj, %slot )
{
	if ( isObject( %obj ) && %slot == 2 )
	{
		%this.damageTick( %obj );
	}
}

function burningImage::onUnMount( %this, %obj, %slot )
{
	if ( isEventPending( %this.damageTick[ %obj ] ) )
	{
		cancel( %this.damageTick[ %obj ] );
		%obj.spawnExplosion( playerSootProjectile, %obj.getSize(), %obj.client );
	}
}

function burningImage::damageTick( %this, %obj )
{
	cancel( %this.damageTick[ %obj ] );
	
	if ( !isObject( %obj ) )
	{
		return;
	}
	
	if ( !isObject( %mn = %obj.getMountedImage( 2 ) ) )
	{
		return;
	}
	
	if ( %mn !$= %this )
	{
		return;
	}
	
	%obj.damage( %obj, %obj.getHackPosition(), 50, $DamageType::Fire, "body" );
	%this.damageTick[ %obj ] = %this.schedule( 1000, "damageTick", %obj );
}

function simObject::dmg( %this, %amnt, %type )
{
	if ( !isFunction( %this.getClassName(), "damage" ) )
	{
		return;
	}
	
	if ( !strLen( %type ) )
	{
		%type = $DamageType::Default;
	}
	
	%this.damage( %this, %this.getPosition(), %amnt, %type, "body" );
}

package damage_package
{
	function wheeledVehicleData::onCollision( %this, %obj, %col, %pos, %vel )
	{
		parent::onCollision( %this, %obj, %col, %pos, %vel );
		
		if ( !( %col.getType() & $TypeMasks::VehicleObjectType ) )
		{
			return;
		}
		
		if ( %vel >= 15 && %obj.health )
		{
			%vel -= 15;
			%amn = 100;
			%amn *= %vel / 50;
			
			%obj.damage( -1, %pos, %amn, $DamageType::Default, "body" );
		}
	}
	
	function flyingVehicle::onCollision( %this, %obj, %col, %pos, %vel )
	{
		wheeledVehicle::onCollision( %this, %obj, %col, %pos, %vel );
	}
	
	function hoverVehicle::onCollision( %this, %obj, %col, %pos, %vel )
	{
		wheeledVehicle::onCollision( %this, %obj, %col, %pos, %vel );
	}
	
	function wheeledVehicle::finalExplosion( %this )
	{
		%db = %this.getDataBlock();
		%vel = getRandom( -10, 10 ) SPC getRandom( -10, 10 ) SPC 10;
		
		%scale = %this.getScale();
		%scale = vectorScale( %scale, %db.finalExplosionScale );
		
		%obj = new Projectile()
		{
			position = %this.getPosition();
			datablock = %db.finalExplosionProjectile;
			initialVelocity = %vel;
			initialPosition = %this.getPosition();
		};
		
		missionCleanup.add( %obj );
		
		%obj.setScale( %scale );
		%obj.explode();
		
		%radius = vectorScale( %scale, %db.finalExplosionProjectile.explosion.damageRadius );
		initContainerRadiusSearch( %this.getPosition(), %radius, $TypeMasks::PlayerObjectType );
		
		while ( isObject( %obj = containerSearchNext() ) )
		{
			%time = %db.burnTime / 1000;
			%time *= vectorDist( %this.getPosition(), %obj.getPosition() ) / %radius;
			
			%obj.burnPlayer( %time );
		}
		
		if ( isObject( %spawn = %this.spawnBrick ) )
		{
			%spawn.schedule( 1000, "respawnVehicle" );
		}
		
		%this.delete();
	}
	
	function flyingVehicle::finalExplosion( %this )
	{
		wheeledVehicle::finalExplosion( %this );
	}
	
	function hoverVehicle::finalExplosion( %this )
	{
		wheeledVehicle::finalExplosion( %this );
	}
	
	function Armor::onEnterLiquid( %this, %obj, %splash, %type )
	{
		parent::onEnterLiquid( %this, %obj, %splash, %type );
		
		%obj.inLiquid = true;
		
		if ( %obj.isOnFire )
		{
			%obj.setOnFire( false );
		}
	}
	
	function Armor::onLeaveLiquid( %this, %obj, %a, %b, %c, %d )
	{
		parent::onLeaveLiquid( %this, %obj, %a, %b, %c, %d );
		%obj.inLiquid = false;
	}
	
	function miniGameCanDamage( %x, %y )
	{
		if ( %y.getClassName() $= "fxDTSBrick" )
		{
			return false;
		}
		
		return true;
	}
	
	function Armor::onAdd( %this, %obj )
	{
		// parent::onAdd( %this, %obj );
		
		%obj.invincible = false;
		%obj.maxHealth = %this.maxDamage;
		%obj.health = %this.maxDamage;
		%obj.damageShield = 0;
		%obj.offenseValue = 1;
		%obj.defenseValue = 1;
	}
	
	function Armor::onNewDataBlock( %this, %obj )
	{
		parent::onNewDataBlock( %this, %obj );
		
		%obj.maxHealth = %this.maxDamage;
		
		if ( !strLen( %obj.health ) )
		{
			%obj.health = %this.maxDamage;
		}
		
		if ( %obj.health > %obj.maxHealth )
		{
			%obj.health = %obj.maxHealth;
		}
	}
	function wheeledVehicleData::onAdd( %this, %obj )
	{
		parent::onAdd( %this, %obj );
		
		%obj.invincible = false;
		%obj.maxHealth = %this.maxDamage;
		%obj.health = %this.maxDamage;
	}
	
	function wheeledVehicleData::onNewDataBlock( %this, %obj )
	{
		// parent::onNewDataBlock( %this, %obj );
		%obj.maxHealth = %this.maxDamage;
		
		if ( !strLen( %obj.health ) )
		{
			%obj.health = %this.maxDamage;
		}
		
		if ( %obj.health > %obj.maxHealth )
		{
			%obj.health = %obj.maxHealth;
		}
	}
	
	function flyingVehicleData::onAdd( %this, %obj )
	{
		// parent::onAdd( %this, %obj );
		
		%obj.invincible = false;
		%obj.maxHealth = %this.maxDamage;
		%obj.health = %this.maxDamage;
	}
	
	function flyingVehicleData::onNewDataBlock( %this, %obj )
	{
		// parent::onNewDataBlock( %this, %obj );
		%obj.maxHealth = %this.maxDamage;
		
		if ( !strLen( %obj.health ) )
		{
			%obj.health = %this.maxDamage;
		}
		
		if ( %obj.health > %obj.maxHealth )
		{
			%obj.health = %obj.maxHealth;
		}
	}
	
	function hoverVehicleData::onAdd( %this, %obj )
	{
		parent::onAdd( %this, %obj );
		
		%obj.invincible = false;
		%obj.maxHealth = %this.maxDamage;
		%obj.health = %this.maxDamage;
	}
	
	function hoverVehicleData::onNewDataBlock( %this, %obj )
	{
		// parent::onNewDataBlock( %this, %obj );
		%obj.maxHealth = %this.maxDamage;
	
		if ( !strLen( %obj.health ) )
		{
			%obj.health = %this.maxDamage;
		}
			
		if ( %obj.health > %obj.maxHealth )
		{
			%obj.health = %obj.maxHealth;
		}
	}
	
	function Player::kill( %this, %damageType )
	{
		if ( getSimTime() - %this.spawnTime < $Game::PlayerInvulnerabilityTime )
		{
			return false;
		}
		
		if ( !strLen( %damageType ) )
		{
			%damageType = $DamageType::Suicide;
		}
		
		%this.setInvincible( false );
		%this.damage( %this, %this.getHackPosition(), %this.getDataBlock().maxDamage + 1, %damageType, "body", true );
	}
	
	function AIPlayer::kill( %this, %damageType )
	{
		Player::kill( %this, %damageType );
	}
	
	function Player::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent )
	{
		if ( %parent )
		{
			parent::damage( %this, %sourceObject, %position, %damage * getWord( %this.getScale(), 2 ), %damageType, %damageLoc );
			return;
		}
		
		if ( getSimTime() - %this.spawnTime < $Game::PlayerInvulnerabilityTime )
		{
			return false;
		}
		
		if ( !isFunction( "serverCanDamage" ) || !serverCanDamage( %sourceObject, %this ) )
		{
			return;
		}
		
		if ( !%this.health )
		{
			return;
		}
		
		if ( strLen( %sourceObject.offenseValue ) )
		{
			%damage *= %sourceObject.offenseValue;
		}
		else if ( isObject( %sourceObject ) && strLen( %off = %sourceObject.getClient().offenseValue ) )
		{
			%damage *= %off;
		}
		
		if ( strLen( %this.defenseValue ) )
		{
			%damage /= %this.defenseValue;
		}
		
		if ( %this.invincible )
		{
			%this.setWhiteOut( %damage / %this.maxHealth );
			return;
		}
		
		if ( %this.damageShield )
		{
			if ( %this.damageShield > %damage )
			{
				%this.subShield( %damage );
				%shielded = %damage;
				%damage -= %shielded;
			}
			else
			{
				%shielded = %this.damageShield;
				%this.setShield( 0 );
				%damage -= %shielded;
			}
			
			%this.setWhiteOut( %damage / %this.maxHealth );
			
			if ( %damage == 0 )
			{
				return;
			}
		}
		
		%mod = 1 - ( ( %this.health - %damage ) / %this.maxHealth );
		
		%this.playPain();
		%this.setDamageFlash( %mod );
		
		if ( %mod >= 2 / 3 )
		{
			%this.emote( painHighImage, true );
		}
		else if ( %mod >= 1 / 3 )
		{
			%this.emote( painMidImage, true );
		}
		else
		{
			%this.emote( painLowImage, true );
		}
		
		%this.health -= %damage;
		
		if ( %this.health < 0 )
		{
			%this.health = 0;
		}
		
		if ( %this.health > %this.maxHealth )
		{
			%this.health = %this.maxHealth;
		}
		
		if ( !%this.health )
		{
			parent::damage( %this, %sourceObject, %position, ( %this.getDataBlock().maxDamage + 1 ) * 5, %damageType, %damageLoc, true );
			
			if ( %this.getClassName() $= "AIPlayer" && isFunction( "AIPlayer", "onDeath" ) )
			{
				%this.onDeath( %sourceObject, ( isObject( %sourceObject ) ? %sourceObject.getClient() : -1 ), %position, %damageType, %damageLoc );
			}
		}
		else
		{
			commandToClient( %this.client, 'CenterPrint', "<just:right><font:impact:30>\c3" @ %this.health @ "\c6/\c3" @ %this.maxHealth @ " \c6HP ", 60 );
		}
	}
	
	function AIPlayer::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent )
	{
		Player::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent );
	}
	
	function wheeledVehicle::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent )
	{
		if ( %parent )
		{
			parent::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc );
		}
		
		if ( !isFunction( "serverCanDamage" ) || !serverCanDamage( %sourceObject, %this ) )
		{
			return;
		}
		
		if ( strLen( %sourceObject.offenseValue ) )
		{
			%damage *= %sourceObject.offenseValue;
		}
		
		if ( strLen( %this.defenseValue ) )
		{
			%damage /= %this.defenseValue;
		}
		
		if ( %this.invincible )
		{
			return;
		}
		
		if ( %this.damageShield )
		{
			if ( %this.damageShield > %damage )
			{
				%this.damageShield -= %damage;
				%damage = 0;
			}
			else
			{
				%damage -= %this.damageShield;
				%this.damageShield = 0;
			}
			
			if ( %damage == 0 )
			{
				return;
			}
		}
		
		%this.health -= %damage;
		
		if ( %this.health < 0 )
		{
			%this.health = 0;
		}
		
		if ( %this.health > %this.maxHealth )
		{
			%this.health = %this.maxHealth;
		}
		
		if ( !%this.health )
		{
			%this.vehicleKillNotice( %sourceObject, %damageType );
			parent::damage( %this, %sourceObject, %position, %this.getDataBlock().maxDamage + 1, %damageType, %damageLoc, true );
		}
	}
	
	function flyingVehicle::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent )
	{
		wheeledVehicle::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent );
	}
	
	function hoverVehicle::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent )
	{
		wheeledVehicle::damage( %this, %sourceObject, %position, %damage, %damageType, %damageLoc, %parent );
	}
	
	function Player::burnPlayer( %this, %time, %cl )
	{
		// parent::burnPlayer( %this, %time, %cl );
		
		cancel( %this.burnSchedule );
		
		if ( %this.inLiquid )
		{
			return;
		}
		
		%this.mountImage( "burningImage", 2 );
		%this.burnSchedule = %this.schedule( %time * 1000, "clearBurn", %cl );
	}
	
	function Player::clearBurn( %this, %cl )
	{
		// parent::clearBurn( %this, %cl );
		%this.unmountImage( 2 );
	}
};

function Player::getSize( %this )
{
	%scale = %this.getScale();
	return getWord( %scale, 0 ) * getWord( %scale, 1 ) * getWord( %scale, 2 );
}

activatePackage( "damage_package" );

function simObject::getClient( %this, %recurse )
{
	if ( %this.pseudoClient )
	{
		return -1;
	}
	
	%class = %this.getClassName();
	
	if ( %class $= "GameConnection" || %class $= "AIConnection" )
	{
		return %this;
	}
	
	if ( isObject( %cl = %this.client ) )
	{
		return %cl;
	}
	
	if ( isObject( %cl = getBrickGroupFromObject( %this ).client ) )
	{
		return %cl;
	}
	
	if ( isObject( %cl = %this.sourceClient ) )
	{
		return %cl;
	}
	
	if ( !%recurse && isObject( %cl = %this.sourceObject ) && isObject( %cl = %cl.getClient( true ) ) )
	{
		return %cl;
	}
	
	if ( isObject( %cl = getBrickGroupFromObject( %this.spawnBrick ).client ) )
	{
		return %cl;
	}
	
	return -1;
}

function wheeledVehicle::vehicleKillNotice( %this, %src, %damageType )
{
	if ( %this.hasMadeKillNotice )
	{
		return;
	}
	
	%this.hasMadeKillNotice = true;
	
	if ( !isObject( %src ) )
	{
		return;
	}
	
	if ( !isObject( %scl = %src.getClient() ) )
	{
		return;
	}
	
	if ( !isObject( %cl = %this.getClient() ) )
	{
		return;
	}
	
	messageAll( '', $DeathMessage_Murder[ %damageType ], %cl.name @ "'s" SPC %this.getDataBlock().uiName, %scl.name );
}

function flyingVehicle::vehicleKillNotice( %this, %src, %damageType )
{
	wheeledVehicle::vehicleKillNotice( %this, %src, %damageType );
}

function hoverVehicle::vehicleKillNotice( %this, %src, %damageType )
{
	wheeledVehicle::vehicleKillNotice( %this, %src, %damageType );
}

function Player::setHealth( %this, %health )
{
	if ( !strLen( %health ) )
	{
		return false;
	}
	
	if ( %health < 0 )
	{
		%health = 0;
	}
	
	if ( %health > %this.maxHealth )
	{
		%health = %this.maxHealth;
	}
	
	%this.health = %health;
	
	if ( !%this.health )
	{
		%this.damage( %this, %this.getHackPosition(), %this.getDataBlock().maxDamage + 1, $DamageType::Default, "body", true );
	}
	
	return true;
}

function Player::setMaxHealth( %this, %maxHealth )
{
	if ( !strLen( %maxHealth ) || %maxHealth <= 0 )
	{
		return false;
	}
	
	%this.maxHealth = %maxHealth;
	
	if ( %this.health > %this.maxHealth )
	{
		%this.health = %this.maxHealth;
	}
	
	return true;
}

function Player::setInvincible( %this, %bool )
{
	%this.invincible = ( %bool );
	return true;
}

function Player::setShield( %this, %value )
{
	if ( %value < 0 )
	{
		%value = 0;
	}
	
	%this.damageShield = %value;
	return true;
}

function Player::addHealth( %this, %health )
{
	return %this.setHealth( %this.health + %health );
}

function Player::addShield( %this, %value )
{
	return %this.setShield( %this.damageShield + %value );
}

function Player::subHealth( %this, %health )
{
	return %this.setHealth( %this.health - %health );
}

function Player::subShield( %this, %value )
{
	return %this.setShield( %this.damageShield - %value );
}

function Player::getHealth( %this )
{
	return %this.health;
}

function Player::getMaxHealth( %this )
{
	return %this.maxHealth;
}

function Player::isInvincible( %this )
{
	return ( %this.invincible );
}

function Player::getShield( %this )
{
	return %this.damageShield;
}

function wheeledVehicle::setHealth(%t,%h){return Player::setHealth(%t,%h);}
function wheeledVehicle::setMaxHealth(%t,%h){return Player::setMaxHealth(%t,%h);}
function wheeledVehicle::setInvincible(%t,%h){return Player::setInvincible(%t,%h);}
function wheeledVehicle::setShield(%t,%h){return Player::setShield(%t,%h);}
function wheeledVehicle::addHealth(%t,%h){return Player::addHealth(%t,%h);}
function wheeledVehicle::addShield(%t,%h){return Player::addShield(%t,%h);}
function wheeledVehicle::subHealth(%t,%h){return Player::subHealth(%t,%h);}
function wheeledVehicle::subShield(%t,%h){return Player::subShield(%t,%h);}
function wheeledVehicle::getHealth(%t){return Player::getHealth(%t);}
function wheeledVehicle::getMaxHealth(%t){return Player::getMaxHealth(%t);}
function wheeledVehicle::isInvincible(%t){return Player::isInvincible(%t);}
function wheeledVehicle::getShield(%t){return Player::getShield(%t);}

function flyingVehicle::setHealth(%t,%h){return Player::setHealth(%t,%h);}
function flyingVehicle::setMaxHealth(%t,%h){return Player::setMaxHealth(%t,%h);}
function flyingVehicle::setInvincible(%t,%h){return Player::setInvincible(%t,%h);}
function flyingVehicle::setShield(%t,%h){return Player::setShield(%t,%h);}
function flyingVehicle::addHealth(%t,%h){return Player::addHealth(%t,%h);}
function flyingVehicle::addShield(%t,%h){return Player::addShield(%t,%h);}
function flyingVehicle::subHealth(%t,%h){return Player::subHealth(%t,%h);}
function flyingVehicle::subShield(%t,%h){return Player::subShield(%t,%h);}
function flyingVehicle::getHealth(%t){return Player::getHealth(%t);}
function flyingVehicle::getMaxHealth(%t){return Player::getMaxHealth(%t);}
function flyingVehicle::isInvincible(%t){return Player::isInvincible(%t);}
function flyingVehicle::getShield(%t){return Player::getShield(%t);}

function hoverVehicle::setHealth(%t,%h){return Player::setHealth(%t,%h);}
function hoverVehicle::setMaxHealth(%t,%h){return Player::setMaxHealth(%t,%h);}
function hoverVehicle::setInvincible(%t,%h){return Player::setInvincible(%t,%h);}
function hoverVehicle::setShield(%t,%h){return Player::setShield(%t,%h);}
function hoverVehicle::addHealth(%t,%h){return Player::addHealth(%t,%h);}
function hoverVehicle::addShield(%t,%h){return Player::addShield(%t,%h);}
function hoverVehicle::subHealth(%t,%h){return Player::subHealth(%t,%h);}
function hoverVehicle::subShield(%t,%h){return Player::subShield(%t,%h);}
function hoverVehicle::getHealth(%t){return Player::getHealth(%t);}
function hoverVehicle::getMaxHealth(%t){return Player::getMaxHealth(%t);}
function hoverVehicle::isInvincible(%t){return Player::isInvincible(%t);}
function hoverVehicle::getShield(%t){return Player::getShield(%t);}

function serverCanDamage( %x, %y )
{
	return true;
}