673f4dfff41cb

673f4e000127a
3 Guests are here.
 

Topic: SS2 Randomizer, Is it even possible? Read 6693 times  

673f4e00018d1JossiRossi

673f4e0001942
Having seen some really impressive randomizer projects done with a variety of different games lately, I was taking a cursory glance at some game resources to see if it was even possible, but frankly am not remotely experienced enough to determine that.

Most other randomizers use an external program to alter files. A start could be simply change door codes. I believe you could generate new log texts with altered codes numbers included (ignoring the audio portion not being reflected), but then you'd need to change the code on the lock itself. Which would require map modifications, can that even be done on a compiled map? Honestly, guessing not? Let alone trying to fancier with randomizing key locations/routes etc. Still, wanted to ask.

673f4e0001b27ZylonBane

673f4e0001b78
Most codes are read in audio logs, so they can't be changed.

Log text also can't be dynamically changed.

673f4e0001ca1JossiRossi

673f4e0001ceb
It wouldn't exactly be dynamic. It'd essentially be a process for creating a.custom mod. So a program would take in the file with the audio log text. Replace the door code with a new random one. Really, the way I'd do it is have a version of the log text file, where codes like 0451 were replaced with *door_code_medsci_01*, then do the substitution and generate an altered version of the log information file. This would not be an in engine process.

The bigger hurdle isn't generating these log files, it would be also generating map information altered to reflect a generated door code. The actual recorded playback of the log could never reflect a random door code, so I'd probably edit the audio with static over where a number is said to avoid the conflict. You would need to look at the text to know the new code

673f4e0001d7cZylonBane

673f4e0001dc4
Or, players could just not open doors that they haven't found the code for yet.

673f4e0001f2cJossiRossi

673f4e0001f83
The door codes are not the end goal of the idea. Check out the Link to the Past Randomizer for an example of what people have been tinkering with in terms of randomizers. You essentially code up a lot of logic of where items can be located and what the different gatekeeping aspects there are. Door Keys, Door Codes, Etc. Then the randomizer creates a possible path that allows a player to collect all the needed gate keeping tools to accomplish everything, but it can take the player through very unconventional paths to do that.

One of the biggest things is just even if it's possible to make these kinds of alterations to the map in the first place in a way that won't require someone to jump through a ton of hoops and export maps manually etc. Ideally, any data that is exposed and modifiable in the map formats could be altered in this way. So a key for Engineering will not be located in it's normal location, and could be just about anywhere (as long as the basic logic of possible paths allows it). And if all items are exposed logically in the map data in some way then you could randomize how they are handled. So, you might need a chemical for research, but they are no longer in the chem storage but could be anywhere, and it'd add a twist to the search and scrounge style of play.

673f4e000204fZylonBane

673f4e0002099
Why didn't you ask that in the first place? Of course that's possible. It was done 15 years ago.

673f4e0002200voodoo47

673f4e000224e
many SS2 quest items are set up in a very specific way that doesn't allow easy swaps, so it's very safe to say that such a randomizer would not be possible.

you could however, set up a low number (2-3) of alternate variations of those objects, and make the game pick one set randomly (so basically, you would have 3 places where a log with a code could be located, and 3 different codes, so 9 possible variations total).

673f4e0002329JossiRossi

673f4e0002374
Ok, I was suspecting that there might have been hardcoded or really restrictive ways for how quest items were handled. It might be fun to try and do some remixing of the items with the method you two linked, but without the ability to really control placement logic to weed out unwinnable states, it feels this is placed in the not possible camp. Thanks for the info though!

673f4e000243cvoodoo47

673f4e0002486
I wouldn't call it restrictive, it's just that the quest setups can be rather complex, so if you want to change them, you need to roll up your sleeves, fire up the editor, and actually change them. if you were hoping for an auto-tool that would modify some hex values on the fly, you are out of luck.

no free lunches with Dark, remember?

673f4e000254dJossiRossi

673f4e0002596
With my limited skill set, I could have handled some editing, but it would have largely been about replacing references that were possible to edit and sliding things around according to a brute force logic set. If I was going to dedicate time to wacky hacking, I was hoping to keep it limited to "build map object lists/alter references" rather than "learn how an archaic editor functions" if that makes sense.

673f4e0002623voodoo47

673f4e000266b
as far as I can tell, that route (alter references etc) is simply not possible here.

673f4e0002c14JossiRossi

673f4e0002c65
So, after banging my head against this for a few days, I actually made some progress! It's never going to be the bigger idea I had, but there might be a use for what I'm working on at the moment. We'll see how far I can get as I explore other aspects, might get something enjoyable out of it. The thing that *might* be good with this method over Zygo's randomizer mod is this only touches dml files, so I think it should be able to be incorporated a little more easily into other projects, vs altering the level data directly?

