Author Topic: Complicated conversation...  (Read 644 times)

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« on: October 25, 2010, 09:42:31 pm »


               I'm scripting quite a difficult conversation now (at least, I think so), and I need some more help. I know this is the third topic I've started this week, so thanks for putting up with me.

So the idea is this: you have a pillar with runes on it, that you can push to activate. You must push three runes in order to activate something. How do I script that a new text may appear when the right three runes are pushed.
For example, I want something to happen when the PC pushes the following runes:

- Activate
- Summon demon
- Enter

But I don't want anything to happen when the PC pushes the following runes:

- Activate
- Enter
- Summon demon

etc.

Any help is greatly appreciated. '<img'>
               
               

               
            

Legacy_HipMaestro

  • Hero Member
  • *****
  • Posts: 2849
  • Karma: +0/-0
Complicated conversation...
« Reply #1 on: October 25, 2010, 10:40:20 pm »


               Until someone who is not a neophyte scripter like myself shows up, I can at least make a guess as to how I would try to script it.  In this way, not only will you get your question answered, but i can get corrected for my poor strategy. '<img'>

I would set specific string variables for each rune and the final string that will trigger the action.  I suppose the OnUse function is the one to use.  Keep concatenating the results and checking against a static value which defines the final action you desire (you indicated a text display along with another action).  For example, the first string would be "a+e+s" and the second "a+s+e", so in this case, only "aes" will trigger.  All other combos should fail.

I am curious myself to see how close I come to the best solution.
               
               

               


                     Modifié par HipMaestro, 25 octobre 2010 - 09:42 .
                     
                  


            

Legacy_GhostOfGod

  • Hero Member
  • *****
  • Posts: 1490
  • Karma: +0/-0
Complicated conversation...
« Reply #2 on: October 26, 2010, 04:36:27 am »


               There really are a LOT of ways you could do this. Since HipMaestro already suggested one method lets take a look at doing it that way.
To keep things very simple let's just use the name of the objects/runes to build the right string sequence. This way you can also use the same script for all three rune/objects. So if you were to literally name these objects "Activate", "Summon demon" and "Enter" you could use a script in the objects "OnUsed" event like so:

void main()
{
//We can just use the name of the object to build the correct string sequence.
string sName = GetName(OBJECT_SELF);
//Get the player who last clicked the object.
object oPC = GetLastUsedBy();
//Get the stored string on the player under the title "RUNE_PUZZLE". If this is
//the first time the player has clicked one of the objects then this will just
//be blank.
string sPuzzle = GetLocalString(oPC, "RUNE_PUZZLE");
//Store the new string under the title "RUNE_PUZZLE" on the player.
SetLocalString(oPC, "RUNE_PUZZLE", sPuzzle + sName);
}

This script builds one long string, based on the order the objects were clicked, and saves it on the player to be checked by the script below. If the player clicked on the "Enter" rune 3 times then the saved string would be "EnterEnterEnter". I didn't add any kind of check for limitations though. If a player clicks the "Activate" rune six times then the stored string would be "AcitvateActivateActivateActivateActivateActivate". I hope that makes sense. And if you want some kind of feed back for the player you could always just add a bit to the bottom of the above script. Like adding a quick visual effect to the rune. Or send a message to the player, etc..

Then for the part of the conversation where the new node would show up if the correct string were stored on the player. The following would go in the "TextAppearsWhen" tab of the new node. It is basically saying that if the string stored on the player is "ActivateSummon demonEnter", then this conversation node will appear.

int StartingConditional()
{
object oPC = GetPCSpeaker();
string iString = GetLocalString(oPC, "RUNE_PUZZLE");
if (iString == "ActivateSummon demonEnter")return TRUE;
else return FALSE;
}

Of course you will also want to delete the stored string every time a player starts the conversation to check to see if they got it right. So in both nodes (correct or incorrect) in the ActionsTaken event of those lines put int something like so:

void main()
{
object oPC = GetPCSpeaker();
DeleteLocalString(oPC, "RUNE_PUZZLE");
}

That is pretty much it. This is a simple crude example but it should still work. Is it the best solution? I don't think there really is a BEST solution in this case. It really just depends on what you want to happen and the how and when and all that.

Hope this at least gets you started.

Good luck.
               
               

               


                     Modifié par GhostOfGod, 26 octobre 2010 - 03:46 .
                     
                  


            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Complicated conversation...
