Author Topic: Feature Request: Flashy weapons script  (Read 3347 times)

0 Members and 1 Guest are viewing this topic.

Offline Nighteyes

  • 211
Feature Request: Flashy weapons script
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.
« Last Edit: May 09, 2010, 09:19:01 pm by Nighteyes »

 

Offline Nighteyes

  • 211
Re: Feature Request: Flashy weapons script
hmm no comment I see... won't it be pretty easy to implement as this feature already exists, just not for weapons?

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: Feature Request: Flashy weapons script
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:

 

Offline Fury

  • The Curmudgeon
  • 213
Re: Feature Request: Flashy weapons script
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.

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: Feature Request: Flashy weapons script
Yes. I have written it. And no i haven't released it yet.
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: Feature Request: Flashy weapons script
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
Code: [Select]
#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
Code: [Select]
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
Code: [Select]
Filename: exp04
Filename: exp05
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: Feature Request: Flashy weapons script
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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
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]
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: Feature Request: Flashy weapons script
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?

 

Offline General Battuta

  • Poe's Law In Action
  • 214
  • i wonder when my postcount will exceed my iq
Re: Feature Request: Flashy weapons script
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.

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: Feature Request: Flashy weapons script
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
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline General Battuta

  • Poe's Law In Action
  • 214
  • i wonder when my postcount will exceed my iq
Re: Feature Request: Flashy weapons script
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.