Hard Light Productions Forums
Modding, Mission Design, and Coding => The Scripting Workshop => Topic started by: Nighteyes on May 09, 2010, 09:15:54 pm
-
Hi guys, I'm just woundering how hard would it be to add the option of blinding effect(similar to the one used in new flashy deaths script) to certain weapons, such as nukes... when it hits and you'r pretty close, a bright flash blinds you for a few moments...
also, while were at it, can the flash effect also be activated at will on weapons as well? this can give more diversity to some missile explosions, as glows, spark or any other effect can be added ontop of the normal missile hit explosion.
-
hmm no comment I see... won't it be pretty easy to implement as this feature already exists, just not for weapons?
-
I don't see what this has to do with SCP... it's not really an engine feature. It should be in the scripting board. :blah:
-
It has already been done by Wanderer but I don't think that script is publicly available, or at least I haven't seen it around. But yes, you've got a good suggestion there and I had completely forgotten about it. I'll ask Wanderer on irc.
-
Yes. I have written it. And no i haven't released it yet.
-
Standalone version - not to be used with flashy deaths script - it might still have some bits of flashy deaths script hanging from it. Integrated version will be posted later if there is interest.
The sct.tbm
#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_WF_rad[name] = 1
arr_WF_eff[name] = 0
arr_WB_int[name] = 0
arr_WB_dur[name] = 0
arr_WB_dist[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)
local result = line_to_parse:sub(start_key)
local r_value = result:match('[0-9%.]+')
r_value = tonumber(r_value)
return r_value
end
--- function to parse arrays of numbers
function parse_number_array(start_key, line_to_parse)
-- stuff the array
local r = { }
local p
for p in line_to_parse:gmatch('[0-9%.]+') 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:")
current_start_line = c_line
else
c_line = use_same_line
end
-- check if we found a new entry
if new_entry == nil then
local 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)
local 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:")
current_start_line = use_same_line
if entry_start ~= nil then
local not_new_entry = false
-- insert while loop here to enable breaks as next statements
while entry_start ~= nil do
if not_new_entry == false then
current_entry = parse_string(entry_start, use_same_line)
-- init the entry
init_entry(current_entry)
use_same_line = false
ba.print("\nClass: " .. current_entry .. "\n")
end
local temp_val = nil
local temp_arr = nil
entry_start = nil
-- final flash radius
temp_val, use_same_line = parse_entry("Flash Radius Multiplier:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
elseif temp_val ~= -1 then
ba.print("FRM: " .. temp_val .. "\n")
arr_WF_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
elseif temp_val ~= -1 then
ba.print("FE: " .. temp_val .. "\n")
math.floor(temp_val)
arr_WF_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
elseif temp_val ~= -1 then
ba.print("BE: " .. temp_val .. "\n")
temp_val = temp_val + "0"
if temp_val < 0 then
temp_val = 0
elseif temp_val > 100 then
temp_val = 100
end
arr_WB_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
elseif temp_val ~= -1 then
ba.print("BEDu: " .. temp_val .. "\n")
arr_WB_dur[current_entry] = temp_val
end
-- blast effect delay
temp_val, use_same_line = parse_entry("Blinding Effect Distance Multiplier:", flashfile, "n", use_same_line)
if temp_val == -2 then
break
elseif temp_val ~= -1 then
ba.print("BEDM: " .. temp_val .. "\n")
arr_WB_dist[current_entry] = temp_val
end
if current_start_line == use_same_line then
use_same_line = get_next_line(flashfile)
local temp_string = find_keyword(use_same_line, "Name:")
if temp_string == nil then
current_start_line = use_same_line
entry_start = use_same_line
else
entry_start = nil
end
not_new_entry = true
end
end
else
use_same_line = get_next_line(flashfile)
end
end
end
end
----------
-- main --
----------
-- init arrays
arrayShipName = {}
arr_WF_rad = {}
arr_WF_eff = {}
arr_WB_int = {}
arr_WB_dur = {}
arr_WB_dist = {}
arr_D_eff = {}
-- open reference file, if any
-- if failed... pass the script
filename_flash = "wep_exp_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)
v_temp = ba.createVector(0,0,0)
v_rnd_sphere = ba.createVector(0,0,0)
bl_int = 0
bl_end = 0
bl_max = 0
bl_start = 0
bl_int_init = 0
else
ba.warning("Failed to initialize flashy weapons 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 = bl_max * 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.flashScreen(a,a,a)
end
end
function do_weapon_flash(weapon)
local class = weapon.Class.Name:lower()
-- death flash explosion - default weapon 'radius' to 10
if arr_WF_rad[class] > 0 then
local v_F_pos = weapon.Position
local n_F_rad = 15 * (math.random() + 0.5) * arr_WF_rad[class]
local l_anim_flash = arr_D_eff[arr_WF_eff[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
end
-- death flash blinding effect
if arr_WB_int[class] > 0 then
local v_F_pos = weapon.Position
local coord_x
local coord_y
coord_x, coord_y = v_F_pos:getScreenCoords()
if coord_x ~= false then
local l_f_dist_mult = 1
local l_player = hv.Player
if l_player:isValid() then
local l_v_plr_pos = l_player.Position
local l_n_distace_fls_plr = v_F_pos:getDistance(l_v_plr_pos)
local l_n_max_fls_distance = 20 * arr_WB_dist[class]
if l_n_distace_fls_plr > l_n_max_fls_distance then
local l_n_exp_dist_mult = l_n_distace_fls_plr / l_n_max_fls_distance
l_f_dist_mult = 1 / math.pow(l_n_exp_dist_mult, 2)
end
blinding_effect(arr_WB_int[class] * l_f_dist_mult, arr_WB_dur[class], f_M_time)
end
end
end
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_weapons = #mn.Weapons
for h = 1, n_weapons do
o_weapon = mn.Weapons[h]
if o_weapon.LifeLeft <= 0 then
do_weapon_flash(o_weapon)
end
end
process_blinding_effect_frame(f_M_time)
end
]
$State: GS_STATE_GAME_PLAY
$On Weapon Collision:
[
f_M_time = mn.getMissionTime()
if ((f_M_time ~= nil) and boolflashfileOK) then
wep = hv.Weapon
do_weapon_flash(wep)
end
]
$Application: FS2_Open
$On Mission End:
[
-- kill the arrays...
if boolflashfileOK then
arrayShipName = nil
arr_WF_rad = nil
arr_WF_eff = nil
arr_WB_int = nil
arr_WB_dur = 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
boolflashfileOK = nil
end
]
#End
wep_exp_flashes.cfg
Name: Subach HL-7
Flash Radius Multiplier: 10
Flash Effect: 1
Blinding Effect Intensity: 1
Blinding Effect Duration: 1000
Blinding Effect Distance Multiplier: 10
Name: Harpoon
Flash Radius Multiplier: 10
Flash Effect: 2
Blinding Effect Intensity: 1
Blinding Effect Duration: 5000
Blinding Effect Distance Multiplier: 10
exp_ani_flashes.cfg
Filename: exp04
Filename: exp05
-
Ok... here goes nothing... Integrated version of the ship detonation, flash and blinding effects and weapon flash and blinding effects. PLEASE NOTICE the slightly different syntax as insisted by Fury. And also the exact file names (though you can change the default file names as you like). And you can name the script tbm as you like as well. TBM goes to data/tables and CFG goes to data/config. Should be multimod friendly and should not require the script and the related cfg files to exists in 'highest priority' mod directory.
Weapon CFG file:
Name: name of the weapon class
Flash Radius: radius in meters
Flash Effect: ID number of the effect
Blinding Effect Intensity: 0 .. 1
Blinding Effect Duration: in milliseconds
Blinding Effect Distance: in meters
Ship CFG file:
Name: name of the ship class
Detonation Radius Multiplier: applied to model radius
Detonation Effects: comma separated list of effect ID numbers
Detonation Multiplier: multiplier applied to the number of the detonations
Flash Radius Multiplier: applied to model radius
Flash Effect: ID number of the effect
Blinding Effect Intensity: 0 .. 1
Blinding Effect Duration: in milliseconds
Blinding Effect Delay: in milliseconds from ship reaching 0 hitpoints
Blinding Effect Distance Multiplier: applied to model radius
Animation CFG file:
List of animations. First animation gains ID number 1, second gains ID number 2 and so on.
I might still work on adding there an option when to trigger the effect for weapons (only on impact, or only on running out of lifetime, or something else)
[attachment deleted by admin]
-
What about 'dinky explosion' variants?
Also, not having looked at the script in detail... does the "blinding" attenuate with distance, and do you have to be facing it for it to affect you?
-
What about 'dinky explosion' variants?
Also, not having looked at the script in detail... does the "blinding" attenuate with distance, and do you have to be facing it for it to affect you?
Yes to the latter.
-
I wrote there a scripting access to the 'is weapon armed' function so you should be able to check if weapon is armed or not and adjust the effects accordingly
-
I wrote there a scripting access to the 'is weapon armed' function so you should be able to check if weapon is armed or not and adjust the effects accordingly
Nice, we can use that.