public static void CreateSpellData( Obj_AI_Base hero, Vector3 spellStartPos, Vector3 spellEndPos, SpellData spellData, GameObject obj = null, float extraEndTick = 0.0f, bool processSpell = true, SpellType spellType = SpellType.None, bool checkEndExplosion = true, float spellRadius = 0) { while (true) { if (checkEndExplosion && spellData.HasEndExplosion) { CreateSpellData(hero, spellStartPos, spellEndPos, spellData, obj, extraEndTick, false, spellData.SpellType, false); processSpell = true; spellType = SpellType.Circular; checkEndExplosion = false; spellRadius = 0; continue; } if (spellStartPos.Distance(MyHero.Position) < spellData.Range + 1000) { var startPosition = spellStartPos.To2D(); var endPosition = spellEndPos.To2D(); var direction = (endPosition - startPosition).Normalized(); var endTick = 0f; if (spellType == SpellType.None) { spellType = spellData.SpellType; } if (spellData.FixedRange) { if (endPosition.Distance(startPosition) > spellData.Range) { endPosition = startPosition + direction * spellData.Range; } } switch (spellType) { case SpellType.Line: endTick = spellData.SpellDelay + spellData.Range / spellData.ProjectileSpeed * 1000; endPosition = startPosition + direction * spellData.Range; if (spellData.FixedRange) { if (endPosition.Distance(startPosition) < spellData.Range) { endPosition = startPosition + direction * spellData.Range; } } if (endPosition.Distance(startPosition) > spellData.Range) { endPosition = startPosition + direction * spellData.Range; } if (spellData.UseEndPosition) { var range = endPosition.Distance(startPosition); endTick = spellData.SpellDelay + range / spellData.ProjectileSpeed * 1000; } if (obj != null) { endTick -= spellData.SpellDelay; } break; case SpellType.Circular: endTick = spellData.SpellDelay; if (endPosition.Distance(startPosition) > spellData.Range) { endPosition = startPosition + direction * spellData.Range; } if (spellData.ProjectileSpeed == 0 && hero != null) { endPosition = hero.ServerPosition.To2D(); } else if (spellData.ProjectileSpeed > 0) { endTick = endTick + 1000 * startPosition.Distance(endPosition) / spellData.ProjectileSpeed; if (spellData.SpellType == SpellType.Line && spellData.HasEndExplosion) { if (!spellData.UseEndPosition) { endPosition = startPosition + direction * spellData.Range; } } } break; case SpellType.Arc: endTick = endTick + 1000 * startPosition.Distance(endPosition) / spellData.ProjectileSpeed; if (obj != null) { endTick -= spellData.SpellDelay; } break; case SpellType.Cone: endPosition = startPosition + direction * spellData.Range; endTick = spellData.SpellDelay; if (endPosition.Distance(startPosition) > spellData.Range) { endPosition = startPosition + direction * spellData.Range; } if (spellData.ProjectileSpeed == 0 && hero != null) { endPosition = hero.ServerPosition.To2D(); } else if (spellData.ProjectileSpeed > 0) { endTick = endTick + 1000 * startPosition.Distance(endPosition) / spellData.ProjectileSpeed; } break; default: return; } if (spellData.Invert) { var dir = (startPosition - endPosition).Normalized(); endPosition = startPosition + dir * startPosition.Distance(endPosition); } if (spellData.IsPerpendicular) { startPosition = spellEndPos.To2D() - direction.Perpendicular() * spellData.SecondaryRadius; endPosition = spellEndPos.To2D() + direction.Perpendicular() * spellData.SecondaryRadius; } endTick += extraEndTick; var newSpell = new Spell { StartTime = Environment.TickCount, EndTime = Environment.TickCount + endTick, StartPos = startPosition, EndPos = endPosition, Height = spellEndPos.Z + spellData.ExtraDrawHeight, Direction = direction, Info = spellData, SpellType = spellType }; newSpell.Radius = spellRadius > 0 ? spellRadius : newSpell.GetSpellRadius(); if (spellType == SpellType.Cone) { newSpell.Radius = 100 + newSpell.Radius * 3; newSpell.CnStart = startPosition + direction; newSpell.CnLeft = endPosition + direction.Perpendicular() * newSpell.Radius; newSpell.CnRight = endPosition - direction.Perpendicular() * newSpell.Radius; } if (hero != null) { newSpell.HeroId = hero.NetworkId; } if (obj != null) { newSpell.SpellObject = obj; newSpell.ProjectileId = obj.NetworkId; } var spellId = CreateSpell(newSpell, processSpell); if (extraEndTick != 1337f) { DelayAction.Add((int) (endTick + spellData.ExtraEndTime), () => DeleteSpell(spellId)); } } break; } }