ID:1000864
 
Keywords: dm, file, movement, switch
(See the best response by Magicsofa.)
How do I change a dm file in game.
As in using one dm and when a quest or battle sequence is in affect it switches to another dm with the same code with other effects.
Like using Movement as an example.
Unchecking the movement dm and then checking the alternate movement dm file.


You cannot do this in game.
However you can have both examples checked and trigger them with a proc/verb.

I wouldn't recommend such things either. There sure is a better way to do it than attempt to change all the behavior.
Best response
What exactly do you mean by "the same code, with other effects?" Do you mean that the code is the same, with different values, or do you mean that one file has additional code? In any case, Fushimi is right - what you must do is find a way to include the distinction between whatever movement systems within your code.

There are many ways to do this (like any programming task) and some are better than others.

One thing you should really try to avoid is copying large blocks of code just so you can change values. At first it can be difficult, but you will get better at it with practice. Here's an example:

Say we want the player to be able to shoot projectiles, which are different depending on which wand they are wielding. One way to do it is write a verb using separate blocks of code for each wand type:

obj
var
//could be speed, damage, and range
proc
Go(direction)
// do projectile-y stuff here
Earth
//...set values for speed/damage/range here
Fire
Water
Air

Wand
EarthWand
FireWand
WaterWand
AirWand

mob
var/obj/Wand/mywand

verb/shoot()
if(mywand.name == "FireWand")
var/obj/Fire/O = new()
O.loc = loc
O.Go(dir)
else if(mywand.name == "EarthWand")
var/obj/Earth/O = new()
O.loc = loc
O.Go(dir)
else if(mywand.name == "WaterWand")
var/obj/Water/O = new()
O.loc = loc
O.Go(dir)
else if(mywand.name == "AirWand")
var/obj/Air/O = new()
O.loc = location
O.Go(dir)


Here's the problem: changing something for all four projectiles means you need to make the change four times, and adding new ones will require copying and pasting a whole new block of code. This a very simple shoot() verb, more complexity would mean it's even more of a pain to make changes.

Instead, it's possible to use just one proc that will figure out which kind of projectile to spawn:


obj
var
//could be speed, damage, and range
proc
Go(direction)
// do projectile-y stuff here
Earth
//...set values for speed/damage/range here
Fire
Water
Air

Wand
var/projectile_type
EarthWand
projectile_type = "Earth"
FireWand
projectile_type = "Fire" //etc.
WaterWand
AirWand

mob
var/obj/Wand/mywand

verb/shoot()
var/wandtype = text2path("/obj/[mywand.projectile_type]")
var/obj/O = new type(wandtype)
O.loc = loc
O.Go(dir)


With this structure, if I wanted to play a sound whenever a projectile is fired, all I'd have to do is add one line to the shoot() verb. And adding new projectiles is as easy as specifying their name and values for their speed, damage, and whatever else.

I'd have to see some of your code to figure out what you are trying to do. As I said before, there's a ton of different ways to do things in programming. You might need to write two separate procedures, if the movement systems are different enough from each other. On the other hand if your movement systems have a lot of similar statements, it shouldn't be too hard to condense them into one proc.

P.S. I hope I'm not being a bone-head and making mistakes in my example...if I am -please- correct me!
I have been curious about something that's somewhat related to this topic.

Would it be possible at all to make a verb that takes a user's DM code, text input as an argument, and uses new() along with text2path() to somehow "inject" whatever code the user inputs into the currently running program?

Please let me know if any such loophole does in fact exist, to allow a running program to "digest" DM code that was not originally part of its source, and run it live without a need to recompile. If it does, it would be so much easier to use that, than to have to write up an entire self-interpreter in the DM language, for the DM language.

The goal here is to be able to make a program that can execute user input DM code directly. In a sense, this would make it "self-aware" of its own language, so that's actually kind of spooky.

Lately I have been thinking about the idea of making a very cool game that can actually teach the players how to program in DM, but I realize that this would be the main obstacle. I hope you can understand what I'm getting at here.

I don't want to derail this topic. I was just reminded of this by what the OP was originally asking, and I decided to just ask here since this is a similar issue.
In response to Multiverse7
I highly doubt that's possible as every .dm file and it's contents are written to the DMB and compile time you can't change them and you can run something that doesn't exist, you could however make a parser that holds every dm proc and allow the user to run a verb to run a proc correct me if I'm wrong on that one... If that was the case the parser would be just as complex as BYOND's inner workings at the moment...
I figured that was probably the case.

Although, how do you explain the fact that Dream Seeker seems to be quite aware of your running program's actual procs and object paths whenever it spits out a runtime error? Surely Dream Seeker has no special power to decompile your whole project. That would be a major security risk, so what exactly is going on there, and why can't this seeming code awareness be utilized by the program itself?
I think you mean Dream Daemon.

And I'm not sure about that that'll be a question for Lummox JR or Tom, or even perhaps someone who knows a lot about these programs.
the compiled dmb stores proc names, object paths, variables and line numbers, in debug mode, just to help people debug.

Other than that, they have to be stored so the game can access things correctly. but the contents of the procedures are stored as binary, so, it'd be pretty hard to decompile, without knowing how the programs work internally.
In response to Multiverse7
Multiverse7 wrote:
I figured that was probably the case.

Although, how do you explain the fact that Dream Seeker seems to be quite aware of your running program's actual procs and object paths whenever it spits out a runtime error? Surely Dream Seeker has no special power to decompile your whole project. That would be a major security risk, so what exactly is going on there, and why can't this seeming code awareness be utilized by the program itself?

Well, DreamSeeker and DreamDaemon (the engine) needs a complete understanding of your DMB to run it, so ... while "de-compile" isn't really the correct word, it definitely needs to interpret the DMB, which contains encoded string data about object names, procedure names etc.

Anywho, to actually answer your (and OP's, kinda) question, BYOND doesn't stably and officially support a means of run-time interpretation of DM. It does contain an unsupported and broken eval() procedure though, that uses the engine that DreamSeeker uses to interpret DM script on the client side. I can't quite recall the precise nature of the break, but I think it has fundamental issues resolving objects in a bunch of contexts.

For OP, your best solution isn't actually just to swap out the DM files per-say (although, you're onto the right idea). You want to keep the proc names that same ideally, so stuff "just works" in the rest of your code, but you want to put the code for each file into some kind of sub-objects, that can be found / attached to the place you want to associate them. Then your current movement code just goes "Where's the actual code I need to call? Ah, it's here!" and calls the area specific stuff.

Magicsofa's example (which in my mind, is probably the better answer) describes how you might do that in code examples. For reference, we like to call this encapsulation, and procedure overriding.
If you're trying to completely change something about the game, or add in like a 'mini game', you COULD compile multiple dmbs and use link() with startup() and Topic()(see Export()) to interact between the two.
Thanks for pointing out eval()! I think that's a leap in the right direction. I made a request for it.

Yeah, I was actually thinking about interlinking 2 running programs, and having one run a compile command on the other, but it seems like it could be pretty complicated. I'm not sure exactly what you are suggesting with all of those procs, but I don't think it could make it any easier if you have one program trying to interpret the other.
In response to Multiverse7
You could make two worlds, starting up one when you need via startup(), then sending the player to it via link(). After which, you could Export() needed information to the main game, then use Topic() to make sure you do what you need with the information sent back.
So, how is Topic() supposed to make use of the DM code it was sent by Export()? This may be of use to the OP, but it's not really what I was asking.
In response to Multiverse7
I was assuming you were talking to me on the second half of your post.