Project

General

Profile

Fire Control » History » Version 12

« Previous - Version 12/21 (diff) - Next » - Current version
Douglas Maxwell, 05/10/2016 10:28 PM


Fire Control

SGL HUD

The SGL HUD is the primary control point for contacts within the STX lanes. It can only control contacts that are in the same region as the wearer. On region transition, the SGL HUD resets and broadcasts to the region to auto-discover what contacts may be active within the region. Depending on what messages it receives, it link-messages the other objects in the HUD to allow for buttons to activate themselves.

The HUD can simultaneously control up to three contacts on each sim. The contacts may be indirect fire (IDF), ambush (small arms or machine gun), and improvised explosive devices (IEDs).

SGL HUD Root

The SGL HUD does not communicate with soldiers, but only communicates with contact scripts.

//  Authors:                                      SGL_HUD.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in root object of HUD

integer controlsEnabled = FALSE;
integer contactOneState;    //IDF
integer contactTwoState;    //MG
integer contactThreeState;  //SA
integer controlChannel = 500;

integer listenHandle;

vector COLOR_WHITE = <1.0, 1.0, 1.0>;
float  OPAQUE             = 1.0;

//  Method used to emulate a toss.  Make sure a grenade prim named 
//  Yellow_Smoke_Grenade_Small is in the root of the HUD.  The grenade
//  should have the particle smoke script in it. (see below)
throwGrenade(){
    vector direction = llRot2Fwd(llGetRootRotation());
    vector throw = <0.0, 0.0, 2.5>;
    llRezObject("Yellow_Smoke_Grenade_Small", llGetPos()+<0,0,1>, 3*direction+throw, llGetRot(), 1);
}

//  Method used to correctly display scenario controller buttons
//  depending upon available contact situations in the region
updateDisplay(){
    string regionName = llGetRegionName();     //region name query
    if(regionName == "STX 31"){
        llSetText("Round 1", COLOR_WHITE, OPAQUE);
    } else if (regionName == "STX 30"){
       llSetText("Round 2", COLOR_WHITE, OPAQUE);
    } else if (regionName == "STX 40"){
        llSetText("Round 3", COLOR_WHITE, OPAQUE);
    } else {
        llSetText("No Contact", COLOR_WHITE, OPAQUE);
    }
}

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry() 
    {
        updateDisplay();
        listenHandle = llListen(controlChannel, "", "", "");
        //assume disabled
        contactOneState = FALSE;
        contactTwoState = FALSE;
        contactThreeState = FALSE;
        llRegionSay(controlChannel, "IDF_status");
        llRegionSay(controlChannel, "MG_status");
        llRegionSay(controlChannel, "SA_status");
    }

    listen(integer channel, string name, key id, string message){
        //if buttons are in region, we can enable and represent their state
        llOwnerSay(message);
        if(message == "IDF_1"){
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c1_on", "");
        } else if(message == "IDF_0") {
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c1_off", "");
        } else if(message == "MG_1"){
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c2_on", "");
        } else if(message == "MG_0"){
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c2_off", "");
        } else if(message == "SA_1"){
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c3_on", "");
        } else if(message == "SA_0"){
            controlsEnabled = TRUE;
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c3_off", "");
        }
        if(controlsEnabled){
            llMessageLinked(LINK_ALL_CHILDREN, 0, "enable_reset", "");
        }
    }

    //  Listen for messages from the buttons.
    link_message(integer source, integer num, string message, key id){
        if(message == "trigger_smoke_grenade")
        {
            throwGrenade();
        }
        if(!controlsEnabled){
            return;
        }
        if(message == "trigger_reset")
        {
            llRegionSay(controlChannel, "reset");
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_reset", "");
        }
        else if(message == "trigger_c1_on")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c1_on", "");
            llRegionSay(controlChannel, "IDF_enable");
        }
        else if(message == "trigger_c1_off")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c1_off", "");
            llRegionSay(controlChannel, "IDF_disable");
        }
        else if(message == "trigger_c2_on")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c2_on", "");
            llRegionSay(controlChannel, "MG_enable");
        }
        else if(message == "trigger_c2_off")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c2_off", "");
            llRegionSay(controlChannel, "MG_disable");
        }
        else if(message == "trigger_c3_on")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c3_on", "");
            llRegionSay(controlChannel, "SA_enable");
        }
        else if(message == "trigger_c3_off")
        {
            llMessageLinked(LINK_ALL_CHILDREN, 0, "confirm_c3_off", "");
            llRegionSay(controlChannel, "SA_disable");
        }
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }

}

SGL HUD Buttons

Each button script has an array of images at the top of the script. These are textures within the prims themselves, and are applied depending on HUD and button state.

Smoke Grenade

Button script for smoke grenade prim

//  Authors:                                      SGL_HUD_GrenadeButton.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in grenade button object of HUD

