Inside3D!
     

Adding new weapons and binary operations...
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Fri Mar 26, 2010 1:41 am    Post subject: Reply with quote

Well, I have managed to understand the code (it cost me like an entire day to figure out the function Razz ) and installed mathlib.qc in the process, and with some modifications, I finally made the hasWeapon() function:
Code:
/*
============
hasWeapon()
Returns TRUE if the player pl currently has the weapon defined by wepid
============
*/
float(entity pl, float wepid) hasWeapon =
{
   local   float   index, power, bitflag, WEP_INDEX_ARR_COUNT;      //Local variables
   
   index = ceil(wepid/WEAPONS_PER_FLOAT);   // wepid is a non-power-of-2 identifier passed to the function when called
   WEP_INDEX_ARR_COUNT = ceil(WEP_LAST_WEAPON/WEAPONS_PER_FLOAT);   // The maximum amount of elements in itemsArray
   
   if (index < 0 || index >= 3)
   {
      // sanity check: prevent a crash if someone passes in an invalid weapon id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid id passed to hasWeapon(): ");
      bprint(ftos(wepid));
      bprint("\n");
      return FALSE;
   }
   
   power = mod(wepid, WEAPONS_PER_FLOAT);   // power is the remainder between wepid and WEAPONS_PER_FLOAT
   bitflag = pow(2, power);         // now we do 2^power to get the bitflag
   
   return pl.itemsArray[index] & bitflag;   // pl is the player entity
};

Well, the function does his work, although I only get displayed the warning of the "sanity check" no matter what number is entered as wepid. I think this happens because I haven't coded all the weapons yet (I only have 6 of the 50 weapons that my mod is going to have) and I haven't made the function to introduce weapons in the array. But the code is good and compile without problems,

So, I decided to start making the addWeapon() function (to add weapons in the array) in items.qc (above the weapon_touch() function), but I get a nasty error when I compile with FTEQCC:
Code:
//normal log until here
compiling items.qc
in function addWeapon (line 391),
items.qc:410: error: Type Mismatch on array assignment
defs.qc:701: itemsArray is defined here


My addWeapon() function to add weapons in the array is this:
Code:
/*
============
addWeapon()
Allows to add a new weapon in the player's inventory array
============
*/
void(entity pl, float wepid) addWeapon =
{
   local   float   index, power, bitflag, WEP_INDEX_ARR_COUNT;      //Local variables
   
   index = ceil(wepid/WEAPONS_PER_FLOAT);   // wepid is a non-power-of-2 identifier passed to the function when called
   WEP_INDEX_ARR_COUNT = ceil(WEP_LAST_WEAPON/WEAPONS_PER_FLOAT);   // The maximum amount of elements in itemsArray
   
   if (index < 0 || index >= WEP_INDEX_ARR_COUNT)
   {
      // sanity check: prevent a crash if someone passes in an invalid weapon id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid id passed to addWeapon(): ");
      bprint(ftos(wepid));
      bprint("\n");
      return;
   }
   
   power = mod(wepid, WEAPONS_PER_FLOAT);   // power is the remainder between wepid and WEAPONS_PER_FLOAT
   bitflag = pow(2, power);         // now we do 2^power to get the bitflag
   
   pl.itemsArray[index] = pl.itemsArray[index] | bitflag;   //this is the line who gave me the error
};


It seems that a space in an .array can't have as a value another .array, and neither seems to tolerate a normal float. So I'm really lost in here, beacuse it seems that arrays in QuakeC work differently compared to Java arrays (or the problem is that I'm too used to work with Java that doesn't let me learn quickly the QuakeC language). Any help is appreciated.
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Fri Mar 26, 2010 2:41 am    Post subject: Reply with quote

FTEQCC's parser sucks.

QC doesn't support very complex instructions.

field[idx] = foo; is quite tricky really.
It needs to combine the array index and the assignment into a single function call. When its a global, anyway.
when its a field, things get a bit messy.
When it sees
ent.field[idx] = foo;
it interprets it as:
ent.(field[idx] = foo);
Which is not what you want. The error is actually about float-->field, and is technically correct. Its just misparsing it.

