Kill Task (Bounty Hunter) Script

Got any custom JavaScript additions/tweaks you think other people would like to see? Post 'em here!
Post Reply
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Kill Task (Bounty Hunter) Script

Post by giwo »

Note that this script will not work with any UOX3 version before 0.98-3.2l which I will be committing to the CVS shortly. I decided to go ahead and post this script anyhow so others can have a look at it.

This script is made up of two scripts, taskmaster.js and global.js. Notably the global.js must be incorporated into whatever script you have set to ID 0 (if none, then simply set it to script ID 0). taskmaster.js simply needs to be assigned to whatever NPC you choose to offer these quests.

taskmaster.js
// Kill Tasks by giwo
// v1.2+
// Last Update: September 22, 2008

// This script is designed to reward players with gold for completing kill tasks at varying levels
// Note that this script will not function properly without the accompanying onDeathBlow() global script.
// Thanks goes to the default UOX3 speech.js writers for the speech handling code.
// Please note that this script is designed for use with UOX3 v0.98-3.2l and above.

function onSpeech( myString, myPlayer, myNPC )
{
    if( !myNPC.InRange( myPlayer, 2 ) )
        return;
    var startQuest = myPlayer.GetTag( "KT_START" );
    var Speech_Array = myString.split(" ");
    var i = 0, currObj = 0;
    for( i = 1; i <Speech_Array> 0 )
                    myNPC.TextMessage( "Alas, you still have "+NumToString( numToKill )+" more monsters to slay before you receive your reward!" );
                else
                {
                    myNPC.TextMessage( "Wonderful work my friend, here is your reward." );
                    var goldToGive = 0;
                    switch( taskLevel )
                    {
                    case 1:     goldToGive = 500;       break;
                    case 2:     goldToGive = 1000;      break;
                    case 3:     goldToGive = 2000;      break;
                    case 4:     goldToGive = 4000;      break;
                    }
                    CreateDFNItem( myPlayer.socket, myPlayer, "0x0EED", goldToGive, "ITEM", true );
                    myPlayer.SoundEffect( 0x0037, false );
                    myPlayer.SetTag( "KT_NUMTOKILL", 0 );
                    myPlayer.SetTag( "KT_IDTOKILL", 0 );
                    myPlayer.SetTag( "KT_LEVEL", 0 );
                }
            }
            else
                myNPC.TextMessage( "You must first take on a task to receive a reward." );
        }
        else if( startQuest )
        {
            if( Speech_Array[currObj].match( /\bNovice\b/i ) )
            {
                myNPC.TurnToward( myPlayer );
                var numToKill = RandomNumber( 3, 7 );
                var typeToKill = CreateGenericQuest( myPlayer, 1, numToKill );
                myNPC.TextMessage( "Excellent, please return to me after you have slain "+NumToString( numToKill )+" "+typeToKill+"." );
            }
            else if( Speech_Array[currObj].match( /\bJourneyman\b/i ) )
            {
                myNPC.TurnToward( myPlayer );
                var numToKill = RandomNumber( 3, 7 );
                var typeToKill = CreateGenericQuest( myPlayer, 2, numToKill );
                myNPC.TextMessage( "Excellent, please return to me after you have slain "+NumToString( numToKill )+" "+typeToKill+"." );
            }
            else if( Speech_Array[currObj].match( /\bAdept\b/i ) )
            {
                myNPC.TurnToward( myPlayer );
                var numToKill = RandomNumber( 3, 7 );
                var typeToKill = CreateGenericQuest( myPlayer, 3, numToKill );
                myNPC.TextMessage( "Excellent, please return to me after you have slain "+NumToString( numToKill )+" "+typeToKill+"." );
            }
            else if( Speech_Array[currObj].match( /\bGrandmaster\b/i ) )
            {
                myNPC.TurnToward( myPlayer );
                var numToKill = RandomNumber( 3, 7 );
                var typeToKill = CreateGenericQuest( myPlayer, 4, numToKill );
                myNPC.TextMessage( "Excellent, please return to me after you have slain "+NumToString( numToKill )+" "+typeToKill+"." );
            }
        }
    ++currObj;
    }
}

