Special Aircraft Service

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 [2]   Go Down

Author Topic: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)  (Read 442 times)

0 Members and 1 Guest are viewing this topic.

DarkenedFantasies

  • member
  • Offline Offline
  • Posts: 6
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #12 on: December 12, 2024, 03:28:23 PM »

I'm not sure whether there's a mistake in your code or I'm having a dumb idiot moment, but I'm not getting the expected results with the cloud height math. Assuming a starting cloud height of 1500, (0.83F + height / 25F) yields 60.83F, which will result in heightAltered being 91245 when the weather worsens. In the case of the weather improving, (1F / (0.83F + height / 25F)) yields approximately 0.016439257F, resulting in heightAltered being approximately 24.658886F. In both cases, the cloud height lands outside of the min/max range, and is the inverse of the intended behavior with height change. Is it actually working as you've described in-game?

A few other things:
  • It's not guaranteed that an unnecessary redraw won't be executed on mission start, as the cloud change is still processed beforehand and may set "flag" to true.
  • Maybe you have plans for its use in the future, but as it currently stands, "clouds" is unused and can be merged with "cloudsAltered".
  • Ignoring the suspected issues with the math, "height" and "heightAltered" could also be merged, and a new field (e.g. "heightStep") should be created to hold the value of (0.83F + height / 25F), to avoid unnecessarily recomputing the value as it is constant throughout the mission.
  • "super.Timer1 = super.Timer2 = i2" is a duplication of "resetTimer(i2)".
  • "flag" could be made local.
  • If this object is never initialized before Mission.cur(), the entire initialization block could be removed from the danger() method and put into the constructor instead of the constant value inits. Along with an initial call to resetTimer in there, "start" could then be retired as well.
Logged

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #13 on: December 12, 2024, 03:53:29 PM »

Here's an example of the resulting progress as I fly from the general weather type 1 (good) to type 5 (rain). Each change occurs at radial distances of 40, 30, 20 and 10km for weather types 2, 3, 4 and 5, respectively. The variables presented by the invoked method HUD.training() I use when testing:
- dist = distance from the StormFront object, in meters.
- clouds = the CloudType entry in the .mis file.
- front = the new weather type.
- height = the cloud base altitude ASL.
- turb =  turbulence, on a scale of 0 to 12.
- gust = gusts, on a scale of 0 to 6.

The 1st screenie is well enough outside the radius of 40km for invocation of the next weather type, that being 2 (hazy). The following grabs were taken fairly soon after the weather had changed. Because of the 30-second timer setting (much better than the former 300-second value), there is a delay before the execution of the change. The plane is moving along at something in the range of 1km every 10 seconds or so. Perhaps I should reduce the timer value even further? Which would be better if one set an even smaller stormDistanceInterval than the 10km I used here. Of course, something of a delay is good for this reason: If one is maneuvering about, crossing a particular distance threshold back and forth, a too-small delay would have the weather changing back and forth at an annoying pace. ;) And so the hysteresis imposed by a delay is a good thing.

Compared to the initial cloud height of 900m, in the rain it has lowered to roughly half.

The turbulence and gust behaviour works really well with my improved Wind.class, as it doesn't get ridiciulous. ;)

[click for larger]



Here's my code as of now:
Code: [Select]
package com.maddox.il2.objects.vehicles.stationary;

import com.maddox.JGP.Point3d;
import com.maddox.il2.ai.World;
import com.maddox.il2.engine.*;
import com.maddox.il2.game.HUD;  //when using HUD.training output
import com.maddox.il2.game.Mission;
import com.maddox.rts.SectFile;
import com.maddox.rts.Time;

// Referenced classes of package com.maddox.il2.objects.vehicles.stationary:
//            CandCGeneric, CandC

//public static class CandC$StormFrontUnit extends CandCGeneric  //static not allowed by my compiler
public class CandC$StormFrontUnit extends CandCGeneric
{

