The concept is all the tech lamps make an electronic buzzing, certain areas have a distant rumbling sound, and there's a distant wind outside that bodes ill.
DECORATE:
Code: Select all
Actor IA_Sound
{
+NOGRAVITY
+FLOAT
States
{
}
}
Code: Select all
class idleambiance_EventHandler : EventHandler
{
struct item
{
string cname;
string sname;
int flags;
double volume;
}
item ItemSounds[50];
int iCounter;
struct flat
{
string fname;
int type;
int height;
string sname;
int flags;
double volume;
}
flat FlatSounds[50];
int fCounter;
void addItemSounds(string cname, string sname, int flags, double volume = 1.0)
{
ItemSounds[iCounter].cname = cname;
ItemSounds[iCounter].sname = sname;
ItemSounds[iCounter].flags = flags;
ItemSounds[iCounter].volume = volume;
iCounter++;
}
void addFlatSounds(string fname, int type, int height, string sname, int flags, double volume = 1.0)
{
FlatSounds[fCounter].fname = fname;
FlatSounds[fCounter].type = type;
FlatSounds[fCounter].height = height;
FlatSounds[fCounter].sname = sname;
FlatSounds[fCounter].flags = flags;
FlatSounds[fCounter].volume = volume;
fCounter++;
}
void LoadArrays()
{
iCounter = 0;
fCounter = 0;
int FLOOR = 0;
int CEILING = 1;
addItemSounds("Column", "buzz", CHANF_LISTENERZ | CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP);
addItemSounds("TechLamp", "buzz", CHANF_LISTENERZ | CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP);
addItemSounds("TechLamp2", "buzz", CHANF_LISTENERZ | CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP);
addFlatSounds("F_SKY1", CEILING, 128, "outsidewind", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP, 0.5);
addFlatSounds("F_SKY2", CEILING, 128, "outsidewind", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP, 0.5);
addFlatSounds("F_SKY3", CEILING, 128, "outsidewind", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP, 0.5);
addFlatSounds("F_SKY4", CEILING, 128, "outsidewind", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP, 0.5);
addFlatSounds("FLOOR4_8", FLOOR, 64, "scifi-rumble", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP);
addFlatSounds("FLOOR5_1", FLOOR, 64, "scifi-rumble", CHANF_LOOP | CHANF_NOSTOP | CHANF_OVERLAP);
}
// returns area of sector (irregular polygon)
float polygonArea(Sector sec)
{
Array<float> lineAreas;
for (int i = 0; i < sec.Lines.Size(); i++)
{
int v1x = int(sec.Lines[i].V1.P.x);
int v1y = int(sec.Lines[i].V1.P.y);
int v2x = int(sec.Lines[i].V2.P.x);
int v2y = int(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 idle ambient sounds
override void WorldLoaded(WorldEvent e)
{
LoadArrays();
int FLOOR = 0;
int CEILING = 1;
TexMan texture;
for(int i = 0; i < Level.Sectors.Size(); i++)
{
textureid floorid = Level.Sectors[i].GetTexture(FLOOR);
textureid ceilingid = Level.Sectors[i].GetTexture(CEILING);
SecPlane ceilingplane = Level.Sectors[i].CeilingPlane;
SecPlane floorplane = Level.Sectors[i].FloorPlane;
int ceilingZ = int(ceilingplane.ZAtPoint((Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y)));
int floorZ = int(floorplane.ZAtPoint((Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y)));
int centerheight = ceilingZ - floorZ;
for (int ii = 0; ii < fCounter; ii++)
{
string flat = FlatSounds[ii].type == CEILING ? texture.GetName(ceilingid) : texture.GetName(floorid);
if (FlatSounds[ii].fname == flat && centerheight > FlatSounds[ii].height)
{
float pArea = polygonArea(Level.Sectors[i]);
if (pArea > 64)
{
console.printf("Adding %s to %s", FlatSounds[ii].sname, FlatSounds[ii].fname);
vector3 v3 = (Level.Sectors[i].CenterSpot.x, Level.Sectors[i].CenterSpot.y, floorZ);
Actor ptr = Actor.Spawn("IA_Sound", v3);
if (ptr)
{
console.printf(ptr.getSpecies());
ptr.A_StartSound(FlatSounds[ii].sname, CHAN_AUTO, FlatSounds[ii].flags, FlatSounds[ii].volume);
}
}
break;
}
}
}
}
override void WorldThingSpawned(WorldEvent e)
{
if (e.thing)
{
for (int i = 0; i < iCounter; i++)
{
if (ItemSounds[i].cname == e.thing.GetSpecies())
{
console.printf("Adding %s to %s", ItemSounds[i].sname, ItemSounds[i].cname);
Actor ptr = e.thing.Spawn("IA_Sound", e.thing.pos);
if (ptr)
{
console.printf(ptr.getSpecies());
ptr.A_StartSound(ItemSounds[i].sname, CHAN_AUTO, ItemSounds[i].flags, ItemSounds[i].volume);
}
}
break;
}
}
}
}
The item sound spawner is somewhat simpler. For now the only item sound is an electronic humming noise. When an item spawns, it loops through the ItemSounds array, matches the actor species, and spawns an IA_Sound actor that returns an Actor ptr. That ptr starts the sound in the array. This isn't attached to the originator, so it's only good for stationary objects such as lamps.
The flat sound spawner has a few more parameters to consider, since sectors often vary in size and shape depending on their purpose. The script loops through all the sectors and for each ceiling and floor flat also loops through the FlatSounds array. When it finds a match it also checks that height exceeds the defined height to add the sound. It also checks the sector area with an arbitrary size of at least 1 square map unit. This makes sure there aren't multiple overlapping sounds for tiny sectors created solely for lighting effects, for example. Other than that it works the same as item sounds.
The sounds aren't fancy. I've added short looping sound effects for outside wind and a "scifi" rumbling, but of course they can be anything that sets a tone or gets under your skin. My intention is to add a universal element of ambiance independent of map design.
I've set this up so all sounds loop, but that doesn't have to be the case; flags can be set differently in the LoadArrays function. An inventory pickup item, for example, may have an option of playing an "ambient" sound once using this method. I haven't tried that, and there are probably more effective ways of accomplishing that.