function CreateGenericQuest( myPlayer, questLevel, numToKill )
{
    var typeToKill = GetMonsterType( myPlayer, questLevel );
    myPlayer.SetTag( "KT_NUMTOKILL", numToKill );
    myPlayer.SetTag( "KT_LEVEL", questLevel );
    myPlayer.SetTag( "KT_START", 0 );
    return typeToKill;
}

function GetMonsterType( myPlayer, questLevel )
{
    var retVal = "";
    switch( questLevel )
    {
    case 1:
        switch( RandomNumber( 0, 2 ) )
        {
        case 0:
            myPlayer.SetTag( "KT_IDTOKILL", 0x008c );
            retVal = "orcish mages";
            break;
        case 1:
            myPlayer.SetTag( "KT_IDTOKILL", 0x008f );
            retVal = "ratman shaman";
            break;
        case 2:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0002 );
            retVal = "ettins";
            break;
        }
        break;
    case 2:
        switch( RandomNumber( 0, 2 ) )
        {
        case 0:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0004 );
            retVal = "gargoyles";
            break;
        case 1:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0016 );
            retVal = "gazers";
            break;
        case 2:
            myPlayer.SetTag( "KT_IDTOKILL", 0x008a );
            retVal = "orc lords";
            break;
        }
        break;
    case 3:
        switch( RandomNumber( 0, 2 ) )
        {
        case 0:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0018 );
            retVal = "liches";
            break;
        case 1:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0089 );
            retVal = "ophidian avengers";
            break;
        case 2:
            myPlayer.SetTag( "KT_IDTOKILL", 0x004c );
            retVal = "titans";
            break;
        }
        break;
    case 4:
        switch( RandomNumber( 0, 2 ) )
        {
        case 0:
            myPlayer.SetTag( "KT_IDTOKILL", 0x002e );
            retVal = "ancient wyrms";
            break;
        case 1:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0028 );
            retVal = "balrons";
            break;
        case 2:
            myPlayer.SetTag( "KT_IDTOKILL", 0x0054 );
            retVal = "ogre lords";
            break;
        }
        break;
    }
    return retVal;
}

global.js
function onDeathBlow( pKilled, pKiller )
{
    var oldNumToKill = pKiller.GetTag( "KT_NUMTOKILL" );
    if( oldNumToKill && pKiller.GetTag( "KT_IDTOKILL" ) == pKilled.id )
    {
        var newNumToKill = (oldNumToKill-1);
        pKiller.SetTag( "KT_NUMTOKILL", newNumToKill );
        if( newNumToKill )
            pKiller.SysMessage( "You have "+NumToString( newNumToKill )+" more creatures to kill." );
        else
            pKiller.SysMessage( "You have completed your task, return to the taskmaster for your reward." );
    }
}
Last edited by giwo on Sat Jan 17, 2009 9:01 pm, edited 4 times in total.
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

I love it :D Great work giwo! :)

One thing though. It seems that setting a tag to null no longer deletes it from the given object - and neither does setting them to 0 as you do in your script. This means there will eventually be quite a lot of tags on characters, even if those tags are no longer used. Any idea what's up with that?
-= Ho Eyo He Hum =-
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

I'll have a look at that, 0 or null should both unset the tag....
Scott
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

Alrighty, I've fixed the issue for my next CVS update. It looks like currently you can unset a tag with SetTag( "tagname", "" ) and SetTag( "tagname" ).

With my changes you can also do so in these manners

SetTag( "tagname", null ) and SetTag( "tagname", 0 );


Note when checking for an unset tag, the easiest way is to do !GetTag( "tagname"); An unset tag will always be returning a 0 (notably not a "null" value).
Scott
stranf
UOX3 Guru
Posts: 939
Joined: Wed Jan 04, 2006 3:59 pm
Has thanked: 0
Been thanked: 0

Post by stranf »

--First off, great work Giwo!

I reccommend this script, especially to anyone who plays single player, it adds a bit more character to the game.

--One thing I noticed...are there two item IDs for Ettins? I went to despise, where the community spawn has a lot of ettins on the lower floor. Only 1 of 3 would lower the tally. Once it said "you have two kills left" I slew 4 more for good measure. When I returned to the taskmaster, he said, "You have 1 kill remaining."

Other than that, this is a great script, and unless you object, I'm including it in Release 3 of my Starter Kit.
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

I'd be glad if you included it. :)

