虚空剑法术(U6)

虚空剑法术(U6)

快看里面的视频!无论身在何处,都能召唤那把臭名昭著的虚空之剑。装备剑后使用动作键即可召唤传送门,长按扳机键可使剑刃燃起紫色火焰。若在此状态下击中敌人或物品,

法术

public class VoidSwordItem : MonoBehaviour { protected Item item; private Player player = Player.local; private Transform portalSpawnPoint; 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.grabHandle == null && !alreadySpawned)
    {
        if (hand.caster.currentSpell.name == "VoidSwordSpell(Clone)")
        {
            if (Vector3.Distance(item.transform.position, hand.transform.position) < Vector3.Distance(item.transform.position, hand.otherHand().transform.position))
            {
                GrabVoidSword(hand.interactor);
                Destroy(hand.caster.currentSpell.gameObject, 1f);
            }
        }
    }
}

void GrabVoidSword(Interactor interact)
{
    interact.Grab(item.handle[0]);
    interact.UnGrab(false);
    interact.Grab(item.handle[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 != player)
                    {
                        if (distance > Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawnPoint.position))
                        {
                            distance = Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawnPoint.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)
    {
        PlayActiveEffects();
    }
    else
    {
        StopActiveEffects();
    }
    // NPCDebugging();
    StayOnGroundDammit();
    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 PlayActiveEffects()
{
    if (!voidActiveFX.isPlaying)
    {
        voidActiveFX.Play();
    }
    if (!voidActiveSFX.isPlaying)
    {
        voidActiveSFX.Play();
    }
}

void PortalFX()
{
    portalSpawnFX.transform.localScale = Vector3.one;
    Debug.Log("PortalFX method called");
    if (portalSpawnFX == null)
    {
        portalSpawnFX = item.transform.Find("SpawnPortalFX").GetComponent<ParticleSystem>();
    }
    Debug.Log("Effects 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 StopActiveEffects()
{
    voidActiveFX.Stop();
    voidActiveSFX.Stop();
}

void CollisionDebugging(ref CollisionStruct collisionInstance)
{
    Debug.Log("---------------------New Collision----------------------");
    Debug.Log("Collision target type: " + collisionInstance.targetType);
    if (collisionInstance.otherCollisionData != null)
    {
        Debug.Log("Other collision data ID: " + collisionInstance.otherCollisionData.id);
        Debug.Log("Texture name: " + collisionInstance.otherCollisionData.textureName);
        if (collisionInstance.otherCollisionData.collidedPhysicMaterials.Count > 0)
        {
            Debug.Log("Collided physic material: " + collisionInstance.otherCollisionData.collidedPhysicMaterials[0]);
        }
        else
        {
            Debug.Log("No physic material attached");
        }
    }
    else
    {
        Debug.Log("No other collision data");
    }
    if (collisionInstance.otherInteractiveObject != null)
    {
        Debug.Log("Other interactive object name: " + collisionInstance.otherInteractiveObject.name);
        if (collisionInstance.otherInteractiveObject.handlers.Count > 0)
        {
            Debug.Log("Has handler: " + collisionInstance.otherInteractiveObject.handlers[0].name);
        }
        else
        {
            Debug.Log("No handler");
        }
    }
    else
    {
        Debug.Log("No other interactive object");
    }
    if (collisionInstance.targetCollider != null)
    {
        Debug.Log("Target collider 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("No rigidbody");
        }
        if (collisionInstance.targetCollider.GetComponentInParent<GameObject>() != null)
        {
            Debug.Log("Parent gameobject name: " + collisionInstance.targetCollider.GetComponentInParent<GameObject>().name);
        }
        else
        {
            Debug.Log("No parent for this collider");
        }
    }
    else
    {
        Debug.Log("No target collider");
    }
    if (collisionInstance.targetColliderGroup != null)
    {
        Debug.Log("Target collider group name: " + collisionInstance.targetColliderGroup.name);
    }
    else
    {
        Debug.Log("No target collider group");
    }
    if (collisionInstance.damageStruct.hitInteractiveObject != null)
    {
        Debug.Log("Hit interactive object name: " + collisionInstance.damageStruct.hitInteractiveObject.name);
    }
    else
    {
        Debug.Log("No hit interactive object");
    }
    Debug.Log("----------------- End Collision -------------------");
}

void NPCDebugging()
{
    foreach (Creature npc in Creature.list)
    {
        if (npc.state == Creature.State.Alive)
        {
            // Green
            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.Downed)
        {
            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: Downed 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 != player)
        {
            if (distance > Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawnPoint.position))
            {
                distance = Vector3.Distance(npc.body.hipsBone.transform.position, portalSpawn.position);
                closestNPC = npc;
                SetNPCColor(npc, Color.yellow);
            }
            SetNPCColor(closestNPC, Color.green);
        }
    }
}

void StayOnGroundDammit()
{
    foreach (Creature npc in Creature.list)
    {
        if (npc != null && npc.ragdoll != null && npc != playerCreature)
        {
            if (npc.ragdoll.isGrounded && npc.state == Creature.State.Dead)
            {
                npc.ragdoll.state = BS.Ragdoll.State.Dead;
                npc.ragdoll.isGrounded = false;
            }
        }
    }
}

}