1
0
mirror of synced 2024-12-01 01:37:23 +01:00
FFBArcadePlugin/Game Files/WMMT5.cpp
Aaron M ea7f30935c Make every game plugin have Running Thread etc
Makes rumble work correctly and stop for each and every game plus other enhancements, also removed Teknoparrot class file etc and just added code to TP games cpp files directly. Removed LastForStop
2019-11-01 18:30:36 +13:00

332 lines
12 KiB
C++

/*This file is part of FFB Arcade Plugin.
FFB Arcade Plugin is free software : you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FFB Arcade Plugin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FFB Arcade Plugin.If not, see < https://www.gnu.org/licenses/>.
*/
#include <string>
#include "WMMT5.h"
#include "SDL.h"
static EffectTriggers* myTriggers;
static EffectConstants* myConstants;
static Helpers* myHelpers;
static SDL_Event e;
static UINT8 oldgear = 0;
static bool init = false;
static bool gameFfbStarted = false;
static wchar_t* settingsFilename = TEXT(".\\FFBPlugin.ini");
static int SpringStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("SpringStrength"), 100, settingsFilename);
static int FrictionStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("FrictionStrength"), 0, settingsFilename);
static int JointsAndStripesStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("JointsAndStripesStrength"), 100, settingsFilename);
static int CollisionsStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("CollisionsStrength"), 100, settingsFilename);
static int TiresSlipStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("TiresSlipStrength"), 100, settingsFilename);
static int HighSpeedVibrationsStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("HighSpeedVibrationsStrength"), 100, settingsFilename);
static int LimitBetweenHighSpeedVibrationsAndTiresSlip = GetPrivateProfileInt(TEXT("Settings"), TEXT("LimitBetweenHighSpeedVibrationsAndTiresSlip"), 75, settingsFilename);
static int GearChangeStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("GearChangeStrength"), 20, settingsFilename);
static int GearChangeDelay = GetPrivateProfileInt(TEXT("Settings"), TEXT("GearChangeDelay"), 250, settingsFilename);
static int GearChangeLength = GetPrivateProfileInt(TEXT("Settings"), TEXT("GearChangeLength"), 200, settingsFilename);
static int WheelSpinStrength = GetPrivateProfileInt(TEXT("Settings"), TEXT("WheelSpinStrength"), 100, settingsFilename);
static int ShowButtonNumbersForSetup = GetPrivateProfileInt(TEXT("Settings"), TEXT("ShowButtonNumbersForSetup"), 0, settingsFilename);
static int ForceFullTune = GetPrivateProfileInt(TEXT("Settings"), TEXT("ForceFullTune"), 0, settingsFilename);
static int DisableRaceTimer = GetPrivateProfileInt(TEXT("Settings"), TEXT("DisableRaceTimer"), 0, settingsFilename);
static int EnableForceFinish = GetPrivateProfileInt(TEXT("Settings"), TEXT("EnableForceFinish"), 0, settingsFilename);
static int EnableForceTimeUp = GetPrivateProfileInt(TEXT("Settings"), TEXT("EnableForceTimeUp"), 0, settingsFilename);
static int ForceFinishButton = GetPrivateProfileInt(TEXT("Settings"), TEXT("ForceFinishButton"), 99, settingsFilename);
static int ForceTimeUpButton = GetPrivateProfileInt(TEXT("Settings"), TEXT("ForceTimeUpButton"), 99, settingsFilename);
static int InputThread(void *ptr)
{
if (1 != EnableForceFinish && 1 != EnableForceTimeUp)
{
return 0;
}
myHelpers->log("starting input thread");
while (SDL_WaitEvent(&e) != 0)
{
if (e.type == SDL_JOYBUTTONDOWN)
{
myHelpers->log("button pressed");
if (1 == EnableForceFinish && e.jbutton.button == ForceFinishButton)
{
INT_PTR ptr1 = myHelpers->ReadIntPtr(0x199A468, true);
myHelpers->WriteByte(ptr1 + 0x28, 8, false);
}
else if (1 == EnableForceTimeUp && e.jbutton.button == ForceTimeUpButton)
{
int tempDisableRaceTimer = DisableRaceTimer;
DisableRaceTimer = 0;
myHelpers->WriteFloat32(0x199AE18, 0, true);
if (1 == tempDisableRaceTimer)
{
Sleep(10000);
DisableRaceTimer = tempDisableRaceTimer;
}
}
}
}
myHelpers->log("input thread stopped");
return 0;
}
static int SpamThread(void* ptr)
{
if (1 != ForceFullTune && 1 != DisableRaceTimer)
{
return 0;
}
Sleep(5000); // To avoid crashes
myHelpers->log("starting spam thread");
while (1)
{
if (1 == ForceFullTune)
{
INT_PTR ptr1 = myHelpers->ReadIntPtr(0x1948F10, true);
INT_PTR ptr2 = myHelpers->ReadIntPtr(ptr1 + 0x180 + 0xa8 + 0x18, false);
UINT8 car = myHelpers->ReadByte(ptr2 + 0x2C, false);
std::string msg = "car: " + std::to_string(car);
myHelpers->log((char*)msg.c_str());
if (0x00 < car)
{
UINT8 power = myHelpers->ReadByte(ptr2 + 0x98, false);
UINT8 handling = myHelpers->ReadByte(ptr2 + 0x9C, false);
msg = "power: " + std::to_string(power) + " | handling: " + std::to_string(handling);
myHelpers->log((char*)msg.c_str());
if (0x20 != (power + handling))
{
myHelpers->log("forcing full tune");
myHelpers->WriteByte(ptr2 + 0x98, 0x10, false);
myHelpers->WriteByte(ptr2 + 0x9C, 0x10, false);
}
}
}
if (1 == DisableRaceTimer)
{
myHelpers->WriteFloat32(0x199AE18, 999.99, true);
}
Sleep(500); // We don't need to spam too much
}
myHelpers->log("spam thread stopped");
return 0;
}
static int GearChangeThread(void* ptr)
{
if (GearChangeDelay > 0)
{
Sleep(GearChangeDelay);
}
myHelpers->log("gear change");
double percentForce = GearChangeStrength / 100.0;
myTriggers->Sine(GearChangeLength, GearChangeLength, percentForce);
myTriggers->Rumble(0, percentForce, 150);
return 0;
}
static int RunningThread(void* ptr)
{
int cnt;
for (cnt = 0; cnt >= 0; ++cnt)
{
if (!init)
{
init = true;
SDL_CreateThread(InputThread, "InputThread", (void*)NULL);
SDL_CreateThread(SpamThread, "SpamThread", (void*)NULL);
}
float spring = myHelpers->ReadFloat32(0x196F18C, true);
float friction = myHelpers->ReadFloat32(0x196F190, true);
float collisions = myHelpers->ReadFloat32(0x196F194, true);
float tiresSlip = myHelpers->ReadFloat32(0x196F188, true);
int speed = myHelpers->ReadInt32(0x196FEBC, true);
std::string msg = "spring: " + std::to_string(spring) + " | friction: " + std::to_string(friction)
+ " | collisions: " + std::to_string(collisions) + " | tires slip: " + std::to_string(tiresSlip)
+ " | speed: " + std::to_string(speed);
myHelpers->log((char*)msg.c_str());
double percentForce;
if (0.001 > spring && !gameFfbStarted)
{
myHelpers->log("fake spring+friction until game's FFB starts");
percentForce = 0.3 * SpringStrength / 100.0;
myTriggers->Spring(percentForce);
percentForce = 0.5 * FrictionStrength / 100.0;
myTriggers->Friction(percentForce);
}
else
{
if (!gameFfbStarted)
{
myHelpers->log("game's FFB started");
gameFfbStarted = true;
}
percentForce = (1.0 * spring) * SpringStrength / 100.0;
myTriggers->Spring(percentForce);
percentForce = (1.0 * friction) * FrictionStrength / 100.0;
myTriggers->Friction(percentForce);
}
if (0 < collisions)
{
if (0.209 <= collisions && 0.311 >= collisions)
{
myHelpers->log("joint/stripe on the right");
percentForce = (1.0 * collisions) * JointsAndStripesStrength / 100.0;
myTriggers->Sine(80, 80, percentForce);
myTriggers->Rumble(0, percentForce, 150);
}
else
{
myHelpers->log("collision on the right");
percentForce = (1.0 * collisions) * CollisionsStrength / 100.0;
myTriggers->Constant(myConstants->DIRECTION_FROM_RIGHT, percentForce);
myTriggers->Rumble(0, percentForce, 150);
}
}
else if (0 > collisions)
{
if (-0.209 >= collisions && -0.311 <= collisions)
{
myHelpers->log("joint/stripe on the left");
percentForce = (1.0 * collisions) * JointsAndStripesStrength / 100.0;
myTriggers->Sine(80, 80, percentForce);
myTriggers->Rumble(0, -1.0 * percentForce, 150);
}
else
{
myHelpers->log("collision on the left");
percentForce = (-1.0 * collisions) * CollisionsStrength / 100.0;
myTriggers->Constant(myConstants->DIRECTION_FROM_LEFT, percentForce);
myTriggers->Rumble(0, percentForce, 150);
}
}
else
{
myHelpers->log("resetting collision");
myTriggers->Constant(myConstants->DIRECTION_FROM_LEFT, 0);
}
if (0 < tiresSlip)
{
myHelpers->log("tires slip left");
bool highSpeedVibrations = (294 <= speed) && (1.0 * tiresSlip) < (LimitBetweenHighSpeedVibrationsAndTiresSlip / 1000.0);
percentForce = (-1.0 * tiresSlip) * (highSpeedVibrations ? HighSpeedVibrationsStrength : TiresSlipStrength) / 100.0;
myTriggers->Sine(100, 100, percentForce);
if (!highSpeedVibrations && ((0 == JointsAndStripesStrength && 0 == CollisionsStrength) || (0.001 > collisions && -0.001 < collisions)))
{
myTriggers->Rumble(0, -1.0 * percentForce, 150);
}
}
else if (0 > tiresSlip)
{
myHelpers->log("tires slip right");
bool highSpeedVibrations = (294 <= speed) && (-1.0 * tiresSlip) < (LimitBetweenHighSpeedVibrationsAndTiresSlip / 1000.0);
percentForce = (-1.0 * tiresSlip) * (highSpeedVibrations ? HighSpeedVibrationsStrength : TiresSlipStrength) / 100.0;
myTriggers->Sine(100, 100, percentForce);
if (!highSpeedVibrations && ((0 == JointsAndStripesStrength && 0 == CollisionsStrength) || (0.001 > collisions && -0.001 < collisions)))
{
myTriggers->Rumble(0, percentForce, 150);
}
}
INT_PTR ptr1 = myHelpers->ReadIntPtr(0x199A450, true);
UINT8 gear = myHelpers->ReadByte(ptr1 + 0x398, false);
if (0 < WheelSpinStrength)
{
INT_PTR ptr1 = myHelpers->ReadIntPtr(0x1948F10, true);
INT_PTR ptr2 = myHelpers->ReadIntPtr(ptr1 + 0x180 + 0xa8 + 0x18, false);
UINT8 power = myHelpers->ReadByte(ptr2 + 0x98, false);
int rpm = myHelpers->ReadInt32(0x1970038, true);
int diff = 0x0A <= power ? 0 : 20;
if (
1 == gear && 10 < speed && (
((30 - diff) > speed && 3500 < rpm)
|| ((55 - diff) > speed && 5500 < rpm)
|| ((75 - diff) > speed && 7000 < rpm)
|| ((100 - diff) > speed && 7800 < rpm)
)
)
{
percentForce = (((100.0 - speed) / 100.0) * ((rpm * 100.0 / 8500.0) / 100.0)) * WheelSpinStrength / 100.0;
myTriggers->Sine(120, 120, percentForce);
myTriggers->Rumble(0, percentForce, 150);
msg = "tires spin: gear: " + std::to_string(gear) + " | speed: " + std::to_string(speed)
+ " | rpm: " + std::to_string(rpm) + " | force: " + std::to_string(percentForce);
myHelpers->log((char*)msg.c_str());
}
else if (
2 == gear && 10 < speed && (
((110 - (2 * diff)) > speed && 5000 < rpm)
|| ((130 - (2 * diff)) > speed && 6000 < rpm)
|| ((145 - (2 * diff)) > speed && 6500 < rpm)
|| ((160 - (2 * diff)) > speed && 7000 < rpm)
)
)
{
percentForce = (((160.0 - speed) / 150.0) * ((rpm * 100.0 / 8500.0) / 100.0)) * WheelSpinStrength / 100.0;
myTriggers->Sine(120, 120, percentForce);
myTriggers->Rumble(0, percentForce, 150);
msg = "tires spin: gear: " + std::to_string(gear) + " | speed: " + std::to_string(speed)
+ " | rpm: " + std::to_string(rpm) + " | force: " + std::to_string(percentForce);
myHelpers->log((char*)msg.c_str());
}
}
if (0 < GearChangeStrength)
{
ptr1 = myHelpers->ReadIntPtr(0x199A468, true);
float time = myHelpers->ReadFloat32(ptr1 + 0x18, false);
if (oldgear != gear && 0 < gear && 0 < time)
{
msg = "oldgear: " + std::to_string(oldgear) + " | gear: " + std::to_string(gear)
+ " | time: " + std::to_string(time) + " | speed: " + std::to_string(speed);
myHelpers->log((char*)msg.c_str());
}
if (oldgear != gear && 0 < gear && 0.5 < time && 0.1 <= speed)
{
SDL_CreateThread(GearChangeThread, "GearChangeThread", (void*)NULL);
}
oldgear = gear;
}
}
return 0;
}
void WMMT5::FFBLoop(EffectConstants* constants, Helpers* helpers, EffectTriggers* triggers){
myTriggers = triggers;
myConstants = constants;
myHelpers = helpers;
SDL_Thread* thread;
thread = SDL_CreateThread(RunningThread, "RunningThread", (void*)NULL);
while (SDL_WaitEvent(&e) != 0)
{
myTriggers = triggers;
myConstants = constants;
myHelpers = helpers;
}
}