Do I need self.value in CSQC?
Moderator: InsideQC Admins
11 posts
• Page 1 of 1
Do I need self.value in CSQC?
Let's make an example without introduction this time.
Let's say I create a code for a pickup weapon in SSQC. Once picked up, I set
In this case, in SSQC, the field is mandatory because in multiplayer the server needs to know which player picked up the rifle.
But, if I send a multicast to csqc
and then, in csqc I read it
In this case I used a simple float pickupRifle. Or should I use a field .pickupRifle? Does CSQC automatically handle only selected player so I don't need to struggle to let the engine knows which player is currently active? It's a question I'm asking myself in these days!
Let's say I create a code for a pickup weapon in SSQC. Once picked up, I set
- Code: Select all
if(other.classname=="player"){
other.pickupRifle = TRUE;
}
In this case, in SSQC, the field is mandatory because in multiplayer the server needs to know which player picked up the rifle.
But, if I send a multicast to csqc
- Code: Select all
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_PICKUPTAKEN);
WriteShort(MSG_MULTICAST, other.pickupRifle);
multicast('0 0 0', MULTICAST_ONE);
and then, in csqc I read it
- Code: Select all
if(byte == PE_PICKUPTAKEN){
pickupRifle = readshort();
}
In this case I used a simple float pickupRifle. Or should I use a field .pickupRifle? Does CSQC automatically handle only selected player so I don't need to struggle to let the engine knows which player is currently active? It's a question I'm asking myself in these days!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Do I need self.value in CSQC?
global float will do fine.
Client Side QuakeC is handling things from the perspective of the client. that is the player seated at the game.
you can still use entities, you can even create one to hold all your player variables if you so desire.
but if you have RIFLE_USED; the other players games wont be able to override your variable, its local to you.
Client Side QuakeC is handling things from the perspective of the client. that is the player seated at the game.
you can still use entities, you can even create one to hold all your player variables if you so desire.
but if you have RIFLE_USED; the other players games wont be able to override your variable, its local to you.
-