To work around, you can do one of:
ent.(field[idx]) = foo;
or
(ent.field[idx]) = foo;
(Basically putting a close bracket before the '=' so the parser doesn't see it until later).
The nexuiz folks chose the former.

I'm poking around in fteqcc as I type this, I should be able to change the parsing so its not so stupid.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Mon Mar 29, 2010 10:06 pm    Post subject: Reply with quote

Thanks Spike, putting pl.itemsArray[index] between parenthesis solved the problem.

Now, I have declared my completed weapons for my mod in defs.qc, and finished both addWeapon() and hasWeapon(). So I decided to put addWeapon() in work adding it in CheatCommand():
Code:
void() CheatCommand =
{
   if (deathmatch || coop)
      return;

   //Adding my new finished weapons
   addWeapon(self, WEP_PISTOL);
   addWeapon(self, WEP_UZI);   

   //Rest of CheatCommand() remains the same
   //...
};

But everytime that I launch my mod in DarkPlaces and put "impulse 9" in the console (to execute CheatCommand), Quake crashes and give me the following error:

(click the image to enlarge it. And yes, I changed the font and the backrground image of the console)

It seems that the pointer of the array is looking for an index outside the bounds of the array, of course I'm just speculating because I don't really know what the error means. It also says something about "statements", I don't know what exactly means with a statement (maybe a line?). But the strangest thing of this error (see my code in the post above) is that only happens when WEP_LAST WEAPON is bigger than 24 (since my mod has 50 weapons it necessarily has to be 51), if i put 24 or less, the game doesn't crash but give me the error of the sanity check ("WARNING: Invalid id passed to hasWeapon(): #"). What I want to know is what the error exactly means and if that "statements" as a reference means that I must look in those functions. Other thing that I'm not sure is if the index count in arrays for QuakeC starts from zero (0,1,2,3,...[like Java]) or from 1 (1,2,3,4,...[like Basic]).


Well, now that I'm thinking (this idea just came into my mind when i'm writing this). I'm now seeing the possibility to transform .itemsArray into a bidimensional array matrix of 10x5 (10 slots with 5 weapons in each slot = 50 weapons), and storing in each bidimensional index a value of true or false to indicate if a weapon is in the inventory of the player. The problem is that I'm not sure if QuakeC can tolerate Booleans. But from what I have seen in the code it seems that QuakeC can interpret 1 as true and 0 as false, or viceversa (I'm not sure, correct me if I'm wrong). So if I do the code it would be something like this:
Declarations in defs.qc:
Code:
float      WEAPONS_PER_CHAIN      = 5;      //Amount of weapons that a slot can handle
.float   itemsArray[10][5];   //Array for declaring Chained Weapons
.float   selWeapon;

hasWeapon() in weapons.qc:
Code:
float(entity pl, float wepid) hasWeapon =
{
   local   float   index_slot, index_weapon, COND_CHECKER;      // Local variables
      
   index_slot = ceil(wepid/WEAPONS_PER_CHAIN);   // index_slot searches for the weapon slot that belongs to each wepid
   index_weapon = mod(wepid/WEAPONS_PER_CHAIN);   // index_weapon searches for the position in each slot that belongs to each weapon
      
   if (index_slot < 0 || index_slot >= 10)
   {
      // sanity check: prevent a crash if someone passes in an invalid slot id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid slot id passed to hasWeapon(): ");
      bprint(ftos(index_slot));
      bprint(" - WEPID: ");
      bprint(ftos(wepid));
      bprint("\n");
      return FALSE;
   }
   if (index_weapon < 0 || index_weapon >= 5)
   {
      // sanity check: prevent a crash if someone passes in an invalid weapon id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid weapon id passed to hasWeapon(): ");
      bprint(ftos(index_weapon));
      bprint(" - WEPID: ");
      bprint(ftos(wepid));
      bprint("\n");
      return FALSE;
   }
   
   COND_CHECKER = 1;      // This is the condition checker - Uses bitwise operations
   return pl.itemsArray[index_slot][index_weapon] & COND_CHECKER;   // This is "supossed" to give TRUE if the weapon exists in the player's inventory
};

addWeapon() in items.qc:
Code:
void(entity pl, float wepid) addWeapon =
{
   local   float   index_slot, index_weapon, COND_CHECKER;      // Local variables
      
   index_slot = ceil(wepid/WEAPONS_PER_CHAIN);   // index_slot searches for the weapon slot that belongs to each wepid
   index_weapon = mod(wepid/WEAPONS_PER_CHAIN);   // index_weapon searches for the position in each slot that belongs to each weapon
      
   if (index_slot < 0 || index_slot >= 10)
   {
      // sanity check: prevent a crash if someone passes in an invalid slot id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid slot id passed to hasWeapon(): ");
      bprint(ftos(index_slot));
      bprint(" - WEPID: ");
      bprint(ftos(wepid));
      bprint("\n");
      return FALSE;
   }
   if (index_weapon < 0 || index_weapon >= 5)
   {
      // sanity check: prevent a crash if someone passes in an invalid weapon id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid weapon id passed to hasWeapon(): ");
      bprint(ftos(index_weapon));
      bprint(" - WEPID: ");
      bprint(ftos(wepid));
      bprint("\n");
      return FALSE;
   }
   
   COND_CHECKER = 1;      // This is the condition checker - Uses bitwise operations
   (pl.itemsArray[index_slot][index_weapon]) = pl.itemsArray[index_slot][index_weapon] | COND_CHECKER;   // This is "supossed" to put TRUE in the weapon's respective slot to indicate the user has that weapon
};

Wow, it looks that I made a very long post. I hope that somebody could read it completely and try to answer some of my questions. Thanks in advance to people that can respond to my post.
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Tue Mar 30, 2010 2:47 am    Post subject: Reply with quote

Don't define double arrays, they will not work. You shouldn't even be able to define them. Define single arrays and multiply one index before adding to the other.
ar[a][b] is equivelent to ar[a*maxb+b] of course.
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Sat Apr 03, 2010 4:23 pm    Post subject: Reply with quote

Well, I think this is my final question in this thread (or I least hope so). This question is for Wazat:

Well, I have both hasWeapon() and addWeapon() working now. I just need to complete selectWeapon() (for selecting weapons in my mod). So, when you said:
Wazat wrote:
Selecting weapons is done with another similar function. The difference is, we want to set the player's .weapon field as well as his .selWeapon field. Remember, we do this to make his HUD look good. How do you decide which weapons light up which numbers? Meh, your choice. You could catalog them by type (explosives go on #6, spread go on #3, etc), by power level (weapons on #3 are weaker than those on #7), etc. Your choice. The main reason to keep the hud functioning is because we are letting the player press a number key multiple times to select a weapon. Highlighting the number key makes it easier for the player to learn which weapon # maps to each player.

I didn't understand you quite well. From what I know setting the .weapons field to one of the original bitfields of Quake's weapons allows you to lit his respective number in the HUD. But what I don't know exactly is how to make .selWeapon field select and equip a determinate weapon. I have working already the HUD's number light up part and the weapons are already cataloged. I just need the final part of the function (since the rest of the function is pretty much the same of the others you showed me) because I don't know exactly how the weapon's change system behave. Any help is appreciated.
Back to top
View user's profile Send private message Visit poster's website
Wazat



Joined: 15 Oct 2004
Posts: 732
Location: Middle 'o the desert, USA

PostPosted: Sun Apr 04, 2010 12:05 am    Post subject: Reply with quote

GaciX 69 wrote:
I didn't understand you quite well. From what I know setting the .weapons field to one of the original bitfields of Quake's weapons allows you to lit his respective number in the HUD. But what I don't know exactly is how to make .selWeapon field select and equip a determinate weapon. I have working already the HUD's number light up part and the weapons are already cataloged. I just need the final part of the function (since the rest of the function is pretty much the same of the others you showed me) because I don't know exactly how the weapon's change system behave. Any help is appreciated.


.weapon has two uses in the original game:
1) The quake engine checks it to update the player's HUD.
2) The QC code checks it to determine which weapon the player is using.

What we're doing is separating out these two uses into separate fields. We have little control over the engine wanting to use .weapon, so we let that one be the HUD controller (note that if you rename .weapon in defs.qc and everywhere else it's used in the code, that works fine. Thus you could rename it to .hudWpn or whatever for clarity). If .weapon is only cosmetic now, that means the QC code should be looking at .selWeapon when it needs to know what weapon the player has equipped, and setting .selWeapon when it wants to change what weapon the player is using. The .weapon var is now only used for the hud, and should never be checked to see what the player is using. This also frees us to use sequential weapon ids with .selWeapon instead of bitflags (this wouldn't work with the hud if we set .weapon this way).

In other words... basically replace .weapon in most places with .selWeapon. So, for example, W_SetCurrentAmmo, W_Attack, W_BestWeapon, and the item touch functions should all be checking .selWeapon (as should any other functions that check .weapon; likewise checking .items for weapons should be done through your new function). I believe W_SetCurrentAmmo is the function responsible for setting up the player's hud on weapon change (it sets the ammo icon for the current weapon), so it's probably where you want to set the player's .weapon (and probably use .weapon no where else).

Beyond that, how your weapon selection works is going to depend on how you're categorizing them and handling the player's button presses. What method did you decide upon?

-Wazat
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Tue Apr 06, 2010 6:26 pm    Post subject: Reply with quote

Wazat wrote:
Beyond that, how your weapon selection works is going to depend on how you're categorizing them and handling the player's button presses. What method did you decide upon?

Well, I'm categorizing the weapons by type, in my mod I'm planning to do 50 weapons, divided in 10 "slots", each number key stores a slot and each slot has 5 weapons to cycle in.

The problem of this is that when I use your implementation for my slots, every time that I use addWeapon() or selectWeapon() for adding or selecting a weapon I get this error:

I also tried transforming .itemsArray into a size of 50 and storing in each index a 1 (for true) or a zero (for false) reflecting if a weapon is present or not (so each wepid has it's own index). The problem is that I get the same error above with my method. About the error, I don't exactly know what it means, maybe is indicating that some variable is pointing to a index outside the array (in the case of your method), or maybe the array is too big (in the case of mine).

Anyway, I'm seriously thinking in moving my progress to CSQC. Everybody say wonderful things about it, and with the big amount of limitations of the standard server-sided QuakeC, I think it might be the best to move for the requirements of my mod. Anyway, while I think if I make the change to CSQC, I will try to fix my problem in the standard Quake source. If I can't fix the bugs in a day or two, I will move to CSQC. I'm setting this personal deadline because I think it's for the best to move to something with less limitations, even if it's not well documented. I'm willing to take the challenge if it's necessary.

By the way, I would like to thank you Wazat for giving me ideas for the problem, and also I'd like to thank to everybody who has taken the time to read or answer this thread. Also, if somebody has an idea to solve my problem with the weapons sort, please post it here. But for now, I'll try to investigate about CSQC and try to fix the error in Wazat's code (if it's possible)...
Back to top
View user's profile Send private message Visit poster's website
Wazat



Joined: 15 Oct 2004
Posts: 732
Location: Middle 'o the desert, USA

PostPosted: Sat Apr 10, 2010 9:13 pm    Post subject: Reply with quote

Looks like the addweapon code is where it crashes. Can you post that function (with the single array code, since double arrays do not work)? And what's being passed into it when you call it (i.e. if it's WEP_UZI, what is WEP_UZI set to?).

Also, how is the itemsArray variable being defined currently?

What this error is saying is that something is trying to access the array out of bounds. For example, if you have an array that is 10 long (can hold items in 0-9), any number at 10 or above and any number below 0 is out of that array's bounds and will cause a crash.

Okay: 0 1 2 3 4 5 6 7 8 9
Bad: 10 or greater, -1 or less.

If you add a bprint to print out some numbers during the course of the function (like its parameters, and the index being used to access the array) that will help you narrow down whats going awry. The error in your console seems to suggest that the index is 5. If your array only goes from 0-4 then that would be the problem. Otherwise something trickier is going on.

-Wazat
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Sat Apr 10, 2010 10:37 pm    Post subject: Reply with quote

Actually, I was suspecting that the function is trying to access out the array's bounds. Anyway, this is my addWeapons() function:
Code:
/*
============
addWeapon()
Allows to add a new weapon in the player's inventory array
Function courtesy of Wazat from Inside3D Forums
============
*/
void(entity pl, float wepid) addWeapon =
{
   local   float   index, LAST_INDEX, COND_CHECKER;      //Local variables
   
   index = (wepid-1);   // wepid is a non-power-of-2 identifier passed to the function when called
   LAST_INDEX = (WEP_LAST_WEAPON);      // Last index in the .itemsArray chain
   
   if (index < 0 || index >= LAST_INDEX)   
   {
      // sanity check: prevent a crash if someone passes in an invalid index id, and print a warning to annoy developer(s) into fixing it.
      bprint("WARNING: Invalid index id passed to addWeapon(): ");
      bprint(ftos(index));
      bprint(" - WEPID: ");
      bprint(ftos(wepid));
      bprint("\n");
      return;
   }
   
   COND_CHECKER = 1;      // This is the condition checker - Uses bitwise operations
   bprint("addWeapon() added a new weapon - WEPID: ");
   bprint(ftos(wepid));
   bprint("\n");
   (pl.itemsArray[index]) = pl.itemsArray[index] | COND_CHECKER;   // pl is the player entity
};


