Initial commit

This commit is contained in:
Rares Bozga
2025-11-29 22:53:32 +02:00
parent e9fa13dbd3
commit 461e95114c
157 changed files with 7597 additions and 1 deletions

BIN
scripts/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,80 @@
animations_command_animationmode:
debug: false
type: command
name: animationmode
description: Animate your hands in a certain direction.
usage: /animationmode
aliases:
- am
permission: animations.command.animationmode
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.item_in_hand.material.name> != air:
- narrate "<&c>You must run this command with an empty hand."
- stop
- define arrow <item[arrow]>
- adjust def:arrow custom_model_data:1
- adjust def:arrow display:<&f>
- flag <[arrow]> animations:true
- if !<player.inventory.can_fit[<[arrow]>]>:
- narrate "<&c>Your inventory is too full. You must have one empty slot in your inventory!"
- stop
- define bow <item[bow]>
- adjust def:bow "display:<&f>Hold right-click to Animate"
- adjust def:bow custom_model_data:1
- flag <[bow]> animations:true
- inventory set slot:hand origin:<[bow]>
- give <[arrow]>
- narrate format:formats_prefix "Hold right-click to animate your hands!"
animations_command_raisehand:
debug: false
type: command
name: raisehand
description: Animate your hand so it looks like you're raising it.
usage: /raisehand
aliases:
- rh
permission: animations.command.raisehand
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.item_in_hand.material.name> != air:
- narrate "<&c>You must run this command with an empty hand."
- stop
- define trident <item[trident]>
- adjust def:trident custom_model_data:1
- adjust def:trident "display:<&f>Hold right-click to Raise Hand"
- flag <[trident]> animations:true
- inventory set slot:hand origin:<[trident]>
- narrate format:formats_prefix "Hold right-click to raise your hand!"
animations_command_handshake:
debug: false
type: command
name: handshake
description: Animate your hand so it looks like you're handshaking.
usage: /handshake
permission: animations.command.handshake
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.item_in_hand.material.name> != air:
- narrate "<&c>You must run this command with an empty hand."
- stop
- define shield <item[shield]>
- adjust def:shield custom_model_data:1
- adjust def:shield "display:<&f>Hold right-click to Handshake"
- flag <[shield]> animations:true
- inventory set slot:hand origin:<[shield]>
- narrate format:formats_prefix "Hold right-click to handshake!"

View File

@@ -0,0 +1,34 @@
animations_world:
debug: false
type: world
events:
# common
on player joins:
- foreach <player.inventory.map_slots> key:slot as:item:
- if <[item].has_flag[animations]>:
- inventory set slot:<[slot]> origin:air
on player scrolls their hotbar:
- if <player.item_in_hand.has_flag[animations]>:
- take flagged:animations quantity:255
on player clicks item in inventory:
- if <context.item.has_flag[animations]>:
- determine cancelled passively
- inventory set slot:hand origin:air
- inventory update
on player drops item:
- if <context.item.has_flag[animations]>:
- remove <context.entity>
# animationmode
on player shoots bow:
- if <context.bow.has_flag[animations]>:
- determine cancelled passively
- take flagged:animations quantity:255
# raisehand
on trident launched:
- if <context.entity.item.has_flag[animations]>:
- determine cancelled passively
- take flagged:animations quantity:255 player:<context.entity.shooter>
# shield
on player lowers item:
- if <context.item.has_flag[animations]>:
- take flagged:animations quantity:255

View File

@@ -0,0 +1,57 @@
announcers_command_intercom:
debug: false
type: command
name: intercom
description: Broadcast a message through the intercom.
usage: /intercom (message)
permission: announcers.command.intercom
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- define message <context.args.space_separated>
- announce "<&6>[<&c><&l>INTERCOM<&6>] <&7><&o>(<player.name>) <&f><proc[character_get_name].context[<player>]> says <&dq><[message]><&dq>"
announcers_command_collegeintercom:
debug: false
type: command
name: collegeintercom
description: Broadcast a message through the college intercom.
usage: /collegeintercom (message)
permission: announcers.command.collegeintercom
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- define message <context.args.space_separated>
- define recipients <server.online_players.filter_tag[<[filter_value].has_permission[announcers.see.collegeintercom]>]>
- narrate targets:<[recipients]> "<&6>[<&c><&l>COLLEGE INTERCOM<&6>] <&7><&o>(<player.name>) <&f><proc[character_get_name].context[<player>]> says <&dq><[message]><&dq>"
announcers_command_advert:
debug: false
type: command
name: advert
description: Broadcast a message for your shop.
usage: /advert (message)
permission: announcers.command.advert
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- define message <context.args.space_separated>
- announce "<&6>[<&2>Advert<&6>]<&f>: <&7><&o>(<player.name>) <&f><proc[character_get_name].context[<player>]> - <[message]>"

View File

@@ -0,0 +1,147 @@
apartments_command_apartmentaddmember:
debug: false
type: command
name: apartmentaddmember
description: Add a member to the apartment you are currently in.
usage: /apartmentaddmember (player)
aliases:
- aptaddmember
- aptam
permission: apartments.command.apartmentaddmember
tab completions:
1: <server.online_players.parse[name]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define apartment <proc[apartments_at].context[<player.location>]>
- if <[apartment]> == null:
- narrate "<&c>You can only use this command inside apartments."
- stop
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <player> != <[owner]>:
- narrate "<&c>You do not own this apartment!"
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Invalid use. Please try /<context.alias> (player)"
- stop
- define target <server.match_offline_player[<context.args.get[1]>].if_null[null]>
- if <[target]> == null:
- narrate "<&c>A player with the username <context.args.get[1]> could not be found."
- stop
- if <[target]> == <player>:
- narrate "<&c>You cannot add yourself as a member!"
- stop
- run apartments_add_member def.apartment:<[apartment]> def.member:<[target]>
- narrate format:formats_prefix "<&a>Added <&7><[target].name> to your apartment (<&b>member<&7>)."
apartments_command_apartmentaddmoderator:
debug: false
type: command
name: apartmentaddmoderator
description: Adds a moderator to the apartment you are currently in.
usage: /apartmentaddmoderator (player)
aliases:
- aptaddmod
permission: apartments.command.apartmentaddmod
tab completions:
1: <server.online_players.parse[name]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define apartment <proc[apartments_at].context[<player.location>]>
- if <[apartment]> == null:
- narrate "<&c>You can only use this command inside apartments."
- stop
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <player> != <[owner]>:
- narrate "<&c>You do not own this apartment!"
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Invalid use. Please try /<context.alias> (player)"
- stop
- define target <server.match_offline_player[<context.args.get[1]>].if_null[null]>
- if <[target]> == null:
- narrate "<&c>A player with the username <context.args.get[1]> could not be found."
- stop
- if <[target]> == <player>:
- narrate "<&c>You cannot add yourself as a moderator!"
- stop
- run apartments_add_moderator def.apartment:<[apartment]> def.moderator:<[target]>
- narrate format:formats_prefix "<&a>Added <&7><[target].name> to your apartment (<&6>moderator<&7>)."
apartments_command_apartmentremoveaccess:
debug: false
type: command
name: apartmentremoveaccess
description: Removes all access for a player from the apartment you are currently in.
usage: /apartmentremoveaccess (player)
aliases:
- aptremoveaccess
- aptrm
permission: apartments.command.apartmentremoveaccess
tab completions:
# TODO: use the procedural tab-complete to handle this correctly!
1: <server.online_players.parse[name]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define apartment <proc[apartments_at].context[<player.location>]>
- if <[apartment]> == null:
- narrate "<&c>You can only use this command inside apartments."
- stop
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <player> != <[owner]>:
- narrate "<&c>You do not own this apartment!"
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Invalid use. Please try /<context.alias> (player)"
- stop
- define target <server.match_offline_player[<context.args.get[1]>].if_null[null]>
- if <[target]> == null:
- narrate "<&c>A player with the username <context.args.get[1]> could not be found."
- stop
- if <[target]> == <player>:
- narrate "<&c>You cannot remove your own access!"
- stop
- if <[target].location.in_region[<[apartment].id>]>:
- run apartments_end_edit def.player:<[target]>
- run apartments_remove_access def.apartment:<[apartment]> def.member:<[target]>
- narrate format:formats_prefix "<&c>Removed <&7>member <[target].name> from your apartment."
apartments_command_apartmenteditmode:
debug: false
type: command
name: apartmenteditmode
description: Toggle edit mode for the apartment you are currently in.
usage: /apartmenteditmode
aliases:
- apteditmode
- editmode
permission: apartments.command.apartmenteditmode
tab completions:
1: <server.online_players.parse[name]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
# toggle off
- if <player.has_flag[apartments_edit]>:
- run apartments_end_edit def.player:<player>
- narrate format:formats_prefix "<&e>Exiting <&6>Edit Mode..."
- stop
# toggle on
- define apartment <proc[apartments_at].context[<player.location>]>
- if <[apartment]> == null:
- narrate "<&c>You can only use this command inside apartments."
- stop
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <player> != <[owner]>:
- define access_level <proc[apartments_access_level].context[<player>|<player.location>]>
- if <[access_level]> != moderator:
- narrate "<&c>You must own this apartment or be an apartment moderator to enable editing here!"
- stop
- run apartments_begin_edit def.apartment:<[apartment]> def.player:<player>
- narrate format:formats_prefix "<&a>Entering <&6>Edit Mode..."

View File

@@ -0,0 +1,111 @@
apartments_at:
debug: false
type: procedure
definitions: location
script:
- determine <[location].regions.filter_tag[<[filter_value].id.starts_with[apt-]>].get[1].if_null[null]>
apartments_owner:
debug: false
type: procedure
definitions: apartment
script:
- determine <[apartment].owners.get[1].if_null[null]>
apartments_access:
debug: false
type: procedure
definitions: player|location
script:
- define apartment <proc[apartments_at].context[<[location]>]>
- if <[apartment]> == null:
- determine true
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <[owner]> == null:
- determine false
- if <[owner]> == <[player]>:
- determine true
- define access <[owner].flag[apartments_access].get[<[apartment]>].get[<[player]>].if_null[null]>
- if <[access]> == null:
- determine false
- determine true
apartments_access_level:
debug: false
type: procedure
definitions: player|location
script:
- define apartment <proc[apartments_at].context[<[location]>]>
- if <[apartment]> == null:
- determine null
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <[owner]> == null:
- determine none
- if <[owner]> == <[player]>:
- determine owner
- define access <[owner].flag[apartments_access].get[<[apartment]>].get[<[player]>].if_null[null]>
- if <[access]> == null:
- determine none
- determine <[access]>
apartments_add_member:
debug: false
type: task
definitions: apartment|member
script:
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <[owner]> == null:
- stop
- define access_all <[owner].flag[apartments_access].get[<[apartment]>].if_null[<map[]>].with[<[member]>].as[member]>
- flag <[owner]> apartments_access:<[owner].flag[apartments_access].if_null[<map[]>].with[<[apartment]>].as[<[access_all]>]>
- execute as_server "as addfriend <[member].name> <[apartment].id>"
apartments_add_moderator:
debug: false
type: task
definitions: apartment|moderator
script:
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <[owner]> == null:
- stop
- execute as_server "rg addmember <[apartment].id> <[moderator].name> -w <[apartment].world.name>"
- define access_all <[owner].flag[apartments_access].get[<[apartment]>].if_null[<map[]>].with[<[moderator]>].as[moderator]>
- flag <[owner]> apartments_access:<[owner].flag[apartments_access].if_null[<map[]>].with[<[apartment]>].as[<[access_all]>]>
- execute as_server "as addfriend <[moderator].name> <[apartment].id>"
apartments_remove_access:
debug: false
type: task
definitions: apartment|member
script:
- define owner <proc[apartments_owner].context[<[apartment]>]>
- if <[owner]> == null:
- stop
- execute as_server "rg removemember <[apartment].id> <[member].name> -w <[apartment].world.name>"
- define access_all <[owner].flag[apartments_access].get[<[apartment]>].if_null[<map[]>].exclude[<[member]>]>
- flag <[owner]> apartments_access:<[owner].flag[apartments_access].if_null[<map[]>].with[<[apartment]>].as[<[access_all]>]>
- execute as_server "as delfriend <[member].name> <[apartment].id>"
apartments_begin_edit:
debug: false
type: task
definitions: apartment|player
script:
- definemap apartments_edit_data:
apartment: <[apartment]>
inventory: <[player].inventory.map_slots>
- flag <[player]> apartments_edit:<[apartments_edit_data]>
- inventory clear player:<[player]>
- adjust <[player]> gamemode:creative
apartments_end_edit:
debug: false
type: task
definitions: player
script:
- define apartments_edit_data <[player].flag[apartments_edit]>
- inventory clear player:<[player]>
- foreach <[apartments_edit_data].get[inventory]> key:slot as:item:
- inventory set origin:<[item]> slot:<[slot]> player:<[player]>
- adjust <[player]> gamemode:survival
- flag <[player]> apartments_edit:!

View File

@@ -0,0 +1,156 @@
apartments_world:
debug: false
type: world
events:
## session safety
on player joins:
- if <player.has_flag[apartments_edit]>:
- run apartments_end_edit def.player:<player>
## extra details
on delta time secondly every:2:
- actionbar "<&6>Editing apartment <&7>[<player.flag[apartments_edit].get[apartment].id>]" targets:<server.players_flagged[apartments_edit]> per_player
## invalid access
on player right clicks block:
- if <player.is_op>:
- stop
- if <context.location.if_null[null]> == null:
- stop
- if !<proc[apartments_access].context[<player>|<context.location>]>:
- determine cancelled
##
## complex creative safety cases
##
# do not allow leaving actual apartment region
on player walks:
- if !<player.has_flag[apartments_edit]>:
- stop
- define apartment <player.flag[apartments_edit].get[apartment]>
- if !<context.new_location.in_region[<[apartment].id>]>:
- determine cancelled
# forbid trying to touch non-blocks in creative inventory
on player clicks item in inventory:
- if !<player.has_flag[apartments_edit]>:
- stop
- if <context.click> != CREATIVE:
- determine cancelled
- if <player.open_inventory.inventory_type.if_null[CRAFTING]> != CRAFTING:
- determine cancelled
- if <context.item.material.is_block> && <context.cursor_item.material.is_block>:
- stop
- determine cancelled passively
- wait 1t
- inventory update destination:<player.inventory>
- adjust <player> item_on_cursor:<item[air]>
# handle container drops & illegal block breaks
on player breaks block bukkit_priority:monitor:
- if <player.is_op>:
- stop
# // careful: == null here; everywhere else it's != null
- if <proc[apartments_at].context[<context.location>]> == null:
- stop
- if <context.location.has_inventory>:
- if <player.gamemode> == creative:
- if <context.location.inventory.map_slots.size> > 0:
- narrate "<&c>This container has items inside. You must clear it first before you can break it."
- determine cancelled
- ratelimit <player> 1t
- define contents <context.location.inventory.map_slots.values>
- if <[contents].is_empty>:
- stop
- define half <context.location.material.half.if_null[null]>
- if <[half]> == right:
- define contents <[contents].get[1].to[27]>
- else if <[half]> == left:
- define contents <[contents].get[28].to[54]>
- foreach <[contents]> as:item:
- drop <[item]> <context.location> delay:10t
# forbid block update and physics inside apartments
on block physics:
- if <context.location.material.half.if_null[null]> != null:
- stop
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled passively
- foreach <context.location.find_entities[dropped_item].within[1]> as:entity:
- remove <[entity]>
# forbid block update and physics for half blocks
on player breaks block:
# // careful: == null here; everywhere else it's != null
- if <proc[apartments_at].context[<context.location>]> == null:
- stop
- define half <context.location.material.half.if_null[null]>
- if <[half]> != null && !<context.location.material.advanced_matches[*trapdoor|*stairs]>:
- if <context.new_material.name.if_null[air]> == air:
- if <[half]> != left && <[half]> != right:
- modifyblock <context.location.add[<context.location.material.relative_vector>]> air no_physics
# forbid blocks that have NBT data - such as prefilled chests
on player places block:
# // careful: == null here; everywhere else it's != null
- if <proc[apartments_at].context[<context.location>]> == null:
- stop
- if <player.is_op>:
- stop
- if <context.item_in_hand.material.advanced_matches[*banner]>:
- stop
- if <context.item_in_hand.all_raw_nbt.exclude[display].exclude[SkullOwner].filter_tag[<[filter_value].size.is_more_than[0]>].size.if_null[0]> > 0:
- determine cancelled
##
## simple creative safety cases
##
# forbid picking up and dropping items
on player drops item:
- if <player.is_op>:
- stop
- if <player.has_flag[apartments_edit]>:
- determine cancelled
on player picks up item:
- if <player.is_op>:
- stop
- if <player.has_flag[apartments_edit]>:
- determine cancelled
# forbid water flow in apartment regions
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# forbid sapling/other growing things in apartment regions
on structure grows:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
on plant grows:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# forbid any items dropping even if broken in apartment regions
on block drops item from breaking:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# forbid any tnt in apartment regions
on tnt primes:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# forbid gravity on blocks inside apartments
on block falls:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# forbid shulker box usage inside apartments
on player places *shulker_box:
- if <proc[apartments_at].context[<context.location>]> != null:
- if !<player.is_op>:
- determine cancelled
# forbid mob spawner usage inside apartments
on player places *spawner:
- if <player.is_op>:
- stop
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled
# prevent lectern grab
on player takes item from lectern:
- if <player.is_op>:
- stop
- if !<proc[apartments_access].context[<player>|<context.location>]>:
- determine cancelled
# prevent redstone in apartments
after redstone recalculated:
- if <proc[apartments_at].context[<context.location>]> != null:
- adjustblock <context.location> power:0 no_physics
# prevent piston use in apartments
on piston extends:
- if <proc[apartments_at].context[<context.location>]> != null:
- determine cancelled

View File

@@ -0,0 +1,12 @@
automoney_world:
debug: false
type: world
events:
on delta time minutely every:1:
- foreach <server.online_players> as:player:
- define last_payment <[player].flag[automoney_last].if_null[<time[2000/01/01_12:00:00:00]>]>
- define time_passed <util.time_now.duration_since[<[last_payment]>]>
- if <[time_passed].is_more_than[<duration[30m]>]>:
- flag <[player]> automoney_last:<util.time_now>
- money give players:<[player]> quantity:500
- narrate format:formats_prefix targets:<[player]> "Thanks for being online! You have received ¥500."

View File

@@ -0,0 +1,66 @@
carry_command_carry:
debug: false
type: command
name: carry
description: Carry another player on your shoulders!
usage: /carry [who?]
permission: carry.command.carry
tab completions:
1: <player.location.find_players_within[5].exclude[<player>].parse[name]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if !<player.is_empty>:
- narrate "<&c>You're already carrying someone!"
- stop
- define target <player.target[player].within[5].if_null[null]>
- if <[target]> == null:
- define target <server.match_player[<context.args.get[1]>].if_null[null]>
- if <[target]> == null:
- narrate "<&c>Please look at the player to carry or specify their username."
- stop
- else:
- if <[target].location.distance[<player>]> > 5:
- narrate "<&c>That player is too far away!"
- stop
- if <[target].is_npc>:
- narrate "<&c>Please look at the player to carry or specify their username."
- stop
- if <[target]> == <player>:
- narrate "<&c>You cannot carry yourself!"
- stop
- if <[target].is_inside_vehicle>:
- narrate "<&c>This player is already being carried!"
- stop
- define player <player>
- clickable usages:1 until:10s save:carry:
- if !<player.is_empty>:
- narrate "<&c>That player is already carrying someone!"
- stop
- if <[target].is_inside_vehicle>:
- narrate targets:<[target]> "<&c>You're already being carried!"
- stop
- adjust <[player]> passengers:<[player].passengers.include[<[target]>]>
- narrate format:formats_prefix "Sent a carry request to <&e><proc[character_get_name].context[<[target]>]>"
#
- narrate format:formats_prefix targets:<[target]> "<&e><proc[character_get_name].context[<player>]> <&7> would like to carry you."
- narrate targets:<[target]> "<element[<&a><&l>[ACCEPT]].on_click[<entry[carry].command>]>"
carry_command_uncarry:
debug: false
type: command
name: uncarry
description: Stop carrying someone.
usage: /uncarry
permission: carry.command.uncarry
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.is_empty>:
- narrate "<&c>You're not carrying anyone!"
- stop
- adjust <player> passengers:<list[]>

View File

@@ -0,0 +1,102 @@
character_command_rpname:
debug: false
type: command
name: rpname
description: Sets your roleplay name.
usage: /rpname (name)
permission: character.command.rpname
tab completions:
1: <&lt>name<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a RP name!"
- stop
- define name <context.args.space_separated.parse_color.strip_color>
- if <[name].length> > 24:
- narrate "<&c>Your RP name must not be longer than 24 characters."
- stop
- if !<[name].regex_matches[^[a-zA-Z0-9\-. <&sq>]+$]>:
- narrate "<&c>Your RP name must only contain alphanumeric characters, spaces, dots, dashes, and single quotes."
- stop
- define used_already <server.flag[character_rpnames].get[<[name]>].if_null[null]>
- if <[used_already]> != null:
- if <[used_already]> != <player.uuid>:
- narrate "<&c>This RP name is already taken!"
- stop
- define new_rpnames <server.flag[character_rpnames].if_null[<map[]>]>
- if <player.has_flag[character_rpname]>:
- define new_rpnames <[new_rpnames].exclude[<player.flag[character_rpname]>]>
- define new_rpnames <[new_rpnames].with[<[name]>].as[<player.uuid>]>
- flag <player> character_rpname:<[name]>
- flag server character_rpnames:<[new_rpnames]>
- narrate format:formats_prefix "Set your RP Name to <&e><[name]><&7>."
character_command_setdescription:
debug: false
type: command
name: setdescription
aliases:
- setdesc
description: Sets your roleplay description.
usage: /setdescription (description)
permission: character.command.setdescription
tab completions:
1: <&lt>description<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a description!"
- stop
- define description <context.args.space_separated.parse_color.strip_color>
- flag <player> character_description:<[description]>
- narrate format:formats_prefix "Changed your description! View it with /viewdescription."
character_command_viewdescription:
debug: false
type: command
name: viewdescription
aliases:
- viewdesc
description: Sets your roleplay description.
usage: /viewdescription
permission: character.command.viewdescription
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define name <proc[character_get_name].context[<player>]>
- define description <proc[character_get_description].context[<player>]>
- narrate format:formats_prefix "<&e><player.name> <&7>Character Info"
- narrate "<&7>Your name<&c>: <&f><[name]>"
- narrate "<&7>Your description<&c>: <&f><[description]>"
character_command_findname:
debug: false
type: command
name: findname
aliases:
- fn
description: Find name of player based on RP name.
usage: /findname (rpname)
permission: character.command.findname
tab completions:
1: <&lt>rpname<&gt>
script:
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a RP name!"
- stop
- define query <context.args.space_separated.parse_color.strip_color>
- define found_player <server.flag[character_rpnames].if_null[<map[]>].get[<[query]>].if_null[null]>
- if <[found_player]> == null:
- narrate format:formats_prefix "No player with this RP name could be found."
- stop
- else:
- define found_player <player[<[found_player]>]>
- narrate format:formats_prefix "The actual name of <[query]> is <&e><[found_player].name>"

View File

@@ -0,0 +1,13 @@
character_get_name:
debug: false
type: procedure
definitions: player
script:
- determine <[player].flag[character_rpname].if_null[<[player].name>]>
character_get_description:
debug: false
type: procedure
definitions: player
script:
- determine <[player].flag[character_description].if_null[No<&sp>description<&sp>set.]>

View File

@@ -0,0 +1,15 @@
character_world:
debug: false
type: world
events:
on player right clicks player:
- define target <context.entity>
- if <[target].is_npc>:
- stop
- determine cancelled passively
- ratelimit <player> 1s
- define name <proc[character_get_name].context[<[target]>]>
- define description <proc[character_get_description].context[<[target]>]>
- narrate format:formats_prefix "<&e><[target].name> <&7>Character Info"
- narrate "<&7>Name<&c>: <&f><[name]>"
- narrate "<&7>Description<&c>: <&f><[description]>"

View File

@@ -0,0 +1,418 @@
chat_command_ooc:
debug: false
type: command
name: ooc
usage: /ooc (message)
description: Sends a message in global OOC.
permission: chat.command.chat.ooc
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- if !<player.has_flag[chat_disableooc]>:
- if <player.flag[chat_channel].if_null[ic]> == ooc:
- narrate "<&c>You are currently switched to OOC chat, so you cannot disable it."
- stop
- flag <player> chat_disableooc:true
- narrate format:formats_prefix "Disabled OOC chat."
- else:
- flag <player> chat_disableooc:!
- narrate format:formats_prefix "Enabled OOC chat."
- stop
- else if <player.has_flag[chat_disableooc]>:
- narrate "<&c>You cannot use OOC chat while it is disabled. Please enable it first."
- stop
- run chat_channel_ooc def.player:<player> def.message:<context.raw_args.escaped.replace[&].with[&\]>
chat_command_looc:
debug: false
type: command
name: looc
usage: /looc (message)
description: Sends a message in local LOOC.
permission: chat.command.chat.looc
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_looc def.player:<player> def.message:<context.raw_args.escaped.replace[&].with[&\]>
chat_command_me:
debug: false
type: command
name: me
usage: /me (message)
description: Sends a message in IC, 1st person action.
permission: chat.command.chat.me
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_me def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_meclose:
debug: false
type: command
name: meclose
usage: /meclose (message)
aliases:
- mec
description: Sends a message in IC, 1st person action, close range.
permission: chat.command.chat.mec
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_mec def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_melong:
debug: false
type: command
name: melong
usage: /melong (message)
aliases:
- mel
description: Sends a message in IC, 1st person action, long range.
permission: chat.command.chat.mel
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_mel def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_whisper:
debug: false
type: command
name: whisper
usage: /whisper (message)
aliases:
- w
description: Sends a message in IC, whispering.
permission: chat.command.chat.whisper
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_whisper def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_yell:
debug: false
type: command
name: yell
usage: /yell (message)
aliases:
- y
description: Sends a message in IC, yelling.
permission: chat.command.chat.yell
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_yell def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_my:
debug: false
type: command
name: my
usage: /my (message)
description: Sends a message in IC, 1st person possessive.
permission: chat.command.chat.my
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_my def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_it:
debug: false
type: command
name: it
usage: /it (message)
description: Sends a message in IC, 3rd person action.
permission: chat.command.chat.it
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_it def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_itclose:
debug: false
type: command
name: itclose
usage: /itclose (message)
aliases:
- itc
description: Sends a message in IC, 3rd person action, close range.
permission: chat.command.chat.itc
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_itc def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_itl:
debug: false
type: command
name: itlong
usage: /itlong (message)
aliases:
- itl
description: Sends a message in IC, 3rd person action, long range.
permission: chat.command.chat.itl
tab completions:
1: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter a message!"
- stop
- run chat_channel_ic_itl def.player:<player> def.message:<context.raw_args.parse_color.escaped.replace[&].with[&\]>
chat_command_languageadd:
debug: false
type: command
name: languageadd
usage: /languageadd (player) (language)
aliases:
- langadd
description: Allows a user to speak a new language.
permission: chat.command.admin.languageadd
tab completions:
1: <server.online_players.parse[name]>
2: <script[chat_data_languages].data_key[known]>
script:
- if <context.args.size> < 2:
- narrate "<&c>Invalid use. Please try /<context.alias> (player) (language)."
- stop
- define player <server.match_offline_player[<context.args.get[1]>].if_null[null]>
- if <[player]> == null:
- narrate "<&c>A player with name <context.args.get[1]> was not found."
- stop
- define language <context.args.get[2].to_sentence_case>
- define known <script[chat_data_languages].data_key[known]>
- if !<[known].contains[<[language]>]>:
- narrate "<&c>Language <[language]> is not a known language."
- stop
- flag <[player]> chat_languages:<[player].flag[chat_languages].if_null[<list[]>].include[<[language]>].deduplicate>
- narrate format:formats_prefix "Player <&e><[player].name> <&7>may now speak in <[language]>."
chat_command_languageremove:
debug: false
type: command
name: languageremove
usage: /languageremove (player) (language)
aliases:
- langremove
- langrem
description: Removes a language that a player knows.
permission: chat.command.admin.languageremove
tab completions:
1: <server.online_players.parse[name]>
2: <script[chat_data_languages].data_key[known]>
script:
- if <context.args.size> < 2:
- narrate "<&c>Invalid use. Please try /<context.alias> (player) (language)."
- stop
- define player <server.match_offline_player[<context.args.get[1]>].if_null[null]>
- if <[player]> == null:
- narrate "<&c>A player with name <context.args.get[1]> was not found."
- stop
- define language <context.args.get[2].to_sentence_case>
- define known <script[chat_data_languages].data_key[known]>
- if !<[known].contains[<[language]>]>:
- narrate "<&c>Language <[language]> is not a known language."
- stop
- flag <[player]> chat_languages:<[player].flag[chat_languages].if_null[<list[]>].exclude[<[language]>]>
- narrate format:formats_prefix "Player <&e><[player].name> <&7>cannot speak <[language]> any longer."
chat_command_language:
debug: false
type: command
name: language
usage: /language (language) (message)
aliases:
- lang
description: Sends a message in IC, in a language.
permission: chat.command.chat.language
tab completions:
1: <player.flag[chat_languages].if_null[<list[]>]>
2: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 1:
- narrate "<&c>Invalid use. Please use /<context.alias> (language) (message)."
- stop
- define language <context.args.get[1].to_sentence_case>
- if !<player.flag[chat_languages].contains[<[language]>].if_null[false]>:
- narrate "<&c>Your character cannot speak in <[language]>."
- stop
- run chat_channel_ic_language def.player:<player> def.message:<context.raw_args.split.get[2].to[last].space_separated.parse_color.escaped.replace[&].with[&\]> def.language:<[language]>
chat_command_languagewhisper:
debug: false
type: command
name: languagewhisper
usage: /languagewhisper (language) (message)
aliases:
- langwhisper
- langw
description: Sends a message in IC, in a language, whispering.
permission: chat.command.chat.languagewhisper
tab completions:
1: <player.flag[chat_languages].if_null[<list[]>]>
2: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 1:
- narrate "<&c>Invalid use. Please use /<context.alias> (language) (message)."
- stop
- define language <context.args.get[1].to_sentence_case>
- if !<player.flag[chat_languages].contains[<[language]>].if_null[false]>:
- narrate "<&c>Your character cannot speak in <[language]>."
- stop
- run chat_channel_ic_languagewhisper def.player:<player> def.message:<context.raw_args.split.get[2].to[last].space_separated.parse_color.escaped.replace[&].with[&\]> def.language:<[language]>
chat_command_languageyell:
debug: false
type: command
name: languageyell
usage: /languageyell (language) (message)
aliases:
- langyell
- langy
description: Sends a message in IC, in a language, yelling.
permission: chat.command.chat.languageyell
tab completions:
1: <player.flag[chat_languages].if_null[<list[]>]>
2: <&lt>message<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 1:
- narrate "<&c>Invalid use. Please use /<context.alias> (language) (message)."
- stop
- define language <context.args.get[1].to_sentence_case>
- if !<player.flag[chat_languages].contains[<[language]>].if_null[false]>:
- narrate "<&c>Your character cannot speak in <[language]>."
- stop
- run chat_channel_ic_languageyell def.player:<player> def.message:<context.raw_args.split.get[2].to[last].space_separated.parse_color.escaped.replace[&].with[&\]> def.language:<[language]>
##
## Channel switch
##
chat_command_channelswitch:
debug: false
type: command
name: channelswitch
usage: /channelswitch (channel)
aliases:
- chsw
description: Changes your main channel.
permission: chat.command.channelswitch
tab completions:
1: <list[ic|ooc]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Invalid use. Please use /<context.alias> (channel)."
- stop
- define channel <context.args.get[1].to_lowercase>
- choose <[channel]>:
- case ic:
- flag <player> chat_channel:ic
- narrate format:formats_prefix "Changed channel to IC."
- stop
- case ooc:
- if <player.has_flag[chat_disableooc]>:
- narrate "<&c>You currently have OOC disabled. Use /ooc first to enable it."
- stop
- flag <player> chat_channel:ooc
- narrate format:formats_prefix "Changed channel to OOC."
- stop
- narrate "<&c>Unknown channel <[channel]>. Please try: ic, ooc."
##
## Chat Color
##
chat_command_chatcolor:
debug: false
type: command
name: chatcolor
usage: /chatcolor (color)
description: Changes the chat color for your actions.
permission: chat.command.chatcolor
tab completions:
1: <proc[chat_allowed_colors]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Invalid use. Please use /<context.alias> (color)."
- stop
- define color <context.args.get[1].to_lowercase>
- if !<proc[chat_allowed_colors].contains[<[color]>]>:
- narrate "<&c>You must choose a color from this list: <proc[chat_allowed_colors].comma_separated>"
- stop
- flag <player> chat_color:<element[&<color[<[color]>].hex>].parse_color>
- narrate format:formats_prefix "Changed chat color to <element[&<color[<[color]>].hex>].parse_color><[color]>."