I *tried* to find monsters that had only one ID to save that exact thing happening, but it's very possible there are two ettin ID's. Unfortunately the system is limited, currently, in that it can only handle one ID per monster type.
Scott
stranf
UOX3 Guru
Posts: 939
Joined: Wed Jan 04, 2006 3:59 pm
Has thanked: 0
Been thanked: 0

Post by stranf »

giwo? Anyway to make it so that if you return to the taskmaster and ask him for a task he will tell you what task he gave you?

I coudln't find the monster he told me to kill, and now I've forgotten what to kill. When I ask him, he just says, "You must kill 3 more montsers".
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

We'd have to add another custom tag via SetTag() to the player, as currently we only store the ID, not the name of the creature type.
Scott
stranf
UOX3 Guru
Posts: 939
Joined: Wed Jan 04, 2006 3:59 pm
Has thanked: 0
Been thanked: 0

Post by stranf »

gotcha.

I'm not sure how you're script works, or I'd try it myself.

Would it be possible for a for loop?

Code: Select all


id =myPC.boutytag;

if (id == 0xabcdef)
{myNPC.TextMessage("Where are the Gargoyle heads?");
if (id == 0xfedcba)
{myNPC.TextMessage("The Ettins are still roaming the mountains!");

stranf
UOX3 Guru
Posts: 939
Joined: Wed Jan 04, 2006 3:59 pm
Has thanked: 0
Been thanked: 0

Post by stranf »

Hey, Giwo, how about a "renounce" or "quit" function?

If a player takes a quest he can't complete, he can renounce that quest (reset the variables) and it would allow him to get a new task.

Also, for roleplaying purposes, you could inflict some penalties.

--GP loss: Bookeeping fee for the taskmasters. It isn't cheap to have bounty hunters renounce quests all the time!

--Fame loss: Renouncing a quest goes against the virtue of valor, and a minimal fame loss should result. (All the bounty hunters in various taverns will spread the cowardice tale...)


Just a few thoughts.
User avatar
Natas
UOX3 Novice
Posts: 70
Joined: Fri Mar 25, 2005 3:00 am
Location: Del Valle, texas United States
Has thanked: 0
Been thanked: 0

Post by Natas »

Hello, I just tried out this scrip and ran into some issues with it. It worked great at first and now I get this error...

ERROR: JS script failure: Script Number <3300> Message <ReferenceError: berak is not defined
ERROR: Filename: ./js/custom/taskmaster1.js
Line Number: 146
ERROR: Erroneous Line: <null>
Token Ptr: <null>

I am not very good with this stuff yet and can't figure it out. And I really like having this quest in my world. So if someone could help me out please. Thank you
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Here are lines 135 to 146. A cookie to whoever manages to spot the error first ;)

Code: Select all

      case 0: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x0004 ); 
         retVal = "gargoyles" 
         [color=green]break;[/color]
      case 1: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x0016 ); 
         retVal = "gazers"; 
         [color=red]berak;[/color] 
      case 2: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x008a ); 
         retVal = "orc lords"; 
         [color=red]berak;[/color] 
-= Ho Eyo He Hum =-
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

;s are overrated.


PS, this is why I love pre-compiled code :)
User avatar
Xuri
Site Admin
Posts: 3704
Joined: Mon Jun 02, 2003 9:11 am
Location: Norway
Has thanked: 48 times
Been thanked: 8 times
Contact:

Post by Xuri »

Just in case it wasn't clear for other people... there were three errors. A missing semi-colon, and two mis-spelled "break;"s. Marked in red below. I'll update the script in the original post after submitting this post.
Xuri wrote:Here are lines 135 to 146. A cookie to whoever manages to spot the error first ;)

Code: Select all

      case 0: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x0004 ); 
         retVal = "gargoyles"[color=red];[/color]
         [color=green]break;[/color]
      case 1: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x0016 ); 
         retVal = "gazers"; 
         [color=red]berak;[/color] 
      case 2: 
         myPlayer.SetTag( "KT_IDTOKILL", 0x008a ); 
         retVal = "orc lords"; 
         [color=red]berak;[/color] 
-= Ho Eyo He Hum =-
giwo
Developer
Posts: 1780
Joined: Fri Jun 18, 2004 4:17 pm
Location: California
Has thanked: 0
Been thanked: 0

Post by giwo »

That's why I prefer C++, the compiler catches stupid mistakes so others don't have to. :)
Post Reply