Duke4.net Forums: Music Control Like in More Modern Games - Duke4.net Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Music Control Like in More Modern Games  "Music controlled by touch plates and switches"

User is offline   HELLMOUSE 

#1

Originally I did my maps modeled off of Doom Music. But now with more modern sound capabilities and larger maps, thanks to the Developers, one track may not be appropriate. Controlling the music in the game via Touch Plates and switches would be an upgrade.

I was thinking of maybe making a new actor type that plays music tracks, NOT music in the form of a sound file. I'm also not sure how to code what connects the actor to the Touch Plate's or switch's tag value.

Basically, there is always a default track, but when the player walks into a certain area, a creepy F.E.A.R. track plays. Another use would be with a well hidden switch or Access Panel: maybe another Doom track, a F.E.A.R. fight theme, or a Dark Forces action theme starts.
0

User is online   Danukem 

  • Duke Plus Developer

#2

View PostHELLMOUSE, on 09 June 2020 - 05:24 PM, said:

I'm also not sure how to code what connects the actor to the Touch Plate's or switch's tag value.


There's no need to have two separate sprites involved in the effect. Here's a touchplate style actor that I coded recently:

        gamevar LOTAG 0 2
        gamevar HITAG 0 2
        gamevar temp 0 0
        gamevar tempb 0 0

        eventloadactor MUSICPLATE
        geta[].lotag LOTAG
        geta[].hitag HITAG
        seta[].lotag 0
        seta[].hitag 0
        cstat 32768
        enda

        actor MUSICPLATE
        ife player[].cursectnum sprite[].sectnum
	{
		getuserdef[].music_episode temp
		getuserdef[].music_level tempb
		ife temp HITAG ife tempb LOTAG nullop else
		starttrackslot HITAG LOTAG
        }
        enda


Obviously you should use your own gamevars if you already have suitable ones in your project.
3

User is offline   oasiz 

  • Dr. Effector

#3

We also use this in Fury to trigger stuff like the pre-boss theme and other changes. Ours allows an input from pretty much anything possible, even enemy kills could cause it to trigger.
While despite not being Duke, it's still all in CON and similar things are possible in Duke.
3

User is offline   HELLMOUSE 

#4

This is great! Thanks. :)

How does the MUSICPLATE work?
1) How is a track list defined?
2) How does a track stop and another one start?
3) Is there a default track?
4) How does a switch control this?

I looked around https://wiki.eduke32.../wiki/Scripting and got a good idea about some of the code, but I'm still unsure of how it works.

It doesn't look like there is a tutorial on this. Maybe in the future some one could add it.

This post has been edited by HELLMOUSE: 10 June 2020 - 03:19 PM

0

User is offline   HELLMOUSE 

#5

What does the MUSICPLATE do?

The MUSICPLATE changes the track only once. You can't have more than one of these. So, you only have 2 tracks per map - not exactly what I was expecting, but this is still very useful.

Can not use with switches.

It is not necessary to have a music list that is assigned to an episode. You can just have this group of tracks out there using the word "music" and a number: ex, music 5.

LOTAG = level track starting at 0
HITAG = episode / music group starting at 0

This is a great thing to have, and I'm sure there are ways to give it more abilities.
0

User is online   Danukem 

  • Duke Plus Developer

#6

View PostHELLMOUSE, on 12 June 2020 - 06:21 PM, said:

What does the MUSICPLATE do?
The MUSICPLATE changes the track only once. You can't have more than one of these. So, you only have 2 tracks per map - not exactly what I was expecting, but this is still very useful.



That is false. The actor will change the music to the designated track whenever you step into its sector and the music is not on that track already. You can put as many as you want in a map and they will work every time you step in them.

I gave you that simply because it was a simple thing to show you, but of course I have had code to trigger music and anything else with tags since 2007. Look at the wiki and look up commands such as checkactivatormotion. You can also make your own activations with vars that don't use that command.
1

User is offline   HELLMOUSE 

#7

