Damage model how-to
===================

This document explains how to reuse the generic damage model from this
aircraft in another FlightGear aircraft.

The current implementation was built around a YASim aircraft, but most of the
property-driven logic is portable. The main script lives in:

  Aircraft/ag-14-fc/Nasal/aircraft-damage.nas

What the damage model does
--------------------------

The script monitors structural abuse and touchdown abuse, then applies:

  - cumulative structural damage
  - control-authority penalties
  - warnings and a damage log panel
  - optional event sounds
  - optional visual damage models
  - fatal breakup / crash-state handling

Events currently covered:

  - positive and negative over-G
  - deterministic positive-G wing overstress tiers
  - hard landings
  - tail strikes
  - wing strikes
  - fatal wing-strike force events
  - total-loss visual state after /sim/crashed becomes true

Minimum install steps
---------------------

1. Copy the script into your aircraft.

   Recommended location:

     Aircraft/your-aircraft/Nasal/aircraft-damage.nas

2. Load the script from your aircraft set file.

   Add a Nasal include in your *-set.xml file:

     <nasal>
      <file>Aircraft/your-aircraft/Nasal/aircraft-damage.nas</file>
     </nasal>

   In this aircraft the include is:

     <file>Aircraft/ag-14-fc/Nasal/aircraft-damage.nas</file>

3. Decide where the damage properties should live.

   By default the script stores aircraft-specific state under:

     /aircraft/damage

   That root is configurable with:

     /sim/aircraft-damage/root

   If you want a different property root, set it before the script initializes.

4. Test the script without visuals first.

   The logic, warnings, and penalties work even if you do not supply any
   damage meshes.

Recommended optional integration
--------------------------------

Aircraft menu items
-------------------

This is optional, but useful during testing. This aircraft exposes menu items
 for:

  - toggle damage model
  - reset damage
  - show damage log
  - toggle damage log transparency

You can copy the same idea into your set file, or drive the properties from
your own menu/UI system.

Useful properties:

  /sim/aircraft-damage/reset-request
  /sim/aircraft-damage/ui/visible
  /sim/aircraft-damage/ui/transparent

Visual damage models
--------------------

The script can load optional damaged models automatically. It does not require
them, but if the files exist it will use them.

How visual discovery works:

  - The script reads /sim/model/path.
  - It derives the model directory and base model name.
  - It searches for damage-model files in the same directory.
  - It prefers .xml, then .ac.

Example:

  If your normal model is:

    Aircraft/your-aircraft/Models/my-aircraft.xml

  then the script will look for files like:

    Aircraft/your-aircraft/Models/my-aircraft_broken_wings_1.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_wings_2.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_wing_left.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_wing_right.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_landing_gear.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_landing_gear_left.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_landing_gear_right.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_hard_landing1.ac
    Aircraft/your-aircraft/Models/my-aircraft_broken_total_loss.ac

Supported visual states
-----------------------

The current naming contract is:

  broken_wings1
  broken_wings2
  broken_wing_left
  broken_wing_right
  broken_landing_gear
  broken_landing_gear_left
  broken_landing_gear_right
  broken_hard_landing1
  broken_total_loss

Notes:

  - broken_wings1 is the non-fatal wing-overstress state
  - broken_wings2 is the fatal wing-overstress state
  - broken_hard_landing1 is the dedicated hard-landing deformation state
  - broken_total_loss is the final stuck model once /sim/crashed is true

Override properties are available if your model naming/layout is unusual:

  /sim/aircraft-damage/visual/model-dir
  /sim/aircraft-damage/visual/model-base

Base-model visibility hook
--------------------------

If your damage mesh is a full replacement airframe, you usually want to hide
the normal aircraft model when the damaged model is active. This aircraft does
that in Models/ag-14.xml with a select animation driven by:

  /sim/aircraft-damage/visual/base-visible

Pattern:

  - when base-visible is 1, show the normal aircraft objects
  - when base-visible is 0, hide the normal aircraft objects

You must adapt the object-name list to match your own model names.

If your damage mesh is only a partial overlay, leave the base model visible and
do not add the hide logic.

Sound support
-------------

The current script plays one-shot sounds directly from Nasal using the
FlightGear command play-audio-sample.

Default sound properties:

  /sim/aircraft-damage/sound/enabled = 1
  /sim/aircraft-damage/sound/path = Aircraft-local Sounds/damage if available
  /sim/aircraft-damage/sound/volume = 1.0

Current event-to-file mapping:

  aircraft_overg_sound.wav
  aircraft_overg_fatal_sound.wav
  aircraft_hard_landing_sound.wav
  aircraft_hard_landing_gear_collapse.wav

You have two practical options:

  1. Put your files in your aircraft's own Sounds/damage directory and let the
    script pick that up automatically from the current model path.

  2. Set /sim/aircraft-damage/sound/path before initialization to an
     aircraft-local location such as:

       Aircraft/your-aircraft/Sounds/damage

If no aircraft-local Sounds/damage directory can be derived or found, the
script falls back to the shared/global Sounds/damage path.

The sound system does not require a separate aircraft sound XML file for these
damage events, because playback is triggered directly by the script.

Tuning the model
----------------

The main tuning object is near the top of aircraft-damage.nas. Read that block
first before changing any numbers.

Important tuning values:

  warn_cooldown_sec
  pos_g_limit
  neg_g_limit
  overg_pos_rate
  overg_neg_rate
  wing_overstress_damage_ratio
  wing_overstress_fatal_ratio
  wing_overstress_damage_amount
  wing_lift_loss_stage1
  hard_landing_fpm
  hard_landing_base
  hard_landing_visual_fpm
  hard_landing_scale
  strike_sink_fpm
  tail_pitch_deg
  wing_roll_deg
  tail_strike_damage
  wing_strike_damage
  gear_collapse_fpm
  gear_collapse_side_roll_deg
  wing_strike_force_ref_kn
  wing_strike_force_damage_kn
  wing_strike_force_fatal_kn
  wing_strike_force_damage_scale

Preset system
-------------

Built-in presets:

  trainer
  ga-utility
  aerobatic

Set the preset before the script initializes:

  /sim/aircraft-damage/preset = trainer
  /sim/aircraft-damage/preset = ga-utility
  /sim/aircraft-damage/preset = aerobatic

The preset applies a sane starting point, but you should still retune the
numbers for your aircraft geometry, weight class, and design limits.

Runtime properties worth knowing
--------------------------------

Core state:

  /aircraft/damage/enabled
  /aircraft/damage/health-norm
  /aircraft/damage/fatigue
  /aircraft/damage/level
  /aircraft/damage/critical
  /aircraft/damage/fatal-active
  /aircraft/damage/fatal-impact
  /aircraft/damage/fatal-state

Event flags and counters:

  /aircraft/damage/events/*
  /aircraft/damage/counters/*

Visual state:

  /sim/aircraft-damage/visual/requested-state
  /sim/aircraft-damage/visual/state
  /sim/aircraft-damage/visual/overlay-active
  /sim/aircraft-damage/visual/base-visible
  /sim/aircraft-damage/visual/active-model-path

Debug values:

  /aircraft/damage/debug/nz
  /aircraft/damage/debug/nz-source
  /aircraft/damage/debug/nz-max
  /aircraft/damage/debug/nz-min

Important behavior notes
------------------------

1. The script uses cumulative damage. Damage remains until reset.

2. Fatal over-G breakup is handled differently from impact crashes.
   During in-flight breakup the script avoids setting /sim/crashed
   immediately, because YASim stops updating once FlightGear considers the
   aircraft crashed.

3. Once /sim/crashed becomes true, the visual system now prefers the terminal
   broken_total_loss model if one exists.

4. If no optional damage mesh exists for a requested visual state, the script
   falls back gracefully and continues operating with logic, warnings, and
   state properties only.

Suggested integration order
---------------------------

1. Copy the Nasal script and confirm it initializes.
2. Enable warnings and verify damage accumulates.
3. Tune G and landing thresholds.
4. Add the damage-log menu/UI helpers.
5. Add visual damage meshes one state at a time.
6. Add sound files and set the desired sound path.
7. Test reset, crash, and total-loss visuals.

Quick test checklist
--------------------

  - Pull a mild over-G and verify warning plus damage accumulation.
  - Exceed the major positive-G threshold and verify broken_wings1.
  - Exceed the fatal positive-G threshold and verify fatal handling.
  - Make a hard landing and verify hard-landing damage and sound.
  - Make a severe landing and verify gear-collapse sound/state.
  - Strike a wing and verify side-specific visual state.
  - Crash the aircraft and verify broken_total_loss appears.
  - Reset and verify properties, visuals, and crash state clear.

Known adaptation points for another aircraft
--------------------------------------------

You will almost certainly need to change:

  - the aircraft file paths
  - the base-model hide/show object-name list
  - the tuning values
  - the optional sound path
  - the damage mesh art and naming

You may need to change:

  - the control-effect penalties in dmg_apply_effects()
  - the touchdown thresholds for your landing gear geometry
  - the G-source selection logic if your aircraft/FDM exposes a better source

If you keep the public property contract and the visual naming convention, you
can still customize the internal damage logic without breaking the integration
points described above.