• Log InLog In
  • Register
Liquid`
Team Liquid Liquipedia
EDT 03:23
CEST 09:23
KST 16:23
  • Home
  • Forum
  • Calendar
  • Streams
  • Liquipedia
  • Features
  • Store
  • EPT
  • TL+
  • StarCraft 2
  • Brood War
  • Smash
  • Heroes
  • Counter-Strike
  • Overwatch
  • Liquibet
  • Fantasy StarCraft
  • TLPD
  • StarCraft 2
  • Brood War
  • Blogs
Forum Sidebar
Events/Features
News
Featured News
[ASL21] Ro24 Preview Pt2: News Flash10[ASL21] Ro24 Preview Pt1: New Chaos0Team Liquid Map Contest #22 - Presented by Monster Energy18ByuL: The Forgotten Master of ZvT30Behind the Blue - Team Liquid History Book20
Community News
Weekly Cups (March 23-29): herO takes triple6Aligulac acquired by REPLAYMAN.com/Stego Research8Weekly Cups (March 16-22): herO doubles, Cure surprises3Blizzard Classic Cup @ BlizzCon 2026 - $100k prize pool51Weekly Cups (March 9-15): herO, Clem, ByuN win4
StarCraft 2
General
Rongyi Cup S3 - Preview & Info Team Liquid Map Contest #22 - Presented by Monster Energy Blizzard Classic Cup @ BlizzCon 2026 - $100k prize pool What mix of new & old maps do you want in the next ladder pool? (SC2) Aligulac acquired by REPLAYMAN.com/Stego Research
Tourneys
RSL Season 4 announced for March-April Sparkling Tuna Cup - Weekly Open Tournament StarCraft Evolution League (SC Evo Biweekly) WardiTV Mondays World University TeamLeague (500$+) | Signups Open
Strategy
Custom Maps
[M] (2) Frigid Storage Publishing has been re-enabled! [Feb 24th 2026]
External Content
The PondCast: SC2 News & Results Mutation # 520 Moving Fees Mutation # 519 Inner Power Mutation # 518 Radiation Zone
Brood War
General
so ive been playing broodwar for a week straight. BSL 22 Map Contest — Submissions OPEN to March 10 Klaucher discontinued / in-game color settings BGH Auto Balance -> http://bghmmr.eu/ Pros React To: JaeDong vs Queen
Tourneys
[Megathread] Daily Proleagues [ASL21] Ro24 Group E [ASL21] Ro24 Group F Azhi's Colosseum - Foreign KCM
Strategy
What's the deal with APM & what's its true value Fighting Spirit mining rates Simple Questions, Simple Answers
Other Games
General Games
Stormgate/Frost Giant Megathread Starcraft Tabletop Miniature Game Nintendo Switch Thread General RTS Discussion Thread Darkest Dungeon
Dota 2
The Story of Wings Gaming Official 'what is Dota anymore' discussion
League of Legends
G2 just beat GenG in First stand
Heroes of the Storm
Simple Questions, Simple Answers Heroes of the Storm 2.0
Hearthstone
Deck construction bug Heroes of StarCraft mini-set
TL Mafia
Mafia Game Mode Feedback/Ideas TL Mafia Community Thread Five o'clock TL Mafia
Community
General
US Politics Mega-thread Russo-Ukrainian War Thread The Chess Thread NASA and the Private Sector Things Aren’t Peaceful in Palestine
Fan Clubs
The IdrA Fan Club
Media & Entertainment
[Req][Books] Good Fantasy/SciFi books [Manga] One Piece Movie Discussion!
Sports
2024 - 2026 Football Thread Formula 1 Discussion Cricket [SPORT] Tokyo Olympics 2021 Thread General nutrition recommendations
World Cup 2022
Tech Support
[G] How to Block Livestream Ads
TL Community
The Automated Ban List
Blogs
Broowar part 2
qwaykee
China Uses Video Games to Sh…
TrAiDoS
Funny Nicknames
LUCKY_NOOB
Iranian anarchists: organize…
XenOsky
FS++
Kraekkling
ASL S21 English Commentary…
namkraft
Electronics
mantequilla
Customize Sidebar...

Website Feedback

Closed Threads



Active: 14937 users

Custom map/ UMS creators wanted

Forum Index > BW General
Post a Reply
Normal
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 01:08:11
April 25 2017 00:30 GMT
#1
+ Show Spoiler +
I'm a programmer (not a pro-gamer) working on a new tool which will drastically expand the capabilities of UMS maps as well as make authoring way easier (no more trigger bullshit). It doesn't use EUD, doesn't require client mods and can't be patched out. The tool is quickly becoming usable and I need someone to help me with testing and feedback. Let me know in this thread if you're interested to help. Experience with SCMDraft 2 and/ or the Blizzard editor as well as (really) basic programming skills are required.


EDIT: Initial version has been released. Check out this post for info - http://www.teamliquid.net/forum/brood-war/521681-custom-map-ums-creators-wanted#19
biryusky
Profile Joined September 2012
70 Posts
April 25 2017 01:57 GMT
#2
if you have source code on on a github repository (either private or public) maybe i can take a look. What language did you write this tool with?
integral
Profile Blog Joined February 2009
United States3156 Posts
April 25 2017 04:24 GMT
#3
I'm curious but skeptical, especially of claims that you can "drastically expand the capabilities of UMS maps". We at staredit.net have pretty well pushed UMS mapping to its limits already. That said, if you can back up your claims, I'll help with both testing and feedback.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-25 13:40:39
April 25 2017 11:33 GMT
#4
On April 25 2017 13:24 integral wrote:
I'm curious but skeptical, especially of claims that you can "drastically expand the capabilities of UMS maps". We at staredit.net have pretty well pushed UMS mapping to its limits already. That said, if you can back up your claims, I'll help with both testing and feedback.


I've created a programming language, IR and a compiler. It takes the source code + a .scx and produces a new .scx. In its essence it's a virtual machine running on triggers. It doesn't offer any new features per se (like EUDs) but you can create much more complicated behaviors and logic than with hand-made triggers as it's a real programming language with variables, expressions, loops, functions, etc.

Here is a simple example I can compile and run right now (image because the forum software messes up the formatting):
[image loading]

And by the way the resources on staredit.net (especially the wiki) have been absolutely essential for creating this, I am so grateful to your community!

On April 25 2017 10:57 biryusky wrote:
if you have source code on on a github repository (either private or public) maybe i can take a look. What language did you write this tool with?


Give me your GitHub username and I'll add you to the repo. The compiler is written in modern C++.

As a sidenote, I will open source everything in the coming weeks (days), as soon as it's in a semi-finished state.
BlueStar
Profile Blog Joined August 2005
Bulgaria1169 Posts
April 25 2017 11:42 GMT
#5
Looking forward to this !!
Please, make poker defense on steroids
Leader of the Bulgarian National SCBW/SC2 team and team pSi.SCBW/SC2
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-26 12:38:23
April 25 2017 22:10 GMT
#6
After some more work today stuff like this works now:

global allowedSwaps = 3;

bring(Player1, AtLeast, 1, TerranMarine, "TestLocation2") => {
if (allowedSwaps == 2) {
print("Sorry, you have no more swaps left.");
return;
}

allowedSwaps--;
kill(TerranMarine, Player1, 1, "TestLocation2");
spawn(ProtossZealot, Player1, 1, "TestLocation");

print("Here is your zealot.");
}

bring(Player1, AtLeast, 1, ProtossZealot, "TestLocation2") => {
if (allowedSwaps == 2) {
print("Sorry, you have no more swaps left.");
return;
}

allowedSwaps--;
kill(ProtossZealot, Player1, 1, "TestLocation2");
spawn(TerranMarine, Player1, 1, "TestLocation");

print("Here is your marine.");
}

fn main() {
spawn(TerranMarine, Player1, 1, "TestLocation");

while (true) {
poll_events();
}
}
biryusky
Profile Joined September 2012
70 Posts
April 25 2017 23:30 GMT
#7
check your pm, ive mailed you my github username
Psyda
Profile Joined April 2017
1 Post
April 26 2017 01:50 GMT
#8
Sounds interesting. I'd like to be apart of this.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-26 01:54:20
April 26 2017 01:52 GMT
#9
Interesting. A lot of that code looks very similar to current triggers. I'm also concerned about how flexible those functions are, I change conditions and actions constantly when I'm making a map. Adding a single condition and action to a particular function seems like it's going to be the same as writing triggers, correct me if I am wrong. A programmatic approach is helpful still, maybe even required for modern maps, so anyone who isn't using something like that will benefit tremendously. I'm currently using a simple string generator, but I suspect with similar results:

[image loading]

One thing I haven't done yet though is write macros to generate the triggers necessary for complex math between two death counts. Multiplication, division, comparison, etc. Currently I'm generating each calculation separately. If you do something like this in your program, I'm sold. This alone is useful enough to make it all worth it.

Another thing I need to do but haven't done yet is figure out how to use death counts as memory for multiple values/variables. Not having any form of memory without death counts sucks and I'm already low on death counts for a lot of maps. I'm not excited trying to think about how to store multiple values in a death count and then extract those values with addition and subtraction. Maybe you're a genius and can do this easily, here's hoping.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-26 02:54:23
April 26 2017 02:36 GMT
#10
The code similarity to current triggers is intentional (to ease the transition for map creators). Don't be mistaken though, this is a full-blown programming language.

I'm very sleepy now (5 am here) so forgive me if I miss some important detail but here's a short explanation of how it works:

- You write your code in a high level language not unlike C++ or JavaScript. It supports local & global variables, arithmetic, complex expressions, function calls with arguments and return value, event callbacks, you name it. This all goes into a handwritten parser which outputs an AST.
- From the AST linearized IR code (basically a list of low level instructions) is generated.
- The IR language has all the instructions you'd expect to be able to implement the higher level one. Stuff like push, pop, call, ret, set, add, sub, etc + integration with the game like spawning/ killing units, checking locations, setting resources. So a piece of code gets translated to something like:

[image loading]

- This list of instructions is fed into the compiler backend which produces a bunch of triggers and creates the new map file. The actual codegen was the hard part of all this but I have it working properly (and pretty efficiently) now.

- For map makers this means calling the .exe with the map and code file which "combines" them into the final map which you can run in the game.

I feel like I'll be able to release something in a few days or a week tops with the progress I'm making. For the future there is a lot of work that can be done on optimizing the AST and IR once I'm done with all the major features.

To answer your questions specifically:

I'm also concerned about how flexible those functions are, I change conditions and actions constantly when I'm making a map


Everything can be changed instantly, recompilation takes milliseconds. You can go from code to testing in the game in 10 seconds. Also there are preprocessor macros (#define for C/ C++ people) and global variables so you can change stuff in a lot of places at once.

Adding a single condition and action to a particular function seems like it's going to be the same as writing triggers, correct me if I am wrong

Well, kind of. With the exception that you can write most stuff once and then reuse it. You can even have multiple code files so you can make a library of common functions for all your maps. Also I'm considering some kind of meta-programming (template) support in the language to make managing a lot of event handlers even less painful.

Multiplication, division, comparison, etc. Currently I'm generating each calculation separately. If you do something like this in your program, I'm sold

Yeah, you can do stuff like ((x + 15) * foo()). You can go crazy with the expressions until you blow the stack.

Another thing I need to do but haven't done yet is figure out how to use death counts as memory for multiple values/variables.

I use the death counts for player 8 as general purpose memory. It would be possible to pack more than one value into a single "register" to save on memory, though I'm not sure if you'd need that many registers (there are ~220 available) if you're not doing the triggers by hand. The compiler is pretty good at figuring out what to throw out when it's not necessary anymore. We'll have to test the tool with a non-trivial map and see what happens and figure it out from there.

I'll be back tomorrow to talk more. Anyone PM me GitHub username if you want access to the work in progress stuff.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-26 03:31:14
April 26 2017 03:18 GMT
#11
Sounds good.

Yeah, you can do stuff like ((x + 15) * foo()). You can go crazy with the expressions until you blow the stack.

Just to be 100% clear, because this is sounding slightly too good to be true, I need the triggers themselves to do the calculating. As in, I need a function that generates the entire subtract/add trees necessary to multiply numbers using triggers. Using complex expressions to generate triggers is nice, but using your program to generate complex expressions *as calculated by triggers* is where the money is.

+ Show Spoiler +

Trigger("All players"){
Conditions:
Deaths("Current Player", "Left Wall Flame Trap", At least, 1024);

Actions:
Set Deaths("Current Player", "Right Wall Missile Trap", Add, 1024);
Set Deaths("Current Player", "Left Wall Flame Trap", Subtract, 1024);
Preserve Trigger();
}

//-----------------------------------------------------------------//
Trigger("All players"){
Conditions:
Deaths("Current Player", "Left Wall Flame Trap", At least, 512);

Actions:
Set Deaths("Current Player", "Right Wall Missile Trap", Add, 512);
Set Deaths("Current Player", "Left Wall Flame Trap", Subtract, 512);
Preserve Trigger();
}


etc. until 0, then take result (right wall missile trap) and subtract it back into left wall flame trap while multiplying or dividing by another value somewhere else, usually hardcoded since you can't exactly have a condition for every possibility without exceeding trigger limit. This is the sort of thing I haven't coded a way to cleanly generate yet, and until I see evidence (as in trigger output) of this function existing in your program I won't believe you've done it either.

I use the death counts for player 8 as general purpose memory. It would be possible to pack more than one value into a single "register" to save on memory, though I'm not sure if you'd need that many registers (there are ~220 available) if you're not doing the triggers by hand. The compiler is pretty good at figuring out what to throw out when it's not necessary anymore. We'll have to test the tool with a non-trivial map and see what happens and figure it out from there.


I'm using almost all already in most of my maps, to the point where I need to start recycling them sometimes where possible. If I had the ability to use more per register I would be able to do some pretty neat stuff with triggers that no one has done before. As an example, I have plans for a primitive AI that would be able to make attack/retreat decisions on the basis of counting non-arbitrary units per non-arbitrary location. I would use ~40 death counts per location, with calculations to extract those values and compare them, if this weren't prohibitively difficult to code.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-26 12:31:29
April 26 2017 12:08 GMT
#12
Just to be 100% clear, because this is sounding slightly too good to be true, I need the triggers themselves to do the calculating. As in, I need a function that generates the entire subtract/add trees necessary to multiply numbers using triggers.


Exactly what I've done. The expressions are emitted as trigger chains and evaluated at runtime inside the game (as in your example). And you can do much more than just multiply two numbers. Here is the result of compiling one of my examples from the previous posts opened in SCMDraft (you don't actually need a map editor for writing the triggers, the compiler reads/ writes to the map file directly).

[image loading]

I would use ~40 death counts per location, with calculations to extract those values and compare them, if this weren't prohibitively difficult to code.


This would be quite possible to code, especially after I implement arrays which is more or less next on my list.

I'm using almost all already in most of my maps, to the point where I need to start recycling them sometimes where possible.

That's possibly because you use a register (death count) only for one thing. The language I'm making is block scoped and reuses "dead" values, so you can do more with less registers. Also temporaries from expression calculations are reused.
2Pacalypse-
Profile Joined October 2006
Croatia9530 Posts
April 26 2017 12:33 GMT
#13
This looks pretty interesting. Good work!

Btw, you can use
[code]some code here[./code]
(without a dot) to post code here in the forum, which preserves formatting.
Moderator"We're a community of geniuses because we've found how to extract 95% of the feeling of doing something amazing without actually doing anything." - Chill
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-26 13:37:05
April 26 2017 13:19 GMT
#14
The expressions are emitted as trigger chains and evaluated at runtime inside the game (as in your example).


k you're a genius, I'm sold

And you can do much more than just multiply two numbers.


keep going I'm close

That's possibly because you use a register (death count) only for one thing. The language I'm making is block scoped and reuses "dead" values, so you can do more with less registers. Also temporaries from expression calculations are reused.


Ok, I was skeptical of you, so you can be skeptical of me! Totally fair. Most are in continual use, actually, and I'm using a lot of the heroes and buildings in the map so I just can't use those. I'm more or less at the limit on everything - ccmu, strings, death counts, locations, switches, death counts, even # of triggers that can run without lag. So yeah I'm definitely at the point where I'd be needing to reuse death counts if I want to add things. What I want to do is probably an edge case though, so probably not where you'll want to focus when you're still in development.

This would be quite possible to code, especially after I implement arrays which is more or less next on my list.

One value per unit type per location and I get ~5 locations without having to reuse stuff, so I haven't even tried to mess with this. Plus I run out of triggers doing a count for every unit type. Until recently I've been pretty sure what I wanted to do is just outside the range of what's possible with the current engine, but if I (we?) can figure out a clever way to store multiple values, I can do some really neat things.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-26 13:55:53
April 26 2017 13:27 GMT
#15
accidental double post. I'll use it to ask some more questions:

Who are you? Where did you come from? (Who the fuck writes a programming language for triggers?) Why are you doing this? What help do you need?
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-26 14:36:36
April 26 2017 14:32 GMT
#16
Who are you?

I'm Alex, I ... mod games I guess. I've participated in many modding communities and started some myself.

Where did you come from?

I used to make UMS maps with the blizzard editor when I was like 10. I think it may have helped me become a programmer. Also I played a lot of competitive SC2 a few years ago, now I'm back to Brood War.

Who the fuck writes a programming language for triggers?

People who should be working for their job instead. Also it just happens I had to write a bunch of code parsers recently so the knowledge is still fresh in my mind. The IR + codegen part is new to me so don't expect LLVM or GCC levels of sophistication, at least to start.

Why are you doing this?

I love modding and I love writing tools so it was a natural consequence. The actual decision to make this came a few days ago after I got annoyed at the limitations of a UMS map I play a lot.

What help do you need?


Testing, feedback and writing documentation. I'll setup avenues for all of this as soon as I decide to release the initial version in a few days.
nlight
Profile Joined October 2011
Bulgaria58 Posts
April 26 2017 16:19 GMT
#17
Some new stuff to show. This code compiles and runs now.

global foo = 15;

fn do_some_stuff() {
return 42;
}

fn main() {
var bar = do_some_stuff();

if (bar == 42) {
set_resource(Player1, Minerals, foo + bar);
}
}
quirinus
Profile Blog Joined May 2007
Croatia2489 Posts
April 26 2017 17:50 GMT
#18
Looks sick. Hopefully, you'll figure out a way to go past the limitations.
All candles lit within him, and there was purity. | First auto-promoted BW LP editor.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 01:08:38
April 26 2017 18:18 GMT
#19
I've decided to release my current version so I can work together with all of you to make it better.

The source code is available at https://github.com/AlexanderDzhoganov/langums under the MIT license. Compileable with any modern C++ compiler, doesn't have any external dependencies.

You can get the whole repo in a .zip file from https://github.com/AlexanderDzhoganov/langums/archive/master.zip

If you don't care about the source code and want just the tool you can get the latest .exe from https://github.com/AlexanderDzhoganov/langums/blob/master/langums.exe?raw=true

Check out the README for usage instructions + language how-to - https://github.com/AlexanderDzhoganov/langums/blob/master/README.md

Some code examples you can find in the test/ folder of the repo - https://github.com/AlexanderDzhoganov/langums/tree/master/test

As you'll see there is plenty missing at the moment, but I'm adding stuff all the time. The readme will also get updated with more info and examples as we go. I'm here to answer any questions.
RWLabs
Profile Joined March 2017
Korea (South)273 Posts
April 26 2017 22:17 GMT
#20
Awesome. I will give it a shot.
Aldaris was the good guy of Brood War.
KhaosKreator
Profile Joined April 2009
Canada145 Posts
April 26 2017 22:35 GMT
#21
This sounds pretty neat. Maybe I'll use this when it's done and start making maps again.
Kyrie, Ignis Divine, Eleison
nlight
Profile Joined October 2011
Bulgaria58 Posts
April 26 2017 23:26 GMT
#22
On April 27 2017 07:35 KhaosKreator wrote:
This sounds pretty neat. Maybe I'll use this when it's done and start making maps again.


Given how much stuff I was able to add in the latest updates you can pretty much start using it. The language syntax will be kept stable so you just have to update langums.exe to get new features when they're available.
TheFish7
Profile Blog Joined February 2012
United States2824 Posts
Last Edited: 2017-04-26 23:32:39
April 26 2017 23:29 GMT
#23
Wow, really great to see something like this popping up.

I used to know the editor pretty much in and out but with 0 programming knowledge outside of that I probably won't be much help.
~ ~ <°)))><~ ~ ~
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 01:09:28
April 27 2017 01:07 GMT
#24
On April 27 2017 08:29 TheFish7 wrote:
Wow, really great to see something like this popping up.

I used to know the editor pretty much in and out but with 0 programming knowledge outside of that I probably won't be much help.


If you have experience with StarEdit or SCMDraft triggers then this should be pretty straightforward for you. Also it can be your foray into real programming ^_^
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-27 03:12:50
April 27 2017 03:12 GMT
#25
Forced player 8 computer and no preplaced units for p8 makes this unusable for a large majority of maps. Just a heads up.
Glenstorm
Profile Joined January 2009
United States69 Posts
Last Edited: 2017-04-27 06:12:52
April 27 2017 05:56 GMT
#26
I took a little time and threw together a very very barebones vscode extension for langums, the only feature is syntax highlighting on language constants and keywords, but hopefully it makes testing out the language a little nicer for you early adopters.

https://marketplace.visualstudio.com/items?itemName=glenstorm.langums

If you haven't used Visual Studio Code before (a different program than standard visual studio), you can grab it here https://code.visualstudio.com/

Here it is on the first test program:
[image loading]
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 09:43:24
April 27 2017 09:28 GMT
#27
On April 27 2017 12:12 integral wrote:
Forced player 8 computer and no preplaced units for p8 makes this unusable for a large majority of maps. Just a heads up.


There needs to be at least one player whose death counts aren't messed with by having his units die. I picked player 8 pretty arbitrarily. Which one it is I'll make configurable (I guess using player 11 would be better?). Do you recommend using another player id by default? I'm pretty sure I can get rid of the requirement for having a Computer player at all which I'll do today.

On April 27 2017 14:56 Glenstorm wrote:
I took a little time and threw together a very very barebones vscode extension for langums


Really cool, already using it! Thanks.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-27 11:43:51
April 27 2017 11:31 GMT
#28
There needs to be at least one player whose death counts aren't messed with by having his units die. I picked player 8 pretty arbitrarily. Which one it is I'll make configurable (I guess using player 11 would be better?). Do you recommend using another player id by default? I'm pretty sure I can get rid of the requirement for having a Computer player at all which I'll do today.


It's probably your highest priority to allow choices here, because your project is 100% dead in the water unless you give mapmakers options. Default player 8 and even default p8 computer is fine, but forced is not -- and if that player has preplaced units and those units can die, then you either need to do conditional checks with triggers (e.g. if this unit is owned by p8, don't use it) or allow mapmakers to identify which units they want to use for death counts. The first thing I do when I'm making a map is make a list of the death counts I'm using and how they're being used, so this would not be unfamiliar.

A simple input system to let users tell the program:
1. which player/force needs to own the death counts
2. which units not to use for death counts

will solve the problem. This will allow users to introduce errors, yes, but it's worth it. One suggestion I have is to use the wiki list of units that can't be killed at all as default, and then allow users to expand these as necessary. Simpler maps won't need much beyond this, and advanced maps usually come with advanced mapmakers who need to be able to choose which units they're using.

+ Show Spoiler +
Goliath Turret
Tank Turret(Tank Mode)
Nuclear Missile
Alan Schezar Turret
Edmund Duke Turret
Edmund Duke Turret
Tank Turret (Siege Mode)
Scanner Sweep
Unused - Cargo Ship
Unused - Mercenary Gunship
Map Revealer
Disruption Web
Unused1
Unused2
Uraj Crystal
Khalis Crystal
Unused Zerg Building1
Unused Zerg Building2
Unused Protoss Building1
Unused Protoss Building2
Khaydarin Crystal Formation
Mineral Field (Type 1)
Mineral Field (Type 2)
Mineral Field (Type 3)
Cave
Cave-in
Cantina
Mining Platform
Independant Command Center
Independant Starport
Independant Jump Gate
Ruins
Kyadarin Crystal Formation
Vespene Geyser
Zerg Marker
Terran Marker
Protoss Marker
Zerg Beacon
Terran Beacon
Protoss Beacon
Zerg Flag Beacon
Terran Flag Beacon
Protoss Flag Beacon
Dark Swarm
Floor Hatch
Left Upper Level Door
Right Upper Level Door
Left Pit Door
Right Pit Door
Start Location
Flag
Psi Emitter
Data Disc
Khaydarin Crystal


I dunno how you coded this, but hopefully it isn't too hard to change.


Also consider that for a number of things I want to run death count calcs for every player on the map, not just player 8. I really need to be able to customize which player (and how many) owns any given trigger, and have death count variables stored for every individual player where necessary. This is pretty much the baseline for functionality. p8 only is pretty specific.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 15:57:41
April 27 2017 12:27 GMT
#29
I've pushed a new version with the following changes:

- A Computer player is no longer necessary
- The main triggers are emitted for Player 1 by default (can be changed with the --triggers-owner option)
- The death counts of Player 8 are still used by default for storage, but can be changed now with the --registers-owner option.

The first thing I do when I'm making a map is make a list of the death counts I'm using and how they're being used

You kind of don't need to do this with LangUMS. The compiler will assign your variables to death counts automatically and more likely than not more efficiently than you can do by hand (at least in theory).

Also consider that for a number of things I want to run death count calcs for every player on the map

You can do this with the deaths() event handler, it allows you to check deaths for whatever player you want. Or you want to check for several players at once with some exclusion mask? I have something for this planned.

A simple input system to let users tell the program:
1. which player/force needs to own the death counts
2. which units not to use for death counts


1 is done in the latest update. I'll consider doing 2 soon.

your highest priority to allow choices


Absolutely agree, let me know what you'd need.

Freakling
Profile Joined October 2012
Germany1533 Posts
Last Edited: 2017-04-27 12:51:53
April 27 2017 12:48 GMT
#30
On April 27 2017 18:28 nlight wrote:
Show nested quote +
On April 27 2017 12:12 integral wrote:
Forced player 8 computer and no preplaced units for p8 makes this unusable for a large majority of maps. Just a heads up.


There needs to be at least one player whose death counts aren't messed with by having his units die. I picked player 8 pretty arbitrarily. Which one it is I'll make configurable (I guess using player 11 would be better?). Do you recommend using another player id by default? I'm pretty sure I can get rid of the requirement for having a Computer player at all which I'll do today.

Show nested quote +
On April 27 2017 14:56 Glenstorm wrote:
I took a little time and threw together a very very barebones vscode extension for langums


Really cool, already using it! Thanks.

Unused players 9...11 would be obvious choices. Neutral P12 for the most part as well, probably (not quite sure how deaths of units from a player who left the game are counted). You could also add some flexibility by detecting players set to unused owner and/or inactive race and use all of their DCs as memory.
Furthermore, there are a ton of unused units, which cannot even be placed in a map without crashing the game. These still have DCs, though, which can be used for any player as nothing can mess with them. DCs for invincible-by-default units, such as resources, powerups or Khaydarin Crystal Formations are also usually safe for grabs (unless there are destroy triggers for them).
Only a limited selection of units will be used per player, to begin with, so ideally, I guess, you should add an advanced option to manually have map makers specify memory space themselves. Does your program parse units pre-placed for each player in a map when compiling the triggers in the map file? You could then just automatically assign every unit to memory which is neither pre-placed for a certain player in the map file nor has any create or give triggers for that player ; or, for maximum flexibility, but less safe, just add a debugger warning whenever a unit assigned as memory clashes with a pre-placed unit or create/give trigger.
nlight
Profile Joined October 2011
Bulgaria58 Posts
April 27 2017 12:55 GMT
#31
Unused players 9...11 would be obvious choices.


Sadly I believe players 9 to 11's death counts can't be manipulated and they can't run triggers, otherwise that'd have been the obvious choice, yes.

Neutral P12 for the most part as well, probably (not quite sure how deaths of units from a player who left the game are counted).

I have no idea about this one, someone more experienced than me should pitch in and say if it would be ok to use Player 12's death counts as storage without messing up.

You could also add some flexibility by detecting players set to unused owner and/or inactive race and use all of their DCs as memory.

Great idea, definitely doing this.

Only a limited selection of units will be used per player, to begin with, so ideally, I guess, you should add an advanced option to manually have map makers specify memory space themselves.

I can do this pretty easily. Look forward to it soon.

Does your program parse units pre-placed for each player in a map when compiling the triggers in the map file?

Yes, it can.

You could then just automatically assign every unit to memory which is neither pre-placed for a certain player in the map file, nor has any create or give triggers for that player, or, for maximum flexibility, but less safe, just add a debugger warning whenever a unit assigned as memory clashes with a pre-placed unit or create/give trigger.


Another really good idea. I'll do this also.
integral
Profile Blog Joined February 2009
United States3156 Posts
April 27 2017 12:57 GMT
#32
You kind of don't need to do this with LangUMS. The compiler will assign your variables to death counts automatically and most likely more efficiently than you can do by hand at least in theory.


People have been making maps for a long time. Even if the compiler you wrote is really fucking cool, and it is, it's actually straight up insulting to think that it knows what I need better than I do. Efficiency is cool, but unless it's able to interface with the decade of work I've already done, it's really not gonna matter if it saves a few triggers here or there. Coming in with a necessarily disruptive approach is gonna put a lot of people off.

I've already got a lot of completed maps. I constantly copy and paste code snippets and modules from other maps I've made. I'm not rewriting my already assigned death counts just so I can use your program to generate some triggers for me. I'm also not gonna rewrite all my already-written modules in your generator just because the compiler wants to assign stuff automatically. Your compiler doesn't know which death counts I'm already using, but I'll tell it if you let me.

Maybe your tool is marketed more toward people who don't really make maps much, or have never really made a map before, or who are making a completely new map. If so, I'll back off a bit. But if you want established mapmakers to use this, it needs to be able to work with the things that people have already done.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 13:39:34
April 27 2017 13:12 GMT
#33
People have been making maps for a long time. Even if the compiler you wrote is really fucking cool, and it is, it's actually straight up insulting to think that it knows what I need better than I do.


I understand. I come from a programming background where we're drilled that "the compiler knows better" from day 1, it's like a mantra (and it's mostly true given a decent enough compiler, which mine most likely ain't yet).

Efficiency is cool, but unless it's able to interface with the decade of work I've already done, it's really not gonna matter if it saves a few triggers here or there.

This is an unusual perspective for me. I did start with the assumption that langums maps will be made from scratch. Interfacing with already existing ones is definitely something I had not considered until now but I do realize it's important and I'm open to making it work. Could you give me a detailed explanation on how you imagine the interfacing between langums code and your existing triggers to work? Feel free to take some time and test out some stuff in langums to get a feel for it.

Coming in with a necessarily disruptive approach is gonna put a lot of people off.


I believe it is a small pain for major gains down the road. Do understand though that I care equally for people entering the community as well as experienced members. The tool must be suitable for both and decisions will be made which may not fully fit one side's point of view. Of course the opinion of experienced people weights a whole lot more in my decision process than someone who has never released a map.

I'm not rewriting my already assigned death counts just so I can use your program to generate some triggers for me. I'm also not gonna rewrite all my already-written modules in your generator just because the compiler wants to assign stuff automatically.

This is understandable. Let's see how to make it work.

Your compiler doesn't know which death counts I'm already using, but I'll tell it if you let me.

This will be a part of the "integration" facilities I can put in. I'm imagining something like

global foo = <Player4, TerranMarine>;


can map an already existing death count to a langums variable. Let me finish adding the basic features over the next few days and I'll see how to make this work.

On a sidenote, can anyone point me to a list of AI scripts available. Their names should be 4 chars long.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-27 13:42:38
April 27 2017 13:40 GMT
#34
This is an unusual perspective for me. I did start with the assumption that langums maps will be made from scratch.


That's a pretty huge assumption, glad you acknowledged it.

Interfacing with already existing ones is definitely something I had not considered until now but I do realize it's important and I'm open to making it work. Could you give me a detailed explanation on how you imagine the interfacing between langums code and your existing triggers to work? Feel free to take some time and test out some stuff in langums to get a feel for it.


Basically just let me tell the program what death counts it's allowed to use and what it isn't, and I'll use it like I currently use my own string generator -- copy and paste the output into my master trigger file. I also don't need (or want) it to auto-generate an .scx file, or even be linked to one. I write a lot of my triggers in modules, separately. An option to output as .txt directly from the script would be great for this.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 13:46:42
April 27 2017 13:46 GMT
#35
Basically just let me tell the program what death counts it's allowed to use and what it isn't


This is next on my list after I'm done implementing the rest of the conditions & actions that are missing at the moment. I can do you one better though and have the compiler automatically figure out which death counts are unused by analyzing the .scx file. Let me know if that's a thing you'd want.

I'll use it like I currently use my own string generator -- copy and paste the output into my master trigger file


Would that be in scmdraft 2's trigger format? I'm not aware of StarEdit having a text format for triggers but I may be wrong.
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-27 14:09:00
April 27 2017 13:58 GMT
#36
Sadly I believe players 9 to 11's death counts can't be manipulated and they can't run triggers, otherwise that'd have been the obvious choice, yes.


Can confirm.

I have no idea about this one, someone more experienced than me should pitch in and say if it would be ok to use Player 12's death counts as storage without messing up.


Not really viable either, for several reasons. Lots of death count uses won't work properly with it. You could try to make it work but it'd be messy. From the quirks and nuances page:

+ Show Spoiler +
  • When a player leaves the game, their units are given to Player 12 (Neutral). Any alliances that remaining players had with the departed player will remain intact toward those Player 12 units. Changing a player's alliance status with the departed player will likewise affect that player's alliance with those units.
  • Deaths for extended players' units (and for Neutral units) can be read in conditions but cannot be altered with the Set Deaths action. They will accurately represent the deaths their units have amassed.
  • Units cannot be created for Players 9-12. You must instead create the units for a normal player, and give the units to P9-12 as a separate action.


Would that be in scmdraft 2's trigger format? I'm not aware of StarEdit having a text format for triggers but I may be wrong.


Yeah. People who want to use StarEdit (I guess they still exist???) can use the auto-generate feature.

I can do you one better though and have the compiler automatically figure out which death counts are unused by analyzing the .scx file. Let me know if that's a thing you'd want.


lol. It actually isn't, automation be damned, because I'll tell you what I'm gonna want to do: I'm gonna use your program to do some math stuff I've been needing to do for a while, and I'm gonna copy and paste it into my pre-existing maps. Even if it could read ALL the maps and figure out which ones weren't used, it's still better if I can just tell it to use the ones I want it to.

On edit: This isn't a huge dealbreaker or anything. As it is I'd just use notepad to find/replace what your compiler came up with, which is more or less fine. I can also extract the .txt file myself by opening scmdraft2 afterwards.

Analyzing the .scx file for unused death counts will be useful in other scenarios for sure.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 15:20:20
April 27 2017 15:10 GMT
#37
I've pushed an update that includes a --reg option which allows you to pass a file that looks like

Player8, TerranMarine
Player8, TerranGhost
Player8, TerranVulture
Player8, TerranGoliath
Player8, TerranGoliathTurret
Player8, TerranSiegeTankTankMode


The compiler will use these death counters as internal registers and won't touch anything else. Keep in mind depending on how complex your calculations are you may need plenty of those. I'd say about 24 is the bare minimum required to operate give or take depending on how many functions/ events you have. You'll probably want to use the --preserve-triggers option also. Soon there will be an easy way to map langums variables to existing (external) death counters to allow for easy interaction both ways.

Also I've added a section about integrating with existing maps to the README - https://github.com/AlexanderDzhoganov/langums#integration-with-existing-maps
frogmelter
Profile Blog Joined April 2009
United States971 Posts
Last Edited: 2017-04-27 16:40:45
April 27 2017 16:40 GMT
#38
Does this have RNG support? [ie. var bar = rand(0, 10) // returns a number from 0 to 10 inclusive at the bottom, exclusive at the top]
TL+ Member
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-27 18:14:13
April 27 2017 17:13 GMT
#39
On April 28 2017 01:40 frogmelter wrote:
Does this have RNG support? [ie. var bar = rand(0, 10) // returns a number from 0 to 10 inclusive at the bottom, exclusive at the top]


It does now. The latest update includes the rnd256() built-in which returns a random value between 0 and 255.
Use like:

var foo = rnd256();

For now you can scale it yourself using division if you need a smaller range though it will give you a non-uniform distribution but that's maybe not an issue for your use case.
Freakling
Profile Joined October 2012
Germany1533 Posts
April 27 2017 17:23 GMT
#40
Show nested quote +
You could then just automatically assign every unit to memory which is neither pre-placed for a certain player in the map file, nor has any create or give triggers for that player, or, for maximum flexibility, but less safe, just add a debugger warning whenever a unit assigned as memory clashes with a pre-placed unit or create/give trigger.


Another really good idea. I'll do this also.

Thinking about this one step further, for units/buildings that can actually be built, it also need to be checked whether the player is actually 1. allowed (via unit settings) and able (has a production structure or worker via pre-placement or create/give trigger) to. at least in theory, acquire that unit. There are of course lots of ways around either allowing the player to have the unit (players has workers, but only unbuildable ground, blocked building exits, units come at prohibitive cost, unit building is just use as control buttons and the units are removed immediately upon spawn etc.) or having unit deaths actually affect death counters (if a known amount of units die in a controlled enough fashion, death counters can be adjusted for that). So ideally you should also allow players to force assign-death a specific death counter to a specific purpose. Means a lot more handiwork and potential errors by the map maker, but can also squeeze out that bit of extra memory and control...
Freakling
Profile Joined October 2012
Germany1533 Posts
Last Edited: 2017-04-27 19:22:32
April 27 2017 17:38 GMT
#41
Maybe your tool is marketed more toward people who don't really make maps much, or have never really made a map before, or who are making a completely new map. If so, I'll back off a bit. But if you want established mapmakers to use this, it needs to be able to work with the things that people have already done.


If the triggers are already written for a map, you certainly don't need any tools for that any more. However, when any one, including you, starts any new map from scratch...

I understand. I come from a programming background where we're drilled that "the compiler knows better" from day 1, it's like a mantra (and it's mostly true given a decent enough compiler, which mine most likely ain't yet).


A good compiler for a sufficiently complex program, certainly. The issue is more that UMS map makers are used to writing all their stuff in assembler, and they don't want to rewrite any code that ain't broken ;D
Also, there is the issue that when memory is very limited (not just data memory but also the memory the program itself takes up, in this case meaning there is a trigger limit to a map), assembler might just be the best choice... So to run with the analogy, you should probably include the option for the super-geeks to use some inline assembler...
KhaosKreator
Profile Joined April 2009
Canada145 Posts
April 27 2017 18:34 GMT
#42
On April 27 2017 21:57 integral wrote:
Maybe your tool is marketed more toward people who don't really make maps much, or have never really made a map before, or who are making a completely new map. If so, I'll back off a bit. But if you want established mapmakers to use this, it needs to be able to work with the things that people have already done.

But established mapmakers make completely new maps all the time?

Having the compiler use available unused memory by default is obviously the way to go. You just have to make sure there are advanced options for people that want to manage that themselves.
Kyrie, Ignis Divine, Eleison
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-28 01:32:15
April 27 2017 21:46 GMT
#43
I've pushed a new version with a much cleaned-up internal code representation with hopefully way less codegen bugs. If something didn't work as it should before, hopefully it works now.

An example of the new rnd256() function.

#define LUCKY_NUMBER 90

countdown(Exactly, 0) => {
set_countdown(2 + rnd256() / 80);

if (rnd256() >= LUCKY_NUMBER) {
print("lucky you");
spawn(TerranMarine, Player1, 1 + rnd256() / 40, "TestLocation");
order(TerranMarine, Player1, Attack, "TestLocation", "TestLocation2");
} else {
print("try again next time");
spawn(TerranMarine, Player2, 1 + rnd256() / 40, "TestLocation2");
order(TerranMarine, Player2, Attack, "TestLocation2", "TestLocation");
}
}

fn main() {
while(true) {
poll_events();
}
}


Also template functions:


fn spawn_units<T>(T, qty) {
talking_portrait(T, 5);
spawn(T, Player1, qty, "TestLocation");
order(T, Player1, Move, "TestLocation", "TestLocation2");
}

fn main() {
spawn_units(TerranMarine, 5);
}

kane]deth[
Profile Joined October 2009
Canada368 Posts
April 28 2017 01:04 GMT
#44
Just wanna chime in and say it's really really cool what you're doing here. I've never made any detailed maps before, but as a programmer knowing I can make cool advanced maps using code instead of having to learn about the trigger system and manipulating death counters is really enticing. I'm going to take a look at this soon!
integral
Profile Blog Joined February 2009
United States3156 Posts
Last Edited: 2017-04-28 03:05:06
April 28 2017 03:03 GMT
#45
On April 28 2017 02:38 Freakling wrote:
Show nested quote +
Maybe your tool is marketed more toward people who don't really make maps much, or have never really made a map before, or who are making a completely new map. If so, I'll back off a bit. But if you want established mapmakers to use this, it needs to be able to work with the things that people have already done.


If the triggers are already written for a map, you certainly don't need any tools for that any more. However, when any one, including you, starts any new map from scratch...


On April 28 2017 03:34 KhaosKreator wrote:
But established mapmakers make completely new maps all the time?



What? Even for maps I've already completed, I still use tools to update and edit it... Even if I didn't, this isn't actually relevant to what I was saying, because even in new maps I still copy and paste from what I've done in the past. The whole point of a program like this is to save time.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-28 14:30:06
April 28 2017 12:35 GMT
#46
The last big limitation is now lifted. You no longer need a reserved player at all. The "unused" unit death counters for all players are mapped by default. This gives us 416 memory locations to work with which should be more than enough for the default configuration. You can still pass a registers file with --reg to override it.

I still need a list of the names of all AI scripts if anyone has such a thing. Otherwise I'll just export a map from scmdraft 2 and extract them manually but it'd be nice to not have to.
integral
Profile Blog Joined February 2009
United States3156 Posts
April 28 2017 16:07 GMT
#47
Good stuff. I think asking on TL for specific things like AI scripts won't be as likely to get a response as asking on staredit.net.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-28 16:21:30
April 28 2017 16:15 GMT
#48
On April 29 2017 01:07 integral wrote:
Good stuff. I think asking on TL for specific things like AI scripts won't be as likely to get a response as asking on staredit.net.


I'd love to join that community but the website is really really slow for me for some reason (10-20 secs to load a page). I had to clone the wiki locally so I can work without waiting forever.
integral
Profile Blog Joined February 2009
United States3156 Posts
April 28 2017 16:59 GMT
#49
On April 29 2017 01:15 nlight wrote:
Show nested quote +
On April 29 2017 01:07 integral wrote:
Good stuff. I think asking on TL for specific things like AI scripts won't be as likely to get a response as asking on staredit.net.


I'd love to join that community but the website is really really slow for me for some reason (10-20 secs to load a page). I had to clone the wiki locally so I can work without waiting forever.


Yeah. It's a long-running joke how slow it is.
nlight
Profile Joined October 2011
Bulgaria58 Posts
April 28 2017 17:40 GMT
#50
TMCu - TerranCustomLevel
ZMCu - ZergCustomLevel
PMCu - ProtossCustomLevel
TMCx - TerranExpansionCustomLevel
ZMCx - ZergExpansionCustomLevel
PMCx - ProtossExpansionCustomLevel
TLOf - TerranCampaignEasy
TMED - TerranCampaignMedium
THIf - TerranCampaignDifficult
TSUP - TerranCampaignInsane
TARE - TerranCampaignAreaTown
ZLOf - ZergCampaignEasy
ZMED - ZergCampaignMedium
ZHIf - ZergCampaignDifficult
ZSUP - ZergCampaignInsane
ZARE - ZergCampaignAreaTown
PLOf - ProtossCampaignEasy
PMED - ProtossCampaignMedium
PHIf - ProtossCampaignDifficult
PSUP - ProtossCampaignInsane
PARE - ProtossCampaignAreaTown
TLOx - ExpansionTerranCampaignEasy
TMEx - ExpansionTerranCampaignMedium
THIx - ExpansionTerranCampaignDifficult
TSUx - ExpansionTerranCampaignInsane
TARx - ExpansionTerranCampaignAreaTown
ZLOx - ExpansionZergCampaignEasy
ZMEx - ExpansionZergCampaignMedium
ZHIx - ExpansionZergCampaignDifficult
ZSUx - ExpansionZergCampaignInsane
ZARx - ExpansionZergCampaignAreaTown
PLOx - ExpansionProtossCampaignEasy
PMEx - ExpansionProtossCampaignMedium
PHIx - ExpansionProtossCampaignDifficult
PSUx - ExpansionProtossCampaignInsane
PARx - ExpansionProtossCampaignAreaTown
Enmy - SetPlayerToEnemy
Ally - SetPlayerToAlly
VluA - ValueThisAreaHigher
EnBk - EnterClosestBunker
EnTr - EnterTransport
ExTr - ExitTransport


I made a list of all AI script names if anyone is interested in it for whatever reason.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-28 21:40:50
April 28 2017 21:33 GMT
#51
There is now a way to spawn units with properties. I think it is more flexible (?) than scmdraft or staredit as you can reuse CUWP slots for different unit types and they're quite scarce at 64 max. More info in the README here - https://github.com/AlexanderDzhoganov/langums#spawning-units-with-properties

Example:

unit LurkerType1 {
Health = 10,
Burrowed = true
}

fn main() {
spawn(ZergLurker, Player1, 1, "TestLocation", LurkerType1);
}
Glenstorm
Profile Joined January 2009
United States69 Posts
Last Edited: 2017-04-29 05:12:25
April 29 2017 05:04 GMT
#52
Just pushed an update to my vscode extension which adds in code completion on intrinsics, and gets up to date with the mammoth pile of new functionality in langums.

Some future features I might be looking at are filling in intellisense when working with intrinsic functions, and scanning the .scx file for locations and exposing those to autocomplete (if I figure out a friendly cross-platform way of distributing libmpq, might poke around asm.js).

Btw, you're a monster nlight, it's taking a pretty big chunk of my post-work free time just to keep up with your language updates
tec27
Profile Blog Joined June 2004
United States3702 Posts
April 29 2017 05:09 GMT
#53
On April 29 2017 14:04 Glenstorm wrote:
Just pushed an update to my vscode extension which adds in code completion on intrinsics, and gets up to date with the mammoth pile of new functionality in langums.

Some future features I might be looking at are filling in intellisense when working with intrinsic functions, and scanning the .scx file for locations and exposing those to autocomplete (if I figure out a friendly cross-platform way of distributing libmpq).

Btw, you're a monster nlight, it's taking a pretty big chunk of my post-work free time just to keep up with your language updates

You might be interested in: https://github.com/neivv/bw-chk

Probably doesn't get you all the way there (it's missing a lot of the stuff that'd probably be useful for you to auto-complete), but gets you much closer without using any native code, and is open for contributions if you'd like to add things
Can you jam with the console cowboys in cyberspace?
Glenstorm
Profile Joined January 2009
United States69 Posts
April 29 2017 05:22 GMT
#54
Looks like that plus your https://github.com/ShieldBattery/scm-extractor should get me there. VSCode is built on a node.js stack so I wont even have to deal with interop Thanks!
Freakling
Profile Joined October 2012
Germany1533 Posts
April 29 2017 09:35 GMT
#55
On April 29 2017 02:40 nlight wrote:
+ Show Spoiler +
TMCu - TerranCustomLevel
ZMCu - ZergCustomLevel
PMCu - ProtossCustomLevel
TMCx - TerranExpansionCustomLevel
ZMCx - ZergExpansionCustomLevel
PMCx - ProtossExpansionCustomLevel
TLOf - TerranCampaignEasy
TMED - TerranCampaignMedium
THIf - TerranCampaignDifficult
TSUP - TerranCampaignInsane
TARE - TerranCampaignAreaTown
ZLOf - ZergCampaignEasy
ZMED - ZergCampaignMedium
ZHIf - ZergCampaignDifficult
ZSUP - ZergCampaignInsane
ZARE - ZergCampaignAreaTown
PLOf - ProtossCampaignEasy
PMED - ProtossCampaignMedium
PHIf - ProtossCampaignDifficult
PSUP - ProtossCampaignInsane
PARE - ProtossCampaignAreaTown
TLOx - ExpansionTerranCampaignEasy
TMEx - ExpansionTerranCampaignMedium
THIx - ExpansionTerranCampaignDifficult
TSUx - ExpansionTerranCampaignInsane
TARx - ExpansionTerranCampaignAreaTown
ZLOx - ExpansionZergCampaignEasy
ZMEx - ExpansionZergCampaignMedium
ZHIx - ExpansionZergCampaignDifficult
ZSUx - ExpansionZergCampaignInsane
ZARx - ExpansionZergCampaignAreaTown
PLOx - ExpansionProtossCampaignEasy
PMEx - ExpansionProtossCampaignMedium
PHIx - ExpansionProtossCampaignDifficult
PSUx - ExpansionProtossCampaignInsane
PARx - ExpansionProtossCampaignAreaTown
Enmy - SetPlayerToEnemy
Ally - SetPlayerToAlly
VluA - ValueThisAreaHigher
EnBk - EnterClosestBunker
EnTr - EnterTransport
ExTr - ExitTransport


I made a list of all AI script names if anyone is interested in it for whatever reason.

You are still missing a lot of them. Those are just the standard StarEdit accessible ones. There are also all the Campaign scripts some spell scripts (recall/Dweb/nuke here, load nuclear silo), scripts that handle some unit spawns in some of the campaign missions, the all-so-important junkyard dog script (makes any unit move around like a critter), the vision scripts, and you even seem to have missed the suicide mission scripts.
Basically, have a look in SCMDraft, it can access all of them, to get the full list.
JungleTerrain
Profile Joined January 2012
Chile799 Posts
April 29 2017 09:49 GMT
#56
On April 29 2017 01:59 integral wrote:
Show nested quote +
On April 29 2017 01:15 nlight wrote:
On April 29 2017 01:07 integral wrote:
Good stuff. I think asking on TL for specific things like AI scripts won't be as likely to get a response as asking on staredit.net.


I'd love to join that community but the website is really really slow for me for some reason (10-20 secs to load a page). I had to clone the wiki locally so I can work without waiting forever.


Yeah. It's a long-running joke how slow it is.


Besides not really being a UMS mapmaker, this is one of the reasons I try to stay away from Staredit.net lol. But for me it's like 1-2 mins to load a page. My god it is horrible. So frustrating lol.

However I find it funny that some of the smartest guys in BW use such a slow website.
www.broodwarmaps.net
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-29 10:53:42
April 29 2017 10:52 GMT
#57
You are still missing a lot of them. Those are just the standard StarEdit accessible ones. There are also all the Campaign scripts some spell scripts (recall/Dweb/nuke here, load nuclear silo), scripts that handle some unit spawns in some of the campaign missions, the all-so-important junkyard dog script (makes any unit move around like a critter), the vision scripts, and you even seem to have missed the suicide mission scripts.
Basically, have a look in SCMDraft, it can access all of them, to get the full list.


I dumped these from scmdraft by using the Classic Triggers editor. Maybe they're not all listed there? Give me some hints where to look.

code completion on intrinsics, and gets up to date with the mammoth pile of new functionality in langums.


Awesome!

Btw, you're a monster nlight, it's taking a pretty big chunk of my post-work free time just to keep up with your language updates


Don't worry this won't be for too long, I'm almost done with the core features
fazek42
Profile Blog Joined April 2011
Hungary438 Posts
April 29 2017 11:19 GMT
#58
You guys are total beasts :O
Glenstorm
Profile Joined January 2009
United States69 Posts
April 29 2017 13:29 GMT
#59
What's the strategy for handling multi-condition events? I was working on some demo code where I found myself wanting to do the trigger equivalent of "Player 1 brings 1 civ to location and has >=100 minerals" and I haven't seen anything setup like that in the tests. Some syntaxes I imagined where nested lambdas, using one condition as an if inside the other, or some weird bring(...) && accumulate(...) => { } setup.

I've been poking around with snippets and in all likelihood I have to make the event snippets a bit less aggressive at setting up syntax for you, if they're viable in stuff like if statements.
[image loading]
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-29 18:05:06
April 29 2017 14:32 GMT
#60
On April 29 2017 22:29 Glenstorm wrote:
What's the strategy for handling multi-condition events? I was working on some demo code where I found myself wanting to do the trigger equivalent of "Player 1 brings 1 civ to location and has >=100 minerals" and I haven't seen anything setup like that in the tests.


You can specify more than one condition per event handler separated by commas (up to 63 total), it's actually in the examples in the README. I will add some to the tests as well. For your case it would look like:


bring(Player1, AtLeast, 1, TerranCivilian, BuyMarines),
accumulate(Player1, AtLeast, 100, Minerals) => {
take_resource(Player1, Minerals, 100);
}


That code completion gif is really cool, nice job.

On a sidenote, LangUMS now supports 100% of the built-in trigger conditions & actions in the game. Now I'm starting to expand into new territory. The first addition is the is_present(Player) function which tells you if a player (or players) is currently present in the game.


if (is_present(Player3)) {
print("Player 3 is in the game.");
}


You can also use it to get the number of players in-game at the moment like this:


var playerCount = is_present();


Everyone who is actively trying out, testing, using, doing whatever with the tool please join the discord here - https://discord.gg/TNehfve so we can talk in real time.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-29 19:42:32
April 29 2017 19:41 GMT
#61
The amount of code necessary to implement proper binary multiplication with triggers ...

[image loading]

I'm almost sure it works correctly t.t
2Pacalypse-
Profile Joined October 2006
Croatia9530 Posts
Last Edited: 2017-04-29 19:45:43
April 29 2017 19:45 GMT
#62
On April 30 2017 04:41 nlight wrote:
The amount of code necessary to implement proper binary multiplication with triggers ...

+ Show Spoiler +
[image loading]


I'm almost sure it works correctly t.t

Infinite amount of code necessary to implement that? It just keeps on scrolling!
Moderator"We're a community of geniuses because we've found how to extract 95% of the feeling of doing something amazing without actually doing anything." - Chill
Freakling
Profile Joined October 2012
Germany1533 Posts
April 29 2017 20:17 GMT
#63
On April 29 2017 19:52 nlight wrote:
Show nested quote +
You are still missing a lot of them. Those are just the standard StarEdit accessible ones. There are also all the Campaign scripts some spell scripts (recall/Dweb/nuke here, load nuclear silo), scripts that handle some unit spawns in some of the campaign missions, the all-so-important junkyard dog script (makes any unit move around like a critter), the vision scripts, and you even seem to have missed the suicide mission scripts.
Basically, have a look in SCMDraft, it can access all of them, to get the full list.


I dumped these from scmdraft by using the Classic Triggers editor. Maybe they're not all listed there? Give me some hints where to look.


Not sure what you did, but you should have access to all of them to either the "execute AI script" or the "execute AI script at location" trigger actions. Maybe you do not have the latest official SCMDraft version (2.0.8.)?
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-29 20:59:38
April 29 2017 20:24 GMT
#64
Not sure what you did, but you should have access to all of them to either the "execute AI script" or the "execute AI script at location" trigger actions. Maybe you do not have the latest official SCMDraft version (2.0.8.)?


I see now. My bad. It appears I did use StarEdit after all because I do see a lot of other AI scripts in scmdraft. I'll make sure to dump these also and include them in the list. Thanks!

EDIT:

I dumped all AI script names from scmdraft, I think. Here it is https://gist.github.com/AlexanderDzhoganov/c64c59d2f6fdb0f148c0ac628872fab9

If anyone can match them to their names that'd be amazing help. Sadly they don't appear to be in the same order as in the menu.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-30 02:02:18
April 29 2017 23:26 GMT
#65
New major feature - arrays. Glenstorm will have to update the syntax highlighting again lol.


global player_score[8];

deaths(Player2, AtLeast, 1, TerranMarine) => {
remove_deaths(Player2, TerranMarine, 1);
player_score[0]++;
player_score[1]++;
}

fn main() {
var foo[4];
foo[0] = 15;
foo[1] = 42;

if (foo[0] == 15) {
print("foo[0] == 15");
}

if ((foo[1] * 2) == 84) {
print("(foo[1] * 2) == 84");
}

while (true) {
poll_events();
}
}


Right now can only be indexed with a constant but there will be a way to iterate them at some point. Indexing with variables is unlikely to be supported.

Also comparison operators are now 5000% (not a real number) faster. Well, much faster and generate much less triggers.
Freakling
Profile Joined October 2012
Germany1533 Posts
April 30 2017 10:57 GMT
#66
On April 30 2017 05:24 nlight wrote:
Show nested quote +
Not sure what you did, but you should have access to all of them to either the "execute AI script" or the "execute AI script at location" trigger actions. Maybe you do not have the latest official SCMDraft version (2.0.8.)?


I see now. My bad. It appears I did use StarEdit after all because I do see a lot of other AI scripts in scmdraft. I'll make sure to dump these also and include them in the list. Thanks!

EDIT:

I dumped all AI script names from scmdraft, I think. Here it is https://gist.github.com/AlexanderDzhoganov/c64c59d2f6fdb0f148c0ac628872fab9

If anyone can match them to their names that'd be amazing help. Sadly they don't appear to be in the same order as in the menu.

I forwarded your request to Suicidal Insanity.
S.I.
Profile Joined April 2017
58 Posts
April 30 2017 12:20 GMT
#67
Have fun!

+ Show Spoiler +


static const size_t NumAIScripts = 293;
const TCHAR AIShortNames[NumAIScripts][5] = {
TEXT("Ter3"),
TEXT("Ter5"),
TEXT("Te5H"),
TEXT("Ter6"),
TEXT("Te6b"),
TEXT("Te6c"),
TEXT("Ter7"),
TEXT("Te7s"),
TEXT("Te7m"),
TEXT("Ter8"),
TEXT("Tr9L"),
TEXT("Tr9H"),
TEXT("Te10"),
TEXT("T11z"),
TEXT("T11a"),
TEXT("T11b"),
TEXT("T12N"),
TEXT("T12P"),
TEXT("T12T"),
TEXT("TED1"),
TEXT("TED2"),
TEXT("TED3"),
TEXT("TSW1"),
TEXT("TSW2"),
TEXT("TSW3"),
TEXT("TSW4"),
TEXT("TSW5"),
TEXT("Zer1"),
TEXT("Zer2"),
TEXT("Zer3"),
TEXT("Zer4"),
TEXT("Ze4S"),
TEXT("Zer6"),
TEXT("Zr7a"),
TEXT("Zr7g"),
TEXT("Zr7s"),
TEXT("Zer8"),
TEXT("Ze8T"),
TEXT("Zer9"),
TEXT("Z9ly"),
TEXT("Z9ry"),
TEXT("Z9lo"),
TEXT("Z9ro"),
TEXT("Z10a"),
TEXT("Z10b"),
TEXT("Z10c"),
TEXT("Z10d"),
TEXT("Z10e"),
TEXT("Pro1"),
TEXT("Pro2"),
TEXT("Pr3R"),
TEXT("Pr3G"),
TEXT("Pro4"),
TEXT("Pr5I"),
TEXT("Pr5B"),
TEXT("Pro7"),
TEXT("Pr7B"),
TEXT("Pr7S"),
TEXT("Pro8"),
TEXT("Pr8B"),
TEXT("Pr8D"),
TEXT("Pro9"),
TEXT("Pr9W"),
TEXT("Pr9Y"),
TEXT("Pr10"),
TEXT("P10C"),
TEXT("P10o"),
TEXT("PB1A"),
TEXT("PB1B"),
TEXT("PB1C"),
TEXT("PB1D"),
TEXT("PB1E"),
TEXT("PB1F"),
TEXT("PB2A"),
TEXT("PB2B"),
TEXT("PB2C"),
TEXT("PB2D"),
TEXT("PB2E"),
TEXT("PB2F"),
TEXT("PB3A"),
TEXT("PB3B"),
TEXT("PB3C"),
TEXT("PB3D"),
TEXT("PB3E"),
TEXT("PB3F"),
TEXT("PB4A"),
TEXT("PB4B"),
TEXT("PB4C"),
TEXT("PB4D"),
TEXT("PB4E"),
TEXT("PB4F"),
TEXT("PB5A"),
TEXT("PB5B"),
TEXT("PB5C"),
TEXT("PB5D"),
TEXT("PB5E"),
TEXT("PB5F"),
TEXT("PB6A"),
TEXT("PB6B"),
TEXT("PB6C"),
TEXT("PB6D"),
TEXT("PB6E"),
TEXT("PB6F"),
TEXT("PB7A"),
TEXT("PB7B"),
TEXT("PB7C"),
TEXT("PB7D"),
TEXT("PB7E"),
TEXT("PB7F"),
TEXT("PB8A"),
TEXT("PB8B"),
TEXT("PB8C"),
TEXT("PB8D"),
TEXT("PB8E"),
TEXT("PB8F"),
TEXT("TB1A"),
TEXT("TB1B"),
TEXT("TB1C"),
TEXT("TB1D"),
TEXT("TB1E"),
TEXT("TB1F"),
TEXT("TB2A"),
TEXT("TB2B"),
TEXT("TB2C"),
TEXT("TB2D"),
TEXT("TB2E"),
TEXT("TB2F"),
TEXT("TB3A"),
TEXT("TB3B"),
TEXT("TB3C"),
TEXT("TB3D"),
TEXT("TB3E"),
TEXT("TB3F"),
TEXT("TB4A"),
TEXT("TB4B"),
TEXT("TB4C"),
TEXT("TB4D"),
TEXT("TB4E"),
TEXT("TB4F"),
TEXT("TB5A"),
TEXT("TB5B"),
TEXT("TB5C"),
TEXT("TB5D"),
TEXT("TB5E"),
TEXT("TB5F"),
TEXT("TB6A"),
TEXT("TB6B"),
TEXT("TB6C"),
TEXT("TB6D"),
TEXT("TB6E"),
TEXT("TB6F"),
TEXT("TB7A"),
TEXT("TB7B"),
TEXT("TB7C"),
TEXT("TB7D"),
TEXT("TB7E"),
TEXT("TB7F"),
TEXT("TB8A"),
TEXT("TB8B"),
TEXT("TB8C"),
TEXT("TB8D"),
TEXT("TB8E"),
TEXT("TB8F"),
TEXT("ZB1A"),
TEXT("ZB1B"),
TEXT("ZB1C"),
TEXT("ZB1D"),
TEXT("ZB1E"),
TEXT("ZB1F"),
TEXT("ZB2A"),
TEXT("ZB2B"),
TEXT("ZB2C"),
TEXT("ZB2D"),
TEXT("ZB2E"),
TEXT("ZB2F"),
TEXT("ZB3A"),
TEXT("ZB3B"),
TEXT("ZB3C"),
TEXT("ZB3D"),
TEXT("ZB3E"),
TEXT("ZB3F"),
TEXT("ZB4A"),
TEXT("ZB4B"),
TEXT("ZB4C"),
TEXT("ZB4D"),
TEXT("ZB4E"),
TEXT("ZB4F"),
TEXT("ZB5A"),
TEXT("ZB5B"),
TEXT("ZB5C"),
TEXT("ZB5D"),
TEXT("ZB5E"),
TEXT("ZB5F"),
TEXT("ZB6A"),
TEXT("ZB6B"),
TEXT("ZB6C"),
TEXT("ZB6D"),
TEXT("ZB6E"),
TEXT("ZB6F"),
TEXT("ZB7A"),
TEXT("ZB7B"),
TEXT("ZB7C"),
TEXT("ZB7D"),
TEXT("ZB7E"),
TEXT("ZB7F"),
TEXT("ZB8A"),
TEXT("ZB8B"),
TEXT("ZB8C"),
TEXT("ZB8D"),
TEXT("ZB8E"),
TEXT("ZB8F"),
TEXT("ZB9A"),
TEXT("ZB9B"),
TEXT("ZB9C"),
TEXT("ZB9D"),
TEXT("ZB9E"),
TEXT("ZB9F"),
TEXT("ZB0A"),
TEXT("ZB0B"),
TEXT("ZB0C"),
TEXT("ZB0D"),
TEXT("ZB0E"),
TEXT("ZB0F"),
TEXT("TMCu"),
TEXT("ZMCu"),
TEXT("PMCu"),
TEXT("TMCx"),
TEXT("ZMCx"),
TEXT("PMCx"),
TEXT("TLOf"),
TEXT("TMED"),
TEXT("THIf"),
TEXT("TSUP"),
TEXT("TARE"),
TEXT("ZLOf"),
TEXT("ZMED"),
TEXT("ZHIf"),
TEXT("ZSUP"),
TEXT("ZARE"),
TEXT("PLOf"),
TEXT("PMED"),
TEXT("PHIf"),
TEXT("PSUP"),
TEXT("PARE"),
TEXT("TLOx"),
TEXT("TMEx"),
TEXT("THIx"),
TEXT("TSUx"),
TEXT("TARx"),
TEXT("ZLOx"),
TEXT("ZMEx"),
TEXT("ZHIx"),
TEXT("ZSUx"),
TEXT("ZARx"),
TEXT("PLOx"),
TEXT("PMEx"),
TEXT("PHIx"),
TEXT("PSUx"),
TEXT("PARx"),
TEXT("Suic"),
TEXT("SuiR"),
TEXT("Rscu"),
TEXT("+Vi0"),
TEXT("+Vi1"),
TEXT("+Vi2"),
TEXT("+Vi3"),
TEXT("+Vi4"),
TEXT("+Vi5"),
TEXT("+Vi6"),
TEXT("+Vi7"),
TEXT("-Vi0"),
TEXT("-Vi1"),
TEXT("-Vi2"),
TEXT("-Vi3"),
TEXT("-Vi4"),
TEXT("-Vi5"),
TEXT("-Vi6"),
TEXT("-Vi7"),
TEXT("MvTe"),
TEXT("ClrC"),
TEXT("Enmy"),
TEXT("Ally"),
TEXT("VluA"),
TEXT("EnBk"),
TEXT("StTg"),
TEXT("StPt"),
TEXT("EnTr"),
TEXT("ExTr"),
TEXT("NuHe"),
TEXT("HaHe"),
TEXT("JYDg"),
TEXT("DWHe"),
TEXT("ReHe") };


const TCHAR AILongNames[NumAIScripts][100] = {
TEXT("Terran 3 - Zerg Town"),
TEXT("Terran 5 - Terran Main Town"),
TEXT("Terran 5 - Terran Harvest Town"),
TEXT("Terran 6 - Air Attack Zerg"),
TEXT("Terran 6 - Ground Attack Zerg"),
TEXT("Terran 6 - Zerg Support Town"),
TEXT("Terran 7 - Bottom Zerg Town"),
TEXT("Terran 7 - Right Zerg Town"),
TEXT("Terran 7 - Middle Zerg Town"),
TEXT("Terran 8 - Confederate Town"),
TEXT("Terran 9 - Light Attack"),
TEXT("Terran 9 - Heavy Attack"),
TEXT("Terran 10 - Confederate Towns"),
TEXT("Terran 11 - Zerg Town"),
TEXT("Terran 11 - Lower Protoss Town"),
TEXT("Terran 11 - Upper Protoss Town"),
TEXT("Terran 12 - Nuke Town"),
TEXT("Terran 12 - Phoenix Town"),
TEXT("Terran 12 - Tank Town"),
TEXT("Terran 1 - Electronic Distribution"),
TEXT("Terran 2 - Electronic Distribution"),
TEXT("Terran 3 - Electronic Distribution"),
TEXT("Terran 1 - Shareware"),
TEXT("Terran 2 - Shareware"),
TEXT("Terran 3 - Shareware"),
TEXT("Terran 4 - Shareware"),
TEXT("Terran 5 - Shareware"),
TEXT("Zerg 1 - Terran Town"),
TEXT("Zerg 2 - Protoss Town"),
TEXT("Zerg 3 - Terran Town"),
TEXT("Zerg 4 - Right Terran Town"),
TEXT("Zerg 4 - Lower Terran Town"),
TEXT("Zerg 6 - Protoss Town"),
TEXT("Zerg 7 - Air Town"),
TEXT("Zerg 7 - Ground Town"),
TEXT("Zerg 7 - Support Town"),
TEXT("Zerg 8 - Scout Town"),
TEXT("Zerg 8 - Templar Town"),
TEXT("Zerg 9 - Teal Protoss"),
TEXT("Zerg 9 - Left Yellow Protoss"),
TEXT("Zerg 9 - Right Yellow Protoss"),
TEXT("Zerg 9 - Left Orange Protoss"),
TEXT("Zerg 9 - Right Orange Protoss"),
TEXT("Zerg 10 - Left Teal (Attack)"),
TEXT("Zerg 10 - Right Teal (Support)"),
TEXT("Zerg 10 - Left Yellow (Support)"),
TEXT("Zerg 10 - Right Yellow (Attack)"),
TEXT("Zerg 10 - Red Protoss"),
TEXT("Protoss 1 - Zerg Town"),
TEXT("Protoss 2 - Zerg Town"),
TEXT("Protoss 3 - Air Zerg Town"),
TEXT("Protoss 3 - Ground Zerg Town"),
TEXT("Protoss 4 - Zerg Town"),
TEXT("Protoss 5 - Zerg Town Island"),
TEXT("Protoss 5 - Zerg Town Base"),
TEXT("Protoss 7 - Left Protoss Town"),
TEXT("Protoss 7 - Right Protoss Town"),
TEXT("Protoss 7 - Shrine Protoss"),
TEXT("Protoss 8 - Left Protoss Town"),
TEXT("Protoss 8 - Right Protoss Town"),
TEXT("Protoss 8 - Protoss Defenders"),
TEXT("Protoss 9 - Ground Zerg"),
TEXT("Protoss 9 - Air Zerg"),
TEXT("Protoss 9 - Spell Zerg"),
TEXT("Protoss 10 - Mini-Ttowns"),
TEXT("Protoss 10 - Mini-Town Master"),
TEXT("Protoss 10 - Overmind Defenders"),
TEXT("Brood Wars Protoss 1 - Town A"),
TEXT("Brood Wars Protoss 1 - Town B"),
TEXT("Brood Wars Protoss 1 - Town C"),
TEXT("Brood Wars Protoss 1 - Town D"),
TEXT("Brood Wars Protoss 1 - Town E"),
TEXT("Brood Wars Protoss 1 - Town F"),
TEXT("Brood Wars Protoss 2 - Town A"),
TEXT("Brood Wars Protoss 2 - Town B"),
TEXT("Brood Wars Protoss 2 - Town C"),
TEXT("Brood Wars Protoss 2 - Town D"),
TEXT("Brood Wars Protoss 2 - Town E"),
TEXT("Brood Wars Protoss 2 - Town F"),
TEXT("Brood Wars Protoss 3 - Town A"),
TEXT("Brood Wars Protoss 3 - Town B"),
TEXT("Brood Wars Protoss 3 - Town C"),
TEXT("Brood Wars Protoss 3 - Town D"),
TEXT("Brood Wars Protoss 3 - Town E"),
TEXT("Brood Wars Protoss 3 - Town F"),
TEXT("Brood Wars Protoss 4 - Town A"),
TEXT("Brood Wars Protoss 4 - Town B"),
TEXT("Brood Wars Protoss 4 - Town C"),
TEXT("Brood Wars Protoss 4 - Town D"),
TEXT("Brood Wars Protoss 4 - Town E"),
TEXT("Brood Wars Protoss 4 - Town F"),
TEXT("Brood Wars Protoss 5 - Town A"),
TEXT("Brood Wars Protoss 5 - Town B"),
TEXT("Brood Wars Protoss 5 - Town C"),
TEXT("Brood Wars Protoss 5 - Town D"),
TEXT("Brood Wars Protoss 5 - Town E"),
TEXT("Brood Wars Protoss 5 - Town F"),
TEXT("Brood Wars Protoss 6 - Town A"),
TEXT("Brood Wars Protoss 6 - Town B"),
TEXT("Brood Wars Protoss 6 - Town C"),
TEXT("Brood Wars Protoss 6 - Town D"),
TEXT("Brood Wars Protoss 6 - Town E"),
TEXT("Brood Wars Protoss 6 - Town F"),
TEXT("Brood Wars Protoss 7 - Town A"),
TEXT("Brood Wars Protoss 7 - Town B"),
TEXT("Brood Wars Protoss 7 - Town C"),
TEXT("Brood Wars Protoss 7 - Town D"),
TEXT("Brood Wars Protoss 7 - Town E"),
TEXT("Brood Wars Protoss 7 - Town F"),
TEXT("Brood Wars Protoss 8 - Town A"),
TEXT("Brood Wars Protoss 8 - Town B"),
TEXT("Brood Wars Protoss 8 - Town C"),
TEXT("Brood Wars Protoss 8 - Town D"),
TEXT("Brood Wars Protoss 8 - Town E"),
TEXT("Brood Wars Protoss 8 - Town F"),
TEXT("Brood Wars Terran 1 - Town A"),
TEXT("Brood Wars Terran 1 - Town B"),
TEXT("Brood Wars Terran 1 - Town C"),
TEXT("Brood Wars Terran 1 - Town D"),
TEXT("Brood Wars Terran 1 - Town E"),
TEXT("Brood Wars Terran 1 - Town F"),
TEXT("Brood Wars Terran 2 - Town A"),
TEXT("Brood Wars Terran 2 - Town B"),
TEXT("Brood Wars Terran 2 - Town C"),
TEXT("Brood Wars Terran 2 - Town D"),
TEXT("Brood Wars Terran 2 - Town E"),
TEXT("Brood Wars Terran 2 - Town F"),
TEXT("Brood Wars Terran 3 - Town A"),
TEXT("Brood Wars Terran 3 - Town B"),
TEXT("Brood Wars Terran 3 - Town C"),
TEXT("Brood Wars Terran 3 - Town D"),
TEXT("Brood Wars Terran 3 - Town E"),
TEXT("Brood Wars Terran 3 - Town F"),
TEXT("Brood Wars Terran 4 - Town A"),
TEXT("Brood Wars Terran 4 - Town B"),
TEXT("Brood Wars Terran 4 - Town C"),
TEXT("Brood Wars Terran 4 - Town D"),
TEXT("Brood Wars Terran 4 - Town E"),
TEXT("Brood Wars Terran 4 - Town F"),
TEXT("Brood Wars Terran 5 - Town A"),
TEXT("Brood Wars Terran 5 - Town B"),
TEXT("Brood Wars Terran 5 - Town C"),
TEXT("Brood Wars Terran 5 - Town D"),
TEXT("Brood Wars Terran 5 - Town E"),
TEXT("Brood Wars Terran 5 - Town F"),
TEXT("Brood Wars Terran 6 - Town A"),
TEXT("Brood Wars Terran 6 - Town B"),
TEXT("Brood Wars Terran 6 - Town C"),
TEXT("Brood Wars Terran 6 - Town D"),
TEXT("Brood Wars Terran 6 - Town E"),
TEXT("Brood Wars Terran 6 - Town F"),
TEXT("Brood Wars Terran 7 - Town A"),
TEXT("Brood Wars Terran 7 - Town B"),
TEXT("Brood Wars Terran 7 - Town C"),
TEXT("Brood Wars Terran 7 - Town D"),
TEXT("Brood Wars Terran 7 - Town E"),
TEXT("Brood Wars Terran 7 - Town F"),
TEXT("Brood Wars Terran 8 - Town A"),
TEXT("Brood Wars Terran 8 - Town B"),
TEXT("Brood Wars Terran 8 - Town C"),
TEXT("Brood Wars Terran 8 - Town D"),
TEXT("Brood Wars Terran 8 - Town E"),
TEXT("Brood Wars Terran 8 - Town F"),
TEXT("Brood Wars Zerg 1 - Town A"),
TEXT("Brood Wars Zerg 1 - Town B"),
TEXT("Brood Wars Zerg 1 - Town C"),
TEXT("Brood Wars Zerg 1 - Town D"),
TEXT("Brood Wars Zerg 1 - Town E"),
TEXT("Brood Wars Zerg 1 - Town F"),
TEXT("Brood Wars Zerg 2 - Town A"),
TEXT("Brood Wars Zerg 2 - Town B"),
TEXT("Brood Wars Zerg 2 - Town C"),
TEXT("Brood Wars Zerg 2 - Town D"),
TEXT("Brood Wars Zerg 2 - Town E"),
TEXT("Brood Wars Zerg 2 - Town F"),
TEXT("Brood Wars Zerg 3 - Town A"),
TEXT("Brood Wars Zerg 3 - Town B"),
TEXT("Brood Wars Zerg 3 - Town C"),
TEXT("Brood Wars Zerg 3 - Town D"),
TEXT("Brood Wars Zerg 3 - Town E"),
TEXT("Brood Wars Zerg 3 - Town F"),
TEXT("Brood Wars Zerg 4 - Town A"),
TEXT("Brood Wars Zerg 4 - Town B"),
TEXT("Brood Wars Zerg 4 - Town C"),
TEXT("Brood Wars Zerg 4 - Town D"),
TEXT("Brood Wars Zerg 4 - Town E"),
TEXT("Brood Wars Zerg 4 - Town F"),
TEXT("Brood Wars Zerg 5 - Town A"),
TEXT("Brood Wars Zerg 5 - Town B"),
TEXT("Brood Wars Zerg 5 - Town C"),
TEXT("Brood Wars Zerg 5 - Town D"),
TEXT("Brood Wars Zerg 5 - Town E"),
TEXT("Brood Wars Zerg 5 - Town F"),
TEXT("Brood Wars Zerg 6 - Town A"),
TEXT("Brood Wars Zerg 6 - Town B"),
TEXT("Brood Wars Zerg 6 - Town C"),
TEXT("Brood Wars Zerg 6 - Town D"),
TEXT("Brood Wars Zerg 6 - Town E"),
TEXT("Brood Wars Zerg 6 - Town F"),
TEXT("Brood Wars Zerg 7 - Town A"),
TEXT("Brood Wars Zerg 7 - Town B"),
TEXT("Brood Wars Zerg 7 - Town C"),
TEXT("Brood Wars Zerg 7 - Town D"),
TEXT("Brood Wars Zerg 7 - Town E"),
TEXT("Brood Wars Zerg 7 - Town F"),
TEXT("Brood Wars Zerg 8 - Town A"),
TEXT("Brood Wars Zerg 8 - Town B"),
TEXT("Brood Wars Zerg 8 - Town C"),
TEXT("Brood Wars Zerg 8 - Town D"),
TEXT("Brood Wars Zerg 8 - Town E"),
TEXT("Brood Wars Zerg 8 - Town F"),
TEXT("Brood Wars Zerg 9 - Town A"),
TEXT("Brood Wars Zerg 9 - Town B"),
TEXT("Brood Wars Zerg 9 - Town C"),
TEXT("Brood Wars Zerg 9 - Town D"),
TEXT("Brood Wars Zerg 9 - Town E"),
TEXT("Brood Wars Zerg 9 - Town F"),
TEXT("Brood Wars Zerg 10 - Town A"),
TEXT("Brood Wars Zerg 10 - Town B"),
TEXT("Brood Wars Zerg 10 - Town C"),
TEXT("Brood Wars Zerg 10 - Town D"),
TEXT("Brood Wars Zerg 10 - Town E"),
TEXT("Brood Wars Zerg 10 - Town F"),
TEXT("Terran Custom Level"),
TEXT("Zerg Custom Level"),
TEXT("Protoss Custom Level"),
TEXT("Terran Expansion Custom Level"),
TEXT("Zerg Expansion Custom Level"),
TEXT("Protoss Expansion Custom Level"),
TEXT("Terran Campaign Easy"),
TEXT("Terran Campaign Medium"),
TEXT("Terran Campaign Difficult"),
TEXT("Terran Campaign Insane"),
TEXT("Terran Campaign Area Town"),
TEXT("Zerg Campaign Easy"),
TEXT("Zerg Campaign Medium"),
TEXT("Zerg Campaign Difficult"),
TEXT("Zerg Campaign Insane"),
TEXT("Zerg Campaign Area Town"),
TEXT("Protoss Campaign Easy"),
TEXT("Protoss Campaign Medium"),
TEXT("Protoss Campaign Difficult"),
TEXT("Protoss Campaign Insane"),
TEXT("Protoss Campaign Area Town"),
TEXT("Expansion Terran Campaign Easy"),
TEXT("Expansion Terran Campaign Medium"),
TEXT("Expansion Terran Campaign Difficult"),
TEXT("Expansion Terran Campaign Insane"),
TEXT("Expansion Terran Campaign Area Town"),
TEXT("Expansion Zerg Campaign Easy"),
TEXT("Expansion Zerg Campaign Medium"),
TEXT("Expansion Zerg Campaign Difficult"),
TEXT("Expansion Zerg Campaign Insane"),
TEXT("Expansion Zerg Campaign Area Town"),
TEXT("Expansion Protoss Campaign Easy"),
TEXT("Expansion Protoss Campaign Medium"),
TEXT("Expansion Protoss Campaign Difficult"),
TEXT("Expansion Protoss Campaign Insane"),
TEXT("Expansion Protoss Campaign Area Town"),
TEXT("Send All Units on Strategic Suicide Missions"),
TEXT("Send All Units on Random Suicide Missions"),
TEXT("Switch Computer Player To Rescue Passive"),
TEXT("Turn ON Shared Vision of Player 1 with current player"),
TEXT("Turn ON Shared Vision of Player 2 with current player"),
TEXT("Turn ON Shared Vision of Player 3 with current player"),
TEXT("Turn ON Shared Vision of Player 4 with current player"),
TEXT("Turn ON Shared Vision of Player 5 with current player"),
TEXT("Turn ON Shared Vision of Player 6 with current player"),
TEXT("Turn ON Shared Vision of Player 7 with current player"),
TEXT("Turn ON Shared Vision of Player 8 with current player"),
TEXT("Turn OFF Shared Vision of Player 1 with current player"),
TEXT("Turn OFF Shared Vision of Player 2 with current player"),
TEXT("Turn OFF Shared Vision of Player 3 with current player"),
TEXT("Turn OFF Shared Vision of Player 4 with current player"),
TEXT("Turn OFF Shared Vision of Player 5 with current player"),
TEXT("Turn OFF Shared Vision of Player 6 with current player"),
TEXT("Turn OFF Shared Vision of Player 7 with current player"),
TEXT("Turn OFF Shared Vision of Player 8 with current player"),
TEXT("Move Dark Templars To Region"),
TEXT("Clear Previous Combat Data"),
TEXT("Set Player To Enemy here"),
TEXT("Set Player To Ally here"),
TEXT("Value This Area Higher"),
TEXT("Enter Closest Bunker"),
TEXT("Set Generic Command Target"),
TEXT("Make These Units Patrol"),
TEXT("Enter Transport"),
TEXT("Exit Transport"),
TEXT("AI Nuke Here"),
TEXT("AI Harass Here"),
TEXT("Set Unit Order To: Junk Yard Dog"),
TEXT("Cast Disruption Web"),
TEXT("Cast Recall (Arbiter required)") };

nlight
Profile Joined October 2011
Bulgaria58 Posts
April 30 2017 12:58 GMT
#68
On April 30 2017 21:20 S.I. wrote:
Have fun!


Awesome! Thank you so much, I'll be implementing all of these asap.
S.I.
Profile Joined April 2017
58 Posts
April 30 2017 13:14 GMT
#69
Looking back on it using a 2D array would have been better... but its 15 year old code ;(
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-30 16:09:59
April 30 2017 13:18 GMT
#70
On April 30 2017 22:14 S.I. wrote:
Looking back on it using a 2D array would have been better... but its 15 year old code ;(


Doesn't really matter to me, I already added them to LangUMS so thanks again.

New feature - template event declarations, so you don't have to write a million event handlers.


for <PlayerId> in (Player1, Player2, Player3, Player4, Player5, Player6) {
accumulate(PlayerId, AtLeast, 10, Minerals),
bring(PlayerId, AtLeast, 1, AllUnits, BuyMarines) => {
take_resource(PlayerId, Minerals, 10);
spawn(TerranMarine, PlayerId, 1, BuyMarines);
print("You purchased a marine, take good care of it.");
}
}


You can repeat players, locations, unit types, pretty much anything with these.
integral
Profile Blog Joined February 2009
United States3156 Posts
April 30 2017 16:23 GMT
#71
Welcome to TL, SI! Big fan.
Whiplash
Profile Blog Joined October 2008
United States2929 Posts
Last Edited: 2017-04-30 16:50:09
April 30 2017 16:49 GMT
#72
Will your editor be able to do advanced functions that programs in the past like firegraft/memgraft have been able to do such as assigning abilities to different units, or replacing unit/portrait graphics with new content, or terrain blending between different titlesets? Doing this without a custom exe is the kind of flexibility I want in SC1.

BTW I'd check the http://www.campaigncreations.org/forum/ forums, there are a lot of old school modders/campaign creators there, potentially a good place to share your work.
Cinematographer / Steadicam Operator. Former Starcraft commentator/player
integral
Profile Blog Joined February 2009
United States3156 Posts
April 30 2017 16:50 GMT
#73
nlight I think I might be the only mapmaker in the world who has a current need to use arrays, and I don't know enough computer science to intuitively grok your implementation here. I don't really have a specific question because I'm not even sure what you've done.

+ Show Spoiler +

global player_score[8];

deaths(Player2, AtLeast, 1, TerranMarine) => {
remove_deaths(Player2, TerranMarine, 1);
player_score[0]++;
player_score[1]++;
}

fn main() {
var foo[4];
foo[0] = 15;
foo[1] = 42;

if (foo[0] == 15) {
print("foo[0] == 15");
}

if ((foo[1] * 2) == 84) {
print("(foo[1] * 2) == 84");
}

while (true) {
poll_events();
}
}



So my understanding is that you're defining an array with 5 elements, 0-4, and then you're able to do stuff with that. What does that look like in triggers though? A unique death count for each element, I assume?
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-04-30 17:22:39
April 30 2017 17:13 GMT
#74
with 5 elements, 0-4


It's four elements - foo[N] declares an array with size N so foo[4] will declare foo with 4 elements.

What does that look like in triggers though? A unique death count for each element, I assume?


Yeah. Each array element takes a register (i.e. death count). It's fair to say that "regular" variables are just arrays with size of one as far as the compiler treats them. Arrays don't survive past the IR phase, they are more or less what you'd call "syntax sugar". Indexing with anything that's not a constant literal is not possible at the moment e.g. being able to say "myArray[someVariable]". Though there are (inefficient) ways to implement it so I'll look into that in the future.

On another note I've started making a "real" playable map to use as example. You can follow the progress here - https://github.com/AlexanderDzhoganov/langums/tree/master/examples
integral
Profile Blog Joined February 2009
United States3156 Posts
April 30 2017 17:30 GMT
#75
On May 01 2017 02:13 nlight wrote:
Show nested quote +
with 5 elements, 0-4


It's four elements - foo[N] declares an array with size N so foo[4] will declare foo with 4 elements.


Ah, ok.

Yeah. Each array element takes a register (i.e. death count). It's fair to say that "regular" variables are just arrays with size of one as far as the compiler treats them. Arrays don't survive past the IR phase, they are more or less what you'd call "syntax sugar". Indexing with anything that's not a constant literal is not possible at the moment e.g. being able to say "myArray[someVariable]". Though there are (inefficient) ways to implement it so I'll look into that in the future.


Everything in starcraft coding is super inefficient, I dunno how the developers could stand making maps and the campaign without actual variables and operators. Kinda boggles my mind a bit.

On another note I've started making a "real" playable map to use as example. You can follow the progress here - https://github.com/AlexanderDzhoganov/langums/tree/master/examples

An example map will be super helpful, thanks. I can't read code very well or fast but I am fluent in triggers
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-01 13:59:57
May 01 2017 13:58 GMT
#76
I have a question. I am getting this really weird repeating sound on my example map about 30 seconds after the map starts.

Here is a video, sound starts at 11 seconds and keeps repeating. Please tell me how to find out what's causing it.

Freakling
Profile Joined October 2012
Germany1533 Posts
May 01 2017 14:53 GMT
#77
That sound is the Terran rescue unit sound (sound\misc\TRescue.wav). Either you have some trigger using that sound directly, or you are creating rescuable units (units for a player set to rescuable) somewhere near your own.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-01 17:09:00
May 01 2017 17:08 GMT
#78
Hi! I by no means mean to deter you from continuing this project (I think it's awesome), but as is the code seems to be a bit difficult to read (i.e. just by looking at your code, it's hard to tell what exactly everything does).

Is there a way you could make it more readable?
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-01 17:29:37
May 01 2017 17:23 GMT
#79
On May 02 2017 02:08 Powder_Keg wrote:
Hi! I by no means mean to deter you from continuing this project (I think it's awesome), but as is the code seems to be a bit difficult to read (i.e. just by looking at your code, it's hard to tell what exactly everything does).

Is there a way you could make it more readable?


You mean the code of the compiler or the LangUMS language itself? Also you'll have to be more specific, which parts do you find unreadable? Maybe give examples.

On May 01 2017 23:53 Freakling wrote:
That sound is the Terran rescue unit sound (sound\misc\TRescue.wav). Either you have some trigger using that sound directly, or you are creating rescuable units (units for a player set to rescuable) somewhere near your own.


It turned out to be a glitched map issue, not triggers related. I'm still investigating what's up.
Powder_Keg
Profile Joined May 2017
8 Posts
May 01 2017 17:59 GMT
#80
Maybe it's just me, and maybe it's just that your language is meant to be understood differently from what people are used to, but here's what I had trouble understanding while reading through your code:

  • When triggers start and when they end
  • Which players own the triggers
  • What variables are deathcounters and what are just integers (similarly boolians and switches)


Though, these are relatively minor complaints. Looking through it again the code is quite understandable, it just takes some getting used to.
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-01 18:32:01
May 01 2017 18:24 GMT
#81
On May 02 2017 02:59 Powder_Keg wrote:
Maybe it's just me, and maybe it's just that your language is meant to be understood differently from what people are used to, but here's what I had trouble understanding while reading through your code:


I think you have a misunderstanding of what the langums language is. It's an imperative language (meaning statements are executed sequentially, never out of order) not unlike C or JavaScript. It is not meant to be read like scmdraft trigger lists. Control starts at the top of the main() function and executes statements one by one. Typically you'll see something like


while(true) {
poll_events();
}


at the end of the main() function. This makes it so all event handlers get executed one after another indefinitely. Again, there is no out of order execution, everything is sequential and linearizable.

[*]What variables are deathcounters and what are just integers (similarly boolians and switches)


All variables are unsigned integers but the underlying storage is death counters. This is abstracted away from the user more or less.

[*]Which players own the triggers


You can set that with the --triggers-owner command-line argument.

[*]When triggers start and when they end


The emitted triggers are vastly different than the langums code and really hard to follow for a human in the same way machine code is hard to follow for a human. You don't really care about that when using this tool.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-01 18:32:05
May 01 2017 18:30 GMT
#82
I think you have a misunderstanding of what the langums language is. It's an imperative language (meaning statements are executed sequentially, never out of order) not unlike C or JavaScript. It is not meant to be read like scmdraft trigger lists.


Your code generates triggers which the map will run through sequentially, that I understand (or am I wrong here? I don't see how I could be.)

What I don't understand from your code is when it generates those triggers.
nlight
Profile Joined October 2011
Bulgaria58 Posts
May 01 2017 18:34 GMT
#83
What I don't understand from your code is when it generates those triggers.


You really shouldn't care about what actual triggers are emitted as long as you can observe the behavior described by the LangUMS code you've written. Well, unless you're working on the compiler itself.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-01 19:08:26
May 01 2017 18:38 GMT
#84
hmmm Can you run through the logic behind how your code decides what triggers to generate please? Without that I just won't understand what I'm doing.

I know how something like

if( conditions ){
deathcounter1 += deathcounter2;
}

would work using switches.

(e.g. the triggers outputted would have "Set Switch1" as an action, and then it would be 32 or so triggers to do a binary addition or w/e it's called adding deathcounter2 to deathcounter1 with each trigger having "Switch 1 is Set" as one of their condition)

Edit: Also, for example, if I just write

var integer = 5

does that take up a deathcounter slot?
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-01 19:39:15
May 01 2017 19:36 GMT
#85

if( conditions ){
deathcounter1 += deathcounter2;
}


The if condition is implemented using two triggers - one will have the false condition, the other the true condition. Depending on which one executes the "instruction counter" will be set to a different location effectively jumping to another point of execution. Basically every emitted trigger begins with a check if the current value of the instruction counter is equal to its address. This way we turn the inherently parallel triggers into a sequential machine. No switches are used for this. Switches are used as mutexes for some operations internally but they are not exposed to the user in any way I think.

Also, for example, if I just write

var integer = 5

does that take up a deathcounter slot?


Yes. Every variable takes up a death count slot and every array takes up as many slots as its size. Local variables exist only for the duration of their block (code surrounded by {}) and their storage gets reused.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-01 19:46:31
May 01 2017 19:41 GMT
#86
So each trigger outputted has a "Deathcounter == X" where X is the line of the code, basically?

Also, triggers are by default sequential - StarCraft runs through them from the top to the bottom, but you probably already knew that.

Edit: Would that sometimes cause some triggers to not be run until the next trigger cycle though? for example, lets say you are at line 500 and then now you want to next execute line 200 - to do that you have to wait until the next trigger cycle, which takes up like 1/11 of a second O_O
nlight
Profile Joined October 2011
Bulgaria58 Posts
May 01 2017 19:49 GMT
#87
On May 02 2017 04:41 Powder_Keg wrote:
So each trigger outputted has a "Deathcounter == X" where X is the line of the code, basically?


This is a relatively simplistic way to put it but yeah.

Also, triggers are by default sequential - StarCraft runs through them from the top to the bottom, but you probably already knew that.


They are executed in sequence by the game code by virtue of the game code being sequential but they are inherently a parallel machine. This "design" makes it easy to introduce race conditions (the bane of sane programming) in your logic. LangUMS actively prevents you from introducing race conditions unless you try really hard to twist it. That's the biggest gain from all this. In the end it's all just automation for something absolutely doable by hand but very tedious and error-prone.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-01 19:56:17
May 01 2017 19:51 GMT
#88
What is a race condition?

Edit: nvm, found it https://en.wikipedia.org/wiki/Race_condition

Thanks for answering all my questions btw, I appreciate it :D

What about this question:
Edit: Would that sometimes cause some triggers to not be run until the next trigger cycle though? for example, lets say you are at line 500 and then now you want to next execute line 200 - to do that you have to wait until the next trigger cycle, which takes up like 1/11 of a second O_O

nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-02 02:07:04
May 01 2017 20:42 GMT
#89
Would that sometimes cause some triggers to not be run until the next trigger cycle though? for example, lets say you are at line 500 and then now you want to next execute line 200 - to do that you have to wait until the next trigger cycle, which takes up like 1/11 of a second O_O


Yeah, jumps take one full cycle to execute in the worst case, though that is amortized by some compiler optimizations and it will only get better at it. This isn't any better if you sequence the triggers by hand.

EDIT: On second thought, maybe you're asking doesn't that mean you will miss in-game events if your code happens to be doing something else at that time. The answer is yes and no. All events are currently buffered but only once. Say you have a "bring marines to x" condition in your code. If the player brings the marines but 20 cycles pass between the calls to poll_events() it won't fire off the event 20 times but just 1. This can be an advantage or a drawback depending on where you're coming from. It's totally possible to buffer all 20 events and fire them off but I think it's more useful the other way around. I can turn this into an option eventually.
ZurgMaster
Profile Joined May 2017
Canada2 Posts
May 04 2017 17:06 GMT
#90
If you still need/want testers, I'm all for it. Just PM me.
"A life is like a garden. Perfect moments can be had, but not preserved, except in memory." – Leonard Nimoy, 2015
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-04 19:12:35
May 04 2017 18:44 GMT
#91
On May 05 2017 02:06 ZurgMaster wrote:
If you still need/want testers, I'm all for it. Just PM me.


Join the Discord @ https://discord.gg/TNehfve that's where we hang out.

Also new features in langums - repeat templates, so you don't have to repeat code for lists of things. Use like:


fn spawn_bonus_items() {
for <Loc> in (BonusLocation1, BonusLocation2, BonusLocation3) {
spawn(PowerupKhalisCrystal, Player8, 1, Loc);
}
}


The bigger news is that a live debugger with breakpoints and variable inspection for VS Code is almost ready and will be available to test soon.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-05 05:14:35
May 05 2017 04:54 GMT
#92
I am confused on why you say SC is inherently parallel.

SC runs triggers in the following way:

1. It first unpacks all triggers belonging to "Force 1," Force 2," etc., and changes them to belong to just the players in those forces - e.g. if Player 1 and Player 2 are in Force 1, then a trigger owned by Force 1 is the same thing as a trigger owned by Player 1 and Player 2. Similarly, a trigger owned by Current Player or All Players is the same thing as a trigger owned by Player 1, Player 2, etc. all the way to Player 8.

2. It then runs through all triggers owned by Player 1, from the top of the list to the bottom of the list. After this has finished it runs through all triggers owned Player 2, and then Player 3, etc. all the way to Player 8.

3. It then repeats this process.

^ How is that not sequential?

EDIT: On second thought, maybe you're asking doesn't that mean you will miss in-game events if your code happens to be doing something else at that time. The answer is yes and no. All events are currently buffered but only once. Say you have a "bring marines to x" condition in your code. If the player brings the marines but 20 cycles pass between the calls to poll_events() it won't fire off the event 20 times but just 1. This can be an advantage or a drawback depending on where you're coming from. It's totally possible to buffer all 20 events and fire them off but I think it's more useful the other way around. I can turn this into an option eventually.


I gotta be honest, I don't understand a lot of what you just said. What does it mean "All events are currently buffered but only once?" What does poll_events() do? If the player brings 20 marines to the location, and this poll_events() doesn't fire, and then the player removes 20 marines from the location, and then poll_events() does fire, will it not realize that in the meantime the player has brought 20 marines to the location?


Yeah, jumps take one full cycle to execute in the worst case, though that is amortized by some compiler optimizations and it will only get better at it. This isn't any better if you sequence the triggers by hand.


So does this mean that sometimes the triggers wont run immediately? e.g. if I have a "Player brings at least 1 Terran marine to location X" condition, and in game player brings a marine to location X, that there is a chance that the trigger still wont execute because there's some inner workings that have to be sorted out first? This sounds like something that could actually totally break a map, and is something that using normal triggers no one would ever have to worry about - i.e. it sounds like it would just be more difficult to make stuff using this than it is otherwise


nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-05 11:04:47
May 05 2017 10:59 GMT
#93
^ How is that not sequential?


Triggers may be executed sequentially in reality but they are inherently a parallel machine i.e. two unrelated statements in different parts of the program can, in effect, act at once and modify the same parts of memory. This is essentially parallelism and suffers from the drawbacks of any parallel machine (you need locking to avoid data races).

If the player brings 20 marines to the location, and this poll_events() doesn't fire, and then the player removes 20 marines from the location, and then poll_events() does fire, will it not realize that in the meantime the player has brought 20 marines to the location?


Yes it will that's the point of buffering the events so you don't lose any.

So does this mean that sometimes the triggers wont run immediately?


Nothing ever runs "immediately". Your CPU needs time to execute instructions after all.

To answer your question, if the main langums loop is busy with something else and you're not calling poll_events() quickly enough it may delay stuff (but not break it). This can be anywhere from one trigger cycle to many depending on what you're doing in the code.

if I have a "Player brings at least 1 Terran marine to location X" condition, and in game player brings a marine to location X, that there is a chance that the trigger still wont execute because there's some inner workings that have to be sorted out first?


I don't know where you got that from. LangUMS doesn't roll dice to figure out if your stuff will run properly or not. It has pretty well defined semantics and the code does what it says. The trigger will be executed for sure on the next poll_events() call.
Powder_Keg
Profile Joined May 2017
8 Posts
Last Edited: 2017-05-05 18:10:26
May 05 2017 18:02 GMT
#94
Triggers may be executed sequentially in reality but they are inherently a parallel machine i.e. two unrelated statements in different parts of the program can, in effect, act at once and modify the same parts of memory. This is essentially parallelism and suffers from the drawbacks of any parallel machine (you need locking to avoid data races).


. . . But two triggers are never run at the same time. They are always checked in the same cycle, and they can both run in the same cycle, but even then SC will just run the first one first in the cycle and the second one second in the cycle. I still don't understand why you say it is parallel. Can you give a concrete example of SC executing triggers in parallel please?

Yes it will that's the point of buffering the events so you don't lose any.


Then why not poll_events() every trigger cycle? I don't understand why this was introduced - what is it's purpose?


Nothing ever runs "immediately". Your CPU needs time to execute instructions after all.



I meant in the same trigger cycle that you meet those conditions. It sounds like with langUMS all the conditions of a trigger can be met for a trigger cycle or two and then become unmet and the triggers would never know.

I don't know where you got that from. LangUMS doesn't roll dice to figure out if your stuff will run properly or not. It has pretty well defined semantics and the code does what it says. The trigger will be executed for sure on the next poll_events() call.


I get that the code determines what happens, but I guess the problem here is I don't understand the code, and from what it sounds like the expected behavior is difficult to determine. I mean, a lot of trigger systems require things to be 'trigger-cycle' perfect (i.e. for triggers to execute as soon as the conditions are met), but with this it seems like sometimes this won't happen?
KhaosKreator
Profile Joined April 2009
Canada145 Posts
May 05 2017 18:57 GMT
#95
I'm going to try to get involved in this and make some test maps this weekend, I think.

I am still confused in the same way Powder Keg is confused though.
Kyrie, Ignis Divine, Eleison
nlight
Profile Joined October 2011
Bulgaria58 Posts
Last Edited: 2017-05-06 00:43:09
May 05 2017 22:44 GMT
#96
On May 06 2017 03:02 Powder_Keg wrote:
Triggers may be executed sequentially in reality but they are inherently a parallel machine i.e. two unrelated statements in different parts of the program can, in effect, act at once and modify the same parts of memory. This is essentially parallelism and suffers from the drawbacks of any parallel machine (you need locking to avoid data races).


That's what I mean by parallel. Two triggers can execute during the same cycle and without some form of locking if they access the same "memory" (death counts or whatever else) it creates a data race. This is an issue that experienced map makers are just used to dealing with but it's not simple and is prone to mistakes.

Then why not poll_events() every trigger cycle? I don't understand why this was introduced - what is it's purpose?


The purpose of poll_events() is to run the associated code for any event handlers whose conditions have been fulfilled since the last time poll_events() was called. This is necessary since LangUMS code is sequential and control can't just jump to random places whenever something in-game happens.

You can't poll_events() until the previous one has finished. So the minimum time between poll_events() is the time it takes to execute all your event handlers. This will never be zero unless you have zero event handlers in which case poll_events() emits no instructions.

I meant in the same trigger cycle that you meet those conditions. It sounds like with langUMS all the conditions of a trigger can be met for a trigger cycle or two and then become unmet and the triggers would never know.


The events are buffered so if the conditions are met the event handler will fire the next poll_events() cycle.

I get that the code determines what happens, but I guess the problem here is I don't understand the code, and from what it sounds like the expected behavior is difficult to determine.


The expected behavior is trivial to determine as the code is sequential. You have to read it like any other programming language, each statement follows the preceding one starting from the top of your main() function. Control never just jumps around the place for no reason.

On May 06 2017 03:57 KhaosKreator wrote:
I'm going to try to get involved in this and make some test maps this weekend, I think.


Come to the Discord - https://discord.gg/TNehfve so we can chat about it.
Normal
Please log in or register to reply.
Live Events Refresh
Next event in 2h 37m
[ Submit Event ]
Live Streams
Refresh
StarCraft 2
NeuroSwarm 204
StarCraft: Brood War
BeSt 1030
Pusan 218
ggaemo 158
Nal_rA 105
Bale 18
Killer 1
League of Legends
JimRising 633
Counter-Strike
shoxiejesuss31
Super Smash Bros
C9.Mang0172
Heroes of the Storm
Khaldor132
Other Games
summit1g13993
WinterStarcraft490
ceh9278
Organizations
Counter-Strike
PGL4676
Other Games
BasetradeTV153
StarCraft 2
Blizzard YouTube
StarCraft: Brood War
BSLTrovo
sctven
[ Show 12 non-featured ]
StarCraft 2
• AfreecaTV YouTube
• intothetv
• Kozan
• IndyKCrew
• LaughNgamezSOOP
• Migwel
• sooper7s
StarCraft: Brood War
• BSLYoutube
• STPLYoutube
• ZZZeroYoutube
League of Legends
• Rush1154
• Stunt406
Upcoming Events
Afreeca Starleague
2h 37m
Wardi Open
3h 37m
Replay Cast
16h 37m
Sparkling Tuna Cup
1d 2h
Kung Fu Cup
2 days
The PondCast
3 days
Replay Cast
3 days
Replay Cast
4 days
CranKy Ducklings
5 days
BSL
5 days
[ Show More ]
Replay Cast
5 days
Sparkling Tuna Cup
6 days
BSL
6 days
Replay Cast
6 days
Liquipedia Results

Completed

CSL Elite League 2026
RSL Revival: Season 4
NationLESS Cup

Ongoing

BSL Season 22
ASL Season 21
CSL Season 20: Qualifier 2
CSL 2026 SPRING (S20)
StarCraft2 Community Team League 2026 Spring
Nations Cup 2026
PGL Bucharest 2026
Stake Ranked Episode 1
BLAST Open Spring 2026
ESL Pro League S23 Finals
ESL Pro League S23 Stage 1&2
PGL Cluj-Napoca 2026
IEM Kraków 2026
BLAST Bounty Winter 2026

Upcoming

Escore Tournament S2: W2
IPSL Spring 2026
Escore Tournament S2: W3
Acropolis #4
BSL 22 Non-Korean Championship
CSLAN 4
Kung Fu Cup 2026 Grand Finals
HSC XXIX
uThermal 2v2 2026 Main Event
RSL Revival: Season 5
IEM Cologne Major 2026
Stake Ranked Episode 2
CS Asia Championships 2026
Asian Champions League 2026
IEM Atlanta 2026
PGL Astana 2026
BLAST Rivals Spring 2026
CCT Season 3 Global Finals
IEM Rio 2026
TLPD

1. ByuN
2. TY
3. Dark
4. Solar
5. Stats
6. Nerchio
7. sOs
8. soO
9. INnoVation
10. Elazer
1. Rain
2. Flash
3. EffOrt
4. Last
5. Bisu
6. Soulkey
7. Mini
8. Sharp
Sidebar Settings...

Advertising | Privacy Policy | Terms Of Use | Contact Us

Original banner artwork: Jim Warren
The contents of this webpage are copyright © 2026 TLnet. All Rights Reserved.