142
scripts/chat/chat_data.dsc Normal file
View File

@@ -0,0 +1,142 @@
chat_data_languages:
debug: false
type: data
# all languages allowed by Google Translate
known:
- Afrikaans
- Akan
- Albanian
- Amharic
- Arabic
- Armenian
- Assamese
- Aymara
- Azerbaijani
- Bambara
- Basque
- Belarusian
- Bengali
- Bhojpuri
- Bosnian
- Bulgarian
- Burmese
- Catalan
- Cebuano
- Chewa
- Chinese
- Corsican
- Croatian
- Czech
- Danish
- Dhivehi
- Dogri
- Dutch
#- English
- Esperanto
- Estonian
- Ewe
- Filipino
- Finnish
- French
- Galician
- Georgian
- German
- Goan Konkani
- Greek
- Guarani
- Gujarati
- Haitian Creole
- Hausa
- Hawaiian
- Hebrew
- Hindi
- Hmong
- Hungarian
- Icelandic
- Igbo
- Ilocano
- Indonesian
- Irish
- Italian
#- Japanese
- Javanese
- Kannada
- Kazakh
- Khmer
- Kinyarwanda
- Konkani
- Korean
- Krio
- Kurdish
- Kyrgyz
- Lao
- Latin
- Latvian
- Lingala
- Lithuanian
- Luganda
- Luxembourgish
- Macedonian
- Maithili
- Malagasy
- Malay
- Malayalam
- Maldivian
- Maltese
- Māori
- Marathi
- Meitei
- Mizo
- Mongolian
- Nepali
- Northern Sotho
- Norwegian
- Nyanja
- Odia
- Oromo
- Pashto
- Persian
- Polish
- Portuguese
- Punjabi
- Quechua
- Romanian
- Russian
- Samoan
- Sanskrit
- Scottish Gaelic
- Serbian
- Shona
- Sindhi
- Sinhala
- Slovak
- Slovene
- Somali
- Sotho
- Southern Quechua
- Spanish
- Sundanese
- Swahili
- Swedish
- Tagalog
- Tajik
- Tamil
- Tatar
- Telugu
- Thai
- Tigrinya
- Tsonga
- Turkish
- Turkmen
- Twi
- Ukrainian
- Urdu
- Uyghur
- Uzbek
- Vietnamese
- Welsh
- West Frisian
- Xhosa
- Yiddish
- Yoruba
- Zulu

266
scripts/chat/chat_tasks.dsc Normal file
View File

@@ -0,0 +1,266 @@
chat_name_ooc:
debug: false
type: procedure
definitions: player
script:
- determine <placeholder[luckperms_prefix_element_highest_on_track_color].player[<[player]>].if_null[<&7>].parse_color><[player].name>
chat_special_group:
debug: false
type: procedure
definitions: player
script:
- define result <placeholder[luckperms_prefix_element_highest_on_track_special].player[<[player]>].if_null[<&f>].parse_color>
- if <[result].strip_color.length> > 0:
- define result <[result]><&sp>
- determine <[result]>
chat_roles_group:
debug: false
type: procedure
definitions: player
script:
- determine <placeholder[luckperms_prefix_element_highest_on_track_roles].player[<[player]>].if_null[<&f>].parse_color><&f>
chat_channel_ooc:
debug: false
type: task
definitions: player|message
script:
- define message <[message].strip_color.replace[&\].with[&].unescaped>
- define final "<&8>[<&7><&l>OOC<&8>] <proc[chat_special_group].context[<[player]>]><proc[chat_name_ooc].context[<[player]>]><&7>: <&l><[message]>"
- narrate targets:<server.online_players.filter_tag[<[filter_value].has_flag[chat_disableooc].not>]> <[final]>
- announce to_console <[final]>
chat_channel_looc:
debug: false
type: task
definitions: player|message
script:
- define message <[message].strip_color.replace[&\].with[&].unescaped>
- define final "<&8>[<&7>LOOC<&8>] <proc[chat_special_group].context[<[player]>]><&7><proc[character_get_name].context[<[player]>]> <proc[chat_name_ooc].context[<[player]>]><&7>: <[message]>"
- narrate targets:<[player].location.find_players_within[10]> <[final]>
- announce to_console <[final]>
chat_allowed_colors:
debug: false
type: procedure
script:
- determine <util.color_names.exclude[black].exclude[transparent].exclude[white]>
chat_tokenize_actions:
debug: false
type: procedure
definitions: message|initializer|actioncolor|speechcolor|separator|forcecaps
script:
- define result <empty>
- define index 1
- if <[message].starts_with[*]>:
- define index 2
- else:
- define result <[actioncolor]><[initializer]>
- foreach <[message].split[*]> as:token:
- if <[token].trim.parse_color.strip_color.length> <= 0:
- foreach next
- if <[index].is_odd>:
- if <[forcecaps]>:
- define token <[token].replace[&\].with[&].unescaped.to_uppercase>
- define result "<[result]> <[separator]><[speechcolor]><[token].trim><[separator]>"
- else:
- define result "<[result]> <[actioncolor]><[token].trim>"
- define index <[index].add[1]>
- determine <[result].trim>
chat_channel_ic:
debug: false
type: task
definitions: player|message
script:
- if <[message].starts_with[*]> && <[message].split[*].size> == 2:
- if <[message].ends_with[*]>:
- run chat_channel_ic_me def.player:<[player]> def.message:<[message].substring[2,<[message].length.sub[1]>]>
- else:
- run chat_channel_ic_me def.player:<[player]> def.message:<[message].substring[2,<[message].length>]>
- stop
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define tokenized <proc[chat_tokenize_actions].context[<[message]>|<player.flag[chat_color].if_null[<&e>]>says<&7>:|<player.flag[chat_color].if_null[<&e>]>|<&f>|<&f><&dq><&f>|false].replace[&\].with[&].unescaped>
- define final "<&color[#b8b9ba]><placeholder[essentials_nickname].player[<[player]>]> <&f><proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <[tokenized]>"
- narrate targets:<[player].location.find_players_within[10]> <[final]>
- announce to_console <[final]>
chat_channel_ic_me:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&e>*** <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <player.flag[chat_color].if_null[<&e>]><&o><[message]>"
- narrate targets:<[player].location.find_players_within[10]> <[final]>
- announce to_console <[final]>
chat_channel_ic_mec:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&e>* <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <player.flag[chat_color].if_null[<&e>]><&o><[message]>"
- narrate targets:<[player].location.find_players_within[3]> <[final]>
- announce to_console <[final]>
chat_channel_ic_mel:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&e>**** <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <player.flag[chat_color].if_null[<&e>]><&o><[message]>"
- narrate targets:<[player].location.find_players_within[25]> <[final]>
- announce to_console <[final]>
chat_channel_ic_whisper:
debug: false
type: task
definitions: player|message
script:
- if <[message].starts_with[*]> && <[message].split[*].size> == 2:
- if <[message].ends_with[*]>:
- run chat_channel_ic_mec def.player:<[player]> def.message:<[message].substring[2,<[message].length.sub[1]>]>
- else:
- run chat_channel_ic_mec def.player:<[player]> def.message:<[message].substring[2,<[message].length>]>
- stop
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define tokenized <proc[chat_tokenize_actions].context[<[message]>|whispers|<&8>|<&7>|<&6><&sq>|false].replace[&\].with[&].unescaped>
- define final "<&color[#d1d1d1]><placeholder[essentials_nickname].player[<[player]>]> <&f><proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <[tokenized]>"
- narrate targets:<[player].location.find_players_within[3]> <[final]>
- announce to_console <[final]>
chat_channel_ic_yell:
debug: false
type: task
definitions: player|message
script:
- if <[message].starts_with[*]> && <[message].split[*].size> == 2:
- if <[message].ends_with[*]>:
- run chat_channel_ic_mel def.player:<[player]> def.message:<[message].substring[2,<[message].length.sub[1]>]>
- else:
- run chat_channel_ic_mel def.player:<[player]> def.message:<[message].substring[2,<[message].length>]>
- stop
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define tokenized <proc[chat_tokenize_actions].context[<[message]>|yells|<&6>|<&f>|<&6><&sq>|true].replace[&\].with[&].unescaped>
- define final "<&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <[tokenized]>"
- narrate targets:<[player].location.find_players_within[25]> <[final]>
- announce to_console <[final]>
chat_channel_ic_my:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define possession_name <proc[character_get_name].context[<[player]>]>
- if <[possession_name].to_lowercase.ends_with[s]>:
- define possession_name <[possession_name]><&sq>
- else:
- define possession_name <[possession_name]><&sq>s
- define final "<&e>*** <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <[possession_name]> <&f><[message]>"
- narrate targets:<[player].location.find_players_within[10]> <[final]>
- announce to_console <[final]>
chat_channel_ic_it:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&6>*** <&e><[message]> <&7>(<proc[character_get_name].context[<[player]>]>)"
- narrate targets:<[player].location.find_players_within[10]> <[final]>
- announce to_console <[final]>
chat_channel_ic_itc:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&6>* <&e><[message]> <&7>(<proc[character_get_name].context[<[player]>]>)"
- narrate targets:<[player].location.find_players_within[3]> <[final]>
- announce to_console <[final]>
chat_channel_ic_itl:
debug: false
type: task
definitions: player|message
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final "<&6>**** <&e><[message]> <&7>(<proc[character_get_name].context[<[player]>]>)"
- narrate targets:<[player].location.find_players_within[25]> <[final]>
- announce to_console <[final]>
chat_channel_ic_language:
debug: false
type: task
definitions: player|message|language
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final_known "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <player.flag[chat_color].if_null[<&f>]>says <&f><&dq><&o><[message]><&f><&dq> in <[language]>"
- define final_unknown "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <player.flag[chat_color].if_null[<&f>]>says something in <[language]>"
- define all <[player].location.find_players_within[10]>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
- announce to_console <[final_known]>
chat_channel_ic_languagewhisper:
debug: false
type: task
definitions: player|message|language
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final_known "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <&f>whispers <&dq><&o><[message]><&f><&dq> in <[language]>"
- define final_unknown "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <&f>whispers something in <[language]>"
- define all <[player].location.find_players_within[3]>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
- announce to_console <[final_known]>
chat_channel_ic_languageyell:
debug: false
type: task
definitions: player|message|language
script:
- define message <[message].replace[&\].with[&].unescaped>
- if !<[player].has_permission[chat.colors]>:
- define message <[message].strip_color>
- define final_known "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <&f>yells <&dq><&o><[message].to_uppercase><&f><&dq> in <[language]>"
- define final_unknown "<&6>[<&7>L<&6>] <&f><placeholder[essentials_nickname].player[<[player]>]> <proc[chat_special_group].context[<[player]>]><proc[chat_roles_group].context[<[player]>]> <proc[character_get_name].context[<[player]>]> <&f>yells something in <[language]>"
- define all <[player].location.find_players_within[25]>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
- announce to_console <[final_known]>

View File

@@ -0,0 +1,11 @@
chat_world:
debug: false
type: world
events:
on player chats:
- determine cancelled passively
- define channel <player.flag[chat_channel].if_null[ic]>
- if <[channel]> == ic:
- run chat_channel_ic def.player:<player> def.message:<context.message.parse_color.escaped.replace[&].with[&\]>
- else if <[channel]> == ooc:
- run chat_channel_ooc def.player:<player> def.message:<context.message.escaped.replace[&].with[&\]>

View File

@@ -0,0 +1,14 @@
furniture_command_furniture:
debug: false
type: command
name: furniture
usage: /furniture
description: Opens the furniture menu.
permission: furniture.command.furniture
tab completions:
1: <list[]>
script:
- if <context.source_type> != player:
- narrate "<&c>You can only use this command as a player."
- stop
- run furniture_menu def.player:<player>

View File

@@ -0,0 +1,47 @@
furniture_config:
debug: false
type: data
# Furniture using note block states
noteblock:
# note_block, custom_model_data = 1 when held
1:
represents: Locker (East)
is: piano,1,false
2:
represents: Locker (South)
is: piano,2,false
3:
represents: Locker (West)
is: piano,3,false
4:
represents: Locker (North)
is: piano,4,false
# Furniture using custom_block.dsc library
custom_block:
# iron_horse_armor, custom_model_data = 1 when held
iron_horse_armor,1:
represents: School Chair
collision: skeleton_skull
iron_horse_armor,2:
represents: TV
collision: barrier
iron_horse_armor,3:
represents: Book (open)
collision: warped_trapdoor
iron_horse_armor,4:
represents: Book
collision: warped_trapdoor
iron_horse_armor,5:
represents: Book Stack
collision: skeleton_skull
iron_horse_armor,6:
represents: Desk Lamp
collision: red_sandstone_wall
iron_horse_armor,7:
represents: Clipboard
collision: warped_trapdoor
# List of collision blocks - disables interaction without perms
collision_blocks:
#- skeleton_skull
#- red_sandstone_Wall
- warped_trapdoor

View File

@@ -0,0 +1,92 @@
furniture_cmd_to_noteblock:
debug: false
type: procedure
definitions: cmd
script:
- define data <script[furniture_config].data_key[noteblock]>
- if !<[data].contains[<[cmd]>]>:
- determine null
- define noteblock_data <[data].get[<[cmd]>].get[is].split[,]>
- define instrument <[noteblock_data].get[1]>
- define note <[noteblock_data].get[2]>
- define switched <[noteblock_data].get[3]>
- determine <material[note_block[instrument=<[instrument]>;note=<[note]>;switched=<[switched]>]]>
furniture_custom_block_any:
debug: false
type: procedure
definitions: material|cmd
script:
- define data <script[furniture_config].data_key[custom_block]>
- determine <[data].contains[<[material].name>,<[cmd]>]>
furniture_cmd_to_custom_block_collision:
debug: false
type: procedure
definitions: material|cmd
script:
- define data <script[furniture_config].data_key[custom_block]>
- if !<[data].contains[<[material].name>,<[cmd]>]>:
- determine null
- determine <[data].get[<[material].name>,<[cmd]>].get[collision]>
furniture_all_items_sorted:
debug: false
type: procedure
script:
- define items <list[]>
- foreach <script[furniture_config].data_key[noteblock]> key:noteblock_cmd as:noteblock_data:
- define noteblock <item[note_block[display=<&f><[noteblock_data].get[represents]>;custom_model_data=<[noteblock_cmd]>]]>
- define items <[items].include[<[noteblock]>]>
- foreach <script[furniture_config].data_key[custom_block]> key:custom_block_item_details as:custom_block_data:
- define custom_block_type_cmd_split <[custom_block_item_details].split[,]>
- define custom_item <item[<[custom_block_type_cmd_split].get[1]>[display=<&f><[custom_block_data].get[represents]>;custom_model_data=<[custom_block_type_cmd_split].get[2]>;hides=all]]>
- define items <[items].include[<[custom_item]>]>
- define items <[items].sort_by_value[display]>
- determine <[items]>
furniture_menu:
debug: false
type: task
definitions: player|page
script:
- define page <[page].if_null[0]>
- define items <proc[furniture_all_items_sorted].get[<[page].mul[45].add[1]>].to[<[page].add[1].mul[45]>]>
- define contents <map[]>
- foreach <[items]> as:item:
- definemap item_entry:
item: <[item]>
script: furniture_menu_give
definitions:
player: <[player]>
item: <[item]>
- define contents <[contents].with[<[loop_index]>].as[<[item_entry]>]>
- if <[page]> > 0:
- define contents_extra:
49:
item: <item[ender_pearl[display=<&a><&lt><&lt>]]>
script: furniture_menu
definitions:
player: <[player]>
page: <[page].sub[1]>
- define contents <[contents].include[<[contents_extra]>]>
- if <[page].add[1].mul[27]> < <[contents].size>:
- define contents_extra:
51:
item: <item[ender_eye[display=<&a><&gt><&gt>]]>
script: furniture_menu
definitions:
player: <[player]>
page: <[page].add[1]>
- define contents <[contents].include[<[contents_extra]>]>
- run menu_open def.player:<[player]> "def.title:<&b> 邑邑<&f>邑邑邑邑鄊" def.size:54 def.contents:<[contents]>
furniture_menu_give:
debug: false
type: task
definitions: player|item
script:
- if !<[player].inventory.can_fit[<[item]>]>:
- narrate targets:<[player]> "<&c>You do not have enough space in your inventory!"
- stop
- give player:<[player]> <[item]> quantity:1

View File

@@ -0,0 +1,105 @@
# NOTE BLOCK HANDLERS
furniture_world_noteblock:
debug: false
type: world
events:
on player places note_block:
- if <player.item_in_hand.custom_model_data.if_null[0]> > 0:
- define noteblock <proc[furniture_cmd_to_noteblock].context[<context.item_in_hand.custom_model_data.if_null[null]>]>
- if <[noteblock]> != null:
- modifyblock <context.location> <[noteblock]> no_physics
- stop
- adjustblock <context.location> note:0
- adjustblock <context.location> instrument:piano
- adjustblock <context.location> switched:false
on player right clicks note_block:
- if !<player.is_sneaking>:
- determine cancelled
on player breaks block:
- if <context.location.below.material.advanced_matches[note_block]>:
- run furniture_world_note_block_undo_update def.at:<context.location.below>
- if <context.location.above.material.advanced_matches[note_block]>:
- run furniture_world_note_block_undo_update def.at:<context.location.above>
on player places block:
- if <context.location.below.material.advanced_matches[note_block]>:
- run furniture_world_note_block_undo_update def.at:<context.location.below>
- if <context.location.above.material.advanced_matches[note_block]>:
- run furniture_world_note_block_undo_update def.at:<context.location.above>
furniture_world_note_block_undo_update:
debug: false
type: task
definitions: at
script:
- define old_material <[at].material>
- modifyblock <[at]> <[old_material]> no_physics delayed
# CUSTOM BLOCK HANDLERS
furniture_world_custom_block:
debug: false
type: world
events:
on player right clicks block:
- if !<player.has_permission[furniture.customblock.place]> && !<player.is_op>:
- stop
- if <context.item.material.advanced_matches[air]>:
- stop
- if !<proc[furniture_custom_block_any].context[<context.item.material>|<context.item.custom_model_data.if_null[0]>]>:
- stop
- ratelimit <player> 5t
- determine cancelled passively
#
- define cursor_solid <player.cursor_on_solid[5].if_null[null]>
- if <[cursor_solid]> == null:
- stop
- define block_face_normal <player.eye_location.ray_trace[range=10;return=normal;ignore=<player>;fluids=false;nonsolids=false]>
- define target_block <[cursor_solid].add[<[block_face_normal]>]>
- if <[target_block].material.is_solid>:
- stop
#
- define material <context.item.material.name>[custom_model_data=<context.item.custom_model_data>]
#
- define pitch <tern[<player.eye_location.pitch.is_more_than_or_equal_to[0]>].pass[0].fail[180]>
- define yaw <player.eye_location.yaw.div_int[45].add[1].div_int[2]>
- if <[yaw]> == 1:
- define yaw 90
- if <[yaw]> == 2:
- define yaw 180
- if <[yaw]> == 3:
- define yaw -90
- if <[yaw]> == 4:
- define yaw 0
#
- define collision_block <proc[furniture_cmd_to_custom_block_collision].context[<context.item.material>|<context.item.custom_model_data>]>
- modifyblock <[target_block]> <[collision_block]> no_physics
#
- run custom_block_create def.at:<[target_block]> def.material:<[material]> def.pitch:<[pitch]> def.yaw:<[yaw]>
- animate <player> animation:ARM_SWING
- playsound sound:BLOCK_STONE_PLACE <player> sound_category:blocks pitch:0.7
on player breaks block:
- if <proc[custom_block_at].context[<context.location>]> == null:
- stop
- if !<player.has_permission[furniture.customblock.break]> && !<player.is_op>:
- determine cancelled passively
- stop
- run custom_block_destroy def.at:<context.location>
#
# WORLDEDIT COMPATIBILITY
#
on custom event id:worldedit_edit:
- announce to_ops "Actor: <context.actor>; Locations: <context.locations>"
# COLLISION BLOCK HANDLERS
furniture_world_collision_block:
debug: false
type: world
events:
on player right clicks block bukkit_priority:high:
- if <context.location.if_null[null]> == null:
- stop
- if !<player.has_permission[furniture.collisionblock.interact]> && !<player.is_op>:
- stop
- if <context.location.material.advanced_matches[air].if_null[false]>:
- stop
- if <script[furniture_config].data_key[collision_blocks].contains[<context.location.material.name>].if_null[false]>:
- determine cancelled

View File

@@ -0,0 +1,29 @@
guns_command_unstun:
debug: false
type: command
name: unstun
description: Unstun a shot or tased player.
usage: /unstun
aliases:
- untase
permission: guns.command.unstun
tab completions:
default: PressEnter
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define target <player.target[player].within[5].if_null[null]>
- if <[target]> == null:
- narrate "<&c>Please look towards the player you want to unstun."
- stop
- if <[target].is_npc>:
- narrate "<&c>Please look towards the player you want to unstun."
- stop
- if !<[target].has_flag[guns_frozen]>:
- narrate "<&c>This player is not stunned!"
- stop
- animate <[target]> animation:stop_sitting
- flag <[target]> guns_frozen:!
- narrate format:formats_prefix "You have unstunned <proc[character_get_name].context[<[target]>]>."
- narrate format:formats_prefix "You have been unstunned." targets:<[target]>

View File

@@ -0,0 +1,10 @@
guns_unfreeze:
debug: false
definitions: player
type: task
script:
- waituntil max:60s <[player].is_online.not.or[<[player].has_flag[guns_frozen].not>]>
- if !<[player].has_flag[guns_frozen]>:
- stop
- animate <[player]> animation:stop_sitting
- flag <[player]> guns_frozen:!

View File

@@ -0,0 +1,65 @@
guns_world_common:
debug: false
type: world
events:
after player join:
- if !<player.has_flag[guns_frozen]>:
- stop
- animate <player> animation:sit
- run guns_unfreeze path:script def:<player>
- narrate format:formats_prefix "You logged off before you were unstunned. You will remain stunned for 60 seconds."
on player teleports:
- if <player.has_flag[guns_frozen]>:
- determine cancelled passively
guns_world_gun:
debug: false
type: world
events:
on player right clicks block:
- if !<player.item_in_hand.has_flag[guns_gun]>:
- stop
- ratelimit <player> 1s
# - playsound <player.location> custom sound:your_custom_sound
- playsound <player.location> sound:entity_arrow_shoot
- define target <player.precise_target[25]||null>
- if <[target]> == null:
- define location <player.cursor_on[25]||null>
- if <[location]> == null:
- define location <player.location.forward[25]>
- playeffect effect:redstone at:<player.location.above[1].points_between[<[location]>].distance[0.1]> special_data:0.5|white visibility:16 quantity:6 offset:0,0,0
- stop
- playeffect effect:redstone at:<player.location.above[1].points_between[<[target].location.above[1]>].distance[0.1]> special_data:0.5|white visibility:16 quantity:6 offset:0,0,0
- if <[target].entity_type> != player:
- stop
- if <[target].has_flag[guns_frozen]>:
- stop
- animate <[target]> animation:sit
- flag <[target]> guns_frozen:true
- run guns_unfreeze path:script def:<[target]>
- narrate format:formats_prefix "You shot <proc[character_get_name].context[<[target]>]>"
- narrate format:formats_prefix "You have been shot by <proc[character_get_name].context[<player>]>" targets:<[target]>
guns_world_taser:
debug: false
type: world
events:
on player right clicks block:
- if !<player.item_in_hand.has_flag[guns_taser]>:
- stop
- ratelimit <player> 1s
- define target <player.precise_target[7]||null>
- if <[target]> == null:
- stop
- if <[target].entity_type> != player:
- stop
- if <[target].has_flag[guns_frozen]>:
- stop
- playeffect effect:redstone at:<player.location.above[1].points_between[<[target].location.above[1]>].distance[0.1]> special_data:0.5|white visibility:16 quantity:6 offset:0,0,0
# - playsound <player.location> custom sound:your_custom_sound
- playsound <player.location> sound:entity_armor_stand_hit
- animate <[target]> animation:sit
- flag <[target]> guns_frozen:true
- run guns_unfreeze path:script def:<[target]>
- narrate format:formats_prefix "You tased <proc[character_get_name].context[<[target]>]>"
- narrate format:formats_prefix "You have been tased by <proc[character_get_name].context[<player>]>" targets:<[target]>

View File

@@ -0,0 +1,62 @@
#
# Anvil Input
# A library that lets you use anvil inputs instead of chat inputs.
#
#
# Requests input from the player with the given prompt, and then applies
# the result to the callback.
#
# The callback is a task with two definitions: a player, and the input.
# The callback is called an filled automatically by this task once the anvil
# input is complete.
#
anvil_input:
debug: false
type: task
definitions: player|prompt|callback
script:
- if !<[player].is_online>:
- stop
- define inventory <inventory[anvil[title=<&f>邑邑邑邑]]>
- define rename <item[warped_trapdoor[display=<&f><[prompt]>]]>
- flag <[rename]> anvil_input:true
- inventory set slot:1 origin:<[rename]> destination:<[inventory]>
- flag <[player]> anvil_input:<[callback]>
- inventory open destination:<[inventory]> player:<[player]>
# Handles anvil input events
anvil_input_world:
debug: false
type: world
events:
on player prepares anvil craft item:
- if !<player.has_flag[anvil_input]>:
- stop
- determine 0 passively
- wait 1t
- take flagged:anvil_input quantity:9999
on player clicks in anvil:
- if !<player.has_flag[anvil_input]>:
- stop
- determine cancelled passively
- if <context.slot> != 3:
- stop
- define result <context.item.display.if_null[<context.inventory.slot[1].display.if_null[<empty>]>].strip_color>
- define callback <player.flag[anvil_input]>
- flag <player> anvil_input:!
- playsound sound:input.ok <player> custom
- run <[callback]> def.player:<player> def.input:<[result]>
- inventory close
- wait 1t
- take flagged:anvil_input quantity:9999
- adjust <player> item_on_cursor:<item[air]>
on player closes anvil:
- if !<player.has_flag[anvil_input]>:
- stop
- flag <player> anvil_input:!
- wait 1t
- take flagged:anvil_input quantity:9999
- narrate "<&c>Cancelled input..."
on player join:
- take flagged:anvil_input quantity:9999

149
scripts/lib/ball.dsc Normal file
View File

@@ -0,0 +1,149 @@
# Ball Library
# A library that manages & controls "bouncing balls", i.e. some kind of game ball
# which has gravity, movement, collision, and so on.
# It also efficiently handles everything and adds custom event handlers that other
# plugins can handle.
# Creates a new ball with the given id, at the given location, with the given
# collision size and using the given display item, and some gravity multiplier.
# Only one ball with a given id can exist at one time. If this method is called
# while another ball with this id exists, it will be removed automatically.
ball_create:
debug: false
type: task
definitions: id|location|size|display_item|gravity_multiplier
script:
- ~run ball_remove def.id:<[id]>
- spawn slime[silent=true;size=<[size]>;has_ai=false;visible=false] <[location].with_pitch[0].with_yaw[0]> save:ball_collision
- define ball_collision <entry[ball_collision].spawned_entity>
- define size <[ball_collision].bounding_box.get[1].sub[<[ball_collision].location>].x.abs.add[0.01]>
- spawn armor_stand[invulnerable=true;has_ai=false;gravity=false;visible=false] <[location].with_pitch[0].with_yaw[0].below[<[size].add[1]>]> save:ball_display
- define ball_display <entry[ball_display].spawned_entity>
- adjust <[ball_display]> equipment:<map[].with[helmet].as[<[display_item]>]>
- flag <[ball_collision]> ball:<[id]>
- flag <[ball_collision]> ball_display:<[ball_display]>
- flag <[ball_collision]> ball_velocity:<location[0,0,0,<[location].world>]>
- flag <[ball_collision]> ball_size:<[size]>
- flag <[ball_collision]> ball_gravity:<[gravity_multiplier]>
- flag <[ball_display]> ball:<[id]>
- flag server ball:<server.flag[ball].if_null[<map[]>].with[<[id]>].as[<[ball_collision]>]>
- determine <[ball_collision]>
# Removes a ball by id. If that ball does not exist, it will silently fail.
ball_remove:
debug: false
type: task
definitions: id
script:
- if <server.flag[ball].if_null[<map[]>].contains[<[id]>]>:
- remove <server.flag[ball].get[<[id]>].flag[ball_display]>
- remove <server.flag[ball].get[<[id]>]>
- flag server ball:<server.flag[ball].exclude[<[id]>]>
# Gets a ball by id.
ball_get:
debug: false
type: procedure
definitions: id
script:
- determine <server.flag[ball].if_null[<map[]>].get[<[id]>]>
# Adds a vector to the ball's current velocity
# This has the effect of "pushing" the ball in that direction.
ball_vector_add:
debug: false
type: task
definitions: ball|vector
script:
- flag <[ball]> ball_velocity:<[ball].flag[ball_velocity].add[<[vector]>]>
# Handling a ball's event:
# Create a world script and add the following event
# // on custom event id:ball_move:
# The following context is provided:
# - <context.ball_id> (EleemntTag) - the ball's ID.
# - <context.ball> (EntityTag) - the ball entity with current state in its flag_map
# - <context.now> (LocationTag) - the ball's current location
# - <context.next> (LocationTag) - the ball's computed next location, which may be reflected if it bounced
# - <context.velocity_t0> (LocationTag) - the ball's current velocity
# - <context.velocity_t1> (LocationTag) - the ball's next computed velocity
# - <context.bounced> (ElementTag) - true if the ball bounced, false otherwise
# - <context.ground> (ElementTag) - true if the ball bounced or is on the ground, false otherwise
# You can cancel the event as any other event, or you can "determine output:<list[...]>" containing:
# - element 1 (LocationTag): the next location for the ball for when it gets moved
# - element 2 (LocationTag): the next velocity for the next processing tick
## Do not change! This handles updating the ball's physics as well as movement.
ball_internal_physics_update:
debug: false
type: world
events:
on tick:
- foreach <server.flag[ball].if_null[<map[]>]> key:id as:ball:
- run ball_internal_physics_update_ball def.ball:<[ball]>
on entity damaged:
- if <context.entity.has_flag[ball]>:
- determine cancelled passively
on player right clicks entity:
- if <context.entity.has_flag[ball]>:
- determine cancelled passively
ball_internal_physics_update_ball:
debug: false
type: task
definitions: ball
script:
- define velocity <[ball].flag[ball_velocity]>
- define gravity <[ball].flag[ball_gravity].mul[0.035]>
- define now <[ball].location>
- define next <[ball].location.add[<[velocity]>]>
- define yaw <[next].direction[<[now]>].yaw.sub[180].if_null[0]>
- define pitch <location[0,1,0].quaternion_between_vectors[<[next].sub[<[now]>].normalize>].represented_angle.to_degrees.sub[90].if_null[0]>
- define now <[now].with_yaw[<[yaw]>].with_pitch[<[pitch]>]>
- define size <[ball].flag[ball_size]>
- define trace <[now].ray_trace[range=<[now].distance[<[next]>].add[<[size]>]>].if_null[null]>
- define bounced false
- if <[trace]> != null:
- define bounced true
- define normal <[trace].direction.vector>
- define direction <[next].sub[<[now]>]>
- define dot <[direction].x.mul[<[normal].x>].add[<[direction].y.mul[<[normal].y>]>].add[<[direction].z.mul[<[normal].z>]>]>
- define reflection <[direction].sub[<[normal].mul[<[dot].mul[2]>]>].mul[0.65]>
- define next <[trace].add[<[reflection]>]>
- define velocity <[reflection]>
- if <util.current_time_millis.sub[<[ball].flag[ball_sound_time].if_null[0]>]> > 200:
- playsound <[now]> sound:BLOCK_STONE_BREAK pitch:1.8
- flag <[ball]> ball_sound_time:<util.current_time_millis>
- define grounded false
- if !<[ball].location.below[<[size].div[4]>].material.is_solid>:
- define velocity <[velocity].mul[0.99]>
- define velocity <[velocity].add[0,-<[gravity]>,0]>
- else:
- define velocity <[velocity].mul[0.75]>
- define next <[next].with_y[<[next].above[<[size].add[0.25]>].block.y>]>
- define grounded true
- if <[next].sub[<[now]>].vector_length_squared> >= 0.01:
- definemap event_context:
ball_id: <[ball].flag[ball]>
ball: <[ball]>
now: <[now]>
next: <[next]>
velocity_t0: <[ball].flag[ball_velocity]>
velocity_t1: <[velocity]>
bounced: <[bounced]>
ground: <[grounded]>
- customevent id:ball_move context:<[event_context]> save:move_event
- if <entry[move_event].any_ran>:
- if <entry[move_event].was_cancelled>:
- stop
- if !<entry[move_event].determination_list.is_empty>:
- define changes <entry[move_event].determination_list>
- define next <[changes].get[1].if_null[<[next]>]>
- define velocity <[changes].get[2].if_null[<[velocity]>]>
- flag <[ball]> ball_velocity:<[velocity]>
- if <[size]> <= 2:
- teleport <[ball].flag[ball_display]> <[next].below[<[size].add[0.7]>]>
- else:
- teleport <[ball].flag[ball_display]> <[next].below[<[size].add[0.7]>]>
- teleport <[ball]> <[next]>

