here is the whole hot tub script with base, water and button parts included.
put this in base unit
//====================================================================================
// Super Hottub 1.1 -- Siggy Romulus -- Get_Toe() Scripts
//------------------------------------------------------------------------------------
// New Features : - Starts with water rezzed
// - Water 'follows' tub when it's moved, no more HOTTUB RESET
// - Buttons 'flash' and recolor to show their settings
// - Variable steam settings
// - Bubble Jets with nifty bubblesounds.
// - Voice commands only from owner
// - Code tidy up, 1.3 friendly, little more streamlined.
//=====================================================================================
// Variables
//-------------------------------------------------------------------------------------
integer WATER_CHANNEL = 31; // Chat channel for water to listen to commands
string WATER_NAME = "Water-1.07"; // Name of the water object
vector WATER_POS; // Waters start position
rotation WATER_ROT; // Waters start rotation
//======================================================================================
// Functions
//--------------------------------------------------------------------------------------
Init_Water() // To Rez Water or to Reset it
{
llSay(WATER_CHANNEL,"WATER DIE"); // Kill any Water we have running
WATER_POS = llGetPos(); // Fetch the tubs coords and calculate
WATER_POS.z = WATER_POS.z + .01; // Water start position and rotation
WATER_ROT = llGetRot();
// Finally, rez the water
llRezObject(WATER_NAME, WATER_POS, ZERO_VECTOR, WATER_ROT, 0);
}
//=======================================================================================
// States
//---------------------------------------------------------------------------------------
default
{
state_entry()
{
string Owner;
key OwnerKey;
OwnerKey = llGetOwner(); // Fetch the owners key
Owner = llKey2Name(OwnerKey); // Work out their name
Init_Water(); // Rez the water object
llListen(0, Owner , "", ""); // Listen for owner commands
}
on_rez( integer start_param) // Setup Water when we rez
{
string Owner; // Do I really need to do all this twice?
key OwnerKey; // Better safe than sorry I suppose
OwnerKey = llGetOwner();
Owner = llKey2Name(OwnerKey);
Init_Water(); // Initialize the water object
llListen(0, Owner, "", "");
}
moving_end() // When the hottub is moved, we want to
{ // 'move' the water into it -- killing the
Init_Water(); // old and rezzing again is a simple way
} // but not terribly elegant.
listen(integer channel, string name, key id, string msg)
{
if (msg == "HOTTUB RESET") // Left in for backwards compatability only
{
Init_Water();
}
}
}
this goes in water
//====================================================================================
// Hot Tub Water 1.10 -- Siggy Romulus, Get_Toe() Scripts.
//====================================================================================
// Variables
//------------------------------------------------------------------------------------
integer HOTTUB_CHANNEL = 31; // Channel the tub will talk on
integer JETS_CHANNEL = 34; // Channel the jets will talk on
integer STEAM_LEVEL; // Current steam level (0 - 3)
float WATER_OFFSET = 0.73; // Offset between full and empty.
float STEP_SIZE = 0.05; // How much to move water each step
float STEP_DELAY = 0.01; // Delay between movement steps
vector WATER_POS; // Water position
vector EMPTY_LEVEL; // Water at empty position
vector FULL_LEVEL; // Water at full postion
string FILL_SOUND = "water.wav"; // Assorted sound files
string EMPTY_SOUND = "lowater.wav";
string WATER_SOUND = "littlewater.wav";
string JETS_SOUND = "bubbling_water.wav";
float VOLUME = 0.8;
//====================================================================================
// Particle Systems -- Abridged, see Ama Omegas particle script 4.0
//------------------------------------------------------------------------------------
Spray_On()
{
llParticleSystem([
PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK |
PSYS_PART_WIND_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE,
PSYS_PART_MAX_AGE, 3.0,
PSYS_SRC_BURST_SPEED_MIN, 0.1,
PSYS_SRC_BURST_SPEED_MAX, 0.5,
PSYS_PART_START_ALPHA, 0.7,
PSYS_PART_END_ALPHA, 0.1,
PSYS_PART_START_COLOR, < 1.0, 1.0, 1.0>,
PSYS_PART_END_COLOR, < 1.0, 1.0, 1.0>,
PSYS_PART_START_SCALE, < 0.5, 0.5, 0.5>,
PSYS_PART_END_SCALE, < 1.1, 1.1, 1.1>,
PSYS_SRC_ACCEL, < 0.0, 0.0, 0.3>,
PSYS_SRC_BURST_RATE, 0.05,
PSYS_SRC_BURST_RADIUS, 0.1,
PSYS_SRC_BURST_PART_COUNT, 1,
PSYS_SRC_OUTERANGLE, 1.54,
PSYS_SRC_INNERANGLE, 1.55,
PSYS_SRC_OMEGA, < 0.0, 0.0, 10.0 >,
PSYS_SRC_MAX_AGE, 0.0
]);
}
//------------------------------------------------------------------------------------
Steam_Low() // Low Level Steam
{
llParticleSystem([
PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK |
PSYS_PART_FOLLOW_VELOCITY_MASK |
PSYS_PART_EMISSIVE_MASK | PSYS_PART_BOUNCE_MASK,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE,
PSYS_PART_MAX_AGE, 2.0,
PSYS_SRC_BURST_SPEED_MIN, 0.3,
PSYS_SRC_BURST_SPEED_MAX, 1.0,
PSYS_PART_START_ALPHA, 0.3,
PSYS_PART_END_ALPHA, 0.01,
PSYS_PART_START_COLOR, < 0.8, 0.8, 0.8>,
PSYS_PART_END_COLOR, < 0.5, 0.5, 0.5>,
PSYS_PART_START_SCALE, < 2.0, 2.0, 2.0>,
PSYS_PART_END_SCALE, < 0.2, 0.2, 0.2>,
PSYS_SRC_ACCEL, < 0.0, 0.0, -1.0>,
PSYS_SRC_BURST_RATE, 0.05,
PSYS_SRC_BURST_RADIUS, 1.0,
PSYS_SRC_BURST_PART_COUNT, 35,
PSYS_SRC_OUTERANGLE, 0.4,
PSYS_SRC_INNERANGLE, 0.55,
PSYS_SRC_OMEGA, < 0.0, 0.0, 0.0 >,
PSYS_SRC_MAX_AGE, 0.0
]);
}
//------------------------------------------------------------------------------------
Steam_Medium() // Medium Level Steam
{
llParticleSystem([
PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK |
PSYS_PART_FOLLOW_VELOCITY_MASK |
PSYS_PART_EMISSIVE_MASK | PSYS_PART_BOUNCE_MASK,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE,
PSYS_PART_MAX_AGE, 2.0,
PSYS_SRC_BURST_SPEED_MIN, 0.5,
PSYS_SRC_BURST_SPEED_MAX, 1.5,
PSYS_PART_START_ALPHA, 0.35,
PSYS_PART_END_ALPHA, 0.05,
PSYS_PART_START_COLOR, < 0.8, 0.8, 0.8>,
PSYS_PART_END_COLOR, < 0.5, 0.5, 0.5>,
PSYS_PART_START_SCALE, < 2.0, 2.0, 2.0>,
PSYS_PART_END_SCALE, < 0.2, 0.2, 0.2>,
PSYS_SRC_ACCEL, < 0.0, 0.0, -3.0>,
PSYS_SRC_BURST_RATE, 0.05,
PSYS_SRC_BURST_RADIUS, 1.0,
PSYS_SRC_BURST_PART_COUNT, 35,
PSYS_SRC_OUTERANGLE, 0.4,
PSYS_SRC_INNERANGLE, 0.55,
PSYS_SRC_OMEGA, < 0.0, 0.0, 0.0 >,
PSYS_SRC_MAX_AGE, 0.0
]);
}
//------------------------------------------------------------------------------------
Steam_High() // High Steam Level
{
llParticleSystem([
PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK |
PSYS_PART_FOLLOW_VELOCITY_MASK |
PSYS_PART_EMISSIVE_MASK | PSYS_PART_BOUNCE_MASK,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE,
PSYS_PART_MAX_AGE, 2.0,
PSYS_SRC_BURST_SPEED_MIN, 1.0,
PSYS_SRC_BURST_SPEED_MAX, 1.9,
PSYS_PART_START_ALPHA, 0.6,
PSYS_PART_END_ALPHA, 0.1,
PSYS_PART_START_COLOR, < 0.8, 0.8, 0.8>,
PSYS_PART_END_COLOR, < 0.5, 0.5, 0.5>,
PSYS_PART_START_SCALE, < 2.1, 2.1, 2.1>,
PSYS_PART_END_SCALE, < 0.3, 0.3, 0.3>,
PSYS_SRC_ACCEL, < 0.0, 0.0, -3.0>,
PSYS_SRC_BURST_RATE, 0.05,
PSYS_SRC_BURST_RADIUS, 1.0,
PSYS_SRC_BURST_PART_COUNT, 38,
PSYS_SRC_OUTERANGLE, 0.4,
PSYS_SRC_INNERANGLE, 0.55,
PSYS_SRC_OMEGA, < 0.0, 0.0, 0.0 >,
PSYS_SRC_MAX_AGE, 0.0
]);
}
//------------------------------------------------------------------------------------
Spray_Off()
{
llParticleSystem([]); // A blank particle system for turning off steam/spray
}
//====================================================================================
// Functions
//------------------------------------------------------------------------------------
Init_Water() // Calculate postions and intitalise variables.
{
EMPTY_LEVEL = llGetPos(); // Rezzes at Empty pos
FULL_LEVEL = llGetPos();
FULL_LEVEL.z += WATER_OFFSET; // Calculate full level
llSay(HOTTUB_CHANNEL, "WATER OFF"); // Water is off
STEAM_LEVEL = 0; // Steam is off
llSay(HOTTUB_CHANNEL, "STEAM LEVEL 0"); // Steam button to off
Spray_Off();
llSay(JETS_CHANNEL, "jets off"); // Turn jets off
llStopSound(); // Stop all sounds
llLoopSound(WATER_SOUND, VOLUME); // Start water sound
report(); // Send key to the jets
}
//------------------------------------------------------------------------------------
Slow_Move (float height) // Move a non phys object slowly in steps
{
vector pos = llGetPos(); // Calculate position steps
integer steps = llAbs((integer)((pos.z - height) / STEP_SIZE));
float step;
integer i;
if (height > pos.z) // Going up or down?
{
step = STEP_SIZE;
}
else
{
step = -STEP_SIZE;
}
for (i = 0; i < steps; ++i) // Go through steps, moving a little each time.
{
pos.z += step;
llSetPos(pos);
llSleep(STEP_DELAY);
}
pos.z = height; // Set to the exact final position
llSetPos(pos);
}
//------------------------------------------------------------------------------------
report()
{
llSay(JETS_CHANNEL, "waterobject " + (string)llGetKey());
}
//====================================================================================
// States
//------------------------------------------------------------------------------------
default
{
state_entry() // Most of this being in state_entry
{ // is for debugging.
string Owner;
key OwnerKey;
OwnerKey = llGetOwner(); // Get the owner for commands
Owner = llKey2Name(OwnerKey); // And their name
// Set the texture rotating
llSetTextureAnim(ANIM_ON | SMOOTH | ROTATE | LOOP, ALL_SIDES, 0, 0, 1.0, 1000, 0.07);
llListen(HOTTUB_CHANNEL, "", "", ""); // Listen for Hottub Commands
llListen(JETS_CHANNEL, "", "", ""); // Listen for Jet Commands
llListen(0, Owner, "", ""); // Only accept voice commands from owner
Init_Water(); // Initialise the water
}
on_rez(integer start_param ) // This is the real workhorse
{ // When the water is rezzed by the tub
Init_Water(); // Initialise the water
}
listen(integer channel, string name, key id, string msg)
{
if (msg == "LEVEL") // Change water level
{
Spray_On(); // Start the spray
llSay(JETS_CHANNEL, "jets off"); // Turn off the jets
WATER_POS = llGetPos();
if (WATER_POS.z > EMPTY_LEVEL.z) // Up or down?
{
llSay(HOTTUB_CHANNEL, "WATER OFF"); // Signal button change to off
llLoopSound(EMPTY_SOUND, VOLUME); // Play water empty sound
Slow_Move(EMPTY_LEVEL.z); // Stop the water
Spray_Off(); // Empty tub, no steam
STEAM_LEVEL = 0; // Steam button to off
llSay(HOTTUB_CHANNEL, "STEAM LEVEL 0");
}
else
{
llSay(HOTTUB_CHANNEL, "WATER ON"); // Signal button change to on
llLoopSound(FILL_SOUND, VOLUME); // Play water fill sound
Slow_Move(FULL_LEVEL.z); // Move the water
Steam_Low(); // Full tub, low steam
STEAM_LEVEL = 1; // Steam button to on
llSay(HOTTUB_CHANNEL, "STEAM LEVEL 1");
}
llLoopSound(WATER_SOUND, VOLUME); // Start water sound
}
//---------------------------------------------------------------------------------
else if (msg == "STEAM")
{
if (STEAM_LEVEL < 3) // Cycle Through Steam Levels
STEAM_LEVEL ++;
else
STEAM_LEVEL = 0;
// Msg to update the steam button
llSay(HOTTUB_CHANNEL, "STEAM LEVEL " + (string) STEAM_LEVEL);
if (STEAM_LEVEL == 0)
{
Spray_Off(); // Call 'blank' particle system
}
else if (STEAM_LEVEL == 1)
{
Steam_Low();
}
else if (STEAM_LEVEL == 2)
{
Steam_Medium();
}
else if (STEAM_LEVEL == 3)
{
Steam_High();
}
}
//---------------------------------------------------------------------------------
else if (msg == "get target")
{
report(); // Jets are requesting the key of the water
}
else if (msg == "JETS ON")
{
llLoopSound(JETS_SOUND, VOLUME); // Requesting a jets sound
}
else if (msg == "JETS OFF")
{
llLoopSound(WATER_SOUND, VOLUME);
}
//---------------------------------------------------------------------------------
else if (msg == "sound off") // Owner Voice Commands
llStopSound();
else if (msg == "steam off") // Kill the sound
{
Spray_Off(); // Kill the steam
STEAM_LEVEL = 0;
llSay(HOTTUB_CHANNEL, "STEAM LEVEL 0");
}
else if (msg == "WATER DIE")
llDie();
}
}
this goes in water off on switch
//======================================================================
// Super Hottub Water Switch -- changes color with water level
//======================================================================
// Variables
//----------------------------------------------------------------------
integer HOTTUB_CHANNEL = 31; // Commmand channel for hottub
//======================================================================
// States
//----------------------------------------------------------------------
default
{
state_entry()
{
llListen(HOTTUB_CHANNEL, "", "", ""); // Listen for commands
}
listen(integer channel, string name, key id, string msg)
{
}
touch_start(integer total_number)
{
llSay(HOTTUB_CHANNEL, "LEVEL"); // Command to change water level
}
}