func WaypointsFunc(me *game.Entity) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "Waypoints") { return 0 } g := me.Game() L.NewTable() count := 0 for _, wp := range g.Waypoints { if wp.Side != me.Side() { continue } count++ L.PushInteger(count) L.NewTable() L.PushString("Name") L.PushString(wp.Name) L.SetTable(-3) L.PushString("Radius") L.PushNumber(wp.Radius) L.SetTable(-3) L.PushString("Pos") game.LuaPushPoint(L, int(wp.X), int(wp.Y)) L.SetTable(-3) L.SetTable(-3) } return 1 } }
func (exec *moveExec) measureCost(ent *game.Entity, g *game.Game) int { if len(exec.Path) == 0 { base.Error().Printf("Zero length path") return -1 } if g.ToVertex(ent.Pos()) != exec.Path[0] { base.Error().Printf("Path doesn't begin at ent's position, %d != %d", g.ToVertex(ent.Pos()), exec.Path[0]) return -1 } graph := g.Graph(ent.Side(), true, nil) v := g.ToVertex(ent.Pos()) cost := 0 for _, step := range exec.Path[1:] { dsts, costs := graph.Adjacent(v) ok := false prev := v base.Log().Printf("Adj(%d):", v) for j := range dsts { base.Log().Printf("Node %d", dsts[j]) if dsts[j] == step { cost += int(costs[j]) v = dsts[j] ok = true break } } base.Log().Printf("%d -> %d: %t", prev, v, ok) if !ok { return -1 } } return cost }
func (a *Move) AiMoveToPos(ent *game.Entity, dst []int, max_ap int) game.ActionExec { base.Log().Printf("PATH: Request move to %v", dst) graph := ent.Game().Graph(ent.Side(), false, nil) src := []int{ent.Game().ToVertex(ent.Pos())} _, path := algorithm.Dijkstra(graph, src, dst) base.Log().Printf("PATH: Found path of length %d", len(path)) ppx, ppy := ent.Pos() if path == nil { return nil } _, xx, yy := ent.Game().FromVertex(path[len(path)-1]) base.Log().Printf("PATH: %d,%d -> %d,%d", ppx, ppy, xx, yy) if ent.Stats.ApCur() < max_ap { max_ap = ent.Stats.ApCur() } path = limitPath(ent, src[0], path, max_ap) _, xx, yy = ent.Game().FromVertex(path[len(path)-1]) base.Log().Printf("PATH: (limited) %d,%d -> %d,%d", ppx, ppy, xx, yy) if len(path) <= 1 { return nil } var exec moveExec exec.SetBasicData(ent, a) exec.Path = path return &exec }
func (a *AoeAttack) AiBestTarget(ent *game.Entity, extra_dist int, spec AiAoeTarget) (x, y int, targets []*game.Entity) { ex, ey := ent.Pos() max := 0 best_dist := 10000 var bx, by int var radius int if a.Range > 0 { radius += a.Range } if extra_dist > 0 { radius += extra_dist } for x := ex - radius; x <= ex+radius; x++ { for y := ey - radius; y <= ey+radius; y++ { if !ent.HasLos(x, y, 1, 1) { continue } targets = a.getTargetsAt(ent.Game(), x, y) ok := true count := 0 for i := range targets { if targets[i].Side() != ent.Side() { count++ } else if ent.Side() == game.SideHaunt && spec == AiAoeHitMinionsOk { if targets[i].HauntEnt == nil || targets[i].HauntEnt.Level != game.LevelMinion { ok = false } } else if spec != AiAoeHitAlliesOk { ok = false } } dx := x - ex if dx < 0 { dx = -dx } dy := y - ey if dy < 0 { dy = -dy } dist := dx if dy > dx { dist = dy } if ok && (count > max || count == max && dist < best_dist) { max = count best_dist = dist bx, by = x, y } } } return bx, by, a.getTargetsAt(ent.Game(), bx, by) }
func (a *Move) findPath(ent *game.Entity, x, y int) { g := ent.Game() dst := g.ToVertex(x, y) if dst != a.dst || !a.calculated { a.dst = dst a.calculated = true src := g.ToVertex(a.ent.Pos()) graph := g.Graph(ent.Side(), true, nil) cost, path := algorithm.Dijkstra(graph, []int{src}, []int{dst}) if len(path) <= 1 { return } algorithm.Map2(path, &a.path, func(a int) [2]int { _, x, y := g.FromVertex(a) return [2]int{int(x), int(y)} }) a.cost = int(cost) a.drawPath(ent, g, graph, src) } }
func limitPath(ent *game.Entity, start int, path []int, max int) []int { total := 0 graph := ent.Game().Graph(ent.Side(), true, nil) for last := 1; last < len(path); last++ { adj, cost := graph.Adjacent(start) found := false for index := range adj { if adj[index] == path[last] { total += int(cost[index]) if total > max { return path[0:last] } start = adj[index] found = true break } } if !found { base.Log().Printf("PATH: DIdn't find, %d / %d", last+1, len(path)) return path[0:last] } } return path }
func (a *BasicAttack) validTarget(source, target *game.Entity) bool { if source.Stats == nil || target.Stats == nil { return false } if distBetweenEnts(source, target) > a.Range { return false } x2, y2 := target.Pos() dx, dy := target.Dims() if !source.HasLos(x2, y2, dx, dy) { return false } if target.Stats.HpCur() <= 0 { return false } if source.Side() == target.Side() && !a.Target_allies { return false } if source.Side() != target.Side() && !a.Target_enemies { return false } return true }