View File

@@ -0,0 +1,179 @@
#
# Custom Block - a lib/framework to create custom blocks with display entities easily.
# Note: this prioritizes being very fast even for many blocks, players, and without lag even on Vanilla.
# As a result, the range and scope of this is limited to that; you should *really* use note-blocks or
# tripwire block states for most things if you can help it. A mix of both is best!
#
# You should change the computations to handle more chunks instead of just a 3x3 area if you don't expect
# too many players, if your CPU is particularly powerful and fast, and if you don't mind client-side lag.
#
# This library will automatically "render" only the custom blocks in a certain range around the player.
# By default, this is a 3x3 chunk area around the player; the item displays have a 0.75 view-range.
# This will not show the custom entities particularly far, but it will ensure very good FPS & TPS.
# The algorithm should be fairly fast, especially for Denizen; likely a pure Java algorithm would
# have better performance but not by much, since the `fakespawn` and `flag` utils of Denizen are
# hard to beat.
#
# API
custom_block_create:
debug: false
type: task
definitions: at|material|pitch|yaw|headless
script:
- define pitch <[pitch].if_null[0]>
- define yaw <[yaw].if_null[0]>
- define world <[at].world.name>
- define chunk_x <[at].chunk.x>
- define chunk_z <[at].chunk.z>
#
- define entry_key custom_block_<[world]>,<[chunk_x]>,<[chunk_z]>
- define at <[at].center>
- define where <[at].x>,<[at].y>,<[at].z>
- define value_key <[where]>,<[pitch]>,<[yaw]>,<[material]>
#
- define block_set <server.flag[<[entry_key]>].if_null[<list[]>]>
- if <[block_set].filter_tag[<[filter_value].starts_with[<[where]>]>].size> > 0:
- debug error "[Custom Block Lib] Duplicate block add: <[where]>,<[world]>! Call custom_block_destroy first"
- stop
- define block_set <[block_set].include[<[value_key]>]>
- flag server <[entry_key]>:<[block_set]>
#
- if <[headless].if_null[false]>:
- stop
- define players <list[]>
- repeat 3 from:<[chunk_x].sub[1]> as:i:
- repeat 3 from:<[chunk_z].sub[1]> as:k:
- define chunk <chunk[<[i]>,<[k]>,<[world]>]>
- foreach <[chunk].players> as:player:
- define players <[players].include[<[player]>].deduplicate>
- foreach <[players]> as:player:
- run custom_block_render def.player:<[player]>
custom_block_destroy:
debug: false
type: task
definitions: at|headless
script:
- define world <[at].world.name>
- define chunk_x <[at].chunk.x>
- define chunk_z <[at].chunk.z>
- define entry_key custom_block_<[world]>,<[chunk_x]>,<[chunk_z]>
#
- define at <[at].center>
- define where <[at].x>,<[at].y>,<[at].z>
#
- define block_set <server.flag[<[entry_key]>].if_null[<list[]>]>
- define block_set_length <[block_set].size>
- define block_set <[block_set].filter_tag[<[filter_value].starts_with[<[where]>].not>]>
- if <[block_set].size> == <[block_set_length]>:
- debug error "[Custom Block Lib] Tried removing inexistent custom block: <[where]>,<[world]>"
- stop
- if <[block_set].size> == 0:
- flag server <[entry_key]>:!
- else:
- flag server <[entry_key]>:<[block_set]>
#
- if <[headless].if_null[false]>:
- stop
- define players <list[]>
- repeat 3 from:<[chunk_x].sub[1]> as:i:
- repeat 3 from:<[chunk_z].sub[1]> as:k:
- define chunk <chunk[<[i]>,<[k]>,<[world]>]>
- foreach <[chunk].players> as:player:
- define players <[players].include[<[player]>].deduplicate>
- foreach <[players]> as:player:
- run custom_block_render def.player:<[player]>
custom_block_at:
debug: false
type: procedure
definitions: at
script:
- define world <[at].world.name>
- define chunk_x <[at].chunk.x>
- define chunk_z <[at].chunk.z>
- define entry_key custom_block_<[world]>,<[chunk_x]>,<[chunk_z]>
#
- define at <[at].center>
- define where <[at].x>,<[at].y>,<[at].z>
#
- if !<server.has_flag[<[entry_key]>]>:
- determine null
- define block_set <server.flag[<[entry_key]>]>
- foreach <[block_set]> as:cblock:
- if <[cblock].starts_with[<[where]>]>:
- determine <[cblock].split[,].get[6]>
- determine null
# Render routine
custom_block_flush:
debug: false
type: task
definitions: player|complete
script:
- define complete <[complete].if_null[false]>
- define prerendered <[player].flag[custom_block_prerendered].if_null[<map[]>]>
- if <[complete]>:
- foreach <[player].fake_entities> as:fentity:
- if <[fentity].custom_name.contains[__CustomBlock__].if_null[false]>:
- fakespawn <[fentity]> cancel player:<[player]>
- else:
- foreach <[player].fake_entities> as:fentity:
- if <[fentity].custom_name.contains[__CustomBlock__].if_null[false]>:
- if !<[prerendered].contains[<[fentity].location.escaped>]>:
- fakespawn <[fentity]> cancel player:<[player]>
custom_block_render:
debug: false
type: task
definitions: player
script:
- define world <[player].location.world.name>
- define chunk_x <[player].location.chunk.x>
- define chunk_z <[player].location.chunk.z>
- define player_y <[player].location.y>
- flag <[player]> custom_block_lrx:<[chunk_x]>
- flag <[player]> custom_block_lrz:<[chunk_z]>
- flag <[player]> custom_block_lry:<[player_y]>
- define prerendered <[player].flag[custom_block_prerendered].if_null[<map[]>]>
- define valid <map[]>
- repeat 3 from:<[chunk_x].sub[1]> as:i:
- repeat 3 from:<[chunk_z].sub[1]> as:k:
- define entry_key custom_block_<[world]>,<[i]>,<[k]>
- if <server.has_flag[<[entry_key]>]>:
- foreach <server.flag[<[entry_key]>]> as:cblock:
- define cblock <[cblock].split[,]>
- if <[cblock].get[2].sub[<[player_y]>].abs> > 24:
- foreach next
- define at <location[<[cblock].get[1]>,<[cblock].get[2]>,<[cblock].get[3]>,<[cblock].get[4]>,<[cblock].get[5]>,<[world]>]>
- define valid <[valid].with[<[at].escaped>].as[true]>
- if <[prerendered].contains[<[at].escaped>]>:
- foreach next
- define of <[cblock].get[6]>
- define display <entity[item_display]>
- adjust def:display item:<item[<[of]>]>
- adjust def:display display:fixed
- adjust def:display view_range:0.75
- adjust def:display custom_name:__CustomBlock__
- fakespawn <[display]> <[at]> player:<[player]> duration:-1
- define prerendered <[prerendered].with[<[at].escaped>].as[true]>
- define prerendered <[prerendered].filter_tag[<[valid].contains[<[filter_key]>]>]>
- flag <[player]> custom_block_prerendered:<[prerendered]>
- run custom_block_flush def.player:<[player]>
custom_block_world:
debug: false
type: world
events:
after player joins:
- flag <player> custom_block_prerendered:!
- run custom_block_flush def.player:<player> def.complete:true
- ~run custom_block_render def.player:<player>
on player walks:
- ratelimit <player> 5t
- if <player.flag[custom_block_lrx].if_null[0]> == <context.new_location.chunk.x>:
- if <player.flag[custom_block_lrz].if_null[0]> == <context.new_location.chunk.z>:
- if <player.flag[custom_block_lry].if_null[0].sub[<context.new_location.y>].abs> <= 8:
- stop
- ~run custom_block_render def.player:<player>

8
scripts/lib/formats.dsc Normal file
View File

