Программы
Предназначение:
Работа с кодом
Warcraft III Reforged привнес в игру скрипты Lua, но многие разработчики карт для WC3 до сих пор используют JASS, а многие и cJass (просто потому, что правила синтаксиса в стиле C тупо рулят) К сожалению, расширение cJass не поддерживается для Reforged, и кто знает, как это будет, вероятнее всего вряд ли c-подобный синтаксис появится в Reforged. А JASS устаревает, крайне дырявый и имеет громоздкий и неудобный синтаксис.
Lua более эффективен, полезен и прост в разработке игр, он фактически стал стандартом в игровом скриптинге благодаря своему удобству, простоте и быстроте. Но многие проекты все еще находятся на cJass/JASS, и нет возможности конвертировать их в Lua. Редактор без расширения cJass не воспринимает этот код и в результате ваш проект может просто пропасть. А многие у кого проект написан на JASS предпочли бы переписать его на более удобный Lua, который легче и приятнее поддерживать. Переписывание кода вручную для Lua может занять много времени, само собой никто не хочет тратить на это время, чтоб делать свой проект фактически второй раз.
Этот инструмент создан, чтобы решить эту проблему. cJass2Lua может легко конвертировать cJass и JASS в читаемый Lua код, он поможет вам менее болезненно перенести код своей карты с JASS и cJass который находится в тупиковом положении на код в Lua. В большинстве случаев при переносе кода его даже не нужно редактировать, чтобы заставить работать, допустимо даже подавать мешанину из cJass и JASS кода на вход.
Скриншот:
Возможности:
  • Полная поддержка cJass и JASS
  • Возможность комбинировать синтаксис этих двух языков в одном файле
  • Поддержка парсинга структур(классов) в Lua'шные объекты мета-таблиц совместимые с оригинальным кодом, зачастую не требующие даже внесения правок чтобы они работали
  • Примитивный синтаксический анализ (на правильность кода) в процессе парсинга и вывод ошибок в лог
  • Генерация Lua кода на основе вашего cJass/JASS кода
  • Генерация спец-комментариев emmyDoc для Lua, которые помогают IDE ориентироваться в коде
  • Способен конвертировать common.j, blizzard.j и JASS код любой сложности
  • Удобный выбор файла/папки с файлами
  • Конвертация одиночных файлов
  • Массовая конвертация файлов из папки в папку
  • Подробное логгирование всех действий программы в лог файл для анализа проблем
  • Распознавание пост-инкрементов и пре-инкрементов
  • 100% читабельный код на выходе
  • Сохраняет комментарии, их позиции и переносы строк в любых местах
  • Сохраняет совместимость кода и его изначальную планировку (порой достаточно просто конвертировать текст каждого триггера по отдельности и ваша карта уже работает на Lua)
  • Расставляет табуляцию
  • Конфигурационный файл с настройками
  • Минималистичный встроенный графический интерфейс где удобно и подробно можно отслеживать прогресс
  • Интерфейс командной строки
Ограничения:
  • Отсутствует и вряд ли планируется семантический анализатор. За семантику выражений отвечает автор скриптов.
  • Структуры не поддерживают наследование и не понимают разницу между public и private (поддерживаются статические методы, статические переменные переводятся в глобальные)
  • Отсутствие поддержки расширенных фич vJASS как module, library, scope (Они по сути в Lua и не нужны, и просто игнорируются при парсе)
  • Не поддерживаются пре-процессорные директивы (Лишено смысла при переводе в Lua)
  • Макросы ограничены. блоки define распознаются, но только как константы. Избегайте функциональных макросов.
  • В некоторых случаях массивы в Lua индексируются с единицы, в большинстве случаев вам это ничем не грозит, но имейте в виду.
  • Инкременты в выражениях выгдядят так a = (var++) --> a = (var + 1). Но сам var в этом случае не увеличится на 1, нужно фиксить руками.
  • Циклы for из cJass не поддерживаются и вряд ли будут, перед тем как транслировать файл на Lua - сохраните его на диск.
  • Всё на английском языке
