User:Allen Kerensky/Myriad Lite/Myriad Lite Turret Bullet-Preview6.lsl
From OpenSimulator
< User:Allen Kerensky | Myriad Lite
Revision as of 10:28, 12 August 2012 by Allen Kerensky (Talk | contribs)
Myriad_Lite_Turret_Bullet-Preview6.lsl
// Myriad_Lite_Turret_Bullet-Preview6.lsl // Copyright (c) 2012 by Allen Kerensky (OSG/SL) All Rights Reserved. // This work is dual-licensed under // Creative Commons Attribution (CC BY) 3.0 Unported // http://creativecommons.org/licenses/by/3.0/ // - or - // Modified BSD License (3-clause) // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Myriad Lite nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN // NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The Myriad RPG System was designed, written, and illustrated by Ashok Desai // Myriad RPG System licensed under: // Creative Commons Attribution (CC BY) 2.0 UK: England and Wales // http://creativecommons.org/licenses/by/2.0/uk/ string VERSION = "0.0.0"; // version number string VERDATE = "20120511"; // version date // Includes Keknehv's Particle Script v1.2 //============================================================================ // MESSAGE FORMAT REFERENCE //============================================================================ // CHANMYRIAD IN - RPEVENT|str event message // CHANPLAYER OUT - DEPRECATED - TOHIT|str attackdice|key who/whatwashit|key bulletowner|str bulletname // CHANPLAYER OUT - RANGEDCOMBAT|str attackdice|key who/whatwashit|key bulletowner|str bulletname //============================================================================ // Bullet Configuration //============================================================================ string RICOCHET = "nebs_smoke_particle_01"; // puff-of-smoke texture to show on bullet hits/ricochets - put this texture in bullet prim string SOUND = ""; // a ricochet sound float BOUYANCY = 1.0; // how buoyant is the bullet for physics float TIMEOUT = 20.0; // control timer to force bullet to die // Myriad config integer MINDAMAGE = 1; // minimum valid damage value for weapon integer MAXDAMAGE = 5; // maximum valid damage value for weapon integer DAMAGE = 1; // default how much damage do you want this weapon to cause? can be overriden on rez! string DIV = "|"; // divider between parts of Myriad API messages integer CHANMYRIAD = -999; // channel to send Myriad RP events to // turret coordination integer CHANOBJECT; // bullet-specific channel key SHOOTERKEY; // key of who shot us //============================================================================ // GLOBAL DIE() // This kludge is to try very hard to force bullets to eventually die on OpenSims. // Requested by Lani Global (OSgrid) //============================================================================ DIE() { while ( TRUE == TRUE ) { // this will always be true, forming an infinite loop llDie(); // just keep trying to die, forever... one will eventually work! } } //============================================================================ // Keknehv's Particle Script v1.2 //============================================================================ // Retrieved 2011-04-30 from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryKeknehvParticles // 1.0 -- 5/30/05 // 1.1 -- 6/17/05 // 1.2 -- 9/22/05 (Forgot PSYS_SRC_MAX_AGE) // This function may be used in anything you choose, including and not limited to commercial products. // Just copy the MakeParticles() function; it will function without any other variables in a different script // ( You can, of course, rename MakeParticles() to something else, such as StartFlames() ) MAKEPARTICLES(string texture) { if ( texture == "" || texture == NULL_KEY ) { // no texture set, no reason to show particles llParticleSystem([ ]); // shut off any particles that were somehow running return; // exit early since we're not going to show more particles without a texture to show } // This is the function that actually starts the particle system. llParticleSystem([ //KPSv1.0 PSYS_PART_FLAGS , 0 //Comment out any of the following masks to deactivate them //| PSYS_PART_BOUNCE_MASK //Bounce on object's z-axis | PSYS_PART_WIND_MASK //Particles are moved by wind | PSYS_PART_INTERP_COLOR_MASK //Colors fade from start to end | PSYS_PART_INTERP_SCALE_MASK //Scale fades from beginning to end //| PSYS_PART_FOLLOW_SRC_MASK //Particles follow the emitter //| PSYS_PART_FOLLOW_VELOCITY_MASK //Particles are created at the velocity of the emitter //| PSYS_PART_TARGET_POS_MASK //Particles follow the target | PSYS_PART_EMISSIVE_MASK //Particles are self-lit (glow) //| PSYS_PART_TARGET_LINEAR_MASK //Undocumented--Sends particles in straight line? //,PSYS_SRC_TARGET_KEY , NULL_KEY, //Key of the target for the particles to head towards //Choose one of these as a pattern: //PSYS_SRC_PATTERN_DROP Particles start at emitter with no velocity //PSYS_SRC_PATTERN_EXPLODE Particles explode from the emitter //PSYS_SRC_PATTERN_ANGLE Particles are emitted in a 2-D angle //PSYS_SRC_PATTERN_ANGLE_CONE Particles are emitted in a 3-D cone //PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY Particles are emitted everywhere except for a 3-D cone ,PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE ,PSYS_SRC_TEXTURE, texture //UUID of the desired particle texture, or inventory name ,PSYS_SRC_MAX_AGE, 1.0 //Time, in seconds, for particles to be emitted. 0 = forever ,PSYS_PART_MAX_AGE, 5.0 //Lifetime, in seconds, that a particle lasts ,PSYS_SRC_BURST_RATE, 0.02 //How long, in seconds, between each emission ,PSYS_SRC_BURST_PART_COUNT, 1 //Number of particles per emission ,PSYS_SRC_BURST_RADIUS, 0.01 //Radius of emission ,PSYS_SRC_BURST_SPEED_MIN, 0.01 //Minimum speed of an emitted particle ,PSYS_SRC_BURST_SPEED_MAX, 1.0 //Maximum speed of an emitted particle ,PSYS_SRC_ACCEL, <0.05,0.05,0.05> //Acceleration of particles each second ,PSYS_PART_START_COLOR, <1.0,1.0,1.0> //Starting RGB color ,PSYS_PART_END_COLOR, <0.5,0.5,0.5> //Ending RGB color, if INTERP_COLOR_MASK is on ,PSYS_PART_START_ALPHA, 0.9 //Starting transparency, 1 is opaque, 0 is transparent. ,PSYS_PART_END_ALPHA, 0.0 //Ending transparency ,PSYS_PART_START_SCALE, <0.5,0.5,0.0> //Starting particle size ,PSYS_PART_END_SCALE, <1.0,1.0,0.0> //Ending particle size, if INTERP_SCALE_MASK is on ,PSYS_SRC_ANGLE_BEGIN, PI //Inner angle for ANGLE patterns ,PSYS_SRC_ANGLE_END, PI //Outer angle for ANGLE patterns ,PSYS_SRC_OMEGA, <0.0,0.0,0.0> //Rotation of ANGLE patterns, similar to llTargetOmega() ]); if ( SOUND != "" ) llPlaySound(SOUND,1.0); // play sound on hit if configured } //============================================================================ // GLOBAL SETUP() //============================================================================ SETUP(integer type) { CHANOBJECT = (integer)("0x"+llGetSubString(llGetKey(),0,6)); // turret will tell us its key on shoot llListen(CHANOBJECT,"",NULL_KEY,""); // setup listener to get shooting turret's key if ( llGetStatus(STATUS_PHYSICS) == FALSE ) { // is the bullet a physics object? llSetStatus(STATUS_PHYSICS, TRUE); // if not, make it one } llSetStatus(STATUS_DIE_AT_EDGE, TRUE); // set bullet to die if it crosses a region edge llSetPrimitiveParams([PRIM_TEMP_ON_REZ,TRUE]); // set bullet to be temp-on-rez to cleanup and not count against prim limits llSetBuoyancy(BOUYANCY); // make bullet float so it flies if ( type >= MINDAMAGE && type <= MAXDAMAGE ) { // is the damage value passed on rez valid? DAMAGE = type; // yes it is, override bullet default } llSetDamage((float)DAMAGE); // set the Linden Lab Combat System damage value to the same as Myriad damage class llSetTimerEvent(TIMEOUT); // start the timeout timer to try to force bullet to die too } //============================================================================ // STATE DEFAULT - where the program starts //============================================================================ default { //------------------------------------------------------------------------ // COLLISION_START - we just hit an object or avatar //------------------------------------------------------------------------ collision_start(integer collisions) { while(collisions--) { // step through each collision event counting down // calculate the dynamic channel of who/what we hit integer dynchan = (integer)("0x"+llGetSubString((string)SHOOTERKEY,0,6)); if ( dynchan == 0 ) { return;} // did not get the turret UUID in chat // send a ranged combat check to the HUD of the shooter // hitting with a bullet is not an automatic "you hit for damage" // instead it triggers the shooter to make a ranged combat skill check against their victim // if the skill check succeeds, THEN the shot is applied against the victim's armor llRegionSay(dynchan,"RANGEDCOMBAT"+DIV+(string)DAMAGE+DIV+(string)llDetectedKey(collisions)+DIV+(string)SHOOTERKEY+DIV+llGetObjectName()); key who = llDetectedKey(collisions); // get the key of what or who we hit // llGetObjectDetails returns avatar key as "owner" of the avatar itself // so if key of what we hit matches owner's key, we hit an avatar themselves rather than someone's object key owner = llList2Key(llGetObjectDetails(who,[OBJECT_OWNER]),0); // get the owner of the key of what we hit if ( who == owner ) { // so, did we hit an actual avatar? // yes, so as a basic anti-cheat, let's announce to the region that someone is being shot at by someone else llRegionSay(CHANMYRIAD,"RPEVENT"+DIV+llKey2Name(SHOOTERKEY)+" shot at "+llDetectedName(collisions)+"!"); } } // TODO Shrapnel? // TODO Through and through? MAKEPARTICLES(RICOCHET); // show the bullet impact DIE(); // jump to infinite die loop to cleanup this bullet } //------------------------------------------------------------------------ // LAND_COLLISION - what to do if bullet hits the ground //------------------------------------------------------------------------ land_collision_start( vector collisions) { collisions = <0,0,0>; // LSLINT MAKEPARTICLES(RICOCHET); // show the poof of smoke from the ricochet, movie style DIE(); // jump to the infinite die loop to clean up this bullet } //------------------------------------------------------------------------ // LISTEN - get shooting objects key after rez //------------------------------------------------------------------------ listen(integer channel,string name,key id,string msg) { channel = 0; // LSLint name = ""; // LSLint msg = ""; // LSLint SHOOTERKEY = id; // store shooterID } //------------------------------------------------------------------------ // ON_REZ - called when bullet is rezzed by firearm //------------------------------------------------------------------------ on_rez(integer start_param) { SETUP(start_param); // pass any start param to setup as a request to set a custom damage value, if valid, it will be used } //------------------------------------------------------------------------ // STATE_ENTRY - called if bullet rezzed onto the ground //------------------------------------------------------------------------ state_entry() { SETUP(DAMAGE); // sets default damage value - may be overridden on rez } //------------------------------------------------------------------------ // TIMER - trigger bullet to die after a given time, if all else fails //------------------------------------------------------------------------ timer() { DIE(); // timer expired, jump to infinite die loop to cleanup this bullet } } //============================================================================ // END //============================================================================