« Reply #3 on: October 26, 2010, 06:09:35 am »


               I would give each rune a number between 1 and 9.  The Number I  would set on each rune. If the runes are set to plot. I would use the hardness stat of the rune to store its unique number on it. So for the three runes you gave I would do something like. 

- Activate                   Set its hardness to 1
- Summon demon    Set its hardness to 2
- Enter                       Set its hardness to 3 


I would then when the rune was used(pushed) place the it number into the lowest decemal place of an intenger. rolling any privious rune pushes to a decimal place higher up in the number.  Then Trimming the number to the last 3 decimal places.  The number I would store on either the PC or the area acording to how i wanted it to work.  PC for if it only matter what the PC pushes for himself or area if other can effect what is happening.  

Example on how the pushes would effect the number.  

The PC first pushs rune 2 our number we will call it nPushes would = 2 

The PC then pushes rune 1  so nPushes now = 21

The PC then pushes rune 3 so nPushes = 213 

if the PC then pushes rune 1 again we would end up with nPushes = 131 dropping the 2 off the front and adding the 1 as the last push.  

Now in order to do this you may need to learn a new operator.  The operator is the Modulo or '%'  what the modulo does is calculate the remainder of a division.  It is what we will use the trim our number to just the last three decimal places. exsample.  

nPushes = 2131; 
nPushes  = nPushes % 1000; 

will make nPushes = 131 The remainder of the devision of   2131/1000 = 2 remainder 131.  

Adding the number for the rune to the end is just as easy all we have to do is multiply it by 10 and add our number.  

nPushes = nPushes * 10 + GetHardness(); // OBJECT_SELF implied  

With the above set up you would end up with something like this on all of your runes.  


 void main()
 {
   object oArea = GetArea(OBJECT_SELF);
   //object oUser = GetLastUsedBy(); // If you want to go this route.
   int nPushes= GetLocalInt(oArea,"pushes");
   int nRuneNumber = GetHardness();
   // Do nothing if the same rune is pushed two time in a row.
   if (nPushes %10  ==  nRuneNumber ) return;
   // If not adjust our number.
   nPushes = nPushes *10 + nRuneNumber;
   nPushes = nPushes % 1000;
   // Restore the number
   SetLocalInt(oArea,"pushes",nPushes);
 }

then your starting condition is simple 

int StartingConditional()
{
  object oArea = GetArea(OBJECT_SELF);
  return  (GetLocalInt(oArea,"pushes") == 123);
}

Just change the 123 to any order you want to use. 
   
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #4 on: October 26, 2010, 11:07:36 am »


               Thanks for the replies! But I don't think I've made myself clear enough.
What I did is make a conversation for the rune pillar, in that conversation at a certain point you have the choice to push several runes. Sort of like this:

- >What runes do you want to push?
------->Activate
-------> Enter
-------> Summon
-------> Summon testobject

etc

So when the PC chooses three of these textstrings in the right order, something happens, like a visual effect and the summoning of a creature. But not every reaction will be the same for every order.
For example, a different creature will be summoned when the pc chooses Activate-Summon-Enter than if the pc chooses Activate-Summon testobject-Enter. And when the PC chooses an invalid string, such as Activate-Activate-Enter or Summon-Activate-Enter, nothing happens.

I think what you thought was that I was using placeable runes, but these are 'imaginary' runes on the pillar you are having a 'conversation' with.

EDIT:
I'm going to make it a little more complicated. I want the pillar only to react to the right runes pushed if the pc has first put all three gems (see other topic I started) in the pillar (also in conversation). So how do I do this?
I suppose set variables to the textstrings, but how do I set that to only set a variable if all three gems are put in?
I hope this is still understandable.
               
               

               


                     Modifié par Eva_hop, 26 octobre 2010 - 03:34 .
                     
                  


            

Legacy_Mudeye

  • Full Member
  • ***
  • Posts: 238
  • Karma: +0/-0
Complicated conversation...
« Reply #5 on: October 26, 2010, 05:25:20 pm »


               Hi,
Below are some button ActionsTaken scripts. For the conversation.  At each step you just display all the button choices.
This assumes the buttons are:
    Activate
    Summon Pit Fiend
    Summon Rat
    Enter

The full text of the display might be something like: "A display panel has several buttons on it. What do you want to do."
And the options are:

"Press Activate"
"Press Summon Pit FIend"
"Press Summon Rat"
"Press Enter"
"Leave"