@@ -0,0 +1,8 @@
#
# Common Formats - change these to change everywhere!
#
formats_prefix:
debug: false
type: format
format: <&8>[<&color[#ff96ee]>Sakura<&color[#e8e8e8]>Falls<&8>] <&7><[text]>

View File

@@ -0,0 +1,63 @@
#
# GUI Restore - deletes & restores inventories that start with
# some specific special chars (usually color codes)
# (but also anvils because of anvil_input.dsc)
#
gui_restore_config:
debug: false
type: data
special_chars: <&f>邑邑邑邑
gui_restore_set_later:
debug: false
type: task
definitions: player|slot|item
script:
- flag <[player]> gui_restore_later:<[player].flag[gui_restore_later].if_null[<map[]>].with[<[slot]>].as[<[item]>]>
gui_restore_save:
debug: false
type: task
definitions: player
script:
- if <[player].has_flag[gui_restore]>:
- run gui_restore_load def.player:<player>
- flag <[player]> gui_restore:<[player].inventory.map_slots>
- define equipment <[player].inventory.equipment_map>
- inventory clear player:<[player]>
- foreach <[equipment]> key:slot as:item:
- inventory set slot:<[slot]> origin:<[item]> player:<[player]>
- foreach <[player].flag[gui_restore_later].if_null[<map[]>]> key:slot as:item:
- inventory set slot:<[slot]> origin:<[item]> player:<[player]>
gui_restore_load:
debug: false
type: task
definitions: player
script:
- if !<[player].has_flag[gui_restore]>:
- stop
- flag <[player]> gui_restore_later:!
- inventory clear player:<[player]>
- foreach <[player].flag[gui_restore]> key:slot as:item:
- inventory set slot:<[slot]> origin:<[item]> player:<[player]>
- flag <[player]> gui_restore:!
gui_restore_world:
debug: false
type: world
events:
on player joins:
- if <player.has_flag[gui_restore_later]>:
- flag <player> gui_restore_later:!
- if <player.has_flag[gui_restore]>:
- run gui_restore_load def.player:<player>
on player opens inventory bukkit_priority:lowest:
- if <context.inventory.title.starts_with[<script[gui_restore_config].data_key[special_chars].parsed>]>:
- run gui_restore_save def.player:<player>
- if <context.inventory.inventory_type> == anvil:
- run gui_restore_save def.player:<player>
on player closes inventory bukkit_priority:lowest:
- if <player.has_flag[gui_restore]>:
- run gui_restore_load def.player:<player>

100
scripts/lib/menu.dsc Normal file
View File

@@ -0,0 +1,100 @@
#
# Utility for creating menus with click handlers on them.
# It also provides a way to make paged menus more easily.
#
# opens a menu with a title, of size, based on the contents.
# the size must be a multiple of 9
#
# the contents should be a map pairing the slot to three keys
# the 'item' key is the item's display in the menu
# the 'script' key is the script to call when clicked
# the 'definitions' key is a map pairing definition name to value
# if the script is null, then no script is called on interaction
# if the definitions are null, the script is called without definitions
# at the end, after opening, this task determines the opened inventory.
#
# the fill argument can be ommitted, or is an item which fills any
# slots not specified in the contents map
menu_open:
debug: false
type: task
definitions: player|title|size|contents|fill
script:
- define display_key <element[menu].to_secret_colors.split[<&ss>].remove[1].parse_tag[<&ss><[parse_value]><&sp>].separated_by[]>
- define inventory <inventory[generic[title=<[title]><[display_key]>;size=<[size]>]]>
# fill
- foreach <[contents]> key:slot as:data:
- define item <[data].get[item].if_null[null]>
# bad item
- if <[item]> == null:
- foreach next
# fit other data
- define script <[data].get[script].if_null[null]>
- define definitions <[data].get[definitions].if_null[null]>
# flag item accordingly
- if <[script]> != null:
- flag <[item]> _menu_script:<[script]>
- if <[definitions]> != null:
- flag <[item]> _menu_definitions:<[definitions]>
# set in inventory
- inventory set slot:<[slot]> origin:<[item]> destination:<[inventory]>
# has fill attribute?
- if <[fill].if_null[null]> != null:
- repeat <[size]> as:slot:
- if !<[contents].contains[<[slot]>]>:
- inventory set slot:<[slot]> origin:<[fill]> destination:<[inventory]>
# open inventory and return
- inventory open player:<[player]> destination:<[inventory]>
- determine <[inventory]>
# checks if the passed menu parameter is actually
# a menu or not based on its display key
menu_is:
debug: false
type: procedure
definitions: inventory
script:
- if <[inventory].title.length.sub[22]> < 1:
- determine false
- define display_key <[inventory].title.substring[<[inventory].title.length.sub[22]>].replace[<&sp>].with[].from_secret_colors>
- determine <[display_key].equals[menu]>
# determines the title of a menu ignoring its display key
# this also strips any colors to avoid annoyances
# useful for other handlers elsewhere
menu_title:
debug: false
type: procedure
definitions: inventory
script:
- determine <[inventory].title.substring[0,<[inventory].title.length.sub[25]>].strip_color.if_null[Unknown]>
# handles basic clicks in menu inventories
menu_click_handler:
debug: false
type: world
events:
on player clicks item in inventory:
# ignore non-gui clicks
## as of 1.20.4
- if <context.inventory.inventory_type> != CHEST:
- stop
# ignore non menus
- if !<proc[menu_is].context[<context.inventory>]>:
- stop
# valid menu, stop all events
- determine cancelled passively
# ignore out of bounds clicks
- if <context.raw_slot> > <context.inventory.size>:
- stop
# handle click if any
- define script <context.item.flag[_menu_script].if_null[null]>
- if <[script]> != null:
- define definitions <context.item.flag[_menu_definitions].if_null[null]>
- if <[definitions]> == null:
# run plain script
- run <[script]>
- else:
# run scripts with definitions
- run <[script]> defmap:<[definitions]>

317
scripts/lib/textbox.dsc Normal file
View File

@@ -0,0 +1,317 @@
#
# Textbox - a lib/framework to display an Undertale/RPG style text box.
# Requires resource pack to be set up correctly.
# The magic character is U+9300, i.e 錀, which you can change in the code.
#
# Writes into the text box display.
# You should provide at most 3 lines into the textbox (though other values are technically allowed).
# Lines are split using $$nl: line3s should be simple text, not a list directly.
# Optionally, provide an avatar_unicode character that should be placed next to the textbox.
textbox_write:
debug: false
type: task
definitions: player|queue|line3s|avatar_unicode
script:
- define avatar_unicode <[avatar_unicode].if_null[null]>
- if <[player].flag[textbox_state].if_null[null]> == writing:
- stop
- if !<[player].is_online>:
- if <[queue].if_null[null]> != null:
- debug log "[Textbox] Write; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline player."
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- if !<[player].is_on_ground> && <player.gamemode> != spectator:
- if <[player].location.below.material.is_solid>:
- teleport <[player]> <[player].location.below.above.with_y[<[player].location.below.above.y.round_down>]>
- else:
- stop
- waituntil <[player].flag[textbox_state].if_null[null]> == null max:5s
- ~run textbox_flush def.player:<[player]>
- if !<[player].is_online>:
- if <[queue].if_null[null]> != null:
- debug log "[Textbox] Write; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline player."
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- define lines <[line3s].split[$$nl].parse_tag[<[parse_value].trim>]>
- flag <[player]> textbox_state:writing
- flag <[player]> textbox_input:<[lines]>
- flag <[player]> textbox_lines:<[lines].size>
- bossbar create textbox_<[player].uuid>_ui players:<[player]> title:錀
- bossbar create textbox_<[player].uuid>_1 players:<[player]> title:<empty>
- bossbar create textbox_<[player].uuid>_2 players:<[player]> title:<empty>
- bossbar create textbox_<[player].uuid>_3 players:<[player]> title:<empty>
- wait 1t
- if <[avatar_unicode]> != null:
- bossbar create textbox_<[player].uuid>_avatar players:<[player]> title:<element[ ].repeat[64]><[avatar_unicode]>
- foreach <[lines]> as:line:
- if <[player].flag[textbox_state].if_null[null]> != writing:
- stop
- if !<[player].is_online>:
- stop
- repeat <[line].length>:
- if <[player].flag[textbox_state].if_null[null]> != writing:
- stop
- if !<[player].is_online>:
- stop
- bossbar update textbox_<[player].uuid>_<[loop_index]> title:<black><bold><[line].substring[1,<[value]>]>
- if <[value].sub[1].mod[3]> == 0:
- playsound sound:textbox.text <[player]> custom pitch:<util.random.decimal[0.98].to[1]>
- wait 1t
- if <[line].substring[<[value].add[1]>,<[value].add[1]>].trim.length.if_null[1]> == 0:
- if <[line].substring[<[value]>,<[value]>]> == ".":
- wait 2t
- if <[line].substring[<[value]>,<[value]>]> == "!":
- wait 2t
- if <[line].substring[<[value]>,<[value]>]> == "?":
- wait 2t
- if <[line].substring[<[value]>,<[value]>]> == "-":
- wait 2t
- if <[line].substring[<[value]>,<[value]>]> == ",":
- wait 2t
- wait <duration[1t]>
- if <[player].flag[textbox_state].if_null[null]> != writing:
- if <[queue].if_null[null]> != null && <[player].flag[textbox_state].if_null[null]> != continue:
- debug log "[Textbox] Write; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; state mismatch."
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- if !<[player].is_online>:
- if <[queue].if_null[null]> != null:
- debug log "[Textbox] Write; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline player."
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- flag <[player]> textbox_state:continue
# Skips the textbox and fills in the text quickly - i.e. text mashing
textbox_skip:
debug: false
type: task
definitions: player
script:
- if <[player].flag[textbox_state].if_null[null]> != writing:
- stop
- repeat <[player].flag[textbox_lines]>:
- if !<server.current_bossbars.contains[textbox_<[player].uuid>_<[value]>]>:
- bossbar create textbox_<[player].uuid>_<[value]> players:<[player]> title:<empty>
- define lines <[player].flag[textbox_input]>
- foreach <[lines]> as:line:
- bossbar update textbox_<[player].uuid>_<[loop_index]> title:<black><bold><[line]>
- flag <[player]> textbox_state:continue
# Clears textbox and flushes all flag memory values
textbox_flush:
debug: false
type: task
definitions: player
script:
- if <server.current_bossbars.contains[textbox_<[player].uuid>_ui]>:
- bossbar remove textbox_<[player].uuid>_ui
- repeat 3:
- if <server.current_bossbars.contains[textbox_<[player].uuid>_<[value]>]>:
- bossbar remove textbox_<[player].uuid>_<[value]>
- if <server.current_bossbars.contains[textbox_<[player].uuid>_avatar]>:
- bossbar remove textbox_<[player].uuid>_avatar
- if <server.current_bossbars.contains[textbox_<[player].uuid>_top]>:
- bossbar remove textbox_<[player].uuid>_top
- bossbar remove textbox_<[player].uuid>_mid
- bossbar remove textbox_<[player].uuid>_bottom
- flag <[player]> textbox_state:!
- flag <[player]> textbox_input:!
- flag <[player]> textbox_lines:!
- flag <[player]> textbox_choices:!
- wait 10t
# Handle textbox events
# Internal only!
textbox_world:
debug: false
type: world
events:
# Skip the text and close the textbox by right click
on player right clicks block bukkit_priority:lowest:
- ratelimit <player> 5t
- if <context.hand> == OFF_HAND:
- stop
- inject textbox_handle_click
on player right clicks entity bukkit_priority:lowest:
- ratelimit <player> 5t
- if <context.hand> == OFF_HAND:
- stop
- inject textbox_handle_click
on player animates arm_swing:
- ratelimit <player> 5t
- inject textbox_handle_click
# Disallow block breaking (because skip is done via clicking, even in Creative Mode)
on player breaks block:
- define state <player.flag[textbox_state].if_null[false]>
- if <[state]> == writing || <[state]> == continue:
- determine cancelled
# Disallow damage when textbox is active
on player damages entity:
- define state <player.flag[textbox_state].if_null[false]>
- if <[state]> == writing || <[state]> == continue:
- determine cancelled
# Flush if rejoin
on player joins:
- run textbox_flush def.player:<player>
# No movement on text
on player walks:
- define state <player.flag[textbox_state].if_null[false]>
- if <[state]> == writing || <[state]> == continue:
- if <context.old_location.with_pitch[0].with_yaw[0]> != <context.new_location.with_pitch[0].with_yaw[0]>:
- determine cancelled
- if <[state]> == choice:
- if <context.old_location.with_pitch[0].with_yaw[0]> != <context.new_location.with_pitch[0].with_yaw[0]>:
- determine cancelled passively
- ratelimit <player> 5t
#
- define reference <context.old_location>
- define left <[reference].left[0.001]>
- define right <[reference].right[0.001]>
- define up <[reference].forward[0.001]>
- define down <[reference].backward[0.001]>
#
- define min <[left].sub[<context.new_location>].vector_length_squared>
- define min_dir left
#
- define right_check <[right].sub[<context.new_location>].vector_length_squared>
- if <[right_check]> < <[min]> :
- define min <[right_check]>
- define min_dir right
#
- define up_check <[up].sub[<context.new_location>].vector_length_squared>
- if <[up_check]> < <[min]> :
- define min <[up_check]>
- define min_dir top
#
- define down_check <[down].sub[<context.new_location>].vector_length_squared>
- if <[down_check]> < <[min]> :
- define min <[down_check]>
- define min_dir bottom
#
- run textbox_internal_choice_select def.player:<player> def.choice_dir:<[min_dir]>
# Internal only!
textbox_handle_click:
debug: false
type: task
script:
- define state <player.flag[textbox_state].if_null[false]>
- if <[state]> == writing:
- determine cancelled passively
- run textbox_skip def.player:<player>
- ratelimit <player> 5t
- else if <[state]> == continue:
- determine cancelled passively
- playsound sound:textbox.close <player> custom
- ~run textbox_flush def.player:<player>
- ratelimit <player> 10t
- else if <[state]> == choice:
- determine cancelled passively
- playsound sound:input.ok <player> custom
- flag <player> textbox_choice_select:<player.flag[textbox_choices].get[current]>
- ~run textbox_flush def.player:<player>
- ratelimit <player> 10t
# Writes into the text box display.
# You should provide at least 2 and up to 4 choices.
# The choices are defined in the top, left, right, and bottom directions.
# The choices map has this structure:
# choices:
# left:
# text: 'Some Choice 1'
# task: task_to_continue_to_1
# right:
# text: 'Some Choice 2'
# task: task_to_continue_to_2
# ...
# When selected, the task receives the player as input in the <[player]> definition.
# The task also receives the direction that was picked in <[choice]>: top, bottom, left or right
textbox_choice:
debug: false
type: task
definitions: player|queue|choices
script:
- if <[player].flag[textbox_state].if_null[null]> == choice:
- stop
- if !<[player].is_online>:
- if <[queue].if_null[null]> != null:
- debug log "[Textbox] Choice; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline"
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- if !<[player].is_on_ground> && <player.gamemode> != spectator:
- if <[player].location.below.material.is_solid>:
- teleport <[player]> <[player].location.below.above.with_y[<[player].location.below.above.y.round_down>]>
- else:
- stop
- waituntil <[player].flag[textbox_state].if_null[null]> == null
- ~run textbox_flush def.player:<[player]>
- flag <[player]> textbox_state:choice
- flag <[player]> textbox_choices:<map[].with[data].as[<[choices]>].with[current].as[left]>
- define first_choice left
- if <[choices].keys.contains[top]>:
- define first_choice top
- if !<[choices].keys.contains[left]>:
- define first_choice <[choices].keys.first>
- run textbox_internal_choice_select def.player:<[player]> def.choice_dir:<[first_choice]>
- waituntil <[player].flag[textbox_choice_select].if_null[null]> != null || !<[player].is_online>
- if !<[player].is_online>:
- if <[queue].if_null[null]> != null:
- debug log "[Textbox] Choice; cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline"
- queue stop <[queue]>
- run textbox_flush def.player:<[player]>
- stop
- define result <[player].flag[textbox_choice_select]>
- flag <[player]> textbox_choice_select:!
- determine <[result]>
# Internal only!
textbox_internal_choice_select:
debug: false
type: task
definitions: player|choice_dir
script:
- if !<server.current_bossbars.contains[textbox_<[player].uuid>_top]>:
- bossbar create textbox_<[player].uuid>_ui players:<[player]> title:錀
- bossbar create textbox_<[player].uuid>_top players:<[player]> title:<empty>
- bossbar create textbox_<[player].uuid>_mid players:<[player]> title:<empty>
- bossbar create textbox_<[player].uuid>_bottom players:<[player]> title:<empty>
- define choices <[player].flag[textbox_choices].get[data]>
#
- define left <&0><&l><[choices].get[left].get[text].if_null[null]>
- define right <&0><&l><[choices].get[right].get[text].if_null[null]>
- define top <&0><&l><[choices].get[top].get[text].if_null[null]>
- define bottom <&0><&l><[choices].get[bottom].get[text].if_null[null]>
#
- if <[choice_dir]> == left:
- if <[left]> == <&0><&l>null:
- stop
- define left "<&4>❤ <&0><&l><[left]>"
- else if <[choice_dir]> == right:
- if <[right]> == <&0><&l>null:
- stop
- define right "<&4>❤ <&0><&l><[right]>"
- else if <[choice_dir]> == top:
- if <[top]> == <&0><&l>null:
- stop
- define top "<&4>❤ <&0><&l><[top]>"
- else:
- if <[bottom]> == <&0><&l>null:
- stop
- define bottom "<&4>❤ <&0><&l><[bottom]>"
#
- define mid_padding <element[<&sp>].repeat[<element[30].sub[<[left].strip_color.length>].sub[<[right].strip_color.length>]>]>
#
- if <[top]> != <&0><&l>null:
- bossbar update textbox_<[player].uuid>_top title:<[top]>
- if <[left]> != <&0><&l>null || <[right]> != <&0><&l>null:
- bossbar update textbox_<[player].uuid>_mid title:<[left]><[mid_padding]><[right]>
- if <[bottom]> != <&0><&l>null:
- bossbar update textbox_<[player].uuid>_bottom title:<[bottom]>
- flag <[player]> textbox_choices:<map[].with[data].as[<[choices]>].with[current].as[<[choice_dir]>]>
- playsound BLOCK_NOTE_BLOCK_BIT <[player]> pitch:2

View File

@@ -0,0 +1,26 @@
liteprofilesutils_command_profiles:
debug: false
type: command
name: profiles
description: Manage your profiles, neatly.
aliases:
- accountmenu
- pfm
usage: /profiles
tab completions:
1: <list[]>
permission: liteprofilesutils.command.profiles
script:
- if <context.source_type> != player:
- narrate "<&c>Run this command as a player"
- stop
- define player <player>
- clickable save:accept usages:1 until:30s:
- flag <[player]> liteprofiles_legacy_menu:!
- run liteprofilesutils_show_menu def.player:<[player]>
- narrate <empty>
- narrate format:formats_prefix "Our profile system lets you own multiple 'unique accounts' by tricking the server to hand you new unique IDs, which may cause the server to incorrectly save your inventory, ranks, or other data."
- narrate <empty>
- narrate "<&c>[<&4><&l>!<&c>] <&7>Consider this feature <&6>experimental<&7>; take screenshots of your items and ranks if you are concerned."
- narrate <element[<&a><&l>[ I UNDERSTAND ]].on_click[<entry[accept].command>]>
- narrate <empty>

View File

@@ -0,0 +1,12 @@
liteprofilesutils_data:
debug: false
type: data
rank-sync:
- owner
- admin
- media
sync-op: true
join-leave:
join: <&8>[<&a>+<&8>] <&7><player.name>
leave: <&8>[<&c>-<&8>] <&7><player.name>
welcome: <&8>[<&6><&l>!<&8>] <&e>Welcome <player.name>!

View File

@@ -0,0 +1,126 @@
liteprofilesutils_load_data:
debug: false
type: task
script:
- ~yaml load:../LiteProfiles/data.yml id:liteprofiles_data
liteprofilesutils_get_master_uuid:
debug: false
type: procedure
definitions: player
script:
- determine <placeholder[liteprofiles_masteruuid].player[<[player]>]>
liteprofilesutils_get_profile_limit:
debug: false
type: procedure
definitions: player
script:
- determine <placeholder[liteprofiles_limit].player[<[player]>]>
liteprofilesutils_get_profile_count:
debug: false
type: procedure
definitions: player
script:
- determine <placeholder[liteprofiles_count].player[<[player]>].sub[1]>
liteprofilesutils_show_menu:
debug: false
type: task
definitions: player
script:
- ~run liteprofilesutils_load_data
- define masteruuid <proc[liteprofilesutils_get_master_uuid].context[<[player]>]>
- define profilelimit <proc[liteprofilesutils_get_profile_limit].context[<[player]>]>
- define profilecount <proc[liteprofilesutils_get_profile_count].context[<[player]>]>
- define contents <list[]>
# master uuid
- define masteritem <item[emerald_block]>
- define mastername <proc[character_get_name].context[<player[<[masteruuid]>]>]>
- if <[mastername]> == null:
- define mastername "Unnamed Character"
- adjust def:masteritem display:<&f><[mastername]>
- adjust def:masteritem lore:<list[<&6>Master Profile|<&f>|<&8>UUID:|<&8><[masteruuid]>]>
- flag <[masteritem]> liteprofiles:<map[].with[type].as[master].with[value].as[<[masteruuid]>]>
- define contents <[contents].include[<[masteritem]>]>
# slave uuids
- define sortedslaveitems <list[]>
- foreach <yaml[liteprofiles_data].read[<[masteruuid]>].keys.exclude[active].exclude[<[masteruuid]>]> as:slaveuuid:
- define slaveitem <item[emerald]>
- define slavename <proc[character_get_name].context[<player[<[slaveuuid]>]>]>
- if <[slavename]> == null:
- define slavename "Unnamed Character"
- adjust def:slaveitem display:<&f><[slavename]>
- adjust def:slaveitem lore:<list[<&e>Alt Profile|<&f>|<&8>UUID:|<&8><[slaveuuid]>]>
- flag <[slaveitem]> liteprofiles:<map[].with[type].as[slave].with[value].as[<[slaveuuid]>]>
- define sortedslaveitems <[sortedslaveitems].include[<[slaveitem]>]>
- define sortedslaveitems <[sortedslaveitems].sort_by_value[display]>
- define contents <[contents].include[<[sortedslaveitems]>]>
# free slots
- if <[profilecount]> < <[profilelimit].sub[1]>:
- define freeitem <item[light_blue_dye]>
- adjust def:freeitem "display:<&b>Free Slot"
- adjust def:freeitem lore:<list[<&f>Click here to create a new profile]>
- flag <[freeitem]> liteprofiles:<map[].with[type].as[free]>
- define contents <[contents].include[<[freeitem]>]>
- repeat <[profilelimit].sub[<[profilecount]>]>:
- define unuseditem <item[gray_dye]>
- adjust def:unuseditem "display:<&7>Free Slot"
- define contents <[contents].include[<[unuseditem]>]>
# show
- run liteprofiles_legacy_menus_open def.player:<[player]> def.id:liteprofiles def.page:0 def.contents:<[contents]>
# # # # # # # # # # # # # # # # # # # # # # # # #
# LEGACY MENU LIBRARY PROVIDED IN LITEPROFILES #
# # # # # # # # # # # # # # # # # # # # # # # # #
# buttons
liteprofiles_legacy_menus_button_previous:
debug: false
type: item
material: ender_pearl
display name: <&a><&lt><&lt>
liteprofiles_legacy_menus_button_next:
debug: false
type: item
material: ender_eye
display name: <&a><&gt><&gt>
# generate menu
liteprofiles_legacy_menus_open:
debug: false
type: task
definitions: player|id|page|contents
script:
- define inventory <inventory[generic[title=<&f>邑邑邑邑鄈;size=18]]>
- foreach <[contents].get[<[page].mul[9].add[1]>].to[<[page].add[1].mul[9]>].if_null[<list[]>]> as:item:
- inventory set origin:<[item]> destination:<[inventory]> slot:<[loop_index]>
- if <[page]> > 0:
- inventory set origin:<item[liteprofiles_legacy_menus_button_previous]> destination:<[inventory]> slot:13
- if <[contents].size> > <[page].add[1].mul[9]>:
- inventory set origin:<item[liteprofiles_legacy_menus_button_next]> destination:<[inventory]> slot:15
- flag <[player]> liteprofiles_legacy_menu:<map[].with[id].as[<[id]>].with[page].as[<[page]>].with[contents].as[<[contents]>]>
- define profilelimit <proc[liteprofilesutils_get_profile_limit].context[<[player]>]>
- inventory set origin:<item[paper[display=<&6>How to use;lore=<&7>Your master profile is your original UUID (your main account).|<&7>You will see your other profiles in the menu. Click on any button|<&7>to change to that profile.|<&f>|<&7>You may also create new profiles if you have free slots.|<&7>You currently own <&e><[profilelimit]> profiles<&7>. You may obtain more|<&7>with donation ranks or for animal characters.]]> destination:<[inventory]> slot:10
- inventory open player:<[player]> destination:<[inventory]>
# menu button handler
liteprofiles_legacy_menus_button_handler:
debug: false
type: world
events:
on player clicks in inventory:
- if <context.inventory.title> != <&f>邑邑邑邑鄈:
- stop
- determine cancelled passively
# if air ignore, means button doesnt exist or is to be handled elsewhere
# 13 prev 15 next everything else ignore
- if <context.slot> == 13:
- if <context.item.material.advanced_matches[ender_pearl]>:
- define data <player.flag[liteprofiles_legacy_menu]>
- run liteprofiles_legacy_menus_open def.player:<player> def.id:<[data].get[id]> def.page:<[data].get[page].sub[1]> def.contents:<[data].get[contents]>
- if <context.slot> == 15:
- if <context.item.material.advanced_matches[ender_eye]>:
- define data <player.flag[liteprofiles_legacy_menu]>
- run liteprofiles_legacy_menus_open def.player:<player> def.id:<[data].get[id]> def.page:<[data].get[page].add[1]> def.contents:<[data].get[contents]>

View File

@@ -0,0 +1,95 @@
liteprofilesutils_world:
debug: false
type: world
events:
## load YAML data
after server start:
- ~run liteprofilesutils_load_data
## patch join/leave & rank sync
on player quits:
- define masteruuid <proc[liteprofilesutils_get_master_uuid].context[<player>]>
- define profilelimit <placeholder[liteprofiles_limit]>
#
- flag server liteprofilesutils_lastseengroups:<server.flag[liteprofilesutils_lastseengroups].if_null[<map[]>].with[<[masteruuid]>].as[<player.groups>]>
#
- define lastbestlimit <server.flag[liteprofilesutils_lastbestlimit].if_null[<map[]>]>
- flag server liteprofilesutils_lastbestlimit:<[lastbestlimit].with[<[masteruuid]>].as[<[profilelimit].max[<[lastbestlimit].get[<[masteruuid]>].if_null[1]>]>]>
#
- define joinleavedata <script[liteprofilesutils_data].data_key[join-leave]>
- announce <[joinleavedata].get[leave].parsed>
on player joins:
- define masteruuid <proc[liteprofilesutils_get_master_uuid].context[<player>]>
# sync groups, O(scary)
- define syncgroupdata <script[liteprofilesutils_data].data_key[rank-sync]>
- define lastseengroups <server.flag[liteprofilesutils_lastseengroups].get[<[masteruuid]>].if_null[<list[]>]>
- if <[lastseengroups].is_empty>:
- goto joinmessage
- foreach <[lastseengroups].include[<player.groups>]> as:trygroup:
- define ok false
- foreach <[syncgroupdata]> as:matchgroup:
- if <[trygroup].advanced_matches[<[matchgroup]>]>:
- define ok true
- foreach stop
- if !<[ok]>:
- foreach next
- if <[lastseengroups].contains[<[trygroup]>]>:
- if !<player.in_group[<[trygroup]>]>:
- group add <[trygroup]>
- else:
- if <player.in_group[<[trygroup]>]>:
- group remove <[trygroup]>
- if !<player.in_group[default]>:
- group add default
# sync best perm level
- define bestlimit <server.flag[liteprofilesutils_lastbestlimit].get[<[masteruuid]>].if_null[1]>
- if !<player.has_permission[liteprofiles.limit.<[bestlimit]>]>:
- permission add liteprofiles.limit.<[bestlimit]>
# sync op
- if <player[<[masteruuid]>].is_op>:
- adjust <player> is_op:true
- else:
- adjust <player> is_op:false
# sync whitelist
- if <player[<[masteruuid]>].whitelisted>:
- adjust <player> whitelisted:true
- else:
- adjust <player> whitelisted:false
# adjust join message
- mark joinmessage
- define joinleavedata <script[liteprofilesutils_data].data_key[join-leave]>
- if <player.uuid> == <[masteruuid]>:
- if <server.flag[liteprofilesutils_welcome].if_null[<list[]>].contains[<player.uuid>]>:
- announce <[joinleavedata].get[welcome].parsed>
- flag server liteprofilesutils_welcome:<server.flag[liteprofilesutils_welcome].if_null[<list[]>].include[<player.uuid>]>
- announce <[joinleavedata].get[join].parsed>
## prevent /profile remove
on command:
- if <context.command.to_lowercase> == profile || <context.command.to_lowercase> == account || <context.command.to_lowercase> == pf:
- if <context.args.get[1].to_lowercase.if_null[null]> == remove:
- determine cancelled passively
- narrate "<&c>You are forbidden from performing this operation."
## GUI menu
on player clicks in inventory bukkit_priority:low:
- if <context.inventory.title> != <&f>邑邑邑邑鄈:
- stop
- if <player.flag[liteprofiles_legacy_menu].get[id].if_null[null]> != liteprofiles:
- stop
- if <context.slot> > 45:
- stop
- if <context.item.advanced_matches[air]>:
- stop
# logic
- define data <context.item.flag[liteprofiles].if_null[null]>
- if <[data]> == null:
- stop
- if <[data].get[type]> == master:
- define value <[data].get[value]>
- inventory close
- execute as_player "profile use <[value]>"
- else if <[data].get[type]> == slave:
- define value <[data].get[value]>
- inventory close
- execute as_player "profile use <[value]>"
- else if <[data].get[type]> == free:
- execute as_player "profile add"
- run liteprofilesutils_show_menu def.player:<player>

View File

@@ -0,0 +1,38 @@
compatibility_check_compare_versions:
debug: false
type: procedure
definitions: version1|version2
script:
- define v1split <[version1].split[.]>
- define v2split <[version2].split[.]>
- foreach <[v1split]> as:v1splitpart:
- define v2splitpart <[v2split].get[<[loop_index]>].if_null[0]>
- if <[v1splitpart]> > <[v2splitpart]>:
- determine 1
- if <[v1splitpart]> < <[v2splitpart]>:
- determine -1
- if <[v2split].size> > <[v1split].size>:
- determine -1
- determine 0
compatibility_check_world:
debug: false
type: world
events:
after player joins:
- define player_version <player.viaversion_version.split[-].get[1].split[.].limit[3].get[1|2].separated_by[.]>
- define server_version <server.version.split[(].get[2].split[:].get[2].split[)].get[1].trim.split[.].limit[3].get[1|2].separated_by[.]>
- if <proc[compatibility_check_compare_versions].context[<[player_version]>|<[server_version]>]> == -1:
- wait 5s
- if !<player.is_online>:
- stop
- narrate ""
- narrate "<&c><&l>[<&4><&l>!<&c><&l>] <&c>You are using an outdated Minecraft version!"
- narrate "<&6>Your version: <&f><[player_version]>"
- narrate "<&6>Server version: <&f><[server_version]>"
- narrate ""
- narrate "<&f>You can still play, however we strongly encourage you to consider <&e>updating your game<&f>."
- narrate "<&f>We will not offer bug support if you are using an outdated version!"
- narrate ""
- narrate "<&7>(Your ViaVersion protocol: <player.viaversion_protocol>)"
- narrate ""

BIN
scripts/payto/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,34 @@
payto_command_payto:
debug: false
type: command
name: payto
usage: /payto (amount)
description: Pays the player you're looking at.
permission: essentials.pay
tab completions:
1: <&lt>amount<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> <= 0:
- narrate "<&c>Please enter an amount to pay!"
- stop
- define amount <context.args.get[1]>
- if !<context.args.get[1].is_decimal>:
- narrate "<&c>You must enter a number to pay!"
- stop
- if <player.money> < <context.args.get[1]>:
- narrate "<&c>You don't have <context.args.get[1].as_money>."
- stop
- define target <player.target[player].within[8].if_null[null]>
- if <[target]> == null:
- narrate "<&c>Please look at a player to send money to."
- stop
- if <[target].is_npc>:
- narrate "<&c>Please look at a player to send money to."
- stop
- clickable usages:1 until:1m save:pay:
- execute as_player "pay <[target].name> <[amount]>"
- narrate format:formats_prefix "<&7>Would you like to pay <&6><[amount].as_money><&7> to <&6><proc[character_get_name].context[<[target]>]>"
- narrate "<element[<&a><&l>[CLICK HERE]].on_click[<entry[pay].command>]>"

View File

@@ -0,0 +1,544 @@
## CALL
phones_commands_phonecall:
debug: false
type: command
name: phonecall
aliases:
- call
description: Call using a phone!
usage: /phonecall (number/contact/message)
permission: phones.command.phonecall
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- determine <list[<&lt>message<&gt>]>
- determine <player.flag[phones].get[contacts].keys.if_null[<list[]>]>
script:
# checks...
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define incall <player.has_flag[phones_call_clickable].not.and[<player.has_flag[phones_call]>]>
# mid call?
- if !<[incall]>:
# waiting call?
- if <player.has_flag[phones_call_clickable]>:
- narrate "<&c>Please wait for the call to be accepted, or unequip to cancel the call."
- stop
# no
- if <context.args.size> < 1:
- narrate "<&c>Invalid use. First, call a number. Please try /<context.alias> (number/contact)."
- stop
# definitions
- define receiver <context.args.get[1]>
- define target <proc[phones_get_owner].context[<player>|<[receiver]>]>
- if !<player.item_in_hand.flag[phones].if_null[false]>:
- narrate "<&c>Please hold a phone in your hand, and ensure it is powered on."
- stop
# invalid number/contact
- if <[target]> == null:
- narrate "<&c>Invalid phone number or contact <[receiver]>. Please try again."
- stop
# lmao
- if <player> == <[target]>:
- narrate "<&c>You can't call yourself!"
- stop
# blocked
- if <player.flag[phones].get[blocked].contains[<[target]>].if_null[false]>:
- narrate "<&c>The receiver is currently in your blocked numbers."
- stop
- if <[target].flag[phones].get[blocked].contains[<player>].if_null[false]>:
- narrate "<&c>The receiver is unable to be contacted at this time. Try again later."
- stop
# not online/no phone/phone is off/etc...
- if !<proc[phones_has_phone].context[<[target]>]>:
- narrate "<&c>The receiver is unable to be contacted at this time. Try again later."
- stop
# mid call...
- if <[target].has_flag[phones_call]>:
- narrate "<&c>The receiver is currently busy. Try again later."
- stop
# call...
- define relative <proc[phones_relative_name].context[<[target]>|<player>]>
- define player <player>
# if accepted, go in
- clickable save:accept until:30s:
- if !<[target].item_in_hand.flag[phones].if_null[false]>:
- narrate targets:<[target]> "<&c>Please hold a phone before accepting the call, and ensure it is powered on."
- stop
- nbs stop targets:<[target]>
- clickable cancel:<[player].flag[phones_call_clickable]>
- flag <[target]> phones_call:<[player]>
- flag <[player]> phones_call:<[target]>
- flag <[player]> phones_call_clickable:!
- flag <[target]> phones_is_maybe_called:!
- narrate targets:<[player]> "<&2>*** <&a><[receiver]> <&a>picked up the phone."
- narrate targets:<[target]> "<&2>*** <&a>You picked up the phone."
- define callgroup <list[<[player]>|<[target]>]>
- narrate targets:<[callgroup]> <&f>
- narrate targets:<[callgroup]> "<&7>Talk using <&e>/call (message)<&7>."
- narrate targets:<[callgroup]> "<&e>Unequip <&7>your phone to <&c>end <&7>the call."
- narrate targets:<[callgroup]> <&f>
#
# before accepted
- if !<[target].has_flag[phones_is_maybe_called]>:
- nbs file:data/phones/songs/<[target].flag[phones].get[ringtone].if_null[Bad Apple]> play targets:<[target]>
- narrate targets:<[target]> "<&6>*** <&e>You're being called by <&e><[relative]><&7>."
- narrate targets:<[target]> "<&hover[<&a>Click to accept call from <[relative]>...]><element[<&a><&l>[ ACCEPT ]].on_click[<entry[accept].command>]><&end_hover>"
# wait...
- flag <player> phones_call:<[target]>
- flag <player> phones_call_clickable:<entry[accept].id>
- flag <[target]> phones_is_maybe_called:true expire:30s
- narrate "<&6>*** <&e>You started to ring <&7><[receiver]>"
- narrate "<&7>Unequip your phone to cancel the call."
- else:
# yes
- if <context.args.size> < 1:
- narrate "<&c>Invalid use. You are mid-call - please try /<context.alias> (message)."
- narrate "<&7>Note: you can unequip the phone to end the current call."
- stop
# definitions
- define target <player.flag[phones_call]>
- define message <context.args.get[1].to[last].space_separated>
# speak...
- define final "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>says <&dq><[message]><&f><&dq> over the phone."
- narrate targets:<player.location.find_players_within[10].include[<[target]>].deduplicate> <[final]>
## callw, cally use similar routines
phones_command_call_common_routine:
debug: false
type: task
script:
# checks...
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- define continue false
- stop
- define incall <player.has_flag[phones_call_clickable].not.and[<player.has_flag[phones_call]>]>
# mid call?
- if !<[incall]>:
# waiting call?
- if <player.has_flag[phones_call_clickable]>:
- narrate "<&c>Please wait for the call to be accepted, or unequip to cancel the call."
- define continue false
- stop
# no
- narrate "<&c>Invalid use. First, call a number. Please try /call (number/contact)."
- define continue false
- else:
# yes
- if <context.args.size> < 1:
- narrate "<&c>Invalid use. You are mid-call - please try /<context.alias> (message)."
- narrate "<&7>Note: you can unequip the phone to end the current call."
- define continue false
- stop
# definitions
- define target <player.flag[phones_call]>
- define message <context.args.get[1].to[last].space_separated>
phones_command_phonecallwhisper:
debug: false
type: command
name: phonecallwhisper
aliases:
- callwhisper
- callw
description: Whisper over the phone while in a call.
usage: /phonecallwhisper (message)
permission: phones.command.phonecallwhisper
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- determine <list[<&lt>message<&gt>]>
- determine <list[]>
script:
- define continue true
- inject phones_command_call_common_routine
- if !<[continue]>:
- stop
# speak...
- define final "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&8>whispers <&6><&sq><&7><[message]><&6><&sq> <&8>over the phone."
- narrate targets:<player.location.find_players_within[3].include[<[target]>].deduplicate> <[final]>
phones_command_phonecallyell:
debug: false
type: command
name: phonecallyell
aliases:
- callyell
- cally
description: Yell over the phone while in a call.
usage: /phonecallyell (message)
permission: phones.command.phonecallyell
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- determine <list[<&lt>message<&gt>]>
- determine <list[]>
script:
- define continue true
- inject phones_command_call_common_routine
- if !<[continue]>:
- stop
# speak...
- define final "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&6>yells <&sq><&f><[message].to_uppercase><&6><&sq> over the phone."
- narrate targets:<player.location.find_players_within[25].include[<[target]>].deduplicate> <[final]>
## langcall, langcallw, langcally use similar routines
phones_command_call_language_common_routine:
debug: false
type: task
script:
# checks...
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- define continue false
- stop
- define incall <player.has_flag[phones_call_clickable].not.and[<player.has_flag[phones_call]>]>
# mid call?
- if !<[incall]>:
# waiting call?
- if <player.has_flag[phones_call_clickable]>:
- narrate "<&c>Please wait for the call to be accepted, or unequip to cancel the call."
- define continue false
- stop
# no
- narrate "<&c>Invalid use. First, call a number. Please try /call (number/contact)."
- define continue false
- else:
# yes
- if <context.args.size> < 2:
- narrate "<&c>Invalid use. You are mid-call - please try /<context.alias> (language) (message)."
- narrate "<&7>Note: you can unequip the phone to end the current call."
- define continue false
- stop
# definitions
- define target <player.flag[phones_call]>
- define language <context.args.get[1].to_sentence_case>
- if !<player.flag[chat_languages].contains[<[language]>].if_null[false]>:
- narrate "<&c>Your character cannot speak in <[language]>."
- define continue false
- stop
- define message <context.args.get[2].to[last].space_separated>
phones_command_phonelangcall:
debug: false
type: command
name: phonelangcall
aliases:
- langcall
description: Speak over the phone in a different language.
usage: /phonelangcall (language) (message)
permission: phones.command.phonelangcall
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- if <context.args.size> <= 0:
- determine <player.flag[chat_languages].if_null[<list[]>]>
- if <context.args.size> <= 1:
- determine <list[<&lt>message<&gt>]>
- determine <list[]>
script:
- define continue true
- inject phones_command_call_language_common_routine
- if !<[continue]>:
- stop
# speak...
- define final_known "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>says <&dq><&o><[message]><&f><&dq> in <[language]> over the phone."
- define final_unknown "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>says something in <[language]> over the phone."
- define all <player.location.find_players_within[10].include[<[target]>].deduplicate>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
phones_command_phonelangcallwhisper:
debug: false
type: command
name: phonelangcallwhisper
aliases:
- langcallwhisper
- langcallw
description: Whisper over the phone in a different language.
usage: /phonelangcallwhisper (language) (message)
permission: phones.command.phonelangcallwhisper
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- if <context.args.size> <= 0:
- determine <player.flag[chat_languages].if_null[<list[]>]>
- if <context.args.size> <= 1:
- determine <list[<&lt>message<&gt>]>
- determine <list[]>
script:
- define continue true
- inject phones_command_call_language_common_routine
- if !<[continue]>:
- stop
# speak...
- define final_known "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>whispers <&dq><&o><[message]><&f><&dq> in <[language]> over the phone."
- define final_unknown "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>whispers something in <[language]> over the phone."
- define all <player.location.find_players_within[3].include[<[target]>].deduplicate>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
phones_command_phonelangcallyell:
debug: false
type: command
name: phonelangcallyell
aliases:
- langcallyell
- langcally
description: Yell over the phone in a different language.
usage: /phonelangcallyell (language) (message)
permission: phones.command.phonelangcallyell
tab complete:
- if <context.server>:
- determine <list[]>
- if <player.has_flag[phones_call]>:
- if <context.args.size> <= 1:
- determine <player.flag[chat_languages].if_null[<list[]>]>
- if <context.args.size> <= 2:
- determine <list[<&lt>message<&gt>]>
- determine <list[]>
script:
- define continue true
- inject phones_command_call_language_common_routine
- if !<[continue]>:
- stop
# speak...
- define final_known "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>yells <&dq><&o><[message].to_uppercase><&f><&dq> in <[language]> over the phone."
- define final_unknown "<&6>[<&7>P<&6>] <&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&f>yells something in <[language]> over the phone."
- define all <player.location.find_players_within[25].include[<[target]>].deduplicate>
- define speakers <[all].filter_tag[<[filter_value].flag[chat_languages].contains[<[language]>].if_null[false]>]>
- define others <[all].exclude[<[speakers]>]>
- narrate targets:<[speakers]> <[final_known]>
- narrate targets:<[others]> <[final_unknown]>
## PHONE UTILITIES
phones_commands_phonenumber:
debug: false
type: command
name: phonenumber
aliases:
- number
- pn
description: View your phone number.
usage: /phonenumber
permission: phones.command.phonenumber
script:
# checks...
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
# ok
- define number <player.flag[phones].get[number]>
- narrate format:formats_prefix <proc[phones_nicer_format].context[<[number]>]>
## PHONE CONTACTS
phones_commands_phonecontacts:
debug: false
type: command
name: phonecontacts
aliases:
- contacts
description: View your contacts.
usage: /phonecontacts (page)
permission: phones.command.contacts
tab completions:
1: <&lt>page<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define contacts <player.flag[phones].get[contacts].if_null[<map[]>]>
- if <[contacts].is_empty>:
- run phones_contacts_print def.player:<player> def.page:0
- stop
- define page 0
- if <context.args.size> >= 1:
- define page <context.args.get[1]>
- if !<[page].is_integer>:
- narrate "<&c>The page must be an integer between 1 and <[contacts].size.sub[1].div_int[6].add[1]>."
- stop
- define page <[page].sub[1]>
- if <[page]> < 0 || <[page]> > <[contacts].size.sub[1].div_int[6]>:
- narrate "<&c>The page must be an integer between 1 and <[contacts].size.sub[1].div_int[6].add[1]>."
- stop
- run phones_contacts_print def.player:<player> def.page:<[page]>
phones_commands_phoneaddcontact:
debug: false
type: command
name: phoneaddcontact
aliases:
- addcontact
- ac
description: Add a contact.
usage: /phoneaddcontact (number) (name)
permission: phones.command.phoneaddcontact
tab completions:
1: <&lt>number<&gt>
2: <&lt>unique name<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> < 2:
- narrate "<&c>Invalid use. Please try /<context.alias> (number) (name)."
- stop
- define number <context.args.get[1].replace[-].with[]>
- define isnumber <[number].regex_matches[^[0-9]+$]>
- if !<[isnumber]> || !<server.flag[phones].contains[<[number]>]>:
- narrate "<&c>Number <context.args.get[1]> <&c>is not a valid number. Did you type it correctly?"
- stop
- define name <context.args.get[2].to_lowercase>
- define isvalid <[name].regex_matches[^[a-z_]+$]>
- if !<[isvalid]>:
- narrate "<&c>Name <context.args.get[2]> <&c>is invalid. Contact names must only contain alphabetical characters and/or the underscore (_) character."
- stop
- if <player.flag[phones].get[contacts].contains[<[name]>].if_null[false]>:
- narrate "<&c>You already have a contact named <[name]><&c>. Please pick a new name or manage your contacts from your home screen."
- stop
- define target <server.flag[phones].get[<[number]>]>
- if <[target]> == <player>:
- narrate "<&c>You can't add yourself as a contact!"
- stop
- if <player.flag[phones].get[contacts].values.contains[<[target]>].if_null[false]>:
- define found
- foreach <player.flag[phones].get[contacts]> key:whoname as:who:
- if <[who]> == <[target]>:
- define found <[whoname]>
- foreach stop
- narrate "<&c>You already have this contact added, using the contact name: <[found]><&c>."
- stop
- define contacts <player.flag[phones].get[contacts].if_null[<map[]>]>
- define contacts <[contacts].with[<[name]>].as[<[target]>]>
- flag <player> phones:<player.flag[phones].with[contacts].as[<[contacts]>]>
- narrate format:formats_prefix "Added new contact <[name]> <&7>, targetting phone number <[number]>."
phones_commands_phoneremovecontact:
debug: false
type: command
name: phoneremovecontact
aliases:
- removecontact
- rc
description: Remove a contact.
usage: /phoneremovecontact (number) (name)
permission: phones.command.phoneremovecontact
tab completions:
1: <player.flag[phones].get[contacts].keys.if_null[<list[]>]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> < 1:
- narrate "<&c>Invalid use. Please try /<context.alias> (name)."
- stop
- define name <context.args.get[1].to_lowercase>
- if !<player.flag[phones].get[contacts].contains[<[name]>].if_null[false]>:
- narrate "<&c>You do not have a contact named <[name]>."
- stop
- define contacts <player.flag[phones].get[contacts].if_null[<map[]>]>
- define contacts <[contacts].exclude[<[name]>]>
- flag <player> phones:<player.flag[phones].with[contacts].as[<[contacts]>]>
- narrate format:formats_prefix "Removed contact <&e><[name]><&7>."
## TEXT MESSAGES
phones_commands_phonetext:
debug: false
type: command
name: phonetext
aliases:
- text
description: Text a number or a contact!
usage: /phonetext (number/contact) (message)
permission: phones.command.phonetext
tab completions:
1: <player.flag[phones].get[contacts].keys.if_null[<list[]>]>
2: <&lt>message<&gt>
script:
# checks...
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> < 2:
- narrate "<&c>Invalid use. Please try /<context.alias> (number/contact) (message)."
- stop
# definitions
- define receiver <context.args.get[1].replace[-].with[]>
- define message <context.args.get[2].to[last].space_separated>
- define target <proc[phones_get_owner].context[<player>|<[receiver]>]>
# no phone
- if !<player.item_in_hand.flag[phones].if_null[false]>:
- narrate "<&c>Please hold a phone in your hand, and ensure it is powered on."
- stop
# invalid number/contact
- if <[target]> == null:
- narrate "<&c>Invalid phone number or contact <&e><[receiver]><&c>. Please try again."
- stop
# lmao
- if <player> == <[target]>:
- narrate "<&c>You can't text yourself!"
- stop
# blocked
- if <player.flag[phones].get[blocked].contains[<[target]>].if_null[false]>:
- narrate "<&c>The receiver is currently in your blocked numbers."
- stop
- if <[target].flag[phones].get[blocked].contains[<player>].if_null[false]>:
- narrate "<&c>The receiver is unable to be contacted at this time. Try again later."
- stop
# send text...
- run phones_texts_store def.player:<player> def.target:<[target]> def.contents:<[message]>
## BLOCKED
phones_commands_phoneblock:
debug: false
type: command
name: phoneblock
aliases:
- phoneunblock
- phblock
- phunblock
description: Add a contact.
usage: /phoneblock (number))
permission: phones.command.phoneblock
tab completions:
1: <list[<&lt>number<&gt>].include[<player.flag[phones].get[blocked].parse_tag[<[parse_value].flag[phones].get[number]>].if_null[<list[]>]>]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> < 1:
- narrate "<&c>Invalid use. Please try /<context.alias> (number)."
- stop
#
- define number <context.args.get[1].replace[-].with[]>
- define isnumber <[number].regex_matches[^[0-9]+$]>
- if !<[isnumber]> || !<server.flag[phones].contains[<[number]>]>:
- narrate "<&c>Number <context.args.get[1]> <&c>is not a valid number. Did you type it correctly?"
- stop
#
- define target <server.flag[phones].get[<[number]>]>
- if <[target]> == <player>:
- narrate "<&c>You can't block your own phone number!"
- stop
#
- if !<player.flag[phones].get[blocked].contains[<[target]>].if_null[false]>:
- define blocked <player.flag[phones].get[blocked].if_null[<list[]>]>
- define blocked <[blocked].include[<[target]>]>
- flag <player> phones:<player.flag[phones].with[blocked].as[<[blocked]>]>
- narrate format:formats_prefix "<&c>Blocked <&7>phone number <&e><[number]><&7>."
- else:
- define blocked <player.flag[phones].get[blocked].if_null[<list[]>]>
- define blocked <[blocked].exclude[<[target]>]>
- flag <player> phones:<player.flag[phones].with[blocked].as[<[blocked]>]>
- narrate format:formats_prefix "<&a>Unblocked <&7>phone number <&e><[number]><&7>."

View File

@@ -0,0 +1,455 @@
####
## GENERAL STUFF
####
phones_get_owner:
debug: false
type: procedure
definitions: player|receiver
script:
- define receiver <[receiver].replace[(].with[].replace[)].with[].replace[-].with[]>
- define isnumber <[receiver].regex_matches[^[0-9]+$]>
- define target null
- if <[isnumber]>:
- define target <server.flag[phones].get[<[receiver]>].if_null[null]>
- else:
- define target <[player].flag[phones].get[contacts].get[<[receiver]>].if_null[null]>
- determine <[target]>
phones_has_phone:
debug: false
type: procedure
definitions: player
script:
- if !<[player].is_online>:
- determine false
- foreach <[player].inventory.map_slots> key:slot as:item:
- if <[item].flag[phones].if_null[false]>:
- determine true
- determine false
phones_relative_name:
debug: false
type: procedure
definitions: player|who
script:
- if <[player].flag[phones].get[contacts].values.contains[<[who]>].if_null[false]>:
- determine <[player].flag[phones].get[contacts].filter_tag[<[filter_value].equals[<[who]>]>].keys.get[1]>
- determine <[who].flag[phones].get[number]>
phones_clean_message:
debug: false
type: procedure
definitions: message
script:
- define clean <empty>
# remove channel marker
- if <[message].starts_with[#]>:
- define message <[message].substring[3]>
# format actions
- foreach <[message].split[*]> as:section:
- if <[section].trim.length> == 0:
- foreach next
- if <[loop_index].is_odd>:
- define clean "<[clean]> <&f><&dq><[section].trim><&f><&dq>"
- else:
- define clean "<[clean]> <&e><[section].trim>"
# good
- determine <[clean].trim>
phones_get_contact_state:
debug: false
type: procedure
definitions: player|target
script:
- if <[target].flag[phones].get[contacts].values.contains[<[player]>].if_null[false]>:
- if <[target].is_online>:
- if <proc[phones_has_phone].context[<[target]>]>:
- determine online
- determine offline
- determine invisible
phones_nicer_format:
debug: false
type: procedure
definitions: number
script:
- determine "<&7>(+81) <&e>(<[number].substring[1,3]>)-<[number].substring[4,6]>-<[number].substring[7,10]>"
phones_get_number:
debug: false
type: procedure
definitions: player
script:
- determine <[player].flag[phones].get[number]>
####
## GUIS
####
phones_gui_home:
debug: false
type: task
definitions: player
script:
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&0>邒]]>"
# settings
- define settings <item[name_tag]>
- adjust def:settings "display:<&6>Settings"
- inventory set destination:<[inventory]> slot:13 origin:<[settings]>
# contacts
- define contacts <item[book]>
- adjust def:contacts "display:<&6>Contacts"
- inventory set destination:<[inventory]> slot:14 origin:<[contacts]>
# texts
- define texts <item[writable_book]>
- adjust def:texts "display:<&6>Messages"
- define notifications_textmessages <[player].flag[phones_notifications].get[textmessages].values.size.if_null[null]>
- if <[notifications_textmessages]> != null && <[notifications_textmessages]> != 0:
- if <[notifications_textmessages]> > 99:
- define notifications_textmessages 99+
- adjust texts lore:<list[<&c>● <&7>You have <&6><[notifications_textmessages]> <&7>unread|<&7>text conversations.]>
- inventory set destination:<[inventory]> slot:15 origin:<[texts]>
# music
- define music <item[jukebox]>
- adjust def:music "display:<&6>Blocky Music <&3>♫"
- adjust def:music "lore:<&7>(music from <&e>noteblock.world<&7>)"
- inventory set destination:<[inventory]> slot:22 origin:<[music]>
# number
- define number <item[player_head]>
- adjust def:number "display:<&6>Your Number"
- adjust def:number lore:<list[<&e><proc[phones_nicer_format].context[<[player].flag[phones].get[number]>]>||<&7>You may also view your number|<&7>using /phonenumber.]>
- flag <[number]> phones_target_skull_uuid:<[player].uuid>
- inventory set destination:<[inventory]> slot:41 origin:<[number]>
#
- inventory open player:<[player]> destination:<[inventory]>
- run phones_target_skulls_update def.player:<[player]>
# ---
# --- contacts related
# ---
phones_contacts_print:
debug: false
type: task
definitions: player|page
script:
- define contacts <[player].flag[phones].get[contacts].if_null[<map[]>]>
- if <[contacts].is_empty>:
- narrate targets:<[player]> format:formats_prefix "You don't have any contacts."
- stop
- define contactslist <[contacts].keys.get[<[page].mul[6].add[1]>].to[<[page].add[1].mul[6]>].if_null[<list[]>]>
- narrate targets:<[player]> format:formats_prefix "<&e>OpenPhones Contacts<&nl>"
# show contacts
- foreach <[contactslist]> as:receiver:
- define target <[contacts].get[<[receiver]>]>
# state
- define contactstate <proc[phones_get_contact_state].context[<[player]>|<[target]>]>
- if <[contactstate]> == invisible:
- define contactstate <&7>⏺
- else if <[contactstate]> == online:
- define contactstate <&a>⏺
- else if <[contactstate]> == offline:
- define contactstate <&c>⏺
#
- define contact "<[contactstate]> <&e><proc[phones_nicer_format].context[<proc[phones_get_number].context[<[target]>]>]> <&7><&o>(<[receiver]>)"
- narrate <[contact]>
# page buttons
- define prevpage <&7><&lt>--
- define nextpage <&7>--<&gt>
- if <[page]> > 0:
- clickable usages:1 until:60s save:prev:
- execute as_player "phonecontacts <[page]>"
- define prevpage "<element[<&a><&lt>--].on_click[<entry[prev].command>]>"
- if <[contacts].size> > <[page].add[1].mul[6]>:
- clickable usages:1 until:60s save:next:
- execute as_player "phonecontacts <[page].add[2]>"
- define nextpage "<element[<&a>--<&gt>].on_click[<entry[next].command>]>"
- narrate targets:<[player]> "<&nl><[prevpage]> <&6>Page <[page].add[1]>/<[contacts].size.sub[1].div[6].round_down.add[1]> <[nextpage]>"
# ---
# --- texts related
# ---
phones_texts_store:
debug: false
type: task
definitions: player|target|contents
script:
- narrate targets:<[player]> format:formats_prefix "Sending..."
#
- define playertexts phones_texts_<[player].uuid>_<[target].uuid>
- if <util.has_file[data/phones/texts/<[player].uuid>_<[target].uuid>.yml]>:
- ~yaml id:<[playertexts]> load:data/phones/texts/<[player].uuid>_<[target].uuid>.yml
- else:
- ~yaml id:<[playertexts]> create
- yaml id:<[playertexts]> set messages.<util.time_now.escaped>:<map[].with[origin].as[sender].with[value].as[<[contents]>]>
- ~yaml savefile:data/phones/texts/<[player].uuid>_<[target].uuid>.yml id:<[playertexts]>
- ~yaml id:phones_texts_<[player].uuid>_<[target].uuid> unload
#
- define targettexts phones_texts_<[target].uuid>_<[player].uuid>
- if <util.has_file[data/phones/texts/<[target].uuid>_<[player].uuid>.yml]>:
- ~yaml id:<[targettexts]> load:data/phones/texts/<[target].uuid>_<[player].uuid>.yml
- else:
- ~yaml id:<[targettexts]> create
- yaml id:<[targettexts]> set messages.<util.time_now.escaped>:<map[].with[origin].as[receiver].with[value].as[<[contents]>]>
- ~yaml savefile:data/phones/texts/<[target].uuid>_<[player].uuid>.yml id:<[targettexts]>
- ~yaml id:phones_texts_<[target].uuid>_<[player].uuid> unload
# send
- define relative <proc[phones_relative_name].context[<[player]>|<[target]>]>
- narrate targets:<[player]> "<&6>[<&7>T<&6>] <&e>You ➠ <[relative]> <&2>sent '<[contents]>' via text"
# notify or send
- if <[target].is_online>:
- if <[target].item_in_hand.has_flag[phones]>:
- define inverserelative <proc[phones_relative_name].context[<[target]>|<[player]>]>
- narrate targets:<[target]> "<&6>[<&7>T<&6>] <&e><[inverserelative]> ➠ You <&2>sent '<[contents]>' via text"
- else:
- narrate targets:<[target]> "<&6>[<&7>T<&6>] <&e>You received a text message."
- else:
- define notifications <[target].flag[phones_notifications].if_null[<map[]>]>
- define textnotifications <[notifications].get[textmessages].if_null[<map[]>]>
- define textnotifications <[textnotifications].with[<[player]>].as[<[textnotifications].get[<[player]>].if_null[0].add[1]>]>
- define notifications <[notifications].with[textmessages].as[<[textnotifications]>]>
- flag <[target]> phones_notifications:<[notifications]>
phones_texts_print:
debug: false
type: task
definitions: player|target|page
script:
- narrate targets:<[player]> format:formats_prefix "Loading..."
#
- define playertexts phones_texts_<[player].uuid>_<[target].uuid>
- ~yaml id:<[playertexts]> load:data/phones/texts/<[player].uuid>_<[target].uuid>.yml
- define messages_size <yaml[<[playertexts]>].read[messages].size>
- define message_keys <yaml[<[playertexts]>].read[messages].keys.reverse.get[<[page].mul[5].add[1]>].to[<[page].add[1].mul[5]>].if_null[<list[]>]>
- define messages <map[]>
- foreach <[message_keys]> as:timestamp:
- define messages <[messages].with[<time[<[timestamp].unescaped>]>].as[<yaml[<[playertexts]>].read[messages.<[timestamp]>]>]>
- ~yaml id:phones_texts_<[player].uuid>_<[target].uuid> unload
#
- define relative <proc[phones_relative_name].context[<[player]>|<[target]>]>
- narrate targets:<[player]> format:formats_prefix "<&e>Messages with <[relative]><&nl>"
- foreach <[messages]> key:timestamp as:message:
- define when <util.time_now.duration_since[<[timestamp]>].formatted>
- if <[message].get[origin]> == sender:
- narrate targets:<[player]> "<&7>You: <&f><[message].get[value]> <&7>(<[when]> ago)"
- else:
- narrate targets:<[player]> "<&e><[relative]><&7>: <&f><[message].get[value]> <&7>(<[when]> ago)"
# page buttons
- define prevpage <&7><&lt>--
- define nextpage <&7>--<&gt>
- if <[page]> > 0:
- clickable usages:1 until:60s save:prev:
- run phones_texts_print def.player:<[player]> def.target:<[target]> def.page:<[page].sub[1]>
- define prevpage "<element[<&a><&lt>--].on_click[<entry[prev].command>]>"
- if <[messages_size]> > <[page].add[1].mul[5]>:
- clickable usages:1 until:60s save:next:
- run phones_texts_print def.player:<[player]> def.target:<[target]> def.page:<[page].add[1]>
- define nextpage "<element[<&a>--<&gt>].on_click[<entry[next].command>]>"
- narrate targets:<[player]> "<&nl><[prevpage]> <&6>Page <[page].add[1]>/<[messages_size].sub[1].div[5].round_down.add[1]> <[nextpage]>"
# clear notifications?
- if <[player].flag[phones_notifications].get[textmessages].get[<[target]>].if_null[0]> > 0:
- define notifications <[player].flag[phones_notifications].if_null[<map[]>]>
- define textnotifications <[notifications].get[textmessages].if_null[<map[]>]>
- define textnotifications <[textnotifications].exclude[<[target]>]>
- define notifications <[notifications].with[textmessages].as[<[textnotifications]>]>
- flag <[player]> phones_notifications:<[notifications]>
phones_gui_texts:
debug: false
type: task
definitions: player|page
script:
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&1>邒]]>"
- define textslist <util.list_files[data/phones/texts].filter[starts_with[<player.uuid>]].parse[split[_].get[2].split[.].get[1]].parse_tag[<player[<[parse_value]>]>].get[<[page].mul[16].add[1]>].to[<[page].add[1].mul[16]>].if_null[<list[]>]>
# show contacts/numbers
- foreach <[textslist]> as:target:
- define receiver <proc[phones_relative_name].context[<[player]>|<[target]>]>
- define textsender <item[player_head]>
- adjust def:textsender display:<&e><[receiver]>
- adjust def:textsender "lore:<list[<&7>Click to view your conversation.]>"
# notifications
- define notifications_text <[player].flag[phones_notifications].get[textmessages].get[<[target]>].if_null[null]>
- if <[notifications_text]> != null:
- if <[notifications_text]> > 99:
- define notifications_text 99+
- adjust def:textsender "lore:<[textsender].lore.include[|<&7>You have <&6><[notifications_text]> <&7>unread messages.]>"
#
- flag <[textsender]> phones:<[target]>
- flag <[textsender]> phones_target_skull_uuid:<[target].uuid>
- inventory set destination:<[inventory]> slot:<[loop_index].sub[1].div[3].round_down.mul[9].add[4].add[<[loop_index].sub[1].mod[3]>]> origin:<[textsender]>
# back
- define back <item[oak_door]>
- adjust def:back display:<&7>Back
- inventory set destination:<[inventory]> slot:50 origin:<[back]>
# page buttons
- if <[page]> > 0:
- define prevpage <item[ender_pearl]>
- adjust def:prevpage "display:<&a>Previous Page"
- inventory set destination:<[inventory]> slot:49 origin:<[prevpage]>
- if <[textslist].size> > <[page].add[1].mul[16]>:
- define nextpage <item[ender_eye]>
- adjust def:nextpage "display:<&a>Next Page"
- inventory set destination:<[inventory]> slot:51 origin:<[nextpage]>
#
- inventory open player:<[player]> destination:<[inventory]>
- run phones_target_skulls_update def.player:<[player]>
# each skull you want to change has to be flagged with phones_target_skull_uuid:<[target].uuid>
phones_target_skulls_update:
debug: false
type: task
definitions: player
script:
- define inventory <[player].open_inventory>
- foreach <[inventory].map_slots> key:slot as:item:
- if <[item].has_flag[phones_target_skull_uuid]>:
- if <[inventory].viewers.if_null[<list[]>].is_empty>:
- stop
- define uuid <[item].flag[phones_target_skull_uuid]>
- inventory adjust slot:<[slot]> skull_skin:<[uuid]>|<player[<[uuid]>].skin_blob.if_null[0000]>|<player[<[uuid]>].name> destination:<[inventory]>
####
## NOTIFICATIONS
####
phones_notify_text_messages:
debug: false
type: task
definitions: player|delayseconds
script:
- wait <[delayseconds]>s
- if !<[player].is_online>:
- stop
- define notifications_textmessages <[player].flag[phones_notifications].get[textmessages].values.filter[equals[0].not].sum.if_null[null]>
- if <[notifications_textmessages]> == null || <[notifications_textmessages]> == 0:
- stop
- if <[notifications_textmessages]> > 99:
- define notifications_textmessages 99+
- narrate targets:<[player]> format:formats_prefix "You have <&6><[notifications_textmessages]> <&7>unread text conversations."
####
## MUSIC APP
####
phones_music_play:
debug: false
type: task
definitions: player|songfile
script:
- if <[player].nbs_is_playing>:
- nbs stop targets:<[player]>
- nbs file:data/phones/songs/<[songfile]> play targets:<[player]>
- narrate targets:<[player]> format:formats_prefix "Playing song..."
phones_music_stop:
debug: false
type: task
definitions: player
script:
- if !<[player].nbs_is_playing>:
- narrate targets:<[player]> format:formats_prefix "No song is playing right now."
- stop
- nbs stop targets:<[player]>
- narrate targets:<[player]> format:formats_prefix "Stopped song."
phones_gui_music:
debug: false
type: task
definitions: player|page|ringtone
script:
# ringtone selection mode?
- define ringtone <[ringtone].if_null[false]>
# make inventory
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&2>邒]]>"
- if <[ringtone]>:
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&4>邒]]>"
- define songsize <util.list_files[data/phones/songs].size>
- define songsonpage <tern[<[ringtone]>].pass[15].fail[14]>
- define songlist <util.list_files[data/phones/songs].parse[split[.].get[1]].filter[length.is_more_than[0]].get[<[page].mul[<[songsonpage]>].add[1]>].to[<[page].add[1].mul[<[songsonpage]>]>].if_null[<list[]>]>
# show songs
- foreach <[songlist]> as:songname:
- define song <item[jukebox]>
- adjust def:song display:<&e><[songname]>
- adjust def:song "lore:<list[<&7>Click to start playing.]>"
- flag <[song]> phones:<[songname]>
- inventory set destination:<[inventory]> slot:<[loop_index].sub[1].div[3].round_down.mul[9].add[4].add[<[loop_index].sub[1].mod[3]>]> origin:<[song]>
# stop
- if !<[ringtone]>:
- define stop <item[redstone_block]>
- adjust def:stop display:<&c>Stop
- inventory set destination:<[inventory]> slot:42 origin:<[stop]>
# back
- define back <item[oak_door]>
- adjust def:back display:<&7>Back
- inventory set destination:<[inventory]> slot:50 origin:<[back]>
# page buttons
- if <[page]> > 0:
- define prevpage <item[ender_pearl]>
- adjust def:prevpage "display:<&a>Previous Page"
- inventory set destination:<[inventory]> slot:49 origin:<[prevpage]>
- if <[songsize]> > <[page].add[1].mul[<[songsonpage]>]>:
- define nextpage <item[ender_eye]>
- adjust def:nextpage "display:<&a>Next Page"
- inventory set destination:<[inventory]> slot:51 origin:<[nextpage]>
#
- inventory open player:<[player]> destination:<[inventory]>
###
## SETTINGS
###
phones_gui_settings:
debug: false
type: task
definitions: player
script:
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&3>邒]]>"
# ringtone
- define ringtone <item[note_block]>
- adjust def:ringtone display:<&6>Ringtone
- adjust def:ringtone "lore:<&7>(music from <&e>noteblock.world<&7>)"
- inventory set destination:<[inventory]> slot:4 origin:<[ringtone]>
# blocked
- define blocked <item[barrier]>
- adjust def:blocked "display:<&6>Blocked Numbers"
- inventory set destination:<[inventory]> slot:5 origin:<[blocked]>
# back
- define back <item[oak_door]>
- adjust def:back display:<&7>Back
- inventory set destination:<[inventory]> slot:50 origin:<[back]>
#
- inventory open player:<[player]> destination:<[inventory]>
phones_gui_settings_blocked:
debug: false
type: task
definitions: player|page
script:
- define inventory "<inventory[generic[size=54;title=<&f>邑邑邑邑鄀<&5>邒]]>"
- define blockedlist <[player].flag[phones].get[blocked].get[<[page].mul[16].add[1]>].to[<[page].add[1].mul[16]>].if_null[<list[]>]>
# show blocked numbers
- foreach <[blockedlist]> as:target:
- define blockednumber <proc[phones_nicer_format].context[<[target].flag[phones].get[number]>]>
- define blocked <item[player_head]>
- adjust def:blocked display:<&e><[blockednumber]>
- adjust def:blocked lore:<list[<&7>You may use /phoneunblock to unblock this number.]>
- flag <[blocked]> phones_target_skull_uuid:<[target].uuid>
- inventory set destination:<[inventory]> slot:<[loop_index].sub[1].div[3].round_down.mul[9].add[4].add[<[loop_index].sub[1].mod[3]>]> origin:<[blocked]>
# back
- define back <item[oak_door]>
- adjust def:back display:<&7>Back
- inventory set destination:<[inventory]> slot:50 origin:<[back]>
# page buttons
- if <[page]> > 0:
- define prevpage <item[ender_pearl]>
- adjust def:prevpage "display:<&a>Previous Page"
- inventory set destination:<[inventory]> slot:49 origin:<[prevpage]>
- if <[blockedlist].size> > <[page].add[1].mul[16]>:
- define nextpage <item[ender_eye]>
- adjust def:nextpage "display:<&a>Next Page"
- inventory set destination:<[inventory]> slot:51 origin:<[nextpage]>
#
- inventory open player:<[player]> destination:<[inventory]>
- run phones_target_skulls_update def.player:<[player]>

