Friday, July 24, 2009
Introducing Osiris
Tuesday, July 7, 2009
Alphabet Soup and Working Titles
The thing is this: in second life we have: WARPS, CCS, DCS, RPS, ... what else? Gobs and gobs of acronyms. So, in launching RPCS a couple months back in beta, we went with a nice simple acronym as the working title.
Now it's time to come up with a real name for the system. I've been brainstorming with folks, but don't have an answer yet. After all, we're looking to make this the premier roleplaying system used in second life, and there's still a LOT of features to come before we're there. So, I'm putting on my brainstorming cap, and others are as well. We'd like your suggestions. What do you think? Is it possible to get away from the acronym soup?
I'm asking our players for suggestions. If we pick yours we'll give you a bundle of RPCS enhanced weapons worth $5,000L. Just to make it worth your time. Thanks!
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.
Tuesday, June 30, 2009
Announcing the first API Enhanced RPCS Weapon
Just a heads up: released the very first RPCS API Enhanced weapon today, version 1.1 of the Gladius. Available from RPCS catalogue vendors and XStreetSL.
Melee Weapon Example Script
The first section of your script should set specific variables as follows:
key gCreatorKey="place your API key here"; string gObjectName="Place the unique name of this weapon here"; string gAPIType="M"; string gEffectedStat="Z"; string gAPIRace="ALL"; string gEmote="%a hits %d over the head"; string gVicEmote="%d cringes in pain"; string gPart="0"; string gPartDur="0"; string gTPart="0"; string gTPartDur="0"; gEffectedStat="Z"; string gCheckURL="http://sl.rpcombat.com/APIcheck.cfm"; integer gAvatarChannel; string gPass; key http_request_id; integer bulletname; //ignored for melee integer initialHUDChannel = -39485739; integer initialHUDListener;These are the the default options for a melee weapon script. Insert your own license key and an object name you select in the first two fields. Other options included here:
- gAPIType: M is for melee. Other options are included in the detailed sample scripts.
- gAPIRace="ALL"; You can make weapons and API objects which will target specific races. A good example of this might be a cross which effects vampire types
- gEmote: This is what the owner's meter will say when the weapon procs
- gVicEmote: this is what the target's meter will say
- gPart, gPartDur: this is for selecting specific particle effects. At this time, best to keep these set to zero, we'll shortly have a particle preview box which will allow you to select and use specific particle effects built into the meter
- gCheckURL: this is the url your script will go to in order to determine the avatar channel and password
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 State_entry() we're going to to do one thing: query to find out if the owner has an RPCS meter, and open a listener on a known channel for a response. The purpose of this is that there is no point in licensing an enhanced weapon for someone who is not wearing the meter.
state_entry() {
initialHUDListener=llListen(initialHUDChannel, "", "", "");
llRegionSay(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();
}
}
}
}
Note that your listener on the default known channel is looking for two things: an acknowledgement that we are wearing RPCS, or a reset command. Any time you get either one of those, you call the getChannel function which will retreive the avatar channel and encryption key.
Next we handle the http response, assigning a avatar specific channel to communicate with the owner, and an encryption password. Note that RPCS uses individual unique channels for each wearer: your API script will only be able to communicate with the owner of the weapon. Everything else is handled by the meter.
http_response(key id,integer h_status,list meta,string body) {
if (h_status==200)
{
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);
}
}
}
Finally we tell the meter that this is an enhanced weapon. I'm doing this on restart/relog and when the weapon is drawn by sending a linked message to the API script. Note that the meter will not retain indefinately that you are using an enhanced weapon: you have to _resend_ the proc every 300 seconds. I stop it from sending the command when the weapon is sheathed by sending a linked message with num 4343, then on drawing the weapon send 4242 and start the timer again.
link_message(integer linknum, integer num, string str, key id) {
if (num==4242) {doProc(NULL_KEY); llSetTimerEvent(300);}
else if (num==4343) {llSetTimerEvent(0.0);}
}
timer () {
doProc(NULL_KEY);
}
Feel free to grab a test key from the Content Creators section on the website and test it out!
Friday, June 19, 2009
Maintenance outage, July 4th
Please be advised that on Saturday, July 4th between 12:01am and 12:16am EDT we will be conducting maintenance on some of our production aggregate switches in Virginia. This will cause an interruption of network service for your server(s) listed above for no more than fifteen minutes.
Capture mode, new particle effects and more
- Capture mode: when you have capture enabled, the loser of a fight is disabled and the winner has the option to bind, release or kill the person they defeated.
- OOC Mode: Not roleplaying at the moment, but observing? Mark yourself OOC by typing /9oocmode
- XP awards for combat: XP awards will now be available for winning and/or losing in combat. Sim owners have the option to make the xp awarded a ratio of the levels of the players involved (more in this below)
- New particle effects: 18 new particle effects have been added to the system, to give some exciting visual variety to the use of skills
- Level display on HUD: This was a popular request, particlarly since 0.70 introduced the ability of sim owners to hide specific data points on the meter. Your hud will now display both your level and experience
- Buffed/Weakened indicator on meter
- API hooks for ranged weapons
- The sim owner sets a base and maximum amount of xp awarded for kills
- When plays who are different levels fight, the xp awarded is based on a ratio of those levels. For example, if a level 10 player kills a level 1 player, the xp award will be 1xp (1/10 of the base). Conversely, if the level 1 player is lucky enough the defeat the level 10 player, the xp award would be 100points.
- The sim owner sets the maximum amount of xp awarded in those conditions.
- Complete the content creators API and open it up to registration and licensing
- Complete player profile and ranking pages on the website
- Build in the logic for how statistics effect the use of skills
- Complete the Roleplay skills menu
- Complete the sim owner's rezzer box (this allows designated staff to rez objects owned by the sim owner such as NPC monsters)
- Integration of the Chatterbox into the code
- Sim owner's API