Paste #25769: ari

Date: 2015/12/21 15:24:47 UTC-08:00
Type: Denizen Script

View Raw Paste Download This Paste
Copy Link


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775


# Hire a Bodyguard
# Citizens 2 (build #1045)
# Sentry (v. 1.8.0)
# Denizen 0.9.3 (build #1417)
#
# Description:
#
# The purpose of this script is to allow you to have a "bodyguard" service for your players. When a player talks
# to the NPC, it will offer them 4 different guards. The first being the weakest and the cheapest up to the
# most expensive but also strongest. You can however modify their strength and armor ratings below
# to suit your server.
#
# On default, each 'level' wears different armor - leather, iron, diamond and chainmail (for the horse mounted
# NPC's). However, the armor is purely cosmetic and doesn't affect their armor rating at all. You can modify 
# the type of armor in the 'default constants' section below.
#
# You should also change the price for each guard to suit your economy and server type.
#
# If the player hired a bodyguard and then forgot them somewhere or they disconnected and the bodyguard
# is gone, they can go back to the mercenary to teleport the bodyguard back to them (if it's still alive).
#
# Credits:
#        * davidcernat for having to add a bunch of new features and bug fixes to make this work.
#        * Jeebiss whose 'Hireable Bodyguards' script was used as a template for this one.
#        * fullwall and jrbudda for super fast fixes to Citizens & Sentry to make this possible.
#
# @author mythanical
# @script version 0.6.3
# @last-updated 10 January 2014
# @irc EsperNet IRC Network #denizen-dev
# @Minecraft Server - minecraft.geek.nz
# @Donate Bitcoin: 1Fzacc2gZ5NGRMXg5jWP6NcUkWei34xjzt
# @Donate Litecoin: LhsaGa1QzmVLjMYwg4ZPTVnmSgnBDGc75U

"Bodyguard Global Flag":
  type: world
  events:
    on reload scripts:
    # --- DO NOT MODIFY THESE TWO VALUES ---
    - flag global "Bodyguard Food:!"
    - flag global "Bodyguard Food Heal Amount:!"

    # The following is a list of foods that will heal a guard. The flag under that hold the corresponding heal
    # amount for the food in the matching position. So, "i@baked_potato" is second in the list, so the second
    # value in the 'heal amount' list is 6. That is how much the guard will be healed.
    - flag global "Bodyguard Food:|:i@apple|i@baked_potato|i@bread|i@cake|i@carrot|i@cooked_beef|i@cooked_chicken|i@cooked_fish|i@grilled_pork|i@cookie|i@melon|i@mushroom_soup|i@pumpkin_pie|i@raw_beef|i@raw_chicken|i@raw_fish|i@pork"
    - flag global "Bodyguard Food Heal Amount:|:4|6|5|12|4|8|6|5|8|2|2|6|8|3|2|2|3"

    # If this value is anything other than '0', the player will get it as a percentage refund on the amount
    # they paid for the guard.
    - flag global "Bodyguard Refund Percentage:50"

    # Give players 15 seconds to type 'bye guard' after clicking a guard, to fire them and get a refund
    # if enabled.
    - flag global "Bodyguard Listen Time:15s"

    # The name for the bodyguard type - this is what the player will need to enter when they buy
    # their bodyguard. If you use the 'dynamic' player suffix setting further below I wouldn't
    # recommend a name longer than 8 characters.
    - flag global "Bodyguard One Name:Peon"
    - flag global "Bodyguard Two Name:Thug"
    - flag global "Bodyguard Three Name:Brute"
    - flag global "Bodyguard Four Name:Knight"

    # Change to 'Disallow' if you do not want to allow Knights (horse mounted Sentries).
    - flag global "SentryHorseMountAllow:Allow"

    # Remove Horse when the NPC is fired or dies.
    - flag global "RemoveHorseMount:Allow"

    # This sets a limit for the number of guards a player can have.
    - flag global "Bodyguard Limit:2"

    # Allows guards names to have the owner's name abbreviated and suffixed at the end. If you
    # change the guard names, you will have to change the abbreviation lengths too otherwise
    # you may get some undesired results.
    #
    # dynamic           (Add the longest player name abbreviation it can fit into 16 chars)
    # 1-16              (If you want a static length abbreviation, then specify a value here. Note, if you make it too long you'll get some undesired results)
    # disallow          (To disable player name suffixes)
    - flag global "Player Name Suffix:dynamic"

    # Specify the colour of the abbreviated player name.
    # Color list available here:
    #  http://jd.bukkit.org/rb/apidocs/org/bukkit/ChatColor.html
    - flag global "Player Name Suffix Color:green"

    # The "sentry" strength for each bodyguard type.
    - flag global "Bodyguard One Strength:7"
    - flag global "Bodyguard Two Strength:7"
    - flag global "Bodyguard Three Strength:8"
    - flag global "Bodyguard Four Strength:9"

    # The "sentry" strength for each bodyguard type.
    - flag global "Bodyguard One Armor:5"
    - flag global "Bodyguard Two Armor:6"
    - flag global "Bodyguard Three Armor:7"
    - flag global "Bodyguard Four Armor:8"

    # This is the number of seconds between heals of 1 point, values less than 1.0 are acceptable. Set to 0 to turn off healing.
    # A heal rate of 0.5 is 2hp per second. A healrate of 0.1 is 10hp per second. A healrate of 0.01 is 100hp per second.
    - flag global "Bodyguard One Healrate:0"
    - flag global "Bodyguard Two Healrate:0"
    - flag global "Bodyguard Three Healrate:0"
    - flag global "Bodyguard Four Healrate:0"

    # Cosmetic Armor to differentiate between guard levels. You can have 'leather', 'chainmail', 'iron', 'gold' and 'diamond'.
    - flag global "Bodyguard One Appearance:Leather"
    - flag global "Bodyguard Two Appearance:Iron"
    - flag global "Bodyguard Three Appearance:Diamond"
    - flag global "Bodyguard Four Appearance:Chainmail"

    # The swords the bodyguards will wield. You can have 'wood', 'stone', 'iron', 'gold', 'diamond'.
    - flag global "Bodyguard One Sword:Wood"
    - flag global "Bodyguard Two Sword:Stone"
    - flag global "Bodyguard Three Sword:Iron"
    - flag global "Bodyguard Four Sword:Diamond"

    # Price to hire guard    
    - flag global "Bodyguard One Price:1500"
    - flag global "Bodyguard Two Price:3000"
    - flag global "Bodyguard Three Price:5000"
    - flag global "Bodyguard Four Price:10000"

    # Show Guard Health as Bar or Percentage (anything other than "bar" will display a percentage for the health).
    # Experiment and see which one you'd prefer your players to see.
    - flag global "Bodyguard Health:bar"

    # -- IGNORE THIS SECTION, NOT IMPLEMENTED YET. ---
    # If this is any value other than 'disallow', an inventory window will open when
    # the guard is right clicked. The guard will also wait until they are right clicked
    # again before they start following the player.
    #
    # drop              (Drop all items on the ground where the guard died)
    # disallow          (Disable bodyguard inventories)
    - flag global "Bodyguard Inventory:disallow"