View File

@@ -0,0 +1,185 @@
phones_world:
debug: false
type: world
events:
## assign new random number & handle notifications
after player joins:
- run phones_notify_text_messages def.player:<player> def.delayseconds:5
#
- if <player.has_flag[phones]>:
- stop
- define number <util.random.int[1000000].to[9999999]>
- while <server.flag[phones].if_null[<map[]>].contains[377<[number]>]>:
- define number <util.random.int[1000000].to[9999999]>
- define number 377<[number]>
- flag <player> phones:<map[].with[number].as[<[number]>]>
- flag server phones:<server.flag[phones].if_null[<map[]>].with[<[number]>].as[<player>]>
## phone drop, phone unequip, player logs off etc.
on player drops item:
- if <player.has_flag[phones_chat_input]>:
- if <context.item.has_flag[phones].if_null[false]>:
- determine cancelled
- if <context.item.has_flag[phones].if_null[false]>:
- nbs stop targets:<player>
- inject phones_inject_end_call
on player scrolls their hotbar:
- if <player.inventory.slot[<context.previous_slot>].has_flag[phones]>:
- inject phones_inject_end_call
on player quits:
- inject phones_inject_end_call
after player clicks in inventory:
- if !<player.item_in_hand.flag[phones].if_null[false]>:
- inject phones_inject_end_call
## boot up/down phone
on player left clicks block:
- if !<player.item_in_hand.has_flag[phones].if_null[false]>:
- stop
- if <player.open_inventory> != <player.inventory>:
- stop
- determine cancelled passively
- if <player.has_flag[phones_chat_input]>:
- flag <player> phones_chat_input:!
- define state <player.item_in_hand.flag[phones].not>
- inventory flag slot:hand phones:<[state]>
- if <[state]>:
- narrate format:formats_prefix "Powered <&a>on <&7>your phone."
#
- run phones_notify_text_messages def.player:<player> def.delayseconds:2
- else:
- narrate format:formats_prefix "Powered <&c>off <&7>your phone."
- nbs stop targets:<player>
- inject phones_inject_end_call
## phone GUI
on player right clicks block:
- if !<player.item_in_hand.has_flag[phones].if_null[false]>:
- stop
- determine cancelled passively
- if <player.has_flag[phones_call]>:
- narrate "<&c>You are currently in the middle of a call (stop holding the phone to end the call)."
- stop
- if <player.has_flag[phones_chat_input]>:
- flag <player> phones_chat_input:!
- if !<player.item_in_hand.flag[phones]>:
- narrate "<&c>Please turn on your phone (left click) to view the home screen."
- stop
- run phones_gui_home def.player:<player>
# used in ending a call because code repeats a lot
phones_inject_end_call:
debug: false
type: task
script:
- if <player.has_flag[phones_is_maybe_called]>:
- flag <player> phones_is_maybe_called:!
- nbs stop
- if !<player.has_flag[phones_call]>:
- stop
- define callwho <player.flag[phones_call]>
- define iswaiting <player.has_flag[phones_call_clickable]>
- flag <player> phones_call:!
- if <[iswaiting]>:
- clickable cancel:<player.flag[phones_call_clickable]>
- flag <player> phones_call_clickable:!
- if <[callwho].flag[phones_call].if_null[null]> == <player>:
- narrate targets:<[callwho]> format:formats_prefix "Call was ended by the other side."
- flag <[callwho]> phones_call:!
- else:
- nbs stop targets:<[callwho]>
- narrate targets:<[callwho]> format:formats_prefix "The person on the other side hung up before you answered."
- narrate format:formats_prefix "You ended the call."
## only gui handling
phones_world_gui:
debug: false
type: world
events:
on player clicks in inventory:
- if !<context.inventory.title.contains[鄀]>:
- stop
- determine cancelled passively
- if <context.slot> > <context.inventory.size>:
- stop
- define title <context.inventory.title.substring[8]>
# Home Page
- if <[title]> == <&0>邒:
- if <context.slot> == 13:
- run phones_gui_settings def.player:<player>
- if <context.slot> == 14:
- inventory close
- run phones_contacts_print def.player:<player> def.page:0
- else if <context.slot> == 15:
- flag <player> phones_gui_page:0
- run phones_gui_texts def.player:<player> def.page:0
- else if <context.slot> == 22:
- flag <player> phones_gui_page:0
- run phones_gui_music def.player:<player> def.page:0 def.ringtone:false
- else if <[title]> == <&1>邒:
- if <context.item.material.name> == ender_pearl:
- define page <player.flag[phones_gui_page].sub_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_texts def.player:<player> def.page:<[page]>
- else if <context.item.material.name> == ender_eye:
- define page <player.flag[phones_gui_page].add_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_texts def.player:<player> def.page:<[page]>
- else if <context.slot> == 50:
- run phones_gui_home def.player:<player>
- else if <context.item.material.name> == player_head:
- inventory close
- run phones_texts_print def.player:<player> def.target:<context.item.flag[phones]> def.page:0
# Music
- else if <[title]> == <&2>邒:
- if <context.item.material.name> == ender_pearl:
- define page <player.flag[phones_gui_page].sub_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_music def.player:<player> def.page:<[page]> def.ringtone:false
- else if <context.item.material.name> == ender_eye:
- define page <player.flag[phones_gui_page].add_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_music def.player:<player> def.page:<[page]> def.ringtone:false
- else if <context.slot> == 50:
- run phones_gui_home def.player:<player>
- else if <context.slot> == 42:
- inventory close
- run phones_music_stop def.player:<player>
- else if <context.item.material.name> == jukebox:
- inventory close
- run phones_music_play def.player:<player> def.songfile:<context.item.flag[phones]>
# Settings
- else if <[title]> == <&3>邒:
- if <context.slot> == 4:
- flag <player> phones_gui_page:0
- run phones_gui_music def.player:<player> def.page:0 def.ringtone:true
- if <context.slot> == 5:
- flag <player> phones_gui_page:0
- run phones_gui_settings_blocked def.player:<player> def.page:0
- else if <context.slot> == 50:
- run phones_gui_home def.player:<player>
# Ringtone Select
- else if <[title]> == <&4>邒:
- if <context.item.material.name> == ender_pearl:
- define page <player.flag[phones_gui_page].sub_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_music def.player:<player> def.page:<[page]> def.ringtone:true
- else if <context.item.material.name> == ender_eye:
- define page <player.flag[phones_gui_page].add_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_music def.player:<player> def.page:<[page]> def.ringtone:true
- else if <context.slot> == 50:
- run phones_gui_settings def.player:<player>
- else if <context.item.material.name> == jukebox:
- flag <player> phones:<player.flag[phones].with[ringtone].as[<context.item.flag[phones]>]>
- run phones_gui_settings def.player:<player>
- narrate format:formats_prefix "Changed your ringtone to <&e><context.item.display.strip_color><&7>."
# Blocked
- else if <[title]> == <&5>邒:
- if <context.item.material.name> == ender_pearl:
- define page <player.flag[phones_gui_page].sub_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_settings_blocked def.player:<player> def.page:<[page]>
- else if <context.item.material.name> == ender_eye:
- define page <player.flag[phones_gui_page].add_int[1]>
- flag <player> phones_gui_page:<[page]>
- run phones_gui_settings_blocked def.player:<player> def.page:<[page]>
- else if <context.slot> == 50:
- run phones_gui_settings def.player:<player>

View File

@@ -0,0 +1,40 @@
rankup_command_playtime:
debug: false
type: command
name: playtime
description: Check your total playtime.
usage: /playtime
permission: rankup.command.playtime
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- narrate format:formats_prefix "You've played for <&a><placeholder[autorank_total_time_of_player_formatted].player[<player>]>"
rankup_command_grade:
debug: false
type: command
name: grade
description: Check to see when you'll grade up next.
usage: /grade
permission: rankup.command.grade
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <yaml.list.contains[autorank_totaltime]>:
- yaml load:../Autorank/data/Total_time.yml id:autorank_totaltime
- if <yaml.list.contains[autorank_paths]>:
- yaml load:../Autorank/Paths.yml id:autorank_paths
- define activepath <placeholder[autorank_active_paths].player[<player>].if_null[null]>
- if <[activepath]> == null || <[activepath].length> <= 0:
- narrate format:formats_prefix "You have completed all grades!"
- stop
- define timeneeded <duration[<yaml[autorank_paths].read[<[activepath]>].get[requirements].get[time].get[value]>]>
- define timepassed <duration[<yaml[autorank_totaltime].read[<player.uuid>]>m]>
- define difference <[timeneeded].sub[<[timepassed]>]>
- narrate format:formats_prefix "You need <&a><[difference].formatted> <&7>more till reaching <&a><[activepath].substring[1,5].to_lowercase> <[activepath].substring[6,7]>"

View File

@@ -0,0 +1,10 @@
rankup_world:
debug: false
type: world
events:
after server start:
- yaml load:../Autorank/data/Total_time.yml id:autorank_totaltime
- yaml load:../Autorank/Paths.yml id:autorank_paths
on delta time minutely every:1:
- yaml load:../Autorank/data/Total_time.yml id:autorank_totaltime
- yaml load:../Autorank/Paths.yml id:autorank_paths

View File

@@ -0,0 +1,33 @@
requestsearch_command_requestsearch:
debug: false
type: command
name: requestsearch
description: Command to search someone's inventory.
usage: /requestsearch
aliases:
- rs
- patdown
permission: invreq.patdown
tab completions:
1: <empyy>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define target <player.target[player].within[5].if_null[null]>
- if <[target]> == null:
- narrate "<&c>Please look at the player you want to search."
- stop
- if <[target].is_npc>:
- narrate "<&c>Please look at the player you want to search."
- stop
- define player <player>
- narrate format:formats_prefix "<&e>Sent an inventory search request to <placeholder[essentials_nickname].player[<[target]>]>"
- clickable usages:1 save:yes:
- narrate targets:<[target]> format:formats_prefix "Your inventory is being searched..."
- inventory player:<[player]> open destination:<[target].inventory>
- clickable usages:1 save:no:
- narrate targets:<[player]> format:formats_prefix "Your inventory search request was denied."
- narrate targets:<[target]> "You denied the inventory search request."
- narrate format:formats_prefix targets:<[target]> "<&e>Do you allow <placeholder[essentials_nickname].player[<player>]><&e> to access your belongings?"
- narrate targets:<[target]> "<&f> <&e> <&f> <element[<&7>[<&a>Accept<&7>]].on_click[<entry[yes].command>]><&f> <&e> <&f> <red><element[<&7>[<&c>Deny<&7>]].on_click[<entry[no].command>]>"

View File

@@ -0,0 +1,26 @@
roll_command_roll:
debug: false
type: command
name: roll
usage: /roll [amount?]
description: Rolls a dice, optionally with an amount.
permission: roll.command.roll
tab completions:
1: <&lt>amount<&gt>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define amount 100
- if <context.args.size> >= 1:
- define amount <context.args.get[1]>
- if !<[amount].is_integer>:
- narrate "<&c>The amount must be an integer between 2 and 200."
- stop
- if <[amount]> < 2 || <[amount]> > 200:
- narrate "<&c>The amount must be an integer between 2 and 200."
- stop
- define roll <util.random.int[1].to[<[amount]>]>
- define final "<&f><placeholder[essentials_nickname].player[<player>]> <proc[chat_special_group].context[<player>]><proc[chat_roles_group].context[<player>]> <proc[character_get_name].context[<player>]> <&6>rolls <&f><[roll]> <&6>out of <&f><[amount]>"
- narrate targets:<player.location.find_players_within[10]> <[final]>
- announce to_console <[final]>

View File

@@ -0,0 +1,113 @@
sports_football_join:
debug: false
type: task
definitions: id|player|team
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- if <[team]> == red:
- teleport <[player]> <[extra].get[red_start]>
- else if <[team]> == blue:
- teleport <[player]> <[extra].get[blue_start]>
- run sports_football_update_glow def.id:<[id]>
- define count <proc[sports_arena_player_count].context[<[id]>]>
- if <[count]> == 2:
- define teams <proc[sports_arena_teams].context[<[id]>]>
- repeat 3:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> title:<&6><element[3].sub[<[value].sub[1]>]> fade_in:0 fade_out:0 stay:1s
- wait 1s
- if <proc[sports_arena_player_count].context[<[id]>]> < 2:
- stop
- run sports_football_restart_game def.id:<[id]>
- if <[count]> < 2:
- run sports_football_idle_game def.id:<[id]>
sports_football_leave:
debug: false
type: task
definitions: id|player
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- teleport <[player]> <[extra].get[exit]>
- glow <[player]> reset
- if <proc[sports_arena_player_count].context[<[id]>]> <= 1:
- run sports_football_idle_game def.id:<[id]>
sports_football_redistribute:
debug: false
type: task
definitions: id|player|from|to
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- if <[to]> == red:
- teleport <[player]> <[extra].get[red_start]>
- narrate targets:<[player]> format:formats_prefix "You were auto-balanced to the <&c>red team"
- else if <[to]> == blue:
- teleport <[player]> <[extra].get[blue_start]>
- narrate targets:<[player]> format:formats_prefix "You were auto-balanced to the <&9>blue team"
- run sports_football_update_glow def.id:<[id]>
sports_football_restart_game:
debug: false
type: task
definitions: id
script:
- define arena <proc[sports_arena].context[<[id]>]>
- define extra <[arena].get[extra_data]>
- run sports_arena_redistribute def.id:<[id]>
- define teams <proc[sports_arena_teams].context[<[id]>]>
- run sports_football_update_glow def.id:<[id]>
- foreach <[teams].get[red]> as:red_player:
- teleport <[red_player]> <[extra].get[red_start]>
- foreach <[teams].get[blue]> as:blue_player:
- teleport <[blue_player]> <[extra].get[blue_start]>
- run sports_arena_set_status def.id:<[id]> def.status:normal
- run ball_create def.id:sports_football def.location:<[extra].get[ball_start]> def.size:<[arena].get[ball_size]> def.display_item:<[arena].get[ball_display]> def.gravity_multiplier:<[arena].get[ball_gravity]>
- glow <proc[ball_get].context[<[id]>]> true for:<[teams].get[red].include[<[teams].get[blue]>]>
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "Next round..."
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&e>Next Round" fade_in:0 fade_out:0 stay:1s
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_PLING pitch:1 volume:30
sports_football_update_glow:
debug: false
type: task
definitions: id
script:
- define teams <proc[sports_arena_teams].context[<[id]>]>
- foreach <[teams].get[red]> as:red_player:
- glow <[red_player]> true for:<[teams].get[red]>
- glow <[red_player]> false for:<[teams].get[blue]>
- foreach <[teams].get[blue]> as:blue_player:
- glow <[blue_player]> true for:<[teams].get[blue]>
- glow <[blue_player]> false for:<[teams].get[red]>
sports_football_idle_game:
debug: false
type: task
definitions: id
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- define teams <proc[sports_arena_teams].context[<[id]>]>
- run sports_arena_set_status def.id:<[id]> def.status:waiting
- run ball_remove def.id:<[id]>
- teleport <[teams].get[red].include[<[teams].get[blue]>]> <[extra].get[ball_start]>
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "Not enough players. Waiting..."
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> title:<&7>Waiting fade_in:0 fade_out:0 stay:3s
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_HAT pitch:1 volume:30
sports_football_score_goal:
debug: false
type: task
definitions: id|team
script:
- run sports_arena_set_status def.id:<[id]> def.status:goal
- define teams <proc[sports_arena_teams].context[<[id]>]>
- if <[team]> == red:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&c>Goal for Red" fade_in:0 fade_out:0 stay:2s
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "<&c>Red team <&7>scored a goal!"
- if <[team]> == blue:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&9>Goal for Blue" fade_in:0 fade_out:0 stay:2s
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "<&9>Blue team <&7>scored a goal!"
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_PLING pitch:2 volume:30
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:ENTITY_FIREWORK_ROCKET_TWINKLE_FAR pitch:1 volume:30
- wait 3s
- run sports_football_restart_game def.id:<[id]>

View File

