I think I've done that, but the results are rough so far. Here are screenshots:
https://i.postimg.cc/2ySNJ4Zt/Screensho ... 093216.png
https://i.postimg.cc/LX0x9fWw/Screensho ... 093159.png
As you can see there are a number of reddish-brown clouds in the courtyard. These gently float this way and that while slowly changing size and opacity as much as can be allowed using integers. Note the cloud shadows. These pan the courtyard also.
ZScript:
Code: Select all
class clouds_EventHandler : EventHandler
{
// returns area of sector (irregular polygon)
float polygonArea(Sector sec)
{
Array<float> lineAreas;
for (int i = 0; i < sec.Lines.Size(); i++)
{
int v1x = sec.Lines[i].V1.P.x;
int v1y = sec.Lines[i].V1.P.y;
int v2x = sec.Lines[i].V2.P.x;
int v2y = sec.Lines[i].V2.P.y;
float avgY = (v1y + v2y) * 0.5 * .015625;
float widthX = (v2x - v1x) * .015625;
lineAreas.Push(avgY * widthX);
}
float totArea;
for (int i = 0; i < lineAreas.Size(); i++)
{
totArea += lineAreas[i];
}
return totArea;
}
// add cloud spawners
override void WorldLoaded(WorldEvent e)
{
Array<string> sky = {
"F_SKY1",
"F_SKY2",
"F_SKY3",
"F_SKY4"
};
int FLOOR = 0;
int CEILING = 1;
TexMan texture;
for(int i = 0; i < Level.Sectors.Size(); i++)
{
textureid ceilingid = Level.Sectors[i].GetTexture(CEILING);
SecPlane ceilingplane = Level.Sectors[i].CeilingPlane;
SecPlane floorplane = Level.Sectors[i].FloorPlane;
int ceilingZ = ceilingplane.ZAtPoint((Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y));
int floorZ = floorplane.ZAtPoint((Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y));
int centerheight = ceilingZ - floorZ;
if (sky.Find(texture.GetName(ceilingid)) != sky.Size() && centerheight > 128)
{
float pArea = polygonArea(Level.Sectors[i]);
int clouds = int(pArea * .03125);
vector3 v3 = (Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y, floorZ);
if (CVar.FindCVar("cloud_debug").GetBool())
{
console.printf("Sector: %d, Polygon Area: %f, needing %d clouds", i, pArea, clouds);
}
for (int ii = 0; ii <= clouds; ii++)
{
Actor.Spawn("CloudSpawner", v3);
}
}
}
}
}
DECORATE:
Code: Select all
Actor CloudSpawner
{
States
{
Spawn:
TNT1 A 1
TNT1 A 1 A_SpawnItemEx("Cloud", FRandom(-128, -128), FRandom(-128, -128), FRandom(ceilingZ - 32, ceilingZ - 16), FRandom(-0.25, 0.25), FRandom(-0.5, 0.5), 0)
STOP
}
}
Actor Cloud
{
var int user_XScale;
var int user_YScale;
var int user_dir;
+MISSILE
+NOBLOCKMAP
+NOGRAVITY
+CASTSPRITESHADOW
+BOUNCEONWALLS
+BOUNCEONCEILINGS
+NOBOUNCESOUND
+INTERPOLATEANGLES
RenderStyle Add
XScale 0.5
YScale 0.5
Alpha 0.15
States
{
Spawn:
TNT1 A 0
TNT1 A 1
{
user_XScale = 5;
user_YScale = 5;
user_dir = 1;
}
TNT1 A 1
{
user_XScale += user_dir;
user_YScale += user_dir;
if (abs(user_dir) == 10)
{
user_dir *= -1;
}
}
CMFX A 1 A_FadeTo(0.15 + (0.05 * user_dir), 0.1, FTF_CLAMP)
CMFX AAAAA Random(35, 72) A_SetScale((user_XScale + 5) * 0.05, user_YScale * 0.05)
GOTO SPAWN+2
}
}
A lot of these choices are arbitrary, of course, and in very tall sectors the clouds will still be close to the top. I suppose in those cases they can be layered to create a greater illusion of depth. I didn't want them too close to the player, since that's fog and otherwise different.
I'm not sure all the flags are needed in the DECORATE definition, such as INTERPOLATEANGLES. It's pretty cool when the slowly drifting clouds cast shadows. Interestingly, these seem to mirror the density of the cloud. Changing the cloud_debug CVar will report some sector statistics, but it's all simple math (fortunately Doom sectors are not curved!).