Jump to content

Home

Checking when buttons are up


Fardreamer

Recommended Posts

I'm trying to find the code that checks whether the attack button has been let go of before having been pressed again, i.e., how you can tell the difference between semi- and auto fire modes. The idea is to force a new button press for every saber move. Any ideas where it's located?

Link to comment
Share on other sites

you use 2 things:

 

1) add a qboolean variable in gentity_t struct to set if the client has fired. Set it to true in the function

 

2) in g_active.c put code similar to:

if ( (pm.cmd.buttons & BUTTON_ATTACK) &&

ent->client->ps.pm_type != PM_DEAD && ent->client->fired==qfalse)

{

// your code here to call the firing function

 

this will fire when USE button is pressed.

 

3) in g_active.c: if ( !(pm.cmd.buttons & BUTTON_ATTACK) ) {

fired=qfalse;

}

or similar method.

This may not work, I never tested it, but basically: on first call set a var to true. call subsequent calls only if it is false. on button release set it to false.

Link to comment
Share on other sites

2) in g_active.c put code similar to:

if ( (pm.cmd.buttons & BUTTON_ATTACK) &&

ent->client->ps.pm_type != PM_DEAD && ent->client->fired==qfalse)

{

// your code here to call the firing function

 

Didn't I say that too???

Link to comment
Share on other sites

I was tricked by that too... ucmd.buttons is not client->buttons, it's two different structs. One is everything relevant to the commands a local player is sending and the other is all the info pertaining the client in general. en->client has an oldbuttons value that keeps track of the buttons held down the previous time the function was called.

 

Anyway, I solved it by adding a new player state to pm->ps. Thanks for your help!

Link to comment
Share on other sites

Originally posted by Fardreamer

Anyway, I solved it by adding a new player state to pm->ps. Thanks for your help!

 

Can you elaborate on this a bit Fardreamer...

I want to do a similar thing, but it says in code that you can't add anything to the playerState_t structure. (pm->ps). I tried - it causes a crash when you spawn a player...

 

So what structure did you actually modify? So far, I've been using the eFlags member of the playerState_t, adding my own flag bits, but the eFlags bitfield seems to get reset or otherwise modified, so that I can't be sure the bit I set is going to STAY set...!! :(

Link to comment
Share on other sites

Please ignore my last post. I've just realised my cgame project wasn't creating it's dll in the right place - so I wasn't actually running it!!!!!! *slaps forehead several times!!!*

 

No wonder I was getting strange results...! :)

 

Using eFlags seems to work fine, and are avaliable in both the areas of code previously talked about. (Well - I've got it to work anyway - so...)

Link to comment
Share on other sites

It creates prediction problems? I've been using it up to now and it seems to work fine. Can you elaborate on this?

 

I'm changing the whole system to queue-based: ClientThink_real adds any new button presses to a queue which is a member of playerState_t. The saber code then goes through the queue, each time popping the first one and reacting accordingly.

 

My goal is to have one unique button press per saber move, but to avoid having to time your button presses perfectly. I.e, tapping left-mouse , right-mouse, left-mouse will do a left-to-right, right to-left, left to right three-slash-combo.

Link to comment
Share on other sites

What I wanted to do was bind a 'defensive' mode to the right mouse button. But, I didn't want to hard-code this defensive mode straight to the right mouse button, in case I wanted to dynamically change it, or activate defensive mode from other sources other than user input. So - I wanted a flag which could be set in one place - i.e. the eFlag! :)

 

The existing eFlags are all defines in bg_public.h. (About 1/3 of the way down the file...). They start with these lines:

 

#define EF_DEAD 0x00000001

#define EF_BOUNCE_SHRAPNEL 0x00000002

#define EF_TELEPORT_BIT 0x00000004

 

Note that ones with the comment...

 

//doesn't do anything

 

...above them are free to be used.

 

So, I added a new flag:

 

//RenegadeOfPhunk's new eFlags!! Rock on!

#define ROP_DEFENDING_AGAINST_ENEMY 0x00008000 //Markes that we are currently in defensive mode

 

I then set / unset this flag when the right mouse button is pressed in g_active.c:

 

for ( i = 0 ; i < MAX_CLIENTS ; i++ )

{

if (g_entities.inuse && g_entities.client)

{

pm.bgClients = &g_entities.client->ps;

}

}

 

if(ent->client->buttons & BUTTON_ALT_ATTACK)

{

ent->client->ps.eFlags |= ROP_DEFENDING_AGAINST_ENEMY;

}

else

{

ent->client->ps.eFlags &= ~ROP_DEFENDING_AGAINST_ENEMY;

}

 

if (ent->client->ps.saberLockTime > level.time)

{

 

And then to check whether the flag is set: (e.g. in bg_saber.c - where I've made the player put the saber into the 'defensive' stance when in defensive mode)

 

if (anim == BOTH_WALKBACK1 || anim == BOTH_WALKBACK2)

{ //normal stance when walking backward so saber doesn't look like it's cutting through leg

anim = PM_GetSaberStance();

}

 

if ((pm->ps->eFlags & ROP_DEFENDING_AGAINST_ENEMY) && !(pm->ps->inAirAnim))

{

//For the moment, we want this stance all the time (except when jumping)

//To look like were in a 'defensive' stance while moving

//We might want to embellish this a bit later on...

anim = PM_GetSaberStance();

}

 

Hope that helps. (This seems to work fine for me...)

Link to comment
Share on other sites

what i mean is:

 

if you add another var or change the order of the existing vars, the game WILL go haywire.

 

aka:

// playerState_t is the information needed by both the client and server

// to predict player motion and actions

// nothing outside of pmove should modify these, or some degree of prediction error

// will occur

 

// you can't add anything to this without modifying the code in msg.c

 

 

the above line is true. msg.c is a part of the engine source, which apparently states the server->client and client->server message format. That means, if we change the message size beyond expected, both the server and the client will have trouble getting and parsing the message. Which leads to deadly prediction errors and breaks the game totally.

 

 

You ARE playing with fire here

Link to comment
Share on other sites

Ask - I'm NOT changing ANYTHING about the playerState_t structure - I'm just setting one of the unused bits in the eFlags integer bitfield. How is that playing with fire...?

 

Yes - if I was adding a new var to the structure then it will go wrong. (As I've found out already...). But setting a new eFlag doesn't make it go wrong - I know because I've done it...

Link to comment
Share on other sites

If you add a var to the playerState_t structure, it will compile fine. But the game crashes when you run it - for the reasons that Ask has already pointed out. (Specifically, for me anyway, it crashed when I tried to add a bot to the game...)

 

But setting eFlags DOESN'T actually alter the playerState_t structure, so that's perfectly allowed, and it works...

 

You cannot access the structure you specified (ent->client) from a lot of areas. (Like moving code and saber code) - BUT you can get access to the playerState_t structure from these areas - in the manner I have already specified earlier... (the bg_saber.c example)

Link to comment
Share on other sites

Compile doesn't check for logic errors, I know that. But I'm telling you it actually worked - as in, I played my mod. But it could be buggy when playing with a real opponent as opposed to a bot.

 

In any case, your system won't work for me because I need a message queue which is an array of a new data type I defined.

Link to comment
Share on other sites

If it did run, then I can only assume you didn't try to add a bot or play against other players - 'cos at that point it should crash...

 

And I see that eFlags aren't gonna solve your particular problem. If I start trying to do something like that and I find the answer, I'll be sure to let you know... :)

 

[edit]

Just checked your post again. So you did spawn a bot and you played against it with the playerState_t structure changed..?! Can you please post EXACTLY what changes you made to the structure?

[/edit]

Link to comment
Share on other sites

I added these two lines:

 

struct attack_t saberAttackQueue[ATTACK_QUEUE_LENGTH];

int saberLastAttackTime;

 

which were accessed and modified in ClientThing() and in WeaponLightsaber().

 

How about if added this stuff to pmove_t? Then I could access it from the saber code.

 

edit: that stuff above didn't work properly... what worked was

 

int saberLastAttackTime;

int saberCurrentAttackTime;

 

at the bottom of the struct - that was before I added the queue system. And pmove_t is cleared every frame so I guess that's no good.

Link to comment
Share on other sites

Well, in case you were wondering, I succeeded in implementing the queue by handling all the checking and queueing actions in ClientThink. When a queued attack needs to be executed, it sets an eFlag (as Renegade suggested) that tells the saber code that an attack is pending. The saber code performs the attack and clears this flag. Thanks for your help :)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...