"Mercenary":
  type: assignment

  interact scripts:
  - 10 Hire a Bodyguard

  actions:
    on assignment:
    # These triggers enable interaction with an NPC via chatting, clicking, entering proximity and when damaging the NPC.
    - trigger name:chat toggle:true
    - trigger name:click toggle:true
    - trigger name:proximity toggle:true
    - trigger name:damage toggle:true
    # Make it so the mercenary can be killed by players. The mercenary will respawn 60 seconds later. Otherwise, just comment the following
    # three lines and the mercenary will be invulnerable.
    - ^execute as_npc "npc sel <npc.id>"
    - ^execute as_npc "npc vulnerable"
    - ^execute as_npc "npc respawn 60"

    on death by player:
    # When a player kills the mercenary, narrate something. On my server, I run another script instead that 
    # changes the alignment of the player for committing this heinous act.
    - narrate "<red>You have killed <yellow><npc.name><red>. Are you pleased with yourself?"

"Hire a Bodyguard":
  type: interact

  steps:
    1:
      proximity trigger:
        entry:
          script:
          # On player entering NPC proximity range, run a script called 'Check Greeting Requirements'. 
          # The default proximity range is set in Denizen\config.yml
          - run "Check Greeting Requirements"

      click trigger:
        script:
        # On clicking, run a slightly different script to check some requirements to see what dialog
        # the player should be presented with.
        - run "Bodyguard Requirement Check"

      damage trigger:
        script:
        # When you hit the NPC, it will run the script called Warning (further below).
        - run "Warning"

    2:
      chat trigger:
        'Lost NPC':
          Trigger: "/Yes/ please, /find/ a guard for me and bring them back."
          script:
          # When the bodyguard is created, they add their own NPC ID into a player flag. This flag is then used to
          # provide the NPC ID in the teleport command and teleport them back to the same location as the player.
          - engage
          - if <player.flag[GuardId].size> >= 1 {
            - random {
              - chat "<yellow>Ok <yellow><player.name><yellow>, we're tracking him down now..."
              - chat "<yellow>I'm sending word now.. your guard is on their way back."
              - chat "<yellow>I have informed the network of your missing guard, they are searching for them now." }
            - wait 4
            - random {
              - chat "<yellow>Found 'em!"
              - chat "<yellow>Ah good, they are still alive. Here you go <white><player.name><yellow>."
              - chat "<yellow>Welcome back <white><player.flag[GuardId].formatted><yellow>." }
            - teleport <player.flag[GuardId].aslist> location:<player.location>
            - ^foreach <player.flag[GuardId].aslist> {
              - if <%value%.flag[Guarding]> == null {
                - flag %value% Guarding
                - execute as_npc "npc sel <%value%.id>"
                - execute as_npc "sentry guard <npc.owner.name>" }
              }
            }

            else {
              - random {
                - chat "<yellow>I'm sorry <white><player.name><yellow>, but I've got nothing on record about you having a guard."
                - chat "<yellow>I..can't find any guards for you on the ledger. Are you sure they're still alive?"
                - chat "<yellow>Your guards either died or you fired them because I can't track any down.."
                }
            }
          - disengage

        'Leave NPC':
          Trigger: /No/ thank you, I want to leave them where they are.
          script:
          - engage
          - chat "<yellow>No problem <white><player.name><yellow>, come see me if you want them brought back."
          - disengage

        'Which Bodyguard':
          Trigger: I am interested in hiring '/REGEX:^\w+$/'.
          script:
          # When the player enters the name of the guard they want to hire, the following logic kicks in.
          # The following options exist in the section below:
          # 1) Engage the NPC so no other players can interact with them.
          # 2) Check to see if what the player entered matches any of the 4 bodyguard names.
          # 3) Has the player already got guards and if so, are they over or under the guard limit. If over, tell
          #    them they cannot hire more guards.
          # 4) Check to see if they've got enough money for the guard name they entered. If they haven't, tell them they don't.
          # 5) Otherwise if what the player typed doesn't match any criteria, tell them the NPC doesn't know what they're saying.
          # 6) Disengage the NPC so other players can interact again.

          - engage
          - ^if "<global.flag[Bodyguard One Name]>|<global.flag[Bodyguard Two Name]>|<global.flag[Bodyguard Three Name]>|<global.flag[Bodyguard Four Name]>" contains <context.message> {
            - if <player.flag[GuardId].size> < "<global.flag[Bodyguard Limit]>" {

              - if <context.message> == "<global.flag[Bodyguard One Name]>" && <player.money> >= "<global.flag[Bodyguard One Price]>" run "Create Bodyguard" def:One instantly
                else if <context.message> == "<global.flag[Bodyguard Two Name]>" && <player.money> >= "<global.flag[Bodyguard Two Price]>" run "Create Bodyguard" def:Two instantly
                else if <context.message> == "<global.flag[Bodyguard Three Name]>" && <player.money> >= "<global.flag[Bodyguard Three Price]>" run "Create Bodyguard" def:Three instantly
                else if <context.message> == "<global.flag[Bodyguard Four Name]>" && <player.money> >= "<global.flag[Bodyguard Four Price]>" run "Create Bodyguard" def:Four instantly

                else if <context.message> == "<global.flag[Bodyguard One Name]>"
                && <player.money> < "<global.flag[Bodyguard One Price]>"
                narrate "<red>You have <gold><player.money.asint><red> <player.money.currency>, but need <gold><global.flag[Bodyguard One Price]><red> <player.money.currency><red> to pay <white><npc.name><red>."
                else if <context.message> == "<global.flag[Bodyguard Two Name]>"
                && <player.money> < "<global.flag[Bodyguard Two Price]>"
                narrate "<red>You have <gold><player.money.asint><red> <player.money.currency>, but need <gold><global.flag[Bodyguard Two Price]><red> <player.money.currency><red> to pay <white><npc.name><red>."
                else if <context.message> == "<global.flag[Bodyguard Three Name]>"
                && <player.money> < "<global.flag[Bodyguard Three Price]>"
                narrate "<red>You have <gold><player.money.asint><red> <player.money.currency>, but need <gold><global.flag[Bodyguard Three Price]><red> <player.money.currency><red> to pay <white><npc.name><red>."
                else if <context.message> == "<global.flag[Bodyguard Four Name]>"
                && <player.money> < "<global.flag[Bodyguard Four Price]>"
                && "<global.flag[SentryHorseMountAllow]>" == "Allow"
                narrate "<red>You have <gold><player.money.asint><red> <player.money.currency>, but need <gold><global.flag[Bodyguard Four Price]><red> <player.money.currency><red> to pay <white><npc.name><red>."
              }

              else {
                - narrate "<red>You cannot hire anymore guards. The guard limit per player is <white><global.flag[Bodyguard Limit]>."
              }
            }
            else {
              - chat "<yellow>I'm sorry <white><player.name><yellow>, but I don't know who or what <white>'<context.message>'<yellow> is."
            }

          - disengage

      click trigger:
        script:
        # It helps to put some extra click and proximity types triggers in the different steps for a script. That way the
        # player will always get some kind of feedback from an NPC to know where they are at with a dialog or if the NPC
        # is waiting for a response of some sort.
        - run "Bodyguard Requirement Check"

      proximity trigger:
        exit:
          script:
          # When player leaves NPC proximity, put them back to step 1 in 'Hire a Bodyguard' script so
          # it'll be a fresh new conversation when they come back.
          - zap step:1