I was hoping you would say that. Maybe I implemented it wrong.

I have the test here. It is a simple map with 2 of them in it. There is a quote that says "MUSIC CHANGE DETECTED" and it does display it both times in the game, but for some odd reason it only changes once. That's why I have posted this up here. Maybe there is something different from some of your cons versus mine. As I said, I may have missed something. I tested this with Duke 3D v1.5 using Mapster32 and EDuke32. This is the only thing that is different from the original game, but it still only changes tracks once.

I don't doubt Trooper Dan, but most likely something is different on my end.

For anyone who is interested in this to see what I'm doing wrong, the EDuke32 version I used is 9053, so all you need is that, the attachment, and the DUKE3D.grp. You might want to have a folder called musicplate test to put this all in.

Attached File  MUSICPLATE_TEST.zip (603.93K)
Number of downloads: 198

Remember, this is a little beyond me so it's easy for someone who normally codes to look at this and figure it out.

This post has been edited by HELLMOUSE: 13 June 2020 - 02:03 PM

0

User is online   Danukem 

  • Duke Plus Developer

#8

I figured it out. You need to change the names of LOTAG and HITAG to something else. You could make them lower case and that should fix it.

Here's what's happening:

Those gamevars have to be per-actor, which allows the different MUSICPLATE to store different values. But there are deprecated global gamevars in Eduke32 with those same names. Because they are global, once the map starts all the MUSICPLATE have the same music setting, so it only works once.

I didn't have this problem in my own mod, because I had used different variable names. I didn't even know that those names were reserved. One thing still seems strange though: I don't understand why it doesn't just overwrite the hardcoded ones with the ones declared in the code that are per-actor. Oh well at least you can make it work now.
1

User is offline   HELLMOUSE 

#9

Thanks :)

I knew you would be able to figure it out. That's why I posted those files so you or anyone else could see exactly what's going on. It is odd, like you said, because "gamevar LOTAG 0 2" as in the "2" makes it a peractor variable, which is one of the items I checked online. This is why I'd rather have someone who has higher programming talents than me to look into that.

I've checked on the wiki about "checkactivatormotion" and didn't find a lot on it. I'm not having much luck with that wiki, trying to figure out how to make a switch trigger the MUSICPLATE. As I said before, programming is a little beyond me. It would be like someone describing how to use a graphics program to someone else who does not have a skill set in art. That's why I'm dependent on someone like you when it comes to programming.

I appreciate this.
0

User is offline   HELLMOUSE 

#10

I've been looking into trying to control the MUSICPLATE with a switch but on the wiki I still can't seem to find anything, or find something that I understand.

All it says about "checkactivatormotion" is "Checks to see if the activator with the lotag specified is in motion or not - if it is, than RETURN is set to 1." I can't find an example of how to implement it using an external switch (access card, switch, dip switch, TP).

This post has been edited by HELLMOUSE: 17 June 2020 - 07:17 PM

0

User is online   Danukem 

  • Duke Plus Developer

#11

Why don't you do something else first that just uses the classic CON commands, like code an enemy.
2

User is offline   HELLMOUSE 

#12

Here is the code inside the actor and I have a few problems.

    ife player[].cursectnum sprite[].sectnum
    {	  
          setvar RETURN 0    			            
          getuserdef[].music_episode MUSICEP 
          getuserdef[].music_level MUSICLE  
          ife MUSICEP EPISODE_OR_GROUP_NUMBER    
            ife MUSICLE LEVEL_OR_IN_ARRAY_TRACK  
              nullop 				 
          else 
          {
            starttrackslot EPISODE_OR_GROUP_NUMBER LEVEL_OR_IN_ARRAY_TRACK    // HITAG = episode/group, LOTAG = level/track
            quote 147 
          }
    }
    else
    { 
      checkactivatormotion 297
      ife RETURN 1
      {
        geta[].lotag LEVEL_OR_IN_ARRAY_TRACK
        geta[].hitag EPISODE_OR_GROUP_NUMBER
        starttrackslot EPISODE_OR_GROUP_NUMBER LEVEL_OR_IN_ARRAY_TRACK
      }
    }


