Qing gang sword & zhu que fan (#85)
- 完成【青釭剑】效果 - 初步完成技能失效技 - 完成【朱雀羽扇】 - 修改“连环状态”传导逻辑 - 修改八卦阵匹配的pattern
This commit is contained in:
parent
44c932981b
commit
dfe3e8b2e7
|
@ -191,7 +191,7 @@ function Card:getTypeString()
|
|||
elseif t == Card.TypeEquip then
|
||||
return "equip"
|
||||
end
|
||||
return "nocolor"
|
||||
return "notype"
|
||||
end
|
||||
|
||||
local function getNumberStr(num)
|
||||
|
|
|
@ -479,9 +479,17 @@ local function getActualSkill(skill)
|
|||
end
|
||||
|
||||
---@param skill string | Skill
|
||||
function Player:hasSkill(skill)
|
||||
function Player:hasSkill(skill, ignoreNullified, ignoreAlive)
|
||||
if not ignoreAlive and self.dead then
|
||||
return false
|
||||
end
|
||||
|
||||
skill = getActualSkill(skill)
|
||||
|
||||
if not (ignoreNullified or skill:isEffectable(self)) then
|
||||
return false
|
||||
end
|
||||
|
||||
if table.contains(self.player_skills, skill) then
|
||||
return true
|
||||
end
|
||||
|
@ -507,7 +515,7 @@ function Player:addSkill(skill, source_skill)
|
|||
local room = Fk:currentRoom()
|
||||
local ret = {}
|
||||
for _, s in ipairs(toget) do
|
||||
if not self:hasSkill(s) then
|
||||
if not self:hasSkill(s, true, true) then
|
||||
table.insert(ret, s)
|
||||
if s:isInstanceOf(TriggerSkill) and RoomInstance then
|
||||
room.logic:addTriggerSkill(s)
|
||||
|
@ -563,7 +571,7 @@ function Player:loseSkill(skill, source_skill)
|
|||
|
||||
local ret = {} ---@type Skill[]
|
||||
for _, s in ipairs(tolose) do
|
||||
if not self:hasSkill(s) then
|
||||
if not self:hasSkill(s, true, true) then
|
||||
table.insert(ret, s)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,4 +51,17 @@ function Skill:isEquipmentSkill()
|
|||
return self.attached_equip and type(self.attached_equip) == 'string' and self.attached_equip ~= ""
|
||||
end
|
||||
|
||||
---@param player Player
|
||||
---@return boolean
|
||||
function Skill:isEffectable(player)
|
||||
local nullifySkills = Fk:currentRoom().status_skills[InvaliditySkill] or {}
|
||||
for _, nullifySkill in ipairs(nullifySkills) do
|
||||
if self.name ~= nullifySkill.name and nullifySkill:getInvalidity(player, self) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return Skill
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
---@class InvaliditySkill : StatusSkill
|
||||
local InvaliditySkill = StatusSkill:subclass("InvaliditySkill")
|
||||
|
||||
---@param from Player
|
||||
---@param skill Skill
|
||||
---@return boolean
|
||||
function InvaliditySkill:getInvalidity(from, skill)
|
||||
return false
|
||||
end
|
||||
|
||||
return InvaliditySkill
|
|
@ -38,7 +38,7 @@ function TriggerSkill:refresh(event, target, player, data) end
|
|||
---@return boolean
|
||||
function TriggerSkill:triggerable(event, target, player, data)
|
||||
return target and (target == player)
|
||||
and (self.global or (target:isAlive() and target:hasSkill(self)))
|
||||
and (self.global or target:hasSkill(self))
|
||||
end
|
||||
|
||||
-- Determine how to cost this skill.
|
||||
|
|
|
@ -11,6 +11,7 @@ AttackRangeSkill = require "core.skill_type.attack_range"
|
|||
MaxCardsSkill = require "core.skill_type.max_cards"
|
||||
TargetModSkill = require "core.skill_type.target_mod"
|
||||
FilterSkill = require "core.skill_type.filter"
|
||||
InvaliditySkill = require "lua.core.skill_type.invalidity"
|
||||
|
||||
BasicCard = require "core.card_type.basic"
|
||||
local Trick = require "core.card_type.trick"
|
||||
|
@ -320,6 +321,21 @@ function fk.CreateFilterSkill(spec)
|
|||
return skill
|
||||
end
|
||||
|
||||
---@class InvaliditySpec: StatusSkillSpec
|
||||
---@field invalidity_func fun(self: InvaliditySkill, from: Player, skill: Skill)
|
||||
|
||||
---@param spec InvaliditySpec
|
||||
---@return InvaliditySkill
|
||||
function fk.CreateInvaliditySkill(spec)
|
||||
assert(type(spec.name) == "string")
|
||||
|
||||
local skill = InvaliditySkill:new(spec.name)
|
||||
readStatusSpecToSkill(skill, spec)
|
||||
skill.getInvalidity = spec.invalidity_func
|
||||
|
||||
return skill
|
||||
end
|
||||
|
||||
---@class CardSpec: Card
|
||||
---@field skill Skill
|
||||
---@field equip_skill Skill
|
||||
|
|
|
@ -11,6 +11,7 @@ GameEvent.functions[GameEvent.ChangeHp] = function(self)
|
|||
num = num,
|
||||
reason = reason,
|
||||
skillName = skillName,
|
||||
damageEvent = damageStruct,
|
||||
}
|
||||
|
||||
if self.logic:trigger(fk.BeforeHpChanged, player, data) then
|
||||
|
|
|
@ -1317,7 +1317,8 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
nullifiedTargets = cardUseEvent.nullifiedTargets or {},
|
||||
tos = aimGroup,
|
||||
firstTarget = firstTarget,
|
||||
additionalDamage = cardUseEvent.additionalDamage
|
||||
additionalDamage = cardUseEvent.additionalDamage,
|
||||
extra_data = cardUseEvent.extra_data,
|
||||
}
|
||||
|
||||
local index = 1
|
||||
|
@ -1344,6 +1345,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
aimStruct.targetGroup = cardUseEvent.tos
|
||||
aimStruct.nullifiedTargets = cardUseEvent.nullifiedTargets or {}
|
||||
aimStruct.firstTarget = firstTarget
|
||||
aimStruct.extra_data = cardUseEvent.extra_data
|
||||
end
|
||||
|
||||
firstTarget = false
|
||||
|
@ -1361,6 +1363,7 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
|
|||
cardUseEvent.from = aimStruct.from
|
||||
cardUseEvent.tos = aimEventTargetGroup
|
||||
cardUseEvent.nullifiedTargets = aimStruct.nullifiedTargets
|
||||
cardUseEvent.extra_data = aimStruct.extra_data
|
||||
|
||||
if #AimGroup:getAllTargets(aimStruct.tos) == 0 then
|
||||
return false
|
||||
|
@ -1824,7 +1827,7 @@ function Room:handleAddLoseSkills(player, skill_names, source_skill, sendlog, no
|
|||
for _, skill in ipairs(skill_names) do
|
||||
if string.sub(skill, 1, 1) == "-" then
|
||||
local actual_skill = string.sub(skill, 2, #skill)
|
||||
if player:hasSkill(actual_skill) then
|
||||
if player:hasSkill(actual_skill, true, true) then
|
||||
local lost_skills = player:loseSkill(actual_skill, source_skill)
|
||||
for _, s in ipairs(lost_skills) do
|
||||
self:doBroadcastNotify("LoseSkill", json.encode{
|
||||
|
@ -1846,7 +1849,7 @@ function Room:handleAddLoseSkills(player, skill_names, source_skill, sendlog, no
|
|||
end
|
||||
else
|
||||
local sk = Fk.skills[skill]
|
||||
if sk and not player:hasSkill(sk) then
|
||||
if sk and not player:hasSkill(sk, true, true) then
|
||||
local got_skills = player:addSkill(sk)
|
||||
|
||||
for _, s in ipairs(got_skills) do
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
---@field num integer
|
||||
---@field reason string
|
||||
---@field skillName string
|
||||
---@field damageEvent DamageStruct|null
|
||||
|
||||
---@class HpLostData
|
||||
---@field num integer
|
||||
|
@ -54,6 +55,7 @@ fk.FireDamage = 3
|
|||
---@field chain boolean
|
||||
---@field damageType DamageType
|
||||
---@field skillName string
|
||||
---@field beginnerOfTheDamage boolean|null
|
||||
|
||||
---@class RecoverStruct
|
||||
---@field who ServerPlayer
|
||||
|
|
|
@ -156,32 +156,34 @@ extension:addCards({
|
|||
local ironChainEffect = fk.CreateTriggerSkill{
|
||||
name = "iron_chain_effect",
|
||||
global = true,
|
||||
priority = 0, -- game rule
|
||||
refresh_events = {fk.DamageFinished},
|
||||
priority = { [fk.BeforeHpChanged] = 10, [fk.DamageFinished] = 0 }, -- game rule
|
||||
refresh_events = { fk.BeforeHpChanged, fk.DamageFinished },
|
||||
can_refresh = function(self, event, target, player, data)
|
||||
return target == player and data.damageType ~= fk.NormalDamage
|
||||
if event == fk.BeforeHpChanged then
|
||||
return target == player and data.damageEvent and data.damageEvent.damageType ~= fk.NormalDamage and player.chained
|
||||
else
|
||||
return target == player and data.beginnerOfTheDamage and not data.chain
|
||||
end
|
||||
end,
|
||||
on_refresh = function(self, event, target, player, data)
|
||||
local room = player.room
|
||||
if data.to.chained then
|
||||
data.to:setChainState(false)
|
||||
if event == fk.BeforeHpChanged then
|
||||
data.damageEvent.beginnerOfTheDamage = true
|
||||
player:setChainState(false)
|
||||
else
|
||||
return
|
||||
end
|
||||
if data.chain then return end
|
||||
|
||||
local targets = table.filter(room:getAlivePlayers(), function(p)
|
||||
return p.chained
|
||||
end)
|
||||
for _, p in ipairs(targets) do
|
||||
room:sendLog{
|
||||
type = "#ChainDamage",
|
||||
from = p.id
|
||||
}
|
||||
local dmg = table.simpleClone(data)
|
||||
dmg.to = p
|
||||
dmg.chain = true
|
||||
room:damage(dmg)
|
||||
local targets = table.filter(room:getAlivePlayers(), function(p)
|
||||
return p.chained
|
||||
end)
|
||||
for _, p in ipairs(targets) do
|
||||
room:sendLog{
|
||||
type = "#ChainDamage",
|
||||
from = p.id
|
||||
}
|
||||
local dmg = table.simpleClone(data)
|
||||
dmg.to = p
|
||||
dmg.chain = true
|
||||
room:damage(dmg)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
@ -320,6 +322,30 @@ local gudingBlade = fk.CreateWeapon{
|
|||
|
||||
extension:addCard(gudingBlade)
|
||||
|
||||
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"
|
||||
end,
|
||||
on_use = function(_, _, _, _, data)
|
||||
local fireSlash = Fk:cloneCard("fire__slash")
|
||||
fireSlash:addSubcard(data.card)
|
||||
data.card = fireSlash
|
||||
end,
|
||||
}
|
||||
Fk:addSkill(fanSkill)
|
||||
local fan = fk.CreateWeapon{
|
||||
name = "fan",
|
||||
suit = Card.Diamond,
|
||||
number = 1,
|
||||
attack_range = 4,
|
||||
equip_skill = fanSkill,
|
||||
}
|
||||
|
||||
extension:addCard(fan)
|
||||
|
||||
local vineSkill = fk.CreateTriggerSkill{
|
||||
name = "#vine_skill",
|
||||
attached_equip = "vine",
|
||||
|
@ -380,7 +406,7 @@ local silverLion = fk.CreateArmor{
|
|||
equip_skill = silverLionSkill,
|
||||
on_uninstall = function(self, room, player)
|
||||
Armor.onUninstall(self, room, player)
|
||||
if player:isWounded() then
|
||||
if player:isWounded() and self.equip_skill:isEffectable(player) then
|
||||
room:broadcastPlaySound("./packages/maneuvering/audio/card/silver_lion")
|
||||
room:setEmotion(player, "./packages/maneuvering/image/anim/silver_lion")
|
||||
room:recover{
|
||||
|
@ -436,6 +462,8 @@ Fk:loadTranslationTable{
|
|||
["fire_attack"] = "火攻",
|
||||
["supply_shortage"] = "兵粮寸断",
|
||||
["guding_blade"] = "古锭刀",
|
||||
["fan"] = "朱雀羽扇",
|
||||
["#fan_skill"] = "朱雀羽扇",
|
||||
["vine"] = "藤甲",
|
||||
["silver_lion"] = "白银狮子",
|
||||
["hualiu"] = "骅骝",
|
||||
|
|
|
@ -773,11 +773,62 @@ extension:addCards({
|
|||
crossbow:clone(Card.Diamond, 1),
|
||||
})
|
||||
|
||||
fk.MarkArmorNullified = "mark__armor_nullified"
|
||||
|
||||
local armorInvalidity = fk.CreateInvaliditySkill {
|
||||
name = "armor_invalidity_skill",
|
||||
global = true,
|
||||
invalidity_func = function(self, from, skill)
|
||||
return
|
||||
from:getMark(fk.MarkArmorNullified) > 0 and
|
||||
from:getEquipment(Card.SubtypeArmor) ~= nil and
|
||||
skill.attached_equip == Fk:getCardById(from:getEquipment(Card.SubtypeArmor)).name
|
||||
end
|
||||
}
|
||||
Fk:addSkill(armorInvalidity)
|
||||
|
||||
local qingGangSkill = fk.CreateTriggerSkill{
|
||||
name = "#qinggang_sword_skill",
|
||||
attached_equip = "qinggang_sword",
|
||||
frequency = Skill.Compulsory,
|
||||
events = { fk.TargetSpecified },
|
||||
can_trigger = function(self, event, target, player, data)
|
||||
return target == player and player:hasSkill(self.name) and
|
||||
data.card and data.card.trueName == "slash"
|
||||
end,
|
||||
on_use = function(self, event, target, player, data)
|
||||
local room = player.room
|
||||
room:addPlayerMark(room:getPlayerById(data.to), fk.MarkArmorNullified)
|
||||
|
||||
data.extra_data = data.extra_data or {}
|
||||
data.extra_data.qinggangNullified = data.extra_data.qinggangNullified or {}
|
||||
data.extra_data.qinggangNullified[tostring(data.to)] = (data.extra_data.qinggangNullified[tostring(data.to)] or 0) + 1
|
||||
end,
|
||||
|
||||
refresh_events = { fk.CardUseFinished },
|
||||
can_refresh = function(self, event, target, player, data)
|
||||
return data.extra_data and data.extra_data.qinggangNullified
|
||||
end,
|
||||
on_refresh = function(self, event, target, player, data)
|
||||
local room = player.room
|
||||
for key, num in pairs(data.extra_data.qinggangNullified) do
|
||||
local p = room:getPlayerById(tonumber(key))
|
||||
if p:getMark(fk.MarkArmorNullified) > 0 then
|
||||
room:removePlayerMark(p, fk.MarkArmorNullified, num)
|
||||
end
|
||||
end
|
||||
|
||||
data.qinggangNullified = nil
|
||||
end,
|
||||
}
|
||||
Fk:addSkill(qingGangSkill)
|
||||
|
||||
local qingGang = fk.CreateWeapon{
|
||||
name = "qinggang_sword",
|
||||
suit = Card.Spade,
|
||||
number = 6,
|
||||
attack_range = 2,
|
||||
equip_skill = qingGangSkill,
|
||||
}
|
||||
|
||||
extension:addCards({
|
||||
|
@ -1035,7 +1086,7 @@ local eightDiagramSkill = fk.CreateTriggerSkill{
|
|||
events = {fk.AskForCardUse, fk.AskForCardResponse},
|
||||
can_trigger = function(self, event, target, player, data)
|
||||
return target == player and player:hasSkill(self.name) and
|
||||
(data.cardName == "jink" or (data.pattern and Exppattern:Parse(data.pattern):matchExp("jink")))
|
||||
(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)
|
||||
local room = player.room
|
||||
|
|
Loading…
Reference in New Issue