Entity flags aren't being transmitted

Hello!

Last time I posted here I announced a mod called Uber Arena and requested help with an issue regarding ioquake3 compatibility, and the kind folks here helped me out significantly. Since then I have made lots of progress on it, cleaning up a bunch of junk code, adding new features, and even getting featured on ModDB for a short while. So just wanted to give a shout out and a huge thank you to everyone here at the ioquake3 forums.

I’m returning here as I am currently hitting a massive roadblock in regards to transmitting entity flag info from the server to the client. I encountered it a while back, decided to just leave it be and come back to it, hoping that maybe I missed something, but I’m still running into the same problems.

So in bg_public.h there are several definitions for entity flags, and because they’re in a bg file they are, in theory, readable from both the server and client games, which should make them a good way to send information about entity state to the client game. I want to add flags for each uberweapon so I can start adding effects like beeping sounds for homing rockets, different colors for the arc lightning gun / ion plasma bolts, etc.

To test things out, I quickly defined an entity flag:
#define EF_TRANSMIT 0x00200000 // just for testing
The one right before it is 0x00100000, so it follows the hex flag numbering scheme properly.

Then I do a bitwise OR assignment in the Upgrade_Weapon function to turn that flag on.
void Upgrade_Weapon(int counter, gentity_t *other, int steps) {

   other->client->ps.eFlags |= EF_TRANSMIT; // just for testing

...

And a Bitwise AND / check in CG_Missile function:
if (cent->currentState.eFlags & EF_TRANSMIT) {
CG_Printf("can you read this");
}

So the intended outcome of this test is:

  1. Upgrade any weapon into an uberweapon (either with 3x pickup, tuning device, or the /uber cmd - all call the same function Upgrade_Weapon). EF_TRANSMIT is turned on.
  2. Game should print “can you read this” continuously while a missile is in the air, if the person who fired it has an uberweapon, since EF_TRANSMIT should now be on.
    (And I can easily revert this test code since I make regular commits to GitHub)

But, just like my last attempts, nothing happens - the game still refuses to send over the information from the server to the client. Would love to know if anyone has ran into similar struggles in the past, what their solutions were, and why the problem occurs in the first place.

I also heard from ToKu over on the Q3W forums that, apparently, flags beyond 0x00800000 don’t get sent to the client. ToKu mentioned that this was a limitation in the ETQW code, but the Quake 3 source code doesn’t have such a comment. If this limitation does indeed exist in Q3 as well (and just wasn’t documented in the original source for whatever reason), is there a way to increase that limit / work around it within the confines of a user-made mod? I’d need a flag for each uberweapon, which would definitely send it above the client limit (if it exists), and there’s only so many existing flags that I can replace / move around / reuse for different entities without conflicts before I run out of those, too.

Here’s the original Q3W thread for reference:
https://www.quake3world.com/forum/viewtopic.php?f=16&t=53914

I noticed you are setting the EF_TRANSMIT flag in the playerstate, but checking for it in an entity. Does the server code copy the flag from the playerstate into the missile entities somehow? I’m not clear on the mechanic of this.

The number of bits transmitted for eFlags is determined in msg.c, which can’t be changed without changing the engine and protocol.

For Quake 3 it appears to be 19 bits for entities and 16 bits for playerstates (probably no good reason why it’s different). That makes the highest possible value for entity eFlags 0x00080000, which is the same as EF_TEAMVOTED as defined in bg_public.h.

For ET Legacy, it appears to be 24 bits for both, so that would explain the higher values used there.

There are generally two ways to deal with these kind of limitations:

  1. Look for bits either in eFlags or other entity fields that aren’t important and can be “borrowed” or reworked so they are no longer needed for their original purpose
  2. Use trap_SendServerCommand to broadcast updates (like any time a player gains or loses an uberweapon) and process the updates on the client in CG_ServerCommand

For the specific goals in your Q3W post, showing a specific effect when a player/weapon is under the effect of an uberweapon, it seems like that might be possible with only a single eFlag bit that represents the uber status of the current active weapon or the weapon that fired the projectile, instead of a having a separate bit for each type of weapon.

2 Likes

Everything Chomenor said is correct.
Just a sidenote to @EmeraldTiger: At the QW forums I talked about ET, not ETQW. I don’t have any knowledge of ETQW code (idtech4).
For all idtech3 nerds, the most advanced idtech3 code in this case im aware of once more is zturtleman’s Spearmint engine. He changed the eFlags back in 23 Aug 2011 :open_mouth:

1 Like

Thanks so much for your input! Wow so the bit limit is even lower than I thought at first - definitely a good thing to know, and makes one wonder why other Q3 coding sites don’t mention something so important.

I’ll admit that my example wasn’t extremely clear. In the CG_Missile function there is a centity_t struct that is passed into the function from CG_AddCEntity. I moved the print test over to CG_AddCEntity and it is able to read the flags over there, but not in CG_Missile, even though the CG_AddCEntity function is passing that same struct with those flags into CG_Missile, with no changes. I did find a way around it by setting some variable based on the flag and passing that in, and it is able to read that.

I have the code setup now to where it can read if the player is carrying an uberweapon and checks to see what weapon the player is carrying, so I only have to use one new flag (I used 0x00000002, which is used for the prox mine beep in Team Arena, so good opportunity to reuse here). The game should produce a beeping sound whenever a rocket fired from a homing rocket launcher is currently traveling.

To test I spawn in, fire a regular rocket - no beeping sound, good. I then turn it into the homing rocket launcher, and now it makes the beeping sound as expected. But now I go to spawn some bots in the arena, and when they go to fire their own rockets, they also make beeping sounds - even though they don’t have the homing rocket launcher yet. If I switch to another weapon besides the homing rocket launcher their rocket sounds go back to normal, but as long as I have the homing RL carried, any other rocket fired by another player will make the beeping noise, regardless of whether or not it was fired from a homing RL.

Here is the code in g_active to check for uberweapon status / setting flags:

// UBER ARENA 0.4
// Check if current weapon is uber (for client-side uberweapon effects)
// May move out of ClientThink_real for optimization later
if (isUber(ent, ent->client->ps.weapon - 1)) {
ent->client->ps.eFlags |= EF_UBER;
}
else {
ent->client->ps.eFlags &= ~EF_UBER;
}

And here is the code for generating the homing rocket beep noises:

// add beeping noise to homing rockets
// problem: should only affect rockets fired by players carrying the homing RL
// actual effect: makes ALL rockets play the beeping noise as long as you have the homing RL in use
if (isUber == qtrue && cent->currentState.weapon == WP_ROCKET_LAUNCHER) {
vec3_t velocity;

  BG_EvaluateTrajectoryDelta(&cent->currentState.pos, cg.time, velocity);

  trap_S_AddLoopingSound(cent->currentState.number, cent->lerpOrigin, velocity, weapon->beepSound);

}

You should be able to add a flag to the weapon projectile entity on the server to indicate it needs to have a certain graphical/sound effect.

For example, in the standard Quake 3 fire_rocket function you could add something like this:

bolt->s.eFlags |= EF_UBER

Then you could should be able to check for it on the client with something like this:

if(cent->currentState.eFlags & EF_UBER) {…}

Remember both playerState_t and entityState_t have an eFlags field, which despite being named the same and sharing the same flag values are functionally separate in most cases.

1 Like

Thanks so much for your help again guys! Just updated a lot of the uberweapons to use some new effects and they work great.