CSQC Nexgun Beam

Developer discussion of experimental fixes, changes, and improvements.

Moderators: Nexuiz Moderators, Moderators

CSQC Nexgun Beam

Postby GreEn`mArine » Sun Feb 15, 2009 10:28 am

Hi there,

this is gonna be somewhat technical, if you are not speaking QuakeC and don't know the nex codebase, don't bother contine reading :)

I'm planning 2 things basically for the nexgun beam:

1) First step: draw the nex beam on the client. This is done so that the client can decide between 2 effects for the nexgun beam [question would be: do this for muzzleflash and impact effect, too? I mean replace the effects wih old ones if there are any?]. One would be the old v2.3 effect (effect TE_TEI_G3, apparently still used in minstagib) and the other one the normal, current SVN effect (effect nex_beam).
Although the easiest solution would be to make it a pseudo client-side setting (like in v2.4 times with cl_weaponswitch and cl_nogibs), I'd rather like CSQC to do it so players can have the "old" beam while playing and the new beam when watching a demo and probably recording it to avi.
The main reason why I want to do that at all is for competitive games (ladder and tourneys) to allow the static beam to be used. However, there will be a limitation, so that the players can only use the old (and better visible) nex beam only on servers that enable a new cvar (e.g. g_allow_oldnexbeam or something like that), which would be the case on the ladder and tourney servers, I assume.

Now to the technical part:
In this first step I'm planning to do it like this - please comment if you have objections or better suggestions:
- In order to keep the muzzleflash and the beam in sync (in case of packetloss) the server doesn't do the
pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
and
trailparticles(world, particleeffectnum("nex_beam"), w_shotorg, trace_endpos);
calls anymore, but instead has to send it to the client in a different way. But here comes the problem: Sending data to the client is either done using stats, temp entites or shared entites. Stats and temp entities are out of question, which leaves me at using a shared entitiy. However, a nexbeam is not like a CSQC_Projectile, it is nothing that moves in the air or needs interpolation, and it is not really an "entity" either, it's just a particle-effect. Actually, when packetloss occurs in the moment of the nexgun shot, you will simply not see the shot when using the current code base, which makes sense, as showing the beam LATER (i.e. "too late") would be ridiculous anyway.

This means that I'm looking for suggestions how to transmit the beam data (I'd send the values of w_shotorg, w_shotdir and trace_endpos btw) to the client, and how to deal with packetloss


2) Second step would be to allow the client to predict the nexgun shot and to "simply" draw the beam locally once +attack button is pushed (however, only on servers that use g_antilag 2, because other methods would probably "bend" the nexbeam and leave the player with an untrue representation). However, I'd like to get my first point done first before annoying you guys with this one, as this one won't be trivial either :O
IRC quote:
[kojn] I've been coming a bit more recently
[kojn] she took it the dirty way
GreEn`mArine
Forum addon
 
Posts: 1509
Joined: Tue Feb 28, 2006 9:33 pm
Location: Germany

Postby divVerent » Sun Feb 15, 2009 10:39 am

You should use a TE for this. Look at the TE_CSQC_ZCURVEPARTICLES TE for an example.
1. Open Notepad
2. Paste: ÿþMSMSMS
3. Save
4. Open the file in Notepad again

You can vary the number of "MS", so you can clearly see it's MS which is causing it.
divVerent
Site admin and keyboard killer
 
Posts: 3809
Joined: Thu Mar 02, 2006 4:46 pm
Location: BRLOGENSHFEGLE

