$Id: callbacks.txt 4720 2023-11-02 23:55:40Z dsb $

Actor Callbacks
---------------

The T2 module supports "actor callbacks", which are member functions that
can be "installed" onto an Actor by talents, temporary effects, objects,
quests or birth descriptors, and will be invoked for the Actor when certain
events occur.  Actor callbacks are defined in a subtable of the source, as
follows:

  - For talents, callbacks defined in the callbacks{} subtable of the
    talent definition will be installed when the talent is learned and
    uninstalled when the talent is unlearned.  In addition, for sustained
    talents, callbacks defined in the active_callbacks{} subtable of the
    talent definition will be installed when the talent is activated and
    uninstalled when the talent is deactivated.

  - For temporary effects, callbacks defined in the callbacks{} subtable of
    the effect definition will be installed when the effect is gained and
    uninstalled when the effect is lost.

  - For objects, callbacks defined in the carried_callbacks{} subtable of
    the object entity definition will be installed when the object is
    picked up and uninstalled when the object is dropped; callbacks defined
    in the worn_callbacks{} subtable of the object entity definition will
    be installed when the object is worn/wielded and uninstalled when the
    object is taken off.

  - For quests, callbacks defined in the callbacks{} subtable of the quest
    definition will be installed when the quest is granted via
    ActorQuest:grantQuest() and uninstalled when the quest's status is
    changed to DONE or FAILED.

  - For birth descriptors, callbacks defined in the callbacks{} subtable
    will be installed when the birth descriptor is applied and uninstalled
    if the descriptor is ever revoked.  In practice, of course, typically
    the latter cannot happen and the former only happens at birth; the only
    exception is god descriptors, which will be revoked when the player
    wears or destroys the One Ring (depending on the god) and will at some
    point be gainable from altars.

Any of the above subtables may contain a priorities{} sub-subtable
specifying the "priorities" of the callbacks, which influences the order in
which the callbacks will be invoked.  If not specified, a callback has
priority 0 by default; callbacks with negative priorities will be called
earlier, and callbacks with positive priorities will be called later.

All actor callback functions take at least two parameters:

  - 'who' is the Actor on whose behalf the callback is being invoked.
  - 'data' is the relevant "data" for the callback source:
    = For talents, 'data' is the talent definition table.
    = For temporary effects, 'data' is the effect data table passed to
      Actor:setEffect().
    = For objects, 'data' is the object itself.
    = For quests, 'data' is the quest object, as returned by
      ActorQuest:hasQuest().
    = For descriptors, 'data' is the birth descriptor.

Some callbacks take additional arguments, which will be described in their
listing below.

Supported Actor Callbacks
-------------------------

The following actor callbacks are supported by the T2 module:

on_act(who, data)
  Called by Actor:act() on the actor's turn.

on_global_turn(who, data)
  Called by Actor:actBase() once per global turn (equivalent to actor turn
  at normal speed).  [Note that for timed effects, this is effectively
  equivalent to using the on_timeout() method.]

on_move(who, data, moved, forced, x, y, ox, oy)
  Called by Actor:move() when the actor moves (or attempts to).
    moved:	True if the actor actually moved, or attempted to.
		[cf. engine.Actor:move()]
    forced:	True if the actor was forced to move by something.
    x, y:	The actor's new location.
    ox, oy:	The actor's previous location.

on_rest_start(who, data)
  Called by Player:onRestStart() when the player begins resting.  Your
  callback may modify who or who.resting{} as needed.

on_rest_stop(who, data)
  Called by Player:onRestStop() when the player stop resting.  Your
  callback may modify who or who.resting{} as needed.

on_rest_step(who, data)
  Called by Player:restStep() once per normal-speed turn while resting, and
  by Player:stay() when waiting one turn via the ',' key (these two cases
  can be distinguished by the presence resp. absence of the who.resting{}
  subtable).  Your callback should not take any action that would use
  energy, as the caller will already have invoked who:useEnergy().

on_rest_check(who, data, p)
  Called by Player:restCheck() once per normal-speed turn while resting to
  determine if the player should continue resting.
    p:		A table into which the callback may place its assessment.
		The handling is slightly involved:

		  * If your callback concludes that the player should stop
		    resting (an immediate danger, for instance), it should
		    set p.stop to true and p.stop_msg to a string describ-
		    ing the reason the player needs to stop resting.

		  * Otherwise, if your callback concludes that the player
		    should continue resting (to regenerate a resource, for
		    instance), AND if no other callback has set p.stop to
		    true, your callback should set p.stop to false.

		  * Otherwise, your callback should leave p.stop unchanged.
		    Your callback may set p.stop_msg to a string describing
		    why the player no longer needs to continue resting (and
		    is encouraged to do so if no other callback has set
		    this field).

		Resting will continue if no callback sets p.stop to true
		and at least one callback sets p.stop to false (and if
		nothing else in :restCheck() concludes that resting should
		stop, of course).

