func (p *PlayerEnt) Supply(mana Mana) Mana { base.DoOrdered(p.Processes, func(a, b int) bool { return a < b }, func(id int, proc Process) { mana = proc.Supply(mana) }) return mana }
func (cp *ControlPoint) Supply(mana Mana) Mana { base.DoOrdered(cp.Processes, func(a, b int) bool { return a < b }, func(id int, proc Process) { mana = proc.Supply(mana) }) return mana }
func (g *Game) DoForEnts(f func(Gid, Ent)) { base.DoOrdered(g.Ents, lessGids, f) }
func (g *Game) ThinkGame() { // cache wall data if g.local.temp.AllWalls == nil || g.local.temp.AllWallsDirty { g.local.temp.AllWallsDirty = false g.local.temp.AllWalls = nil g.local.temp.WallCache = nil g.local.temp.VisibleWallCache = nil // Can't use a nil slice, otherwise we'll run this block every Think for levels // with no walls. allWalls := make([]linear.Seg2, 0) base.DoOrdered(g.Level.Room.Walls, func(a, b string) bool { return a < b }, func(_ string, walls linear.Poly) { for i := range walls { allWalls = append(allWalls, walls.Seg(i)) } }) g.local.temp.AllWalls = allWalls g.local.temp.WallCache = &wallCache{} g.local.temp.WallCache.SetWalls(g.Level.Room.Dx, g.Level.Room.Dy, allWalls, 100) g.local.temp.VisibleWallCache = &wallCache{} g.local.temp.VisibleWallCache.SetWalls(g.Level.Room.Dx, g.Level.Room.Dy, allWalls, stats.LosPlayerHorizon) g.local.pathingData = makePathingData(&g.Level.Room) } // cache ent data for _, ent := range g.local.temp.AllEnts { if ent.Dead() { if _, ok := ent.(*PlayerEnt); ok { var id int64 _, err := fmt.Sscanf(string(ent.Id()), "Engine:%d", &id) if err != nil { _, err = fmt.Sscanf(string(ent.Id()), "Ai:%d", &id) id = -id // Ai's engine ids are negative } if err != nil { base.Error().Printf("Unable to parse player id '%v'", ent.Id()) } else { if engineData, ok := g.Engines[id]; ok { if !ok { base.Error().Printf("Unable to find engine %d for player %v", id, ent.Id()) } else { engineData.CountdownFrames = 60 * 10 base.Log().Printf("%v died, counting down....", *engineData) } } } } ent.OnDeath(g) g.RemoveEnt(ent.Id()) } } // Death countdown base.DoOrdered(g.Engines, func(a, b int64) bool { return a < b }, func(_ int64, engineData *PlayerData) { if engineData.CountdownFrames > 0 { engineData.CountdownFrames-- if engineData.CountdownFrames == 0 { g.AddPlayers([]*PlayerData{engineData}) } } }) if g.local.temp.AllEnts == nil || g.local.temp.AllEntsDirty { g.local.temp.AllEnts = g.local.temp.AllEnts[0:0] g.DoForEnts(func(gid Gid, ent Ent) { g.local.temp.AllEnts = append(g.local.temp.AllEnts, ent) }) g.local.temp.AllEntsDirty = false } if g.local.temp.EntGrid == nil { g.local.temp.EntGrid = MakeEntCache(g.Level.Room.Dx, g.Level.Room.Dy) } g.local.temp.EntGrid.SetEnts(g.local.temp.AllEnts) for _, proc := range g.Processes { proc.Think(g) } algorithm.Choose(&g.Processes, func(proc Process) bool { return !proc.Dead() }) // Advance players, check for collisions, add segments eps := 1.0e-3 for _, ent := range g.local.temp.AllEnts { ent.Think(g) for _, ab := range ent.Abilities() { ab.Think(ent, g) } pos := ent.Pos() pos.X = clamp(pos.X, eps, float64(g.Level.Room.Dx)-eps) pos.Y = clamp(pos.Y, eps, float64(g.Level.Room.Dy)-eps) ent.SetPos(pos) } var nearby []Ent for i := 0; i < len(g.local.temp.AllEnts); i++ { outerEnt := g.local.temp.AllEnts[i] outerSize := outerEnt.Stats().Size() if outerSize == 0 { continue } g.local.temp.EntGrid.EntsInRange(outerEnt.Pos(), 100, &nearby) for _, innerEnt := range nearby { innerSize := innerEnt.Stats().Size() if innerSize == 0 { continue } distSq := outerEnt.Pos().Sub(innerEnt.Pos()).Mag2() colDist := innerSize + outerSize if distSq > colDist*colDist { continue } if distSq < 0.015625 { // this means that dist < 0.125 continue } dist := math.Sqrt(distSq) force := 50.0 * (colDist - dist) innerEnt.ApplyForce(innerEnt.Pos().Sub(outerEnt.Pos()).Scale(force / dist)) } } g.Level.ManaSource.Think(g.Ents) }
func (u SetupComplete) Apply(_g interface{}) { g := _g.(*Game) if g.Setup == nil { return } sideCount := make(map[int]int) // Must have at least two sides sideCount[0] = 0 sideCount[1] = 0 for _, spd := range g.Setup.Players { sideCount[spd.Side]++ } g.Engines = make(map[int64]*PlayerData) for id, player := range g.Setup.Players { var gid Gid if id < 0 { gid = Gid(fmt.Sprintf("Ai:%d", -id)) } else { gid = Gid(fmt.Sprintf("Engine:%d", id)) } g.Engines[id] = &PlayerData{ PlayerGid: Gid(gid), Side: player.Side, ChampIndex: player.ChampIndex, } } // Now that we have the information we can set up a lot of the local data for // this engine's player. if g.IsPlaying() { g.local.Side = g.Engines[g.local.Engine.Id()].Side g.local.Gid = g.Engines[g.local.Engine.Id()].PlayerGid g.local.Data = g.Engines[g.local.Engine.Id()] } var room Room err := base.LoadJson(filepath.Join(base.GetDataDir(), "rooms/basic.json"), &room) if err != nil { base.Error().Fatalf("%v", err) } errs := room.Validate() for _, err := range errs { base.Error().Printf("%v", err) } if len(errs) > 0 { base.Error().Fatalf("Errors with the level, bailing...") } g.Level = &Level{} g.Level.Room = room g.Rng = cmwc.MakeGoodCmwc() g.Rng.Seed(u.Seed) g.Ents = make(map[Gid]Ent) g.Friction = 0.97 g.losCache = makeLosCache(g.Level.Room.Dx, g.Level.Room.Dy) sides := make(map[int][]int64) var playerDatas []*PlayerData base.DoOrdered(g.Engines, func(a, b int64) bool { return a < b }, func(id int64, data *PlayerData) { sides[data.Side] = append(sides[data.Side], id) playerDatas = append(playerDatas, data) }) for id, ed := range g.Engines { base.Log().Printf("%v -> %v", id, *ed) } g.AddPlayers(playerDatas) g.MakeControlPoints() g.Init() base.Log().Printf("Nillifying g.Setup()") g.Setup = nil }