Friday, July 3, 2009

Ranged Weapons API Ready with release of 0.73

With the release of 0.73 this morning, the ranged weapons API is now available to developers. Most of this works exactly the same as melee procs, with a couple of changes, in particular the addition of the bullet name.

Note: this script does _not_ go in the bullets. Rather it goes in the actual gun/attachment, and ideally should be integrated with your main script in whatever way is most convenient for you.

Set initial variables

key gCreatorKey="your key goes here";
string bulletname;
string gObjectName="Your weapon's object name here";
string gAPIType="R"; 
string gAPIRace="ALL";  
string gPartDur="0";
string gTPart="0";
string gTPartDur="0";          
string gCheckURL="http://sl.rpcombat.com/APIcheck.cfm";
integer gAvatarChannel; 
string gPass;
key http_request_id; 
integer initialHUDChannel = -39485739;
integer initialHUDListener;

Next step is put in the functions:

string crypt(string str){
    return llXorBase64StringsCorrect(llStringToBase64(str),llStringToBase64(gPass));
}
string decrypt(string str){
    return llBase64ToString(llXorBase64StringsCorrect(str,llStringToBase64(gPass)));
}
getChannel()
{
    http_request_id=llHTTPRequest(gCheckURL + "?cKey=" + llEscapeURL(gCreatorKey) + "&obn=" + llEscapeURL(gObjectName) + "&crKe=" + llEscapeURL(llGetCreator()) + "&scKey=" + llEscapeURL(llGetInventoryCreator(llGetScriptName())), [],"");
}
doProc(key target)
{
    string msg="V||" + (string)target + "^" + gAPIType + "|" + gAPIRace + "|" + gEffectedStat + "|" + gEmote + "|" + gVicEmote + "|" + gPart + "|" + gPartDur + "|" + gTPart + "|" + gTPartDur; 
    llRegionSay(gAvatarChannel, crypt(msg));
}

In the body of your script, you're going to start with setting the listener for the meter. This only accepts two commands: RESET or RPCS... the purpose here is for you to be able to confirm the player is wearing RPCS before you register your weapon.

In the listen event, we call the getChannel() function when a reset happens

    state_entry() {
        initialHUDListener=llListen(initialHUDChannel, "", "", "");
        llSay(initialHUDChannel, "QUERY|RPCS"); 
    }
    listen(integer channel,string name,key id,string message) {
        if (channel==initialHUDChannel) {
            if (llGetOwnerKey(id)==llGetOwner()) {
                if (message=="RPCS" || message=="RPCS|RESET") {
                    getChannel();    
                }
            }
        }
    }

The getChannel() function called above will return an http response. We deal with that here:

    http_response(key id,integer h_status,list meta,string body) {
        if (h_status==200)
        {
            llOwnerSay(body);
            list response=llCSV2List(llStringTrim(body, STRING_TRIM));
                if (llList2String(response, 0)=="MSG") {
                    llOwnerSay(llList2String(response, 1));
                } else if (llList2String(response, 0)=="GO") {
                    gAvatarChannel=llList2Integer(response, 1);
                    gPass=llStringTrim(llList2String(response, 2), STRING_TRIM);
                    bulletname=llStringTrim(llList2String(response, 3), STRING_TRIM);
                    llMessageLinked(LINK_SET, 3959492, bulletname, NULL_KEY);
                }
        }    
    }

Note the last two lines of this which are quite different than the melee test script. First, we set a bullet name, then pass that out via linked message. You can do this however you want to... the main thing is you need to be able to set a global variable in your main script with the bulletname text. We'll see why in just a moment.

Next step is to know when to tell the meter we are enhanced. The easiest way is to have your script send a linked message when the weapon is drawn (in this example, we're sending a linked message with the num 4242 to tell the API script it needs to be sending to the meter now. That way, the the meter is ready to deal out enhanced commands the moment you are combat ready.

That said, we don't want to be sending it constantly. Put it on a timer... send the proc to the meter every 30 seconds... then when the weapon is put away, kill the timer.

Sending the command to the meter

    link_message(integer linknum, integer num, string str, key id) {
        if (num==4242) {doProc(NULL_KEY); llSetTimerEvent(30.0);}
        else if (num==4343) {llSetTimerEvent(0.0);}
    }
    timer () {
        doProc(NULL_KEY);    
    }

At this point what's happening is your gun is telling the meter: "my bullets are enhanced." The meter is telling everyone around you ... that your bullets are enhanced.

The problem is: they aren't yet. There's one final step that has to be taken.

Setting the bullet name

The way this works is pretty simple. At this point, because you've sent the enhancement information to the meter, and it has communicated with your neighbors, your victims are ready to be shot. Except how will they know the bullet came from your enhanced weapon, and not a freebie popgun you pick up somewhere.

Here's how. Remember earlier where we set the bulletname variable and sent it to the rest of the object via linked request? Here it is again:

bulletname=llStringTrim(llList2String(response, 3), STRING_TRIM);
llMessageLinked(LINK_SET, 3959492, bulletname, NULL_KEY);

The reason for this is because the enemy's meter will give enhanced damage _if_ your meter sent out the signal (see above) and _if_ the bullet name matches. When you rez your bullet, you're going to send an integer to it matching the desired bullet name:

llRezObject("bullet", pos, vel, rot, (integer)bulletname); 

Your bullet should grab that variable on rez, then

 llSetObjectName((string)bulletname);

So... if your bullet name matches, then each bullet you send downrange will do an extra +2 points of damage.

0 comments:

Post a Comment