炸弹虫 (U6)

炸弹虫 (U6)

已为U7更新!孤身一人上路很危险,带上这个吧!来自《塞尔达传说》的炸弹虫,将它放置在地面上,它会移动直到撞上敌人,并自动追踪目标。然后爆炸。你可以在“陷阱”分类中找到它。

武器

public class ItemBombchu : MonoBehaviour { protected Item item; private Transform bombchuTransform; private ParticleSystem explosionEffect; private MeshRenderer mesh; private Transform targetTransform = null; private AudioSource explosionSFX; private AudioSource startRunningSFX; private AudioSource runningSFX; private float timeOut = 1f; private float timerBombchu = 0f; private bool hasExploded = false; private bool isBombchuActive = false; private bool bombchuRunning = false; private bool hasTarget = false; private bool bombchuTurn = false; private float distNPC = 0f; private float expReductor = 0f; private Vector3 expForceDirection; private float detectionBubble = 20f; private float distanceToTarget = 0f; private float angleToTarget = 0f; private Vector3 vectorBombchuToTarget; private Creature nearestTarget; public float explosionRadius = 5f; public float expForceMultiplier = 50f; public float rotationSpeed = 0.2f;

protected void Awake()
{
    item = this.GetComponent<Item>();
    mesh = item.GetComponentInChildren<MeshRenderer>();
    bombchuTransform = item.transform;
    explosionEffect = item.GetComponentInChildren<ParticleSystem>();
    explosionSFX = item.transform.Find("ExplosionSFX").GetComponent<AudioSource>();
    startRunningSFX = item.transform.Find("StartRunningSFX").GetComponent<AudioSource>();
    runningSFX = item.transform.Find("RunningSFX").GetComponent<AudioSource>();
    item.OnCollisionEvent += OnBombchuCollisionEvent;
    item.OnGrabEvent += OnBombchuGrabEvent;
    item.OnTeleGrabEvent += OnBombchuTeleGrab;
    item.OnUngrabEvent += OnBombchuUngrabEvent;
    foreach (Collider col in item.GetComponentsInChildren<Collider>())
    {
        col.material.frictionCombine = 0f;
        col.material.dynamicFriction = 0f;
        col.material.staticFriction = 0f;
    }
}

void OnBombchuCollisionEvent(ref CollisionStruct collisionInstance)
{
    if (collisionInstance.targetType == CollisionStruct.TargetType.NPC && isBombchuActive)
    {
        Explode(explosionRadius);
        item.enabled = false;
        mesh.enabled = false;
        hasExploded = true;
    }
    if (isBombchuActive && !bombchuRunning)
    {
        bombchuRunning = true;
        startRunningSFX.Play();
    }
}

void OnBombchuTeleGrab(Handle handle, Telekinesis teleGrabber)
{
    DeactivateBombchu();
}

void OnBombchuGrabEvent(Handle handle, Interactor interactor)
{
    DeactivateBombchu();
}

void OnBombchuUngrabEvent(Handle handle, Interactor interactor, bool thrown)
{
    isBombchuActive = true;
}

void FixedUpdate()
{
    if (bombchuRunning)
    {
        BombchuRunning();
    }
    if (hasExploded)
    {
        timerBombchu += Time.deltaTime;
    }
    if (timerBombchu > timeOut)
    {
        item.Despawn();
    }
}

void DeactivateBombchu()
{
    bombchuRunning = false;
    isBombchuActive = false;
    runningSFX.Stop();
    RemoveTarget();
}

void Explode(float radius)
{
    ExplosionEffect();
    foreach (Creature npc in Creature.List)
    {
        if (npc != Player)
        {
            distNPC = Vector3.Distance(npc.gameObject.transform.position, bombchuTransform.position);
            if (distNPC < radius)
            {
                expReductor = (radius - distNPC) / radius;
                expForceDirection = npc.gameObject.transform.position - bombchuTransform.position;
                expForceDirection.Normalize();
                expForceDirection += Vector3.up;
                expForceDirection.Normalize();
                if (npc.state != Creature.State.Dead)
                {
                    npc.ragdoll.SetState(BS.Ragdoll.State.Fallen);
                }
                foreach (RagdollPart ragdollPart in npc.ragdoll.parts)
                {
                    ragdollPart.rb.AddForce(expForceDirection * expForceMultiplier * expReductor, ForceMode.Impulse);
                }
                npc.health.Kill();
            }
        }
    }
}

void BombchuRunning()
{
    item.rb.AddForce(bombchuTransform.forward * 10f, ForceMode.Force);
    if (!startRunningSFX.isPlaying && !runningSFX.isPlaying && !hasExploded)
    {
        runningSFX.Play();
    }
    if (!hasTarget)
    {
        SetTarget();
    }
    if (hasTarget && (targetTransform != null))
    {
        distanceToTarget = Vector3.Distance(bombchuTransform.position, targetTransform.position);
        if (distanceToTarget <= detectionBubble)
        {
            bombchuTurn = true;
        }
        else
        {
            bombchuTurn = false;
            RemoveTarget();
        }
    }
    if (bombchuTurn)
    {
        Turn();
    }
}

void ExplosionEffect()
{
    runningSFX.Stop();
    explosionEffect.Play();
    explosionSFX.Play();
}

void SetTarget()
{
    foreach (Creature target in Creature.List)
    {
        if (target != Player)
        {
            if (target.state != Creature.State.Dead)
            {
                if (Vector3.Distance(bombchuTransform.position, target.transform.position) < detectionBubble)
                {
                    vectorBombchuToTarget = target.transform.position - bombchuTransform.position;
                    vectorBombchuToTarget.y = 0f;
                    angleToTarget = Vector3.Angle(bombchuTransform.forward, vectorBombchuToTarget);
                    if (angleToTarget < 90f)
                    {
                        nearestTarget = target;
                    }
                }
            }
        }
    }
    if (nearestTarget != null)
    {
        targetTransform = nearestTarget.transform;
        hasTarget = true;
    }
}

void RemoveTarget()
{
    targetTransform = null;
    nearestTarget = null;
    hasTarget = false;
    angleToTarget = 0f;
    bombchuTurn = false;
}

void Turn()
{
    vectorBombchuToTarget = targetTransform.position - bombchuTransform.position;
    vectorBombchuToTarget.y = 0f;
    angleToTarget = Vector3.SignedAngle(bombchuTransform.forward, vectorBombchuToTarget, bombchuTransform.up);
    if (angleToTarget > 3f)
    {
        item.transform.Rotate(bombchuTransform.up, rotationSpeed);
    }
    else if (angleToTarget < -3f)
    {
        item.transform.Rotate(bombchuTransform.up, -1 * rotationSpeed);
    }
}

}