Player replicationinfo

Discussions about Coding and Scripting
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Player replicationinfo

Post by Rakiayn »

is it possible for a player to have two or more playerreplicationinfo's?
Im using a PRI for a mutator but I dont want other pri to be replaced
gopostal

Re: Player replicationinfo

Post by gopostal »

No. However there are other things you can use to get around this. What are you trying to do?
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

well,as you already know, im working on a spawner that spawns pretty much everything you want.
you can select in a window (still in progress) what you want to spawn.
the window reads/changes some values in the custom PRI the player is carrying.
but if a player cant have more then 1 pri, then I guess my mutator cant be played with ,lets say, jailbreak , becase jailbreak has its own PRI too
gopostal

Re: Player replicationinfo

Post by gopostal »

So why can't you run everything through inventory? Have the mod create some custom inventory that is assigned to the player and crib all your values in there. I've used that several times to do things and aside from the updated values PRI keeps, it will work (mostly) just as good.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

yes, but when you die you lose your inventory,
do you know how you can keep your inventory when you die?
I triedto make that, but It didnt work
gopostal

Re: Player replicationinfo

Post by gopostal »

This will be a little challenging but here is what you need to address:

In Pawn there is a bit of code in "function Died" that reads

Code: Select all

if ( CarriedDecoration != None )
        DropDecoration();
and also

Code: Select all

if( Event != '' )
        foreach AllActors( class 'Actor', A, Event )
            A.Trigger( Self, Killer );
    Level.Game.DiscardInventory(self);
and finally in pickup there is

Code: Select all

function UsedUp()
{
    if ( Pawn(Owner) != None )
    {
BLAH BLAH REMOVED
    Destroy();
}
Now depending on what you want to do, one of those can be massaged to what you need. Inventory is tied to the PRI, and only destroys on death because it is coded to. If you need something excluded from doing that just make it that way.

Oh, and be sure to add a "game ended" destroy check or your item could ghost forward into the next map if the server doesn't clear itself well on mapchange.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

does that mean I have to subclass playerpawn or is there an other way to do that
gopostal

Re: Player replicationinfo

Post by gopostal »

Not necessarily. There are ways to assign things to PRI. Here, take a look at Pheonix:
PheonixMut.zip
This is just the class sheet, but if you read through it, you'll see how they did it, and hopefully you'll find your answer. One problem I have seen though is that some mods conflict with this and Phoenix needs to be at the end of the chain. Probably the mod is holding information that should be destroyed so take care if you follow the mod very closely.
You do not have the required permissions to view the files attached to this post.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

hmm. Ibelieve this is beyond my skill. maybe later when im better in coding I can try changing it.
I had an idea though.
I can let the inventory of the player drop an invisible projectile (not moving, can not be destroyed)
the variables of the inventory are copied to this projectile. and a string is placed between the player and the projectile.
when the player respawns , he respawns with the inventory, and the variables of the projectile are copied to the new spawned inventory,
then the projectile destroys itself.
what do you think?
gopostal

Re: Player replicationinfo

Post by gopostal »

Lets back up a bit and discuss what sort of things you want to do with this inventory. Are you using some sort of "save everything" inventory thing? The problem I see is that if you want to save a lot of information, it's going to create lag spikes like you see when players join.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

yes. with the spawner weapon you can spawn everything you want. but that requires some info. the spawner must know what to spawn and als what are the properties of what it is about to spawn (because you can alter them)
the spawner reads that info before it fires and gives the variables to the actor it spawns.
I already was afraid of it causing lag. but the info doesnt have to be replicated to other clients if im not mistaken. only the things it spawns must be replicated correctly right?
gopostal

Re: Player replicationinfo

Post by gopostal »

If I understand you correctly, then no. If you allow a player to spawn something in the world that is not a defined class (meaning it has properties that differ from an established class) you'll have to make sure it's covered in replication.

For instance I create a gun that spawns wooden boxes. No problem there, other players will see the projectile (the box) because projectiles are covered under normal replication. If however I add the option to add things to the box that spawn when it is destroyed (contents code) then I probably am going to have to create replication for that to ensure the proper information is sent to all clients.

Ferali is by far the weapons master. I'll bet he has a workaround already you could use. I've found him to be incredibly creative in his solutions, so he may see something I don't.
User avatar
Feralidragon
Godlike
Posts: 5489
Joined: Wed Feb 27, 2008 6:24 pm
Personal rank: Work In Progress
Location: Liandri

Re: Player replicationinfo

Post by Feralidragon »

gopostal wrote: Ferali is by far the weapons master. I'll bet he has a workaround already you could use. I've found him to be incredibly creative in his solutions, so he may see something I don't.
Actually I don't have a workaround since I still don't know what exactly Rakiayn wants to do yet (plus, I would like to master the weapons field indeed, but I still didn't reach that level rofl, my own are the example of that, some bugs yet to solve).

Rakiayn, you say you want a weapon to spawn any class, but I bet it's not "any" class at all, since around half (if not more) of the classes under Actor aren't even "spawnable" of sort to speak (under Object, only Actor and below are spawnable).

So we need to know exactly what you want to spawn, modify, those sort of things. If you want something to hold information even when you die or even reconnect, that just takes only 1 actor per player/bot controlling that info server-side (make a subclass in actor, info, effects or even keypoint, although subclassing "info" to make that object would be the most correct way I think).

In the case of this object, each one has a owner (player/bot), and each one controls itself client-side, and as we all know, replication only occurs only if needed if the environment is correctly controlled (although this may sound difficult, this is the easiest part to understand in replication). The only checks the object has to do is just: see if the player still exists (in case of a reconnect, the object won't find the player anymore, but if you want it to be smart enough to "recover" the data if the player rejoins, one of that info that makes the object unique to the player is his/her IP, and when a player joins, your mutator just has to check if there's a "lost object" in the map, that's why I say "server-side") and if so, if he's alive and playing ("Owner.bHidden = False" and "Pawn(Owner).Health > 0", easy).

This object can be first spawned in a location where you are obsolutelly sure it exists in any map, let's say, the first playerstart you find (you don't need to "carry" the object around the map, the relevancy will be kept everytime you change or call something there), and not in the player's location (I think it's better since the playerstarts cannot be destroyed and always exist in a map, and therefore giving always the best stable position in the map, unlike the players locations are volatile and the server might get wrong values, since the player location can have "unrecoverable" package losses without screwing the game overall, but this is just my way of thinking though).

And if you want to freely iterate through these objects with a mutator or simply another object of some sort without using ForEach AllActors to keep the server stressing low, just create your own dynamic list like the Pawn list. It's something really simple to do and that actually works if done correctly: all you have to do is add one more variable to the object (var YourWhateverObj NextWhateverObj) which will link all these objects like a chain, and then you can make your own iterator list like the one from pawnList. And since you don't need to destroy any of these objects at all during the game (after all, they should only cover players and possibly bots, you won't have more than around 32 players+bots during the whole match most of the time, and once they get innactive, they will just sleep until the game ends or if the player rejoins during that match), but if you want to destroy them after a certain time and still keep the chain, the easiest way would set a boolean variable such as "DestroyMePls", and in the next update your mutator does a check in the objects, it can easilly destroy the object itself and give its "nextObj" to the previous iterated object, but if you want my opinion, I would let them stay and that way the player would always recover its data during a single match using the IP check.

Well, but fact is, you want to have a weapon to control this info, right? Well, in that case, this object will replicate 0, nothing, "nada" to the clients, only the server will handle this info, and it will just receive from a single player (when he/she (re)joins or when dying/respawning), and never broadcast to the clients. Why? It's simple, if your weapon will handle the info, all you have to do is to link your weapon somehow by reference to this object (well, it will have to look for your object, but ForEach ChildObjects (or something like that) is slow as AllActors, and that's why the sugestion of a simple dynamic list to look for it in much much less time), and once "attached", the output info the object will give will be sent to its attached weapon in the server, so no replication here yet (it's a simple "data trading" process between 2 objects in the server), and the replication only of the info that must be sent to its player owner would be filtered, controlled and done by the weapon itself and only for its player owner (server --> player owner replication), since any carried inventory do that with much more accuracy, performance and you will be sure that most info will be replicated to the playerowner itself unless you specify in the weapon otherwise, unlike other classes (with some exceptions).

Then the selecting and such in the weapon is something simple to do, but I would advice you to use an idle animation to control the selection. In case you use only the fire/altfire functions, if you select too fast, the weapon will simple block itself until you throw it away and get it up again, and even controlled by "time" might block it for some whatever reason (reason I still yet to find out since I have one or another problem of that kind in my own weapons). If you make the animation time control it, it will be pretty much flawless, almost problems free in that field.

But if you want to make a good spawner weapon, I sugest you to check the main "weapon" utlility from the Siege gametype. There's a weapon which only purpose it to spawn things depending on your "money" (RU), and I never looked at its code, but I already used it many times in the servers in siege matches, and it never failed to select or spawn something, so I can say it's a much better worked weapon you should look at so you can know exactly what to do in that part.

There might be a big hole in this wall of text and the way you could do it, but so far, this is what came to my mind since I read this thread during a bit more time.

Well, just my 2 cents in the subject, and I can't say anything more since you didn't give any clues yet on what kind of classes you want to spawn (inventory, projectiles, projectiles that spawn something else? idk since you didn't say so yet).

And no, there's no magic there, it's something pretty simple to do if you do it calmly. :tongue:
But again, I am not sure about what you want to do, so I threw a possible solution from what I understood you wanted.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

thnx guys for your help :tu:

please read the forst post of this topic
http://www.ut99.org/forum/viewtopic.php?f=34&t=2444
It is better explained of what I want.

@Feralidragon
your suggestion is very interresting. although im not sure how to do al those things yet, I will certainly take your advice to hearth.
Ill explain now what I have so far:

I have created a spawner that can spawn actors, like
-pawns
-projectiles
-inventory
-decoration.

Normal fire is used to spawn.
altfire is used to switch between SLOTS
the spawner has 10 slots.
so with the spawner you can spawn 10 different things
Feralidragon, I know what you mean with the switching being jammed. I Used a method that does not involve weapons animation. at first I had the same problem as you. but I did solve it. It never jams now.
If you want to see the code. please download my ''monstermatch beta''
here : http://www.ut99.org/forum/viewtopic.php?f=34&t=2444
if its not working.you can PM me.

Let me tell how the spawner works.

As I said before, the spawner has 10 slots.
they are actually 10 vars in the spawner

var() class<actor> SlotInfo[10];

10 being the number of slots. these vars are not actual actor that is spawned. they are a special kind of ''projectile''. this projectile is only used as an information carrier. it carries information like:
-what actor must be spawned
-how much ammo does it cost to spawn this.
-what name does the spawned actor has
-how populair is it for bots, to spawn actor
-how long does the spawner takes to recharge when spawning this actor

every time you switch to a different slot, this projectile is spawned. it is invisible. then the spawner takes the information of this Slotinfo, and adds it to its own properties.
then the slotinfo is destroyed


now I will explain what happens when you want to spawn a monster.
first you select a slot you want to spawn.
lets say you want to spawn a brute.
you press fire. the spawner looks at its own variables to see what is about to be spawned.
if it is a projectile. the spawner will spawn that projectile.
if it is something else. it will spawn a special projectile. called: P_MMSpawnerProjectile.
the spawner will pass its information of what must be spawned , to this P_MMSpawnerProjectile.
the P_MMSpawnerProjectile will then explode and spawn an other projectile called ''P_MMSpawnerProjectileB''
it also gives its information to the ''P_MMSpawnerProjectileB''
this ''P_MMSpawnerProjectileB'' will spawn the monster

this is how made it. and it works perfectly.
It also works perfectly on LAN games.
I dont now how it works online, and I dont know if when it works on LAN, it will work online too.


However I want to do something else:
I want a player to be able to change properties of what he wants to spawn too.
lets say you want to spawn a brute. I want the player to be able to alter that brutes properties too before he spawns it.
think of properties like, skins,health,drawscale,ground/air/water speed, etc....

I already made a start with this and Im using a custom playerreplication info as an information carrier.
instead of the actual spawner.
but I think I will use the ferralidragon method now.
User avatar
Rakiayn
Masterful
Posts: 550
Joined: Fri Aug 28, 2009 3:33 pm

Re: Player replicationinfo

Post by Rakiayn »

ok. I have made an infoclass that is spawned on the playerstart and is connecected to its owner and the spawner.
I even managed to let it rejoin a player that has left, through an IP-adres check.

here is the part of the code of the spawner:

Code: Select all


var SpawnerMasterinfo ownerinfo;    
//Rakiayn: info of Pawn who is owner of this spawner

var string MMPlayerIP;
//Rakiayn: the IPadress of the player who owns this Spawner



function FindSpawnerInfo()
{
local SpawnerMasterInfo masterinfo;
local playerstart p;
local spawnermasterinfo i;
local bool foundinfo;
local inventory a;
local inventory sp;
local inventory inv;



foundinfo = false;


	if (ownerinfo != none)
	{
	ownerinfo.testnumber += 1;
	}

	if ((Bot(owner) != none) || (bots(Owner) != none))
	{
  		if (ownerinfo == none)
  		{
			BroadcastMessage("Looking for MasterInfo");
			foreach AllActors(class'SpawnerMasterInfo', MasterInfo)

			{
				//	BroadcastMessage("Looking for MasterInfo");
				if (MasterInfo != none)
				{
				//Rakiayn: there are masterinfo's in the map
					BroadcastMessage("A Master info has been found");

					if (MasterInfo.master == pawn(owner))
					{
					//Rakiayn: Info of owner of spawner has been found
					BroadcastMessage("Master info is from owner");

					foundinfo = true;
					break;
					}
				}
		
			}

			if (foundinfo == false)
			{
			BroadcastMessage("No Masterinfo was found");
				if (masterinfo == none)
				{
				//Rakiayn: there are no masterinfo's in the map


					foreach AllActors(class'playerstart', P)
					{
					BroadcastMessage("Looking for a playerstart");
						if (p != none)
						{
						BroadcastMessage("Playerstart has been found");
						i = Spawn(class'SpawnerMasterInfo',,,p.location);
						i.master = pawn(owner);
						i.drawscale = 0.4;
						ownerinfo = i;
						
						BroadcastMessage("Creating MasterInfo for owner");
						break;
				
						}
					}
					if (p == none)
					{
					BroadcastMessage("No playerstart has been found");
					}

				}
			}
  		}
	}
	


	if (PlayerPawn(owner) != none)
	{

  		if (ownerinfo == none)
  		{
			BroadcastMessage("Looking for MasterInfo");
			foreach AllActors(class'SpawnerMasterInfo', MasterInfo)

			{
				//	BroadcastMessage("Looking for MasterInfo");
				if (MasterInfo != none)
				{
				
				//Rakiayn: there are masterinfo's in the map
					BroadcastMessage("A Master info has been found");

					if (MasterInfo.MMPlayerIP == MMPlayerIP)
					{
					//Rakiayn: Info of owner of spawner has been found
					BroadcastMessage("Master info is from owner");
					masterinfo.master = pawn(owner);
					ownerinfo = masterinfo;
					BroadcastMessage("IP adress confirmed");
					foundinfo = true;
					break;
					}
				}
		
			}

			if (foundinfo == false)
			{
			BroadcastMessage("No Masterinfo was found");
				if (masterinfo == none)
				{
				//Rakiayn: there are no masterinfo's in the map


					foreach AllActors(class'playerstart', P)
					{
					BroadcastMessage("Looking for a playerstart");
						if (p != none)
						{
						BroadcastMessage("Playerstart has been found");
						i = Spawn(class'SpawnerMasterInfo',,,p.location);
						i.master = pawn(owner);
						i.MMPlayerIP = MMPlayerIP;
						i.drawscale = 0.4;
						ownerinfo = i;
						BroadcastMessage("Creating MasterInfo for owner");
						BroadcastMessage("Saving IP adress confirmed");
						break;
				
						}
					}
					if (p == none)
					{
					BroadcastMessage("No playerstart has been found");
					}

				}
			}
  		}
	}

}

simulated event Tick(float TimeDelta)
{
findspawnerinfo();
MMPlayerIP = left(playerpawn(owner).GetPlayerNetworkAddress(), InStr(playerpawn(owner).GetPlayerNetworkAddress(), ":"));


	if (ownerinfo.tempammocount > 0 && pawn(owner).health > 0)
	{
	//Rakiayn: this is used to save ammo when you die, so you will never lose it.			pawn(owner).ClientMessage("loading ammocount");
	ammotype.ammoamount = ownerinfo.tempammocount;
	ownerinfo.tempammocount = 0;
	}

	
//BroadcastMessage(MMPlayerIP);
//	if ( Role == ROLE_Authority )
//		RemoteRole = ROLE_AutonomousProxy;

Disable('Tick');
}




function Destroyed()
{
//
// Called by engine when destroyed.
//
//Rakiayn: copied this from inventory and altered it

local inventory a;
local Inventory v;

//Log(class$":timer : checking monsters orders.");

		pawn(owner).ClientMessage("Saving ammocount");
		ownerinfo.tempammocount = ammotype.ammoamount;
        pawn(owner).ClientMessage("Saving ammocount,master ammo found");
		//Rakiayn: saving ammoamount
		
	
	Super.Destroyed();
	if( (Pawn(Owner)!=None) && (Pawn(Owner).Weapon == self) )
		Pawn(Owner).Weapon = None;

}
and here is the part of the code of the info class

Code: Select all


class SpawnerMasterInfo expands Info;

var Pawn Master;    
//Rakiayn: Pawn who is master over this info

var string MMPlayerIP;
//Rakiayn: the IPadress of the player who owns this info

var int testnumber;



replication
{
	// Variables the server should send to the client.
	reliable if( Role==ROLE_Authority )
		master,mmPlayerIP,testnumber,
}

function FirstInfo()
{
local MM_mutator M;
local byte i;

local inventory a;
local Inventory v;


	if (master != none)
	{
	mesh = master.mesh;
	skin = master.skin;
	multiskins[3] = master.multiskins[3];
	multiskins[2] = master.multiskins[2];
	multiskins[1] = master.multiskins[1];
	multiskins[0] = master.multiskins[0];
	bunlit = true;
	style = STY_translucent;
	}
master.clientMessage(testnumber);
master.clientMessage(tempammocount);




foreach AllActors(class'Monstermatch.MM_Mutator',M)
		{
			
		if ( M != None )
				{
                pawn(owner).ClientMessage("Giving StartingammoAmount");
                                
				tempammocount = M.StartingAmmoAmount;	
				credit = M.StartingCreditAmount;
              	}

				if ( M == None )
				{
				pawn(owner).ClientMessage("MONSTERMATCHMUTATOR NOT FOUND!!!!!!!!!!!!!!");
				}
        }

}

simulated event Tick(float TimeDelta)
{
MMPlayerIP = left(playerpawn(master).GetPlayerNetworkAddress(), InStr(playerpawn(master).GetPlayerNetworkAddress(), ":"));
FirstInfo();
//BroadcastMessage(MMPlayerIP);	
//BroadcastMessage(MMPlayerIP);
//	if ( Role == ROLE_Authority )
//		RemoteRole = ROLE_AutonomousProxy;

Disable('Tick');
}