- Added GetPlayerInput() for examining a player's inputs from ACS. Most

buttons are now passed across the network, and there are four new user
  buttons specifically for use with this command. Also defined +zoom
  and +reload for future implementation.

  See http://zdoom.org/files/examples/playerinput.zip for an example.


SVN r1215 (trunk)
This commit is contained in:
Randy Heit 2008-09-13 02:55:45 +00:00
parent 4ffa924929
commit 5cd4604f81
14 changed files with 250 additions and 47 deletions

View file

@ -1,3 +1,8 @@
September 12, 2008
- Added GetPlayerInput() for examining a player's inputs from ACS. Most
buttons are now passed across the network. Also added four user buttons
that are specifically for use with this command.
September 11, 2008
- Fixed: Hexen's fourth weapon pieces did not play the correct pickup sound,
and when they were fully assembled, they did not play the sound across the

View file

@ -116,7 +116,9 @@ FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
Button_Attack, Button_Speed, Button_MoveRight, Button_MoveLeft,
Button_Strafe, Button_LookDown, Button_LookUp, Button_Back,
Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch;
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch,
Button_Zoom, Button_Reload,
Button_User1, Button_User2, Button_User3, Button_User4;
bool ParsingKeyConf;
@ -128,11 +130,16 @@ bool ParsingKeyConf;
FActionMap ActionMaps[] =
{
{ 0x125f5226, &Button_User2, "user2" },
{ 0x1eefa611, &Button_Jump, "jump" },
{ 0x201f1c55, &Button_Right, "right" },
{ 0x20ccc4d5, &Button_Zoom, "zoom" },
{ 0x23a99cd7, &Button_Back, "back" },
{ 0x426b69e7, &Button_Reload, "reload" },
{ 0x4463f43a, &Button_LookDown, "lookdown" },
{ 0x534c30ee, &Button_User4, "user4" },
{ 0x5622bf42, &Button_Attack, "attack" },
{ 0x577712d0, &Button_User1, "user1" },
{ 0x57c25cb2, &Button_Klook, "klook" },
{ 0x59f3e907, &Button_Forward, "forward" },
{ 0x6167ce99, &Button_MoveDown, "movedown" },
@ -143,6 +150,7 @@ FActionMap ActionMaps[] =
{ 0xab2c3e71, &Button_Crouch, "crouch" },
{ 0xb000b483, &Button_Left, "left" },
{ 0xb62b1e49, &Button_LookUp, "lookup" },
{ 0xb6f8fe92, &Button_User3, "user3" },
{ 0xb7e6a54b, &Button_Strafe, "strafe" },
{ 0xd5897c73, &Button_ShowScores, "showscores" },
{ 0xe0ccb317, &Button_Speed, "speed" },

View file

@ -149,7 +149,9 @@ extern FButtonStatus Button_Mlook, Button_Klook, Button_Use, Button_AltAttack,
Button_Attack, Button_Speed, Button_MoveRight, Button_MoveLeft,
Button_Strafe, Button_LookDown, Button_LookUp, Button_Back,
Button_Forward, Button_Right, Button_Left, Button_MoveDown,
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch;
Button_MoveUp, Button_Jump, Button_ShowScores, Button_Crouch,
Button_Zoom, Button_Reload,
Button_User1, Button_User2, Button_User3, Button_User4;
extern bool ParsingKeyConf;
void ResetButtonTriggers (); // Call ResetTriggers for all buttons

View file

@ -76,18 +76,40 @@ typedef enum
//
// Button/action code definitions.
// The net code supports up to 29 buttons, so don't make this longer than that.
//
typedef enum
{
BT_ATTACK = 1, // Press "Fire".
BT_USE = 2, // Use button, to open doors, activate switches.
BT_JUMP = 4,
BT_DUCK = 8, // Unimplemented
BT_TURN180 = 16,
BT_ALTATTACK = 32, // Press your other "Fire".
} buttoncode_t;
BT_ATTACK = 1<<0, // Press "Fire".
BT_USE = 1<<1, // Use button, to open doors, activate switches.
BT_JUMP = 1<<2,
BT_CROUCH = 1<<3,
BT_TURN180 = 1<<4,
BT_ALTATTACK = 1<<5, // Press your other "Fire".
BT_RELOAD = 1<<6, // Not connected to anything at the moment.
BT_ZOOM = 1<<7, // Neither is this.
#define IMP_WEAPONSLOT
// The rest are all ignored by the play simulation and are for scripts.
BT_SPEED = 1<<8,
BT_STRAFE = 1<<9,
BT_MOVERIGHT = 1<<10,
BT_MOVELEFT = 1<<11,
BT_BACK = 1<<12,
BT_FORWARD = 1<<13,
BT_RIGHT = 1<<14,
BT_LEFT = 1<<15,
BT_LOOKUP = 1<<16,
BT_LOOKDOWN = 1<<17,
BT_MOVEUP = 1<<18,
BT_MOVEDOWN = 1<<19,
BT_SHOWSCORES = 1<<20,
BT_USER1 = 1<<21,
BT_USER2 = 1<<22,
BT_USER3 = 1<<23,
BT_USER4 = 1<<24,
} buttoncode_t;
//

