diff --git a/doomsday/api/api_player.h b/doomsday/api/api_player.h index 7e53304a33..722eab90a7 100644 --- a/doomsday/api/api_player.h +++ b/doomsday/api/api_player.h @@ -40,6 +40,8 @@ enum { CTL_MODIFIER_2 = 7, CTL_MODIFIER_3 = 8, CTL_MODIFIER_4 = 9, + CTL_LOOK_PITCH = 10, ///< Determines look pitch as absolute value. + CTL_LOOK_YAW = 11, ///< Additional look yaw angle. CTL_FIRST_GAME_CONTROL = 1000 }; @@ -105,8 +107,10 @@ typedef struct { float offset[2]; } ddpsprite_t; +#define LOOKDIRMAX 110.0f // 85 degrees + /// Player lookdir (view pitch) conversion to degrees. @ingroup player -#define LOOKDIR2DEG(x) ((x) * 85.0/110.0) +#define LOOKDIR2DEG(x) ((x) * 85.0f/LOOKDIRMAX) /// Player lookdir (view pitch) conversion to radians. @ingroup player #define LOOKDIR2RAD(x) (LOOKDIR2DEG(x)/180*PI) @@ -170,6 +174,14 @@ DENG_API_TYPEDEF(Player) void (*NewControl)(int id, controltype_t type, const char* name, const char* bindContext); + /** + * Determines if a control has been bound to anything. + * + * @param playerNum Console/player number. + * @param control Control id. + */ + int (*IsControlBound)(int playerNum, int control); + void (*GetControlState)(int playerNum, int control, float* pos, float* relativeOffset); int (*GetImpulseControlState)(int playerNum, int control); @@ -185,6 +197,7 @@ DENG_API_T(Player); #define DD_GetPlayer _api_Player.GetPlayer #define P_NewPlayerControl _api_Player.NewControl #define P_GetControlState _api_Player.GetControlState +#define P_IsControlBound _api_Player.IsControlBound #define P_GetImpulseControlState _api_Player.GetImpulseControlState #define P_Impulse _api_Player.Impulse #endif diff --git a/doomsday/api/apis.h b/doomsday/api/apis.h index d7481352b7..dcfcc4c501 100644 --- a/doomsday/api/apis.h +++ b/doomsday/api/apis.h @@ -108,7 +108,8 @@ enum { DE_API_MATERIAL_ARCHIVE = DE_API_MATERIAL_ARCHIVE_v1, DE_API_PLAYER_v1 = 1500, // 1.10 - DE_API_PLAYER = DE_API_PLAYER_v1, + DE_API_PLAYER_v2 = 1501, // 1.13 + DE_API_PLAYER = DE_API_PLAYER_v2, DE_API_PLUGIN_v1 = 1600, // 1.10 DE_API_PLUGIN = DE_API_PLUGIN_v1, diff --git a/doomsday/client/src/ui/p_control.cpp b/doomsday/client/src/ui/p_control.cpp index 6182129d6f..483c24f936 100644 --- a/doomsday/client/src/ui/p_control.cpp +++ b/doomsday/client/src/ui/p_control.cpp @@ -333,6 +333,32 @@ void P_MaintainControlDoubleClicks(int playerNum, int control, float pos) } #endif // __CLIENT__ +#undef P_IsControlBound +DENG_EXTERN_C int P_IsControlBound(int playerNum, int control) +{ +#ifdef __CLIENT__ + struct bcontext_s* bc = 0; + struct dbinding_s* binds = 0; + playercontrol_t* pc = P_PlayerControlById(control); + + // Check that this is really a numeric control. + DENG_ASSERT(pc); + DENG_ASSERT(pc->type == CTLT_NUMERIC || pc->type == CTLT_NUMERIC_TRIGGERED); + + // Bindings are associated with the ordinal of the local player, not + // the actual console number (playerNum) being used. That is why + // P_ConsoleToLocal() is called here. + binds = B_GetControlDeviceBindings(P_ConsoleToLocal(playerNum), control, &bc); + + // Is this not an empty list? + return binds && binds->next != binds; +#else + DENG_UNUSED(playerNum); + DENG_UNUSED(control); + return 0; +#endif +} + #undef P_GetControlState DENG_EXTERN_C void P_GetControlState(int playerNum, int control, float* pos, float* relativeOffset) { @@ -344,8 +370,8 @@ DENG_EXTERN_C void P_GetControlState(int playerNum, int control, float* pos, flo playercontrol_t* pc = P_PlayerControlById(control); // Check that this is really a numeric control. - assert(pc); - assert(pc->type == CTLT_NUMERIC || pc->type == CTLT_NUMERIC_TRIGGERED); + DENG_ASSERT(pc); + DENG_ASSERT(pc->type == CTLT_NUMERIC || pc->type == CTLT_NUMERIC_TRIGGERED); // Ignore NULLs. if(!pos) pos = &tmp; diff --git a/doomsday/client/src/world/p_players.cpp b/doomsday/client/src/world/p_players.cpp index 25810814d1..16d85b251b 100644 --- a/doomsday/client/src/world/p_players.cpp +++ b/doomsday/client/src/world/p_players.cpp @@ -189,6 +189,7 @@ DENG_EXTERN_C Smoother *Net_PlayerSmoother(int player); // p_control.c DENG_EXTERN_C void P_NewPlayerControl(int id, controltype_t type, char const *name, char const *bindContext); +DENG_EXTERN_C int P_IsControlBound(int playerNum, int control); DENG_EXTERN_C void P_GetControlState(int playerNum, int control, float *pos, float *relativeOffset); DENG_EXTERN_C int P_GetImpulseControlState(int playerNum, int control); DENG_EXTERN_C void P_Impulse(int playerNum, int control); @@ -201,6 +202,7 @@ DENG_DECLARE_API(Player) = Net_PlayerSmoother, DD_GetPlayer, P_NewPlayerControl, + P_IsControlBound, P_GetControlState, P_GetImpulseControlState, P_Impulse