h8rt3rmin8r

borderlands3-dps.sh

Jan 27th, 2021 (edited)
734
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #! /usr/bin/env bash
  2. #>-------------------------------------------------------------------------------
  3. #>
  4. #> [ bl3-dps ]
  5. #>
  6. #>    Calculate damage-per-second on guns found in Borderlands 3
  7. #>
  8. #>    This is an interactive script (no direct inputs are required). Outputs
  9. #>    are saved into a local CSV file. Over time, this output file can serve
  10. #>    as a personal DPS database.
  11. #>
  12. #> SOURCE:
  13. #>
  14. #>    Pastebin: http://bit.ly/39qhOiG
  15. #>    Github: http://bit.ly/39slArV
  16. #>
  17. #> USAGE:
  18. #>
  19. #>    ./bl3-dps.sh (<OPTION>)
  20. #>
  21. #>    where "OPTION" is an optional input; and where "OPTION" is one of the
  22. #>    following:
  23. #>
  24. #>                    |
  25. #>    --change-log    | Print the script change log to the terminal
  26. #>                    |
  27. #>    -h, --help      | Print this help text to the terminal
  28. #>                    |
  29. #>    -r, --read      | Print the entire local DPS data file to the standard
  30. #>                    | output (renders data in JSON syntax)
  31. #>                    |
  32. #>    -R, --read-csv  | Same as '--read' but prints the output in CSV format
  33. #>                    |
  34. #>
  35. #>-------------------------------------------------------------------------------
  36. #C>-------------------------------------------------------------------------------
  37. #C> CHANGE LOG:
  38. #C>
  39. #C>    Created on 20210125 by h8rt3rmin8r
  40. #C>
  41. #C>      - Began script creation
  42. #C>
  43. #C>    Updated on 20210127 by h8rt3rmin8r
  44. #C>
  45. #C>      - Completed first version of the script
  46. #C>
  47. #C>    Updated on 20210128 by h8rt3rmin8r
  48. #C>
  49. #C>      - Added help text function
  50. #C>      - Added change log function
  51. #C>      - Added standalone function for conversion of JSON syntax into CSV
  52. #C>      - Truncated sub-decimal zeros on damage_final and fire_rate_final
  53. #C>      - Added support for anoint text
  54. #C>      - Added automatic de-duplication on record inserts
  55. #C>      - Updated self-referencing process used by script verbosity function
  56. #C>
  57. #C> TO-DO:
  58. #C>
  59. #C>      - Add support for weapon elements
  60. #C>      - Add support for Accuracy, Handling, Reload Time, and Magazine Size
  61. #C>
  62. #C>-------------------------------------------------------------------------------
  63.  
  64. #________________________________________________________________________________
  65. # Declare functions
  66.  
  67. ## interactive functions
  68.  
  69.     function bl3dps_ask_string() {
  70.         #> Ask the user for a string in response to a specified question
  71.         #>
  72.         #> Outputs are exported as the global variable "$OUST"
  73.         #>
  74.         #______________________________________________________________________________
  75.  
  76.         local question=$(echo -n "$@")
  77.  
  78.         read -p "${question} " REPLY
  79.  
  80.         local reply_mod=$(tr -d "'*\\\"," <<<"${REPLY}")
  81.  
  82.         export OUST="${reply_mod}"
  83.  
  84.         return $?
  85.     }
  86.  
  87.     function bl3dps_ask_number_positive() {
  88.         #> Ask the user to enter a non-negative number in response to a question
  89.         #>
  90.         #> Outputs are exported as the global variable "$OUST"
  91.         #>
  92.         #______________________________________________________________________________
  93.  
  94.         local reply_mod=""
  95.         local INST="$@"
  96.  
  97.         read -p "${INST} (#?):  " REPLY
  98.  
  99.         local reply_src="${REPLY}"
  100.         local reply_mod=$(echo "${REPLY,,}" | tr -d "'*\\\"+%,")
  101.         local reply_mod_test=$(egrep --quiet '^([1-9]|[1-9][0-9]+|[0-9][.][0-9]+|[1-9][0-9]+[.][0-9]+)$' <<<"${reply_mod}"; echo $?)
  102.  
  103.         while [[ ! "${reply_mod_test}" -eq 0 ]]; do
  104.  
  105.             echo "" &>/dev/stderr  ##==> line break
  106.             echo "ERROR: Unknown response detected" &>/dev/stderr
  107.             echo "Please enter a valid non-negative number ..." &>/dev/stderr
  108.  
  109.             ${FUNCNAME} "${INST}"
  110.  
  111.             local reply_mod_test=$(egrep --quiet '^([1-9]|[1-9][0-9]+|[0-9][.][0-9]+|[1-9][0-9]+[.][0-9]+)$' <<<"${reply_mod}"; echo $?)
  112.         done
  113.  
  114.         export OUST="${reply_mod}"
  115.  
  116.         return $?
  117.     }
  118.  
  119.     function bl3dps_ask_number_whole() {
  120.         #> Ask the user to enter a whole number in response to a question
  121.         #>
  122.         #> Outputs are exported as the global variable "$OUST"
  123.         #>
  124.         #______________________________________________________________________________
  125.  
  126.         local reply_mod=""
  127.         local INST="$@"
  128.  
  129.         read -p "${INST} (#?):  " REPLY
  130.  
  131.         local reply_src="${REPLY}"
  132.         local reply_mod=$(echo "${REPLY,,}" | tr -d "'*\\\"+%,")
  133.  
  134.         while [[ ! "${reply_mod}" =~ ^-?[0-9]+$ ]]; do
  135.  
  136.             echo "" &>/dev/stderr  ##==> line break
  137.             echo "ERROR: Unknown response detected" &>/dev/stderr
  138.             echo "Please enter a valid positive or negative whole number ..." &>/dev/stderr
  139.  
  140.             ${FUNCNAME} "${INST}"
  141.         done
  142.  
  143.         export OUST="${reply_mod}"
  144.  
  145.         return $?
  146.     }
  147.  
  148.     function bl3dps_ask_number_whole_positive() {
  149.         #> Ask the user to enter a non-negative whole number in response to a question
  150.         #>
  151.         #> Outputs are exported as the global variable "$OUST"
  152.         #>
  153.         #______________________________________________________________________________
  154.  
  155.         local reply_mod=""
  156.         local INST="$@"
  157.  
  158.         read -p "${INST} (#?):  " REPLY
  159.  
  160.         local reply_src="${REPLY}"
  161.         local reply_mod=$(echo "${REPLY,,}" | tr -d "'*\\\"+%,")
  162.  
  163.         while [[ ! "${reply_mod}" =~ ^[0-9]+$ ]]; do
  164.  
  165.             echo "" &>/dev/stderr  ##==> line break
  166.             echo "ERROR: Unknown response detected" &>/dev/stderr
  167.             echo "Please enter a valid non-negative whole number ..." &>/dev/stderr
  168.  
  169.             ${FUNCNAME} "${INST}"
  170.         done
  171.  
  172.         export OUST="${reply_mod}"
  173.  
  174.         return $?
  175.     }
  176.  
  177.     function bl3dps_ask_options() {
  178.         #> Ask the user to select an answer from a list of indicated options
  179.         #>
  180.         #> Outputs are exported as the global variable "$OUST"
  181.         #>
  182.         #______________________________________________________________________________
  183.  
  184.         local runtime="$(date '+%s%N')"
  185.         local nonce="${RANDOM:0:1}${RANDOM: -1}${RANDOM: -1}${RANDOM: -1}${RANDOM: -1}"
  186.         local tmpf="/tmp/${FUNCNAME}_${runtime}-${nonce}"
  187.         local OPTIONS_COUNT="$#"
  188.         local OPTIONS_INPUT="$@"
  189.         local PRINT_OPEN="(Select a number from the following list)"
  190.  
  191.         echo "${OPTIONS_INPUT}" \
  192.             | sed 's/--//g' \
  193.             | tr ' ' '\n' \
  194.             | tr -d '"' \
  195.             | tr '_' ' ' >> "${tmpf}"
  196.  
  197.         mapfile -t L_ARR <"${tmpf}"
  198.  
  199.         echo "${PRINT_OPEN}" &>/dev/stderr
  200.  
  201.         select opt in "${L_ARR[@]}"; do
  202.             echo "" &>/dev/stderr
  203.             export OUST="$opt"
  204.             break
  205.         done
  206.  
  207.         rm "${tmpf}" &>/dev/null
  208.  
  209.         return $?
  210.     }
  211.  
  212.     function bl3dps_ask_truefalse() {
  213.         #> Ask a true/false question (output is $OUST as "true" or "false")
  214.         #>
  215.         #______________________________________________________________________________
  216.  
  217.         local reply_mod=""
  218.         local INST="$@"
  219.  
  220.         read -p "${INST} (True/False):  " REPLY
  221.        
  222.         local reply_src="${REPLY}"
  223.         local reply_mod=$(echo "${REPLY,,}" | tr -d "'*\\\",")
  224.         local reply_mod="${reply_mod:0:1}"
  225.  
  226.         while [[ ! "${reply_mod}" =~ ^[FfTt]$ ]]; do
  227.             echo "" &>/dev/stderr  ##==> line break
  228.             echo "ERROR: Unknown response detected" &>/dev/stderr
  229.             echo "Please indicate either (T)rue or (F)alse ..." &>/dev/stderr
  230.        
  231.             ${FUNCNAME} "${INST}"
  232.         done
  233.  
  234.         case "${reply_mod}" in
  235.             f|F)
  236.                 export OUST="false"
  237.                 return $?
  238.                 ;;
  239.             t|T)
  240.                 export OUST="true"
  241.                 return $?
  242.                 ;;
  243.         esac
  244.     }
  245.  
  246. ## math functions
  247.  
  248.     function bl3dps_math_add() {
  249.         # Addition function
  250.  
  251.         declare -a IN_ARR=( $@ )
  252.  
  253.         dc -e "0 ${IN_ARR[*]/-/_} ${IN_ARR[*]/*/+} p" 2>/dev/null
  254.  
  255.         local e_c="$?"
  256.  
  257.         unset IN_ARR
  258.  
  259.         return $?
  260.     }
  261.  
  262.     function bl3dps_math_divide() {
  263.         # Division function
  264.  
  265.         declare -a IN_ARR=( $@ )
  266.  
  267.         if [[ "${#IN_ARR[@]}" -gt 2 ]]; then
  268.             local result=""
  269.  
  270.             while [[ "${#IN_ARR[@]}" -gt 0 ]]; do
  271.  
  272.                 if [[ "x${result}" == "x" ]]; then
  273.                     local result=$(echo "${IN_ARR[0]} / ${IN_ARR[1]}" | bc -l 2>/dev/null)
  274.                     local e_c="$?"
  275.                     local IN_ARR=(${IN_ARR[@]:2})
  276.                 else
  277.                     local result=$(echo "${result} / ${IN_ARR[0]}" | bc -l 2>/dev/null)
  278.                     local e_c="$?"
  279.                     local IN_ARR=(${IN_ARR[@]:1})
  280.                 fi
  281.             done
  282.  
  283.             echo "${result}"
  284.         else
  285.             echo "${IN_ARR[0]} / ${IN_ARR[1]}" \
  286.                 | bc -l 2>/dev/null
  287.            
  288.             local e_c="$?"
  289.         fi
  290.  
  291.         unset IN_ARR
  292.  
  293.         return ${e_c}
  294.     }
  295.  
  296.     function bl3dps_math_multiply() {
  297.         # Multiplication function
  298.  
  299.         declare -a IN_ARR=( $@ )
  300.  
  301.         if [[ "${#IN_ARR[@]}" -gt 2 ]]; then
  302.             local result=""
  303.  
  304.             while [[ "${#IN_ARR[@]}" -gt 0 ]]; do
  305.  
  306.                 if [[ "x${result}" == "x" ]]; then
  307.                     local result=$(echo "${IN_ARR[0]} * ${IN_ARR[1]}" | bc -l 2>/dev/null)
  308.                     local e_c="$?"
  309.                     local IN_ARR=(${IN_ARR[@]:2})
  310.                 else
  311.                     local result=$(echo "${result} * ${IN_ARR[0]}" | bc -l 2>/dev/null)
  312.                     local e_c="$?"
  313.                     local IN_ARR=(${IN_ARR[@]:1})
  314.                 fi
  315.             done
  316.  
  317.             echo "${result}"
  318.         else
  319.             echo "${IN_ARR[0]} * ${IN_ARR[1]}" \
  320.                 | bc -l 2>/dev/null
  321.            
  322.             local e_c="$?"
  323.         fi
  324.  
  325.         unset IN_ARR
  326.  
  327.         return ${e_c}
  328.     }
  329.  
  330.     function bl3dps_math_subtract() {
  331.         # Subtraction function
  332.  
  333.         declare -a IN_ARR=( $@ )
  334.  
  335.         local IN_ARR_MOD=(${IN_ARR[@]:1})
  336.         local X_1="${IN_ARR[0]}"
  337.         local X_2=$(dc -e "0 ${IN_ARR_MOD[*]/-/_} ${IN_ARR_MOD[*]/*/+} p" 2>/dev/null)
  338.  
  339.         echo "scale=11; ${X_1} - ${X_2} " \
  340.             | bc 2>/dev/null
  341.  
  342.         local e_c="$?"
  343.  
  344.         unset IN_ARR
  345.  
  346.         return ${e_c}
  347.     }
  348.  
  349. ## core process functions
  350.  
  351.     function bl3dps_proc_csv2json() {
  352.         #> Convert JSON syntax into CSV (requires incoming pipe)
  353.  
  354.         jq -Rnc '( input  | split(",") ) as $keys | ( inputs | split(",") ) as $vals | [[$keys, $vals] | transpose[] | {key:.[0],value:.[1]}] | from_entries' \
  355.             | sed 's/$/,/' \
  356.             | tr -d '\n' \
  357.             | sed 's/^/\[/;s/,$/\]/;s/\"\\\"/\"/g;s/\\\"\"/\"/g' \
  358.             | jq '.' 2>/dev/null
  359.        
  360.         return $?
  361.     }
  362.  
  363.     function bl3dps_proc_damage_final() {
  364.         # (base_damage * damage_multiplier) + (base_damage * damage_multiplier) * (damage_bump / 100)
  365.  
  366.         local total_base_damage=$(bl3dps_math_multiply "${x_base_damage}" "${x_damage_multiplier}")
  367.  
  368.         ## uncomment the following line for debugging purposes:
  369.         #bl3dps_vbs "${FUNCNAME}: total_base_damage: ${total_base_damage}"
  370.        
  371.         if [[ "${x_damage_bump}" == "0" ]]; then
  372.             local total_damage_bump=0
  373.         else
  374.             local total_damage_bump_pre=$(bl3dps_math_divide "${x_damage_bump}" "100")
  375.             local total_damage_bump=$(bl3dps_math_multiply "${total_base_damage}" "${total_damage_bump_pre}")
  376.         fi
  377.  
  378.         ## uncomment the following line for debugging purposes:
  379.         #bl3dps_vbs "${FUNCNAME}: total_damage_bump: ${total_damage_bump}"
  380.  
  381.         local output_pre=$(bl3dps_math_add "${total_base_damage}" "${total_damage_bump}")
  382.        
  383.         if [[ "${output_pre}" =~ [.] ]]; then
  384.             ## truncate sub-decimal results to only TWO decimal places
  385.  
  386.             local out_mod_prefix="${output_pre//.*}"
  387.             local out_mod_suffix="${output_pre//*.}"
  388.             local out_mod_suffix_trunk="${out_mod_suffix:0:2}"
  389.             local output="${out_mod_prefix}.${out_mod_suffix_trunk}"
  390.         else
  391.             local output="${output_pre}"
  392.         fi
  393.  
  394.         echo "${output}"
  395.  
  396.         return $?
  397.     }
  398.  
  399.     function bl3dps_proc_dps() {
  400.         ## damage_final * fire_rate_final
  401.  
  402.         local output_pre$(bl3dps_math_multiply "${x_damage_final}" "${x_fire_rate_final}")
  403.  
  404.         if [[ "${output_pre}" =~ [.] ]]; then
  405.             ## truncate sub-decimal results to only TWO decimal places
  406.  
  407.             local out_mod_prefix="${output_pre//.*}"
  408.             local out_mod_suffix="${output_pre//*.}"
  409.             local out_mod_suffix_trunk="${out_mod_suffix:0:2}"
  410.             local output="${out_mod_prefix}.${out_mod_suffix_trunk}"
  411.         else
  412.             local output="${output_pre}"
  413.         fi
  414.  
  415.         echo "${output}"
  416.  
  417.         return $?
  418.     }
  419.  
  420.     function bl3dps_proc_firerate_final() {
  421.         ## fire_rate + (fire_rate * (fire_rate_bump / 100))
  422.  
  423.         local total_base_fire_rate="${x_fire_rate}"
  424.  
  425.         ## uncomment the following line for debugging purposes:
  426.         #bl3dps_vbs "${FUNCNAME}: total_base_fire_rate: ${total_base_fire_rate}"
  427.  
  428.         if [[ "${x_fire_rate_bump}" == "0" ]]; then
  429.             local total_fire_rate_bump=0
  430.         else
  431.             local total_fire_rate_bump_pre=$(bl3dps_math_divide "${x_fire_rate_bump}" "100")
  432.             local total_fire_rate_bump=$(bl3dps_math_multiply "${total_base_fire_rate}" "${total_fire_rate_bump_pre}")
  433.         fi
  434.  
  435.         ## uncomment the following line for debugging purposes:
  436.         #bl3dps_vbs "${FUNCNAME}: total_fire_rate_bump: ${total_fire_rate_bump}"
  437.  
  438.         local output_pre=$(bl3dps_math_add "${total_base_fire_rate}" "${total_fire_rate_bump}")
  439.        
  440.         if [[ "${output_pre}" =~ [.] ]]; then
  441.             ## truncate sub-decimal results to only TWO decimal places
  442.  
  443.             local out_mod_prefix="${output_pre//.*}"
  444.             local out_mod_suffix="${output_pre//*.}"
  445.             local out_mod_suffix_trunk="${out_mod_suffix:0:2}"
  446.             local output="${out_mod_prefix}.${out_mod_suffix_trunk}"
  447.         else
  448.             local output="${output_pre}"
  449.         fi
  450.  
  451.         echo "${output}"
  452.  
  453.         return $?
  454.     }
  455.  
  456.     function bl3dps_proc_output_columns() {
  457.         ## meta values
  458.         local col_a="${_q2}id${_q2}"                     ## [SHA-256 checksum of all record data]
  459.         local col_b="${_q2}title${_q2}"                  ## [text string]
  460.         local col_c="${_q2}datetime${_q2}"               ## [human-friendly date and time]
  461.         local col_d="${_q2}runtime${_q2}"                ## [unix timestamp]
  462.         local col_e="${_q2}weapon_type${_q2}"            ## Pistol, SMG, Assault Rifle, Shotgun, Sniper Rifle, Launcher
  463.         local col_f="${_q2}mayhem_level${_q2}"           ## 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
  464.         local col_g="${_q2}level_required${_q2}"         ## 1, 2, 3 ... 65
  465.         local col_h="${_q2}item_score${_q2}"             ## [whole number between 1 and 999]
  466.         local col_i="${_q2}is_anointed${_q2}"            ## true, false
  467.         local col_j="${_q2}anointed_type${_q2}"          ## Operative, Gunner, Siren, Beastmaster, Generic, null
  468.         local col_k="${_q2}anoint_text${_q2}"            ## [text string]
  469.  
  470.         ## damage values
  471.         local col_l="${_q2}base_damage${_q2}"            ## [non-negative whole number]
  472.         local col_m="${_q2}has_base_multiplier${_q2}"    ## true, false
  473.         local col_n="${_q2}damage_multiplier${_q2}"      ## [non-negative whole number]
  474.         local col_o="${_q2}damage_bump${_q2}"            ## [positive or negative whole number]
  475.         local col_p="${_q2}damage_final${_q2}"           ## [positive whole number]
  476.  
  477.         ## fire-rate values
  478.         local col_q="${_q2}fire_rate${_q2}"              ## [positive decimal number]
  479.         local col_r="${_q2}fire_rate_bump${_q2}"         ## [positive or negative whole number]
  480.         local col_s="${_q2}fire_rate_final${_q2}"        ## [positive whole number]
  481.  
  482.         ## final DPS value
  483.         local col_t="${_q2}damage_per_second${_q2}"      ## [positive decimal number]
  484.  
  485.         ## column sections
  486.         local cols_meta="${col_a}${_cm}${col_b}${_cm}${col_c}${_cm}${col_d}${_cm}${col_e}${_cm}${col_f}${_cm}${col_g}${_cm}${col_h}${_cm}${col_i}${_cm}${col_j}${_cm}${col_k}"
  487.         local cols_damage="${col_l}${_cm}${col_m}${_cm}${col_n}${_cm}${col_o}${_cm}${col_p}"
  488.         local cols_firerate="${col_q}${_cm}${col_r}${_cm}${col_s}"
  489.         local cols_dps="${col_t}"
  490.  
  491.         ## final columns header line
  492.         local cols_header="${cols_meta}${_cm}${cols_damage}${_cm}${cols_firerate}${_cm}${cols_dps}"
  493.  
  494.         echo "${cols_header}"
  495.  
  496.         return $?
  497.     }
  498.  
  499.     function bl3dps_proc_output_data() {
  500.         # column sections
  501.  
  502.         ### meta values
  503.         local cols_meta="${_q2}${x_id}${_q2}${_cm}${_q2}${x_title}${_q2}${_cm}${_q2}${x_datetime}${_q2}${_cm}${_q2}${x_runtime}${_q2}${_cm}${_q2}${x_weapon_type}${_q2}${_cm}${_q2}${x_mayhem_level}${_q2}${_cm}${_q2}${x_level_required}${_q2}${_cm}${_q2}${x_item_score}${_q2}${_cm}${_q2}${x_is_anointed}${_q2}${_cm}${_q2}${x_anointed_type}${_q2}${_cm}${_q2}${x_anoint_text}${_q2}"
  504.  
  505.         ### damage values
  506.         local cols_damage="${_q2}${x_base_damage}${_q2}${_cm}${_q2}${x_has_base_multiplier}${_q2}${_cm}${_q2}${x_damage_multiplier}${_q2}${_cm}${_q2}${x_damage_bump}${_q2}${_cm}${_q2}${x_damage_final}${_q2}"
  507.  
  508.         ### fire-rate values
  509.         local cols_firerate="${_q2}${x_fire_rate}${_q2}${_cm}${_q2}${x_fire_rate_bump}${_q2}${_cm}${_q2}${x_fire_rate_final}${_q2}"
  510.  
  511.         ### final DPS value
  512.         local cols_dps="${_q2}${x_damage_per_second}${_q2}"
  513.  
  514.         # final data string
  515.  
  516.         local data_output="${cols_meta}${_cm}${cols_damage}${_cm}${cols_firerate}${_cm}${cols_dps}"
  517.  
  518.         echo "${data_output}"
  519.  
  520.         return $?
  521.     }
  522.  
  523.     function bl3dps_proc_output_file() {
  524.         if [[ ! -f "${out_file}" ]]; then
  525.             bl3dps_proc_output_columns > "${out_file}"
  526.         fi
  527.  
  528.         return $?
  529.     }
  530.  
  531.     function bl3dps_proc_output_result() {
  532.         local i_n="$@"
  533.  
  534.         if [[ "x${i_n}" == "x" ]]; then
  535.             ## uncomment the following line for debugging purposes:
  536.             #bl3dps_vbs "${FUNCNAME}: ERROR: null input detected; No output string was generated"
  537.  
  538.             return 1
  539.         fi
  540.  
  541.         ## make sure the required output file exists and contains required column names
  542.  
  543.         bl3dps_proc_output_file
  544.  
  545.         ## perform automatic de-duplication before record insert
  546.  
  547.         sed -i "/$x_id/d" "${out_file}"
  548.  
  549.         ## write the new record into the DPS storage file
  550.  
  551.         echo "${i_n}" >> "${out_file}"
  552.  
  553.         ## create and print a copy of only the latest record
  554.  
  555.         bl3dps_proc_output_columns > "${tmpf}"
  556.            
  557.         echo "${i_n}" >> "${tmpf}"
  558.  
  559.         csvjson "${tmpf}" 2>/dev/null \
  560.             | jq '.' 2>/dev/null
  561.  
  562.         local e_c="$?"
  563.  
  564.         ## remove the temp file and kill the function
  565.  
  566.         rm "${tmpf}" &>/dev/null
  567.        
  568.         return ${e_c}
  569.     }
  570.  
  571.     function bl3dps_proc_sha256() {
  572.         printf '%s' "${x_title}${x_weapon_type}${x_mayhem_level}${x_level_required}${x_item_score}${x_is_anointed}${x_anointed_type}${x_base_damage}${x_has_base_multiplier}${x_damage_multiplier}${x_damage_bump}${x_fire_rate}${x_fire_rate_bump}" \
  573.             | sha256sum \
  574.             | cut -d ' ' -f1
  575.        
  576.         return $?
  577.     }
  578.  
  579. ## verbosity and help functions
  580.  
  581.     function bl3dps_vbs() {
  582.         local i_n="$@"
  583.         local runtime="$(date '+%s')"
  584.  
  585.         echo "${runtime}|${sh_name}|${i_n}" &>/dev/stderr
  586.  
  587.         return $?
  588.     }
  589.  
  590.     function bl3dps_changelog() {
  591.         cat "${0}" \
  592.             | grep -E '^#C[>]' \
  593.             | sed 's/^...//'
  594.        
  595.         return $?
  596.     }
  597.  
  598.     function bl3dps_vbs_help() {
  599.         cat "${0}" \
  600.             | grep -E '^#[>]' \
  601.             | sed 's/^..//'
  602.        
  603.         return $?
  604.     }
  605.  
  606. #________________________________________________________________________________
  607. # Declare variables
  608.  
  609. ## unicode character variables (Reference: https://home.unicode.org/)
  610.  
  611.     _cm=$'\u002C'
  612.     _co=$'\u003A'
  613.     _pa=$'\u0028'
  614.     _pb=$'\u0029'
  615.     _q1=$'\u0027'
  616.     _q2=$'\u0022'
  617.     _sp=$'\u0020'
  618.     _and=$'\u0026'
  619.     _cba=$'\u007B'
  620.     _cbb=$'\u007D'
  621.     _sba=$'\u005B'
  622.     _sbb=$'\u005D'
  623.     _usd=$'\u0024'
  624.  
  625. ## main script variables
  626.  
  627.     sh_path="${0}"
  628.     sh_file_name="${sh_path//*\/}"
  629.     sh_name="${sh_file_name%.sh}"
  630.     t_s=$(date '+%s')
  631.     d_t=$(printf "%(%Y-%m-%d %H:%M:%S)T\n" "${t_s}" | tr 'T' ' ')
  632.     here_now="${PWD}"
  633.     out_file="${here_now}/bl3-dps.csv"
  634.     tmpf="/tmp/${sh_name}_${t_s}"
  635.     in_main="${1}"
  636.     in_mod="${in_main//-}"
  637.  
  638. ## output field variables
  639.  
  640.     ## id .................... [SHA-256 checksum of all record data]
  641.     ## title ................. [text string]
  642.     ## datetime .............. [human-friendly date and time]
  643.     ## runtime ............... [unix timestamp]
  644.     ## weapon_type ........... Pistol, SMG, Assault Rifle, Shotgun, Sniper Rifle, Launcher
  645.     ## mayhem_level .......... 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
  646.     ## level_required ........ 1, 2, 3 ... 65
  647.     ## item_score ............ [whole number between 1 and 999]
  648.     ## is_anointed ........... true, false
  649.     ## anointed_type ......... Operative, Gunner, Siren, Beastmaster, Generic, null
  650.     ## anoint_text ........... [text string]
  651.     ## base_damage ........... [non-negative whole number]
  652.     ## has_base_multiplier ... true, false
  653.     ## damage_multiplier ..... [non-negative whole number]
  654.     ## damage_bump ........... [positive or negative whole number]
  655.     ## damage_final .......... [positive whole number]
  656.     ## fire_rate ............. [positive decimal number]
  657.     ## fire_rate_bump ........ [positive or negative whole number]
  658.     ## fire_rate_final ....... [positive whole number]
  659.     ## damage_per_second ..... [positive decimal number]
  660.  
  661.     x_id=""
  662.     x_title=""
  663.     x_datetime="${d_t}"
  664.     x_runtime="${t_s}"
  665.     x_weapon_type=""
  666.     x_mayhem_level="0"
  667.     x_level_required=""
  668.     x_item_score=""
  669.     x_is_anointed=""
  670.     x_anointed_type=""
  671.     x_anoint_text=""
  672.     x_base_damage=""
  673.     x_has_base_multiplier=""
  674.     x_damage_multiplier="1"
  675.     x_damage_bump=""
  676.     x_damage_final=""
  677.     x_fire_rate=""
  678.     x_fire_rate_bump=""
  679.     x_fire_rate_final=""
  680.     x_damage_per_second=""
  681.  
  682. ## final data string
  683.  
  684.     data_string=""
  685.  
  686. #________________________________________________________________________________
  687. # Execute operations
  688.  
  689. case "${in_mod}" in
  690.     c|C|changelog)
  691.         bl3dps_changelog
  692.  
  693.         exit $?
  694.         ;;
  695.     h|H|help)
  696.         bl3dps_vbs_help
  697.  
  698.         exit $?
  699.         ;;
  700.     r|read|readjson)
  701.         if [[ ! -f "${out_file}" ]]; then
  702.             bl3dps_vbs "ERROR: No local data file found"
  703.  
  704.             exit 1
  705.         fi
  706.  
  707.         cat "${out_file}" \
  708.             | bl3dps_proc_csv2json
  709.        
  710.         exit $?
  711.         ;;
  712.     R|readcsv)
  713.         if [[ ! -f "${out_file}" ]]; then
  714.             bl3dps_vbs "ERROR: No local data file found"
  715.  
  716.             exit 1
  717.         fi
  718.  
  719.         cat "${out_file}"
  720.  
  721.         exit $?
  722.         ;;
  723. esac
  724.  
  725. ## title
  726.  
  727.     bl3dps_ask_string "Weapon title:"
  728.  
  729.     x_title="${OUST}"
  730.  
  731.     unset OUST
  732.  
  733.     ## uncomment the following line for debugging purposes:
  734.     #bl3dps_vbs "x_title: ${x_title}"
  735.  
  736. ## weapon_type
  737.  
  738.     echo "Select the weapon type:" &>/dev/stderr
  739.  
  740.     bl3dps_ask_options --Pistol --SMG --Assault_Rifle --Shotgun --Sniper_Rifle --Launcher
  741.  
  742.     x_weapon_type="${OUST}"
  743.  
  744.     unset OUST
  745.  
  746.     ## uncomment the following line for debugging purposes:
  747.     #bl3dps_vbs "x_weapon_type: ${x_weapon_type}"
  748.  
  749. ## mayhem_level
  750.  
  751.     bl3dps_ask_number_whole_positive "Mayhem level (0-10)"
  752.  
  753.     x_mayhem_level_temp="${OUST}"
  754.     x_mayhem_level_test=$(egrep --quiet '^(0|1|2|3|4|5|6|7|8|9|10)$' <<<"${x_mayhem_level_temp}"; echo $?)
  755.  
  756.     if [[ "${x_mayhem_level_test}" -ne 0 ]]; then
  757.         bl3dps_vbs "ERROR: Mayhem level must be a number between 0 and 10"
  758.         bl3dps_vbs "Please try again ..."
  759.  
  760.         bl3dps_ask_number_whole_positive "Mayhem level (0-10)"
  761.     fi
  762.  
  763.     x_mayhem_level="${OUST}"
  764.  
  765.     unset OUST
  766.  
  767.     ## uncomment the following line for debugging purposes:
  768.     #bl3dps_vbs "x_mayhem_level: ${x_mayhem_level}"
  769.  
  770. ## level_required
  771.  
  772.     bl3dps_ask_number_whole_positive "Item user level (1-65)"
  773.  
  774.     x_level_required_temp="${OUST}"
  775.     x_level_required_test=$(egrep --quiet '^(1|2|3|4|5|6|7|8|9|[1-5][0-9]|6[0-5])$' <<<"${x_level_required_temp}"; echo $?)
  776.  
  777.     if [[ "${x_level_required_test}" -ne 0 ]]; then
  778.         bl3dps_vbs "ERROR: The required user level must be a number between 1 and 65"
  779.         bl3dps_vbs "Please try again ..."
  780.  
  781.         bl3dps_ask_number_whole_positive "Item user level (1-65)"
  782.     fi
  783.  
  784.     x_level_required="${OUST}"
  785.  
  786.     unset OUST
  787.  
  788.     ## uncomment the following line for debugging purposes:
  789.     #bl3dps_vbs "x_level_required: ${x_level_required}"
  790.  
  791. ## item_score
  792.  
  793.     bl3dps_ask_number_whole_positive "Item point score (1-999)"
  794.  
  795.     x_item_score_temp="${OUST}"
  796.     x_item_score_test=$(egrep --quiet '^(1|2|3|4|5|6|7|8|9|[1-9][0-9]|[1-9][0-9][0-9])$' <<<"${x_item_score_temp}"; echo $?)
  797.  
  798.     if [[ "${x_item_score_test}" -ne 0 ]]; then
  799.         bl3dps_vbs "ERROR: The item score must be a number between 1 and 999"
  800.         bl3dps_vbs "Please try again ..."
  801.  
  802.         bl3dps_ask_number_whole_positive "Item point score (1-999)"
  803.     fi
  804.  
  805.     x_item_score="${OUST}"
  806.  
  807.     unset OUST
  808.  
  809.     ## uncomment the following line for debugging purposes:
  810.     #bl3dps_vbs "x_item_score: ${x_item_score}"
  811.  
  812. ## is_anointed
  813.  
  814.     bl3dps_ask_truefalse "Is the item 'Anointed'"
  815.  
  816.     x_is_anointed="${OUST}"
  817.  
  818.     unset OUST
  819.  
  820.     ## uncomment the following line for debugging purposes:
  821.     #bl3dps_vbs "x_is_anointed: ${x_is_anointed}"
  822.  
  823. ## anointed_type && anoint_text
  824.  
  825.     if [[ "${x_is_anointed}" =~ "true" ]]; then
  826.         echo "Select the Anointed type" &>/dev/stderr
  827.  
  828.         bl3dps_ask_options --Operative --Gunner --Siren --Beastmaster --Generic
  829.  
  830.         x_anointed_type="${OUST}"
  831.  
  832.         unset OUST
  833.  
  834.         bl3dps_ask_string "Anoint text (on one line):"
  835.  
  836.         x_anoint_text="${OUST}"
  837.  
  838.         unset OUST
  839.     else
  840.         x_anointed_type="null"
  841.         x_anoint_text="null"
  842.     fi
  843.  
  844.     ## uncomment the following line for debugging purposes:
  845.     #bl3dps_vbs "x_anointed_type: ${x_anointed_type}"
  846.     #bl3dps_vbs "x_anoint_text: ${x_anoint_text}"
  847.  
  848. ## Define: base_damage
  849.  
  850.     bl3dps_ask_number_whole_positive "Base damage (without a shot multiplier)"
  851.  
  852.     x_base_damage="${OUST}"
  853.  
  854.     unset OUST
  855.  
  856.     ## uncomment the following line for debugging purposes:
  857.     #bl3dps_vbs "x_base_damage: ${x_base_damage}"
  858.  
  859. ## Define: has_base_multiplier
  860.  
  861.     bl3dps_ask_truefalse "Does base damage have a shot multiplier (Example: '394x3')"
  862.  
  863.     x_has_base_multiplier="${OUST}"
  864.  
  865.     unset OUST
  866.  
  867.     ## uncomment the following line for debugging purposes:
  868.     #bl3dps_vbs "x_has_base_multiplier: ${x_has_base_multiplier}"
  869.  
  870. ## Define: damage_multiplier
  871.  
  872.     if [[ "${x_has_base_multiplier}" =~ "true" ]]; then
  873.         bl3dps_ask_number_whole_positive "Base damage shot multiplier"
  874.  
  875.         x_damage_multiplier="${OUST}"
  876.  
  877.         unset OUST
  878.     else
  879.         x_damage_multiplier="1"
  880.     fi
  881.  
  882.     ## uncomment the following line for debugging purposes:
  883.     #bl3dps_vbs "x_damage_multiplier: ${x_damage_multiplier}"
  884.  
  885. ## Define: damage_bump
  886.  
  887.     bl3dps_ask_number_whole "Percent damage bump (positive or negative); if none, enter '0'"
  888.  
  889.     x_damage_bump="${OUST}"
  890.  
  891.     unset OUST
  892.  
  893.     ## uncomment the following line for debugging purposes:
  894.     #bl3dps_vbs "x_damage_bump: ${x_damage_bump}"
  895.  
  896. ## Define: damage_final
  897.  
  898.     x_damage_final=$(bl3dps_proc_damage_final)
  899.  
  900.     ## uncomment the following line for debugging purposes:
  901.     #bl3dps_vbs "x_damage_final: ${x_damage_final}"
  902.  
  903. ## Define: fire_rate
  904.  
  905.     bl3dps_ask_number_positive "Fire rate (a positive decimal number)"
  906.  
  907.     x_fire_rate="${OUST}"
  908.  
  909.     unset OUST
  910.  
  911.     ## uncomment the following line for debugging purposes:
  912.     #bl3dps_vbs "x_fire_rate: ${x_fire_rate}"
  913.  
  914. ## Define: fire_rate_bump
  915.  
  916.     bl3dps_ask_number_whole "Percent fire rate bump (positive or negative); if none, enter '0'"
  917.  
  918.     x_fire_rate_bump="${OUST}"
  919.  
  920.     unset OUST
  921.  
  922.     ## uncomment the following line for debugging purposes:
  923.     #bl3dps_vbs "x_fire_rate_bump: ${x_fire_rate_bump}"
  924.  
  925. ## Define: fire_rate_final
  926.  
  927.     x_fire_rate_final=$(bl3dps_proc_firerate_final)
  928.  
  929.     ## uncomment the following line for debugging purposes:
  930.     #bl3dps_vbs "x_fire_rate_final: ${x_fire_rate_final}"
  931.  
  932. ## Define: damage_per_second
  933.  
  934.     ## damage_per_second =
  935.     ##    [
  936.     ##        (
  937.     ##            base_damage * damage_multiplier
  938.     ##        ) + (
  939.     ##            (base_damage * damage_multiplier) * (damage_bump / 100)
  940.     ##        )
  941.     ##    ] * [
  942.     ##        fire_rate + (fire_rate * (fire_rate_bump / 100))
  943.     ##    ]
  944.  
  945.     x_damage_per_second=$(bl3dps_proc_dps)
  946.  
  947.     ## uncomment the following line for debugging purposes:
  948.     #bl3dps_vbs "x_damage_per_second: ${x_damage_per_second}"
  949.  
  950. ## Define: id
  951.  
  952.     x_id=$(bl3dps_proc_sha256)
  953.  
  954.     ## uncomment the following line for debugging purposes:
  955.     #bl3dps_vbs "x_id: ${x_id}"
  956.  
  957. ## Generate output and kill the script
  958.  
  959.     data_string=$(bl3dps_proc_output_data)
  960.  
  961.     bl3dps_proc_output_result "${data_string}"
  962.  
  963. #________________________________________________________________________________
  964.  
  965. exit $?
  966.  
RAW Paste Data