For some reason the checkactivatormotion 297 code only plays track 0 0. The music plate engages in a Doom style door sector (LoTag 20) with an ACTIVATOR but it seems like the sprite tags don't work. I have the sprite set to LoTag 20 and HiTag 5. Another problem I discovered is when I run over another music plate it does not cancel the track activated by the switch of a LoTag of 297. It keeps playing the switch triggered track even when I turn the switch to off and have a line "setvar RETURN 0". I've been told that it is possible to trigger music with anything but I don't see how it can work even with a simple switch. I know it can be done. But this doesn't work and I'm not sure why.
0

User is online   Danukem 

  • Duke Plus Developer

#13

EPISODE_OR_GROUP_NUMBER

Those super long var names make it too hard to read for me.
1

User is offline   HELLMOUSE 

#14

Shortening...
Done...

eventloadactor DANMUSICPLATE
  geta[].lotag LEVEL_TRACK 
  geta[].hitag EPISODE_NUMBER
  seta[].lotag 0
  seta[].hitag 0
  cstat 32768
enda

actor DANMUSICPLATE		   		   
    ife player[].cursectnum sprite[].sectnum
    {
          getuserdef[].music_episode MUSIC_E 
          getuserdef[].music_level MUSIC_L  
          ife MUSIC_E EPISODE_NUMBER    
            ife MUSIC_L LEVEL_TRACK              // if either are false then else  
              nullop 				
          else 
          {
            starttrackslot EPISODE_NUMBER LEVEL_TRACK
            quote 147 
          }
    }
    else  // This is the part I added
    { 
      checkactivatormotion 297
      ife RETURN 1
      {
        geta[].lotag LEVEL_TRACK
        geta[].hitag EPISODE_NUMBER
        starttrackslot EPISODE_NUMBER LEVEL_TRACK
      }
    }
enda

0

User is offline   HELLMOUSE 

#15

After I added the "eventloadactor" for the Hazard Actor I thought the "geta[]..." lines were the problem with the music plate but there's still an issue. After the switch is flipped, the music goes *bld-p-p-p* and the normal touch plate keeps running.

I'm wondering if I should code another music player actor just for a switch trigger.
0

User is offline   HELLMOUSE 

#16

actor DANMUSICPLATE	   		   
    ife player[].cursectnum sprite[].sectnum  
    {
       // Normal code for the music plate is still here.
    }
    else			      // This can only be done once per map unless DMP0_OVERRIDE is set to 0 by a DMP of pal 2. 
      ife DMP0_OVERRIDE 0             // The switch will only start it once.
        ifg sector[].lotag 8          // A door or elevator sector can trigger this when activated with an ACTIVATOR.
        {			      // This needs to be here so the other touch plates don't bother this type / block of code.
          checkactivatormotion 297    // This sets RETURN to 1.
          ife RETURN 1
          {  
            setvar DMP0_OVERRIDE 1    // Enables a secondary set of music plates to be touch triggered. 
            starttrackslot EPISODE_NUMBER LEVEL_TRACK
            quote 147
          }
        }
enda


I figured it out. Even if another track is playing from a DMP, this will play the correct track. I only want this to happen once in a map. The track will not start again even if the switch is flipped back to on. The Global Boolean Variable DMP0_OVERRIDE was originally to override the DMP as a touch plate while the Boss 2 music is playing. A DMP with a palette of 2 will set the variable to 0 again and allow the other DMPs to work normally. The DMP0_OVERRIDE is also used to enable for a secondary set of DMPs of a palette of 8 to be enabled.

Here's something that I'm still wondering. What is RETURN? Is it a peractor or global? I'm just using my DMP0_OVERRIDE variable because I know what it is. The code that I have does allow for the switch triggered track to be stopped but only activated again when the switch is turned off AND THEN back on. It seems like the game knows what the switch is doing and not just blindly activating. There is an "ON" and "OFF" position. Since RETURN only seems to effect one sprite I think it may be a peractor variable but I'm still not completely sure.