list images = ["Smoke_Grenade_Up"];
integer pressed = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, 0), 0);
    }

    touch_end(integer num)
    {
        llMessageLinked(LINK_ROOT, 0, "trigger_smoke_grenade", "");
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }
}

Reset

Button script for reset all contacts prim

//  Authors:                                      SGL_HUD_ResetButton.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in reset button object of HUD

list images = ["Reset_Up", "Reset_Down", "Reset_Gray"];
integer pressed = FALSE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, 2), 0);
    }

    touch_end(integer num)
    {
        if(!pressed){
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
            llMessageLinked(LINK_ROOT, 0, "trigger_reset", "");
        }
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "confirm_reset") {
            llSetTexture(llList2String(images, pressed), 0);
            llSleep(1);
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
        } else if(message == "enable_reset"){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
        }
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }
}

Contact 1

Button script for contact 1.

//  Authors:                                      SGL_HUD_Contact1Button.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in contact 1 button object of HUD

list images = ["Contact_1_OFF", "Contact_1_ON", "Contact_1_ON_Gray"];
integer pressed = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, 2), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_c1_off", "");
        }
        else {
            llMessageLinked(LINK_ROOT, 0, "trigger_c1_on", "");
        }
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "confirm_c1_on") {
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
        }
        else if( message == "confirm_c1_off" ){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
        }
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }
}

Contact 2

Button script for contact 2:

//  Authors:                                      SGL_HUD_Contact2Button.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in Contact 2 button object of HUD

list images = ["Contact_2_OFF", "Contact_2_ON", "Contact_2_ON_Gray"];
integer pressed = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, 2), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_c2_off", "");
        } else {
            llMessageLinked(LINK_ROOT, 0, "trigger_c2_on", "");
        }
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "confirm_c2_on") {
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
        }
        else if( message == "confirm_c2_off" ){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
        }
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }
}

Contact 3

Button script for Contact 3.

//  Authors:                                      SGL_HUD_Contact3Button.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in Contact 3 button object of HUD

list images = ["Contact_3_OFF", "Contact_3_ON", "Contact_3_ON_Gray"];
integer pressed = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, 2), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_c3_off", "");
        } else {
            llMessageLinked(LINK_ROOT, 0, "trigger_c3_on", "");
        }
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "confirm_c3_on") {
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
        }
        else if( message == "confirm_c3_off" ){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
        }
    }

    changed(integer change){
        if (change & CHANGED_REGION) //note that it's & and not &&... it's bitwise!
        {
            llResetScript();
        }
    }
}

Soldier Animation Override

The soldier HUD does not directly interact with any objects in a scene. On firing, it will deduct it's own ammo count, but only broadcasts the names of objects that it is firing at.

Soldier Animation Override Script:

//  Authors:                                      Soldier_AO.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in XXX
//
//  Soldier states

integer weaponUp = FALSE;
integer holdUp = FALSE;

integer gHasPermission = FALSE;

string current_animation = "";

//Standing animations
string stand_weapon_down_no_hold  = "weap_down_stand_01";
string stand_weapon_up_no_hold       = "weap_up_stand_01";
string stand_weapon_down_hold        = "Handup_WeaponDown_v2";
string stand_weapon_up_hold             = "weap_up_hold_stand_02";
string run_weapon_up_no_hold           = "St_Jog_FWD_A";
string run_weapon_down_no_hold      = "weap_down_run_01";
string walk_weapon_up_no_hold         = "weap_up_walk_01";
string walk_weapon_down_no_hold    = "weap_down_walk_01";

//Kneeling animations
// weap down no hold
string kneel_weapon_down_animation  = "CR_IDLE_GunDWN";
//weap up no hold
string kneel_weapon_up_animation    = "CR_IDLE_AIM";

//Prone
string prone_animation              = "PR_Idle_A";
string prone_move_animation         = "PR_walk01b";

// Current Animation Set
string cur_anim_stand = "";
string cur_anim_walk = "";
string cur_anim_run = "";
string cur_anim_turn_left = "";
string cur_anim_turn_right = "";
// these are assigned to at the opening of each state
string anim_stand = "";
string anim_stand_weap = "";
string anim_stand_hold = "";
string anim_stand_weap_hold = "";
string anim_walk = "";
string anim_walk_weap = "";
string anim_walk_weap_hold = "";
string anim_walk_hold = "";
string anim_run = "";
string anim_run_weap = "";
string anim_run_weap_hold = "";
string anim_run_hold = "";
string anim_turn_left = "";
string anim_turn_left_weap = "";
string anim_turn_left_weap_hold = "";
string anim_turn_left_hold = "";
string anim_turn_right = "";
string anim_turn_right_weap = "";
string anim_turn_right_weap_hold = "";
string anim_turn_right_hold = "";

