720 lines
20 KiB
Go
720 lines
20 KiB
Go
package game
|
|
|
|
import "fmt"
|
|
|
|
type EffectState struct {
|
|
Active bool
|
|
CardTypeID string
|
|
CasterID string
|
|
Step int
|
|
WaitingFor string
|
|
ChoiceType string
|
|
ChoiceData map[string]interface{}
|
|
TempData map[string]interface{}
|
|
PendingResponses map[string]interface{}
|
|
AllCollected bool
|
|
}
|
|
|
|
func (e *Engine) triggerEffect(caster *PlayerState, card *Card) bool {
|
|
switch card.TypeID {
|
|
case "student_council_president", "culprit", "alien":
|
|
return false
|
|
case "library_committee_member":
|
|
return e.effectLibrary(caster)
|
|
case "discipline_committee_member":
|
|
return e.effectDiscipline(caster)
|
|
case "health_committee_member":
|
|
return e.effectHealth(caster)
|
|
case "go_home_club":
|
|
return e.effectGoHome(caster)
|
|
case "accomplice":
|
|
return e.effectAccomplice(caster)
|
|
case "class_monitor":
|
|
return e.effectClassMonitor(caster)
|
|
case "young_lady":
|
|
return e.effectYoungLady(caster)
|
|
case "newspaper_club":
|
|
return e.effectNewspaper(caster)
|
|
case "honor_student":
|
|
return e.effectHonorStudent(caster)
|
|
case "infected_person":
|
|
return e.effectInfected(caster)
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (e *Engine) effectLibrary(caster *PlayerState) bool {
|
|
if len(e.HarmonyZone) == 0 {
|
|
return false
|
|
}
|
|
var cards []map[string]interface{}
|
|
for _, c := range e.HarmonyZone {
|
|
cards = append(cards, map[string]interface{}{
|
|
"uid": c.UID, "type_id": c.TypeID, "name": c.Name, "mp": c.MP,
|
|
})
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "library_committee_member", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "view_cards", Step: 0,
|
|
ChoiceData: map[string]interface{}{"cards": cards, "message": "调和区的卡牌"},
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectDiscipline(caster *PlayerState) bool {
|
|
var targets []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
if p.ID != caster.ID && !p.IsExited && len(p.Hand) > 0 {
|
|
targets = append(targets, map[string]interface{}{"player_id": p.ID, "nickname": p.Nickname})
|
|
}
|
|
}
|
|
if len(targets) == 0 {
|
|
return false
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "discipline_committee_member", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_player", Step: 0,
|
|
ChoiceData: map[string]interface{}{"targets": targets, "message": "选择要查看手牌的玩家"},
|
|
TempData: make(map[string]interface{}),
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectHealth(caster *PlayerState) bool {
|
|
var cards []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
for _, c := range p.SkillZone {
|
|
if c.TypeID != "health_committee_member" {
|
|
cards = append(cards, map[string]interface{}{
|
|
"uid": c.UID, "type_id": c.TypeID, "name": c.Name, "owner_id": p.ID,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
if len(cards) == 0 {
|
|
return false
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "health_committee_member", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_skill_card", Step: 0,
|
|
ChoiceData: map[string]interface{}{"cards": cards, "message": "选择一张已使用的牌加入手牌"},
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectGoHome(caster *PlayerState) bool {
|
|
if len(e.HarmonyZone) == 0 || len(caster.Hand) == 0 {
|
|
return false
|
|
}
|
|
var handCards []map[string]interface{}
|
|
for _, c := range caster.Hand {
|
|
handCards = append(handCards, map[string]interface{}{"uid": c.UID, "type_id": c.TypeID, "name": c.Name})
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "go_home_club", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_card_from_hand", Step: 0,
|
|
ChoiceData: map[string]interface{}{"cards": handCards, "message": "选择一张手牌与调和区交换"},
|
|
TempData: make(map[string]interface{}),
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectAccomplice(caster *PlayerState) bool {
|
|
var cards []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
for _, c := range p.ChallengeZone {
|
|
cards = append(cards, map[string]interface{}{
|
|
"uid": c.UID, "owner_id": p.ID,
|
|
})
|
|
}
|
|
}
|
|
if len(cards) == 0 {
|
|
return false
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "accomplice", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_challenge_card", Step: 0,
|
|
ChoiceData: map[string]interface{}{"cards": cards, "message": "选择一张质疑区的牌"},
|
|
TempData: make(map[string]interface{}),
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectClassMonitor(caster *PlayerState) bool {
|
|
var targets []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
if !p.IsExited && len(p.Hand) > 0 {
|
|
targets = append(targets, map[string]interface{}{"player_id": p.ID, "nickname": p.Nickname})
|
|
}
|
|
}
|
|
if len(targets) < 2 {
|
|
return false
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "class_monitor", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_player", Step: 0,
|
|
ChoiceData: map[string]interface{}{"targets": targets, "message": "选择换牌的第一名玩家(可以是自己)"},
|
|
TempData: make(map[string]interface{}),
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectYoungLady(caster *PlayerState) bool {
|
|
var targets []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
if p.ID != caster.ID && !p.IsExited && len(p.Hand) > 0 {
|
|
targets = append(targets, map[string]interface{}{"player_id": p.ID, "nickname": p.Nickname})
|
|
}
|
|
}
|
|
if len(targets) == 0 {
|
|
return false
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "young_lady", CasterID: caster.ID,
|
|
WaitingFor: caster.ID, ChoiceType: "select_player", Step: 0,
|
|
ChoiceData: map[string]interface{}{"targets": targets, "message": "选择一名玩家抽取手牌"},
|
|
TempData: make(map[string]interface{}),
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectNewspaper(caster *PlayerState) bool {
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "newspaper_club", CasterID: caster.ID,
|
|
ChoiceType: "all_select_card", Step: 0,
|
|
ChoiceData: map[string]interface{}{"message": "选择一张手牌传给左手边的玩家"},
|
|
PendingResponses: make(map[string]interface{}),
|
|
}
|
|
for _, p := range e.Players {
|
|
if !p.IsExited && len(p.Hand) > 0 {
|
|
e.Effect.WaitingFor = p.ID
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectHonorStudent(caster *PlayerState) bool {
|
|
var culpritHolder, alienHolder string
|
|
for _, p := range e.Players {
|
|
if p.ID == caster.ID {
|
|
continue
|
|
}
|
|
for _, c := range p.Hand {
|
|
if c.TypeID == "culprit" {
|
|
culpritHolder = p.ID
|
|
}
|
|
if c.TypeID == "alien" {
|
|
alienHolder = p.ID
|
|
}
|
|
}
|
|
}
|
|
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "honor_student", CasterID: caster.ID,
|
|
TempData: map[string]interface{}{
|
|
"culprit_holder": culpritHolder,
|
|
"alien_holder": alienHolder,
|
|
},
|
|
}
|
|
|
|
if culpritHolder != "" {
|
|
cp := e.GetPlayer(culpritHolder)
|
|
if cp != nil && !cp.IsExited {
|
|
e.Effect.Step = 0
|
|
e.Effect.WaitingFor = culpritHolder
|
|
e.Effect.ChoiceType = "select_option"
|
|
e.Effect.ChoiceData = map[string]interface{}{
|
|
"message": "有人使用了优等生!你是犯人,必须吐出舌头。",
|
|
"options": []map[string]interface{}{
|
|
{"value": "long", "label": "吐长舌头"},
|
|
{"value": "short", "label": "吐短舌头"},
|
|
},
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
if alienHolder != "" {
|
|
ap := e.GetPlayer(alienHolder)
|
|
if ap != nil && !ap.IsExited {
|
|
e.Effect.Step = 1
|
|
e.Effect.WaitingFor = alienHolder
|
|
e.Effect.ChoiceType = "select_option"
|
|
e.Effect.ChoiceData = map[string]interface{}{
|
|
"message": "有人使用了优等生!你是外星人,是否要装作犯人吐舌头?",
|
|
"options": []map[string]interface{}{
|
|
{"value": "long", "label": "吐长舌头"},
|
|
{"value": "short", "label": "吐短舌头"},
|
|
{"value": "none", "label": "不吐舌头"},
|
|
},
|
|
}
|
|
return true
|
|
}
|
|
}
|
|
|
|
e.Effect.Step = 99
|
|
e.Effect.WaitingFor = caster.ID
|
|
e.Effect.ChoiceType = "view_cards"
|
|
e.Effect.ChoiceData = map[string]interface{}{"message": "优等生效果:没有人吐舌头"}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) effectInfected(caster *PlayerState) bool {
|
|
if len(caster.Hand) <= 1 {
|
|
return false
|
|
}
|
|
caster.InfectedActive = true
|
|
return false
|
|
}
|
|
|
|
// HandleEffectResponse processes a player's response during effect resolution
|
|
func (e *Engine) HandleEffectResponse(playerID string, response map[string]interface{}) error {
|
|
ef := e.Effect
|
|
if ef == nil || !ef.Active {
|
|
return fmt.Errorf("no active effect")
|
|
}
|
|
|
|
switch ef.CardTypeID {
|
|
case "library_committee_member", "student_council_president":
|
|
return e.finishEffect()
|
|
case "discipline_committee_member":
|
|
return e.respondDiscipline(playerID, response)
|
|
case "health_committee_member":
|
|
return e.respondHealth(playerID, response)
|
|
case "go_home_club":
|
|
return e.respondGoHome(playerID, response)
|
|
case "accomplice":
|
|
return e.respondAccomplice(playerID, response)
|
|
case "class_monitor":
|
|
return e.respondClassMonitor(playerID, response)
|
|
case "young_lady":
|
|
return e.respondYoungLady(playerID, response)
|
|
case "newspaper_club":
|
|
return e.respondNewspaper(playerID, response)
|
|
case "honor_student":
|
|
return e.respondHonorStudent(playerID, response)
|
|
case "infected_person":
|
|
return e.respondInfected(playerID, response)
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondDiscipline(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
if ef.Step == 0 {
|
|
tid, _ := resp["player_id"].(string)
|
|
target := e.GetPlayer(tid)
|
|
if target == nil {
|
|
return fmt.Errorf("invalid target")
|
|
}
|
|
var cards []map[string]interface{}
|
|
for _, c := range target.Hand {
|
|
cards = append(cards, map[string]interface{}{"uid": c.UID, "type_id": c.TypeID, "name": c.Name, "mp": c.MP})
|
|
}
|
|
ef.Step = 1
|
|
ef.ChoiceType = "view_cards"
|
|
ef.ChoiceData = map[string]interface{}{"cards": cards, "message": target.Nickname + " 的手牌"}
|
|
return nil
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondHealth(pid string, resp map[string]interface{}) error {
|
|
uid, _ := resp["card_uid"].(string)
|
|
for _, p := range e.Players {
|
|
for i, c := range p.SkillZone {
|
|
if c.UID == uid && c.TypeID != "health_committee_member" {
|
|
p.SkillZone = append(p.SkillZone[:i], p.SkillZone[i+1:]...)
|
|
caster := e.GetPlayer(e.Effect.CasterID)
|
|
caster.Hand = append(caster.Hand, c)
|
|
return e.finishEffect()
|
|
}
|
|
}
|
|
}
|
|
return fmt.Errorf("card not found")
|
|
}
|
|
|
|
func (e *Engine) respondGoHome(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
if ef.Step == 0 {
|
|
uid, _ := resp["card_uid"].(string)
|
|
ef.TempData["hand_card_uid"] = uid
|
|
ef.Step = 1
|
|
var hCards []map[string]interface{}
|
|
for i, c := range e.HarmonyZone {
|
|
hCards = append(hCards, map[string]interface{}{"uid": c.UID, "index": i})
|
|
}
|
|
ef.ChoiceType = "select_harmony_card"
|
|
ef.ChoiceData = map[string]interface{}{"cards": hCards, "message": "选择调和区的一张牌"}
|
|
return nil
|
|
}
|
|
hUID, _ := resp["card_uid"].(string)
|
|
handUID, _ := ef.TempData["hand_card_uid"].(string)
|
|
caster := e.GetPlayer(ef.CasterID)
|
|
|
|
var handCard *Card
|
|
for i, c := range caster.Hand {
|
|
if c.UID == handUID {
|
|
handCard = c
|
|
caster.Hand = append(caster.Hand[:i], caster.Hand[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
var harmonyCard *Card
|
|
for i, c := range e.HarmonyZone {
|
|
if c.UID == hUID {
|
|
harmonyCard = c
|
|
e.HarmonyZone = append(e.HarmonyZone[:i], e.HarmonyZone[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
if handCard != nil {
|
|
e.HarmonyZone = append(e.HarmonyZone, handCard)
|
|
}
|
|
if harmonyCard != nil {
|
|
caster.Hand = append(caster.Hand, harmonyCard)
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondAccomplice(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
if ef.Step == 0 {
|
|
uid, _ := resp["card_uid"].(string)
|
|
ef.TempData["challenge_uid"] = uid
|
|
owner, _ := resp["owner_id"].(string)
|
|
ef.TempData["challenge_owner"] = owner
|
|
ef.Step = 1
|
|
var targets []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
if p.ID != owner {
|
|
targets = append(targets, map[string]interface{}{"player_id": p.ID, "nickname": p.Nickname})
|
|
}
|
|
}
|
|
ef.ChoiceType = "select_player"
|
|
ef.ChoiceData = map[string]interface{}{"targets": targets, "message": "选择转移到哪个玩家面前"}
|
|
return nil
|
|
}
|
|
targetID, _ := resp["player_id"].(string)
|
|
cUID, _ := ef.TempData["challenge_uid"].(string)
|
|
ownerID, _ := ef.TempData["challenge_owner"].(string)
|
|
|
|
owner := e.GetPlayer(ownerID)
|
|
target := e.GetPlayer(targetID)
|
|
if owner == nil || target == nil {
|
|
return e.finishEffect()
|
|
}
|
|
for i, c := range owner.ChallengeZone {
|
|
if c.UID == cUID {
|
|
owner.ChallengeZone = append(owner.ChallengeZone[:i], owner.ChallengeZone[i+1:]...)
|
|
target.ChallengeZone = append(target.ChallengeZone, c)
|
|
break
|
|
}
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondClassMonitor(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
if ef.Step == 0 {
|
|
aid, _ := resp["player_id"].(string)
|
|
ef.TempData["player_a_id"] = aid
|
|
ef.Step = 1
|
|
var targets []map[string]interface{}
|
|
for _, p := range e.Players {
|
|
if p.ID != aid && !p.IsExited && len(p.Hand) > 0 {
|
|
targets = append(targets, map[string]interface{}{"player_id": p.ID, "nickname": p.Nickname})
|
|
}
|
|
}
|
|
ef.WaitingFor = ef.CasterID
|
|
ef.ChoiceType = "select_player"
|
|
ef.ChoiceData = map[string]interface{}{"targets": targets, "message": "选择换牌的第二名玩家"}
|
|
return nil
|
|
}
|
|
if ef.Step == 1 {
|
|
bid, _ := resp["player_id"].(string)
|
|
ef.TempData["player_b_id"] = bid
|
|
ef.Step = 2
|
|
aid, _ := ef.TempData["player_a_id"].(string)
|
|
playerA := e.GetPlayer(aid)
|
|
ef.WaitingFor = aid
|
|
var cards []map[string]interface{}
|
|
for _, c := range playerA.Hand {
|
|
cards = append(cards, map[string]interface{}{"uid": c.UID, "type_id": c.TypeID, "name": c.Name})
|
|
}
|
|
ef.ChoiceType = "select_card_from_hand"
|
|
ef.ChoiceData = map[string]interface{}{"cards": cards, "message": playerA.Nickname + ":选择一张手牌交给对方"}
|
|
return nil
|
|
}
|
|
if ef.Step == 2 {
|
|
uid, _ := resp["card_uid"].(string)
|
|
ef.TempData["card_a_uid"] = uid
|
|
ef.Step = 3
|
|
bid, _ := ef.TempData["player_b_id"].(string)
|
|
playerB := e.GetPlayer(bid)
|
|
ef.WaitingFor = bid
|
|
var cards []map[string]interface{}
|
|
for _, c := range playerB.Hand {
|
|
cards = append(cards, map[string]interface{}{"uid": c.UID, "type_id": c.TypeID, "name": c.Name})
|
|
}
|
|
ef.ChoiceType = "select_card_from_hand"
|
|
ef.ChoiceData = map[string]interface{}{"cards": cards, "message": playerB.Nickname + ":选择一张手牌交给对方"}
|
|
return nil
|
|
}
|
|
bUID, _ := resp["card_uid"].(string)
|
|
aUID, _ := ef.TempData["card_a_uid"].(string)
|
|
aid, _ := ef.TempData["player_a_id"].(string)
|
|
bid, _ := ef.TempData["player_b_id"].(string)
|
|
pA := e.GetPlayer(aid)
|
|
pB := e.GetPlayer(bid)
|
|
var cA, cB *Card
|
|
for i, c := range pA.Hand {
|
|
if c.UID == aUID {
|
|
cA = c
|
|
pA.Hand = append(pA.Hand[:i], pA.Hand[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
for i, c := range pB.Hand {
|
|
if c.UID == bUID {
|
|
cB = c
|
|
pB.Hand = append(pB.Hand[:i], pB.Hand[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
if cA != nil {
|
|
pB.Hand = append(pB.Hand, cA)
|
|
}
|
|
if cB != nil {
|
|
pA.Hand = append(pA.Hand, cB)
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondYoungLady(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
caster := e.GetPlayer(ef.CasterID)
|
|
if ef.Step == 0 {
|
|
tid, _ := resp["player_id"].(string)
|
|
target := e.GetPlayer(tid)
|
|
if target == nil || len(target.Hand) == 0 {
|
|
return e.finishEffect()
|
|
}
|
|
drawn := target.Hand[e.rng.Intn(len(target.Hand))]
|
|
e.removeFromHand(target, drawn.UID)
|
|
caster.Hand = append(caster.Hand, drawn)
|
|
|
|
ef.TempData["target_id"] = tid
|
|
ef.Step = 1
|
|
ef.WaitingFor = ef.CasterID
|
|
var cards []map[string]interface{}
|
|
for _, c := range caster.Hand {
|
|
cards = append(cards, map[string]interface{}{"uid": c.UID, "type_id": c.TypeID, "name": c.Name})
|
|
}
|
|
ef.ChoiceType = "select_card_from_hand"
|
|
ef.ChoiceData = map[string]interface{}{
|
|
"cards": cards,
|
|
"message": "从 " + target.Nickname + " 抽到了「" + drawn.Name + "」,选择一张手牌反面返还",
|
|
}
|
|
return nil
|
|
}
|
|
uid, _ := resp["card_uid"].(string)
|
|
tid, _ := ef.TempData["target_id"].(string)
|
|
target := e.GetPlayer(tid)
|
|
for i, c := range caster.Hand {
|
|
if c.UID == uid {
|
|
caster.Hand = append(caster.Hand[:i], caster.Hand[i+1:]...)
|
|
if target != nil {
|
|
target.Hand = append(target.Hand, c)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondNewspaper(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
uid, _ := resp["card_uid"].(string)
|
|
ef.PendingResponses[pid] = uid
|
|
|
|
allDone := true
|
|
for _, p := range e.Players {
|
|
if !p.IsExited && len(p.Hand) > 0 {
|
|
if _, ok := ef.PendingResponses[p.ID]; !ok {
|
|
allDone = false
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !allDone {
|
|
return nil
|
|
}
|
|
|
|
type passInfo struct {
|
|
from *PlayerState
|
|
card *Card
|
|
}
|
|
var passes []passInfo
|
|
activePlayers := e.getActivePlayers()
|
|
for _, p := range activePlayers {
|
|
uidStr, ok := ef.PendingResponses[p.ID].(string)
|
|
if !ok {
|
|
continue
|
|
}
|
|
for _, c := range p.Hand {
|
|
if c.UID == uidStr {
|
|
passes = append(passes, passInfo{from: p, card: c})
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, pi := range passes {
|
|
e.removeFromHand(pi.from, pi.card.UID)
|
|
}
|
|
for i, pi := range passes {
|
|
nextIdx := (i + 1) % len(activePlayers)
|
|
activePlayers[nextIdx].Hand = append(activePlayers[nextIdx].Hand, pi.card)
|
|
}
|
|
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) respondHonorStudent(pid string, resp map[string]interface{}) error {
|
|
ef := e.Effect
|
|
|
|
if ef.Step == 0 {
|
|
tongue, _ := resp["value"].(string)
|
|
culpritID, _ := ef.TempData["culprit_holder"].(string)
|
|
cp := e.GetPlayer(culpritID)
|
|
name := culpritID
|
|
if cp != nil {
|
|
name = cp.Nickname
|
|
}
|
|
tongues := []interface{}{map[string]interface{}{"nickname": name, "tongue": tongue}}
|
|
ef.TempData["tongues"] = tongues
|
|
|
|
alienHolder, _ := ef.TempData["alien_holder"].(string)
|
|
if alienHolder != "" {
|
|
ap := e.GetPlayer(alienHolder)
|
|
if ap != nil && !ap.IsExited {
|
|
ef.Step = 1
|
|
ef.WaitingFor = alienHolder
|
|
ef.ChoiceType = "select_option"
|
|
ef.ChoiceData = map[string]interface{}{
|
|
"message": "有人使用了优等生!你是外星人,是否要装作犯人吐舌头?",
|
|
"options": []interface{}{
|
|
map[string]interface{}{"value": "long", "label": "吐长舌头"},
|
|
map[string]interface{}{"value": "short", "label": "吐短舌头"},
|
|
map[string]interface{}{"value": "none", "label": "不吐舌头"},
|
|
},
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
return e.showHonorResult()
|
|
}
|
|
|
|
if ef.Step == 1 {
|
|
tongue, _ := resp["value"].(string)
|
|
if tongue != "none" {
|
|
alienHolder, _ := ef.TempData["alien_holder"].(string)
|
|
ap := e.GetPlayer(alienHolder)
|
|
name := alienHolder
|
|
if ap != nil {
|
|
name = ap.Nickname
|
|
}
|
|
tongues, _ := ef.TempData["tongues"].([]interface{})
|
|
tongues = append(tongues, map[string]interface{}{"nickname": name, "tongue": tongue})
|
|
ef.TempData["tongues"] = tongues
|
|
}
|
|
return e.showHonorResult()
|
|
}
|
|
|
|
return e.finishEffect()
|
|
}
|
|
|
|
func (e *Engine) showHonorResult() error {
|
|
ef := e.Effect
|
|
tongues, _ := ef.TempData["tongues"].([]interface{})
|
|
msg := fmt.Sprintf("优等生效果:%d人吐了舌头\n", len(tongues))
|
|
for _, t := range tongues {
|
|
tm, _ := t.(map[string]interface{})
|
|
nick, _ := tm["nickname"].(string)
|
|
tongue, _ := tm["tongue"].(string)
|
|
label := "长舌头"
|
|
if tongue == "short" {
|
|
label = "短舌头"
|
|
}
|
|
msg += fmt.Sprintf(" • %s — %s\n", nick, label)
|
|
}
|
|
ef.Step = 99
|
|
ef.WaitingFor = ef.CasterID
|
|
ef.ChoiceType = "view_cards"
|
|
ef.ChoiceData = map[string]interface{}{"message": msg, "tongues": tongues}
|
|
return nil
|
|
}
|
|
|
|
func (e *Engine) finishEffect() error {
|
|
e.Effect = nil
|
|
caster := e.GetPlayer(e.Players[e.CurrentTurn].ID)
|
|
e.finishTurn(caster)
|
|
return nil
|
|
}
|
|
|
|
func (e *Engine) getActivePlayers() []*PlayerState {
|
|
var active []*PlayerState
|
|
for _, p := range e.Players {
|
|
if !p.IsExited && len(p.Hand) > 0 {
|
|
active = append(active, p)
|
|
}
|
|
}
|
|
return active
|
|
}
|
|
|
|
func (e *Engine) CheckInfectedEffect() bool {
|
|
p := e.CurrentPlayer()
|
|
if p == nil || !p.InfectedActive {
|
|
return false
|
|
}
|
|
|
|
still := false
|
|
for _, c := range p.SkillZone {
|
|
if c.TypeID == "infected_person" {
|
|
still = true
|
|
break
|
|
}
|
|
}
|
|
if !still || len(e.HarmonyZone) == 0 {
|
|
p.InfectedActive = false
|
|
return false
|
|
}
|
|
|
|
p.InfectedActive = false
|
|
var hCards []map[string]interface{}
|
|
for _, c := range e.HarmonyZone {
|
|
hCards = append(hCards, map[string]interface{}{"uid": c.UID})
|
|
}
|
|
e.Effect = &EffectState{
|
|
Active: true, CardTypeID: "infected_person", CasterID: p.ID,
|
|
WaitingFor: p.ID, ChoiceType: "select_harmony_card", Step: 0,
|
|
ChoiceData: map[string]interface{}{"cards": hCards, "message": "感染者效果:选择调和区的一张牌加入手牌"},
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (e *Engine) respondInfected(pid string, resp map[string]interface{}) error {
|
|
uid, _ := resp["card_uid"].(string)
|
|
caster := e.GetPlayer(e.Effect.CasterID)
|
|
for i, c := range e.HarmonyZone {
|
|
if c.UID == uid {
|
|
e.HarmonyZone = append(e.HarmonyZone[:i], e.HarmonyZone[i+1:]...)
|
|
caster.Hand = append(caster.Hand, c)
|
|
break
|
|
}
|
|
}
|
|
e.Effect = nil
|
|
return nil
|
|
}
|