About this mod
It's dangerous to go alone, take this! Link's hookshot from The Legend of Zelda. Press trigger to fire it, and when the hook makes contact with a surface, you'll be launched towards it. Thanks to Drags for the new texture!
- Permissions and credits
- Changelogs
- Donations
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 chainGO;
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("Available levels: ");
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("SpawnPoint");
chainSpawnTransform = item.definition.GetCustomReference("ChainSpawnPoint");
ringChainsTransform1 = meshTransform.Find("Ringchain1");
ringChainsTransform2 = meshTransform.Find("Ringchain2");
ringChainsTransform3 = meshTransform.Find("Ringchain3");
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.NPC) && (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 throwing)
{
}
void FixedUpdate()
{
/*Debug.Log("Let's see the state of the player: ");
Debug.Log("Kinematic? " + Creature.player.locomotion.rb.isKinematic);
Debug.Log("Climber? "+Creature.player.climber.enabled);
Debug.Log("Ragdoll state? "+Creature.player.ragdoll.state);
Debug.Log("Creature stance? "+Creature.player.stance);
Debug.Log("Is hanging? " + Creature.player.body.isHanging);
Debug.Log("Is grounded? " + Creature.player.ragdoll.isGrounded);
Debug.Log("Use physics? "+Creature.player.ragdoll.usePhysic);*/
if (hookshotGoing)
{
if (item.rb.isKinematic)
{
item.rb.isKinematic = false;
}
if (!hasFreezePosition)
{
SetFreezeHookshot();
hasFreezePosition = true;
}
Spin(ringChainSpinSpeed);
HookShoot(hookshotSpeed);
FreezeHookshot();
}
if (hookshotReturning)
{
if (!landedOnTerrain && hasFreezePosition)
{
FreezeHookshot();
}
Spin(-1*returnSpeedMultiplier*ringChainSpinSpeed);
HookshotReturn();
}
if (landedOnTerrain)
{
GoingToTarget(hookshotSpeed*returnSpeedMultiplier);
}
}
void Spin(float speed)
{
ringChainsTransform1.Rotate(Vector3.up, speed);
ringChainsTransform2.Rotate(Vector3.up, speed);
ringChainsTransform3.Rotate(Vector3.up, speed);
}
void HookShoot(float speed)
{
Instantiate(chainGO, 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)
{
HookShoot(-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 GoingToTarget(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;
}
}