game/server/items/effects.go
2026-04-20 16:07:22 +08:00

220 lines
7.2 KiB
Go
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package items
import (
"fmt"
"math/rand"
"wuziqi-server/core"
)
// --- Medkit ---
type MedkitStrategy struct{}
func (s *MedkitStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
if user.Character == "elephant" {
ctx.Logger.Info("Elephant refused medkit")
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "ability", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "medkit",
Message: "🐘 大象无法使用该道具!",
})
return false
}
user.Poisoned = false
user.PoisonSteps = 0
ctx.Logic.HealPlayer(user, 1)
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "medkit", Value: 1,
Message: "💊 使用医疗包回复1血并解除中毒",
})
return true
}
// --- BombTimer ---
type BombTimerStrategy struct{}
func (s *BombTimerStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
user.TimeBombTurns = 3
ctx.Logger.Info("Player %s has a time bomb! Explodes in 3 turns", user.UserID)
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "bomb_timer", Value: 3,
Message: "⏰ 定时炸弹启动3回合后爆炸",
})
return true
}
// --- Poison ---
type PoisonStrategy struct{}
func (s *PoisonStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
target := ctx.Logic.GetRandomAliveTarget(state, user.UserID)
if target != nil {
if target.Character == "sloth" {
ctx.Logger.Info("Sloth resisted poison")
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, TargetID: target.UserID, TargetName: target.Username, ItemID: "poison",
Message: "🦥 树懒免疫了毒药!",
})
} else {
target.Poisoned = true
target.PoisonSteps = 0
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, TargetID: target.UserID, TargetName: target.Username, ItemID: "poison",
Message: fmt.Sprintf("☠️ %s 中毒了!", target.Username),
})
}
}
return true
}
// --- Shield ---
type ShieldStrategy struct{}
func (s *ShieldStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
user.Shield = true
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "shield",
Message: "🛡️ 获得护盾,可抵挡一次伤害!",
})
return true
}
// --- Skip ---
type SkipStrategy struct{}
func (s *SkipStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
user.SkipTurn = true
user.Shield = true
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "skip",
Message: "⏭️ 好人卡:跳过回合并获得护盾!",
})
return true
}
// --- Magnifier ---
type MagnifierStrategy struct{}
func (s *MagnifierStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
for i := 0; i < 100; i++ {
idx := rand.Intn(len(state.Grid))
if !state.Grid[idx].Revealed {
cellType := state.Grid[idx].Type
if state.Grid[idx].Type == "item" {
cellType = state.Grid[idx].ItemID
}
user.RevealedCells[idx] = cellType
coords := state.FormatCoordinates(idx)
contentDesc := core.TranslateCellType(cellType)
msg := fmt.Sprintf("🔍 放大镜:透视了 %s内容是 [%s]", coords, contentDesc)
ctx.Logger.Info("Magnifier: Player %s can now see cell %d (%s) at %s", user.UserID, idx, cellType, coords)
ctx.Logic.SendPrivateEvent(user.UserID, core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "magnifier",
Message: msg,
CellIndex: idx, CellType: cellType,
})
break
}
}
return true
}
// --- Knife ---
type KnifeStrategy struct{}
func (s *KnifeStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
dmg := 1
isAOE := false
// 检查场上是否有存活的老虎(任何玩家是老虎都会触发增强)
for _, p := range state.Players {
if p.Character == "tiger" && p.HP > 0 {
dmg = 2
isAOE = true
break
}
}
if isAOE {
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "knife", Value: dmg,
Message: fmt.Sprintf("🐯🔪 老虎在场!飞刀变为全体攻击,对所有敌人造成%d点伤害", dmg),
})
for _, p := range state.Players {
if p.UserID != user.UserID && p.HP > 0 {
ctx.Logic.ApplyDamage(state, p, dmg, true)
}
}
} else {
target := ctx.Logic.GetRandomAliveTarget(state, user.UserID)
if target != nil {
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, TargetID: target.UserID, TargetName: target.Username, ItemID: "knife", Value: dmg,
Message: fmt.Sprintf("🔪 飞刀命中 %s造成%d点伤害", target.Username, dmg),
})
ctx.Logic.ApplyDamage(state, target, dmg, true)
}
}
return true
}
// --- Revive ---
type ReviveStrategy struct{}
func (s *ReviveStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
if user.Character == "elephant" {
ctx.Logger.Info("Elephant refused revive")
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "ability", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "revive",
Message: "🐘 大象无法使用该道具!",
})
return false
}
user.Revive = true
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "revive",
Message: "💖 获得复活甲,可免疫一次死亡!",
})
return true
}
// --- Lightning ---
type LightningStrategy struct{}
func (s *LightningStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "lightning", Value: 1,
Message: "⚡ 闪电对所有玩家造成1点伤害",
})
for _, p := range state.Players {
ctx.Logic.ApplyDamage(state, p, 1, true)
}
return true
}
// --- Chest ---
type ChestStrategy struct{}
func (s *ChestStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
user.ChestCount++
ctx.Logger.Info("Player %s found a chest! Total chests: %d", user.UserID, user.ChestCount)
ctx.Logic.BroadcastEvent(core.GameEvent{
Type: "item", PlayerID: user.UserID, PlayerName: user.Username, ItemID: "chest", Value: user.ChestCount,
Message: "📦 发现宝箱!游戏结束后可获得奖励!",
})
return true
}
// --- Curse ---
type CurseStrategy struct{}
func (s *CurseStrategy) Use(state *core.GameState, user *core.Player, ctx ItemContext) bool {
user.Curse = true
// 逻辑上诅咒只是设置标志。原始代码中没有广播?
// 嗯,原始代码确实只是设置了标志。
// 我们可以选择添加广播,或者让客户端查看状态图标。
// 如果需要清晰度,我们可以添加广播,但原始代码在 resolveItem 的 switch 诅咒分支中并没有专门的广播...
// 等等,检查原始代码。
// case "curse": player.Curse = true。就这样。
// 我将保持最小化。
return true
}