So, right now I have a script I can run and it'll create randomized dml outputs for corpses in MedSci1. Nothing terribly advanced and it will likely result in unwinnable states, and the corpses don't always align right, and who knows what else. But for a first poke into creating a python script to generate usable game info, I'm rather surprised that it worked at all.

By using info from the hierarchy export in the editor, you can quickly get the positional data of all corpses in a level. I plugged that into a python script that mixes up all the Object IDs and the Object coordinates, and exports them in the dml format to swap all the corpses around in the level.

Here are 3 randomized versions I just exported for example if anyone wanted to give something that WILL break the game logic. The odds of getting the door code corpse as one of the two immediately available corpses is extremely low for instance. However, with some routing logic I'd be able to control for that. Want to see what else I can do before bothering with that aspect though.

To use just take this code and cram it into the bottom of the medsci1 dml file.

Random Medsci1 Corpses 1
Code: [Select]
//Randomized Corpses
+ObjProp 833 "Position"
{
"Location" 37.80, -161.26, -18.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1680 "Position"
{
"Location" 93.17, 79.42, -13.77
"Heading" e005
"Pitch" 0
"Bank" 0
}

+ObjProp 492 "Position"
{
"Location" 43.68, 116.57, -15.25
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 781 "Position"
{
"Location" 77.88, -100.65, -18.77
"Heading" aa6
"Pitch" 0
"Bank" 0
}

+ObjProp 880 "Position"
{
"Location" -22.58, -106.00, -9.88
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 219 "Position"
{
"Location" -14.62, 61.68, -2.67
"Heading" 4000
"Pitch" 0
"Bank" 0
}

+ObjProp 831 "Position"
{
"Location" -78.29, -187.01, -3.96
"Heading" 8f07
"Pitch" 0
"Bank" 0
}

+ObjProp 1177 "Position"
{
"Location" 47.17, -171.49, 3.33
"Heading" e03e
"Pitch" 0
"Bank" 0
}

+ObjProp 1095 "Position"
{
"Location" -48.89, -6.37, -14.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 165 "Position"
{
"Location" -44.51, -78.61, -2.67
"Heading" 17cb
"Pitch" 0
"Bank" 0
}

+ObjProp 1351 "Position"
{
"Location" -48.25, 88.43, -2.79
"Heading" 92d2
"Pitch" 0
"Bank" 0
}

+ObjProp 867 "Position"
{
"Location" 43.24, 26.74, -3.89
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 1428 "Position"
{
"Location" -48.13, 128.36, -3.86
"Heading" f8e3
"Pitch" 0
"Bank" 0
}

+ObjProp 998 "Position"
{
"Location" 0.21, -19.20, -14.77
"Heading" 3ffd
"Pitch" 0
"Bank" 0
}

+ObjProp 931 "Position"
{
"Location" -31.64, 113.44, -3.96
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 702 "Position"
{
"Location" 56.64, -143.63, -18.67
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1182 "Position"
{
"Location" 2.66, -71.45, -3.25
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 507 "Position"
{
"Location" -75.40, 22.79, -3.00,
"Heading" d3b4
"Pitch" 0
"Bank" 0
}

+ObjProp 735 "Position"
{
"Location" -77.10, -72.53, -3.96
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 490 "Position"
{
"Location" -27.69, -14.70, -3.61
"Heading" ef97
"Pitch" 0
"Bank" 0
}

+ObjProp 294 "Position"
{
"Location" 78.36, -23.84, -2.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1153 "Position"
{
"Location" -67.46, -147.73, 4.77
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1584 "Position"
{
"Location" 39.83, -111.82, -3.66
"Heading" e2b4
"Pitch" 0
"Bank" 0
}

+ObjProp 967 "Position"
{
"Location" 45.20, -18.21, -3.73
"Heading" 3949
"Pitch" 0
"Bank" 0
}


Random Medsci1 Corpses 2
Code: [Select]
//Randomized Corpses
+ObjProp 219 "Position"
{
"Location" -75.40, 22.79, -3.00,
"Heading" e03e
"Pitch" 0
"Bank" 0
}

+ObjProp 831 "Position"
{
"Location" -67.46, -147.73, 4.77
"Heading" 92d2
"Pitch" 0
"Bank" 0
}

+ObjProp 1680 "Position"
{
"Location" -31.64, 113.44, -3.96
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 492 "Position"
{
"Location" -48.89, -6.37, -14.79
"Heading" 8f07
"Pitch" 0
"Bank" 0
}

+ObjProp 1584 "Position"
{
"Location" 43.24, 26.74, -3.89
"Heading" 4000
"Pitch" 0
"Bank" 0
}

+ObjProp 165 "Position"
{
"Location" -78.29, -187.01, -3.96
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 294 "Position"
{
"Location" 43.68, 116.57, -15.25
"Heading" aa6
"Pitch" 0
"Bank" 0
}

+ObjProp 1351 "Position"
{
"Location" -22.58, -106.00, -9.88
"Heading" f8e3
"Pitch" 0
"Bank" 0
}

+ObjProp 1428 "Position"
{
"Location" -14.62, 61.68, -2.67
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 931 "Position"
{
"Location" -77.10, -72.53, -3.96
"Heading" e2b4
"Pitch" 0
"Bank" 0
}

+ObjProp 867 "Position"
{
"Location" -48.25, 88.43, -2.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 833 "Position"
{
"Location" -34.38, -54.92, -2.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1362 "Position"
{
"Location" 47.17, -171.49, 3.33
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 1182 "Position"
{
"Location" 37.80, -161.26, -18.79
"Heading" 3949
"Pitch" 0
"Bank" 0
}

+ObjProp 735 "Position"
{
"Location" 0.21, -19.20, -14.77
"Heading" d3b4
"Pitch" 0
"Bank" 0
}

+ObjProp 490 "Position"
{
"Location" 45.20, -18.21, -3.73
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 781 "Position"
{
"Location" 77.88, -100.65, -18.77
"Heading" ef97
"Pitch" 0
"Bank" 0
}

+ObjProp 702 "Position"
{
"Location" 2.66, -71.45, -3.25
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 507 "Position"
{
"Location" 93.17, 79.42, -13.77
"Heading" 3ffd
"Pitch" 0
"Bank" 0
}

+ObjProp 1177 "Position"
{
"Location" -48.13, 128.36, -3.86
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1095 "Position"
{
"Location" -44.51, -78.61, -2.67
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1153 "Position"
{
"Location" 39.83, -111.82, -3.66
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 880 "Position"
{
"Location" -27.69, -14.70, -3.61
"Heading" e005
"Pitch" 0
"Bank" 0
}

+ObjProp 998 "Position"
{
"Location" 56.64, -143.63, -18.67
"Heading" 0
"Pitch" 0
"Bank" 0
}


Random Medsci1 Corpses 3
Code: [Select]
//Randomized Corpses
+ObjProp 931 "Position"
{
"Location" 93.17, 79.42, -13.77
"Heading" f8e3
"Pitch" 0
"Bank" 0
}

+ObjProp 880 "Position"
{
"Location" 0.21, -19.20, -14.77
"Heading" aa6
"Pitch" 0
"Bank" 0
}

+ObjProp 1153 "Position"
{
"Location" -14.62, 61.68, -2.67
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 702 "Position"
{
"Location" 43.24, 26.74, -3.89
"Heading" ef97
"Pitch" 0
"Bank" 0
}

+ObjProp 490 "Position"
{
"Location" -48.25, 88.43, -2.79
"Heading" e005
"Pitch" 0
"Bank" 0
}

+ObjProp 998 "Position"
{
"Location" -34.38, -54.92, -2.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 781 "Position"
{
"Location" 45.20, -18.21, -3.73
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1177 "Position"
{
"Location" 37.80, -161.26, -18.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 833 "Position"
{
"Location" -67.46, -147.73, 4.77
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 735 "Position"
{
"Location" 77.88, -100.65, -18.77
"Heading" e2b4
"Pitch" 0
"Bank" 0
}

+ObjProp 294 "Position"
{
"Location" -48.89, -6.37, -14.79
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 492 "Position"
{
"Location" 78.36, -23.84, -2.79
"Heading" 3949
"Pitch" 0
"Bank" 0
}

+ObjProp 967 "Position"
{
"Location" -44.51, -78.61, -2.67
"Heading" 8f07
"Pitch" 0
"Bank" 0
}

+ObjProp 219 "Position"
{
"Location" -48.13, 128.36, -3.86
"Heading" 92d2
"Pitch" 0
"Bank" 0
}

+ObjProp 1428 "Position"
{
"Location" 47.17, -171.49, 3.33
"Heading" 3ffd
"Pitch" 0
"Bank" 0
}

+ObjProp 507 "Position"
{
"Location" 56.64, -143.63, -18.67
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1182 "Position"
{
"Location" 39.83, -111.82, -3.66
"Heading" d3b4
"Pitch" 0
"Bank" 0
}

+ObjProp 1680 "Position"
{
"Location" 2.66, -71.45, -3.25
"Heading" 17cb
"Pitch" 0
"Bank" 0
}

+ObjProp 831 "Position"
{
"Location" 43.68, 116.57, -15.25
"Heading" 8000
"Pitch" 0
"Bank" 0
}

+ObjProp 165 "Position"
{
"Location" -22.58, -106.00, -9.88
"Heading" c000
"Pitch" 0
"Bank" 0
}

+ObjProp 1351 "Position"
{
"Location" -78.29, -187.01, -3.96
"Heading" 4000
"Pitch" 0
"Bank" 0
}

+ObjProp 1362 "Position"
{
"Location" -77.10, -72.53, -3.96
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1095 "Position"
{
"Location" -75.40, 22.79, -3.00,
"Heading" 0
"Pitch" 0
"Bank" 0
}

+ObjProp 1584 "Position"
{
"Location" -27.69, -14.70, -3.61
"Heading" 0
"Pitch" 0
"Bank" 0
}

673f4e0002d81voodoo47

673f4e0002dd3
so, you are using an external tool to randomly pick a dml from an pre-configured existing set? that's.. different.

but whatever gets the job done, I suppose.

673f4e0002eafJossiRossi

673f4e0002f02
It generates dml data on the fly, when I run a small Python script. Right now it has a harcoded list of all the current corpse locations, it then generates the dml data and gives every corpse a different random location sourced from the list. I can easily enough add new corpse locations too, so corpses can be in a mix of classic and brand new positions if I wanted. So it's not preconfigured really and is very easily extendable.
673f4e000305e
IIRC NewDark has a script language available named squirrel. Might make sense to write the generator in that.

673f4e0003106JossiRossi

673f4e0003157
Squirrel seems interesting I do want to.try and learn more about how it works. For protyping I can probably keep rolling with Python short term while I get used to things. It's very much still learn as.I go.
Acknowledged by: Kolya

673f4e0003368JossiRossi

673f4e00033b5
Did some cleanup today. So the script now pulls info from a modifiable text file, that includes all the data needed to generate the randomized locations. As part of that I also tested adding new locations, and the barest of logic.

Right now I can randomize all the corpse locations, while ensuring that the corpse with the 45100 door code log will always spawn before that door. Ensuring that a player (who somehow doesn't know that code AND is trying out a randomizer for whatever ill advised reason) won't get stuck.

Edit
https://imgur.com/gallery/ymrhhlr check out images here for what I am talking about.

2 versions of that room right before the 45100 door. Sometimes there's 2 corpses in that room, other times none and the log is in a different location in the hallway or where wrench corpse usually is.

That said, definitely kinks I am working out, like poses are supposed to be linked to location, basically copying what the existing pose was of whatever corpse originally was there. But there's issues with that were it seems different corpse models have different offsets when utilizing a pose, like Dead2. 3 models will have 3 different heights using that one pose. Not too worried about it, but it'll be a back burner concern.
« Last Edit: 22. April 2020, 00:28:54 by JossiRossi »

673f4e000356aJossiRossi

673f4e00035b3
I'm hoping this question gets seen, don't want to revive old threads or start a new one for this question, but I've done a lot of searching the past few days with no luck. I saw in the DML limitations thread that you can now create new items instead of only modifying old ones. I can't seem to get this to work. I have been using the Create dml command, but I haven't had any luck, are there any existing examples of placing brand new objects into a .mis?

673f4e0003687voodoo47

673f4e00036d2
the examples in the Docs folder should be enough, but if you need an existing mod, Droid Immortality would be a good start (see gamesys.dml).

673f4e000377fJossiRossi

673f4e00037c8
Thank you, I'll try that out later. I saw the examples in the doc and for the life of me couldn't make any progress on it working

673f4e0003875JossiRossi

673f4e00038be
Thanks again voodoo. Figured out the issue eventually...

Helps to use the version of New Dark that supports the feature trying to be used  O_o

673f4e000399dvoodoo47

673f4e00039f0
well yes, that indeed sounds like a good idea.

add dbmod_log 10 to your cam_ext, and explore dbmod.log when things are going south - if you see syntax errors, unexpected tokens etc, you should focus at the code bits where they are generated. helps a lot.
Acknowledged by: JossiRossi

673f4e0003b16JossiRossi

673f4e0003b60
The dbmog.log tip has helped a lot while doing more testing/feature exploration, thank you voodoo. I spent some time getting the starting area modified some. I want to force a player to realize things have been changed. So the 45100 door lock has now replaced the cryo door with the ghost. And the log will be located anywhere before that door and after the airlock door. Also made the one way doors in those first few rooms two way, so you can go back if you missed something before you leave that area forever through the one way vent.

Also discovered the way to set door codes, so I can actually randomize door codes! I'd need to have the script alter the text log scripts so that the new codes exist somewhere, but it's an actual possibility now, which is pretty fun.
3 Guests are here.
I find you in quite the disarray
Contact SMF 2.0.19 | SMF © 2016, Simple Machines | Terms and Policies
FEEP
673f4e0004707