Would this help:
Toggle shower on/off with click
Use 3 particle sources (simulate multiple jets/nozzles) with adjustable positions & angles
Play looping shower water sound with fade in/out
Allow easy customization of particle appearance, sound volume, and spray parameters
Be heavily commented for easy understanding and future edits
Advanced High-Class Shower Script for OpenSimulator (LSL)
// High-Class Shower with multi-source particles and smooth looping sound
// Author: ChatGPT / Your Name
// Usage: Click the prim to toggle shower ON/OFF
// Customize the parameters below for texture, sound, particle style, and nozzle positions
// ========== CONFIGURATION ==========
// Particle texture UUID (upload your own water droplet texture and replace this)
string PARTICLE_TEXTURE = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
// Shower water looping sound UUID (upload your own shower water sound)
string SHOWER_SOUND = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy";
// Particle emission rate (seconds between bursts)
float PARTICLE_BURST_RATE = 0.1; // Lower = more frequent
// Number of particles per burst per nozzle
integer PARTICLES_PER_BURST = 5;
// Particle size vector (x, y, z) start size of each particle
vector PARTICLE_START_SIZE = ;
// Particle end size (shrinks to this during lifetime)
vector PARTICLE_END_SIZE = ;
// Particle acceleration (gravity effect)
vector PARTICLE_ACCEL = ; // Negative Z = falling down
// Particle color start (RGBA)
vector PARTICLE_START_COLOR = ; // Light blue
float PARTICLE_START_ALPHA = 0.7;
// Particle color end (RGBA)
vector PARTICLE_END_COLOR = ; // Darker blue
float PARTICLE_END_ALPHA = 0.0;
// Max age of particles in seconds
float PARTICLE_MAX_AGE = 2.0;
// Spray radius for particle bursts (how spread out)
float PARTICLE_BURST_RADIUS = 0.05;
// Spray angle range (radians) per nozzle (spread cone)
float SPRAY_ANGLE_BEGIN = 0.0;
float SPRAY_ANGLE_END = 0.1;
// Shower sound volume range
float MAX_SOUND_VOLUME = 1.0; // Max volume when fully ON
float SOUND_FADE_STEP = 0.05; // Volume increment/decrement per timer tick
float SOUND_FADE_INTERVAL = 0.1; // Seconds between volume fades
// Timer interval for particle emission (should match PARTICLE_BURST_RATE)
float PARTICLE_TIMER_INTERVAL = PARTICLE_BURST_RATE;
// Number of particle emitters (spray nozzles)
integer NUM_NOZZLES = 3;
// Offsets for each nozzle from the object's center (local coordinates)
vector NOZZLE_POSITIONS[3] = [
, // Center nozzle
, // Right nozzle
// Left nozzle
];
// Spray directions per nozzle (unit vectors)
vector NOZZLE_DIRECTIONS[3] = [
, // Straight down
, // Slightly angled right and down
// Slightly angled left and down
];
// ========== END CONFIGURATION ==========
// Internal state
integer showerOn = FALSE;
float currentSoundVolume = 0.0; // Current sound volume for fade in/out
// Helper function: generate a particle system list for one nozzle
list createParticleSystem(vector nozzlePos, vector nozzleDir) {
return [
PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_WIND_MASK,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP,
PSYS_PART_START_COLOR, PARTICLE_START_COLOR,
PSYS_PART_END_COLOR, PARTICLE_END_COLOR,
PSYS_PART_START_ALPHA, PARTICLE_START_ALPHA,
PSYS_PART_END_ALPHA, PARTICLE_END_ALPHA,
PSYS_PART_START_SCALE, PARTICLE_START_SIZE,
PSYS_PART_END_SCALE, PARTICLE_END_SIZE,
PSYS_SRC_ACCEL, PARTICLE_ACCEL,
PSYS_SRC_TEXTURE, PARTICLE_TEXTURE,
PSYS_SRC_BURST_RATE, PARTICLE_BURST_RATE,
PSYS_SRC_BURST_RADIUS, PARTICLE_BURST_RADIUS,
PSYS_SRC_BURST_PART_COUNT, PARTICLES_PER_BURST,
PSYS_SRC_MAX_AGE, PARTICLE_MAX_AGE,
PSYS_SRC_ANGLE_BEGIN, SPRAY_ANGLE_BEGIN,
PSYS_SRC_ANGLE_END, SPRAY_ANGLE_END,
PSYS_SRC_OMEGA, ,
PSYS_SRC_BURST_SPEED_MIN, 1.0,
PSYS_SRC_BURST_SPEED_MAX, 1.5,
PSYS_SRC_ACCEL, PARTICLE_ACCEL,
PSYS_SRC_ANGLE_DIRECTION, nozzleDir,
PSYS_SRC_OFFSET, nozzlePos,
PSYS_SRC_MAX_AGE, PARTICLE_MAX_AGE
];
}
// Combine multiple particle system lists for all nozzles
list buildMultiNozzleParticleSystem() {
list combined = [];
integer i;
for (i = 0; i < NUM_NOZZLES; ++i) {
combined += createParticleSystem(NOZZLE_POSITIONS[i], NOZZLE_DIRECTIONS[i]);
}
return combined;
}
default
{
state_entry()
{
llOwnerSay("Shower system ready! Click to toggle ON/OFF.");
}
touch_start(integer total_number)
{
showerOn = !showerOn;
if (showerOn)
{
llOwnerSay("Shower ON");
currentSoundVolume = 0.0;
llSetTimerEvent(SOUND_FADE_INTERVAL); // Use timer for sound fade & particles
llPlaySoundLoop(SHOWER_SOUND, currentSoundVolume);
}
else
{
llOwnerSay("Shower OFF");
// Start fading sound out, timer will handle cleanup
}
}
timer()
{
if (showerOn)
{
// Fade sound volume up to MAX_SOUND_VOLUME gradually
if (currentSoundVolume < MAX_SOUND_VOLUME)
{
currentSoundVolume += SOUND_FADE_STEP;
if (currentSoundVolume > MAX_SOUND_VOLUME)
currentSoundVolume = MAX_SOUND_VOLUME;
llSetSoundVolume(currentSoundVolume);
}
// Emit combined particle system for all nozzles
llParticleSystem(buildMultiNozzleParticleSystem());
}
else
{
// Fade sound volume down to 0, then stop timer and particle system
if (currentSoundVolume > 0.0)
{
currentSoundVolume -= SOUND_FADE_STEP;
if (currentSoundVolume < 0.0)
currentSoundVolume = 0.0;
llSetSoundVolume(currentSoundVolume);
}
else
{
llStopSound();
llParticleSystem([]); // Stop particles
llSetTimerEvent(0.0); // Stop timer
}
}
}
on_rez(integer start_param)
{
llResetScript();
}
attach(key id)
{
if (id == NULL_KEY)
{
// Detach detected, cleanup
showerOn = FALSE;
llStopSound();
llParticleSystem([]);
llSetTimerEvent(0.0);
}
}
}
How to Adjust This Script
Particle Texture: Upload your water droplet texture → Right-click → Copy Asset UUID → paste in PARTICLE_TEXTURE
Shower Sound: Upload shower water sound → Copy Asset UUID → paste in SHOWER_SOUND
Particle Appearance: Adjust colors, alpha, size, acceleration, and burst parameters in the config section.
Nozzle Positions and Directions: Change the vectors in NOZZLE_POSITIONS and NOZZLE_DIRECTIONS to move or angle jets. Positions are local to the prim center. Directions are normalized vectors pointing where the water sprays.
Particle Rate & Count: Modify PARTICLE_BURST_RATE and PARTICLES_PER_BURST for denser or lighter spray.
Sound Volume & Fading: Adjust MAX_SOUND_VOLUME, SOUND_FADE_STEP, and SOUND_FADE_INTERVAL for how quickly sound fades in/out.
Add more nozzles: Increase NUM_NOZZLES and add more entries in the two nozzle arrays.
Explanation
Clicking toggles shower on/off.
When ON, the script plays a looping sound and slowly fades it in, and emits particles from 3 nozzles to simulate water spray.
When OFF, the sound fades out smoothly and particles stop.
Particle emitters are combined from multiple nozzle positions and directions, giving a realistic multi-stream shower effect.
The timer manages both particle emission and sound fading every 0.1 seconds.
like(1)