common tricks completed (#35)

* common tricks completed

* fix muti-targets tricks
This commit is contained in:
Ho-spair 2022-12-20 21:15:49 +08:00 committed by GitHub
parent dfa88df214
commit 2f9f13f74b
6 changed files with 278 additions and 26 deletions

View File

@ -219,22 +219,8 @@ function Player:getMaxCards()
return baseValue
end
---@param subtype CardSubtype
---@return integer|null
function Player:getEquipBySubtype(subtype)
local equipId = nil
for _, id in ipairs(self.player_cards[Player.Equip]) do
if Fk:getCardById(id).sub_type == subtype then
equipId = id
break
end
end
return equipId
end
function Player:getAttackRange()
local weapon = Fk:getCardById(self:getEquipBySubtype(Card.SubtypeWeapon))
local weapon = Fk:getCardById(self:getEquipment(Card.SubtypeWeapon))
local baseAttackRange = math.max(weapon and weapon.attack_range or 1, 0)
return math.max(baseAttackRange, 0)

View File

@ -263,6 +263,14 @@ end
function AimGroup.static:addTargets(room, aimEvent, playerIds)
local playerId = type(playerIds) == "table" and playerIds[1] or playerIds
table.insert(aimEvent.tos[AimGroup.Undone], playerId)
if type(playerIds) == "table" then
for i = 2, #playerIds do
aimEvent.subTargets = aimEvent.subTargets or {}
table.insert(aimEvent.subTargets, playerIds[i])
end
end
room:sortPlayersByAction(aimEvent.tos[AimGroup.Undone])
if aimEvent.targetGroup then
TargetGroup:pushTargets(aimEvent.targetGroup, playerIds)

View File

@ -736,6 +736,20 @@ local onAim = function(room, cardUseEvent, aimEventCollaborators)
additionalDamage = cardUseEvent.addtionalDamage
}
local index = 1
for _, targets in ipairs(cardUseEvent.tos) do
if index > collaboratorsIndex[toId] then
break
end
if #targets > 1 then
for i = 2, #targets do
aimStruct.subTargets = {}
table.insert(aimStruct.subTargets, targets[i])
end
end
end
collaboratorsIndex[toId] = 1
initialEvent = true
else
@ -799,7 +813,7 @@ end
---@param cardUseEvent CardUseStruct
---@return boolean
function Room:useCard(cardUseEvent)
local from = cardUseEvent.customFrom or cardUseEvent.from
local from = cardUseEvent.from
self:moveCards({
ids = { cardUseEvent.cardId },
from = from,
@ -807,6 +821,10 @@ function Room:useCard(cardUseEvent)
moveReason = fk.ReasonUse,
})
if Fk:getCardById(cardUseEvent.cardId).skill then
Fk:getCardById(cardUseEvent.cardId).skill:onUse(self, cardUseEvent)
end
self:setEmotion(self:getPlayerById(from), Fk:getCardById(cardUseEvent.cardId).name)
self:doAnimate("Indicate", {
from = from,
@ -850,9 +868,6 @@ function Room:useCard(cardUseEvent)
}
end
if Fk:getCardById(cardUseEvent.cardId).skill then
Fk:getCardById(cardUseEvent.cardId).skill:onUse(self, cardUseEvent)
end
if self.logic:trigger(fk.PreCardUse, self:getPlayerById(cardUseEvent.from), cardUseEvent) then
return false
end
@ -980,6 +995,7 @@ function Room:useCard(cardUseEvent)
collaboratorsIndex[toId] = collaboratorsIndex[toId] or 1
local curAimEvent = aimEventCollaborators[toId][collaboratorsIndex[toId]]
cardEffectEvent.subTargets = curAimEvent.subTargets
cardEffectEvent.addtionalDamage = curAimEvent.additionalDamage
if curAimEvent.disresponsiveList then
@ -1089,6 +1105,30 @@ function Room:doCardEffect(cardEffectEvent)
end
end
---@param cardResponseEvent CardResponseEvent
function Room:responseCard(cardResponseEvent)
local from = cardResponseEvent.customFrom or cardResponseEvent.from
self:moveCards({
ids = { cardResponseEvent.cardId },
from = from,
toArea = Card.Processing,
moveReason = fk.ReasonResonpse,
})
self:setEmotion(self:getPlayerById(from), Fk:getCardById(cardResponseEvent.cardId).name)
for _, event in ipairs({ fk.PreCardRespond, fk.CardResponding, fk.CardRespondFinished }) do
self.logic:trigger(event, self:getPlayerById(cardResponseEvent.from), cardResponseEvent)
end
if self:getCardArea(cardResponseEvent.cardId) == Card.Processing or cardResponseEvent.skipDrop then
self:moveCards({
ids = { cardResponseEvent.cardId },
toArea = Card.DiscardPile,
moveReason = fk.ReasonPutIntoDiscardPile,
})
end
end
------------------------------------------------------------------------
-- move cards, and wrappers
------------------------------------------------------------------------
@ -1421,6 +1461,10 @@ function Room:damage(damageStruct)
return false
end
if damageStruct.from and not self:getPlayerById(damageStruct.from):isAlive() then
damageStruct.from = nil
end
assert(type(damageStruct.to) == "number")
local stages = {

View File

@ -11,11 +11,12 @@
---@alias DeathStruct { who: integer, damage: DamageStruct }
---@alias CardUseStruct { from: integer, tos: TargetGroup, cardId: integer, toCardId: integer|null, responseToEvent: CardUseStruct|null, nullifiedTargets: interger[]|null, extraUse: boolean|null, disresponsiveList: integer[]|null, unoffsetableList: integer[]|null, addtionalDamage: integer|null, customFrom: integer|null, cardIdsResponded: integer[]|null }
---@alias AimStruct { from: integer, cardId: integer, tos: AimGroup, to: integer, targetGroup: TargetGroup|null, nullifiedTargets: integer[]|null, firstTarget: boolean, additionalDamage: integer|null, disresponsive: boolean|null, unoffsetableList: boolean|null }
---@alias CardEffectEvent { from: integer, tos: TargetGroup, cardId: integer, toCardId: integer|null, responseToEvent: CardUseStruct|null, nullifiedTargets: interger[]|null, extraUse: boolean|null, disresponsiveList: integer[]|null, unoffsetableList: integer[]|null, addtionalDamage: integer|null, customFrom: integer|null, cardIdsResponded: integer[]|null }
---@alias AimStruct { from: integer, cardId: integer, tos: AimGroup, to: integer, subTargets: integer[]|null, targetGroup: TargetGroup|null, nullifiedTargets: integer[]|null, firstTarget: boolean, additionalDamage: integer|null, disresponsive: boolean|null, unoffsetableList: boolean|null }
---@alias CardEffectEvent { from: integer, to: integer, subTargets: integer[]|null, tos: TargetGroup, cardId: integer, toCardId: integer|null, responseToEvent: CardUseStruct|null, nullifiedTargets: interger[]|null, extraUse: boolean|null, disresponsiveList: integer[]|null, unoffsetableList: integer[]|null, addtionalDamage: integer|null, customFrom: integer|null, cardIdsResponded: integer[]|null, disresponsive: boolean|null, unoffsetable: boolean|null }
---@alias SkillEffectEvent { from: integer, tos: integer[], cards: integer[] }
---@alias JudgeStruct { who: ServerPlayer, card: Card, reason: string }
---@alias CardResponseEvent { from: integer, cardId: integer, responseToEvent: CardEffectEvent|null, skipDrop: boolean|null, customFrom: integer|null }
---@alias CardMoveReason integer

View File

@ -28,7 +28,7 @@ local slashSkill = fk.CreateActiveSkill{
room:damage({
from = from,
to = to,
damage = 1,
damage = 1 + (effect.addtionalDamage or 0),
damageType = fk.NormalDamage,
skillName = self.name
})
@ -134,12 +134,12 @@ local peachSkill = fk.CreateActiveSkill{
local to = effect.to
local from = effect.from
room:recover{
room:recover({
who = to,
num = 1,
recoverBy = from,
skillName = self.name
}
})
end
}
local peach = fk.CreateBasicCard{
@ -163,10 +163,35 @@ extension:addCards({
peach:clone(Card.Heart, 12),
})
local dismantlementSkill = fk.CreateActiveSkill{
name = "dismantlement_skill",
target_filter = function(self, to_select, selected)
if #selected == 0 then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player and not player:isAllNude()
end
end,
feasible = function(self, selected)
return #selected == 1
end,
on_effect = function(self, room, effect)
local to = room:getPlayerById(effect.to)
local from = room:getPlayerById(effect.from)
local cid = room:askForCardChosen(
from,
to,
"hej",
self.name
)
room:throwCard(cid, self.name, to, from)
end
}
local dismantlement = fk.CreateTrickCard{
name = "dismantlement",
suit = Card.Spade,
number = 3,
skill = dismantlementSkill,
}
Fk:loadTranslationTable{
["dismantlement"] = "过河拆桥",
@ -202,7 +227,7 @@ local snatchSkill = fk.CreateActiveSkill{
room:getPlayerById(from),
room:getPlayerById(to),
"hej",
"snatch"
self.name
)
room:obtainCard(from, cid)
@ -227,10 +252,60 @@ extension:addCards({
snatch:clone(Card.Diamond, 4),
})
local duelSkill = fk.CreateActiveSkill{
name = "duel_skill",
target_filter = function(self, to_select, selected)
if #selected == 0 then
local player = Fk:currentRoom():getPlayerById(to_select)
return Self ~= player
end
end,
feasible = function(self, selected)
return #selected == 1
end,
on_effect = function(self, room, effect)
local to = room:getPlayerById(effect.to)
local from = room:getPlayerById(effect.from)
local responsers = { to, from }
local currentTurn = 1
local currentResponser = to
while currentResponser:isAlive() do
if effect.disresponsive or table.contains(effect.disresponsiveList or {}, currentResponser.id) then
break
end
local cardIdResponded = room:askForResponse(currentResponser, 'slash')
if cardIdResponded then
room:responseCard({
from = currentResponser.id,
cardId = cardIdResponded,
responseToEvent = effect,
})
else
break
end
currentTurn = currentTurn % 2 + 1
currentResponser = responsers[currentTurn]
end
if currentResponser:isAlive() then
room:damage({
from = responsers[currentTurn % 2 + 1].id,
to = currentResponser.id,
damage = 1 + (effect.addtionalDamage or 0),
damageType = fk.NormalDamage,
skillName = self.name,
})
end
end
}
local duel = fk.CreateTrickCard{
name = "duel",
suit = Card.Spade,
number = 1,
skill = duelSkill,
}
Fk:loadTranslationTable{
["duel"] = "决斗",
@ -244,10 +319,44 @@ extension:addCards({
duel:clone(Card.Diamond, 1),
})
local collateralSkill = fk.CreateActiveSkill{
name = "collateral_skill",
target_filter = function(self, to_select, selected)
local player = Fk:currentRoom():getPlayerById(to_select)
if #selected == 0 then
return Self ~= player and player:getEquipment(Card.SubtypeWeapon)
elseif #selected == 1 then
return Fk:currentRoom():getPlayerById(selected[1]):inMyAttackRange(player)
end
end,
feasible = function(self, selected)
return #selected == 2
end,
on_use = function(self, room, cardUseEvent)
cardUseEvent.tos = { { cardUseEvent.tos[1][1], cardUseEvent.tos[2][1] } }
end,
on_effect = function(self, room, effect)
local cardIdResponded = nil
if not (effect.disresponsive or table.contains(effect.disresponsiveList or {}, effect.to)) then
cardIdResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash')
end
if cardIdResponded then
room:useCard({
from = effect.to,
tos = { { effect.subTargets[1] } },
cardId = cardIdResponded,
})
else
room:obtainCard(effect.from, room:getPlayerById(effect.to):getEquipment(Card.SubtypeWeapon), true, fk.ReasonGive)
end
end
}
local collateral = fk.CreateTrickCard{
name = "collateral",
suit = Card.Club,
number = 12,
skill = collateralSkill,
}
Fk:loadTranslationTable{
["collateral"] = "借刀杀人",
@ -269,7 +378,6 @@ local exNihiloSkill = fk.CreateActiveSkill{
room:drawCards(room:getPlayerById(cardEffectEvent.to), 2, "ex_nihilo")
end
}
local exNihilo = fk.CreateTrickCard{
name = "ex_nihilo",
suit = Card.Heart,
@ -317,10 +425,44 @@ extension:addCards({
nullification:clone(Card.Diamond, 12),
})
local savageAssaultSkill = fk.CreateActiveSkill{
name = "savage_assault_skill",
on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end,
on_effect = function(self, room, effect)
local cardIdResponded = nil
if not (effect.disresponsive or table.contains(effect.disresponsiveList or {}, effect.to)) then
cardIdResponded = room:askForResponse(room:getPlayerById(effect.to), 'slash')
end
if cardIdResponded then
room:responseCard({
from = effect.to,
cardId = cardIdResponded,
responseToEvent = effect,
})
else
room:damage({
from = effect.from,
to = effect.to,
damage = 1 + (effect.addtionalDamage or 0),
damageType = fk.NormalDamage,
skillName = self.name,
})
end
end
}
local savageAssault = fk.CreateTrickCard{
name = "savage_assault",
suit = Card.Spade,
number = 7,
skill = savageAssaultSkill,
}
Fk:loadTranslationTable{
["savage_assault"] = "南蛮入侵",
@ -332,10 +474,44 @@ extension:addCards({
savageAssault:clone(Card.Club, 7),
})
local archeryAttackSkill = fk.CreateActiveSkill{
name = "archery_attack_skill",
on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getOtherPlayers(room:getPlayerById(cardUseEvent.from))) do
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end,
on_effect = function(self, room, effect)
local cardIdResponded = nil
if not (effect.disresponsive or table.contains(effect.disresponsiveList or {}, effect.to)) then
cardIdResponded = room:askForResponse(room:getPlayerById(effect.to), 'jink')
end
if cardIdResponded then
room:responseCard({
from = effect.to,
cardId = cardIdResponded,
responseToEvent = effect,
})
else
room:damage({
from = effect.from,
to = effect.to,
damage = 1 + (effect.addtionalDamage or 0),
damageType = fk.NormalDamage,
skillName = self.name,
})
end
end
}
local archeryAttack = fk.CreateTrickCard{
name = "archery_attack",
suit = Card.Heart,
number = 1,
skill = archeryAttackSkill,
}
Fk:loadTranslationTable{
["archery_attack"] = "万箭齐发",
@ -345,10 +521,29 @@ extension:addCards({
archeryAttack,
})
local godSalvationSkill = fk.CreateActiveSkill{
name = "god_salvation_skill",
on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getAlivePlayers()) do
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end,
on_effect = function(self, room, cardEffectEvent)
room:recover({
who = cardEffectEvent.to,
num = 1,
skillName = self.name,
})
end
}
local godSalvation = fk.CreateTrickCard{
name = "god_salvation",
suit = Card.Heart,
number = 1,
skill = godSalvationSkill,
}
Fk:loadTranslationTable{
["god_salvation"] = "桃园结义",
@ -358,10 +553,25 @@ extension:addCards({
godSalvation,
})
local amazingGraceSkill = fk.CreateActiveSkill{
name = "amazing_grace_skill",
on_use = function(self, room, cardUseEvent)
if not cardUseEvent.tos or #TargetGroup:getRealTargets(cardUseEvent.tos) == 0 then
cardUseEvent.tos = {}
for _, player in ipairs(room:getAlivePlayers()) do
TargetGroup:pushTargets(cardUseEvent.tos, player.id)
end
end
end,
on_effect = function(self, room, cardEffectEvent)
room:getPlayerById(cardEffectEvent.to):drawCards(1, 'god_salvation')
end
}
local amazingGrace = fk.CreateTrickCard{
name = "amazing_grace",
suit = Card.Heart,
number = 3,
skill = amazingGraceSkill,
}
Fk:loadTranslationTable{
["amazing_grace"] = "五谷丰登",

View File

@ -77,6 +77,7 @@ Item {
progress.visible = false;
okCancel.visible = false;
endPhaseButton.visible = false;
respond_play = false;
if (dashboard.pending_skill !== "")
dashboard.stopPending();
@ -100,6 +101,7 @@ Item {
progress.visible = true;
okCancel.visible = true;
endPhaseButton.visible = true;
respond_play = false;
}
}
},
@ -123,6 +125,7 @@ Item {
dashboard.disableAllCards();
dashboard.disableSkills();
progress.visible = true;
respond_play = false;
}
}
}