Files
Boutros Tawaifi 49464c56f6 Add an "On Ship Damage" script hook (#7894)
* Add an "On Ship Damage" script hook

Runs after resolved damage has been applied to a ship (lethal hits run before
the destruction callback). Hook variables: Target, Source, Attacker,
WeaponClass, WeaponSubtype, SourceKind (PROJECTILE, BEAM, SHOCKWAVE, COLLISION,
OTHER), DamageType, ShieldDamage, HullDamage, Quadrant, Ballistic, BeamWeapon
and LethalHit. Conditions can filter on the target ship. Nothing is computed
unless a script has registered the hook.

* Move the On Ship Damage hook call out of a lambda

ship_do_damage() now calls a file-level static function, ship_run_damage_hook(), that takes the values it needs as arguments instead of capturing the function state. Hook behaviour is unchanged.

* Report subsystem damage in the On Ship Damage hook

Adds SubsystemDamage, the total subsystem strength a damage application removed, so a hit absorbed by subsystems no longer looks like a small hull hit. The hook description now says it only runs where damage is applied, which excludes multiplayer clients.

* Address On Ship Damage review comments

- Remove WeaponClass, WeaponSubtype, Ballistic and BeamWeapon from the
  hook. Scripts read these from Source when it is a weapon.
- Add a "Weapon class" condition for the On Ship Damage hook. It matches
  only when the damage source is a weapon of that class; a weapon name
  that does not exist never matches.
- SubsystemDamage is now a table keyed by subsystem handle that lists only
  the subsystems that lost strength. The total is removed.
- Rename PROJECTILE to NON_BEAM_WEAPON.
- Classify SourceKind by damage source: COLLISION for ship, debris and
  asteroid collisions; EXPLOSION for ship-death and docked-ship blasts and
  asteroid blasts; WASH for engine wash; SELF for kills where the ship
  damages itself; OTHER for other ship-sourced damage.
- Reword the hook description.

* Key On Ship Damage SubsystemDamage by canonical name

Lua tables cannot use subsystem handles as keys in a usable way, so key
the SubsystemDamage table by each subsystem's CanonicalName instead.

* Tag ship-vs-prop damage as a collision and use in_bounds

The ship-vs-prop collision call didn't pass DamageSource::Collision, so
the On Ship Damage hook reported those hits as OTHER. Every other
collision path was already tagged.

Also use SCP_vector::in_bounds() for the Weapon_info and Damage_types
index checks in ship_run_damage_hook().
2026-11-06 18:41:29 -05:00

114 lines
6.3 KiB
C++

#include "hook_api.h"
#include "scripting/hook_conditions.h"
namespace scripting {
namespace hooks {
extern const std::shared_ptr<Hook<>> OnGameInit;
extern const std::shared_ptr<Hook<>> OnSplashEnd;
extern const std::shared_ptr<OverridableHook<>> OnIntroAboutToPlay;
extern const std::shared_ptr<OverridableHook<>> OnMovieAboutToPlay;
extern const std::shared_ptr<Hook<>> OnOptionsTabChanged;
extern const std::shared_ptr<Hook<>> OnOptionsMenuClosed;
extern const std::shared_ptr<Hook<>> OnHUDConfigMenuClosed;
extern const std::shared_ptr<Hook<>> OnControlConfigMenuClosed;
//The On State Start hook previously used to pass OldState to the conditions, but no semantically sensible condition read the value, so we pretend it has no local condition
extern const std::shared_ptr<OverridableHook<>> OnStateStart;
extern const std::shared_ptr<Hook<>> OnLoadScreen;
extern const std::shared_ptr<Hook<>> OnLoadComplete;
extern const std::shared_ptr<Hook<>> OnCampaignMissionAccept;
extern const std::shared_ptr<Hook<>> OnBriefStage;
extern const std::shared_ptr<Hook<>> OnMissionStart;
extern const std::shared_ptr<Hook<>> OnGameplayStart;
extern const std::shared_ptr<Hook<>> OnPhotoModeStarted;
extern const std::shared_ptr<Hook<>> OnPhotoModeEnded;
extern const std::shared_ptr<Hook<ControlActionConditions>> OnAction;
extern const std::shared_ptr<Hook<ControlActionConditions>> OnActionStopped;
extern const std::shared_ptr<OverridableHook<KeyPressConditions>> OnKeyPressed;
extern const std::shared_ptr<Hook<KeyPressConditions>> OnKeyReleased;
extern const std::shared_ptr<Hook<>> OnMouseMoved;
extern const std::shared_ptr<Hook<>> OnMousePressed;
extern const std::shared_ptr<Hook<>> OnMouseReleased;
extern const std::shared_ptr<Hook<ShipSourceConditions>> OnAfterburnerStart;
extern const std::shared_ptr<Hook<ShipSourceConditions>> OnAfterburnerEnd;
extern const std::shared_ptr<Hook<>> OnSupportRearmStarted;
extern const std::shared_ptr<Hook<>> OnSupportRearmFinished;
extern const std::shared_ptr<Hook<ShipSourceConditions>> OnWaypointsDone;
extern const std::shared_ptr<Hook<ShipSourceConditions>> OnGoalsCleared;
extern const std::shared_ptr<Hook<ShipSourceConditions>> OnDebrisCreated;
extern const std::shared_ptr<Hook<>> OnAsteroidCreated;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnShipCollision;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnPropCollision;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnWeaponCollision;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnBeamCollision;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnDebrisCollision;
extern const std::shared_ptr<OverridableHook<CollisionConditions>> OnAsteroidCollision;
extern const std::shared_ptr<Hook<ShipArriveConditions>> OnShipArrive;
extern const std::shared_ptr<Hook<WeaponCreatedConditions>> OnWeaponCreated;
extern const std::shared_ptr<Hook<ShipDeathConditions>> OnShipDeathStarted;
extern const std::shared_ptr<OverridableHook<ShipDeathConditions>> OnShipDeath;
extern const std::shared_ptr<Hook<WeaponDeathConditions>> OnMissileDeathStarted;
extern const std::shared_ptr<Hook<WeaponDeathConditions>> OnMissileDeath;
extern const std::shared_ptr<OverridableHook<WeaponProximityTriggeredConditions>> OnWeaponProximityTriggered;
extern const std::shared_ptr<Hook<>> OnBeamDeath;
extern const std::shared_ptr<Hook<>> OnAsteroidDeath;
extern const std::shared_ptr<Hook<>> OnDebrisDeath;
extern const std::shared_ptr<Hook<SubsystemDeathConditions>> OnSubsystemDestroyed;
extern const std::shared_ptr<Hook<ShipDepartConditions>> OnShipDepart;
extern const std::shared_ptr<Hook<WeaponDeathConditions>> OnWeaponDelete;
extern const std::shared_ptr<Hook<WeaponEquippedConditions>> OnWeaponEquipped;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnWeaponFired;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnPrimaryFired;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnSecondaryFired;
extern const std::shared_ptr<Hook<WeaponSelectedConditions>> OnWeaponSelected;
extern const std::shared_ptr<Hook<WeaponDeselectedConditions>> OnWeaponDeselected;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnTurretFired;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnBeamWarmup;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnBeamFired;
extern const std::shared_ptr<Hook<WeaponUsedConditions>> OnBeamWarmdown;
extern const std::shared_ptr<OverridableHook<>> OnHudCommMenuOpened;
extern const std::shared_ptr<OverridableHook<>> OnHudCommMenuClosed;
extern const std::shared_ptr<OverridableHook<CommOrderConditions>> OnHudCommOrderIssued;
extern const std::shared_ptr<OverridableHook<ObjectDrawConditions>> OnHudDraw;
extern const std::shared_ptr<OverridableHook<ObjectDrawConditions>> OnObjectRender;
extern const std::shared_ptr<Hook<>> OnSimulation;
extern const std::shared_ptr<OverridableHook<>> OnDialogInit;
extern const std::shared_ptr<OverridableHook<>> OnDialogFrame;
extern const std::shared_ptr<Hook<>> OnDialogClose;
extern const std::shared_ptr<Hook<>> OnCheat;
extern const std::shared_ptr<OverridableHook<>> OnMissionGoalStatusChanged;
extern const std::shared_ptr<Hook<>> OnMissionAboutToEndHook;
extern const std::shared_ptr<OverridableHook<>> OnMissionEndHook;
extern const std::shared_ptr<Hook<>> OnStateAboutToEndHook;
extern const std::shared_ptr<OverridableHook<>> OnStateEndHook;
extern const std::shared_ptr<Hook<>> OnCameraSetUpHook;
extern const std::shared_ptr<Hook<ShipDamageConditions>> OnShipDamage;
// FRED Hooks
extern const std::shared_ptr<Hook<>> FredOnMissionLoad;
extern const std::shared_ptr<Hook<>> FredOnMissionSpecsSave;
// deprecated
extern const std::shared_ptr<OverridableHook<>> OnSplashScreen;
extern const std::shared_ptr<OverridableHook<ObjectDeathConditions>> OnDeath;
}
} // namespace scripting