// animation states: http://wiki.secondlife.com/wiki/LlGetAnimation
animOverride() 
{
    if (gHasPermission)
    {
        string curAnimState = llGetAnimation(llGetOwner());
        string newAnimation;

        if(curAnimState == "Standing")
        {
            newAnimation = cur_anim_stand;
        }
        else if(curAnimState == "Walking")
        {
            newAnimation = cur_anim_walk;
        }
        else if(curAnimState == "Running")
        {
            newAnimation = cur_anim_run;
        }
        else if(curAnimState == "Turning Left")
        {
            newAnimation = cur_anim_turn_left;
        }
        else if(curAnimState == "Turning Right")
        {
            newAnimation = cur_anim_turn_right;
        }
        if(newAnimation != current_animation)
        {
            llStopAnimation(current_animation);
            llStartAnimation(newAnimation);
            current_animation = newAnimation;
        }
    }
}

setAnimations(){
    if( !weaponUp && !holdUp ){
        cur_anim_stand = anim_stand;
        cur_anim_walk = anim_walk;
        cur_anim_run = anim_run;
        cur_anim_turn_left = anim_turn_left;
        cur_anim_turn_right = anim_turn_right;
    } else if( weaponUp && holdUp ){
        cur_anim_stand = anim_stand_weap_hold;
        cur_anim_walk = anim_walk_weap_hold;
        cur_anim_run = anim_run_weap_hold;
        cur_anim_turn_left = anim_turn_left_weap_hold;
        cur_anim_turn_right = anim_turn_right_weap_hold;
    } else if( weaponUp && !holdUp ){
        cur_anim_stand = anim_stand_weap;
        cur_anim_walk = anim_walk_weap;
        cur_anim_run = anim_run_weap;
        cur_anim_turn_left = anim_turn_left_weap;
        cur_anim_turn_right = anim_turn_right_weap;
    } else if(!weaponUp && holdUp ){
        cur_anim_stand = anim_stand_hold;
        cur_anim_walk = anim_walk_hold;
        cur_anim_run = anim_run_hold;
        cur_anim_turn_left = anim_turn_left_hold;
        cur_anim_turn_right = anim_turn_right_hold;
    }
}

handleMessage(string message){
    if(message == "animation_set_kneel")
    {
        state kneel;
    }
    else if(message == "animation_set_stand")
    {
        state stand;
    }
    else if(message == "animation_set_prone")
    {
        state prone;
    }
    else if(message == "animation_set_weapon_up")
    {
        weaponUp = TRUE;
    }
    else if(message == "animation_set_weapon_down")
    {
        weaponUp = FALSE;
    }
    else if(message == "animation_set_hold_up"){
        holdUp = TRUE;
    }
    else if(message == "animation_set_hold_down"){
        holdUp = FALSE;
    }
    setAnimations();
}

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry() 
    {
        current_animation = "";
        gHasPermission = FALSE;
        weaponUp = FALSE;
        holdUp = FALSE;
        if (llGetAttached())
        {
            llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
        }
        llSetTimerEvent(1.0);
    }
    run_time_permissions(integer parm)
    {
        if( parm & PERMISSION_TRIGGER_ANIMATION)
        {
            gHasPermission = TRUE;
            state stand;
        }
        else
        {
            llOwnerSay("what happened?");
        }
    }
    attach( key k) {
        if ( k != NULL_KEY )
        {
            llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
        }
    }
    link_message(integer source, integer num, string message, key id){
        handleMessage(message);
    }
}

state prone {
    state_entry()
    {
        anim_stand = prone_animation;
        anim_stand_weap = prone_animation;
        anim_stand_hold = prone_animation;
        anim_stand_weap_hold = prone_animation;
        anim_walk = prone_move_animation;
        anim_walk_weap = prone_move_animation;
        anim_walk_weap_hold = prone_move_animation;
        anim_walk_hold = prone_move_animation;
        anim_run = prone_move_animation;
        anim_run_weap = prone_move_animation;
        anim_run_weap_hold = prone_move_animation;
        anim_run_hold = prone_move_animation;
        anim_turn_left = prone_move_animation;
        anim_turn_left_weap = prone_move_animation;
        anim_turn_left_weap_hold = prone_move_animation;
        anim_turn_left_hold = prone_move_animation;
        anim_turn_right = prone_move_animation;
        anim_turn_right_weap = prone_move_animation;
        anim_turn_right_weap_hold = prone_move_animation;
        anim_turn_right_hold = prone_move_animation;
        setAnimations();
    }
    link_message(integer source, integer num, string message, key id){
        handleMessage(message);
        animOverride();
    }
    timer() {
        animOverride();
    }
}

