A trigger zone component that simulates a sticky tar area. It tints model renderers of objects that enter, restores tint on exit, and slows physics rigidbodies and character controllers while inside.
using Sandbox;
using System.Collections.Generic;
public sealed class StickyTarZone : Component, Component.ITriggerListener
{
[Property] public float SpeedMultiplier { get; set; } = 0.4f;
[Property] public float RigidbodyDrag { get; set; } = 0.85f;
[Property] public Color TarTint { get; set; } = new Color( 0.1f, 0.1f, 0.1f, 1f );
private readonly HashSet<GameObject> _insideObjects = new();
private readonly Dictionary<ModelRenderer, Color> _originalColors = new();
public void OnTriggerEnter( Collider other )
{
if ( !other.GameObject.IsValid() ) return;
var rootObj = other.GameObject.Root;
_insideObjects.Add( rootObj );
var renderers = rootObj.Components.GetAll<ModelRenderer>();
foreach ( var mr in renderers )
{
if ( mr.IsValid() && !_originalColors.ContainsKey( mr ) )
{
_originalColors[mr] = mr.Tint;
mr.Tint = TarTint;
}
}
}
public void OnTriggerExit( Collider other )
{
if ( !other.GameObject.IsValid() ) return;
var rootObj = other.GameObject.Root;
_insideObjects.Remove( rootObj );
var renderers = rootObj.Components.GetAll<ModelRenderer>();
foreach ( var mr in renderers )
{
if ( mr.IsValid() && _originalColors.TryGetValue( mr, out var origColor ) )
{
mr.Tint = origColor;
_originalColors.Remove( mr );
}
}
}
protected override void OnFixedUpdate()
{
_insideObjects.RemoveWhere( obj => !obj.IsValid() );
foreach ( var targetObj in _insideObjects )
{
var rb = targetObj.Components.Get<Rigidbody>();
if ( rb.IsValid() && rb.PhysicsBody.IsValid() )
{
rb.PhysicsBody.Velocity *= 0.5f; // Замедление в смоле
}
var cc = targetObj.Components.Get<CharacterController>();
if ( cc.IsValid() )
{
cc.Velocity *= SpeedMultiplier;
}
}
}
}