Enhancement (#292)

1. 卡牌一览中音效播放(装备牌鸽)
2. 修改游戏桌面菜单式样,增加音量
3. 卡牌使用时prompt
4. 比较角色性别是否相同
5. 修一些函数提示
6. getEventsOfScope找不到start_event直接返回
7. 应用all_card_types
8. 修改askForCard的默认返回值
9. 增加装备牌技能触发log
10. phase_state初始化
11. 额外阶段走phaseChanging
12. 亮将增加一个时机并做调整(但还是不对……)
13. 标准包和军争篇增加卡牌prompt,修改描述
14. 运用一些Util,hasSkill精简
15. 修改一些神秘英语单词,水

---------

Signed-off-by: Mechanel <nyutanislavsky@qq.com>
This commit is contained in:
Nyutanislavsky 2023-12-09 21:57:47 +08:00 committed by GitHub
parent 8df1985b99
commit 5abbdc9b23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 666 additions and 324 deletions

View File

@ -226,8 +226,9 @@ Item {
}
detailCard.known = true;
cardText.clear();
audioRow.clear();
cardText.append(Backend.translate(":" + data.name));
addCardAudio(data)
const skills = JSON.parse(Backend.callLuaFunction
("GetCardSpecialSkills", [cid]));
if (skills.length > 0) {
@ -287,6 +288,35 @@ Item {
textFormat: TextEdit.RichText
font.pixelSize: 16
}
GridLayout {
columns: 2
Repeater {
model: ListModel {
id: audioRow
}
Button {
Layout.fillWidth: true
contentItem: Text {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: {
if (gender === "male") {
return Backend.translate("Male Audio");
} else {
return Backend.translate("Female Audio");
}
}
font.pixelSize: 14
}
onClicked: {
const data = JSON.parse(Backend.callLuaFunction("GetCardData", [cardDetail.cid]));
Backend.playSound("./packages/" + extension + "/audio/card/" + gender + "/" + data.name);
}
}
}
}
}
}
}
@ -299,6 +329,29 @@ Item {
}
}
function addCardAudio(card) {
const extension = card.extension;
const orig_extension = Backend.callLuaFunction("GetCardExtensionByName", [card.name]);
let fname = AppPath + "/packages/" + extension + "/audio/card/male/" + card.name + ".mp3";
if (Backend.exists(fname)) {
audioRow.append( {gender: "male", extension: extension} );
} else {
fname = AppPath + "/packages/" + orig_extension + "/audio/card/male/" + card.name + ".mp3";
if (Backend.exists(fname)) {
audioRow.append( {gender: "male", extension: orig_extension} );
}
}
fname = AppPath + "/packages/" + extension + "/audio/card/female/" + card.name + ".mp3";
if (Backend.exists(fname)) {
audioRow.append( {gender: "female", extension: extension} );
}else {
fname = AppPath + "/packages/" + orig_extension + "/audio/card/female/" + card.name + ".mp3";
if (Backend.exists(fname)) {
audioRow.append( {gender: "female", extension: orig_extension} );
}
}
}
function loadPackages() {
if (loaded) return;
const packs = JSON.parse(Backend.callLuaFunction("GetAllCardPack", []));

View File

@ -81,104 +81,140 @@ Item {
}
}
// tmp
Button {
ToolButton {
id: menuButton
anchors.top: parent.top
anchors.topMargin: 12
anchors.right: parent.right
anchors.rightMargin: 10
text: Backend.translate("Menu")
z: 2
anchors.rightMargin: 36
icon.source: AppPath + "/image/modmaker/menu"
icon.width: 36
icon.height: 36
onClicked: {
menuContainer.visible || menuContainer.open();
if (menuContainer.visible){
menuContainer.close();
} else {
menuContainer.open();
}
}
}
Menu {
id: menuContainer
x: parent.width - menuButton.width - menuContainer.width - 17
width: menuRow.width
height: menuRow.height
verticalPadding: 0
spacing: 7
z: 2
background.implicitWidth: 60
background.implicitHeight: 60
Row {
id: menuRow
spacing: 7
Button {
id: surrenderButton
enabled: !config.observing && !config.replaying
text: Backend.translate("Surrender")
onClicked: {
if (isStarted && !getPhoto(Self.id).dead) {
const surrenderCheck = JSON.parse(Backend.callLuaFunction('CheckSurrenderAvailable', [miscStatus.playedTime]));
if (!surrenderCheck.length) {
surrenderDialog.informativeText = Backend.translate('Surrender is disabled in this mode');
} else {
surrenderDialog.informativeText = surrenderCheck.map(str => `${Backend.translate(str.text)}${str.passed ? '√' : '×'}`).join('<br>');
}
surrenderDialog.open();
}
}
Menu {
id: menuContainer
y: menuButton.height - 12
width: 115
height: menuRow.height
verticalPadding: 0
spacing: 15
z: 2
background: Rectangle {
implicitWidth: 200
implicitHeight: 40
color: "transparent"
border.color: "transparent"
}
MessageDialog {
id: surrenderDialog
title: Backend.translate("Surrender")
informativeText: ''
buttons: MessageDialog.Ok | MessageDialog.Cancel
onButtonClicked: function (button, role) {
switch (button) {
case MessageDialog.Ok: {
const surrenderCheck = JSON.parse(Backend.callLuaFunction('CheckSurrenderAvailable', [miscStatus.playedTime]));
if (surrenderCheck.length && !surrenderCheck.find(check => !check.passed)) {
ClientInstance.notifyServer("PushRequest", [
"surrender", true
]);
}
surrenderDialog.close();
break;
}
case MessageDialog.Cancel: {
surrenderDialog.close();
}
}
}
}
Column {
id: menuRow
width: menuContainer.width
Layout.fillWidth: true
spacing: 7
Button {
id: quitButton
text: Backend.translate("Quit")
onClicked: {
if (config.replaying) {
Backend.controlReplayer("shutdown");
mainStack.pop();
} else if (config.observing) {
ClientInstance.notifyServer("QuitRoom", "[]");
} else {
quitDialog.open();
}
}
}
MessageDialog {
id: quitDialog
title: Backend.translate("Quit")
informativeText: Backend.translate("Are you sure to quit?")
buttons: MessageDialog.Ok | MessageDialog.Cancel
onButtonClicked: function (button) {
switch (button) {
case MessageDialog.Ok: {
Button {
id: quitButton
text: Backend.translate("Quit")
font.pixelSize: 28
Layout.fillWidth: true
width: menuContainer.width
height: menuContainer.width * 0.65
onClicked: {
if (config.replaying) {
Backend.controlReplayer("shutdown");
mainStack.pop();
} else if (config.observing) {
ClientInstance.notifyServer("QuitRoom", "[]");
break;
} else {
quitDialog.open();
}
case MessageDialog.Cancel: {
quitDialog.close();
}
}
MessageDialog {
id: quitDialog
title: Backend.translate("Quit")
informativeText: Backend.translate("Are you sure to quit?")
buttons: MessageDialog.Ok | MessageDialog.Cancel
onButtonClicked: function (button) {
switch (button) {
case MessageDialog.Ok: {
ClientInstance.notifyServer("QuitRoom", "[]");
break;
}
case MessageDialog.Cancel: {
quitDialog.close();
}
}
}
}
Button {
id: surrenderButton
enabled: !config.observing && !config.replaying
text: Backend.translate("Surrender")
font.pixelSize: 28
Layout.fillWidth: true
width: menuContainer.width
height: menuContainer.width * 0.65
onClicked: {
if (isStarted && !getPhoto(Self.id).dead) {
const surrenderCheck = JSON.parse(Backend.callLuaFunction('CheckSurrenderAvailable', [miscStatus.playedTime]));
if (!surrenderCheck.length) {
surrenderDialog.informativeText = Backend.translate('Surrender is disabled in this mode');
} else {
surrenderDialog.informativeText = surrenderCheck.map(str => `${Backend.translate(str.text)}${str.passed ? '√' : '×'}`).join('<br>');
}
surrenderDialog.open();
}
}
}
MessageDialog {
id: surrenderDialog
title: Backend.translate("Surrender")
informativeText: ''
buttons: MessageDialog.Ok | MessageDialog.Cancel
onButtonClicked: function (button, role) {
switch (button) {
case MessageDialog.Ok: {
const surrenderCheck = JSON.parse(Backend.callLuaFunction('CheckSurrenderAvailable', [miscStatus.playedTime]));
if (surrenderCheck.length && !surrenderCheck.find(check => !check.passed)) {
ClientInstance.notifyServer("PushRequest", [
"surrender", true
]);
}
surrenderDialog.close();
break;
}
case MessageDialog.Cancel: {
surrenderDialog.close();
}
}
}
}
Button {
id: volumeButton
text: Backend.translate("Audio Settings")
font.pixelSize: 28
Layout.fillWidth: true
width: menuContainer.width
height: menuContainer.width * 0.65
onClicked: {
volumeDialog.open();
}
}
}
}
}
@ -518,6 +554,7 @@ Item {
onCardSelected: function(card) {
Logic.enableTargets(card);
roomScene.resetPrompt();
if (typeof card === "number" && card !== -1 && roomScene.state === "playing"
&& JSON.parse(Backend.callLuaFunction("GetPlayerHandcards", [Self.id])).includes(card)) {
@ -527,6 +564,14 @@ Item {
skills.unshift("_normal_use");
}
specialCardSkills.model = skills;
const skillName = Backend.callLuaFunction("GetCardSkill", [card]);
const prompt = JSON.parse(Backend.callLuaFunction(
"ActiveSkillPrompt",
[skillName, card, selected_targets]
));
if (prompt !== "") {
roomScene.setPrompt(processPrompt(prompt));
}
} else {
specialCardSkills.model = [];
}
@ -692,13 +737,28 @@ Item {
text: Backend.translate(modelData)
checked: index === 0
onCheckedChanged: {
roomScene.resetPrompt();
const card = dashboard.selected_card;
let prompt = ""
if (modelData === "_normal_use") {
Logic.enableTargets(dashboard.selected_card);
Logic.enableTargets(card);
const skillName = Backend.callLuaFunction("GetCardSkill", [card]);
prompt = JSON.parse(Backend.callLuaFunction(
"ActiveSkillPrompt",
[skillName, card, selected_targets]
));
} else {
Logic.enableTargets(JSON.stringify({
skill: modelData,
subcards: [dashboard.selected_card],
subcards: [card],
}));
prompt = JSON.parse(Backend.callLuaFunction(
"ActiveSkillPrompt",
[modelData, card, selected_targets]
));
}
if (prompt !== "") {
roomScene.setPrompt(processPrompt(prompt));
}
}
}
@ -928,6 +988,60 @@ Item {
anchors.fill: parent
}
Dialog {
id: volumeDialog
title: Backend.translate("Audio Settings")
anchors.centerIn: roomScene
ColumnLayout {
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("BGM Volume")
}
Slider {
Layout.rightMargin: 16
Layout.fillWidth: true
from: 0
to: 100
value: config.bgmVolume
onValueChanged: config.bgmVolume = value;
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: Backend.translate("Effect Volume")
}
Slider {
Layout.rightMargin: 16
Layout.fillWidth: true
from: 0
to: 100
value: Backend.volume
onValueChanged: Backend.volume = value;
}
}
Switch {
text: Backend.translate("Disable message audio")
checked: config.disableMsgAudio
onCheckedChanged: config.disableMsgAudio = checked;
}
Switch {
text: Backend.translate("Hide unselectable cards")
checked: config.hideUseless
onCheckedChanged: {
config.hideUseless = checked;
}
}
}
}
Rectangle {
anchors.fill: dashboard
visible: config.observing && !config.replaying
@ -1039,6 +1153,18 @@ Item {
onActivated: Logic.doCancelButton();
}
function processPrompt(prompt) {
const data = prompt.split(":");
let raw = Backend.translate(data[0]);
const src = parseInt(data[1]);
const dest = parseInt(data[2]);
if (raw.match("%src")) raw = raw.replace(/%src/g, Backend.translate(getPhoto(src).general));
if (raw.match("%dest")) raw = raw.replace(/%dest/g, Backend.translate(getPhoto(dest).general));
if (raw.match("%arg2")) raw = raw.replace(/%arg2/g, Backend.translate(data[4]));
if (raw.match("%arg")) raw = raw.replace(/%arg/g, Backend.translate(data[3]));
return raw;
}
function getCurrentCardUseMethod() {
if (specialCardSkills.count === 1 && specialCardSkills.model[0] !== "_normal_use") {
return specialCardSkills.model[0];

View File

@ -576,9 +576,9 @@ function enableTargets(card) { // card: int | { skill: string, subcards: int[] }
if (roomScene.extra_data instanceof Object) {
const must = roomScene.extra_data.must_targets;
const included = roomScene.extra_data.include_targets;
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) photo.selectable = false;
const exclusive = roomScene.extra_data.exclusive_targets;
if (exclusive instanceof Array) {
if (exclusive.indexOf(id) === -1) photo.selectable = false;
}
if (must instanceof Array) {
if (must.filter((val) => {
@ -654,9 +654,9 @@ function updateSelectedTargets(playerid, selected) {
if (roomScene.extra_data instanceof Object) {
const must = roomScene.extra_data.must_targets;
const included = roomScene.extra_data.include_targets;
const exclusived = roomScene.extra_data.exclusive_targets;
if (exclusived instanceof Array) {
if (exclusived.indexOf(id) === -1) photo.selectable = false;
const exclusive = roomScene.extra_data.exclusive_targets;
if (exclusive instanceof Array) {
if (exclusive.indexOf(id) === -1) photo.selectable = false;
}
if (must instanceof Array) {
if (must.filter((val) => {

View File

@ -123,10 +123,7 @@ function GetCardData(id, virtualCardForm)
end
function GetCardExtensionByName(cardName)
local card = table.find(Fk.cards, function(card)
return card.name == cardName
end)
local card = Fk.all_card_types[cardName]
return card and card.package.extensionName or ""
end
@ -220,6 +217,10 @@ function GetCards(pack_name)
return json.encode(ret)
end
function GetCardSkill(cid)
return Fk:getCardById(cid).skill and Fk:getCardById(cid).skill.name or ""
end
function GetCardSpecialSkills(cid)
return json.encode(Fk:getCardById(cid).special_skills or Util.DummyTable)
end

View File

@ -89,6 +89,8 @@ Fk:loadTranslationTable{
["Cards Overview"] = "卡牌一览",
["Special card skills:"] = "<b>卡牌的特殊用法:</b>",
["Every suit & number:"] = "<b>所有的花色和点数:</b>",
["Male Audio"] = "男性音效",
["Female Audio"] = "女性音效",
["Scenarios Overview"] = "玩法一览",
["Replay"] = "录像",
["Replay Manager"] = "来欣赏潇洒的录像吧!",

View File

@ -428,7 +428,7 @@ end
--- 比较两张卡牌的花色是否相同
---@param anotherCard Card @ 另一张卡牌
---@param diff? boolean @ 比较二者相同还是不同
---@param diff? boolean @ 比较二者不同
---@return boolean 返回比较结果
function Card:compareSuitWith(anotherCard, diff)
if self ~= anotherCard and table.contains({ self.suit, anotherCard.suit }, Card.NoSuit) then
@ -444,8 +444,8 @@ end
--- 比较两张卡牌的颜色是否相同
---@param anotherCard Card @ 另一张卡牌
---@param diff boolean @ 比较二者相同还是不同
---@return boolean 返回比较结果
---@param diff? boolean @ 比较二者不同
---@return boolean @ 返回比较结果
function Card:compareColorWith(anotherCard, diff)
if self ~= anotherCard and table.contains({ self.color, anotherCard.color }, Card.NoColor) then
return false
@ -460,8 +460,8 @@ end
--- 比较两张卡牌的点数是否相同
---@param anotherCard Card @ 另一张卡牌
---@param diff boolean @ 比较二者相同还是不同
---@return boolean 返回比较结果
---@param diff? boolean @ 比较二者不同
---@return boolean @ 返回比较结果
function Card:compareNumberWith(anotherCard, diff)
if self ~= anotherCard and self.number < 1 or anotherCard.number < 1 then
return false

View File

@ -293,6 +293,7 @@ function Engine:addCard(card)
cardId = cardId + 1
table.insert(self.cards, card)
if self.all_card_types[card.name] == nil then
self.skills[card.skill.name] = card.skill
self.all_card_types[card.name] = card
end
end

View File

@ -451,7 +451,7 @@ function Player:getMaxCards()
return math.max(baseValue, 0)
end
--- 获取玩家攻击距离
--- 获取玩家攻击范围
function Player:getAttackRange()
local weapon = Fk:getCardById(self:getEquipment(Card.SubtypeWeapon))
local baseAttackRange = math.max(weapon and weapon.attack_range or 1, 0)
@ -544,7 +544,7 @@ function Player:distanceTo(other, mode, ignore_dead)
return math.max(ret, 1)
end
--- 获取其他玩家是否在玩家的攻击距离内。
--- 获取其他玩家是否在玩家的攻击范围内。
---@param other Player @ 其他玩家
---@param fixLimit? integer @ 卡牌距离限制增加专用
function Player:inMyAttackRange(other, fixLimit)
@ -596,7 +596,7 @@ end
---@return ServerPlayer
function Player:getLastAlive(ignoreRemoved, num)
num = num or 1
local index = ignoreRemoved and #Fk:currentRoom().alive_players or #table.filter(Fk:currentRoom().alive_players, function(p) return not p:isRemoved() end) - num
local index = (ignoreRemoved and #Fk:currentRoom().alive_players or #table.filter(Fk:currentRoom().alive_players, function(p) return not p:isRemoved() end)) - num
return self:getNextAlive(ignoreRemoved, index)
end
@ -1047,4 +1047,19 @@ function Player:isBuddy(other)
return self.id == id or table.contains(self.buddy_list, id)
end
--- 比较两名角色的性别是否相同。
---@param other Player @ 另一名角色
---@param diff? bool @ 比较二者不同
---@return boolean @ 返回比较结果
function Player:compareGenderWith(other, diff)
if self == other then return not diff end
if self.gender == General.Agender or other.gender == General.Agender then return false end
if self.gender == General.Bigender or other.gender == General.Bigender then return true end
if diff then
return self.gender ~= other.gender
else
return self.gender == other.gender
end
end
return Player

View File

@ -445,6 +445,9 @@ local defaultCardSkill = fk.CreateActiveSkill{
local defaultEquipSkill = fk.CreateActiveSkill{
name = "default_equip_skill",
prompt = function(_, selected_cards, _)
return "#default_equip_skill:::" .. Fk:getCardById(selected_cards).name .. ":" .. Fk:getCardById(selected_cards):getSubtypeString()
end,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return #Fk:currentRoom():getPlayerById(to_select):getAvailableEquipSlots(card.sub_type) > 0
end,

View File

@ -12,10 +12,10 @@ function RandomAI:useActiveSkill(skill, card)
local filter_func = skill.cardFilter
if card then
filter_func = function() return false end
filter_func = Util.FalseFunc
end
if self.command == "PlayCard" and card and (not player:canUse(card) or player:prohibitUse(card)) then
if self.command == "PlayCard" and card and (not skill:canUse(player, card) or player:prohibitUse(card)) then
return ""
end
@ -28,7 +28,7 @@ function RandomAI:useActiveSkill(skill, card)
local max_card = skill:getMaxCardNum()
for _ = 0, max_try_times do
if skill:feasible(selected_targets, selected_cards, self.player, card) then break end
local avail_targets = table.filter(self.room:getAlivePlayers(), function(p)
local avail_targets = table.filter(room:getAlivePlayers(), function(p)
local ret = skill:targetFilter(p.id, selected_targets, selected_cards, card or Fk:cloneCard'zixing')
if ret and card then
if player:isProhibited(p, card) then

View File

@ -125,6 +125,7 @@ fk.AfterSkillEffect = 82
fk.AreaAborted = 87
fk.AreaResumed = 88
fk.GeneralShown = 95
fk.GeneralRevealed = 89
fk.GeneralHidden = 90
@ -134,4 +135,4 @@ fk.BeforePropertyChange = 92
fk.PropertyChange = 93
fk.AfterPropertyChange = 94
fk.NumOfEvents = 95
fk.NumOfEvents = 96

View File

@ -28,11 +28,9 @@ local playCardEmotionAndSound = function(room, player, card)
soundName = "./packages/" .. card.package.extensionName .. "/audio/card/"
.. (player.gender == General.Male and "male/" or "female/") .. card.name
if not FileIO.exists(soundName .. ".mp3") then
for _, dir in ipairs(FileIO.ls("./packages/")) do
soundName = "./packages/" .. dir .. "/audio/card/"
.. (player.gender == General.Male and "male/" or "female/") .. card.name
if FileIO.exists(soundName .. ".mp3") then break end
end
local orig = Fk.all_card_types[card.name]
soundName = "./packages/" .. orig.package.extensionName .. "/audio/card/"
.. (player.gender == General.Male and "male/" or "female/") .. orig.name
end
end
room:broadcastPlaySound(soundName)

View File

@ -446,7 +446,7 @@ function GameLogic:getEventsOfScope(eventType, n, func, scope)
elseif scope == Player.HistoryPhase then
start_event = event:findParent(GameEvent.Phase, true)
end
if not start_event then return {} end
return start_event:searchEvents(eventType, n, func)
end

View File

@ -310,7 +310,7 @@ function Room:getPlayerById(id)
return nil
end
--- 将房间中的玩家按照座位顺序重新排序。
--- 将房间中的玩家按照行动顺序重新排序。
---@param playerIds integer[] @ 玩家id列表这个数组会被这个函数排序
function Room:sortPlayersByAction(playerIds, isTargetGroup)
table.sort(playerIds, function(prev, next)
@ -1273,19 +1273,12 @@ function Room:askForCard(player, minNum, maxNum, includeEquip, skillName, cancel
chosenCards = ret.cards
else
if cancelable then return {} end
local hands = player:getCardIds(Player.Hand)
if includeEquip then
table.insertTable(hands, player:getCardIds(Player.Equip))
end
local cards = player:getCardIds("he&")
local exp = Exppattern:Parse(pattern)
hands = table.filter(hands, function(cid)
cards = table.filter(cards, function(cid)
return exp:match(Fk:getCardById(cid))
end)
for _ = 1, minNum do
local randomId = hands[math.random(1, #hands)]
table.insert(chosenCards, randomId)
table.removeOne(hands, randomId)
end
chosenCards = table.random(cards, minNum)
end
return chosenCards
@ -2873,14 +2866,14 @@ function Room:drawCards(player, num, skillName, fromPlace)
end
--- 将一张或多张牌移动到某处
---@param card integer | Card | Card[] @ 要移动的牌
---@param card integer | integer[] | Card | Card[] @ 要移动的牌
---@param to_place integer @ 移动的目标位置
---@param target ServerPlayer @ 移动的目标玩家
---@param target? ServerPlayer @ 移动的目标角色
---@param reason? integer @ 移动时使用的移牌原因
---@param skill_name? string @ 技能名
---@param special_name? string @ 私人牌堆名
---@param visible? boolean @ 是否明置
---@param proposer? integer
---@param proposer? integer @ 移动操作者的id
function Room:moveCardTo(card, to_place, target, reason, skill_name, special_name, visible, proposer)
reason = reason or fk.ReasonJustMove
skill_name = skill_name or ""
@ -3268,10 +3261,15 @@ function Room:useSkill(player, skill, effect_cb)
player:revealBySkillName(skill.name)
if not skill.mute then
if skill.attached_equip then
local equip = Fk:cloneCard(skill.attached_equip)
local equip = Fk.all_card_types[skill.attached_equip]
local pkgPath = "./packages/" .. equip.package.extensionName
local soundName = pkgPath .. "/audio/card/" .. equip.name
self:broadcastPlaySound(soundName)
self:sendLog{
type = "#InvokeSkill",
from = player.id,
arg = skill.name,
}
self:setEmotion(player, pkgPath .. "/image/anim/" .. equip.name)
else
player:broadcastSkillInvoke(skill.name)

View File

@ -38,6 +38,7 @@ function ServerPlayer:initialize(_self)
self.reply_cancel = false
self.phases = {}
self.skipped_phases = {}
self.phase_state = {}
self._fake_skills = {}
self._manually_fake_skills = {}
@ -469,11 +470,13 @@ function ServerPlayer:changePhase(from_phase, to_phase)
return false
end
---@param phase Phase
---@param delay? boolean
function ServerPlayer:gainAnExtraPhase(phase, delay)
local room = self.room
delay = (delay == nil) and true or delay
local logic = room.logic
if delay then
local logic = room.logic
local turn = logic:getCurrentEvent():findParent(GameEvent.Phase, true)
if turn then
turn:prependExitFunc(function() self:gainAnExtraPhase(phase, false) end)
@ -482,16 +485,43 @@ function ServerPlayer:gainAnExtraPhase(phase, delay)
end
local current = self.phase
local phase_change = {
from = current,
to = phase
}
local skip = logic:trigger(fk.EventPhaseChanging, self, phase_change)
phase = phase_change.to
self.phase = phase
room:broadcastProperty(self, "phase")
room:sendLog{
type = "#GainAnExtraPhase",
from = self.id,
arg = phase_name_table[phase],
}
local cancel_skip = true
if phase ~= Player.NotActive and (skip) then
cancel_skip = logic:trigger(fk.EventPhaseSkipping, self)
end
if (not skip) or (cancel_skip) then
room:sendLog{
type = "#GainAnExtraPhase",
from = self.id,
arg = phase_name_table[phase],
}
GameEvent(GameEvent.Phase, self, self.phase):exec()
GameEvent(GameEvent.Phase, self, self.phase):exec()
phase_change = {
from = phase,
to = current
}
logic:trigger(fk.EventPhaseChanging, self, phase_change)
else
room:sendLog{
type = "#PhaseSkipped",
from = self.id,
arg = phase_name_table[phase],
}
end
self.phase = current
room:broadcastProperty(self, "phase")
@ -592,6 +622,7 @@ function ServerPlayer:endPlayPhase()
-- TODO: send log
end
---@param delay? boolean
function ServerPlayer:gainAnExtraTurn(delay)
local room = self.room
delay = (delay == nil) and true or delay
@ -624,10 +655,13 @@ function ServerPlayer:gainAnExtraTurn(delay)
room.current = current
end
--- 当前是否处于额外的回合。
--- @return boolean
function ServerPlayer:insideExtraTurn()
return self.tag["_extra_turn_count"] and #self.tag["_extra_turn_count"] > 0
end
--- 当前额外回合的技能原因。
---@return string
function ServerPlayer:getCurrentExtraTurnReason()
local ex_tag = self.tag["_extra_turn_count"]
@ -637,13 +671,18 @@ function ServerPlayer:getCurrentExtraTurnReason()
return ex_tag[#ex_tag]
end
--- 角色摸牌。
---@param num integer @ 摸牌数
---@param skillName? string @ 技能名
---@param fromPlace? string @ 摸牌的位置,"top" 或者 "bottom"
---@return integer[] @ 摸到的牌
function ServerPlayer:drawCards(num, skillName, fromPlace)
return self.room:drawCards(self, num, skillName, fromPlace)
end
---@param pile_name string
---@param card integer|Card
---@param visible boolean
---@param visible? boolean
---@param skillName? string
function ServerPlayer:addToPile(pile_name, card, visible, skillName)
local room = self.room
@ -923,13 +962,21 @@ function ServerPlayer:revealGeneral(isDeputy, no_trigger)
arg2 = generalName,
}
local data = {[isDeputy and "d" or "m"] = generalName}
room.logic:trigger(fk.GeneralShown, self, data)
if not no_trigger then
local current_event = room.logic:getCurrentEvent()
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.event) then
room.logic:trigger(fk.GeneralRevealed, self, {[isDeputy and "d" or "m"] = generalName})
room.logic:trigger(fk.GeneralRevealed, self, data)
else
if current_event.parent then
repeat
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.parent.event) then break end
current_event = current_event.parent
until (not current_event.parent)
end
current_event:addExitFunc(function ()
room.logic:trigger(fk.GeneralRevealed, self, {[isDeputy and "d" or "m"] = generalName})
room.logic:trigger(fk.GeneralRevealed, self, data)
end)
end
end
@ -940,11 +987,18 @@ function ServerPlayer:revealGenerals()
self:revealGeneral(true, true)
local room = self.room
local current_event = room.logic:getCurrentEvent()
local data = {["m"] = self:getMark("__heg_general"), ["d"] = self:getMark("__heg_deputy")}
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.event) then
room.logic:trigger(fk.GeneralRevealed, self, {["m"] = self:getMark("__heg_general"), ["d"] = self:getMark("__heg_deputy")})
room.logic:trigger(fk.GeneralRevealed, self, data)
else
if current_event.parent then
repeat
if table.contains({GameEvent.Round, GameEvent.Turn, GameEvent.Phase}, current_event.parent.event) then break end
current_event = current_event.parent
until (not current_event.parent)
end
current_event:addExitFunc(function ()
room.logic:trigger(fk.GeneralRevealed, self, {["m"] = self:getMark("__heg_general"), ["d"] = self:getMark("__heg_deputy")})
room.logic:trigger(fk.GeneralRevealed, self, data)
end)
end
end

View File

@ -3,27 +3,36 @@ return {
["thunder__slash"] = "Thunder Slash",
[":thunder__slash"] = "Thunder Slash (basic card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player within your ATK range<br /><b>Effect</b>: Deal 1 Thunder DMG to the targets.<br/><b>Note</b>: You can only use 1 Slash per action phase.",
["#thunder__slash_skill"] = "Choose 1 player within your ATK range, deal 1 Thunder DMG to him",
["#thunder__slash_skill_multi"] = "Choose up to %arg players within your ATK range. Deal 1 Thunder DMG to them",
["fire__slash"] = "Fire Slash",
[":fire__slash"] = "Fire Slash (basic card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player within your ATK range<br /><b>Effect</b>: Deal 1 Fire DMG to the targets.<br/><b>Note</b>: You can only use 1 Slash per action phase.",
["#fire__slash_skill"] = "Choose 1 player within your ATK range, deal 1 Fire DMG to him",
["#fire__slash_skill_multi"] = "Choose up to %arg players within your ATK range. Deal 1 Fire DMG to them",
["analeptic"] = "Alcohol",
[":analeptic"] = "Alcohol (basic card)<br /><b>Phase</b>: 1. Action phase 2. When you are dying<br /><b>Target</b>: Yourself<br /><b>Effect</b>: 1. the DMG of the next Slash you use this turn is increased by +1. (This effect can only be used once per turn) 2. You heal 1 HP.",
["#analeptic_skill"] = "the DMG of the next Slash you use this turn is increased by +1",
["iron_chain"] = "Iron Chain",
[":iron_chain"] = "Iron Chain (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: 1~2 players<br /><b>Effect</b>: Change chain state of the targets.",
["#iron_chain_skill"] = "Choose 1~2 players. Change their chain states",
["_normal_use"] = "Normally use",
["recast"] = "Recast",
[":recast"] = "Put this card into discard pile, then draw 1 card.",
["#recast"] = "Put this card into discard pile, then draw 1 card",
["fire_attack"] = "Fire Attack",
["fire_attack_skill"] = "Fire Attack",
[":fire_attack"] = "Fire Attack (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: A player with hand cards<br /><b>Effect</b>: That player shows 1 hand card; then, if you discard 1 card with the same suit, you deal 1 Fire DMG to him.",
[":fire_attack"] = "Fire Attack (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: A player with hand cards<br /><b>Effect</b>: The target player shows 1 hand card; then, if you discard 1 card with the same suit, you deal 1 Fire DMG to him.",
["#fire_attack-show"] = "%src used Fire Attack to you, please show 1 hand card",
["#fire_attack-discard"] = "You can discard 1 %arg hand card, then deal 1 Fire DMG to %src",
["#fire_attack_skill"] = "Choose a player with hand cards. He shows 1 hand card;<br />then, if you discard 1 card with the same suit, you deal 1 Fire DMG to him",
["supply_shortage"] = "Supply Shortage",
[":supply_shortage"] = "Supply Shortage (delayed trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player at distance 1<br /><b>Effect</b>: Place this card in target's judgement area. He performs a judgement in his judge phase: if result is not club, he skips his draw phase.",
[":supply_shortage"] = "Supply Shortage (delayed trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player at distance 1<br /><b>Effect</b>: Place this card in target's judgement area. He performs a judgement in his judge phase: if result is not ♣, he skips his draw phase.",
["#supply_shortage_skill"] = "Place this card in another player's judgement area. He performs a judgement in his judge phase:<br />If result is not ♣, he skips his draw phase",
["guding_blade"] = "Ancient Scimitar",
[":guding_blade"] = "Ancient Scimitar (equip card, weapon)<br /><b>ATK range</b>: 2<br /><b>Weapon skill</b>: When your used Slash is about to cause DMG, if the target player has no hand cards: the DMG is increased by +1.",

View File

@ -6,6 +6,19 @@ local slash = Fk:cloneCard("slash")
local thunderSlashSkill = fk.CreateActiveSkill{
name = "thunder__slash_skill",
prompt = function(self, selected_cards)
local card = Fk:cloneCard("thunder__slash")
card.subcards = Card:getIdList(selected_cards)
local max_num = self:getMaxTargetNum(Self, card)
if max_num > 1 then
local num = #table.filter(Fk:currentRoom().alive_players, function (p)
return p ~= Self and not Self:isProhibited(p, card)
end)
max_num = math.min(num, max_num)
end
card.subcards = {}
return max_num > 1 and "#thunder__slash_skill_multi:::" .. max_num or "#thunder__slash_skill"
end,
max_phase_use_time = 1,
target_num = 1,
can_use = slash.skill.canUse,
@ -45,6 +58,19 @@ extension:addCards{
local fireSlashSkill = fk.CreateActiveSkill{
name = "fire__slash_skill",
prompt = function(self, selected_cards)
local card = Fk:cloneCard("fire__slash")
card.subcards = Card:getIdList(selected_cards)
local max_num = self:getMaxTargetNum(Self, card)
if max_num > 1 then
local num = #table.filter(Fk:currentRoom().alive_players, function (p)
return p ~= Self and not Self:isProhibited(p, card)
end)
max_num = math.min(num, max_num)
end
card.subcards = {}
return max_num > 1 and "#fire__slash_skill_multi:::" .. max_num or "#fire__slash_skill"
end,
max_phase_use_time = 1,
target_num = 1,
can_use = slash.skill.canUse,
@ -80,8 +106,9 @@ extension:addCards{
local analepticSkill = fk.CreateActiveSkill{
name = "analeptic_skill",
prompt = "#analeptic_skill",
max_turn_use_time = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
mod_target_filter = function(self, to_select, _, _, card, _)
return self:withinTimesLimit(Fk:currentRoom():getPlayerById(to_select), Player.HistoryTurn, card, "analeptic", Fk:currentRoom():getPlayerById(to_select)) and
not table.find(Fk:currentRoom().alive_players, function(p)
return p.dying
@ -90,7 +117,7 @@ local analepticSkill = fk.CreateActiveSkill{
can_use = function(self, player, card)
return self:withinTimesLimit(player, Player.HistoryTurn, card, "analeptic", player)
end,
on_use = function(self, room, use)
on_use = function(_, _, use)
if not use.tos or #TargetGroup:getRealTargets(use.tos) == 0 then
use.tos = { { use.from } }
end
@ -99,7 +126,7 @@ local analepticSkill = fk.CreateActiveSkill{
use.extraUse = true
end
end,
on_effect = function(self, room, effect)
on_effect = function(_, room, effect)
local to = room:getPlayerById(effect.to)
if effect.extra_data and effect.extra_data.analepticRecover then
room:recover({
@ -120,7 +147,7 @@ local analepticEffect = fk.CreateTriggerSkill{
global = true,
priority = 0, -- game rule
events = { fk.PreCardUse, fk.EventPhaseStart },
can_trigger = function(self, event, target, player, data)
can_trigger = function(_, event, target, player, data)
if target ~= player then
return false
end
@ -131,7 +158,7 @@ local analepticEffect = fk.CreateTriggerSkill{
return target.phase == Player.NotActive
end
end,
on_trigger = function(self, event, target, player, data)
on_trigger = function(_, event, _, player, data)
local room = player.room
if event == fk.PreCardUse then
data.additionalDamage = (data.additionalDamage or 0) + player.drank
@ -168,8 +195,9 @@ extension:addCards({
local recast = fk.CreateActiveSkill{
name = "recast",
prompt = "#recast",
target_num = 0,
on_use = function(self, room, effect)
on_use = function(_, room, effect)
room:recastCard(effect.cards, room:getPlayerById(effect.from))
end
}
@ -177,17 +205,16 @@ Fk:addSkill(recast)
local ironChainCardSkill = fk.CreateActiveSkill{
name = "iron_chain_skill",
prompt = "#iron_chain_skill",
min_target_num = 1,
max_target_num = 2,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
mod_target_filter = Util.TrueFunc,
target_filter = function(self, to_select, selected, _, card)
if #selected < self:getMaxTargetNum(Self, card) then
return self:modTargetFilter(to_select, selected, Self.id, card)
end
end,
on_effect = function(self, room, cardEffectEvent)
on_effect = function(_, room, cardEffectEvent)
local to = room:getPlayerById(cardEffectEvent.to)
to:setChainState(not to.chained)
end,
@ -210,8 +237,9 @@ extension:addCards{
local fireAttackSkill = fk.CreateActiveSkill{
name = "fire_attack_skill",
prompt = "#fire_attack_skill",
target_num = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
mod_target_filter = function(_, to_select, _, _, _, _)
local to = Fk:currentRoom():getPlayerById(to_select)
return not to:isKongcheng()
end,
@ -256,8 +284,9 @@ extension:addCards{
local supplyShortageSkill = fk.CreateActiveSkill{
name = "supply_shortage_skill",
prompt = "#supply_shortage_skill",
distance_limit = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
mod_target_filter = function(self, to_select, _, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
local from = Fk:currentRoom():getPlayerById(user)
return from ~= player and not (distance_limited and not self:withinDistanceLimit(from, false, card, player))
@ -302,8 +331,8 @@ local gudingSkill = fk.CreateTriggerSkill{
attached_equip = "guding_blade",
frequency = Skill.Compulsory,
events = {fk.DamageCaused},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
can_trigger = function(self, _, target, player, data)
return target == player and player:hasSkill(self) and
data.to:isKongcheng() and data.card and data.card.trueName == "slash" and
not data.chain
end,
@ -326,8 +355,8 @@ local fanSkill = fk.CreateTriggerSkill{
name = "#fan_skill",
attached_equip = "fan",
events = { fk.AfterCardUseDeclared },
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.card.name == "slash"
can_trigger = function(self, _, target, player, data)
return target == player and player:hasSkill(self) and data.card.name == "slash"
end,
on_use = function(_, _, _, _, data)
local card = Fk:cloneCard("fire__slash")
@ -356,15 +385,15 @@ local vineSkill = fk.CreateTriggerSkill{
events = {fk.PreCardEffect, fk.DamageInflicted},
can_trigger = function(self, event, target, player, data)
if event == fk.DamageInflicted then
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
data.damageType == fk.FireDamage
end
local effect = data ---@type CardEffectEvent
return player.id == effect.to and player:hasSkill(self.name) and
return player.id == effect.to and player:hasSkill(self) and
(effect.card.name == "slash" or effect.card.name == "savage_assault" or
effect.card.name == "archery_attack")
end,
on_use = function(self, event, target, player, data)
on_use = function(_, event, _, player, data)
local room = player.room
if event == fk.DamageInflicted then
room:broadcastPlaySound("./packages/maneuvering/audio/card/vineburn")
@ -392,8 +421,8 @@ local silverLionSkill = fk.CreateTriggerSkill{
attached_equip = "silver_lion",
frequency = Skill.Compulsory,
events = {fk.DamageInflicted},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.damage > 1
can_trigger = function(self, _, target, player, data)
return target == player and player:hasSkill(self) and data.damage > 1
end,
on_use = function(_, _, _, _, data)
data.damage = 1
@ -456,31 +485,50 @@ Fk:loadTranslationTable{
["thunder__slash"] = "雷杀",
[":thunder__slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名角色<br /><b>效果</b>对目标角色造成1点雷电伤害。",
["#thunder__slash_skill"] = "选择攻击范围内的一名角色对其造成1点雷电伤害",
["#thunder__slash_skill_multi"] = "选择攻击范围内的至多%arg名角色对这些角色各造成1点雷电伤害",
["fire__slash"] = "火杀",
[":fire__slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名角色<br /><b>效果</b>对目标角色造成1点火焰伤害。",
["#fire__slash_skill"] = "选择攻击范围内的一名角色对其造成1点火焰伤害",
["#fire__slash_skill_multi"] = "选择攻击范围内的至多%arg名角色对这些角色各造成1点火焰伤害",
["analeptic"] = "",
[":analeptic"] = "基本牌<br /><b>时机</b>:出牌阶段/你处于濒死状态时<br /><b>目标</b>:你<br /><b>效果</b>:目标角色本回合使用的下一张【杀】将要造成的伤害+1/目标角色回复1点体力。",
["#analeptic_skill"] = "你于此回合内使用的下一张【杀】的伤害值基数+1",
["iron_chain"] = "铁锁连环",
[":iron_chain"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一至两名角色<br /><b>效果</b>:横置或重置目标角色的武将牌。",
["#iron_chain_skill"] = "选择一至两名角色,这些角色横置或重置",
["_normal_use"] = "正常使用",
["recast"] = "重铸",
[":recast"] = "你可以将此牌置入弃牌堆,然后摸一张牌。",
["#recast"] = "将此牌置入弃牌堆,然后摸一张牌",
["fire_attack"] = "火攻",
["fire_attack_skill"] = "火攻",
[":fire_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名有手牌的角色<br /><b>效果</b>:目标角色展示一张手牌,然后你可以弃置一张与所展示牌花色相同的手牌令其受到1点火焰伤害。",
[":fire_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名有手牌的角色<br /><b>效果</b>:目标角色展示一张手牌,然后你可以弃置一张与此牌花色相同的手牌对其造成1点火焰伤害。",
["#fire_attack-show"] = "%src 对你使用了火攻,请展示一张手牌",
["#fire_attack-discard"] = "你可弃置一张 %arg 手牌,对 %src 造成1点火属性伤害",
["#fire_attack_skill"] = "选择一名有手牌的角色,令其展示一张手牌,<br />然后你可以弃置一张与此牌花色相同的手牌对其造成1点火焰伤害",
["supply_shortage"] = "兵粮寸断",
[":supply_shortage"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>距离1的一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为梅花,其跳过摸牌阶段。然后将【兵粮寸断】置入弃牌堆。",
[":supply_shortage"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>距离1的一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为♣,其跳过摸牌阶段。然后将【兵粮寸断】置入弃牌堆。",
["#supply_shortage_skill"] = "选择距离1的一名角色将此牌置于其判定区内。其判定阶段判定<br />若结果不为♣,其跳过摸牌阶段",
["guding_blade"] = "古锭刀",
[":guding_blade"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技。每当你使用【杀】对目标角色造成伤害时,若该角色没有手牌,此伤害+1。",
["fan"] = "朱雀羽扇",
[":fan"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:你可以将一张普通【杀】当火【杀】使用。",
["#fan_skill"] = "朱雀羽扇",
["vine"] = "藤甲",
[":vine"] = "装备牌·防具<br /><b>防具技能</b>:锁定技。【南蛮入侵】、【万箭齐发】和普通【杀】对你无效。每当你受到火焰伤害时,此伤害+1。",
["silver_lion"] = "白银狮子",
[":silver_lion"] = "装备牌·防具<br /><b>防具技能</b>锁定技。每当你受到伤害时若此伤害大于1点防止多余的伤害。每当你失去装备区里的【白银狮子】后你回复1点体力。",
["hualiu"] = "骅骝",
[":hualiu"] = "装备牌·坐骑<br /><b>坐骑技能</b>:其他角色与你的距离+1。",
}

View File

@ -15,8 +15,8 @@ Fk:loadTranslationTable({
["jianxiong"] = "Villainous Hero",
[":jianxiong"] = "After you suffer DMG: you can take the card(s) that caused it.",
["hujia"] = "Royal Escort",
[":hujia"] = "<b>Lord skill</b>, when you need to use/play Dodge: you can ask other Wei characters to play Dodge, which is regard as you use/play that.",
["#hujia-ask"] = "Royal Escort: you can play a jink, which is regarded as %src uses/plays",
[":hujia"] = "(lord) When you need to use/play Dodge: you can ask other Wei characters to play Dodge, which is regard as you use/play that.",
["#hujia-ask"] = "Royal Escort: you can play a Dodge, which is regarded as %src uses/plays",
["simayi"] = "Sima Yi",
["guicai"] = "Demonic Talent",
@ -57,7 +57,7 @@ Fk:loadTranslationTable({
["rende"] = "Benevolence",
[":rende"] = "In your Action Phase: you can give any # of hand cards to other players; then, if you have given a total of 2 or more cards, you heal 1 HP (only once).",
["jijiang"] = "Rouse",
[":jijiang"] = "<b>Lord skill</b>, when you need to use/play Slash: you can ask other Shu characters to play Slash, which is regard as you use/play that.",
[":jijiang"] = "(lord) When you need to use/play Slash: you can ask other Shu characters to play Slash, which is regard as you use/play that.",
["#jijiang-ask"] = "Rouse: you can play a Slash, which is regarded as %src uses/plays",
["guanyu"] = "Guan Yu",
@ -66,13 +66,13 @@ Fk:loadTranslationTable({
["zhangfei"] = "Zhang Fei",
["paoxiao"] = "Roar",
[":paoxiao"] = "<b>Compulsory skill</b>, you can use any # of Slash.",
[":paoxiao"] = "(forced) You can use any # of Slash.",
["zhugeliang"] = "Zhuge Liang",
["guanxing"] = "Stargaze",
[":guanxing"] = "In your Beginning Phase: you can examine X cards from the deck; then, you can place any # of them at the top of the deck and the rest at the bottom. (X = # of living players, max. 5)",
["kongcheng"] = "Empty Fort",
[":kongcheng"] = "<b>Compulsory skill</b>, if you dont have hand cards, you cannot be the target of Sha or Duel.",
[":kongcheng"] = "(forced) If you dont have hand cards, you cannot be the target of Sha or Duel.",
["zhaoyun"] = "Zhao Yun",
["longdan"] = "Dragon Heart",
@ -80,7 +80,7 @@ Fk:loadTranslationTable({
["machao"] = "Ma Chao",
["mashu"] = "Horsemanship",
[":mashu"] = "<b>Compulsory skill</b>, the distance from you to other players is reduced by -1.",
[":mashu"] = "(forced) The distance from you to other players is reduced by -1.",
["tieqi"] = "Iron Cavalry",
[":tieqi"] = "After you use Slash to target a player: you can perform a judgment; if its red, he can't use Dodge.",
@ -88,19 +88,19 @@ Fk:loadTranslationTable({
["jizhi"] = "Wisdom",
[":jizhi"] = "When you use a non-delay trick card, you can draw 1 card.",
["qicai"] = "Genius",
[":qicai"] = "<b>Compulsory skill</b>, your trick cards have unlimited range.",
[":qicai"] = "(forced) Your trick cards have unlimited range.",
["sunquan"] = "Sun Quan",
["zhiheng"] = "Balance of Power",
[":zhiheng"] = "Once per Action Phase: you can discard any # of cards; then, draw the same # of cards.",
["jiuyuan"] = "Rescued",
[":jiuyuan"] = "<b>Lord skill, compulsory skill</b>, when another Wu character uses Peach to you, you heal +1 HP.",
[":jiuyuan"] = "(lord, forced) When another Wu character uses Peach to you, you heal +1 HP.",
["ganning"] = "Gan Ning",
["qixi"] = "Surprise Raid",
[":qixi"] = "You can use any black card as Dismantlement.",
["lvmeng"] = "Lv Meng",
["lvmeng"] = "Lü Meng",
["keji"] = "Self Mastery",
[":keji"] = "If you haven't used/played Slash in your Action Phase, you can skip your Discard Phase.",
@ -123,7 +123,7 @@ Fk:loadTranslationTable({
["luxun"] = "Lu Xun",
["qianxun"] = "Humility",
[":qianxun"] = "<b>Compulsory skill</b>, you can't be the target of Snatch or Indulgence.",
[":qianxun"] = "(forced) You can't be the target of Snatch or Indulgence.",
["lianying"] = "One After Another",
[":lianying"] = "When you lose your last hand card: you can draw 1 card.",
@ -139,9 +139,9 @@ Fk:loadTranslationTable({
["jijiu"] = "First Aid",
[":jijiu"] = "Outside of your turn: you can use any red card as Peach.",
["lvbu"] = "Lv Bu",
["lvbu"] = "Lü Bu",
["wushuang"] = "Without Equal",
[":wushuang"] = "<b>Compulsory skill</b>, if you use Slash to target a player, the target needs to use 2 Dodge to evade it. During Duel, the opponent must play 2 Slash per round.",
[":wushuang"] = "(forced) If you use Slash to target a player, the target needs to use 2 Dodge to evade it. During Duel, the opponent must play 2 Slash per round.",
["diaochan"] = "Diao Chan",
["lijian"] = "Seed of Animosity",
@ -199,7 +199,17 @@ Fk:loadTranslationTable({
["choose_players_to_move_card_in_board"] = "Choose players",
["reveal_skill"] = "Reveal",
["#reveal_skill"] = "Choose a character to reveal",
[":reveal_skill"] = "In action phase, you can reveal a character who has Compulsory skills.",
[":reveal_skill"] = "In action phase, you can reveal a character who has Forced skills.",
["game_rule"] = "Discard",
}, "en_US")
-- init
Fk:loadTranslationTable({
["left lord and loyalist alive"] = "You're the only surviving Renegade and all others alive are lord and loyalists.",
["left one rebel alive"] = "You're the only surviving Rebel and there's no surviving Renegade.",
["left you alive"] = "No surviving loyalists and only another fraction remains.",
["loyalist never surrender"] = "Loyalist never surrender!",
["anjiang"] = "Hidden Char.",
}, "en_US")

View File

@ -55,7 +55,7 @@ Fk:loadTranslationTable{
["$luoyi1"] = "脱!",
["$luoyi2"] = "谁来与我大战三百回合?",
["luoyi"] = "裸衣",
[":luoyi"] = "摸牌阶段,你可以少摸一张牌,若如此做,本回合你使用【杀】或【决斗】对目标角色造成伤害时,此伤害+1。",
[":luoyi"] = "摸牌阶段,你可以少摸一张牌,然后本回合你使用【杀】或【决斗】对目标角色造成伤害时,此伤害+1。",
["guojia"] = "郭嘉",
["~guojia"] = "咳,咳……",
@ -66,7 +66,7 @@ Fk:loadTranslationTable{
["$yiji1"] = "也好。",
["$yiji2"] = "罢了。",
["yiji"] = "遗计",
[":yiji"] = "当你受到1点伤害后你可以观看牌堆顶的两张牌并任意分配它们。",
[":yiji"] = "当你受到1点伤害后你可以观看牌堆顶的两张牌并任意分配它们。",
["yiji_active"] = "遗计",
["#yiji-give"] = "遗计:你可以将这些牌分配给任意角色,点“取消”自己保留",
@ -75,7 +75,7 @@ Fk:loadTranslationTable{
["$luoshen1"] = "髣髴兮若轻云之蔽月。",
["$luoshen2"] = "飘飖兮若流风之回雪。",
["luoshen"] = "洛神",
[":luoshen"] = "准备阶段开始时,你可以进行判定:若结果为黑色,判定牌生效后你获得之,然后你可以再次发动“洛神”",
[":luoshen"] = "准备阶段开始时,你可以进行判定:若结果为黑色,判定牌生效后你获得之,然后你可以重复此流程",
["#luoshen_obtain"] = "洛神",
["$qingguo1"] = "凌波微步,罗袜生尘。",
["$qingguo2"] = "体迅飞凫,飘忽若神。",
@ -129,27 +129,27 @@ Fk:loadTranslationTable{
["machao"] = "马超",
["~machao"] = "(马蹄远去声)",
["mashu"] = "马术",
[":mashu"] = "锁定技你与其他角色的距离-1。",
[":mashu"] = "锁定技你与其他角色的距离-1。",
["$tieqi1"] = "全军突击!",
["$tieqi2"] = "(马蹄、马嘶声)",
["tieqi"] = "铁骑",
[":tieqi"] = "当你指定【杀】的目标后,你可以进行判定:若结果为红色,该角色不能使用【闪】响应此【杀】。",
[":tieqi"] = "当你指定【杀】的目标后,你可以进行判定:若结果为红色,该角色不能使用【闪】响应此【杀】。",
["huangyueying"] = "黄月英",
["~huangyueying"] = "亮……",
["$jizhi1"] = "哼哼~",
["$jizhi2"] = "哼~",
["jizhi"] = "集智",
[":jizhi"] = "每当你使用一张非延时锦囊牌时,你可以摸一张牌。",
[":jizhi"] = "当你使用非转化的普通锦囊牌时,你可摸一张牌。",
["qicai"] = "奇才",
[":qicai"] = "锁定技你使用锦囊牌无距离限制。",
[":qicai"] = "锁定技你使用锦囊牌无距离限制。",
["sunquan"] = "孙权",
["~sunquan"] = "父亲,大哥,仲谋愧矣……",
["$zhiheng1"] = "容我三思。",
["$zhiheng2"] = "且慢。",
["zhiheng"] = "制衡",
[":zhiheng"] = "阶段技,你可以弃置至少一张牌然后摸等量的牌。",
[":zhiheng"] = "出牌阶段限一次,你可以弃置至少一张牌然后摸等量的牌。",
["$jiuyuan1"] = "有汝辅佐,甚好!",
["$jiuyuan2"] = "好舒服啊。",
["jiuyuan"] = "救援",
@ -196,7 +196,7 @@ Fk:loadTranslationTable{
["$liuli1"] = "交给你了。",
["$liuli2"] = "你来嘛~",
["liuli"] = "流离",
[":liuli"] = "当你成为【杀】的目标时,你可以弃置一张牌并选择你攻击范围内为此【杀】合法目标(无距离限制)的一名角色:若如此做,该角色代替你成为此【杀】的目标。",
[":liuli"] = "当你成为【杀】的目标时,你可以弃置一张牌并选择你攻击范围内为此【杀】合法目标(无距离限制)的一名角色:若如此做,该角色代替你成为此【杀】的目标。",
["#liuli-target"] = "流离:你可以弃置一张牌,将【杀】的目标转移给一名其他角色",
["luxun"] = "陆逊",
@ -208,25 +208,25 @@ Fk:loadTranslationTable{
["$lianying1"] = "牌不是万能的,但是没牌是万万不能的。",
["$lianying2"] = "旧的不去,新的不来。",
["lianying"] = "连营",
[":lianying"] = "当你失去最后的手牌后,你可以摸一张牌。",
[":lianying"] = "当你失去最后的手牌后,你可以摸一张牌。",
["sunshangxiang"] = "孙尚香",
["~sunshangxiang"] = "不,还不可以死……",
["$xiaoji1"] = "哼!",
["$xiaoji2"] = "看我的厉害!",
["xiaoji"] = "枭姬",
[":xiaoji"] = "当你失去一张装备区的装备牌后,你可以摸两张牌。",
[":xiaoji"] = "当你失去一张装备区的装备牌后,你可以摸两张牌。",
["$jieyin1"] = "夫君,身体要紧。",
["$jieyin2"] = "他好,我也好。",
["jieyin"] = "结姻",
[":jieyin"] = "阶段技你可以弃置两张手牌并选择一名已受伤的男性角色若如此做你和该角色各回复1点体力。",
[":jieyin"] = "出牌阶段限一次你可以弃置两张手牌并选择一名已受伤的男性角色若如此做你和该角色各回复1点体力。",
["huatuo"] = "华佗",
["~huatuo"] = "医者……不能自医啊……",
["$qingnang1"] = "早睡早起,方能养生。",
["$qingnang2"] = "越老越要补啊。",
["qingnang"] = "青囊",
[":qingnang"] = "阶段技你可以弃置一张手牌并选择一名已受伤的角色若如此做该角色回复1点体力。",
[":qingnang"] = "出牌阶段限一次你可以弃置一张手牌并选择一名已受伤的角色若如此做该角色回复1点体力。",
["$jijiu1"] = "别紧张,有老夫呢。",
["$jijiu2"] = "救人一命,胜造七级浮屠。",
["jijiu"] = "急救",
@ -244,7 +244,7 @@ Fk:loadTranslationTable{
["$lijian1"] = "嗯呵呵~~呵呵~~",
["$lijian2"] = "夫君,你要替妾身作主啊……",
["lijian"] = "离间",
[":lijian"] = "阶段技,你可以弃置一张牌并选择两名其他男性角色,后选择的角色视为对先选择的角色使用了一张不能被无懈可击的决斗。",
[":lijian"] = "出牌阶段限一次,你可以弃置一张牌并选择两名其他男性角色,后选择的角色视为对先选择的角色使用了一张不能被无懈可击的决斗。",
["$biyue1"] = "失礼了~",
["$biyue2"] = "羡慕吧~",
["biyue"] = "闭月",

View File

@ -10,7 +10,7 @@ local jianxiong = fk.CreateTriggerSkill{
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
if target == player and player:hasSkill(self.name) and data.card then
if target == player and player:hasSkill(self) and data.card then
local room = player.room
local subcards = data.card:isVirtual() and data.card.subcards or {data.card.id}
return #subcards>0 and table.every(subcards, function(id) return room:getCardArea(id) == Card.Processing end)
@ -78,7 +78,7 @@ local guicai = fk.CreateTriggerSkill{
anim_type = "control",
events = {fk.AskForRetrial},
can_trigger = function(self, event, target, player, data)
return player:hasSkill(self.name) and not player:isKongcheng()
return player:hasSkill(self) and not player:isKongcheng()
end,
on_cost = function(self, event, target, player, data)
local room = player.room
@ -98,7 +98,7 @@ local fankui = fk.CreateTriggerSkill{
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
if target == player and player:hasSkill(self.name) and data.from and not data.from.dead then
if target == player and player:hasSkill(self) and data.from and not data.from.dead then
if data.from == player then
return #player.player_cards[Player.Equip] > 0
else
@ -122,9 +122,6 @@ local ganglie = fk.CreateTriggerSkill{
name = "ganglie",
anim_type = "masochism",
events = {fk.Damaged},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name)
end,
on_use = function(self, event, target, player, data)
local room = player.room
local from = data.from
@ -156,13 +153,13 @@ local tuxi = fk.CreateTriggerSkill{
anim_type = "control",
events = {fk.EventPhaseStart},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and player.phase == Player.Draw and
return target == player and player:hasSkill(self) and player.phase == Player.Draw and
table.find(player.room:getOtherPlayers(player), function(p) return not p:isKongcheng() end)
end,
on_cost = function(self, event, target, player, data)
local room = player.room
local targets = table.map(table.filter(room:getOtherPlayers(player), function(p)
return not p:isKongcheng() end), function (p) return p.id end)
return not p:isKongcheng() end), Util.IdMapper)
local result = room:askForChoosePlayers(player, targets, 1, 2, "#tuxi-ask", self.name)
if #result > 0 then
@ -191,7 +188,7 @@ local luoyi = fk.CreateTriggerSkill{
anim_type = "offensive",
events = {fk.DrawNCards},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.n > 0
return target == player and player:hasSkill(self) and data.n > 0
end,
on_use = function(self, event, target, player, data)
data.n = data.n - 1
@ -205,9 +202,7 @@ local luoyi_trigger = fk.CreateTriggerSkill{
return target == player and player:usedSkillTimes("luoyi", Player.HistoryTurn) > 0 and
not data.chain and data.card and (data.card.trueName == "slash" or data.card.name == "duel")
end,
on_cost = function(self, event, target, player, data)
return true
end,
on_cost = Util.TrueFunc,
on_use = function(self, event, target, player, data)
local room = player.room
player:broadcastSkillInvoke("luoyi")
@ -224,7 +219,7 @@ local tiandu = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.FinishJudge},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and player.room:getCardArea(data.card) == Card.Processing
return target == player and player:hasSkill(self) and player.room:getCardArea(data.card) == Card.Processing
end,
on_use = function(self, event, target, player, data)
player.room:obtainCard(player.id, data.card, true, fk.ReasonJustMove)
@ -332,7 +327,7 @@ local luoshen = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.EventPhaseStart},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and player.phase == Player.Start
return target == player and player:hasSkill(self) and player.phase == Player.Start
end,
on_use = function(self, event, target, player, data)
local room = player.room
@ -419,9 +414,7 @@ local jijiang = fk.CreateViewAsSkill{
name = "jijiang$",
anim_type = "offensive",
pattern = "slash",
card_filter = function(self, to_select, selected)
return false
end,
card_filter = Util.FalseFunc,
view_as = function(self, cards)
if #cards ~= 0 then
return nil
@ -517,7 +510,7 @@ local paoxiaoAudio = fk.CreateTriggerSkill{
visible = false,
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
data.card.trueName == "slash" and
player:usedCardTimes("slash") > 1
end,
@ -534,7 +527,7 @@ local paoxiao = fk.CreateTargetModSkill{
name = "paoxiao",
frequency = Skill.Compulsory,
bypass_times = function(self, player, skill, scope)
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
if player:hasSkill(self) and skill.trueName == "slash_skill"
and scope == Player.HistoryPhase then
return true
end
@ -549,7 +542,7 @@ local guanxing = fk.CreateTriggerSkill{
anim_type = "control",
events = {fk.EventPhaseStart},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
player.phase == Player.Start
end,
on_use = function(self, event, target, player, data)
@ -561,7 +554,7 @@ local kongchengAudio = fk.CreateTriggerSkill{
name = "#kongchengAudio",
refresh_events = {fk.AfterCardsMove},
can_refresh = function(self, event, target, player, data)
if not player:hasSkill(self.name) then return end
if not player:hasSkill(self) then return end
if not player:isKongcheng() then return end
for _, move in ipairs(data) do
if move.from == player.id then
@ -582,7 +575,7 @@ local kongcheng = fk.CreateProhibitSkill{
name = "kongcheng",
frequency = Skill.Compulsory,
is_prohibited = function(self, from, to, card)
if to:hasSkill(self.name) and to:isKongcheng() then
if to:hasSkill(self) and to:isKongcheng() then
return card.trueName == "slash" or card.trueName == "duel"
end
end,
@ -631,7 +624,7 @@ local mashu = fk.CreateDistanceSkill{
name = "mashu",
frequency = Skill.Compulsory,
correct_func = function(self, from, to)
if from:hasSkill(self.name) then
if from:hasSkill(self) then
return -1
end
end,
@ -641,7 +634,7 @@ local tieqi = fk.CreateTriggerSkill{
anim_type = "offensive",
events = {fk.TargetSpecified},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
data.card.trueName == "slash"
end,
on_use = function(self, event, target, player, data)
@ -666,7 +659,7 @@ local jizhi = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.CardUsing},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and data.card:isCommonTrick() and
return target == player and player:hasSkill(self) and data.card:isCommonTrick() and
(not data.card:isVirtual() or #data.card.subcards == 0)
end,
on_use = function(self, event, target, player, data)
@ -677,7 +670,7 @@ local qicai = fk.CreateTargetModSkill{
name = "qicai",
frequency = Skill.Compulsory,
bypass_distances = function(self, player, skill, card)
return player:hasSkill(self.name) and card and card.type == Card.TypeTrick
return player:hasSkill(self) and card and card.type == Card.TypeTrick
end,
}
local huangyueying = General:new(extension, "huangyueying", "shu", 3, 3, General.Female)
@ -690,11 +683,11 @@ local zhiheng = fk.CreateActiveSkill{
can_use = function(self, player)
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
card_filter = function(self, to_select, selected)
return not Self:prohibitDiscard(Fk:getCardById(to_select))
end,
target_num = 0,
min_card_num = 1,
card_filter = function(self, to_select)
return not Self:prohibitDiscard(Fk:getCardById(to_select))
end,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
room:throwCard(effect.cards, self.name, from, from)
@ -712,7 +705,7 @@ local jiuyuan = fk.CreateTriggerSkill{
can_trigger = function(self, event, target, player, data)
return
target == player and
player:hasSkill(self.name) and
player:hasSkill(self) and
data.card and
data.card.trueName == "peach" and
data.recoverBy and
@ -754,7 +747,7 @@ local keji = fk.CreateTriggerSkill{
anim_type = "defensive",
events = {fk.EventPhaseChanging},
can_trigger = function(self, event, target, player, data)
if target == player and player:hasSkill(self.name) and data.to == Player.Discard then
if target == player and player:hasSkill(self) and data.to == Player.Discard then
local room = player.room
local logic = room.logic
local e = logic:getCurrentEvent():findParent(GameEvent.Turn, true)
@ -866,7 +859,7 @@ local liuli = fk.CreateTriggerSkill{
anim_type = "defensive",
events = {fk.TargetConfirming},
can_trigger = function(self, event, target, player, data)
local ret = target == player and player:hasSkill(self.name) and
local ret = target == player and player:hasSkill(self) and
data.card.trueName == "slash"
if ret then
local room = player.room
@ -912,7 +905,7 @@ local qianxun = fk.CreateProhibitSkill{
name = "qianxun",
frequency = Skill.Compulsory,
is_prohibited = function(self, from, to, card)
if to:hasSkill(self.name) then
if to:hasSkill(self) then
return card.name == "indulgence" or card.name == "snatch"
end
end,
@ -922,7 +915,7 @@ local lianying = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.AfterCardsMove},
can_trigger = function(self, event, target, player, data)
if not player:hasSkill(self.name) then return end
if not player:hasSkill(self) then return end
if not player:isKongcheng() then return end
for _, move in ipairs(data) do
if move.from == player.id then
@ -947,7 +940,7 @@ local xiaoji = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.AfterCardsMove},
can_trigger = function(self, event, target, player, data)
if not player:hasSkill(self.name) then return end
if not player:hasSkill(self) then return end
for _, move in ipairs(data) do
if move.from == player.id then
for _, info in ipairs(move.moveInfo) do
@ -992,7 +985,7 @@ local jieyin = fk.CreateActiveSkill{
return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
end,
card_filter = function(self, to_select, selected)
return #selected < 2 and Fk:currentRoom():getCardArea(to_select) == Player.Hand
return #selected < 2 and Fk:currentRoom():getCardArea(to_select) == Player.Hand and not Self:prohibitDiscard(Fk:getCardById(to_select))
end,
target_filter = function(self, to_select, selected)
local target = Fk:currentRoom():getPlayerById(to_select)
@ -1090,7 +1083,7 @@ local wushuang = fk.CreateTriggerSkill{
frequency = Skill.Compulsory,
events = {fk.TargetSpecified, fk.TargetConfirmed},
can_trigger = function(self, event, target, player, data)
if not player:hasSkill(self.name) then
if not player:hasSkill(self) then
return false
end
@ -1150,7 +1143,7 @@ local biyue = fk.CreateTriggerSkill{
anim_type = "drawcard",
events = {fk.EventPhaseStart},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name)
return target == player and player:hasSkill(self)
and player.phase == Player.Finish
end,
on_use = function(self, event, target, player, data)
@ -1346,7 +1339,7 @@ local role_mode = fk.CreateGameMode{
}
extension:addGameMode(role_mode)
Fk:loadTranslationTable{
["time limitation: 5 sec"] = "游戏时长达到5秒测试用",
["time limitation: 5 min"] = "游戏时长达到5分钟",
["left lord and loyalist alive"] = "仅剩你和主忠方存活",
["left one rebel alive"] = "反贼仅剩你存活且不存在存活内奸",
["left you alive"] = "主忠方仅剩你存活且其他阵营仅剩一方",

View File

@ -28,7 +28,9 @@ Fk:loadTranslationTable({
-- ["weapon"] = "武器牌",
-- ["armor"] = "防具牌",
["defensive_horse"] = "+1 horse",
["defensive_ride"] = "+1 horse",
["offensive_horse"] = "-1 horse",
["offensive_ride"] = "-1 horse",
["equip_horse"] = "horse",
-- ["treasure"] = "宝物牌",
["delayed_trick"] = "delayed trick",
@ -50,53 +52,67 @@ Fk:loadTranslationTable({
["slash"] = "Slash",
[":slash"] = "Slash (basic card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player within your ATK range<br /><b>Effect</b>: Deal 1 DMG to the targets.<br/><b>Note</b>: You can only use 1 Slash per action phase.",
["#slash-jink"] = "%src used Slash to you, please use %arg Dodge(s)",
["#slash_skill"] = "Choose 1 player within your ATK range, deal 1 DMG to him",
["#slash_skill_multi"] = "Choose up to %arg players within your ATK range. Deal 1 DMG to them",
["jink"] = "Dodge",
[":jink"] = "Dodge (basic card)<br /><b>Phase</b>: When Slash is about to effect on you<br /><b>Target</b>: This Slash<br /><b>Effect</b>: Counter the target Slash.",
["peach"] = "Peach",
[":peach"] = "Peach (basic card)<br /><b>Phase</b>: 1. Action phase 2. When a player is dying<br /><b>Target</b>: Wounded yourself/the player who is dying<br /><b>Effect</b>: The target heals 1 HP.",
["#peach_skill"] = "You heal 1 HP",
["dismantlement"] = "Dismantlement",
[":dismantlement"] = "Dismantlement (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player with cards in any area<br /><b>Effect</b>: Discard 1 card in one of the areas of the target player.",
["dismantlement_skill"] = "Dismantlement",
["#dismantlement_skill"] = "Choose another player with cards in any area. Discard 1 card in one of his areas",
["snatch"] = "Snatch",
[":snatch"] = "Snatch (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player at distance 1 with cards in any area<br /><b>Effect</b>: Take 1 card in one of the areas of the target player.",
[":snatch"] = "Snatch (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player at distance 1 with cards in any area<br /><b>Effect</b>: Take 1 card in one of the areas of the target player.",
["snatch_skill"] = "Snatch",
["#snatch_skill"] = "Choose another player at distance 1 with cards in any area. Take 1 card in one of his areas",
["duel"] = "Duel",
[":duel"] = "Duel (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player<br /><b>Effect</b>: In turns (starting with the target player), both of you play Slash successively. The first player who doesn't play Slash suffers 1 DMG from the other player.",
["#duel_skill"] = "Choose another player. In turns (starting with the target player), both of you play Slash successively.<br />The first player who doesn't play Slash suffers 1 DMG from the other player",
["collateral"] = "Collateral",
[":collateral"] = "Collateral (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player with an equipped weapon (Player A)<br /><b>Sub-target</b>: A player within Player A's ATK range (Player B)<br /><b>Effect</b>: Unless A uses Slash to B, he gives you his equipped weapon.",
["#collateral-slash"] = "Collateral: You shall use Slash to %dest , or %src takes your weapon",
["#collateral-slash"] = "Collateral: You shall use Slash to %dest , or give your weapon to %src",
["#collateral_skill"] = "Choose another player with an equipped weapon (Player A),<br />then choose another player within Player A's ATK range (Player B).<br />Unless A uses Slash to B, he gives you his equipped weapon",
["ex_nihilo"] = "Ex Nihilo",
[":ex_nihilo"] = "Ex Nihilo (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Yourself<br /><b>Effect</b>: The target draws 2 cards.",
["#ex_nihilo_skill"] = "You draw 2 cards",
["nullification"] = "Nullification",
[":nullification"] = "Nullification (trick card)<br /><b>Phase</b>: When a trick card is about to take effect (including Nullification itself)<br /><b>Target</b>: This trick card<br /><b>Effect</b>: Counter the target trick card.",
["savage_assault"] = "Savage Assault",
[":savage_assault"] = "Savage Assault (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: All other players<br /><b>Effect</b>: Each target player needs to play Slash, otherwise they suffer 1 DMG from you.",
["#savage_assault_skill"] = "Each other players needs to play Slash, otherwise they suffer 1 DMG from you",
["archery_attack"] = "Archery Attack",
[":archery_attack"] = "Archery Attack (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: All other players<br /><b>Effect</b>: Each target player needs to play Dodge, otherwise they suffer 1 DMG from you.",
["#archery_attack_skill"] = "Each other players needs to play Dodge, otherwise they suffer 1 DMG from you",
["god_salvation"] = "God Salvation",
[":god_salvation"] = "God Salvation (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: All players<br /><b>Effect</b>: Each target player heals 1 HP.",
["#god_salvation_skill"] = "Each players heals 1 HP",
["amazing_grace"] = "Amazing Grace",
[":amazing_grace"] = "Amazing Grace (trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: All players<br /><b>Effect</b>: Reveal as many cards from the draw pile as target players; then, each target player takes 1 of those cards.",
["amazing_grace_skill"] = "AG",
["Please choose cards"] = "Please choose a card",
["#amazing_grace_skill"] = "Reveal as many cards from the draw pile as all players;<br />then, each player takes 1 of those cards",
["lightning"] = "Lightning",
[":lightning"] = "Lightning (delayed trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Yourself<br /><b>Effect</b>: Place this card in target's judgement area. He performs a judgement in his judge phase: If the judgement result is 2-9♠, he suffers 3 Thunder DMG, otherwise move Lightning to his next player's judgement area.",
["#lightning_skill"] = "Place this card in your judgement area. Target player performs a judgement in his judge phase:<br />If the judgement result is 2-9♠, he suffers 3 Thunder DMG, otherwise move Lightning to his next player's judgement area",
["indulgence"] = "Indulgence",
[":indulgence"] = "Indulgence (delayed trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player<br /><b>Effect</b>: Place this card in target's judgement area. He performs a judgement in his judge phase: if result is not heart, he skips his action phase.",
[":indulgence"] = "Indulgence (delayed trick card)<br /><b>Phase</b>: Action phase<br /><b>Target</b>: Another player<br /><b>Effect</b>: Place this card in target's judgement area. He performs a judgement in his judge phase: if result is not <font color='#CC3131'>♥</font>, he skips his action phase.",
["#indulgence_skill"] = "Place this card in another player's judgement area. He performs a judgement in his judge phase:<br />If result is not <font color='#CC3131'>♥</font>, he skips his action phase",
["crossbow"] = "Crossbow",
[":crossbow"] = "Crossbow (equip card, weapon)<br /><b>ATK range</b>: 1<br /><b>Weapon skill</b>: You can use any amount of Slash in your action phase.",
@ -122,6 +138,7 @@ Fk:loadTranslationTable({
[":spear"] = "Spear (equip card, weapon)<br /><b>ATK range</b>: 3<br /><b>Weapon skill</b>: You can use/play 2 hand cards as Slash.",
["spear_skill"] = "Spear",
[":spear_skill"] = "You can use/play 2 hand cards as Slash.",
["#spear_skill"] = "You can use/play 2 hand cards as Slash",
["axe"] = "Axe",
[":axe"] = "Axe (equip card, weapon)<br /><b>ATK range</b>: 3<br /><b>Weapon skill</b>: When your used Slash is countered by Dodge, you can discard 2 cards (except equipped Axe), then make this Slash still effective to the target.",
@ -159,4 +176,6 @@ Fk:loadTranslationTable({
["zixing"] = "Zi Xing",
[":zixing"] = "Zi Xing (equip card, horse)<br /><b>Horse skill</b>: The distance from you to other players is reduced by -1.",
["#default_equip_skill"] = "Equip %arg2 %arg",
}, "en_US")

View File

@ -28,7 +28,9 @@ Fk:loadTranslationTable{
["weapon"] = "武器牌",
["armor"] = "防具牌",
["defensive_horse"] = "防御坐骑牌",
["defensive_ride"] = "防御坐骑牌",
["offensive_horse"] = "进攻坐骑牌",
["offensive_ride"] = "进攻坐骑牌",
["equip_horse"] = "坐骑牌",
["treasure"] = "宝物牌",
["delayed_trick"] = "延时类锦囊牌",
@ -48,73 +50,87 @@ Fk:loadTranslationTable{
["method_discard"] = "弃置",
["slash"] = "",
[":slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名其他角色<br /><b>效果</b>对目标角色造成1点伤害。",
[":slash"] = "基本牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:攻击范围内的一名角色<br /><b>效果</b>对目标角色造成1点伤害。",
["#slash-jink"] = "%src 对你使用了杀,请使用 %arg 张闪",
["#slash_skill"] = "选择攻击范围内的一名角色对其造成1点伤害",
["#slash_skill_multi"] = "选择攻击范围内的至多%arg名角色对这些角色各造成1点伤害",
["jink"] = "",
[":jink"] = "基本牌<br /><b>时机</b>:【杀】对你生效时<br /><b>目标</b>:此【杀】<br /><b>效果</b>:抵消此【杀】的效果。",
["peach"] = "",
[":peach"] = "基本牌<br /><b>时机</b>:出牌阶段/一名角色处于濒死状态时<br /><b>目标</b>:已受伤的你/处于濒死状态的角色<br /><b>效果</b>目标角色回复1点体力。",
["#peach_skill"] = "你回复1点体力",
["dismantlement"] = "过河拆桥",
[":dismantlement"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名区域内有牌的其他角色。<br /><b>效果</b>:你弃置目标角色区域内的一张牌。",
["dismantlement_skill"] = "过河拆桥",
["#dismantlement_skill"] = "选择一名区域内有牌的其他角色,你弃置其区域内的一张牌",
["snatch"] = "顺手牵羊",
[":snatch"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>距离1的一名区域内有牌的角色<br /><b>效果</b>:你获得目标角色区域内的一张牌。",
["snatch_skill"] = "顺手牵羊",
["#snatch_skill"] = "选择距离1的区域内有牌的角色你获得其区域内的一张牌",
["duel"] = "决斗",
[":duel"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>由目标角色开始你与其轮流打出一张【杀】否则受到对方的1点伤害并结束此牌结算。",
[":duel"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>由目标角色开始其与你轮流打出一张【杀】直到其与你中的一名角色未打出【杀】。未打出【杀】的角色受到其与你中的另一名角色造成的1点伤害。",
["#duel_skill"] = "选择一名其他角色,由其开始,其与你轮流打出一张【杀】,直到其与你中的一名角色未打出【杀】。<br />未打出【杀】的角色受到其与你中的另一名角色造成的1点伤害",
["collateral"] = "借刀杀人",
[":collateral"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>装备区内有武器牌且攻击范围内有【杀】的合法目标的一名其他角色A你需要选择一名A攻击范围内的【杀】的合法目标B<br /><b>效果</b>A须对B使用一张【杀】否则你获得A装备区内的武器牌。",
["#collateral-slash"] = "借刀杀人:你需对 %dest 使用【杀】,否则 %src 获得你的武器",
[":collateral"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>装备区里有武器牌且攻击范围内有【杀】的合法目标的一名其他角色A你需要选择一名A攻击范围内的【杀】的合法目标B<br /><b>效果</b>A需对B使用一张【杀】否则将装备区里的武器牌交给你。",
["#collateral-slash"] = "借刀杀人:你需对 %dest 使用【杀】,否则将你的装备区里的武器牌交给 %src",
["#collateral_skill"] = "选择装备区里有武器牌且攻击范围内有【杀】的合法目标的一名其他角色A<br />再选择一名A攻击范围内的【杀】的合法目标B。A需对B使用【杀】否则将装备区里的武器牌交给你",
["ex_nihilo"] = "无中生有",
[":ex_nihilo"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:你<br /><b>效果</b>:目标角色摸两张牌。",
["#ex_nihilo_skill"] = "你摸两张牌",
["nullification"] = "无懈可击",
[":nullification"] = "锦囊牌<br /><b>时机</b>:锦囊牌对目标角色生效前,或一张【无懈可击】生效前<br /><b>目标</b>:该锦囊牌<br /><b>效果</b>:抵消该锦囊牌对该角色产生的效果,或抵消另一张【无懈可击】产生的效果。",
["savage_assault"] = "南蛮入侵",
[":savage_assault"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色须打出一张【杀】否则受到1点伤害。",
[":savage_assault"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色需打出一张【杀】否则受到1点伤害。",
["#savage_assault_skill"] = "所有其他角色需打出一张【杀】否则受到1点伤害",
["archery_attack"] = "万箭齐发",
[":archery_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色须打出一张【闪】否则受到1点伤害。",
[":archery_attack"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有其他角色<br /><b>效果</b>每名目标角色需打出一张【闪】否则受到1点伤害。",
["#archery_attack_skill"] = "所有其他角色需打出一张【闪】否则受到1点伤害",
["god_salvation"] = "桃园结义",
[":god_salvation"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有角色<br /><b>效果</b>每名目标角色回复1点体力。",
["#god_salvation_skill"] = "所有角色回复1点体力",
["amazing_grace"] = "五谷丰登",
[":amazing_grace"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有角色<br /><b>效果</b>亮出牌堆顶等于角色数的牌,每名目标角色获得其中一张牌,后将其余的牌置入弃牌堆。",
[":amazing_grace"] = "锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:所有角色<br /><b>效果</b>亮出牌堆顶等于目标角色数的牌,每名目标角色获得其中一张牌,结算结束后将其余的牌置入弃牌堆。",
["amazing_grace_skill"] = "五谷选牌",
["Please choose cards"] = "请选择一张卡牌",
["#amazing_grace_skill"] = "亮出牌堆顶等于所有角色数的牌,每名角色获得其中一张牌",
["lightning"] = "闪电",
[":lightning"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:你<br /><b>效果</b>将此牌置于目标角色判定区内。其判定阶段进行判定若结果为黑桃2-9其受到3点雷电伤害并将【闪电】置入弃牌堆否则将【闪电】移动至其下家判定区内。",
[":lightning"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:你<br /><b>效果</b>将此牌置于目标角色判定区内。其判定阶段进行判定若结果为♠2-9其受到3点雷电伤害并将【闪电】置入弃牌堆否则将【闪电】移动至其下家判定区内。",
["#lightning_skill"] = "将此牌置于你的判定区内。目标角色判定阶段判定:<br />若结果为♠2-9其受到3点雷电伤害并将【闪电】置入弃牌堆否则将【闪电】移动至其下家判定区内",
["indulgence"] = "乐不思蜀",
[":indulgence"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为红桃,其跳过出牌阶段。然后将【乐不思蜀】置入弃牌堆。",
[":indulgence"] = "延时锦囊牌<br /><b>时机</b>:出牌阶段<br /><b>目标</b>:一名其他角色<br /><b>效果</b>:将此牌置于目标角色判定区内。其判定阶段进行判定:若结果不为<font color='#CC3131'>♥</font>,其跳过出牌阶段。然后将【乐不思蜀】置入弃牌堆。",
["#indulgence_skill"] = "选择一名其他角色,将此牌置于其判定区内。其判定阶段判定:<br />若结果不为<font color='#CC3131'>♥</font>,其跳过出牌阶段",
["crossbow"] = "诸葛连弩",
[":crossbow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你于出牌阶段内使用【杀】无次数限制。",
[":crossbow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你于出牌阶段内使用【杀】无次数限制。",
["qinggang_sword"] = "青釭剑",
[":qinggang_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你的【杀】无视目标角色的防具。",
[":qinggang_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你的【杀】无视目标角色的防具。",
["ice_sword"] = "寒冰剑",
[":ice_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用【杀】对目标角色造成伤害时,若该角色有牌,你可以防止此伤害,然后依次弃置其两张牌。",
[":ice_sword"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用【杀】对目标角色造成伤害时,若该角色有牌,你可以防止此伤害,然后依次弃置其两张牌。",
["#ice_sword_skill"] = "寒冰剑",
["double_swords"] = "雌雄双股剑",
[":double_swords"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你指定异性角色为【杀】的目标后,你可以令其选择一项:弃置一张手牌,或令你摸一张牌。",
[":double_swords"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你指定异性角色为【杀】的目标后,你可以令其选择一项:弃置一张手牌,或令你摸一张牌。",
["#double_swords_skill"] = "雌雄双股剑",
["#double_swords-invoke"] = "雌雄双股剑:你需弃置一张手牌,否则 %src 摸一张牌",
["blade"] = "青龙偃月刀",
[":blade"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用的【杀】被【闪】抵消后,你可以对该角色再使用一张【杀】(无距离限制且不能选择额外目标)。",
[":blade"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用的【杀】被【闪】抵消后,你可以对该角色再使用一张【杀】(无距离限制且不能选择额外目标)。",
["#blade_skill"] = "青龙偃月刀",
["#blade_slash"] = "青龙偃月刀:你可以对 %src 再使用一张【杀】",
@ -122,21 +138,22 @@ Fk:loadTranslationTable{
[":spear"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:你可以将两张手牌当【杀】使用或打出。",
["spear_skill"] = "丈八矛",
[":spear_skill"] = "你可以将两张手牌当【杀】使用或打出。",
["#spear_skill"] = "你可以将两张手牌当【杀】使用或打出",
["axe"] = "贯石斧",
[":axe"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用的【杀】被【闪】抵消后,你可以弃置两张牌,则此【杀】继续造成伤害。",
[":axe"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用的【杀】被【闪】抵消后,你可以弃置两张牌,则此【杀】继续造成伤害。",
["#axe_skill"] = "贯石斧",
["#axe-invoke"] = "贯石斧:你可以弃置两张牌,令你对 %dest 使用的【杀】依然生效",
["halberd"] = "方天画戟",
[":halberd"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你使用最后的手牌【杀】可以额外选择至多两名目标。",
[":halberd"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>:锁定技你使用最后的手牌【杀】可以额外选择至多两名目标。",
["kylin_bow"] = "麒麟弓",
[":kylin_bow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用【杀】对目标角色造成伤害时,你可以弃置其装备区的一张坐骑牌。",
[":kylin_bow"] = "装备牌·武器<br /><b>攻击范围</b><br /><b>武器技能</b>当你使用【杀】对目标角色造成伤害时,你可以弃置其装备区的一张坐骑牌。",
["#kylin_bow_skill"] = "麒麟弓",
["eight_diagram"] = "八卦阵",
[":eight_diagram"] = "装备牌·防具<br /><b>防具技能</b>当你需要使用或打出一张【闪】时,你可以进行判定:若结果为红色,视为你使用或打出了一张【闪】。",
[":eight_diagram"] = "装备牌·防具<br /><b>防具技能</b>当你需要使用或打出一张【闪】时,你可以进行判定:若结果为红色,视为你使用或打出了一张【闪】。",
["#eight_diagram_skill"] = "八卦阵",
["nioh_shield"] = "仁王盾",
@ -159,4 +176,6 @@ Fk:loadTranslationTable{
["zixing"] = "紫骍",
[":zixing"] = "装备牌·坐骑<br /><b>坐骑技能</b>:你与其他角色的距离-1。",
["#default_equip_skill"] = "装备%arg2【%arg】",
}

View File

@ -5,6 +5,19 @@ extension.metadata = require "packages.standard_cards.metadata"
local slashSkill = fk.CreateActiveSkill{
name = "slash_skill",
prompt = function(self, selected_cards)
local slash = Fk:cloneCard("slash")
slash.subcards = Card:getIdList(selected_cards)
local max_num = self:getMaxTargetNum(Self, slash) -- halberd
if max_num > 1 then
local num = #table.filter(Fk:currentRoom().alive_players, function (p)
return p ~= Self and not Self:isProhibited(p, slash)
end)
max_num = math.min(num, max_num)
end
slash.subcards = {}
return max_num > 1 and "#slash_skill_multi:::" .. max_num or "#slash_skill"
end,
max_phase_use_time = 1,
target_num = 1,
can_use = function(self, player, card)
@ -86,9 +99,7 @@ extension:addCards({
local jinkSkill = fk.CreateActiveSkill{
name = "jink_skill",
can_use = function()
return false
end,
can_use = Util.FalseFunc,
on_effect = function(self, room, effect)
if effect.responseToEvent then
effect.responseToEvent.isCancellOut = true
@ -123,6 +134,7 @@ extension:addCards({
local peachSkill = fk.CreateActiveSkill{
name = "peach_skill",
prompt = "#peach_skill",
mod_target_filter = function(self, to_select)
return Fk:currentRoom():getPlayerById(to_select):isWounded() and
not table.find(Fk:currentRoom().alive_players, function(p)
@ -171,6 +183,7 @@ extension:addCards({
local dismantlementSkill = fk.CreateActiveSkill{
name = "dismantlement_skill",
prompt = "#dismantlement_skill",
target_num = 1,
mod_target_filter = function(self, to_select, selected, user, card)
local player = Fk:currentRoom():getPlayerById(to_select)
@ -209,6 +222,7 @@ extension:addCards({
local snatchSkill = fk.CreateActiveSkill{
name = "snatch_skill",
prompt = "#snatch_skill",
distance_limit = 1,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
@ -247,6 +261,7 @@ extension:addCards({
local duelSkill = fk.CreateActiveSkill{
name = "duel_skill",
prompt = "#duel_skill",
mod_target_filter = function(self, to_select, selected, user, card)
return user ~= to_select
end,
@ -332,6 +347,7 @@ extension:addCards({
local collateralSkill = fk.CreateActiveSkill{
name = "collateral_skill",
prompt = "#collateral_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
local player = Fk:currentRoom():getPlayerById(to_select)
return user ~= to_select and player:getEquipment(Card.SubtypeWeapon)
@ -374,9 +390,7 @@ local collateralSkill = fk.CreateActiveSkill{
use.extraUse = true
room:useCard(use)
else
room:obtainCard(effect.from,
room:getPlayerById(effect.to):getEquipment(Card.SubtypeWeapon),
true, fk.ReasonGive)
room:moveCardTo(to:getEquipment(Card.SubtypeWeapon), Card.PlayerHand, room:getPlayerById(effect.from), fk.ReasonGive, "collateral", nil, true, to.id)
end
end
}
@ -394,9 +408,8 @@ extension:addCards({
local exNihiloSkill = fk.CreateActiveSkill{
name = "ex_nihilo_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
prompt = "#ex_nihilo_skill",
mod_target_filter = Util.TrueFunc,
can_use = function(self, player, card)
return not player:isProhibited(player, card)
end,
@ -427,9 +440,7 @@ extension:addCards({
local nullificationSkill = fk.CreateActiveSkill{
name = "nullification_skill",
can_use = function()
return false
end,
can_use = Util.FalseFunc,
on_use = function() RoomInstance:delay(1200) end,
on_effect = function(self, room, effect)
if effect.responseToEvent then
@ -455,6 +466,7 @@ extension:addCards({
local savageAssaultSkill = fk.CreateActiveSkill{
name = "savage_assault_skill",
prompt = "#savage_assault_skill",
can_use = Util.AoeCanUse,
on_use = Util.AoeOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
@ -498,6 +510,7 @@ extension:addCards({
local archeryAttackSkill = fk.CreateActiveSkill{
name = "archery_attack_skill",
prompt = "#archery_attack_skill",
can_use = Util.AoeCanUse,
on_use = Util.AoeOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
@ -539,11 +552,10 @@ extension:addCards({
local godSalvationSkill = fk.CreateActiveSkill{
name = "god_salvation_skill",
prompt = "#god_salvation_skill",
can_use = Util.GlobalCanUse,
on_use = Util.GlobalOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
mod_target_filter = Util.TrueFunc,
about_to_effect = function(self, room, effect)
if not room:getPlayerById(effect.to):isWounded() then
return true
@ -577,11 +589,10 @@ extension:addCards({
local amazingGraceSkill = fk.CreateActiveSkill{
name = "amazing_grace_skill",
prompt = "#amazing_grace_skill",
can_use = Util.GlobalCanUse,
on_use = Util.GlobalOnUse,
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
mod_target_filter = Util.TrueFunc,
on_effect = function(self, room, effect)
local to = room:getPlayerById(effect.to)
if not (effect.extra_data and effect.extra_data.AGFilled) then
@ -664,9 +675,8 @@ extension:addCards({
local lightningSkill = fk.CreateActiveSkill{
name = "lightning_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return true
end,
prompt = "#lightning_skill",
mod_target_filter = Util.TrueFunc,
can_use = function(self, player, card)
return not player:isProhibited(player, card)
end,
@ -737,6 +747,7 @@ extension:addCards({
local indulgenceSkill = fk.CreateActiveSkill{
name = "indulgence_skill",
prompt = "#indulgence_skill",
mod_target_filter = function(self, to_select, selected, user, card, distance_limited)
return user ~= to_select
end,
@ -783,20 +794,25 @@ local crossbowAudio = fk.CreateTriggerSkill{
name = "#crossbowAudio",
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and player.phase == Player.Play and
return target == player and player:hasSkill(self) and player.phase == Player.Play and
data.card.trueName == "slash" and player:usedCardTimes("slash", Player.HistoryPhase) > 1
end,
on_refresh = function(self, event, target, player, data)
local room = player.room
room:broadcastPlaySound("./packages/standard_cards/audio/card/crossbow")
room:setEmotion(player, "./packages/standard_cards/image/anim/crossbow")
room:sendLog{
type = "#InvokeSkill",
from = player.id,
arg = "crossbow",
}
end,
}
local crossbowSkill = fk.CreateTargetModSkill{
name = "#crossbow_skill",
attached_equip = "crossbow",
bypass_times = function(self, player, skill, scope)
if player:hasSkill(self.name) and skill.trueName == "slash_skill"
if player:hasSkill(self) and skill.trueName == "slash_skill"
and scope == Player.HistoryPhase then
return true
end
@ -841,7 +857,7 @@ local qingGangSkill = fk.CreateTriggerSkill{
frequency = Skill.Compulsory,
events = { fk.TargetSpecified },
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
data.card and data.card.trueName == "slash"
end,
on_use = function(self, event, target, player, data)
@ -874,7 +890,7 @@ local iceSwordSkill = fk.CreateTriggerSkill{
attached_equip = "ice_sword",
events = {fk.DamageCaused},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and (not data.chain) and
return target == player and player:hasSkill(self) and (not data.chain) and
data.card and data.card.trueName == "slash" and not data.to:isNude()
end,
on_use = function(self, event, target, player, data)
@ -907,11 +923,10 @@ local doubleSwordsSkill = fk.CreateTriggerSkill{
attached_equip = "double_swords",
events = {fk.TargetSpecified},
can_trigger = function(self, event, target, player, data)
if target == player and player:hasSkill(self.name) and
if target == player and player:hasSkill(self) and
data.card and data.card.trueName == "slash" then
local to = player.room:getPlayerById(data.to)
if player.gender == General.Agender or to.gender == General.Agender then return false end
return to.gender ~= player.gender or player.gender == General.Bigender or to.gender == General.Bigender
local target = player.room:getPlayerById(data.to)
return player:compareGenderWith(target, true)
end
end,
on_use = function(self, event, target, player, data)
@ -945,7 +960,7 @@ local bladeSkill = fk.CreateTriggerSkill{
attached_equip = "blade",
events = {fk.CardEffectCancelledOut},
can_trigger = function(self, event, target, player, data)
return player:hasSkill(self.name) and data.from == player.id and data.card.trueName == "slash" and not player.room:getPlayerById(data.to).dead
return player:hasSkill(self) and data.from == player.id and data.card.trueName == "slash" and not player.room:getPlayerById(data.to).dead
end,
on_cost = function(self, event, target, player, data)
local room = player.room
@ -976,6 +991,7 @@ extension:addCards({
local spearSkill = fk.CreateViewAsSkill{
name = "spear_skill",
prompt = "#spear_skill",
attached_equip = "spear",
pattern = "slash",
card_filter = function(self, to_select, selected)
@ -1010,7 +1026,7 @@ local axeSkill = fk.CreateTriggerSkill{
attached_equip = "axe",
events = {fk.CardEffectCancelledOut},
can_trigger = function(self, event, target, player, data)
return player:hasSkill(self.name) and data.from == player.id and data.card.trueName == "slash" and not player.room:getPlayerById(data.to).dead
return player:hasSkill(self) and data.from == player.id and data.card.trueName == "slash" and not player.room:getPlayerById(data.to).dead
end,
on_cost = function(self, event, target, player, data)
local room = player.room
@ -1049,7 +1065,7 @@ local halberdAudio = fk.CreateTriggerSkill{
name = "#halberdAudio",
refresh_events = {fk.CardUsing},
can_refresh = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
data.card.trueName == "slash" and #TargetGroup:getRealTargets(data.tos) > 1
end,
on_refresh = function(self, event, target, player, data)
@ -1062,7 +1078,7 @@ local halberdSkill = fk.CreateTargetModSkill{
name = "#halberd_skill",
attached_equip = "halberd",
extra_target_func = function(self, player, skill, card)
if player:hasSkill(self.name) and skill.trueName == "slash_skill" then
if player:hasSkill(self) and skill.trueName == "slash_skill" then
local cards = card:isVirtual() and card.subcards or {card.id}
local handcards = player:getCardIds(Player.Hand)
if #cards == #handcards and table.every(cards, function(id) return table.contains(handcards, id) end) then
@ -1090,7 +1106,7 @@ local kylinBowSkill = fk.CreateTriggerSkill{
attached_equip = "kylin_bow",
events = {fk.DamageCaused},
can_trigger = function(self, event, target, player, data)
local ret = target == player and player:hasSkill(self.name) and
local ret = target == player and player:hasSkill(self) and
data.card and data.card.trueName == "slash" and (not data.chain)
if ret then
---@type ServerPlayer
@ -1135,7 +1151,7 @@ local eightDiagramSkill = fk.CreateTriggerSkill{
attached_equip = "eight_diagram",
events = {fk.AskForCardUse, fk.AskForCardResponse},
can_trigger = function(self, event, target, player, data)
return target == player and player:hasSkill(self.name) and
return target == player and player:hasSkill(self) and
(data.cardName == "jink" or (data.pattern and Exppattern:Parse(data.pattern):matchExp("jink|0|nosuit|none")))
end,
on_use = function(self, event, target, player, data)
@ -1188,10 +1204,10 @@ local niohShieldSkill = fk.CreateTriggerSkill{
events = {fk.PreCardEffect},
can_trigger = function(self, event, target, player, data)
local effect = data ---@type CardEffectEvent
return player.id == effect.to and player:hasSkill(self.name) and
return player.id == effect.to and player:hasSkill(self) and
effect.card.trueName == "slash" and effect.card.color == Card.Black
end,
on_use = function() return true end,
on_use = Util.TrueFunc,
}
Fk:addSkill(niohShieldSkill)
local niohShield = fk.CreateArmor{

View File

@ -7,12 +7,8 @@ local cheat = fk.CreateActiveSkill{
name = "cheat",
anim_type = "drawcard",
prompt = "#cheat",
can_use = function(self, player)
return true
end,
card_filter = function(self, card)
return false
end,
can_use = Util.TrueFunc,
card_filter = Util.FalseFunc,
target_num = 0,
on_use = function(self, room, effect)
local from = room:getPlayerById(effect.from)
@ -64,16 +60,8 @@ local test_filter = fk.CreateFilterSkill{
local control = fk.CreateActiveSkill{
name = "control",
anim_type = "control",
can_use = function(self, player)
return true
end,
card_filter = function(self, card)
-- if self.interaction.data == "joy" then
--local c = Fk:getCardById(card)
--return Self:getPileNameOfId(card) == self.name and c.color == Card.Red
return false
-- end
end,
can_use = Util.TrueFunc,
card_filter = Util.FalseFunc,
card_num = 0,
target_filter = function(self, to_select)
return to_select ~= Self.id
@ -225,12 +213,8 @@ local damage_maker = fk.CreateActiveSkill{
name = "damage_maker",
anim_type = "offensive",
prompt = "#damage_maker",
can_use = function(self, player)
return true
end,
card_filter = function(self, card)
return false
end,
can_use = Util.TrueFunc,
card_filter = Util.FalseFunc,
card_num = 0,
target_filter = function(self, to_select, selected)
if self.interaction.data == "revive" then return false end
@ -300,12 +284,8 @@ local damage_maker = fk.CreateActiveSkill{
}
local change_hero = fk.CreateActiveSkill{
name = "change_hero",
can_use = function(self, player)
return true
end,
card_filter = function(self, card)
return false
end,
can_use = Util.TrueFunc,
card_filter = Util.FalseFunc,
card_num = 0,
target_filter = function(self, to_select, selected)
return #selected < 1
@ -344,12 +324,8 @@ local test_zhenggong = fk.CreateTriggerSkill{
}
local test_feichu = fk.CreateActiveSkill{
name = "test_feichu",
can_use = function(self, player)
return true
end,
card_filter = function(self, card)
return false
end,
can_use = Util.TrueFunc,
card_filter = Util.FalseFunc,
card_num = 0,
target_filter = function(self, to_select, selected)
return #selected < 1