Forum

Bitflag doubt

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

Bitflag doubt

Postby Orion » Fri Aug 08, 2008 9:37 pm

Hi, I figured out that a .float variable can't have more than 24 bitflags for it (eg .items), which, you can have a maximum of 11 weapon slots unless if you do hacks, like creating a secondary float for more items.

I'm doing a mod where there's already 15 weapons to choose (including original weapons).

I fixed that health rotting issue which makes it rot down twice or 3x faster when you pick up 2 or more megahealths, and with that fixed IT_SUPERHEALTH isn't needed anymore (in my mod), which I created another constant that has the same number as IT_SUPERHEALTH.

So I got 12 weapon slots. Firstly, I added the 13rd weapon using the original .items float, but this caused problems, it removed the single-barrel shotgun from my inventory and I gained a nailgun plus the new weapon! :shock:

After that I created .items2 variable, and to avoid problems on identifying self.weapon, I didn't change the constant's numbers (I didn't start from 1, 2, 4, 8 and so on).

.items2 is currently storing 4 weapons and a powerup, but as the constant's numbers are different, will it be able to store 24 more items?

Look at the code:

Code: Select all
float IT_RAILGUN = 65536; // same as IT_SUPERHEALTH
float IT_SMARTBOMB = 8388608;
float IT_TRIPLE_SHOTGUN = 16777216;
float IT_EMPATHY = 33554432;
float IT_HOMING_MISSILE = 67108864;
float IT_CHAINGUN = 134217728;
float IT_EMPGUN = 268435456;


These are the new weapon constants.
IT_TRIPLE_SHOTGUN and the other constants below it are all stored in .items2, and they're working well.

But as it start from millions instead of 1, will it be able to store 24 flags?


That's just a little doubt I have, so I don't have to create too many .item# vars. :)
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby Lardarse » Sat Aug 09, 2008 5:39 pm

The highest flag that can be stored is the 8388608 if you are also relying on the 1 being readable. As for just using higher numbers... I think it should work, but I'm not sure. I suggest some thorough testing.

Can I ask why you need to use higher order numbers? Why not just do this:

Code: Select all
float IT2_TRIPLE_SHOTGUN = 1;
float IT2_EMPATHY = 2;
float IT2_HOMING_MISSILE = 4;
float IT2_CHAINGUN = 8;
float IT2_EMPGUN = 16;
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK

Postby Orion » Sat Aug 09, 2008 6:40 pm

I was thinking about that, but as IT_TRIPLE_SHOTGUN number will be 1 (same as IT_SHOTGUN), won't it cause conflicts when changing weapons?
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby Lardarse » Sun Aug 10, 2008 11:32 am

Not if you write your code correctly... :-)

Just remember to check each flag against the correct variable. This is why I suggested to call it IT2_TRIPLE_SHOTGUN, the 2 being a visual aid to memory of which variable it relates to.
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK

Postby Orion » Sun Aug 10, 2008 6:22 pm

Just tried it. I couldn't switch back to the shotgun. :(
I think I should use the millions, but I renamed'em to IT2_ instead of just IT_.
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby Dr. Shadowborg » Sun Aug 10, 2008 6:49 pm

Here's what I would do:

Store weapon inventory in a separate float, ala IT2_TRIPLE_SHOTGUN in .items2 or .items3.

Next, recode your weapon routines (such as W_Attack and W_SetCurrentAmmo) to do something like:

Code: Select all
if(self.weapon == 1) // shotgun
...
if(self.weapon == 11) // Triple Shotgun


And in W_ChangeWeapon, you would do something like:

Code: Select all
if(self.impulse == 1) // Axe
 {
  self.weapon = 1;
 }
...
else if (self.impulse == 30 && (self.items2 & IT2_TRIPLE_SHOTGUN)) // Triple shotgun


Obviously, you'll need to do more than that to W_ChangeWeapon and the rest, but this should point you in the right general direction. If not, let me know and I'll cook up a tutorial. (Actually, it probably wouldn't hurt to cook up a tutorial anyway. Maybe I'll do tutorials for the expo since Hellsmash QSR isn't ready.)
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Orion » Sun Aug 10, 2008 9:21 pm

Hmm...

Afaik, in order to a bitflag work properly it should be 1, 10, 100, 1000 and so on in binary. I opened the calculator here and corverted 11 to binary, which is 1011, and that wouldn't work well I think...

Here's the hacks I did.


Part of weapon_touch() in items.qc:

Code: Select all
else if (self.classname == "weapon_tripleshotgun")
   {
      if (leave && (other.items2 & IT2_TRIPLE_SHOTGUN) )
         return;
      hadammo = other.ammo_rockets;         
      new = IT2_TRIPLE_SHOTGUN;
      other.ammo_shells = other.ammo_shells + 10;
   }
   else if (self.classname == "weapon_homingmissile")
   {
      if (leave && (other.items2 & IT2_HOMING_MISSILE) )
         return;
      hadammo = other.ammo_rockets;         
      new = IT2_HOMING_MISSILE;
      other.ammo_rockets = other.ammo_rockets + 15;
   }
   else if (self.classname == "weapon_chaingun")
   {
      if (leave && (other.items2 & IT2_CHAINGUN) )
         return;
      hadammo = other.ammo_rockets;         
      new = IT2_CHAINGUN;
      other.ammo_shells = other.ammo_shells + 25;
   }
   else if (self.classname == "weapon_empgun")
   {
      if (leave && (other.items2 & IT2_EMPGUN) )
         return;
      hadammo = other.ammo_rockets;         
      new = IT2_EMPGUN;
      other.ammo_cells = other.ammo_cells + 30;
   }

...

if (self.classname == "weapon_tripleshotgun" || self.classname == "weapon_homingmissile"
   || self.classname == "weapon_chaingun" || self.classname == "weapon_empgun")
      other.items2 = other.items2 | new;
   else
      other.items = other.items | new;



I did similar stuff with powerup_touch() and BackpackTouch().


End of W_ChangeWeapon() in weapons.qc:

Code: Select all
if (fl == IT2_TRIPLE_SHOTGUN || fl == IT2_HOMING_MISSILE || fl == IT2_CHAINGUN || fl == IT2_EMPGUN)
   {
      if (!(self.items2 & fl))
      {   // don't have the weapon or the ammo
         sprint (self, "no weapon.\n");
         return;
      }
   }
   else
   {
      if (!(self.items & fl) && fl != IT_HANDGRENADE)
      {   // don't have the weapon or the ammo
         sprint (self, "no weapon.\n");
         return;
      }
   }


I also added parm10 to don't lose the custom weapons in a map change.

These hacks work well, I didn't have any problems with them, but in order not to conflict .weapon, I started these IT2_ floats from millions, unfortunately.
User avatar
Orion
 
Posts: 476
Joined: Fri Jan 12, 2007 6:32 pm
Location: Brazil

Postby Lardarse » Tue Aug 12, 2008 12:25 am

Ahhh yes, I forgot about .weapon

There's no reason why you have to keep using bitflags in .weapon, as I don't think very much code actually depends on it. On second thoughts, I might be wrong, though.
User avatar
Lardarse
 
Posts: 266
Joined: Sat Nov 05, 2005 1:58 pm
Location: Bristol, UK

Postby Dr. Shadowborg » Tue Aug 12, 2008 1:46 am

Lardarse wrote:Ahhh yes, I forgot about .weapon

There's no reason why you have to keep using bitflags in .weapon, as I don't think very much code actually depends on it. On second thoughts, I might be wrong, though.


I can't really think of any reason why you'd need too.

About all that might depend on using bitflags with .weapon is automatic weapon changing stuff, and that's easily rewritten. (If not better yet done away with entirely... :wink: )
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm

Postby Elite_Babe1990 » Mon Aug 25, 2008 5:50 am

Hmmm. Ok?
I may be cte but I can pwn u at halo!
User avatar
Elite_Babe1990
 
Posts: 4
Joined: Thu Aug 14, 2008 10:22 pm

Postby Spike » Wed Aug 27, 2008 8:03 am

Lardarse wrote:There's no reason why you have to keep using bitflags in .weapon, as I don't think very much code actually depends on it. On second thoughts, I might be wrong, though.

The selected weapon on the hud depends upon it.
But the selected weapon is implemented in the client as equality rather than bitflags. Thus you need to keep the same values in there, but can use the integers between the flags if you so choose.
The hud is the only thing that interprets the items and weapons fields (other than sending them - the server mixes items and items2 admittedly).

The engine will shift items2 to the left 23 places and mix it into the items stat if the items2 field is present (which will ignore the serverflags global).
Thus the four runes are present in the items2 bitfield with values: 32, 64, 128, 256. Lower bit values in items2 will never be seen without csqc/rogue/hipnotic. Higher values will be truncated on the server.
You can use this to show posession of these additional weapons, although you cannot show that they are selected without client side stuff.
Spike
 
Posts: 2892
Joined: Fri Nov 05, 2004 3:12 am
Location: UK

Postby Dr. Shadowborg » Wed Aug 27, 2008 4:02 pm

Do'h!

Completely forgot about the damn hud. :oops:
User avatar
Dr. Shadowborg
InsideQC Staff
 
Posts: 1110
Joined: Sat Oct 16, 2004 3:34 pm


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest