20

» Game Dev / Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах

Рецензия на публикацию
Я не смог читать дальше. Статья совершенно бесполезная и не несет никакой ценности. Вся статья состоит или из бреда, или из очевидной информации которую каждый понимает на уровне интуиции.
Баланс всегда и везде ломался на уровне механик, а не чисел. Числа балансить не так-то то уж и сложно.
20

» Game Dev / Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах

А потом мы переосмыслили кривую развития и убедились, что 30 битв - это слишком быстро, и нужно сделать 100 битв для левелапа. Но так как системы с взаимосвязями у нас уже настроены, нам достаточно изменить кривую развития, а формулы автоматически пересчитают все зависимые внутриигровые числа. Или не автоматически, или в ручном режиме, как вам угодно, но главное, что это будут контролируемые процессы, и каждая новая итерация не вынудит полностью менять подход к балансу всего проекта.
Вода. А чтобы игру создать, нужно сначала идею придумать.
20

» Game Dev / Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах

Ну даже к деббафам поинт супер странный. Замедление "юнитов" играх с маленьким ттк зачастую намного страшнее, чем в играх с большим ттк. Так что поинт совершенно не туда. Может это статья посвящена какому то игровому жанру, но ты забыл указать какому?
20

» Game Dev / Как спроектировать игровую математическую модель, забалансить её и не сдуреть. Разбор на практических кейсах

Если мы выберем быстротечные сражения, чтобы враги убивались за 1-2 тычки, то мы тем самым обесценим дебаффы и в некоторой степени тактические скилы.
Некоторые считают Zero Hour буквально самой продвинутой стратегией в плане тактического и стратегического разнообразия и скилла. Очевидно, я также. А там юниты буквально отлетают за секунды. Не зря киберспорт там до сих пор живет и недавно был турик на 20к баксов. Я хотел прочитать и выкинуть большую рецензию, но тут просто ложь написана сразу.
20

» WarCraft 3 / Warcraft Cavegame

Рецензия на публикацию
Ждали этот проект всем селом.
Кубы — это модно и молодежно, тут сразу ставишь лайк без вопросов. Смотреть на то, как Minecraft пытается жить в недрах Warcraft, так же захватывающе, как и играть в пеонов в своё время. Безумно рад, что инженерный гений трахает Warcraft через UjAPI. Итак, если вы хотите забыть про гуй муй, оп-лимит, разрыв потока, фазы лун с cjassи раздор в комьюнити Warcraft, то добро пожаловать в чудесный мир UjAPI и Warcraft Cavegame!
20

» MARS / MARS 0.88c

ScorpioT1000,
в гугле твою карту не найдут
Я понимаю в чем был поинт, и показывать что-то 4 летнему комментарию глупо, но теперь найдут)
Загруженные файлы
20

» Unryze Jass API / UjAPI - Jass vs lua vs AngelScript

ScorpioT1000, Z в любом случае нужно синхать, даже если сделаешь ХТ, то откуда ты можешь знать, что она не будет отличаться у игроков?
20

» WarCraft 3 / Meltlilith (Fate Series)

dohieu1850,
«Скин не работал в игре Warcraft Reforged — возникла проблема. Я протестировал другие скины, они работали. Похоже, нужно кое-что ещё исправить, чтобы скин заработал в Warcraft III Reforged. Есть ли какие-то другие аниме-скины, помимо тех, что уже в списке? (Это вопрос)
(ссылка 1): Обратите внимание на эту ссылку: там есть способ всё исправить и ссылка на тот самый аниме-скин.
Ссылка на музыку:
(ссылка 2): Возможно, это идеи для следующего Warcraft III Reforged.»
20

» WarCraft 3 / Meltlilith (Fate Series)

Anime Chan, Он говорит, что хочет чтобы исправили "skin, потому что на рефе текстура (я так понял) белая. Модель в рефе отображается белым. Нужно скачать/установить правильную текстуру, чтобы все работало."
20

» The Scouring / The Scouring

Тот самый, Ну давайте еще поставим ИИ вместо тебя играть, а на старте автопобеда.
20

» WarCraft 3 / Health Mana Bar

Такую же систему сделал, но проблема всегда в том, что базовые хпбары безболезненно для других юи элемнтов не отключить.
Загруженные файлы
20

» WarCraft 3 / Есть ли идеи как сделать ульту пангольера из доты?

Проверяешь следующую точку передвижения + половину от физического размера юнита, если точка непроходима, то отталкиваешь его от стены. Движение на векторах проще всего будет сделать.
Или можно проверять на высоту, смотря что тебе нужно.
Вот примерный рефлект 3Д вектора от террайна:
				// Check for terrain
				if (obj1.v.z - obj1.size < GetTerrainZ(obj1.v.x + obj1.vx * obj1.INTERVAL * obj1.size / 10, obj1.v.y + obj1.vy * obj1.INTERVAL * obj1.size / 10)) {
					obj1.collide();
					obj1.vx = obj1.vx * obj1.bounceResistXY;
					obj1.vy = obj1.vy * obj1.bounceResistXY;
					obj1.vz = obj1.vz * obj1.bounceResistZ;

					vImpulse = Vec3.createAt(obj1.vx, obj1.vy, obj1.vz);

					ReflectVectorTerrain(vImpulse, (obj1.v.x + obj1.vx * obj1.INTERVAL * obj1.size / 10 + obj1.v.x)/2, (obj1.v.y + obj1.vy * obj1.INTERVAL * obj1.size / 10 + obj1.v.y)/2);

					obj1.vx = vImpulse.x;
					obj1.vy = vImpulse.y;
					obj1.vz = vImpulse.z;
					vImpulse.destroy();
				}