"Check Greeting Requirements":
  type: task
  speed: 0

  script:
  # The following options exist here (only really for player immersion)
  # 1) If a bodyguard has been hired already, greet them with the 'Mercenary Hired Bodyguard Chat' script.
  # 2) Else simply greet them with the 'Mercenary General Chat'.
  - if <player.flag[GuardId].size> == 1 {
    - random {
      - chat "<yellow>Welcome back <white><player.name><yellow>, hope all is going well with your bodyguard?"
      - chat "<yellow>Hi <white><player.name><yellow>, how is it going with your bodyguard? Are you just checking in?"
      - chat "<yellow>If you ever lose your guard, just come talk to me and I can track them down for you."
      - chat "<yellow>Your bodyguards is a great fighter, but not the smartest. If they ever get lost, just come chat to me."
      - chat "<yellow>Ah <white><player.name><yellow>, I see on the list you've employed one of our fine fighters. Hope all is well."
      - chat "<yellow>Hope your bodyguard has been a great help cracking zombie skulls." }
    }

    else if <player.flag[GuardId].size> > 1 {
    - random {
      - chat "<yellow>Welcome back <white><player.name><yellow>, hope all is going well with your <player.flag[GuardId].size> bodyguards?"
      - chat "<yellow>Hi <white><player.name><yellow>, how is it going with your bodyguards? Are you just checking in?"
      - chat "<yellow>If you ever lose your guards, just come talk to me and I can track the <player.flag[GuardId].size> down for you."
      - chat "<yellow>These bodyguards are great fighters, but not the smartest. If they ever get lost, just come chat to me."
      - chat "<yellow>Ah <white><player.name><yellow>, I see on the list you've employed <player.flag[GuardId].size> of our fine fighters. Hope all is well."
      - chat "<yellow>Hope your bodyguards have been a great help cracking zombie skulls." }
    }

    else {
      - random {
        - chat "<yellow>Are you interested in some extra protection? Come chat to me."
        - chat "<yellow>Hi <white><player.name><yellow>, need someone to help you out? I can provide a bodyguard at a reasonable price."
        - chat "<yellow>Seems to me like you can use a bodyguard <white><player.name><yellow>."
        - chat "<yellow>Help is hard to find these days, except when you've got coin. Let's talk business."
        - chat "<yellow>Are you an important public figure? Someone wants you dead? Don't worry, I've got a solution."
        - chat "<yellow>Small zombie hordes knocking at the door? Our bodyguards will be knocking on their skulls instead." }
    }

