Announcement

Collapse
No announcement yet.

Actor not being replicated, when base does.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Actor not being replicated, when base does.

    Hi guys,

    I'm struggling with this issue for about 2 days now.
    I have an actor called DGItem, which holds information about a game item. This actor has no mesh or collision. This actor has a "proxy actor" inside used for clients to render object when its placed in the level (for pickup) or it's being hold by a player.

    In addition, when a monster drops an item (when killed), I create a new actor called DGDroppedPickup, which has a collision, and gets tossed from Monster. This last actor contains a reference to DGItem (the item itself).

    The procedure that toss the item when the monster happens from DGItem.

    NPC dies , call DGItem.
    DGItem drops itself creating a DGDroppedPickup.

    Code:
    function DropFrom(vector StartLocation, vector StartVelocity)
    {
    	local DGDroppedPickup P;
    
    	`Log(Self@"DropFrom");
    
    	if( Instigator != None && DGPawn(Instigator).ItemsInventory != None )
    	{
    		//DGPawn(Instigator).ItemsInventory.RemoveFromInventory(Self);
    	}
    
    	// if cannot spawn a pickup, then destroy and quit
    	if( DroppedPickupClass == None || DroppedPickupMesh == None )
    	{
    		Destroy();
    		return;
    	}
    
    	`Log(Self@"Spawn DroppedPickup");
    
    	P = Spawn(DroppedPickupClass,,, StartLocation);
    	if( P == None )
    	{
    		Destroy();
    		return;
    	}
    
    	`Log(Self@"DroppedPickup"@P);
    
    	// Item Attachment
    	Self.ItemAttach = Spawn(Self.ItemAttachment.Class,,,P.Location,P.Rotation,Self.ItemAttachment);
    	`Log(Self@"SetOwner"@P);
    	Self.SetOwner(P);
    	Self.SetBase(P);
    	Self.ItemAttach.SetBase(P);
    	bForceNetUpdate = TRUE;
    
    	// DroppedPickup
    	P.SetPhysics(PHYS_Falling);
    	P.Item = Self;
    	P.Velocity = StartVelocity;
    	P.Instigator = Instigator;
    
    	Instigator = None;
    }
    The thing is:
    1) DGDroppickup gets replicated.
    2) DGItem doesn't get replicated. (data, not physical representation)
    3) DGItemAttach gets replicated (phyisical representation of item)

    Object
    Code:
    	bReplicateInstigator=TRUE
    	RemoteRole=ROLE_SimulatedProxy
    	bHidden=false
    	NetPriority=+1.4
    These are the "Relevancy Rules", and I can't understand why its not being replicated.


    If the actor has a RemoteRole of ROLE_None, it is not relevant --- Its ROLE_SimulatedProxy
    If the actor's NetUpdateTime is larger than the current time, it is not relevant --- I don't really get this, but I understand no matter the NetUpdateTime, it should get replicated at some point.
    If the actor is bAlwaysRelevant, it is relevant --- If I use this, it gets replicated, ofc! but its not the idea.
    If the actor is owned by a viewer (could also be the client), it is relevant --- No apply
    If the actor is owned by the client, it is relevant --- No apply
    If the actor is the viewer, it is relevant ---- No apply
    If the viewer is the actor's instigator, it is relevant ---- No apply
    If the actor's Base is set it is relevenat if the Base actor is relevant ----- I'm setting DGItem BASE to "DGDroppedPickup", and DGDroppedPickup is being replicated!
    If the actor does not have bBlockActors and is bHidden or bOnlyOwnerSee, it is not relevant
    If the actor is visible according to a line-of-sight check between the actor's Location and the player's ViewLocation, then it is relevant
    If the actor is visible according to a line-of-sight check through a portal, it is relevant
    Otherwise, it is not relevant

    Any ideas?

    #2
    If the DGItem is invisible anyway and you have a visual representation via DGItemAttach, then why would you want DGItem replicated as well? Sounds like a waste of bandwidth to me.

    Comment


      #3
      Originally posted by Wormbo View Post
      If the DGItem is invisible anyway and you have a visual representation via DGItemAttach, then why would you want DGItem replicated as well? Sounds like a waste of bandwidth to me.
      DGItem contains data information, like name, quantity, which needs to be displayed when the Item is in the floor waiting to be picked up.

      Comment


        #4
        What about bOnlyRelevantToOwner? Must be False, otherwise the item will not be relevant to anyone but the owning client.

        Comment


          #5
          Originally posted by Wormbo View Post
          What about bOnlyRelevantToOwner? Must be False, otherwise the item will not be relevant to anyone but the owning client.
          bOnlyRelevantToOwner is not defined in DGItem properties. I tried by defining it in false just in case, but no luck.
          It works when I force it with bAlwaysRelevant, so for some reason, the engine is setting it as not relevant, even when its base is relevant.

          Comment


            #6
            Why 3 classes for one pickup ? you just need 1.

            Code:
            //////////////////////////////////////////////
            //Written by Neongho
            //This is the item , as a visual item
            //////////////////////////////////////////////
            class SLIItem extends KActorSpawnable placeable;
            
             var (InventoryInfo) const String PathToIcon;
             var (InventoryInfo) string TheName;
             var (InventoryInfo) string DisplayText;
             var (InventoryInfo) int Quantity;
             var (InventoryInfo) int MaxQuantity;
             var (InventoryInfo) float Weight;
            
             var(PostBeginPlayOptions) bool bIsPlaced;
            
             var() SkeletalMesh SKEOfItem; //for equiping
             var() StaticMesh STAOfItem; //for having the original reference
             var() name SocketForEquipping; //what socket should equip this item at
            
             //actual status variables////////////////////////
             var repnotify bool bPickedNotVisible;
             /////////////////////////////////////////////////
            
             replication
             {
            
              if(bNetDirty)
              bPickedNotVisible;
            
             }
            
             simulated function PostBeginplay()
             {
             }
            
            
             //equips this item up
             simulated function bool Equip(SLIPawn Equiper)//if equipped right true else false
             {
             Equiper.PrimaryWeapon = self;
             Equiper.AttachRightAttachmentToASocket(Equiper.RightAttachment,SocketForEquipping);
             Equiper.SetMeshToTheRightAttachment(Equiper.RightAttachment,SKEOfItem);
            
            
            
             return true;
             }
            
             //unequip
             simulated function bool UnEquip(SLIPawn Equiper)//if equipped right true else false
             {
             return true;
             }
            
            
            
            
             //picks this item up
             Simulated function bool GetPickedUp(SLIPawn Picker)//if picked right true else false
             {
              return Picker.Inv.AddItemInInventory(self);
             }
            
             //drops the item and sets all up so it gets dropped
             simulated function GetDroppedDown()
             {
              if(WorldInfo.game != none)
              {
              WorldInfo.game.broadcast(self, "Dropping item "@OWner );
            
              }
            
             SetHidden(false);
             SetLocation( Owner.location + vect(0,0,70)  );
             SetCollision( true, true, false);
             SetOwner(none);
             }
            
            
            
              //picks this item up
             Simulated function bool Use(SLIPawn User)//if picked right true else false
             {
             GetPickedUp(User); //as standart
            
             return true;
             }
            
            //-------------------------replication----------------------------------------------------------//
            
            
             //---------------------------------Client functions-------------------------------------/
            
             //---------------------------------Client functions-------------------------------------/
            
             //---------------------------------Server functions-------------------------------------/
            
            
             //picks this item up
             Simulated function bool GetPickedByServer(SLIItem Item)//if picked right true else false
             {
              Item.SetPhysics(0); Item.SetHidden( true ); Item.SetCollision(false,false,false);
              Item.bPickedNotVisible = true; //Trigger up the replication
              return true;
             }
            
            
             //Equip for the server
             reliable Server function ServerPawnEquipMe(SLIPawn Equiper)
             {
             `log(Owner@" "@Equiper);
             Equiper.PrimaryWeapon = self;
            
             }
            
             //---------------------------------Server functions-------------------------------------/
            
             simulated event ReplicatedEvent(name varName)
             {
             super.ReplicatedEvent(VarName);
            
             `log("Replicated event "@VarName@"  "@self);
             }
            
            //-------------------------replication----------------------------------------------------------//
            
            function string GetStringOfSpaceToLineUp(int spaces)
            {
            local string TheSpaceString;
            local int i;
            
              for(i = 0; i < spaces; i++ )
              {
              TheSpaceString @= " ";
              }
            return TheSpaceString;
            }
            
            //whenever tear off  = true this is called
            simulated event TornOff()
            {
             super.Tornoff();
            
             `log("Hello im not relevant anymore item");
             }
            
            
            
            DefaultProperties
            {
            RemoteRole = ROLE_SimulatedProxy;
            SocketForEquipping = WeaponPoint;
            }

            See, i can place it i can pick it, others can ir cannot see it ; ).

            Comment


              #7
              Originally posted by Neongho View Post
              Why 3 classes for one pickup ? you just need 1.

              See, i can place it i can pick it, others can ir cannot see it ; ).
              The idea of having separated classes (actors) for items, comes from the same structure UT uses. They have an Weapon (logical item), WeaponAttachment (phyisical representation), and UTDroppedPikcup (the drop manager).
              I've learned to code UnrealScript mostly based on how Epic does things, and I assume they know best than I do (or we do).

              I'm trying to understand the reason why an actor is not being replicated when, based on the rules in their documentation, I understand the actor should replicate. I'm definitelly doing something wrong, but I can't figure out where.

              If the base actor is being replicated, why not the actor inside of it? (.SetOwner and .SetBase are set to the parent, in this case DGDroppedPickup).

              Any thoughts?

              Thanks.

              Comment


                #8
                Im not sure of the panorama, of all of this.

                So, ok you have a placed item, wich is neither bStatic and bNoDelete, It's a simulatedProxy .
                Wich spawns an actor from PBP ( postbeginplay ) , 2 other actors of the same kind right ?

                Remember, you are only suposed to spawn them from server. " in case you want replication to be enabled " .

                Comment


                  #9
                  Originally posted by Neongho View Post
                  Im not sure of the panorama, of all of this.

                  So, ok you have a placed item, wich is neither bStatic and bNoDelete, It's a simulatedProxy .
                  Wich spawns an actor from PBP ( postbeginplay ) , 2 other actors of the same kind right ?

                  Remember, you are only suposed to spawn them from server. " in case you want replication to be enabled " .
                  I'm not spawning the actor from PBP, the process is:

                  1) The monster dies.
                  2) calls a static function ProcessDrop from DGDropSystem.uc (Object).
                  3) DGDropSystem.ProcessDrop determines which item to drop, and makes the Monster spawn the item, and call Item.DropFrom().
                  4) Item.DropFrom, creates the DGDropPickup and DGItemAttachment, and set Owners and Bases accordingly.

                  All this probably happens BEFORE calling PBP (I assume, not checked).

                  All this is happening only in the server.

                  If, during the process, I set bAlwaysRelevant, the object gets replicated.

                  I will try by doing the process once the actor calls PBP, just in case the Owner and Base gets set to something different afterwards.

                  Thanks

                  Comment


                    #10
                    I've checked, and all is happening after item's PostBeginPlay. Don't know where the problem is.

                    Comment


                      #11
                      Well the thing is , that if you spawn something on the client, the roles will be taken a different way.
                      And this creates some problems.


                      make sure in PBP you place

                      if(Role == ROLE_Authority && RemoteRole == ROLE_SimulatedProxy) it's the server.
                      {
                      Spawn the actor now.
                      }

                      Comment


                        #12
                        I'm 100% sure spawn is happening only in server. I checked roles, ownership, bhidden, base.

                        Item is not spawning at client so far. I'm subclassing form actor.


                        Sent from my iPhone using Tapatalk

                        Comment


                          #13
                          You better post all your code then .

                          Comment


                            #14
                            Monster dies (Enemy , DGPawn, Pawn):

                            Code:
                            /**
                             * This pawn has died.
                             *
                             * @param	Killer			Who killed this pawn
                             * @param	DamageType		What killed it
                             * @param	HitLocation		Where did the hit occur
                             *
                             * @returns true if allowed
                             */
                            simulated function bool Died(Controller Killer, class<DamageType> DamageType, vector HitLocation) {
                            	// Calculate drop
                            	if (Role == ROLE_Authority) {
                            		class'DGDropSystem'.static.ProcessDrop(Self, Drops, Killer, Self.CylinderComponent); 
                            		//Self.ProcessDrops(Killer);
                            	}
                            	// Check if this enemy is a map objective
                            	if (bIsObjective) {
                            		ProcessObjective();
                            	}
                            	return super.Died(Killer, DamageType, HitLocation);
                            }
                            DropSystem.DropItem function:

                            Code:
                            static function DropItem(Actor Who, DGItem ItemArchetype, int Amount, Controller Killer, optional CylinderComponent WhoCylinderComponent) {
                            	local DGItem Item;
                            	local vector	POVLoc, TossVel;
                            	local rotator	POVRot;
                            	local Vector	X,Y,Z;
                            	local Vector FindLocation;
                            
                            	`Log("Enemy DropItem");
                            	`Log("Item"@ItemArchetype@"Amount"@Amount);
                            
                            	// Create Item
                            	Item = Who.Spawn(ItemArchetype.Class,,,Who.Location,,ItemArchetype);
                            	`Log("Item.ItemArchetype"@Item.ItemArchetype);
                            	Item.ItemArchetype = ItemArchetype;
                            	`Log("Item.ItemArchetype"@Item.ItemArchetype);
                            	//Item.ObjectArchetype
                            	if (Item.bStackable) {
                            		Item.amount = Amount;
                            	}
                            
                            	// Location from drop
                            	Who.GetActorEyesViewPoint(POVLoc, POVRot);
                            	TossVel = VRand();
                            	TossVel = TossVel * ((Who.Velocity Dot TossVel) + 500) + Vect(0,0,200);
                            
                            	// Drop item
                            	GetAxes(Who.Rotation, X, Y, Z);
                            	if (WhoCylinderComponent != None) {
                            		Item.DropFrom(Who.Location + 0.8 * WhoCylinderComponent.CollisionRadius * X - 0.5 * WhoCylinderComponent.CollisionRadius * Y, TossVel);
                            	} else {
                            		FindLocation = Who.Location;
                            		if (Who.FindSpot(Vect(30,30,30), FindLocation)) {
                            			Item.DropFrom(FindLocation, TossVel);
                            		}
                            	}
                            }
                            DGItem.DropFrom function:

                            Code:
                            /**
                             * Drop this item out in to the world
                             *
                             * @param	StartLocation 		- The World Location to drop this item from
                             * @param	StartVelocity		- The initial velocity for the item when dropped
                             */
                            function DropFrom(vector StartLocation, vector StartVelocity)
                            {
                            	local DGDroppedPickup P;
                            
                            	`Log(Self@"DropFrom");
                            
                            	if( Instigator != None && DGPawn(Instigator).ItemsInventory != None )
                            	{
                            		//DGPawn(Instigator).ItemsInventory.RemoveFromInventory(Self);
                            	}
                            
                            	// if cannot spawn a pickup, then destroy and quit
                            	if( DroppedPickupClass == None || DroppedPickupMesh == None )
                            	{
                            		Destroy();
                            		return;
                            	}
                            
                            	`Log(Self@"Spawn DroppedPickup");
                            
                            	P = Spawn(DroppedPickupClass,,, StartLocation);
                            	if( P == None )
                            	{
                            		Destroy();
                            		return;
                            	}
                            
                            	`Log(Self@"DroppedPickup"@P);
                            
                            	// Item Attachment
                            	Self.ItemAttach = Spawn(Self.ItemAttachment.Class,,,P.Location,P.Rotation,Self.ItemAttachment);
                                    // attemtp to make "Item" replicate.
                            	`Log(Self@"SetOwner"@P);
                            	Self.SetOwner(P);
                            	Self.SetBase(P);
                            	Self.ItemAttach.SetBase(P);
                            	Self.ItemAttach.ItemName = Self.ItemName;
                            	P.ItemAttach = Self.ItemAttach;
                            	bForceNetUpdate = TRUE;
                            	//bAlwaysRelevant = true; // REMOVE THIS, this is not the way of doing it, isnt it? :P
                            
                            	// DroppedPickup
                            	P.SetPhysics(PHYS_Falling);
                            	P.Item = Self;
                            	P.Velocity = StartVelocity;
                            	P.Instigator = Instigator;
                            
                            	Instigator = None;
                            }
                            And this is the entire DGItem class:

                            Code:
                            class DGItem extends Actor;
                            
                            var(Item, Info) bool bStackable;
                            var(Item, Info) int amountMax;
                            var(Item, Info) int ItemID;
                            var(Item, Info) Texture IconImage;
                            var(Item, Info) String ItemType;
                            var(Item, Info) String ItemName;
                            var(Item, Info) bool bAutoPickup;
                            var(Item, Info)	class<DGDroppedPickup> DroppedPickupClass;
                            var(Item, Info) PrimitiveComponent PickupFactoryMesh;
                            var(Item, Info) PrimitiveComponent DroppedPickupMesh;
                            var(Item, Info) ParticleSystemComponent DroppedPickupParticles;
                            var(Item, Info) DGItemAttachment ItemAttachment;
                            
                            var DGItemAttachment ItemAttach;
                            var int amount;
                            var DGInventoryManager InvManager;
                            var int InvManagerSlot;
                            var archetype DGItem ItemArchetype;
                            
                            
                            replication {
                            	if (bNetDirty) 
                            		ItemAttach;
                            
                            	if (bNetOwner && bNetDirty)
                            		amount, InvManager, InvManagerSlot;
                            }
                            
                            function ResetOwner(Actor P) {
                            	Self.SetOwner(P);
                            	Self.Instigator = Pawn(P);
                            }
                            
                            simulated event PostBeginPlay()
                            {
                            	`Log(Self@"PostBeginPlay");
                            	super.PostBeginPlay();
                            }
                            
                            simulated event Destroyed() {
                            	DestroyProcess();
                            }
                            
                            function FreeItem() {
                            	`Log(Self@"FreeItem");
                            	// Remove from inventory
                            	if (Self.InvManager != None) {
                            		Self.InvManager.RemoveFromInventory(Self);
                            		Self.InvManager = None;
                            	}
                            	Self.InvManagerSlot = -1;
                            	// Remove from Shortcut
                            }
                            
                            simulated function DestroyProcess() {
                            	`Log(Self@"DestroyProcess");
                            	if (InvManager != None) {
                            		InvManager.RemoveFromInventory(Self);
                            	}
                            	// Remove references to inventory
                            	InvManager = None;
                            	
                            }
                            
                            simulated function String GetIconImagePath() {
                            	local String ImgPath;
                            	ImgPath = "";
                            	if (Self.IconImage != None) {
                            		if (Self.IconImage.Outer.Outer != None) {
                            			ImgPath = Self.IconImage.Outer.Outer $ ".";
                            		}
                            		ImgPath = ImgPath $ Self.IconImage.Outer.Name $ "." $ Self.IconImage.Name;
                            	}
                            	return ImgPath;
                            }
                            
                            simulated function BeginUseItem();
                            
                            simulated function String GetItemType() {
                            	return ItemType;
                            }
                            
                            simulated function bool IsAutoPickup() {
                            	return bAutoPickup;
                            }
                            
                            /**
                             * Drop this item out in to the world
                             *
                             * @param	StartLocation 		- The World Location to drop this item from
                             * @param	StartVelocity		- The initial velocity for the item when dropped
                             */
                            function DropFrom(vector StartLocation, vector StartVelocity)
                            {
                            	local DGDroppedPickup P;
                            
                            	`Log(Self@"DropFrom");
                            
                            	if( Instigator != None && DGPawn(Instigator).ItemsInventory != None )
                            	{
                            		//DGPawn(Instigator).ItemsInventory.RemoveFromInventory(Self);
                            	}
                            
                            	// if cannot spawn a pickup, then destroy and quit
                            	if( DroppedPickupClass == None || DroppedPickupMesh == None )
                            	{
                            		Destroy();
                            		return;
                            	}
                            
                            	`Log(Self@"Spawn DroppedPickup");
                            
                            	P = Spawn(DroppedPickupClass,,, StartLocation);
                            	if( P == None )
                            	{
                            		Destroy();
                            		return;
                            	}
                            
                            	`Log(Self@"DroppedPickup"@P);
                            
                            	// Item Attachment
                            	Self.ItemAttach = Spawn(Self.ItemAttachment.Class,,,P.Location,P.Rotation,Self.ItemAttachment);
                            	`Log(Self@"SetOwner"@P);
                            	Self.SetOwner(P);
                            	Self.SetBase(P);
                            	Self.ItemAttach.SetBase(P);
                            	Self.ItemAttach.ItemName = Self.ItemName;
                            	P.ItemAttach = Self.ItemAttach;
                            	bForceNetUpdate = TRUE;
                            	//bAlwaysRelevant = true; // REMOVE THIS, this is not the way of doing it, isnt it? :P
                            
                            	// DroppedPickup
                            	P.SetPhysics(PHYS_Falling);
                            	P.Item = Self;
                            	P.Velocity = StartVelocity;
                            	P.Instigator = Instigator;
                            
                            	Instigator = None;
                            }
                            
                            function GiveTo(Pawn Other) {
                            	local DGPawn DGPawn;
                            
                            	DGPawn = DGPawn(Other);
                            
                            	`Log(Self@"Item.ItemArchetype"@Self.ItemArchetype);
                            
                            	if (DGPawn != None && DGPawn.ItemsInventory != None) {
                            		Self.ItemAttach.Destroy();
                            		if (DGPawn.ItemsInventory.AddInventory(Self)) {
                            			/*
                            			Self.ResetOwner(Other);
                            			Self.SetBase(Other);
                            			*/
                            		} else {
                            			// SOLUCIONAR El drop para que el que lo tira no lo agarre inmediatamente por el Touch de la colision , y esto genere un loop infinito.
                            			//Self.DropFrom(Location, vect(100,0,100));
                            		}
                            	}
                            }
                            
                            DefaultProperties
                            {
                            	bReplicateInstigator=TRUE
                            	RemoteRole=ROLE_SimulatedProxy
                            	bHidden=false
                            	NetPriority=+1.4
                            
                            	// Game specific props
                            	bStackable=false
                            	amount=1
                            	amountMax=1
                            	InvManagerSlot=-1
                            	DroppedPickupClass=class'DGDroppedPickup'
                            	bAutoPickup=false
                            	bOnlyRelevantToOwner=false
                            
                            }

                            Comment


                              #15
                              Any ideas? Anyone?

                              Comment

                              Working...
                              X