Difference between revisions of "Script - Flashy Deaths (new)"
m (changed location of the cfg files of the script) |
(update) |
||
| Line 3: | Line 3: | ||
Please note that this script requires two additional files in .cfg format whose specs can be found below. | Please note that this script requires two additional files in .cfg format whose specs can be found below. | ||
| + | |||
| + | <font color=red>NOTE THAT .CFG FILES GO TO DATA/CONFIG DIRECTORY</font> | ||
==Table Entry== | ==Table Entry== | ||
| Line 13: | Line 15: | ||
[ | [ | ||
| − | --------------- | + | ---------------------- |
| − | -- functions -- | + | -- parser functions -- |
| − | --------------- | + | ---------------------- |
--- get newline and make sure its lowercase | --- get newline and make sure its lowercase | ||
| Line 32: | Line 34: | ||
-- find any instances of the keyword | -- find any instances of the keyword | ||
keyword = keyword:lower() | keyword = keyword:lower() | ||
| − | key_s, key_e = line_to_parse:find(keyword) | + | local key_s, key_e = line_to_parse:find(keyword) |
-- if we cant find a thing | -- if we cant find a thing | ||
| Line 38: | Line 40: | ||
return nil | return nil | ||
end | end | ||
| + | |||
| + | -- check if the line has been commented away | ||
| + | local comment_s, comment_e = line_to_parse:find("--") | ||
| + | |||
| + | if comment_s == nil then | ||
| + | return key_e | ||
| + | elseif comment_s < key_s then | ||
| + | return nil | ||
| + | end | ||
| + | |||
return key_e | return key_e | ||
end | end | ||
| Line 43: | Line 55: | ||
--- function to initialize the vars | --- function to initialize the vars | ||
function init_entry(name) | function init_entry(name) | ||
| − | + | arr_SW[name] = 0 | |
| − | + | arr_SH[name] = 0 | |
| − | + | arr_SL[name] = 0 | |
| − | + | arr_SD_rad[name] = 0 | |
| − | + | arr_SD_eff[name] = { } | |
| − | + | arr_SD_m[name] = 1 | |
| − | + | arr_SF_rad[name] = 0 | |
| − | + | arr_SF_eff[name] = 0 | |
| + | arr_SB_int[name] = 0 | ||
| + | arr_SB_dur[name] = 0 | ||
| + | arr_SB_time[name] = 0 | ||
end | end | ||
| Line 65: | Line 80: | ||
--- function to parse numbers | --- function to parse numbers | ||
function parse_number(start_key, line_to_parse) | function parse_number(start_key, line_to_parse) | ||
| − | result = line_to_parse:match("%d+", e_key) | + | local result = line_to_parse:match("%d+", e_key) |
return tonumber(result) | return tonumber(result) | ||
end | end | ||
| Line 95: | Line 110: | ||
while c_line:len() == 0 do | while c_line:len() == 0 do | ||
c_line = get_next_line(flashfile) | c_line = get_next_line(flashfile) | ||
| + | if c_line == nil then | ||
| + | -- end of file | ||
| + | return -2, false, return_array | ||
| + | end | ||
end | end | ||
new_entry = find_keyword(c_line, "Name:") | new_entry = find_keyword(c_line, "Name:") | ||
| Line 144: | Line 163: | ||
local current_entry = parse_string(entry_start, c_line) | local current_entry = parse_string(entry_start, c_line) | ||
animation = gr.loadTexture(current_entry, true) | animation = gr.loadTexture(current_entry, true) | ||
| − | table.insert( | + | table.insert(arr_D_eff, animation) |
if animation:isValid() == false then | if animation:isValid() == false then | ||
ba.warning("Animation defined in " .. filename_flashani .. " " .. current_entry .. " is invalid") | ba.warning("Animation defined in " .. filename_flashani .. " " .. current_entry .. " is invalid") | ||
| Line 187: | Line 206: | ||
break | break | ||
else | else | ||
| − | + | arr_SW[current_entry] = temp_val | |
end | end | ||
| Line 195: | Line 214: | ||
break | break | ||
else | else | ||
| − | + | arr_SH[current_entry] = temp_val | |
end | end | ||
| Line 203: | Line 222: | ||
break | break | ||
else | else | ||
| − | + | arr_SL[current_entry] = temp_val | |
end | end | ||
| Line 211: | Line 230: | ||
break | break | ||
else | else | ||
| − | + | arr_SD_rad[current_entry] = temp_val | |
end | end | ||
-- random detonation effects | -- random detonation effects | ||
| Line 219: | Line 238: | ||
break | break | ||
else | else | ||
| − | + | arr_SD_eff[current_entry] = temp_arr | |
end | end | ||
| Line 227: | Line 246: | ||
break | break | ||
elseif temp_val ~= -1 then | elseif temp_val ~= -1 then | ||
| − | + | arr_SD_m[current_entry] = temp_val | |
end | end | ||
| Line 235: | Line 254: | ||
break | break | ||
else | else | ||
| − | + | arr_SF_rad[current_entry] = temp_val | |
end | end | ||
| Line 244: | Line 263: | ||
else | else | ||
math.floor(temp_val) | math.floor(temp_val) | ||
| − | + | arr_SF_eff[current_entry] = temp_val | |
| + | end | ||
| + | |||
| + | -- blinding effect | ||
| + | temp_val, use_same_line = parse_entry("Blinding Effect Intensity:", flashfile, "n", use_same_line) | ||
| + | if temp_val == -2 then | ||
| + | break | ||
| + | else | ||
| + | if temp_val < 0 then | ||
| + | temp_val = 0 | ||
| + | elseif temp_val > 100 then | ||
| + | temp_val = 100 | ||
| + | end | ||
| + | arr_SB_int[current_entry] = temp_val | ||
| + | end | ||
| + | |||
| + | -- blinding duration | ||
| + | temp_val, use_same_line = parse_entry("Blinding Effect Duration:", flashfile, "n", use_same_line) | ||
| + | if temp_val == -2 then | ||
| + | break | ||
| + | else | ||
| + | arr_SB_dur[current_entry] = temp_val | ||
| + | end | ||
| + | |||
| + | -- blast effect delay | ||
| + | temp_val, use_same_line = parse_entry("Blast Effect Delay:", flashfile, "n", use_same_line) | ||
| + | if temp_val == -2 then | ||
| + | break | ||
| + | else | ||
| + | arr_SB_time[current_entry] = temp_val | ||
end | end | ||
end | end | ||
| Line 260: | Line 308: | ||
-- init arrays | -- init arrays | ||
arrayShipName = {} | arrayShipName = {} | ||
| − | + | arr_SW = {} | |
| − | + | arr_SH = {} | |
| − | + | arr_SL = {} | |
| − | + | arr_SD_rad = {} | |
| − | + | arr_SD_eff = {} | |
| − | + | arr_SD_m = {} | |
| − | + | arr_SF_rad = {} | |
| − | + | arr_SF_eff = {} | |
| − | + | arr_SB_int = {} | |
| + | arr_SB_dur = {} | ||
| + | arr_SB_time = {} | ||
| + | arr_D_eff = {} | ||
-- open reference file, if any | -- open reference file, if any | ||
| Line 274: | Line 325: | ||
filename_flash = "expl_flashes.cfg" | filename_flash = "expl_flashes.cfg" | ||
filename_flashani = "exp_ani_flashes.cfg" | filename_flashani = "exp_ani_flashes.cfg" | ||
| − | if ((cf.fileExists(filename_flash, "data/ | + | if ((cf.fileExists(filename_flash, "data/config/", true) == true) and (cf.fileExists(filename_flashani, "data/config/", true) == true)) then |
boolflashfileOK = true | boolflashfileOK = true | ||
end | end | ||
| Line 280: | Line 331: | ||
if boolflashfileOK then | if boolflashfileOK then | ||
-- open to read the contents | -- open to read the contents | ||
| − | flashanifile = cf.openFile(filename_flashani, "r | + | flashanifile = cf.openFile(filename_flashani, "r") |
-- parse contents | -- parse contents | ||
parse_flash_ani_file(flashanifile) | parse_flash_ani_file(flashanifile) | ||
| Line 287: | Line 338: | ||
-- continue with the rest in similar manner | -- continue with the rest in similar manner | ||
| − | flashfile = cf.openFile(filename_flash, "r | + | flashfile = cf.openFile(filename_flash, "r") |
parse_flash_file(flashfile) | parse_flash_file(flashfile) | ||
flashfile:close() | flashfile:close() | ||
| Line 293: | Line 344: | ||
-- setup rest of the required stuff | -- setup rest of the required stuff | ||
math.randomseed( os.time() ) | math.randomseed( os.time() ) | ||
| − | + | f_counter = {} | |
| − | + | v_null = ba.createVector(0,0,0) | |
| − | + | arr_FS_List = {} | |
| − | + | arr_FS = {} | |
| − | + | arr_FS_Class = {} | |
| − | + | arr_FS_Pos = {} | |
| − | + | arr_FS_done = {} | |
| + | arr_FS_time = {} | ||
| + | bl_int = 0 | ||
| + | bl_end = 0 | ||
| + | bl_max = 0 | ||
| + | bl_start = 0 | ||
| + | bl_int_init = 0 | ||
else | else | ||
ba.warning("Failed to initialize flashy deaths script") | ba.warning("Failed to initialize flashy deaths script") | ||
| + | end | ||
| + | |||
| + | ---------------------------------- | ||
| + | -- functions for later sections -- | ||
| + | ---------------------------------- | ||
| + | |||
| + | function blinding_effect(intensity, duration, time) | ||
| + | bl_int_init = bl_int | ||
| + | |||
| + | if (intensity < bl_max) then | ||
| + | if intensity > bl_int then | ||
| + | local effect_time = bl_end - bl_start | ||
| + | local delta_time = time - bl_start | ||
| + | |||
| + | if effect_time == 0 then | ||
| + | bl_max = intensity | ||
| + | bl_start = time | ||
| + | bl_end = time + (duration / 1000) | ||
| + | else | ||
| + | local pct_time = (effect_time - delta_time) / effect_time | ||
| + | if pct_time < 0.85 then | ||
| + | bl_max = intensity | ||
| + | bl_start = time | ||
| + | bl_end = time + (duration / 1000) | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | else | ||
| + | bl_max = intensity | ||
| + | bl_start = time | ||
| + | bl_end = time + (duration / 1000) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | function process_blinding_effect_frame(time) | ||
| + | if bl_max == 0 then | ||
| + | return | ||
| + | end | ||
| + | |||
| + | local effect_time = bl_end - bl_start | ||
| + | local delta_time = time - bl_start | ||
| + | local pct_time = (effect_time - delta_time) / effect_time | ||
| + | local case_time | ||
| + | |||
| + | -- lets go case by case | ||
| + | if pct_time < 0.0 then | ||
| + | -- effect has faded away | ||
| + | bl_int = 0 | ||
| + | bl_max = 0 | ||
| + | blindint_intensity_start = 0 | ||
| + | elseif pct_time < 0.85 then | ||
| + | -- effect is still fading away | ||
| + | case_time = 1 - (pct_time / 0.85) | ||
| + | bl_int = math.pow(((1 + math.cos(case_time * math.pi))/2),3) | ||
| + | elseif pct_time > 0.90 then | ||
| + | -- effect is still getting stronger | ||
| + | if pct_time == 0 then | ||
| + | case_time = -1 | ||
| + | else | ||
| + | case_time = -1 * ((pct_time - 0.9) / 0.1) | ||
| + | end | ||
| + | bl_int = math.pow(((1 + math.cos(case_time * math.pi))/2),2) * (bl_max - bl_int_init) + bl_int_init | ||
| + | else | ||
| + | bl_int = bl_max | ||
| + | end | ||
| + | |||
| + | if bl_int ~= 0 then | ||
| + | a = bl_int * 255 | ||
| + | gr.drawString(a, 255,255) | ||
| + | gr.flashScreen(a,a,a) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | function do_death_flash(name, number) | ||
| + | |||
| + | -- death flash explosion | ||
| + | arr_FS_List[name] = 2 | ||
| + | local v_F_pos = arr_FS_Pos[name] | ||
| + | arr_FS_Pos[name] = nil | ||
| + | local str_F_class = arr_FS_Class[name] | ||
| + | arr_FS_Class[name] = nil | ||
| + | local n_F_rad = (math.random() + 0.5) * arr_SF_rad[str_F_class] | ||
| + | local l_anim_flash = arr_D_eff[arr_SF_eff[str_F_class]] | ||
| + | if l_anim_flash:isValid() then | ||
| + | ts.createParticle(v_F_pos,v_null,f_F_time,n_F_rad,PARTICLE_BITMAP,-1,false,l_anim_flash) | ||
| + | end | ||
| + | |||
| + | -- death flash blinding effect | ||
| + | if arr_SB_int[str_F_class] > 0 then | ||
| + | local coord_x | ||
| + | local coord_y | ||
| + | coord_x, coord_y = v_F_pos:getScreenCoords() | ||
| + | |||
| + | if coord_x ~= false then | ||
| + | blinding_effect(arr_SB_int[str_F_class], arr_SB_dur[str_F_class], f_M_time) | ||
| + | end | ||
| + | end | ||
| + | |||
| + | -- purge from the list | ||
| + | table.insert(arr_FS_done, number) | ||
| + | end | ||
| + | |||
| + | function check_flash(name) | ||
| + | local class = arr_FS_Class[name] | ||
| + | if arr_SB_time[class] > 0 then | ||
| + | if arr_FS_time[name] <= f_M_time then | ||
| + | return true; | ||
| + | end | ||
| + | end | ||
| + | |||
| + | return false; | ||
| + | end | ||
| + | |||
| + | function add_to_flash_list(name, class) | ||
| + | arr_FS_List[name] = 1 | ||
| + | arr_FS_Class[name] = class | ||
| + | if arr_SB_time[class] > 0 then | ||
| + | local temp_time = math.random() + 1 | ||
| + | arr_FS_time[name] = arr_SB_time[class] * temp_time / 1000 + f_M_time | ||
| + | end | ||
| + | table.insert(arr_FS,name) | ||
end | end | ||
| Line 311: | Line 489: | ||
[ | [ | ||
| − | + | f_M_time = mn.getMissionTime() | |
| − | if (( | + | if ((f_M_time ~= nil) and boolflashfileOK) then |
| − | + | f_F_time = ba.getFrametime(true) | |
| − | + | f_rnd = math.random() | |
| − | + | n_ships = #mn.Ships | |
| − | for h = 1, | + | for h = 1, n_ships do |
| − | + | o_ship = mn.Ships[h] | |
| − | + | str_S_class = o_ship.Class.Name:lower() | |
--ONLY SHIPS WITH EFFECTS-- | --ONLY SHIPS WITH EFFECTS-- | ||
| − | if (( | + | if ((arr_SF_rad[str_S_class] ~= nil) and (arr_SD_rad[str_S_class] ~= nil)) then |
| − | + | str_S_name = o_ship.Name | |
| − | floatHP = | + | floatHP = o_ship.HitpointsLeft |
if floatHP <= 0 then | if floatHP <= 0 then | ||
| − | + | v_S_pos = o_ship.Position | |
| − | if | + | if arr_SF_rad[str_S_class] > 0 then |
| − | if | + | if arr_FS_List[str_S_name] == nil then |
| − | + | add_to_flash_list(str_S_name, str_S_class) | |
| − | |||
| − | |||
end | end | ||
end | end | ||
| − | if | + | if arr_SD_rad[str_S_class] > 0 then |
| − | + | arr_FS_Pos[str_S_name] = v_S_pos | |
| − | if | + | if f_counter[str_S_name] == nil then |
| − | + | f_counter[str_S_name] = 0 | |
end | end | ||
| − | + | f_rnd = math.random() | |
| − | local | + | local l_n_SD_eff = #arr_SD_eff[str_S_class] |
| − | while | + | while f_counter[str_S_name] > f_rnd do |
| − | + | f_counter[str_S_name] = f_counter[str_S_name] - f_rnd | |
| − | + | local l_or_ship = o_ship.Orientation | |
| − | local | + | local n_attempts = arr_SD_m[str_S_class] |
local n_partials | local n_partials | ||
| − | + | n_attempts, n_partials = math.modf(n_attempts) | |
if n_partials ~= 0 then | if n_partials ~= 0 then | ||
if math.random() > n_partials then | if math.random() > n_partials then | ||
| − | + | n_attempts = n_attempts + 1 | |
end | end | ||
end | end | ||
| − | for n = 1, | + | for n = 1,n_attempts do |
| − | local | + | local l_f_rnd_1 = (math.random() - 0.5) * arr_SW[str_S_class] |
| − | local | + | local l_f_rnd_2 = (math.random() - 0.5) * arr_SH[str_S_class] |
| − | local | + | local l_f_rnd_3 = (math.random() - 0.5) * arr_SL[str_S_class] |
| − | local | + | local l_v_rnd = ba.createVector(l_f_rnd_1,l_f_rnd_2,l_f_rnd_3) |
| − | local | + | local l_f_det_r = (math.random() + 0.5) * arr_SD_rad[str_S_class] |
| − | local | + | local l_v_rot_rnd = l_or_ship:unrotateVector(l_v_rnd) |
| − | local | + | local l_v_det_pos = v_S_pos + l_v_rot_rnd |
| − | local | + | local l_arr_SD_eff = arr_SD_eff[str_S_class] |
| − | if | + | if l_n_SD_eff == 1 then |
| − | + | anim_det = l_arr_SD_eff[1] | |
| − | if | + | if anim_det:isValid() then |
| − | ts.createParticle( | + | ts.createParticle(l_v_det_pos,v_null,f_F_time,l_f_det_r,PARTICLE_BITMAP,-1,false,anim_det) |
end | end | ||
| − | elseif | + | elseif l_n_SD_eff > 1 then |
| − | + | local l_n_rnd_id = math.random(l_n_SD_eff) | |
| − | + | anim_det = arr_D_eff[l_arr_SD_eff[l_n_rnd_id]] | |
| − | if | + | if anim_det:isValid() then |
| − | ts.createParticle( | + | ts.createParticle(l_v_det_pos,v_null,f_F_time,l_f_det_r,PARTICLE_BITMAP,-1,false,anim_det) |
end | end | ||
end | end | ||
end | end | ||
| − | if | + | if f_counter[str_S_name] <= 0 then |
| − | + | f_counter[str_S_name] = 0 | |
else | else | ||
| − | + | f_rnd = math.random() | |
end | end | ||
end | end | ||
| − | + | f_counter[str_S_name] = f_counter[str_S_name] + f_F_time | |
end | end | ||
| Line 402: | Line 578: | ||
end | end | ||
| − | + | n_FS = #arr_FS | |
| − | for x=1, | + | for x=1,n_FS do |
| − | + | name = arr_FS[x] | |
| − | if | + | if arr_FS_List[name] == 1 then |
| − | if mn.Ships[ | + | if mn.Ships[name]:isValid() == false then |
| − | + | do_death_flash(name, x) | |
| − | + | else | |
| − | + | -- randomized flash explosion | |
| − | + | if check_flash(name) == true then | |
| − | + | do_death_flash(name, x) | |
| − | |||
| − | |||
| − | if | ||
| − | |||
end | end | ||
| − | |||
end | end | ||
| Line 427: | Line 598: | ||
end | end | ||
| − | + | n_FS_done = #arr_FS_done | |
| − | if | + | if n_FS_done > 0 then |
| − | for o= | + | for o=n_FS_done,1,-1 do |
| − | table.remove( | + | table.remove(arr_FS,arr_FS_done[o]) |
end | end | ||
| − | + | arr_FS_done = nil | |
| − | + | arr_FS_done = {} | |
end | end | ||
end | end | ||
| + | |||
| + | process_blinding_effect_frame(f_M_time) | ||
end | end | ||
| Line 454: | Line 627: | ||
if boolflashfileOK then | if boolflashfileOK then | ||
arrayShipName = nil | arrayShipName = nil | ||
| − | + | arr_SW = nil | |
| − | + | arr_SH = nil | |
| − | + | arr_SL = nil | |
| − | + | arr_SD_rad = nil | |
| − | + | arr_SD_eff = nil | |
| − | + | arr_SF_rad = nil | |
| − | + | arr_SF_eff = nil | |
| − | local n_effects = # | + | arr_SB_int = nil |
| + | arr_SB_dur = nil | ||
| + | arr_SB_time = nil | ||
| + | local n_effects = #arr_D_eff | ||
for j=1,n_effects do | for j=1,n_effects do | ||
| − | + | arr_D_eff[j]:unload() | |
end | end | ||
| − | + | arr_D_eff = nil | |
| − | + | f_counter = nil | |
| − | + | arr_FS_List = nil | |
| − | + | arr_FS = nil | |
| − | + | arr_FS_Class = nil | |
| − | + | arr_FS_Pos = nil | |
| − | + | arr_FS_done = nil | |
| + | arr_FS_time = nil | ||
boolflashfileOK = nil | boolflashfileOK = nil | ||
| Line 482: | Line 659: | ||
==expl_flashes.cfg== | ==expl_flashes.cfg== | ||
| − | This file needs to be placed into '''''../data/ | + | This file needs to be placed into '''''../data/config/''''' directory. |
Please note that the following list isn't complete yet. | Please note that the following list isn't complete yet. | ||
| − | + | *'''Name:''' defines the ship for which this entry is made for | |
| − | + | *'''Width:''' & '''Height:''' & '''Length:''' define the dimensions inside which the detonations occur | |
| − | + | *'''Detonation Radius:''' defines the radius (base radius) of the detonation effects | |
| − | + | *'''Detonation Effects:''' list of ID values of the effects (defined in the other cfg file), may have multiple ones | |
| − | + | *'''Detonation Multiplier:''' multiplier which controls the amount of explosions triggered. 0.2 is 80% decrease, 1.2 is 20% increase | |
| − | + | *'''Flash Radius:''' defines the radius of the flash when ship actually goes away | |
| − | + | *'''Flash Effect:''' ID values of the flash effect, as listed in line order entry in additional cfg | |
| + | *'''Blinding Effect Intensity:''' value from 0 to 100, sets the intensity of the blinding effect - requires flash effect to be defined | ||
| + | *'''Blinding Effect Duration:''' sets the duration of the blinding effect in milliseconds | ||
| + | *'''Blast Effect Delay:''' sets the base time for flash & blinding effect to appear in milliseconds | ||
| + | |||
| + | Table allows for lines to be commented using '--' as comment marker | ||
<pre> | <pre> | ||
| Line 815: | Line 997: | ||
==exp_ani_flashes.cfg== | ==exp_ani_flashes.cfg== | ||
| − | This file needs to be placed into '''''../data/ | + | This file needs to be placed into '''''../data/config/''''' directory. |
Contains an '''ordered''' list of animations. First defined effect gets ID number 1, second gets ID number 2 and so on. These ID numbers are used in '''Detonation Effects:''' and '''Flash Effect:''' entries to define the desired animations. | Contains an '''ordered''' list of animations. First defined effect gets ID number 1, second gets ID number 2 and so on. These ID numbers are used in '''Detonation Effects:''' and '''Flash Effect:''' entries to define the desired animations. | ||
Revision as of 10:35, 26 January 2010
Function
New version of the flashy deaths effect by Wanderer. You may wish to check out the script's thread on HLP.
Please note that this script requires two additional files in .cfg format whose specs can be found below.
NOTE THAT .CFG FILES GO TO DATA/CONFIG DIRECTORY
Table Entry
We'll call this deto-sct.tbm - it needs to be placed into ../data/tables/ directory.
#Conditional Hooks
$Application: FS2_Open
$On Mission Start:
[
----------------------
-- parser functions --
----------------------
--- get newline and make sure its lowercase
function get_next_line(nfile)
-- read the line
nline = nfile:read("*l")
-- change to lowercase
if nline ~= nil then
nline = nline:lower()
end
return nline
end
--- find keyword and return the place where it ends
function find_keyword(line_to_parse, keyword)
-- find any instances of the keyword
keyword = keyword:lower()
local key_s, key_e = line_to_parse:find(keyword)
-- if we cant find a thing
if key_s == nil then
return nil
end
-- check if the line has been commented away
local comment_s, comment_e = line_to_parse:find("--")
if comment_s == nil then
return key_e
elseif comment_s < key_s then
return nil
end
return key_e
end
--- function to initialize the vars
function init_entry(name)
arr_SW[name] = 0
arr_SH[name] = 0
arr_SL[name] = 0
arr_SD_rad[name] = 0
arr_SD_eff[name] = { }
arr_SD_m[name] = 1
arr_SF_rad[name] = 0
arr_SF_eff[name] = 0
arr_SB_int[name] = 0
arr_SB_dur[name] = 0
arr_SB_time[name] = 0
end
--- specific parsing funcs to make things easier to read ---
--- string or rather substring parser
function parse_string(start_key, line_to_parse)
local substring = line_to_parse:sub(start_key)
-- remove empty spaces
local substring_start = substring:find("%a")
substring = substring:sub(substring_start)
return substring
end
--- function to parse numbers
function parse_number(start_key, line_to_parse)
local result = line_to_parse:match("%d+", e_key)
return tonumber(result)
end
--- function to parse arrays of numbers
function parse_number_array(start_key, line_to_parse)
-- stuff the array
local r = { }
for p in line_to_parse:gmatch("%d+") do
p = tonumber(p)
p = math.floor(p)
table.insert(r, p)
end
return r
end
--- function to parse things
function parse_entry(keyword, flashfile, type, use_same_line)
local new_entry = nil
local return_val
local return_array = {}
local c_line
if use_same_line == false then
c_line = get_next_line(flashfile)
if c_line == nil then
-- end of file
return -2, false, return_array
end
while c_line:len() == 0 do
c_line = get_next_line(flashfile)
if c_line == nil then
-- end of file
return -2, false, return_array
end
end
new_entry = find_keyword(c_line, "Name:")
else
c_line = use_same_line
end
-- check if we found a new entry
if new_entry == nil then
c_key = find_keyword(c_line, keyword)
if c_key == nil then
-- we didn't find the thing...
return -1, c_line, return_array
end
if type == "n" then
-- soo... parse a number
return_val = parse_number(c_key, c_line)
return return_val, false, return_array
elseif type == "array_n" then
-- soo... parse an array of numbers
return_array = parse_number_array(c_key, c_line)
return_val = #return_array
return return_val, false, return_array
end
else
-- found new entry instead...
return -2, c_line, return_array
end
end
-----------------------------------------------
-- loading the flash animations
function parse_flash_ani_file(n_file)
local something_to_parse = true
while something_to_parse == true do
local c_line = get_next_line(n_file)
-- if we are at end of file, stop the loop
if c_line == nil then
something_to_parse = false
break
end
local entry_start = find_keyword(c_line, "Filename:")
-- if we found something else, try next line
if entry_start ~= nil then
-- ok... so we should have a good entry candidate and all that
local current_entry = parse_string(entry_start, c_line)
animation = gr.loadTexture(current_entry, true)
table.insert(arr_D_eff, animation)
if animation:isValid() == false then
ba.warning("Animation defined in " .. filename_flashani .. " " .. current_entry .. " is invalid")
end
end
end
end
-- actual flash effect parsing function
function parse_flash_file(flashfile)
-- pick first line
entries_left = true
use_same_line = false
while entries_left == true do
-- find ship name
if use_same_line == false then
use_same_line = get_next_line(flashfile)
end
if use_same_line == nil then
-- end of file
entries_left = false
break
end
if use_same_line:len() == 0 then
use_same_line = false
else
entry_start = find_keyword(use_same_line, "Name:")
if entry_start ~= nil then
-- insert while loop here to enable breaks as next statements
while entry_start ~= nil do
current_entry = parse_string(entry_start, use_same_line)
-- init the entry
init_entry(current_entry)
use_same_line = false
local temp_val = nil
local temp_arr = nil
entry_start = nil
-- detonation box width
temp_val, use_same_line = parse_entry("Width:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SW[current_entry] = temp_val
end
-- detonation box height
temp_val, use_same_line = parse_entry("Height:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SH[current_entry] = temp_val
end
-- detonation box lenght
temp_val, use_same_line = parse_entry("Length:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SL[current_entry] = temp_val
end
-- detonation radius
temp_val, use_same_line = parse_entry("Detonation Radius:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SD_rad[current_entry] = temp_val
end
-- random detonation effects
local temp_arr = {}
temp_val, use_same_line, temp_arr = parse_entry("Detonation Effects:", flashfile, "array_n", use_same_line)
if temp_val == -2 then
break
else
arr_SD_eff[current_entry] = temp_arr
end
-- multiplier for the detonation occurrance
temp_val, use_same_line = parse_entry("Detonation Multiplier:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
elseif temp_val ~= -1 then
arr_SD_m[current_entry] = temp_val
end
-- final flash radius
temp_val, use_same_line = parse_entry("Flash Radius:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SF_rad[current_entry] = temp_val
end
-- flash effect
temp_val, use_same_line = parse_entry("Flash Effect:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
math.floor(temp_val)
arr_SF_eff[current_entry] = temp_val
end
-- blinding effect
temp_val, use_same_line = parse_entry("Blinding Effect Intensity:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
if temp_val < 0 then
temp_val = 0
elseif temp_val > 100 then
temp_val = 100
end
arr_SB_int[current_entry] = temp_val
end
-- blinding duration
temp_val, use_same_line = parse_entry("Blinding Effect Duration:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SB_dur[current_entry] = temp_val
end
-- blast effect delay
temp_val, use_same_line = parse_entry("Blast Effect Delay:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
else
arr_SB_time[current_entry] = temp_val
end
end
else
use_same_line = get_next_line(flashfile)
end
end
end
end
----------
-- main --
----------
-- init arrays
arrayShipName = {}
arr_SW = {}
arr_SH = {}
arr_SL = {}
arr_SD_rad = {}
arr_SD_eff = {}
arr_SD_m = {}
arr_SF_rad = {}
arr_SF_eff = {}
arr_SB_int = {}
arr_SB_dur = {}
arr_SB_time = {}
arr_D_eff = {}
-- open reference file, if any
-- if failed... pass the script
filename_flash = "expl_flashes.cfg"
filename_flashani = "exp_ani_flashes.cfg"
if ((cf.fileExists(filename_flash, "data/config/", true) == true) and (cf.fileExists(filename_flashani, "data/config/", true) == true)) then
boolflashfileOK = true
end
if boolflashfileOK then
-- open to read the contents
flashanifile = cf.openFile(filename_flashani, "r")
-- parse contents
parse_flash_ani_file(flashanifile)
-- close the file
flashanifile:close()
-- continue with the rest in similar manner
flashfile = cf.openFile(filename_flash, "r")
parse_flash_file(flashfile)
flashfile:close()
-- setup rest of the required stuff
math.randomseed( os.time() )
f_counter = {}
v_null = ba.createVector(0,0,0)
arr_FS_List = {}
arr_FS = {}
arr_FS_Class = {}
arr_FS_Pos = {}
arr_FS_done = {}
arr_FS_time = {}
bl_int = 0
bl_end = 0
bl_max = 0
bl_start = 0
bl_int_init = 0
else
ba.warning("Failed to initialize flashy deaths script")
end
----------------------------------
-- functions for later sections --
----------------------------------
function blinding_effect(intensity, duration, time)
bl_int_init = bl_int
if (intensity < bl_max) then
if intensity > bl_int then
local effect_time = bl_end - bl_start
local delta_time = time - bl_start
if effect_time == 0 then
bl_max = intensity
bl_start = time
bl_end = time + (duration / 1000)
else
local pct_time = (effect_time - delta_time) / effect_time
if pct_time < 0.85 then
bl_max = intensity
bl_start = time
bl_end = time + (duration / 1000)
end
end
end
else
bl_max = intensity
bl_start = time
bl_end = time + (duration / 1000)
end
end
function process_blinding_effect_frame(time)
if bl_max == 0 then
return
end
local effect_time = bl_end - bl_start
local delta_time = time - bl_start
local pct_time = (effect_time - delta_time) / effect_time
local case_time
-- lets go case by case
if pct_time < 0.0 then
-- effect has faded away
bl_int = 0
bl_max = 0
blindint_intensity_start = 0
elseif pct_time < 0.85 then
-- effect is still fading away
case_time = 1 - (pct_time / 0.85)
bl_int = math.pow(((1 + math.cos(case_time * math.pi))/2),3)
elseif pct_time > 0.90 then
-- effect is still getting stronger
if pct_time == 0 then
case_time = -1
else
case_time = -1 * ((pct_time - 0.9) / 0.1)
end
bl_int = math.pow(((1 + math.cos(case_time * math.pi))/2),2) * (bl_max - bl_int_init) + bl_int_init
else
bl_int = bl_max
end
if bl_int ~= 0 then
a = bl_int * 255
gr.drawString(a, 255,255)
gr.flashScreen(a,a,a)
end
end
function do_death_flash(name, number)
-- death flash explosion
arr_FS_List[name] = 2
local v_F_pos = arr_FS_Pos[name]
arr_FS_Pos[name] = nil
local str_F_class = arr_FS_Class[name]
arr_FS_Class[name] = nil
local n_F_rad = (math.random() + 0.5) * arr_SF_rad[str_F_class]
local l_anim_flash = arr_D_eff[arr_SF_eff[str_F_class]]
if l_anim_flash:isValid() then
ts.createParticle(v_F_pos,v_null,f_F_time,n_F_rad,PARTICLE_BITMAP,-1,false,l_anim_flash)
end
-- death flash blinding effect
if arr_SB_int[str_F_class] > 0 then
local coord_x
local coord_y
coord_x, coord_y = v_F_pos:getScreenCoords()
if coord_x ~= false then
blinding_effect(arr_SB_int[str_F_class], arr_SB_dur[str_F_class], f_M_time)
end
end
-- purge from the list
table.insert(arr_FS_done, number)
end
function check_flash(name)
local class = arr_FS_Class[name]
if arr_SB_time[class] > 0 then
if arr_FS_time[name] <= f_M_time then
return true;
end
end
return false;
end
function add_to_flash_list(name, class)
arr_FS_List[name] = 1
arr_FS_Class[name] = class
if arr_SB_time[class] > 0 then
local temp_time = math.random() + 1
arr_FS_time[name] = arr_SB_time[class] * temp_time / 1000 + f_M_time
end
table.insert(arr_FS,name)
end
]
$State: GS_STATE_GAME_PLAY
$On Frame:
[
f_M_time = mn.getMissionTime()
if ((f_M_time ~= nil) and boolflashfileOK) then
f_F_time = ba.getFrametime(true)
f_rnd = math.random()
n_ships = #mn.Ships
for h = 1, n_ships do
o_ship = mn.Ships[h]
str_S_class = o_ship.Class.Name:lower()
--ONLY SHIPS WITH EFFECTS--
if ((arr_SF_rad[str_S_class] ~= nil) and (arr_SD_rad[str_S_class] ~= nil)) then
str_S_name = o_ship.Name
floatHP = o_ship.HitpointsLeft
if floatHP <= 0 then
v_S_pos = o_ship.Position
if arr_SF_rad[str_S_class] > 0 then
if arr_FS_List[str_S_name] == nil then
add_to_flash_list(str_S_name, str_S_class)
end
end
if arr_SD_rad[str_S_class] > 0 then
arr_FS_Pos[str_S_name] = v_S_pos
if f_counter[str_S_name] == nil then
f_counter[str_S_name] = 0
end
f_rnd = math.random()
local l_n_SD_eff = #arr_SD_eff[str_S_class]
while f_counter[str_S_name] > f_rnd do
f_counter[str_S_name] = f_counter[str_S_name] - f_rnd
local l_or_ship = o_ship.Orientation
local n_attempts = arr_SD_m[str_S_class]
local n_partials
n_attempts, n_partials = math.modf(n_attempts)
if n_partials ~= 0 then
if math.random() > n_partials then
n_attempts = n_attempts + 1
end
end
for n = 1,n_attempts do
local l_f_rnd_1 = (math.random() - 0.5) * arr_SW[str_S_class]
local l_f_rnd_2 = (math.random() - 0.5) * arr_SH[str_S_class]
local l_f_rnd_3 = (math.random() - 0.5) * arr_SL[str_S_class]
local l_v_rnd = ba.createVector(l_f_rnd_1,l_f_rnd_2,l_f_rnd_3)
local l_f_det_r = (math.random() + 0.5) * arr_SD_rad[str_S_class]
local l_v_rot_rnd = l_or_ship:unrotateVector(l_v_rnd)
local l_v_det_pos = v_S_pos + l_v_rot_rnd
local l_arr_SD_eff = arr_SD_eff[str_S_class]
if l_n_SD_eff == 1 then
anim_det = l_arr_SD_eff[1]
if anim_det:isValid() then
ts.createParticle(l_v_det_pos,v_null,f_F_time,l_f_det_r,PARTICLE_BITMAP,-1,false,anim_det)
end
elseif l_n_SD_eff > 1 then
local l_n_rnd_id = math.random(l_n_SD_eff)
anim_det = arr_D_eff[l_arr_SD_eff[l_n_rnd_id]]
if anim_det:isValid() then
ts.createParticle(l_v_det_pos,v_null,f_F_time,l_f_det_r,PARTICLE_BITMAP,-1,false,anim_det)
end
end
end
if f_counter[str_S_name] <= 0 then
f_counter[str_S_name] = 0
else
f_rnd = math.random()
end
end
f_counter[str_S_name] = f_counter[str_S_name] + f_F_time
end
end
end
n_FS = #arr_FS
for x=1,n_FS do
name = arr_FS[x]
if arr_FS_List[name] == 1 then
if mn.Ships[name]:isValid() == false then
do_death_flash(name, x)
else
-- randomized flash explosion
if check_flash(name) == true then
do_death_flash(name, x)
end
end
end
end
n_FS_done = #arr_FS_done
if n_FS_done > 0 then
for o=n_FS_done,1,-1 do
table.remove(arr_FS,arr_FS_done[o])
end
arr_FS_done = nil
arr_FS_done = {}
end
end
process_blinding_effect_frame(f_M_time)
end
]
$Application: FS2_Open
$On Mission End:
[
-- kill the arrays...
if boolflashfileOK then
arrayShipName = nil
arr_SW = nil
arr_SH = nil
arr_SL = nil
arr_SD_rad = nil
arr_SD_eff = nil
arr_SF_rad = nil
arr_SF_eff = nil
arr_SB_int = nil
arr_SB_dur = nil
arr_SB_time = nil
local n_effects = #arr_D_eff
for j=1,n_effects do
arr_D_eff[j]:unload()
end
arr_D_eff = nil
f_counter = nil
arr_FS_List = nil
arr_FS = nil
arr_FS_Class = nil
arr_FS_Pos = nil
arr_FS_done = nil
arr_FS_time = nil
boolflashfileOK = nil
end
]
#End
expl_flashes.cfg
This file needs to be placed into ../data/config/ directory.
Please note that the following list isn't complete yet.
- Name: defines the ship for which this entry is made for
- Width: & Height: & Length: define the dimensions inside which the detonations occur
- Detonation Radius: defines the radius (base radius) of the detonation effects
- Detonation Effects: list of ID values of the effects (defined in the other cfg file), may have multiple ones
- Detonation Multiplier: multiplier which controls the amount of explosions triggered. 0.2 is 80% decrease, 1.2 is 20% increase
- Flash Radius: defines the radius of the flash when ship actually goes away
- Flash Effect: ID values of the flash effect, as listed in line order entry in additional cfg
- Blinding Effect Intensity: value from 0 to 100, sets the intensity of the blinding effect - requires flash effect to be defined
- Blinding Effect Duration: sets the duration of the blinding effect in milliseconds
- Blast Effect Delay: sets the base time for flash & blinding effect to appear in milliseconds
Table allows for lines to be commented using '--' as comment marker
==Terran== Name: GTDr Amazon Advanced Width: 80 Height: 100 Length: 200 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 750 Flash Effect: 1 Name: GTFr Triton Width: 110 Height: 130 Length: 250 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 750 Flash Effect: 1 Name: TC-Tri Width: 110 Height: 130 Length: 250 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 750 Flash Effect: 1 Name: GTFr Poseidon Width: 35 Height: 30 Length: 60 Detonation Radius: 25 Detonation Effects: 2, 3 Flash Radius: 700 Flash Effect: 1 Name: @GTC Fenris Width: 150 Height: 200 Length: 250 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 1000 Flash Effect: 1 Name: GTM Hippocrates Width: 80 Height: 275 Length: 375 Detonation Radius: 200 Detonation Effects: 2, 3 Flash Radius: 1700 Flash Effect: 1 Name: GTC Leviathan Width: 150 Height: 200 Length: 250 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 1000 Flash Effect: 1 Name: GTSc Faustus Width: 95 Height: 85 Length: 160 Detonation Radius: 50 Detonation Effects: 2, 3 Flash Radius: 800 Flash Effect: 1 Name: GTG Zephyrus Width: 80 Height: 70 Length: 255 Detonation Radius: 80 Detonation Effects: 2, 3 Flash Radius: 800 Flash Effect: 1 Name: GTA Charbydis Width: 60 Height: 90 Length: 110 Detonation Radius: 75 Detonation Effects: 2, 3 Flash Radius: 600 Flash Effect: 1 Name: GTD Orion Width: 500 Height: 500 Length: 1900 Detonation Radius: 500 Detonation Effects: 2, 3 Flash Radius: 2500 Flash Effect: 1 Name: GTD Hecate Width: 700 Height: 500 Length: 1900 Detonation Radius: 500 Detonation Effects: 2, 3 Flash Radius: 2500 Flash Effect: 1 Name: GTD Hades Width: 700 Height: 500 Length: 3200 Detonation Radius: 800 Detonation Effects: 2, 3 Flash Radius: 4000 Flash Effect: 1 Name: GTI Arcadia Width: 1000 Height: 1200 Length: 800 Detonation Radius: 1000 Detonation Effects: 2, 3 Flash Radius: 5000 Flash Effect: 1 Name: GTVA Colossus Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Detonation Effects: 2, 3 Flash Radius: 50000 Flash Effect: 1 Name: GTCv Deimos Width: 350 Height: 400 Length: 750 Detonation Radius: 200 Detonation Effects: 2, 3 Flash Radius: 1500 Flash Effect: 1 Name: GTC Aeolus Width: 80 Height: 90 Length: 275 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 1000 Flash Effect: 1 Name: NTF Iceni Width: 400 Height: 450 Length: 1000 Detonation Radius: 300 Detonation Effects: 2, 3 Flash Radius: 1500 Flash Effect: 1 Name: NTF Boadicea Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Detonation Effects: 2, 3 Flash Radius: 50000 Flash Effect: 1 Name: @GTT Elysium Width: 35 Height: 45 Length: 35 Detonation Radius: 25 Detonation Effects: 2, 3 Flash Radius: 500 Flash Effect: 1 Name: @GTT Argo Width: 95 Height: 70 Length: 160 Detonation Radius: 75 Detonation Effects: 2, 3 Flash Radius: 600 Flash Effect: 1 Name: GTI Ganymede Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Detonation Effects: 2, 3 Flash Radius: 50000 Flash Effect: 1 Name: Knossos Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Detonation Effects: 2, 3 Flash Radius: 50000 Flash Effect: 1 Name: TC-Meson Bomb Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Detonation Effects: 2, 3 Flash Radius: 50000 Flash Effect: 1 ==Vasudan== Name: PVFr Ma'at Width: 20 Height: 20 Length: 55 Detonation Radius: 25 Detonation Effects: 2, 3 Flash Radius: 600 Flash Effect: 1 Name: GVFr Bes Width: 25 Height: 15 Length: 60 Detonation Radius: 25 Detonation Effects: 2, 3 Flash Radius: 600 Flash Effect: 1 Name: GVFr Satis Width: 45 Height: 50 Length: 110 Detonation Radius: 50 Detonation Effects: 2, 3 Flash Radius: 800 Flash Effect: 1 Name: GVG Anuket Width: 85 Height: 80 Length: 350 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 900 Flash Effect: 1 Name: GVC Aten Width: 150 Height: 50 Length: 240 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 1000 Flash Effect: 1 Name: GVC Mentu Width: 180 Height: 140 Length: 325 Detonation Radius: 100 Detonation Effects: 2, 3 Flash Radius: 800 Flash Effect: 1 Name: GVCv Sobek Width: 275 Height: 275 Length: 620 Detonation Radius: 200 Detonation Effects: 2, 3 Flash Radius: 1500 Flash Effect: 1 Name: GVD Typhon Width: 700 Height: 300 Length: 2200 Detonation Radius: 500 Detonation Effects: 2, 3 Flash Radius: 2500 Flash Effect: 1 Name: GVA Setekh Width: 100 Height: 100 Length: 200 Detonation Radius: 75 Detonation Effects: 2, 3 Flash Radius: 600 Flash Effect: 1 Name: GVD Hatshepsut Width: 700 Height: 600 Length: 2200 Detonation Radius: 500 Detonation Effects: 2, 3 Flash Radius: 2500 Flash Effect: 1 Name: GTSG Mjolnir Width: 100 Height: 110 Length: 90 Detonation Radius: 40 Detonation Effects: 2, 3 Flash Radius: 500 Flash Effect: 1
exp_ani_flashes.cfg
This file needs to be placed into ../data/config/ directory.
Contains an ordered list of animations. First defined effect gets ID number 1, second gets ID number 2 and so on. These ID numbers are used in Detonation Effects: and Flash Effect: entries to define the desired animations.
Filename: EXP_flash Filename: exp04 Filename: exp05
Notes
As stated above the shiplist isn't complete yet, meaning that the destruction of any ships other than the ones specified in the current expl_flashes.cfg will not trigger any effect.