"Warning":
  type: task
  speed: 0

  script:
  # If you hit the mercenary, the "damage" triggers in the "Hire a Bodyguard" section above will run this script.
  - random {
    - chat "<red>Oucch! <yellow>Why would you do that? If I die, you WILL regret it!"
    - chat "<red>Aaarrggg! <yellow>What did I ever do to you? Don't hit me again!"
    - chat "<red>Wha..why are you hurting me? <yellow>Oh, these cuts..they hurt so much."
    - chat "<red>Please don't hurt me! <yellow>I have never done anything bad to you!"
    - chat "<red>Owwee! <yellow>Don't do something now that you will regret later.." }

"Bodyguard Requirement Check":
  type: task
  speed: 0

  script:
  # This task runs when the player interacts with the Mercenary.
  # 1) First it checks to see if the player has reached their bodyguard limit, if so, it will present
  #    them with only the teleport options.
  # 2) Else, if they have a guard but are still under the bodyguard limit it will present them with
  #    a dialogue that lists the guards but also give the 'Find' option to teleport them back.
  # 3) Lastly, if the player doesn't have any guards, it will simply present them with a list of available
  #    guards.
  #
  # This part of the script only shows stuff on the screen, it's the command at the bottom
  # called 'zap' that takes it to the right section where it's waiting for a response from the player.

  - if <player.flag[GuardId].size> >= "<global.flag[Bodyguard Limit]>" {
    - random {
      - chat "<yellow>Hi <white><player.name><yellow>, did you lose your bodyguard? We can use our network of agents to track 'em down."
      - chat "<yellow>You can't hire any more guards, but I can track down the missing ones for you."
      - chat "<yellow>I never said these guards were smart. Did you want me to bring them back?" }
    - narrate "<red>Say<&co>"
    - narrate "  <gray>[<green>Yes<gray>] <red>- To teleport <white><player.flag[GuardId].formatted><red> back to you."
    - narrate "  <gray>[<yellow>No<gray>] <red> - To cancel teleport dialogue."
    }

    else if <player.flag[GuardId].size> >= 1 && <player.flag[GuardId].size> < "<global.flag[Bodyguard Limit]>" {
      - random {
        - chat "<yellow>Hi <white><player.name><yellow> are you here to hire another guard or find a missing one?"
        - if "<el@val[<m:<global.flag[Bodyguard Limit]>-<player.flag[GuardId].size>>].asint>" > 1 {
          - chat "<yellow>You can still hire <gold><el@val[<m:<global.flag[Bodyguard Limit]>-<player.flag[GuardId].size>>].asint><yellow> guards or do you want me to find a lost guard for you?" }

          else {
            - chat "<yellow>Hi <white><player.name><yellow>, do you want to hire another guard or track down a missing one?" }

        - chat "<yellow>You've got a couple of options <white><player.name><yellow>, either hire another guard or I can track down your other ones and teleport them back."
        }
      - narrate "<red>Say<&co>"
      - narrate "  <gray>[<white><global.flag[Bodyguard One Name]><gray>]  - Low Level - <gold><global.flag[Bodyguard One Price]> <player.money.currency>"
      - narrate "  <gray>[<yellow><global.flag[Bodyguard Two Name]><gray>]   - Mid Level  - <gold><global.flag[Bodyguard Two Price]> <player.money.currency>"
      - narrate "  <gray>[<blue><global.flag[Bodyguard Three Name]><gray>] - High Level - <gold><global.flag[Bodyguard Three Price]> <player.money.currency>"
      - if "<global.flag[SentryHorseMountAllow]>" == "Allow" narrate "  <gray>[<dark_purple><global.flag[Bodyguard Four Name]><gray>] - Ultra Level - <gold><global.flag[Bodyguard Four Price]> <player.money.currency>"
      - narrate "  <gray>[<green>Find<gray>]<red> to teleport <white><player.flag[GuardId].formatted><red> back to you."
    }

    else {
      - random {
        - chat "<yellow>These men will protect you..for a price."
        - chat "<yellow>The more coin you have, the better protection you can buy."
        - chat "<yellow>You have the following guards to choose from..."
        - chat "<yellow>What type of help are you looking for?" }
      - narrate "<red>Say<&co>"
      - narrate "  <gray>[<white><global.flag[Bodyguard One Name]><gray>]  - Low Level - <gold><global.flag[Bodyguard One Price]> <player.money.currency>"
      - narrate "  <gray>[<yellow><global.flag[Bodyguard Two Name]><gray>]   - Mid Level  - <gold><global.flag[Bodyguard Two Price]> <player.money.currency>"
      - narrate "  <gray>[<blue><global.flag[Bodyguard Three Name]><gray>] - High Level - <gold><global.flag[Bodyguard Three Price]> <player.money.currency>"
      - if "<global.flag[SentryHorseMountAllow]>" == "Allow" narrate "  <gray>[<dark_purple><global.flag[Bodyguard Four Name]><gray>] - Ultra Level - <gold><global.flag[Bodyguard Four Price]> <player.money.currency>"
    }
  - zap "s@Hire a Bodyguard" step:2


"Create Bodyguard":
  type: task