on_enter_level(who, data, zone, level, lev, old_zone, old_lev, params)
  Called by Game:changeLevel() when the player enters a new level, just
  before fates and level feelings are handled.
    zone:	The Zone the player is in or has entered.
    level:	The Level the player has just entered.
    lev:	The numerical depth of the level, not adjusted by
		Zone:level_adjust_level().
    old_zone:	The Zone the player just left, or nil if the player changed
		levels within the current zone.
    old_lev:	The numerical depth of the level the player just left, not
		adjusted by Zone:level_adjust_level().
    params:	The extra parameters passed to Game:changeLevel(), if any.

on_leave_level(who, data, zone, level, lev, params)
  Called by Game:changeLevel() just before the player leaves the old level.
    zone:	The Zone the player is currently in.
    level:	The Level the player is about to leave.
    lev:	The numerical depth of the level the player is about to
		leave, not adjusted by Zone:level_adjust_level().
    params:	The extra parameters passed to Game:changeLevel(), if any.

on_take_hit_pre(who, data, src, p, wpn)
  Called by Actor:onTakeHit() before damage is applied in Actor:takeHit().
    src:	The source of the damage, typically the attacking Actor.
    p:		A table with a single 'damage' field containing the damage
		done.  Your callback may set this field to a new value to
		alter the damage amount actually applied in Actor:takeHit().
		Other callbacks might already have altered this field, of
		course; your callback might, for instance, wish to refrain
		from taking any action if damage has been set to zero.
    wpn:	If the damage is from a melee attack, the weapon (or analogue)
		used in said attack; otherwise nil.
  The "weapon" value in the 'wpn' argument can be further delineated as
  follows:
    - If the 'type' field is present and has value 'weapon' or 'ammo', the
      value is the actual weapon or ammo Object.
    - If the 'method' field is present, the value is a NPC melee attack, as
      defined under mod.class.AttackType.  Callbacks may wish to check for
      the 'no_retal' field, which indicates attack types like 'gaze' that
      do not make physical contact with the target.
    - Otherwise, the value is a stub representing a Barehand-combat or
      Bearform-combat attack by the player.

on_take_hit_post(who, data, src, dam)
  Called by Actor:onTakeHitPost() after damage is applied in Actor:takeHit().
    src:	The source of the damage, typically the attacking Actor.
    dam:	The amount of damage done.

on_melee_blow(who, data, target, hit, wpn)
  Called by NPC:attackTarget() or PlayerCombat:attackTarget() after each
  attempted melee blow by the actor, if both the actor and its target are
  still alive.
    target:	The actor being attacked.
    hit:	True if the attack hit.
    wpn:	The weapon (or analogue) used in the attack, as described
		above under on_take_hit_pre().

on_melee_attack(who, data, target, n_hits, n_attacks)
  Called by NPC:attackTarget() or PlayerCombat:attackTarget() after the
  actor attempts all of its melee attacks, if both the actor and its target
  are still alive.
    target:	The actor being attacked.
    n_hits:	The number of successful hits the actor made.
    n_attacks:	The number of melee blows the actor attempted.

on_melee_attack_pre(who, data, target, p)
  Called at the start of NPC:attackTarget() or PlayerCombat:attackTarget().
    target:	The actor we are about to attack.
    p:		A table with a single 'no_attack' field, which will be true
		if an earlier callback has blocked this attack.  If this
		field is set to true by any callback, the calling method
		will return immediately.

on_wpn_hit_pre(who, data, target, wpn, p, dam)
  Called by PlayerCombat:oneBlowWithWeapon() while computing the effects of
  a melee hit with a weapon, after total damage is computed but just before
  it is applied.  This is where things like chaotic effects and vampiric
  effects from object flags are applied.
    target:	The actor being attacked.
    wpn:	The weapon (or analogue) used in the attack, as described
		above under on_take_hit_pre().
    p:		A table with a single 'stop' field.  Your callback may set
		this field to true to stop further processing of the hit
		(if, for instance, the effect teleports the monster away).
		Your callback may also wish to check this flag and withhold
		its effect if a prior callback has set it.
    dam:	The total damage computed for the weapon hit.

