ASH Scripting with intellisense

Linknoid

Member
Last night I decided I was finally motivated enough to jump into ASH scripting. The language itself is pretty simply, but the size of the API is a bit intimidating.

Looking through the syntax, most of the constructs are very similar to C/C++/Java/C#. I realized that if I could write code in the subset of ASH and C# that overlap, I could have Intellisense autocomplete and documentation in Microsoft Visual Studio (I spend 8 hours a day working in Visual Studio, so it's my native environment).

I went through the Wiki, copy/pasted all the functions, transformed them into static methods (and class methods, if the method takes a first parameter of the right type), and formatted the descriptions into XML comments. It uses features added in the latest version of C# (specifically "using static" to bring static methods into global scope in a file), so it won't work with Visual Studio older than 2015.

If I'm writing code from scratch, it lets me get auto-completion, auto-documentation, auto-formatting, syntax highlighting, and name checking. I tried importing an existing script into a C# file, but there are enough things that you can do in ASH that are completely invalid C# that it's not at all useful for most existing scripts. But maybe someone else who wants to start learning will find this useful in the future. If not, at least it's useful to me.

Here's the issues I ran into:

* Record type "class" (as in character class) is a reserved keyword in C#. It has to be escaped in C# as @class, which is incompatible. But it doesn't appear to be used much.
* The maps correlate to dictionaries in C#, but the syntax is very different. Simple integer indexed arrays are ALMOST identical. [EDIT: I figured out how to represent map syntax using generics of each class. However, anything where the value is int or string has to be escaped @int or @string]
* for loop is completely different. [Edit - I was reading other posts, and it looks like C style for loops are now supported in ASH, but I guess the Wiki hasn't been updated.]
* foreach loop is almost identical, but ASH doesn't put parentheses around the looping construct.
* Comments start with # vs. //
* ASH seems to allow a bunch of functionality that doesn't translate into C# at all, like unquoted strings.


A few places I didn't know what a parameter meant, I just called it xx,yy,zz, etc.

Instructions: unzip the project, open it in Visual Studio, copy the file "StandardHeaders.cs" as a template, and start writing your code inside "class ScriptTemplate". When you're done, you'll need to translate any C#isms to valid ASH syntax. Maybe I'll get around to writing a small utility to do so later.
 

Attachments

  • MafiaScriptHelper-1.02.zip
    32.9 KB · Views: 23
Last edited:

heeheehee

Developer
Staff member
* for loop is completely different. [Edit - I was reading other posts, and it looks like C style for loops are now supported in ASH, but I guess the Wiki hasn't been updated.]
This is correct.

* Comments start with # vs. //
Actually, both styles of quotes are supported, as well as C-style multi-line quotes (/* ... */). I'm not sure why.

* ASH seems to allow a bunch of functionality that doesn't translate into C# at all, like unquoted strings.
I'm not sure I understand. Are you referring to typed constants?
 

ckb

Minion
Staff member
Also, the wiki is often missing some ASH commands. Typing 'ashref' into the CLI will give you a current list of all of Mafia's ASH commands.
 

Linknoid

Member
I'm not sure I understand. Are you referring to typed constants?

This is what I mean by unquoted strings: $skill[ Inigo's Incantation of Inspiration ]

C# obviously won't like the $, and the [ Inigo's Incantation of Inspiration ] without quotes around it. I don't think there's anything I can do to make it accept that as valid syntax. But I can write code as "Inigo's Incantation of Inspiration".to_skill() to accomplish the same thing, right?

ASH also seems to allow global static code anywhere you feel like it (i.e. code that's at the very top level, not in any method), which is pretty standard in scripting languages. But in C# all code has to be inside methods (except field initializers). I can avoid writing that kind of code, but it means I can't just import existing code and expect it to be valid. I was looking at bumcheekascend, and it has code like this interspersed between function definitions:

int max_bees = 0;
if (get_property("bcasc_maxBees").to_int() > 0) max_bees = get_property("bcasc_maxBees").to_int();

Other differences include C# "struct" vs ASH "record" (and the fact that C# requires you to declare stuff public), the C# requirement to explicitly initialize local variables before using them, and ASH allowing non-const "case" values in a "switch".

I'm wondering if it might work better to use a C++ project instead, I could probably get around some of that using #defines, but the intellisense for C++ is lower quality than for C#. And there's probably a different set of tradeoffs I'd have to make.

At some point, having auto-complete will probably become less important than being able to write code in it's final format, and then I'll ditch this learning framework.
 
At some point, having auto-complete will probably become less important than being able to write code in it's final format, and then I'll ditch this learning framework.

Use keyword highlighting for ASH built-in functions and keep the wiki open? Sure, the wiki is a tad out of date in some places but it gets the job done.
 

Linknoid

Member
Also, the wiki is often missing some ASH commands. Typing 'ashref' into the CLI will give you a current list of all of Mafia's ASH commands.

Thanks, I'll try to go through and see what I'm missing.

Is there also a list of all the properties that can be used with get_property and set_property? I have a lot of things I want to query that aren't part of the main API, and I suspect I could find through properties.
 
Is there also a list of all the properties that can be used with get_property and set_property? I have a lot of things I want to query that aren't part of the main API, and I suspect I could find through properties.

The "prefref" command (with no arguments) in the CLI will dump everything. It may take several seconds before it starts output though.
 

heeheehee

Developer
Staff member
This is what I mean by unquoted strings: $skill[ Inigo's Incantation of Inspiration ]

C# obviously won't like the $, and the [ Inigo's Incantation of Inspiration ] without quotes around it. I don't think there's anything I can do to make it accept that as valid syntax. But I can write code as "Inigo's Incantation of Inspiration".to_skill() to accomplish the same thing, right?
Mostly, yeah.

ASH also seems to allow global static code anywhere you feel like it (i.e. code that's at the very top level, not in any method), which is pretty standard in scripting languages. But in C# all code has to be inside methods (except field initializers). I can avoid writing that kind of code, but it means I can't just import existing code and expect it to be valid. I was looking at bumcheekascend, and it has code like this interspersed between function definitions:
Yeah, C++ would probably be a somewhat better fit on this point.

Other differences include C# "struct" vs ASH "record" (and the fact that C# requires you to declare stuff public), the C# requirement to explicitly initialize local variables before using them, and ASH allowing non-const "case" values in a "switch".
Well, I imagine you could preprocess the code to turn record -> struct. I'm not terribly familiar with C# -- is there no default visibility? Ultimately you're going to run into limitations, since ASH isn't exactly C# (or any other language) -- it has a number of language-specific features (e.g those typed constants, as well as aggregate literals) that don't translate cleanly.

Is there also a list of all the properties that can be used with get_property and set_property? I have a lot of things I want to query that aren't part of the main API, and I suspect I could find through properties.

Sort of. There's defaults.txt, which the devs need to manually keep updated, but fundamentally, get/set_property manipulate a key-value store with arbitrary keys to achieve persistence between sessions, so there isn't a master list of every property you can use with those.
 

Linknoid

Member
C# default visibility for all fields/methods/properties is private, which means nothing would be accessible without the public keyword. In C++ struct it defaults to public, so it has that advantage.
 

Linknoid

Member
I managed to find most of the details I want. But there's a few I couldn't find.

I want to check which Thanksgarden foods I've already eaten. I can get the count from _thanksgettingFoodsEaten, but that doesn't tell me which ones are still left to eat. I think it might be valid to check _timeSpinnerFoodAvailable, but I don't know if that's reliable on a character without a Time Spinner.

Bag O' Tricks has the setting _bagOTricksUsed, which I think applies to the buff extender ability, but it also has an in combat buff ability. Is there anything that keeps track of how many times it has been used in combat?

I want to check which item is currently in the workshed, and whether it can be swapped. I see _workshedItemUsed, does that mean it has already be swapped today?

If I take a picture with a 4-d camera, how do I check what monster is captured inside the Shaking 4-d camera?

Thanks,

-Linknoid
 

lostcalpolydude

Developer
Staff member
I want to check which Thanksgarden foods I've already eaten. I can get the count from _thanksgettingFoodsEaten, but that doesn't tell me which ones are still left to eat. I think it might be valid to check _timeSpinnerFoodAvailable, but I don't know if that's reliable on a character without a Time Spinner.
That setting is valid even without a Time-Spinner.

Bag O' Tricks has the setting _bagOTricksUsed, which I think applies to the buff extender ability, but it also has an in combat buff ability. Is there anything that keeps track of how many times it has been used in combat?
There is not.

I want to check which item is currently in the workshed, and whether it can be swapped. I see _workshedItemUsed, does that mean it has already be swapped today?
Yes. You can check get_campground() to see what your current workshed item is.

If I take a picture with a 4-d camera, how do I check what monster is captured inside the Shaking 4-d camera?
_cameraMonster
 
Top