// Rainbow v003.001.046 // Preset players pick colors // New players pick colors to signup //flow control integer PreSet; // True if first player was set by game //time control integer Delay; integer TimeLeft; integer ReportFreq = 30; integer ReportCount; //space control float seekArea = 10.0; float seekFreq = 5.0; integer seekIndex = 0; //text string needs1more = "\nneeds another player!\n"; string choose_color = " to choose a color."; string superText; string subText; string LF = "\n"; string TouchMe = "To play,\ntouch the rainbow"; //comm integer TalkOn = -1; integer listen_handle; string sayOK; //color info list Color_Vectors; vector white = < 1.0, 1.0, 1.0 >; //all players info integer maxPlayers; list Player_Keys; list Player_Colors; //current player info integer WhoseTurn = 0; // Count through players key WhoseKey; string WhoseName; integer AnyTouch = TRUE; // True:Anyone; False:Only player 1 can touch integer WhoQuit; //calling program info key Boss = NULL_KEY; string BossName; string Game; setText( integer Timed ){ string toGo; if( Timed ) toGo = (string) TimeLeft + "sec" + LF; toGo = Game + superText + toGo + subText; llSetText( toGo, white, 1.0 ); } setupWho(){ llSetTimerEvent( 0.0 ); WhoseKey = llList2Key( Player_Keys, WhoseTurn ); PreSet = ( WhoseKey != NULL_KEY ); string text2say = "Anyone care to join in a game of " + BossName + "?"; string msg = "Player " + (string) WhoseTurn + " is "; if( PreSet ){ TimeLeft = Delay; WhoseName = llKey2Name( WhoseKey ); // msg += WhoseName; text2say = WhoseName + " has " + (string) TimeLeft + " seconds" + choose_color; superText = WhoseName + LF + "has "; subText = choose_color; } else { TimeLeft = Delay * 2; // msg += "anyone"; if( WhoseTurn == 0 ){ superText = "No players signed up.\n"; subText = TouchMe; } else { superText = ""; integer count = 0; string named; text2say = "Anyone care to join "; for(; count < WhoseTurn; ++count ){ named = llKey2Name( llList2Key( Player_Keys, count )); superText += named + LF; text2say += named; if(( WhoseTurn > 2 ) && ( count < WhoseTurn - 1 )) text2say += ","; text2say += " "; if(( count == WhoseTurn - 1 ) && ( count > 1 )) text2say += "& "; } text2say += "in a game of " + BossName + "?"; integer left2play = maxPlayers - WhoseTurn; superText += "need"; if( WhoseTurn < 2 ) superText += "s"; superText += " " + (string) left2play + " more player"; if( left2play > 1 ) superText += "s"; superText += LF + "within "; subText = TouchMe; } } // msg += "\ngetWho:\nWhoseKey: " + (string) WhoseKey // + "\nPreSet = " + (string) PreSet; // llOwnerSay( msg ); llWhisper( 0, text2say ); integer doTime = ( ( PreSet != 0 ) || ( WhoseTurn > 0 ) ); setText( doTime ); ReportCount = 0; seekIndex = 0; llSetTimerEvent( seekFreq ); if( doTime ){ llSensor( "", llList2Key( Player_Keys, seekIndex ), AGENT, seekArea, PI ); } } setAllColors(){ integer count = 0; for(; count < llGetListLength( Color_Vectors ); ++count ) { vector colorUp = llList2Vector( Color_Vectors, count ); llSetLinkPrimitiveParams( count + 1, [ PRIM_COLOR, ALL_SIDES, colorUp, 1.0, PRIM_FULLBRIGHT, ALL_SIDES, TRUE ]); } } default{ state_entry(){ llSetText( "", white, 0.0 ); TouchMe += choose_color; } on_rez( integer param ) { TalkOn = param; if( TalkOn == 0 ) TalkOn = -4444; sayOK = "REZD"; listen_handle = llListen( TalkOn, "", NULL_KEY, ""); llSay( TalkOn, sayOK ); // llOwnerSay( "/" + (string) TalkOn + " " + sayOK ); llSetTimerEvent( 20 ); } timer() { llSay( TalkOn, sayOK ); // llOwnerSay( "/" + (string) TalkOn + " " + sayOK ); } listen( integer channel, string name, key id, string message ){ if( message == "BYE!" ) { llDie(); llListenRemove( listen_handle ); llResetTime(); jump endListen; } // hears "PICK" followed by Delay, color vectors & player keys // // llOwnerSay("Heard " + message ); list msgRecd = llParseString2List( message, [ "//" ], [ "" ] ); // list msgRecd = [ "PICK", // 30, // <1.00000, 0.00000, 0.00000>, // <0.00000, 0.00000, 1.00000>, // <1.00000, 1.00000, 0.00000>, // <0.00000, 1.00000, 0.00000>, // <1.00000, 0.00000, 1.00000>, // <0.00000, 1.00000, 1.00000>, // NULL_KEY, // NULL_KEY]; string Told = llList2String( msgRecd, 0 ); //llOwnerSay("Heard " + Told); if( Told != "PICK" ) jump endListen; sayOK = "WAIT"; Delay = (integer) llList2String( msgRecd, 1 ); if( Delay < 1 ) Delay = 30; integer index = 2; string item; vector newColor; key newKey; integer posCV; integer posPK; // integer count; do { item = llStringTrim( llList2String( msgRecd, index ), STRING_TRIM); newColor = (vector) item; newKey = (key) item; integer goodColor = ( newColor != ZERO_VECTOR ); if( goodColor ) { posCV = llGetListLength( Color_Vectors ); Color_Vectors = llListInsertList( Color_Vectors, [ newColor ], posCV ); jump incrIndex; } else if( newKey ){ jump gotKey; } else if( newKey == NULL_KEY ){ jump gotKey; } else { jump endListen; } @gotKey; posPK = llGetListLength( Player_Keys ); Player_Keys = llListInsertList( Player_Keys, [ newKey ], posPK ); @incrIndex; ++index; } while( index < llGetListLength( msgRecd ) ); integer qPlayers = llGetListLength( Player_Keys ); integer qColors = llGetListLength( Color_Vectors ); if( ( qPlayers < 1 ) || ( qColors < 1 ) || ( qPlayers > qColors ) || ( qColors > llGetNumberOfPrims() ) ) jump endListen; maxPlayers = qPlayers; // string msg = LF + "Colors: " + (string) qColors // + LF + "Players: " + (string) qPlayers; // integer count = 0; // for(; count < maxPlayers; ++count){ // key aKey = llList2Key( Player_Keys, count ); // if( aKey != NULL_KEY ) // msg+= LF + llKey2Name( aKey ); // } // llOwnerSay( msg ); Boss = id; BossName = name; Game = "*** " + BossName + " ***\n" + (string) qPlayers + "-player game\n---\n\n"; setAllColors(); state PickColors; @endListen; sayOK = "REZD"; } } state PickColors{ // Starts waiting for touch // For each preset player in turn to choose color, // Then for any further players to sign up by choosing a color. // For presets and after-the-first-person, // if not enough touched within Delay seconds, // cancels all signups and starts over. state_entry(){ listen_handle = llListen(TalkOn, "", Boss, ""); sayOK = "WAIT"; setupWho(); } timer(){ if( ReportCount == 0 ) llSay( TalkOn, sayOK ); ReportCount = ( ReportCount + (integer) seekFreq ) % ReportFreq; // // llOwnerSay("Count: " + (string) ReportCount ); // all players must stay in vicinity integer doTime = ( PreSet != 0 ) || ( WhoseTurn > 0 ); if( doTime ){ if( WhoseTurn > 0 ) seekIndex = ( seekIndex + 1 ) % WhoseTurn; llSensor( "", llList2Key( Player_Keys, seekIndex ), AGENT, seekArea, PI ); //llOwnerSay( "TimeLeft == " + (string) TimeLeft ); TimeLeft -= (integer) seekFreq; setText( TRUE ); if( TimeLeft <= 0 ){ string TimedOut = "Timed out waiting for "; if( PreSet ) { TimedOut += WhoseName + choose_color; llWhisper( 0, TimedOut ); WhoQuit = WhoseTurn; state Cancel_Player; } TimedOut += "another player."; llWhisper( 0, TimedOut ); state ReSet_Players; } } } no_sensor() { WhoQuit = seekIndex; string nameQuit = llKey2Name( llList2Key( Player_Keys, WhoQuit ) ); llWhisper( 0, WhoseName + " went out of range." ); state Cancel_Player; } touch_start( integer touches ){ // Discounted if player roster is full and just waiting to die rag if( WhoseTurn == maxPlayers ) jump endTouch; integer which_touch = 0; @forTouch; integer touchPrim = llDetectedLinkNumber ( which_touch ) - 1; if( WhoseTurn == 0 ) jump PreSetCheck; // Discounted if color is not available integer available = TRUE; integer pikd; integer count = 0; for(; count < WhoseTurn ; ++count ){ pikd = llList2Integer( Player_Colors, count ); if( pikd == touchPrim ){ available = FALSE; count = maxPlayers; } } if( !available ) jump nextTouch; @PreSetCheck; // Discounted if PreSet true but not PreSet player key touchKey = llDetectedKey( 0 ); if( PreSet && ( touchKey != WhoseKey ) ) jump nextTouch; list Tlist = llGetObjectDetails( touchKey, [ OBJECT_NAME, OBJECT_POS ] ); // Discounted if from outside perimeter vector vecWho = llList2Vector( Tlist, 1 ); float farAway = llVecDist( vecWho, llGetPos() ); if( farAway > seekArea ) jump nextTouch; // Accept player // remember player key if( !PreSet) Player_Keys = llListReplaceList( Player_Keys, [ touchKey ], WhoseTurn, WhoseTurn ); // remember player color index Player_Colors = llListReplaceList( Player_Colors, [ touchPrim ], WhoseTurn, WhoseTurn); // Darken the touched sphere and make it semi-transparent; vector darker = llList2Vector( Color_Vectors, touchPrim ); darker = < darker.x / 4, darker.y / 4, darker.z / 4 >; llSetLinkPrimitiveParams( touchPrim + 1, [ PRIM_COLOR, ALL_SIDES, darker, 0.5, PRIM_FULLBRIGHT, ALL_SIDES, FALSE ]); ++WhoseTurn; if( WhoseTurn < maxPlayers ){ setupWho(); jump nextTouch; } // Roster is full. // Tells calling game "DONE" // followed by the list of player keys & color indexes list Finished = Player_Colors; Finished = [ "DONE" ]; Finished = llListInsertList( Finished, Player_Keys, 1 ); Finished = llListInsertList( Finished, Player_Colors, maxPlayers + 1); llSay( TalkOn, llDumpList2String( Finished, "//" ) ); // All prims are darkened-transparentized integer qColors = llGetListLength( Color_Vectors ); if( WhoseTurn == qColors ) jump endTouch; llSetLinkPrimitiveParams( LINK_SET, [ PRIM_COLOR, ALL_SIDES, < 0.0, 0.0, 0.0 >, 0.0, PRIM_FULLBRIGHT, ALL_SIDES, FALSE ]); jump endTouch; @nextTouch; ++which_touch; if( which_touch < touches ) jump forTouch; @endTouch; } listen( integer channel, string name, key id, string message ){ if( message == "BYE!" ) llDie(); } } state ReSet_Players { state_entry() { integer count = 0; for(; count < maxPlayers; ++count ) Player_Keys = llListReplaceList( Player_Keys, [ NULL_KEY ], count, count ); WhoseTurn = 0; PreSet = FALSE; setAllColors(); state PickColors; } } state Cancel_Player { state_entry() { //reinstate chosen color integer whichColor = llList2Integer( Player_Colors, WhoQuit ); vector thatColor = llList2Vector( Color_Vectors, whichColor ); llSetLinkPrimitiveParams( WhoQuit, [ PRIM_COLOR, ALL_SIDES, thatColor, 1.0, PRIM_FULLBRIGHT, ALL_SIDES, TRUE ]); //unregister player & move any later players down 1 if( WhoseTurn == WhoQuit ) jump nullPlayer; integer count = WhoQuit; for(; count < WhoseTurn - 1; ++count){ integer aColor = llList2Integer( Player_Colors, count + 1 ); Player_Colors = llListReplaceList( Player_Colors, [ aColor ], count, count ); key aKey = llList2Key( Player_Keys, count + 1 ); Player_Keys = llListReplaceList ( Player_Keys, [ aKey ], count, count ); } --WhoseTurn; @nullPlayer; Player_Keys = llListReplaceList ( Player_Keys, [ NULL_KEY ], count, count ); state PickColors; } }