예제 #1
0
파일: Node.cs 프로젝트: wwarnick/Sever
        /// <summary>Attempt to claim this node for the specified segment.</summary>
        /// <param name="segment">The segment attempting to claim the node.</param>
        /// <returns>Whether or not the claim was successful.</returns>
        public bool claim(Segment segment)
        {
            bool claimed = false;
            int relSegIndex = -1;
            int lane = segment.getNodeIndex(this);
            int oppLane = 1 - lane;
            Node oppNode = segment.Nodes[oppLane];

            // Determine whether or not the claim is successful
            if (Destroyed || Owner != segment.Owner)
            {
                // can't claim destroyed nodes or nodes owned by someone else
            }
            else if (!Active) // if the node is inactive...
            {
                if (InWorld.Collision.nodeCollision(Pos, Radius, new List<SegmentSkel>(1) { segment }, new List<NodeSkel>(1) { this })
                    || InWorld.Collision.nodeCollNodeSpacing(Pos, Radius, Spacing, Owner, new List<NodeSkel>(1) { this }, false))
                    destroy();
                else
                    claimed = true;
            }
            else if ((relSegIndex = relatedSeg(oppNode)) != -1) // if the node is related
            {
                claimed = true;

                // make sure the connection is more than one segment away
                foreach (Segment seg in Segments)
                {
                    if (seg != null && seg.getOppNode(this) == oppNode)
                    {
                        claimed = false;
                        break;
                    }
                }

                if (claimed)
                    severSegment(relSegIndex);
            }
            else if (NumSegments < Segments.Length) // if same owner, but unrelated
            {
                claimed = true;
            }

            if (!claimed)
            {
                segment.State[oppLane] = Segment.SegState.Retracting;
            }
            else
            {
                // complete the segment
                segment.State[oppLane] = Segment.SegState.Complete;

                // prepare to invalidate visibility for old owner
                // and apply new visibility to new owner
                Player invalOwner = (Active && Owner != segment.Owner && Owner.Type == Player.PlayerType.Human) ? Owner : null;
                bool applyVisibility = (!Active || Owner != segment.Owner) && segment.Owner.Type == Player.PlayerType.Human;

                Active = true;
                addSegment(segment, true);
                Owner = segment.Owner;

                // exchange parentage and density
                if (segment.State[lane] == Segment.SegState.Complete)
                {
                    // exchange density
                    int peopleToSend = 0;
                    FInt capacityToSend = FInt.F0;
                    for (int i = 0; i < Segments.Length; i++)
                    {
                        if (Segments[i] != null)
                        {
                            peopleToSend += SegNumPeople[i];
                            capacityToSend += SegCapacity[i];
                        }
                    }

                    int peopleToReceive = oppNode.PeopleToSort;
                    FInt capacityToReceive = FInt.F0;
                    for (int i = 0; i < oppNode.Segments.Length; i++)
                    {
                        if (oppNode.Segments[i] != null)
                        {
                            peopleToReceive += oppNode.SegNumPeople[i];
                            capacityToReceive += oppNode.SegCapacity[i];
                        }
                    }

                    alterDensity(peopleToReceive, capacityToReceive, segment);
                    oppNode.alterDensity(peopleToSend, capacityToSend, segment);

                    // exchange parentage
                    Node[] parentsToSend = null;

                    if (Parents.Count > 0 || IsParent)
                    {
                        parentsToSend = new Node[Parents.Count + (IsParent ? 1 : 0)];
                        Parents.CopyTo(parentsToSend);
                        if (IsParent)
                            parentsToSend[parentsToSend.Length - 1] = this;
                    }

                    if (oppNode.Parents.Count > 0 || oppNode.IsParent)
                    {
                        if (!oppNode.IsParent)
                        {
                            addParents(segment, oppNode.Parents);
                        }
                        else
                        {
                            List<Node> parentsToReceive = new List<Node>(oppNode.Parents.Count + 1);
                            parentsToReceive.AddRange(oppNode.Parents);
                            parentsToReceive.Add(oppNode);
                            addParents(segment, parentsToReceive);
                        }
                    }

                    if (parentsToSend != null)
                        oppNode.addParents(segment, parentsToSend);
                }
                else // get segment's density
                {
                    int peopleToReceive = segment.NumPeople;
                    FInt capacityToReceive = (segment.State[lane] != Segment.SegState.Retracting) ? segment.Capacity : FInt.F0;

                    alterDensity(peopleToReceive, capacityToReceive, segment);
                }

                // update visibility
                if (invalOwner != null)
                {
                    invalOwner.Fog.invalidate(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + SightDistance, Y + SightDistance));
                    InWorld.refreshVisibility(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + Radius, Y + Radius));
                }

                if (applyVisibility)
                {
                    Owner.Fog.applyVisibility(this);
                    InWorld.refreshVisibility(new VectorF(X - SightDistance, Y - SightDistance), new VectorF(X + SightDistance, Y + SightDistance));
                }

                Visible = Owner.Type == Player.PlayerType.Human || (Active && InWorld.HumanPlayer.Fog.isVisible(this));

                // add event
                InWorld.addEvent(ID, WorldEvent.EventType.NodeChangeState);

                // run script if on hotspot
                if (OwnsHotspot != null && !string.IsNullOrWhiteSpace(OwnsHotspot.Script))
                    InWorld.Script.runScript(OwnsHotspot.Script);
            }

            // add event
            if (!Destroyed)
                InWorld.addEvent(segment.ID, WorldEvent.EventType.SegChangeState);

            return claimed;
        }