    public boolean danger()
    {
        if(Time.current() < (long)(Mission.cur().sectFile().get("Mods", "StormFrontDelay", 0) * 60))
            return false;
        super.pos.getAbs(point3d);
        com.maddox.il2.objects.air.Aircraft aircraft = World.getPlayerAircraft();
clouds = Mission.cur().sectFile().get("Main", "CloudType", 2);  //NEW
height = Mission.cur().sectFile().get("Main", "CloudHeight", 1500F);  //NEW
        int worstClouds = Mission.cur().sectFile().get("Mods", "WorstClouds", 6);
if(worstClouds < clouds)
worstClouds = clouds + 1;
if(worstClouds > 6)
worstClouds = 6;
        float stormDistanceInterval = Mission.cur().sectFile().get("Mods", "StormDistanceInterval", 50);  //NEW; 50km if not specified in .mis file
if(stormDistanceInterval < 5F)
stormDistanceInterval = 5F;
if(stormDistanceInterval > 100F)
stormDistanceInterval = 100F;
        double distanceFront = ((Actor) (aircraft)).pos.getAbsPoint().distance(point3d);
        if(distanceFront > 0.0D)
        {
            if(distanceFront > 6000D * (double) stormDistanceInterval)
{
                front = worstClouds - 6;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront > 5000D * (double) stormDistanceInterval && distanceFront <= 6000D * (double) stormDistanceInterval)
{
                front = worstClouds - 5;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront > 4000D * (double) stormDistanceInterval && distanceFront <= 5000D * (double) stormDistanceInterval)
{
                front = worstClouds - 4;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront > 3000D * (double) stormDistanceInterval && distanceFront <= 4000D * (double) stormDistanceInterval)
{
                front = worstClouds - 3;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront > 2000D * (double) stormDistanceInterval && distanceFront <= 3000D * (double) stormDistanceInterval)
{
                front = worstClouds - 2;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront > 1000D * (double) stormDistanceInterval && distanceFront <= 2000D * (double) stormDistanceInterval)
{
                front = worstClouds - 1;
if(front < clouds)
front = clouds;
}
            else
            if(distanceFront <= 1000D * (double) stormDistanceInterval)  //NEW
{
                front = worstClouds;  //if <= 1 * stormDistanceInterval
if(front < clouds)  //superfluous?
front = clouds;
}
        }

// ========================================================================================================================  //experiment for updating turbulence and gusts
            direction = Mission.cur().sectFile().get("WEATHER", "WindDirection", direction, 0.0F, 359.99F);
            speed = 0.25F + (float)(clouds * clouds) * 0.12F;
            speed = Mission.cur().sectFile().get("WEATHER", "WindSpeed", speed, 0.0F, 15F);
            gust = clouds > 3 ? (float)clouds * 2.0F : 0.0F;
            gust = Mission.cur().sectFile().get("WEATHER", "Gust", gust, 0.0F, 12F);  //0, 8, 10, 12
if(front - clouds > 0)
{
gust += (float) (front - clouds) * 1.5F;
if(gust > 12F)
gust = 12F;
}
            turb = clouds > 2 ? clouds : 0.0F;
            turb = Mission.cur().sectFile().get("WEATHER", "Turbulence", turb, 0.0F, 6F);  //0, 3, 4, 5, 6
if(front - clouds > 0)
{
turb += (float) (front - clouds) / 2F;
if(turb > 6F)
turb = 6F;
}
            World.wind().set(height, direction, speed, gust, turb);
// ========================================================================================================================

        if(front != lastfront)
        {
//            Mission.createClouds(front, 1000F);  //original
            Mission.createClouds(front, height * (float) Math.pow(0.85F, (float) (front - clouds)));
            World.land().cubeFullUpdate();
HUD.training("dist: " + distanceFront + " clouds: " + clouds + " front:" + front + " height:" + height * (float) Math.pow(0.85F, (float) (front - clouds)) + " turb:" + turb + " gust:" + gust);
        }
        lastfront = front;
        return true;
    }

    private Point3d point3d;
    private int front;
    private int lastfront;
    private int clouds;  //NEW
    private float height;  //NEW
private int worstClouds;  //NEW
private float stormDistanceInterval;  //NEW
private float direction;  //NEW
private float speed;  //NEW
private float gust;  //NEW
private float turb;  //NEW

    public CandC$StormFrontUnit()
    {
        point3d = new Point3d();
        front = -1;  //was 1
        lastfront = -1;  //was 1
// clouds = 2;  //NEW
// height = 1500;  //NEW
// stormDistanceInterval = 50F;  //NEW
// super.Timer1 = super.Timer2 = 300F;  //original; 5 min
        super.Timer1 = super.Timer2 = 30F;  //30 sec
    }
}
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #14 on: December 12, 2024, 04:04:30 PM »

I'm not sure whether there's a mistake in your code or I'm having a dumb idiot moment, but I'm not getting the expected results with the cloud height math. Assuming a starting cloud height of 1500, (0.83F + height / 25F) yields 60.83F, which will result in heightAltered being 91245 when the weather worsens. In the case of the weather improving, (1F / (0.83F + height / 25F)) yields approximately 0.016439257F, resulting in heightAltered being approximately 24.658886F. In both cases, the cloud height lands outside of the min/max range, and is the inverse of the intended behavior with height change. Is it actually working as you've described in-game?

A few other things:
  • It's not guaranteed that an unnecessary redraw won't be executed on mission start, as the cloud change is still processed beforehand and may set "flag" to true.
  • Maybe you have plans for its use in the future, but as it currently stands, "clouds" is unused and can be merged with "cloudsAltered".
  • Ignoring the suspected issues with the math, "height" and "heightAltered" could also be merged, and a new field (e.g. "heightStep") should be created to hold the value of (0.83F + height / 25F), to avoid unnecessarily recomputing the value as it is constant throughout the mission.
  • "super.Timer1 = super.Timer2 = i2" is a duplication of "resetTimer(i2)".
  • "flag" could be made local.
  • If this object is never initialized before Mission.cur(), the entire initialization block could be removed from the danger() method and put into the constructor instead of the constant value inits. Along with an initial call to resetTimer in there, "start" could then be retired as well.


