Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Pistol Script (Open Source) v1.0.0
- // Author: Code Slacker
- // Description: This script operates a normal pistol with single fire and burst fire modes.
- // ==== NOTES ====
- // - The reason this script will require slave scripts is because it will be more responsive on fast mouse clicks. Otherwise there would be a 0.1 second delay, which bugs me. :p
- // - Linked Message number will correspond to the following: -1 for the animation script and casing scripts, 0 for the bullet name, velocity and distance settings, and any number higher will be the number of the bullet slave script
- // - Linked Messages: "f" is fire for the slave and casing scripts
- // "f" on -2 is for any muzzle flash scripts to start
- // "nf" on -2 is for any muzzle flash scripts to stop
- // "r" is reload for the animation script
- // "stop" is for the animation script to stop if running
- // "reset" is for resetting the animation and casing scripts (animation script will start)
- // "crouch" is for the animation script to start the crouching animation
- // "nocrouch" is for the animation script to stop the crouching animation
- // "effectsoff" is for setting the casing scripts to not eject shell casings
- // "effectson" is for setting the casing scripts to eject shell casings
- // ==== FORMAT ====
- // - All global variables will have a "g_" at the beginning of their name
- // - All global variables will be in camelcasing (eg. g_thisVar)
- // - All constants will be all in uppercase, excluding the beginning "g_"
- // - All local variables will be in lowercase and have underscores ("_") to separate words (eg. integer local_variable;)
- // - Subprocedures will be in camelcasing and exclude a "g_" at the beginning of their name
- // - All functions - subprocedures that require input or return output, will be in camelcasing, exclude the "g_" but instead have a "func" at the beginning of their name to distinguish them from normal subprocedures (eg. funcFunkTown)
- // ==== CONSTANTS ====
- integer g_COMMCHAN = 19; // public command channel
- integer g_MENUCHAN = -25; // menu command channel
- integer g_NUMOFSLAVES = 0; // number of slaves (update in run_time_permissions)
- float g_DELAYRELOAD = 3.0; // number of seconds for reloading
- string g_HELPNOTE = "help"; // the notecard to give when the user says "help"
- // SOUNDS
- string g_SNDFIRE = "Fire"; // name of the firing sound
- string g_SNDRELOAD = "Reload"; // name of the reloading sound
- string g_SNDNOAMMO = "b38bdcc9-3a98-8875-da60-b4d1e6805796"; // name of the no ammo sound (the clicking noise)
- string g_SNDDRAW = ""; // this is an optional sound for drawing (won't play if it's empty)
- string g_SNDSLING = ""; // this is an optional sound for slinging (won't play if it's empty)
- key g_OWNER; // store the owner's key to reduce llGetOwner() calls
- // ==== VARIABLES ====
- integer g_magazineSize = 15; // default size of bullets per magazine (can be changed through command)
- integer g_bulletsLeft = g_magazineSize; // the number of bullets currently left in the magazine
- integer g_stopFire = FALSE; // flag to trigger when reloading or in safe mode (stops firing ability)
- integer g_safeMode = FALSE; // safe mode flag (this is only used for the gun's display text)
- integer g_effectsOn = TRUE; // effects to eject casings when firing and magazine when reloading
- integer g_burstFire = FALSE; // flag for burst fire or single fire mode
- integer g_txtOn = TRUE; // display text above gun or not
- integer g_slaveNum = 1; // the current bullet slave number to call upon
- float g_delayFire = 0.03; // number of seconds to delay between firing (can be changed through command)
- float g_velocity = 150.0; // default bullet velocity in meters per second
- float g_velocityLimit = 250.0; // the limit for bullet velocity to be set
- float g_distance = 6.0; // default rez distance roughly meters from camera position
- vector g_TXTCOLOR = <1.0, 1.0, 1.0>; // gun text color (default is green)
- string g_txt = ""; // the gun's display text
- string g_bulletName = "Phantom"; // the currently loaded bullet
- // ==== SUBPROCEDURES ====
- // updateTxt() - updates the gun display text
- // reload() - reloads the gun
- updateTxt()
- {
- // escape if the gun text feature isn't on
- if (g_txtOn == FALSE)
- {
- llSetText("", <0.0, 1.0, 0.0>, 1.0);
- return;
- }
- // display "[ Safe ]" on the gun if safety is on
- if (g_safeMode == TRUE)
- {
- g_txt = "[ Safe ]\n[ " + g_bulletName + " ]";
- // display burst or single fire
- if (g_burstFire == TRUE)
- {
- g_txt += "\n[ Burst Fire ]";
- }
- else
- {
- g_txt += "\n[ Single Fire ]";
- }
- }
- // if safety is off, display normally
- else
- {
- g_txt = "[ " + g_bulletName + " ]\n";
- // display burst or single fire
- if (g_burstFire == TRUE)
- {
- g_txt += "[ Burst Fire ]";
- }
- else
- {
- g_txt += "[ Single Fire ]";
- }
- }
- // add bullets remaining + magazine size
- g_txt += "\n[ " + (string)g_bulletsLeft + "/" + (string)g_magazineSize + " ]";
- // llSetText(g_txt, g_TXTCOLOR, 1.0);
- }
- reload()
- {
- g_stopFire = TRUE; // make sure the gun can't fire during reload
- llMessageLinked(LINK_SET, -2, "nf", ""); // tell any muzzle flash scripts to stop
- if (g_txtOn == TRUE)
- {
- llSetText("", g_TXTCOLOR, 1.0); // "Reloading" text
- }
- llTriggerSound(g_SNDRELOAD, 1.0);
- llMessageLinked(LINK_THIS, -1, "r", ""); // trigger reload animation in animation script
- if (g_effectsOn == TRUE)
- {
- vector pos = llGetPos();
- rotation rot = llGetRot();
- vector fwd = llRot2Fwd(rot)*0.2;
- llRezObject("Magazine", pos+fwd, ZERO_VECTOR, rot, 1);
- }
- g_bulletsLeft = g_magazineSize;
- llSetTimerEvent(g_DELAYRELOAD); // delay the reload for an amount of time
- }
- // ==== FUNCTIONS ====
- // genMenu(integer menu_num) - generates a menu or submenu depending upon the number passed to it
- genMenu(integer menu_num)
- {
- list buttons = [];
- string menu_txt = "";
- // main menu
- if (menu_num == 0)
- {
- buttons = ["Bullet", "Other", "Help", "Firing Mode"];
- menu_txt = "[Select Option]";
- if (g_safeMode == TRUE)
- {
- buttons += "Nosafe";
- }
- else
- {
- buttons += "Safe";
- }
- buttons += "Sling";
- }
- // firing mode submenu
- else if (menu_num == 1)
- {
- buttons = ["Single", "Burst", "Main"];
- menu_txt = "[Firing Modes]\n\nSingle Fire - Fires a single round\nBurst Fire - Fires 3-rounds per shot";
- }
- // bullet selection submenu
- else if (menu_num == 2)
- {
- buttons = ["Damage", "Training", "Phantom", "Main"];
- menu_txt = "[Bullet Types]\n\nDamage - 100% Linden Combat Damage\nTraining - 0% Linden Combat Damage\nPhantom - Penetrates walls and objects; 100% Damage";
- }
- // other submenu
- else if (menu_num == 3)
- {
- buttons = ["Reset"];
- if (g_effectsOn == TRUE)
- {
- buttons += "Effects Off";
- }
- else
- {
- buttons += "Effects On";
- }
- // if (g_txtOn == TRUE)
- // {
- // buttons += "Textoff";
- // }
- // else
- // {
- // buttons += "Texton";
- // }
- buttons += ["Mem", "Main"];
- menu_txt = "[Other]\n\nReset - Resets all scripts\nEffects On - Turns case ejection on\nEffects Off - Turns case ejection off\nMem - Displays available memory";
- }
- llDialog(g_OWNER, menu_txt, buttons, g_MENUCHAN);
- buttons = [];
- }
- default
- {
- state_entry()
- {
- g_OWNER = llGetOwner();
- // make the gun visible and set text
- llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES);
- llSetText("", g_TXTCOLOR, 1.0); // clear the text incase text is off (it will just return in updateTxt
- llListen(g_COMMCHAN, "", g_OWNER, "");
- llListen(g_MENUCHAN, "", g_OWNER, "");
- // check if attached
- if (llGetAttached() > 0)
- {
- llRequestPermissions(g_OWNER, PERMISSION_TAKE_CONTROLS);
- }
- }
- touch_start(integer num_detected)
- {
- if (llDetectedKey(0) == g_OWNER)
- {
- genMenu(0);
- }
- }
- run_time_permissions(integer perms_granted)
- {
- // if permissions are granted
- if (perms_granted & PERMISSION_TAKE_CONTROLS)
- {
- llTakeControls(CONTROL_ML_LBUTTON | CONTROL_FWD | CONTROL_BACK | CONTROL_DOWN | CONTROL_UP, TRUE, TRUE);
- // play draw sound if it exists
- if (g_SNDDRAW != "")
- {
- llTriggerSound(g_SNDDRAW, 1.0);
- }
- g_NUMOFSLAVES = 0; // reset number of slaves
- llMessageLinked(LINK_THIS, -1, "reset", ""); // reset animation and casing scripts
- updateTxt(); // incase text is on, set it
- // get number of slave scripts there are
- integer num_of_scripts = llGetInventoryNumber(INVENTORY_SCRIPT)+1;
- integer i;
- for (i=1; i<num_of_scripts; i++)
- {
- // check if the script "os_pistol.Slave + i" exists
- integer find_slave = llGetInventoryType("os_pistol.Slave" + (string)i);
- // it exists! add to number of slaves
- if (find_slave == INVENTORY_SCRIPT)
- {
- g_NUMOFSLAVES++;
- }
- // none, stop the loop
- else
- {
- i = num_of_scripts;
- }
- }
- // check if there are enough slaves (there must be at least one)
- if (g_NUMOFSLAVES < 1)
- {
- llOwnerSay("/me - [ERROR] You have no bullet slave scripts!");
- }
- llSleep(0.2); // delay incase the scripts are slow at initiating
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- }
- // permissions denied
- else
- {
- llOwnerSay("/me - [ERROR] Permissions Denied.");
- }
- }
- attach(key id)
- {
- // if detached
- if (id == NULL_KEY)
- {
- // release controls for good practice
- if (llGetPermissions() & PERMISSION_TAKE_CONTROLS)
- {
- llReleaseControls();
- }
- llMessageLinked(LINK_THIS, -1, "stop", ""); // tell animation script to stop
- }
- // reset script to update owner
- else if (id != g_OWNER)
- {
- // Delay to reduce the stupid "SlaveX" not found error
- llSleep(0.2);
- llResetScript();
- }
- // normal attach
- else
- {
- // Delay to reduce the stupid "SlaveX" not found error
- llSleep(0.2);
- llRequestPermissions(g_OWNER, PERMISSION_TAKE_CONTROLS);
- }
- }
- // check for any new added bullet slave scripts
- changed(integer change)
- {
- if (~change & CHANGED_INVENTORY)
- {
- return;
- }
- integer next_slave = g_NUMOFSLAVES+1;
- integer find_slave = llGetInventoryType("os_pistol.Slave" + (string)next_slave);
- if (find_slave == INVENTORY_SCRIPT)
- {
- g_NUMOFSLAVES++;
- llSetScriptState("os_pistol.Slave" + (string)next_slave, TRUE);
- llResetOtherScript("os_pistol.Slave" + (string)next_slave);
- llOwnerSay("/me - [Bullet Slave Added]");
- }
- llSleep(0.2); // delay incase the scripts are slow at initiating
- // set the bullet settings to the new slave (will also go to the others)
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- }
- // This is where all of the firing is controlled
- control(key id, integer held, integer level)
- {
- if (g_stopFire == TRUE) // stops gun from firing if reloading or in safe mode
- {
- return;
- }
- // mouse button pressed
- if (level & held & CONTROL_ML_LBUTTON)
- {
- if (g_burstFire == TRUE)
- {
- llMessageLinked(LINK_ALL_OTHERS, -2, "f", ""); // tell any muzzle flash scripts to start
- // loop three times
- integer i;
- for (i=0; i<3; i++) // lol <3
- {
- // check if there is any ammo left
- if (g_bulletsLeft <= 0)
- {
- llTriggerSound(g_SNDNOAMMO, 1.0);
- }
- // there are bullets left
- else
- {
- llMessageLinked(LINK_THIS, g_slaveNum, "f", ""); // fire bullet
- llTriggerSound(g_SNDFIRE, 1.0);
- g_bulletsLeft--;
- g_slaveNum++;
- // line up next slave
- if (g_slaveNum > g_NUMOFSLAVES)
- {
- g_slaveNum = 1;
- }
- llSleep(g_delayFire);
- } // end of checking if bullets are left
- } // end of for loop
- llMessageLinked(LINK_ALL_OTHERS, -2, "nf", ""); // tell any flash muzzles to stop
- } // end of burst mode
- // single fire mode
- else
- {
- llTriggerSound(g_SNDFIRE, 1.0);
- llMessageLinked(LINK_THIS, g_slaveNum, "f", "");
- llMessageLinked(LINK_ALL_OTHERS, -2, "f", ""); // tell any muzzle flash scripts to start
- g_bulletsLeft--;
- g_slaveNum++;
- if (g_slaveNum > g_NUMOFSLAVES)
- {
- g_slaveNum = 1;
- }
- llMessageLinked(LINK_ALL_OTHERS, -2, "nf", ""); // tell any flash muzzles to stop
- llSleep(g_delayFire);
- }
- updateTxt();
- }
- // mouse button released
- else if (level & ~held & CONTROL_ML_LBUTTON)
- {
- llMessageLinked(LINK_SET, -2, "nf", ""); // tell any muzzle flash scripts to stop
- // check if reload is needed
- if (g_bulletsLeft <= 0)
- {
- reload();
- return;
- }
- }
- // W+S (forward+back) reload
- else if ((level & ~held & CONTROL_FWD) && (level & ~held & CONTROL_BACK))
- {
- reload();
- }
- // not crouching
- else if (level & held & CONTROL_UP)
- {
- llMessageLinked(LINK_THIS, -1, "nocrouch", ""); // tell animation script to play normal standing animation
- }
- // crouch
- else if (level & held & CONTROL_DOWN)
- {
- llMessageLinked(LINK_THIS, -1, "crouch", ""); // tell animation script to play crouch animation
- }
- }
- timer()
- {
- llSetTimerEvent(0.0);
- updateTxt();
- g_stopFire = FALSE;
- llOwnerSay("/me - [Reloaded]");
- }
- // HERE IS WHERE ALL OF THE COMMANDS ARE
- listen(integer channel, string name, key id, string msg)
- {
- // check if message is longer than necessary
- if (llStringLength(msg) > 11)
- {
- return;
- }
- msg = llToLower(msg); // make case-insensitive
- // do a simple parse for the : commands (velocity, distance, and rounds)
- list parsed = llParseString2List(msg, [":", " "], []);
- string command = llList2String(parsed, 0); // reduces llList2String calls
- // Go in order from most used commands to least used (by assumption)
- // Use a return at each clause to exit the listen event immediately
- if (msg == "r" || msg == "reload") // reload command
- {
- reload();
- }
- else if (msg == "sf" || msg == "single") // single fire command
- {
- g_burstFire = FALSE;
- updateTxt();
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Firing mode switched to Single Fire]");
- }
- else if (msg == "bf" || msg == "burst") // burst fire command
- {
- g_burstFire = TRUE;
- updateTxt();
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Firing mode switched to Burst Fire]");
- }
- else if (msg == "damage") // damage bullet command
- {
- g_bulletName = "Damage";
- updateTxt();
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Bullet switched to Damage]");
- reload();
- }
- else if (msg == "training") // training bullet command
- {
- g_bulletName = "Training";
- updateTxt();
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Bullet switched to Training]");
- reload();
- }
- else if (msg == "phantom") // phantom bullet command
- {
- g_bulletName = "Phantom";
- updateTxt();
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Bullet switched to Phantom]");
- reload();
- }
- else if (msg == "safe") // safe mode command
- {
- g_safeMode = TRUE;
- g_stopFire = TRUE;
- updateTxt();
- llOwnerSay("/me - [Safe mode set to ON]");
- }
- else if (msg == "nosafe" || msg == "arm") // nosafe/arm command
- {
- g_safeMode = FALSE;
- g_stopFire = FALSE;
- updateTxt();
- llOwnerSay("/me - [Safe mode set to OFF]");
- }
- else if (msg == "sling") // sling command
- {
- llSay(19, "sling");
- llReleaseControls();
- state sling;
- }
- else if (command == "vel") // velocity command
- {
- // check if velocity is over or under the limit
- float tmp = (float)llList2String(parsed, 1);
- if (tmp > g_velocityLimit || tmp < 0)
- {
- llOwnerSay("/me - [Bullet velocity must be set between 0 and " + (string)g_velocityLimit + "m/s]");
- return;
- }
- // if the velocity is in range
- g_velocity = tmp;
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Bullet velocity set to " + (string)g_velocity + "m/s]");
- }
- else if (command == "dist") // distance command
- {
- // check if distance is over or under the limit
- float tmp = (float)llList2String(parsed, 1);
- if (tmp > 10 || tmp < 0)
- {
- llOwnerSay("/me - [Bullet rez distance must set between 0 and 10 meters]");
- return;
- }
- g_distance = tmp;
- llMessageLinked(LINK_THIS, 0, g_bulletName + ":" + (string)g_velocity + ":" + (string)g_distance, (string)g_burstFire);
- llOwnerSay("/me - [Bullet rez distance set to " + (string)g_distance + " meters]");
- }
- else if (command == "rounds") // rounds command
- {
- integer tmp = (integer)llList2String(parsed, 1);
- if (tmp < 1)
- {
- llOwnerSay("/me - [Number of rounds cannot be set lower than 1]");
- return;
- }
- g_magazineSize = tmp;
- llOwnerSay("/me - [Number of rounds set to " + (string)g_magazineSize + "]");
- reload();
- }
- else if (msg == "effects off")
- {
- g_effectsOn = FALSE;
- llMessageLinked(LINK_THIS, -1, "effectsoff", "");
- llOwnerSay("/me - [Effects turned OFF. Shell casings and magazines will not be rezzed]");
- }
- else if (msg == "effects on")
- {
- g_effectsOn = TRUE;
- llMessageLinked(LINK_THIS, -1, "effectson", "");
- llOwnerSay("/me - [Effects turned ON. Shell casings and magazines will be rezzed.]");
- }
- else if (msg == "texton")
- {
- g_txtOn = TRUE;
- updateTxt();
- llOwnerSay("/me - [Display text turned ON]");
- }
- else if (msg == "textoff")
- {
- g_txtOn = FALSE;
- updateTxt();
- llOwnerSay("/me - [Display text turned OFF]");
- }
- else if (msg == "reset")
- {
- llMessageLinked(LINK_THIS, -1, "reset", ""); // tell animation script to reset
- llResetScript();
- }
- else if (msg == "menu" || (msg == "main" && channel == g_MENUCHAN)) // main menu
- {
- genMenu(0);
- }
- else if (msg == "firing mode" && channel == g_MENUCHAN) // firing mode submenu
- {
- genMenu(1);
- }
- else if (msg == "bullet" && channel == g_MENUCHAN) // bullet selection submenu
- {
- genMenu(2);
- }
- else if (msg == "other" && channel == g_MENUCHAN) // other submenu
- {
- genMenu(3);
- }
- else if (msg == "help")
- {
- llGiveInventory(g_OWNER, g_HELPNOTE);
- }
- else if (msg == "mem")
- {
- llOwnerSay("/me - [Memory Available: " + (string)llGetFreeMemory() + " bytes]");
- }
- // incase garbage collection sucks
- parsed = [];
- } // end of listen event
- }
- //*************************************************************************************************
- // SLING STATE
- //*************************************************************************************************
- state sling
- {
- on_rez(integer param)
- {
- llResetScript();
- }
- state_entry()
- {
- llMessageLinked(LINK_SET, -2, "nf", ""); // tell any muzzle flash scripts to stop
- // play sling sound if it exists
- if (g_SNDSLING != "")
- {
- llTriggerSound(g_SNDSLING, 1.0);
- }
- llMessageLinked(LINK_THIS, -1, "stop", ""); // tell animation script to stop
- llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES); // make gun invisible
- llListen(g_COMMCHAN, "", g_OWNER, "");
- llListen(g_MENUCHAN, "", g_OWNER, "");
- }
- touch_start(integer num_detected)
- {
- if (llDetectedKey(0) == g_OWNER)
- {
- llDialog(g_OWNER, "Slung", ["Draw", "Reset"], g_MENUCHAN);
- }
- }
- listen(integer channel, string name, key id, string msg)
- {
- if (llStringLength(msg) > 5)
- {
- return;
- }
- msg = llToLower(msg);
- if (msg == "draw")
- {
- llSay(19, "draw");
- state default;
- }
- else if (msg == "reset")
- {
- llResetScript();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement