package server import ( "fmt" "log" "time" "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game" ) // CheckCoinCollision prüft ob Spieler Coins einsammelt func (r *Room) CheckCoinCollision(p *ServerPlayer) { if !p.IsAlive || p.IsSpectator { return } playerHitbox := game.Rect{ OffsetX: p.X + r.pDrawOffX + r.pHitboxOffX, OffsetY: p.Y + r.pDrawOffY + r.pHitboxOffY, W: r.pW, H: r.pH, } for _, activeChunk := range r.ActiveChunks { chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID] if !exists { continue } for objIdx, obj := range chunkDef.Objects { assetDef, ok := r.World.Manifest.Assets[obj.AssetID] if !ok || assetDef.Type != "coin" { continue } coinKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx) if r.CollectedCoins[coinKey] { continue } coinHitbox := game.Rect{ OffsetX: activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX, OffsetY: obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY, W: assetDef.Hitbox.W, H: assetDef.Hitbox.H, } if game.CheckRectCollision(playerHitbox, coinHitbox) { r.CollectedCoins[coinKey] = true p.BonusScore += 200 p.Score = p.DistanceScore + p.BonusScore log.Printf("💰 %s hat Coin eingesammelt! Score: %d", p.Name, p.Score) } } } } // CheckPowerupCollision prüft ob Spieler Powerups einsammelt func (r *Room) CheckPowerupCollision(p *ServerPlayer) { if !p.IsAlive || p.IsSpectator { return } playerHitbox := game.Rect{ OffsetX: p.X + r.pDrawOffX + r.pHitboxOffX, OffsetY: p.Y + r.pDrawOffY + r.pHitboxOffY, W: r.pW, H: r.pH, } for _, activeChunk := range r.ActiveChunks { chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID] if !exists { continue } for objIdx, obj := range chunkDef.Objects { assetDef, ok := r.World.Manifest.Assets[obj.AssetID] if !ok || assetDef.Type != "powerup" { continue } powerupKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx) if r.CollectedPowerups[powerupKey] { continue } powerupHitbox := game.Rect{ OffsetX: activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX, OffsetY: obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY, W: assetDef.Hitbox.W, H: assetDef.Hitbox.H, } if game.CheckRectCollision(playerHitbox, powerupHitbox) { r.CollectedPowerups[powerupKey] = true switch obj.AssetID { case "jumpboost": p.HasDoubleJump = true p.DoubleJumpUsed = false p.DoubleJumpEndTime = time.Now().Add(15 * time.Second) log.Printf("⚡ %s hat Double Jump erhalten! (15 Sekunden)", p.Name) case "godmode": p.HasGodMode = true p.GodModeEndTime = time.Now().Add(10 * time.Second) log.Printf("🛡️ %s hat Godmode erhalten! (10 Sekunden)", p.Name) case "magnet": p.HasMagnet = true p.MagnetEndTime = time.Now().Add(8 * time.Second) log.Printf("🧲 %s hat Magnet erhalten! (8 Sekunden)", p.Name) } } } } } // ApplyMagnetEffect sammelt alle Coins im Umkreis von ~300px automatisch ein func (r *Room) ApplyMagnetEffect(p *ServerPlayer) { const magnetRadius = 300.0 playerCenterX := p.X + r.pDrawOffX + r.pHitboxOffX + r.pW/2 playerCenterY := p.Y + r.pDrawOffY + r.pHitboxOffY + r.pH/2 for _, activeChunk := range r.ActiveChunks { chunkDef, exists := r.World.ChunkLibrary[activeChunk.ChunkID] if !exists { continue } for objIdx, obj := range chunkDef.Objects { assetDef, ok := r.World.Manifest.Assets[obj.AssetID] if !ok || assetDef.Type != "coin" { continue } coinKey := fmt.Sprintf("%s_%d", activeChunk.ChunkID, objIdx) if r.CollectedCoins[coinKey] { continue } coinCenterX := activeChunk.X + obj.X + assetDef.DrawOffX + assetDef.Hitbox.OffsetX + assetDef.Hitbox.W/2 coinCenterY := obj.Y + assetDef.DrawOffY + assetDef.Hitbox.OffsetY + assetDef.Hitbox.H/2 dx := coinCenterX - playerCenterX dy := coinCenterY - playerCenterY if dx*dx+dy*dy <= magnetRadius*magnetRadius { r.CollectedCoins[coinKey] = true p.BonusScore += 200 p.Score = p.DistanceScore + p.BonusScore log.Printf("🧲 %s hat Coin per Magnet eingesammelt! Score: %d", p.Name, p.Score) } } } } // UpdateDistanceScore aktualisiert Distanz-basierte Punkte func (r *Room) UpdateDistanceScore() { if r.Status != "RUNNING" { return } aliveCount := 0 for _, p := range r.Players { if p.IsAlive && !p.IsSpectator { aliveCount++ } } if aliveCount == 0 { return } for _, p := range r.Players { if p.IsAlive && !p.IsSpectator { p.DistanceScore += aliveCount p.Score = p.DistanceScore + p.BonusScore } } } // KillPlayer markiert Spieler als tot func (r *Room) KillPlayer(p *ServerPlayer) { if !p.IsAlive { return } p.IsAlive = false p.IsSpectator = true log.Printf("💀 %s ist gestorben! Final Score: %d", p.Name, p.Score) aliveCount := 0 for _, pl := range r.Players { if pl.IsAlive && !pl.IsSpectator { aliveCount++ } } if aliveCount == 0 && r.Status == "RUNNING" { log.Printf("🏁 Alle Spieler tot - Game Over!") r.Status = "GAMEOVER" } }