@@ -0,0 +1,55 @@
sports_football_world:
debug: false
type: world
events:
## ball click
on player damages entity bukkit_priority:low:
- ratelimit <player> 10t
- if !<context.entity.has_flag[ball]>:
- stop
- if !<context.entity.flag[ball].starts_with[sports_football]>:
- stop
- if !<player.has_flag[sports]>:
- stop
- define arena_id <player.flag[sports].get[id]>
- if !<[arena_id].starts_with[sports_football]>:
- stop
- if <proc[sports_arena_get_status].context[<[arena_id]>]> != normal:
- stop
- define min_y <player.eye_location.direction.vector.y>
- if <[min_y]> < 0:
- define min_y 0
- define velo <context.entity.flag[ball_velocity].normalize.mul[0.05]>
- define kick <player.eye_location.direction.vector.mul[0.75].with_y[<[min_y]>].add[0,0.25,0].add[<[velo]>]>
- if <player.is_sprinting>:
- define kick <player.eye_location.direction.vector.with_y[0.25].mul[1.5]>
- if !<player.is_on_ground>:
- define kick <player.eye_location.direction.vector.with_y[0.75].mul[1.5]>
- run ball_vector_add def.ball:<context.entity> def.vector:<[kick]>
## out of bounds & ball collision
on player walks:
- if !<player.has_flag[sports]>:
- stop
- define arena_id <player.flag[sports].get[id]>
- if !<[arena_id].starts_with[sports_football]>:
- stop
- if <proc[sports_arena_get_status].context[<[arena_id]>]> != normal:
- stop
# ball collision
- define ball <proc[ball_get].context[<[arena_id]>]>
- if <player.location.y.add[0.1]> > <[ball].location.y>:
- if <player.location.distance_squared[<[ball].location>]> < 0.5:
- run ball_vector_add def.ball:<[ball]> def.vector:<[ball].location.sub[<player.location>].normalize.mul[0.5].add[0,0.05,0]>
- ratelimit <player> 10t
## goal scoring
on custom event id:ball_move bukkit_priority:low:
- if !<context.ball_id.starts_with[sports_football]>:
- stop
- define arena_id <context.ball_id>
- if <proc[sports_arena_get_status].context[<[arena_id]>]> != normal:
- stop
- define extra <proc[sports_arena].context[<[arena_id]>].get[extra_data]>
- if <[extra].get[red_goal].contains[<context.now>]> || <[extra].get[red_goal].contains[<context.next>]>:
- run sports_football_score_goal def.id:<[arena_id]> def.team:blue
- else if <[extra].get[blue_goal].contains[<context.now>]> || <[extra].get[blue_goal].contains[<context.next>]>:
- run sports_football_score_goal def.id:<[arena_id]> def.team:red

View File

@@ -0,0 +1,217 @@
sports_arena_register:
debug: false
type: task
definitions: id|cuboid|max_per_team|ball_display|ball_size|ball_gravity|on_join_task|on_leave_task|on_redistribute_task|default_status|extra_data
script:
- definemap arena:
id: <[id]>
cuboid: <[cuboid]>
max_per_team: <[max_per_team]>
ball_display: <[ball_display]>
ball_size: <[ball_size]>
ball_gravity: <[ball_gravity]>
on_join_task: <[on_join_task]>
on_leave_task: <[on_leave_task]>
on_redistribute_task: <[on_redistribute_task]>
default_status: <[default_status]>
extra_data: <[extra_data]>
- flag server sports_arenas:<server.flag[sports_arenas].if_null[<map[]>].with[<[id]>].as[<[arena]>]>
- flag server sports_status:<server.flag[sports_status].if_null[<map[]>].with[<[id]>].as[<[default_status]>]>
sports_arena_update_property:
debug: false
type: task
definitions: id|property|new_value
script:
- define arena <server.flag[sports_arenas].if_null[<map[]>].get[<[id]>]>
- if !<[arena].keys.contains[<[property]>]>:
- narrate "<&c> Could not update arena property: <[property]> is an inexistent property."
- stop
- define arena <[arena].with[<[property]>].as[<[new_value]>]>
- flag server sports_arenas:<server.flag[sports_arenas].if_null[<map[]>].with[<[id]>].as[<[arena]>]>
sports_arena_exists:
debug: false
type: procedure
definitions: id
script:
- determine <server.flag[sports_arenas].contains[<[id]>].if_null[false]>
sports_arena_cleanup:
debug: false
type: task
definitions: id
script:
- define on_leave_task <server.flag[sports_arenas].get[<[id]>].get[on_leave_task]>
- foreach <server.flag[sports_teams].get[<[id]>].get[red].if_null[<list[]>]> as:player:
- run <[on_leave_task]> def.id:<[id]> def.player:<[player]>
- foreach <server.flag[sports_teams].get[<[id]>].get[blue].if_null[<list[]>]> as:player:
- run <[on_leave_task]> def.id:<[id]> def.player:<[player]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].exclude[<[id]>]>
- define default_status <server.flag[sports_arenas].get[<[id]>].get[default_status]>
- flag server sports_status:<server.flag[sports_status].if_null[<map[]>].with[<[id]>].as[<[default_status]>]>
sports_arena_unregister:
debug: false
type: task
definitions: id
script:
- run sports_arena_cleanup def.id:<[id]>
- flag server sports_arenas:<server.flag[sports_arenas].if_null[<map[]>].exclude[<[id]>]>
- flag server sports_status:<server.flag[sports_status].if_null[<map[]>].exclude[<[id]>]>
sports_arena:
debug: false
type: procedure
definitions: id
script:
- determine <server.flag[sports_arenas].if_null[<map[]>].get[<[id]>]>
sports_arena_can_join:
debug: false
type: procedure
definitions: id|team
script:
- define max_per_team <server.flag[sports_arenas].get[<[id]>].get[max_per_team]>
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define red <[teams].get[red]>
- define blue <[teams].get[blue]>
- if <[red].size> >= <[max_per_team]> && <[blue].size> >= <[max_per_team]>:
- determine false
- else if <[red].size> >= <[max_per_team]>:
- determine blue
- else if <[blue].size> >= <[max_per_team]>:
- determine red
- determine any
sports_arena_player_count:
debug: false
type: procedure
definitions: id
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define red <[teams].get[red]>
- define blue <[teams].get[blue]>
- determine <[red].size.add[<[blue].size>]>
sports_arena_teams:
debug: false
type: procedure
definitions: id
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define red <[teams].get[red]>
- define blue <[teams].get[blue]>
- determine <map[].with[red].as[<[red]>].with[blue].as[<[blue]>]>
# team is "red" or "blue"
sports_arena_join:
debug: false
type: task
definitions: id|player|team
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define teams <[teams].with[<[team]>].as[<[teams].get[<[team]>].include[<[player]>].deduplicate>]>
- flag <[player]> sports:<map[].with[id].as[<[id]>].with[team].as[<[team]>]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- define on_join_task <server.flag[sports_arenas].get[<[id]>].get[on_join_task]>
- run <[on_join_task]> def.id:<[id]> def.player:<[player]> def.team:<[team]>
sports_arena_join_auto:
debug: false
type: task
definitions: id|player
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define red <[teams].get[red]>
- define blue <[teams].get[blue]>
- define on_join_task <server.flag[sports_arenas].get[<[id]>].get[on_join_task]>
- if <[red].size> < <[blue].size>:
- define teams <[teams].with[red].as[<[red].include[<[player]>].deduplicate>]>
- flag <[player]> sports:<map[].with[id].as[<[id]>].with[team].as[red]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- run <[on_join_task]> def.id:<[id]> def.player:<[player]> def.team:red
- else:
- define teams <[teams].with[blue].as[<[blue].include[<[player]>].deduplicate>]>
- flag <[player]> sports:<map[].with[id].as[<[id]>].with[team].as[blue]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- run <[on_join_task]> def.id:<[id]> def.player:<[player]> def.team:blue
sports_arena_leave:
debug: false
type: task
definitions: id|player
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define teams <[teams].with[red].as[<[teams].get[red].exclude[<[player]>]>]>
- define teams <[teams].with[blue].as[<[teams].get[blue].exclude[<[player]>]>]>
- flag <[player]> sports:!
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- define on_leave_task <server.flag[sports_arenas].get[<[id]>].get[on_leave_task]>
- run <[on_leave_task]> def.id:<[id]> def.player:<[player]>
sports_arena_redistribute:
debug: false
type: task
definitions: id
script:
- define teams <server.flag[sports_teams].get[<[id]>].if_null[<map[].with[red].as[<list[]>].with[blue].as[<list[]>]>]>
- define red <[teams].get[red]>
- define blue <[teams].get[blue]>
- if <[red].size.sub[1]> > <[blue].size>:
- define random <[red].random>
- define teams <[teams].with[red].as[<[red].exclude[<[random]>].deduplicate>]>
- define teams <[teams].with[blue].as[<[blue].include[<[random]>].deduplicate>]>
- flag <[random]> sports:<map[].with[id].as[<[id]>].with[team].as[red]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- define on_redistribute_task <server.flag[sports_arenas].get[<[id]>].get[on_redistribute_task]>
- run <[on_redistribute_task]> def.id:<[id]> def.player:<[random]> def.from:red def.to:blue
- determine red
- if <[blue].size.sub[1]> > <[red].size>:
- define random <[blue].random>
- define teams <[teams].with[blue].as[<[blue].exclude[<[random]>].deduplicate>]>
- define teams <[teams].with[red].as[<[red].include[<[random]>].deduplicate>]>
- flag <[random]> sports:<map[].with[id].as[<[id]>].with[team].as[blue]>
- flag server sports_teams:<server.flag[sports_teams].if_null[<map[]>].with[<[id]>].as[<[teams]>]>
- define on_redistribute_task <server.flag[sports_arenas].get[<[id]>].get[on_redistribute_task]>
- run <[on_redistribute_task]> def.id:<[id]> def.player:<[random]> def.from:blue def.to:red
- determine blue
- determine none
sports_arena_set_status:
debug: false
type: task
definitions: id|status
script:
- flag server sports_status:<server.flag[sports_status].if_null[<map[]>].with[<[id]>].as[<[status]>]>
sports_arena_get_status:
debug: false
type: procedure
definitions: id
script:
- determine <server.flag[sports_status].if_null[<map[]>].get[<[id]>]>
sports_arena_enter_arena_prompt:
debug: false
type: task
definitions: id|player
script:
- ratelimit <[player]> 2s
- clickable save:join_arena usages:1 until:30s:
- if <[player].has_flag[sports]>:
- stop
- run sports_arena_join_auto def.id:<[id]> def.player:<[player]>
- narrate targets:<[player]> format:formats_prefix "Join this game? <element[<&a><&l>[YES]].on_click[<entry[join_arena].command>]>"
sports_arena_exit_arena_prompt:
debug: false
type: task
definitions: id|player
script:
- ratelimit <[player]> 2s
- clickable save:leave_arena usages:1 until:30s:
- if !<[player].has_flag[sports]>:
- stop
- run sports_arena_leave def.id:<[id]> def.player:<[player]>
- narrate targets:<[player]> format:formats_prefix "Leave this game? <element[<&a><&l>[YES]].on_click[<entry[leave_arena].command>]>"

View File

@@ -0,0 +1,83 @@
sports_arena_collision_world:
debug: false
type: world
events:
on custom event id:ball_move:
- if !<context.ball_id.starts_with[sports_]>:
- stop
- define arena <proc[sports_arena].context[<context.ball_id>]>
- define cuboid <[arena].get[cuboid]>
- define corners <[cuboid].corners>
# axis-aligned boundary reflection algorithm
- define min <[corners].get[1]>
- define max <[corners].get[8]>
- define damping 0.75
- define new_next <context.next>
- define new_velocity <context.velocity_t1>
- define bounced false
- define min_x <[min].x>
- define max_x <[max].x>
- define min_y <[min].y>
- define max_y <[max].y>
- define min_z <[min].z>
- define max_z <[max].z>
# X
- if <[new_next].x> < <[min_x]>:
- define new_next <[new_next].with_x[<[min_x]>]>
- define new_velocity <[new_velocity].with_x[<[new_velocity].x.mul[-<[damping]>]>]>
- define bounced true
- if <[new_next].x> > <[max_x]>:
- define new_next <[new_next].with_x[<[max_x]>]>
- define new_velocity <[new_velocity].with_x[<[new_velocity].x.mul[-<[damping]>]>]>
- define bounced true
# Y
- if <[new_next].y> < <[min_y]>:
- define new_next <[new_next].with_y[<[min_y]>]>
- define new_velocity <[new_velocity].with_y[<[new_velocity].y.mul[-<[damping]>]>]>
- define bounced true
- if <[new_next].y> > <[max_y]>:
- define new_next <[new_next].with_y[<[max_y]>]>
- define new_velocity <[new_velocity].with_y[<[new_velocity].y.mul[-<[damping]>]>]>
- define bounced true
# Z
- if <[new_next].z> < <[min_z]>:
- define new_next <[new_next].with_z[<[min_z]>]>
- define new_velocity <[new_velocity].with_z[<[new_velocity].z.mul[-<[damping]>]>]>
- define bounced true
- if <[new_next].z> > <[max_z]>:
- define new_next <[new_next].with_z[<[max_z]>]>
- define new_velocity <[new_velocity].with_z[<[new_velocity].z.mul[-<[damping]>]>]>
- define bounced true
# update to bounce
- if <[bounced]>:
- determine output:<[new_next]> passively
- determine output:<[new_velocity]> passively
on player walks:
- if !<player.has_flag[sports]>:
- define arenas <server.flag[sports_arenas]>
- foreach <[arenas]> as:arena:
- if <[arena].get[cuboid].contains[<context.new_location>]> && !<[arena].get[cuboid].contains[<context.old_location>]>:
- if <player.gamemode> == survival || <player.gamemode> == adventure:
- determine cancelled passively
- run sports_arena_enter_arena_prompt def.id:<[arena].get[id]> def.player:<player>
- stop
- else:
- define arena_id <player.flag[sports].get[id]>
- define arena <proc[sports_arena].context[<[arena_id]>]>
- if !<[arena].get[cuboid].contains[<context.new_location>]> && !<[arena].get[cuboid].contains[<context.old_location>]>:
- if <player.gamemode> == survival || <player.gamemode> == adventure:
- determine cancelled passively
- run sports_arena_exit_arena_prompt def.id:<[arena_id]> def.player:<player>
on player quits:
- if !<player.has_flag[sports]>:
- stop
- define arena_id <player.flag[sports].get[id]>
- run sports_arena_leave def.id:<[arena_id]> def.player:<player>
sports_arena_cleanup_world:
debug: false
type: world
events:
after server start:
- foreach <server.flag[sports_arenas]> as:arena:
- run sports_arena_cleanup def.id:<[arena].get[id]>

View File

@@ -0,0 +1,100 @@
sports_volleyball_join:
debug: false
type: task
definitions: id|player|team
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- if <[team]> == red:
- teleport <[player]> <[extra].get[red_start]>
- else if <[team]> == blue:
- teleport <[player]> <[extra].get[blue_start]>
- define count <proc[sports_arena_player_count].context[<[id]>]>
- if <[count]> == 2:
- define teams <proc[sports_arena_teams].context[<[id]>]>
- repeat 3:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> title:<&6><element[3].sub[<[value].sub[1]>]> fade_in:0 fade_out:0 stay:1s
- wait 1s
- if <proc[sports_arena_player_count].context[<[id]>]> < 2:
- stop
- run sports_volleyball_restart_game def.id:<[id]> def.side:red
- stop
- if <[count]> < 2:
- run sports_volleyball_idle_game def.id:<[id]>
sports_volleyball_leave:
debug: false
type: task
definitions: id|player
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- teleport <[player]> <[extra].get[exit]>
- glow <[player]> reset
- define ball <proc[ball_get].context[<[id]>].if_null[null]>
- if <proc[sports_arena_player_count].context[<[id]>]> <= 1:
- run sports_volleyball_idle_game def.id:<[id]>
sports_volleyball_redistribute:
debug: false
type: task
definitions: id|player|from|to
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- if <[to]> == red:
- teleport <[player]> <[extra].get[red_start]>
- narrate targets:<[player]> format:formats_prefix "You were auto-balanced to the <&c>red team"
- else if <[to]> == blue:
- teleport <[player]> <[extra].get[blue_start]>
- narrate targets:<[player]> format:formats_prefix "You were auto-balanced to the <&9>blue team"
sports_volleyball_restart_game:
debug: false
type: task
definitions: id|side
script:
- define arena <proc[sports_arena].context[<[id]>]>
- define extra <[arena].get[extra_data]>
- run sports_arena_redistribute def.id:<[id]>
- define teams <proc[sports_arena_teams].context[<[id]>]>
- foreach <[teams].get[red]> as:red_player:
- teleport <[red_player]> <[extra].get[red_start]>
- foreach <[teams].get[blue]> as:blue_player:
- teleport <[blue_player]> <[extra].get[blue_start]>
- run sports_arena_set_status def.id:<[id]> def.status:<tern[<[side].equals[red]>].pass[red_start].fail[blue_start]>
- define ball_start <tern[<[side].equals[red]>].pass[<[extra].get[red_ball_start]>].fail[<[extra].get[blue_ball_start]>]>
- run ball_create def.id:<[id]> def.location:<[ball_start]> def.size:<[arena].get[ball_size]> def.display_item:<[arena].get[ball_display]> def.gravity_multiplier:<[arena].get[ball_gravity]>
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "Next round..."
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&e>Next Round" fade_in:0 fade_out:0 stay:1s
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_PLING pitch:1 volume:30
sports_volleyball_idle_game:
debug: false
type: task
definitions: id
script:
- define extra <proc[sports_arena].context[<[id]>].get[extra_data]>
- define teams <proc[sports_arena_teams].context[<[id]>]>
- run sports_arena_set_status def.id:<[id]> def.status:waiting
- run ball_remove def.id:<[id]>
- teleport <[teams].get[red]> <[extra].get[red_start]>
- teleport <[teams].get[blue]> <[extra].get[blue_start]>
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "Not enough players. Waiting..."
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> title:<&7>Waiting fade_in:0 fade_out:0 stay:3s
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_HAT pitch:1 volume:30
sports_volleyball_score_goal:
debug: false
type: task
definitions: id|team
script:
- run sports_arena_set_status def.id:<[id]> def.status:goal
- define teams <proc[sports_arena_teams].context[<[id]>]>
- if <[team]> == red:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&c>Point for Red" fade_in:0 fade_out:0 stay:2s
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "<&c>Red team <&7>scored a goal!"
- if <[team]> == blue:
- title targets:<[teams].get[red].include[<[teams].get[blue]>]> "title:<&9>Point for Blue" fade_in:0 fade_out:0 stay:2s
- narrate targets:<[teams].get[red].include[<[teams].get[blue]>]> format:formats_prefix "<&9>Blue team <&7>scored a goal!"
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:BLOCK_NOTE_BLOCK_PLING pitch:2 volume:30
- playsound <[teams].get[red].include[<[teams].get[blue]>]> sound:ENTITY_FIREWORK_ROCKET_TWINKLE_FAR pitch:1 volume:30
- wait 3s
- run sports_volleyball_restart_game def.id:<[id]> def.side:<tern[<[team].equals[red]>].pass[red].fail[blue]>

View File

@@ -0,0 +1,67 @@
sports_volleyball_world:
debug: false
type: world
events:
## ball click
on player damages entity bukkit_priority:low:
- ratelimit <player> 10t
- define ball <context.entity>
- if !<[ball].has_flag[ball]>:
- stop
- if <[ball].entity_type> == armor_stand:
- define ball <proc[ball_get].context[<[ball].flag[ball]>]>
- if !<[ball].flag[ball].starts_with[sports_volleyball]>:
- stop
- if !<player.has_flag[sports]>:
- stop
- define arena_id <player.flag[sports].get[id]>
- if !<[arena_id].starts_with[sports_volleyball]>:
- stop
- define status <proc[sports_arena_get_status].context[<[arena_id]>]>
- if <[status]> == normal:
- if <player.location.with_y[<[ball].location.y>].distance_squared[<[ball].location>]> > 22:
- stop
- define y <player.eye_location.direction.vector.y>
- if <[y]> < 0.45:
- define y 0.45
- if <[y]> > 0.95:
- define y 0.95
- define kick <player.eye_location.direction.vector.mul[0.58].with_y[<[y]>]>
- if <player.is_sneaking>:
- define kick <location[0,0.525,0]>
- if !<player.is_on_ground>:
- define kick <location[0,0.375,0]>
- define kick <[kick].add[<player.eye_location.direction.vector.with_y[0].mul[0.35]>]>
- define kick <[kick].add[<location[0,0,0].sub[<[ball].flag[ball_velocity]>]>]>
- run ball_vector_add def.ball:<[ball]> def.vector:<[kick]>
- flag <[ball]> sports_volleyball_delay_score:!
- else if <[status]> == blue_start || <[status]> == red_start:
- run sports_arena_set_status def.id:<[arena_id]> def.status:normal
- define kick <player.eye_location.direction.vector.mul[0.58].with_y[0.75]>
- run ball_vector_add def.ball:<[ball]> def.vector:<[kick]>
- playsound <[ball].location> sound:BLOCK_STONE_BREAK pitch:1.8
## point scored
on custom event id:ball_move bukkit_priority:low:
- if !<context.ball_id.starts_with[sports_volleyball]>:
- stop
- define arena_id <context.ball_id>
- if <proc[sports_arena_get_status].context[<[arena_id]>]> != normal:
- define status <proc[sports_arena_get_status].context[<[arena_id]>]>
- if <[status]> == blue_start || <[status]> == red_start:
- determine cancelled
- stop
- if !<context.ball.has_flag[sports_volleyball_delay_score]>:
- if !<context.bounced>:
- stop
- flag <context.ball> sports_volleyball_delay_score:<util.current_time_millis>
- stop
- else:
- if <util.current_time_millis.sub[<context.ball.flag[sports_volleyball_delay_score]>]> < 300:
- stop
- define extra <proc[sports_arena].context[<[arena_id]>].get[extra_data]>
- define red_start <[extra].get[red_start]>
- define blue_start <[extra].get[blue_start]>
- if <context.next.distance_squared[<[red_start]>]> < <context.next.distance_squared[<[blue_start]>]>:
- run sports_volleyball_score_goal def.id:<[arena_id]> def.team:blue
- else:
- run sports_volleyball_score_goal def.id:<[arena_id]> def.team:red

View File

@@ -0,0 +1,238 @@
ch1_1_preassign:
debug: false
type: world
events:
on player joins:
- if <proc[storyboard_player_state_get].context[<player>|preassign]> == null:
- run storyboard_npc_memalloc "def:<player>|marie|player|<location[-4,2,-15,world]>|Marie Ayashibayomi|true|<script[storyboard_skin_dump].data_key[marie].get[a]>"
- run storyboard_npc_set_assignment def.player:<player> def.name:marie def.assignment:ch1_1_marie_assign
- run storyboard_player_state_set def.player:<player> def.key:preassign def.value:true
ch1_1_marie_assign:
debug: false
type: assignment
actions:
on assignment:
- trigger name:click state:true
interact scripts:
- ch1_1_marie_interact
# TODO: this seems like the wrong place
ch1_1_define_phone:
debug: false
type: task
script:
- define phone <item[glistering_melon_slice]>
- adjust def:phone "display:<&e>Flip Phone"
- adjust def:phone custom_model_data:2
- flag <[phone]> phones:true
- determine <[phone]>
ch1_1_marie_interact:
debug: false
type: interact
steps:
1:
click trigger:
script:
- if <player.flag[textbox_state].if_null[null]> != null:
- stop
- engage player duration:999999s
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Hey there, <proc[storyboard_character_first_name].context[<player>]>!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'm so happy to see ya!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- definemap choices:
left:
text: Likewise
right:
text: My name?
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == right:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Oh, right." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[sweat]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Let's just say a little bird$$nltold me it, wink wink!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So, what do you think?$$nlThis town's looking neat, no?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- definemap choices:
left:
text: Yeah
right:
text: Don't know
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == left:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Right???$$nlOh man." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Golly me! I just love$$nlit here." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* That's alright, you got this!$$nlYou'll fit right in, I'm sure of it." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[sweat]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'm actually really fond of this$$nltown, although it's a little small." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You're new anyway, you probably need$$nlsomebody to show you around a little,$$nlno?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- definemap choices:
top:
text: It would help
bottom:
text: You talk a lot
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- define displeased false
- if <[choice]> == top:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Oh welp, I had a feeling." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Don't worry dearie, I've gotcha$$nlaaaall covered!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll be in front of the Academy." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You know, like... the big building." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* The one with the big gates." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You cannot miss it!$$nlSee you there!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- else:
- define displeased true
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Oh.." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[ummm]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Um.." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Yeah, I, uh.." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Actually.." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll be in front of the Academy." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[oof]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Sorry." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[oof]>
- run storyboard_player_freeze def.player:<player>
- ~walk <npc> <location[-4,2,-33,world]>
- run storyboard_npc_movement_commit def.player:<player> def.name:marie def.new_location:<location[-5,2,-78,world]>
- run storyboard_player_unfreeze def.player:<player>
- if !<[displeased]>:
- run storyboard_npc_state_set def.player:<player> def.name:marie def.key:opinion def.value:1
- else:
- run storyboard_npc_state_set def.player:<player> def.name:marie def.key:opinion def.value:-1
- zap 2
- disengage player
2:
click trigger:
script:
- if <player.flag[textbox_state].if_null[null]> != null:
- stop
- engage player duration:999999s
- define displeased false
- define opinion <proc[storyboard_npc_state_get].context[<player>|marie|opinion]>
- ~run ch1_1_define_phone save:result
- define phone <entry[result].created_queue.determination.get[1]>
- if <[opinion]> == null:
- define opinion 1
- if <[opinion]> == 1:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Alrighty, here we are!!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Sorry, sorry." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[sweat]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll calm myself down now." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[oof]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I've got to show ya things$$nland I can't be all jumpy!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Oh. Hey." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Need something?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- definemap choices:
left:
text: I'm sorry
right:
text: No, bye
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == right:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Mkay." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- wait 1s
- disengage player
- stop
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Hm. Are you now?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You know, that was kind of$$nlmean of you." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Why should I help you, anyway?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- definemap choices:
top:
text: I'll change my ways
bottom:
text: You're right, I'm pretending
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == top:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Well." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* . . ." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Okay, look, if you insist." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[oof]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll try to pretend that$$nlnever happened." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- else:
- define displeased true
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Well." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[ugh]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I should've guessed." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So look, I'll cut it short." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I was going to show you around$$nland then give you a flip phone." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* But honestly, I don't care$$nlabout that anymore, so why don't$$nlyou just take the phone instead?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Makes things easier." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:$$nl(You got the flip phone.)"
- give <[phone]>
- run storyboard_player_freeze def.player:<player>
- ~walk <npc> <location[-6,2,-83,world]>
- run storyboard_npc_memfree def.player:<player> def.name:marie
- run storyboard_player_unfreeze def.player:<player>
- goto done
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* As promised, I'll show you around." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- if <[opinion]> == 1:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You should pay attention$$nlbecause it's going to help you out!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I hope so at least!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You can pay attention, but$$nlhonestly I don't care." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Anyway, follow me." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~walk <npc> <location[2,2,-130,world]> speed:1
- ~run storyboard_waituntil_safe def.player:<player> def.queue:<queue> def.condition:[player].location.distance_squared[<location[2,2,-130,world]>].is_less_than[10]
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So this is the academy." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Really big place." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Nobody really likes the <&4><&l>dean<&0><&l>, or$$nlwell, so I hear." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Grumpy, rich... You get the idea." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Although, they did something right." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Behind this building, there are$$nlsome <&o>sport fields." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* A lot of people really enjoy them." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll take you there soon, but$$nllet's walk through the academy a bit." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~walk <npc> <location[23,2,-174,world]> speed:1
- ~walk <npc> <location[2,2,-197,world]> speed:1
- ~walk <npc> <location[2,5,-225,world]> speed:1
- ~run storyboard_waituntil_safe def.player:<player> def.queue:<queue> def.condition:[player].location.distance_squared[<location[2,5,-225,world]>].is_less_than[10]
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So, anyway, the <&4><&l>dean<&0><&l> really went$$nlextra with this." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* No, but really...$$nlA decorative garden at the$$nlentrance...?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[surprised]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Anyway, let's keep going." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~walk <npc> <location[12,5,-240,world]> speed:1
- ~walk <npc> <location[2,5,-254,world]> speed:1
- ~walk <npc> <location[2,4,-314,world]> speed:1
- ~run storyboard_waituntil_safe def.player:<player> def.queue:<queue> def.condition:[player].location.distance_squared[<location[2,4,-314,world]>].is_less_than[10]
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* It is pretty, is it not?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Maybe they had a point." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[surprised]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Though I think people would appreciate$$nlit if they stopped being as snarky." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Not everyone in this town is kind and$$nlnice to you, you know?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- if <[opinion]> != 1:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* <&o>I can think of one, at least." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[upset]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So it's best you are careful." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You never know who you'll run into." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~walk <npc> <location[2,2,-333,world]> speed:1
- ~walk <npc> <location[-34,2,-359,world]> speed:1
- ~walk <npc> <location[-24,2,-398,world]> speed:1
- ~walk <npc> <location[2,2,-419,world]> speed:1
- ~run storyboard_waituntil_safe def.player:<player> def.queue:<queue> def.condition:[player].location.distance_squared[<location[2,2,-419,world]>].is_less_than[10]
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Well, here are the sport fields." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I heard they're quite fun to play at!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Though I suppose you'll need a friend,$$nlso maybe go together with someone!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[neutral]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'm sure you can call someone on$$nlthe phone!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- define should_give_phone <player.inventory.map_slots.values.filter[has_flag[phones]].is_empty>
- if <[should_give_phone]>:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* ..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[ummm]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* What?!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[ummm]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You don't have a phone?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[ummm]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Hey, I know." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll just give you a flip phone!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You can call, text, play music..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Give it a try!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:$$nl(You got the flip phone.)"
- fakeitem <[phone]> slot:hand
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Oh, and..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* We can continue at the Central Park." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I hear it's really easy to get there!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:$$nl(You remember something about /spawn)"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Well then, toodles!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[marie].get[happy]>
- run storyboard_player_freeze def.player:<player>
- ~walk <npc> <location[-44,2,-378,world]> speed:2
- run storyboard_player_unfreeze def.player:<player>
- run storyboard_npc_movement_commit def.player:<player> def.name:marie def.new_location:<location[-4,2,-15,world]>
- inventory update
- if <[should_give_phone]>:
- give <[phone]>
- mark done
- if !<[displeased]>:
- run storyboard_npc_state_set def.player:<player> def.name:marie def.key:opinion def.value:<[opinion].add[1]>
- else:
- run storyboard_npc_state_set def.player:<player> def.name:marie def.key:opinion def.value:<[opinion].sub[1]>
- inventory update
- zap 3
- disengage player

View File

@@ -0,0 +1,24 @@
storyboard_skin_dump:
debug: false
type: data
marie:
a: ewogICJ0aW1lc3RhbXAiIDogMTcwNjgwNTQ4MjM3OSwKICAicHJvZmlsZUlkIiA6ICJhODJkZTliNjZhYjE0OGZhOTQ3OGY0OWJiZjg5OTk1YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJmdWhyM3JibDRiIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Q5OTI3MTA4ZDI4MmQ0NTYxMmM5YWZmZGQ4NDA2ODAzYWNjYmY5ZWY5N2MyMzA4NDgwNGQ3YzYwNjAyNTlkZGMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==;to+5mawLkRklTI+r+N5HE/aMJPRtBYAzccTCAWfDhcH/6qpV3t25tsokGhZIfwyzn34ckycN0+Qo/HwIHpK4BYljf4TfnEI1/zLoH7V4oPnVjlwOuZuFT30OVlTo6z2vaWm3ZvhzAYsW6prt51CBZY2sGu76cBtbck7qOVUCdVzo+998dXWz19NF6mfZk11wKEsMeTWId9xB6KsNhZeqYrUr1R+PTzLl9fgsexPJ2WqZFpk1sGVzxdsxdjDxB4tDin9hulfnCq3Ar4xP+N8d1k6DMeudFaD6HltNRyfRr5nxIq7IyBU4dLG/aakUyasgVsU00v68+yzTA90sga8NSv9b1C0YTv91HcCIGbwmAoqGxuDibafkDTpEMfLAjRSIA4lxzJqZXCXssuTCzWnQVgS4OCm+MAwB08uX6uPMdL0EJwX3vMeiajQrX4P0oViKO4H0KwQnMXMOx5PqLDdFtWiBOE0NGTdJ1BqBfNbg4h3tNIv08y3hqUgUj/owfRnJ9X5EXibH2qk5+p4pHa15oDgM2Q6mSn4tkofR5nymvV8/YhtQLG9LJgeHsn6gY4ndWWk3zM3Gx3TOsDozrYs0hIfBSdLo6FJ0+7I2N/ga1Zj3Rj40d8EwGzrJrIY7v5Cz3zLnH8b70eUdAtGwW67/Qx1x/tmykKS1nfS9CGQW91M=;Marie
storyboard_avatar_dump:
debug: false
type: data
marie:
normal: 錁
neutral: 錂
happy: 錃
upset: 錄
surprised: 錅
ummm: 錆
sweat: 錇
ugh: 錈
oof: 錉
emika:
normal: 錑
smirk: 錒
smile: 錓
unimpressed: 錔

View File

@@ -0,0 +1,47 @@
dialogue_npc_kobayashi_assign:
debug: false
type: assignment
actions:
on assignment:
- trigger name:click state:true
interact scripts:
- dialogue_npc_kobayashi
dialogue_npc_kobayashi:
debug: false
type: interact
steps:
1:
click trigger:
script:
- if <player.flag[textbox_state].if_null[null]> != null:
- stop
- engage player
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Heya, sorry luv."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:We're currently under renovations, luv."
- definemap choices:
left:
text: Why?
right:
text: Unfortunate
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == left:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:What?$$nlWhy?"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Well, look, I can't tell you that, luv.$$nl It's against Hospital Policy."
- definemap choices:
left:
text: Sorry
right:
text: Don't care
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == left:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:No worries, luv!"
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:What?$$nlYou don't care?"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:I'm afraid I can't treat that, luv."
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Indeed, luv."
- wait 1s
- disengage player

View File

@@ -0,0 +1,25 @@
dialogue_npc_patchouli_assign:
debug: false
type: assignment
actions:
on assignment:
- trigger name:click state:true
interact scripts:
- dialogue_npc_patchouli
dialogue_npc_patchouli:
debug: false
type: interact
steps:
1:
click trigger:
script:
- if <player.flag[textbox_state].if_null[null]> != null:
- stop
- engage player
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:. . ."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:. . ."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:She is fast asleep."
- wait 1s
- disengage player
- ratelimit <player> 10t

View File

@@ -0,0 +1,31 @@
dialogue_npc_ryuko_assign:
debug: false
type: assignment
actions:
on assignment:
- trigger name:click state:true
interact scripts:
- dialogue_npc_ryuko
dialogue_npc_ryuko:
debug: false
type: interact
steps:
1:
click trigger:
script:
- if <player.flag[textbox_state].if_null[null]> != null:
- stop
- engage player
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Hey, what's up?!"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I hang out here a lot.$$nlI love to stay fit, be athletic."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Kicking balls is great!$$nl $$nl* uh.."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Anyway, the Academy sorta ran out of$$nlof tennis rackets."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Something about them being broken$$nland rusty, apparently."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* If you ask me, that's a bunch of crap!$$nlI think <&4><&l>the dean<&0><&l> is just no fun."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I think they don't want us playing.$$nlIt wouldn't be the first time."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I also haven't seen anyone play any$$nlbasketball recently, so I'm not sure$$nlwhat that's about."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* They should resolve this as soon as$$nlpossible before the students start a$$nlrebellion."
- wait 1s
- disengage player
- ratelimit <player> 10t

View File

@@ -0,0 +1,10 @@
intro_book:
debug: false
type: book
title: Intro Book
author: bqkitcat
signed: true
text:
- <bold>Welcome to SakuraFalls<n><n><reset>We encourage you to enable the resource pack for the best experience.<n><n>Please read the next page for more information.
- <bold>Tutorial<n><n><reset>You are going through the introductory tutorial. We will help you pick a character name and description, as well as your starting role.<n><n>Please read everything! It will help a lot.
- <bold>Questions<n><n><reset>Please type <bold>/ticket create<reset> in chat if you are having issues with the tutorial.<n><n>Send messages with <bold>/ooc (message)<reset> for everyone online.<n><n>You can also contact us on Discord, too, by <blue><underline><&click[https://discord.gg/bvDvQbT4s8].type[OPEN_URL]>clicking here<&end_click>

View File

@@ -0,0 +1,200 @@
# Posters
intro_interact_posters:
debug: false
type: world
events:
on player right clicks block:
- if !<context.location.note_name.if_null[null].starts_with[intro_interact_posters]>:
- stop
- determine cancelled passively
- if <player.has_flag[textbox_state]>:
- stop
- run intro_interact_posters_task
intro_interact_posters_task:
debug: false
type: task
script:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Book-related posters are on the wall."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:<&o><&dq>Screw that. I'm running away.<&dq>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:<&o><&dq>Where?<&dq>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:<&o><&dq>Dunno. Do you want to come?<&dq>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:<&o><&dq>Yes,<&dq> I said without thinking."
# Cirno
intro_interact_cirno:
debug: false
type: world
events:
on player right clicks block:
- if !<context.location.note_name.if_null[null].starts_with[intro_interact_cirno]>:
- stop
- determine cancelled passively
- if <player.has_flag[textbox_state]>:
- stop
- run intro_interact_cirno_task
intro_interact_cirno_task:
debug: false
type: task
script:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:A quality, soft plushie of a beloved$$nlcharacter."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:It seems familiar, as if there are a$$nlsubstantial amount of images circulating$$nlaround with this character."
# Laptop
intro_interact_laptop:
debug: false
type: world
events:
on player right clicks block:
- if !<context.location.note_name.if_null[null].starts_with[intro_interact_laptop]>:
- stop
- determine cancelled passively
- if <player.has_flag[textbox_state]>:
- stop
- run intro_interact_laptop_task
intro_interact_laptop_task:
debug: false
type: task
script:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:It looks like a game is booted up.$$nlYou can see a city, and it looks like..."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:. . ."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:It's <bold>you!$$nl. . .$$nlWell, it's your character."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:You should give your character$$nla cool name, right?"
- waituntil <player.has_flag[textbox_state].not> max:5s
- ~run textbox_flush def.player:<player>
- run anvil_input def.player:<player> "def.prompt:Character Name" def.callback:intro_interact_laptop_task_name_callback
intro_interact_laptop_task_name_callback:
debug: false
type: task
definitions: player|input
script:
- define __player <[player]>
- define name <[input].substring[1,24]>
- execute as_player player:<[player]> "rpname <[name]>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:<[name]>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:How nice!"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Let's give them a description.$$nlDescribe their physical attributes."
- waituntil <player.has_flag[textbox_state].not> max:5s
- ~run textbox_flush def.player:<player>
- run anvil_input def.player:<player> "def.prompt:Description" def.callback:intro_interact_laptop_task_description_callback
intro_interact_laptop_task_description_callback:
debug: false
type: task
definitions: player|input
script:
- define __player <[player]>
- execute as_player player:<[player]> "setdesc <[input]>"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Great, your character's almost ready."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Lastly, your character can start$$nlout as a student or as$$nlan <bold>adult."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Both options are great, and it's$$nlmostly a matter of preference."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:For complete beginners, we recommend$$nlstarting out as a student."
- waituntil <player.has_flag[textbox_state].not> max:5s
- ~run textbox_flush def.player:<player>
- run intro_interact_laptop_task_role_menu def.player:<player>
intro_interact_laptop_task_role_menu:
debug: false
type: task
definitions: player
script:
- definemap contents:
1:
item: <item[paper[display=<&6><&l>» <&e>Choose your starting role;lore=<&7>Your role gives you different roleplay opportunities and gameplay.|<&7>You can make a new character after the tutorial if you are unsure.]]>
4:
item: <item[book[display=<&f>鐀;lore=<&7><&o>A new student at Tatsuru Academy, ready to learn|<&7><&o>and live a highschooler's life.]]>
script: intro_interact_laptop_task_role_callback
definitions:
player: <[player]>
input: no
6:
item: <item[book[display=<&f>鐃;lore=<&7><&o>Freshly moved into Atarashikibo, on your way to|<&7><&o>find a job and a meaning.]]>
script: intro_interact_laptop_task_role_callback
definitions:
player: <[player]>
input: yes
- run menu_open def.player:<[player]> "def.title:<&f>邑邑邑邑酐<&a><&sp><&b><&sp><&c><&sp>" def.size:9 def.contents:<[contents]>
intro_interact_laptop_task_role_callback:
debug: false
type: task
definitions: player|input
script:
- inventory close player:<[player]>
- define __player <[player]>
- define adult <[input].to_lowercase.trim.equals[yes]>
- if <[adult]>:
- execute as_server "lp user <player.name> parent add adult"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:An adult it shall be.$$nlIf this is wrong, let us know."
- else:
- execute as_server "lp user <player.name> parent add grade-10"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:A student it shall be.$$nlIf this is wrong, let us know."
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:You should now be ready to start!"
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:Have fun!"
- waituntil <player.has_flag[textbox_state].not> max:5s
- cast BLINDNESS duration:infinite <player> no_ambient hide_particles no_icon
- wait 1s
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Though..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I feel obligated to ask." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Have you heard of <&o>IC<&0><&l> and <&o>OOC<&0><&l>?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- definemap choices:
left:
text: Not really
right:
text: Yeah
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == left:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Ah..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You see, this WORLD..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* This... <&o>representation<&0><&l>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You exist beyond it." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'm talking about you, <player.name>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smirk]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Your character.$$nlYour VESSEL.$$nl<player.flag[character_rpname]>" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* They do not." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smirk]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You, <player.name>, are <&o>out of character<&0><&l>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Your VESSEL...$$nl<player.flag[character_rpname]>$$nlThey are <&o>in character<&0><&l>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So, when your VESSEL speaks..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* That is not <&o>you<&0><&l>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Your VESSEL has different feelings,$$nlemotions, and experiences." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* What those are is for you to decide." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smirk]>
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Ah..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[unimpressed]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So you know they stand for$$nl<&o>in character<&0><&l> and <&o>out of character." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You are probably familiar with$$nlthis WORLD." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* You are probably familiar with$$nlroleplaying, too." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I apologise for doubting you$$nllike that." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* . . ." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[unimpressed]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* In this world, we get to choose who$$nlwe are, at least sort of." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Maybe we cannot decide what the$$nloutcome will be, but we can try." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* <player.flag[character_rpname]>, I..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[normal]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I think your choices are important,$$nlregardless." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I think you should try your best to$$nldo what your heart tells you." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Wouldn't you agree?" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- definemap choices:
left:
text: Correct
right:
text: ...
- ~run textbox_choice def.player:<player> def.queue:<queue> def.choices:<[choices]> save:result
- define choice <entry[result].created_queue.determination.get[1]>
- if <[choice]> == left:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'm glad you understand." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- else:
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Ah..." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[unimpressed]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I see." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smirk]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* Very well. You are truly ready." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* When you are finally linked to$$nlour WORLD, you will see <&o>Marie<&0><&l>." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* She has talked to many others just$$nllike you." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* So, you should probably talk to her." def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- ~run textbox_write def.player:<player> def.queue:<queue> "def.line3s:* I'll be on my way.$$nlGood luck!" def.avatar_unicode:<script[storyboard_avatar_dump].data_key[emika].get[smile]>
- waituntil <player.has_flag[textbox_state].not> max:5s
- ~run textbox_flush def.player:<player>
- adjust <player> remove_effects
- adjust <player> show_to_players
- flag <player> intro:done
- execute as_player player:<player> "spawn"

View File

@@ -0,0 +1,18 @@
intro_world:
debug: false
type: world
events:
after player joins:
- define intro <player.flag[intro].if_null[null]>
- if <[intro]> != done:
- adjust <player> hide_from_players
- adjust <player> remove_effects
- run textbox_flush def.player:<player>
- if <[intro]> == null:
- teleport <player> <location[313.5,3,258.5,0,270,world]>
- flag <player> intro:progress
- adjust <player> show_book:intro_book
on player teleports bukkit_priority:lowest:
- if <player.flag[intro].if_null[null]> == progress:
- determine cancelled passively
- narrate "<&c>You may not teleport at this time."

View File

@@ -0,0 +1,255 @@
#
# Storyboard NPC Tasks
#
# Adds a complex set of per-player state managed NPC routines which
# allow for the creation of RPG-like stories, similar to Undertale.
#
# The routines and state system is also as memory efficient and lazy
# as possible. It utilizes Denizen and Citizens to their best, taking
# advantage of Denizen's innate scripting possibilites.
#
# Allocates an NPC with a given name at some location for the current player.
#
# Optionally, specify a display name, display name visibility, and a skin_blob.
# Generate Skin Blobs using https://mineskin.org - it cannot be done automatically
# at this time.
#
# If the NPC is reallocated from player state, it will try to re-fill these values.
# You can specify new values to change these.
# Note it will only try to fill these optional values, not "name", "type", and "at".
#
# The name of the NPC must be unique - this is not the same as the display
# name of the NPC; rather it is an internal name, so it's recommended to
# keep it lowercase.
#
# If the NPC is not allocated but was saved in the player's mem state, it
# will be created and its state will be restored.
# If the NPC is already allocated, it will simply teleport the NPC.
#
# All NPCs are memfree'd when a player leaves, which does not reduce storage
# overhead, but does greatly reduce overhead when hiding/showing per-player NPCs.
# They are automatically memalloc'ed when a player rejoins.
storyboard_npc_memalloc:
debug: false
type: task
definitions: player|name|type|at|display_name|show_name|skin_blob
script:
- define registry registry_<[player].uuid>
- define npc_id npc_<[player].uuid>_<[name]>
- if !<server.npcs[<[registry]>].if_null[<list[]>].contains[<[npc_id]>]>:
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- create <[type]> <[npc_id]> <[at]> registry:<[registry]> save:npc
- define npc <entry[npc].created_npc>
- define npc_state <map[]>
- define assignment null
- if <[npcs].contains[<[name]>]>:
- define npc_data <[npcs].get[<[name]>]>
- define npc_state <[npc_data].get[state]>
- if <[display_name].if_null[null]> == null:
- define display_name <[npc_data].get[display_name]>
- if <[show_name].if_null[null]> == null:
- define show_name <[npc_data].get[show_name]>
- if <[skin_blob].if_null[null]> == null:
- define skin_blob <[npc_data].get[skin_blob]>
- define assignment <[npc_data].get[assignment].if_null[null]>
- else:
- if <[display_name].if_null[null]> == null:
- define display_name <[display_name].if_null[<[name].to_sentence_case>]>
- if <[show_name].if_null[null]> == null:
- define show_name <[show_name].if_null[true]>
- if <[skin_blob].if_null[null]> == null:
- define skin_blob <[skin_blob].if_null[null]>
- definemap npc_data:
name: <[name]>
type: <[type]>
at: <[at]>
state: <[npc_state]>
display_name: <[display_name]>
show_name: <[show_name]>
skin_blob: <[skin_blob]>
allocated: true
assignment: <[assignment]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
- adjust <[npc]> auto_update_skin:false
- adjust <[npc]> name_visible:false
- lookclose <[npc]> state:true range:4
- if !<[show_name]>:
- adjust <[npc]> hologram_lines:<list[]>
- else:
- adjust <[npc]> "hologram_lines:<&f>鐓 <[display_name]>"
- if <[skin_blob]> != null:
- adjust <[npc]> skin_blob:<[skin_blob]>
- if <[assignment]> != null:
- assignment set script:<[assignment]> to:<[npc]>
- wait 2t
- run storyboard_npc_internal_show_to_player def.player:<[player]> def.npc:<[npc]>
- else:
- define index <server.npcs[<[registry]>].find[<[npc_id]>]>
- define npc <npc[<[index]>,<[registry]>]>
- teleport <[npc]> <[at]>
# Retrieves an NPC from the player's unique NPC registry by name.
storyboard_npc_by_name:
debug: false
type: procedure
definitions: player|name
script:
- define registry registry_<[player].uuid>
- define npc_id npc_<[player].uuid>_<[name]>
- determine <server.npcs[<[registry]>].filter_tag[<[filter_value].name.equals[<[npc_id]>]>].get[1]>
# Frees an NPC from memory, but does not destroy its state.
#
# This is often done automatically when the player leaves the server, however it may
# be useful for programmers to manually call this routine for optimization purposes.
#
# If you don't want the server to reallocate the NPC on player join, provide
# the reallocate definition as 'reallocate' (or just don't provide it).
storyboard_npc_memfree:
debug: false
type: task
definitions: player|name|reallocate
script:
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- define reallocate <[reallocate].if_null[false]>
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define npc_data <[npc_data].with[allocated].as[<[reallocate]>]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
- remove <[npc]>
# Destroys an NPC from memory, which destroys its state.
# Further memalloc's will re-create the NPC with new state data.
# Use this when you are 100% done with using an NPC.
# If you only want to remove an NPC until later, but keep its state,
# consider calling storyboard_npc_memfree instead.
storyboard_npc_memdestroy:
debug: false
type: task
definitions: player|name
script:
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npcs <[npcs].exclude[<[name]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- remove <[npc]>
# Flags the NPC by name, mapping the given key to the given value.
storyboard_npc_state_set:
debug: false
type: task
definitions: player|name|key|value
script:
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define state <[npc_data].get[state].if_null[<map[]>]>
- define state <[state].with[<[key]>].as[<[value]>]>
- define npc_data <[npc_data].with[state].as[<[state]>]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
# Gets a state value from the NPC by name and key; effectively like reading a flag.
# If the given key does not exist/is not set, determines null.
storyboard_npc_state_get:
debug: false
type: procedure
definitions: player|name|key
script:
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define state <[npc_data].get[state].if_null[<map[]>]>
- determine <[state].get[<[key]>].if_null[null]>
# Deletes a flag from the NPC by name and key.
storyboard_npc_state_clear:
debug: false
type: task
definitions: player|name|key
script:
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define state <[npc_data].get[state].if_null[<map[]>]>
- define state <[state].exclude[<[key]>]>
- define npc_data <[npc_data].with[state].as[<[state]>]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
# Sets an NPCs assignment, which also persists across memfrees.
storyboard_npc_set_assignment:
debug: false
type: procedure
definitions: player|name|assignment
script:
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define npc_data <[npc_data].with[assignment].as[<[assignment]>]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
- assignment set script:<[assignment]> to:<[npc]>
# Moves an NPC to a new location, both physically, and in memory also.
# When an NPC is moved by normal teleports or the walk command, its location isn't stored.
# Use this to either commit its final position, or teleport it after a cutscene.
storyboard_npc_movement_commit:
debug: false
type: procedure
definitions: player|name|new_location
script:
- define npc <proc[storyboard_npc_by_name].context[<[player]>|<[name]>]>
- define npcs <[player].flag[storyboard_state].get[npcs].if_null[<map[]>]>
- define npc_data <[npcs].get[<[name]>]>
- define npc_data <[npc_data].with[at].as[<[new_location]>]>
- define npcs <[npcs].with[<[name]>].as[<[npc_data]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[npcs].as[<[npcs]>]>
- teleport <[npc]> <[new_location]>
## Internal only!
storyboard_npc_internal_auto_memory_management:
debug: false
type: world
events:
after player joins:
- define npcs <player.flag[storyboard_state].get[npcs].if_null[<map[]>]>
- foreach <[npcs]> key:name as:data:
- if <[data].get[allocated]> == reallocate:
- define name <[data].get[name]>
- define type <[data].get[type]>
- define at <[data].get[at]>
- run storyboard_npc_memalloc def.player:<player> def.name:<[name]> def.type:<[type]> def.at:<[at]>
on player quits:
- define registry registry_<player.uuid>
- define npcs <server.npcs[<[registry]>].if_null[<list[]>]>
- define substr_length <element[npc_<player.uuid>_].length.add[1]>
- foreach <[npcs]> as:npc:
- define name <[npc].name.substring[<[substr_length]>]>
- run storyboard_npc_memfree def.player:<player> def.name:<[name]> def.reallocate:reallocate
storyboard_npc_internal_show_to_player:
debug: false
type: task
definitions: player|npc
script:
- adjust <[npc]> hide_from_players
- adjust <[player]> show_entity:<[npc]>
- foreach <[npc].hologram_npcs.if_null[<list[]>]> as:hologram:
- adjust <[hologram]> hide_from_players
- adjust <[player]> show_entity:<[hologram]>
storyboard_npc_internal_auto_display_entities:
debug: false
type: world
events:
on player joins bukkit_priority:high:
- foreach <server.online_players.exclude[<player>]> as:target:
- define registry registry_<[target].uuid>
- define npcs <server.npcs[<[registry]>].if_null[<list[]>]>
- foreach <[npcs]> as:npc:
- adjust <player> hide_entity:<[npc]>
- foreach <[npc].hologram_npcs.if_null[<list[]>]> as:hologram:
- adjust <player> hide_entity:<[hologram]>

View File

@@ -0,0 +1,70 @@
#
# Storyboard Player Tasks
#
# Adds a set of tasks for managing player storyboard state.
# Pretty common in use.
#
# Note: These actions are **committed** - so should be executed LAST in a script.
# This allows the actions to "rollback" in case the server crashes/player disconnects.
#
# Sets a named key to any value in the player state.
storyboard_player_state_set:
debug: false
type: task
definitions: player|key|value
script:
- define state <[player].flag[storyboard_state].get[state].if_null[<map[]>]>
- define state <[state].with[<[key]>].as[<[value]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[state].as[<[state]>]>
# Removes a named key from player state.
# If the key doesn't exist, silently fails.
storyboard_player_state_clear:
debug: false
type: task
definitions: player|key
script:
- define state <[player].flag[storyboard_state].get[state].if_null[<map[]>]>
- define state <[state].exclude[<[key]>]>
- flag <[player]> storyboard_state:<[player].flag[storyboard_state].if_null[<map[]>].with[state].as[<[state]>]>
# Gets a named key from player state.
# If the key doesn't exist, "null" is returned.
storyboard_player_state_get:
debug: false
type: procedure
definitions: player|key
script:
- define state <[player].flag[storyboard_state].get[state].if_null[<map[]>]>
- determine <[state].get[<[key]>].if_null[null]>
# Freezes a player in place by setting their speed to 0.
# On relogs, automatically 'unfreezes' them.
# See the complementary task storyboard_player_unfreeze
storyboard_player_freeze:
debug: false
type: task
definitions: player
script:
- flag <player> storyboard_freeze_speed:<player.walk_speed>
- adjust <player> walk_speed:0
# Unfreezes a player. Always happens automatically on relogs.
# See the complementary task storyboard_player_freeze
storyboard_player_unfreeze:
debug: false
type: task
definitions: player
script:
- adjust <player> walk_speed:<player.flag[storyboard_freeze_speed]>
- flag <player> storyboard_freeze_speed:!
## Internal only!
storyboard_player_freeze_check:
debug: false
type: world
events:
on player joins:
- if <player.has_flag[storyboard_freeze_speed]>:
- run storyboard_player_unfreeze def.player:<player>

View File

@@ -0,0 +1,27 @@
#
# Storyboard Player Utils
# Various optional utils which tend to be pretty helpful.
#
# Gets the player character's first name (or what should be the first name).
storyboard_character_first_name:
debug: false
type: procedure
definitions: player
script:
- determine <[player].flag[character_rpname].split.first.to_sentence_case.if_null[<&lt>?<&gt>]>
# Effectively like a permanent waituntil, except checks if player's online, etc.; if not, kills the queue.
storyboard_waituntil_safe:
debug: false
type: task
definitions: player|queue|condition
script:
- while true:
- define condition_parsed <element[<&lt><[condition]><&gt>].parsed>
- if <[condition_parsed]> || !<[player].is_online>:
- while stop
- wait 10t
- if !<[player].is_online>:
- queue stop <[queue]>
- debug log "[Storyboard] Cancelled queue <[queue].numeric_id><&at><[queue].script.name> for <[player].name>; offline"

View File

@@ -0,0 +1,16 @@
stroll_command_stroll:
debug: false
type: command
name: stroll
usage: /stroll
description: Makes you walk a lil slower, until you run or sneak.
permission: stroll.command.stroll
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- flag <player> stroll_speed:<player.walk_speed>
- adjust <player> walk_speed:0.1
- narrate format:formats_prefix "You are now strolling. Sprint or sneak to stop strolling."

View File

@@ -0,0 +1,12 @@
stroll_world:
debug: false
type: world
events:
on player toggles sneaking:
- if <player.has_flag[stroll_speed]>:
- adjust <player> walk_speed:<player.flag[stroll_speed]>
- flag <player> stroll_speed:!
on player toggles sprinting:
- if <player.has_flag[stroll_speed]>:
- adjust <player> walk_speed:<player.flag[stroll_speed]>
- flag <player> stroll_speed:!

View File

@@ -0,0 +1,17 @@
suspension_command_suspension:
debug: false
type: command
name: suspension
description: Check how long you have until suspension expires.
usage: /suspension
permission: suspension.command.suspension
tab completions:
1: <empty>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.in_group[suspended]>:
- narrate format:formats_prefix "You are suspended for <&e><placeholder[luckperms_group_expiry_time_suspended].player[<player>]><&7>."
- else:
- narrate format:formats_prefix "You are not suspended."

View File

@@ -0,0 +1,78 @@
tabcomplete_config:
debug: false
type: data
groups:
default:
commands:
- plugins
- sit
- lay
- crawl
- call
- text
- ooc
- looc
- chsw
- channelswitch
- spawn
- balance
- bal
- stroll
- roll
- findname
- fn
- rpname
- setdesc
- viewdescription
- viewdesc
- setdescription
- carry
- uncarry
- apartmentaddmember
- aptaddmember
- aptam
- apartmentaddmoderator
- aptaddmod
- apartmentremoveaccess
- aptremoveaccess
- aptrm
- apartmenteditmode
- apteditmode
- editmode
- grade
- playtime
- wardrobe
- ticket
- langcall
- langcally
- langcallw
- cally
- callw
- yell
- y
- whisper
- w
- me
- mel
- melong
- mec
- meclose
- itc
- itclose
- itl
- itlong
- it
- my
- language
- lang
- languagewhisper
- langwhisper
- langw
- languageyell
- langyell
- langy
- payto
- ticket
- chatcolor
- spawn
- profiles

View File

@@ -0,0 +1,11 @@
tabcomplete_fetch:
debug: false
type: procedure
definitions: player
script:
- define result <list[]>
- define data <script[tabcomplete_config].data_key[groups]>
- foreach <[data]> key:group as:group_data:
- if <[group]> == default || <[player].has_permission[<[group_data].get[permission].if_null[true]>]>:
- define result <[result].include[<[group_data].get[commands].if_null[<list[]>]>]>
- determine <[result]>

View File

@@ -0,0 +1,9 @@
tabcomplete_world:
debug: false
type: world
events:
on player receives commands:
- if <player.is_op>:
- if <player.flag[tabcomplete_ignore].if_null[false]>:
- stop
- determine <proc[tabcomplete_fetch].context[<player>]>

View File

@@ -0,0 +1,130 @@
templatetools_command_templatetools:
debug: false
type: command
name: templatetools
description: TemplateTools info.
usage: /templatetools
aliases:
- tt
permission: templatetools.command.tt
tab completions:
1: <list[]>
script:
- narrate format:templatetools_formats_main "TemplateTools (Denizen impl.) v1.0.0.0"
- narrate format:templatetools_formats_main "Author: unsafemalloc"
templatetools_command_ttpack:
debug: false
type: command
name: ttpack
description: Changes pack for Template Tool usage.
usage: /ttpack (pack)
permission: templatetools.command.ttpack
tab completions:
1: <proc[templatetools_available_packs].context[<player>]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> != 1:
- narrate "<&c>Invalid use. Please try /<context.alias> (pack)."
- stop
- if !<proc[templatetools_available_packs].contains[<context.args.get[1]>]>:
- narrate "<&c>There is no such pack: <context.args.get[1]>"
- stop
- flag <player> templatetools_pack:<context.args.get[1]>
- flag <player> templatetools_pack_index:1
- ~run templatetools_schematic_set_index def.player:<player>
- run templatetools_preview_queue def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
- narrate format:templatetools_formats_main "Set TemplateTools pack to <context.args.get[1]> (use /ttschematic to select a schematic)"
templatetools_command_ttschematic:
debug: false
type: command
name: ttschematic
description: Changes schematic for Template Tool usage.
usage: /ttschematic (schematic)
permission: templatetools.command.ttschematic
tab completions:
1: <proc[templatetools_available_schematics].context[<player>]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <context.args.size> != 1:
- narrate "<&c>Invalid use. Please try /<context.alias> (schematic)."
- stop
- if !<player.has_flag[templatetools_pack]>:
- narrate "<&c>Please select a template pack first using /ttpack."
- stop
- if !<proc[templatetools_available_schematics].context[<player>].contains[<context.args.get[1]>]>:
- narrate "<&c>There is no such schematic: <context.args.get[1]>"
- stop
- if <schematic.list.contains[templatetools_<player.uuid>]>:
- ~schematic unload name:templatetools_<player.uuid>
- schematic load name:templatetools_<player.uuid> filename:<player.flag[templatetools_pack]>/<context.args.get[1]>
- flag <player> templatetools_schematic:templatetools_<player.uuid>
- narrate format:templatetools_formats_main "Set TemplateTools schematic to <context.args.get[1]> (you can preview it using a Spider Eye)"
templatetools_command_ttundo:
debug: false
type: command
name: ttundo
description: Undoes last operation.
usage: /ttundo
permission: templatetools.command.ttundo
tab completions:
1: <list[]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- if <player.flag[templatetools_undo].if_null[<list[]>].is_empty>:
- narrate format:templatetools_formats_main "Nothing left to undo."
- stop
- run templatetools_pop_undo def.player:<player>
- narrate format:templatetools_formats_main "Undid previous operation."
templatetools_command_ttsetcursor:
debug: false
type: command
name: ttsetcursor
aliases:
- ttsc
description: Sets blocks in WorldEdit selection using the material you're looking at.
usage: /ttsetcursor
permission: templatetools.command.ttsetcursor
tab completions:
1: <list[]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- define material <player.cursor_on.material.if_null[null]>
- if <[material]> == null:
- narrate "<&c>Invalid material. Please look at a material to set first!"
- stop
- define we_selection <player.we_selection.if_null[null]>
- if <[we_selection]> == null:
- narrate "<&c>You must first make a WorldEdit selection."
- stop
- ~modifyblock <[we_selection]> <[material]> no_physics
- narrate format:templatetools_formats_main "Set cursor blocks (<[we_selection].volume.if_null[?]>)."
templatetools_command_that:
debug: false
type: command
name: that
description: TemplateTools info.
usage: /that
permission: templatetools.command.that
tab completions:
1: <list[]>
script:
- define material <player.cursor_on.material.if_null[null]>
- if <[material]> == null:
- narrate "<&c>Nothing to copy."
- define item <item[<[material].name>].if_null[null]>:
- narrate "<&c>Nothing to copy."
- inventory set slot:hand origin:<[item]>
- narrate format:templatetools_formats_main "Copied <[material].name>."

View File

@@ -0,0 +1,4 @@
templatetools_formats_main:
debug: false
type: format
format: <&8>(<&b><&l>TT<&8>) <&7><[text]>

View File

@@ -0,0 +1,183 @@
templatetools_available_packs:
debug: false
type: procedure
script:
- determine <util.list_files[schematics].filter_tag[<[filter_value].advanced_matches[*.*].not>]>
templatetools_pack_length:
debug: false
type: procedure
definitions: player
script:
- if !<[player].has_flag[templatetools_pack]>:
- determine 0
- determine <proc[templatetools_available_schematics].context[<[player]>].size>
templatetools_pack_increment:
debug: false
type: task
definitions: player
script:
- define pack_length <proc[templatetools_pack_length].context[<[player]>]>
- if <[pack_length]> == 0:
- stop
- define index <[player].flag[templatetools_pack_index].add[1]>
- if <[index]> > <[pack_length]>:
- define index 1
- flag <[player]> templatetools_pack_index:<[index]>
templatetools_pack_decrement:
debug: false
type: task
definitions: player
script:
- define pack_length <proc[templatetools_pack_length].context[<[player]>]>
- if <[pack_length]> == 0:
- stop
- define index <[player].flag[templatetools_pack_index].sub[1]>
- if <[index]> < 1:
- define index <[pack_length]>
- flag <[player]> templatetools_pack_index:<[index]>
templatetools_available_schematics:
debug: false
type: procedure
definitions: player
script:
- if !<[player].has_flag[templatetools_pack]>:
- determine <list[]>
- determine <util.list_files[schematics/<[player].flag[templatetools_pack]>].parse_tag[<[parse_value].replace_text[regex:.schem$].with[]>].if_null[<list[]>].alphanumeric>
templatetools_schematic_set_index:
debug: false
type: task
definitions: player
script:
- define schematics <proc[templatetools_available_schematics].context[<[player]>]>
- if <schematic.list.contains[<[player].flag[templatetools_schematic]>]>:
- ~schematic unload name:<[player].flag[templatetools_schematic]>
- schematic load name:templatetools_<[player].uuid> filename:<[player].flag[templatetools_pack]>/<[schematics].get[<[player].flag[templatetools_pack_index]>]>
- actionbar "<&e>Schematic <[player].flag[templatetools_pack_index]>: <&f><[schematics].get[<[player].flag[templatetools_pack_index]>]>" targets:<[player]>
templatetools_preview_queue:
debug: false
type: task
definitions: player|schematic
script:
- if <[player].has_flag[templatetools_preview_queue]>:
- stop
- flag <[player]> templatetools_preview_queue:true expire:0.5s
- wait 0.5s
- if !<schematic.list.contains[<[schematic]>]>:
- stop
- waituntil <schematic[<[schematic]>].width.if_null[-1]> != -1 max:2s
- flag <[player]> templatetools_preview_queue:!
- run templatetools_preview def.player:<[player]> def.schematic:<[schematic]>
templatetools_preview_show:
debug: false
type: task
definitions: player|schematic
script:
- define cursor_on <[player].cursor_on.if_null[null]>
- if <[cursor_on]> == null:
- stop
- if !<schematic.list.contains[<[schematic]>]>:
- stop
- define cuboid <schematic[<[schematic]>].cuboid[<[cursor_on]>]>
- define middle <[cuboid].center>
- define smallest_y <[cuboid].corners.get[first].y>
- if <[cuboid].corners.get[last].y> < <[smallest_y]>:
- define smallest_y <[cuboid].corners.get[last].y>
- define difference_y <[cursor_on].y.sub[<[smallest_y]>]>
- define cursor_on <[cursor_on].sub[0,<[difference_y].sub[1]>,0]>
- define fakedlocations <list[]>
- if !<[player].item_in_hand.advanced_matches[spider_eye]>:
- run templatetools_preview_clear def.player:<[player]>
- stop
- define halfwidth <schematic[<[schematic]>].width.div[2]>
- define halflength <schematic[<[schematic]>].length.div[2]>
- repeat <schematic[<[schematic]>].width> from:0 as:x:
- repeat <schematic[<[schematic]>].height> from:0 as:y:
- repeat <schematic[<[schematic]>].length> from:0 as:z:
- define location <location[<[x]>,<[y]>,<[z]>,<[player].world.name>]>
- define block <schematic[<[schematic]>].block[<[location]>]>
- if <[block].name> == air:
- repeat next
- define fakedlocation <[cursor_on].add[<[location]>].sub[<[halfwidth]>,0,<[halflength]>].add[1,0,1]>
- showfake <schematic[<[schematic]>].block[<[location]>]> <[fakedlocation]> players:<[player]> duration:1h
- define fakedlocations <[fakedlocations].include[<[fakedlocation]>]>
- flag <[player]> templatetools_preview_region:<[fakedlocations]>
templatetools_preview_clear:
debug: false
type: task
definitions: player
script:
- if !<[player].has_flag[templatetools_preview_region]>:
- stop
- showfake cancel <[player].flag[templatetools_preview_region]>
- flag <[player]> templatetools_preview_region:!
templatetools_preview:
debug: false
type: task
definitions: player|schematic
script:
- ~run templatetools_preview_clear def.player:<[player]>
- run templatetools_preview_show def.player:<[player]> def.schematic:<[schematic]>
templatetools_preview_paste:
debug: false
type: task
definitions: player|schematic
script:
- define cursor_on <[player].cursor_on.if_null[null]>
- if <[cursor_on]> == null:
- stop
- define cuboid <schematic[<[schematic]>].cuboid[<[cursor_on]>]>
- define middle <[cuboid].center>
- define smallest_y <[cuboid].corners.get[first].y>
- if <[cuboid].corners.get[last].y> < <[smallest_y]>:
- define smallest_y <[cuboid].corners.get[last].y>
- define difference_y <[cursor_on].y.sub[<[smallest_y]>]>
- define cursor_on <[cursor_on].sub[0,<[difference_y].sub[1]>,0]>
- if !<[player].item_in_hand.advanced_matches[spider_eye]>:
- run templatetools_preview_clear def.player:<[player]>
- stop
- define halfwidth <schematic[<[schematic]>].width.div[2]>
- define halflength <schematic[<[schematic]>].length.div[2]>
- define count 0
- define undodata <map[]>
- repeat <schematic[<[schematic]>].width> from:0 as:x:
- repeat <schematic[<[schematic]>].height> from:0 as:y:
- repeat <schematic[<[schematic]>].length> from:0 as:z:
- define location <location[<[x]>,<[y]>,<[z]>,<[player].world.name>]>
- define block <schematic[<[schematic]>].block[<[location]>]>
- if <[block].name> == air:
- repeat next
- define fakedlocation <[cursor_on].add[<[location]>].sub[<[halfwidth]>,0,<[halflength]>].add[1,0,1]>
- define previousmaterial <[fakedlocation].material>
- modifyblock <schematic[<[schematic]>].block[<[location]>]> <[fakedlocation]> no_physics
- define undodata <[undodata].with[<[fakedlocation]>].as[<[previousmaterial]>]>
- define count <[count].add[1]>
- run templatetools_push_undo def.player:<[player]> def.data:<[undodata]>
- determine <[count]>
templatetools_push_undo:
debug: false
type: task
definitions: player|data
script:
- flag <[player]> templatetools_undo:<[player].flag[templatetools_undo].if_null[<list[]>].include[<[data]>]>
templatetools_pop_undo:
debug: false
type: task
definitions: player
script:
- if <[player].flag[templatetools_undo].if_null[<list[]>].is_empty>:
- stop
- foreach <[player].flag[templatetools_undo].last> key:location as:material:
- modifyblock <[material]> <[location]> no_physics
- flag <[player]> templatetools_undo:<[player].flag[templatetools_undo].remove[last]>

View File

@@ -0,0 +1,98 @@
templatetools_world_cleanup:
debug: false
type: world
events:
after server start:
- foreach <schematic.list.filter_tag[<[filter_value].starts_with[templatetools_]>]> as:schematic:
- schematic unload name:<[schematic]>
- foreach <server.players_flagged[templatetools_undo]> as:player:
- flag <[player]> templatetools_undo:!
templatetools_world_preview:
debug: false
type: world
events:
on player walks:
- if !<player.item_in_hand.advanced_matches[spider_eye]>:
- stop
- if !<player.has_permission[templatetools.tools.schematic]>:
- stop
- if !<player.has_flag[templatetools_pack]>:
- stop
- if !<player.has_flag[templatetools_schematic]>:
- stop
- run templatetools_preview_queue def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
on player scrolls their hotbar:
- if !<player.has_permission[templatetools.tools.schematic]>:
- stop
- if !<player.has_flag[templatetools_pack]>:
- stop
- if <player.is_sneaking>:
- if !<player.item_in_hand.advanced_matches[spider_eye]>:
- stop
- determine cancelled passively
- if <context.new_slot> > <context.previous_slot>:
- if <context.previous_slot> == 1 && <context.new_slot> == 9:
- run templatetools_pack_increment def.player:<player>
- else:
- run templatetools_pack_decrement def.player:<player>
- else:
- if <context.previous_slot> == 9 && <context.new_slot> == 1:
- run templatetools_pack_decrement def.player:<player>
- else:
- run templatetools_pack_increment def.player:<player>
- run templatetools_schematic_set_index def.player:<player>
- run templatetools_preview_queue def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
- else:
- if !<player.has_flag[templatetools_schematic]>:
- stop
- if <player.inventory.slot[<context.new_slot>].material.name> == spider_eye:
- run templatetools_preview_queue def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
- else:
- run templatetools_preview_clear def.player:<player>
after player clicks in inventory:
- if !<player.has_permission[templatetools.tools.schematic]>:
- stop
- if !<player.has_flag[templatetools_pack]>:
- stop
- if !<player.has_flag[templatetools_schematic]>:
- stop
- if <player.item_in_hand.advanced_matches[spider_eye]>:
- run templatetools_preview def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
- determine cancelled passively
- else:
- run templatetools_preview_clear def.player:<player>
on player left clicks block:
- if !<player.has_permission[templatetools.tools.schematic]>:
- stop
- if !<player.item_in_hand.advanced_matches[spider_eye]>:
- stop
- if !<player.has_flag[templatetools_pack]>:
- stop
- if !<player.has_flag[templatetools_schematic]>:
- stop
- determine cancelled passively
- if <player.is_sneaking>:
- schematic rotate name:<player.flag[templatetools_schematic]> angle:90
- run templatetools_preview_queue def.player:<player> def.schematic:<player.flag[templatetools_schematic]>
- actionbar "<&e>Rotated schematic 90 degrees."
- else:
- run templatetools_preview_paste def.player:<player> def.schematic:<player.flag[templatetools_schematic]> save:return
- define count <entry[return].created_queue.determination.get[1]>
- narrate format:templatetools_formats_main "Placed schematic (<[count]>)."
templatetools_world_redtorchtool:
debug: false
type: world
events:
on player right clicks block:
- if !<player.has_permission[templatetools.tools.redtorch]>:
- stop
- if !<player.item_in_hand.advanced_matches[redstone_torch]>:
- stop
- if <player.is_sneaking>:
- stop
- determine cancelled passively
- if <context.location.material.switched.if_null[null]> != null:
- switch <context.location> no_physics
- narrate format:templatetools_formats_main "Switched block state."

View File

@@ -0,0 +1,8 @@
timebar_worlds:
debug: false
type: data
world: Atarashikibo
atarashikibo: Atarashikibo
matsuhama: Matsuhama [ DEBUG ]
noshoko: Noshoko
pussyschool: Pussy

View File

@@ -0,0 +1,52 @@
# use in PAPI: %denizen_<proc[timebar_format]>%
timebar_format:
debug: false
type: procedure
script:
- define time <server.flag[timebar_time].if_null[<util.time_now>]>
# typical format
- define result "<&6>☀ <&f><[time].format[HH:mm, E.]>"
# dawn, morning, noon, afternoon, evening, night
- define period Dawn
- if <[time].hour> < 6 || <[time].hour> >= 22:
- define period Night
- else if <[time].hour> < 12:
- define period Morning
- else if <[time].hour> < 15:
- define period Noon
- else if <[time].hour> < 18:
- define period Afternoon
- else if <[time].hour> < 22:
- define period Evening
- define result "<[result]> <&e>🔔 <&f><[period]>"
# map name
- define location <script[timebar_worlds].data_key[<player.location.world.name>]>
- define regions <player.location.regions.filter_tag[<[filter_value].id.starts_with[zone_]>]>
- if <[regions].size> > 0:
- define location <[regions].get[1].id.replace[zone_].with[].split[_].parse[to_sentence_case].space_separated>
- define result "<[result]> <&c>📌 <&f><[location]>"
# result
- determine <[result]>
timebar_increment:
debug: false
type: task
script:
- define time <server.flag[timebar_time].if_null[<util.time_now>]>
- define time <[time].add[5s]>
- flag server timebar_time:<[time]>
- run timebar_sync_sun
timebar_sync_sun:
debug: false
type: task
script:
- define time <server.flag[timebar_time].if_null[<util.time_now>]>
- define hour <[time].hour>
- define minute <[time].minute>
- define second <[time].second>
# calculate as floor((hour - 6) * 1000 + minute * (1000 / 60) + second * (1000 / 60 / 60))
- define thousanddivsixty <element[1000].div[60]>
- define total_ticks <[hour].sub[6].mul[1000].add[<[minute].mul[<[thousanddivsixty]>]>].add[<[second].mul[<[thousanddivsixty].div[60]>]>].round_down>
- foreach <server.worlds> as:world:
- adjust <[world]> time:<[total_ticks]>

View File

@@ -0,0 +1,6 @@
timebar_world:
debug: false
type: world
events:
on delta time secondly every:1:
- run timebar_increment

View File

@@ -0,0 +1,14 @@
vehicles_config:
debug: false
type: data
vehicles:
mx5:
name: <&6>MX5
material: diamond_horse_armor
custom-model-data: 1
driver-offset: 0,-1.25,0
passengers:
- 0,-1.25,1
acceleration: 0.03
max-speed: 2.25
turn-speed-percentage: 0.01

View File

@@ -0,0 +1,118 @@
vehicle_relative_location:
debug: false
type: procedure
definitions: location|relative
script:
- define relative <[relative].split[,]>
- define location <[location].forward_flat[<[relative].get[1]>]>
- define location <[location].above[<[relative].get[2]>]>
- define location <[location].left[<[relative].get[3]>]>
- determine <[location]>
vehicle_create:
debug: false
type: task
definitions: vehicle_id|owner|location
script:
- define location <[location].with_pitch[0]>
#
- define vehicle_id <[vehicle_id].to_lowercase>
- define vehicle <map[]>
- define vehicle_data <script[vehicles_config].data_key[vehicles].get[<[vehicle_id]>]>
- define vehicle <[vehicle].with[id].as[<[vehicle_id]>]>
- define vehicle <[vehicle].with[owner].as[<[owner]>]>
- define vehicle <[vehicle].with[acceleration].as[<[vehicle_data].get[acceleration]>]>
- define vehicle <[vehicle].with[max_speed].as[<[vehicle_data].get[max-speed]>]>
- define vehicle <[vehicle].with[turn_speed_percentage].as[<[vehicle_data].get[turn-speed-percentage]>]>
#
- define vehicle_item <item[<[vehicle_data].get[material]>[custom_model_data=<[vehicle_data].get[custom-model-data]>]]>
- define vehicle <[vehicle].with[name].as[<[vehicle_data].get[name].parsed>]>
- define vehicle <[vehicle].with[item].as[<[vehicle_item]>]>
#
- spawn armor_stand <[location]> persistent reason:custom save:model
- define model_entity <entry[model].spawned_entity>
- adjust <[model_entity]> invulnerable:true
- adjust <[model_entity]> visible:false
- adjust <[model_entity]> equipment:<map[].with[helmet].as[<[vehicle_item]>]>
- flag <[model_entity]> vehicles:model
- define vehicle <[vehicle].with[model_entity].as[<[model_entity]>]>
#
- define driver_offset <[vehicle_data].get[driver-offset]>
- define driver_location <proc[vehicle_relative_location].context[<[location]>|<[driver_offset]>]>
- spawn armor_stand <[driver_location]> persistent reason:custom save:driver
- define driver_entity <entry[driver].spawned_entity>
- adjust <[driver_entity]> invulnerable:true
- adjust <[driver_entity]> visible:false
- adjust <[driver_entity]> gravity:false
- flag <[driver_entity]> vehicles:driver
- flag <[driver_entity]> vehicles_data:<[model_entity]>
- define vehicle <[vehicle].with[driver_entity].as[<[driver_entity]>]>
- define vehicle <[vehicle].with[driver_offset].as[<[driver_offset]>]>
#
- define passenger_entities <map[]>
- foreach <[vehicle_data].get[passengers]> as:passenger_offset:
- define passenger_location <proc[vehicle_relative_location].context[<[location]>|<[passenger_offset]>]>
- spawn armor_stand <[location].add[<[passenger_offset]>]> persistent reason:custom save:passenger<[loop_index]>
- define passenger_entity <entry[passenger<[loop_index]>].spawned_entity>
- adjust <[passenger_entity]> invulnerable:true
- adjust <[passenger_entity]> visible:false
- adjust <[passenger_entity]> gravity:false
- flag <[passenger_entity]> vehicles:passenger
- flag <[passenger_entity]> vehicles_data:<[model_entity]>
- define passenger_entities <[passenger_entities].with[<[passenger_entity]>].as[<[passenger_offset]>]>
- define vehicle <[vehicle].with[passenger_entities].as[<[passenger_entities]>]>
#
- flag <[model_entity]> vehicles_data:<[vehicle]>
- flag <[model_entity]> vehicles_last_location:<[model_entity].location.add[0,1,0]>
- flag server vehicles:<server.flag[vehicles].if_null[<list[]>].include[<[model_entity]>]>
- determine <[model_entity]>
vehicle_destroy:
debug: false
type: task
definitions: vehicle_entity
script:
- define vehicle <[vehicle_entity].flag[vehicles_data].if_null[null]>
- if <[vehicle]> == null:
- debug error "Vehicle entity <[vehicle_entity]> is not a vehicle!"
- stop
- remove <[vehicle].get[driver_entity]>
- remove <[vehicle].get[passenger_entities].keys>
- remove <[vehicle_entity]>
vehicle_find_snap_location:
debug: false
type: procedure
definitions: next_location
script:
- if <[next_location].above[0.15].material.is_solid>:
- if !<[next_location].above.material.is_solid>:
- determine <[next_location].above[0.5]>
- else:
- determine collide
- determine null
vehicle_pickup:
debug: false
type: task
definitions: vehicle_entity
script:
- define owner <[vehicle_entity].flag[vehicles_data].get[owner]>
- define item <[vehicle_entity].flag[vehicles_data].get[item]>
- adjust def:item display:<[vehicle_entity].flag[vehicles_data].get[name]>
- flag <[item]> vehicles:<[vehicle_entity].flag[vehicles_data].get[id]>
- if <[owner].inventory.can_fit[<[item]>]>:
- give <[item]> player:<[owner]>
- run vehicle_destroy def.vehicle_entity:<[vehicle_entity]>
- flag <[owner]> vehicles:!
- if <[owner].is_online>:
- narrate targets:<[owner]> format:formats_prefix "Picked up previous vehicle!"
- else:
- if <[owner].is_online>:
- narrate "<&c>You don't have enough space in your inventory to pick up the vehicle!"
- else:
# praying there's nothing there... will special-flag just in case
- flag <[owner]> vehicles_i_need_help:<player.inventory.map_slots.get[18]>
- inventory set slot:18 origin:<[item]> player:<[owner]>
- run vehicle_destroy def.vehicle_entity:<[vehicle_entity]>
- flag <[owner]> vehicles:!

View File

@@ -0,0 +1,146 @@
vehicles_world:
debug: false
type: world
events:
# cleanup lost vehicles
after server start:
- flag server vehicles:!
- foreach <server.worlds> as:world:
- foreach <[world].entities> as:entity:
- if <[entity].has_flag[vehicles]>:
- run vehicle_pickup def.vehicle_entity:<[entity]>
on player quits:
- if <player.has_flag[vehicles]>:
- define vehicle <player.flag[vehicles]>
- run vehicle_pickup def.vehicle_entity:<[vehicle]>
# vehicle tick
on tick:
- ratelimit server 1t
- define remove <list[]>
- foreach <server.flag[vehicles].if_null[<list[]>]> as:vehicle:
- if !<[vehicle].is_spawned>:
- define remove <[remove].include[<[vehicle]>]>
- foreach next
- run vehicle_world_parallel_loop def.vehicle:<[vehicle]>
- flag server vehicles:<server.flag[vehicles].if_null[<list[]>].exclude[<[remove]>]>
# vehicle safety
on armor_stand damaged:
- if <context.entity.has_flag[vehicles]>:
- determine cancelled
# add passenger on click or pickup vehicle
on player right clicks armor_stand bukkit_priority:lowest:
- if !<context.entity.has_flag[vehicles]>:
- stop
- determine cancelled passively
- if <context.entity.has_passenger>:
- stop
- if <context.entity.flag[vehicles]> == model:
- define driver_entity <context.entity.flag[vehicles_data].get[driver_entity]>
- if <[driver_entity].has_passenger>:
- stop
- if <context.entity.flag[vehicles_data].get[owner]> != <player> && !<player.is_op>:
- stop
- if <player.is_sneaking>:
- run vehicle_pickup def.vehicle_entity:<context.entity>
- else:
- adjust <[driver_entity]> passenger:<player>
- else if <context.entity.flag[vehicles]> == driver:
- define model_entity <context.entity.flag[vehicles_data]>
- if <context.entity.has_passenger>:
- stop
- if <[model_entity].flag[vehicles_data].get[owner]> != <player> && !<player.is_op>:
- stop
- if <player.is_sneaking>:
- run vehicle_pickup def.vehicle_entity:<[model_entity]>
- else:
- adjust <context.entity> passenger:<player>
- else if <context.entity.flag[vehicles]> == passenger:
- adjust <context.entity> passenger:<player>
# vehicle control
on player steers armor_stand:
- if <context.entity.flag[vehicles].if_null[null]> != driver:
- stop
- define vehicle <context.entity.flag[vehicles_data]>
- flag <[vehicle]> vehicles_player_input:<map[].with[forward].as[<context.forward>].with[sideways].as[<context.sideways>]>
# place vehicle down
on player right clicks block:
- if <player.item_in_hand.has_flag[vehicles]>:
- determine cancelled passively
- if <player.has_flag[vehicles]>:
- narrate "<&c>You have spawned a vehicle already. Want to pick it up?"
- define vehicle <player.flag[vehicles]>
- clickable save:pickup until:1m usages:1:
- run vehicle_pickup def.vehicle_entity:<[vehicle]>
- narrate <&e><underline><element[Pick up].on_click[<entry[pickup].command>]>
- stop
- ~run vehicle_create def.vehicle_id:<player.item_in_hand.flag[vehicles]> def.owner:<player> def.location:<player.location> save:result
- define vehicle <entry[result].created_queue.determination.get[1]>
- flag <player> vehicles:<[vehicle]>
- if <player.gamemode> != creative:
- take iteminhand
vehicle_world_parallel_loop:
debug: false
type: task
definitions: vehicle
script:
- if !<[vehicle].flag[vehicles_data].get[driver_entity].has_passenger>:
- flag <[vehicle]> vehicles_player_input:!
- define vehicles_player_input <[vehicle].flag[vehicles_player_input].if_null[null]>
- define forward <[vehicles_player_input].get[forward].if_null[0]>
- define sideways <[vehicles_player_input].get[sideways].if_null[0]>
- if <[forward]> != 0:
- define speed <[vehicle].flag[vehicles_speed].if_null[0]>
- define speed <[speed].add[<[vehicle].flag[vehicles_data].get[acceleration].mul[<[forward]>]>]>
- define max <[vehicle].flag[vehicles_data].get[max_speed]>
- if <[speed]> < <[max].mul[-1].div[3]>:
- define speed <[max].mul[-1].div[3]>
- if <[speed]> > <[max]>:
- define speed <[max]>
- flag <[vehicle]> vehicles_speed:<[speed]>
- if <[sideways]> != 0:
- define speed <[vehicle].flag[vehicles_speed].if_null[0]>
- if <[speed].abs> > 0.1:
- define max_speed <[vehicle].flag[vehicles_data].get[max_speed]>
- define speed_turn_coefficient <[speed].div[<[max_speed]>].mul[0.25].add[0.85]>
- define turn_speed <[vehicle].flag[vehicles_data].get[turn_speed_percentage].mul[360].mul[<[speed_turn_coefficient]>]>
- define turn_speed <[turn_speed].mul[<[sideways]>].mul[-1].mul[<tern[<[speed].is_less_than[0]>].pass[-1].fail[1]>]>
- rotate <[vehicle]> duration:1t yaw:<[turn_speed]>
- define speed <[vehicle].flag[vehicles_speed].if_null[0]>
- if <[speed].abs> < 0.1:
- define speed 0
- else:
- define speed <[speed].div[1.015]>
- if <[speed]> >= 0:
- define ray_cast_location <[vehicle].location.above[0.5].ray_trace[range=<[speed].abs>].if_null[null]>
- else:
- define backwards <[vehicle].location.direction.vector.mul[-1]>
- define ray_cast_location <[vehicle].location.with_pitch[<[backwards].pitch>].with_yaw[<[backwards].yaw>].above[0.5].ray_trace[range=<[speed].abs>].if_null[null]>
- if <[ray_cast_location]> != null:
- define new_location <[ray_cast_location].with_pitch[<[vehicle].location.pitch>].with_yaw[<[vehicle].location.yaw>]>
- define speed <[speed].div[1.075]>
- else:
- define new_location <[vehicle].location.forward_flat[<[speed]>]>
- define snap <proc[vehicle_find_snap_location].context[<[new_location]>]>
- if <[snap]> != null:
- if <[snap]> == collide:
- define new_location <[vehicle].location>
- define speed <[speed].div[1.1]>
- else:
- define new_location <[snap]>
- if !<[new_location].below[0.25].material.is_solid>:
- define new_location <[new_location].add[0,-<element[<[vehicle].location.y.sub[<[vehicle].location.below[0.15].y.round_down>]>].min[0.25].sub[0.001]>,0]>
- if <[vehicle].flag[vehicles_speed].if_null[0]> != 0:
- if <[speed].abs> > 0:
- teleport <[vehicle]> <[new_location]> cause:plugin offthread_repeat:8
- flag <[vehicle]> vehicles_speed:<[speed]>
- if <[vehicle].flag[vehicles_data].get[driver_entity].has_passenger>:
- playsound <[new_location]> custom sound:vehicle.engine pitch:<element[0.5].add[<[speed].abs.mul[32].mod[24].round_down.div[18]>]>
- if <[vehicle].flag[vehicles_last_location]> == <[new_location]>:
- stop
- define driver_entity <[vehicle].flag[vehicles_data].get[driver_entity]>
- define driver_offset <[vehicle].flag[vehicles_data].get[driver_offset]>
- teleport <[driver_entity]> <proc[vehicle_relative_location].context[<[new_location]>|<[driver_offset]>]> cause:plugin offthread_repeat:8
- foreach <[vehicle].flag[vehicles_data].get[passenger_entities]> key:passenger_entity as:passenger_offset:
- teleport <[passenger_entity]> <proc[vehicle_relative_location].context[<[new_location]>|<[passenger_offset]>]> cause:plugin offthread_repeat:8
- flag <[vehicle]> vehicles_last_location:<[vehicle].location>

View File

@@ -0,0 +1,14 @@
wardrobe_command_wardrobe:
debug: false
type: command
name: wardrobe
usage: /wardrobe
description: View and manage your skins in the wardrobe.
permission: wardrobe.command.wardrobe
tab completions:
1: <list[]>
script:
- if <context.source_type> != player:
- narrate "<&c>Please run this command as a player."
- stop
- run wardrobe_menu def.player:<player>

View File

@@ -0,0 +1,127 @@
####
## TARGET LIBRARY UTILITY FOR FILLING HEADS IN GUI ASYNC
####
# asynchronously and slowly updates all player skulls in any inventory
# each skull you want to change has to be flagged with wardrobe_skull_texture:<[target].uuid>
wardrobe_skull_texture_update:
debug: false
type: task
definitions: player
speed: 2t
script:
- define inventory <[player].open_inventory>
- foreach <[inventory].map_slots> key:slot as:item:
- if <[item].has_flag[wardrobe_skull_texture]>:
- if <[inventory].viewers.if_null[<list[]>].is_empty>:
- stop
- define texture <[item].flag[wardrobe_skull_texture]>
- run wardrobe_skull_texture_update_single def.inventory:<[inventory]> def.slot:<[slot]> def.texture:<[texture]>
# dont use by itself - always use wardrobe_skull_texture_update
# creates a new queue to prevent overloading the main task
wardrobe_skull_texture_update_single:
debug: false
type: task
definitions: inventory|slot|texture
script:
- inventory adjust slot:<[slot]> skull_skin:<[texture]> destination:<[inventory]>
##
wardrobe_max_skins:
debug: false
type: procedure
definitions: player
script:
- define max 9
- while <[max]> > 3:
- if <[player].has_permission[wardrobe.skins.<[max]>]>:
- determine <[max]>
- define max <[max].sub[1]>
- determine <[max]>
wardrobe_texture_decode:
debug: false
type: procedure
definitions: skin_blob
script:
- determine <[skin_blob].split[;].get[1].base64_decode.substring[197,298]>
wardrobe_save_latest:
debug: false
type: task
definitions: player
script:
- define latest_texture <proc[wardrobe_texture_decode].context[<[player].flag[wardrobe_latest]>]>
- define textures <[player].flag[wardrobe_all].values.if_null[<list[]>]>
- if <[textures].contains[<[latest_texture]>]>:
- narrate targets:<[player]> "<&c>You already have your latest Minecraft skin saved in your wardrobe."
- stop
- flag <[player]> wardrobe_all:<[player].flag[wardrobe_all].if_null[<map[]>].with[<[player].flag[wardrobe_latest]>].as[<[latest_texture]>]>
- narrate format:formats_prefix "Saved latest Minecraft skin in your wardrobe."
wardrobe_delete:
debug: false
type: task
definitions: player|skin_blob
script:
- flag <[player]> wardrobe_all:<[player].flag[wardrobe_all].exclude[<[skin_blob]>]>
- narrate format:formats_prefix "Deleted saved skin."
wardrobe_apply:
debug: false
type: task
definitions: player|skin_blob
script:
- adjust <[player]> skin_blob:<[skin_blob]>
- flag <[player]> wardrobe_current:<[skin_blob]>
- narrate format:formats_prefix "Applied saved skin from wardrobe."
wardrobe_clear:
debug: false
type: task
definitions: player
script:
- adjust <[player]> skin:<[player].name>
- flag <[player]> wardrobe_current:!
- narrate format:formats_prefix "Cleared current skin. You are now using your latest Minecraft skin instead."
wardrobe_menu:
debug: false
type: task
definitions: player
script:
- define inventory <inventory[generic[size=54;title=<&f>邑邑邑邑鄇]]>
#
- define max <proc[wardrobe_max_skins].context[<[player]>]>
- define position 31
- define i 0
- foreach <[player].flag[wardrobe_all].if_null[<map[]>]> key:skin_blob as:texture:
- define skinitem <item[player_head]>
- adjust def:skinitem "display:<&e>Skin #<[loop_index]>"
- adjust def:skinitem lore:<list[<&7>Left click to <&a>apply|<&7>Right click to <&c>delete]>
- flag <[skinitem]> wardrobe:<[skin_blob]>
- flag <[skinitem]> wardrobe_skull_texture:<[skin_blob].split[;].get[1]>
- inventory set slot:<[position]> origin:<[skinitem]> destination:<[inventory]>
- define position <[position].add[1]>
- define i <[i].add[1]>
- if <[i].mod[3]> == 0:
- define position <[position].add[6]>
- repeat <element[<[max]>].sub[<[i]>]>:
- define unusedskin <item[wither_skeleton_skull]>
- adjust def:unusedskin "display:<&7>Unused Skin Slot"
- adjust def:unusedskin lore:<list[<&7>Click to <&e>save <&7>your latest Minecraft skin.]>
- inventory set slot:<[position]> origin:<[unusedskin]> destination:<[inventory]>
- define position <[position].add[1]>
- define i <[i].add[1]>
- if <[i].mod[3]> == 0:
- define position <[position].add[6]>
#
- define clearitem <item[warped_trapdoor]>
- adjust def:clearitem "display:<&f>Clear Skin"
- run gui_restore_set_later def.player:<[player]> def.slot:13 def.item:<[clearitem]>
- run gui_restore_set_later def.player:<[player]> def.slot:14 def.item:<[clearitem]>
- run gui_restore_set_later def.player:<[player]> def.slot:15 def.item:<[clearitem]>
#
- inventory open destination:<[inventory]>
- run wardrobe_skull_texture_update def.player:<[player]>

View File

@@ -0,0 +1,30 @@
wardrobe_world:
debug: false
type: world
events:
on player joins:
- flag <player> wardrobe_latest:<player.skin_blob>
- if <player.has_flag[wardrobe_current]>:
- adjust <player> skin_blob:<player.flag[wardrobe_current]>
on player clicks in inventory:
- if !<context.inventory.title.contains[鄇]>:
- stop
- determine cancelled passively
# - if <context.slot> > <context.inventory.size>:
# - stop
- if <context.item.advanced_matches[wither_skeleton_skull]>:
- run wardrobe_save_latest def.player:<player>
- inventory close
- wait 1t
- run wardrobe_menu def.player:<player>
- else if <context.item.advanced_matches[player_head]>:
- if <context.click> == right:
- run wardrobe_delete def.player:<player> def.skin_blob:<context.item.flag[wardrobe]>
- inventory close
- wait 1t
- run wardrobe_menu def.player:<player>
- else:
- run wardrobe_apply def.player:<player> def.skin_blob:<context.item.flag[wardrobe]>
- inventory close
- else if <context.item.advanced_matches[warped_trapdoor]>:
- run wardrobe_clear def.player:<player>