Need gibs in Prop OnBreak

Started by Gamer 1 post 34 views

Reply on sbox.game
  1. #1
    Gamer
    I need to get the gibs from the prop OnBreak event to do things like apply the velocity of the parent to them. 
     
    Currently I cannot figure out how to do this in a sensible way. 
    The callback is invoked before they are created. 
    	void OnBreak()
    	{
    		OnPropBreak?.Invoke();
    
    		PlayBreakSound();
    
    		NetworkCreateGibs();
    
    		CreateExplosion();
    	}
    

    NetworkCreateGibs() does not return the list of gibs so I think that there is probably something I'm missing or a way to get the gibs from a network event? 

    I ended up writing some really hacky code to find them like this async function to wait one frame. 

    	async void ApplyImpulseToGibs(GameObject obj, Vector3 point, Vector3 impulse) 
    	{
    		var scene = Scene;
    		var prop = obj.GetComponentInParent<Prop>();
    		if ( !prop.IsValid() ) return;
    
    		var objectName = obj.Name;
    		var gibName = $"{objectName} (gib)";
    
    		var wait = TaskSource.Create();
    		try
    		{
    			await wait.Frame();
    		}
    		catch ( TaskCanceledException )
    		{
    			return;
    		}
    
    		if ( !scene.IsValid() )
    			return;
    
    		var gibs = scene.GetAllComponents<Gib>();
    		foreach ( var gib in gibs )
    		{
    			if ( !gib.IsValid() || gib.GameObject.Name != gibName )
    				continue;
    
    			var rb = gib.GetComponent<Rigidbody>();
    			if ( rb.IsValid() ) {
    				rb.ApplyImpulseAt(point, impulse);
    			}
    		}
    	}
    

    Or this component that fudges the prop health and handles the events manual. 


    public sealed class Gibbable : Component, Component.IDamageable, IDestructible
    {
    	[Property] public float Health { get; set; } = 100f;
    	[Property] public Prop Prop { get; private set; }
    
    	protected override void OnStart()
    	{
    		Prop ??= GetComponent<Prop>();
    		if ( Prop.IsValid() )
    			Prop.Health = 1_000_000f;   // Prop never auto-breaks
    	}
    
    	public void OnDamage( in DamageInfo damage )
    	{
    		Health -= damage.Damage;
    		Prop.Health += damage.Damage;
    		if ( Health <= 0f )
    			Break( damage.Position, (damage.Position - Transform.World.Position).Normal * 1200f );
    	}
    
    	public void TakeImpact( GameObject hitObject, Vector3 point, Vector3 impulse, float damage_scale )
    	{
    		if ( hitObject != GameObject ) return;
    
    		Health -= impulse.Length * damage_scale;
    
    		if ( Health <= 0f )
    			Break( point, impulse );
    	}
    
    	private void Break( Vector3 point, Vector3 impulse )
    	{
    		if ( !Prop.IsValid() ) return;
    
    		var gibs = Prop.CreateGibs();
    		Prop.NetworkCreateGibs();
    
    		foreach ( var gib in gibs )
    		{
    			if ( !gib.IsValid() ) continue;
    			var rb = gib.GetComponent<Rigidbody>();
    			if ( rb.IsValid() )
    				rb.ApplyImpulseAt( point, impulse );
    		}
    
    		GameObject.Destroy();
    	}
    }

    In conclusion how do I get the gibs from a prop that breaks.

    Any help is appreciated.