Tell Lunaran I will have his man-babies if...
-
- Posts: 179
- Joined: Tue Nov 16, 1999 8:00 am
Tell Lunaran I will have his man-babies if...
...he shares the Python script he used for mirroring Q4CTF bases.
(Large, healthy man-babies.)
(Large, healthy man-babies.)
-
- Posts: 56
- Joined: Mon Nov 07, 2005 2:12 pm
-
- Posts: 56
- Joined: Mon Nov 07, 2005 2:12 pm
-
- Posts: 284
- Joined: Thu Feb 16, 2006 3:48 pm
-
- Posts: 56
- Joined: Mon Nov 07, 2005 2:12 pm
-
- Posts: 284
- Joined: Thu Feb 16, 2006 3:48 pm
-
- Posts: 179
- Joined: Tue Nov 16, 1999 8:00 am
While we're sort of on the topic of automation... does anyone have a pointer toward documentation on the Q4 map file format?. The brush descriptions seem pretty straightforward, and I'm sure I could figure out the texturing representation pretty quickly, but I bet there's a lot of little quirks and options as well.
-
- Posts: 179
- Joined: Tue Nov 16, 1999 8:00 am
you can buy me a new brain. one that actually remembers to do things people ask me. =p
http://www.lunaran.com/files/entflip.py
You'll need the python binaries from python.org, wherein you'll also find instructions for running scripts.
I need to specify up front this script as-is will MIRROR the entities in the .map you feed it over the Y axis, ie q4ctf6/7 style. If your map is set up to be rotated 180 you'll have to change it or promise me further manbabies.
/me copies and pastes from his other email
The function is named flipEntities, on line 53. you'll have to modify the path on lines 54 and 109 to point to the right folder.
What it does is load the whole map file and parse through it line by line. If the line starts with the prefix for a certain key it alters it, if not it takes it as is, and stashes the line in memory either way. When it's done it writes all that to a new file. It doesn't check what entity these lines are a part of, because the scope is only one line at a time, so you'll have to only select the stuff you want flipped and export them to a separate .map, or it'll give you a bunch of screwed up func_statics and func_groups and the like. Only point entities work, anything with brushes will explode.
The meat of it is simply multiplying one of the coord values of each ent by -1, thus flipping it over an axis. It doesn't handle offsets so center the map on the origin (or, tinker with the script
). CTF7 was mirrored over the Y axis, so the whole script is y-specific, but it's a simple matter of altering which coordinate it inverts to change it to x (for a 180 rotation, invert both x and y).
It skips commented lines and removes lines that begin with "light_rotation" and "light_origin". These are specific to lights with attached models (of the shift-K variety), and since brushmodels explode the script, it just ignores these lines. As such, don't combine lights with models - this is pretty unreliable anyway, and we have lights deliver color/soundshader by targetting them at func_statics in q4 now anyway, so it's a good time to get everyone into the habit of targetting and not combining.
It'll add '_flipped' to the end of any "name" key to avoid clashes when you reimport (this is part of what breaks func_things - the name changes but the model key still points to the unflipped brushmodel's name), then changes "team" from marine to strogg to handle team spawns and arena ctf items (but not strogg to marine without a manual edit of the script), and changes any "angle" keys it finds to properly mirror those (also for spawns).
It also handles model and light "rotation" keys, and I'll freely admit I don't know why it works.
The rotation key is three vec3's defining new orientations for x, y, and z (so an unrotated object is 1 0 0 0 1 0 0 0 1 - providing non-normalized vectors for these produces some funky skewing/scaling effects), and I found by trial and error in the editor that if you reverse the sign of the second and fifth values it mirrors over the y axis. So, I implemented it like that without bothering to check on the math. I'm an otherwise dumb map designer, so if you can easily explain the math behind it, I'd be rather grateful 
The way it handles "_color" keys is cheap but effective. If the red channel is darker than green, it assumes the light is a green marine light, and makes it orange. It kind of tries to preserve the saturation by checking the intensity of the blue channel, so subtly tinted lights stay subtly tinted, and obscene party-green lights stay obscene. CTF7 has no blue-dominant lights, so I didn't bother to address that those will probably go all wacky purple. Thus, you might want to make this part a little more robust if you're going to turn your designers loose with python.
There's also a chopped-up version that I used when relighting ctf4, which is a 180-rotated map, so there's a little two-axis stuff in there. The separate function at the start of the file is what I came up with to replace the green MP textures with the orange counterparts, but the list is also ctf7 specific so if you guys want to use that it'll have to be expanded quite a bit.
Thus, I could just make all my alterations to the marine base, and let the script flip everything. The workflow was: select all the ents I wanted flipped (lights, spawns, a few mapmodels, items) and export them to one .map, select all the brushwork I wanted mirrored and mirror that manually in radiant (making sure there were no duplicate brushe that overlapped each other in the midground), save that to a second .map, run the ent flipper on one and the texture flipper on the other, then import the two flipped maps into the original. Not perfectly streamlined, but still a ton easier than doing it by hand.
if you have any other questions, tell KFS and he'll remind me that this thread exists.
http://www.lunaran.com/files/entflip.py
You'll need the python binaries from python.org, wherein you'll also find instructions for running scripts.
I need to specify up front this script as-is will MIRROR the entities in the .map you feed it over the Y axis, ie q4ctf6/7 style. If your map is set up to be rotated 180 you'll have to change it or promise me further manbabies.
/me copies and pastes from his other email
The function is named flipEntities, on line 53. you'll have to modify the path on lines 54 and 109 to point to the right folder.
What it does is load the whole map file and parse through it line by line. If the line starts with the prefix for a certain key it alters it, if not it takes it as is, and stashes the line in memory either way. When it's done it writes all that to a new file. It doesn't check what entity these lines are a part of, because the scope is only one line at a time, so you'll have to only select the stuff you want flipped and export them to a separate .map, or it'll give you a bunch of screwed up func_statics and func_groups and the like. Only point entities work, anything with brushes will explode.
The meat of it is simply multiplying one of the coord values of each ent by -1, thus flipping it over an axis. It doesn't handle offsets so center the map on the origin (or, tinker with the script

