塞尔达传说之钩索 (U8.2)

塞尔达传说之钩索 (U8.2)

独自前行太危险了,带上这个吧!来自《塞尔达传说》中林克的钩爪枪。按下扳机发射,当钩爪触碰到表面时,你会被弹射向目标。感谢Drags提供的新纹理!

武器

以下是代码(旧版,已失效):

public class ItemHookshot : MonoBehaviour
{
    protected Item item;
    private Transform hookshotTransform;
    public static bool frozenHookshots = false;
    private Transform meshTransform;
    private Transform spearMeshTransform;
    private Transform headCollider;
    private Transform audio;
    private Transform spawnTransform;
    private Transform chainSpawnTransform;
    private GameObject chainGameObject;
    private Transform ringChainsTransform1;
    private Transform ringChainsTransform2;
    private Transform ringChainsTransform3;
    private Vector3 hookshotNewPosition;
    private Vector3 hookshotFreezePosition;
    private Quaternion hookshotFreezeRotation;
    private float ringChainSpinSpeed = 2f;
    public float hookshotSpeed = 0.07f;
    public float returnSpeedMultiplier = 1.25f;
    private bool hookshotGoing = false;
    private bool hookshotReturning = false;
    private bool landedOnTerrain = false;
    private bool hasFreezePosition = false;
    AudioSource hookInActionSFX;
    AudioSource hookHitSFX;

    protected void Awake()
    {
        Debug.Log("可用关卡:");
        Debug.Log(GameManager.GetAvailableLevels());

        item = this.GetComponent<Item>();
        hookshotTransform = item.transform;
        meshTransform = hookshotTransform.Find("Mesh");
        spearMeshTransform = hookshotTransform.Find("HeadMesh");
        chainGO = spearMeshTransform.Find("Chain").gameObject;
        headCollider = hookshotTransform.Find("HeadColliders");
        spawnTransform = item.definition.GetCustomReference("生成点");
        chainSpawnTransform = item.definition.GetCustomReference("ChainSpawnPoint");
        ringChainsTransform1 = meshTransform.Find("Ringchain1");
        ringChainsTransform2 = meshTransform.Find("环链2");
        ringChainsTransform3 = meshTransform.Find("环链3");
        Audio = hookshotTransform.Find("Audio");
        hookInActionSFX = Audio.Find("FireVFX").GetComponent<AudioSource>();
        hookHitSFX = Audio.Find("TargetVFX").GetComponent<AudioSource>();

        item.OnCollisionEvent += OnHookshotCollisionEvent;
        item.OnGrabEvent += OnHookshotGrabEvent;
        item.OnTeleGrabEvent += OnHookshotTeleGrab;
        item.OnUngrabEvent += OnHookshotUngrabEvent;
        item.OnHeldActionEvent += OnHookshotHeldAction;
    }

    void OnHookshotHeldAction(Interactor interactor, Handle handle, Interactable.Action action)
    {
        if (!landedOnTerrain)
        {
            if (action == Interactable.Action.UseStart)
            {
                hookshotGoing = true;
            }
            if (action == Interactable.Action.UseStop)
            {
                hookshotGoing = false;
                hookshotReturning = true;
            }
        }
    }

    void OnHookshotCollisionEvent(ref CollisionStruct collisionInstance)
    {
        if ((collisionInstance.targetType != CollisionStruct.TargetType.NonPlayerCharacter) && (collisionInstance.targetType != CollisionStruct.TargetType.Avatar))
        {
            if (hookshotGoing)
            {
                Creature.player.GetHeldobject(Side.Left).rb.isKinematic = false;
                Creature.player.GetHeldobject(Side.Right).rb.isKinematic = false;
                hookHitSFX.Play();
                hasFreezePosition = false;
                item.rb.isKinematic = true;
                landedOnTerrain = true;
                hookshotReturning = true;
                hookshotGoing = false;
                PlayerControl.local.Jump(Side.Right, true);
            }
        }
    }

    void OnHookshotTeleGrab(Handle handle, Telekinesis teleGrabber)
    {
    }

    void OnHookshotGrabEvent(Handle handle, Interactor interactor)
    {
    }