Postby GreEn`mArine » Sun Feb 15, 2009 8:45 pm

divVerent wrote:You should use a TE for this. Look at the TE_CSQC_ZCURVEPARTICLES TE for an example.

Thanks for the hint, worked like a charm :)

Now I'm going over to the 2nd point. Here are my thoughts so far, please comment or suggestion improvements:

Only shoot a predicted nexgun shot by intercepting +attack, if:
- g_antilag = 2 (needs to be made a stat)

- cl_predict_nexbeam = 1 (just an idea of how the clientside setting could be called)

- Active weapon is Nexgun

- When you have Cell ammo, and especially if you have >= 5 ammo (actually, g_balance_nex_ammo needs to be transmitted, probably as stat)

- When actually playing, that is, don't do anything when isDemo() returns true or when classname != "player"

- When the nexgun is actually ready to fire (could not be ready to fire due to either weaponswitch in progress or refire time needs be waited for)
--approach 1: transmit both the weaponswitch time and refire time (e.g. via stat ... hell, there a lot of stats by now) and let the client do the logic
--approach 2: the server keeps doing the logic and transmit the point in time when the client is allowed to fire the next shot (again, could be done by transmitting a float via stat), and the client just checks whether time is >= that value


However, even if all that worked, there are still remaining issues:
- in order to be able to predict the shot, the fact must be considered that g_shootfromcenter or g_shootfromeye could be active, so the server must tell the client some sort of offset beforehand
- a client, due to cl_movement, will be "ahead of time" (regarding his position) when moving around, so what exactly would happen if I told the engine to draw a particle beam from my "current" position? would it use the one I see myself at, or the one where I am on the server? And am I actually able to trace the proper end of things, so that I can also draw the nex_impact effect on a wall?
- In case the client decided to draw the nexgun beam on clientside, it will need a working mechanism to decide which one of the nexbeams (send as TE via broadcast, so unreliable) NOT to draw anymore because it already drawed it on the client. My solution for that would be that each nexgun shot has an individual, incrementing ID per client, which means that when the server sends the nexbeam he received to all players, he attaches both the edict number of the player who fired it as well as the incrementing ID of the nexgun shot. However, this means that the client needs to transmit that incrementing number, so I would need to break the common mechanism of how weapons are triggered (w_nex()), which is bad...
If the client compares the edict number of the received nex shot to his own (that also still doesn't work, no idea how to do it) and it matches, he has a look whether the incrementing ID of the nex shot was the ID of the last nexshot he alraedy drew on clientside only, and if it matches, he doesn't draw the nex shot at all, as it was already drawn before.
- Another problem is that I now have to remove the sound() calls from the server that are caused from nex shots and instead attach the edict num of the player who fired it to my TE. However, as I already said, I'm having difficulties to get the sound effect of the nexfire sound to be as it used to be, because transmitting the shooter's edict_num and converting that back to an entity and putting that entity into the sound() call doesn't have the same effect like when I had called "sound(self...), since the sound is now "stationary" and doesn't move with me as a moving player

yeah, many questions, I know ... sorry.
IRC quote:
[kojn] I've been coming a bit more recently
[kojn] she took it the dirty way
GreEn`mArine
Forum addon
 
Posts: 1509
Joined: Tue Feb 28, 2006 9:33 pm
Location: Germany

Postby divVerent » Sun Feb 15, 2009 8:56 pm

