func (exec basicAttackExec) Push(L *lua.State, g *game.Game) { exec.BasicActionExec.Push(L, g) if L.IsNil(-1) { return } target := g.EntityById(exec.Target) L.PushString("Target") game.LuaPushEntity(L, target) L.SetTable(-3) }
func (a *Ai) addEntityContext() { a.loadUtils("entity") game.LuaPushEntity(a.L, a.ent) a.L.SetGlobal("Me") a.L.NewTable() game.LuaPushSmartFunctionTable(a.L, game.FunctionTable{ "BasicAttack": func() { a.L.PushGoFunction(DoBasicAttackFunc(a)) }, "AoeAttack": func() { a.L.PushGoFunction(DoAoeAttackFunc(a)) }, "Move": func() { a.L.PushGoFunction(DoMoveFunc(a)) }, "DoorToggle": func() { a.L.PushGoFunction(DoDoorToggleFunc(a)) }, "InteractWithObject": func() { a.L.PushGoFunction(DoInteractWithObjectFunc(a)) }, }) a.L.SetMetaTable(-2) a.L.SetGlobal("Do") a.L.NewTable() game.LuaPushSmartFunctionTable(a.L, game.FunctionTable{ "AllPathablePoints": func() { a.L.PushGoFunction(AllPathablePointsFunc(a)) }, "RangedDistBetweenPositions": func() { a.L.PushGoFunction(RangedDistBetweenPositionsFunc(a)) }, "RangedDistBetweenEntities": func() { a.L.PushGoFunction(RangedDistBetweenEntitiesFunc(a)) }, "NearestNEntities": func() { a.L.PushGoFunction(NearestNEntitiesFunc(a.ent)) }, "Waypoints": func() { a.L.PushGoFunction(WaypointsFunc(a.ent)) }, "Exists": func() { a.L.PushGoFunction(ExistsFunc(a)) }, "BestAoeAttackPos": func() { a.L.PushGoFunction(BestAoeAttackPosFunc(a)) }, "NearbyUnexploredRooms": func() { a.L.PushGoFunction(NearbyUnexploredRoomsFunc(a)) }, "RoomPath": func() { a.L.PushGoFunction(RoomPathFunc(a)) }, "RoomContaining": func() { a.L.PushGoFunction(RoomContainingFunc(a)) }, "RoomsAreEqual": func() { a.L.PushGoFunction(RoomAreEqualFunc(a)) }, "AllDoorsBetween": func() { a.L.PushGoFunction(AllDoorsBetween(a)) }, "AllDoorsOn": func() { a.L.PushGoFunction(AllDoorsOn(a)) }, "DoorPositions": func() { a.L.PushGoFunction(DoorPositionsFunc(a)) }, "DoorIsOpen": func() { a.L.PushGoFunction(DoorIsOpenFunc(a)) }, "RoomPositions": func() { a.L.PushGoFunction(RoomPositionsFunc(a)) }, "Rand": func() { a.L.PushGoFunction(randFunc(a)) }, }) a.L.SetMetaTable(-2) a.L.SetGlobal("Utils") a.L.NewTable() game.LuaPushSmartFunctionTable(a.L, game.FunctionTable{ "GetEntsByName": func() { a.L.PushGoFunction(GetEntsByName(a)) }, }) a.L.SetMetaTable(-2) a.L.SetGlobal("Cheat") }
func (exec interactExec) Push(L *lua.State, g *game.Game) { exec.BasicActionExec.Push(L, g) if L.IsNil(-1) { return } L.PushString("Toggle Door") L.PushBoolean(exec.Toggle_door) L.SetTable(-3) if exec.Toggle_door { L.PushString("Door") game.LuaPushDoor(L, g, exec.getDoor(g)) } else { L.PushString("Target") game.LuaPushEntity(L, g.EntityById(exec.Target)) } L.SetTable(-3) }
func allMinions(a *Ai) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "AllMinions") { return 0 } L.NewTable() count := 0 for _, ent := range a.game.Ents { if ent.HauntEnt != nil { count++ L.PushInteger(count) game.LuaPushEntity(L, ent) L.SetTable(-3) } } return 1 } }
func GetEntsByName(a *Ai) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "GetEntsByName", game.LuaString) { return 0 } name := L.ToString(-1) count := 1 L.NewTable() for _, ent := range a.game.Ents { if ent.Name == name { L.PushInteger(count) count++ game.LuaPushEntity(L, ent) L.SetTable(-3) } } return 1 } }
// Performs an aoe attack against centered at the specified position. // Format: // target = BestAoeAttackPos(attack, extra_dist, spec) // // Inputs: // attack - string - Name of the attack to use. // extra_dist - integer - Available distance to move before attacking. // spec - string - One of the following values: // "allies ok", "minions ok", "enemies only" // // Outputs: // pos - table[x,y] - Position to place aoe for maximum results. // hits - array[ents] - Visible entities that will be in the aoe func BestAoeAttackPosFunc(a *Ai) lua.GoFunction { return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "BestAoeAttackPos", game.LuaString, game.LuaInteger, game.LuaString) { return 0 } me := a.ent name := L.ToString(-3) action := getActionByName(me, name) if action == nil { game.LuaDoError(L, fmt.Sprintf("Entity '%s' (id=%d) has no action named '%s'.", me.Name, me.Id, name)) return 0 } attack, ok := action.(*actions.AoeAttack) if !ok { game.LuaDoError(L, fmt.Sprintf("Action '%s' is not an aoe attack.", name)) return 0 } var spec actions.AiAoeTarget switch L.ToString(-1) { case "allies ok": spec = actions.AiAoeHitAlliesOk case "minions ok": spec = actions.AiAoeHitMinionsOk case "enemies only": spec = actions.AiAoeHitNoAllies default: game.LuaDoError(L, fmt.Sprintf("'%s' is not a valid value of spec for BestAoeAttackPos().", L.ToString(-1))) return 0 } x, y, hits := attack.AiBestTarget(me, L.ToInteger(-2), spec) game.LuaPushPoint(L, x, y) L.NewTable() for i := range hits { L.PushInteger(i + 1) game.LuaPushEntity(L, hits[i]) L.SetTable(-3) } return 2 } }
// Returns an array of all entities of a specified type that are in this // entity's los. The entities in the array will be sorted in ascending order // of distance from this entity. // Format // ents = nearestNEntites(max, kind) // // Input: // max - integer - Maximum number of entities to return // kind - string - One of "intruder" "denizen" "minion" "servitor" // "master" "non-minion" "non-servitor" "non-master" and // "all". The "non-*" parameters indicate denizens only // (i.e. will *not* include intruders) that are not of the // type specified. // // Output: // ents - array[integer] - Array of entity ids. func NearestNEntitiesFunc(me *game.Entity) lua.GoFunction { valid_kinds := map[string]bool{ "intruder": true, "denizen": true, "minion": true, "servitor": true, "master": true, "object": true, } return func(L *lua.State) int { if !game.LuaCheckParamsOk(L, "NearestNEntities", game.LuaInteger, game.LuaString) { return 0 } g := me.Game() max := L.ToInteger(-2) kind := L.ToString(-1) if !valid_kinds[kind] { err_str := fmt.Sprintf("NearestNEntities expects kind in the set ['intruder' 'denizen' 'servitor' 'master' 'minion'], got %s.", kind) base.Warn().Printf(err_str) L.PushString(err_str) L.Error() return 0 } var eds entityDistSlice for _, ent := range g.Ents { if ent.Stats != nil && ent.Stats.HpCur() <= 0 { continue } switch kind { case "intruder": if ent.Side() != game.SideExplorers { continue } case "denizen": if ent.Side() != game.SideHaunt { continue } case "minion": if ent.HauntEnt == nil || ent.HauntEnt.Level != game.LevelMinion { continue } case "servitor": if ent.HauntEnt == nil || ent.HauntEnt.Level != game.LevelServitor { continue } case "master": if ent.HauntEnt == nil || ent.HauntEnt.Level != game.LevelMaster { continue } case "object": if ent.ObjectEnt == nil { continue } } x, y := ent.Pos() dx, dy := ent.Dims() if !me.HasTeamLos(x, y, dx, dy) { continue } eds = append(eds, entityDist{rangedDistBetween(me, ent), ent}) } // TODO: ONLY GUYS THAT EXIST sort.Sort(eds) if max > len(eds) { max = len(eds) } if max < 0 { max = 0 } eds = eds[0:max] // eds contains the results, in order. Now we make a lua table and // populate it with the entity ids of the results. L.NewTable() for i := range eds { L.PushInteger(i + 1) game.LuaPushEntity(L, eds[i].ent) L.SetTable(-3) } return 1 } }