# You'll notice this task keeps on referencing to a variable called %1%. This value got passed into the task
# when the 'run' command was executed in a section above when the player types in whether they wanted a 'Peon',
# 'Brute' etc. So if the user picked the 'Peon', it will pass the word 'One' as a definition into the task.
# So the %1% is then substituted with the word 'One' - so "Bodyguard %1% Price" becomes "Bodyguard One Price" and
# so on.

  script:
  # Take the money from the player for the relevant guard - remember, %1% will be substituted with One, Two,
  # Three or Four.
  - ^take money "qty:<global.flag[Bodyguard %1% Price]>"

  # Flag the player with how much they paid for the guard and also what Tier the guard is. Both these flags are
  # actually transfered to the Bodyguard as NPC flags and is used when the guard is upgraded to know which tier
  # they can be upgraded to and what the difference is the player needs to pay.
  - ^flag <player> "Bodyguard Price Paid:<global.flag[Bodyguard %1% Price]>"
  - ^flag <player> "Bodyguard Tier:%1%"

  # Give a bit of info on the guard, depending on their tier.
  - ^if %1% == One chat "<yellow>Alright, <white><player.name><yellow>. His life is in your hands. Try not to get him killed too quickly."
    else if %1% == Two chat "<yellow>Alright, <white><player.name><yellow>. <global.flag[Bodyguard Two Name]> is ruthless - but not too smart."
    else if %1% == Three chat "<yellow>Alright, <white><player.name><yellow>. You shouldn<&sq>t be worried about creepers for a while, this <global.flag[Bodyguard %1% Name]> can handle his own..."
    else if %1% == Four chat "<white><player.name><yellow> I present to you the best of the best. The one, the only.. <white><global.flag[Bodyguard %1% Name]><yellow>!"

  # Narrate to the player how much they paid.
  - ^narrate "<red>You pay <npc.name> <gold><global.flag[Bodyguard %1% Price]><red> <player.money.currency>."

  # This part uses some smarts to add an abbreviation of the player's name at the end of the guard name. The
  # problem is that guard names can be different lengths.
  # 1) If you picked 'dynamic' at the top of the script, it will calculate how much space is available in
  #    the guard's name and try to fit in as much of the player's name. It does this by using the "substring" tag
  #    and manipulates it's length based on a small calculation.
  # 2) Else if it's been 'disallowed' just create the NPC with their usual name.
  # 3) If not dynamic or disallowed then it'll be expecting a number between 1-16. This is obviously if you only
  #    ever want the first, say, 3 letters of an owner's name, but then you NEED to make sure the entire name length
  #    doesn't exceed 16 chars.
  - ^if "<global.flag[Player Name Suffix]>" == "dynamic" {
    - execute as_npc "npc create <global.flag[Bodyguard %1% Name]> [<<global.flag[Player Name Suffix Color]>><player.name.substring[1,<el@val[<m:13-<el@<global.flag[Bodyguard %1% Name]>.length>>].asint>]><white>] --speed 1.2 --trait sentry"
    }
    else if "<global.flag[Player Name Suffix]>" == "disallow" {
      - execute as_npc "npc create <global.flag[Bodyguard %1% Name]> --speed 1.2 --trait sentry"
    }
    else {
      - execute as_npc "npc create <global.flag[Bodyguard %1% Name]> [<<global.flag[Player Name Suffix Color]>><player.name.substring[1,<global.flag[Player Name Suffix]>]><white>] --speed 1.2 --trait sentry"
    }

  # This script is commented further below.
  - ^run "Bodyguard Basics" instantly

  # If they picked 'Knight', it will translate to tier 'Four' which is a bodyguard on a horse.
  - ^if %1% == Four execute as_npc "sentry mount"

  # Next set the relevant strength, healrate and armor.
  - ^execute as_npc "sentry strength <global.flag[Bodyguard %1% Strength]>"
  - ^execute as_npc "sentry healrate <global.flag[Bodyguard %1% Healrate]>"
  - ^execute as_npc "sentry armor <global.flag[Bodyguard %1% Armor]>"

  # Equip the NPC with their corresponding armour set at the top of the script.
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Sword]>_SWORD"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_HELMET"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_CHESTPLATE"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_LEGGINGS"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_BOOTS"

"Upgrade Bodyguard":
  type: task

# This task is almost a repeat of the one above. The only difference really being
# that it charges the different between the price from the original to the new Tier.

  script:
  - ^define UpgradeCost "<el@val[<m:<global.flag[Bodyguard %1% Price]>-<npc.flag[Price]>>].asint>"
  - ^take money qty:%UpgradeCost%
  - ^narrate "<red>You pay <npc.name> <gold>%UpgradeCost%<red> <player.money.currency>."
  - ^flag <npc> "Price:<global.flag[Bodyguard %1% Price]>"
  - ^flag <npc> "Tier:%1%"
  - ^if %1% == Two chat "<yellow>Ok boss, I have gone for some training and I'm a <white><global.flag[Bodyguard Two Name]><yellow> now! I can smash things with my head!"
    else if %1% == Three chat "<yellow>Alright, <white><player.name><yellow>. You shouldn<&sq>t be worried about creepers for a while, as a <white><global.flag[Bodyguard %1% Name]><yellow> I can handle my own..."
    else if %1% == Four chat "<yellow>I am <white><global.flag[Bodyguard %1% Name]><yellow>. Here to serve and protect with honor. Long live <white><player.name><yellow>!"

  - ^if "<global.flag[Player Name Suffix]>" == "dynamic" {
    - rename "<global.flag[Bodyguard %1% Name]> [<<global.flag[Player Name Suffix Color]>><player.name.substring[1,<el@val[<m:13-<el@<global.flag[Bodyguard %1% Name]>.length>>].asint>]><white>]"
    }
    else if "<global.flag[Player Name Suffix]>" == "disallow" {
      - rename "<global.flag[Bodyguard %1% Name]>"
    }
    else {
      - rename "<global.flag[Bodyguard %1% Name]> [<<global.flag[Player Name Suffix Color]>><player.name.substring[1,<global.flag[Player Name Suffix]>]><white>]"
    }
  - ^execute as_npc "npc sel <npc.id>"
  - ^if %1% == Four execute as_npc "sentry mount"
  - ^execute as_npc "sentry strength <global.flag[Bodyguard %1% Strength]>"
  - ^execute as_npc "sentry healrate <global.flag[Bodyguard %1% Healrate]>"
  - ^execute as_npc "sentry armor <global.flag[Bodyguard %1% Armor]>"
  - ^execute as_npc "sentry equip none"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Sword]>_SWORD"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_HELMET"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_CHESTPLATE"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_LEGGINGS"
  - ^execute as_npc "sentry equip <global.flag[Bodyguard %1% Appearance]>_BOOTS"
  - ^if <npc.flag[Guarding]> == null execute as_npc "sentry guard"
    else execute as_npc "sentry guard <npc.owner.name>"


