func (a *AoeAttack) Maintain(dt int64, g *game.Game, ae game.ActionExec) game.MaintenanceStatus { if ae != nil { a.exec = ae.(*aoeExec) a.targets = a.getTargetsAt(g, a.exec.X, a.exec.Y) if a.Current_ammo > 0 { a.Current_ammo-- } a.ent = g.EntityById(ae.EntityId()) if !a.ent.HasLos(a.exec.X, a.exec.Y, 1, 1) { base.Error().Printf("Entity %d tried to target position (%d, %d) with an aoe but doesn't have los to it: %v", a.ent.Id, a.exec.X, a.exec.Y, a.exec) return game.Complete } if a.Ap > a.ent.Stats.ApCur() { base.Error().Printf("Got an aoe attack that required more ap than available: %v", a.exec) return game.Complete } a.ent.Stats.ApplyDamage(-a.Ap, 0, status.Unspecified) // Track this information for the ais - the attacking ent will only // remember one ent that it hit, but that's ok for _, target := range a.targets { if target.Side() != a.ent.Side() { target.Info.LastEntThatAttackedMe = a.ent.Id a.ent.Info.LastEntThatIAttacked = target.Id } } } if a.ent.Sprite().State() != "ready" { return game.InProgress } for _, target := range a.targets { if target.Stats.HpCur() > 0 && target.Sprite().State() != "ready" { return game.InProgress } } a.ent.TurnToFace(a.exec.X, a.exec.Y) for _, target := range a.targets { target.TurnToFace(a.ent.Pos()) } a.ent.Sprite().Command(a.Animation) for _, target := range a.targets { if g.DoAttack(a.ent, target, a.Strength, a.Kind) { for _, name := range a.Conditions { target.Stats.ApplyCondition(status.MakeCondition(name)) } target.Stats.ApplyDamage(0, -a.Damage, a.Kind) if target.Stats.HpCur() <= 0 { target.Sprite().CommandN([]string{"defend", "killed"}) } else { target.Sprite().CommandN([]string{"defend", "damaged"}) } } else { target.Sprite().CommandN([]string{"defend", "undamaged"}) } } return game.Complete }
func (a *Move) Maintain(dt int64, g *game.Game, ae game.ActionExec) game.MaintenanceStatus { if ae != nil { exec := ae.(*moveExec) a.ent = g.EntityById(ae.EntityId()) if len(exec.Path) == 0 { base.Error().Printf("Got a move exec with a path length of 0: %v", exec) return game.Complete } a.cost = exec.measureCost(a.ent, g) if a.cost > a.ent.Stats.ApCur() { base.Error().Printf("Got a move that required more ap than available: %v", exec) base.Error().Printf("Path: %v", exec.Path) return game.Complete } if a.cost == -1 { base.Error().Printf("Got a move that followed an invalid path: %v", exec) base.Error().Printf("Path: %v", exec.Path) if a.ent == nil { base.Error().Printf("ENT was Nil!") } else { x, y := a.ent.Pos() v := g.ToVertex(x, y) base.Error().Printf("Ent pos: (%d, %d) -> (%d)", x, y, v) } return game.Complete } algorithm.Map2(exec.Path, &a.path, func(v int) [2]int { _, x, y := g.FromVertex(v) return [2]int{x, y} }) base.Log().Printf("Path Validated: %v", exec) a.ent.Stats.ApplyDamage(-a.cost, 0, status.Unspecified) src := g.ToVertex(a.ent.Pos()) graph := g.Graph(a.ent.Side(), true, nil) a.drawPath(a.ent, g, graph, src) } // Do stuff factor := float32(math.Pow(2, a.ent.Walking_speed)) dist := a.ent.DoAdvance(factor*float32(dt)/200, a.path[0][0], a.path[0][1]) for dist > 0 { if len(a.path) == 1 { a.ent.DoAdvance(0, 0, 0) a.ent.Info.RoomsExplored[a.ent.CurrentRoom()] = true a.ent = nil return game.Complete } a.path = a.path[1:] a.ent.Info.RoomsExplored[a.ent.CurrentRoom()] = true dist = a.ent.DoAdvance(dist, a.path[0][0], a.path[0][1]) } return game.InProgress }
func (a *BasicAttack) Maintain(dt int64, g *game.Game, ae game.ActionExec) game.MaintenanceStatus { if ae != nil { a.exec = ae.(*basicAttackExec) a.ent = g.EntityById(ae.EntityId()) a.target = a.ent.Game().EntityById(a.exec.Target) // Track this information for the ais if a.ent.Side() != a.target.Side() { a.ent.Info.LastEntThatIAttacked = a.target.Id a.target.Info.LastEntThatAttackedMe = a.ent.Id } if a.Ap > a.ent.Stats.ApCur() { base.Error().Printf("Got a basic attack that required more ap than available: %v", a.exec) base.Error().Printf("Ent: %s, Ap: %d", a.ent.Name, a.ent.Stats.ApCur()) return game.Complete } if !a.validTarget(a.ent, a.target) { base.Error().Printf("Got a basic attack that was invalid for some reason: %v", a.exec) return game.Complete } } if a.ent.Sprite().State() == "ready" && a.target.Sprite().State() == "ready" { a.target.TurnToFace(a.ent.Pos()) a.ent.TurnToFace(a.target.Pos()) if a.Current_ammo > 0 { a.Current_ammo-- } a.ent.Stats.ApplyDamage(-a.Ap, 0, status.Unspecified) var defender_cmds []string if g.DoAttack(a.ent, a.target, a.Strength, a.Kind) { for _, name := range a.Conditions { a.target.Stats.ApplyCondition(status.MakeCondition(name)) } a.target.Stats.ApplyDamage(0, -a.Damage, a.Kind) if a.target.Stats.HpCur() <= 0 { defender_cmds = []string{"defend", "killed"} } else { defender_cmds = []string{"defend", "damaged"} } results[a.exec.id] = BasicAttackResult{Hit: true} } else { defender_cmds = []string{"defend", "undamaged"} results[a.exec.id] = BasicAttackResult{Hit: false} } sprites := []*sprite.Sprite{a.ent.Sprite(), a.target.Sprite()} sprite.CommandSync(sprites, [][]string{[]string{a.Animation}, defender_cmds}, "hit") return game.Complete } return game.InProgress }
func (a *Interact) Maintain(dt int64, g *game.Game, ae game.ActionExec) game.MaintenanceStatus { if ae != nil { exec := ae.(*interactExec) a.ent = g.EntityById(ae.EntityId()) if (exec.Target != 0) == (exec.Toggle_door) { base.Error().Printf("Got an interact that tried to target a door and an entity: %v", exec) return game.Complete } if exec.Target != 0 { target := g.EntityById(exec.Target) if target == nil { base.Error().Printf("Tried to interact with an entity that doesn't exist: %v", exec) return game.Complete } if target.ObjectEnt == nil { base.Error().Printf("Tried to interact with an entity that wasn't an object: %v", exec) return game.Complete } if target.Sprite().State() != "ready" { base.Error().Printf("Tried to interact with an object that wasn't in its ready state: %v", exec) return game.Complete } if distBetweenEnts(a.ent, target) > a.Range { base.Error().Printf("Tried to interact with an object that was out of range: %v", exec) return game.Complete } x, y := target.Pos() dx, dy := target.Dims() if !a.ent.HasLos(x, y, dx, dy) { base.Error().Printf("Tried to interact with an object without having los: %v", exec) return game.Complete } a.ent.Stats.ApplyDamage(-a.Ap, 0, status.Unspecified) target.Sprite().Command("inspect") return game.Complete } else { // We're interacting with a door here if exec.Floor < 0 || exec.Floor >= len(g.House.Floors) { base.Error().Printf("Specified an unknown floor %v", exec) return game.Complete } floor := g.House.Floors[exec.Floor] if exec.Room < 0 || exec.Room >= len(floor.Rooms) { base.Error().Printf("Specified an unknown room %v", exec) return game.Complete } room := floor.Rooms[exec.Room] if exec.Door < 0 || exec.Door >= len(room.Doors) { base.Error().Printf("Specified an unknown door %v", exec) return game.Complete } door := room.Doors[exec.Door] x, y := a.ent.Pos() dx, dy := a.ent.Dims() ent_rect := makeIntFrect(x, y, x+dx, y+dy) if !ent_rect.Overlaps(makeRectForDoor(room, door)) { base.Error().Printf("Tried to open a door that was out of range: %v", exec) return game.Complete } _, other_door := floor.FindMatchingDoor(room, door) if other_door != nil { door.SetOpened(!door.IsOpened()) other_door.SetOpened(door.IsOpened()) // if door.IsOpened() { // sound.PlaySound(door.Open_sound) // } else { // sound.PlaySound(door.Shut_sound) // } g.RecalcLos() a.ent.Stats.ApplyDamage(-a.Ap, 0, status.Unspecified) } else { base.Error().Printf("Couldn't find matching door: %v", exec) return game.Complete } } } return game.Complete }