state kneel {
    state_entry()
    {

        anim_stand = kneel_weapon_down_animation;
        anim_stand_weap = kneel_weapon_up_animation;
        anim_stand_hold = kneel_weapon_down_animation;
        anim_stand_weap_hold = kneel_weapon_up_animation;
        anim_walk = kneel_weapon_down_animation;
        anim_walk_weap = kneel_weapon_up_animation;
        anim_walk_weap_hold = kneel_weapon_up_animation;
        anim_walk_hold = kneel_weapon_down_animation;
        anim_run = kneel_weapon_down_animation;
        anim_run_weap = kneel_weapon_up_animation;
        anim_run_weap_hold = kneel_weapon_up_animation;
        anim_run_hold = kneel_weapon_down_animation;
        anim_turn_left = kneel_weapon_down_animation;
        anim_turn_left_weap = kneel_weapon_up_animation;
        anim_turn_left_weap_hold = kneel_weapon_up_animation;
        anim_turn_left_hold = kneel_weapon_down_animation;
        anim_turn_right = kneel_weapon_down_animation;
        anim_turn_right_weap = kneel_weapon_up_animation;
        anim_turn_right_weap_hold = kneel_weapon_up_animation;
        anim_turn_right_hold = kneel_weapon_down_animation;
        setAnimations();
    }
    link_message(integer source, integer num, string message, key id){
        handleMessage(message);
        animOverride();
    }
    timer() {
        animOverride();
    }
}

state stand {
    state_entry()
    {
        anim_stand = stand_weapon_down_no_hold;
        anim_stand_weap = stand_weapon_up_no_hold;
        anim_stand_hold = stand_weapon_down_hold;
        anim_stand_weap_hold = stand_weapon_up_hold;
        anim_walk = walk_weapon_down_no_hold;
        anim_walk_weap = walk_weapon_up_no_hold;
        anim_walk_weap_hold = walk_weapon_up_no_hold;
        anim_walk_hold = walk_weapon_down_no_hold;
        anim_run = run_weapon_down_no_hold;
        anim_run_weap = run_weapon_up_no_hold;
        anim_run_weap_hold = run_weapon_up_no_hold;
        anim_run_hold = run_weapon_down_no_hold;
        anim_turn_left = "";
        anim_turn_left_weap = "";
        anim_turn_left_weap_hold = "";
        anim_turn_left_hold = "";
        anim_turn_right = "";
        anim_turn_right_weap = "";
        anim_turn_right_weap_hold = "";
        anim_turn_right_hold = "";
        setAnimations();
    }
    link_message(integer source, integer num, string message, key id){
        handleMessage(message);
        animOverride();
    }
    timer() {
        animOverride();
    }
}

Mouselook Operations

This mouselook testing script allows for weapon fire while in first person perspective. EXPERIMENTAL

float   gap = 2.0;

checkMouselook(){
    integer flags = llGetAgentInfo(llGetOwner());
    if(flags & AGENT_MOUSELOOK)
        llMessageLinked(LINK_THIS, 0, "firstPersonView", "");
    else
        llMessageLinked(LINK_THIS, 0, "thirdPersonView", "");
}

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTimerEvent(gap);
        checkMouselook();
    }
    timer()
    {
        checkMouselook();
    }
}

Soldier HUD

Soldier HUD Control Script

The Soldier HUD has buttons for animations, a compass, fire weapons.

//  Authors:                                      Soldier_HUD.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in root object of HUD
//
//                Edit these fields to match the soldier equipment
integer secondsToReload   = 5;
integer roundsPerMagazine = 15;
integer numberOfReloads   = 2;
string fire_weapon_sound  = "AW_Fire_M16_001";

// DO NOT modify below here unless you know what you are doing
integer currentMagazine   = 15;
integer reloadsRemaining  = 2;
integer reloading = FALSE;
integer isMouseLook = FALSE;
integer gHasPermission = FALSE;

string speedState = "walk";
string bodyState = "stand";
integer weaponUp = FALSE;
integer holdUp = FALSE;

integer wasWeaponUp = FALSE;
integer wasHoldUp = FALSE;

vector COLOR_WHITE = <1.0, 1.0, 1.0>;
float  OPAQUE      = 1.0;
floatingText(){
    llSetText("Rounds               : " + (string)currentMagazine + "\nExtra Magazines: " + reloadsRemaining + "\n\n\n\n\n\n", COLOR_WHITE, OPAQUE);
}