"Bodyguard Basics":
  type: task

  script:
  # The point of this script is to combine as many of the commands that are shared between the guards into one script
  # so they don't have to be repeated unnecessarily.
  - ^execute as_npc "npc owner <player.name>"
  - ^execute as_npc "sentry invincible false"
  - ^execute as_npc "sentry respawn -1"
  # Run the script called "Bodyguard Life and Death" in the section below.
  - ^execute as_npc 'npc assign --set "Bodyguard Life and Death"'
  - ^execute as_npc "sentry speed 1.2"
  - ^execute as_npc "sentry guard <player.name>"
  - ^execute as_npc "sentry follow 4"
  - ^flag <player> Guard:Hired

# The following assignment is given to the bodyguard itself and controls the living and dying aspects of it.

'Bodyguard Life and Death':
  type: assignment

  actions:
    on assignment:
    # This assignment only has one trigger and that's so the bodyguard can be instructed to follow the player
    # or stay in one spot.
    - trigger name:click toggle:true
    # Because the player didn't create this bodyguard, we need to tell the flag specifically who it should be
    # setting the flag against. The mercenary initially assigned the owner and now this command will put a
    # flag on the owner that holds the NPC ID for the bodyguard. This is so the mercenary will know which NPC
    # it's supposed to teleport back.
    - flag <npc.owner> GuardId:->:<npc>
    # This sets the flag status of the guard to 'true' initially, because it's guarding the player.
    - flag <npc> Guarding
    # Flag the guard with how much they were purchased for. This is used when calculating the refund percentage.
    - flag <npc> "Price:<npc.owner.flag[Bodyguard Price Paid]>"

    # Flag the guard with their tier, this is necessary to upgrade the guard.
    - flag <npc> "Tier:<npc.owner.flag[Bodyguard Tier]>"

    on click:
    # 1) When a player clicks the bodyguard and they are not the owner, it will tell them who the owner is.
    # 2) If they are the owner, and they are holding any of the foods listed in the 'Bodyguard Food' flag at
    #    the top of the script AND if the guard's health is below 100%, it will take the food and heal the
    #    guard with the corresponding value in the 'Bodyguard Food Heal Amount' global flag.
    # 3) Else if they are the owner and the 'Guarding' flag is set to 'true' (which it is initially) then change it's Sentry
    #    behaviour to guard it's area rather than its owner and display the Sentry's current health.
    # 4) Otherwise, if no criteria is met, run the command to guard the owner (player), update the flag and display the Sentry's current health.
    - ^if <npc.owner> != <player> chat "<yellow>I'm sorry <white><player.name><yellow>, but I work for <white><npc.owner.name><yellow> so I'm not going to take orders from you."

      else if "<global.flag[Bodyguard Food].aslist>" contains <player.item_in_Hand> && <npc.health.percentage> != 100 {
        - narrate "<red>You give <white><npc.name><red> <player.item_in_Hand.material.formatted><red> which heals them <green><global.flag[Bodyguard Food Heal Amount].get[<<global.flag[Bodyguard Food].aslist>.find[<player.item_in_Hand>]>]><red> health points."
        - run "Bodyguard Sound"
        - take <player.item_in_Hand>
        - heal <npc> "<global.flag[Bodyguard Food Heal Amount].get[<<global.flag[Bodyguard Food].aslist>.find[<player.item_in_Hand>]>]>"
        - if "<global.flag[Bodyguard Health]>" == "bar" run "Bodyguard Health Status" instantly
          else narrate "<yellow>NPC Health<&co> <red><npc.health.percentage.asint>%"
      }

      else if <npc.flag[Guarding]> {
        - if <global.flag[Bodyguard Food].size> > 0 && <npc.health.percentage> != 100 {
          - random {
            - chat "<yellow>I'll wait here boss, but do you have any food? I'm injured!"
            - chat "<yellow>I could really go for <<global.flag[Bodyguard Food].random>.material.formatted> now to heal up. I'll wait around here."
            - chat "<yellow>My mom always used to say, '<italic>Nothing like <<global.flag[Bodyguard Food].random>.material.formatted> to heal an aspiring young guard!<reset><yellow>'."
            - chat "<yellow>Urg, I'm bleeding. Have you got some food to help me heal? In the meanwhile, I'll wait around here until you give me new orders."
            - chat "<yellow>Hmm, <<global.flag[Bodyguard Food].random>.material.formatted> will help heal these wounds. I'll guard this spot."
            - chat "<yellow>Have you got <<global.flag[Bodyguard Food].random>.material.formatted> that I can snack on while I wait?"
            - chat "<yellow>Oh man, these wounds. You know, <<global.flag[Bodyguard Food].random>.material.formatted> will help me heal up while I wait for you to return."
            - chat "<yellow>Any food, like <<global.flag[Bodyguard Food].random>.material.formatted> will give me some health. Got any?"
            - chat "<yellow>How about <<global.flag[Bodyguard Food].random>.material.formatted> sandwich with <<global.flag[Bodyguard Food].random>.material.formatted> on top to heal me?"
            - chat "<yellow>My mom always used to make me <<global.flag[Bodyguard Food].random>.material.formatted> kebab. Hmmm, bet that will go well with <<global.flag[Bodyguard Food].random>.material.formatted> to heal these wounds."
            }
          }

          else {           
            - random {
            - chat "<yellow>Oh ok boss, I'll wait back here for you."
            - chat "<yellow>Don't worry about me, I'll stay back here. Please don't forget about me."
            - chat "<yellow>I'll wait around for you..but please don't forget about me."
            - chat "<yellow>You want me to hang back? Ok, no problem."
            - chat "<yellow>Ok, I'll guard this spot."
            - chat "<yellow>I'll stand here and wait until you come get me again."
            }
          }
        - ^execute as_npc "npc sel <npc.id>"
        - ^execute as_npc "sentry guard"
        - ^execute as_npc "sentry spawn"
        - flag <npc> Guarding:!
        - if "<global.flag[Bodyguard Health]>" == "bar" run "Bodyguard Health Status" instantly
          else narrate "<yellow>NPC Health<&co> <red><npc.health.percentage.asint>%" }

      else {
        - random {
          - chat "<yellow>Ok, I'm following you."
          - chat "<yellow>Great <white><player.name><yellow>, I'm right behind you."
          - chat "<yellow>You lead the way boss."
          - chat "<yellow>Watching your back. Let's go."
          - chat "<yellow>Great, let's go for a walk."
          - chat "<yellow>Hope we're going to crush some zombie skulls. Let's move." }
        - ^execute as_npc "npc sel <npc.id>"
        - ^execute as_npc "sentry guard <npc.owner.name>"
        - flag <npc> Guarding
        - if "<global.flag[Bodyguard Health]>" == "bar" run "Bodyguard Health Status" instantly
          else narrate "<yellow>NPC Health<&co> <red><npc.health.percentage.asint>%" }

    on death:
    # When the bodyguard dies, it will send a message to the owner, clears all the flags (so another bodyguard 
    # can be hired) and also removes the NPC from Citizens register.
    - narrate "<red>Your bodyguard, <white><npc.name><red>, has died." targets:<npc.owner>
    - flag <npc.owner> GuardId:<-:<npc>
    - if <global.flag[RemoveHorseMount]> == allow && <npc.get_vehicle> != null remove <npc.get_vehicle>

  interact scripts:
  - 10 Bodyguard

