Page 1 of 2

Water restarts music

Posted: Tue Nov 25, 2014 11:57 pm
by minmay
Falling into water changes the level's background music to "underwater", and climbing back out changes it back, which makes perfect sense. However, this also has the effect of restarting the background music. This is not much of a problem for the ambient tracks in the original game, but I'm making a mod with background music that's actually...well, music. And the restarting is very awkward and grating.
Is there a way for me to let players dive into water without restarting the music? It restarts even if the above-water and below-water music are both the "underwater" track, so redefining that won't work.

(Boss fights do this too, but that's not much of a problem since I'm going to end up implementing my own boss fight system anyway...)

edit: not defining the "underwater" track at all also doesn't work. The original music will keep playing when you enter the water (though the console will complain), but as you might expect, it will still restart when you leave the water.

Re: Water restarts music

Posted: Wed Nov 26, 2014 3:20 am
by Batty
I would define the above-water ambient as nothing or silent. Then add a Sound component to an object that follows the party everywhere & have it play your track. You can adjust the volume of Sound components (SoundComponent:setVolume(number) - I assume works dynamically) so when water is entered turn the volume to zero, turn it back up on exit.

Just an idea, haven't tried any of it. :)

Edit: you could maybe set maxDistance in the sound's definition at 32 and just stick the object with the Sound component in the wall somewhere.

Edit #2: :lol: I made a rock that plays all the game sounds, here's the script, bit long but yes you can adjust sound volume dynamically:

Code: Select all

