Aller au contenu

Photo

Explorer's XP?


  • Veuillez vous connecter pour répondre
17 réponses à ce sujet

#1
Who said that I

Who said that I
  • Members
  • 492 messages

okay I need some help here with a small script I got here. I want to reward players for entering a new area with some XP, though most area's have multiple exits and entrances so wondering if anyone has a fix for me?

 

basically I want to have the xp rewarded given ONLY if the PC has not entered the area before.

 

void main()
{
    // Get the creature who triggered this event.
    object oPC = GetEnteringObject();
 
    // Only fire for (real) PCs.
    if ( !GetIsPC(oPC)  ||  GetIsDMPossessed(oPC) )
        return;
 
    // Only fire once per PC.
    if ( GetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF)) )
        return;
    SetLocalInt(oPC, "DO_ONCE__" + GetTag(OBJECT_SELF), TRUE);
 
    // Give 25 experience to the PC.
    GiveXPToCreature(oPC, 25);
}
 

 

 

thanks in advance! :D



#2
Tarot Redhand

Tarot Redhand
  • Members
  • 2 677 messages

In the OnEnter script for the area check for a flag. If the flag is not set give the award and set the flag otherwise skip that section of code.

 

TR



#3
Who said that I

Who said that I
  • Members
  • 492 messages

In the OnEnter script for the area check for a flag. If the flag is not set give the award and set the flag otherwise skip that section of code.

 

TR

 

hmm could you help me with how this works since well first of all I am a bit rusty with the scripting and am not entirely sure how you mean. sorry :S



#4
Pstemarie

Pstemarie
  • Members
  • 2 745 messages

object oPC = GetEnteringObject();

 

if (!GetIsPC(oPC) || GetLocalInt(oPC, "player_awarded") == 1)

     return;

 

else

{

     SetLocalInt(oPC, "player_awarded", 1);

     //award the xp here

}


  • Who said that I aime ceci

#5
Failed.Bard

Failed.Bard
  • Members
  • 774 messages

I broke it up into separate functions, in case you wanted to store the variable in a different way, but something like this would work:

 

 

// Retrieves the string for storing visited areas.

string GetVisitedAreaList(object oPC);
// Saves the visited area list.
void SetVisitedAreaList(object oPC, string sList);
 
// Checks if the PC has entered that area before.
// returns FALSE if oPC is not a PC, or they aren't in a valid area.
// Area list is updated automatically if the area hasn't been visited before.
int GetPCFirstTimeEnteringArea(object oPC);
 
 
string GetVisitedAreaList(object oPC)
{
    // Using PC skin method for the example.
    object oSkin=GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC);
    return GetLocalString(oSkin, "VISITED_AREA_LIST");
}
 
void SetVisitedAreaList(object oPC, string sList)
{
    // Using PC skin method for the example.
    object oSkin=GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC);
    SetLocalString(oSkin, "VISITED_AREA_LIST", sList);
}
 
 
int GetPCFirstTimeEnteringArea(object oPC)
{
    // Sanity checks.  Must be a PC in a valid area, with a set (non-blank) tag.
    if(!GetIsPC(oPC))return FALSE;
    object oArea=GetArea(oPC);
    if(oArea==OBJECT_INVALID)return FALSE;
    string sTag=GetTag(oArea);
    if(sTag=="")return FALSE;
 
    string sList = GetVisitedAreaList(oPC);
    // This will equal -1 if the area tag isn't found in the list,
    if(FindSubString(sList, sTag)== -1)
    {
        SetVisitedAreaList(oPC, sList+"_"+sTag);
        return TRUE;
    }
    return FALSE;
}
 
 
void main()
{
    object oPC=GetEnteringObject();
 
 
    // PC only exploration XP section.
    // Function cotains PC only sanity check.
    if(GetPCFirstTimeEnteringArea(oPC))
    {
        // Give 25 experience to the PC.
        GiveXPToCreature(oPC, 25);
    }
}

 

The main body would have to go into the area's OnEnter, though the other functions could stay above it in the same script or be moved into an include.



#6
Shadooow

Shadooow
  • Members
  • 4 470 messages

object oPC = GetEnteringObject();

 

if (!GetIsPC(oPC) || GetLocalInt(oPC, "player_awarded") == 1)

     return;

 

else

{

     SetLocalInt(oPC, "player_awarded", 1);

     //award the xp here

}

