Cataclysm-DDA icon indicating copy to clipboard operation
Cataclysm-DDA copied to clipboard

Dinosaur engines need more horsepower

Open stuart909 opened this issue 1 year ago • 4 comments

Is your feature request related to a problem? Please describe.

Large dino herbivores seem to not pull my carts as well as a horse, if at all. My own character has little difficulty pulling an unladen cart, as does the horse, however, the dinos seem to either be uncooperative or a bit lacking in the engine department.

What we got

  • lazy dinos

Solution you would like.

Expectation

large herbivores should have substantially more horsepower than a horse and should have no problem pulling a basic horse cart or fully laden car that had a yoke and harness lazily bolted to the front.

Describe alternatives you have considered.

Alternatives

  • use horse :(

Additional context

  • The horse can maintain 7 or higher MPH in grass or dirt and get over speeds of 10MPH on concrete. image

  • The achelousaurus was able to pull the cart on concrete at speeds of less than 1MPH, but got stuck in the grass. image

  • cart image image image image image

  • Cart was empty during tests

stuart909 avatar Jun 27 '24 18:06 stuart909

Animal power is calculated like this:

  • factor starts at 1 for every size class above tiny
    • a horse is Large, so its factor is 3
    • an achelousaurus is Huge, so its factor is 4
  • multiply this by the monster's speed
    • horse is 300 -> 900 factor
    • achelousaurus is 110 -> 440 factor
  • multiply this by the 'mountable weight ratio'
    • neither creature specifies a factor, default is 0.2
    • horse factor = 180
    • achelousaurus factor = 88
  • multiply by 15 to get total power in watts
    • horse = 2700 W (~3.6 hp)
    • achelousaurus = 1320 W (~1.7 hp)

So the problem is that the dino is ~3x slower than the horse, which is not offset by it being physically 2x larger and one size class greater than the horse. A comment indicates that it should actually be ~6x larger than the horse, but it is already in the largest size class and increasing that wouldn't actually have any effect.

There is also a check to prevent animal-powered vehicles from exceeding the speed of the animal pulling them, but I would estimate that to be somewhere around 15 MPH for the dino - not sure what the moves-to-mph conversion is OTTOMH.

This exposes the general ~issue~ quirk with the vehicle code whereby all power is treated equally with no distinction between torque (pulling force) and RPM (maximum speed). The horse should be able to pull a light cart at high speed, whereas the dino should be able to pull considerably more weight but with a much lower top speed. This is why the tractors can reach 100 mph no problem - there's no transmission system to gear down all that power into pulling force.

Related might be #73341 which was fixed a few weeks ago, not sure if your game includes this. Generally you'd see much higher offroad speeds for drawn vehicles, especially when much of the mass of the vehicle is from animals.

There doesn't seem to be any quick fixes for this either in the json or code. I think the best bet might be adding some nonlinearity to the size class factor bonus, balanced around the horse, and maybe adding another size class + increasing the physical size of the dinos to match. Even if you do get reasonable power output you're going to have to be careful not to overspeed your vehicle.

natsirt721 avatar Jun 29 '24 16:06 natsirt721

Oh boy. It appears that a lot of work was spent making an arbitrary game system when it would have been easier to just use basic car math. I think the only real thing missing in the JSON is torque. Don't really need RPM because we can use defaults for different engine/animal types. We already have horsepower and mass. We also have wheel sizes, which is important. Animals could have arbitrary wheel sizes based on class or additional json for balancing. Gear ratios can be simulated with a sin curve, so we lose pull force as we gain speed. This will prevent massive top ends for high horsepower vehicles with low mass.

Parameters:

  • Weight being pulled (W): The total weight of the load.
  • Engine horsepower (HP): The power output of the engine.
  • Engine torque (T): The rotational force produced by the engine.
  • Mass (M): The mass of the vehicle or object pulling the weight.
  • Top speed (V_max): The maximum achievable speed.
  • Pull force (F): The force needed to pull the weight.

Concept:

To simulate the reduction of pull force at higher speeds and the influence of torque on low-speed pulling power, we can introduce a factor that modifies pull force based on speed. We can use a sine curve to represent this relationship, ensuring that pull force decreases as speed approaches top speed.

Equation Derivation:

Basic Pull Force:

The pull force at zero speed can be derived from torque and the wheel radius as before:

F = T / r

Pull Force with Speed Adjustment:

We introduce a speed factor f_speed that adjusts pull force based on current speed (v):

f_speed = sin(π * (v / V_max))

This factor ranges from 0 (at top speed) to 1 (at zero speed).

Combined Pull Force:

The effective pull force considering speed can then be calculated as:

F_effective = (T / r) * f_speed

Top Speed Adjustment:

To ensure that vehicles with higher torque don't mistakenly get higher top speeds, we can adjust top speed calculation by considering both horsepower and mass:

V_max = k * sqrt(HP / M)

where 'k' is a scaling constant to adjust units and balance the equation.

Implementation Example:

Here’s a simplified implementation in C++:

#include <iostream>
#include <cmath>

// Constants
const double frictionCoefficient = 0.7; // Typical value for tires on asphalt
const double k = 1.0; // Scaling constant for top speed calculation

// Function to calculate effective pull force
double calculatePullForce(double torque, double wheelRadius, double currentSpeed, double maxSpeed) {
    // Basic pull force from torque
    double basePullForce = torque / wheelRadius;
    
    // Speed factor using sine curve
    double speedFactor = sin(M_PI * (currentSpeed / maxSpeed));
    
    // Effective pull force adjusted for speed
    return basePullForce * speedFactor;
}

// Function to calculate top speed
double calculateTopSpeed(double horsepower, double mass) {
    return k * sqrt(horsepower / mass);
}

int main() {
    double weight = 5000; // Weight in pounds
    double horsepower = 200; // Engine horsepower
    double torque = 300; // Engine torque in lb-ft
    double wheelRadius = 1.5; // Wheel radius in feet
    double mass = 3000; // Mass of the vehicle in pounds
    
    // Calculate top speed
    double maxSpeed = calculateTopSpeed(horsepower, mass);
    
    // Example current speed
    double currentSpeed = 30; // Current speed in mph

    // Calculate effective pull force at current speed
    double pullForce = calculatePullForce(torque, wheelRadius, currentSpeed, maxSpeed);
    
    std::cout << "Top Speed: " << maxSpeed << " MPH\n";
    std::cout << "Effective Pull Force at " << currentSpeed << " MPH: " << pullForce << " pounds-force\n";
    
    return 0;
}

Explanation:

Calculate Basic Pull Force:

basePullForce = torque / wheelRadius

Adjust for Speed Using Sine Curve:

speedFactor = sin(M_PI * (currentSpeed / maxSpeed))

Calculate Effective Pull Force:

F_effective = basePullForce * speedFactor

Calculate Top Speed:

V_max = k * sqrt(horsepower / mass)

This model ensures that pull force decreases as speed increases, and it balances the influence of torque and horsepower on top speed and pulling power. By adjusting the scaling constant k, you can fine-tune the balance between speed and pull force to fit the specific requirements of your game system.

stuart909 avatar Jun 29 '24 22:06 stuart909

I'm just gonna say 'its not that simple'. There are easily 15k lines of vehicle code, of which perhaps 2-3k are directly relevant to vehicle dynamics and at least another 2k or so would need to be scrutinized for any impacts. There are a number of things that would immediately need to be addressed even if we were to drop that code sample in place, such as:

  1. You already correctly identified that this straight-up does not work for animals (as an aside I find this extremely ironic, given the original topic). The 8" in 8" yoke and harness is the effective diameter of that "wheel" using the current system. Each beast would effectively need its own wheel radius for this to modulate the balance between torque and RPM.
  2. Sqrt appears to be completely arbitrary, there are myriad sources of drag/resistance that go into actually defining a vehicle's top speed, such as vehicle weight distribution, wheel factors such as traction, contact area, and rolling rolling resistance, vehicle air or water resistance, friction with parts dragging on the ground like skids or plows, and the maximum RPM of the engine providing the power.
  3. Sin 0 is 0, so you would not be accelerating at all from a standstill. Using a trig function is probably not the right choice for scaling anyway.
  4. Most engines don't have constant horsepower (and therefore torque) over a range of RPMs, nor is the shape of the curve consistent. Electric motors produce massive torque at low RPMs, whereas gas and diesel 4 stroke engines peak near the second/first third of their max RPM respectively.

Don't get me wrong, it is a noble goal. The current vehicle code, while being a lot to read through, pretty effective for what it does. But it isn't going to support a drop-in torque model overnight, not without introducing a whole host of other changes. And it certainly wont get implemented by 40 lines of C++ in a vacuum.

natsirt721 avatar Jun 30 '24 00:06 natsirt721

I'm just spit balling ideas. I wouldn't implement my spaghetti code math ideas into the actual model without first diving into whatever is driving the vehicle's speed and acceleration. That specific portion shouldn't be 3k lines of code. And I wouldn't use the yoke for wheel size either, the animal class, animal mass, and leg count should set wheel size for animals. Wheel size for cars should be the average of wheel sizes because we don't have a drivetrain in the game, IE rear axel car has two 17" wheels in the rear, so it's 17 despite the front being 16 for some reason. But our game is always AWD.

A torque system can actually be calculated too. We do have engine types, gas, diesel, electric, foot petal, & animal. Default factors can be set for each one, and you can account for engine weight and volume to create torque if you don't want to arbitrarily set torque in the JSON for all of the engines. So basically, create a game system to get wheel size, create a game system to get torque, and you take JSON data that we do own and you come up with slightly better math than what I have to set top speed, pull force, acceleration, etc. It's a bit of math but not 1000 lines, and you should only be plugging in to the specific code that accelerates the car forward and back.

Terrain should be modifying the system you already have, so you might be able to get away with NOT modifying the code that governs terrain speeds too much...unless you are calculating terrain maths for each case, though I have no clue because I haven't searched the code to see.

If you know which files those are in, I'd be happy to clone the repo and take a look.

stuart909 avatar Jun 30 '24 04:06 stuart909

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not bump or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.

github-actions[bot] avatar Jul 30 '24 05:07 github-actions[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not bump or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.

github-actions[bot] avatar Jan 31 '25 07:01 github-actions[bot]