function grimRadio()

   if not findEntity('radioCounter') then
	
      spawn('counter', 1, 1, 1, 1, 1, 'radioCounter').counter:setValue(1)
      spawn('counter', 1, 1, 1, 1, 1, 'counter2D').counter:setValue(0)
	
   end

   tunes3D = { 'air_elemental_attack', 'air_elemental_die', 'air_elemental_hit',
               'air_elemental_walk', 'balance', 'barrel_die',
               'barrel_hit', 'beach_waves', '2D', 'blob',
               'blob_hit', 'blob_hit_receptor', 'blob_launch', '2D', 'brew_potion',
               'button', 'cage_open', 'cage_rattle', 'castle_button', 'champion_die',
               'chest_close', 'chest_open', '2D', '2D', '2D',
               'consume_potion', '2D', 'container_box_close', 'container_sack_close',
               'container_sack_open', 'crab_attack', 'crab_die', 'crab_hit', 'crab_walk', 
               'crowern_attack', 'crowern_die', 'crowern_footstep', 'crowern_hit',
               'crowern_walk', 'crows_flying', 'crystal_ambient', 'damage_bear', 'damage_human_female',
               'damage_human_male', 'damage_insectoid_female', 'damage_insectoid_male',
               'damage_lizardman_female', 'damage_lizardman_male', 'damage_minotaur_female',
               'damage_minotaur_male', 'damage_ratling_female', 'damage_ratling_male',
               'dark_acolyte_attack', 'dark_acolyte_die', 'dark_acolyte_hit', 'dark_acolyte_spell',
               'dark_acolyte_walk', 'dark_bolt', 'dark_bolt_hit', 'dark_bolt_launch', '2D',
               'dispel_hit', 'dispel_launch', 'essence_ambient', 'eyctopus_attack', 'eyctopus_die',
               'eyctopus_fart', 'eyctopus_hit', 'eyctopus_walk', 'fire_elemental_attack',
               'fire_elemental_burn', 'fire_elemental_die', 'fire_elemental_hit', 'fire_elemental_walk',
               'fire_pit', '2D', 'fireball', 'fireball_hit', 'fireball_launch',
               'fireburst', 'force_field_ambient', 'force_field_ambient_quiet', 'force_field_cast',
               'forest_trees_wind', 'frostbolt', 'frostbolt_hit', 'frostbolt_launch', 'frostburst',
               '2D', 'gate_close', 'gate_iron_close', 'gate_iron_open', 'gate_lock',
               'gate_open', 'generic_spell', 'goromorg_shield_break', 'goromorg_shield_hit',
               'gun_reload', 'gun_shot_cannon', 'gun_shot_large', 'gun_shot_small', '2D',
               'herder_attack', 'herder_big_attack', 'herder_big_die', 'herder_die', 'herder_footstep',
               'herder_hit', 'herder_small_attack', 'herder_small_die', 'herder_walk', 'ice_guardian_attack',
               'ice_guardian_die', 'ice_guardian_hit', 'ice_guardian_walk', 'ice_hit', 'ice_shard',
               'impact_arrow', 'impact_blade', 'impact_blunt', 'impact_generic', 'impact_plant',
               'impact_punch', 'insectoid_happy', '2D', '2D', '2D', 'key_lock',
               'key_lock_faint', '2D', 'lever', 'light', 'lightning_bolt', 'lightning_bolt_hit',
               'lightning_bolt_hit_small', 'lightning_bolt_launch', 'lindworm_attack', '2D',
               'lindworm_dash', 'lindworm_die', 'lindworm_fly_maneuver1', 'lindworm_fly_maneuver2',
               'lindworm_fly_maneuver3', 'lindworm_hit', 'lindworm_intro', 'lindworm_knockback',
               'lindworm_roar', 'lindworm_shield_break', 'lindworm_summon', 'lindworm_walk', 'lindworm_wing_attack',
               'lizardman_happy', 'lock_chest', 'lock_incorrect', 'magic_bridge_ambient', 'magma_golem_attack',
               'magma_golem_die', 'magma_golem_footstep', 'magma_golem_ground_pound', 'magma_golem_hit',
               'magma_golem_meteor_fall', 'magma_golem_ranged_attack', 'magma_golem_turn_attack', 'magma_golem_walk',
               'map_turn_page', 'master_gate_open', 'medusa_attack', 'medusa_die', 'medusa_gaze', 'medusa_hit',
               'medusa_walk', 'mimic_attack', 'mimic_die', 'mimic_hit', 'mimic_open', 'mimic_walk',
               'mosquito_swarm_attack', 'mosquito_swarm_die', 'mosquito_swarm_hit', 'mosquito_swarm_walk',
               'mummy_attack_01', 'mummy_attack_02', 'mummy_attack_03', 'mummy_attack_04', 'mummy_die',
               'mummy_footstep', 'mummy_hit', 'mummy_walk', 'ogre_attack', 'ogre_die', 'ogre_footstep', 'ogre_hit',
               'ogre_impact', 'ogre_rush_begin', 'ogre_walk', 'ogre_whoosh', 'party_climb_ladder', 'party_crushed',
               '2D', 'party_drown', 'party_enter_stairs', 'party_fall', 'party_land', 'party_move',
               '2D', 'party_move_burdened', 'party_move_dive', 'party_move_grass', 'party_move_overloaded',
               'party_move_wade', '2D', '2D', 'pit_close', 'pit_open',
               'power_attack_charging', 'power_attack_fail', '2D', '2D',
               'power_attack_yell_human_male', 'power_attack_yell_insectoid_female', 'power_attack_yell_insectoid_male',
               'power_attack_yell_lizardman_female', 'power_attack_yell_lizardman_male', '2D',
               '2D', 'power_attack_yell_ratling_female', 'power_attack_yell_ratling_male',
               'power_gem_ambient', 'pressure_plate_pressed', 'pressure_plate_released', 'projectile_hit_party',
               'pushable_block_blocked', 'pushable_block_fall', 'pushable_block_hover', 'pushable_block_push',
               'pushable_block_rise', 'rat_swarm_attack', 'rat_swarm_die', 'rat_swarm_hit', 'rat_swarm_walk',
               'ratling1_alert', 'ratling1_attack', 'ratling1_whoosh_01', 'ratling1_whoosh_02', 'ratling2_alert',
               'ratling2_attack', 'ratling3_alert', 'ratling3_attack', 'ratling_boss_alert', 'ratling_boss_attack',
               'ratling_boss_die', 'ratling_boss_footstep', 'ratling_boss_hit', 'ratling_boss_walk', 'ratling_die',
               'ratling_footstep', 'ratling_happy', 'ratling_hit', 'ratling_walk', 'read_scroll', 'read_tome',
               'river_ambient', '2D', '2D', 'serpent_staff', 'serpent_staff_blast', 'serpent_staff_launch',
               'shockburst', 'shrakk_torr_attack', 'shrakk_torr_die', 'shrakk_torr_fly', 'shrakk_torr_hit',
               'skeleton_archer_attack', 'skeleton_archer_footstep', 'skeleton_attack', 'skeleton_commander_attack',
               'skeleton_commander_ice_shards', 'skeleton_commander_move_attack', 'skeleton_commander_summon_spell',
               'skeleton_commander_turn_attack', 'skeleton_commander_walk', 'skeleton_die', 'skeleton_footstep',
               'skeleton_hit', 'skeleton_trooper_attack', 'skeleton_walk', 'slime_attack', 'slime_die', 'slime_hit',
               'slime_walk', 'snake_attack', 'snake_die', 'snake_hit', 'snake_walk', 'spear_door', '2D',
               'spell_fizzle', 'spell_out_of_energy', 'spider_attack', 'spider_die',
               'spider_eggs_ambient', 'spider_eggs_hit', 'spider_hit', 'spider_walk', 'spike_trap', 'spore_mushroom_die',
               'spore_mushroom_sprout', 'stone_philosopher_eyes', 'summon_stone_attack',
               'summon_stone_die', 'summon_stone_footstep', 'summon_stone_hit', 'summon_stone_wake_up', 'summon_stone_walk',
               '2D', 'swipe_bow', 'swipe_claw', 'swipe_heavy', 'swipe_light', 'swipe_special', '2D', 'teleport', 'teleporter_ambient',
               'terracotta_jar_die', 'terracotta_jar_hit', 'torch_burning', 'trickster_appear', '2D',
               'trickster_escape', 'trickster_laugh', '2D', 'trickster_pull_lever', 'trickster_throw',
               'trickster_walk', 'trickster_zap', 'turtle_alert', 'turtle_attack', 'turtle_die', 'turtle_dive',
               'turtle_diving_alert', 'turtle_diving_attack', 'turtle_double_attack', 'turtle_footstep', 'turtle_hit',
               'turtle_move_attack', 'turtle_walk', 'twigroot_attack', 'twigroot_die', 'twigroot_hit', 'twigroot_strafe',
               'twigroot_walk', 'uggardian_attack', 'uggardian_die', 'uggardian_hit', 'uggardian_walk', 'undead_attack',
               'undead_die', 'undead_rise', 'undead_walk', 'viper_root_attack', 'viper_root_die', 'viper_root_hit',
               'viper_root_ranged_attack', 'viper_root_rise', 'wall_fire', 'wall_sliding', 'wall_sliding_lock', 'wall_tapestry_tear',
               'wand_fear', 'warg_attack', 'warg_die', 'warg_hit', 'warg_howl', 'warg_walk', 'water_hit_large', 'water_hit_small',
               'wind_howl', 'wizard_check_door', 'wizard_clone_die', 'wizard_crystal', 'wizard_hit', 'wizard_laugh', 'wizard_letter',
               'wizard_push', 'wizard_ranged_attack', '2D', 'wizard_shield', 'wizard_teleport', 'wizard_turn',
               'wizard_warp', 'wyvern_attack', 'wyvern_die', 'wyvern_footstep', 'wyvern_hit', 'wyvern_walk',
               'xeloroid_attack', 'xeloroid_die', 'xeloroid_footstep', 'xeloroid_hit', 'xeloroid_lightning', 'xeloroid_walk',
               'zarchton_attack', 'zarchton_die', 'zarchton_dive', 'zarchton_diving_alert', 'zarchton_diving_attack',
               'zarchton_diving_leap_attack', 'zarchton_footstep', 'zarchton_hit', 'zarchton_leap_attack', 'zarchton_walk', '2D' }

   tunes2D = { 'beacon_furnace_activate', 'blow_horn', 'click_down', 'click_up', 'consume_food',
               'container_box_open', 'discover_spell', 'firearm_jammed', 'game_over', 'heal_party', 'item_drop',
               'item_equip', 'item_pick_up', 'level_up', 'lindworm_cinematic_tower', 'party_dig', 'party_move_blocked',
               'party_water_exit', 'party_water_exit_gasp', 'power_attack_ready', 'power_attack_yell_human_female',
               'power_attack_yell_minotaur_female', 'power_attack_yell_minotaur_male', 'scramble_writer', 'secret',
               'spell_expires', 'swipe', 'swipe_thrown', 'trickster_die', 'trickster_polymorph', 'wizard_rumble', 'spell_gesture' }
	
   if not findEntity('soundRock') then
	
      spawn('rock', party.level, party.x, party.y, 1, party.elevation, 'soundRock')
		
   else
	
      soundRock.sound:stop()
      soundRock:removeComponent('Sound')
	
   end
	
   if tunes3D[radioCounter.counter:getValue()] == '2D' then
	
      playSound(tunes2D[counter2D.counter:getValue()])
      hudPrint(radioCounter.counter:getValue() .. ' of ' .. #tunes3D .. ': ' .. tunes2D[counter2D.counter:getValue()])
	
   else
		
      soundRock:createComponent('Sound')
      soundRock.sound:setSound(tunes3D[radioCounter.counter:getValue()])
      soundRock.sound:setVolume(2)
      soundRock.sound:play(tunes3D[radioCounter.counter:getValue()])
      hudPrint(radioCounter.counter:getValue() .. ' of ' .. #tunes3D .. ': ' .. tunes3D[radioCounter.counter:getValue()])
		
   end
	
   hudPrint('')
   hudPrint('')

   if tunes3D[radioCounter.counter:getValue()] == '2D' and
      tunes2D[counter2D.counter:getValue()] == 'beacon_furnace_activate' then
	
      delayedCall(self.go.id, 15, 'grimRadio') 
      radioCounter.controller:increment()

   elseif tunes2D[radioCounter.counter:getValue()] == '2D' and
      tunes2D[counter2D.counter:getValue()] == 'game_over' then
	
      delayedCall(self.go.id, 9, 'grimRadio') 
      radioCounter.controller:increment()

   elseif tunes3D[radioCounter.counter:getValue()] == '2D' and
      tunes2D[counter2D.counter:getValue()] == 'trickster_die' then
	
      delayedCall(self.go.id, 17, 'grimRadio') 
      radioCounter.controller:increment()

   elseif radioCounter.counter:getValue() < #tunes3D then

      delayedCall(self.go.id, 3, 'grimRadio')
      radioCounter.controller:increment()
	
   else

      hudPrint('The End')
	
   end

   if tunes3D[radioCounter.counter:getValue()] == '2D' then counter2D.controller:increment() end
	
end

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:02 am
by NutJob
Ha! That's awesome Batty.

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:07 am
by Batty
Yes, just have a plate activate the script and you can drink Glögg and listen to all the sounds at 3:00 am, :lol: I even adjusted for length to account for some longer sounds. Takes a good while to listen to them all.

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:11 am
by minmay
As entertaining as your script is*, this is not a practical solution because ogg is not supported for sound effects, only ambient tracks. That's 85 MB per minute of stereo music, even a quality 10 (extremely high) stereo ogg is about 3 MB per minute at 44100Hz.

*Though I can't resist correcting you on one point: you have 3D and 2D sounds the wrong way around. "3D" sounds are actually the mono ones; they're so named because they have a position in the 3D world that determines their panning. 2D sounds are so named because they do not (they should really be called 0D sounds :P).

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:20 am
by GoldenShadowGS
Batty wrote:Yes, just have a plate activate the script and you can drink Glögg and listen to all the sounds at 3:00 am, :lol: I even adjusted for length to account for some longer sounds. Takes a good while to listen to them all.
You can auto exec a function just by doing this:

Code: Select all

dothis()

function dothis()
--something here
end
Everything outside of the function definition is run automatically. Simpler than making an invisible trigger and connecting it to the function.

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:23 am
by Batty
GoldenShadowGS wrote: You can auto exec a function just by doing this:

Code: Select all

dothis()

function dothis()
--something here
end
Everything outside of the function definition is run automatically. Simpler than making an invisible trigger and connecting it to the function.
Ah, right, try the script, you don't want it autoexecuting. :)

Re: Water restarts music

Posted: Wed Nov 26, 2014 4:41 am
by Batty
minmay wrote:As entertaining as your script is*, this is not a practical solution because ogg is not supported for sound effects, only ambient tracks. That's 85 MB per minute of stereo music, even a quality 10 (extremely high) stereo ogg is about 3 MB per minute at 44100Hz.
Oh yeah, only .wav in definitions, there is SoundComponent:setSoundType(type), I don't know what that does but I suspect it won't help.
minmay wrote:*Though I can't resist correcting you on one point: you have 3D and 2D sounds the wrong way around. "3D" sounds are actually the mono ones; they're so named because they have a position in the 3D world that determines their panning. 2D sounds are so named because they do not (they should really be called 0D sounds :P).
See this post, according to the editor the sounds in my tunes3D table are 3D.

Re: Water restarts music

Posted: Wed Nov 26, 2014 6:32 am
by minmay
Batty wrote:See this post, according to the editor the sounds in my tunes3D table are 3D.
Again, you have it backwards. What that error message means is that you can't play a non-mono sound as a 3D sound. playSound() can play stereo or mono sounds because it doesn't play the sound in the game world, it just plays the sound. Using a stereo sound in the game world makes no sense because it's only being emitted from one place.
Batty wrote:Oh yeah, only .wav in definitions, there is SoundComponent:setSoundType(type), I don't know what that does but I suspect it won't help.
Ah, I missed that. If sound type is "point", the default, the component plays a 3D (mono) sound at its location. If the sound type is "ambient" it plays a 2D (stereo or mono) sound while activated - this is used for the stone philosophers in the main campaign. So you wouldn't need two sound components to have a stereo sound play all the time (but there's still the filesize problem).

Re: Water restarts music

Posted: Wed Nov 26, 2014 7:43 am
by Batty
minmay wrote:Again, you have it backwards. What that error message means is that you can't play a non-mono sound as a 3D sound. playSound() can play stereo or mono sounds because it doesn't play the sound in the game world, it just plays the sound. Using a stereo sound in the game world makes no sense because it's only being emitted from one place.
Oh I get it, I read the error wrong, so the sounds that don't work with Sound components are stereo. The Sound component is for directional mono "3D" sounds. :)