Внимание:
Перед преобразованием кода, убедитесь что...
  • Ваш код на 100% правильный и не содержит ошибок
  • Ваши структуры не используют наследование
  • Если в вашей структуре предусмотрен конструктор (статический "создавальщик") то он обязан называться new или create
  • Если у вас в коде используются структуры не объявленные в этом файле, объявите их в начале файла при помощи type StructName, так парсер поймет с чем имеет дело
  • Не используются ключевые слова в качестве идентификаторов. Такие как do, else, while, then и тд.
  • Имейте в виду, что хоть и присутствует умная замена оператора конкатенации строк, строчные идентификаторы и функции объявленные в других файлах не будут распознаны как строки и если + не поменялся на .. - это придется делать вручную.
Приложение оставляет после своей работы рядом с собой лог файл, читайте его если вдруг что-то не так. Когда нормально отрабатывает приложение - там не должно быть ни одного сообщения типа Warning, Critical или Fatal.
Пример преобразования:
//Входящий JASS/cJass код
type Projectile

bool KatonItachiConditions()
{
	if (GetSpellAbilityId() == 'A07Z')
	{
		return true;
	}

	return false;
}

define
	KATON_DUMMY           =  1
	KATON_RADIUS		  =  2
	KATON_DAMAGE		  =  3
	KATON_FINAL_POINT_X   =  4
	KATON_FINAL_POINT_Y   =  5
	KATON_EFFECT          =  6
	KATON_DIRECTION       =  7
	KATON_TRAVELED        =  8
	KATON_DMG_FACTOR      =  9
	
	
	KATON_DISTANCE        =  1100
	KATON_VELOCITY        =  5.35
enddefine

globals 
	unit g_KatonDummy;
	float g_KatonDMG;
	trigger g_TrgKatonPreCast;
endglobals

void KatonItachiActions()
{
	unit u = GetTriggerUnit();
	player p = GetOwningPlayer(u);
	location loc = GetSpellTargetLoc();
	location myLoc = GetUnitLoc(u);
	float facing = GetUnitFacing(u);
	location spawnPoint = PolarProjectionBJ(myLoc, 115.00, facing);
	location finalPoint = PolarProjectionBJ(spawnPoint, KATON_DISTANCE, facing);
	int lvl = GetUnitAbilityLevel(u, GetSpellAbilityId());
	float r = 200 + (25 * (lvl - 1));
	float dmg = 10;//10 + (4 * (lvl - 1)); 
	float travelFactor = 0.006 + (0.002 * (lvl - 1));
	float dummyScale = 2.00 + (0.30 * (lvl - 1));
	
	timer t = CreateTimer();
	InitPeriodicTimer(t, 0.01, 3.5);
	unit dummy =  CreateDummy(p, u, spawnPoint);
	SetUnitPathing(dummy, false);
	effect e = AddSpecialEffectTarget("fireball.mdx", dummy, "origin");
	SetUnitScale(dummy, dummyScale, dummyScale, dummyScale);
	SaveUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY, dummy);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_RADIUS, r);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR, travelFactor);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION, facing);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, 0);
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X, GetLocationX(finalPoint));
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y, GetLocationY(finalPoint));
	SaveEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT, e);
	
	RemoveLocation(spawnPoint);
	RemoveLocation(loc);
	RemoveLocation(myLoc);
	RemoveLocation(finalPoint);
	
	TimerStart(t, 0.01, true, lambda void ()
	{
		timer t = GetExpiredTimer();
		float dur = GetTimerDuration(t);
		unit dummy = LoadUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY);
		location dummyLoc = GetUnitLoc(dummy);
		float r = LoadReal(g_Hashtable, GetHandleId(t), KATON_RADIUS);
		float traveled = LoadReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED);
		float dir = LoadReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION);
		float finalPointX = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X);
		float finalPointY = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y);
		location newLoc = PolarProjectionBJ(dummyLoc, KATON_VELOCITY, dir);
		SetUnitPositionLoc(dummy, newLoc);
		RemoveLocation(newLoc);
		RemoveLocation(dummyLoc);
		traveled += KATON_VELOCITY;
		SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, traveled);
		
		if (ModuloInteger(R2I(dur * 100), 10) == 0)
		{
			group g = CreateGroup();
			float travelFactor = LoadReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR);
			float dmg = LoadReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE) + (traveled * travelFactor);
			g_KatonDummy = dummy;
			g_KatonDMG = dmg;
			boolexpr bexp = Condition(lambda bool ()
			{
				unit u = GetFilterUnit();
				if (!IsPlayerAlly(GetOwningPlayer(u), GetOwningPlayer(g_KatonDummy)) && !IsUnitType(u, UNIT_TYPE_STRUCTURE) && IsUnitAlive(u) && !IsUnitDummy(u))
				{
					return true;
				}
				return false;
			});
			GroupEnumUnitsInRange(g, GetUnitX(dummy), GetUnitY(dummy), r, bexp);
			ForGroup(g, lambda void ()
			{
				 DummyDealDamage(g_KatonDummy, GetEnumUnit(), g_KatonDMG, SCHOOL_MAGIC);
			});
			SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg);
			DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", GetUnitX(dummy), GetUnitY(dummy)));
			DestroyBoolExpr(bexp);
			DestroyGroup(g);
		}
		
		
		
		if (!TimerTick(t) || dummy == null || traveled > KATON_DISTANCE)
		{
			DestroyEffect(LoadEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT));
			RemoveUnit_s(dummy, "KatonItachiActions", "KatonItachi");
			DestroyTimer_s(t);
		}
	});
}

