About this mod
LOOK AT THE VIDEO INSIDE! Hornet's Needle from Hollow Knight. Thrown it and a string of silk will attach to your hand, making the Needle return to you no matter how far away you throw it. it also auto-destucks from enemies.
- Permissions and credits
- Changelogs
Here's the code:
public class ItemHornetNeedle : MonoBehaviour
{
protected Item item;
private Transform needleTransform;
private Transform silkSpawnTransform;
private Transform handTransform;
private Transform meshTransform;
private GameObject silk;
private GameObject silkClone;
private Interactor throwingHand;
private Vector3 returnDirection;
private bool isReturning = false;
private bool wasThrown = false;
private bool justThrown = true;
public float returnSpeed = 15f;
public float returningBubble = 0.5f;
public float maxSpeed = 15f;
public float stuckMultiplier = 1f;
public float stuckMultiplierValue = 20f;
public float silkSize = 1f;
public float initialSize;
protected void Awake()
{
item = this.GetComponent<Item>();
needleTransform = item.transform;
silkSpawnTransform = item.definition.GetCustomReference("SilkSpawnTransform");
silk = needleTransform.Find("Silk").gameObject;
Debug.Log(silk.name);
meshTransform = needleTransform.Find("Mesh");
item.OnCollisionEvent += OnNeedleCollisionEvent;
item.OnGrabEvent += OnNeedleGrabEvent;
item.OnTeleGrabEvent += OnNeedleTeleGrab;
item.OnUngrabEvent += OnNeedleUngrabEvent;
}
void OnNeedleCollisionEvent(ref CollisionStruct collisionInstance)
{
}
void OnNeedleTeleGrab(Handle handle, Telekinesis teleGrabber)
{
isReturning = false;
}
void OnNeedleGrabEvent(Handle handle, Interactor interactor)
{
Reset();
}
void OnNeedleUngrabEvent(Handle handle, Interactor interactor, bool throwing)
{
handTransform = interactor.transform;
throwingHand = interactor;
item.rb.useGravity = false;
item.rb.freezeRotation = true;
}
void FixedUpdate()
{
if (item.isFlying && justThrown)
{
wasThrown = true;
justThrown = false;
silkClone = Instantiate(silk, silkSpawnTransform.position, silkSpawnTransform.rotation, meshTransform);
initialSize = silkClone.transform.localScale.y;
Debug.Log("Initial size: " + initialSize);
}else if(!item.isFlying && justThrown && wasThrown)
{
item.rb.useGravity = true;
}
if (wasThrown)
{
silkSize = Vector3.Distance(needleTransform.position, handTransform.position)*100f;
silkClone.transform.localScale = new Vector3(silkClone.transform.localScale.x, silkClone.transform.localScale.y, silkSize * initialSize);
Debug.Log("Recalculated size: " + silkSize * initialSize);
}
if (item.isPenetrating && isReturning)
{
Invoke("Destuck", 0.5f);
}
else
{
stuckMultiplier = 1f;
}
if (isReturning)
{
Returning();
}
if (wasThrown)
{
SetRotation();
}
if (item.rb.velocity.magnitude <= 3f && !isReturning && wasThrown)
{
isReturning = true;
item.isFlying = false;
}
}
void StartReturning()
{
isReturning = true;
}
void Returning()
{
returnDirection = handTransform.position - needleTransform.position;
returnDirection.Normalize();
needleTransform.LookAt(handTransform);
if (item.rb.velocity.magnitude < maxSpeed)
{
item.rb.AddForce(returnDirection * returnSpeed* stuckMultiplier, ForceMode.Force);
}
needleTransform.LookAt(handTransform);
if (Vector3.Distance(needleTransform.position, handTransform.position) <= returningBubble)
{
if(throwingHand.grabbedHandle == null)
{
throwingHand.Grab(item.handles[0]);
}
else
{
Reset();
}
}
}
void SetRotation()
{
needleTransform.LookAt(handTransform);
}
void Reset()
{
item.rb.useGravity = true;
isReturning = false;
wasThrown = false;
item.rb.freezeRotation = false;
justThrown = true;
Destroy(silkClone);
}
void Destuck()
{
stuckMultiplier = stuckMultiplierValue;
}
}