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 *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 (e *Entity) SetGear(gear_name string) bool { if e.ExplorerEnt == nil { base.Error().Printf("Tried to set gear on a non-explorer entity.") return false } if e.ExplorerEnt.Gear != nil && gear_name != "" { base.Error().Printf("Tried to set gear on an explorer that already had gear.") return false } if e.ExplorerEnt.Gear == nil && gear_name == "" { base.Error().Printf("Tried to remove gear from an explorer with no gear.") return false } if gear_name == "" { algorithm.Choose(&e.Actions, func(a Action) bool { return a.String() != e.ExplorerEnt.Gear.Action }) if e.ExplorerEnt.Gear.Condition != "" { e.Stats.RemoveCondition(e.ExplorerEnt.Gear.Condition) } e.ExplorerEnt.Gear = nil return true } var g Gear g.Defname = gear_name base.GetObject("gear", &g) if g.Name == "" { base.Error().Printf("Tried to load gear '%s' that doesn't exist.", gear_name) return false } e.ExplorerEnt.Gear = &g if g.Action != "" { e.Actions = append(e.Actions, MakeAction(g.Action)) } if g.Condition != "" { e.Stats.ApplyCondition(status.MakeCondition(g.Condition)) } return true }
func ConditionsSpec(c gospec.Context) { c.Specify("Conditions are loaded properly.", func() { basic := status.MakeCondition("Basic Test") _, ok := basic.(*status.BasicCondition) c.Expect(ok, Equals, true) c.Expect(basic.Strength(), Equals, 5) c.Expect(basic.Kind(), Equals, status.Fire) var b status.Base b = basic.ModifyBase(b, status.Unspecified) c.Expect(b.Attack, Equals, 3) }) c.Specify("Conditions can be gobbed without loss of type.", func() { buf := bytes.NewBuffer(nil) enc := gob.NewEncoder(buf) var cs []status.Condition cs = append(cs, status.MakeCondition("Basic Test")) err := enc.Encode(cs) c.Assume(err, Equals, nil) dec := gob.NewDecoder(buf) var cs2 []status.Condition err = dec.Decode(&cs2) c.Assume(err, Equals, nil) _, ok := cs2[0].(*status.BasicCondition) c.Expect(ok, Equals, true) }) c.Specify("Conditions stack properly", func() { var s status.Inst fd := status.MakeCondition("Fire Debuff Attack") pd := status.MakeCondition("Poison Debuff Attack") pd2 := status.MakeCondition("Poison Debuff Attack 2") c.Expect(s.AttackBonusWith(status.Unspecified), Equals, 0) s.ApplyCondition(pd) c.Expect(s.AttackBonusWith(status.Unspecified), Equals, -1) s.ApplyCondition(fd) c.Expect(s.AttackBonusWith(status.Unspecified), Equals, -2) s.ApplyCondition(fd) c.Expect(s.AttackBonusWith(status.Unspecified), Equals, -2) s.ApplyCondition(pd) c.Expect(s.AttackBonusWith(status.Unspecified), Equals, -2) s.ApplyCondition(pd2) c.Expect(s.AttackBonusWith(status.Unspecified), Equals, -3) }) c.Specify("Resistances work", func() { var s status.Inst fr1 := status.MakeCondition("Fire Resistance") fr2 := status.MakeCondition("Greater Fire Resistance") c.Expect(s.CorpusVs("Fire"), Equals, s.CorpusVs("Unspecified")) s.ApplyCondition(fr1) c.Expect(s.CorpusVs("Fire"), Equals, s.CorpusVs("Unspecified")+1) c.Expect(s.CorpusVs("Panic"), Equals, s.CorpusVs("Unspecified")) c.Expect(s.CorpusVs("Brutal"), Equals, s.CorpusVs("Unspecified")) s.ApplyCondition(fr2) c.Expect(s.CorpusVs("Fire"), Equals, s.CorpusVs("Unspecified")+3) c.Expect(s.CorpusVs("Panic"), Equals, s.CorpusVs("Unspecified")) c.Expect(s.CorpusVs("Brutal"), Equals, s.CorpusVs("Unspecified")) }) c.Specify("Basic conditions last the appropriate amount of time", func() { var s status.Inst s.UnmarshalJSON([]byte(` { "Base": { "Hp_max": 100, "Ap_max": 10 }, "Dynamic": { "Hp": 100 } }`)) pd := status.MakeCondition("Poison Debuff Attack") pd2 := status.MakeCondition("Poison Debuff Attack 2") pd.Strength() pd2.Strength() c.Expect(s.HpCur(), Equals, 100) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) c.Expect(s.HpCur(), Equals, 100) s.OnRound() c.Expect(s.HpCur(), Equals, 99) s.OnRound() c.Expect(s.HpCur(), Equals, 98) s.OnRound() c.Expect(s.HpCur(), Equals, 97) s.OnRound() c.Expect(s.HpCur(), Equals, 97) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 96) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 95) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 94) s.OnRound() c.Expect(s.HpCur(), Equals, 93) s.OnRound() c.Expect(s.HpCur(), Equals, 92) s.OnRound() c.Expect(s.HpCur(), Equals, 92) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.ApplyCondition(status.MakeCondition("Poison Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 90) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 88) s.OnRound() c.Expect(s.HpCur(), Equals, 86) s.OnRound() c.Expect(s.HpCur(), Equals, 85) s.OnRound() c.Expect(s.HpCur(), Equals, 85) s.ApplyCondition(status.MakeCondition("Fire Debuff Attack")) s.ApplyCondition(status.MakeCondition("Poison Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 83) s.ApplyCondition(status.MakeCondition("Poison Debuff Attack 2")) s.OnRound() c.Expect(s.HpCur(), Equals, 80) s.ApplyCondition(status.MakeCondition("Poison Debuff Attack")) s.OnRound() c.Expect(s.HpCur(), Equals, 77) s.OnRound() c.Expect(s.HpCur(), Equals, 75) s.OnRound() c.Expect(s.HpCur(), Equals, 75) }) }