void KatonSoundActions()
{
	unit u = GetTriggerUnit();
	AddSoundUnit("katon.mp3", u);
	u = null;
}

void KatonItachiActionsNew()
{
	unit u = GetTriggerUnit();
	location loc = GetSpellTargetLoc();
	int lvl = GetUnitAbilityLevel(u, GetSpellAbilityId());
	float r = 200 + (25 * (lvl - 1));
	float dmg = 100;//100 + (4 * (lvl - 1)); 
	float travelFactor = 0.04 + (0.02 * (lvl - 1));
	float dummyScale = 2.00 + (0.30 * (lvl - 1));
	
	FinishDuel();
	Projectile katonProj = Projectile.create(DEFAULT_DUMMY, "fireball.mdx", dummyScale, u, 110);
	katonProj.SetVelocity(535, 1.0);
	katonProj.DamageOnce(false);
	katonProj.SetDamageData(0.1, dmg, r, 0, 0, travelFactor, SCHOOL_MAGIC);
	katonProj.SetDestLoc(loc);
	katonProj.SetDistance(1100, true);
	katonProj.InstantRemove(true);
	katonProj.SetDamageEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl");
	katonProj.Launch();
	
	RemoveLocation(loc);
	u = null;
	loc = null;
}

void InitTrig_KatonItachi()
{
    gg_trg_KatonItachi = CreateTrigger();
	g_TrgKatonPreCast = CreateTrigger();
    TriggerRegisterAnyUnitEventBJ(gg_trg_KatonItachi, EVENT_PLAYER_UNIT_SPELL_EFFECT);
	TriggerRegisterAnyUnitEventBJ(g_TrgKatonPreCast, EVENT_PLAYER_UNIT_SPELL_CHANNEL);
    TriggerAddCondition(gg_trg_KatonItachi, Condition(function KatonItachiConditions));
    TriggerAddAction(gg_trg_KatonItachi, function KatonItachiActionsNew);
	TriggerAddCondition(g_TrgKatonPreCast, Condition(function KatonItachiConditions));
    TriggerAddAction(g_TrgKatonPreCast, function KatonSoundActions);
}
-- Lua код на выходе

