Exemple #1
0
        public void AddBlock(TankBlock block, IntVector3 pos, OrthoRotation rot)
        {
            blocks.Add(block);
            block.trans.parent        = transform;
            block.trans.localPosition = pos;
            block.trans.localRotation = rot;
            Dirty = true;

            for (int ap = 0; ap < block.attachPoints.Length; ap++)
            {
                IntVector3 filledCellForAPIndex = block.GetFilledCellForAPIndex(ap);
                IntVector3 v3    = block.attachPoints[ap] * 2f - filledCellForAPIndex - filledCellForAPIndex;
                IntVector3 index = pos + rot * filledCellForAPIndex;
                byte       b     = (rot * v3).APHalfBits();
                ClusterAPBitField.TryGetValue(index, out byte ptr);
                ptr |= b;
                ClusterAPBitField[index] = ptr;
            }

            ModuleWeapon weapon = block.GetComponent <ModuleWeapon>();

            if (weapon != null)
            {
                blockWeapons.Add(weapon);
            }
            ModuleDrill drill = block.GetComponent <ModuleDrill>();

            if (drill != null)
            {
                blockDrills.Add(drill);
            }

            return;
        }
Exemple #2
0
            private void Detonate(TechSplitNamer obj)
            {
                if (base.block.tank.beam.IsActive)
                {
                    base.block.tank.beam.EnableBeam(false, false, false);
                }
                blockA         = block.ConnectedBlocksByAP[0]; blockB = block.ConnectedBlocksByAP[1];
                cachedWorldPos = block.trans.position;
                cachedSplitRot = block.cachedLocalRotation; cachedWorldRot = block.trans.rotation;
                if (blockA != null)
                {
                    cachedBlockAOffset = block.cachedLocalPosition - blockA.cachedLocalPosition;
                }
                if (blockB != null)
                {
                    cachedBlockBOffset = block.cachedLocalPosition - blockB.cachedLocalPosition;
                }

                if (blockB == null)
                {
                    blockA.AttachEvent.Subscribe(AfterDetonate);
                }
                else
                {
                    blockB.AttachEvent.Subscribe(AfterDetonate);
                }
                Singleton.Manager <ManLooseBlocks> .inst.HostDetachBlock(base.block, false, true);

                block.damage.Explode(false); // Explode this
                Detonated = true;
            }
Exemple #3
0
        internal override bool CanStartGetBlocks(BlockManager blockMan)
        {
            ClearSegmentList();          // Remove pointers to this block

            foreach (var m in posCurves) // Clear position animation
            {
                m.keys = new Keyframe[1] {
                    new Keyframe(0f, 0f, 0f, 0f, 0f, 0f)
                }
            }
            ;
            foreach (var m in rotCurves) // Clear rotation animation
            {
                m.keys = new Keyframe[1] {
                    new Keyframe(0f, 0f, 0f, 0f, 0f, 0f)
                }
            }
            ;

            Quaternion TravelQuat = Quaternion.identity;
            //Vector3 TravelRot = Vector3.zero;
            OrthoRotation OriginalRot        = block.cachedLocalRotation;
            float         Length             = starterAnim.AddToAnimCurves(OrthoRotation.identity, this, 0f, ref TravelQuat, starterAnim, 0f);//, ref TravelQuat);//, ref TravelRot);
            float         prevTrueLimitVALUE = TrueLimitVALUE;

            TrueLimitVALUE = 0f;

            TankBlock   LastBlock = block;
            AttachPoint LastAP    = starterAnim; //For grabbing the block at the next position

            TankBlock Segment = LastAP.GetBlockAtPos(LastBlock, blockMan);

            while (Segment != null)
            {
                Print(">> Found block " + Segment.cachedLocalPosition);
                ModuleBMSegment component = Segment.GetComponent <ModuleBMSegment>();
                if (component == null) // Not a rail segment
                {
                    Print("   Not a segment");
                    ModuleBMRail opposer = Segment.GetComponent <ModuleBMRail>();
                    if (opposer == null || !LastAP.CanConnect(LastBlock, Segment, opposer.starterAnim)) // Not an opposing rail, or not sharing
                    {
                        break;
                    }
                    // Cut shared rail in half to prevent overlap
                    Print("   Is another head!");
                    CutSegmentListInHalf();
                    TrueLimitVALUE = HalfLimitVALUE - 0.5f; // Move back .5 for block-room on the AP
                    break;
                }

                if (component.blockMoverHeadType != m_thisHeadType)//component.blockMoverHeadType.Contains(m_thisHeadType))
                {
                    Print("   Wrong rail type!");
                    break; // A different rail system
                }

                var _Segment = Segment;
                Segment = null; // Nullify this, if not re-set it will break the loop

                for (int i = 0; i < 2; i++)
                {
                    if (LastAP.CanConnect(LastBlock, _Segment, component.APs[i]))
                    {
                        m_Segments.Add(component);
                        LastBlock = _Segment;
                        LastAP    = component.APs[1 - i];

                        Length  = component.APs[i].AddToAnimCurves(Quaternion.Inverse(OriginalRot) * _Segment.cachedLocalRotation, this, Length, ref TravelQuat, LastAP, component.AnimWeight); //, ref TravelQuat);//, ref TravelRot);
                        Segment = LastAP.GetBlockAtPos(_Segment, blockMan);                                                                                                                     // Set the new segment, continue

                        Print("   Connected!");
                        break; // Exit the foreach
                    }
                }
                if (Segment == null)
                {
                    Print(">> No more blocks");
                }
            }

            //if (TrueLimitVALUE == 0f) TrueLimitVALUE = 0.25f;
            ValidateSegmentList(out bool DisableFreeJoint);

            CannotBeFreeJoint = true;//DisableFreeJoint;

            if (MAXVALUELIMIT >= TrueLimitVALUE)
            {
                SetMaxLimit(TrueLimitVALUE);
                if (PVALUE > TrueLimitVALUE)
                {
                    PVALUE = TrueLimitVALUE;
                }
                if (VALUE > TrueLimitVALUE)
                {
                    VALUE = TrueLimitVALUE;
                }
            }
            else if (prevTrueLimitVALUE == 0f || MAXVALUELIMIT == prevTrueLimitVALUE || !UseLIMIT)
            {
                SetMaxLimit(TrueLimitVALUE);
            }

            return(true);
        }
Exemple #4
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
                }
            }