Another thing I'm wondering is how do you make "297" something that is a variable set by a LoTag and not just a predefined constant. I've looked for something like getactivator or activatortag and I'm not finding anything.
0

User is offline   HELLMOUSE 

#17

Here is the DMP so far. Valid palettes are 0, 2 (All Red), and 8 (All Green).
I Don't think there is anything else that I want to do with this other than give it the ability to have assigned ACTIVATOR LoTags via the map.
Thanks for the help.

// IN USER.CON
definequote 147	      ^12MUSIC CHANGE DETECTED - DETAILS: F5

// IN GAME.CON
// **** DANUKEM MUSICPLATE (DMP) ****

gamevar LEVEL_TRACK 0 2    // every actor of this type has a copy
gamevar EPISODE_NUMBER 0 2
gamevar MUSIC_E 0 0        // PRIME
gamevar MUSIC_L 0 0        // PRIME
gamevar DMP0_OVERRIDE 0 0  // Used for music tracks to only start once when boss 2 sees Duke
			   // or when a track is triggered by a switch and the secondary tracks play.
state MUSIC_PLAY
  starttrackslot EPISODE_NUMBER LEVEL_TRACK    // HITAG = episode/group, LOTAG = level/track
  quote 147
ends

state MUSIC_SELECT
  getuserdef[].music_episode MUSIC_E 
  getuserdef[].music_level MUSIC_L  
  ife MUSIC_E EPISODE_NUMBER    
    ife MUSIC_L LEVEL_TRACK  // This is an AND.
      nullop 		     // Both must be true for the DMP to do nothing.   
  else 		             // If either one is false then else which will play the selected track.
    state MUSIC_PLAY
ends 
        
eventloadactor DANMUSICPLATE
  geta[].lotag LEVEL_TRACK    // when selecting tracks for the sprite - start at 0 for level / in array spot
  geta[].hitag EPISODE_NUMBER // when selecting tracks for the sprite - start at 0 for episode / group 
  seta[].lotag 0
  seta[].hitag 0
  cstat 32768
enda

// DMP0_OVERRIDE must be set to 1 either by a boss or switch triggered DMP.
// DMP0_OVERRIDE is global variable.  If DMP0_OVERRIDE is 1 then music does not change unless 
// a DMP of pal 2 or 8 is walked on.  If sprite pal is 2 then set DMP0... to 0 and then return 
// to normal behavior (pal 0 and cancel pal 8)
// If a DMP pal 2 is the first one walked on then DMP still works same way with pal 0 because DMP0... is 0 
// Pal 8 is for a secondary set of music tracks in a map.

actor DANMUSICPLATE	   		   
  ife player[].cursectnum sprite[].sectnum  
  {
    ifspritepal 0 { ife DMP0_OVERRIDE 0  state MUSIC_SELECT }
    else
      ifspritepal 2 { setvar DMP0_OVERRIDE 0  state MUSIC_SELECT }
    else
      ifspritepal 8         // Secondary set of music plates.
        ife DMP0_OVERRIDE 1
          state MUSIC_SELECT      
  }
  else		            // This can only be done once per map unless DMP0_OVERRIDE is set to 0 by a DMP of pal 2. 
    ife DMP0_OVERRIDE 0     // The switch will only start it once.
      ifg sector[].lotag 8  // A door or elevator sector can trigger this when activated with an ACTIVATOR.
      {			      
        checkactivatormotion 297    
        ife RETURN 1 { setvar DMP0_OVERRIDE 1  state MUSIC_PLAY }
      }              
        // DMP0_OVERRIDE 1 Enables a secondary set of music plates (pal 8) to be touch triggered. 
enda

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic


All copyrights and trademarks not owned by Voidpoint, LLC are the sole property of their respective owners. Play Ion Fury! ;) © Voidpoint, LLC

Enter your sign in name and password


Sign in options