diff options
Diffstat (limited to 'internal/game/sys_combat.go')
| -rw-r--r-- | internal/game/sys_combat.go | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/internal/game/sys_combat.go b/internal/game/sys_combat.go index bf4f882..e23d94b 100644 --- a/internal/game/sys_combat.go +++ b/internal/game/sys_combat.go @@ -2,9 +2,9 @@ package game import ( "fmt" + "math/rand" "sort" - "thehouseoficarus/internal/engine" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) @@ -68,6 +68,14 @@ func (g *Game) dropItemsOnDeath(p *player.Player) { } } +// aggroChancePerTick is the probability per engine tick that an aggressive mob +// in the player's room initiates combat against them. The first roll happens +// inline on arrival (so a player who enters and immediately moves again — the +// 1-tick single-move case — still risks being caught ~33% of the time); if the +// initial roll fails, a per-tick retry subscriber keeps rolling for any +// subsequent tick the player lingers in the room. +const aggroChancePerTick = 0.33 + func (g *Game) checkAggro(sess *net.Session) { p := sess.Player @@ -97,14 +105,25 @@ func (g *Game) checkAggro(sess *net.Session) { continue } aggMob := mob - g.Ticks.Subscribe(engine.ToTicks(1), func() bool { + + // rollAggro attempts to start combat this instant. It returns true + // when aggro should stop retrying that mob for this player — either + // because it succeeded, because the mob/player is no longer eligible, + // or because the roll failed and the caller subscribed a per-tick + // retry. The retry subscriber returns the negation of the inline + // call's "stop" so it stays subscribed only while the player is + // still a valid target the roll hasn't yet hit. + rollAggro := func() (stop bool) { if g.Combat.Get(p.Name) != nil { - return false + return true } if aggMob.HP <= 0 || aggMob.RoomID != p.RoomID { - return false + return true } if g.Combat.IsMobInCombat(aggMob.InstanceID) { + return true + } + if rand.Float64() >= aggroChancePerTick { return false } attacker := aggMob.Name @@ -113,8 +132,13 @@ func (g *Game) checkAggro(sess *net.Session) { } sess.WriteLine(fmt.Sprintf("%s attacks you!", g.colorize(sess, "mob", attacker))) g.startCombat(sess, p, aggMob) - return false - }) + return true + } + + if rollAggro() { + break + } + g.Ticks.Subscribe(1, func() bool { return !rollAggro() }) break } } |
