210 lines
7.0 KiB
C++
210 lines
7.0 KiB
C++
|
#include "rulemodule.h"
|
||
|
|
||
|
#include <QMetaObject>
|
||
|
#include <QMetaProperty>
|
||
|
#include <QDebug>
|
||
|
#include <QRandomGenerator>
|
||
|
|
||
|
#include "math.h"
|
||
|
#include "common/scssdk_telemetry_common_gameplay_events.h"
|
||
|
|
||
|
double peakedSine(double x, double peakTime = 0.2)
|
||
|
{
|
||
|
double stretchedX;
|
||
|
if (x < peakTime)
|
||
|
stretchedX = x / (peakTime*2.0);
|
||
|
else
|
||
|
stretchedX = 0.5+( ( (x-peakTime)/(1-peakTime) )*0.5 );
|
||
|
|
||
|
double ret = 1.0-((1.0+(std::cos(stretchedX * M_PI * 2.0)))/2.0);
|
||
|
qDebug() << "peakedSine(" << x << ") =" << ret;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
RuleModule::RuleModule(QObject *parent)
|
||
|
: QObject{parent}
|
||
|
{
|
||
|
// const QMetaObject* meta = metaObject();
|
||
|
// for (int idx = 1; idx < meta->propertyCount(); idx++)
|
||
|
// {
|
||
|
// QMetaProperty prop = meta->property(idx);
|
||
|
// connect(this, prop.notifySignal(), this, [&]());
|
||
|
// }
|
||
|
}
|
||
|
|
||
|
void RuleModule::save(QSettings& settings) const
|
||
|
{
|
||
|
const QMetaObject* meta = metaObject();
|
||
|
settings.beginGroup(objectName());
|
||
|
for (int idx = 1; idx < meta->propertyCount(); idx++)
|
||
|
{
|
||
|
QMetaProperty prop = meta->property(idx);
|
||
|
QVariant value = prop.read(this);
|
||
|
qDebug() << "Saving settings: " << objectName() << "/" << prop.name() << " = " << value;
|
||
|
settings.setValue(prop.name(), value);
|
||
|
}
|
||
|
settings.endGroup();
|
||
|
}
|
||
|
|
||
|
void RuleModule::load(QSettings& settings)
|
||
|
{
|
||
|
const QMetaObject* meta = metaObject();
|
||
|
settings.beginGroup(objectName());
|
||
|
for (int idx = 1; idx < meta->propertyCount(); idx++)
|
||
|
{
|
||
|
QMetaProperty prop = meta->property(idx);
|
||
|
QVariant value = settings.value(prop.name(), prop.read(this));
|
||
|
qDebug() << "Loading settings: " << objectName() << "/" << prop.name() << " = " << value;
|
||
|
prop.write(this, value);
|
||
|
emit prop.notifySignal();
|
||
|
}
|
||
|
settings.endGroup();
|
||
|
}
|
||
|
|
||
|
double SpeedModule::process(const TelemetryState& telemetry, double previous, double delta)
|
||
|
{
|
||
|
double ret = previous;
|
||
|
if (Enabled && TopSpeed > 0)
|
||
|
{
|
||
|
double speedN = std::abs(telemetry.speed * 3.6) / TopSpeed;
|
||
|
sine_x += delta * speedN;
|
||
|
double sine = std::sin(sine_x * WaveFrequency * M_PI * 2);
|
||
|
double power = std::clamp(speedN + (sine * speedN * WaveAmplitude), 0.0, 1.0);
|
||
|
ret += power * MaxOutput;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
double RPMModule::process(const TelemetryState& telemetry, double previous, double delta)
|
||
|
{
|
||
|
double ret = previous;
|
||
|
if (Enabled && (TopRPM - BottomRPM) > 0)
|
||
|
{
|
||
|
double rpmN = (telemetry.rpm - BottomRPM) / (TopRPM - BottomRPM);
|
||
|
ret += rpmN * MaxOutput;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void CrimeModule::gameEvent(const QString name, const QMap<QString, QVariant> attributes)
|
||
|
{
|
||
|
if (name == SCS_TELEMETRY_GAMEPLAY_EVENT_player_fined)
|
||
|
{
|
||
|
if (attributes.contains(SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_fine_amount))
|
||
|
{
|
||
|
uint64_t amount = attributes[SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_fine_amount].toULongLong();
|
||
|
timeout += amount * SecondsPerEuro;
|
||
|
}
|
||
|
if (attributes.contains(SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_fine_offence))
|
||
|
{
|
||
|
QString offence = attributes[SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_fine_offence].toString();
|
||
|
|
||
|
// You...
|
||
|
if (offence == "crash")
|
||
|
whatYouDid = "killed someone";
|
||
|
else if (offence == "red_signal")
|
||
|
whatYouDid = "ran a red light";
|
||
|
else if (offence == "avoid_sleeping")
|
||
|
whatYouDid = "were caught being eepy";
|
||
|
else if (offence == "speeding_camera")
|
||
|
whatYouDid = "got flashed";
|
||
|
else if (offence == "no_lights")
|
||
|
whatYouDid = "forgot to press the headlight button twice";
|
||
|
// else if (offence == "speeding")
|
||
|
// whatYouDid = "";
|
||
|
// else if (offence == "avoid_weighing")
|
||
|
// whatYouDid = "";
|
||
|
else if (offence == "illegal_trailer")
|
||
|
whatYouDid = "got found packing heat";
|
||
|
else if (offence == "avoid_inspection")
|
||
|
whatYouDid = "missed penis inspection day";
|
||
|
// else if (offence == "illegal_border_crossing")
|
||
|
// whatYouDid = "";
|
||
|
// else if (offence == "hard_shoulder_violation")
|
||
|
// whatYouDid = "";
|
||
|
// else if (offence == "damaged_vehicle_usage")
|
||
|
// whatYouDid = "";
|
||
|
else if (offence == "generic")
|
||
|
whatYouDid = "failed the vibe check";
|
||
|
else
|
||
|
whatYouDid = "broke the law";
|
||
|
// ...! You'll be punished for X seconds!
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double CrimeModule::process(const TelemetryState& telemetry, double previous, double delta)
|
||
|
{
|
||
|
double ret = previous;
|
||
|
if (Enabled)
|
||
|
{
|
||
|
if (timeout > 0.0)
|
||
|
{
|
||
|
timeout -= delta;
|
||
|
ret *= PowerMultiplier;
|
||
|
|
||
|
emit statusUpdate(QString("You %2! You'll be punished for %1 seconds!").arg(timeout, 0, 'f', 1).arg(whatYouDid));
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void JobModule::gameEvent(const QString name, const QMap<QString, QVariant> attributes)
|
||
|
{
|
||
|
if (name == SCS_TELEMETRY_GAMEPLAY_EVENT_job_delivered)
|
||
|
{
|
||
|
totalTime = 0.0;
|
||
|
if (attributes.contains(SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_revenue))
|
||
|
{
|
||
|
uint64_t amount = attributes[SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_revenue].toULongLong();
|
||
|
totalTime += (amount/100.0) * SecondsPerEuro;
|
||
|
}
|
||
|
if (attributes.contains(SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_earned_xp))
|
||
|
{
|
||
|
uint64_t amount = attributes[SCS_TELEMETRY_GAMEPLAY_EVENT_ATTRIBUTE_earned_xp].toULongLong();
|
||
|
totalTime += (amount/100.0) * SecondsPerXP;
|
||
|
}
|
||
|
timeout = totalTime;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double JobModule::process(const TelemetryState& telemetry, double previous, double delta)
|
||
|
{
|
||
|
double ret = previous;
|
||
|
if (Enabled)
|
||
|
{
|
||
|
if (timeout > 0.0)
|
||
|
{
|
||
|
timeout -= delta;
|
||
|
ret += peakedSine((totalTime-timeout)/totalTime, 0.1) * PowerBoost;
|
||
|
|
||
|
emit statusUpdate(QString("Well done! You'll be rewarded for %1 seconds!").arg(timeout, 0, 'f', 1));
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
double DistanceModule::process(const TelemetryState& telemetry, double previous, double delta)
|
||
|
{
|
||
|
double ret = previous;
|
||
|
if (Enabled)
|
||
|
{
|
||
|
if (telemetry.distance > nextReward)
|
||
|
{
|
||
|
double random = (1.0 - Randomness) + (QRandomGenerator::global()->generateDouble() * 2.0 * Randomness);
|
||
|
qDebug () << "Random factor: " << random;
|
||
|
double distanceToNext = Distance * 1000.0 * random;
|
||
|
timeout = Duration;
|
||
|
nextReward += distanceToNext;
|
||
|
qDebug() << "Next distance reward will be in " << distanceToNext << " metres, at " << nextReward;
|
||
|
}
|
||
|
if (timeout > 0.0)
|
||
|
{
|
||
|
timeout -= delta;
|
||
|
ret += peakedSine((Duration-timeout)/Duration, 0.4) * PowerBoost;
|
||
|
emit statusUpdate(QString("You've driven so far! You'll be rewarded for %1 seconds!").arg(timeout, 0, 'f', 1));
|
||
|
}
|
||
|
}
|
||
|
return ret;
|
||
|
}
|