Skip to content

Help with Teleport Stuff

Goal #1: Have PC exchange an amulet for a map.

//Put this on action taken in the conversation editor
void main()
{

object oPC = GetPCSpeaker();

object oItem;
oItem = GetFirstItemInInventory(oPC);

while (GetIsObjectValid(oItem))
   {
   if (GetTag(oItem)=="BSCULT_MARK_001") DestroyObject(oItem);

   oItem = GetNextItemInInventory(oPC);
   }

CreateItemOnObject("bscult_map_001", oPC);

}

Goal #2: PC uses the map to teleport to a particular location.
// ** This script uses "tag-based" item scripting.
// ** If you use the item this script it named after, target yourself with the curser
//    then, it will teleport you to the TAG of the Waypoint named in this script.
// To use: Name this SCRIPT after the ITEM to be used.  On the ITEM, give it the item property "Unique Power".
//         Select yourself as the target of the "Unique Power"; the VFX will fire & you'll be teleported there.
//
//


void main()
{
object oPC;

if (!GetIsPC(GetItemActivatedTarget())
){

SendMessageToPC(GetItemActivator(), "Improper use of item!");
return;}

oPC = GetItemActivator();

object oTarget;
location lTarget;
oTarget = GetWaypointByTag("HELMITE_TEMPLE_001");

lTarget = GetLocation(oTarget);

//only do the jump if the location is valid.
//though not flawless, we just check if it is in a valid area.
//the script will stop if the location isn't valid - meaning that
//nothing put after the teleport will fire either.
//the current location won't be stored, either

if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;

AssignCommand(oPC, ClearAllActions());

DelayCommand(3.0, AssignCommand(oPC, ActionJumpToLocation(lTarget)));

oTarget = oPC;

//Visual effects can't be applied to waypoints, so if it is a WP
//the VFX will be applied to the WP's location instead

int nInt;
nInt = GetObjectType(oTarget);

if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), oTarget);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), GetLocation(oTarget));

}

Here are the issues I'm having:
1.) When the PC gets another map they automatically teleport to the location. It doesn't offer the option to use the item on the PC, it just teleports the PC automatically.
2.) If the PC turns in more than one amulet, the NPC gives the PC a map for each of the amulets taken.
3.) I'd like only one map to only appear in the PCs inventory - when the amulet is turned into the NPC. Then have that single map stay in the PCs inventory forever; non-droppable or tradeable.

