作为一个一天速成的小活动,在一开始其实有很多设定不合理之处。开活动的这三天,各种设定也在不断完善。希望这次小活动大家都打的开心~
策划阶段
主题确定
刚办完圣诞活动,马上又来一个大型活动显然是不合适的,所以我们当时定下的就是一个小型活动。考虑到圣诞活动很肝,这次就打算办一个能让大家摸摸鱼的活动。首先想到的就是大团队竞技,全部玩家分成两方,相互对抗那样。想着新年打打杀杀也不太好,于是决定活动中不包含pvp元素,但我们一直都没想到什么非pvp竞技的好点子。
作为新年活动,还有几个需要满足的需求,一是画面感强烈,玩起来热闹;二是方便制作,没有复杂的CB或建筑。在这些条件下,活动鬼才兽兽提出了一个保卫战的想法,得到了大家的一致认可。活动主题就这样确定了。
玩法与机制
守卫战的玩法就很简单了,玩家需要抵挡四面八方涌来的怪物,保卫家园。结合MC里的怪物仇恨机制,为了让怪物自发的往中间走,显然中间需要站一个什么东西。于是村民就成了不二的选择,而村民的血量也成为了胜负的关键。
按波次计分是我一口定下的。相比于按击杀数计分,这样可以让玩家更有集体感(也更容易摸鱼),也促进玩家之间产生分工。这时打怪就仅仅作为玩家的经济来源。
每一波的怪物生成自然是手动刷的。自动化太耗肝,数值还不好调整,万一出了事情还难收场。正是因为手动刷怪,我们就没有设定最高能达到的波次,毕竟只要多刷一点,玩家是必死的(
怪物的种类从原版到自定义都有。一开始我们没有设计很多自定义怪物,但后面两场随着大家越发熟练,原版怪物已经无法左右玩家了,就……
使用大量自定义怪物还有一个原因:服务器的性能无法支持过多的实体。尽管原版怪物也可以靠数量取胜,但若导致服务器TPS显著下降,在性能恢复tps补偿时会产生灾难性的后果。这也是我们在第二天的时候发现的
平衡设计
说实话在这方面,我们一开始的设计显然是过于高估玩家的水平了。本以为原版怪物都是各种被玩家吊打的,结果发现……
于是我们逐渐关闭了死亡掉落和队友伤害,并把领主的生命从50提升到了100。在后面,我们还降低了各种物品的兑换难度,缩短了每一波的时间,添加了自定义物品,甚至添加了复活领主的道具。为了给变得过于IMBA的玩家找点旗鼓相当的对手,我们也添加了大量的自定义怪物。可以看到,这个游戏从硬盒逐渐变的无脑了起来,目的自然是能让大部分玩家都玩得开心。
建造阶段
服务器搭建、各项配置和世界设定
基本同圣诞活动~
建筑与地图
作为守卫战的地图,最先想到的自然是堡垒,这时我们想起在前一阵活跃在毛线的建筑大佬 @Xiuye 的城堡。征得同意后,我们将他的城堡直接复制过来作为了本次活动的建筑,并加以修改。(比较残念的是修野似乎在忙期末考试没空参加活动)
关于城堡的内饰和周围地形,兽兽则请了 @Yukkikaze 帮忙建造。对这些方面原本也没有特殊的要求,所以造成什么样都是可以接受的,不过真没想到最后居然是个火焰山(那么说到火焰山……)
怪物设计
为了让刷出来的怪物不傻站着而是去找玩家,所有的怪物都修改了跟随距离为 50 格。以僵尸为例:
/summon zombie ~ ~ ~ {Attributes:[{Name:generic.followRange,Base:50}]}
如果绕着城堡刷一圈这样的僵尸,在没有玩家去把它们的仇恨引开的情况下,它们会直接奔着城堡中央的领主去,场景活像食堂开饭。
至于各种自定义怪物都是怎么生成的,这里就不列举了。总之大部分的怪物都是刷怪鬼才卷老师制作出来的。相信在毛线玩过各种刷怪游戏的大家应该都比较熟悉吧。
刷怪总不可能每次都手动输入指令,那样就过于麻烦了。一开始我们用了Essentials里面的powertool工具,将指令绑定到物品的左键。还是以僵尸为例,手持一个物品(比如木棍)输入:
/pt summon zombie ~ ~ ~ {Attributes:[{Name:generic.followRange,Base:50}]}
就可以将命令绑定在木棍上,之后在每次左键点击木棍时都会执行这条命令。绑定的命令存储在玩家数据中,即使重新登录后,也可以继续使用。对于过长的命令,在聊天框无法输入,因此需要借助命令方块。以僵尸为例:
/sudo Aqua_nano pt summon zombie ~ ~ ~ {Attributes:[{Name:generic.followRange,Base:50}]}
使用/sudo
模拟玩家输入指令,即可解决输不下的问题。由于sudo也是essentials的功能,后接的指令可以为插件命令。而原版的/execute
则做不到这点。一个小小的问题是,sudo后的玩家名无法用选择器代替。卷老师觉得这非常难受,于是直接……用 RGI 把所有刷怪道具重制了:
/rpgitem 2018end_summon_zombie create
/rpgitem 2018end_summon_zombie display 僵尸
/rpgitem 2018end_summon_zombie power command command:`summon zombie ~ ~ ~ {Attributes:[{Name:generic.followRange,Base:50}]}` cooldown:0 display:``
/rpgitem 2018end_summon_zombie toggleArmorLore
关于RGI的使用,即使懒得看文档,仅通过游戏内的补全,也可以理解大部分的功能和参数。
硬核的CB设计
又到了开发笔记中最为硬核的部分。本来这里没有很多内容,不过后来为了实现类似领主受伤提示和领主复活的功能,最后还是搞得挺麻烦的。一些不涉及核心功能的内容就不写出来了。
波次进度的显示
使用了1.13的新功能——bossbar。事先创造bossbar和相关计分板项
/bossbar add time 波次进度
/bossbar set time max 4800
/scoreboard objectives add time dummy
/team add rua
/team modify rua friendlyFire false
/scoreboard objectives add round dummy
/scoreboard objectives setdisplay sidebar round
在每一波开始时,执行下列命令:
/summon armor_stand ~ ~1 ~ {Invulnerable:1b,Tags:["timer"]}
/bossbar set time players @a
/team join rua @a[gamemode=adventure]
/title @a title ["blah"]
/scoreboard players add 当前波次 round 1
/scoreboard players add 本波奖励积分 round 50
同时激活下面的高频
/execute as @e[tag=timer] store result bossbar time value run scoreboard players add @s time 1
/execute as @e[tag=timer,scores={time=4800..}] run setblock * * * air
高频的上面一条将会持续更新波次进度,而下面一条则会检测当前进度是否完成。由于我喜欢用红石块激活高频,所以下面的会命令会直接把红石块替换为空气,从而终止高频,并通过电路触发下面的命令,执行一些成功防御后的操作:
/scoreboard players operation 总积分 round += 本波奖励积分 round
/title @a title ["blahblahblah"]
/minecraft:kill @e[tag=timer]
/minecraft:kill @e[type=zombie]
……
清除计时用的盔甲架的同时,也将盔甲架上累计的时间也清空,因此也回到了下一波开始前的初始状态。如果要将波次归零,可直接执行下列命令:
/scoreboard players set 当前波次 round 0
/scoreboard players set 本波奖励积分 round 0
/scoreboard players set 总积分 round 0
领主显血以及受伤提示
因为很多人都没有装显血插件,所以能看到领主的血量就比较重要。这部分的功能实现起来会比较麻烦,因为计分板无法直接追踪生物的血量,因此需要用execute绕个弯子。高频激活下面的命令可以将领主的血量存到health的计分板项上:
/execute as @e[tag=landlord] store result score @s health run data get entity @s Health
后来想到,bossbar其实可以有多条,以后可以考虑把领主的血条也显示在顶上。
如果要判断领主是否受伤,则需要知道领主当前的血量是否比之前要少。因此接着上面的高频,同时高频执行下列命令:
/scoreboard players operation @e[tag=landlord] healthdiff = @e[tag=landlord] health
/scoreboard players operation @e[tag=landlord] healthdiff -= 领主生命 round
/execute @e[tag=landlord,scores={healthdiff=..-1}] run title @a title ["RUA!"]
/setblock * * * redstone_block
/scoreboard players operation 领主生命 round = @e[tag=landlord] health
这里用领主生命
的round
计分板项纪录了领主之前的血量,并通过中间变量healthdiff
来比较两者的大小。(没错!在MC里面比较两数大小就是这么硬核!)
上面的高频命令之中,setblock
一行使用的是条件命令方块,即只有前面一条成功执行后,它才会执行,其目的是激活别处的电路,由此实现受伤后屏幕发红一段时间(包括各种名称颜色变红)的视觉效果。屏幕发红的效果其实是接近世界边界时的效果,非常适合应用在这种场合。只要通过下列指令即可实现:
/worldborder warning distance 10000
取消效果的话,只要把参数改回去就行了。
/worldborder warning distance 5
因此如果要让屏幕发红一小段时间,只要延时一小段时间依次激活两个命令方块就行了。不过值得一提的是,控制延迟的电路必须要传递完整的脉冲信号,而一般的中继器会过滤掉过短的负脉冲。这里我使用了一些额外的setblock
命令来确保过短的负脉冲不被中继器过滤掉。
不止大家有没有注意到,屏幕的红边在领主血量过低时会保持。这是通过高频下面命令方块实现的:
/execute as @e[tag=landlord,scores={health=..40}] run worldborder warning distance 10000
在领主血量恢复的瞬间,红边会被立刻移除。首先高频检测领主的血量:
/execute as @e[tag=landlord,scores={health=41..}]
用比较器接出这个高频方块,这样在领主血量恢复时,比较器的信号会产生一个下降沿。由此可以激活命令方块来移除红边。
领主死亡提示
本来是没做这个的,想着领主死了就直接GG了,后来在卷老师的教育之下,还是做了出来。
高频检测领主是否存在:
/execute as @e[tag=landlord]
同样用比较器接出。在领主突然不见时,通过比较器信号的下降沿来激活下面的命令:
/minecraft:kill @e[tag=timer]
/bc GG
恩就这么简单。
领主复活道具
好在做了死亡检测,这为之后的复活提供了一些便利。复活道具只是一个简单的RGI,使用后,会在控制室放置一个红石块,并激活一系列的命令方块:
/data merge entity @e[tag=landlord] {Health:10}
/minecraft:kill @e[tag=timer]
/minecraft:kill @e[type=zombie]
……
/summon armor_stand ~ ~1 ~ {Invulnerable:1b,Tags:["timer"]}
/title @a title ["blah"]
简单的来说,就是重设领主血量,重置时间,清怪并发个公告。另外,如果领主已经死亡(通过之前检测领主是否死亡的信号判断),则召唤一个新的领主。
活动流程
没啥好说的,人差不多了直接开。新玩家也可以直接加进来玩。
文案
小活动,没写文案。至于怪物到底跟这领主有多大仇…… 抱歉我也不知道。
活动奖励
艾玛终于把硬核的CB部分写完了
因为圣诞活动刚过去,不想做新的道具,于是复刻了部分以前的活动道具。凤凰十字弓是应群众的呼声加上去的。
一个比较尴尬的事情就是,在兑换NPC放出一天之后,我才发现我的NPC写错了,一组换一个的直接变成了一组换十六个…… 这导致原本GBF的兑换瞬间变得简单了。为了让大家再花掉点肝,我又做了个新的纪念品。顺便在这里透露下新纪念品的命令:
/give @p minecraft:enchanted_book{Unbreakable:1b,HideFlags:2,display:{Lore:["§f向过去作个告别","§f带着这份新年祝福","§f与明日的多彩世界道声"," §c §c §c §c §c §c §c §c §c——“新年快乐!”","","§a毛玉缐圈物語 §c2019 §e新年纪念"],Name:"{\"text\":\"§f✧ §e来自明日的祝福之卷 §f✧\"}"},StoredEnchantments:[{lvl:10s,id:"minecraft:luck_of_the_sea"},{lvl:10s,id:"minecraft:fortune"}],AttributeModifiers:[{UUIDMost:540699L,UUIDLeast:551827L,Amount:0.05d,Slot:"offhand",AttributeName:"generic.movementSpeed",Operation:0,Name:"generic.movementSpeed"},{UUIDMost:151052L,UUIDLeast:822868L,Amount:-2.0d,Slot:"offhand",AttributeName:"generic.attackDamage",Operation:0,Name:"generic.attackDamage"},{UUIDMost:784101L,UUIDLeast:500235L,Amount:2.0d,Slot:"offhand",AttributeName:"generic.armorToughness",Operation:0,Name:"generic.armorToughness"},{UUIDMost:49319L,UUIDLeast:666648L,Amount:1.0d,Slot:"offhand",AttributeName:"generic.luck",Operation:0,Name:"generic.luck"}]} 1
大概需要转化一下命令才能复制到原版的CB里面,不然输出的物品是不带颜色的。