updateMouselook(integer mouseLook){
    if(mouseLook && !isMouseLook){
        //entering mouselook, store weapon and hand state
        wasWeaponUp = weaponUp;
        wasHoldUp = holdUp;
        weaponUp = TRUE;
        holdUp = FALSE;
        //force weapon up and hand down in mouselook
        llMessageLinked(LINK_ALL_OTHERS, 0, "weapon_up_confirm", "");
        llMessageLinked(LINK_THIS, 0, "animation_set_weapon_up", "");
        llMessageLinked(LINK_ALL_OTHERS, 0, "hold_down_confirm", "");
        llMessageLinked(LINK_THIS, 0, "animation_set_hold_down", "");
        llMessageLinked(LINK_ALL_OTHERS, 0, "HUD_Mouselook", "");
    }
    if(!mouseLook && isMouseLook)
    {
        //leaving mouselook, restore weapon and hand state
        weaponUp = wasWeaponUp;
        holdUp = wasHoldUp;
        //restore previous animation state
        if(!weaponUp){
            llMessageLinked(LINK_ALL_OTHERS, 0, "weapon_down_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_weapon_down", "");
        }
        if(holdUp){
            llMessageLinked(LINK_ALL_OTHERS, 0, "hold_up_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_hold_up", "");
        }
        llMessageLinked(LINK_ALL_OTHERS, 0, "HUD_Normallook", "");
    }
    isMouseLook = mouseLook;
}

fireWeapon()
{
    if(reloading){
        if(llGetTime() > secondsToReload){
            reloading = FALSE;
        } else {
            return;
        }
    }
    if( currentMagazine == 0 && reloadsRemaining == 0 ) {
        return;
    } else {
        //remove a round to fire
        currentMagazine = currentMagazine - 1;
    }

    llTriggerSound(fire_weapon_sound, 1.0);

    //cast a ray in the direction
    vector pos = llGetPos();
    vector direction = llRot2Fwd(llGetCameraRot());
    direction.z = 0;
    list myRay = llCastRay(
        pos + direction,
        pos + direction*256,
        [RC_MAX_HITS,1, RC_DETECT_PHANTOM,0]
    );

    string collider =  llKey2Name(llList2Key(myRay,0));
    if( collider )
    {
        llSay(600,collider);
    }

    floatingText();
    //reload if this empties us
    if(currentMagazine == 0 && reloadsRemaining > 0){
        llResetTime();
        reloading = TRUE;
        currentMagazine = roundsPerMagazine;
        reloadsRemaining = reloadsRemaining - 1;
        floatingText();
    }
}

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        reloadsRemaining = numberOfReloads;
        currentMagazine = roundsPerMagazine;
        gHasPermission = FALSE;
        speedState = "walk";
        bodyState = "stand";
        weaponUp = FALSE;
        if (llGetAttached())
        {
            llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION|PERMISSION_TAKE_CONTROLS|PERMISSION_ATTACH|PERMISSION_TRACK_CAMERA);
        }
        floatingText();
        //listen for ammo reload messages
        llListen(501, "", "", "Reload:" + llKey2Name(llGetOwner()));
    }
    run_time_permissions(integer perm)
    {
        if(PERMISSION_TAKE_CONTROLS & perm){
            gHasPermission = TRUE;
            llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE);
        }
    }

    listen(integer channel, string name, key id, string message)
    {
        reloadsRemaining = numberOfReloads;
        currentMagazine = roundsPerMagazine;
        floatingText();
    }

    link_message(integer sender_num, integer num, string msg, key id)
    {
        if(msg == "firstPersonView"){
            updateMouselook(TRUE);
        }
        else if(msg == "thirdPersonView")
        {
            updateMouselook(FALSE);
        }
        else if(msg == "trigger_kneel" && bodyState != "kneel")
        {
            bodyState = "kneel";
            llMessageLinked(LINK_ALL_OTHERS, 0, "kneel_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_kneel", "");
        }
        else if(msg == "trigger_stand" && bodyState != "stand"){
            bodyState = "stand";
            llMessageLinked(LINK_ALL_OTHERS, 0, "stand_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_stand", "");
        }
        else if(msg == "trigger_prone" && bodyState != "prone"){
            bodyState = "prone";
            llMessageLinked(LINK_ALL_OTHERS, 0, "prone_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_prone", "");
        }
        else if(msg == "trigger_weapon_up" && !weaponUp)
        {
            weaponUp = TRUE;
            llMessageLinked(LINK_ALL_OTHERS, 0, "weapon_up_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_weapon_up", "");
        }
        else if(msg == "trigger_weapon_down" && weaponUp)
        {
            weaponUp = FALSE;
            llMessageLinked(LINK_ALL_OTHERS, 0, "weapon_down_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_weapon_down", "");
        }
        else if(msg == "trigger_hold_up" && !holdUp)
        {
            holdUp = TRUE;
            llMessageLinked(LINK_ALL_OTHERS, 0, "hold_up_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_hold_up", "");
        }
        else if(msg == "trigger_hold_down" && holdUp){
            holdUp = FALSE;
            llMessageLinked(LINK_ALL_OTHERS, 0, "hold_down_confirm", "");
            llMessageLinked(LINK_THIS, 0, "animation_set_hold_down", "");
        }
        else if(msg == "trigger_fire" && weaponUp){
            fireWeapon();
        }
    }

    control(key id, integer level, integer edge)
    {
        if ( level & CONTROL_ML_LBUTTON && edge & CONTROL_ML_LBUTTON  )
        {
            fireWeapon();
        }
    }
}