It skips commented lines and removes lines that begin with "light_rotation" and "light_origin". These are specific to lights with attached models (of the shift-K variety), and since brushmodels explode the script, it just ignores these lines. As such, don't combine lights with models - this is pretty unreliable anyway, and we have lights deliver color/soundshader by targetting them at func_statics in q4 now anyway, so it's a good time to get everyone into the habit of targetting and not combining.
It'll add '_flipped' to the end of any "name" key to avoid clashes when you reimport (this is part of what breaks func_things - the name changes but the model key still points to the unflipped brushmodel's name), then changes "team" from marine to strogg to handle team spawns and arena ctf items (but not strogg to marine without a manual edit of the script), and changes any "angle" keys it finds to properly mirror those (also for spawns).
It also handles model and light "rotation" keys, and I'll freely admit I don't know why it works.


The way it handles "_color" keys is cheap but effective. If the red channel is darker than green, it assumes the light is a green marine light, and makes it orange. It kind of tries to preserve the saturation by checking the intensity of the blue channel, so subtly tinted lights stay subtly tinted, and obscene party-green lights stay obscene. CTF7 has no blue-dominant lights, so I didn't bother to address that those will probably go all wacky purple. Thus, you might want to make this part a little more robust if you're going to turn your designers loose with python.
There's also a chopped-up version that I used when relighting ctf4, which is a 180-rotated map, so there's a little two-axis stuff in there. The separate function at the start of the file is what I came up with to replace the green MP textures with the orange counterparts, but the list is also ctf7 specific so if you guys want to use that it'll have to be expanded quite a bit.
Thus, I could just make all my alterations to the marine base, and let the script flip everything. The workflow was: select all the ents I wanted flipped (lights, spawns, a few mapmodels, items) and export them to one .map, select all the brushwork I wanted mirrored and mirror that manually in radiant (making sure there were no duplicate brushe that overlapped each other in the midground), save that to a second .map, run the ent flipper on one and the texture flipper on the other, then import the two flipped maps into the original. Not perfectly streamlined, but still a ton easier than doing it by hand.

if you have any other questions, tell KFS and he'll remind me that this thread exists.
-
- Posts: 179
- Joined: Tue Nov 16, 1999 8:00 am
-
- Posts: 284
- Joined: Thu Feb 16, 2006 3:48 pm
-
- Posts: 179
- Joined: Tue Nov 16, 1999 8:00 am
I would guess that it actually needs to reverse the sign on the Y component of each vector, so that would be the 2nd 5th and and 8th values. Maybe in the ones you tried, the 8th value was zero?Lunaran wrote:It also handles model and light "rotation" keys, and I'll freely admit I don't know why it works.The rotation key is three vec3's defining new orientations for x, y, and z (so an unrotated object is 1 0 0 0 1 0 0 0 1 - providing non-normalized vectors for these produces some funky skewing/scaling effects), and I found by trial and error in the editor that if you reverse the sign of the second and fifth values it mirrors over the y axis. So, I implemented it like that without bothering to check on the math. I'm an otherwise dumb map designer, so if you can easily explain the math behind it, I'd be rather grateful
Yeah, I guess it would be all three. I never needed to try the 8th value because the lights were all rotated around the z-axis and thus the third vec remained 0 0 1. I guess technically I inverted the light volumes in that case ... I'm surprised they didn't explode into horrible arrays of rendering artifacts.