View file

@ -200,6 +200,8 @@ public:
APlayerPawn *mo;
BYTE playerstate;
ticcmd_t cmd;
usercmd_t original_cmd;
DWORD original_oldbuttons;
userinfo_t userinfo; // [RH] who is this?
@ -220,8 +222,8 @@ public:
bool centering;
BYTE turnticks;
short oldbuttons;
bool attackdown;
DWORD oldbuttons;
int health; // only used between levels, mo->health
// is used during levels

View file

@ -150,8 +150,30 @@ int UnpackUserCmd (usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream)
if (flags)
{
// We can support up to 29 buttons, using from 0 to 4 bytes to store them.
if (flags & UCMDF_BUTTONS)
ucmd->buttons = ReadByte (stream);
{
DWORD buttons = ucmd->buttons;
BYTE in = ReadByte(stream);
buttons = (buttons & ~0x7F) | (in & 0x7F);
if (in & 0x80)
{
in = ReadByte(stream);
buttons = (buttons & ~(0x7F << 7)) | ((in & 0x7F) << 7);
if (in & 0x80)
{
in = ReadByte(stream);
buttons = (buttons & ~(0x7F << 14)) | ((in & 0x7F) << 14);
if (in & 0x80)
{
in = ReadByte(stream);
buttons = (buttons & ~(0xFF << 21)) | (in << 21);
}
}
}
ucmd->buttons = buttons;
}
if (flags & UCMDF_PITCH)
ucmd->pitch = ReadWord (stream);
if (flags & UCMDF_YAW)
@ -176,6 +198,7 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream)
BYTE *temp = *stream;
BYTE *start = *stream;
usercmd_t blank;
DWORD buttons_changed;
if (basis == NULL)
{
@ -185,10 +208,41 @@ int PackUserCmd (const usercmd_t *ucmd, const usercmd_t *basis, BYTE **stream)
WriteByte (0, stream); // Make room for the packing bits
if (ucmd->buttons != basis->buttons)
buttons_changed = ucmd->buttons ^ basis->buttons;
if (buttons_changed != 0)
{
BYTE bytes[4] = { ucmd->buttons & 0x7F,
(ucmd->buttons >> 7) & 0x7F,
(ucmd->buttons >> 14) & 0x7F,
(ucmd->buttons >> 21) & 0xFF };
flags |= UCMDF_BUTTONS;
WriteByte (ucmd->buttons, stream);
if (buttons_changed & 0xFFFFFF80)
{
bytes[0] |= 0x80;
if (buttons_changed & 0xFFFFC000)
{
bytes[1] |= 0x80;
if (buttons_changed & 0xFFE00000)
{
bytes[2] |= 0x80;
}
}
}
WriteByte (bytes[0], stream);
if (bytes[0] & 0x80)
{
WriteByte (bytes[1], stream);
if (bytes[1] & 0x80)
{
WriteByte (bytes[2], stream);
if (bytes[2] & 0x80)
{
WriteByte (bytes[3], stream);
}
}
}
}
if (ucmd->pitch != basis->pitch)
{
@ -299,13 +353,25 @@ int SkipTicCmd (BYTE **stream, int count)
{
moreticdata = false;
skip = 1;
if (*flow & UCMDF_BUTTONS) skip += 1;
if (*flow & UCMDF_PITCH) skip += 2;
if (*flow & UCMDF_YAW) skip += 2;
if (*flow & UCMDF_FORWARDMOVE) skip += 2;
if (*flow & UCMDF_SIDEMOVE) skip += 2;
if (*flow & UCMDF_UPMOVE) skip += 2;
if (*flow & UCMDF_ROLL) skip += 2;
if (*flow & UCMDF_BUTTONS)
{
if (*++flow & 0x80)
{
if (*++flow & 0x80)
{
if (*++flow & 0x80)
{
++flow;
}
}
}
}
flow += skip;
}
else if (type == DEM_EMPTYUSERCMD)

View file

@ -69,11 +69,10 @@ struct zdemoheader_s {
struct usercmd_s
{
BYTE buttons;
BYTE pad;
DWORD buttons;
short pitch; // up/down
short yaw; // left/right // If you haven't guessed, I just
short roll; // tilt // ripped these from Quake2's usercmd.
short yaw; // left/right
short roll; // "tilt"
short forwardmove;
short sidemove;
short upmove;
@ -92,7 +91,7 @@ enum
UCMDF_FORWARDMOVE = 0x08,
UCMDF_SIDEMOVE = 0x10,
UCMDF_UPMOVE = 0x20,
UCMDF_ROLL = 0x40
UCMDF_ROLL = 0x40,
};
// When changing the following enum, be sure to update Net_SkipCommand()

View file

@ -33,11 +33,6 @@
struct ticcmd_t
{
usercmd_t ucmd;
/*
char forwardmove; // *2048 for move
char sidemove; // *2048 for move
short angleturn; // <<16 for angle delta
*/
SWORD consistancy; // checks for net game
};

View file

@ -531,20 +531,32 @@ void G_BuildTiccmd (ticcmd_t *cmd)
side -= sidemove[speed];
// buttons
if (Button_Attack.bDown)
cmd->ucmd.buttons |= BT_ATTACK;
if (Button_Attack.bDown) cmd->ucmd.buttons |= BT_ATTACK;
if (Button_AltAttack.bDown) cmd->ucmd.buttons |= BT_ALTATTACK;
if (Button_Use.bDown) cmd->ucmd.buttons |= BT_USE;
if (Button_Jump.bDown) cmd->ucmd.buttons |= BT_JUMP;
if (Button_Crouch.bDown) cmd->ucmd.buttons |= BT_CROUCH;
if (Button_Zoom.bDown) cmd->ucmd.buttons |= BT_ZOOM;
if (Button_Reload.bDown) cmd->ucmd.buttons |= BT_RELOAD;
if (Button_AltAttack.bDown)
cmd->ucmd.buttons |= BT_ALTATTACK;
if (Button_User1.bDown) cmd->ucmd.buttons |= BT_USER1;
if (Button_User2.bDown) cmd->ucmd.buttons |= BT_USER2;
if (Button_User3.bDown) cmd->ucmd.buttons |= BT_USER3;
if (Button_User4.bDown) cmd->ucmd.buttons |= BT_USER4;
if (Button_Use.bDown)
cmd->ucmd.buttons |= BT_USE;
if (Button_Jump.bDown)
cmd->ucmd.buttons |= BT_JUMP;
if (Button_Crouch.bDown)
cmd->ucmd.buttons |= BT_DUCK;
if (Button_Speed.bDown) cmd->ucmd.buttons |= BT_SPEED;
if (Button_Strafe.bDown) cmd->ucmd.buttons |= BT_STRAFE;
if (Button_MoveRight.bDown) cmd->ucmd.buttons |= BT_MOVERIGHT;
if (Button_MoveLeft.bDown) cmd->ucmd.buttons |= BT_MOVELEFT;
if (Button_LookDown.bDown) cmd->ucmd.buttons |= BT_LOOKDOWN;
if (Button_LookUp.bDown) cmd->ucmd.buttons |= BT_LOOKUP;
if (Button_Back.bDown) cmd->ucmd.buttons |= BT_BACK;
if (Button_Forward.bDown) cmd->ucmd.buttons |= BT_FORWARD;
if (Button_Right.bDown) cmd->ucmd.buttons |= BT_RIGHT;
if (Button_Left.bDown) cmd->ucmd.buttons |= BT_LEFT;
if (Button_MoveDown.bDown) cmd->ucmd.buttons |= BT_MOVEDOWN;
if (Button_MoveUp.bDown) cmd->ucmd.buttons |= BT_MOVEUP;
if (Button_ShowScores.bDown) cmd->ucmd.buttons |= BT_SHOWSCORES;
// [RH] Scale joystick moves to full range of allowed speeds
if (JoyAxes[JOYAXIS_PITCH] != 0)
@ -1208,7 +1220,8 @@ void G_PlayerReborn (int player)
p->skill = b_skill; //Added by MC:
p->oldbuttons = 255, p->attackdown = true; // don't do anything immediately
p->oldbuttons = ~0, p->attackdown = true; // don't do anything immediately
p->original_oldbuttons = ~0;
p->playerstate = PST_LIVE;
if (gamestate != GS_TITLELEVEL)

View file

@ -2382,6 +2382,77 @@ int DLevelScript::GetActorProperty (int tid, int property)
}
}
enum
{
// These are the original inputs sent by the player.
INPUT_OLDBUTTONS,
INPUT_BUTTONS,
INPUT_PITCH,
INPUT_YAW,
INPUT_ROLL,
INPUT_FORWARDMOVE,
INPUT_SIDEMOVE,
INPUT_UPMOVE,
// These are the inputs, as modified by P_PlayerThink().
// Most of the time, these will match the original inputs, but
// they can be different if a player is frozen or using a
// chainsaw.
MODINPUT_OLDBUTTONS,
MODINPUT_BUTTONS,
MODINPUT_PITCH,
MODINPUT_YAW,
MODINPUT_ROLL,
MODINPUT_FORWARDMOVE,
MODINPUT_SIDEMOVE,
MODINPUT_UPMOVE
};
int DLevelScript::GetPlayerInput(int playernum, int inputnum)
{
player_t *p;
if (playernum < 0)
{
p = activator->player;
}
else if (playernum >= MAXPLAYERS || !playeringame[playernum])
{
return 0;
}
else
{
p = &players[playernum];
}
if (p == NULL)
{
return 0;
}
switch (inputnum)
{
case INPUT_OLDBUTTONS: return p->original_oldbuttons; break;
case INPUT_BUTTONS: return p->original_cmd.buttons; break;
case INPUT_PITCH: return p->original_cmd.pitch; break;
case INPUT_YAW: return p->original_cmd.yaw; break;
case INPUT_ROLL: return p->original_cmd.roll; break;
case INPUT_FORWARDMOVE: return p->original_cmd.forwardmove; break;
case INPUT_SIDEMOVE: return p->original_cmd.sidemove; break;
case INPUT_UPMOVE: return p->original_cmd.upmove; break;
case MODINPUT_OLDBUTTONS: return p->oldbuttons; break;
case MODINPUT_BUTTONS: return p->cmd.ucmd.buttons; break;
case MODINPUT_PITCH: return p->cmd.ucmd.pitch; break;
case MODINPUT_YAW: return p->cmd.ucmd.yaw; break;
case MODINPUT_ROLL: return p->cmd.ucmd.roll; break;
case MODINPUT_FORWARDMOVE: return p->cmd.ucmd.forwardmove; break;
case MODINPUT_SIDEMOVE: return p->cmd.ucmd.sidemove; break;
case MODINPUT_UPMOVE: return p->cmd.ucmd.upmove; break;
default: return 0; break;
}
}
#define NEXTWORD (LittleLong(*pc++))
#define NEXTBYTE (fmt==ACS_LittleEnhanced?getbyte(pc):NEXTWORD)
#define STACK(a) (Stack[sp - (a)])
@ -4946,6 +5017,11 @@ int DLevelScript::RunScript ()
sp -= 1;
break;
case PCD_GETPLAYERINPUT:
STACK(2) = GetPlayerInput (STACK(2), STACK(1));
sp -= 1;
break;
case PCD_PLAYERNUMBER:
if (activator == NULL || activator->player == NULL)
{

View file

@ -553,8 +553,9 @@ public:
PCD_CHECKPLAYERCAMERA, // [TN]
PCD_MORPHACTOR, // [MH]
PCD_UNMORPHACTOR, // [MH]
PCD_GETPLAYERINPUT,
PCODE_COMMAND_COUNT
/*348*/ PCODE_COMMAND_COUNT
};
// Some constants used by ACS scripts
@ -689,6 +690,7 @@ protected:
void SetActorProperty (int tid, int property, int value);
void DoSetActorProperty (AActor *actor, int property, int value);
int GetActorProperty (int tid, int property);
int GetPlayerInput (int playernum, int inputnum);
private:
DLevelScript ();

View file

@ -2455,7 +2455,9 @@ enum
};
FUNC(LS_SetPlayerProperty)
// SetPlayerProperty (who, set, which)
// SetPlayerProperty (who, value, which)
// who == 0: set activator's property
// who == 1: set every player's property
{
int mask = 0;

View file

@ -1955,6 +1955,11 @@ void P_PlayerThink (player_t *player)
player->mo->flags &= ~MF_NOCLIP;
}
cmd = &player->cmd;
// Make unmodified copies for ACS's GetPlayerInput.
player->original_oldbuttons = player->original_cmd.buttons;
player->original_cmd = cmd->ucmd;
if (player->mo->flags & MF_JUSTATTACKED)
{ // Chainsaw/Gauntlets attack auto forward motion
cmd->ucmd.yaw = 0;
@ -1990,7 +1995,10 @@ void P_PlayerThink (player_t *player)
}
// Handle crouching
if (player->cmd.ucmd.buttons & BT_JUMP) player->cmd.ucmd.buttons &= ~BT_DUCK;
if (player->cmd.ucmd.buttons & BT_CROUCH)
{
player->cmd.ucmd.buttons &= ~BT_CROUCH;
}
if (player->morphTics == 0 && player->health > 0 && level.IsCrouchingAllowed())
{
if (!(player->cheats & CF_TOTALLYFROZEN))
@ -1999,9 +2007,9 @@ void P_PlayerThink (player_t *player)
if (crouchdir==0)
{
crouchdir = (player->cmd.ucmd.buttons & BT_DUCK)? -1 : 1;
crouchdir = (player->cmd.ucmd.buttons & BT_CROUCH)? -1 : 1;
}
else if (player->cmd.ucmd.buttons & BT_DUCK)
else if (player->cmd.ucmd.buttons & BT_CROUCH)
{
player->crouching=0;
}
@ -2452,7 +2460,9 @@ void player_t::Serialize (FArchive &arc)
arc << crouchfactor
<< crouching
<< crouchdir
<< crouchviewdelta;
<< crouchviewdelta
<< original_cmd
<< original_oldbuttons;
if (isbot)
{
@ -2486,6 +2496,7 @@ void player_t::Serialize (FArchive &arc)
// If the player reloaded because they pressed +use after dying, we
// don't want +use to still be down after the game is loaded.
oldbuttons = ~0;
original_oldbuttons = ~0;
}
}

View file

@ -54,7 +54,7 @@
// Version identifier for network games.
// Bump it every time you do a release unless you're certain you
// didn't change anything that will affect sync.
#define NETGAMEVERSION 216
#define NETGAMEVERSION 217
// Version stored in the ini's [LastRun] section.
// Bump it if you made some configuration change that you want to
@ -64,7 +64,7 @@
// Protocol version used in demos.
// Bump it if you change existing DEM_ commands or add new ones.
// Otherwise, it should be safe to leave it alone.
#define DEMOGAMEVERSION 0x20C
#define DEMOGAMEVERSION 0x20D
// Minimum demo version we can play.
// Bump it whenever you change or remove existing DEM_ commands.
@ -75,7 +75,7 @@
// SAVESIG should match SAVEVER.
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 1209
#define MINSAVEVER 1215
#if SVN_REVISION_NUMBER < MINSAVEVER
// Never write a savegame with a version lower than what we need