How Warcraft 3 helped me learn a couple of YPs


This language has a fairly verbose syntax, as well as an event-oriented structure, so two well-known (in the world of mapping) people created language preprocessors, which are also written on the wiki. The first - vJass (v - from the creator’s nickname - Vexorian ) added to JASS the features and all the resulting goodies (encapsulation, etc.). After the Russian programmer ADOLF released its parser, which created a new dialect - cJass , the parser wrote on MASM. He made JASS syntax look like classic C, and also added preprocessing (enumerations, macros, connection of external scripts, for handler, the increment, decrement operator, abbreviated calculations (+ =, - =, / =, * =) and much more). Example below:
function test takes nothing returns integer
local integer i = 0
set i = i + 1
return i
//Simple function on "pure JASS"
endfunctionint test()
{
int i = 0;
return ++i;
//Same on cJass
}Unfortunately, the project was abandoned, and there are very few knowledgeable assemblers in the circle of map makers. But not about that.
Once, it occurred to me to compose my own parser. Since I do not understand programming in a practical way, my choice fell on Delphi . Giving the parser a trivial name ( JASP - Just Another Script Preprocessor), I sat down to compose the buns. This is how dynamically typed variables (like in C # ), a single declaration of global variables, destruction of objects, etc., that was so lacking in vJass & cJass, were born . After composing the first two versions of the parser, in which I added all these small, but useful buns (they can be studied in the manual), I realized that we need to improve. My choice fell on C #, and since relatively recently I have been transferring (or rather already transferring and finishing with a file) the latest version 0.3, periodically unsubscribing on thematic forums and replenishing my notes . In the end, I want to say that the same JASS, which my father called pampering, taught me the basics of programming and allowed me to go deeper from Delphi to Sharp, which cannot but please me. I think that's enough, thank you all for your attention.
scope FreezingShoot
{
#define
{
;
private isEnemy(t, u) = IsUnitEnemy(t, GetOwningPlayer(u)) && GetWidgetLife(u) > .405;
}
#include "cj_types_priv.j";
private struct FS
{
unit caster;
unit array dummy[3];
static constant int count = 3;
real dist = 0.;
static void Timer()
{
var t = GetExpiredTimer();
FS s = LoadInteger(hash, GetHandleId(t), 0);
real x, y;
if (s.dist <= 750.)
{
for (int i = 0; i < s.count; i++)
{
var angle = GetUnitFacing(s.dummy[i]) * .0174532;
x = GetWidgetX(s.dummy[i]) + 25. * Cos(angle);
y = GetWidgetY(s.dummy[i]) + 25. * Sin(angle);
SetUnitPosition(s.dummy[i], x, y);
for (unit target; UnitsInRange(x, y, 80.) use temp)
{
if (isEnemy(s.caster, target))
{
UnitDamageTarget(s.caster, target, 100., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
delete AddSpecialEffect("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", x, y);
DummycastToTarget(s.caster, target, 'A001', 852075);
RemoveDummy(s.dummy[i]);
}
}
}
s.dist += 25.;
} elseif (s.dist > 750. || s.count <= 0) {
for (int i = 0; i < s.count; i++)
{
if (s.dummy[i] != null)
{
x = GetWidgetX(s.dummy[i]);
y = GetWidgetY(s.dummy[i]);
delete AddSpecialEffect("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", x, y);
RemoveDummy(s.dummy[i]);
}
}
FlushChildHashtable(hash, GetHandleId(t));
PauseTimer(t);
delete t, s;
}
flush t;
}
static void Init(unit caster, real tX, real tY)
{
new FS s, timer t;
s.caster = GetTriggerUnit();
var angle = Atan2(tY - GetWidgetY(s.caster), tX - GetWidgetX(s.caster)) * 57.295;
var x = GetWidgetX(s.caster);
var y = GetWidgetY(s.caster);
for (int i = 0; i < s.count; i++)
{
s.dummy[i] = CreateDummy(GetOwningPlayer(caster), "Abilities\\Weapons\\ColdArrow\\ColdArrowMissile.mdl", .7, x, y, 100., angle);
angle -= 20.;
}
SaveInteger(hash, GetHandleId(t), 0, s);
TimerStart(t, .04, true, function thistype.Timer);
flush t;
}
}
callback onUnitSpellEffect('A000')
{
FS.Init(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY());
}
}