---@class  Projectile
---@return bool
function KatonItachiConditions()
	if (GetSpellAbilityId() == FourCC('A07Z')) then
		return true
	end
	
	return false
end

KATON_DUMMY = 1	---@type integer	
KATON_RADIUS = 2	---@type integer	
KATON_DAMAGE = 3	---@type integer	
KATON_FINAL_POINT_X = 4	---@type integer	
KATON_FINAL_POINT_Y = 5	---@type integer	
KATON_EFFECT = 6	---@type integer	
KATON_DIRECTION = 7	---@type integer	
KATON_TRAVELED = 8	---@type integer	
KATON_DMG_FACTOR = 9	---@type integer	
KATON_DISTANCE = 1100	---@type integer	
KATON_VELOCITY = 5.35	---@type real	

-- g_KatonDummy	---@type unit	
-- g_KatonDMG	---@type float	
-- g_TrgKatonPreCast	---@type trigger	

---@return void
function KatonItachiActions()
	local u = GetTriggerUnit()
	local p = GetOwningPlayer(u)
	local loc = GetSpellTargetLoc()
	local myLoc = GetUnitLoc(u)
	local facing = GetUnitFacing(u)
	local spawnPoint = PolarProjectionBJ(myLoc, 115.00, facing)
	local finalPoint = PolarProjectionBJ(spawnPoint, KATON_DISTANCE, facing)
	local lvl = GetUnitAbilityLevel(u, GetSpellAbilityId())
	local r = 200 + (25 * (lvl - 1))
	local dmg = 10	-- 10 + (4 * (lvl - 1)); 
	local travelFactor = 0.006 + (0.002 * (lvl - 1))
	local dummyScale = 2.00 + (0.30 * (lvl - 1))
	
	local t = CreateTimer()
	InitPeriodicTimer(t, 0.01, 3.5)
	local dummy = CreateDummy(p, u, spawnPoint)
	SetUnitPathing(dummy, false)
	local e = AddSpecialEffectTarget("fireball.mdx", dummy, "origin")
	SetUnitScale(dummy, dummyScale, dummyScale, dummyScale)
	SaveUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY, dummy)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_RADIUS, r)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR, travelFactor)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION, facing)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, 0)
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X, GetLocationX(finalPoint))
	SaveReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y, GetLocationY(finalPoint))
	SaveEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT, e)
	
	RemoveLocation(spawnPoint)
	RemoveLocation(loc)
	RemoveLocation(myLoc)
	RemoveLocation(finalPoint)
	
	TimerStart(t, 0.01, true, function ()
		local t = GetExpiredTimer()
		local dur = GetTimerDuration(t)
		local dummy = LoadUnitHandle(g_Hashtable, GetHandleId(t), KATON_DUMMY)
		local dummyLoc = GetUnitLoc(dummy)
		local r = LoadReal(g_Hashtable, GetHandleId(t), KATON_RADIUS)
		local traveled = LoadReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED)
		local dir = LoadReal(g_Hashtable, GetHandleId(t), KATON_DIRECTION)
		local finalPointX = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_X)
		local finalPointY = LoadReal(g_Hashtable, GetHandleId(t), KATON_FINAL_POINT_Y)
		local newLoc = PolarProjectionBJ(dummyLoc, KATON_VELOCITY, dir)
		SetUnitPositionLoc(dummy, newLoc)
		RemoveLocation(newLoc)
		RemoveLocation(dummyLoc)
		traveled = traveled + KATON_VELOCITY
		SaveReal(g_Hashtable, GetHandleId(t), KATON_TRAVELED, traveled)
		
		if (ModuloInteger(R2I(dur * 100), 10) == 0) then
			local g = CreateGroup()
			local travelFactor = LoadReal(g_Hashtable, GetHandleId(t), KATON_DMG_FACTOR)
			local dmg = LoadReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE) + (traveled * travelFactor)
			g_KatonDummy = dummy
			g_KatonDMG = dmg
			local bexp = Condition(function ()
				local u = GetFilterUnit()
				if ( not IsPlayerAlly(GetOwningPlayer(u), GetOwningPlayer(g_KatonDummy)) and  not IsUnitType(u, UNIT_TYPE_STRUCTURE) and IsUnitAlive(u) and  not IsUnitDummy(u)) then
					return true
				end
				return false
			end)
			GroupEnumUnitsInRange(g, GetUnitX(dummy), GetUnitY(dummy), r, bexp)
			ForGroup(g, function ()
				DummyDealDamage(g_KatonDummy, GetEnumUnit(), g_KatonDMG, SCHOOL_MAGIC)
			end)
			SaveReal(g_Hashtable, GetHandleId(t), KATON_DAMAGE, dmg)
			DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", GetUnitX(dummy), GetUnitY(dummy)))
			DestroyBoolExpr(bexp)
			DestroyGroup(g)
		end
		
		
		if ( not TimerTick(t) or dummy == nil or traveled > KATON_DISTANCE) then
			DestroyEffect(LoadEffectHandle(g_Hashtable, GetHandleId(t), KATON_EFFECT))
			RemoveUnit_s(dummy, "KatonItachiActions", "KatonItachi")
			DestroyTimer_s(t)
		end
	end)
