package event
Package event is where a map script says what should happen when: register a function for an event and the game calls it at the right step. Registration goes in the script's main function (or in an init function); the game runs main once, before the map starts.
Every On... function returns a Handle. Ignore it for a hook that stays for the whole game; keep it to disable, enable again or remove the hook later (even from inside the hook itself):
var h event.Handle
h = event.OnUnitDied(func(u game.Unit) {
game.Print("first death:", u.ID())
h.Remove() // a one-shot
})A hook that is disabled or removed is not called again, not even for the events of the step it was switched off in, and the engine stops sending its kind of event when no enabled hook is left for it, so a hook nobody needs costs nothing. Hooks of one kind are called in the order they were registered, events in the order they happened. The state of every hook lives in the script's memory, so it is saved with the game (checkpoints, saves, replays).
import "w4/event"Constants and variables
const StepsPerSecond = 30Steps per second of the simulation.
Types
AbilityCastEvent
type AbilityCastEvent struct {
Caster game.Unit
// Target is the unit aimed at; its ID is -1 for a cast with no unit target.
Target game.Unit
// HasPoint says the cast was aimed at a spot (X, Y), in world units from the middle of the map.
HasPoint bool
X, Y float64
// Ability is the id of the ability's definition, as the editor shows it.
Ability string
}AbilityCastEvent is a cast that went through (cost paid, cooldown started).
AbilityHitEvent
type AbilityHitEvent struct {
Caster, Target game.Unit
// Ability is the id of the ability's definition, as the editor shows it.
Ability string
}AbilityHitEvent is an ability's effects reaching one unit.
BlockedEvent
type BlockedEvent struct {
Target game.Unit
Prevented int
}BlockedEvent is part of a blow being blocked.
CastInterruptedEvent
type CastInterruptedEvent struct {
Unit game.Unit
// Ability is the id of the ability's definition, as the editor shows it.
Ability string
}CastInterruptedEvent is a cast cut short while it was winding up.
DamageEvent
type DamageEvent struct {
Target game.Unit
// Source is the unit that struck; its ID is -1 when nobody did (a script's or a cheat's damage).
Source game.Unit
// Total is what the target really lost (never more than it had); Physical, Magic and True are
// the parts after armour and magic resist, their sum.
Total, Physical, Magic, True int
// Crit says the blow was a critical strike (a spell never is).
Crit bool
}DamageEvent is health taken off a unit by one blow or spell.
GoldEvent
type GoldEvent struct {
Player player.ID
Amount int
// HasPoint says the gold came from a place, (X, Y) in world units from the middle of the map.
HasPoint bool
X, Y float64
}GoldEvent is gold received by a player.
Handle
type Handle struct {
// contains filtered or unexported fields
}Handle names one hook: what every On... function returns. The zero Handle names nothing and every method of it does nothing. A Handle is a small number, never reused, so a stale one can not touch another hook.
OnAbilityCast
func OnAbilityCast(fn func(AbilityCastEvent)) HandleOnAbilityCast calls fn when a cast goes through.
event.OnAbilityCast(func(e event.AbilityCastEvent) { game.Print("cast", e.Ability) })OnAbilityHit
func OnAbilityHit(fn func(AbilityHitEvent)) HandleOnAbilityHit calls fn once for each unit the effects of a cast reach (damage, heal, stun, slow
from the ability's effects list), just before the events of the effects themselves
(OnDamage, OnHealed, OnStunned). Abilities with no effects never call it.
event.OnAbilityHit(func(e event.AbilityHitEvent) { game.Print(e.Target.ID(), "was hit by", e.Ability) })OnBlocked
func OnBlocked(fn func(BlockedEvent)) HandleOnBlocked calls fn when part of a blow is blocked. Not called today (the rules have no block).
event.OnBlocked(func(e event.BlockedEvent) { game.Print("blocked", e.Prevented) })OnBuilt
func OnBuilt(fn func(game.Unit)) HandleOnBuilt calls fn with a building whose construction finished.
event.OnBuilt(func(u game.Unit) { game.Print("built", u.ID()) })OnCastInterrupted
func OnCastInterrupted(fn func(CastInterruptedEvent)) HandleOnCastInterrupted calls fn when an ability with a cast time is cut short because its caster died or was stunned before the time was over. The cost stays paid and the effects never land.
event.OnCastInterrupted(func(e event.CastInterruptedEvent) { game.Print(e.Unit.ID(), "lost its cast") })OnDamage
func OnDamage(fn func(DamageEvent)) HandleOnDamage calls fn for every blow that took health off a unit: one call per blow, with the parts it was made of. OnUnitDamaged is the short form with the total only.
event.OnDamage(func(e event.DamageEvent) { game.Printf("%d magic of %d", e.Magic, e.Total) })OnEnter
func OnEnter(region game.Region, fn func(game.Unit)) HandleOnEnter calls fn with each unit that walks (or is put) into the region. A unit already inside when the region was made does not count. Dead units do not enter.
OnGoldGained
func OnGoldGained(fn func(GoldEvent)) HandleOnGoldGained calls fn when a player receives gold.
event.OnGoldGained(func(e event.GoldEvent) { game.Print("gold", e.Amount) })OnHealed
func OnHealed(fn func(HealedEvent)) HandleOnHealed calls fn when health is restored by the rules. Not called today: a heal from a script (Unit.Heal) sets the stat and is reported by OnStat.
event.OnHealed(func(e event.HealedEvent) { game.Print("healed", e.Amount) })OnHit
func OnHit(fn func(HitEvent)) HandleOnHit calls fn when an attack lands, just before the OnDamage of the same blow.
event.OnHit(func(e event.HitEvent) { if e.Crit { game.Print("critical!") } })OnImmune
func OnImmune(fn func(game.Unit)) HandleOnImmune calls fn with a unit that ignored a blow or spell because it is immune. Not called today (the rules have no immunity yet).
event.OnImmune(func(u game.Unit) { game.Print(u, "is immune") })OnItemBought
func OnItemBought(fn func(ItemEvent)) HandleOnItemBought calls fn when a unit buys an item at a shop.
event.OnItemBought(func(e event.ItemEvent) { game.Print(e.Unit.ID(), "bought", e.Item) })OnItemDropped
func OnItemDropped(fn func(ItemEvent)) HandleOnItemDropped calls fn when a unit drops an item or dies carrying one; X and Y say where it fell, in world units from the middle of the map.
event.OnItemDropped(func(e event.ItemEvent) { game.Print(e.Unit.ID(), "dropped", e.Item, "at", e.X, e.Y) })OnItemPickedUp
func OnItemPickedUp(fn func(ItemEvent)) HandleOnItemPickedUp calls fn when a unit picks an item up from the ground.
event.OnItemPickedUp(func(e event.ItemEvent) { game.Print(e.Unit.ID(), "picked up", e.Item) })OnItemSold
func OnItemSold(fn func(ItemEvent)) HandleOnItemSold calls fn when a unit sells an item.
event.OnItemSold(func(e event.ItemEvent) { game.Print(e.Unit.ID(), "sold", e.Item) })OnItemUsed
func OnItemUsed(fn func(ItemEvent)) HandleOnItemUsed calls fn when a unit uses the active ability of an item (a use the game accepted: not on cooldown, with the mana and a valid target).
event.OnItemUsed(func(e event.ItemEvent) { game.Print(e.Unit.ID(), "used slot", e.Slot) })OnLeave
func OnLeave(region game.Region, fn func(game.Unit)) HandleOnLeave calls fn with each unit that leaves the region. A unit that dies inside leaves it (it is not alive in the handler).
OnLevelUp
func OnLevelUp(fn func(game.Unit)) HandleOnLevelUp calls fn with a hero that went up a level.
event.OnLevelUp(func(u game.Unit) { game.Print("level up", u.ID()) })OnLoaded
func OnLoaded(fn func(TransportEvent)) HandleOnLoaded calls fn when a unit climbs into a transport.
event.OnLoaded(func(e event.TransportEvent) { game.Print("boarded", e.Transport.ID()) })OnManaChanged
func OnManaChanged(fn func(ManaChangedEvent)) HandleOnManaChanged calls fn when a unit's mana changes by Delta (a cast paying its cost is negative).
event.OnManaChanged(func(e event.ManaChangedEvent) { game.Print("mana", e.Delta) })OnMapInit
func OnMapInit(fn func()) HandleOnMapInit calls fn once when the game starts.
OnMiss
func OnMiss(fn func(MissEvent)) HandleOnMiss calls fn when an attack misses. The rules have no miss chance yet, so it is not called today; a map that listens works unchanged when it arrives.
event.OnMiss(func(e event.MissEvent) { game.Print("missed") })OnPaused
func OnPaused(fn func()) HandleOnPaused calls fn when the host pauses the game. (The game does not step while it is paused; the hook runs on the first step after the host resumes, before OnResumed.)
event.OnPaused(func() { game.Print("paused") })OnPlayerJoined
func OnPlayerJoined(fn func(PlayerEvent)) HandleOnPlayerJoined calls fn when a player is seated in the running game (late join included).
event.OnPlayerJoined(func(e event.PlayerEvent) { game.Print(e.Player, "joined team", e.Team) })OnPlayerLeft
func OnPlayerLeft(fn func(PlayerEvent)) HandleOnPlayerLeft calls fn when a seat is marked abandoned because its player left. Its units stay.
event.OnPlayerLeft(func(e event.PlayerEvent) { game.Print(e.Player, "left") })OnResumed
func OnResumed(fn func()) HandleOnResumed calls fn when the host resumes a paused game.
event.OnResumed(func() { game.Print("resumed") })OnSeatChanged
func OnSeatChanged(fn func(SeatEvent)) HandleOnSeatChanged calls fn when a seat opens, is taken or is abandoned (after OnPlayerJoined or OnPlayerLeft of the same change).
event.OnSeatChanged(func(e event.SeatEvent) { game.Print(e.Player, "seat is now", int(e.State)) })OnShot
func OnShot(fn func(ShotEvent)) HandleOnShot calls fn when a ranged attacker lets a shot go; the matching OnHit comes when it lands.
event.OnShot(func(e event.ShotEvent) { game.Print("shot from", e.Attacker.ID()) })OnSpawned
func OnSpawned(fn func(game.Unit)) HandleOnSpawned calls fn with every new unit (a script's spawn, a trained unit, a placed building).
event.OnSpawned(func(u game.Unit) { game.Print("new unit", u.ID()) })OnStat
func OnStat(fn func(StatEvent)) HandleOnStat calls fn when a stat of a unit is set to a value by a script's heal, a mana set, a cast paying its mana or a hero's level set.
event.OnStat(func(e event.StatEvent) { if e.Stat == event.StatLevel { game.Print("level", e.Value) } })OnStunned
func OnStunned(fn func(StunnedEvent)) HandleOnStunned calls fn when a unit is stunned. Not called today (the rules have no stun yet).
event.OnStunned(func(e event.StunnedEvent) { game.Print("stunned for", e.Seconds) })OnTrained
func OnTrained(fn func(TrainedEvent)) HandleOnTrained calls fn when a building finishes training a unit (OnSpawned for the same unit comes just before).
event.OnTrained(func(e event.TrainedEvent) { game.Print("ready", e.Unit.ID()) })OnUnitDamaged
func OnUnitDamaged(fn func(unit, attacker game.Unit, amount float64)) HandleOnUnitDamaged calls fn whenever a unit loses health: with the unit, who struck it and how much health it lost (a blow that was more than it had left counts what it had). The attacker is a unit that is not alive (its ID is -1) when nobody struck, as with Unit.Damage from a script. A unit that dies of the blow is heard here first and then in OnUnitDied. OnDamage tells more (the parts of the blow, whether it was critical).
OnUnitDied
func OnUnitDied(fn func(game.Unit)) HandleOnUnitDied calls fn with every unit that dies.
OnUnitRevealed
func OnUnitRevealed(fn func(RevealEvent)) HandleOnUnitRevealed calls fn when a unit becomes visible to enemies because it attacked or cast from fog or brush, for a short time. A refresh while still shown is not a new event.
event.OnUnitRevealed(func(e event.RevealEvent) { game.Print(e.Unit, "was revealed") })OnUnloaded
func OnUnloaded(fn func(TransportEvent)) HandleOnUnloaded calls fn when a unit steps out of a transport.
event.OnUnloaded(func(e event.TransportEvent) { game.Print("landed", e.Unit.ID()) })OnUpgraded
func OnUpgraded(fn func(game.Unit)) HandleOnUpgraded calls fn with a building that finished an upgrade.
event.OnUpgraded(func(u game.Unit) { game.Print("upgraded", u.ID()) })OnUtilityRecharged
func OnUtilityRecharged(fn func(UtilityEvent)) HandleOnUtilityRecharged calls fn when a charge of a unit's slot comes back.
event.OnUtilityRecharged(func(e event.UtilityEvent) { game.Print("ready:", e.Charges) })OnUtilitySwapped
func OnUtilitySwapped(fn func(UtilityEvent)) HandleOnUtilitySwapped calls fn when a unit swaps the tool in its slot near its base; the new tool starts full.
event.OnUtilitySwapped(func(e event.UtilityEvent) { game.Print("now holds tool", int(e.Tool)) })OnUtilityUsed
func OnUtilityUsed(fn func(UtilityEvent)) HandleOnUtilityUsed calls fn when a unit spends a charge of its slot (a ward placed, a sweep started).
event.OnUtilityUsed(func(e event.UtilityEvent) { game.Print(e.Charges, "charges left") })OnWardDestroyed
func OnWardDestroyed(fn func(WardEvent)) HandleOnWardDestroyed calls fn when a ward is killed by blows.
event.OnWardDestroyed(func(e event.WardEvent) { game.Print("ward killed", e.Ward) })OnWardExpired
func OnWardExpired(fn func(WardEvent)) HandleOnWardExpired calls fn when a ward runs out of time or is pushed out by a newer one.
event.OnWardExpired(func(e event.WardEvent) { game.Print("ward gone", e.Ward) })OnWardPlaced
func OnWardPlaced(fn func(WardEvent)) HandleOnWardPlaced calls fn when a ward is placed.
event.OnWardPlaced(func(e event.WardEvent) { game.Print("ward", e.Ward, "at", e.X, e.Y) })OnWardRevealed
func OnWardRevealed(fn func(WardEvent)) HandleOnWardRevealed calls fn when a stealth ward of Owner is revealed to Team (a pink ward or a sweep covers it).
event.OnWardRevealed(func(e event.WardEvent) { game.Print("ward seen by team", e.Team) })OnXpGained
func OnXpGained(fn func(XpGainedEvent)) HandleOnXpGained calls fn when a hero gains experience (each hero of a kill separately).
event.OnXpGained(func(e event.XpGainedEvent) { game.Print("xp", e.Amount) })Register
func Register(kind Kind, fn any) HandleRegister adds fn for an event: a func() for MapInit, a func(game.Unit) for UnitDied. A function of the wrong shape is reported in the log and ignored (the Handle is then the zero Handle).
Handle.Disable
func (h Handle) Disable()Disable stops the hook from being called until Enable. Takes effect at once: a hook disabled by an earlier hook of the same event does not run for that event. Disabling a disabled or removed hook does nothing.
Handle.Enable
func (h Handle) Enable()Enable lets a disabled hook run again, for the events that happen from now on. It does nothing for a hook that is enabled or was removed.
Handle.Enabled
func (h Handle) Enabled() boolEnabled reports whether the hook exists and will be called.
Handle.Remove
func (h Handle) Remove()Remove takes the hook away for good (a Handle of a removed hook can not be enabled again). It may be called from inside the hook itself, which makes it a one-shot, or from another hook.
HealedEvent
type HealedEvent struct {
Target game.Unit
Amount int
// Source is the unit that healed; its ID is -1 when nobody did.
Source game.Unit
}HealedEvent is health really restored to a unit.
HitEvent
type HitEvent struct {
Attacker, Target game.Unit
Crit bool
}HitEvent is a blow landing (melee, or a shot arriving).
ItemEvent
type ItemEvent struct {
Unit game.Unit
// Item is the id of the item's definition, as the editor shows it.
Item string
// Slot is the inventory slot (0 to 5) for a use, and -1 for a purchase or a sale.
Slot int
// X and Y are where an item fell, in world units from the map's middle (OnItemDropped only).
X, Y float64
// Ground is the id the item has while it lies on the ground (OnItemDropped and OnItemPickedUp
// only); it is the same number in both, and 0 for the other events.
Ground int
}ItemEvent is a unit buying, selling or using an item.
Kind
type Kind intKind names an event for Register.
const (
// MapInit fires once, at the first step of the game, with a func().
MapInit Kind = iota
// UnitDied fires when a unit dies, with a func(game.Unit).
UnitDied
)ManaChangedEvent
type ManaChangedEvent struct {
Unit game.Unit
Delta int
}ManaChangedEvent is a change of a unit's mana.
MissEvent
type MissEvent struct{ Attacker, Target game.Unit }MissEvent is an attack that missed or was evaded.
PlayerEvent
type PlayerEvent struct {
Player player.ID
// Team of the seat (0: none known); set for OnPlayerJoined only.
Team int
}PlayerEvent is a player joining or leaving.
RevealEvent
type RevealEvent struct {
Unit game.Unit
// Team it is shown to; 0 means every team that could not see it (brush).
Team int
}RevealEvent is a unit being shown to the other side because it attacked or cast unseen.
SeatEvent
type SeatEvent struct {
Player player.ID
State SeatState
}SeatEvent is a seat changing state.
SeatState
type SeatState intSeatState is the state of a player's seat.
const (
// SeatOpen is a seat nobody has taken yet.
SeatOpen SeatState = iota
// SeatSeated is a seat with a player in it.
SeatSeated
// SeatAbandoned is a seat whose player left; its units stay.
SeatAbandoned
)ShotEvent
type ShotEvent struct {
Projectile int
Attacker game.Unit
Target game.Unit
// Where the shot left, in world units from the middle of the map.
X, Y float64
}ShotEvent is a ranged attacker letting a shot go.
Stat
type Stat intStat is which stat of a unit a StatEvent is about.
const (
StatHealth Stat = iota
StatMana
StatLevel
)StatEvent
type StatEvent struct {
Unit game.Unit
Stat Stat
Value int
}StatEvent is a stat of a unit set by something other than a fight.
StunnedEvent
type StunnedEvent struct {
Target game.Unit
Seconds float64
Source game.Unit
}StunnedEvent is a unit being stunned.
Timer
type Timer struct {
// contains filtered or unexported fields
}Timer is a function the game calls later, made by Every or After. Stop it to cancel it.
After
func After(seconds float64, fn func()) *TimerAfter calls fn once, seconds seconds of game time from now (at least one step). Stop the
returned timer to cancel it before it runs.
Every
func Every(seconds float64, fn func()) *TimerEvery calls fn every seconds seconds of game time (at least once a step), the first time
after that long counted from when Every was called. Stop the returned timer to end it.
Timer.Stop
func (t *Timer) Stop()Stop cancels the timer: it is not called again. Stopping a timer that already ran (an After) or was stopped is fine.
TrainedEvent
type TrainedEvent struct{ Building, Unit game.Unit }TrainedEvent is a building finishing training a unit.
TransportEvent
type TransportEvent struct{ Unit, Transport game.Unit }TransportEvent is a unit climbing into or out of a transport.
UtilityEvent
type UtilityEvent struct {
Unit game.Unit
Tool UtilityTool
// Charges the slot holds now (OnUtilityUsed and OnUtilityRecharged).
Charges int
}UtilityEvent is something that happened to a unit's utility (trinket) slot.
UtilityTool
type UtilityTool intUtilityTool is what a unit's utility (trinket) slot holds.
const (
// StealthTool places yellow wards.
StealthTool UtilityTool = iota
// FarsightTool places blue wards.
FarsightTool
// SweeperTool reveals and disables enemy wards in an area.
SweeperTool
)WardEvent
type WardEvent struct {
Ward int
Owner player.ID
// Kind is set for OnWardPlaced only.
Kind WardKind
// Team is the team the ward was revealed to (OnWardRevealed only).
Team int
// Where the ward stands, in world units from the middle of the map.
X, Y float64
}WardEvent is something that happened to a ward.
WardKind
type WardKind intWardKind is the kind of a ward.
const (
// YellowWard is the stealth ward: it sees, and is invisible until revealed.
YellowWard WardKind = iota
// PinkWard is the control ward: it reveals enemy wards around it.
PinkWard
// BlueWard is the farsight ward: it sees far, for a short time.
BlueWard
)XpGainedEvent
type XpGainedEvent struct {
Unit game.Unit
Amount int
}XpGainedEvent is experience given to a hero.