    void OnHookshotUngrabEvent(Handle handle, Interactor interactor, bool thrown)
    {
    }

    void FixedUpdate()
    {
        /*Debug.Log("让我们看看玩家的状态:");
        Debug.Log("运动学状态? " + Creature.player.locomotion.rb.isKinematic);
        Debug.Log("攀爬者? "+Creature.player.climber.enabled);
        Debug.Log("布娃娃状态?"+Creature.player.ragdoll.state);
        Debug.Log("生物姿态? "+Creature.player.stance);
        Debug.Log("是否悬挂? " + Creature.player.body.isHanging);
        Debug.Log("是否着地?" + Creature.player.ragdoll.isGrounded);
        Debug.Log("是否使用物理? "+Creature.player.ragdoll.usePhysic);*/

        if (hookshotGoing)
        {
            if (item.rb.isKinematic)
            {
                item.rb.isKinematic = false;
            }
            if (!hasFreezePosition)
            {
                SetFreezeHookshot();
                hasFreezePosition = true;
            }
            Spin(ringChainSpinSpeed);
            HookshotShoot(hookshotSpeed);
            FreezeHookshot();
        }

        if (hookshotReturning)
        {
            if (!landedOnTerrain && hasFreezePosition)
            {
                FreezeHookshot();
            }
            Spin(-1 * returnSpeedMultiplier * ringChainSpinSpeed);
            HookshotReturn();
        }

        if (landedOnTerrain)
        {
            GoToTarget(hookshotSpeed * returnSpeedMultiplier);
        }
    }

    void Spin(float speed)
    {
        ringChainsTransform1.Rotate(Vector3.up, speed);
        ringChainsTransform2.Rotate(Vector3.up, speed);
        ringChainsTransform3.Rotate(Vector3.up, speed);
    }

    void HookshotShoot(float speed)
    {
        Instantiate(chainGameObject, chainSpawnTransform.position, chainSpawnTransform.rotation, spearMeshTransform);
        hookshotNewPosition = spawnTransform.position - hookshotTransform.position;
        hookshotNewPosition.Normalize();
        spearMeshTransform.position += hookshotNewPosition * speed;
        headCollider.position += hookshotNewPosition * speed;
        if (!hookInActionSFX.isPlaying)
        {
            hookInActionSFX.Play();
        }
    }

    void HookshotReturn()
    {
        if (Vector3.Distance(spearMeshTransform.position, spawnTransform.position) > 0.1f)
        {
            HookshotShoot(-1 * returnSpeedMultiplier * hookshotSpeed);
            for (int i = 0; i < spearMeshTransform.childCount; i++)
            {
                if (spearMeshTransform.GetChild(i).name == "Chain(Clone)")
                {
                    if (Vector3.Distance(spearMeshTransform.GetChild(i).transform.position, chainSpawnTransform.position) < 0.1f)
                    {
                        Destroy(spearMeshTransform.GetChild(i).gameObject);
                    }
                }
            }
        }
        else
        {
            spearMeshTransform.position = spawnTransform.position;
            headCollider.position = spawnTransform.position;
            hookshotReturning = false;
            hasFreezePosition = false;
            hookInActionSFX.Stop();
            if (!landedOnTerrain)
            {
                item.rb.isKinematic = false;
            }
            for (int i = 0; i < spearMeshTransform.childCount; i++)
            {
                if (spearMeshTransform.GetChild(i).name == "Chain(Clone)")
                {
                    Destroy(spearMeshTransform.GetChild(i).gameObject);
                }
            }
            landedOnTerrain = false;
        }
    }

    void GoToTarget(float speed)
    {
        hookshotNewPosition = spawnTransform.position - hookshotTransform.position;
        hookshotNewPosition.Normalize();
        hookshotTransform.position += hookshotNewPosition * speed;
    }

    void SetFreezeHookshot()
    {
        hookshotFreezePosition = hookshotTransform.position;
        hookshotFreezeRotation = hookshotTransform.rotation;
    }

    void FreezeHookshot()
    {
        hookshotTransform.position = hookshotFreezePosition;
        hookshotTransform.rotation = hookshotFreezeRotation;
    }
}