If any of the button press options are selected just jump to the same conversation node again.  If they select Leave then exit the conversation.

The user must press:  Activate, then one of the summon buttons and finally Enter
So:  Activate, Summon Pit Fiend, Enter
or:  Activate, Summon Rat, Enter

If they press:  Enter, Summon Rat, Activate
it won't work.

There must be a waypoint with the tag: WP_SUMMON
That will be used as the location for the summon to appear.

If they mess up it always resets when you press activate so they could press:

Summon Pit Fiend, Enter, Activate, Summon Rat, Enter

The first 2 are in error. But when they press Activate it starts over. So the final three: Activate,Summon Rat,Enter
will cause a rat to be summoned.

This hasn't been tested but the idea is sound and it is pretty close to correct.


//Activate Button
void main()
{
    SetLocalInt(OBJECT_SELF,"ButtonState",1);
}

//Summon Demon Button
void main()
{
    int state = GetLocalInt( OBJECT_SELF, "ButtonState" );
    if( state == 1 )
    {
        SetLocalInt( OBJECT_SELF, "ButtonState", 10 );
    }
    else
    {
        SetLocalInt( OBJECT_SELF, "ButtonState", 0 );
    }
}

//Summon Rat Button
void main()
{
    int state = GetLocalInt( OBJECT_SELF, "ButtonState" );
    if( state == 1 )
    {
        SetLocalInt( OBJECT_SELF, "ButtonState", 20 );
    }
    else
    {
        SetLocalInt( OBJECT_SELF, "ButtonState", 0 );
    }
}

//Enter Button
void main()
{
    int state = GetLocalInt( OBJECT_SELF, "ButtonState" );
    object wp = GetWaypointByTag("WP_SUMMON");
    location loc = GetLocation(wp);
    if( state == 10 )
    {
        //summon a pit fiend
        CreateObject(OBJECT_TYPE_CREATURE,"nw_devil001",loc);
    }
    else if( state == 20 )
    {
        //summon a rat
        CreateObject(OBJECT_TYPE_CREATURE,"nw_rat001",loc);
    }   
    SetLocalInt( OBJECT_SELF, "ButtonState", 0);
}
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #6 on: October 27, 2010, 09:07:54 pm »


               Thank you! I will test this as soon as possible and let you know if it works or if any other problems pop up.
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #7 on: October 30, 2010, 12:10:28 am »


               Hey Mudeye,
your script works well. '<img'> I tested it and have it up to date.
This is what the 'enter button' looks like now:

void main()
{
   int state = GetLocalInt( OBJECT_SELF, "ButtonState" );
   object wp = GetWaypointByTag("WP_summon");
   location loc = GetLocation(wp);
   if( state == 10 )
   {
       //summon Dantello
       CreateObject(OBJECT_TYPE_CREATURE,"Dantello",loc);
   }
   else if( state == 20 )
   {
       //summon a testobject
       CreateObject(OBJECT_TYPE_CREATURE,"UrduPenguin",loc);
   }
   else if( state == 40 )
   {//summon Hasheida
   CreateObject(OBJECT_TYPE_CREATURE,"Hasheida",loc);
   }
   { //phylactery activate
     object oPC = GetPCSpeaker();

object oTarget;
oTarget = GetObjectByTag("OBJECT");

//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_RAISE_DEAD), oTarget);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_RAISE_DEAD), GetLocation(oTarget));

object oSpawn;
location lTarget;
oTarget = GetWaypointByTag("WP_summon");

lTarget = GetLocation(oTarget);

oSpawn = CreateObject(OBJECT_TYPE_PLACEABLE, "urdu_summon", lTarget);

oTarget = oSpawn;

//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

nInt = GetObjectType(oTarget);

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

//visual effect phylactery
oTarget = GetObjectByTag("WP_phylactery");

//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

nInt = GetObjectType(oTarget);

if (nInt != OBJECT_TYPE_WAYPOINT) ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_LOS_EVIL_20), oTarget);
else ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_LOS_EVIL_20), GetLocation(oTarget));
    }
   SetLocalInt( OBJECT_SELF, "ButtonState", 0);
}


Every summon and effect functions, but there's something more I'd like to do.
As you may know (other topic) I've also been messing around with gems that have to put in the pillar (in conversation). I only want the summons and runes to work if at least three of the four gems have been put into the pillar.
Next to that, I only want the summons to work if the phylactery has been 'activated' first (also one of the rune options). How do I make it do that?