on_wpn_hit_dam_mod(who, data, target, wpn, p)
  Called by PlayerCombat:oneBlowWithWeapon() while computing the damage to
  be dealt by a melee hit with a weapon.
    target:	The actor being attacked.
    wpn:	The weapon (or analogue) used in the attack, as described
		above under on_take_hit_pre().
    p:		A table containing fields 'base' and 'bonus', reflecting,
		respectively, the base weapon damage and to-dam bonus
		computed so far.  Your callback may modify these in place
		as needed.

on_wpn_slay_brand(who, data, target, wpn, defs)
  Called by Combat:compute_brand_slay_mult() while computing the slay/brand
  multiplier to use for a weapon attack.
    target:	The actor being attacked.
    wpn:	The weapon (or analogue) used in the attack, as described
		above under on_take_hit_pre().
    defs:	The slay/brand definitions accumulated so far.  Your
		callback may append additional definitions to this table as
		needed.  Definitions should be of the form:
		  - function(who, target, wpn), which should return the
		    appropriate slay/brand multiplier value.
		  - { flag=FLG, M }; will use multiplier M if the target
		    has the specified flag.
		  - { damtype=DT, M1, M2 }; will use multiplier M2 if
		    target is vulnerable to the specified DamageType, or M1
		    if target does not resist said DamageType.

on_hit_in_melee(who, data, attacker, wpn)
  Called by Actor:onHitInMelee() after the actor is hit by a melee attack,
  if it is still alive.
    attacker:	The actor that hit this actor.
    wpn:	The weapon (or analogue) used in the attack, as described
		above under on_take_hit_pre().

on_die_pre(who, data, src, p)
  Called at the start of Actor:die().  This callback is where you can
  optionally prevent the death of the actor.
    src:	The actor that killed this actor.
    p:		A table with a single 'no_die' field, which will be true if
		an earlier callback has blocked this actor's death.  You
		can set this field to true to prevent the actor from dying.

on_kill(who, data, target, rsrc)
  Called in Actor:die() when the actor has killed another actor, just after
  assigning experience for the kill.
    target:	The actor that this actor just killed.
    rsrc:	The "resolved" killer, if it is different from this actor.
		This could distinguish a summoned Actor from its summoner,
		for instance, or a symbiote from its host; see
		Actor:resolveSource() and related methods.  This callback
		will be invoked on both the promixate and "resolved" killer
		if they are different; the former will receive a non-nil
		value in the 'rsrc' parameter, and the latter will receive
		a nil value.

on_wear_pre(who, data, o, inven, p)
  Called at the start of Object:on_canwear() when an actor tries to wear an
  object.  This callback will be invoked in a coroutine context suitable
  for the use of ActorTalents:talentDialog() and related methods.
    o:		The object to be worn.
    inven:	The inventory into which the object will be worn.
    p:		An empty table to pass back a return value.  Your callback
		can set the 'no_wear' field of this table to true to
		prevent the item from being worn, or to false to bypass
		subsequent checking and allow the object to be worn.  Note
		that other callbacks may have set this field before this
		callback is called.

on_wear(who, data, o, inven_id)
  Called by Object:on_wear() after an object has been worn.  Note that this
  is done before the object's worn_callbacks{} are installed, so any
  on_wear() callback therein will not be called.
    o:		The object that has just been worn.
    inven_id:	The identifying tag of the inventory into which the object
		has been worn. [cf. ActorInventory:getInven()]

on_pickup_floor(who, data, o, n)
  Called at the end of Actor:on_pickup_object() when an actur has picked up
  an object.
    o:		The 'newo' parameter passed to Actor:on_pickup_object();
		this is the picked-up object in inventory, possibly stacked
		with other objects already present in inventory.
    n:		The 'num' parameter passed to Actor:on_pickup_object();
		this is the number of objects picked up from the floor.

on_drop_pre(who, data, o, silent, p)
  Called at the start of Object:on_drop() when an actor tries to drop an
  object.
    o:		The object to be dropped.
    silent:	The 'silent' paramenter passed to :on_drop().
    p:		An empty table to pass back a return value.  Your callback
		can set the 'no_drop' field of this table to true to
		prevent the item from being dropped, or to false to bypass
		subsequent checking and allow the object to be dropped.
		Note that other callbacks may have set this field before
		this callback is called.

on_talent_desc_rsrc(who, data, t, lines)
  Called by Actor:getTalentFullDescription() while constructing the
  description of the talent's resource costs.
    t:		The talent for which a description is being created.
    lines:	The list of text lines populated so far.  Your callback may
		append additional lines describing the talent's resource
		costs.

