things/enemies/Tree.cs

Enemy subclass Tree, defines a stationary, non-attacking tree enemy with specific stats, loot/gib behavior, and simple physics damping. It customizes spawn scale, health, gib assets, and spawns particle effects and randomized gibs on death.

File Access
using System;
using Sandbox;

public class Tree : Enemy
{
	public override EnemyType EnemyType => EnemyType.Tree;
	public override float GetMaxHealth()
	{
		return 100f;
	}

	public override Vector3 SpawnScale => new Vector3( 1.2f );
	public override bool CanHaveTarget => false;
	public override bool CanAttack => false;
	public override bool CanTurn => false;
	public override bool CanBeBackstabbed => false;
	public override bool CountsAsKill => false;
	public override bool CanMove => false;
	public override bool CanBeTargeted => false;
	public override bool CanBeStunned => false;
		 

	public override string GibFolder => "wood";
	public override float OverrideGibChance => 1f;
	public override float HealthPackChanceMultiplier => 4f;

	public override float ParticleYPosOverride => 0.65f;

	protected override void OnStart()
	{
		base.OnStart();

		CoinValueMin = 1;
		CoinValueMax = 2;
		CoinChance = 0.75f;

		PushStrength = 20000f;
		Weight = 8f;

		if ( IsProxy )
			return;

		Deceleration = 4.5f;
	}

	protected override void OnUpdate()
	{
		base.OnUpdate();

		//Gizmo.Draw.Color = Color.White;
		//Gizmo.Draw.Text( $"{Health}", new global::Transform( WorldPosition ) );

		if ( IsProxy || IsDying || IsSpawning )
			return;

		Velocity *= Math.Max( 1f - Time.Delta * Deceleration * Manager.Instance.GlobalFrictionModifier, 0f );

		WorldPosition += (Vector3)Velocity * Time.Delta;
	}

	public override void Flinch( float time, Vector2 dir )
	{
		base.Flinch( time, dir );

		ModelRenderer.LocalRotation = new Angles( Game.Random.Float( -3f, 3f ), 0f, Game.Random.Float( -3f, 3f ) );
	}

	public override void StopFlinching()
	{
		base.StopFlinching();

		ModelRenderer.LocalRotation = new Angles( 0f, 0f, 0f );
	}

	protected override void HandleAnimation()
	{

	}
	public override void SetAnim( string name, bool forceRestart = false )
	{
		
	}

	protected override void DropLoot( Player player )
	{
		base.DropLoot( player );
		//Barrel.DropLoot( player, Position2D );	
	}

	//protected override void ResetMaterial()
	//{
	//	ModelRenderer.ClearMaterialOverrides();
	//	ModelRenderer.RenderType = Sandbox.ModelRenderer.ShadowRenderType.On;
	//}

	protected override void SpawnGibs( Vector2 dir, float force, DamageType damageType )
	{
		//GameObject.Clone( "prefabs/effects/tree_debris.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( WorldPosition.WithZ( Game.Random.Float( 40f, 60f ) ), Rotation.Identity ) } );

		GameObject.Clone( $"prefabs/effects/dark_cloud_explosion.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( WorldPosition.WithZ( Game.Random.Float( 20f, 40f ) ), Rotation.Identity ) } );
		GameObject.Clone( $"prefabs/effects/dark_cloud_explosion.prefab", new CloneConfig { StartEnabled = true, Transform = new Transform( WorldPosition.WithZ( Game.Random.Float( 110f, 125f ) ), Rotation.Identity ) } );

		SpawnGibs( "fragment", Game.Random.Int( 4, 8 ), force, damageType );
		SpawnGibs( "fragment_2", Game.Random.Int( 4, 8 ), force, damageType );
		SpawnGibs( "fragment_3", Game.Random.Int( 4, 8 ), force, damageType );
	}

	void SpawnGibs( string name, int count, float force, DamageType damageType )
	{
		for ( int i = 0; i < count; i++ )
		{
			var color = Color.Lerp( TintFullHp, TintZeroHp, Game.Random.Float( 0.25f, 1f ) );
			color = Color.Lerp( color, Color.Black, Game.Random.Float( 0.3f, 0.7f ) );

			SpawnGoreGib(
				$"{GibFolder}/{name}",
				localPos: new Vector3( Game.Random.Float( -10f, 10f ), Game.Random.Float( -10f, 10f ), Game.Random.Float( 20f, 65f ) ) + Vector3.Random * Game.Random.Float( 0f, 30f ),
				localRot: Rotation.Random,
				scaleMultiplier: Game.Random.Float( 1f, 1.5f ),
				dir: Vector3.Random,
				force: Game.Random.Float( 0.25f, 3f ),
				color,
				damageType
			);
		}
	}
}