Oh yeah, to make it more complicated, I want Hasheida (a demon) only to be summoned when also the fourth gem has been put into the pillar. Next to that, the phylactery can only be activated once, and Hasheida and the god can only be summoned once...How do I do that?
I hope this all still makes sense. To clarify a little:

There's a pretty pillar incised with runes
---> choose what runes to push
------> summon god (Dantello)
------> summon test object
------> summon bound demon
------> Activate
------> Enter
------> phylactery
Put gems in empty slots
----> put fire opal in
----> put blood coral in
----> put rose ruby in
----> put dark garnet in (fourth gem)


               
               

               


                     Modifié par Eva_hop, 30 octobre 2010 - 12:07 .
                     
                  


            

Legacy_Mudeye

  • Full Member
  • ***
  • Posts: 238
  • Karma: +0/-0
Complicated conversation...
« Reply #8 on: October 30, 2010, 03:55:12 pm »


               First, I'd suggest only displaying the summon options that are enabled.  That means that the "Summon bound demon" would only show up as an option if all 4 gems are inserted and the phylactery has been activated.  That kind of testing needs to happen in the "Text Appears When" script.  Is that alright with you.
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #9 on: October 30, 2010, 04:29:09 pm »


               I considered it, and it can be done, but I'd like it much more if I can just let it say "nothing happens", otherwise it's not much of a puzzle. Can that be done?
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #10 on: October 31, 2010, 08:48:39 pm »


               No one has a solution?
               
               

               
            

Legacy_Olblach

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Complicated conversation...
« Reply #11 on: October 31, 2010, 10:21:43 pm »


               It's not that complicated. You need two variables, lets call them "gems_activated" and "Philactery_Activated" that you can check for your first goal.
Now you want the philactery activated only once. Then it will be the same variable "Philactery_Activated" that you will check.
For Hasheida you need another variable "Hasheida_Spawned".
Now your next problem is when and where you set and check those variables.
I would elaborate more but unfortunately it's been a while that I didn't use Aurora so I'm walking on eggs hehe.
However I can give you Hasheida code, I shouldn't be making mistakes here:

else if( state == 40 )
{//summon Hasheida
if (GetLocalInt(OBJECT_SELF, "Hasheida_Spawned") == 0)
{
CreateObject(OBJECT_TYPE_CREATURE,"Hasheida",loc);
SetLocalInt(OBJECT_SELF, "Hasheida_Spawned", 1) ;
}
}

               
               

               


                     Modifié par Olblach, 31 octobre 2010 - 10:23 .
                     
                  


            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #12 on: November 01, 2010, 10:29:32 am »


               Thanks Olblach, I've been messing around with variables but i've never been any good with math. '<img'>

I'm going to try this out and hope it works.
               
               

               
            

Legacy_Olblach

  • Newbie
  • *
  • Posts: 14
  • Karma: +0/-0
Complicated conversation...
« Reply #13 on: November 01, 2010, 11:35:23 am »


               Try to see if it works with Hasheida then we can move on the other problems later.
               
               

               
            

Legacy_Eva_hop

  • Jr. Member
  • **
  • Posts: 88
  • Karma: +0/-0
Complicated conversation...
« Reply #14 on: November 02, 2010, 09:39:27 am »


               It works! Hasheida won't be summoned again. I guess I can use the same script on Dantello.
But when I press "activate""wake bound demon""enter" the summoning visual effect's are still there. Instead of that I'd like a message or textstring to come up "nothing happens".

Also, if Hasheida is summoned, I want Harsheeta (another NPC) to disappear. Right now I have this but it's not working:
EDIT: apparently you can't say **** on this forum so I changed Har****a's name to Harsheeta.

else if( state == 40 )
{//summon Hasheida
if (GetLocalInt(OBJECT_SELF, "Hasheida_Spawned") == 0)
{
CreateObject(OBJECT_TYPE_CREATURE,"Hasheida",loc);
SetLocalInt(OBJECT_SELF, "Hasheida_Spawned", 1) ;
}
object oTarget;
oTarget = GetObjectByTag("Har****a");

effect eEffect;
eEffect = EffectDeath();

ApplyEffectToObject(DURATION_TYPE_PERMANENT, eEffect, oTarget);
   }


               
               

               


                     Modifié par Eva_hop, 02 novembre 2010 - 09:40 .