Mouselook script on each HUD object that is to disappear while in mouselook

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetAlpha(1.0, ALL_SIDES);
    }
    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "HUD_Mouselook") {
            llSetAlpha(0.0, ALL_SIDES);
        } else if( message == "HUD_Normallook") {
            llSetAlpha(1.0, ALL_SIDES);
        }
    }
}

Soldier Fire

Script to activate weapon.

//  Authors:                                      Soldier_FireButton.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in fire button object of HUD

list images = ["Fire_Gray", "Fire_Up"];
integer pressed = FALSE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, pressed), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_fire", "");
        }
        llSetTexture(llList2String(images, pressed), 0);
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "weapon_down_confirm") {
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
        if( message == "weapon_up_confirm" ){
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
    }
}

Weapon Up/Down

Script to activate animation for Soldier bring Weapon up or down.

//  Authors:                                      Soldier_WeaponUpDownButton.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in weapon up/down button object of HUD

list images = ["Weapon_Down", "Weapon_Up_NEW"];
integer pressed = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, pressed), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_weapon_up", "");
        } else {
            llMessageLinked(LINK_ROOT, 0, "trigger_weapon_down", "");
        }
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "weapon_down_confirm") {
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
        if( message == "weapon_up_confirm" ){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
    }
}

Soldier Hand Up/Down

//  Authors:                                      Soldier_HandUpDownButton.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in Hand up/down button object of HUD

list images = ["Hand_Up", "Hand_Down"];
integer pressed = FALSE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }
    state_entry()
    {
        llSetTexture(llList2String(images, pressed), 0);
    }

    touch_end(integer num)
    {
        if(pressed){
            llMessageLinked(LINK_ROOT, 0, "trigger_hold_down", "");
        } else {
            llMessageLinked(LINK_ROOT, 0, "trigger_hold_up", "");
        }
        llSetTexture(llList2String(images, pressed), 0);
    }

    link_message(integer Sender, integer Number, string message, key Key){
        if( message == "hold_up_confirm") {
            pressed = TRUE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
        if( message == "hold_down_confirm" ){
            pressed = FALSE;
            llSetTexture(llList2String(images, pressed), 0);
            return;
        }
    }
}

Compass

Soldiers need to be able to navigate the operational area. This script emulates a compass.

//  Authors:                                     Compass.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in Compass object of the HUD

vector rot_xyz;
vector root_rot;
float gap = 0.25;

default
{
    state_entry()
    {
        rot_xyz = llRot2Euler(llGetRot());
        llSetTimerEvent(gap);
    }

    timer(){
        vector rootRotation = llRot2Euler(llGetRootRotation());
        if(root_rot != rootRotation){
            root_rot = rootRotation;
            rot_xyz.z = -1*(rootRotation.z);
            llSetRot(llEuler2Rot(rot_xyz));
        }
    }
}

Reload

Soldier reload ammo on touch script.

//  Authors:                                                      Reload.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in an ammo box object.  Sometimes known to plan bad Metallica riffs.

default
{
    state_entry()
    {
    }
    touch(integer num_detected)
    {
        llSay(501, "Reload:"+llDetectedName(0));
    }
}

Contact Objects

Ambush Objects Scripts

Small Arms Trigger

Script that performs entity detection and provides small arms ambush fire:

//  Authors:                                      SmallArmsTrigger.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in prim 

float detectingRange = 45.0; //meters
float percentageHit = 0.75; //percent
integer controlChannel = 500;
string triggerName = "SA";

integer listenHandle;
integer enabled = TRUE;

default
{
    on_rez( integer _code ) 
    {
        llResetScript();
    }

    state_entry() {
        listenHandle = llListen(controlChannel, "", "", "");
        llSensorRepeat("", NULL_KEY, AGENT, detectingRange, PI, 1.0);
        llRegionSay(controlChannel, triggerName + "_" + (string)enabled);
    }

    //control messages from HUD
    listen(integer channel, string name, key id, string message)
    {
        if(message == triggerName + "_status"){
            llRegionSay(controlChannel, triggerName + "_" + (string)enabled);
        } else if(message == triggerName + "_enable"){
            enabled = TRUE;
            llSensorRepeat("", NULL_KEY, AGENT, detectingRange, PI, 1.0);
        } else if(message == triggerName + "_disable"){
            enabled = FALSE;
            llSensorRemove();
        } else if(message == "reset"){
            llMessageLinked(LINK_THIS, 0, "reset", "");
            llResetScript();
        }
    }

    //detect a user
    sensor(integer total_number) {
        if(!enabled){
            return;
        }
        if(llFrand(1.0) < percentageHit)
        {
            llMessageLinked(LINK_THIS, 0, "detected", "");
        }
        llSensorRemove();
        llSetTimerEvent(5 + llFrand(-4));
    }

    //one-shot cooldown to prevent firing too quickly
    timer()
    {
        llSensorRepeat("", NULL_KEY, AGENT, detectingRange, PI, 1);
        llSetTimerEvent(0.0);
    }
}