end

---@return void
function KatonSoundActions()
	local u = GetTriggerUnit()
	AddSoundUnit("katon.mp3", u)
	u = nil
end

---@return void
function KatonItachiActionsNew()
	local u = GetTriggerUnit()
	local loc = GetSpellTargetLoc()
	local lvl = GetUnitAbilityLevel(u, GetSpellAbilityId())
	local r = 200 + (25 * (lvl - 1))
	local dmg = 100	-- 100 + (4 * (lvl - 1)); 
	local travelFactor = 0.04 + (0.02 * (lvl - 1))
	local dummyScale = 2.00 + (0.30 * (lvl - 1))
	
	FinishDuel()
	local katonProj = Projectile:create(DEFAULT_DUMMY, "fireball.mdx", dummyScale, u, 110)
	katonProj.SetVelocity(535, 1.0)
	katonProj.DamageOnce(false)
	katonProj.SetDamageData(0.1, dmg, r, 0, 0, travelFactor, SCHOOL_MAGIC)
	katonProj.SetDestLoc(loc)
	katonProj.SetDistance(1100, true)
	katonProj.InstantRemove(true)
	katonProj.SetDamageEffect("Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl")
	katonProj.Launch()
	
	RemoveLocation(loc)
	u = nil
	loc = nil
end

