Skip to content

Commit

Permalink
SERVER/CLIENT: Support for GamePad rumble
Browse files Browse the repository at this point in the history
  • Loading branch information
MotoLegacy committed Jul 1, 2024
1 parent fb31ead commit be9796f
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 124 deletions.
21 changes: 5 additions & 16 deletions source/client/defs/custom.qc
Original file line number Diff line number Diff line change
Expand Up @@ -210,22 +210,11 @@ int stopwatch_round_hr;
int stopwatch_round_isactive;
float stopwatch_round_starttime;

//controller buttons

/*
reference:
0: A
1: B
2: X
3: Y
4: DPAD UP
5: DPAD DOWN
6: DPAD LEFT
7: DPAD RIGHT

*/
float GPActive[32];
float GPButtonHeldBeginTime[24];
//
// GamePad Input Variables
//
float GPButtonHeldBeginTime[24]; // Tracks time button down event is called, to track holding down for different actions.
float last_input_deviceid; // The Device ID of the input hardware that last called CSQC_InputEvent, to target it directly.

string build_datetime;
#define VERSION_STRING "v1.0"
Expand Down
42 changes: 9 additions & 33 deletions source/client/main.qc
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,12 @@ void(float button, string key) setToBind =

noref float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent =
{

if (last_input_deviceid != devid)
print(sprintf("device id swapped to %d\n", last_input_deviceid));

last_input_deviceid = devid;

if (evtype == IE_KEYDOWN) {
switch (scanx) {
case K_GP_A:
Expand Down Expand Up @@ -1068,45 +1074,12 @@ noref float(float evtype, float scanx, float chary, float devid) CSQC_InputEvent
return TRUE;
}
}

// Controller Menu Navigation
if (scanx == K_JOY2) {
GPActive[0] = TRUE;
}

if (scanx == K_JOY4) {
GPActive[1] = TRUE;
}

if (scanx == K_JOY1) {
GPActive[2] = TRUE;
}

}

Input_Movecheck(scanx, 1);

return FALSE;
case IE_KEYUP:

// Controller Menu Navigation
if(in_menu != MENU_NONE) {
if (scanx == K_JOY2) {
GPActive[0] = FALSE;
}

if (scanx == K_JOY4) {
GPActive[1] = FALSE;
}

if (scanx == K_JOY1) {
GPActive[2] = FALSE;
}
}


Input_Movecheck(scanx, 0);

return FALSE;
case IE_MOUSEDELTA:
return FALSE;
Expand Down Expand Up @@ -1192,6 +1165,9 @@ noref void() CSQC_Parse_Event =
screenflash_worktime = 0;
screenflash_starttime = time;
break;
case CSQC_EVENT_RUMBLE:
gp_rumble(last_input_deviceid, readshort(), readshort(), readshort());
break;
case EVENT_WEAPONRECOIL:
local vector rec;
rec_x = readcoord()/5;
Expand Down
14 changes: 0 additions & 14 deletions source/client/menu.qc
Original file line number Diff line number Diff line change
Expand Up @@ -1089,15 +1089,6 @@ void(float index) Update_Button =
}
};

float xd;
void() Controller_UpdateButton =
{
/*if (GPActive[0]) {

}*/
drawstring([0.025*g_width, 0.375*g_height, 0], ftos(GPActive[2]), [g_height * 0.020, g_height * 0.020, 1], [0.8,0.8,0.8], 1, 0);
}

float button_timer;
void(float index, float type) Button_Click =
{
Expand Down Expand Up @@ -2188,9 +2179,4 @@ void() Draw_Menu =
{
Update_Button(i);
}

// TODO - Controller Support
/*if (cvar("in_xinput")) {
Controller_UpdateButton();
}*/
};
3 changes: 3 additions & 0 deletions source/server/ai/zombie_core.qc
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,9 @@ void() zombie_attack2 =
DamageHandler (self.enemy, self, 40, DMG_TYPE_ZOMBIESWIPE);
else
DamageHandler (self.enemy, self, 50, DMG_TYPE_ZOMBIESWIPE);