this would work only once, PC wouldnt get any XP after entering first area

 

I broke it up into separate functions, in case you wanted to store the variable in a different way, but something like this would work:

 

 

The main body would have to go into the area's OnEnter, though the other functions could stay above it in the same script or be moved into an include.

Generally ok, but your script has two issues.

1) polymorphed creatures can get XP repeatedly

2) in multiplayer server with ILR or ELC on and without CPP 1.71 (or rather without the scrripting solution from 1.71 which usually needs to be merged with own module event scripts), player will get a completely new skin each login and all variables will be deleted.

 

solutions:

- save the exploration datas to module "database item" (eg. id card or whatever)

- or save the exploration datas to database (bioware or nwnx)

- or implement the "losing skin" fix from 1.71 into your module events and then use SKIN_SupportGetSkin function to get skin instead of GetItemInSlot (requires x3_inc_skin)



#7
Failed.Bard

Failed.Bard
  • Members
  • 774 messages

A database item or actual database usage would definitely have advantages over PC skin, yes.  Most servers tend to have their own skin scripts, so I never considered the terrible way that the vanilla scripts handle them, but polymorphing would be an issue regardless.

A quasi IC item like a "Travel journal", that the variable was stored to, and that could even be used to list all areas visited, would be pretty easy to implement.  The ability to fine tune the storage method was a large part of why I wrote the script up as multiple small functions.

 

Changing these:

 

string GetVisitedAreaList(object oPC)

{
    // Using PC skin method for the example.
    object oSkin=GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC);
    return GetLocalString(oSkin, "VISITED_AREA_LIST");
}
 
void SetVisitedAreaList(object oPC, string sList)
{
    // Using PC skin method for the example.
    object oSkin=GetItemInSlot(INVENTORY_SLOT_CARMOUR, oPC);
    SetLocalString(oSkin, "VISITED_AREA_LIST", sList);
}

to:

 

string GetVisitedAreaList(object oPC)

{
    // Using a DB item
    object oDB=GetItemPossessedBy(oPC, "TRAVEL_DB_BOOK");
    return GetLocalString(oDB, "VISITED_AREA_LIST");
}
 
void SetVisitedAreaList(object oPC, string sList)
{
    
    // Using a DB item
    object oDB=GetItemPossessedBy(oPC, "TRAVEL_DB_BOOK");
    SetLocalString(oDB, "VISITED_AREA_LIST", sList);
}

would be enough to change it to look for an item instead.

It's still not ideal, since a module with hundreds of areas would lead to a very long string, but short of numbering every area, stored onto it by variable, and making a pseudo bitwise string to check against, it's as good a method as most would need.



#8
Who said that I

Who said that I
  • Members
  • 492 messages

A database item or actual database usage would definitely have advantages over PC skin, yes.  Most servers tend to have their own skin scripts, so I never considered the terrible way that the vanilla scripts handle them, but polymorphing would be an issue regardless.

A quasi IC item like a "Travel journal", that the variable was stored to, and that could even be used to list all areas visited, would be pretty easy to implement.  The ability to fine tune the storage method was a large part of why I wrote the script up as multiple small functions.

 

Changing these:

to:

would be enough to change it to look for an item instead.

It's still not ideal, since a module with hundreds of areas would lead to a very long string, but short of numbering every area, stored onto it by variable, and making a pseudo bitwise string to check against, it's as good a method as most would need.

awesome, I totally appreciate this guys, been struggling with this for a while now and well been out of the scripting for a bit (If I do not do scripting for a few months it takes some time for me to get back into it)  

 

anyway regarding the storage item....I already have so many items that store data of the character in their inventory, I am kinda wanting not to add any more items to it otherwise the inventory is already full at the beginning of the game XD  

 

So could I switch TRAVEL_DB_BOOK" to anything I want?

 

so far the module has around 30+ area's and more coming up, this will be a big PW by the time we are done with it. So would totally appreciate the one with the least issues XD



#9
Shadooow

Shadooow
  • Members
  • 4 470 messages

 

So could I switch TRAVEL_DB_BOOK" to anything I want?

Absolutely, you can store all informations in single item - just make sure player cant lose it. (make it undroppable and not equippable)



#10
Shadooow

Shadooow
  • Members
  • 4 470 messages

 

So could I switch TRAVEL_DB_BOOK" to anything I want?

Absolutely, you can store all informations in single item - just make sure player cant lose it. (make it undroppable and not equippable)


  • Who said that I aime ceci