My field declarations in defs.qc:
Code:
float   WEAPONS_PER_FLOAT      = 24;   // Amount of weapons that a float can handle (Chained Weapons stuff)
float   WEAPONS_PER_CHAIN      = 5;   // Amount of weapons that a chain can handle (Chained Weapons stuff)
.float   itemsArray[50];   // Array for declaring Chained Weapons
.float   selWeapon;      // Field for selecting main weapon


And my weapon declarations (used as wepid) in defs.qc (I'm not going to post the entire list, there are 50 weapons in my mod and I don't want to bloat the post):
Code:
float   WEP_FISTS            = 1;
float   WEP_AXE            = 2;
//some weapons
float   WEP_RUGER         = 6;
float   WEP_SV_PISTOL         = 7;
//more weapons
float   WEP_SHOTGUN         = 11;
float   WEP_SUPER_SHOTGUN      = 12;
//more weapons
float   WEP_UZI            = 16;
float   WEP_NAILGUN         = 17;
float   WEP_SUPER_NAILGUN      = 18;
//even more weapons
float   WEP_GRENADE_LAUNCHER   = 28;
float   WEP_ROCKET_LAUNCHER   = 29;
float   WEP_SV_STEYER         = 30;
float   WEP_LIGHTNING         = 31;
//a lot of more weapons
float   WEP_BLASTER         = 50;
float   WEP_LAST_WEAPON      = 50;

These weapons are the ones with I have tested the code, the rest of numbers are just placeholders of weapons that aren't coded yet. I also tried by putting these weapons in secuential order (1,2,3,...). But that doesn't work either and gives me the same error. About the index 5 being the guilty I think that the number belongs to WEP_RUGER (since my code looks for the "wepid-1" index) and that's the first weapon being added in the player's inventory (I made aspecial function to add additional parameters like the addWeapon() functions at the start of the game).

Now I really suspect that something trickier is going on. I have double and triple-checked all the variables and it doesn't work. Even I made the math operations in the function in paper and works as it should, but in the practice the function doesn't work at all.

If you can't find the problem, it doesn't matter now, I've decided to use CSQC to solve this issue (and also I needed to modify the HUD to show all the weapon slots). Anyway I would like to thank you Wazat for helping me with this problem, I've learned a lot while trying to solve this up.
Back to top
View user's profile Send private message Visit poster's website
Wazat



Joined: 15 Oct 2004
Posts: 732
Location: Middle 'o the desert, USA

PostPosted: Sun Apr 11, 2010 12:13 am    Post subject: Reply with quote

The only thing that jumps out at me is:

(pl.itemsArray[index]) = pl.itemsArray[index] | COND_CHECKER; // pl is the player entity

Maybe that should be:

(pl.itemsArray[index]) = (pl.itemsArray[index]) | COND_CHECKER; // pl is the player entity

because of the weird way in with .float arrays are handled.

Anyway, sorry it hasn't been working for you. Good luck!
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
GaciX 69



Joined: 27 Feb 2010
Posts: 11
Location: Chile

PostPosted: Sun Apr 11, 2010 10:42 pm    Post subject: Reply with quote

Wazat wrote:
Maybe that should be:

(pl.itemsArray[index]) = (pl.itemsArray[index]) | COND_CHECKER; // pl is the player entity

because of the weird way in with .float arrays are handled.

Anyway, sorry it hasn't been working for you. Good luck!

No, it doesn't work with that correction either. Now I'm trying to solve this issue in CSQC and I'll comment later if something comes on the way. I really don't need further help from now and I think I can handle things for myself now. Anyway, thanks for the effort and help given to solve this problem.
Back to top
View user's profile Send private message Visit poster's website
Wazat



Joined: 15 Oct 2004
Posts: 732
Location: Middle 'o the desert, USA

PostPosted: Wed Apr 14, 2010 12:05 am    Post subject: Reply with quote

Okay, good luck to you.
_________________
When my computer inevitably explodes and kills me, my cat inherits everything I own. He may be the only one capable of continuing my work.
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming All times are GMT
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group