"Bodyguard":
  type: interact

  steps:
    1:
      click trigger:
        script:
        # This will construct a little menu when a player interacts with the guard. Currently there
        # are only two options as 'Inventory' is disabled until Developed by Denizen devs.
        # 1) [Upgrade] the guard to the next tier - show the player how much it's going to cost
        #    by doing a calculation on how much they paid initially and what the cost of the next
        #    tier is.
        # 2) [Fire] the guard. If there is a refund percentage specified in the 'Bodyguard Refund Percentage'
        #    flag it'll show what the refund percentage is.
        #
        # When the guard is right clicked, it will zap the interact step to "2" which includes a chat trigger.
        # So, effectively that guard starts 'listening' for certain keywords from the player. It does this
        # for the time specified in the 'Bodyguard Listen Time' global flag before it zaps back to step:1 
        # which doesn't have a 'chat' trigger.. so it stops listening. The reason for this is so that the guard
        # doesn't continuously intercept chats meant to go to other NPC's or players.
        - if <npc.owner> == <player> {
          - zap step:2
          - narrate "<green>------------------------------------------"
          - narrate "<red>You've got <global.flag[Bodyguard Listen Time]> to say<&co>"
          - if "<global.flag[Bodyguard Inventory]>" != disallow narrate "  <green>[<bold>Inventory<reset><green>]<white>  - Not Enabled Yet"
          - if <npc.flag[Tier]> == One {
            - define UpgradeCost "<el@val[<m:<global.flag[Bodyguard Two Price]>-<npc.flag[Price]>>].asint>"
            - narrate "  <blue>[<bold>Upgrade<reset><blue>]<white>    - Upgrade guard to <yellow>Tier 2<white> for <gold>%UpgradeCost%<white> <player.money.currency>" }

            else if <npc.flag[Tier]> == Two {
            - define UpgradeCost "<el@val[<m:<global.flag[Bodyguard Three Price]>-<npc.flag[Price]>>].asint>"
            - narrate "  <blue>[<bold>Upgrade<reset><blue>]<white>    - Upgrade guard to <blue>Tier 3<white> for <gold>%UpgradeCost%<white> <player.money.currency>" }

            else if <npc.flag[Tier]> == Three {
            - define UpgradeCost "<el@val[<m:<global.flag[Bodyguard Four Price]>-<npc.flag[Price]>>].asint>"
            - narrate "  <blue>[<bold>Upgrade<reset><blue>]<white>    - Upgrade guard to <dark_purple>Tier 4<white> for <gold>%UpgradeCost%<white> <player.money.currency>" }

          - if "<global.flag[Bodyguard Refund Percentage]>" > 0 narrate "  <red>[<bold>Fire<reset><red>]<white>          - Fire your guard and get a <gold><global.flag[Bodyguard Refund Percentage]>%<white> refund."
            else narrate "  <red>[<bold>Fire<reset><red>]<white>          - Fire your guard and get no refund."
          - narrate "<green>------------------------------------------"
          - wait "<global.flag[Bodyguard Listen Time]>"
          - zap step:1
          }

    2:
      chat trigger:
        'Inventory':
          trigger: "/inventory/"

          script:
          - if <global.flag[Bodyguard Inventory]> != disallow narrate "<red>Feature not enabled yet."

        'Upgrade':
          trigger: "/upgrade/"

          script:
          # When the player looks at the guard and types in 'upgrade' it will check the current tier and if they've
          # got enough money before running the upgrade task.
          - if <npc.flag[Tier]> == One && <player.money> >= "<el@val[<m:<global.flag[Bodyguard Two Price]>-<npc.flag[Price]>>].asint>" run "Upgrade Bodyguard" def:Two instantly
            else if <npc.flag[Tier]> == Two && <player.money> >= "<el@val[<m:<global.flag[Bodyguard Three Price]>-<npc.flag[Price]>>].asint>" run "Upgrade Bodyguard" def:Three instantly
            else if <npc.flag[Tier]> == Three && <player.money> >= "<el@val[<m:<global.flag[Bodyguard Four Price]>-<npc.flag[Price]>>].asint>" run "Upgrade Bodyguard" def:Four instantly

            else if <npc.flag[Tier]> == One && <player.money> < "<el@val[<m:<global.flag[Bodyguard Two Price]>-<npc.flag[Price]>>].asint>"
            narrate "<red>You need an additional <gold><el@val[<m:<m:<global.flag[Bodyguard Two Price]>-<npc.flag[Price]>>-<player.money>>].asint><red> <player.money.currency> to afford this upgrade."

            else if <npc.flag[Tier]> == Two && <player.money> < "<el@val[<m:<global.flag[Bodyguard Three Price]>-<npc.flag[Price]>>].asint>"
            narrate "<red>You need an additional <gold><el@val[<m:<m:<global.flag[Bodyguard Three Price]>-<npc.flag[Price]>>-<player.money>>].asint><red> <player.money.currency> to afford this upgrade."

            else if <npc.flag[Tier]> == Three && <player.money> < "<el@val[<m:<global.flag[Bodyguard Four Price]>-<npc.flag[Price]>>].asint>"
            narrate "<red>You need an additional <gold><el@val[<m:<m:<global.flag[Bodyguard Four Price]>-<npc.flag[Price]>>-<player.money>>].asint><red> <player.money.currency> to afford this upgrade."

            else narrate "<red>This guard can not be upgraded any further."

        'Fire Guard':
          trigger: "/fire/"

          # When the player triggers this, it will first check to see if the player is the owner. Then
          # check if the 'Bodyguard Refund Percentage' is larger than 0, if so it'll do a basic calculation depending
          # on how much the guard was purchased for and then give the player a specified percentage of their
          # money back.

          script:
          - if <npc.owner> != <player> narrate "<red>This guard belongs to <white><npc.owner.name><red>, you cannot fire it."
          - ^if <npc.owner> == <player> {
            - if "<global.flag[Bodyguard Refund Percentage]>" > 0
              {
              - define percentage "<m:<global.flag[Bodyguard Refund Percentage]>/100>"
              - define totalrefund <el@val[<m:<npc.flag[Price]>*%percentage%>].asint>
              - narrate "<red>Your guard, <white><npc.name><red>, has been removed and you<&sq>ve been refunded <gold>%totalrefund%<red> <player.money.currency>."
              - give money qty:%totalrefund%
              }
            - flag <npc.owner> GuardId:<-:<npc>
            - if <global.flag[RemoveHorseMount]> == allow && <npc.get_vehicle> != null remove <npc.get_vehicle>
            - remove <npc>
            }