VectorAPI.zn
Открыть
library VectorAPI requires Vector {

	public function AngleBetweenVectors(Vec3 first, Vec3 second) -> real {
		return Acos((first.x*second.x + first.y*second.y + first.z*second.z)/SquareRoot(first.x*first.x + first.y*first.y + first.z*first.z)*SquareRoot(second.x*second.x + second.y*second.y + second.z*second.z));
	}

	public function DotProduct(Vec3 first, Vec3 second) -> real {
		return first.x*second.x + first.y*second.y + first.z*second.z;
	}

	public function CrossProduct(Vec3 edge1, Vec3 edge2) -> Vec3 {
		return Vec3.createAt(edge1.y*edge2.z - edge1.z*edge2.y, edge1.z*edge2.x - edge1.x*edge2.z, edge1.x*edge2.y - edge1.y*edge2.x);
	}

	public function VectorSum(Vec3 summand1, Vec3 summand2) -> Vec3 {
		return Vec3.createAt(summand1.x + summand2.x, summand1.y + summand2.y, summand1.z + summand2.z);
	}

	public function VectorSub(Vec3 minuend, Vec3 subtrahend) -> Vec3 {
		return Vec3.createAt(minuend.x - subtrahend.x, minuend.y - subtrahend.y, minuend.z - subtrahend.z);
	}

	public function VectorMult(Vec3 multiplied, real multipler) -> Vec3 {
		return Vec3.createAt(multiplied.x*multipler, multiplied.y*multipler, multiplied.z*multipler);
	}

	public function VectorDiv(Vec3 dividend, real divisor) -> Vec3 {
		return Vec3.createAt(dividend.x/divisor, dividend.y/divisor, dividend.z/divisor);
	}

	public function TriangleNormal(Vec3 a, Vec3 b, Vec3 c) -> Vec3 {
		Vec3 edge1 = Vec3.clone(b).sub(a);
		Vec3 edge2 = Vec3.clone(a).sub(a);
		Vec3 result = CrossProduct(edge1, edge2).normalize();
		edge1.destroy();
		edge2.destroy();
		return result;
	}

	public function TerrainNormal(real x, real y) -> Vec3 {
		Vec3 vertex = Vec3.createAt(x, y + 2.0, GetTerrainZ(x, y + 2.0));
		Vec3 edge1 = Vec3.createAt(x - 1.0, y - SQRT3, GetTerrainZ(x - 1.0, y - SQRT3)).sub(vertex);
		Vec3 edge2 = Vec3.createAt(x - 1.0, y + SQRT3, GetTerrainZ(x - 1.0, y + SQRT3)).sub(vertex);
		Vec3 result = CrossProduct(edge1, edge2).normalize();
		vertex.destroy();
		edge1.destroy();
		edge2.destroy();
		return result;
	}

	public function ReflectVector(Vec3 toReflect, Vec3 normal) {
		Vec3 tempNormal = Vec3.clone(normal);
		toReflect.sub(tempNormal.scale(2.0*DotProduct(tempNormal, toReflect)));
		tempNormal.destroy();
	}

	public function ReflectVectorTerrain(Vec3 toReflect, real x, real y) {
		Vec3 terrainNormal = TerrainNormal(x, y);
		toReflect.sub(terrainNormal.scale(2.0*DotProduct(terrainNormal, toReflect)));
		terrainNormal.destroy();
	}
}
Vector.zn
Открыть
library Vector requires Debug {

   public struct Vec2 {
		real x, y;
		
		// Constructors
		static method createAt(real x, real y) -> Vec2 {
			return Vec2.allocate().setAt(x, y);
		}
		
		static method create() -> Vec2 {
			return Vec2.allocate().setAt(0.0, 0.0);
		}
	
		static method createRandom() -> Vec2 {
			return Vec2.allocate().setAt(GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0));
		}
		
		// Transitional behavior
		static method clone(Vec2 another) -> Vec2 {
			return Vec2.allocate().setAt(another.x, another.y);
		}
		
		method setAt(real x, real y) -> Vec2 {
			this.x = x;
			this.y = y;
			return this;
		}
	

		method clear() -> Vec2 {
			return this.setAt(0.0, 0.0);
		}

	
		method copy(Vec2 another) -> Vec2 {
			return this.setAt(another.x, another.y);
		}
	
		// Math
		method add(Vec2 another) -> Vec2 {
			return this.setAt(this.x + another.x, this.y + another.y);
		}
	
		method sub(Vec2 another) -> Vec2 {
			return this.setAt(this.x - another.x, this.y - another.y);
		}
	
		method scale(real number) -> Vec2 {
			return this.setAt(this.x*number, this.y*number);
		}
	
		method div(real number) -> Vec2 {
			return this.scale(1.0/number);
		}
	
		method dot(Vec2 another) -> real {
			return this.x*another.x + this.y*another.y;
		}
	
		method lengthSqr() -> real {
			return this.x*this.x + this.y*this.y;
		}
	
		method length() -> real {
			return SquareRoot(this.x*this.x + this.y*this.y);
		}
	
		method distToSqr(Vec2 another) -> real {
			return (this.x - another.x)*(this.x - another.x) + (this.y - another.y)*(this.y - another.y);
		}
	
		method distTo(Vec2 another) -> real {
			return SquareRoot(this.distToSqr(another));
		}
	
		method angle(Vec2 another) -> real {
			return Acos(this.dot(another)/this.length()*another.length());  // radians
		}
	
		method normalize() -> Vec2 {
			debug if (this.length == 0.0) { dbgT("attempt to normalize vector with zero length"); return this; }
			return this.scale(1.0/this.length());
		}
	
		// Misc.
		method reflect(Vec2 normal) -> Vec2 {
			Vec2 temp = Vec2.clone(normal).scale(2.0*this.dot(normal));
			this.sub(temp);
			temp.destroy();
			return this;
		}
	}   



	public struct Vec3 {
		real x, y, z;
	
		// Constructors
		static method create() -> Vec3 {
			return Vec3.allocate().setAt(0.0, 0.0, 0.0);
		}
	
		static method createAt(real x, real y, real z) -> Vec3 {
			return Vec3.allocate().setAt(x, y, z);
		}
	
		static method createRandom() -> Vec3 {
			return Vec3.allocate().setAt(GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0));
		}
	
		// Transitional behavior
		static method clone(Vec3 another) -> Vec3 {
			return Vec3.allocate().setAt(another.x, another.y, another.z);
		}
		
		method setAt(real x, real y, real z) -> Vec3 {
			this.x = x;
			this.y = y;
			this.z = z;
			return this;
		}
		
		method clear() -> Vec3 {
			return this.setAt(0.0, 0.0, 0.0);
		}
	
		method copy(Vec3 another) -> Vec3 {
			return this.setAt(another.x, another.y, another.z);
		}
	
		// Math
		method add(Vec3 another) -> Vec3 {
			return this.setAt(this.x + another.x, this.y + another.y, this.z + another.z);
		}
	
		method sub(Vec3 another) -> Vec3 {
			return this.setAt(this.x - another.x, this.y - another.y, this.z - another.z);
		}
	
		method scale(real number) -> Vec3 {
			return this.setAt(this.x*number, this.y*number, this.z*number);
		}
	
		method div(real number) -> Vec3 {
			return this.scale(1.0/number);
		}
	
		method dot(Vec3 another) -> real {
			return this.x*another.x + this.y*another.y + this.z*another.z;
		}
	
		method lengthSqr() -> real {
			return this.x*this.x + this.y*this.y + this.z*this.z;
		}
	
		method length() -> real {
			return SquareRoot(this.x*this.x + this.y*this.y + this.z*this.z);
		}
	
		method distToSqr(Vec3 another) -> real {
			return (this.x - another.x)*(this.x - another.x) + (this.y - another.y)*(this.y - another.y) + (this.z - another.z)*(this.z - another.z);
		}
	
		method distTo(Vec3 another) -> real {
			return SquareRoot(this.distToSqr(another));
		}
	
		method angle(Vec3 another) -> real {
			return Acos(this.dot(another)/this.length()*another.length());
		}
	
		method normalize() -> Vec3 {
			debug if (this.length == 0.0) { dbgT("attempt to normalize vector with zero length"); return this; }
			return this.scale(1.0/this.length());
		}
	
		static method cross(Vec3 edge1, Vec3 edge2) -> Vec3 {
			return Vec3.createAt(edge1.y*edge2.z - edge1.z*edge2.y, edge1.z*edge2.x - edge1.x*edge2.z, edge1.x*edge2.y - edge1.y*edge2.x);
		}
	
		// Misc.
		method reflect(Vec3 normal) -> Vec3 {
			Vec3 temp = Vec3.clone(normal).scale(2.0*this.dot(normal));
			this.sub(temp);
			temp.destroy();
			return this;
		}
	
		static method triangleNormal(Vec3 a, Vec3 b, Vec3 c) -> Vec3 {
			Vec3 edge1 = Vec3.clone(b).sub(a);
			Vec3 edge2 = Vec3.clone(c).sub(a);
			Vec3 result = Vec3.cross(edge1, edge2).normalize();
			edge1.destroy();
			edge2.destroy();
			return result;
		}
	}

}
20

» WarCraft 3 / Есть ли идеи как сделать ульту пангольера из доты?

Крч, надо взять героя, свернуть его в шар и катить вперед, плавно поворачивая по сторонам. Не благодари!