예제 #1
0
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
}
예제 #2
0
파일: move.go 프로젝트: genbattle/haunts
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
}
예제 #3
0
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
}
예제 #4
0
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
}