What's the best layout for scripting NPCs?

General discussion of Denizen-Bukkit, or even just Bukkit.
Post Reply
luigi_vampa
User
User
Posts: 6
Joined: August 6th, 2016, 1:26 pm

What's the best layout for scripting NPCs?

Post by luigi_vampa » August 7th, 2016, 5:31 am

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: Select all

"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
Regular
Regular
Posts: 78
Joined: August 6th, 2016, 1:44 am

Re: What's the best layout for scripting NPCs?

Post by BlackCoyote » August 7th, 2016, 5:40 am

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: Select all

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
          }

luigi_vampa
User
User
Posts: 6
Joined: August 6th, 2016, 1:26 pm

Re: What's the best layout for scripting NPCs?

Post by luigi_vampa » August 9th, 2016, 4:58 am

Thanks Coyote. I'll look into that and give it a go.

User avatar
mcmonkey
Site Admin
Site Admin
Posts: 217
Joined: August 5th, 2016, 7:27 pm
Location: Los Angeles, California, USA
Contact:

Re: What's the best layout for scripting NPCs?

Post by mcmonkey » August 16th, 2016, 7:11 pm

Topic moved.
Denizen lead developer.
http://mcmonkey.org

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest