#!/usr/bin/env bash
# shellcheck disable=SC2086
# author: alvazir
# version: 2.2
# permissions: You can use this however you want, as long as you credit authors.

# List of plugins to process. Just delete these lines and insert those you need.
plugins="
Ald-Ruhn Temple Expansion 1.5.esp
Animated_Morrowind - merged.esp
Ashlander Traders Remastered.esp
BM_S_Inn.ESP
BT_Whitewolf_2_0_HOTV.esp
Balmora Waterworks.esp
Balmora_Rooftop_Apartments_1-0.esp
BeaconOfstRilmsNoAnim.ESP
Building Up Uvirith's Legacy1.1.ESP
CCM-SecretsofVos-V2-TB.esp
Camonna Tong.esp
DA_Sobitur_Repurposed_1.ESP
DD_Caldera_Expansion.esp
Hlormaren Reclaimed.ESP
Immersive Mournhold.esp
Improved Inns Expanded - Entertainers.ESP
Inner Sea Trading Company.esp
Memento Mori.ESP
Morag Tong Polished.esp
Mudcrab Imports NoBB.esp
NVI Lite.esp
OAAB_Tel Mora.ESP
OldVosTradepost.ESP
SadrithMoraExpandedTR.esp
SecretsOfTheCrystalCity.esp
Tel_Aruhn_Chronicles.ESP
Tel_Eurus.esp
The Merchants of Sadrith Mora.ESP
The Rise of the Tribe Unmourned.esp
The_Vanilla_Quest_Tweaks_RP_Choices_Consequences_Super_Mega_Package_-_Ultimate_Edition.ESP
Thirsk Expanded.esp
TravelingMerchants_v2_3.esp
Vivec Waistworks Expansion - GoVH comp.ESP
War Leader Nerevar.ESP
Wolverine Hall Interior Expanded - No Legion HQ.esp
Your Own Ashlander Tribe.ESP
Havish.esm
Wyrmhaven.esm
Cyr_Main.esm
Sky_Main.esm
TR_Mainland.esm
"
# Path to tes3cmd
tes3cmd="./tes3cmd"
# Directory where to place output
dir="container_generator_dir"

# This script should be portable after removing few bashisms (file redirections)
# Should be somewhat readable as it's just a bunch of spaghetti code with strange formatting

ARGUMENTS="$(printf '"%s" ' "${@}")"
# Simple command interface
while [[ $# -gt 0 ]]; do arg="${1}"
  case ${arg} in
    -0|0|-r|r|--run|run)                                assign=1; place=1; create=1; shift ;;
    -1|1|-a|a|--assign|assign)                                             assign=1; shift ;;
    -2|2|-p|p|--place|place)                                                place=1; shift ;;
    -3|3|-c|c|--create|create)                                             create=1; shift ;;
    -d|d|--dir|dir|--directory|directory)                         dir="${2}"; shift; shift ;;
    -h|h|--help|help)                                                        help=1; shift ;;
    -b|b|--basename|basename)                       basename_provided="${2}"; shift; shift ;;
    -m|m|--modular|modular)                                               modular=1; shift ;;
    -v|v|--verbose|verbose)                                                  v="-v"; shift ;;
    -jo|jo|--just-one|just-one)                       just_one_plugin="${2}"; shift; shift ;;
    -xa|xa|--exclude-any|exclude-any)              exclude_any_plugin="${2}"; shift; shift ;;
    -xl|xl|--exclude-last|exclude-last)                       exclude_last_plugin=1; shift ;;
    --pandoc|pandoc|--html|html)                                           pandoc=1; shift ;;
    --debug-esp|debug-esp)                                              debug_esp=1; shift ;;
    --filter-cont|filter-cont)                            filter_cont="${2}"; shift; shift ;;
    --filter-out-lid|filter-out-lid)                   filter_out_lid="${2}"; shift; shift ;;
    --special-cont-id-mode|special-cont-id-mode) special_cont_id_mode="${2}"; shift; shift ;;
    --publicans-mode|publicans-mode)                               publicans_mode=1; shift ;;
    --taverns-mode|taverns-mode)                           taverns_mode=1; create=0; shift ;;
    *)                                                                      usage=1; shift ;;
  esac
done

# Show help if needed
set -e; if [ "${help}" = 1 ]; then
  printf '
USAGE:
\t%s [FLAGS/OPTIONS]
\nFLAGS:
\t-0, --run
\t\tRun all steps (--assign --place --create)
\n\t-1, --assign
\t\tGet NPC_ records from plugins and assign containers to them
\n\t-2, --place
\t\tPlace containers into CELLs and prepare scripts to make ESPs
\n\t-3, --create
\t\tCreate ESPs from generated scripts
\n\t-h, --help
\t\tShow help page
\n\t--debug-esp
\t\tCreate additional debug esp with increased wares
\nOPTIONS:
\t-d, --dir "<dir>"
\t\tSet directory to store output instead of default: "%s"
\t-b, --basename "<string>"
\t\tSet output files basename instead of default: "Wares-base"
\n\t-m, --modular
\t\tCreate ESP for each plugin in addition to merged
\n\t-v, --verbose
\t\tShow files move and delete
\n\t-ja, --just-one "<plugin>"
\t\tCreate specific esp for one <plugin> in additional <dir> with " - <plugin>" suffix
\n\t-xa, --exclude-any "<plugin>"
\t\tCreate merged esp without <plugin> in additional <dir> with " - No <plugin>" suffix
\n\t-xl, --exclude-last
\t\tCreate additional merged esp without last plugin in list with " - No <last_plugin>" suffix
\nOPTIONS (EXPERIMENTAL):
\tUse at your own risk. No checks for variables correctness
\n\t--filter-cont "<wares_container_name>"
\t\tOnly work with NPCs that would have <wares_container_name> assigned.
\n\t--filter-out-lid "<lowercased_NPC_id>"
\t\tExclude one NPC ID.
\n\t--special-cont-id-mode "<cont_prefix>"
\t\tCreate non-respawning "<cont_prefix>_ID" CONT record and create instance of it for each NPC ID
\t\tRequires --filter-cont "<...>" argument set for now
\n\tUsed this options to create non-Wares patch with the following arguments:
\t\t--filter-cont "aa_wares_publican" --filter-out-lid "tr_m3_bols narvol" --special-cont-id-mode "aspc"
\t\tThis command created unique non-respawning container for each publican except Bols Narvol
\n\t--publicans-mode
\t\tAdditional very specific mode to add and remove some publicans from previous command
\t\tRequires --filter-cont "<...>" argument set for now
\n\t--taverns-mode
\t\tAdditional very specific mode to place sound acitvators for Better Sounds
\t\tRequires --filter-cont "<...>" argument set for now
\n\t--pandoc, --html
\t\tCreate html pages for containers_assigned, containers_placed. Requires "pandoc" to be present in PATH
\nCONFIGURATION:
\tSet variables on top of this file:
\t1. Plugins list:
\t\tplugins="\n\t\t<one plugin per line>\n\t\t"
\t2. Tes3cmd path:
\t\ttes3cmd="<path>"\n' "${0}" "${dir}"
  printf '\n%s\n\n' 'DIRECTORY STRUCTURE (after running example command "./container_generator.sh --run --debug-esp"):'
  printf '%-40s %s\n' '├── .temp                          ' '# temp files are placed here and deleted after every run'
  printf '%-40s %s\n' '├── backup                         ' '# backups are placed here before changing any file'
  printf '%-40s %s\n' '│   ├── esp                        ' '# '
  printf '%-40s %s\n' '│   ├── log                        ' '# '
  printf '%-40s %s\n' '│   ├── script                     ' '# '
  printf '%-40s %s\n' '│   └── container_generator.sh     ' '# backup of the generator script just in case'
  printf '%-40s %s\n' '├── containers_assigned.txt        ' '# list of containers assigned to NPCs (created at step 1)'
  printf '%-40s %s\n' '├── containers_placed.txt          ' '# list of containers placed into cells (created at step 2)'
  printf '%-40s %s\n' '├── esp                            ' '# result ESPs are placed here (created at step 3)'
  printf '%-40s %s\n' '│   ├── Wares-base - Merged.esp    ' '# ultimate result - plugin with containers placed from all plugins listed'
  printf '%-40s %s\n' '│   └── util                       ' '# small utility ESPs are placed here'
  printf '%-40s %s\n' '│       ├── cell_donor.esp         ' '# produced with Merged ESP and is used to speed up process'
  printf '%-40s %s\n' '│       └── wares_debug.esp        ' '# produced with "--debug-esp" flag and may be used to easily see changes in game'
  printf '%-40s %s\n' '├── log                            ' '# logs of ESPs generation'
  printf '%-40s %s\n' '│   ├── Wares-base - Merged.log    ' '# log of corresponding script run (created at step 3)'
  printf '%-40s %s\n' '│   └── wares_debug.log            ' '# '
  printf '%-40s %s\n' '└── script                         ' '# scripts to make ESPs are placed here (created at step 2)'
  printf '%-40s %s\n' '    └── Wares-base - Merged.sh     ' '# script of correcsponding ESP'
  printf '\n'; false
# Show brief usage and exit if no flag is set
elif [ "${usage}" = "1" ] || { [ -z "${assign}" ] && [ -z "${place}" ] && [ -z "${create}" ] && [ -z "${debug-esp}" ]; }; then
  printf 'Usage:\n\t%s [flags] [options [<name>]]\n\nFor more information try --help\n' "${0}"; false
# Direcory is required to continue
elif [ -z "${dir}" ]; then
  printf 'ERROR: Variable "dir" is empty\n'; false
fi; set +e

# Check for required programs
readonly REQUIRED_BUILTINS="command printf echo"
readonly REQUIRED_PROGRAMS="$tes3cmd mkdir tee cut sort mv sed wc tr rm cp ls comm"
for program in ${REQUIRED_BUILTINS}; do
  if ! command -v "${program}" > /dev/null 2>&1; then
    noreq=1; printf 'ERROR: SHELL_BUILTIN:%s not found. Try another shell to run the script.\n' "${program}"
  fi
done
for program in ${REQUIRED_PROGRAMS}; do
  if ! command -v "${program}" > /dev/null 2>&1; then
    noreq=1; printf 'ERROR: PROGRAM:%s not found. Install it to run the script.\n' "${program}"
  fi
done
if [ -n "${noreq}" ]; then
  printf 'ERROR: Exit due to unsatisfied requirements\n'; set -e; false
fi

# This checks pandoc availability when '--pandoc' argument present.
if [ -n "${pandoc}" ]; then
  if ! command -v "pandoc" > /dev/null 2>&1; then
    printf 'ERROR: PROGRAM:%s not found. Make sure to have it in PATH or run without "--pandoc" argument.\n' "pandoc"
    set -e; false
  fi
fi

# Faster grep selector. Ripgrep(rg) speeds up process A LOT when working with large plugins like TR_Mainland.esm.
# For ordinary small plugins it hardly make any difference.
readonly FASTER_GREP="rg"
if command -v "${FASTER_GREP}" > /dev/null 2>&1; then
  readonly grep=${FASTER_GREP}
else
  # shellcheck disable=SC2209
  readonly grep=grep
fi

# This mode is to quickly check / create one plugin (before adding it to plugin list perhaps)
if [ -n "${just_one_plugin}" ]; then
  just_one_plugin="$(echo "${just_one_plugin}" | $grep -v '^$' | sed -e 's/^[[:blank:]]*//' -e 's/[[:blank:]]*$//')"
  if [ "${just_one_plugin}" = "" ]; then
    echo "ERROR: Plugin name is empty"; set -e; false
  elif [ ! -e "${just_one_plugin}" ]; then
    echo "ERROR: Plugin \"${just_one_plugin}\" is missing"; set -e; false
  fi
  unset exclude_any_plugin exclude_last_plugin debug_esp
  modular=0
  plugins="${just_one_plugin}"
  dir="${dir} - ${just_one_plugin%.*}"
  merged_infix=" - ${just_one_plugin%.*}"
fi

# Allow to exclude 1 plugin. Made it specifically to allow merged without TR_Mainland with the same plugin list
if [ -n "${exclude_any_plugin}" ]; then
  if [ "${assign}" = "1" ]; then
    excluded_plugin="$(echo "${exclude_any_plugin}" | $grep -v '^$' | sed -e 's/^[[:blank:]]*//' -e 's/[[:blank:]]*$//')"
    if [ "${excluded_plugin}" = "" ]; then
      echo "ERROR: Plugin name to exclude is missing"; set -e; false
    elif [ ! -e "${excluded_plugin}" ]; then
      echo "ERROR: Couldn't find excluded plugin. Fix or remove it from the plugin list."; set -e; false
    fi
    excluded_suffix=" - No ${excluded_plugin%.*}"
    dir="${dir}${excluded_suffix}"
  else
    echo "ERROR: Exclude should only be used with \"--assign\" or \"--run\" flags"; set -e; false
  fi
fi

# Only allow using special_cont_id_mode when filter_cont set
if [ -n "${special_cont_id_mode}" ]; then
  if [ -z "${filter_cont}" ]; then
    echo "ERROR: --special-cont-id-mode is only allowed with --filter-cont set for now"; set -e; false
  fi
fi

# Directory paths
# Should probably switch to mktemp, but that'd make resulting script contain more logic :-\
readonly TEMP_DIR="${dir}/.temp"
readonly ESP_DIR="${dir}/esp"
readonly SCRIPT_DIR="${dir}/script"
readonly UTIL_DIR="${ESP_DIR}/util"
readonly LOG_DIR="${dir}/log"
readonly BACKUP_DIR="${dir}/backup"
readonly ESP_BACKUP_DIR="${BACKUP_DIR}/esp"
readonly SCRIPT_BACKUP_DIR="${BACKUP_DIR}/script"
readonly LOG_BACKUP_DIR="${BACKUP_DIR}/log"
# This will only be present when using --pandoc option
readonly CSS_DIR="${dir}/css"
readonly CSS_BACKUP_DIR="${BACKUP_DIR}/css"
# Output files names
if [ -n "${special_cont_id_mode}" ]; then
  readonly BASE_ESM="Morrowind.esm"
else
  readonly BASE_ESM="Wares-base.esm"
fi
if [ -n "${basename_provided}" ]; then
  readonly BASENAME="${basename_provided}"
else
  readonly BASENAME="${BASE_ESM%.*}"
fi
if [ -z "${merged_infix}" ]; then 
  merged_infix=" - Merged"
fi
readonly MERGED_SUFFIX="${merged_infix}${excluded_suffix}"
readonly MERGED_ESP="${ESP_DIR}/${BASENAME}${MERGED_SUFFIX}.esp"
readonly MERGED_SCRIPT="${SCRIPT_DIR}/${BASENAME}${MERGED_SUFFIX}.sh"
readonly MERGED_LOG="${LOG_DIR}/${BASENAME}${MERGED_SUFFIX}.log"
readonly CONTAINERS_ASSIGNED="${dir}/containers_assigned.txt"
readonly CONTAINERS_PLACED="${dir}/containers_placed.txt"
# Helper files names
readonly INITIAL_CELL_DONOR="Morrowind.esm"
readonly INITIAL_CONT_DONOR="Morrowind.esm"
readonly CELL_DONOR_ESP="${UTIL_DIR}/cell_donor.esp"
readonly CONT_DONOR_ESP="${UTIL_DIR}/cont_donor.esp"
readonly WARES_DEBUG_ESP="${UTIL_DIR}/wares_debug.esp"
# Other internal variables
readonly DONOR_INTERIOR_CELL_INITIAL="seyda neen, arrille's tradehouse"
readonly DONOR_EXTERIOR_CELL_INITIAL="sadrith mora (18, 4)"
readonly DONOR_INTERIOR_CELL="interior for generator"
readonly DONOR_EXTERIOR_CELL="exterior for generator (1, 1)"
readonly DONOR_CONT_INITIAL="crate_01_arrille"
readonly DONOR_CONT="donor_cont"
readonly HIDE="--backup-dir \"${TEMP_DIR}\" --hide-backups"
if [ "${modular}" != "1" ]; then modular=0; fi

# Create directory structure
set -e
if [ ! -d "${dir}" ]               ; then mkdir ${v} -- "${dir}"               ; fi
if [ ! -d "${TEMP_DIR}" ]          ; then mkdir ${v} -- "${TEMP_DIR}"          ; fi
if [ ! -d "${ESP_DIR}" ]           ; then mkdir ${v} -- "${ESP_DIR}"           ; fi
if [ ! -d "${SCRIPT_DIR}" ]        ; then mkdir ${v} -- "${SCRIPT_DIR}"        ; fi
if [ ! -d "${UTIL_DIR}" ]          ; then mkdir ${v} -- "${UTIL_DIR}"          ; fi
if [ ! -d "${LOG_DIR}" ]           ; then mkdir ${v} -- "${LOG_DIR}"           ; fi
if [ ! -d "${BACKUP_DIR}" ]        ; then mkdir ${v} -- "${BACKUP_DIR}"        ; fi
if [ ! -d "${ESP_BACKUP_DIR}" ]    ; then mkdir ${v} -- "${ESP_BACKUP_DIR}"    ; fi
if [ ! -d "${SCRIPT_BACKUP_DIR}" ] ; then mkdir ${v} -- "${SCRIPT_BACKUP_DIR}" ; fi
if [ ! -d "${LOG_BACKUP_DIR}" ]    ; then mkdir ${v} -- "${LOG_BACKUP_DIR}"    ; fi
if [ -n "${pandoc}" ]; then
if [ ! -d "${CSS_DIR}" ]           ; then mkdir ${v} -- "${CSS_DIR}"           ; fi
if [ ! -d "${CSS_BACKUP_DIR}" ]    ; then mkdir ${v} -- "${CSS_BACKUP_DIR}"    ; fi
fi
set +e

# Finally backup itself just in case
cp ${v} -- "${0}" "${BACKUP_DIR}/"

# Print command with arguments just in case
echo "Script arguments: ${ARGUMENTS}"

# Scan plugins for NPCs and assign them containers
if [ "${assign}" = 1 ]; then
  plugins="$(echo "${plugins}" | $grep -v '^$' | sed -e 's/^[[:blank:]]*//' -e 's/[[:blank:]]*$//')"
  if [ -n "${excluded_plugin}" ]; then
    plugins_without_excluded="$(echo "${plugins}" | $grep -v '^'"${excluded_plugin}"'$')"
    if [ "${plugins_without_excluded}" != "${plugins}" ]; then
      plugins="${plugins_without_excluded}"
    else
      echo "ERROR: Exclude failed - there is no difference without it. Check that name passed is correct."; set -e; false
    fi
  fi
  # Check plugins list exist
  if [ "${plugins}" = "" ]; then
    echo "ERROR: Plugins list is empty. Place plugin names into \"plugins:\" section of \"${0}\""; set -e; false
  fi
  # Check plugins exist
  plugins_absent="$(echo "${plugins}" | while read -r plugin; do
      if [ ! -s "${plugin}" ]; then
        printf 'ERROR: PLUGIN: "%s" not found\n' "${plugin}"
      fi; done)"
  if [ -n "${plugins_absent}" ]; then
    echo "${plugins_absent}"; set -e; false
  fi
  # Show step title
  printf '\n\t[[ Step 1: Start | Get NPC_ records from plugins and assign containers to them ]]\n\n'
  # Backup previous list of containers assigned if it exists
  if [ -s "${CONTAINERS_ASSIGNED}" ]; then
    mv $v -- "${CONTAINERS_ASSIGNED}" "${BACKUP_DIR}/"
    : > "${CONTAINERS_ASSIGNED}"
  fi
  # Start the main step loop 
  # shellcheck disable=SC2030
  echo "${plugins}" | while read -r plugin; do
    # Print legend first if it was not displayed
    if [ -z "${legend_printed}" ]; then
      legend_plugin_column_size="$(echo "${plugins}" | while read -r plug_line; do echo ${#plug_line}; done | sort -n | tail -1)"
      legend_filler="$(printf '|%0 *s|' "$(( 73 + legend_plugin_column_size ))" "" | tr '0' '-')"
      printf '%s\n%-24s | %-24s | %-16s | %s\n%s\n' "${legend_filler}" "Container name" "Owner ID" "Reason to assign" "Plugin name" "${legend_filler}"
      unset legend_filler legend_plugin_column_size
      legend_printed=1
    fi
    # Only select NPCs with required services, not "Training" or "Spellmaking"
    $tes3cmd dump "${plugin}" --type NPC_ --no-match 'Services:\[0x(00|02|40|08|48|88|c8|a000|140|188)00 ' | \
      sed -n \
        -e 's/  NAME: ID:\(.*\)/\1|/ p' \
        -e 's/  FNAM: Name:\(.*\)/\1|/ p' \
        -e 's/  CNAM: Class:\(.*\)/\1|/ p' \
        -e 's/  ANAM: Faction:\(.*\)/\1|/ p' \
        -e 's/ \*NPCO: Count:\-[0-9][0-9]*  Object:\(.*\)/\1,/ p' \
        -e 's/  AIDT:.*Services:\(.*\)/|\1^/ p' | \
      tr -d '\n' | tr '^' '\n' | \
      while read -r npc_str; do
        unset cont reason
        id="$(echo "${npc_str}"       | cut -d '|' -f 1 )"
        name="$(echo "${npc_str}"     | cut -d '|' -f 2 )"
        class="$(echo "${npc_str}"    | cut -d '|' -f 3 )"
        faction="$(echo "${npc_str}"  | cut -d '|' -f 4 )"
        objects="$(echo "${npc_str}"  | cut -d '|' -f 5 )"
        svc_str="$(echo "${npc_str}"  | cut -d '|' -f 6 )"
        if [ -n "${objects}" ]; then objects="${objects:0:-1}"; fi
        # shellcheck disable=SC2001
        svc_num="$(echo "${svc_str}"  | sed 's/\[0x\(.*\) (.*/\1/')"
        # These normalized values will be used in container regexps
        lid="$(echo "${id}"           | tr '[:upper:]' '[:lower:]')"
        lclass="$(echo "${class}"     | tr '[:upper:]' '[:lower:]')"
        lfaction="$(echo "${faction}" | tr '[:upper:]' '[:lower:]')"
        lplugin="$(echo "${plugin}"   | tr '[:upper:]' '[:lower:]')"
        # Let's find container type for this instance
        # Set container for specific NPCs
        case ${lid} in
          "sernsi drelas")                                 cont=aa_wares_trader_hlaalu     ; reason=id                   ;;
          # ashlander traders remastered.esp
          "cv_elder")                                      cont=aa_wares_trader_ash        ; reason=id                   ;;
          "cv_potter1")                                    cont=aa_wares_trader_ash        ; reason=id                   ;;
          # bt_whitewolf_2_0_hotv.esp
          "aa_shaman snorri")                              cont=aa_wares_apothecary        ; reason=id                   ;;
          # ccm-secretsofvos-v2-tb.esp
          "ccm-merchant-ashlander")                        cont=aa_wares_trader_ash        ; reason=id                   ;;
          # da_sobitur_repurposed_1.esp
          "_da_thiefcyborg")                               cont="########################" ; reason=id                   ;;
          # immersive mournhold.esp
          "1jw_newchar_servant2")                          cont="########################" ; reason=id                   ;;
          "1jw_newchar_servant3")                          cont="########################" ; reason=id                   ;;
          "1jw_newchar_servant4")                          cont="########################" ; reason=id                   ;;
          "rp_bazar_bookseller")                           cont=aa_wares_bookseller        ; reason=id                   ;;
          "rp_bazar_jeweler")                              cont="########################" ; reason=id                   ;;
          # mudcrab imports pirate adventures.esp 
          "mct_tradehousestaff2")                          cont=aa_wares_baker             ; reason=id                   ;;
          "ssa_scbarkeep1")                                cont=aa_wares_publican          ; reason=id                   ;;
          # sadrithmoraexpandedtr.esp # need only drinks levi, publican won't work here
          "exsadrith_dresbar")                             cont="########################" ; reason=id                   ;;
          # sadrithmoraexpandedtr.esp # need only drinks levi, publican won't work here
          "exsadrith_outbar")                              cont="########################" ; reason=id                   ;;
          # tel_aruhn_chronicles.esp # need only drinks levi, publican won't work here
          "llcs_bar_host")                                 cont="########################" ; reason=id                   ;;
          # tel_aruhn_chronicles.esp
          "llcs_bazar_armorer")                            cont=aa_wares_smith             ; reason=id                   ;;
          "llcs_bazar_bookseller")                         cont=aa_wares_bookseller        ; reason=id                   ;;
          "llcs_bazar_general")                            cont=aa_wares_pawn              ; reason=id                   ;;
          "llcs_bazar_jeweler")                            cont="########################" ; reason=id                   ;;
          # travelingmerchants_v2_3.esp
          "hb_wishheart")                                  cont=aa_wares_bookseller        ; reason=id                   ;;
          # nvi lite.esp
          "_vivnem_erasus_montaus")                        cont="########################" ; reason=id                   ;;
          "_vivnem_soruf_verus")                           cont=aa_wares_alchemist         ; reason=id                   ;;
          # vivec waistworks expansion - govh comp.esp
          "crcl_fqmiscmerch2")                             cont="########################" ; reason=id                   ;;
          "crcl_telvmixingseller")                         cont="########################" ; reason=id                   ;;
          "crcl_telvmuskman")                              cont="########################" ; reason=id                   ;;
          "crcl_tour3")                                    cont="########################" ; reason=id                   ;;
          "crcl_vivec_ashlander")                          cont=aa_wares_trader_ash        ; reason=id                   ;;
          "crcl_vivec_baker1")                             cont=aa_wares_baker             ; reason=id                   ;;
          "crcl_vivec_bluealit1")                          cont=aa_wares_publican          ; reason=id                   ;;
          "crcl_vivec_skooma")                             cont="########################" ; reason=id                   ;;
          "crcl_vivec_tatshopowner")                       cont="########################" ; reason=id                   ;;
          # wyrmhaven.esm
          "_wyrm_arnold")                                  cont=aa_wares_baker             ; reason=id                   ;;
          "_wyrm_belle")                                   cont=aa_wares_publican          ; reason=id                   ;;
          "_wyrm_benji")                                   cont="########################" ; reason=id                   ;;
          "_wyrm_joshua")                                  cont="########################" ; reason=id                   ;;
          "_wyrm_marius")                                  cont="########################" ; reason=id                   ;;
          "_wyrm_osriel")                                  cont="########################" ; reason=id                   ;;
          "_wyrm_reginald")                                cont="########################" ; reason=id                   ;;
          "_wyrm_snake")                                   cont="########################" ; reason=id                   ;;
          # cyrodiil_main.esm
          "pc_i1-str_aistillin")                           cont=aa_wares_publican          ; reason=id                   ;;
          "pc_i1-str_sylori")                              cont=aa_wares_publican          ; reason=id                   ;;
          # sky_main.esm
          "sky_ire_dsw_azkol")                             cont="########################" ; reason=id                   ;;
          "sky_ire_dsw_frithil")                           cont=aa_wares_smith             ; reason=id                   ;;
          "sky_ire_dsw_hjerolf")                           cont="########################" ; reason=id                   ;;
          "sky_ire_kw_ber-ryi")                            cont="########################" ; reason=id                   ;;
          "sky_ire_th_cypriana")                           cont="########################" ; reason=id                   ;;
          "sky_ire_th_gurna")                              cont=aa_wares_healer            ; reason=id                   ;;
          "sky_xre_dse_orcath")                            cont="########################" ; reason=id                   ;;
          "sky_ire_vf_azob")                               cont="########################" ; reason=id                   ;;
          # TR_Mainland.esm
          "tr_m1_hizam_aneroth")                           cont=aa_wares_publican          ; reason=id                   ;;
          #"tr_m1_kevlin")                                  cont="########################" ; reason=id                   ;;
          "tr_m1_olanasa_wenil")                           cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m1_thelera_tllas")                           cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m2_branasa tirvesu")                         cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m3_tilme sevenas")                           cont=aa_wares_publican          ; reason=id                   ;;
          # TR_Mainland.esm, v22.11, strange place with moon sugar, looks like a den
          "tr_m1_polanna")                                 cont="########################" ; reason=id                   ;;
          # TR_Mainland.esm, v22.11, cammona tong publican doesn't fit into this    
          "tr_m4_darayne_llarem")                          cont="########################" ; reason=id                   ;;
          # TR_Mainland.esm, this one is a jeweller, not clothes seller
          "tr_m1_cabrinth_dven")                           cont=aa_wares_trader            ; reason=id                   ;;
          # TR_Mainland.esm, v23.10
          # Sell EEC papers
          "tr_m1_alia jural")                              cont="########################" ; reason=id                   ;;
          "tr_m3_silver-paws ineni")                       cont="########################" ; reason=id                   ;;
          # Should only repair
          "tr_m3_anderyn lloran")                          cont="########################" ; reason=id                   ;;
          "tr_m3_buljor")                                  cont="########################" ; reason=id                   ;;
          "tr_m3_hal_indsmith")                            cont="########################" ; reason=id                   ;;
          "tr_m4_ilmesi adryn")                            cont="########################" ; reason=id                   ;;
          "tr_m4_ilmesi adryn2")                           cont="########################" ; reason=id                   ;;
          "tr_m4_v_velynthindo")                           cont="########################" ; reason=id                   ;;
          "tr_m7_lazare pajaud")                           cont="########################" ; reason=id                   ;;
          "tr_m7_o_rogon")                                 cont="########################" ; reason=id                   ;;
          # Only sells drinks
          "tr_m3_elanu tilvani")                           cont="########################" ; reason=id                   ;;
          # Only sells ranged
          "tr_m3_gaelwaen")                                cont="########################" ; reason=id                   ;;
          # Only sells religious books
          "tr_m7_bolnora omani")                           cont="########################" ; reason=id                   ;;
          # Only sells items in front of her
          "tr_m7_indriri terilu")                          cont="########################" ; reason=id                   ;;
          # Only sells most common items
          "tr_m7_fagus dorso")                             cont="########################" ; reason=id                   ;;
          # She's travelling
          "tr_m7_vamona folvyn")                           cont="########################" ; reason=id                   ;;
          # Not in that location
          "tr_m4_v_alvayah")                               cont="########################" ; reason=id                   ;;
          "tr_m4_v_utukkuseri")                            cont="########################" ; reason=id                   ;;
          "tr_m4_rowdy rilmas")                            cont="########################" ; reason=id                   ;;
          # Doesn't feel right
          "tr_m7_galas moran")                             cont="########################" ; reason=id                   ;;
          "tr_m7_binayne maren")                           cont="########################" ; reason=id                   ;;
          "tr_m7_uradras uvaren")                          cont="########################" ; reason=id                   ;;
          # These should have pulicans containers
          "tr_m3_ano dreloth")                             cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m1_froljir")                                 cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m7_anel rathri")                             cont=aa_wares_publican          ; reason=id                   ;;
          "tr_m3_guril vandus")                            cont=aa_wares_publican          ; reason=id                   ;;
          # Havish.esm
          # Havish.esm, not proper Inns
          "zh_tg_nevin")                                   cont="########################" ; reason=id                   ;;
          "zh_tg_bevanera ")                               cont="########################" ; reason=id                   ;;
          "zh_tg_meril ")                                  cont="########################" ; reason=id                   ;;
          "zh_yanni")                                      cont="########################" ; reason=id                   ;;
          "zh_tg_amanir")                                  cont="########################" ; reason=id                   ;;
          "zh_myrik")                                      cont="########################" ; reason=id                   ;;
          "zh_tg_alaina")                                  cont="########################" ; reason=id                   ;;
          # Havish.esm, not proper Healer
          "zh_c_dorbitodd_d")                              cont="########################" ; reason=id                   ;;
          # Havish.esm, should be commoners without access to extended wares
          "zh_c_keineth haleste")                          cont="########################" ; reason=id                   ;;
          "zh_c_reginus holdris")                          cont="########################" ; reason=id                   ;;
          "zh_c_selenia")                                  cont="########################" ; reason=id                   ;;
          "zh_c_moriel leaste")                            cont="########################" ; reason=id                   ;;
          "zh_c_avril")                                    cont="########################" ; reason=id                   ;;
          "zh_c_selis beveran")                            cont="########################" ; reason=id                   ;;
          # Havish.esm, sells only bows(and a lot of them), doesn't need access to other weapons
          "zh_t_elwing")                                   cont="########################" ; reason=id                   ;;
          # OAAB_Tel Mora, NPC_ from base game that doesn't need more containers
          "elegnan")                                       cont="########################" ; reason=id                   ;;
        esac
        if [ -n "${publicans_mode}" ]; then
          case "${lid}" in
            "tr_m1_sa'assa")                               cont=aa_wares_publican          ; reason=publicans            ;;
            "tr_m4_cirifae")                               cont=aa_wares_publican          ; reason=publicans            ;;
            # 23.10 Vavis Danvon used to have some food around, but now it looks like strictly drinking place
            "tr_m3_vavis"*)                          cont="########################" ; reason=publicans            ;;
          esac
        fi
        if [ -n "${taverns_mode}" ]; then
          case ${lid} in
          "zh_tg_nevin")                                   cont=aa_wares_publican          ; reason=taverns              ;;
          "zh_tg_meril ")                                  cont=aa_wares_publican          ; reason=taverns              ;;
          "zh_tg_amanir")                                  cont=aa_wares_publican          ; reason=taverns              ;;
          "zh_myrik")                                      cont=aa_wares_publican          ; reason=taverns              ;;
          "zh_t_berynn")                                   cont="########################" ; reason=taverns              ;;
          "pc_i1-str_aistillin")                           cont="########################" ; reason=taverns              ;;
          "tr_m1_yersod")                                  cont="########################" ; reason=taverns              ;;
          "tr_m3_oe_tg_delagiag_01")                       cont="########################" ; reason=taverns              ;;
          "tr_m3_bols narvol")                             cont="########################" ; reason=taverns              ;;
          "cs_nebia3")                                     cont="########################" ; reason=taverns              ;;
          "tolvise othralen")                              cont="########################" ; reason=taverns              ;;
          "binn_tr_m3_darnim_2_pub")                       cont="########################" ; reason=taverns              ;;
          "tr_m2_mjornir")                                 cont=aa_wares_publican          ; reason=taverns              ;;
          "tr_m1_elos_uvelen")                             cont="########################" ; reason=taverns              ;;
          "tr_m4_olvys omayn")                             cont="########################" ; reason=taverns              ;;
          "tr_m4_narusea verenim2")                        cont="########################" ; reason=taverns              ;;
          "tr_m3_charna gramohl")                          cont="########################" ; reason=taverns              ;;
          "tr_m2_uleras morenu")                           cont="########################" ; reason=taverns              ;;
          "tr_m4_lacey")                                   cont="########################" ; reason=taverns              ;;
          "tr_m4_kraki the grey")                          cont="########################" ; reason=taverns              ;;
          "tr_m4_dralen fols")                             cont="########################" ; reason=taverns              ;;
          "tr_m4_elynu_girando")                           cont="########################" ; reason=taverns              ;;
          # TR_Mainland.esm, v23.10
          "tr_m1_froljir")                                 cont="########################" ; reason=taverns              ;;
          "tr_m3_ano dreloth")                             cont="########################" ; reason=taverns              ;;
          "tr_m7_anel rathri")                             cont="########################" ; reason=taverns              ;;
          "tr_m7_dils sadri")                              cont="########################" ; reason=taverns              ;;
          "tr_m7_folms terians")                           cont="########################" ; reason=taverns              ;;
          "tr_m7_sanvyr deroth")                           cont="########################" ; reason=taverns              ;;
          esac
        fi
        # Some plugins do not need wares containers
        if [ -z "${cont}" ]; then
          case ${lplugin} in
          "memento mori.esp")                              cont="########################" ; reason=plugin               ;;
          "secretsofthecrystalcity.esp")                   cont="########################" ; reason=plugin               ;;
          "tel_eurus.esp")                                 cont="########################" ; reason=plugin               ;;
          esac
        fi
        # Set container based on class name
        if [ -z "${cont}" ]; then
          if   [[ "${lclass}" == *"alchemist"*    ]]; then cont=aa_wares_alchemist         ; reason=class
          elif [[ "${lclass}" == *"apothecary"*   ]]; then cont=aa_wares_apothecary        ; reason=class
          elif [[ "${lclass}" == *"assassin"*     ]]; then cont=aa_wares_assassin          ; reason=class
          elif [[ "${lclass}" == *"bookseller"*   ]]; then cont=aa_wares_bookseller        ; reason=class
          elif [[ "${lclass}" == *"clothier"*     ]]; then cont=aa_wares_clothes           ; reason=class
          elif [[ "${lclass}" == *"enchanter"*    ]]; then cont=aa_wares_magical           ; reason=class
          elif [[ "${lclass}" == *"healer"*       ]]; then cont=aa_wares_healer            ; reason=class
          elif [[ "${lclass}" == *"pawnbroker"*   ]]; then cont=aa_wares_pawn              ; reason=class
          elif [[ "${lclass}" == *"priest"*       ]]; then cont=aa_wares_priest            ; reason=class
          elif [[ "${lclass}" == *"publican"*     ]]; then cont=aa_wares_publican          ; reason=class
          elif [[ "${lclass}" == *"savant"*       ]]; then cont=aa_wares_savant            ; reason=class
          elif [[ "${lclass}" == *"smith"*        ]]; then cont=aa_wares_smith             ; reason=class
          elif [[ "${lclass}" == *"baker"*        ]]; then cont=aa_wares_baker             ; reason=class
          elif [[ "${lclass}" == *"thief"*        ]]; then cont=aa_wares_thief             ; reason=class
          elif [[ "${lclass}" == *"trader"*       ]]; then cont=aa_wares_trader            ; reason=class
          elif [[ "${lclass}" == *"merchant"*     ]]; then cont=aa_wares_trader            ; reason=class
          elif [[ "${lclass}" == *"wise"*"woman"* ]]; then cont=aa_wares_wise              ; reason=class
          fi
        fi
        # Set container based on services flag if not assigned yet; otherwise set to '#{24}'
        if [ -z "${cont}" ]; then
          case ${svc_num} in
            3110)
                                                           cont=aa_wares_alchemist         ; reason=service              ;;
            2110 | 3010)
                                                           cont=aa_wares_apothecary        ; reason=service              ;;
            4061)
                                                           cont=aa_wares_assassin          ; reason=service              ;;
            0004 | 0006 | 0014 | 0414 | 0415 | 1004)
                                                           cont=aa_wares_clothes           ; reason=service              ;;
            11000 | 11008 | 1140f | 11c0f | 1540f | 1b50f | 1c000 | 3560f | 3800 | 5c08 | 9800 | a23230 | b810 | b81c | f800)
                                                           cont=aa_wares_magical           ; reason=service              ;;
            2810 | 6110 | 7810 | 6810 | e810 | b910 | 6000 | 2008)
                                                           cont=aa_wares_healer            ; reason=service              ;;
            1777 | 269c | 2714 | 36f7 | 37f7)
                                                           cont=aa_wares_pawn              ; reason=service              ;;
            5808 | a02018 | a818 | b818)
                                                           cont=aa_wares_priest            ; reason=service              ;;
            6070 | 22010)
                                                           cont=aa_wares_publican          ; reason=service              ;;
            4008)
                                                           cont=aa_wares_savant            ; reason=service              ;;
            0001 | 0002 | 0003 | 0203 | 20002 | 20202 | 20203 | 20603 | 24203)
                                                           cont=aa_wares_smith             ; reason=service              ;;
            0060 | 0068 | 0470 | 4060 | 446c | 4470)
                                                           cont=aa_wares_thief             ; reason=service              ;;
            048c | 0695 | 1769 | 2369f | 268f | 27697 | 3108 | 34ff | 3697 | 369f | 377f | 379f | 37ff | 3fff)
                                                           cont=aa_wares_trader            ; reason=service              ;;
            a010 | a02800)
              if [ "${lfaction}" = "ashlanders" ]; then    cont=aa_wares_wise              ; reason=service; fi          ;;
            *)
                                                           cont="########################" ; reason="################"   ;;
          esac
        fi
        # Reassign containers based on faction
        case ${cont} in
          aa_wares_magical)
            case ${lfaction} in
              "imperial cult")                             cont=aa_wares_magical_IC        ; reason="faction[${reason}]" ;;
              "telvanni")                                  cont=aa_wares_magical_telv      ; reason="faction[${reason}]" ;;
              "temple")                                    cont=aa_wares_magical_temple    ; reason="faction[${reason}]" ;;
            esac                                                                                                         ;;
          aa_wares_trader)
            case ${lfaction} in
              "imperial cult")                             cont=aa_wares_trader_IC         ; reason="faction[${reason}]" ;;
              "t_sky_imperialcult")                        cont=aa_wares_trader_IC         ; reason="faction[${reason}]" ;;
              "ashlanders")                                cont=aa_wares_trader_ash        ; reason="faction[${reason}]" ;;
              "hlaalu")                                    cont=aa_wares_trader_hlaalu     ; reason="faction[${reason}]" ;;
              "imperial legion")                           cont=aa_wares_trader_legion     ; reason="faction[${reason}]" ;;
              "redoran")                                   cont=aa_wares_trader_redo       ; reason="faction[${reason}]" ;;
              "telvanni")                                  cont=aa_wares_trader_telv       ; reason="faction[${reason}]" ;;
            esac                                                                                                         ;;
        esac
        # Only work with NPCs who has "${filter_cont}" assigned
        if [ -n "${filter_cont}" ]; then
          if [ "${filter_cont}" != "${cont}" ]; then
            continue
          else 
            # Place unique container for each NPC
            if [ -n "${special_cont_id_mode}" ]; then
              if [ -n "${publicans_mode}" ]; then
                # don't remember reasons for these, but let's pretend it's ok
                case "${lid}" in
                  # 23.10 - decided to finally give him food. Plates around hint that he should have some food.
                  # "tr_m3_bols narvol")        continue ;;
                  "cs_nebia3")                continue ;;
                  "binn_tr_m3_darnim_2_pub")  continue ;;
                esac
              fi
              cont="${special_cont_id_mode}_${id//\'/\\\'}"
            fi
          fi
        fi
        # Filter out one NPC ID (lowercased)
        if [ -n "${filter_out_lid}" ]; then
          if [ "${filter_out_lid}" = "${lid}" ]; then
            continue
          fi
        fi
        # Print the result to terminal and file
        printf '%-24s | %-24s | %-16s | %s\n' "${cont:0:24}" "${id:0:24}" "${reason:0:16}" "${plugin}" 
        { printf '%s|' "${plugin}" "${id}" "${cont}" "${reason}" "${name}" "${class}" "${faction}" "${svc_str}"
          printf '%s\n' "${objects}"; } >> "${CONTAINERS_ASSIGNED}"
      done
    done
  # This is unneeded, as variable was assigned in subshell, though to be 100% sure
  unset legend_printed
  # Few more checks after the loop finished
  if [ ! -s "${CONTAINERS_ASSIGNED}" ]; then
    printf '\nERROR: Found no NPCs to assign containers in plugins listed. Try other plugins.\n\n'
    # In this case break next step run conditions
    place=0; create=0
  else
    # Generate html version if --pandoc options supplied
    if [ -n "${pandoc}" ]; then
      # Creates css if not present
      if [ ! -s "${CSS_DIR}/containers.css" ]; then
        printf 'table {\n\tborder-spacing: 0;\n\tcolor: black;\n\tbackground-color: whitesmoke;\n\tborder: 1px solid darkgray;\n}
table th {\n\tpadding: 3px 10px;\n\tbackground-color: seagreen;\n\tborder: 1px solid darkgray;\n\ttext-align: left;\n}
table td {\n\tpadding: 1px 10px;\n\tborder-bottom: 1px solid darkgray;\n\tborder-left: 1px solid whitesmoke;\n\tborder-right: 1px solid whitesmoke;\n}
tr:nth-child(even) {background-color: ghostwhite;}\ntr:hover {background-color: lightcyan;}\n' \
          > "${CSS_DIR}/containers.css"
      fi
      # Backup previous html if it exists
      if [ -s "${CONTAINERS_ASSIGNED%.*}.html" ]; then
        mv $v -- "${CONTAINERS_ASSIGNED%.*}.html" "${BACKUP_DIR}/"
        # Copy css for it as well, because the path to css is local inside html
        if [ -s "${CSS_DIR}/containers.css" ]; then
          cp $v -- "${CSS_DIR}/containers.css" "${CSS_BACKUP_DIR}/"
        fi
      fi
      # Transform the text and pass it to pandoc
      { echo '|Plugin|ID|Container|Reason|Name|Class|Faction|Services|Respawning items|'
        echo '|---|---|---|---|---|---|---|----|---|'
        sed -e 's/ /\\ /g' -e 's/|/ | /g' -e 's/^/| /' "${CONTAINERS_ASSIGNED}"
      } | pandoc -f markdown -t html -o "${CONTAINERS_ASSIGNED%.*}.html" -c "${CSS_DIR##*/}/containers.css" -s --quiet --metadata title="Containers assigned" -
    fi
    # Step 1 recap
    step_recap="Step 1: Finish"
    step_details="Details: \"${CONTAINERS_ASSIGNED}\""
    fill_x0=${#step_recap}
    fill_x1=${#step_details}
    filler="$(printf '|%0 *s|' "$((  fill_x0 + fill_x1 + 5 ))" "" | tr '0' '-')"
    printf '\n\t%s\n\t| %*s | %*s |\n' \
      "${filler}" "-${fill_x0}" "${step_recap}" "-${fill_x1}" "${step_details}"
    if [ -n "${pandoc}" ] && [ -s "${CONTAINERS_ASSIGNED%.*}.html" ]; then
      printf '\t| %*s | %*s |\n\t%s\n\n' \
        "-${fill_x0}" "" "-${fill_x1}" "HTML: \"${CONTAINERS_ASSIGNED%.*}.html\"" "${filler}"
    else
      printf '\t%s\n\n' "${filler}"
    fi
    # Tell if some plugins gain nothing from this script
    $grep -v '[|]########################[|]' -- "${CONTAINERS_ASSIGNED}" | cut -d '|' -f 1 | sort -u | comm -13 - <(echo "${plugins}" | sort -u) | \
      sed 's/^\(..*\)/NOTE: None instances selected for PLUGIN: "\1". Probably it gains nothing from this script./'
  fi
fi

# Make scripts that will produce patches
# It may be run separately long after Step 1, hence the rechecks of plugins existance etc
if [ "${place}" = "1" ] || { [ "${assign}" = "1" ] && [ "${create}" = "1" ] ;}; then
  # Show step title
  printf '\n\t[[ Step 2: Start | Place containers into CELLs and prepare scripts to make ESPs ]]\n\n'
  # Check list of containers assigned from previous step exists and not empty
  if [ -s "${CONTAINERS_ASSIGNED}" ]; then
    # Get list of plugins from previous step
    plugins="$($grep -v '[|]########################[|]' -- "${CONTAINERS_ASSIGNED}" | cut -d '|' -f 1 | uniq )" 
    # Get last plugin name if --exclude-last-plugin option is used
    x=1
    if [ "${exclude_last_plugin}" = "1" ]; then
      if [ "$(echo "${plugins}" | wc -l | tr -d '')" -gt 2 ]; then
        last_plugin="$(echo "${plugins}" | tail -1)"
      else
        echo "NOTE: Exclude last plugin option makes no sense now as there are less than 3 plugins listed"
      fi
    fi
    # Check plugins list exist
    if [ "${plugins}" = "" ]; then
      echo "ERROR: No plugins selected for this step"; set -e; false
    fi
    # Check plugins exist
    plugins_absent="$(echo "${plugins}" | while read -r plugin; do
        if [ "${plugin}" = "" ]; then
          echo "ERROR: Something went wrong when assiging containers. Some rows contain no plugin name."
        elif [ ! -s "${plugin}" ]; then
          printf 'ERROR: PLUGIN: "%s" not found\n' "${plugin}"
        fi
      done)"
    if [ -n "${plugins_absent}" ]; then echo "${plugins_absent}"; set -e; false; fi
    # If per plugin patches needed and more than one plugin listed
    if [ "${modular}" != "0" ]; then
      plugins_quantity="$(echo "${plugins}" | wc -l | tr -d '')"
      if [ "${plugins_quantity}" -gt 1 ]; then
        modular=1
      else
        modular=0
      fi
    fi
    # Backup files from previous run
    if [ -s "${MERGED_SCRIPT}" ]; then
      mv $v -- "${MERGED_SCRIPT}" "${SCRIPT_BACKUP_DIR}/"
    fi
    if [ -s "${CONTAINERS_PLACED}" ]; then
      mv $v -- "${CONTAINERS_PLACED}" "${BACKUP_DIR}/"
    fi
    # Create empty file for placed containers
    : > "${CONTAINERS_PLACED}"
    # Start loop to generate scripts
    echo "${plugins}" | while read -r plugin; do
      if [ "${modular}" = "1" ]; then
        modular_script="${SCRIPT_DIR}/${BASENAME} - ${plugin%.*}.sh"
        modular_esp="${ESP_DIR}/${BASENAME} - ${plugin%.*}.esp"
        if [ -s "${modular_script}" ]; then
          mv ${v} -- "${modular_script}" "${SCRIPT_BACKUP_DIR}/"
        fi
      fi
      # Print legend first if it was not displayed
      # shellcheck disable=SC2031
      if [ -z "${legend_printed}" ]; then
        legend_filler="$(printf '|%0 *s|' "105" "" | tr '0' '-')"
        printf '%s\n%-24s | %-24s | %-24s | %s\n%s\n' "${legend_filler}" "Container name" "Owner ID" "Plugin name" "Cell ID" "${legend_filler}"
        unset legend_filler
        legend_printed=1
      fi
      plugin_dump="${TEMP_DIR}/${plugin//-/_}.dump.txt"
      plugin_dump="${plugin_dump//\//_}"
      # Dump plugin CELLs into text. This take a while for very large plugins, i.e. 15 seconds for TR_Mainland.esm (the largest i've seen) on my machine
      $tes3cmd dump --type CELL "${plugin}" > "${plugin_dump}"
      # Create merged script without last plugin if --exclude-last-plugin option is used
      if [ "${exclude_last_plugin}" = "1" ]; then
        if [ "${plugin}" = "${last_plugin}" ]; then
          no_last_plugin_esp="${MERGED_ESP%.*} - No ${last_plugin%.*}.esp"
          no_last_plugin_script="${MERGED_SCRIPT%.*} - No ${last_plugin%.*}.sh"
          if [ -s "${no_last_plugin_script}" ]; then
            mv ${v} -- "${no_last_plugin_script}" "${SCRIPT_BACKUP_DIR}/"
          fi
          sed "s|\"${MERGED_ESP}\"|\"${no_last_plugin_esp}\"|" "${MERGED_SCRIPT}" > "${no_last_plugin_script}"
          chmod +x -- "${no_last_plugin_script}" > /dev/null 2>&1
        fi
      fi
      # Unreadable lines till while loop. Here i get all required subrecords to reconstrcut cells and add containers.
      # Scan text dump, mark lines with CELL and NPC instance records, then get them and parse to pass to loop
      # Using faster version of grep (rg, ag etc) is recommended here for large files and doesn't matter for most.
      # With rg it takes less than second for TR_Mainland.esm, 5 minutes without.
      sed -n -f <($grep -n -f <(echo 'Record: CELL' 
      sed -n "s/^${plugin}|\([^|]*\)|[^#].*/Name:\1$/p" "${CONTAINERS_ASSIGNED}") \
      -- "${plugin_dump}" | tac | sed -n '/NAME: Name:/,/Record: CELL/p' | tac | \
      sed -n -e 's|^\([0-9]*\):Record:.*|\1,/FRMR:/p|p' -e 's|^\([0-9]*\):  NAME:.*|\1,/DATA:/p|p') \
      "${plugin_dump}" | sed -n \
      -e 's/Record: CELL "\(.*\)" Flags:0x\(.*\) ()/c|\1|\2/p' \
      -e 's/  NAME: Name:\(.*\)/n|\1/p' \
      -e 's/  DATA: (Interior) Fog_Density:\(.*\)  Flags:0x\(.*\) (.*)/i|\1|\2/p' \
      -e 's/  DATA: (Exterior) Coordinates: (\([-0-9][0-9]*\), \([-0-9][0-9]*\))  Flags:0x\(.*\) (.*)/e|\1|\2|\3/p' \
      -e 's/  RGNN: Region:\(.*\)/r|\1/p' \
      -e 's/  NAM5: Color:\(.*\)/o|\1/p' \
      -e 's/ \*FRMR: .*/f|/p' \
      -e 's/  DATA: X:\([-0-9][\.0-9]*\)  Y:\([-0-9][\.0-9]*\)  Z:\([-0-9][\.0-9]*\) .*/x|\1|\2|\3/p' | \
      while read -r line; do
        # Process the list of main cell subrecords and npc instances
        # Look at first line letter (type of subrecord) and get values then
        case "${line:0:1}" in
          c)  cell="$(echo            "${line:2}" | cut -d '|' -f 1 )"
              case "${cell}" in
                "cyr_purgatory")
                  unset cell; continue ;;
              esac
              cell_flags="$(echo      "${line:2}" | cut -d '|' -f 2 )"
              cell_flags=$((16#$cell_flags))
              unset cell_name cell_type donor_cell cell_created modular_cell_created interior_fog interior_flags \
               exterior_x exterior_y exterior_flags region color placing_containers modular_refcount;;
          n)  if [ -z "${cell}" ]; then continue; fi
              if [ -z "${placing_containers}" ]; then
                cell_name="$(echo     "${line:2}" | cut -d '|' -f 1 )"
              else
                name="$(echo          "${line:2}" | cut -d '|' -f 1 )"
                # This is due to few npcs named with trailing space
                name_cont_pair="$($grep "^${plugin}[|]${name} *[|]" "${CONTAINERS_ASSIGNED}" | cut -d '|' -f 2,3 )" 
                name="$(echo "${name_cont_pair}"  | cut -d '|' -f 1 )"
                cont="$(echo "${name_cont_pair}"  | cut -d '|' -f 2 )"
              fi ;;
          i)  if [ -z "${cell}" ]; then continue; fi
              donor_cell="${DONOR_INTERIOR_CELL}"
              interior_fog="$(echo    "${line:2}" | cut -d '|' -f 1 )"
              interior_flags="$(echo  "${line:2}" | cut -d '|' -f 2 )"
              # Flags require hex to decimal conversion
              interior_flags=$((16#$interior_flags))
              cell_type=interior ;;
          e)  if [ -z "${cell}" ]; then continue; fi
              donor_cell="${DONOR_EXTERIOR_CELL}"
              exterior_x="$(echo      "${line:2}" | cut -d '|' -f 1 )"
              exterior_y="$(echo      "${line:2}" | cut -d '|' -f 2 )"
              exterior_flags="$(echo  "${line:2}" | cut -d '|' -f 3 )"
              exterior_flags=$((16#$exterior_flags))
              cell_type=exterior ;;
          r)  if [ -z "${cell}" ]; then continue; fi
              region="$(echo          "${line:2}" | cut -d '|' -f 1 )" ;;
          o)  if [ -z "${cell}" ]; then continue; fi
              color="$(echo           "${line:2}" | cut -d '|' -f 1 )" ;;
          f)  if [ -z "${cell}" ]; then continue; fi
              placing_containers=1 
              if [ -z "${counter}" ]; then
                counter=$(( $($grep -c '' "${CONTAINERS_PLACED}") + 1 ))
              fi
              # If script has not been created yet, then it's first pass - create helper cell donor esp to make patches a bit faster
              if [ ! -s "${MERGED_SCRIPT}" ]; then
                if [ -z "${taverns_mode}" ]; then
                { echo "$tes3cmd dump   \"${INITIAL_CELL_DONOR}\" --raw-with-header \"${CELL_DONOR_ESP}\" --type CELL \\
                   --exact-id \"${DONOR_INTERIOR_CELL_INITIAL}\" --exact-id \"${DONOR_EXTERIOR_CELL_INITIAL}\""
                  echo "$tes3cmd delete \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --instance-match \".*\""
                  echo "$tes3cmd delete \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --sub-match \"Reference_Count:\""
                  echo "$tes3cmd delete \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --sub-match \"Color:\""
                  echo "$tes3cmd delete \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --sub-match \"Water_Height:\""
                  echo "$tes3cmd delete \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --sub-match \"Ambient:\""
                  echo "$tes3cmd modify \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --exact-id \"${DONOR_INTERIOR_CELL_INITIAL}\" --run \"\\
                    \\\$R->set({f=>'Name'}, '${DONOR_INTERIOR_CELL}')\""
                  echo "$tes3cmd modify \"${CELL_DONOR_ESP}\" ${HIDE} --type CELL --exact-id \"${DONOR_EXTERIOR_CELL_INITIAL}\" --run \"\\
                    \\\$R->set({f=>'Name'}, '${DONOR_EXTERIOR_CELL// (*/}'), \\
                    \\\$R->set({t=>'DATA', f=>'X'}, '1'), \\
                    \\\$R->set({t=>'DATA', f=>'Y'}, '1')\""
                  echo
                  echo "$tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw-with-header \"${MERGED_ESP}\" --type CELL --exact-id \"${donor_cell}\""
                  initial_cell_placed=1
                  # shellcheck disable=SC2030,SC2031
                  if [ -z "${special_cont_id_mode}" ]; then
                    # Create file header and make Wares-base it's master # Don't do it if working in special_cont_id_mode
                    echo "$tes3cmd modify \"${MERGED_ESP}\" ${HIDE} --type TES3 --run \"\\
                    \\\$R->append(TES3::MAST->new({'master', 'Morrowind.esm'})), \\
                    \\\$R->append(TES3::DATA->new({'length', '79837557'})), \\
                    \\\$R->append(TES3::MAST->new({'master', 'Tribunal.esm'})), \\
                    \\\$R->append(TES3::DATA->new({'length', '4565686'})), \\
                    \\\$R->append(TES3::MAST->new({'master', 'Bloodmoon.esm'})), \\
                    \\\$R->append(TES3::DATA->new({'length', '9631798'})), \\
                    \\\$R->append(TES3::MAST->new({'master', '${BASE_ESM}'})), \\
                    \\\$R->append(TES3::DATA->new({'length', '266648'}))\""
                    echo "$tes3cmd header \"${MERGED_ESP}\" --synchronize ${HIDE}"
                    echo
                  fi
                } >> "${MERGED_SCRIPT}"
                fi
              fi
              # Do not create cell record if container was placed into this cell already
              if ! $grep -qF "|${cell}|" -- "${CONTAINERS_PLACED}"; then
                if [ -n "${taverns_mode}" ]; then
                { if [ -z "${initial_cell_placed}" ]; then
                    echo "curidx=\$((curidx + 1))"
                    echo "\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"${donor_cell}\""
                  fi
                  unset initial_cell_placed
                  # Few strings further get single quote sign escaped (prepended with backslash) with shell variable substring operation
                echo "\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"${donor_cell}\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, '${cell_name//\'/\\\'}'), \\"
                if [ -n "${exterior_flags}" ]; then
                  echo "\
                  \\\$R->set({t=>'DATA', f=>'X'}, '${exterior_x}'), \\
                  \\\$R->set({t=>'DATA', f=>'Y'}, '${exterior_y}'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '${exterior_flags}'), \\
                  \\\$R->set({t=>'RGNN', f=>'Region'}, '${region//\'/\\\'}'), \\"
                fi
                if [ -n "${interior_flags}" ]; then
                  echo "\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '${interior_fog}'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '${interior_flags}'), \\"
                  if [ -n "${region}" ]; then
                    echo "\
                  \\\$R->append(CELL::RGNN->new({'region', '${region//\'/\\\'}'})), \\"
                  fi
                fi
                if [ -n "${color}" ]; then
                  echo "\
                  \\\$R->append(CELL::NAM5->new({'color', '${color}'})), \\"
                fi } >> "${MERGED_SCRIPT}"
                else
                { if [ -z "${initial_cell_placed}" ]; then
                    echo "$tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw \"${MERGED_ESP}\" --type CELL --exact-id \"${donor_cell}\""
                  fi
                  unset initial_cell_placed
                  # Few strings further get single quote sign escaped (prepended with backslash) with shell variable substring operation
                echo "$tes3cmd modify \"${MERGED_ESP}\" ${HIDE} --type CELL --exact-id \"${donor_cell}\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, '${cell_name//\'/\\\'}'), \\"
                if [ -n "${exterior_flags}" ]; then
                  echo "\
                  \\\$R->set({t=>'DATA', f=>'X'}, '${exterior_x}'), \\
                  \\\$R->set({t=>'DATA', f=>'Y'}, '${exterior_y}'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '${exterior_flags}'), \\
                  \\\$R->set({t=>'RGNN', f=>'Region'}, '${region//\'/\\\'}'), \\"
                fi
                if [ -n "${interior_flags}" ]; then
                  echo "\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '${interior_fog}'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '${interior_flags}'), \\"
                  if [ -n "${region}" ]; then
                    echo "\
                  \\\$R->append(CELL::RGNN->new({'region', '${region//\'/\\\'}'})), \\"
                  fi
                fi
                if [ -n "${color}" ]; then
                  echo "\
                  \\\$R->append(CELL::NAM5->new({'color', '${color}'})), \\"
                fi } >> "${MERGED_SCRIPT}"
                fi
              else
                cell_created=1
              fi 
              # Repeat patch and cell creation command per each plugin if that's needed
              if [ "${modular}" = "1" ]; then
                if [ -z "${modular_counter}" ]; then
                  modular_counter=1
                  { echo "$tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw-with-header \"${modular_esp}\" --type CELL --exact-id \"${donor_cell}\""
                    modular_initial_cell_placed=1
                    echo "$tes3cmd modify \"${modular_esp}\" ${HIDE} --type TES3 --run \"\\
                      \\\$R->append(TES3::MAST->new({'master', 'Morrowind.esm'})), \\
                      \\\$R->append(TES3::DATA->new({'length', '79837557'})), \\
                      \\\$R->append(TES3::MAST->new({'master', 'Tribunal.esm'})), \\
                      \\\$R->append(TES3::DATA->new({'length', '4565686'})), \\
                      \\\$R->append(TES3::MAST->new({'master', 'Bloodmoon.esm'})), \\
                      \\\$R->append(TES3::DATA->new({'length', '9631798'})), \\
                      \\\$R->append(TES3::MAST->new({'master', '${BASE_ESM}'})), \\
                      \\\$R->append(TES3::DATA->new({'length', '102158'}))\""
                    echo "$tes3cmd header \"${modular_esp}\" --synchronize ${HIDE}"
                    echo
                  } >> "${modular_script}"
                fi 
                { if [ -z "${modular_initial_cell_placed}" ]; then
                    echo "$tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw \"${modular_esp}\" --type CELL --exact-id \"${donor_cell}\""
                  fi
                  unset modular_initial_cell_placed
                  echo "$tes3cmd modify \"${modular_esp}\" ${HIDE} --type CELL --exact-id \"${donor_cell}\" --run \"\\
                      \\\$R->set({t=>'NAME', f=>'Name'}, '${cell_name//\'/\\\'}'), \\"
                  if [ -n "${exterior_flags}" ]; then
                    echo "\
                      \\\$R->set({t=>'DATA', f=>'X'}, '${exterior_x}'), \\
                      \\\$R->set({t=>'DATA', f=>'Y'}, '${exterior_y}'), \\
                      \\\$R->set({t=>'DATA', f=>'Flags'}, '${exterior_flags}'), \\
                      \\\$R->set({t=>'RGNN', f=>'Region'}, '${region//\'/\\\'}'), \\"
                  fi
                  if [ -n "${interior_flags}" ]; then
                    echo "\
                      \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '${interior_fog}'), \\
                      \\\$R->set({t=>'DATA', f=>'Flags'}, '${interior_flags}'), \\"
                    if [ -n "${region}" ]; then
                      echo "\
                      \\\$R->append(CELL::RGNN->new({'region', '${region//\'/\\\'}'})), \\"
                    fi
                  fi
                  if [ -n "${color}" ]; then
                    echo "\
                      \\\$R->append(CELL::NAM5->new({'color', '${color}'})), \\"
                  fi } >> "${modular_script}"
              fi ;;
          x)  if [ -z "${cell}" ]; then continue; fi
              x="$(echo "${line:2}" | cut -d '|' -f 1 )"
              y="$(echo "${line:2}" | cut -d '|' -f 2 )"
              z="$(echo "${line:2}" | cut -d '|' -f 3 )"
              { if [ -z "${cell_created}" ]; then
                  echo "\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\"
                  cell_created=1
                else
                  refcount="$($grep -cF "|${cell}|" -- "${CONTAINERS_PLACED}")"
                  echo "$tes3cmd modify \"${MERGED_ESP}\" ${HIDE} --type CELL --exact-id \"${cell}\" --run \"\\
                      \\\$R->set({t=>'NAM0', f=>'reference_count'}, '$(( refcount + 1 ))'), \\"
                  unset refcount
                fi
                if [ -n "${taverns_mode}" ]; then
                  echo "\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '${x}', 'y', '${y}', 'z', '${z}', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\""
                else
                  echo "\
                      \\\$R->append(CELL::FRMR->new({'objidx', '${counter}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', '${cont}'})), \\
                      \\\$R->append(CELL::ANAM->new({'owner_actor', '${name//\'/\\\'}'})), \\
                      \\\$R->append(CELL::INTV->new({'health_left', '0'})), \\
                      \\\$R->append(CELL::NAM9->new({'owned', '1'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '${x}', 'y', '${y}', 'z', '${z}', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\""
                  printf 'echo "[add] %-24s | %-24s | %-24s | %s"\n' "${cont:0:24}" "${name:0:24}" "${plugin:0:24}" "${cell}" 
                  counter=$(( counter + 1 ))
                fi
                echo 
              } >> "${MERGED_SCRIPT}"
              # Repeat container placement in per plugin patches if needed
              if [ "${modular}" = "1" ]; then
                { if [ -z "${modular_cell_created}" ]; then
                    echo "\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\"
                    modular_cell_created=1
                    modular_refcount=1
                  else
                    modular_refcount=$(( modular_refcount + 1 ))
                    echo "$tes3cmd modify \"${modular_esp}\" ${HIDE} --type CELL --exact-id \"${cell}\" --run \"\\
                      \\\$R->set({t=>'NAM0', f=>'reference_count'}, '$(( modular_refcount ))'), \\"
                  fi
                  echo "\
                      \\\$R->append(CELL::FRMR->new({'objidx', '${modular_counter}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', '${cont}'})), \\
                      \\\$R->append(CELL::ANAM->new({'owner_actor', '${name//\'/\\\'}'})), \\
                      \\\$R->append(CELL::INTV->new({'health_left', '0'})), \\
                      \\\$R->append(CELL::NAM9->new({'owned', '1'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '${x}', 'y', '${y}', 'z', '${z}', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\""
                  printf 'echo "[add] %-24s | %-24s | %s"\n' "${cont:0:24}" "${name:0:24}" "${cell}" 
                  modular_counter=$(( modular_counter + 1 ))
                  echo 
                } >> "${modular_script}"
              fi
              # Finally print placed container information both to terminal and file
              printf '%-24s | %-24s | %-24s | %s\n' "${cont:0:24}" "${name:0:24}" "${plugin:0:24}" "${cell}" 
              { printf '%s|' "${plugin}" "${name}" "${cont}" "${cell}" "${x}" "${y}" "${z}"
                printf '%s\n' "${cell_type}"; } >> "${CONTAINERS_PLACED}" ;;
          *) continue ;;
        esac
      done

      # Remove plugin's text dump - it's not longer needed
      if [ -e "${plugin_dump}" ]; then
        rm -- "${plugin_dump}"
      fi
      # Make per plugin scripts executable
      if [ "${modular}" = "1" ] && [ -s "${modular_script}" ]; then
        chmod +x -- "${modular_script}" > /dev/null 2>&1
      fi
      # Process next plugin
    done

    # Very specific not really Wares-base related mode. Create unique container records.
    # shellcheck disable=SC2031
    if [ -n "${special_cont_id_mode}" ]; then
      if [ -n "${publicans_mode}" ]; then
        # shellcheck disable=SC2002
        publicans_mode_counter="$(cat "${CONTAINERS_PLACED}" | wc -l | tr -d ' ')"
        {
          printf '%s\n' "Morrowind.esm|darvam hlaren|aspc_darvam hlaren|ald-ruhn, council club|43.296|-308.173|0.147|interior"
          printf '%s\n' "Morrowind.esm|trivura arenim|aspc_trivura arenim|ald velothi, outpost|548.490|-249.783|-340.422|interior"
          printf '%s\n' "Morrowind.esm|orns omaren|aspc_orns omaren|molag mar, st. veloth's hostel|3762.389|3777.303|15556.428|interior"
        } >> "${CONTAINERS_PLACED}"
        # shellcheck disable=SC2028
        echo "./tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw \"${MERGED_ESP}\" --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\"
./tes3cmd modify \"${MERGED_ESP}\" --backup-dir \"${TEMP_DIR}\" --hide-backups --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Ald-ruhn, Council Club'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '$(( publicans_mode_counter + 1 ))', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'aspc_darvam hlaren'})), \\
                      \\\$R->append(CELL::ANAM->new({'owner_actor', 'darvam hlaren'})), \\
                      \\\$R->append(CELL::INTV->new({'health_left', '0'})), \\
                      \\\$R->append(CELL::NAM9->new({'owned', '1'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '43.296', 'y', '-308.173', 'z', '0.147', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"
echo \"[add] aspc_darvam hlaren       | darvam hlaren            | Improved Inns Expanded - | Ald-ruhn, Council Club\"

./tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw \"${MERGED_ESP}\" --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\"
./tes3cmd modify \"${MERGED_ESP}\" --backup-dir \"${TEMP_DIR}\" --hide-backups --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Ald Velothi, Outpost'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '$(( publicans_mode_counter + 2 ))', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'aspc_trivura arenim'})), \\
                      \\\$R->append(CELL::ANAM->new({'owner_actor', 'trivura arenim'})), \\
                      \\\$R->append(CELL::INTV->new({'health_left', '0'})), \\
                      \\\$R->append(CELL::NAM9->new({'owned', '1'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '548.490', 'y', '-249.783', 'z', '-340.422', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"
echo \"[add] aspc_trivura arenim      | trivura arenim           | Improved Inns Expanded - | Ald Velothi, Outpost\"
./tes3cmd dump   \"${CELL_DONOR_ESP}\" --raw \"${MERGED_ESP}\" --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\"
./tes3cmd modify \"${MERGED_ESP}\" --backup-dir \"${TEMP_DIR}\" --hide-backups --type CELL --exact-id \"${DONOR_INTERIOR_CELL}\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Molag Mar, St. Veloth\'s Hostel'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '$(( publicans_mode_counter + 3 ))', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'aspc_orns omaren'})), \\
                      \\\$R->append(CELL::ANAM->new({'owner_actor', 'orns omaren'})), \\
                      \\\$R->append(CELL::INTV->new({'health_left', '0'})), \\
                      \\\$R->append(CELL::NAM9->new({'owned', '1'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '3762.389', 'y', '3777.303', 'z', '15556.428', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"
echo \"[add] aspc_orns omaren         | orns omaren              | Improved Inns Expanded - | Molag Mar, St. Veloth's Hostel\"
" >> "${MERGED_SCRIPT}"
      fi
      # First create cont_donor_esp to speed up the process
      if [ -z "${taverns_mode}" ]; then
      { echo "$tes3cmd dump   \"${INITIAL_CONT_DONOR}\" --raw-with-header \"${CONT_DONOR_ESP}\" --type CONT --exact-id \"${DONOR_CONT_INITIAL}\""
        echo "$tes3cmd delete \"${CONT_DONOR_ESP}\" ${HIDE} --type CONT --sub-match \"Count:\""
        echo "$tes3cmd delete \"${CONT_DONOR_ESP}\" ${HIDE} --type CONT --sub-match \"Name:\""
        echo "$tes3cmd modify \"${CONT_DONOR_ESP}\" ${HIDE} --type CONT --exact-id \"${DONOR_CONT_INITIAL}\" --run \"\\
          \\\$R->set({t=>'MODL', f=>'Model'}, 'EditorMarker.nif'), \\
          \\\$R->set({t=>'Name', f=>'ID'}, '${DONOR_CONT}')\""
        } >> "${MERGED_SCRIPT}"
        # Finally create container records. Note that they are not respawning here, unlike Wares-base
        cut -d '|' -f 3 "${CONTAINERS_PLACED}" | while read -r special_cont; do
          echo "$tes3cmd dump \"${CONT_DONOR_ESP}\" --raw \"${MERGED_ESP}\" --type CONT --exact-id \"${DONOR_CONT}\""
          echo "$tes3cmd modify \"${MERGED_ESP}\" ${HIDE} --type CONT --exact-id \"${DONOR_CONT}\" --run \"\\
            \\\$R->set({t=>'NAME', f=>'ID'}, '${special_cont//\'/\\\'}')\""
          echo
        done >> "${MERGED_SCRIPT}"
      fi
      if [ -n "${taverns_mode}" ]; then
        # shellcheck disable=SC2028
        echo "curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Raven Rock, Bar'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '1.00'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '538.436', 'y', '568.410', 'z', '80.604', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Sadrith Mora, Fara\'s Hole in the Wall'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '-2.905', 'y', '-216.206', 'z', '404.663', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Tel Branora, Sethan\'s Tradehouse'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '813.537', 'y', '-501.339', 'z', '124.000', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"
curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Vivec, Black Shalk Cornerclub'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '690.420', 'y', '-346.855', 'z', '-48.392', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Vivec, The Flowers of Gold'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '-335.750', 'y', '53.296', 'z', '-106.560', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Vivec, The Lizard\'s Head'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '416.118', 'y', '176.211', 'z', '-119.333', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Vos, Varo Tradehouse'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '-27.988', 'y', '-208.901', 'z', '128.938', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Khuul, Thongar\'s Tradehouse'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '4241.494', 'y', '4498.365', 'z', '13746.809', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Maar Gan, Andus Tradehouse'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '8.000', 'y', '600.000', 'z', '-0.453', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Molag Mar, The Pilgrim\'s Rest'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '-968.095', 'y', '43.596', 'z', '-0.688', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Mournhold, The Winged Guar'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.50'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '-141.268', 'y', '161.891', 'z', '156.242', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Ald-ruhn, Council Club'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '43.296', 'y', '-308.173', 'z', '0.147', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"

curidx=\$((curidx + 1))
\${tes3cmd} dump   \"\${cell_donor}\" --raw \"\${result2}\" --type CELL --exact-id \"interior for generator\"
\${tes3cmd} modify \"\${result2}\" --hide-backups --type CELL --exact-id \"interior for generator\" --run \"\\
                  \\\$R->set({t=>'NAME', f=>'Name'}, 'Caldera, Shenk\'s Shovel'), \\
                  \\\$R->set({t=>'DATA', f=>'Fog_Density'}, '0.75'), \\
                  \\\$R->set({t=>'DATA', f=>'Flags'}, '5'), \\
                      \\\$R->append(CELL::NAM0->new({'reference_count', '1'})), \\
                      \\\$R->append(CELL::FRMR->new({'objidx', '\${curidx}', 'mastidx', '0'})), \\
                      \\\$R->append(CELL::NAME->new({'name', 'Sound_Tawern_Amb00'})), \\
                      \\\$R->append(CELL::DATA->new({'x', '255.728', 'y', '20.966', 'z', '127.471', 'x_angle', '0', 'y_angle', '0', 'z_angle', '0'}))\"
" >> "${MERGED_SCRIPT}"
      fi
    fi

    # Make script executable after outer loop completion
    chmod +x -- "${MERGED_SCRIPT}" > /dev/null 2>&1
    # Generate html version if --pandoc options supplied
    if [ -n "${pandoc}" ]; then
      # Creates css if not present
      if [ ! -s "${CSS_DIR}/containers.css" ]; then
        printf 'table {\n\tborder-spacing: 0;\n\tcolor: black;\n\tbackground-color: whitesmoke;\n\tborder: 1px solid darkgray;\n}
table th {\n\tpadding: 3px 10px;\n\tbackground-color: seagreen;\n\tborder: 1px solid darkgray;\n\ttext-align: left;\n}
table td {\n\tpadding: 1px 10px;\n\tborder-bottom: 1px solid darkgray;\n\tborder-left: 1px solid whitesmoke;\n\tborder-right: 1px solid whitesmoke;\n}
tr:nth-child(even) {background-color: ghostwhite;}\ntr:hover {background-color: lightcyan;}\n' \
          > "${CSS_DIR}/containers.css"
      fi
      # Backup previous html if it exists
      if [ -s "${CONTAINERS_PLACED%.*}.html" ]; then
        mv $v -- "${CONTAINERS_PLACED%.*}.html" "${BACKUP_DIR}/"
        # Copy css for it as well, because the path to css is local inside html
        if [ -s "${CSS_DIR}/containers.css" ]; then
          cp $v -- "${CSS_DIR}/containers.css" "${CSS_BACKUP_DIR}/"
        fi
      fi
      # Transform the text and pass it to pandoc
      { echo '|Plugin|ID|Container|Cell|X|Y|Z|Cell type|'
        echo '|---|---|---|---|---|---|---|----|'
        sed -e 's/ /\\ /g' -e 's/|/ | /g' -e 's/^/| /' "${CONTAINERS_PLACED}"
      } | pandoc -f markdown -t html -o "${CONTAINERS_PLACED%.*}.html" -c "${CSS_DIR##*/}/containers.css" -s --quiet --metadata title="Containers placed" -
    fi
    # Step 2 recap
    step_recap="Step 2: Finish"
    step_details="Details: \"${CONTAINERS_PLACED}\""
    step_details_2="Script dir: \"${SCRIPT_DIR}/\""
    fill_x0=${#step_recap}
    fill_x1="$(printf '%s\n' ${#step_details} ${#step_details_2} | sort -n | tail -1)"
    filler="$(printf '|%0 *s|' "$((  fill_x0 + fill_x1 + 5 ))" "" | tr '0' '-')"
    printf '\n\t%s\n\t| %*s | %*s |\n\t| %*s | %*s |\n' \
      "${filler}" "-${fill_x0}" "${step_recap}" "-${fill_x1}" "${step_details}" "-${fill_x0}" "" "-${fill_x1}" "${step_details_2}"
    if [ -n "${pandoc}" ] && [ -s "${CONTAINERS_PLACED%.*}.html" ]; then
      printf '\t| %*s | %*s |\n\t%s\n\n' \
        "-${fill_x0}" "" "-${fill_x1}" "HTML: \"${CONTAINERS_PLACED%.*}.html\"" "${filler}"
    else
      printf '\t%s\n\n' "${filler}"
    fi
    # Tell if some plugins gain nothing from this script (NPCs that were assigned the container are obviously instanced in another plugin)
    cut -d '|' -f 1 -- "${CONTAINERS_PLACED}" | sort -u | comm -13 - <(echo "${plugins}" | sort -u) | \
      sed 's/^\(..*\)/NOTE: None containers placed for PLUGIN: "\1". Probably it gains nothing from this script./'
  else
    echo "ERROR: List of containers assigned is empty. Run with \" --assign\" or \" --run\", or select other plugins."
    # In this case break next step run conditions
    create=0
  fi
fi

# Run scripts to create patches. Just for convenience to avoid running multiple scripts manually
# Even more spaghetti from here on
if [ "${create}" = 1 ]; then
  # Show step title
  printf '\n\t[[ Step 3: Start | Create ESPs from generated scripts ]]\n\n'
  # Check required files from previous step exist
  if [ -e "${MERGED_SCRIPT}" ]; then
    if [ -s "${MERGED_SCRIPT}" ]; then
      if [ -s "${CONTAINERS_PLACED}" ]; then
        plugins="$(cut -d '|' -f 1 "${CONTAINERS_PLACED}" | uniq )" 
        if [ "${plugins}" = "" ]; then
          echo "ERROR: No plugins in list of containers placed. This should have never happen. Run with \" --assign\" or \" --run\" or run scripts manually."; set -e; false
        fi
        # Check plugins existance
        plugins_absent="$(echo "${plugins}" | while read -r plugin; do
            if [ "${plugin}" = "" ]; then
              echo "ERROR: Something went wrong when placing containers. Some rows contain no plugin name."
            elif [ ! -s "${plugin}" ]; then
              printf 'ERROR: PLUGIN: "%s" not found\n' "${plugin}"
            fi
          done)"
        if [ -n "${plugins_absent}" ]; then echo "${plugins_absent}"; set -e; false; fi
      elif [ -e "${CONTAINERS_PLACED}" ]; then
        echo "ERROR: List of containers placed it empty. Run with \" --assign\" or \" --run\" or select other plugins or run scripts manually."; set -e; false
      else
        echo "ERROR: List of containers placed is not found. Run with \" --assign\" or \" --run\" or select other plugins or run scripts manually."; set -e; false
      fi
      if [ "${exclude_last_plugin}" = "1" ]; then
        if [ "$(echo "${plugins}" | wc -l | tr -d '')" -gt 2 ]; then
          last_plugin="$(echo "${plugins}" | tail -1)"
          no_last_plugin_script="${MERGED_SCRIPT%.*} - No ${last_plugin%.*}.sh"
          if [ -e "${no_last_plugin_script}" ]; then
            if [ ! -s "${no_last_plugin_script}" ]; then
              echo "ERROR: FILE:${no_last_plugin_script} contains nothing to do."; set -e; false
            fi
          else
            echo "ERROR: FILE:${no_last_plugin_script} not found. Run with \" --place\" or \" --run\" to make it."; set -e; false
          fi
        fi
      fi
      if [ "${modular}" != "0" ]; then
        plugins_quantity="$(echo "${plugins}" | wc -l | tr -d ' ')"
        if [ "${plugins_quantity}" -gt 1 ]; then
          modular=1
          echo "${plugins}" | while read -r plugin; do
            modular_script="${SCRIPT_DIR}/${BASENAME} - ${plugin%.*}.sh"
            if [ -e "${modular_script}" ]; then
              if [ ! -s "${modular_script}" ]; then
                printf 'NOTE: FILE:"%s" contains nothing to do.\n' "${modular_script}"
              fi
            else
              printf 'NOTE: FILE:"%s" not found. Probably PLUGIN: "%s" gains nothing from this script.\n' "${modular_script}" "${plugin}"
            fi
          done
        else
          modular=0
        fi
      fi
      # Backup previously made esp and log
      if [ -s "${MERGED_ESP}" ]; then
        mv ${v} -- "${MERGED_ESP}" "${ESP_BACKUP_DIR}/" 
      fi
      if [ -s "${MERGED_LOG}" ]; then
        mv ${v} -- "${MERGED_LOG}" "${LOG_BACKUP_DIR}/" 
      fi
      fill="$(printf '%s\n' ${#MERGED_SCRIPT} ${#MERGED_LOG} ${#MERGED_ESP} | sort -n | tail -1)"
      fill=$(( fill + 2 ))
      filler="$(printf '  |%0 *s|' "$(( fill + 7 ))" "" | tr '0' '-')"
      printf '%s\n  | Run: %*s |\n  | Log: %*s |\n  | Out: %*s |\n%s\n' \
        "${filler}" "-${fill}" "\"${MERGED_SCRIPT}\"" "-${fill}" "\"${MERGED_LOG}\"" "-${fill}" "\"${MERGED_ESP}\"" "${filler}"
      ./"${MERGED_SCRIPT}" 2>&1 | tee -- "${MERGED_LOG}" | $grep '^\[add\]'
      grep -i 'warning\|error' -- "${MERGED_LOG}" | sed 's/^/   [ERROR IN LOG] /'
      if [ "${exclude_last_plugin}" = "1" ]; then
        no_last_plugin_script="${MERGED_SCRIPT%.*} - No ${last_plugin%.*}.sh"
        no_last_plugin_esp="${MERGED_ESP%.*} - No ${last_plugin%.*}.esp"
        no_last_plugin_log="${MERGED_LOG%.*} - No ${last_plugin%.*}.log"
        if [ -s "${no_last_plugin_script}" ]; then
          if [ -s "${no_last_plugin_esp}" ]; then
            mv ${v} -- "${no_last_plugin_esp}" "${ESP_BACKUP_DIR}/" 
          fi
          if [ -s "${no_last_plugin_log}" ]; then
            mv ${v} -- "${no_last_plugin_log}" "${LOG_BACKUP_DIR}/" 
          fi
          fill="$(printf '%s\n' ${#no_last_plugin_script} ${#no_last_plugin_log} ${#no_last_plugin_esp} | sort -n | tail -1)"
          fill=$(( fill + 2 ))
          filler="$(printf '  |%0 *s|' "$(( fill + 7 ))" "" | tr '0' '-')"
          printf '%s\n  | Run: %*s |\n  | Log: %*s |\n  | Out: %*s |\n%s\n' \
            "${filler}" "-${fill}" "\"${no_last_plugin_script}\"" "-${fill}" "\"${no_last_plugin_log}\"" "-${fill}" "\"${no_last_plugin_esp}\"" "${filler}"
          ./"${no_last_plugin_script}" 2>&1 | tee -- "${no_last_plugin_log}" | $grep '^\[add\]'
          grep -i 'warning\|error' -- "${no_last_plugin_log}" | sed 's/^/   [ERROR IN LOG] /'
        fi
      fi
      if [ "${modular}" = "1" ]; then
        echo "${plugins}" | while read -r plugin; do
          modular_script="${SCRIPT_DIR}/${BASENAME} - ${plugin%.*}.sh"
          modular_esp="${ESP_DIR}/${BASENAME} - ${plugin%.*}.esp"
          modular_log="${LOG_DIR}/${BASENAME} - ${plugin%.*}.log"
          if [ -s "${modular_script}" ]; then
            if [ -s "${modular_esp}" ]; then
              mv ${v} -- "${modular_esp}" "${ESP_BACKUP_DIR}/" 
            fi
            if [ -s "${modular_log}" ]; then
              mv ${v} -- "${modular_log}" "${LOG_BACKUP_DIR}/" 
            fi
            fill="$(printf '%s\n' ${#modular_script} ${#modular_log} ${#modular_esp} | sort -n | tail -1)"
            fill=$(( fill + 2 ))
            filler="$(printf '  |%0 *s|' "$(( fill + 7 ))" "" | tr '0' '-')"
            printf '%s\n  | Run: %*s |\n  | Log: %*s |\n  | Out: %*s |\n%s\n' \
              "${filler}" "-${fill}" "\"${modular_script}\"" "-${fill}" "\"${modular_log}\"" "-${fill}" "\"${modular_esp}\"" "${filler}"
            ./"${modular_script}" 2>&1 | tee -- "${modular_log}" | $grep '^\[add\]'
            grep -i 'warning\|error' -- "${modular_log}" | sed 's/^/   [ERROR IN LOG] /'
          fi
        done
      fi
    else
      echo "ERROR: FILE:${MERGED_SCRIPT} contains nothing to do. Run with \" --run\" or select other plugins."
    fi
  else
    echo "ERROR: FILE:${MERGED_SCRIPT} not found. Run with \" --run\" or select other plugins."
  fi
  # Step 3 recap
  step_recap="Step 3: Finish"
  step_details="Log dir: \"${LOG_DIR}/\""
  step_details_2="ESP dir: \"${ESP_DIR}/\""
  fill_x0=${#step_recap}
  fill_x1="$(printf '%s\n' ${#step_details} ${#step_details_2} | sort -n | tail -1)"
  filler="$(printf '|%0 *s|' "$((  fill_x0 + fill_x1 + 5 ))" "" | tr '0' '-')"
  printf '\n\t%s\n\t| %*s | %*s |\n\t| %*s | %*s |\n\t%s\n\n' \
    "${filler}" "-${fill_x0}" "${step_recap}" "-${fill_x1}" "${step_details}" "-${fill_x0}" "" "-${fill_x1}" "${step_details_2}" "${filler}"
  # Cleaning temp files, should be harmless
  # shellcheck disable=SC2012
  if [ "$(ls -1 -- "${TEMP_DIR}" | wc -l | tr -d ' ')" != "0" ]; then
    rm $v -- "${TEMP_DIR}/"*
  fi
fi

# Create additional plugin with reshuffled wares value so you can easily see if everything's ok in game, 
# i.e. clothier would have few dozens of pants if affected by wares.
if [ "${debug_esp}" = 1 ]; then
  wares_debug_log_file="${LOG_DIR}/${WARES_DEBUG_ESP##*/}"
  wares_debug_log_file="${wares_debug_log_file%.*}.log"
  fill="$(printf '%s\n' ${#wares_debug_log_file} ${#WARES_DEBUG_ESP} | sort -n | tail -1)"
  fill=$(( fill + 2 ))
  filler="$(printf '  |%0 *s|' "$(( fill + 7 ))" "" | tr '0' '-')"
  printf '\n%s\n  | Log: %*s |\n  | Out: %*s |\n%s\n' \
    "${filler}" "-${fill}" "\"${wares_debug_log_file}\"" "-${fill}" "\"${WARES_DEBUG_ESP}\"" "${filler}"
  {
    $tes3cmd dump "${BASE_ESM}" --raw-with-header "${WARES_DEBUG_ESP}" \
      --type CONT \
      --exact-id "aa_wares_trader" \
      --exact-id "aa_wares_smith" \
      --exact-id "aa_wares_alchemist" \
      --exact-id "aa_wares_publican" \
      --exact-id "aa_wares_bookseller" \
      --exact-id "aa_wares_apothecary" \
      --exact-id "aa_wares_priest" \
      --exact-id "aa_wares_healer" \
      --exact-id "aa_wares_clothes"

    $tes3cmd dump "${BASE_ESM}" --raw "${WARES_DEBUG_ESP}" \
      --type LEVI \
      --exact-id "aa_trader_misc" \
      --exact-id "aa_trader_repair" \
      --exact-id "aa_trader_armour" \
      --exact-id "aa_trader_weapons" \
      --exact-id "aa_trader_apparatus" \
      --exact-id "aa_trader_drinks" \
      --exact-id "aa_trader_books" \
      --exact-id "aa_trader_foods" \
      --exact-id "aa_trader_potions_resist" \
      --exact-id "aa_trader_potions_cure" \
      --exact-id "aa_trader_potions_restore" \
      --exact-id "aa_trader_accessories" \
      --exact-id "aa_trader_clothes"

    $tes3cmd delete "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups \
      --type CONT --exact-id "aa_wares_trader" --sub-no-match "t:aa_trader_misc" --sub-match "Count:"
    $tes3cmd delete "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups \
      --type CONT --exact-id "aa_wares_alchemist" --sub-no-match "t:aa_trader_apparatus" --sub-match "Count:"
    $tes3cmd delete "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups \
      --type CONT --exact-id "aa_wares_apothecary" --sub-no-match "t:aa_trader_apparatus" --sub-match "Count:"

    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type CONT \
      --match "aa_wares_" --run "\$R->set({t=>'NPCO', f=>'Count'}, '50')"

    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_misc" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'ingred_bread_01'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_repair" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'hammer_repair'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_armour" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'netch_leather_boots'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_weapons" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'iron club'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_apparatus" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'apparatus_a_alembic_01'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_drinks" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'potion_comberry_brandy_01'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_foods" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'ingred_bread_01'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_books" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'bk_DoorsOfTheSpirit'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_potions_resist" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'p_disease_resistance_b'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_potions_cure" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'p_cure_common_s'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_potions_restore" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'p_restore_agility_b'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_accessories" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'common_ring_01'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
    $tes3cmd modify "${WARES_DEBUG_ESP}" --backup-dir "${TEMP_DIR}" --hide-backups --type LEVI --exact-id "aa_trader_clothes" --run "\
      \$R->append(LEVI::INDX->new({'item_count', '1'})), \
      \$R->append(LEVI::INAM->new({'item_id', 'common_pants_02'})), \
      \$R->append(LEVI::INTV->new({'level', '1'}))"
  } \
    > "${wares_debug_log_file}" 2>&1
  $grep -i 'warning\|error' -- "${wares_debug_log_file}" | sed 's/^/   [ERROR IN LOG] /'
  echo
  # Cleaning temp files, should be harmless
  # shellcheck disable=SC2012
  if [ "$(ls -1 -- "${TEMP_DIR}" | wc -l | tr -d ' ')" != "0" ]; then
    rm $v -- "${TEMP_DIR}/"*
  fi
fi
# Following mods do not need additional container IMO:
# ABCmod.ESP
# The Doors of Oblivion 1.4.esp
# GhostRevenge.ESP
# GhostRevenge_TR1912.esp
# Sotha Sil Expanded.ESP
# Welcome to the Arena! v6.7.esp
# Cavern Tavern.ESP
# Ebonheart Imperial Chapels Redo v2.01.esp
# Epilogue - Sail to Akavir.ESP
# TeaMod_2.1.esp
# Temple Bath Houses v1.2.esp
# Soul Gems at Ghostgate.ESP
# Silent Island.esp
# Racer Dust Arms and Armor.ESP
# Fighters_Guild_Questline_Overhaul.ESP
# The Lamp.esp
# Clean_Mines & Caverns.esp
# DartboardsExpanded.esp
# Mage Robes.ESP
# Guild of Vampire Hunters.ESP
# MQE_MainQuestEnhancers.esp
# NON1.LoveintheTimeofDaedra.v1.03_Abot.esp
# OAAB - Shipwrecks.ESP
# DA_Sobitur_Facility_Clean.ESP
# RP House Hlaalu.esp
# RPNR_Vivec_Street_Vendors.ESP
# Salt Gems of Bensamsi.ESP
# ShrineOfAzura.ESP
# The Great Fantasco.ESP
# Of Dungeons and Abodes.esp
# OldMournholdOverhaul.ESP
# quarraclan_refreshed.esp
# Quests for Clans and Vampire Legends.ESP
# Redoran Archmaster's Office v2.1.esp
# Uvirith's Legacy_3.53.esp
#
# Remove:
# Clean Dagon Fel Mages' Guild - NoQuests.ESP
# Improved Inns Expanded - TR Addon - Entertainers.ESP
#
# Add:
# Memento Mori.ESP
# SecretsOfTheCrystalCity.esp
# Tel_Eurus.esp