Small Arms Responder

Responder script that takes action when a trigger script on the same object fires

//  Authors:                                     SmallArmsResponder.lsl                     
//  Mike Heilmann
//  Doug Maxwell
//  
//  Usage:  Place this script in weapon up/down button object of HUD

integer gunChannel = 600;

integer listenHandle;
string myName = "";

string soundFile = "Ak47_burst";

integer hit;

default
{
    on_rez(integer _code) {
        llResetScript();
    }

    state_entry() {
        listenHandle = llListen(gunChannel, "", "", "");
        myName = llGetObjectName();
    }

    link_message(integer Sender, integer Number, string String, key Key) // This script is in the object too.
    {
        if(String == "detected"){
            if(hit){
                return;
            }
            llTriggerSound(soundFile, 1.0);
        } else if(String == "reset"){
            llResetScript();
        }
    }

    listen(integer channel, string name, key id, string message)
    {
        if(message == myName){
            hit = TRUE;
        }
    }
}

Simplified responder script that onle plays a sound

integer announceChannel = 500;
string announceMessage = "detected";

integer listenHandle;

default
{

    state_entry() {
        listenHandle = llListen(announceChannel, "", "", announceMessage);
    }

    listen(integer channel, string name, key id, string message)
    {
        llPlaySound("PipeBomb_001_Louder", 1.0);
    }
}

Tossable smoke grenade script:

//  Douglas Maxwell         PurpleGrendade.lsl      26 JAN 2016
//
vector OLIVE=<0.239,0.6,0.439>;
vector GREEN=<0.18,0.8,0.251>;
vector PURPLE=<0.694,0.051,0.788>;
vector FUCHSIA=<0.941,0.071,0.745>;
vector YELLOW=<1.0, 0.863, 0.0>;
vector SUNNY=<1.00000, 0.522, 0.106>;
integer particleON = 0;

makeSmoke(){
llParticleSystem([ PSYS_PART_MAX_AGE, 8.500000,
PSYS_PART_FLAGS, 267,
PSYS_PART_START_COLOR, YELLOW,
PSYS_PART_END_COLOR, SUNNY,
PSYS_PART_START_SCALE, <0.2150, 0.2150, 0.200000>,
PSYS_PART_END_SCALE, <02.0000, 2.0000, 2.00000>,
PSYS_SRC_PATTERN, 0x04,
PSYS_SRC_BURST_RATE,0.04000,
PSYS_SRC_ACCEL,<0.00000, 0.00000, 0.30000>,
PSYS_SRC_BURST_PART_COUNT,5,
PSYS_SRC_BURST_RADIUS,0.000000,
PSYS_SRC_BURST_SPEED_MIN,0.410000,
PSYS_SRC_BURST_SPEED_MAX,0.090000,
PSYS_SRC_BURST_RADIUS, 0,
PSYS_SRC_ANGLE_BEGIN, 0,
PSYS_SRC_ANGLE_END, 3.14,
PSYS_SRC_OMEGA,<0.10000, -0.10000, 0.00000>,
PSYS_SRC_MAX_AGE,0.000000,
PSYS_PART_START_ALPHA,1.000000,
PSYS_PART_END_ALPHA,0.000000,
PSYS_SRC_TEXTURE, "",
PSYS_SRC_TARGET_KEY,(key)"" ]);
}

noSmoke(){
    particleON = 0;
    llParticleSystem([]);
}

default
{
    state_entry()
    {
        noSmoke();
    }
    on_rez(integer start_params)
    {
        if(start_params == 0)
        {
            noSmoke();
        }
        else
        {
            llSleep(2);
            makeSmoke();
            llSleep(10.0);
            llDie();
        }
    }
}

Contact_SA_Off.png - SGL HUD Contact Small Arms Fire Button OFF (36 KB) Douglas Maxwell, 05/13/2016 09:01 AM

Contact_SA_On.png - SGL HUD Contact Small Arms Fire Button ON (31.9 KB) Douglas Maxwell, 05/13/2016 09:03 AM

Contact_SA_Gray.png - SGL HUD Contact Small Arms Fire Button Gray (33 KB) Douglas Maxwell, 05/13/2016 09:04 AM

Contact_MG_Off.png - SGL HUD Contact Machine Gun Button OFF (35.7 KB) Douglas Maxwell, 05/13/2016 09:04 AM

Contact_MG_On.png - SGL HUD Contact Machine Gun Button ON (31.7 KB) Douglas Maxwell, 05/13/2016 09:13 AM