Comments

  • ProlericProleric Member Posts: 1,282
    Goal #1 can be simplified - GetItemPossessedBy().

    To avoid creating more than one map, SetLocalInt on the PC when the map is first given. At the start of the script, if GetLocalInt is set on the PC, return without doing anything.

    The problem with Goal #2 is that tag-based scripts fire for every item event, including Acquire.

    You only want the script to do something on Activate.

    This tutorial shows exactly how:

    https://nwnlexicon.com/index.php/Grimlar_-_Introduction_To_Tag_Based_Scripting
  • ForSeriousForSerious Member Posts: 446
    I would also like to point out that this section of code has a high chance of doing unexpected things:
    AssignCommand(oPC, ClearAllActions());
    
    DelayCommand(3.0, AssignCommand(oPC, ActionJumpToLocation(lTarget)));
    
    The call to clear all actions and jump to location should be wrapped in a function. Use a delay to call the function. 3 seconds is a long time. There are several things the player can do in that time to unintentionally stop the teleportation.
  • ProlericProleric Member Posts: 1,282
    True - better without any delay.
  • Ugly_DuckUgly_Duck Member Posts: 182
    Thanks for all the feedback. But, I use LS's Script Generator because I don't know how to write code. I looked at the lexicon for a while but still couldn't figure out what I'm supposed to do. The script generator didn't have the functions that I thought were necessary. So, I'm completely lost.
  • ForSeriousForSerious Member Posts: 446
    I won't get a chance for another 9ish hours, but when I do, I'll take a shot at it, if you want. I rather enjoy figuring out scripts.
  • TarotRedhandTarotRedhand Member Posts: 1,481
    @Ugly_Duck said

    because I don't know how to write code
    Did you try the tutorials contained in the Lexicon?

    Then there's all the tutorials linked to in this pinned thread on the vault -

    The Starting Point - module building tutorials for beginners - and where to find them

    Then there's the Scripting Frequently Asked Questions (with answers - includes tutorials) -

    Just The FAQs, ma'am

    And the tutorials that I wrote. Start with -

    TR's Basics - Variables, Types and Functions (TBC)

    Finally there are all the prefab items and systems linked to in this pinned thread on the vault that require little to no scripting -

    Books & Things

    TR
  • NeverwinterWightsNeverwinterWights Member Posts: 339
    edited March 2022
    Lilac's also has the function to properly build tag based scripts but the way it does it requires an additional script. Basically you need a check at the top of your script to make sure it only completely fires for a specific item event. Was the item picked up, dropped, equipped, activated, etc? So as far as the 2nd script goes, just make sure your item has the same tag as the name of your script and skip the Lilacs second script thing for each tag based script.

    The script you posted with the check added:
    // ** This script uses "tag-based" item scripting.
    // ** If you use the item this script it named after, target yourself with the curser
    //    then, it will teleport you to the TAG of the Waypoint named in this script.
    // To use: Name this SCRIPT after the ITEM to be used.  On the ITEM, give it the item property "Unique Power".
    //         Select yourself as the target of the "Unique Power"; the VFX will fire & you'll be teleported there.
    //
    //
    
    //"include" script needed for item event checking
    #include "x2_inc_switches"
    void main()
    {
        int iEvent = GetUserDefinedItemEventNumber();//what event just happened? item picked up, dropped, activated, etc?
        if (iEvent != X2_ITEM_EVENT_ACTIVATE) return;//if it wasn't the item 'activated' event then just end the script now.
    
    object oPC;
    
    if (!GetIsPC(GetItemActivatedTarget())
    ){
    
    SendMessageToPC(GetItemActivator(), "Improper use of item!");
    return;}
    
    oPC = GetItemActivator();
    
    object oTarget;
    location lTarget;
    oTarget = GetWaypointByTag("HELMITE_TEMPLE_001");
    
    lTarget = GetLocation(oTarget);
    
    //only do the jump if the location is valid.
    //though not flawless, we just check if it is in a valid area.
    //the script will stop if the location isn't valid - meaning that
    //nothing put after the teleport will fire either.
    //the current location won't be stored, either
    
    if (GetAreaFromLocation(lTarget)==OBJECT_INVALID) return;
    
    AssignCommand(oPC, ClearAllActions());
    
    DelayCommand(3.0, AssignCommand(oPC, ActionJumpToLocation(lTarget)));
    
    oTarget = oPC;
    
    //Visual effects can't be applied to waypoints, so if it is a WP
    //the VFX will be applied to the WP's location instead
    
    int nInt;
    nInt = GetObjectType(oTarget);
    
    if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), oTarget);
    else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), GetLocation(oTarget));
    
    }
    

    This is basically the same script but cleaned up a bit:
    //"include" needed for item event checking
    #include "x2_inc_switches"
    
    void main()
    {
        int iEvent = GetUserDefinedItemEventNumber();//what event just happened? item picked up, dropped, activated, etc?
        if (iEvent != X2_ITEM_EVENT_ACTIVATE) return;//if it wasn't the item activated event then just end the script now.
    
        object oPC = GetItemActivator();
    
        if (!GetIsPC(oPC))//if it wasn't a player who activated the item then send em a message and end the script.
        {
            SendMessageToPC(GetItemActivator(), "Improper use of item!");
            return;
        }
    
        object oWaypoint = GetWaypointByTag("HELMITE_TEMPLE_001");//just get the waypoint itself
        
        if (GetIsObjectValid(oWaypoint))//If the waypoint is legit..
        {
            //used a different jump function to add the action to the top of action queue.
            DelayCommand(3.0, AssignCommand(oPC, JumpToObject(oWaypoint)));
            //just apply the effect directly to the player and not their location
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_UNSUMMON), oPC);
        }
    }
    

    Edit: 2nd script had an extra set of curly brackets left over. I removed them.
    Post edited by NeverwinterWights on
  • TarotRedhandTarotRedhand Member Posts: 1,481
    @Ugly_Duck have you tried the No Scripting Quest System? It seems to work as I tested the first tutorial with EE, just a few hours ago. Think Plot Wizard but a lot more choice of quest type and much more control over the quest from beginning to end with no scripting on your part.

    TR
  • Ugly_DuckUgly_Duck Member Posts: 182
    Thanks TarotRedhand! I will check that out as soon as i can.
Sign In or Register to comment.