gnounc - Posts: 424
- Joined: Mon Apr 06, 2009 6:26 am
Re: Do I need self.value in CSQC?
That was exactly what I wanted to know! Thanks a lot, gnounc!gnounc wrote:Client Side QuakeC is handling things from the perspective of the client. that is the player seated at the game.
So, in this case, the only method I could use, to share this piece of information with the other clients, would be to send it to server with sendevent, right (I'm usigin FTE)?but if you have RIFLE_USED; the other players games wont be able to override your variable, its local to you.
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Do I need self.value in CSQC?
As a rule of thumb, if you are creating a multiplayer game, the server stills being the right place to the core logic. CSQC won't change this (mostly).
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Re: Do I need self.value in CSQC?
So, you're saying that CSQC should be considered only as a "destination point", not a "sharing point" with SSQC?
But let's take this example. I'm hadling all the skeletal stuff to CSQC (for obvious reason), so, animations, weapon models(not shooting behaviours) are handled client side. And inputs to control them are handled client side too, through InputEvent.
Now, if I write in my player_predraw function something like that:
I then add entity to view through
in the predraw.
or
in UpdateView, it's the same.
The skeletal run animation is handled correctly, also with body splitting and bla bla, but now, how CSQC should propagate to other clients (through server) the new animation of player X ?
Should I write some code or it's handled automatically but CSQC? This last part always wondered me!
But let's take this example. I'm hadling all the skeletal stuff to CSQC (for obvious reason), so, animations, weapon models(not shooting behaviours) are handled client side. And inputs to control them are handled client side too, through InputEvent.
Now, if I write in my player_predraw function something like that:
- Code: Select all
player.frame = runAnimation;
I then add entity to view through
- Code: Select all
PREDRAW_AUTOADD
in the predraw.
or
- Code: Select all
addentity(player);
in UpdateView, it's the same.
The skeletal run animation is handled correctly, also with body splitting and bla bla, but now, how CSQC should propagate to other clients (through server) the new animation of player X ?
Should I write some code or it's handled automatically but CSQC? This last part always wondered me!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Do I need self.value in CSQC?
if you might be tracking multiple such values at the same time then its going to have to be a field.
if there can be only one, then you can get away with using a global (and thereby save some field space).
think of it in terms of ownership. who owns the value? if its a field, then the owner is the entity that its a field of. and if its a global? then its singular and owned by the entire local csprogs - and as such can only be used for the local player's entity.
as a general rule, if its an animation thing, then you're going to want to be animating all players (us+them) with roughly the same code, and will thus need to use fields in order to stop them fighting over ownership/meaning.
you should not trust any csqc module for anything but user inputs (due to bots+hacks+cheats), and thus you should be determining frames based only upon snapshots from the ssqc (or your local csqc's prediction of said snapshots). for foot sync, using only the .origin+.angle should really be needed (you can determine if the player is onground etc with traceboxes based upon the player's origin, while frame1time can be updated based upon distance traveled instead of sliding on the ground when they're trying to run into a wall), with the ssqc's .frame or whatever just controlling the torso's animations.
splitscreen makes things more complicated. :s
if there can be only one, then you can get away with using a global (and thereby save some field space).
think of it in terms of ownership. who owns the value? if its a field, then the owner is the entity that its a field of. and if its a global? then its singular and owned by the entire local csprogs - and as such can only be used for the local player's entity.
as a general rule, if its an animation thing, then you're going to want to be animating all players (us+them) with roughly the same code, and will thus need to use fields in order to stop them fighting over ownership/meaning.
you should not trust any csqc module for anything but user inputs (due to bots+hacks+cheats), and thus you should be determining frames based only upon snapshots from the ssqc (or your local csqc's prediction of said snapshots). for foot sync, using only the .origin+.angle should really be needed (you can determine if the player is onground etc with traceboxes based upon the player's origin, while frame1time can be updated based upon distance traveled instead of sliding on the ground when they're trying to run into a wall), with the ssqc's .frame or whatever just controlling the torso's animations.
splitscreen makes things more complicated. :s
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: Do I need self.value in CSQC?
toneddu2000 wrote:So, you're saying that CSQC should be considered only as a "destination point", not a "sharing point" with SSQC?
Hence the "client" in CSQC.
toneddu2000 wrote:But let's take this example. I'm hadling all the skeletal stuff to CSQC (for obvious reason), so, animations, weapon models(not shooting behaviours) are handled client side. And inputs to control them are handled client side too, through InputEvent.
Of course skeletal animations and VFX in general are much better handled client side.
But when you say "inputs to control them are handled client side too, through InputEvent"... Well, everyone needs to know you are walking or jumping or firing a weapon, then this should be informed by the server to the clients.
So, TL;DR:
- if what I am doing concerns *ONLY* to my client in the sense it won't affect the game state for other players, it's okay (and likely better) to be handled by CSQC;
- otherwise, SSQC is the way to go.
toneddu2000 wrote:The skeletal run animation is handled correctly, also with body splitting and bla bla, but now, how CSQC should propagate to other clients (through server) the new animation of player X ?
The answer is: it should NOT. Remember, the server MUST BE authoritative regarding game state. Player movement is a (very important) game state, therefore should "happen" in the server side first (trigggered by a client input), and only then "displayed" client side (using all the bells and whistles CSQC provides to the modder/developer).
(Unless you are entirely dropping the server part and going to a peer-to-peer approach. If that's the case then good luck, you will need it.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Re: Do I need self.value in CSQC?
Ok, at this point I wanted to arrive! This phrase littelarlly explains what I was thinking but this other phrase:Spike wrote:think of it in terms of ownership. who owns the value? if its a field, then the owner is the entity that its a field of. and if its a global? then its singular and owned by the entire local csprogs - and as such can only be used for the local player's entity.
Spike wrote:as a general rule, if its an animation thing, then you're going to want to be animating all players (us+them) with roughly the same code, and will thus need to use fields in order to stop them fighting over ownership/meaning.
it sounds like as it'd put in contraddiction the first one. I mean, if I'm animating a player in CSQC, I'm animating the local one! Or not? I can't control in CSQC a different player than the local one. I think, at least.
a code like
- Code: Select all
if (self.entnum == player_localentnum){
playerActive = self;
//self.renderflags = RF_EXTERNALMODEL;
}
For me, in CSQC, it doesn't make any sense because " I " should be the local player ( or active player as you want to call it)! But if you don't put that code in playerpredraw, when 2 clients connect, one of them "encroaches" the other's view.
So, actually, in this case, the use of field is mandatory I guess.
Well, I must say, splitscreen helped to find errors in code that probably I'd left untouched because "on single player works flawless"! But, when I create a server and connect 2 clients...bang!Spike wrote:splitscreen makes things more complicated. :s
IMPORTANT NOTE TO SPIKE: I think I found a bug in FTE: when you launch the dedicated server and the map loaded has meshcollide surfaceparm on it, server crashes!
I see.. I only asked because when once I said "So, CSQC can only be used for HUD and pure player stuff?" gnounc said: "NO, it's not like that!"frag.machine wrote:Hence the "client" in CSQC.
So I guess that I was understimating and misunderstanting real potentialities of CSQC.
I see. In my test code only the "weapon fire trigger" is handled by CSQC, the rest is SSQC (but when a bullet particle explodes, that part I manage it in CSQC). Should I completely remove it and rewrite also that part in SSQC, or at least that part is "safe"?frag.machine wrote:But when you say "inputs to control them are handled client side too, through InputEvent"... Well, everyone needs to know you are walking or jumping or firing a weapon, then this should be informed by the server to the clients.
Ok, clear.frag.machine wrote:The answer is: it should NOT. Remember, the server MUST BE authoritative regarding game state. Player movement is a (very important) game state, therefore should "happen" in the server side first (trigggered by a client input), and only then "displayed" client side (using all the bells and whistles CSQC provides to the modder/developer).
Thanks a lot guys! Now I've a lot of material to study on!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Do I need self.value in CSQC?
OK, now I studied!
This concept literally drives me crazy. Let's just use an example to demonstrate if I'm stupid or if this is a limit of CSQC.
DISCLAIMER: I use FTE. Dunno if this procedure is replicable on DP. Last time I took a look, CSQC_ParseEvent wasn't present in dpextensions.qc
Let's imagine we want to play a fire animation in CSQC (no, you don't want it, YOU MUST DO IT in CSQC, because, server side, you cannot split skeleton for upper / lower part)
I first used something like this
SERVER SIDE - weapons
SERVER SIDE - send stuff
CLIENT SIDE - main
CLIENT SIDE - player
If I start only a client, I can see my shadow changing animation so it works. BUT.. if I connect two clients to my local server, I position the two clients, facing each other, when I press fire only the other player in my own screen will change animation, but, in the other screen, the player I see (that is the one who pressed fire) remains still.
I also used .shot field instead of a float, both in SSQC and CSQC - I also tried MULTICAST_ONE instead of MULTICAST_ALL - same results.
********WORKING METHOD
INSTEAD, if I use .shot field in ssqc and, instead of using CSQC_ParseEvent I use SendEntity in PutClientServer and sending all the fields I need to update (.origin,.angles,.velocity,etc) and I add self.shot at the list,
and in CSQC_EntUpdate I add
Then in the client side animation
If I connect 2 clients, now I can see the other client in THE OTHER screen play fire animaion when I, in my own screen, press mouse button. Perfect, now IT WORKS.
This is exactly same issue I posted here. But, back then, I wasn't so sure of the mechanism.And, even back then, the solution was to use CSQC_EntUpdate instead of CSQC_ParseEvent. Now I could say I'm becoming more confident with CSQC so I now there's nothing I made wrong in the testing part. So, there are 2 possibilities:
DISCLAIMER: I use FTE. Dunno if this procedure is replicable on DP. Last time I took a look, CSQC_ParseEvent wasn't present in dpextensions.qc
Let's imagine we want to play a fire animation in CSQC (no, you don't want it, YOU MUST DO IT in CSQC, because, server side, you cannot split skeleton for upper / lower part)
I first used something like this
SERVER SIDE - weapons
- Code: Select all
void MyWeaponFireFunc()
{
if(time < self.weaponRefireTime){
SendCsShotOn();
return;
}
else{
SendCsShotOff();
}
}
SERVER SIDE - send stuff
- Code: Select all
void SendCsShotOn()
{
msg_entity = self;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_WEAPONSHOT);
WriteByte(MSG_MULTICAST, 1);
multicast(self.origin, MULTICAST_ALL);
}
void SendCsShotOff()
{
msg_entity = self;
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, PE_WEAPONSHOT);
WriteByte(MSG_MULTICAST, 0);
multicast(self.origin, MULTICAST_ALL);
}
CLIENT SIDE - main
- Code: Select all
noref void() CSQC_Parse_Event =
{
local float rb = readbyte();
if(rb == PE_WEAPONSHOT){
weaponShot = readbyte();
}
}
CLIENT SIDE - player
- Code: Select all
void PlayerAnimFire()
{
if(weaponShot == 1){
self.frame = animFireShotgun;
}
else{
self.frame = animFireShotgunIdle;
}
}
If I start only a client, I can see my shadow changing animation so it works. BUT.. if I connect two clients to my local server, I position the two clients, facing each other, when I press fire only the other player in my own screen will change animation, but, in the other screen, the player I see (that is the one who pressed fire) remains still.
I also used .shot field instead of a float, both in SSQC and CSQC - I also tried MULTICAST_ONE instead of MULTICAST_ALL - same results.
********WORKING METHOD
INSTEAD, if I use .shot field in ssqc and, instead of using CSQC_ParseEvent I use SendEntity in PutClientServer and sending all the fields I need to update (.origin,.angles,.velocity,etc) and I add self.shot at the list,
- Code: Select all
float SendPlayerData (entity playerent, float changedflags)
{
//entity
WriteByte(MSG_ENTITY, ENT_PLAYER);
//movements
WriteCoord(MSG_ENTITY, self.origin_x);
WriteCoord(MSG_ENTITY, self.blabla
//frame
WriteByte(MSG_ENTITY, self.frame);
//
WriteByte(MSG_ENTITY, self.shot);
return TRUE;
}
and in CSQC_EntUpdate I add
- Code: Select all
void CSQC_Ent_Update (float isnew)
{
local float i = readbyte();
if (i == ENT_PLAYER){
//read here all send values from client.c in ssqc
//movements
self.origin_x = readcoord();
self.blabla
//frame
self.frame = readbyte();
//
self.shot = readbyte();
//all the remaining stuff
}
}
Then in the client side animation
- Code: Select all
void PlayerAnimFire()
{
if(self.shot == 1){
self.frame = animFireShotgun;
self.frame1time += frametime;
}
else{
self.frame = animFireShotgunIdle;
self.frame1time += frametime;
}
skel_build(self.skeletonindex, self, self.modelindex, 0, bSpine2, bHolsterL, 1);
}
If I connect 2 clients, now I can see the other client in THE OTHER screen play fire animaion when I, in my own screen, press mouse button. Perfect, now IT WORKS.
This is exactly same issue I posted here. But, back then, I wasn't so sure of the mechanism.And, even back then, the solution was to use CSQC_EntUpdate instead of CSQC_ParseEvent. Now I could say I'm becoming more confident with CSQC so I now there's nothing I made wrong in the testing part. So, there are 2 possibilities:
- This is not the right method to parse an event for a specific client
- CSQC_ParseEvent is not made for sending client-specific data
Please CSQC Gurus, help me! So I can update fteskel project soon! There are a lot of updates to bake!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
Re: Do I need self.value in CSQC?
CSQC_Parse_Event events have no intrinsic relationship to any entity. you can send an entity index to the client, but the client possibly won't know what you're talking about (if the entity is not within that client's pvs at the time - there's always lag and resends that can give you problems like this). this is why there's a writeentity(), but only a readentitynum() that needs a separate lookup against entnum field, eg {entity e = find(world, entnum, readentitynum()); if (!e) panic();}
this might be fine if its a regular thing like an animation, but you're probably better off just transfering some field like .origin is transferred.
writing to a global when refering to the state of a single entity is dangerous - if your code uses the same global for every entity, that global will necissarily affect every entity that uses it. hence why it bugs out in that they're all affected.
you CAN use CSQC_Parse_Event for throwaway things like spawning particle effects in some weird crazy pattern, you can use it to update the client's hud, or update global state, but affecting a single entity is typically going to be unreliable.
this might be fine if its a regular thing like an animation, but you're probably better off just transfering some field like .origin is transferred.
writing to a global when refering to the state of a single entity is dangerous - if your code uses the same global for every entity, that global will necissarily affect every entity that uses it. hence why it bugs out in that they're all affected.
you CAN use CSQC_Parse_Event for throwaway things like spawning particle effects in some weird crazy pattern, you can use it to update the client's hud, or update global state, but affecting a single entity is typically going to be unreliable.
- Spike
- Posts: 2892
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: Do I need self.value in CSQC?
Wow, thanks Spike for the super quick reply!!
So, what should I use to keep track of entity fields in a reliable way? CSQC_EntUpdate()? Can you please explain self.SendEntity and self.SendFlags a little more? Because I only use them with player entity (self.SendEntity in the PutClientInServer() and self.SendFlags = FULLSEND; in PlayerPostThink(), otherwise player is blocked at middle air)but I really cannot say how I understood how it works and where it's possible to use it. I tried to send also non-player entities (like monsters) with this method but I always failed because I didn't know where to call self.SendEntity self.SendFlags.
For example I needed to add (following your leads of course, I didn't invent it
)
to call, after
Why that define it's not in the extensions? What does that statement mean?
Thanks a lot Spike for your big help!!
Yeah, I tried also using a field but with no luck either.Spike wrote:writing to a global when refering to the state of a single entity is dangerous - if your code uses the same global for every entity, that global will necissarily affect every entity that uses it. hence why it bugs out in that they're all affected.
That's was exactly the answer I was waiting for! Thanks!Spike wrote:you CAN use CSQC_Parse_Event for throwaway things like spawning particle effects in some weird crazy pattern, you can use it to update the client's hud, or update global state, but affecting a single entity is typically going to be unreliable.
So, what should I use to keep track of entity fields in a reliable way? CSQC_EntUpdate()? Can you please explain self.SendEntity and self.SendFlags a little more? Because I only use them with player entity (self.SendEntity in the PutClientInServer() and self.SendFlags = FULLSEND; in PlayerPostThink(), otherwise player is blocked at middle air)but I really cannot say how I understood how it works and where it's possible to use it. I tried to send also non-player entities (like monsters) with this method but I always failed because I didn't know where to call self.SendEntity self.SendFlags.
For example I needed to add (following your leads of course, I didn't invent it
- Code: Select all
#define FULLSEND 0xffffff
to call, after
- Code: Select all
self.SendFlags = FULLSEND;
Why that define it's not in the extensions? What does that statement mean?
Thanks a lot Spike for your big help!!
Meadow Fun!! - my first commercial game, made with FTEQW game engine
- toneddu2000
- Posts: 1352
- Joined: Tue Feb 24, 2009 4:39 pm
- Location: Italy
11 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest