View previous topic :: View next topic |
Author |
Message |
dayfive

Joined: 10 Nov 2006 Posts: 77
|
Posted: Fri Dec 01, 2006 11:13 am Post subject: Detecting multiple powerups... |
|
|
Ok, so say I wanted to make some code that detects if a player has acquired more than one powerup... what is a way to do this??
ive tried
Code: |
if ((self.items == IT_INVISIBILITY) &&
(self.items == IT_QUAD) &&
(self.items == IT_INVULNERABILITY))
{
sprint (other, "Oh noes! Powerful player running around...\n");
// more code here
}
|
and
Code: |
if ((self.classname == "item_artifact_invisibility") &&
(self.classname == "item_artifact_super_damage") &&
(self.items == "item_artifact_invulnerability"))
{
sprint (other, "Oh noes! Powerful player running around...\n");
// more code here
}
|
and neither work correctly... I'm sure this is a trivial fix, but I'm not sure what the correct way to detect the player's acquired items is..?
any help appreciated! |
|
Back to top |
|
 |
dayfive

Joined: 10 Nov 2006 Posts: 77
|
Posted: Fri Dec 01, 2006 11:13 am Post subject: |
|
|
forgot to mention...
the code above appears in the powerup_touch() function in items.qc, if that helps. |
|
Back to top |
|
 |
Quake Matt

Joined: 05 Jun 2005 Posts: 129
|
Posted: Fri Dec 01, 2006 12:59 pm Post subject: |
|
|
The problem is that 'other' in this context refers to the player, while 'self' refers to the powerup. Because this is the touch function of the powerup, that powerup will be self when the touch function is triggered. Likewise, the player may also have a touch function and, when that's triggered, the player will be self.
Basically, you'll want something like this (not tested!):
Code: | if ((other.items & IT_INVISIBILITY) &&
(other.items & IT_QUAD) &&
(other.items & IT_INVULNERABILITY))
{
bprint ("Oh noes! Powerful player running around...\n");
// more code here
} |
This checks to see if the entity that's touching the item has the three powerups then, if it has, does a bprint (broadcasts message to all players) to let everyone know.
You might also notice that I've replaced the == in the if statement with &. This is because powerups, like most items, are stored in the player entity as bit flags. They work a bit like this:
Code: | IT_Shotgun = 1 = 0001
IT_Super_Shotgun = 2 = 0010
IT_Nailgun = 4 = 0100
IT_Super_Nailgun = 8 = 1000
Bitwise OR: 0001 | 0100 = 0101
Bitwise AND: 1010 & 0011 = 0010 |
So, basically, you can use a single .items variable to store all information on lots of items, since each one only uses a single binary digit. It's probably not worth worrying about it too much yet, but if still need help with this, just ask and we'll explain what we can.
If you wanted to hide the message from the player that's just picked up the item, you'd need to use sprint again, but you'd need to call it once for each other player in the game, not just use 'other'![/code] |
|
Back to top |
|
 |
dayfive

Joined: 10 Nov 2006 Posts: 77
|
Posted: Fri Dec 01, 2006 3:24 pm Post subject: |
|
|
Hi Quake Matt!
Thanks for your reply.
Quake Matt wrote: | The problem is that 'other' in this context refers to the player, while 'self' refers to the powerup. Because this is the touch function of the powerup, that powerup will be self when the touch function is triggered. Likewise, the player may also have a touch function and, when that's triggered, the player will be self.
...
This checks to see if the entity that's touching the item has the three powerups then, if it has, does a bprint (broadcasts message to all players) to let everyone know.
|
so I tried your example and it didn't work out of the box, but what you said makes a lot of sense. A thought occurred that, if you touch the powerup and it checks for all 3, it won't return true unless it's the second powerup of a certain type you get, since you wont actually have all 3 at the instant you touch the third.
This is what ended up working for me based on your suggestions and advice
Code: |
if (((other.items & IT_INVISIBILITY) && (other.items & IT_QUAD)) ||
((other.items & IT_INVISIBILITY) && (other.items & IT_INVULNERABILITY)) ||
((other.items & IT_QUAD) && (other.items & IT_INVULNERABILITY)))
{
bprint (other.netname);
bprint (" has acquired all 3 powerups!\n");
}
|
i'm sure there's a more elegant way to accomplish this, but that's just the first thing i thought of.... if anyone else has a better way, please share!
For the full test example, I was using this (in void() powerup_touch right before "if (deathmatch)")
Code: |
if (((other.items & IT_INVISIBILITY) && (other.items & IT_QUAD)) ||
((other.items & IT_INVISIBILITY) && (other.items & IT_INVULNERABILITY)) ||
((other.items & IT_QUAD) && (other.items & IT_INVULNERABILITY)))
{
bprint (other.netname);
bprint (" has acquired all 3 powerups!\n");
other.invisible_time = 1;
other.invisible_finished = time + 30;
other.invincible_time = 1;
other.invincible_finished = time + 30;
other.super_time = 1;
other.super_damage_finished = time + 30;
}
|
so it basically just resets the timers so all three powerups end at exactly the same time. i tested it in dm3.bsp
thanks again for your help! |
|
Back to top |
|
 |
Preach
Joined: 25 Nov 2004 Posts: 122
|
Posted: Fri Dec 01, 2006 3:33 pm Post subject: |
|
|
Currently the way you have it, the message will go off if the player has two of the three powerups and then touches any powerup. So if they got quad, then pent, then a second quad, the message would go off even though they only have those two powerups. What you could do is put the original check for all three powerups in, but put it further down in powerup_touch, specifically after the line
other.items = other.items | self.items;
At this point the player does have all three items, so you can do the check and it'll succeed. |
|
Back to top |
|
 |
dayfive

Joined: 10 Nov 2006 Posts: 77
|
Posted: Fri Dec 01, 2006 3:46 pm Post subject: |
|
|
Preach wrote: | Currently the way you have it, the message will go off if the player has two of the three powerups and then touches any powerup. So if they got quad, then pent, then a second quad, the message would go off even though they only have those two powerups. What you could do is put the original check for all three powerups in, but put it further down in powerup_touch, specifically after the line
other.items = other.items | self.items;
At this point the player does have all three items, so you can do the check and it'll succeed. |
oh! i see... thanks for pointing this out! i tried your suggestion and it works as expected. i think i understand the concept much better than the first post in this thread.
thank you Preach and Quake Matt! |
|
Back to top |
|
 |
r00k
Joined: 13 Nov 2004 Posts: 483
|
Posted: Sat Dec 02, 2006 6:15 am Post subject: |
|
|
in powerup_touch....
after other.items = other.items | self.item;
add...
Code: |
if (other.items & IT_INVISIBILITY | IT_INVULNERABILITY | IT_QUAD)
{
other.invisible_time = other.invincible_time = other.super_time = 1;
other.invisible_finished = other.invincible_finished = other.super_damage_finished = time + 30;
}
|
 |
|
Back to top |
|
 |
Sajt
Joined: 16 Oct 2004 Posts: 1026
|
Posted: Sat Dec 02, 2006 4:46 pm Post subject: |
|
|
That'll detect if you have any one or more of them...
if ((other.items & IT_INVISIBILITY | IT_INVULNERABILITY | IT_QUAD) == IT_INVISIBILITY | IT_INVULNERABILITY | IT_QUAD)
would be the full solution, equivalent to Preach's solution
Might need more parentheses in there though, not sure. _________________ F. A. Špork, an enlightened nobleman and a great patron of art, had a stately Baroque spa complex built on the banks of the River Labe. |
|
Back to top |
|
 |
|
|
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
|