// Getting hit by Zombies triggers a GamePad rumble.
nzp_rumble(self.enemy, 1000, 1200, 75);
}
}
else return;
Expand Down
16 changes: 16 additions & 0 deletions source/server/clientfuncs.qc
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,22 @@ void(entity target, float color, float duration, float type) nzp_screenflash =
}
};

//
// nzp_rumble(target, low_frequency, high_frequency, duration)
// FTE equivalent of the nzp_rumble builtin.
//
void(entity target, float low_frequency, float high_frequency, float duration) nzp_rumble =
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, CSQC_EVENT_RUMBLE);
WriteShort(MSG_MULTICAST, low_frequency);
WriteShort(MSG_MULTICAST, high_frequency);
WriteShort(MSG_MULTICAST, duration);

msg_entity = target;
multicast('0 0 0', MULTICAST_ONE);
};

#endif // FTE

void(float count) UpdatePlayerCount = {
Expand Down
3 changes: 3 additions & 0 deletions source/server/damage.qc
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ void(entity inflictor, entity attacker, float damage2, float mindamage, float ra
while(distance_y > 10 || distance_y < -10) {
distance_y /= 2;
}

// Give a heavy rumble for feedback of being in explosion vicinity.
nzp_rumble(ent, 1400, 2000, 200);

// apply
ent.punchangle_x = distance_x;
Expand Down
1 change: 1 addition & 0 deletions source/server/defs/standard.qc
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ void (entity who, string name)
void (entity who, float version) nzp_setdoubletapver = #506;
void (entity who, float color, float duration, float type) nzp_screenflash = #507;
void (entity who, float state) nzp_lockviewmodel = #508;
void (entity who, float low_frequency, float high_frequency, float duration) nzp_rumble = #509;

//
// constants
Expand Down
2 changes: 1 addition & 1 deletion source/server/player/player_core.qc
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void() PAnim_EnterDive3 =[ 4, PAnim_EnterDive4 ] {self.frame = 206;}
void() PAnim_EnterDive4 =[ 5, SUB_Null ] {self.frame = 207;}

// Flop from Dive
void() PAnim_Flop =[ 1, PAnim_Flop1 ] {self.frame = 208; self.tp_anim_time = time + 1;}
void() PAnim_Flop =[ 1, PAnim_Flop1 ] {self.frame = 208; self.tp_anim_time = time + 1; nzp_rumble(self, 1000, 1200, 75);}
void() PAnim_Flop1 =[ 2, PAnim_Flop2 ] {self.frame = 209;}
void() PAnim_Flop2 =[ 3, PAnim_Flop3 ] {self.frame = 210;}
void() PAnim_Flop3 =[ 4, SUB_Null ] {self.frame = 211;}
Expand Down
2 changes: 2 additions & 0 deletions source/server/weapons/bouncing_betty.qc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ void() Betty_Drop =
self.animend = W_PlayTakeOut;
self.callfuncat = 0;
self.isBuying = false;

nzp_rumble(self, 1000, 1200, 75);
}

//
Expand Down
16 changes: 13 additions & 3 deletions source/server/weapons/frames_core.qc
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ void () W2_Frame_Update =
}
}
}
PlayWeaponSound(self.weapon, self.weapon2_anim_type, FALSE, self.weapon2frame);

if (PlayWeaponSound(self.weapon, self.weapon2_anim_type, FALSE, self.weapon2frame)) {
// Slight rumble because we triggered a weapon sound
nzp_rumble(self, 1000, 1200, 75);
}
return;
}
else
Expand Down Expand Up @@ -151,11 +155,17 @@ void () W_Frame_Update =
}
}
}
PlayWeaponSound(self.weapon, self.weapon_anim_type, FALSE, self.weaponframe);

