Angband can be controlled by user-created Lua scripts that are called at certain points in the game or at specific times. These "events" can happen under a variety of circumstances. The Lua scripts may set up an arbitrary function to be called when an event occurs, and this event may do whatever is needed. For example, an event is invoked when the player enters a new dungeon level. The scripts can set up an event handler to create a specific monster if he happens to enter dungeon level 100.
Certain events look at the values returned by the Lua event handler to do different things depending on the situation.
To associate a Lua function with a given event, use the "add_event_handler" function. The first argument is the event name, and the second argument is the Lua function to be called.
-- "use_object" is the name of the event -- "use_object_hook" is the event handler to be called for this event add_event_handler("use_object", use_object_hook)
It is possible to add several different event handlers to a single event. These event handlers are then called when the event occures in the order they have been added.
Adding new events to the game engine is easy, so if you need a new one for some reason, let me know and I'll try to add it in the next version.
Called when the player uses an object, for example by aiming a wand, quaffing a potion, zapping a rod, or activating an artifact. Returns two boolean values:
function use_object_hook(object) -- Get the basic name of the object local o_name = object_desc(object, false, 0) msg_print(string.format("The %s will be identified.", o_name)) return true, false end
Called when the game needs a textual description of the objects activation effect.
Called when the game restocks the inventory of a shop. The "store_number" indicates which store is being updated. The event handler should return the object_index of the object to be created in the store.
Called when the player gets hit by a bold, beam, or ball spell effect or monster breath. "who" is the index of the monster that attacked the player, "damage" is the amount of damage the spell does, and "type" indicated the type of the attack (for example fire, cold, poison, or confusion).
By returning the boolean value 'true' the event handler can prevent the game engine from processing the event internally. This allows replacing the normal Angband damage effects with Lua code.
Example (take 10% of poison damage immediately when hit):
function projection_hit_player_hook(who, dam, typ) -- Get the source monster local monster = mon_list[who + 1] -- Get the monster's real name local killer = monster_desc(monster, tonumber("88", 16)) if typ == GF_POIS then if player.blind then msg_print("You are hit by poison!") end if player.resist_pois then dam = (dam + 2) / 3 end if player.oppose_pois > 0 then dam = (dam + 2) / 3 end -- take 10% damage now local dam_cur = (dam / 10) + 1 take_hit(dam_cur, killer) if player.wizard then msg_print("Poison damage total: "..dam) end if player.wizard then msg_print("Poison damage now: "..dam_cur) end -- take the rest later set_poisoned(player.poisoned + dam - dam_cur) -- Stop processing return true end end add_event_handler("projection_hit_player", projection_hit_player_hook)
This event is triggered every 10 game turns (every player turn at normal speed).
Example (take 10% of the accumulated poison damage each turn):
-- Take damage from poison function poison_damage_hook() if player.poisoned > 0 then -- take 10% of total damage per turn local dam = (player.poisoned / 10) + 1 -- Take damage take_hit(dam, "poison") if player.wizard then msg_print("Poison damage this turn: " .. dam) end -- Reduce poison effect over time set_poisoned(player.poisoned - dam) end end add_event_handler("process_world", poison_damage_hook)