GreEn`mArine wrote:Now I'm going over to the 2nd point. Here are my thoughts so far, please comment or suggestion improvements:

Only shoot a predicted nexgun shot by intercepting +attack, if:
- g_antilag = 2 (needs to be made a stat)


No, not a stat. Use a shared entity for this, maybe attach this to the existing ENT_CLIENT_CLIENTINFO.

- cl_predict_nexbeam = 1 (just an idea of how the clientside setting could be called)

- Active weapon is Nexgun


Or MinstaNex, or any other "supported" weapon. Maybe make this part of that per-client shared entity (as in, a flag whether a beam is to be predicted, and which effect index to use for it).

- When you have Cell ammo, and especially if you have >= 5 ammo (actually, g_balance_nex_ammo needs to be transmitted, probably as stat)


That COULD be a stat, but you'll already need a shared ent, so add this too.

- When actually playing, that is, don't do anything when isDemo() returns true or when classname != "player"

- When the nexgun is actually ready to fire (could not be ready to fire due to either weaponswitch in progress or refire time needs be waited for)
--approach 1: transmit both the weaponswitch time and refire time (e.g. via stat ... hell, there a lot of stats by now) and let the client do the logic
--approach 2: the server keeps doing the logic and transmit the point in time when the client is allowed to fire the next shot (again, could be done by transmitting a float via stat), and the client just checks whether time is >= that value


Server MUST do the logic, or you'll have cheaters all over the place soon.

Idea would be:

- a stat that ALWAYS contains the refire time of the current weapon (updated in WeaponFrame).

- the shared entity would contain the following info:
* minimum ammo count of this weapon, or -1 if no beam prediction is to be done
* effect number of beam (short)
* effect number of muzzle flash
* beam shot origin (three coords)

However, even if all that worked, there are still remaining issues:
- in order to be able to predict the shot, the fact must be considered that g_shootfromcenter or g_shootfromeye could be active, so the server must tell the client some sort of offset beforehand


Sure, see above.

- a client, due to cl_movement, will be "ahead of time" (regarding his position) when moving around, so what exactly would happen if I told the engine to draw a particle beam from my "current" position? would it use the one I see myself at, or the one where I am on the server? And am I actually able to trace the proper end of things, so that I can also draw the nex_impact effect on a wall?


No idea.

- In case the client decided to draw the nexgun beam on clientside, it will need a working mechanism to decide which one of the nexbeams (send as TE via broadcast, so unreliable) NOT to draw anymore because it already drawed it on the client. My solution for that would be that each nexgun shot has an individual, incrementing ID per client, which means that when the server sends the nexbeam he received to all players, he attaches both the edict number of the player who fired it as well as the incrementing ID of the nexgun shot. However, this means that the client needs to transmit that incrementing number, so I would need to break the common mechanism of how weapons are triggered (w_nex()), which is bad...
If the client compares the edict number of the received nex shot to his own (that also still doesn't work, no idea how to do it) and it matches, he has a look whether the incrementing ID of the nex shot was the ID of the last nexshot he alraedy drew on clientside only, and if it matches, he doesn't draw the nex shot at all, as it was already drawn before.


Difficult, and you won't be able to solve this perfectly anyway. E.g. what if ammo is too low on the client, you fire and it predicts no beam - but on the server, a cells pack below your feet JUST respawned, so when the input packet gets to the server, you actually ARE able to fire, and do so?

- Another problem is that I now have to remove the sound() calls from the server that are caused from nex shots and instead attach the edict num of the player who fired it to my TE. However, as I already said, I'm having difficulties to get the sound effect of the nexfire sound to be as it used to be, because transmitting the shooter's edict_num and converting that back to an entity and putting that entity into the sound() call doesn't have the same effect like when I had called "sound(self...), since the sound is now "stationary" and doesn't move with me as a moving player


You can't solve this perfectly in csqc, until the player entity is csqc networked too. Forget that part.

Anyway, I suppose you should postpone this second part, and finish the first part (clean up the code, etc.). That way, the first part might become part of the next release, for which I see no hope for the second part.
1. Open Notepad
2. Paste: ÿþMSMSMS
3. Save
4. Open the file in Notepad again

You can vary the number of "MS", so you can clearly see it's MS which is causing it.
divVerent
Site admin and keyboard killer
 
Posts: 3809
Joined: Thu Mar 02, 2006 4:46 pm
Location: BRLOGENSHFEGLE

Postby GreEn`mArine » Sun Feb 15, 2009 11:23 pm

divVerent wrote:You can't solve this perfectly in csqc, until the player entity is csqc networked too. Forget that part.

Anyway, I suppose you should postpone this second part, and finish the first part (clean up the code, etc.). That way, the first part might become part of the next release, for which I see no hope for the second part.

Thanks for all your input!

I agree that it seems to be too complicated to do in the short amount of time left. I uploaded my version of the first feature to the tracker. Do not forget to run that cvar update script please, I didn't manage yet to execute it myself (I'm on windows if that poor excuse fits :P)
IRC quote:
[kojn] I've been coming a bit more recently
[kojn] she took it the dirty way
GreEn`mArine
Forum addon
 
Posts: 1509
Joined: Tue Feb 28, 2006 9:33 pm
Location: Germany

Postby GreEn`mArine » Wed Feb 18, 2009 5:03 pm

Can I assume that my patch gets in until sunday?
IRC quote:
[kojn] I've been coming a bit more recently
[kojn] she took it the dirty way
GreEn`mArine
Forum addon
 
Posts: 1509
Joined: Tue Feb 28, 2006 9:33 pm
Location: Germany


Return to Nexuiz - Development

Who is online

Users browsing this forum: No registered users and 1 guest

cron