18
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-15 05:59:06 +01:00
Files
maszyna/tests/unit/test_smoke.cpp
jerrrrycho a6c7d53983 fix: SmokeDelay defaults to 0, the delay comes only from the vehicle's .fiz (eu07/maszyna#523)
Without SmokeDelay in its Engine section a diesel smokes as soon as the
starter turns, as before; the delay is set per locomotive in its own .fiz.
The value stays a member of the vehicle's mover, read from its .fiz with
an explicit default of 0.

Tests: the real SM42 and ST44 with SmokeDelay=2 and 5 in the .fiz, and
without it (smoke at once), next to a locomotive with a delay loaded
just before, which keeps its own value.
2026-11-08 12:33:53 +01:00

162 lines
6.0 KiB
C++

#include "stdafx.h"
#include "doctest.h"
#include "vehicle.h"
#include "drive.h"
#include "vehicle/smoke.h"
// the smoke of a vehicle's engine: how many particles the smoke source of the vehicle's model spawns in an update
namespace {
// a source of 20 particles per second, with room for 100
smoke::spawn_rate const source{0.f, 20.f, 1.f, 100.f};
double const update{0.1}; // s
// a diesel at work, its engine in the state of one of the cases below
test::vehicle diesel() {
test::vehicle vehicle{test::definition::load("wagon")};
vehicle->MainCtrlPosNo = 1;
vehicle->DElist[1].RPM = 1500.0;
vehicle->enrot = 300.0;
vehicle->EnginePower = 400.0;
return vehicle;
}
} // namespace
TEST_CASE("smoke: a vehicle taken off the tracks puffs no more (#90)") {
auto vehicle{diesel()};
SUBCASE("engine starting") { vehicle->dizel_spinup = true; }
SUBCASE("engine idling") { vehicle->DirAbsolute = 0; }
SUBCASE("engine under load") {
vehicle->DirAbsolute = 1;
vehicle->Im = 400.0;
}
// on the tracks the engine puffs
REQUIRE(smoke::vehicle_spawn_count(vehicle.mover(), true, source, update) >= 1.f);
// gone through a portal, the pending particles are dropped too
auto pending{source};
pending.pending = 5.f;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), false, pending, update) == 0.f);
}
TEST_CASE("smoke: a road vehicle back on the road from the pool puffs again") {
auto vehicle{diesel()};
// waiting in the pool, the count stays at zero update after update
auto rate{source};
for (auto i{0}; i < 10; ++i) {
rate.pending = smoke::vehicle_spawn_count(vehicle.mover(), false, rate, update);
}
REQUIRE(rate.pending == 0.f);
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, rate, update) >= 1.f);
}
TEST_CASE("smoke: the engine adds to the steady rate of the source") {
auto vehicle{diesel()};
vehicle->DirAbsolute = 0;
auto const steady{source.rate * update}; // the rate of a source of the scenery
vehicle->EnginePower = 0.0;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, source, update) == doctest::Approx(steady));
vehicle->EnginePower = 400.0;
auto const working{smoke::vehicle_spawn_count(vehicle.mover(), true, source, update)};
CHECK(working > steady);
// the faster the starting engine turns, the more it puffs
vehicle->dizel_spinup = true;
vehicle->enrot = 100.0;
auto const slow{smoke::vehicle_spawn_count(vehicle.mover(), true, source, update)};
vehicle->enrot = 400.0;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, source, update) > slow);
}
TEST_CASE("smoke: the pending particles never outgrow the room of the source") {
auto vehicle{diesel()};
vehicle->dizel_spinup = true;
vehicle->enrot = 100000.0;
auto rate{source};
rate.pending = 99.f;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, rate, 10.0) == rate.limit);
}
TEST_CASE("smoke: an engine the starter turns lets out no smoke until it fires (#523)") {
auto vehicle{diesel()};
vehicle->dizel_spinup = true;
auto pending{source};
pending.pending = 5.f;
vehicle->dizel_FiringCountdown = 0.5;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, pending, update) == 0.f);
vehicle->dizel_FiringCountdown = 0.0;
CHECK(smoke::vehicle_spawn_count(vehicle.mover(), true, pending, update) >= 1.f);
}
namespace {
// the locomotive's engine started the way the AI starts it, a second at a time, until it runs (Mains)
bool start_engine(test::driven const &Driven, test::track const &Track) {
for (int second = 0; second < 120 && false == Driven.controlling.Mains; ++second) {
test::start_up(Driven, Track, 1.0);
}
return Driven.controlling.Mains;
}
} // namespace
TEST_CASE("smoke: a real diesel smokes only once its engine has fired, SmokeDelay after the starter began (#523)") {
// a diesel with a mechanical transmission and a diesel-electric one
for (auto const *path : {"sm42_v1/6d1", "st44_v2/m62-1151"}) {
CAPTURE(path);
test::track const track{};
{
// SmokeDelay set in the .fiz of the locomotive
test::vehicle locomotive{test::definition{test::definition::fiz(path)}.set("Engine", "SmokeDelay", 2)};
REQUIRE(locomotive->dizel_SmokeDelay == doctest::Approx(2.0));
auto const driven{test::driving(locomotive)};
REQUIRE(start_engine(driven, track));
// the engine started less than a second ago: the starter still turns it
CHECK(locomotive->dizel_FiringCountdown > 0.5);
CHECK(smoke::vehicle_spawn_count(locomotive.mover(), true, source, update) == 0.f);
// it has fired since
test::drive(driven, track, 3.0);
CHECK(locomotive->Mains);
CHECK(locomotive->dizel_FiringCountdown == 0.0);
CHECK(smoke::vehicle_spawn_count(locomotive.mover(), true, source, update) >= 1.f);
}
{
// a longer delay from the .fiz
test::vehicle locomotive{test::definition{test::definition::fiz(path)}.set("Engine", "SmokeDelay", 5)};
auto const driven{test::driving(locomotive)};
REQUIRE(start_engine(driven, track));
test::drive(driven, track, 3.0);
CHECK(smoke::vehicle_spawn_count(locomotive.mover(), true, source, update) == 0.f);
test::drive(driven, track, 3.0);
CHECK(smoke::vehicle_spawn_count(locomotive.mover(), true, source, update) >= 1.f);
}
}
}
TEST_CASE("smoke: without SmokeDelay in its .fiz a diesel smokes as soon as the starter turns, as before (#523)") {
for (auto const *path : {"sm42_v1/6d1", "st44_v2/m62-1151"}) {
CAPTURE(path);
test::track const track{};
// a locomotive which has the delay, loaded first, doesn't hand it on to the next one: the value is the vehicle's own
test::vehicle delayed{test::definition{test::definition::fiz(path)}.set("Engine", "SmokeDelay", 3)};
REQUIRE(delayed->dizel_SmokeDelay == doctest::Approx(3.0));
test::vehicle locomotive{test::definition::fiz(path)};
REQUIRE(locomotive->dizel_SmokeDelay == 0.0);
CHECK(delayed->dizel_SmokeDelay == doctest::Approx(3.0));
auto const driven{test::driving(locomotive)};
REQUIRE(start_engine(driven, track));
CHECK(locomotive->dizel_FiringCountdown == 0.0);
CHECK(smoke::vehicle_spawn_count(locomotive.mover(), true, source, update) >= 1.f);
}
}