About this mod
LOOK AT THE VIDEO INSIDE! Summon the infamous Void Sword no matter where you are. Use the action button with the sword equiped to summon a portal, and hold trigger to set the blade on purple fire. If you hit an enemy or item in this state, it will be teleported to the portal.
- Permissions and credits
- Changelogs
- Donations
public class ItemVoidSword : MonoBehaviour
{
protected Item item;
private Player player = Player.local;
private Transform portalSpawn;
private GameObject portal;
public static GameObject portalInstance;
private ParticleSystem voidActiveFX;
private AudioSource voidActiveSFX;
private ParticleSystem portalSpawnFX;
private AudioSource portalSpawnSFX;
// private ParticleSystem portalFX;
//private AudioSource portalSFX;
public float spawnForce = 10f;
public bool alreadySpawned = false;
private static bool isPortalActive;
private bool isCharged = false;
protected void Awake()
{
item = this.GetComponent<Item>();
portalSpawn = item.definition.GetCustomReference("PortalSpawn");
portalSpawnFX = item.transform.Find("SpawnPortalFX").GetComponent<ParticleSystem>();
portalSpawnSFX = item.transform.Find("SpawnPortalSFX").GetComponent<AudioSource>();
voidActiveFX = item.transform.Find("SwordActiveFX").GetComponent<ParticleSystem>();
voidActiveSFX = item.transform.Find("SwordActiveSFX").GetComponent<AudioSource>();
portal = item.transform.Find("Portal").gameObject;
if (portalInstance == null)
{
portalInstance = Instantiate(portal);
portalInstance.SetActive(false);
isPortalActive = false;
}
portal.SetActive(false);
item.OnHeldActionEvent += OnVoidHeldAction;
item.OnCollisionEvent += OnVoidCollision;
Spawn(player.body.handRight);
Spawn(player.body.handLeft);
}
void Spawn(BodyHand hand)
{
if (hand.caster.currentSpell != null && hand.interactor.grabbedHandle == null && !alreadySpawned)
{
if (hand.caster.currentSpell.name == "VoidSwordSpell(Clone)")
{
if (Vector3.Distance(item.transform.position, hand.transform.position) < Vector3.Distance(item.transform.position, hand.GetOtherHand().transform.position))
{
GrabVoidSword(hand.interactor);
Destroy(hand.caster.currentSpell.gameObject, 1f);
}
}
}
}
void GrabVoidSword(Interactor interact)
{
interact.Grab(item.handles[0]);
interact.UnGrab(false);
interact.Grab(item.handles[0]);
alreadySpawned = true;
}
void OnVoidHeldAction(Interactor interactor, Handle handle, Interactable.Action action)
{
if (action == Interactable.Action.AlternateUseStop && !isPortalActive)
{
CreatePortal();
}
else if (action == Interactable.Action.AlternateUseStop && isPortalActive)
{
DestroyPortal();
}
if (action == Interactable.Action.UseStart)
{
isCharged = true;
}
else
{
isCharged = false;
}
}
void OnVoidCollision(ref CollisionStruct collisionInstance)
{
bool wasDead = false;
if (isCharged && isPortalActive)
{
if (collisionInstance.targetType == CollisionStruct.TargetType.NPC)
{
float distance = 100f;
Creature closestNPC = null;
foreach (Creature npc in Creature.list)
{
if(npc != null)
{
if (npc != Creature.player)
{
if (distance > Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawn.position))
{
distance = Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawn.position);
closestNPC = npc;
}
}
}
}
if (closestNPC != null)
{
if (closestNPC.state == Creature.State.Dead)
{
wasDead = true;
}
TeleportFX(closestNPC.transform);
closestNPC.ragdoll.SetState(BS.Ragdoll.State.Alive);
closestNPC.transform.position = portalInstance.transform.position;
closestNPC.ragdoll.SetState(BS.Ragdoll.State.Fallen);
foreach (RagdollPart part in closestNPC.ragdoll.parts)
{
part.rb.AddForce(portalInstance.transform.forward * spawnForce, ForceMode.Impulse);
}
if (wasDead)
{
closestNPC.ragdoll.SetState(BS.Ragdoll.State.Dead);
}
}
}
if (collisionInstance.otherInteractiveObject != null)
{
if(collisionInstance.otherInteractiveObject.data.id != "VoidSword" && collisionInstance.otherInteractiveObject.data.id != "Hand")
{
if (collisionInstance.otherInteractiveObject.handlers.Count == 1)
{
collisionInstance.otherInteractiveObject.handlers[0].UnGrab(true);
}
TeleportFX(collisionInstance.otherInteractiveObject.transform);
collisionInstance.otherInteractiveObject.transform.position = portalInstance.transform.position;
collisionInstance.otherInteractiveObject.rb.AddForce(portalInstance.transform.forward * spawnForce, ForceMode.VelocityChange);
}
}
}
}
void FixedUpdate()
{
if (isCharged)
{
PlayActiveFX();
}
else
{
StopActiveFX();
}
//NPCDebugging();
StayOnTheGroundGodDammit();
if (isPortalActive)
{
SpinPortal(portalInstance.transform);
}
}
void CreatePortal()
{
portalInstance.SetActive(true);
portalInstance.transform.position = portalSpawn.position;
portalInstance.transform.rotation = portalSpawn.rotation;
isPortalActive = true;
PortalFX();
}
void SpinPortal(Transform portal)
{
portal.Rotate(0f, 0f, -0.75f);
}
void DestroyPortal()
{
portalInstance.SetActive(false);
isPortalActive = false;
}
void PlayActiveFX()
{
if (!voidActiveFX.isPlaying)
{
voidActiveFX.Play();
}
if (!voidActiveSFX.isPlaying)
{
voidActiveSFX.Play();
}
}
void PortalFX()
{
portalSpawnFX.transform.localScale = Vector3.one;
Debug.Log("Portal FX method called");
if(portalSpawnFX == null)
{
portalSpawnFX = item.transform.Find("SpawnPortalFX").GetComponent<ParticleSystem>();
}
Debug.Log("FX set to play");
portalSpawnFX.Stop();
portalSpawnFX.Play();
if (portalSpawnSFX == null)
{
portalSpawnSFX = item.transform.Find("SpawnPortalSFX").GetComponent<AudioSource>();
}
portalSpawnSFX.Stop();
portalSpawnSFX.Play();
}
void TeleportFX(Transform trans)
{
GameObject portalFX = Instantiate(portalSpawnFX.gameObject, trans.position, trans.rotation);
Destroy(portalFX, 2f);
portalSpawnFX.transform.localScale = Vector3.one * 0.5f;
portalSpawnFX.Play();
}
void StopActiveFX()
{
voidActiveFX.Stop();
voidActiveSFX.Stop();
}
void CollisionDebugging(ref CollisionStruct collisionInstance)
{
Debug.Log("---------------------NEW COLLISION----------------------");
Debug.Log("Target Type of the collision: " + collisionInstance.targetType);
if (collisionInstance.otherCollisionData != null)
{
Debug.Log("otherCollisionData.id: " + collisionInstance.otherCollisionData.id);
Debug.Log("textureName: " + collisionInstance.otherCollisionData.textureName);
if (collisionInstance.otherCollisionData.collidedPhysicMaterials.Count > 0)
{
Debug.Log("Collided physics material: " + collisionInstance.otherCollisionData.collidedPhysicMaterials[0]);
}
else
{
Debug.Log("With no phyisical materials attached");
}
}
else
{
Debug.Log("No otherCollisionData");
}
if (collisionInstance.otherInteractiveObject != null)
{
Debug.Log("otherInteractiveObject.name: " + collisionInstance.otherInteractiveObject.name);
if (collisionInstance.otherInteractiveObject.handlers.Count > 0)
{
Debug.Log("with handler: " + collisionInstance.otherInteractiveObject.handlers[0].name);
}
else
{
Debug.Log("With no handler");
}
}
else
{
Debug.Log("No other Interactive object");
}
if (collisionInstance.targetCollider != null)
{
Debug.Log("targetCollider.name: " + collisionInstance.targetCollider.name);
Debug.Log("GameObject name: " + collisionInstance.targetCollider.gameObject.name);
if (collisionInstance.targetCollider.attachedRigidbody != null)
{
Debug.Log("Rigidbody GameObject name (only for Gameobjects with rigidbody): " + collisionInstance.targetCollider.attachedRigidbody.gameObject.name);
}
else
{
Debug.Log("With no rigidbody");
}
if (collisionInstance.targetCollider.GetComponentInParent<GameObject>() != null)
{
Debug.Log("Name of the parent GameObject: " + collisionInstance.targetCollider.GetComponentInParent<GameObject>().name);
}
else
{
Debug.Log("This collider has no parent");
}
}
else
{
Debug.Log("No targetCollider");
}
if (collisionInstance.targetColliderGroup != null)
{
Debug.Log("targetColliderGroup.name: " + collisionInstance.targetColliderGroup.name);
}
else
{
Debug.Log("No targetColliderGroup");
}
if (collisionInstance.damageStruct.hitInteractiveObject != null)
{
Debug.Log("hitInteractiveObject name: " + collisionInstance.damageStruct.hitInteractiveObject.name);
}
else
{
Debug.Log("No hitInteractiveObject");
}
Debug.Log("----------------- END OF THE COLLISION -------------------");
}
void NPCDebugging()
{
foreach (Creature npc in Creature.list)
{
if (npc.state == Creature.State.Alive)
{
//Verde
if (npc.ragdoll.state == BS.Ragdoll.State.Alive)
{
SetNPCColor(npc, Color.green);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Fallen)
{
SetNPCColor(npc, Color.yellow);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Dead)
{
SetNPCColor(npc, Color.cyan);
}
else
{
Debug.Log("Error: Alive NPC has no Ragdoll state");
}
}
else if (npc.state == Creature.State.KnockedOut)
{
if (npc.ragdoll.state == BS.Ragdoll.State.Alive)
{
SetNPCColor(npc, Color.blue);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Fallen)
{
SetNPCColor(npc, Color.red);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Dead)
{
SetNPCColor(npc, Color.gray);
}
else
{
Debug.Log("Error: KnockedOut NPC has no Ragdoll state");
}
}
else if (npc.state == Creature.State.Dead)
{
if (npc.ragdoll.state == BS.Ragdoll.State.Alive)
{
SetNPCColor(npc, Color.white);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Fallen)
{
SetNPCColor(npc, Color.clear);
}
else if (npc.ragdoll.state == BS.Ragdoll.State.Dead)
{
SetNPCColor(npc, Color.black);
}
else
{
Debug.Log("Error: Dead NPC has no Ragdoll state");
}
}
}
}
void SetNPCColor(Creature npc, Color color)
{
foreach (Material mat in npc.bodyMeshRenderer.materials)
{
mat.color = color;
}
}
void NPCDebugging2()
{
float distance = 10000f;
Creature closestNPC = null;
foreach (Creature npc in Creature.list)
{
SetNPCColor(npc, Color.red);
if (npc != Creature.player)
{
if (distance > Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawn.position))
{
distance = Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawn.position);
closestNPC = npc;
SetNPCColor(npc, Color.yellow);
}
SetNPCColor(closestNPC, Color.green);
}
}
}
void StayOnTheGroundGodDammit()
{
foreach (Creature npc in Creature.list)
{
if(npc != null && npc.ragdoll != null && npc != Creature.player)
{
if (npc.ragdoll.isGrounded && npc.state == Creature.State.Dead)
{
npc.ragdoll.state = BS.Ragdoll.State.Dead;
npc.ragdoll.isGrounded = false;
}
}
}
}
}