为了排解郁闷的心情,孙悟空又躲到角落里薅它头上的猴毛去了,只见随口一吹,几根毛发就变成了几个小猴子,来陪它来联机打太阳神三国杀了。
</br>(编者:不要总羡慕关羽能拿红牌当杀了,我们来设计一个所有牌都能当杀的技能盖过他吧?孙悟空:要所有牌都当决斗!……)
</br>好吧,所以我们为了安慰我们的新武将孙悟空同志,就来看一看怎样实现下面的一个技能吧:
> 斗佛:你可以将一张牌当作【决斗】使用。
</br>首先我们来分析一下这个技能:
</br>这个技能和之前我们设计的技能有一个很大的不同,那就是前面的技能大多都有明确的触发时机,属于触发技;而这个技能虽然只能在出牌阶段使用,但是并没有明确的触发时机。我们可以上来就发动,也可以先装个八卦阵什么的再发动,甚至可以不发动。
</br>更为明显的是,这个技能明确表明,要将一张卡牌视作另外的一张卡牌使用。这样的一个技能,不正符合早先我们提到的“视为技”的特点吗?没错了,这就是一个典型的视为技了。
</br>所以为了创建这个技能,我们就应当采用创建视为技的那个方法了……叫什么来着?哦,是这个:sgs.CreateViewAsSkill。
</br>根据斗佛这个技能名字,还是取`name = "LuaDoufo"`吧。
</br>这是一个要求用1张牌发动技能的视为技,所以必然有参数n=1。
</br>由于任何一张牌都可以用来发动技能,所以view_filter函数直接返回true就好啦。
</br>view_as函数描述的是被视为的卡牌,我们需要花费心思的地方到了!
</br>还记得在游戏里面那个游戏记录是怎么说的吧?
“武将a 使用了【技能b】将 卡牌c 当成了 卡牌d 使用,目标是 武将e”
</br>所以为了发动这个视为技,我们至少需要提供以下五个信息:
1. 技能的使用者武将a;
2. 技能的名字b
3. 发动技能所用的卡牌c;
4. 被视作的卡牌d;
5. 技能的使用对象武将e。
</br>而具体到被视为的卡牌上,需要的信息就是:技能名字b、发动卡牌c,和由此得到的被视作的卡牌d了。
</br>技能的名字啊……当然是刚才确定的"LuaDoufo"了;
</br>而发动的卡牌呢?还记得view_as函数的原型是function(self, cards)吧?这个cards就是被选取用来发动技能的卡牌名单了。可以考虑从这里做一些文章。
</br>获取这个名单中的第一张卡牌(其实总共应该就有一张而已啦),所用的方法很简单,使用一个方括号里面写个"1"标注一下就可以了:cards[1]。
</br>不过在获取这张卡牌之前呢,还是要先猫腰打探一下名单里面到底有没有卡牌为妙。具体的方法就是测量一下名单到底有多长,要是0的话就没有卡牌,要是1的话就说明正确选取了发动技能的卡牌。
</br>测量名单长度的方法就更简单了,只需要把一个"#"放到名单前面,就可以了。没错,#cards就代表了cards这个名单的长度。
</br>所以现在代码应该是这样写的:
![](https://img.kancloud.cn/01/3c/013cd5386cf57ea082a2d43863369ef0_617x329.png)
</br>那么要怎么创建这个虚构的卡牌呢?
</br>一个卡牌有这么几个必要的信息:
1. 卡牌编号(id),是一个数字啦,表示在卡牌一览那个表里面的默认出现顺序啦。所以对于每张卡牌来说,编号是唯一的。当然虚构的卡牌就没有具体的编号了。
2. 卡牌花色(suit),就是什么黑桃、红心、方块、草花什么的信息了。我们这里就用卡牌c的花色作为这个虚构的卡牌花色吧。
3. 卡牌点数(number),用数字1~13代表A、2……10、J、Q、K这些现实中的点数。这里我们同样用c的点数作为这个虚构的卡牌点数吧。
</br>所以首先我们要先获得发动技能的这张卡牌的上述信息。这时来了一封邮件,是一个不熟悉的地址来的。“我是Card,是管教你们所遇到的各种卡牌的指挥官。你们可以从源码(可在群文件里搜索 秒沉水 查找到源码)的src\core\card.h中找到我。”接下来它为我们介绍了许多有关Card自身的信息,然后推荐了一些成员函数:
</br>☆ getId():可以获得一张卡牌的编号
![](https://img.kancloud.cn/10/5b/105b1036b3d51189803e998817fbfb1a_182x28.png)
</br>☆ getEffectiveId():可以获得一张卡牌的名义上的编号(虚构卡牌也可用)
![](https://img.kancloud.cn/d7/72/d772a52cdbb632614405939d01414564_273x26.png)
</br>☆ getSuit():可以获得一张卡牌的花色
![](https://img.kancloud.cn/25/9d/259d67285d55a5bd6fedde0937184e33_216x26.png)
</br>☆ getNumber():可以获得一张卡牌的点数
![](https://img.kancloud.cn/0a/c0/0ac05d0a96148e947d52489fb0f1f093_224x25.png)
</br>因此接下来的代码就是:
![](https://img.kancloud.cn/b1/0c/b10cf50986f3a9d709633ccc0819cb4c_475x154.png)
</br>接下来到了关键的一步——创建虚构的决斗卡牌!
</br>这需要我们邀请一位BOSS级别的大仙闪亮登场了!被称为太阳神三国杀发动机的Engine终于千呼万唤始出来了!大仙有一个堪称法宝的成员函数,那就是可以根据卡牌原型为我们创造各种虚构卡牌的
cloneCard!它的函数原型有三个,分别是:
```
cloneCard(card)
cloneCard(name, suit, number)
cloneCard(name, suit, number, flags)
```
![](https://img.kancloud.cn/25/2a/252aec11ddd0547f0e0a538204937924_955x65.png)
</br>第一个原型是根据一张已有的卡牌创造一张一样的卡牌,参数card就是那张给定的卡牌了;
</br>第二个原型是根据给定的卡牌名称、花色、点数创造一张符合条件的卡牌,参数name表示卡牌类型名称,suit表示卡牌花色,number表示卡牌点数。
</br>第三个原型和第二个差不多,都是根据给定条件创造一张卡牌,参数上也就是多了一个flags而已。这个flags表示一些特定标志的列表。
</br>此外,在我们的诚挚请求下,Engine大仙还带来了它的一个得意化身来帮助我们完成这件事情,这就是:sgs.Sanguosha前辈。
</br>我们已经打探到,关于Engine和sgs.Sanguosha的详细信息,还是可以从源文件下的swig\sanguosha.i文件中找到的。
</br>在此有必要了解一下我们要创造的卡牌到底是什么名称,提供了这些细节的东西,才好继续我们的工作嘛。
</br>卡牌的类型名称,就列在下面了:
</br>☆ 基本牌:
* 杀:slash
* 火杀:fire_slash
* 雷杀:thunder_slash
* 闪:jink
* 桃:peach
* 酒:analeptic
☆ 非延时性锦囊牌:
* 决斗:duel
* 火攻:fire_attack
* 南蛮入侵:savage_assault
* 万箭齐发:archery_attack
* 过河拆桥:dismantlement
* 顺手牵羊:snatch
* 桃园结义:god_salvation
* 五谷丰登:amazing_grace
* 铁锁链环:iron_chain
* 借刀杀人:collateral
* 无中生有:ex_nihilo
* 无懈可击:nullification
☆ 延时性锦囊牌:
* 乐不思蜀:indulgence
* 兵粮寸断:supply_shortage
* 闪电:lightning
</br>所以,创建一个虚构的决斗,应该是这样写的:
```
sgs.Sanguosha:cloneCard("duel", suit, point)
```
![](https://img.kancloud.cn/f1/8e/f18edc87eb30689f08e89f102eb268e1_646x197.png)
</br>这是一张刚刚被创建的卡牌,什么都没有,只是一层外壳,还很虚弱;而我们接下来要做的,就是建立它和我们发动技能的卡牌的联系,用我们的卡牌充实它,让它有信心、有能力实现自己的使命。
</br>用已有卡牌充实这张虚构卡牌的任务,就交给了Card的一个专职于此的成员函数:`addSubcard`,翻译为“添加子卡”。这个函数的原型是:
```
addSubcard(id)
addSubcard(card)
```
![](https://img.kancloud.cn/2e/f7/2ef70585677de1676e93bd0cf4bfa760_425x46.png)
</br>哦,有两个原型,一个是以卡牌编号id为参数的,另一个是以卡牌本身card为参数的。这里我们就选择第一个好啦。
![](https://img.kancloud.cn/32/1a/321a0d61db5c64b543e054eed79c8fb3_613x135.png)
</br>OK,虚构卡牌完成,把早就等在一旁的技能名字"LuaDoufo"也交给它吧。这回,借助Card的成员函数setSkillName就可以了。原型是这样的:
```
setSkillName(skill_name)
```
![](https://img.kancloud.cn/fb/41/fb4156e0f17dc456d5fea1a1d1a478ea_534x25.png)
其中的参数`skill_name`就是技能的名字啦。
这下,view_as部分就完整了!代码如下:
![](https://img.kancloud.cn/66/c3/66c3f3b44653c84d0168d41ce7a81b5b_684x355.png)
</br>然后我们继续……
由于我们可以在出牌阶段随意使用决斗,而在回合外又不能用决斗进行什么响应,跟无懈可击也没什么关系,所以剩下的三个函数:
* enabled_at_play(默认为true)
* enabled_at_response(默认为false)
* enabled_at_nullification(默认为false)
</br>我们就不再写了,让它们取默认值去吧!
</br>最终这个技能就是这么创建出来的了……
![](https://img.kancloud.cn/5a/7e/5a7ec80e0abff4228f800fc15d3a86ec_742x508.png)
</br>到游戏里面体验一下吧!
![](https://img.kancloud.cn/27/68/276884f2a27df418bbaf9462d4af1dcd_244x122.png)
</br>搞定!(编者:悟空!你去跟关羽决斗吧!)
- 编写说明
- 第一章 创建一个新武将
- 1.1 开发环境准备
- 1.2 创建一个新的武将扩展包
- 1.3 创建我们的新武将
- 第二章 添加技能
- 第三章 武将美化
- 3.1 美化环境准备
- 3.2 添加武将卡牌
- 3.3 添加武将头像
- 3.4 添加武将标签
- 第四章 创建一个新技能
- 第五章 添加音效
- 5.1 打造自己的声音工作室
- 5.2 添加技能使用音效
- 5.3 添加武将阵亡音效
- 第六章 添加提示信息
- 6.1 添加代码注释
- 6.2 显示提示信息
- 6.3 启动全屏信息特效
- 第七章 武将变更
- 第八章 启用AI
- 8.1 创建我们的AI文件
- 8.2 真实的AI
- 8.3 动手写AI
- 第九章 修改距离
- 第十章 技能管理
- 10.1 技能判定
- 10.2 创建技能
- 10.3 获得技能
- 10.4 失去技能
- 第十一章 修改手牌上限
- 第十二章 体力变更
- 12.1 流失体力
- 12.2 制造伤害
- 13.3 恢复体力
- 12.4 流失体力上限
- 12.5 增长体力上限
- 第十三章 游戏进程的变更
- 13.1 创建阶段触发技能
- 13.2 跳过回合阶段
- 13.3 插入一个额外的回合阶段
- 13.4 启用翻面
- 13.5 获得一个额外的回合
- 第十四章 启用标记(Mark)
- 14.1 添加标记
- 14.2 获得标记
- 14.3 失去标记
- 14.4 查看标记数目
- 第十五章 卡牌转换
- 15.1 主动牌的转换
- 15.2 被动牌的转换
- 第十六章 卡牌传递
- 16.1 创建摸牌技能
- 16.2 游戏中摸牌
- 16.3 游戏中弃牌
- 16.4 从其他武将处获得牌
- 16.5 判断目标区域是否有牌
- 16.6 移动场上的牌
- 第十七章 用牌实现技能效果
- 第十八章 启用标志(Flag)
- 第十九章 涉足判定领域
- 19.1 启用判定
- 19.2 更改判定
- 19.3 获得判定牌
- 第二十章 私家牌堆
- 20.1 向牌堆中添加牌
- 20.2 查看牌堆中牌的数量
- 20.3 从牌堆中移除牌
- 第二十一章 牌的锁定
- 第二十二章 免疫牌
- 第二十三章 让房间提供牌
- 23.1 提供主动牌
- 23.2 提供被动牌
- 第二十四章 启用标签(Tag)
- 第二十五章 濒死结算
- 第二十六章 交换座次
- 第二十七章 创建主公技
- 27.1 创建由主公发起的主公技
- 27.2 创建由他人发起的主公技
- 第二十八章 强力技能
- 28.1 直接死亡
- 28.2 改换身份
- 28.3 原地复活
- 28.4 立即胜利