diff --git a/README.md b/README.md index bd8b057..ceeee6a 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,23 @@ ICollect-Alpha 是一个使用 Carpet 脚本的“物品收集x狼人杀 Minecra 欢迎来到物品收集x狼人杀 Minecraft小游戏!以下是游戏规则: 【职业】 -1. 狼人:坏人阵营,可以用望远镜发射火焰弹,可以定位任意玩家的精确坐标。 +1. 狼人:坏人阵营,可以使用全部望远镜的特殊能力,可以定位任意玩家的精确坐标。 2. 平民:好人阵营,没有特殊技能。 -3. 猎人:好人阵营,望远镜可以发射火焰弹(10秒冷却时间)。 +3. 猎人/烟花猎人/建筑师:好人阵营,可以对应的望远镜的特殊能力。 【流程】 -1. 游戏开始时,会给出一个包含6个物品的列表,并进入10分钟的准备时间,准备时间内不能发射弹药。每个玩家都会获得鞘翅和无限烟花。 -2. 准备时间结束后,进入60分钟的收集时间。好人阵营在10分钟内必须收集完列表中的1个物品,20分钟内必须收集完2个,以此类推,60分钟结束前必须收集满6个物品。坏人阵营则要阻挠好人阵营收集物品。 -3. 每10分钟会有一个投票环节,所有玩家都可以把票投给一个自己怀疑是狼人的玩家,票数最高者出局。可以投弃权票,如果票数最高者有多人得票数相同,或票数最高者得票数不严格多于弃权票数量,则该轮投票无人出局。投票为一人一票,不记名,投票后不可撤销。 -4. 如果好人阵营没能在任意一个第N个10分钟结束前收集到N个物品,或者好人阵营全部死光,则坏人阵营获胜。反之,如果坏人阵营全部死光,或者好人阵营成功完成6个物品的收集,则好人阵营获胜。 -5. 每个玩家只有一条生命,被杀死、票死或者因为环境而死的玩家将变成旁观者模式。在准备时间内死亡不会变成旁观者,而是会正常复活。 -6. 游戏过程中,玩家获得持续的生命回复I和抗性提升I(每10秒更新一次状态效果为15秒)。 +1. 游戏开始时,会给出一个包含6个物品的列表,并进入10分钟的准备阶段,准备阶段内不能发射弹药。每个玩家都会获得鞘翅和无限烟花。 +2. 准备阶段结束后,进入60分钟的收集阶段。好人阵营在10分钟内必须收集完列表中的1个物品,20分钟内必须收集完2个,以此类推,60分钟结束前必须收集满6个物品。坏人阵营则要阻挠好人阵营收集物品。 +3. 每10分钟会有一个投票环节,投票为一人一票,不记名,投票后不可撤销。所有玩家都可以把票投给一个自己怀疑是狼人的玩家,票数最高者出局。可以投弃权票,如果票数最高者有多人得票数相同,或票数最高者得票数不严格多于弃权票数量,则该轮投票无人出局。 +4. 如果好人阵营没能在规定时间内完成收集任务,则坏人阵营获胜。反之,如果好人阵营成功完成6个物品的收集,则好人阵营获胜。 +5. 每个玩家只有一条生命,被杀死、票死或者因为环境而死的玩家将变成旁观者模式。在准备阶段内死亡不会变成旁观者,而是会正常复活。 +6. 游戏过程中,玩家获得持续的生命回复II和伤害吸收III(每20秒更新一次状态效果为30秒)。 + +【望远镜的特殊能力】 + +1. 发射火球:发射与TNT爆炸威力相同的恶魂火球。 +2. 发射烟花:发射可以造成大量伤害的烟花火箭。 +3. 建筑烟花:发射在其下方生成道路的烟花火箭(道路建筑材料为_石化橡木台阶_)。 【指令使用】 1. `/ica`:列出物品收集目标和时限信息 @@ -25,7 +31,8 @@ ICollect-Alpha 是一个使用 Carpet 脚本的“物品收集x狼人杀 Minecra 3. `/ica me`:查看自己的身份 4. `/ica seed`:查看地图种子 5. `/ica refill`:刷新自己的烟花 -6. `/ica locate `:定位某一玩家位置,空手使用时可获得指向位置的指南针 +6. `/ica locate `:定位某一玩家位置,空手使用时可获得指向位置的指南针(不能跨维度定位) +7. `/ica spyglass `:切换望远镜的能力 7. `/ica-vote`:查看当前投票状态信息 8. `/ica-vote abstain`:投弃权票 9. `/ica-vote sus `:投票给某一玩家 @@ -34,10 +41,16 @@ ICollect-Alpha 是一个使用 Carpet 脚本的“物品收集x狼人杀 Minecra ## 管理员命令 -首先需要安装 Fabric 和 Fabric Carpet 模组,然后将 `src` 目录下的 `.sc` 代码复制到世界的 `script` 文件夹下。打开世界后,使用 `script load ica-loader` 加载加载脚本,使用命令 `ica-loader` 加载各个模块: +首先需要安装 Fabric 和 Fabric Carpet 模组,然后将 `src` 目录下的 `.sc` 代码复制到世界的 `script` 文件夹下。打开世界后,使用 `/script load ica-loader` 加载加载脚本,使用命令 `/ica-loader` 加载各个模块: + +- 使用 `/ica-setting career ` 设置职业的玩家数量 +- 使用 `/ica-setting add ` 设置一个未使用的收集目标 +- 使用 `/ica-setting set ` 设置一个指定的收集目标 +- 使用 `/ica-admin confirm` 开始游戏,开始时请保证所有参与者在线 + +## 调试命令 + +- 使用 `/ica-effect-applier enable` 强制启用状态效果广播 +- 使用 `/ica-effect-applier enable` 强制禁用状态效果广播 +- 使用 `/ica-admin cancel` 终止游戏 -- 使用 `ica-setting career hunter ` 设置猎人数量 -- 使用 `ica-setting career wolf ` 设置狼人数量 -- 使用 `ica-setting add ` 设置一个未使用的收集目标 -- 使用 `ica-setting set ` 设置一个指定的收集目标 -- 使用 `ica-admin confirm` 开始游戏,开始时请保证所有参与者在线。 diff --git a/src/ica-admin.sc b/src/ica-admin.sc index b0b38d7..914ff9c 100644 --- a/src/ica-admin.sc +++ b/src/ica-admin.sc @@ -32,9 +32,11 @@ clearBossbars() -> ( cleanPlayerTags() -> ( for(player('all'), modify(_, 'clear_tag', ['ica.piggy' - , 'ica.wolf', 'ica.hunter', 'ica.spyglasser', 'ica.spyglass_fireball' + , 'ica.wolf', 'ica.hunter', 'ica.fireball_spyglasser', 'ica.spyglass_fireball' , 'ica.voter', 'ica.flyer', 'ica.spyglasser_cooldown' - , 'ica.coordinator', 'ica.deceased', 'ica.participant'])); + , 'ica.coordinator', 'ica.deceased', 'ica.participant' + , 'ica.firework_spyglasser', 'ica.build_spyglasser' + , 'ica.spyglass_builder', 'ica.spyglass_firework'])); ); endCleanup() -> ( @@ -125,18 +127,22 @@ getFirstUnsetGoal() -> ( return(6); ); +actionbarMessage(msg) -> ( + display_title(player('all'), 'actionbar', msg, 100, 100, 100); +); + warnDeadline(dt) -> ( if (dt == 1200, ( - print(player('all'), '[WARN] Submission deadline in 1 minute.'); + actionbarMessage('[WARN] Submission deadline in 1 minute.'); )); if (dt == 600, ( - print(player('all'), '[WARN] Submission deadline in 30 seconds.'); + actionbarMessage('[WARN] Submission deadline in 30 seconds.'); )); if (dt == 300, ( - print(player('all'), '[WARN] Submission deadline in 15 seconds.'); + actionbarMessage('[WARN] Submission deadline in 15 seconds.'); )); if (dt <= 200 && dt % 20 == 0, ( - print(player('all'), str('[WARN] Submission deadline in %d second%s!' + actionbarMessage(str('[WARN] Submission deadline in %d second%s!' , dt / 20, if(dt > 20, 's', ''))); )); ); @@ -152,13 +158,13 @@ electionKill(pname) -> ( checkVotes(tm) -> ( if(tm % 12000 == 3600, ( - print(player('all'), '[WARN] Vote ends in 1 minute'); + actionbarMessage('[WARN] Vote ends in 1 minute'); return(false); )); if(tm % 12000 == 2400, ( max_p = findVoteMax(); phint = if(max_p == null, ( - 'nobody was elected.' + 'nobody was elected' ), ( ele_p = player(max_p); schedule(200, 'electionKill', ele_p); @@ -195,9 +201,13 @@ startCollectStage() -> ( bossbar('ica:collected', 'value', 0); for(player('all'), ( - if(query(_, 'has_scoreboard_tag', 'ica.spyglasser'), ( + if(query(_, 'has_scoreboard_tag', 'ica.fireball_spyglasser'), ( modify(_, 'tag', 'ica.spyglass_fireball'); - )); + ), if(query(_, 'has_scoreboard_tag', 'ica.firework_spyglasser'), ( + modify(_, 'tag', 'ica.spyglass_firework'); + ), if(query(_, 'has_scoreboard_tag', 'ica.build_spyglasser'), ( + modify(_, 'tag', 'ica.spyglass_builder'); + )))); )); put(nbt_storage('ica:data'):'Preparing', '0b'); @@ -262,7 +272,9 @@ cmdStart() -> ( participants_list = shuffleList(participants_list); wolf_n = countCareer('wolf'); hunter_n = countCareer('hunter') + wolf_n; - if(hunter_n > length(participants_list), ( + builder_n = countCareer('builder') + hunter_n; + firework_hunter_n = countCareer('firework_hunter') + builder_n; + if(firework_hunter_n > length(participants_list), ( print('Not enough players online.'); return(false); )); @@ -280,8 +292,10 @@ cmdStart() -> ( for(participants_list, ( modify(_, 'tag', ['ica.voter', 'ica.flyer', 'ica.participant']); career_tag = 'ica.piggy'; - if(_i < hunter_n, career_tag = ['ica.hunter', 'ica.spyglasser', 'ica.spyglasser_cooldown']); - if(_i < wolf_n, career_tag = ['ica.wolf', 'ica.spyglasser', 'ica.coordinator']); + if(_i < firework_hunter_n, career_tag = ['ica.hunter_firework', 'ica.firework_spyglasser', 'ica.spyglasser_cooldown']); + if(_i < builder_n, career_tag = ['ica.builder', 'ica.build_spyglasser']); + if(_i < hunter_n, career_tag = ['ica.hunter', 'ica.fireball_spyglasser', 'ica.spyglasser_cooldown']); + if(_i < wolf_n, career_tag = ['ica.wolf', 'ica.fireball_spyglasser', 'ica.firework_spyglasser', 'ica.build_spyglasser', 'ica.coordinator']); modify(_, 'tag', career_tag); )); @@ -293,6 +307,7 @@ cmdStart() -> ( run('time set day'); run('gamerule keepInventory true'); run('gamerule playersSleepingPercentage 0'); + run('gamerule randomTickSpeed 12'); run('worldborder set 10000'); ); diff --git a/src/ica-effect-applier.sc b/src/ica-effect-applier.sc index 6be11e1..93d8825 100644 --- a/src/ica-effect-applier.sc +++ b/src/ica-effect-applier.sc @@ -1,34 +1,57 @@ global_enabled = false; -global_effects = ['regeneration', 'resistance']; __config() -> { - 'command_permission' -> 'ops', - 'scope' -> 'global', - 'commands' -> { - '' -> 'getStatus', - 'enable' -> _() -> global_enabled = true, - 'disable' -> _() -> global_enabled = false, - }, + 'command_permission' -> 'ops', + 'scope' -> 'global', + 'commands' -> { + '' -> 'getStatus', + 'enable' -> _() -> global_enabled = true, + 'disable' -> _() -> global_enabled = false, + }, }; getStatus() -> ( - if(global_enabled, ( - print('effect-applier: on') - ), ( - print('effect-applier: off') - )) + if(global_enabled, ( + print('effect-applier: on') + ), ( + print('effect-applier: off') + )) ); updateEffects() -> ( - if(global_enabled, ( - for(global_effects, ( - e = _; - for(player('all'), modify(_, 'effect', e, 300, 1, false, true)); - )); - )); - schedule(200, 'updateEffects'); + if(global_enabled, ( + for(player('all'), ( + modify(_, 'effect', 'regeneration', 600, 1, false, true); + modify(_, 'effect', 'absorption', 600, 2, false, true); + )); + )); + schedule(400, 'updateEffects'); +); + +setBlock(pos, use_upper_half) -> ( + set(pos, str('petrified_oak_slab[type=%s]', if(use_upper_half, 'top', 'bottom'))); +); + +updatePath() -> ( + for(entity_selector('@e[tag=ica.builder_rocket,distance=0..]'), ( + rk_pos = query(_, 'pos') - [0, 2, 0]; + rd_pos = [round(rk_pos:0), round(rk_pos:1), round(rk_pos:2)]; + upper_half = (rk_pos:1) % 1 < 0.5; + b = block(rd_pos); + if(block_tags(b, 'replaceable'), ( + schedule(5, 'setBlock', rd_pos, upper_half); + )); + )); +); + +updateBuilder() -> ( + updatePath(); + in_dimension('nether', updatePath()); + in_dimension('end', updatePath()); + schedule(1, 'updateBuilder'); ); __on_start() -> ( - schedule(1, 'updateEffects') + schedule(1, 'updateBuilder'); + schedule(1, 'updateEffects'); ); \ No newline at end of file diff --git a/src/ica-fireball.sc b/src/ica-fireball.sc deleted file mode 100644 index df8124f..0000000 --- a/src/ica-fireball.sc +++ /dev/null @@ -1,45 +0,0 @@ -global_lastUseSpyglass = -1000; - -shootFireball(myself, rm) -> ( - playerPos = query(myself, 'pos') + l(0, query(myself, 'eye_height'), 0); // Set the position where the fireball will spawn - playerM = query(myself, 'motion'); - - v = query(myself, 'look'); - fbv = v * 0.3; - fireball = spawn('fireball', playerPos + v * 2 - , nbt(str('{ExplosionPower: 4b, power: [%fd,%fd,%fd], Motion: [%fd,%fd,%fd]}' - , fbv:0, fbv:1, fbv:2, playerM:0, playerM:1, playerM:2))); - gamemode = myself ~ 'gamemode'; - if(rm && (gamemode == 'survival' || gamemode == 'adventure'), - inventory_remove(myself, 'fire_charge'); - ); - return(true); -); - -__on_player_uses_item(myself, item_tuple, hand) -> ( - if(item_tuple:0 == 'fire_charge', - shootFireball(myself, true); - ); -); - -shootFireballSpyglass(myself) -> ( - if(!query(myself, 'has_scoreboard_tag', 'ica.spyglass_fireball'), ( - return(null); - )); - nowTT = tick_time(); - dt = nowTT - global_lastUseSpyglass; - if(query(myself, 'has_scoreboard_tag', 'ica.spyglasser_cooldown') - && dt < 200, ( - print(str('spyglass too hot, please wait another %.2f seconds to shoot again.' - , (200 - dt) / 20.0)); - return(null); - )); - shootFireball(myself, false); - global_lastUseSpyglass = nowTT; -); - -__on_player_releases_item(myself, item_tuple, hand) -> ( - if(item_tuple:0 == 'spyglass', - shootFireballSpyglass(myself); - ); -); diff --git a/src/ica-loader.sc b/src/ica-loader.sc index 483d4e2..be82b2c 100644 --- a/src/ica-loader.sc +++ b/src/ica-loader.sc @@ -24,7 +24,7 @@ cmdLoad() -> ( print(licenseHeader()); run('script load ica-admin'); run('script load ica-effect-applier'); - run('script load ica-fireball'); + run('script load ica-spyglass'); run('script load ica'); run('script load ica-vote'); run('script load ica-settings'); diff --git a/src/ica-settings.sc b/src/ica-settings.sc index d0fba32..68deacc 100644 --- a/src/ica-settings.sc +++ b/src/ica-settings.sc @@ -12,7 +12,8 @@ __config() -> { 'slot' -> { 'type' -> 'int', 'min' -> 0, 'max' -> 5 , 'suggest' -> [0, 1, 2, 3, 4, 5] }, 'item' -> { 'type' -> 'item' }, - 'career_type' -> { 'type' -> 'string', 'options' -> [ 'wolf', 'hunter' ] }, + 'career_type' -> { 'type' -> 'string' + , 'options' -> [ 'wolf', 'hunter', 'builder', 'firework_hunter' ] }, 'amount' -> { 'type' -> 'int', 'min' -> 0, 'suggest' -> [1] }, }, }; diff --git a/src/ica-spyglass.sc b/src/ica-spyglass.sc new file mode 100644 index 0000000..32a60db --- /dev/null +++ b/src/ica-spyglass.sc @@ -0,0 +1,86 @@ +global_lastUseSpyglass = -500; + +shootFireball(myself) -> ( + playerPos = query(myself, 'pos') + l(0, query(myself, 'eye_height'), 0); + playerM = query(myself, 'motion'); + + v = query(myself, 'look'); + fbv = v * 0.3; + fireball = spawn('fireball', playerPos + v * 2 + , nbt(str('{ExplosionPower: 4b, power: [%fd,%fd,%fd], Motion: [%fd,%fd,%fd]}' + , fbv:0, fbv:1, fbv:2, playerM:0, playerM:1, playerM:2))); + return(true); +); + +fireworkExplotionTags() -> ( + 'FireworksItem: {Count:1b,id:"minecraft:firework_rocket",tag:{Fireworks: {Flight: 2b, Explosions: [{Type: 1b, Colors: [I; 3887386], Trail: 1b}, {Type: 1b, Colors: [I; 12801229], Trail: 1b}, {Type: 1b, Colors: [I; 11743532], Trail: 1b}, {Type: 1b, Colors: [I; 15790320], Trail: 1b}, {Type: 1b, Colors: [I; 6719955], Trail: 1b}, {Type: 1b, Colors: [I; 15435844], Trail: 1b}, {Type: 1b, Colors: [I; 3887386], Trail: 1b}, {Type: 1b, Colors: [I; 12801229], Trail: 1b}, {Type: 1b, Colors: [I; 11743532], Trail: 1b}, {Type: 1b, Colors: [I; 15790320], Trail: 1b}, {Type: 1b, Colors: [I; 6719955], Trail: 1b}, {Type: 1b, Colors: [I; 15435844], Trail: 1b}, {Type: 1b, Colors: [I; 3887386], Trail: 1b}, {Type: 1b, Colors: [I; 12801229], Trail: 1b}, {Type: 1b, Colors: [I; 11743532], Trail: 1b}, {Type: 1b, Colors: [I; 15790320], Trail: 1b}, {Type: 1b, Colors: [I; 6719955], Trail: 1b}, {Type: 1b, Colors: [I; 15435844], Trail: 1b},{Type: 0b, Colors: [I; 3887386], Trail: 1b}, {Type: 0b, Colors: [I; 12801229], Trail: 1b}, {Type: 0b, Colors: [I; 11743532], Trail: 1b}, {Type: 0b, Colors: [I; 15790320], Trail: 1b}, {Type: 0b, Colors: [I; 6719955], Trail: 1b}, {Type: 0b, Colors: [I; 15435844], Trail: 1b}, {Type: 0b, Colors: [I; 3887386], Trail: 1b}, {Type: 0b, Colors: [I; 12801229], Trail: 1b}, {Type: 0b, Colors: [I; 11743532], Trail: 1b}, {Type: 0b, Colors: [I; 15790320], Trail: 1b}, {Type: 0b, Colors: [I; 6719955], Trail: 1b}, {Type: 0b, Colors: [I; 15435844], Trail: 1b}, {Type: 0b, Colors: [I; 3887386], Trail: 1b}, {Type: 0b, Colors: [I; 12801229], Trail: 1b}, {Type: 0b, Colors: [I; 11743532], Trail: 1b}, {Type: 0b, Colors: [I; 15790320], Trail: 1b}, {Type: 0b, Colors: [I; 6719955], Trail: 1b}, {Type: 0b, Colors: [I; 15435844], Trail: 1b}]}}}' +); + +shootFirework(myself) -> ( + playerPos = query(myself, 'pos') + l(0, query(myself, 'eye_height'), 0); + playerM = query(myself, 'motion'); + + v = query(myself, 'look'); + fbv = playerM + v * 2; + rocket = spawn('firework_rocket', playerPos + v + , nbt(str('{LifeTime: %d, Motion: [%fd,%fd,%fd], ShotAtAngle: 1b, %s}' + , 35 + rand(10), fbv:0, fbv:1, fbv:2, fireworkExplotionTags()))); + return(true); +); + +shootBuilderFirework(myself) -> ( + playerPos = query(myself, 'pos') + l(0, query(myself, 'eye_height'), 0); + playerM = query(myself, 'motion'); + + v = query(myself, 'look'); + fbv = playerM + v; + rocket = spawn('firework_rocket', playerPos + 2 * v + , nbt(str('{LifeTime: %d, Motion: [%fd,%fd,%fd], ShotAtAngle: 1b}' + , 75 + rand(10), fbv:0, fbv:1, fbv:2))); + modify(rocket, 'tag', 'ica.builder_rocket'); + return(true); +); + +checkCooldown(myself) -> ( + nowTT = tick_time(); + dt = nowTT - global_lastUseSpyglass; + if(query(myself, 'has_scoreboard_tag', 'ica.spyglasser_cooldown') + && dt < 100, ( + display_title(player(), 'actionbar' + , str('spyglass too hot, please wait another %.2f seconds to shoot again.' + , (100 - dt) / 20.0), 100, 100, 100); + return(true); + )); + global_lastUseSpyglass = nowTT; + return(false); +); + +shootFireballSpyglass(myself) -> ( + if(!query(myself, 'has_scoreboard_tag', 'ica.spyglass_fireball'), ( + return(null); + )); + shootFireball(myself); +); + +shootFireworkSpyglass(myself) -> ( + if(!query(myself, 'has_scoreboard_tag', 'ica.spyglass_firework'), ( + return(null); + )); + shootFirework(myself); +); + +shootBuilderFireworkSpyglass(myself) -> ( + if(!query(myself, 'has_scoreboard_tag', 'ica.spyglass_builder'), ( + return(null); + )); + shootBuilderFirework(myself); +); + +__on_player_releases_item(myself, item_tuple, hand) -> ( + if(item_tuple:0 == 'spyglass', + if(checkCooldown(myself), (return(null))); + shootFireballSpyglass(myself); + shootFireworkSpyglass(myself); + shootBuilderFireworkSpyglass(myself); + ); +); diff --git a/src/ica.sc b/src/ica.sc index 2818f1b..a92482f 100644 --- a/src/ica.sc +++ b/src/ica.sc @@ -8,14 +8,23 @@ __config() -> { 'me' -> 'cmdMe', 'whoami' -> 'cmdMe', 'locate ' -> 'cmdLocate', + 'spyglass ' -> 'cmdSpyglassSwitch', }, 'arguments' -> { 'slot' -> { 'type' -> 'int', 'min' -> 0, 'max' -> 5 , 'suggest' -> [0, 1, 2, 3, 4, 5] }, 'participant' -> { 'type' -> 'players' }, + 'spyglass_feature' -> { 'type' -> 'string', + 'options' -> [ 'builder', 'firework', 'fireball' ] } } }; +global_capMarkerMap = { + 'builder' -> 'ica.build_spyglasser', + 'fireball' -> 'ica.fireball_spyglasser', + 'firework' -> 'ica.firework_spyglasser', +}; + tm_total() -> ( 72000 ); @@ -24,6 +33,14 @@ tm_per_goal() -> ( 12000 ); +lackOfAbilityReject() -> ( + display_title(player(), 'actionbar', 'You don\'t have this ability.'); +); + +bystandReject() -> ( + display_title(player(), 'actionbar', 'You can only bystand.'); +); + cmdLocate(pname) -> ( if(!nbt_storage('ica:data'):'Started', ( print('Not started. use /ica-admin confirm to start.'); @@ -31,12 +48,12 @@ cmdLocate(pname) -> ( )); myself = player(); if(query(myself, 'has_scoreboard_tag', 'ica.deceased'), ( - print('You can only bystand.'); + bystandReject(); return(false); )); if(!query(player(), 'has_scoreboard_tag', 'ica.coordinator'), ( - print('You don\'t have this ability.'); - return(false) + lackOfAbilityReject(); + return(false); )); p = player(pname:0); @@ -79,10 +96,6 @@ cmdRefill() -> ( if(query(myself, 'has_scoreboard_tag', 'ica.flyer'), ( run('give @s minecraft:firework_rocket 64'); )); - if(query(myself, 'has_scoreboard_tag', 'ica.spyglasser') - && !nbt_storage('ica:data'):'Preparing', ( - modify(myself, 'tag', 'ica.spyglass_fireball'); - )); ); cmdList() -> ( @@ -119,8 +132,10 @@ cmdMe() -> ( career_hints = { 'Bystander' -> 'You have nothing to do, just watch.', 'Piggy' -> 'Complete all goals in time to win!', - 'Hunter' -> 'Protect piggies and kill the wolf.', - 'Wolf' -> 'Stop them complete the goals!', + 'Hunter(Fireball)' -> 'Protect piggies and kill the wolf.', + 'Hunter(Firework)' -> 'Protect piggies and kill the wolf.', + 'Builder' -> 'Build protections and complete the goals!', + 'Wolf' -> 'Stop them completing the goals!', }; career = 'Bystander'; @@ -128,7 +143,13 @@ cmdMe() -> ( career = 'Piggy'; )); if(query(myself, 'has_scoreboard_tag', 'ica.hunter'), ( - career = 'Hunter'; + career = 'Hunter(Fireball)'; + )); + if(query(myself, 'has_scoreboard_tag', 'ica.hunter_firework'), ( + career = 'Hunter(Firework)'; + )); + if(query(myself, 'has_scoreboard_tag', 'ica.builder'), ( + career = 'Builder'; )); if(query(myself, 'has_scoreboard_tag', 'ica.wolf'), ( career = 'Wolf'; @@ -141,8 +162,14 @@ cmdMe() -> ( if(query(myself, 'has_scoreboard_tag', 'ica.flyer'), ( print('[ability] flyer: you can fly with an elytra.'); )); - if(query(myself, 'has_scoreboard_tag', 'ica.spyglasser'), ( - print('[ability] spyglasser: You can shoot fireballs with a spyglass(except in prepare stage).'); + if(query(myself, 'has_scoreboard_tag', 'ica.fireball_spyglasser'), ( + print('[ability] shooter: You can shoot fireballs with a spyglass(except in prepare stage).'); + )); + if(query(myself, 'has_scoreboard_tag', 'ica.firework_spyglasser'), ( + print('[ability] launcher: You can launch fireworks with a spyglass(except in prepare stage).'); + )); + if(query(myself, 'has_scoreboard_tag', 'ica.build_spyglasser'), ( + print('[ability] builder: You can build paths with a spyglass(except in prepare stage).'); )); // if(query(myself, 'has_scoreboard_tag', 'ica.kungfu_master'), ( // print('[ability] kungfu master: You can get a temporary slow-falling effect by using a feather.'); @@ -152,6 +179,34 @@ cmdMe() -> ( )); ); +disableAllSpyglassAbilities(me) -> ( + modify(me, 'clear_tag', [ 'ica.spyglass_fireball', 'ica.spyglass_firework' + , 'ica.spyglass_builder' ]); +); + +cmdSpyglassSwitch(feature_id) -> ( + if(!nbt_storage('ica:data'):'Started', ( + print('Not started. use /ica-admin confirm to start.'); + return(false) + )); + me = player(); + if(nbt_storage('ica:data'):'Preparing', ( + display_title(me, 'actionbar', 'Currently preparing, please switch later.'); + return(false) + )); + if(query(me, 'has_scoreboard_tag', 'ica.deceased'), ( + bystandReject(); + return(false); + )); + + if(query(me, 'has_scoreboard_tag', global_capMarkerMap:feature_id), ( + disableAllSpyglassAbilities(me); + modify(me, 'tag', str('ica.spyglass_%s', feature_id)); + ), ( + lackOfAbilityReject(); + )) +); + cmdSubmit(slot_id) -> ( if(!nbt_storage('ica:data'):'Started', ( print('Not started. use /ica-admin confirm to start.'); @@ -181,7 +236,6 @@ cmdSubmit(slot_id) -> ( )); put(nbt_storage('ica:data'):(pkey+'.Completed'), '1b'); iv = bossbar('ica:collected', 'value') + 1; - print(iv); bossbar('ica:collected', 'value', iv); - print('OK.'); + display_title(me, 'actionbar', 'OK.'); );