Script - Flashy Deaths (new)
From FreeSpace Wiki
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.
Table Entry
#Conditional Hooks $Application: FS2_Open $On Mission Start: [ --------------- -- 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() key_s, key_e = line_to_parse:find(keyword) -- if we cant find a thing if key_s == nil then return nil end return key_e end --- function to initialize the vars function init_entry(name) arrayShipW[name] = 0 arrayShipH[name] = 0 arrayShipL[name] = 0 arrayShipDetRadius[name] = 0 arrayShipFlsRadius[name] = 0 arrayShipDetEffects[name] = { 0 } arrayShipFlsEffect[name] = 0 arrayShipDetMult[name] = 1 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) 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 = { 0 } for p in line_to_parse:gmatch("%d+") do r[1] = r[1] + 1 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) 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 arrayDetEffects[1] = 0 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) arrayDetEffects[1] = arrayDetEffects[1] + 1 table.insert(arrayDetEffects, 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 arrayShipW[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 arrayShipH[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 arrayShipL[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 arrayShipDetRadius[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 arrayShipFlsRadius[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 arrayShipDetEffects[current_entry] = temp_arr 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) arrayShipFlsEffect[current_entry] = temp_val 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 else arrayShipDetMult[current_entry] = temp_val end end else use_same_line = get_next_line(flashfile) end end end end ---------- -- main -- ---------- -- init arrays arrayShipName = {} arrayShipW = {} arrayShipH = {} arrayShipL = {} arrayShipDetRadius = {} arrayShipFlsRadius = {} arrayShipDetEffects = {} arrayShipFlsEffect = {} arrayDetEffects = {} arrayShipDetMult = {} -- 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/tables/", false) == true) and (cf.fileExists(filename_flashani, "data/tables/", false) == true)) then boolflashfileOK = true end if boolflashfileOK then -- open to read the contents flashanifile = cf.openFile(filename_flashani, "r", "data/tables/") -- 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", "data/tables/") parse_flash_file(flashfile) flashfile:close() -- setup rest of the required stuff math.randomseed( os.time() ) floatCounter = {} vectorNull = ba.createVector(0,0,0) arrayFlashShipList = {} arrayFlashShips = {} arrayFlashShipClass = {} arrayFlashShipPosition = {} arrayFlashedShips = {} else ba.warning("Failed to initialize flashy deaths script") end ] $State: GS_STATE_GAME_PLAY $On Frame: [ floatMissionTime = mn.getMissionTime() if ((floatMissionTime ~= nil) and boolflashfileOK) then floatFrameTime = ba.getFrametime(true) floatRandom = math.random() integerShips = #mn.Ships for h = 1, integerShips do objectShip = mn.Ships[h] stringShipClass = objectShip.Class.Name:lower() --ONLY SHIPS WITH EFFECTS-- if arrayShipFlsRadius[stringShipClass] ~= nil then stringShipName = objectShip.Name floatHP = objectShip.HitpointsLeft if floatHP <= 0 then vectorShipPosition = objectShip.Position if arrayFlashShipList[stringShipName] == nil then arrayFlashShipList[stringShipName] = 1 arrayFlashShipClass[stringShipName] = stringShipClass table.insert(arrayFlashShips,stringShipName) end arrayFlashShipPosition[stringShipName] = vectorShipPosition if floatCounter[stringShipName] == nil then floatCounter[stringShipName] = 0 end floatRandom = math.random() while floatCounter[stringShipName] > floatRandom do floatCounter[stringShipName] = floatCounter[stringShipName] - floatRandom orientationShip = objectShip.Orientation local number_of_attempts = arrayShipDetMult[stringShipClass] local n_partials number_of_attempts, n_partials = math.modf(number_of_attempts) if n_partials ~= 0 then if math.random() > n_partials then number_of_attempts = number_of_attempts + 1 end end for n = 1,number_of_attempts do local floatRand_1 = (math.random() - 0.5) * arrayShipW[stringShipClass] local floatRand_2 = (math.random() - 0.5) * arrayShipH[stringShipClass] local floatRand_3 = (math.random() - 0.5) * arrayShipL[stringShipClass] local vectorRand = ba.createVector(floatRand_1,floatRand_2,floatRand_3) local floatDetoSize = (math.random() + 0.5) * arrayShipDetRadius[stringShipClass] local vectorOrientedRand = orientationShip:unrotateVector(vectorRand) local vectorDetoPosition = vectorShipPosition + vectorOrientedRand local l_arrayShpDetEffects = arrayShipDetEffects[stringShipClass] if l_arrayShpDetEffects[1] == 1 then animationDet = l_arrayShpDetEffects[2] if animationDet:isValid() then ts.createParticle(vectorDetoPosition,vectorNull,floatFrameTime,floatDetoSize,PARTICLE_BITMAP,-1,false,animationDet) end elseif l_arrayShpDetEffects[1] > 1 then -- + 2 to take account for the lua indices as well as the array size stored at [1] numberRandomID = math.random(l_arrayShpDetEffects[1]) + 1 animationDet = arrayDetEffects[1+l_arrayShpDetEffects[numberRandomID]] if animationDet:isValid() then ts.createParticle(vectorDetoPosition,vectorNull,floatFrameTime,floatDetoSize,PARTICLE_BITMAP,-1,false,animationDet) end end end if floatCounter[stringShipName] <= 0 then floatCounter[stringShipName] = 0 else floatRandom = math.random() end end floatCounter[stringShipName] = floatCounter[stringShipName] + floatFrameTime end end floatFlashShips = #arrayFlashShips for x=1,floatFlashShips do stringFlashShipName = arrayFlashShips[x] if arrayFlashShipList[stringFlashShipName] == 1 then if mn.Ships[stringFlashShipName]:isValid() == false then arrayFlashShipList[stringFlashShipName] = nil local vectorFlashPosition = arrayFlashShipPosition[stringFlashShipName] arrayFlashShipPosition[stringFlashShipName] = nil local stringFlashClass = arrayFlashShipClass[stringFlashShipName] arrayFlashShipClass[stringFlashShipName] = nil local floatFlashRadius = (math.random() + 0.5) * arrayShipFlsRadius[stringFlashClass] local animationFlash = arrayDetEffects[arrayShipFlsEffect[stringFlashClass]] if animationFlash:isValid() then ts.createParticle(vectorFlashPosition,vectorNull,floatFrameTime,floatFlashRadius,PARTICLE_BITMAP,-1,false,animationFlash) end table.insert(arrayFlashedShips,x) end end end integerFlashedShips = #arrayFlashedShips if integerFlashedShips > 0 then for o=integerFlashedShips,1,-1 do table.remove(arrayFlashShips,arrayFlashedShips[o]) end arrayFlashedShips = nil arrayFlashedShips = {} end end end ] $Application: FS2_Open $On Mission End: [ -- kill the arrays... if boolflashfileOK then arrayShipName = nil arrayShipW = nil arrayShipH = nil arrayShipL = nil arrayShipDetRadius = nil arrayShipFlsRadius = nil arrayShipDetEffects = nil arrayShipFlsEffect = nil for j=1,arrayDetEffects[1] do arrayDetEffects[j+1]:unload() end arrayDetEffects = nil floatCounter = nil arrayFlashShipList = nil arrayFlashShips = nil arrayFlashShipClass = nil arrayFlashShipPosition = nil arrayFlashedShips = nil boolflashfileOK = nil end ] #End
expl_flashes.cfg
Please note that the following list isn't complete yet.
==Terran== Name: GTFr Triton Width: 110 Height: 130 Length: 250 Detonation Radius: 100 Flash Radius: 750 Detonation Effects: Flash Effect: Name: GTFr Poseidon Width: 35 Height: 30 Length: 60 Detonation Radius: 25 Flash Radius: 700 Detonation Effects: Flash Effect: Name: @GTC Fenris Width: 150 Height: 200 Length: 250 Detonation Radius: 100 Flash Radius: 1000 Detonation Effects: Flash Effect: Name: GTM Hippocrates Width: 80 Height: 275 Length: 375 Detonation Radius: 200 Flash Radius: 1700 Detonation Effects: Flash Effect: Name: GTC Leviathan Width: 150 Height: 200 Length: 250 Detonation Radius: 100 Flash Radius: 1000 Detonation Effects: Flash Effect: Name: GTSc Faustus Width: 95 Height: 85 Length: 160 Detonation Radius: 50 Flash Radius: 800 Detonation Effects: Flash Effect: Name: GTG Zephyrus Width: 80 Height: 70 Length: 255 Detonation Radius: 80 Flash Radius: 800 Detonation Effects: Flash Effect: Name: GTA Charbydis Width: 60 Height: 90 Length: 110 Detonation Radius: 75 Flash Radius: 600 Detonation Effects: Flash Effect: Name: GTD Orion Width: 500 Height: 500 Length: 1900 Detonation Radius: 500 Flash Radius: 2500 Detonation Effects: Flash Effect: Name: GTD Hecate Width: 700 Height: 500 Length: 1900 Detonation Radius: 500 Flash Radius: 2500 Detonation Effects: Flash Effect: Name: GTD Hades Width: 700 Height: 500 Length: 3200 Detonation Radius: 800 Flash Radius: 4000 Detonation Effects: Flash Effect: Name: GTI Arcadia Width: 1000 Height: 1200 Length: 800 Detonation Radius: 1000 Flash Radius: 5000 Detonation Effects: Flash Effect: Name: GTVA Colossus Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Flash Radius: 50000 Detonation Effects: Flash Effect: Name: GTCv Deimos Width: 350 Height: 400 Length: 750 Detonation Radius: 200 Flash Radius: 1500 Detonation Effects: Flash Effect: Name: GTC Aeolus Width: 80 Height: 90 Length: 275 Detonation Radius: 100 Flash Radius: 1000 Detonation Effects: Flash Effect: Name: NTF Iceni Width: 400 Height: 450 Length: 1000 Detonation Radius: 300 Flash Radius: 1500 Detonation Effects: Flash Effect: Name: NTF Boadicea Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Flash Radius: 50000 Detonation Effects: Flash Effect: Name: @GTT Elysium Width: 35 Height: 45 Length: 35 Detonation Radius: 25 Flash Radius: 500 Detonation Effects: Flash Effect: Name: @GTT Argo Width: 95 Height: 70 Length: 160 Detonation Radius: 75 Flash Radius: 600 Detonation Effects: Flash Effect: Name: GTI Ganymede Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Flash Radius: 50000 Detonation Effects: Flash Effect: Name: Knossos Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Flash Radius: 50000 Detonation Effects: Flash Effect: Name: TC-Meson Bomb Width: 10000 Height: 12000 Length: 8000 Detonation Radius: 10000 Flash Radius: 50000 Detonation Effects: Flash Effect: ==Vasudan== Name: PVFr Ma'at Width: 20 Height: 20 Length: 55 Detonation Radius: 25 Flash Radius: 600 Detonation Effects: Flash Effect: Name: GVFr Bes Width: 25 Height: 15 Length: 60 Detonation Radius: 25 Flash Radius: 600 Detonation Effects: Flash Effect: Name: GVFr Satis Width: 45 Height: 50 Length: 110 Detonation Radius: 50 Flash Radius: 800 Detonation Effects: Flash Effect: Name: GVG Anuket Width: 85 Height: 80 Length: 350 Detonation Radius: 100 Flash Radius: 900 Detonation Effects: Flash Effect: Name: GVC Aten Width: 150 Height: 50 Length: 240 Detonation Radius: 100 Flash Radius: 1000 Detonation Effects: Flash Effect: Name: GVC Mentu Width: 180 Height: 140 Length: 325 Detonation Radius: 100 Flash Radius: 800 Detonation Effects: Flash Effect: Name: GVCv Sobek Width: 275 Height: 275 Length: 620 Detonation Radius: 200 Flash Radius: 1500 Detonation Effects: Flash Effect: Name: GVD Typhon Width: 700 Height: 300 Length: 2200 Detonation Radius: 500 Flash Radius: 2500 Detonation Effects: Flash Effect: Name: GVA Setekh Width: 100 Height: 100 Length: 200 Detonation Radius: 75 Flash Radius: 600 Detonation Effects: Flash Effect: Name: GVD Hatshepsut Width: 700 Height: 600 Length: 2200 Detonation Radius: 500 Flash Radius: 2500 Detonation Effects: Flash Effect: Name: GTSG Mjolnir Width: 100 Height: 110 Length: 90 Detonation Radius: 40 Flash Radius: 500 Detonation Effects: Flash Effect:
exp_ani_flashes.cfg
Filename: EXP_flash.eff Filename: exp04.ani Filename: exp05.ani
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.