v0.1.0 initial commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"symph/parameter"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Status is the persistent player effect state granted by items. It survives a
|
||||
// level change and is cleared on restart. Timed effects hold an absolute
|
||||
// deadline, charge effects a count. Adding an effect adds a field here plus a
|
||||
// row in resolvers — the pause/interlude shift and the restart clear are
|
||||
// already funneled through this type
|
||||
type Status struct {
|
||||
BoostUntil time.Time // zero or past = inactive
|
||||
Shield int // charges; each absorbs one negative contact. No expiry
|
||||
}
|
||||
|
||||
// Shielded reports whether an absorb charge is held
|
||||
func (s Status) Shielded() bool { return s.Shield > 0 }
|
||||
|
||||
// Boosted reports whether a Boost is active at instant t. Drives the tempo
|
||||
// (deltaAt, evaluated at beat boundaries) and hazard immunity (hitHazard,
|
||||
// evaluated at the contact instant)
|
||||
func (s Status) Boosted(t time.Time) bool {
|
||||
return !s.BoostUntil.IsZero() && t.Before(s.BoostUntil)
|
||||
}
|
||||
|
||||
// BoostRemaining reports the Boost span left at t; 0 when inactive
|
||||
func (s Status) BoostRemaining(t time.Time) time.Duration {
|
||||
if !s.Boosted(t) {
|
||||
return 0
|
||||
}
|
||||
return s.BoostUntil.Sub(t)
|
||||
}
|
||||
|
||||
// shift moves every absolute deadline forward by d, holding the remaining span
|
||||
// across a pause or a level-clear interlude
|
||||
// `at` is the instant the dead span opened. A deadline already lapsed
|
||||
// at `at` is cleared, not shifted — dead time never revives an effect
|
||||
func (s *Status) shift(at time.Time, d time.Duration) {
|
||||
if s.BoostUntil.IsZero() {
|
||||
return
|
||||
}
|
||||
if !s.Boosted(at) {
|
||||
s.BoostUntil = time.Time{}
|
||||
return
|
||||
}
|
||||
s.BoostUntil = s.BoostUntil.Add(d)
|
||||
}
|
||||
|
||||
// grantShield arms the absorb charge. Charges do not stack: a pickup while
|
||||
// shielded re-arms
|
||||
func (s *Status) grantShield() { s.Shield = parameter.ShieldCharges }
|
||||
|
||||
// grantBoost re-arms the tempo deadline
|
||||
func (s *Status) grantBoost(now time.Time) { s.BoostUntil = now.Add(parameter.BoostDuration) }
|
||||
|
||||
// absorb spends one charge; reports whether one was held
|
||||
func (s *Status) absorb() bool {
|
||||
if s.Shield <= 0 {
|
||||
return false
|
||||
}
|
||||
s.Shield--
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user