on_use_talent_pre_rsrc(who, data, t, silent, dry_run, p)
  Called by Actor:preUseTalent() while checking whether the actor has
  sufficient resources to use this talent.  Will not be called if use of
  resources has been suppressed via the 'ignore_ressources' parameter to
  Actor:forceUseTalent() [q.v.], or when deactivating a sustained talent.
  This callback will be invoked in a coroutine context suitable for the use
  of ActorTalents:talentDialog() and related methods.
    t:		The talent definition of the talent being used.
    silent:	The 'silent' parameter passed to :preUseTalent().
    dry_run:	The 'dry_run' parameter passed to :preUseTalent().
    p:		A table with a single 'no_use' field, which will be true if
		some earlier callback has vetoed use of this talent.  Your
		callback should set this field to true if it determines
		that the actor lacks sufficient resources to use this
		talent.

on_use_talent_pre(who, data, t, silent, dry_run, p)
  Called near the end of Actor:preUseTalent(), after all other failure
  checks have been done but before usage messages are printed.
    t:		The talent definition of the talent being used.
    silent:	The 'silent' parameter passed to :preUseTalent().
    dry_run:	The 'dry_run' parameter passed to :preUseTalent().
    p:		A table with a single 'no_use' field, which will be true if
		some earlier callback has vetoed use of this talent.  Your
		callback may set this field to true to block the talent
		from being used.

on_use_talent_post_rsrc(who, data, t, ret)
  Called by Actor:postUseTalent() to consume resources used by a talent.
  Will not be called if use of resources has been suppressed via the
  'ignore_ressources' parameter to Actor:forceUseTalent() [q.v.].  Remember
  that this callback is called before a sustained talent is actually
  activated or deactivated by Actor:useTalent(), so who:isTalentActive(t.id)
  will return false for a sustained talent that is being activated.
    t:		The talent definition of the talent being used.
    ret:	The 'ret' parameter passed to :postUseTalent().

on_object_desc(who, data, o, df, p)
  Called near the end of Object:getDesc() while constructing the object
  description.
    o:		The object being described.
    df:		A copy of the parameters table passed to Object:getDesc().
    p:		A table with a single 'desc' string field containing the
		object description constructed so far.  Your callback may
		modify this field in place.

on_identify(who, data, o, lvl, old_lvl)
  Called by Object:identify() after an object's identification level
  changes.
    o:		The object being identified.
    lvl:	The "level" of identification passed to :identify();
		supported values are false, true or 'full'.
    old_lvl:	The object's "level" of identification before :identify()
		was called; supported values are false, true or 'full'.

on_adding_party_member(who, data, actor, def)
  Called at the beginning of Party:addMember(), before the new member has
  been added to game.party.members{} and game.party.m_list{}.  This
  callback will not be called for the member being added.
    actor:	The actor being added to the party
    def:	The party member definition table passed to
		Party:addMember().

on_added_party_member(who, data, actor, def)
  Called at the end of Party:addMember(), after the new member has been
  added to game.party.members{} and game.party.m_list{}.  This callback
  *will* be called for the member being added.
    actor:	The actor being added to the party
    def:	The party member definition table passed to
		Party:addMember().

on_removing_party_member(who, data, actor, def)
  Called at the beginning of Party:removeMember(), before the member has
  been removed from game.party.members{} and game.party.m_list{}.  This
  callback *will* be called for the member being removed.
    actor:	The actor being removed to the party
    def:	The party member definition table for the actor being
		removed, as previously provided via Party:addMember().

on_removed_party_member(who, data, actor, def)
  Called at the end of Party:removeMember(), after the member has been
  removed from game.party.members{} and game.party.m_list{}.  This callback
  will not be called for the member being removed.
    actor:	The actor being removed to the party
    def:	The party member definition table for the actor being
		removed, as previously provided via Party:addMember().

on_player_calc_max_life(who, data)
  Called at the end of Player:recalcHP().  Your callback may modify
  who.max_life directly; it will be bounded below at 1 after all callbacks
  are fired.

on_player_calc_max_mana(who, data)
  Called at the end of Player:recalcMana().  Your callback may modify
  who.max_mana directly; it will be bounded below at 0 after all callbacks
  are fired.

on_terrain_effect(who, data, x, y, grid, effects)
  Called by Player:terrainEffects() while accumulating timed effects for
  the player's current location.
    x, y:	The player's location
    grid:	The Grid entity for the player's location, as returned by
		game.level.map(x, y, Map.TERRAIN).
    effects:	The table of effects computed so far; keys are timed effect
		IDs and values are effect parameter tables suitable for
		passing to ActorTemporaryEffects:setEffect() [q.v.].
		Your callback may add effects to this table as needed.  
