Example #1
0
            private void AfterDetonate()
            {
                if (!Detonated)
                {
                    Console.WriteLine("FusionBlock.ModuleMerger.AfterDetonate() has been called more than once!");
                }
                Detonated = false;

                if (blockB == null)
                {
                    blockA.AttachEvent.Unsubscribe(AfterDetonate);
                }
                else
                {
                    blockB.AttachEvent.Unsubscribe(AfterDetonate);
                }

                TankBlock halfBlockA = ManSpawn.inst.SpawnBlock(SubstituteType, cachedWorldPos, cachedWorldRot);                               // Create substitute #1
                TankBlock halfBlockB = ManSpawn.inst.SpawnBlock(SubstituteType, cachedWorldPos, cachedWorldRot * Quaternion.Euler(180, 0, 0)); // Create substitute #2

                halfBlockA.SetSkinIndex(block.GetSkinIndex());
                halfBlockB.SetSkinIndex(block.GetSkinIndex());                                 // Set that skins so they are pretty
                halfBlockA.visible.damageable.InitHealth(block.visible.damageable.Health / 2);
                halfBlockB.visible.damageable.InitHealth(block.visible.damageable.Health / 2); // Set the healths to halves of the whole
                ModuleFuseHalf fuseBlockA = halfBlockA.GetComponent <ModuleFuseHalf>();

                if (fuseBlockA != null)
                {
                    fuseBlockA.Timeout = DelayAfterDetonate;
                }
                ModuleFuseHalf fuseBlockB = halfBlockB.GetComponent <ModuleFuseHalf>();

                if (fuseBlockB != null)
                {
                    fuseBlockB.Timeout = DelayAfterDetonate;
                }

                block.visible.RemoveFromGame(); // Rid of this

                if (blockA != null && blockA.tank != null)
                {
                    blockA.tank.blockman.AddBlockToTech(halfBlockA, blockA.cachedLocalPosition + cachedBlockAOffset, cachedSplitRot); // Put that block where it belongs
                }
                if (blockB != null && blockB.tank != null)
                {
                    blockB.tank.blockman.AddBlockToTech(halfBlockB, blockB.cachedLocalPosition + cachedBlockBOffset, new OrthoRotation(cachedSplitRot * Quaternion.Euler(180, 0, 0))); // Put that other block where it belongs
                }
            }
