What's the best layout for scripting NPCs?

luigi_vampa

Member
Aug 6, 2016
6
0
0
Most of the NPCs on my server are involved in multi-step quests for each of a variety of Star Wars based ranks. What's the best layout for a script to handle all of these different circumstances?

The layout I'm using at the moment is to give each NPC one interact script and then depending on what rank the player has use the - zap command attached to the proximity enter trigger in step 1 to send them to a specific step for that rank. When the player walks away from the NPC, the proximity exit trigger in the step returns the position to step 1 in case next time a player meets they're in a different rank.

In the specific step I attach a 'quest' flag to the player to keep a note of where they are in the story line.
When you've got a dozen ranks and a dozen story lines for each there's so many flags and if/else statements. It's copy/paste of the same code for - if <player.in_group> for the proximity triggers, chat triggers, damage triggers, etc. Any suggestions for a better, more concise layout?

Code:
"Sith_Recruiter Assignment":
    type: assignment

    actions:
      on assignment:
      - trigger name:proximity toggle:true
      - trigger name:chat toggle:true
      - trigger name:click toggle:true
      - trigger name:damage toggle:true
      - lookclose toggle:true
      
      on unavailable:
      - chat "Hold on, I'm busy right now."
      
    interact scripts:
    - 10 Sith_Recruiter Introduction
 

'Sith_Recruiter Introduction':
    type: interact

    steps:
        '1*':
            proximity trigger:
              entry:
                script:
                - if <player.in_group[Staff]> {
                  - zap 'step:2'
                  }
                  else if <player.in_group[Stormtrooper]> {
                  - zap 'step:6'
                  }
                  else if <player.in_group[Citizen]> {
                  - zap 'step:7'
                  }
                  else {
                  - zap 'step:10'
                  }
        
        # Staff
        '2':
            proximity trigger:
              exit:
                script:
                - zap 'step:1'
                
            click trigger:
                script:
                - chat "How may I serve you?"

            damage trigger:
                script:
                - chat "Forgive me!"

            chat trigger:
                'catch-all':
                    trigger: '/REGEX:\w+/'
                    script:
                    - chat "I'm sorry. I don't know what you're talking about."
             
        # Stormtrooper
        '6':
            proximity trigger:
              exit:
                script:
                - zap 'step:1'
                
            click trigger:
                script:
                - if <player.flag[Quest]> == "" || player.flag[Quest]> == null {
                  - chat "This is a hard hat area."
                  - wait 1
                  - chat "Use /kit stormtrooper and put on your helmet."
                  - flag <player> "Quest:EmpireStepOne"
                  }
                  else if <player.flag[Quest]> == "EmpireStepOne" {
                  - if <player.equipment.helmet> == "i@iron_helmet" {
                    - chat "Excellent work."
                    - flag <player> "Quest:EmpireStepTwo"
                    }
                    else {
                    - chat "Put on a Stormtrooper helmet that isn't damaged and right click the NPC."
                    }
                  }
                  else if <player.flag[Quest]> == "EmpireStepTwo" {
                  - chat "Blah blah blah."
                  - wait 1
                  - chat "Finished."
                  - flag <player> "Quest:!"
                  }
                  else {
                  - chat "This bit only runs when I've updated the quest and the flag is out of date so it's a nice catch-all."
                  - flag <player> "Quest:!"
                  }

            damage trigger:
                script:
                - chat "Don't be silly."

            chat trigger:
                'catch-all':
                    trigger: '/REGEX:\w+/'
                    script:
                    - chat "I'm sorry. I don't know what you're talking about."
           
        # Citizen
        '7':
            proximity trigger:
              exit:
                script:
                - zap 'step:1'
                
            click trigger:
                script:
                - chat "Have you come to serve the <&b>Empire<&f>?"

            damage trigger:
                script:
                - chat "Don't be silly."

            chat trigger:
                'Empire':
                    trigger: '/Empire/'
                    script:
                    - chat "There are many skills you will learn along the way."
                    - wait 1
                    - chat "There are also many dangers you will face."
                    - wait 2
                    - chat "Are you sure you are ready to <&b>join<&f>?"
                'Join':
                    trigger: '/Join/'
                    script:
                    - chat "The Rebel Alliance will be crushed beneath the Empire."
                    - execute as_server "manuadd <player.name> Stormtrooper"
                    - zap 'step:6'
                'catch-all':
                    trigger: '/REGEX:\w+/'
                    script:
                    - chat "I'm sorry. I don't know what you're talking about."
        
        # Default
        '10':
            proximity trigger:
              exit:
                script:
                - zap 'step:1'
                
            click trigger:
                script:
                - chat "Report to the Registration Clerk at the Ubrikkian Trade Tower."

            damage trigger:
                script:
                - chat "Don't be silly."

            chat trigger:
                'catch-all':
                    trigger: '/REGEX:\w+/'
                    script:
                    - chat "I'm sorry. I don't know what you're talking about."
 

BlackCoyote

Well-known member
Aug 6, 2016
78
0
0
The best layout is avoiding interact scripts all together.

using actions as triggers, and your own logic (preferably the choose command) is far better, and maybe even simpler.

Here's an example:
Code:
myAssignmentScript:
  type: assignment
  actions:
    on assignment:
    - trigger name:proximity toggle:true
    - trigger name:chat toggle:true
    - trigger name:click toggle:true
    - trigger name:damage toggle:true
    - lookclose toggle:true
    on click:
    - if <player.has_flag[npc_cooldown]> queue clear
    - flag <player> npc_cooldown duration:10s
    - choose <player.flag[myassignmentScriptStep]||0>:
      - case 0:
        - narrate "Hello, What is your name?" format:myFormatScript
      - case 1:
        - narrate "Good, now that i know your name, we can continue" format:myFormatScript
        - wait 4s
        - narrate "Kill 5 zombies for me!!" format:myFormatScript
        - flag myassignmentScriptStep:2
      - case 2:
        - narrate "You have to kill 5 zombies first." format:myFormatScript
      - case 3:
        - narrate "Hooray you did it!"  format:myFormatScript
    on chat:
    - if <player.has_flag[npc_cooldown]> queue clear
    - flag <player> npc_cooldown duration:10s
    - choose <player.flag[myassignmentScriptStep]||0>:
      - case 0:
        - if <context.message> == <player.name> {
          - narrate "Okay good! click to continue!" format:myFormatScript
          - flag myassignmentScriptStep:1
          } else {
          - narrate "Liar! Try again." format:myFormatScript
          }
myWorldScript:
  type: world
  events:
    on player kills zombie:
    - choose <player.flag[myassignmentScriptStep]||0>:
      - case 2:
        - flag <player> myassignmentScriptzombies:++
        - if <player.flag[myassignmentScriptzombies]||0> >= 5 {
          - narrate "You killed 5 zombies!" format:myFormatScript
          - flag myassignmentScriptStep:3
          }