Staredit Network

Staredit Network -> SCMDraft -> SCMDraft 2 & TrigEdit
Report, edit, etc...Posted by toxik on 2006-08-07 at 00:25:35
Hello.

I've been making zero-clutter maps and stuff for quite the time, but I didn't know SCMDraft 2 was existing (I used my own homebrewed CHK/Hex editor)

It came to my attention while making another defense, that text-based triggering would solve a lot of my problems as far as effort is concerned.

While looking at how to map protection works (anyone know? I'd really want to know...) I saw links to SCMDraft 2 and SCXE (what I used to use) - and of course, I went all o_O over text-based trigger support.

However, not to be rude, the scripting wasn't at all what I expected, it was inconvenient because the command and condition names were a bit too long, and the AI script names were shortened down, yet not telling me what the script did.

Seeing as I believe in Free Software, I opened my SCMDraft folder up, looked inside of plugins/ and opened TrigEdit with notepad. The signature was a .exe one, so I tried to copy it to be executed as a .exe would be. It appears to me that there is an icon in the .exe's resource header, and it is displayed, but I can't start it, so here's the real question:

How do I make addons for SCMDraft?

ADDITION:
Oh I forgot,

My intent was to create a better script language, something like this:

QUOTE
trig for p1, p4
    conds {
        cplayer has > 6 men;
        p5 suffered = 5 men;
    }
    actions {
        kill all any for p2;
    }
(had to quote for colors)
(red = optional for readability)


Trigger
Description:
Sample trigger
Players:
¤ Player 1
¤ Player 2
Conditions:
¤ Current Player commands at most 5 men
¤ Player 5 has suffered 5 deaths of men
Actions:
¤ Kill all Any unit for Player 2


Now you're thinking "What a crap idea" - right?
I think not. It's logical, very logical, and it will evaluate the whole code before actually processing (compiling) it, so constructs like while, if and for are possible, and to chain them, and a pre-compile type of variable will be available too.

Say you want 16 triggers that kill one unit each (game) second, for each player in a cycle, you'd do this:
CODE
for ($i = 1 to 16) {
   trig for p[$i % 8] {
       conds { elapsed time = $i; }
       actions { kill 1 men for p[$i % 8]; }
   }
}

Or something alike, I see before me how this processing would go:
1. Analyze code, unroll all for loops (I use gentoo) - expand all [] statements (pre-evaluation.. evaluates the code before other), recursively.
2. Compile the triggers into 2400 byte long sections
3. Store the array of sections into a big array continious memory segment. (just how the TRIG section looks)

Oh and % is the modular operator, go google if you're confused. It basically makes sure you don't get p9 or above.

For those of you with C-style languages, you can clearly see the imitation.

And of course, location statements will have drop-downs with locations, AI script statements will have drop downs for that, and autocompletion will be available.
Oh and CallTips will be possible.
I'm thinking of making it possible to reuse code - that is, you define a virtual trigger that you can 'bake' into other triggers, but only the action part then... Need to think more about that.
Report, edit, etc...Posted by Cole on 2006-08-07 at 01:12:33
QUOTE
While looking at how to map protection works (anyone know? I'd really want to know...

Map Protection is finding flaws in how Staredit reads the CHK vs how Starcraft reads the CHK.

Anyway as you figured out in the other topic they are C++. You will need a compiler and resource editor(or if you can hand edit resources).

While I don't have it opened right infront of me at the moment, I believe Scmdraft 2 provides a pointer to a buffer that contains the TRIG section. You are then free to read this data. I'm not sure how you write back the data, my guess is returning a pointer to a buffer or deleting the TRIG buffer and creating it again to the correct size. If I had a decent resource editor I would definently create a Scmdraft 2 plugin.
Report, edit, etc...Posted by toxik on 2006-08-07 at 04:13:45
QUOTE(Min @ Aug 7 2006, 07:12 AM)
Map Protection is finding flaws in how Staredit reads the CHK vs how Starcraft reads the CHK.

Anyway as you figured out in the other topic they are C++. You will need a compiler and resource editor(or if you can hand edit resources).

While I don't have it opened right infront of me at the moment, I believe Scmdraft 2 provides a pointer to a buffer that contains the TRIG section. You are then free to read this data. I'm not sure how you write back the data, my guess is returning a pointer to a buffer or deleting the TRIG buffer and creating it again to the correct size. If I had a decent resource editor I would definently create a Scmdraft 2 plugin.
[right][snapback]541275[/snapback][/right]

Yes, I'm thinking maybe a plugin -- the problem is that I'm not too good with C++ (just yet).
I was thinking I'd make a stand-alone application to make it more full-fledged, so to speak.
The problem then becomes what language, since I don't know C/C++/Java that well (besides, I don't think Java would cut it) - Python and the wxPython module can create pretty (very) good editors, so I'd probably create it in Python - but then comes the next problem:
How to open .mpq files in Python? o_O
I'd probably be able to implement something if it isn't already done - if I had the specs, that is.
Report, edit, etc...Posted by Cole on 2006-08-07 at 10:30:40
The MPQ specs arn't anything that easy. Files are split into sectors, you gotta understand hash tables, block tables, both btw are encrypted. Many compression and decompression formats are used aswell. So if lets say python dosn't have an API for decompressing a certain file, you will have to write that in by hand.

I'd suggest just using an already made C++ or Visual Basic api for opening and writing to MPQ archives.

However try and learn C++, it gets easier once you get the hang of it. My current project has been my most involving C++ project. Teaching me the concept & many uses of pointers, how to work with strings in C++, and understanding unmanaged to managed code transitions.
Report, edit, etc...Posted by Carlsagan43 on 2006-08-07 at 10:49:56
Trigger Duplicator by MindArchon does pretty much exaclty what you want, but in a seperate program. Its fairly easy to use, but you pretty much have to create the base trigger beforehand, rather than writing it in his program. (it is possible, but the syntax isnt perfect for doing it there. I though about adding in some trigger duplication functionality into my program, but not at the moment. I think it would be easy to implement such a system, and not that hard for some one to write in a tiny edit to the system. I am considering making it opensource, since editing it is very easy, and I have done all the hard stuff for you.
Report, edit, etc...Posted by toxik on 2006-08-07 at 15:48:35
QUOTE(Min @ Aug 7 2006, 04:30 PM)
The MPQ specs arn't anything that easy. Files are split into sectors, you gotta understand hash tables, block tables, both btw are encrypted. Many compression and decompression formats are used aswell. So if lets say python dosn't have an API for decompressing a certain file, you will have to write that in by hand.

I'd suggest just using an already made C++ or Visual Basic api for opening and writing to MPQ archives.

However try and learn C++, it gets easier once you get the hang of it. My current project has been my most involving C++ project. Teaching me the concept & many uses of pointers, how to work with strings in C++, and understanding unmanaged to managed code transitions.
[right][snapback]541422[/snapback][/right]

I understand strings, hash tables and such, and I know they're encrypted and can coexist by locale ID, and so on, but I got an idea - Python can use C++ code, it's how the main libraries of Python work, by calling other libraries to do the real work to avoid reimplementing things such as sockets. I'd say you should be able to do this for MPQ files too, and that API, to create an OOP interface within Python, using the SWIG thing.
Ever heard of this before?
Report, edit, etc...Posted by evolipel on 2006-08-07 at 16:41:37
...reposting this from another thread, but since you asked how to make a plugin:

QUOTE
DllMain: part of every dll, look on MSDN when it's called.



GetPluginVersion: as the comment says, leave it alone. It makes sure whether the plugin version and the SCMD2 version are compatible.



InitPlugin: called when the plugin is initialized, usually at SCMD2 startup. That messagebox you see when the sample plugin runs on SCMD2 startup is called on from here. Here is also where you set which sections of the map you request SCMD2 to give your plugin. SCMD2 will pretty much only give you TRIG and MBRF, which are the sections you need for a trigger editor. This is due to SCMD2 not being designed to have plugins altering other sections (which could cause crashes). However, if you have a good enough reason, you could convince SI to add support for other sections to be given.

HWND MainWindow: Handle to the SCMD2 main window. Useful to be assigned to a global handle so that you can disable it when your plugin runs.

HINSTANCE MainInstance: Handle to the instance of SCMD2.

AllocRam AllocMem

DeAllocRam DeleteMem

ReAllocRam ResizeMem
: Memory allocation stuff, I don't know when these could be used. I once asked SI about it and he said TrigEdit could use them.

DWORD* RequestedSections: Pointer to an array of 8 (or maybe 9) DWORDs that are names of sections that your plugin requests SCMD2 to give.



PluginGetMenuString: this function will be called several times, for each section that you requested. It asks you to provide the menu item string under the "plugins" menu.

DWORD Section: The current section for which the function is asking the menu item string of.

CHAR* MenuStr: The string to which you copy the menu item string.

WORD StrLen: The maximum length of the menu item string. Check against this value before doing strcpy to MenuStr.



RunPlugin: this is when the user clicks on a menu item of your plugin. So, here is where the "meat" of your plugin goes. The datachunks contain everything you need for a trigger editing plugin.

TEngineData* EngineData: A pointer to the engine data structure (see SCMDPlugin.h).

DWORD CurSection: The section for which the plugin is being run. Either triggers or mission briefings.

CChunkData* Triggers: Pointer to the trigger datachunk (see SCMDPlugin.h). A datachunk is just the size of a section (DWORD) and the section data (array of BYTE).

CChunkData* MissionBriefing: Pointer to the mission briefing (MBRF) datachunk.

CChunkData* SwitchRenaming: Pointer to the switch renaming (SWNM) datachunk.

CChunkData* UnitProperties: Pointer to the unit properties (UPRP) datachunk.

CChunkData* UnitPropUsage: Pointer to the unit properties usage (UPUS) datachunk.



Here are the various structure notes from SCMDPlugin.h:

SCLocation/LocationNode: SCLocation contains the various location data, LocationNode is a node containing SCLocation and whether the data is used or not.



CChunkData: Datachunk structure, see above.



TEngineData: Engine data structure:

MapLocations: Always 256 of these, regardless of whether the map is SC or BW. (MRGN)

WavStringIndexii: Always 512 of these (map .wav string numbers). (WAV )

ActionLog: Null, see below.

ActionLogLevel: SCMD2 Output log data... SI never got around to giving the format to this.

DataInterface: Null, "until virtual class is implemented." Interpret this however you want.

CurSelLocation: Having the currently selected location display on the minimap of SCMD2 (feature that's not implemented yet).

UnitCustomNames: Don't use; use UnitNames instead (see below). String numbers: "0" indicates none, everything else is off by one (1-based). 228 entries.

ForceNames: String Numbers: "0" indicates none, everything else is off by one (1-based). 4 entries.

UnitNames: "char*[228] with non identical unit names."



TPluginInfo: Have no idea where this is used. It doesn't seem to be used anywhere else in the plugin, but TrigEdit might use it (or might have used it) for some odd reason.



UnitProp: Unit properties data chunk member. (UPRP)


Please note that I heard SI was considering to remove the plugins interface due to nobody actually bothering to make plugins, so you might wanna talk to him.

Edit: ...as for protection, it does a lot of stuff to the .chk that causes it to be corrupt to StarEdit/SF/SCMD2, but still be able to be read by SC. From a thread at BlizzForums (made a few changes from new info from DK, actually LW, and Min):

QUOTE
SC reads the last instance of each section, and the last "good" instance of STR, TRIG, and MBRF. "Good" means non-null in the case of STR (i.e. the section length isn't "0") and have at least one owned trigger in the case of TRIG/MBRF. Technically, it reads every instance of each section, but the last ones are the ones where data is "left alone", since there are no more duplicate sections to overwrite it.

This distinction is important in "dimensioned" sections (i.e. sections that have been sized via DIM): if the first instance of, say, MTXM, in a map that's 128x128 (full normal section length for MTXM: 32768) contains only the first 16384 bytes as "garbage" (what Uberation does sometimes) and the rest are correct, then the second duplicate whose section length is 16384 bytes and contains the "right" data overwrites those first 16384 bytes in the static array SC already created (SC doesn't resize the dimensioned arrays like it does with section-length dependent ones: DD2, UNIT, etc).

SC first reads the .chk in the map selection screen, where it looks for DIM, STR, SPRP, MTXM, ERA, FORC, SIDE and maybe a few other sections. If it doesn't find those, or if VCOD, VER, or (I think) OWNR aren't correct, it says that the scenario is invalid, or if the VER is different, then it says it's obsolete or something. Later on, if your map has those sections correct, but has a missing or corrupt, say, THG2, then it will crap out on you (the time of which depends on which section is missing or corrupt). Obviously, different game types load different sections, so SC will load a map fine without TRIG or MBRF or sections like that if the game type is "melee". The ones that aren't used ever are UPUS, DD2, IOWN, ISOM, TILE, WAV, IVER (I think), IVE2 (I think), and the upgrade sections not relating to your version (i.e. if the map is set as BW, SC will ignore upgrade sections like UPGS, TECS, etc... if the map is "hybrid", SC will ignore those "old" upgrade sections too... and if the map is "SC", then it will ignore the BW upgrade sections like PUPx, TECx, etc.)

Edit: A section can be "corrupt" if it's supposed to be a fixed length (i.e. 12 for OWNR), but deviates from that length (I think that the length being "more" works, but "less" doesn't; I forgot since I tested this close to a year ago). I think if stuff like UNIT isn't divisible by the length of a single UNIT structure, it's also "corrupt"... I don't know for sure about this, you might want to test it.

So, "static" sections (upgrade sections, things like OWNR, SPRP, FORC, etc.; their size doesn't change dynamically) are read correctly if they're at least the size they're supposed to be (exactly the size?). "Dynamic" sections I think work if they are divisible by the length of their single respective structures, though probably they'll work if they're any size. I think dimensioned sections work in any way, as long as they're present.

Basically, you might want to test the above 2 paragraphs for validity since I forgot how exactly it works and the .chk specs I talked about are on a HD I can't access right now.

...and STR works as long as its section length isn't "0" (yes, if it's one, it will give you garbage data, but it's read in SC anyway). STR also doesn't have to have exactly 1024 strings.
Report, edit, etc...Posted by toxik on 2006-08-07 at 17:19:21
QUOTE(evolipel @ Aug 7 2006, 10:41 PM)

...reposting this from another thread, but since you asked how to make a plugin:
Please note that I heard SI was considering to remove the plugins interface due to nobody actually bothering to make plugins, so you might wanna talk to him.

Edit: ...as for protection, it does a lot of stuff to the .chk that causes it to be corrupt to StarEdit/SF/SCMD2, but still be able to be read by SC. From a thread at BlizzForums (made a few changes from new info from DK, actually LW, and Min):
[right][snapback]541741[/snapback][/right]

Great answer. Thanks a bunch, will try this - I guess SE/SCXE/SCMD will fail at loading "protected"/half-corrupt maps because they find the "DIM " and then say the MTXM is too small or too big, error out out to prevent mysterious bugs. I guess it'd be rather easy to make a map editor that looks for a good section and uses the last instead, but then again - we don't want that, do we (plaugerism... *shudder*)

Thanks again.
Report, edit, etc...Posted by Cole on 2006-08-07 at 20:12:29
QUOTE
SC first reads the .chk in the map selection screen, where it looks for DIM, STR, SPRP, MTXM, ERA, FORC, SIDE and maybe a few other sections. If it doesn't find those, or if VCOD, VER, or (I think) OWNR aren't correct, it says that the scenario is invalid, or if the VER is different, then it says it's obsolete or something.

You forgot TYPE.
TYPE:
Defines the type of scenario. If the last TYPE section has a bad length it will default to an error "This scenario is to be used with the Starcraft Expansion Set". If the first TYPE section has a bad length it will call the scenario corrupt, even if the second TYPE is correct. Also the 4 chars in the TYPE section can be anything as far as I can tell and it will load in Starcraft.

That should be right anyway.


Edit:
I'd like to note that Starcraft does read the TRIG section when you click on the map. The first comparison is making sure the actual number of bytes in the Trig section is equal to the number of bytes listed. They do not have to be a multiple of 2400 when you click on the map. I'll start doing checks for map load next on the trig section

QUOTE
Great answer. Thanks a bunch, will try this - I guess SE/SCXE/SCMD will fail at loading "protected"/half-corrupt maps because they find the "DIM " and then say the MTXM is too small or too big, error out out to prevent mysterious bugs. I guess it'd be rather easy to make a map editor that looks for a good section and uses the last instead, but then again - we don't want that, do we (plaugerism... *shudder*)

Scmdraft 2 can read almost any unprotected map, however it will refuse to load if it detects a protected map. SI and DW are the only people whos versions are enabled to open protected maps.
Report, edit, etc...Posted by evolipel on 2006-08-08 at 02:43:48
QUOTE(Min @ Aug 7 2006, 07:12 PM)
You forgot TYPE.
TYPE:
Defines the type of scenario. If the last TYPE section has a bad length it will default to an error "This scenario is to be used with the Starcraft Expansion Set". If the first TYPE section has a bad length it will call the scenario corrupt, even if the second TYPE is correct. Also the 4 chars in the TYPE section can be anything as far as I can tell and it will load in Starcraft.

That should be right anyway.
Edit:
I'd like to note that Starcraft does read the TRIG section when you click on the map. The first comparison is making sure the actual number of bytes in the Trig section is equal to the number of bytes listed. They do not have to be a multiple of 2400 when you click on the map. I'll start doing checks for map load next on the trig section
Scmdraft 2 can read almost any unprotected map, however it will refuse to load if it detects a protected map. SI and DW are the only people whos versions are enabled to open protected maps.
[right][snapback]541871[/snapback][/right]

About the type thing:
It probably allocates memory for the string on the first pass, thus explaining the behavior.

About the trigger thing: what do you mean when you say it compares the "actual number of bytes in the Trig section [to] the number of bytes listed"? What "bytes listed"? Second, how do you know it does the comparison at all? It most likely just checks that the section is there, since there's no point to compare anything.

I highly doubt the "dynamic" sections have to be a multiple of anything -- the code is just probably "whatever < sectionlength / 2400 or 36 or w/e each structure size is", which works fine.

...and SI told me he hasn't even updated SCMD2 internally, so it can't open the (relatively) recent protection stuff.
Report, edit, etc...Posted by toxik on 2006-08-08 at 05:00:54
QUOTE(Min @ Aug 8 2006, 02:12 AM)
You forgot TYPE.
TYPE:
Defines the type of scenario. If the last TYPE section has a bad length it will default to an error "This scenario is to be used with the Starcraft Expansion Set". If the first TYPE section has a bad length it will call the scenario corrupt, even if the second TYPE is correct. Also the 4 chars in the TYPE section can be anything as far as I can tell and it will load in Starcraft.

That should be right anyway.
Edit:
I'd like to note that Starcraft does read the TRIG section when you click on the map. The first comparison is making sure the actual number of bytes in the Trig section is equal to the number of bytes listed. They do not have to be a multiple of 2400 when you click on the map. I'll start doing checks for map load next on the trig section
Scmdraft 2 can read almost any unprotected map, however it will refuse to load if it detects a protected map. SI and DW are the only people whos versions are enabled to open protected maps.
[right][snapback]541871[/snapback][/right]

About the protected maps; you can probably patch SCMD to read the maps anyway - unless they used some #ifdef construct during compile, so that the actual code never got in the binary distributed.
By the way, just for the sake of science, I made a python program that protects/unprotects maps by assigning a special section an MD5 hashed password :-)
And I tried unprotecting other maps, seems to me that they use another idea (easily "uncorruptable") - making sections with their length field set to something really high at the end of the file, seeing as StarCraft won't try to load all sections but only the ones it needs as opposed to SE which will try to load all sections.
Report, edit, etc...Posted by Cole on 2006-08-08 at 09:26:30


QUOTE
About the trigger thing: what do you mean when you say it compares the "actual number of bytes in the Trig section [to] the number of bytes listed"? What "bytes listed"? Second, how do you know it does the comparison at all? It most likely just checks that the section is there, since there's no point to compare anything.

A TRIG section that had 7200 bytes before the next section started. Map is fine.
I changed the section length then to 14400, map was corrupt.
I then changed it back to 7200, map was fine.
I changed it to 7400 and added 200 bytes before the next section started. It wasn't corrupt.

Note: This isn't actually loading the map, only in the menu system.

QUOTE
About the protected maps; you can probably patch SCMD to read the maps anyway

Yes.

QUOTE
It probably allocates memory for the string on the first pass, thus explaining the behavior.

I'll keep running tests later.
Report, edit, etc...Posted by evolipel on 2006-08-08 at 12:31:38
QUOTE(Min @ Aug 8 2006, 08:26 AM)
A TRIG section that had 7200 bytes before the next section started. Map is fine.
I changed the section length then to 14400, map was corrupt.
I then changed it back to 7200, map was fine.
I changed it to 7400 and added 200 bytes before the next section started. It wasn't corrupt.

Note: This isn't actually loading the map, only in the menu system.
Yes.
I'll keep running tests later.
[right][snapback]542165[/snapback][/right]

Umm... If the section length is said to be something other than the section's true size, the loop fails, and most likely (because of garbage data; depends on how lucky you are), it probably won't get to read any section afterwards. That's the whole reason they have a section length: how else are you gonna find it out?

Thus, it most likely checks for if TRIG is there or not.
Next Page (1)