多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
然而,只吞不吐也不是一个好现象,有了积蓄就要适时用掉才能良性循环呀。 </br>所以我们决定再设计一个用牌的技能: > 普照:出牌阶段,你可以弃一张“光”并选择场上一名角色,该角色摸X张牌。X为这张“光”的点数的一半(向上取整)。 </br>想一想邓艾急袭是怎么发动的吧。首先是通过一个类似于五谷丰登的窗口展示了他所有的田,然后从中选择一张,接下来就可以用这张选出来的田当作顺手牵羊使用了。 </br>没错,为了移除牌堆中的某张牌,我们要做的,就应该也是用那个小窗口展示我们所有的光了。换句话说,就是将我们的光,通通扔进那个小窗口里。 </br>完成这个步骤,是Room兄的一个成员函数`fillAG`的专长。它的原型是: ``` fillAG(card_ids, who=NULL) ``` ![](https://img.kancloud.cn/bc/a3/bca3974cb3cd60aad4700b71bbc4c0f1_661x23.png) </br>这个函数可以把一些卡牌填充到五谷丰登的窗口中。其中: 1. `card_ids`表示要填充的卡牌的编号的列表。还记得我们提到过牌堆本质上就是卡牌编号的列表吧?所以这里可以直接把牌堆填进去。 2. `who`表示可以看到这个窗口的特定的角色,默认是空,也就是大家都能看到。 </br>下一步,就是在装有这些牌的窗口里进行选择了,选出一张我们要弃掉的光。这需要用到另一个Room的成员函数:`askForAG`。函数原型是这样的: ``` askForAG(player, card_ids, refusable, reason) ``` ![](https://img.kancloud.cn/84/af/84af43e1d8fbba4b790e3fb0b48445af_1019x24.png) </br>其中: 1. player就是要作出选择的那个角色了。 2. card_ids是刚才填充到窗口中的卡牌编号列表,在这里再填一次吧。 3. refusable表示是否可以拒绝这次选择。填true表示允许拒绝,这时点叉关掉窗口就什么事都没有;填false表示不能拒绝,如果直接关掉窗口的话,系统会强制帮我们选择列表中的第一个编号对应的卡牌作为选择结果。 4. reason表示询问选择的原因,一般是发动的技能的名字。 </br>当太阳神三国杀遇到`askForAG`时,就会把刚才填充好的小窗口弹出来,让我们进行选择,并且把选择的编号告诉我们。这样,我们就可以用这个编号找到那张卡牌,进行我们想要的各种活动了。 </br>但是,选择之后,窗口是不会主动消失的,所以还要给它一个信号提醒它一下。这个信号是`clearAG`,我们用ServerPlayer的一个成员函数`invoke`发送它。 </br>这下我们就清楚了整个移除卡牌的过程了。现在回到我们的技能上来。 </br>这是一个主动使用的技能。对于主动使用的技能,如果有明确的发动时机,我们一般就作为触发技处理了;而那些没有明确发动时机的,我们通常情况下就把它们当作视为技了。因为我们可以使用技能卡描述技能的效果,然后技能的描述就变成了:“某某阶段,你可以使用一张如此的技能卡”的形式了。 </br>根据这个思路,我们可以写出这样的代码: </br>技能卡部分: ![](https://img.kancloud.cn/b2/3b/b23b57b64f2a01050c8d210e2d8ffdee_524x180.png) </br>视为技部分: ![](https://img.kancloud.cn/28/4f/284f871ef1c6f166d66d04fca59a8152_463x245.png) </br>只有我们的牌堆有牌时才能发动技能,所以在视为技的`enabled_at_play`部分,我们需要检查一下牌堆中牌的数目是否是正数。所以视为技的代码就该是这样的: ![](https://img.kancloud.cn/ce/42/ce42194fff273d6bf6cc2608bda0de9f_473x284.png) </br>而技能卡部分,就是来实现技能效果的了。 </br>第一步:使用fillAG把“光”填到小窗口里: ![](https://img.kancloud.cn/47/6f/476f5ea28bcbdd06ad9994047a0e133f_468x111.png) </br>第二步:询问选择一张“光”并弃掉: ![](https://img.kancloud.cn/ed/18/ed183711940be77b868b18604380925b_595x133.png) </br>此时我们已经得到了被弃掉的那张"光"的编号了,后面可以用这个编号得到这张卡牌的点数信息,进行摸牌。 </br>第三步:给窗口发送"clearAG"信号以关掉窗口: ![](https://img.kancloud.cn/a7/43/a74361f27cac6c7cbc54de7688944352_591x94.png) </br>这样,牌堆部分的任务就完成了~ </br>接下来,第四步:获得卡牌的点数: </br>为了通过编号获得那张已经被我们丢掉的卡牌,我们用到了Engine大仙的一个成员函数getCard,它的原型是: ``` >getCard(cardId) ``` ![](https://img.kancloud.cn/14/26/14267fe15e2946b7e006eaa218ae30d9_262x23.png) </br>当然参数`cardId`就是卡牌的编号了。 </br>跟之前那次一样,Engine自己是不出马的,要去找sgs.Sanguosha才行。所以代码是: ![](https://img.kancloud.cn/62/76/627666cc9f4f31833a12279e88c03093_565x64.png) </br>剩下的就是最后一步了:指定一名场上角色,让TA摸牌。 </br>只见Room老兄也来凑热闹,它派出了一名成员函数`getAlivePlayers`协助我们。这个函数可以用来得到场上所有存活的武将的列表,原型是: ``` getAlivePlayers() ``` ![](https://img.kancloud.cn/d6/f9/d6f98c2122f153583a36a97e7df8284e_464x23.png) </br>而询问选择场上角色,依然用我们打过照面的`askForPlayerChosen`。 </br>于是代码就成了这个样子: ![](https://img.kancloud.cn/da/cf/dacfe23674a0fa5a4fe81b3caa79c333_636x136.png) </br>到游戏中体验一下强力辅助的感觉吧~ </br>先看看我们积攒的“光”: ![](https://img.kancloud.cn/71/da/71da9c1fb1f3b01469ffdaf3d4a12470_170x172.png) </br>然后发动普照: </br>会提示我们选择一张牌扔掉…… ![](https://img.kancloud.cn/a1/bf/a1bfc8726224b83155e34ce3701e61d6_562x350.png) </br>然后选择那张铁锁链环(当然点数要越大越好了!),再选择自己(……): ![](https://img.kancloud.cn/f6/e2/f6e24bbe78873e92b06f1e7978ffb9e7_480x201.png) </br>再选择自己(邓艾:喂……) ![](https://img.kancloud.cn/5b/0f/5b0f3034fb377f6923f2fd4f2586ad20_173x171.png) </br>结果呢?看游戏记录就知道了…… ![](https://img.kancloud.cn/66/28/662827752409e809b2c02b8d36f2c702_214x65.png) </br>由于点数是10,一半是5,所以我们摸了5张牌。 </br>成功!