Example #2
0
            public void AttemptMerge(ModuleFuseHalf other)
            {
                // Dot products are basically "Hey how much in this vector is this vector?"
                // Magnitude relevance of two vectors based on how alike their directions are.
                // Parallel are A.mag x B.mag, parallel but reverse is -(A.mag x B.mag), right-angle vectors are just 0.
                // Here dot products are being used to estimate how alike these 1-length directions are to one another.
                var a = ModelForwardSignificance ? Vector3.Dot(other.transform.forward, ModelForwardPairing * transform.forward) : 1f; // If it matters, are the blocks facing the right way
                var b = Vector3.Dot(other.transform.up, -transform.up);                                                                // Both blocks must be facing upwards at eachother
                var c = Vector3.Dot(other.block.tank.transform.forward, block.tank.transform.forward);                                 // Both techs must be vertically relevant.
                var d = Vector3.Dot(other.block.tank.transform.up, block.tank.transform.up);                                           // Both techs must be in the same general direction. I probably could just use quaternion math.

                //Console.WriteLine($"Testing if sacred ritual may commense:\n Block forward matching = {a}\n Block upward matching = {b}\n Tank forward matching = {c}\n Tank upward matching = {d}");
                if (a > 0.85f &&
                    b > 0.85f &&
                    c > 0.85f &&
                    d > 0.85f)
                {
                    Console.WriteLine($"Commencing the sacred ritual:\n Block forward matching = {a}\n Block upward matching = {b}\n Tank forward matching = {c}\n Tank upward matching = {d}"); //Commence the sacred ritual

                    Tank   tankA = block.tank, tankB = other.block.tank;                                                                                                                         // Tank cache. Because they would be lost without it
                    string tankAName = tankA.name, tankBName = tankB.name;
                    if (Singleton.playerTank == tankB)                                                                                                                                           // If player is tankB it's going to null
                    {
                        Singleton.SetPlayerTankInternal(tankA);                                                                                                                                  // Change it to this tank, because this one is the merge host
                    }
                    Vector3          cachedMergePos = block.cachedLocalPosition;                                                                                                                 // Where to put the substitute block
                    OrthoRotation    cachedMergeRot = block.cachedLocalRotation;                                                                                                                 // How to put the substitute block
                    List <TankBlock> array          = GetSafeBlockStep(other.block);                                                                                                             // Iterate the other tech's blocks to get a way to add them all

                    block.tank.blockman.Detach(block, true, false, false);                                                                                                                       // Remove this block
                    other.block.tank.blockman.Detach(other.block, true, false, false);                                                                                                           // Remove that block

                    Quaternion hecku;                                                                                                                                                            // Not going to try and figure out all that inverse transformation frick

                    hecku = tankA.transform.rotation;                                                                                                                                            // Yeah that's right get shunned
                    tankB.transform.rotation  = tankA.transform.rotation;                                                                                                                        // They are supposed to be in the same direction anyways so this should be fine
                    tankB.transform.position += transform.position - other.transform.position + (transform.TransformDirection(JoinOffset));                                                      // Move the tech by the offset of the two blocks, and join offset

                    tankB.blockman.Disintegrate(false, false);                                                                                                                                   // Melt that bad boy
                    if (MakeSubstitiute)                                                                                                                                                         // Does this have a block to go between or is this one of those glue kinds of fusing
                    {
                        TankBlock mergedBlock = ManSpawn.inst.SpawnBlock(SubstituteType, Vector3.zero, Quaternion.identity);                                                                     // Create that substitute
                        mergedBlock.SetSkinIndex(block.GetSkinIndex());                                                                                                                          // Set that skin so it is pretty
                        mergedBlock.visible.damageable.InitHealth(block.visible.damageable.Health + other.block.visible.damageable.Health);                                                      // Set the health to both of the halves
                        tankA.blockman.AddBlockToTech(mergedBlock, cachedMergePos, cachedMergeRot);                                                                                              // Put that block where it belongs
                    }

                    List <TankBlock> retry = new List <TankBlock>();

                    foreach (TankBlock sb in array) // Iterate from the array back up there from that tech, but now on this tech
                    {
                        // Add the block, using the block's rotation from memory, and just use the block's positions
                        if (!tankA.blockman.AddBlockToTech(sb, block.cachedLocalPosition + sb.cachedLocalPosition - other.block.cachedLocalPosition + block.cachedLocalRotation * JoinOffset, sb.cachedLocalRotation)) /*new IntVector3(tankA.transform.InverseTransformPoint(sb.transform.position))*/
                        {
                            retry.Add(sb);                                                                                                                                                                             // If it didn't attach, try again after
                        }
                    }

                    int retryCount = 2;                         // How many times to retry attaching
                    while (retryCount != 0 && retry.Count != 0) // While there are things left, and can retry
                    {
                        retryCount--;                           // Spend a token
                        int iter = 0;                           // Start the iterator
                        while (retry.Count > iter)              // Go through the elements
                        {
                            var sb = retry[iter];
                            if (!tankA.blockman.AddBlockToTech(sb, block.cachedLocalPosition + sb.cachedLocalPosition - other.block.cachedLocalPosition + block.cachedLocalRotation * JoinOffset, sb.cachedLocalRotation))
                            {
                                iter++; // Skip
                            }
                            else
                            {
                                retry.RemoveAt(iter); // Move elements down, keep placement
                            }
                        }
                    }
                    if (retry.Count != 0)
                    {
                        Console.WriteLine("AttemptMerge(" + tankBName + " to " + tankAName + "): Failed to merge " + retry.Count.ToString() + (retry.Count != 1 ? " blocks!" : " block!"));
                    }

                    tankA.transform.rotation = hecku; // Ok you can come back now



                    block.damage.Explode(false);          // Explode this
                    other.block.damage.Explode(false);    // Explode that
                    block.visible.RemoveFromGame();       // Rid of this
                    other.block.visible.RemoveFromGame(); // Rid of that
                }
            }