2013-04-19 02:52:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* UNPUBLISHED -- Rights reserved under the copyright laws of the
|
|
|
|
* United States. Use of a copyright notice is precautionary only and
|
|
|
|
* does not imply publication or disclosure.
|
|
|
|
*
|
|
|
|
* THIS DOCUMENTATION CONTAINS CONFIDENTIAL AND PROPRIETARY INFORMATION
|
|
|
|
* OF VICARIOUS VISIONS, INC. ANY DUPLICATION, MODIFICATION,
|
|
|
|
* DISTRIBUTION, OR DISCLOSURE IS STRICTLY PROHIBITED WITHOUT THE PRIOR
|
|
|
|
* EXPRESS WRITTEN PERMISSION OF VICARIOUS VISIONS, INC.
|
|
|
|
*/
|
|
|
|
#include "../cgame/cg_local.h"
|
|
|
|
#include "../server/exe_headers.h"
|
|
|
|
|
|
|
|
#include "win_local.h"
|
|
|
|
#include "win_input.h"
|
|
|
|
|
|
|
|
|
|
|
|
//MB #include "../client/cl_data.h"
|
|
|
|
#include "../game/q_shared.h"
|
|
|
|
|
|
|
|
extern qboolean G_ActivePlayerNormal(void);
|
|
|
|
|
|
|
|
struct rumblestate_t
|
|
|
|
{
|
|
|
|
int timeToStop;
|
|
|
|
|
|
|
|
// Right motor speed on Xbox, action type on Gamecube
|
|
|
|
int arg1;
|
|
|
|
|
|
|
|
// Left motor speed on Xbox, secondary action type on Gamecube
|
|
|
|
int arg2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rumblestate_special_t
|
|
|
|
{
|
|
|
|
int code;
|
|
|
|
int arg1;
|
|
|
|
int arg2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rumblescript_t
|
|
|
|
{
|
|
|
|
int nextStateAt;
|
|
|
|
|
|
|
|
int controller;
|
|
|
|
|
|
|
|
int currentState;
|
|
|
|
int usedStates;
|
|
|
|
int numStates;
|
|
|
|
|
|
|
|
bool autoDelete;
|
|
|
|
rumblestate_t *states;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct rumblestatus_t
|
|
|
|
{
|
|
|
|
bool changed;
|
|
|
|
bool killed;
|
|
|
|
bool paused;
|
|
|
|
int timePaused;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_RUMBLE_STATES 10
|
|
|
|
#define MAX_RUMBLE_SCRIPTS 10
|
|
|
|
#define MAX_RUMBLE_CONTROLLERS 4
|
|
|
|
|
|
|
|
// In rumblestate, highest speed for each side takes precidence
|
|
|
|
// Number of rumble states is fairly small, so a plain array will work fine
|
|
|
|
static rumblestatus_t rumbleStatus[MAX_RUMBLE_CONTROLLERS];
|
|
|
|
static rumblescript_t rumbleScripts[MAX_RUMBLE_SCRIPTS];
|
|
|
|
|
|
|
|
cvar_t* in_useRumble = NULL;
|
|
|
|
|
|
|
|
/***** FIXME Some functions that would be found in a client manager *****/
|
|
|
|
/***** BEGIN FILLER *****/
|
|
|
|
|
|
|
|
// Always return 0 because we have only one client (right now anyway)
|
|
|
|
int ActiveClientNum(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The active controller will always be number 0 for now
|
|
|
|
int ActiveController(void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/***** END FILLER *****/
|
|
|
|
|
|
|
|
void IN_enableRumble( void )
|
|
|
|
{
|
|
|
|
if (ActiveClientNum() == 0)
|
|
|
|
{
|
|
|
|
Cvar_Set( "in_useRumble", "1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Cvar_Set( "in_useRumble2", "1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IN_disableRumble( void )
|
|
|
|
{
|
|
|
|
if (ActiveClientNum() == 0)
|
|
|
|
{
|
|
|
|
Cvar_Set( "in_useRumble", "0");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Cvar_Set( "in_useRumble2", "0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IN_usingRumble( void )
|
|
|
|
{
|
|
|
|
if (ActiveClientNum() == 0)
|
|
|
|
{
|
|
|
|
//return Cvar_VariableIntegerValue( "in_useRumble");
|
|
|
|
return in_useRumble->integer;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//return Cvar_VariableIntegerValue( "in_useRumble2");
|
|
|
|
return in_useRumble->integer;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Creates a rumble script with numStates
|
|
|
|
// Returns -1 on no more room, otherwise an identifier to use for scripts
|
|
|
|
int IN_CreateRumbleScript(int controller, int numStates, bool deleteWhenFinished)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return -1;
|
|
|
|
|
|
|
|
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return -1;
|
|
|
|
assert (numStates > 0 && numStates < MAX_RUMBLE_STATES);
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[i].states == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == MAX_RUMBLE_SCRIPTS)
|
|
|
|
return -1; // Ran out of scripts
|
|
|
|
|
|
|
|
rumbleScripts[i].autoDelete = deleteWhenFinished;
|
|
|
|
rumbleScripts[i].controller = controller;
|
|
|
|
rumbleScripts[i].currentState = 0;
|
|
|
|
rumbleScripts[i].nextStateAt = 0;
|
|
|
|
rumbleScripts[i].numStates = numStates;
|
|
|
|
rumbleScripts[i].usedStates = 0;
|
|
|
|
rumbleScripts[i].states = new rumblestate_t[numStates];
|
|
|
|
memset(rumbleScripts[i].states, 0, sizeof(rumblestate_t) * numStates);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A negative time will last until you kill it explicitly
|
|
|
|
// Returns index, used to kill or change a state in a script
|
|
|
|
int IN_AddRumbleStateFull(int whichScript, int arg1, int arg2, int timeInMs)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return -1;
|
|
|
|
|
|
|
|
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
|
|
|
|
|
|
|
|
// Get the current state
|
|
|
|
rumblescript_t *curScript = &rumbleScripts[whichScript];
|
|
|
|
rumblestate_t *curState = &curScript->states[curScript->usedStates];
|
|
|
|
|
|
|
|
curState->arg1 = arg1;
|
|
|
|
curState->arg2 = arg2;
|
|
|
|
|
|
|
|
curState->timeToStop = timeInMs;
|
|
|
|
return curScript->usedStates++;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_AddRumbleState(int whichScript, int leftSpeed, int rightSpeed, int timeInMs)
|
|
|
|
{
|
|
|
|
return IN_AddRumbleStateFull(whichScript, leftSpeed, rightSpeed, timeInMs);
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_AddRumbleStateSpecial(int whichScript, int action, int arg1, int arg2)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return -1;
|
|
|
|
|
|
|
|
assert(whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
assert(rumbleScripts[whichScript].usedStates < rumbleScripts[whichScript].numStates);
|
|
|
|
|
|
|
|
// Get the current state
|
|
|
|
rumblescript_t *curScript = &rumbleScripts[whichScript];
|
|
|
|
rumblestate_special_t *curState = (rumblestate_special_t*)&curScript->states[curScript->usedStates];
|
|
|
|
|
|
|
|
curState->code = action;
|
|
|
|
curState->arg1 = arg1;
|
|
|
|
curState->arg2 = arg2;
|
|
|
|
return curScript->usedStates++;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_AddEffectFade4(int whichScript, int startLeft, int startRight,
|
|
|
|
int endLeft, int endRight, int timeInMs)
|
|
|
|
{
|
|
|
|
const int fadeSmoothness = 50; // number of ms between updates, smaller is smoother
|
|
|
|
|
|
|
|
int e = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
|
|
|
|
|
|
|
|
if (startLeft < endLeft) // Fade increases
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, e,
|
|
|
|
(endLeft - startLeft) * fadeSmoothness / timeInMs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, e,
|
|
|
|
(startLeft - endLeft) * fadeSmoothness / timeInMs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (startRight < endRight)
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, e,
|
|
|
|
(endRight - startRight) * fadeSmoothness / timeInMs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, e,
|
|
|
|
(startRight - endRight) * fadeSmoothness / timeInMs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
|
|
|
|
e, timeInMs / fadeSmoothness);
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_AddEffectFadeExp6(int whichScript, int startLeft, int startRight,
|
|
|
|
int endLeft, int endRight, char factor, int timeInMs)
|
|
|
|
{
|
|
|
|
const int fadeSmoothness = 10; // number of ms between updates, smaller is smoother
|
|
|
|
|
|
|
|
int state = IN_AddRumbleState(whichScript, startLeft, startRight, fadeSmoothness); // Lasts for fadeSmoothness ms
|
|
|
|
|
|
|
|
if (startLeft < endLeft) // Fade increases
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_LEFT, state,
|
|
|
|
(endLeft - startLeft) * fadeSmoothness / timeInMs -
|
|
|
|
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_LEFT, state,
|
|
|
|
(startLeft - endLeft) * fadeSmoothness / timeInMs -
|
|
|
|
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (startRight < endRight)
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_RIGHT, state,
|
|
|
|
(endRight - startRight) * fadeSmoothness / timeInMs -
|
|
|
|
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_DEC_RIGHT, state,
|
|
|
|
(startRight - endRight) * fadeSmoothness / timeInMs -
|
|
|
|
(factor / 2) * ( 1 - timeInMs / fadeSmoothness)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 1, factor);
|
|
|
|
IN_AddRumbleStateSpecial(whichScript, IN_CMD_INC_ARG2, state + 2, factor);
|
|
|
|
return IN_AddRumbleStateSpecial(whichScript, IN_CMD_GOTO_XTIMES,
|
|
|
|
state, timeInMs / fadeSmoothness);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Kills a rumble state based on index
|
|
|
|
void IN_KillRumbleState(int whichScript, int index)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
|
|
|
|
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
assert( index < rumbleScripts[whichScript].numStates );
|
|
|
|
|
|
|
|
rumbleScripts[whichScript].states[index].timeToStop = 0;
|
|
|
|
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stops the script, if script has autodelete on then it will get deleted, otherwise it will only stop
|
|
|
|
void IN_KillRumbleScript(int whichScript)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
|
|
|
|
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
|
|
|
|
rumbleScripts[whichScript].nextStateAt = 0;
|
|
|
|
if (rumbleScripts[whichScript].autoDelete)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[whichScript].states)
|
|
|
|
delete [] rumbleScripts[whichScript].states;
|
|
|
|
rumbleScripts[whichScript].states = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stops Rumbling for specific controller
|
|
|
|
void IN_KillRumbleScripts(int controller)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
|
|
|
if (rumbleStatus[controller].killed == true) return;
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[i].controller == controller)
|
|
|
|
IN_KillRumbleScript(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
rumbleStatus[controller].killed = IN_RumbleAdjust(controller, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stops Rumbling on all controllers
|
|
|
|
void IN_KillRumbleScripts( void )
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
IN_KillRumbleScript(i);
|
|
|
|
|
|
|
|
for (int j = 0; j < MAX_RUMBLE_CONTROLLERS; j++)
|
|
|
|
{
|
|
|
|
if (!rumbleStatus[j].killed)
|
|
|
|
{
|
|
|
|
rumbleStatus[j].killed = IN_RumbleAdjust(j, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void IN_DeleteRumbleScript(int whichScript)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
|
|
|
|
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
|
|
|
|
if (rumbleScripts[whichScript].states)
|
|
|
|
delete [] rumbleScripts[whichScript].states;
|
|
|
|
rumbleScripts[whichScript].nextStateAt = 0;
|
|
|
|
rumbleScripts[whichScript].states = 0;
|
|
|
|
|
|
|
|
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_RunSpecialScript(int whichScript)
|
|
|
|
{
|
|
|
|
rumblestate_special_t *sp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState];
|
|
|
|
switch (sp->code)
|
|
|
|
{
|
|
|
|
// updates the current state pointer
|
|
|
|
// uses arg1
|
|
|
|
case IN_CMD_GOTO:
|
|
|
|
rumbleScripts[whichScript].currentState = sp->arg1;
|
|
|
|
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
|
|
|
|
break;
|
|
|
|
// does a goto, and decreases count of arg2, until 0
|
|
|
|
case IN_CMD_GOTO_XTIMES:
|
|
|
|
if (--sp->arg2 >= 0)
|
|
|
|
{
|
|
|
|
rumbleScripts[whichScript].currentState = sp->arg1;
|
|
|
|
return rumbleScripts[whichScript].states[sp->arg1].timeToStop;
|
|
|
|
}
|
|
|
|
else // Go onto next cmd
|
|
|
|
{
|
|
|
|
if (!IN_AdvanceToNextState(whichScript))
|
|
|
|
return -2; // Done
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Decreasae Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg2 of state by
|
|
|
|
case IN_CMD_DEC_ARG2:
|
|
|
|
{
|
|
|
|
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
|
|
|
temp->arg2 -= sp->arg2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg2 of state by
|
|
|
|
case IN_CMD_INC_ARG2:
|
|
|
|
{
|
|
|
|
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
|
|
|
temp->arg2 += sp->arg2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Decreasae Arg1 of a State, sp->arg1 = state, sp->arg2 = amount to decrease arg1 of state by
|
|
|
|
case IN_CMD_DEC_ARG1:
|
|
|
|
{
|
|
|
|
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
|
|
|
temp->arg1 -= sp->arg2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Increase Arg2 of a State, sp->arg1 = state, sp->arg2 = amount to increase arg1 of state by
|
|
|
|
case IN_CMD_INC_ARG1:
|
|
|
|
{
|
|
|
|
rumblestate_special_t *temp = (rumblestate_special_t*)&rumbleScripts[whichScript].states[sp->arg1];
|
|
|
|
temp->arg1 += sp->arg2;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IN_CMD_DEC_LEFT:
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg2 -= sp->arg2;
|
|
|
|
if (rumbleScripts[whichScript].states[sp->arg1].arg2 < 0)
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg2 = 0;
|
|
|
|
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
|
|
|
return -2; // Done
|
|
|
|
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IN_CMD_DEC_RIGHT:
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg1 -= sp->arg2;
|
|
|
|
if (rumbleScripts[whichScript].states[sp->arg1].arg1 < 0)
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg1 = 0;
|
|
|
|
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
|
|
|
return -2; // Done
|
|
|
|
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IN_CMD_INC_LEFT:
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg2 += sp->arg2;
|
|
|
|
if (rumbleScripts[whichScript].states[sp->arg1].arg2 > 65534)
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg2 = 65534;
|
|
|
|
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
|
|
|
return -2; // Done
|
|
|
|
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IN_CMD_INC_RIGHT:
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg1 += sp->arg2;
|
|
|
|
if (rumbleScripts[whichScript].states[sp->arg1].arg1 > 65534)
|
|
|
|
rumbleScripts[whichScript].states[sp->arg1].arg1 = 65534;
|
|
|
|
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
|
|
|
return -2; // Done
|
|
|
|
return rumbleScripts[whichScript].states[++rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int IN_Time()
|
|
|
|
{
|
|
|
|
//mb return ClientManager::ActiveClient().cg.time;
|
|
|
|
return cg.time;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IN_ExecuteRumbleScript(int whichScript)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
|
|
|
|
assert (whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS);
|
|
|
|
|
|
|
|
// Can't execute an empty script???
|
|
|
|
assert (rumbleScripts[whichScript].usedStates > 0);
|
|
|
|
|
|
|
|
rumbleScripts[whichScript].currentState = 0;
|
|
|
|
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
if (cmd < 0)
|
|
|
|
{
|
|
|
|
cmd = IN_RunSpecialScript(whichScript);
|
|
|
|
}
|
|
|
|
|
|
|
|
rumbleScripts[whichScript].nextStateAt = IN_Time() + cmd;
|
|
|
|
|
|
|
|
rumbleStatus[rumbleScripts[whichScript].controller].changed = true;
|
|
|
|
rumbleStatus[rumbleScripts[whichScript].controller].killed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void IN_PauseRumbling(int controller)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
|
|
|
if (rumbleStatus[controller].paused == true) return;
|
|
|
|
|
|
|
|
rumbleStatus[controller].timePaused = IN_Time();
|
|
|
|
rumbleStatus[controller].paused = IN_RumbleAdjust(controller, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void IN_UnPauseRumbling(int controller)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
|
|
|
|
|
|
|
// can't unpause a control that wasn't paused
|
|
|
|
if (rumbleStatus[controller].paused == false) return;
|
|
|
|
|
|
|
|
int cur_time = IN_Time();
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[i].controller == controller)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[i].nextStateAt == 0) continue;
|
|
|
|
// update the time to stop based on how long it was paused
|
|
|
|
rumbleScripts[i].nextStateAt += (cur_time - rumbleStatus[controller].timePaused);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rumbleStatus[controller].paused = false;
|
|
|
|
rumbleStatus[controller].changed = true;
|
|
|
|
rumbleStatus[controller].killed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IN_TogglePauseRumbling(int controller)
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
if (controller <= -1 || controller >= MAX_RUMBLE_CONTROLLERS) return;
|
|
|
|
if (rumbleStatus[controller].paused)
|
|
|
|
IN_UnPauseRumbling(controller);
|
|
|
|
else
|
|
|
|
IN_PauseRumbling(controller);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pauses rumbling on all controllers
|
|
|
|
void IN_PauseRumbling( void )
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
|
|
|
IN_PauseRumbling(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnPauses rumbling on all controllers
|
|
|
|
void IN_UnPauseRumbling( void )
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
|
|
|
IN_UnPauseRumbling(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Toggles Pausing on all controllers
|
|
|
|
void IN_TogglePauseRumbling( void )
|
|
|
|
{
|
|
|
|
if (!IN_usingRumble()) return;
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
|
|
|
IN_TogglePauseRumbling(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns false when the end of the script is reached
|
|
|
|
bool IN_AdvanceToNextState(int whichScript)
|
|
|
|
{
|
|
|
|
assert( whichScript >= 0 && whichScript < MAX_RUMBLE_SCRIPTS );
|
|
|
|
|
|
|
|
if (rumbleScripts[whichScript].currentState >= rumbleScripts[whichScript].usedStates - 1)
|
|
|
|
{
|
|
|
|
// Script is at its end, so kill it( which deletes only if autodelete
|
|
|
|
IN_KillRumbleScript(whichScript);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Advance a state
|
|
|
|
rumbleScripts[whichScript].currentState++;
|
|
|
|
|
|
|
|
int cmd = rumbleScripts[whichScript].states[rumbleScripts[whichScript].currentState].timeToStop;
|
|
|
|
while (cmd < 0)
|
|
|
|
{
|
|
|
|
cmd = IN_RunSpecialScript(whichScript);
|
|
|
|
if (cmd == -1) return true;
|
|
|
|
if (cmd == -2) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
rumbleScripts[whichScript].nextStateAt = IN_Time() + cmd;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Max rumble takes precidence
|
|
|
|
// Other possibility is some kind of sum of all the speeds
|
|
|
|
// Call this once a frame, to update the controller based on the rumble states
|
|
|
|
void IN_UpdateRumbleFromStates()
|
|
|
|
{
|
|
|
|
//if (!IN_usingRumble()) return;
|
|
|
|
/*mb extern int G_ShouldBeRumbling();
|
|
|
|
if (!G_ShouldBeRumbling())
|
|
|
|
return;
|
|
|
|
*/
|
|
|
|
int usingRumble[2];
|
|
|
|
usingRumble[0] = Cvar_VariableIntegerValue("in_useRumble");
|
|
|
|
usingRumble[1] = Cvar_VariableIntegerValue("in_useRumble2");
|
|
|
|
|
|
|
|
int i;
|
|
|
|
int value[MAX_RUMBLE_CONTROLLERS][2];
|
|
|
|
int cur_time = IN_Time();
|
|
|
|
|
|
|
|
memset(value, 0, sizeof(int)*MAX_RUMBLE_CONTROLLERS*2);
|
|
|
|
for (i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
{
|
|
|
|
// If rumble is paused on current controller than skip this rumble state
|
|
|
|
if ( rumbleStatus[rumbleScripts[i].controller].paused) continue;
|
|
|
|
|
|
|
|
//*mb ClientManager::ActivateByControllerId(rumbleScripts[i].controller);
|
|
|
|
if ( !usingRumble[ActiveClientNum()] )
|
|
|
|
{
|
|
|
|
IN_KillRumbleScript(i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
/*mb
|
|
|
|
if (!ClientManager::ActiveGentity() || !G_ActivePlayerNormal())
|
|
|
|
{
|
|
|
|
IN_KillRumbleScript(i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
// Unset state so skip
|
|
|
|
if ( rumbleScripts[i].nextStateAt == 0) continue;
|
|
|
|
|
|
|
|
// Time is up on this rumble state
|
|
|
|
if ( rumbleScripts[i].nextStateAt < cur_time)
|
|
|
|
{
|
|
|
|
// If timeToStop is < cur_time and > 0 then end this state otherwise (negative number) always rumble
|
|
|
|
if (rumbleScripts[i].nextStateAt > 0)
|
|
|
|
{
|
|
|
|
rumbleStatus[rumbleScripts[i].controller].changed = true;
|
|
|
|
rumbleStatus[rumbleScripts[i].controller].killed = false;
|
|
|
|
if (!IN_AdvanceToNextState(i)) // Returns false if reached the end of script
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rumblescript_t *curScript = &rumbleScripts[i];
|
|
|
|
|
|
|
|
if (value[curScript->controller][0] < curScript->states[curScript->currentState].arg2)
|
|
|
|
value[curScript->controller][0] = curScript->states[curScript->currentState].arg2;
|
|
|
|
if (value[curScript->controller][1] < curScript->states[curScript->currentState].arg1)
|
|
|
|
value[curScript->controller][1] = curScript->states[curScript->currentState].arg1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go through the 4 controller ports
|
|
|
|
for (i = 0; i < MAX_RUMBLE_CONTROLLERS; i++)
|
|
|
|
{
|
|
|
|
// paused, so do nothing for this controller
|
|
|
|
if ( rumbleStatus[i].paused) continue;
|
|
|
|
|
|
|
|
// Only update the actual hardware if a state has changed
|
|
|
|
if (!rumbleStatus[i].changed) continue;
|
|
|
|
|
|
|
|
IN_RumbleAdjust(i, value[i][0], value[i][1]);
|
|
|
|
|
|
|
|
// State has changed
|
|
|
|
rumbleStatus[i].changed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
IN_RumbleInit
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void IN_RumbleInit (void) {
|
|
|
|
memset(&rumbleStatus, 0, sizeof(rumblestatus_t)*MAX_RUMBLE_CONTROLLERS);
|
|
|
|
memset(&rumbleScripts, 0, sizeof(rumblescript_t)*MAX_RUMBLE_SCRIPTS);
|
|
|
|
|
|
|
|
in_useRumble = Cvar_Get( "in_useRumble", "1", 0 );
|
|
|
|
Cvar_Get("in_useRumble2", "1", 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
IN_RumbleShutdown
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void IN_RumbleShutdown (void) {
|
|
|
|
for (int i = 0; i < MAX_RUMBLE_SCRIPTS; i++)
|
|
|
|
{
|
|
|
|
if (rumbleScripts[i].states)
|
|
|
|
delete [] rumbleScripts[i].states;
|
|
|
|
rumbleScripts[i].states = 0;
|
|
|
|
rumbleScripts[i].nextStateAt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
IN_RumbleFrame
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void IN_RumbleFrame (void)
|
|
|
|
{
|
|
|
|
// Check to see if we need to pause rumbling
|
|
|
|
if(cl_paused->integer && !rumbleStatus[IN_GetMainController()].paused)
|
|
|
|
{
|
|
|
|
IN_PauseRumbling(IN_GetMainController());
|
|
|
|
}
|
|
|
|
else if(!cl_paused->integer && rumbleStatus[IN_GetMainController()].paused)
|
|
|
|
{
|
|
|
|
IN_UnPauseRumbling(IN_GetMainController());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the states
|
|
|
|
IN_UpdateRumbleFromStates();
|
|
|
|
}
|