---@return void
function InitTrig_KatonItachi()
	gg_trg_KatonItachi = CreateTrigger()
	g_TrgKatonPreCast = CreateTrigger()
	TriggerRegisterAnyUnitEventBJ(gg_trg_KatonItachi, EVENT_PLAYER_UNIT_SPELL_EFFECT)
	TriggerRegisterAnyUnitEventBJ(g_TrgKatonPreCast, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
	TriggerAddCondition(gg_trg_KatonItachi, Condition(KatonItachiConditions))
	TriggerAddAction(gg_trg_KatonItachi, KatonItachiActionsNew)
	TriggerAddCondition(g_TrgKatonPreCast, Condition(KatonItachiConditions))
	TriggerAddAction(g_TrgKatonPreCast, KatonSoundActions)
end

Инструкция:
Чтобы пользоваться просто укажите во входящий путь в окне приложения путь к файлу или папке с cjass/jass файлами при помощи кнопки Browse. Чтобы выбрать папку, а не файл - нажмите Browse с зажатым шифтом. Внизу укажите путь к папке в которую запишется готовый Lua файл (или прямой путь к выходному луа файлу), выбор файла или папки через Browse аналогичен. Также имеется и консольный интерфейс (первый аргумент входящий путь, второй - исходящий). Если исходящий путь не указан, то .lua файлик сохранится туда же, где и входящий .j файлик.
СКАЧАТЬ: (версия v1.12 07.12.2019)
x86 сборка: Скачать
x64 сборка: Скачать
Исходный код (и подробности использования):
GitHub: github.com/fullmetal-a/cjass2lua
Изменения v1.12:
  • Исправлены все случаи, когда this. не добавлялся периодически перед членами и методами
  • Исправлен баг, когда иногда оператор ! заменялся на - вместо not
  • Теперь все названия методов корректны и полностью работоспособны, они больше не пишутся через :
  • Добавлена поддержка .deallocate
  • Теперь переменная объекта текущего класса, созданная в методе .create при помощи .allocate удаляется при трансляции кода, а все обращения к ней меняются на this.
  • Исправлено множество багов
Изменения v1.11/1.10:
  • Улучшен парсинг
  • Улучшен консольный интерфейс
  • Исправлены редкие критические баги
  • Исправлен критический баг с трансляцией идентификаторов
  • Теперь поля входящих и выходящих путей в интерфейсе больше не read-only
Изменения v1.09:
  • Добавлена поддержка перевода структур/классов в мета-табличные объекты
  • Добавлена поддержка коротких void лямбда-выражений через оператор ()->
  • Парс теперь прерывается с ошибкой если мы переобъявляем глобальную функцию\переменную
  • Небольшие улучшения и оптимизация
  • Исправления багов
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
3
28
4 года назад
3
А как по мне, синтаксис пайтона 3 куда лучше, чем в С, долой {} скобки!
Имхо, когда я вижу стену кода в С стиле с кучей {} скобок, которая ещё и растёт вширь, мне становится плохо.
0
16
4 года назад
Отредактирован Drulia_san
0
PT153:
А как по мне, синтаксис пайтона 3 куда лучше, чем в С, долой {} скобки!
Имхо, когда я вижу стену кода в С стиле с кучей {} скобок, которая ещё и растёт вширь, мне становится плохо.
Периодически приходится работать с питоном и честно говоря я его не люблю за его подход построения блоков через отступы, старые добрые фигурные скобочки моё всё, впрочем каждому своё) Ну и как я описал выше, для любителей JASS я добавил его полную поддержку, cJass теперь не обязателен во входящих файлах
1
28
4 года назад
Отредактирован PT153
1
честно говоря я его не люблю за его подход построения блоков через отступы
Есть небольшой лайфхак: если какой-то блок занимает 1 строчку, можно не делать перенос, а просто пробел после :.
if bad(smth): return
Я в шутку сказал, я нормально отношусь ко всем синтаксисам. В С мне конкретно не нравятся операторы &&, || и !. and, or и not, имхо, делают код более читабельным и не сильно больше места занимают.
3
17
4 года назад
Отредактирован GetLocalPlayer
3
Периодически приходится работать с питоном и честно говоря я его не люблю за его подход построения блоков через отступы
Каким бы не был способ разделения блоков кода, человеческий глаз в любом случае ориентируется на отступы. При всех прелестях C, на пятый час писанины фигурные скобки начинают в глазах сливаться с фоном. Отступы это обязательный стандарт оформления кода. Что могло быть лучше, чем сделать его частью синтаксиса.
Drulia_san:
Я сомневаюсь что многим людям нравится писать local перед типом данных, call перед каждым вызовом и set перед каждым присвоением, и конечно же типы данных без сокращений вроде integer и boolean.
Зависит от опыта конкретного кодера. На хайве можно найти опросы и вопросы, что лучше, vJass, cJass или ZINC. Мнение за бугром обычно не в пользу сJass, На это приводят набор объективных причин, среди которых отсутствие жесткого требования следовать языку и, как следствие, возможность смешивать JASS и vJass конструкции с cJass. В итоге код превращается в жуткую мешанину из набора разных синтаксисов.
В то же время молодые, неопытные пользователи куда легче воспринимают именно ключевые слова
               endif
            endloop
        endmethod
    endstruct