[EDITED upon discovering my silly error!]
This construction

    heightAltered *= (0.83F + height / 25F);

is indeed wrong! It should be

    heightAltered *= (0.83F + height / 1000F / 40F);

as originally formulated. I stupidly contracted the algorithm without applying careful thought.  :-[  I've updated the code pasted in my top post.

This multiplies heightAltered by essentially around 0.83 for the lowest cloud, that factor increasing to around 0.95 for the highest cloud at 5,000m. For instance, height = 500 yields heightAltered = 421.25 (delta = 79), and height = 3000 yields heightAltered = 2715 (delta = 285).

The calculations are conducted only when the timer has counted down, not continuously. At least, the updated data I present via HUD.training() does so. And from other code I know that HUD.training() output is cranked out at ~30 times/sec (every game tick) when the calculations are continuous.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #15 on: December 12, 2024, 04:32:13 PM »

I edited a small part of my text in Reply #13 above. Here's the main change:

"The plane is moving along at something in the range of 1km every 10 seconds or so. Perhaps I should reduce the timer value even further? Which would be better if one set an even smaller stormDistanceInterval than the 10km I used here. Of course, something of a delay is good for this reason: If one is maneuvering about, crossing a particular distance threshold back and forth, a too-small delay would have the weather changing back and forth at an annoying pace. ;) And so the hysteresis imposed by a delay is a good thing."

For those who've already read the early version of the aforementioned post, it's worth going over the matter of the timer delay. As the paragraph above points out, a too-brief delay would be bad in cases where the player is stooging about at a particular radial distance threshold. For instance, imagine if the delay was very brief, say a brisk one second. If you were turning circles and crossing a threshold radius twice every turn, the weather would also change twice every turn. With a timer delay of 30 seconds, this introduces hysteresis, whereby that 30 seconds will have to expire before a new weather setting is invoked. If one crosses the radial every 12 seconds, for instance, 30 seconds will nonetheless have to pass AND a different weather value must be in effect before the draw operation is executed.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #16 on: December 12, 2024, 07:05:28 PM »

I'm not sure whether there's a mistake in your code or I'm having a dumb idiot moment, but I'm not getting the expected results with the cloud height math. Assuming a starting cloud height of 1500, (0.83F + height / 25F) yields 60.83F, which will result in heightAltered being 91245 when the weather worsens. In the case of the weather improving, (1F / (0.83F + height / 25F)) yields approximately 0.016439257F, resulting in heightAltered being approximately 24.658886F. In both cases, the cloud height lands outside of the min/max range, and is the inverse of the intended behavior with height change. Is it actually working as you've described in-game?


DarkenedFantasies,
Back to your observation. Good catch! Below is what I originally had derived, then just before posting the code had stupidly contracted the algorithm. I just discovered the error of my ways when trying out the addition of adjustment to turbulence and gusts, seeing really outlandish cloud heights.

The correct form as originally worked; I went back and edited the full code pasted in my top post.
    heightAltered *= (0.83F + height / 1000F / 40F)

Thanks for your careful eye!

Glenn

Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)

DarkenedFantasies

  • member
  • Offline Offline
  • Posts: 6
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #17 on: December 13, 2024, 01:08:26 AM »

Now this makes a lot more sense. I was staring at it for a good few minutes trying to see how you were getting those results out of that equation, and was even more confused after your last reply. Glad to know I haven't slipped into some strange alternate reality.

On another note, concerning your comment: //"static" not allowed by my compiler
Your compiler is correct, as it is indeed not a valid use case of the static keyword here. I suppose you've decompiled it as an individual classfile when it originally was an inner class of CandC.java. If you're going to keep it as its own class file, it may be problematic to preserve the "CandC$" prefix in your class name since the $ character has some reserved uses. As far as I'm aware, there's no utility in manually defining class hierarchy like that; it's only an internal thing.
Logged

Frankiek

  • SAS Team
  • member
  • Offline Offline
  • Posts: 2951
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #18 on: December 13, 2024, 03:02:29 AM »

Normally these $ class files are automatically generated when you compile the main class. Would it be possible to alter the main class in a way to obtain the desired result?
Logged

WxTech

  • Modder
  • member
  • Offline Offline
  • Posts: 6040
Re: Fixing and augmenting the C&C Dynamic Weather object (and StormFront too)
« Reply #19 on: December 13, 2024, 04:13:50 AM »

I think I recall having a problem compiling the whole class, hence this approach to dealing with each 'module' separately.
Logged
Great minds discuss ideas. Average minds discuss events. Small minds discuss people. - Hyman Rickover (but probably predating his use.)
Pages: 1 [2]   Go Up
 

Page created in 0.034 seconds with 25 queries.