#11
Pstemarie

Pstemarie
  • Members
  • 2 745 messages

this would work only once, PC wouldnt get any XP after entering first area

 

 

True, I missed in the OP's post about being useful for multiple areas. Thanks Shadooow.

 

@ WhoSaid...In this case you'd want to use a string variable and store it directly on a PC item - like FailedBard and Shadooow suggests. For the data stored just use the area tag (make sure all areas have different tags).



#12
Who said that I

Who said that I
  • Members
  • 492 messages

thank you all for the info! I am so happy with this! :D



#13
Who said that I

Who said that I
  • Members
  • 492 messages

hm apparently its not entirely working....it does not seem to save it on the item and the pc keeps getting the xp each time entering the area.....

 

anything I did wrong perhapa? Put it on enterarea and honestly only changed the database section and changed the item it should store the item on. I miss something here?



#14
Failed.Bard

Failed.Bard
  • Members
  • 774 messages

It should work using an item, so long as you changed the "TRAVEL_DB_BOOK" tag to the tag of a possessed item, bearing in mind that tags are case sensitive, so have to match exactly.



#15
Who said that I

Who said that I
  • Members
  • 492 messages
I did, i simply copy pasted the tag of the new item over where the "TRAVEL_DB_BOOK" is supposed to be. I got no errors but it does not matter what I do I keep getting xp entering the area

#16
LoA_Tristan

LoA_Tristan
  • Members
  • 40 messages

A travel book could store database variables, but why the heck not change its description instead, to reflect exploration.

 

Area OnEnter:

void main()
{
    object oPC = GetEnteringObject();
    if (!GetIsPC(oPC)) return; // kill script if entering object is not a player
    object oJournal = GetItemPossessedBy(oPC, "TRAVEL_DB_BOOK");  // Get the travel guide object
    if (oJournal != OBJECT_INVALID)
    {
        string sDescription = GetDescription(oJournal); // Get its full description
        if (FindSubString(sDescription, "Neverwinter City Dump") == -1)
        { // Search description and append more text to it, if it doesn't have that text already
            GiveXPToCreature(oPC, 25);
            SetDescription(oJournal, sDescription + "\nThe next entry describes your exciting journey to the Neverwinter City Dump.\n");
        }
    }
}


#17
kalbaern

kalbaern
  • Members
  • 824 messages

Here's a version that should work from either a trigger covering the entire map (or even a specific portion of it) or used in the area itself. Set into the OnEnter event in either case. It does require that each Area have a unique TAG though. I always match an Area's ResRef and TAGs to ensure no duplicates.

//Exploration XP Script by Kalbaern 12/02/15
void main()
{
object oPC = GetEnteringObject();
object oArea = GetArea(OBJECT_SELF);
object oItem = GetItemPossessedBy(oPC,"REPLACE_WITH_TAG_OF_UNDROPPABLE_DB_ITEM");
string sArea = GetTag(oArea);
int nExplore = GetLocalInt(oItem,sArea);

if (oItem == OBJECT_INVALID) return;
if (nExplore == 1) return;

else
{
SetLocalInt(oItem,sArea, 1);
SendMessageToPC(oPC, "Exploration XP Reward Earned");
GiveXPToCreature(oPC, 25);//Set XP as desired
}
return;
}



#18
Who said that I

Who said that I
  • Members
  • 492 messages

Here's a version that should work from either a trigger covering the entire map (or even a specific portion of it) or used in the area itself. Set into the OnEnter event in either case. It does require that each Area have a unique TAG though. I always match an Area's ResRef and TAGs to ensure no duplicates.

//Exploration XP Script by Kalbaern 12/02/15
void main()
{
object oPC = GetEnteringObject();
object oArea = GetArea(OBJECT_SELF);
object oItem = GetItemPossessedBy(oPC,"REPLACE_WITH_TAG_OF_UNDROPPABLE_DB_ITEM");
string sArea = GetTag(oArea);
int nExplore = GetLocalInt(oItem,sArea);

if (oItem == OBJECT_INVALID) return;
if (nExplore == 1) return;

else
{
SetLocalInt(oItem,sArea, 1);
SendMessageToPC(oPC, "Exploration XP Reward Earned");
GiveXPToCreature(oPC, 25);//Set XP as desired
}
return;
}

 

thanks kal! this one works like a charm!!