endlibrary
где они могут сразу понять, о каких именно блоках кода идет речь, чем эквивалентный
                }
            }
        }
    }
}
8
29
4 года назад
8
Это продукт для паверюзеров изначально, совершенно нассать как там код воспринимают молодые и неопытные. Закрывающие кейворды, разные для каждого блока, очень мешают при рефакторинге. В цинке есть пара хороших идей, но в сумме это тоже говно, объявлять все локалки в начале функции - треш. В сжассе при этом есть полезные фичи вроде форича по группам.
0
17
4 года назад
Отредактирован Vlod
0
PT153:
А как по мне, синтаксис пайтона 3 куда лучше, чем в С
Да, есть такое, просто они там парятся с обратной совместимостью, язык старенький, хотя и завезли плюшек в 20ом стандарте

GetLocalPlayer, поддерживаю, как-то прогал на ночь, так эти скобки в глазах слипались донельзя
2
16
4 года назад
2
поддерживаю, как-то прогал на ночь, так эти скобки в глазах слипались донельзя
Надо просто спать идти в таких случаях =) Если сонным прогать потом с утра охренеешь с той каши что увидишь в редакторе и вопросов самому себе "как мне вообще такое пришло в голову"
А если серьезно поддерживаю вышесказанное от Doc, мусорные слова в духе endloop endfunction endif, call set захламляют видимость и сбивают с умных мыслей, когда скобочка просто закрывает блок и не привлекает к себе внимания, когда глаза скользят по словам, а новичкам нужно просто по-практиковаться и начинать с чего-то простого, например с Lua, у него синтаксис идеален для начинающих
0
17
4 года назад
Отредактирован Vlod
0
Для меня главный интерес представляют макросы. С помощью них можно было устанавливать параметры функции по умолчанию, создавать шаблоны классов, создавать подобие inline функций. А также добавлять недостающие языку возможности вводя новые синт. конструкций
0
23
4 года назад
0
Drulia_san, мне интересно, программку сам же написал? С нуля? Что использовал для этого или большая часть ручной работы думая своей головой? Интересно мнение разработчика, каково писать такую программку и сколько это заняло времени/сил (раскрыть секреты производства) ;)
4
16
4 года назад
Отредактирован Drulia_san
4
konvan5:
Drulia_san, мне интересно, программку сам же написал? С нуля? Что использовал для этого или большая часть ручной работы думая своей головой? Интересно мнение разработчика, каково писать такую программку и сколько это заняло времени/сил (раскрыть секреты производства) ;)
Да, писал с нуля исключительно сам, начал еще летом, потом времени не было и было лень закончить, продолжил в начале ноября. Изначально это был проект для меня, думал напишу кое-как ради того чтоб свою карту конвертировать, которая была под угрозой. Все компоненты написаны мной (обертка для регулярок, логгер и тд), используется лишь stl и немного winapi. Ты сам можешь посмотреть там ссылка на гитхаб висит, можешь поковырять там что угодно. Позже это начало вырастать в нечто большее и решил это выложить. По времени в общей сложности заняло месяц где-то если сложить всё вместе, опять же можешь глянуть календарь активности на гитхабе) Если ты заметил, там класс называется Parser2, потому что был первый парсер и он был ужасен, пришлось переписывать снова.
Я использовал чистый винапи по нескольким причинам:
  1. Никто не будет запускать это на линуксе\маке, весь геймдев по варкрафту был есть и будет на винде
  2. Он быстрый и очень функциональный
  3. Я и любой кто захочет это собрать сможет это сделать сходу ничего не подключая и не скачивая
  4. Хотелось облегчить проект от лишних библиотек вроде Qt, MFC
0
29
4 года назад
Отредактирован nazarpunk
0
Drulia_san, коли уже есть поддержка jass можно ли научить программу разбирать эти файлы:
чтоб получилось нечто подобное:
а то я для подсветки просто позаменял всё регулярками, что не всегда нормально сработало.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.