if (PlayWeaponSound(self.weapon, self.weapon_anim_type, FALSE, self.weaponframe)) {
// Slight rumble because we triggered a weapon sound
nzp_rumble(self, 1000, 1200, 75);
}

// FIXME: We need a way to play sounds at specific frames for any viewmodel, not just weapons
if (self.weaponmodel == "models/weapons/grenade/v_betty.mdl" && self.weaponframe == 9)
if (self.weaponmodel == "models/weapons/grenade/v_betty.mdl" && self.weaponframe == 9) {
sound (self, CHAN_WEAPON, "sounds/weapons/grenade/prime.wav", 1, ATTN_NORM);
nzp_rumble(self, 1000, 1200, 75);
}
return;
}
else
Expand Down
9 changes: 9 additions & 0 deletions source/server/weapons/weapon_core.qc
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ void() ReturnWeaponModel =
W_SprintStart();

W_ShowCrosshair(self);

// Slight rumble whenever we pull our weapon out again.
nzp_rumble(self, 1000, 1200, 75);
}

void() W_PlayTakeOut =
Expand Down Expand Up @@ -1113,6 +1116,9 @@ void(float side) W_Fire =
startframe = endframe = GetFrame(self.weapon, FIRE_HOLD);
}

// Rumble the GamePad a fixed amount when we fire a weapon.
nzp_rumble(self, 1400, 2000, 200);

// Increment the amount of shots fired while downed
if (self.downed == true)
self.teslacount++;
Expand Down Expand Up @@ -1442,6 +1448,7 @@ void() checkHold =
sound (self, CHAN_WEAPON, "sounds/weapons/grenade/throw.wav", 1, ATTN_NORM);
self.reload_delay2 = self.fire_delay2 = self.reload_delay = self.fire_delay = time + 0.4;
self.throw_delay = time + 0.9;
nzp_rumble(self, 1000, 1200, 75);
}
else
{
Expand Down Expand Up @@ -1476,6 +1483,8 @@ void() W_Grenade =
self.primary_grenades -= 1;
self.reload_delay2 = self.fire_delay2 = self.throw_delay = self.reload_delay = self.fire_delay = time + 6;
self.grenade_delay = time + 5;

nzp_rumble(self, 1000, 1200, 75);
}

void(float wepnum) CheckButton = {
Expand Down
32 changes: 18 additions & 14 deletions source/shared/shared_defs.qc
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,24 @@
// <byte> screenflash_duration
// <byte> screenflash_type

#define EVENT_UPDATE 19
#define EVENT_BLACKOUT 20
#define EVENT_WORLDDATA 21
#define EVENT_PLAYERUPDATE 22
#define EVENT_REVIVEON 23
#define EVENT_REVIVEOFF 24
#define EVENT_REVIVECHANGE 25
#define EVENT_WEAPONRECOIL 26
#define EVENT_GRENADEPULSE 27
#define EVENT_BETTYPROMPT 28
#define EVENT_CHATMESSAGE 29
#define EVENT_DOUBLETAPUPDATE 30
#define EVENT_ENDGAME 31
#define EVENT_MAPTYPE 32
#define CSQC_EVENT_RUMBLE 19 // <short> low_frequency
// <short> high_frequency
// <short> duration

#define EVENT_UPDATE 20
#define EVENT_BLACKOUT 21
#define EVENT_WORLDDATA 22
#define EVENT_PLAYERUPDATE 23
#define EVENT_REVIVEON 24
#define EVENT_REVIVEOFF 25
#define EVENT_REVIVECHANGE 26
#define EVENT_WEAPONRECOIL 27
#define EVENT_GRENADEPULSE 28
#define EVENT_BETTYPROMPT 29
#define EVENT_CHATMESSAGE 30
#define EVENT_DOUBLETAPUPDATE 31
#define EVENT_ENDGAME 32
#define EVENT_MAPTYPE 33

//
// Types of screen-flashes, global.
Expand Down
Loading

0 comments on commit be9796f

Please sign in to comment.