"Bodyguard Sound":
  type: task

# This sound plays when the guard has been given food.

  script:
  - playsound sound:eat location:<npc.location>
  - playsound sound:eat location:<npc.location>
  - playsound sound:eat location:<npc.location>

#-------------------------------------------------------------------------------#
# The following script builds up a health bar for the NPC. It does
# this by dividing their current health by 10, the result of that, say 7.2 is
# then rounded down to 7. It then repeats a loop 7 times, each time adding
# 10 "|" characters into a flag. So 7 x ||||||||||.. the remaining 2 (7.2)
# then just gets added onto that, e.g. ||
#
# The reason I did it this way was so that it didn't repeat the loop 70 times to
# build up the number of health bars.
#
# In the example, 72 bars will be <GREEN> and the remaining 28 bars will be
# <RED>.
#
# This can be used with any NPC regardless of how much health they have 
# because it uses their "percentage" of health rather than max value health.
#-------------------------------------------------------------------------------#

"Bodyguard Health Status":
  type: task
  script:
  - ^if <npc.health.percentage> == 100
    narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green>||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||<white>]"

    else {
      - ^define GreenTenCount <el@val[<m:floor(<npc.health.percentage>/10)>].asint>
      - ^define GreenTenTotal <el@val[<m:%GreenTenCount%*10>].asint>
      - ^define GreenOneCount <el@val[<m:<npc.health.percentage>-%GreenTenTotal%>].asint>

      - ^define RedTenCount <el@val[<m:floor(<m:100-<npc.health.percentage>>/10)>].asint>
      - ^define RedTenTotal <el@val[<m:%RedTenCount%*10>].asint>
      - ^define RedOneCount <el@val[<m:<m:100-<npc.health.percentage>>-%RedTenTotal%>].asint>

      - ^repeat %GreenTenCount% {
        - flag <npc> "GreenBars:<npc.flag[GreenBars].replace[null]>||||||||||" }

      - ^repeat %GreenOneCount% {
        - flag <npc> "GreenBars:<npc.flag[GreenBars].replace[null]>|" }

      - ^repeat %RedTenCount% {
        - flag <npc> "RedBars:<npc.flag[RedBars].replace[null]>||||||||||" }

      - ^repeat %RedOneCount% {
        - flag <npc> "RedBars:<npc.flag[RedBars].replace[null]>|" }

      - ^if <npc.flag[RedBars]> == null narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green><npc.flag[GreenBars]><white>]"
        else narrate "<red><npc.name.substring[1,12]> Health<&co><white> [<green><npc.flag[GreenBars]><red><npc.flag[RedBars].replace[null]><white>]"
      - ^flag <npc> GreenBars:!
      - ^flag <npc> RedBars:!
    }