// 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; }
// 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); } } }
// 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; } }
// 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(VM_Call( uivm, UI_IS_FULLSCREEN )) { IN_KillRumbleScripts(); return; } int usingRumble[2]; usingRumble[0] = in_useRumble->integer; usingRumble[1] = in_useRumble2->integer; int i; int value[MAX_RUMBLE_CONTROLLERS][2]; int cur_time = IN_Time(); bool canKillScripts = false; 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; canKillScripts = true; if(rumbleScripts[i].nextStateAt == -1) { int cmd = rumbleScripts[i].states[rumbleScripts[i].currentState].timeToStop; rumbleScripts[i].nextStateAt = cur_time + cmd; } // 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; } if(canKillScripts) { if( (cur_time - rumble_timer) > 5000 ) IN_KillRumbleScripts(); } else { rumble_timer = cur_time; } }
void FF_Play(ffFX_e effect) { int s; // script id static int const_rumble[2] = {-1}; // script id for constant rumble int client; // super huge switch for rumble effects switch(effect) { case fffx_AircraftCarrierTakeOff: case fffx_BasketballDribble: case fffx_CarEngineIdle: case fffx_ChainsawIdle: case fffx_ChainsawInAction: case fffx_DieselEngineIdle: case fffx_Jump: s = IN_CreateRumbleScript(IN_GetMainController(), 2, true); if (s != -1) { IN_AddRumbleState(s, 50000, 10000, 200); IN_AddRumbleState(s, 0, 0, 10); IN_ExecuteRumbleScript(s); } break; case fffx_Land: s = IN_CreateRumbleScript(IN_GetMainController(), 2, true); if (s != -1) { IN_AddRumbleState(s, 50000, 10000, 200); IN_AddRumbleState(s, 0, 0, 10); IN_ExecuteRumbleScript(s); } break; case fffx_MachineGun: s = IN_CreateRumbleScript(IN_GetMainController(), 2, true); if (s != -1) { IN_AddRumbleState(s, 56000, 20000, 230); IN_AddRumbleState(s, 0, 0, 10); IN_ExecuteRumbleScript(s); } break; case fffx_Punched: case fffx_RocketLaunch: case fffx_SecretDoor: case fffx_SwitchClick: // used by saber s = IN_CreateRumbleScript(IN_GetMainController(), 1, true); if (s != -1) { IN_AddRumbleState(s, 30000, 10000, 120); IN_ExecuteRumbleScript(s); } break; case fffx_WindGust: case fffx_WindShear: case fffx_Pistol: s = IN_CreateRumbleScript(IN_GetMainController(), 2, true); if (s != -1) { IN_AddRumbleState(s, 50000, 10000, 200); IN_AddRumbleState(s, 0, 0, 10); IN_ExecuteRumbleScript(s); } break; case fffx_Shotgun: case fffx_Laser1: case fffx_Laser2: case fffx_Laser3: case fffx_Laser4: case fffx_Laser5: case fffx_Laser6: case fffx_OutOfAmmo: case fffx_LightningGun: case fffx_Missile: case fffx_GatlingGun: s = IN_CreateRumbleScript(IN_GetMainController(), 2, true); if (s != -1) { IN_AddRumbleState(s, 39000, 0, 220); IN_AddRumbleState(s, 0, 0, 10); IN_ExecuteRumbleScript(s); } break; case fffx_ShortPlasma: case fffx_PlasmaCannon1: case fffx_PlasmaCannon2: case fffx_Cannon: case fffx_FallingShort: case fffx_FallingMedium: s = IN_CreateRumbleScript(IN_GetMainController(), 1, true); if (s != -1) { IN_AddRumbleState(s, 25000,10000, 230); IN_ExecuteRumbleScript(s); } break; case fffx_FallingFar: s = IN_CreateRumbleScript(IN_GetMainController(), 1, true); if (s != -1) { IN_AddRumbleState(s, 32000,10000, 230); IN_ExecuteRumbleScript(s); } break; case fffx_StartConst: client = IN_GetMainController(); if(const_rumble[client] == -1) { const_rumble[client] = IN_CreateRumbleScript(IN_GetMainController(), 9, true); if (const_rumble[client] != -1) { IN_AddEffectFade4(const_rumble[client], 0,0, 50000, 0, 2000); IN_AddRumbleState(const_rumble[client], 50000, 0, 300); IN_AddEffectFade4(const_rumble[client], 50000,50000, 0, 0, 1000); IN_ExecuteRumbleScript(const_rumble[client]); } } break; case fffx_StopConst: client = IN_GetMainController(); if (const_rumble[client] == -1) return; IN_KillRumbleScript(const_rumble[client]); const_rumble[client] = -1; break; default: Com_Printf("No rumble script is defined for fffx_id = %i\n",effect); break; } }