Contact_MG_Gray.png - SGL HUD Contact Machine Gun Button Gray (32.4 KB) Douglas Maxwell, 05/13/2016 09:13 AM

Contact_IDF_Off.png - SGL HUD Contact Indirect Fire Button OFF (35.3 KB) Douglas Maxwell, 05/13/2016 09:13 AM

Contact_IDF_On.png - SGL HUD Contact Indirect Fire Button ON (31.4 KB) Douglas Maxwell, 05/13/2016 09:14 AM

Contact_IDF_Gray.png - SGL HUD Contact Indirect Fire Button Gray (32.2 KB) Douglas Maxwell, 05/13/2016 09:14 AM

Smoke_Grenade_Up.png - SGL HUD Smoke Grenade Button (32.9 KB) Douglas Maxwell, 05/13/2016 09:14 AM

Kneel_Down_Green.png - Soldier HUD Kneel Activate Animation GREEN Button (50.6 KB) Douglas Maxwell, 05/13/2016 09:19 AM

Prone_Down_Green.png - Soldier HUD Prone Activate Animation GREEN Button (52.4 KB) Douglas Maxwell, 05/13/2016 09:20 AM

Stand_Down_Green.png - Soldier HUD Stand Activate Animation GREEN Button (52.6 KB) Douglas Maxwell, 05/13/2016 09:20 AM

Fire_Up_Green.png - Soldier HUD Fire Up Animation Activate GREEN Button (41.1 KB) Douglas Maxwell, 05/13/2016 09:21 AM

Fire_Gray.png - Soldier HUD Fire GRAY Button (30.5 KB) Douglas Maxwell, 05/13/2016 09:21 AM

Hand_Down.png - Soldier HUD Hand Activate Animation Down Button (35.7 KB) Douglas Maxwell, 05/13/2016 09:21 AM

Hand_Up.png - Soldier HUD Hand Activate Animation Up Button (29.9 KB) Douglas Maxwell, 05/13/2016 09:22 AM

Weapon_Up_NEW.png - Soldier HUD Weapon Up Activate Animation Button (31.7 KB) Douglas Maxwell, 05/13/2016 09:22 AM

Weapon_Down.png - Soldier HUD Weapon Down Activate Animation Button (37.8 KB) Douglas Maxwell, 05/13/2016 09:22 AM

Stand_Up.png - Soldier HUD Stand Up Activate Animation Button (29 KB) Douglas Maxwell, 05/13/2016 09:22 AM

Prone_Up.png - Soldier HUD Prone to Up Activate Animation Button (28.7 KB) Douglas Maxwell, 05/13/2016 09:25 AM

Kneel_Up.png - Soldier HUD Kneel to Up Activate Animation Button (27.3 KB) Douglas Maxwell, 05/13/2016 09:25 AM

Ak47_burst.wav - AK 47 Burst Sound (310 KB) Douglas Maxwell, 05/13/2016 09:26 AM

incoming_mortar_whislte.wav - Indirect Fire Incoming Mortar Whistle (198 KB) Douglas Maxwell, 05/13/2016 09:26 AM

AW_Fire_M16_001_Burst.wav - M16 / M4 Burst Sound (51.2 KB) Douglas Maxwell, 05/13/2016 09:26 AM

AW_Explo_PipeBomb_001.WAV - IED Explosion Sound (232 KB) Douglas Maxwell, 05/13/2016 09:27 AM

PR_walk01b.bvh (27.6 KB) Douglas Maxwell, 05/13/2016 10:29 AM

PR_walk01a.bvh (27 KB) Douglas Maxwell, 05/13/2016 10:29 AM

Handup_WeaponDown_v2.bvh (126 KB) Douglas Maxwell, 05/13/2016 10:29 AM

HandUp_WeaponUp.bvh (122 KB) Douglas Maxwell, 05/13/2016 10:29 AM

Hand_Down.bvh (7.58 KB) Douglas Maxwell, 05/13/2016 10:29 AM

PR_Walk_FWD_A.bvh (16 KB) Douglas Maxwell, 05/13/2016 10:29 AM

PR_Idle_A.bvh (35.7 KB) Douglas Maxwell, 05/13/2016 10:29 AM

St_Jog_FWD_A.bvh (11.2 KB) Douglas Maxwell, 05/13/2016 10:29 AM

Greeting_HST.bvh (60.8 KB) Douglas Maxwell, 05/13/2016 10:29 AM

Greeting_FRD.bvh (46 KB) Douglas Maxwell, 05/13/2016 10:29 AM

CR_IDLE_GunDWN.bvh (115 KB) Douglas Maxwell, 05/13/2016 10:30 AM

CR_IDLE_AIM.bvh (115 KB) Douglas Maxwell, 05/13/2016 10:30 AM

CR_IDLE_AIM2.bvh (38.8 KB) Douglas Maxwell, 05/13/2016 10:30 AM