Skip to main content

Developer Guidelines

Things to follow and things to avoid

We highly suggest to follow these guidelines when developing Lua scripts for LS.
Please take your time and go through this article carefully.

Getting Started

  • LS looks up Lua modules in GS\tier3\ folder. There is an example Twisted Fate script located in that folder.
  • Lua Manager can be accessed from in-game menu, in Champion tab.
  • Module name is the same as folder name in GS\tier3\{MODULE_NAME} path.
  • Entry point file must be named module.lua.
  • We use luajit-2.1.0 in case if you want luac your raw source to bytecode.
  • For more detailed information read Getting Started article.

Guidelines

General Lua

Hashes

In LS we prefer using hashes where we can instead of string comparisons. This is what the game does, number comparison is faster and more reliable.
Read more about hashes here.

Champion Script Requirements

  • Make sure to call Champions.CppScriptMaster(false) to unload internal core (C++) champion script. You can see how it's done in example Twisted Fate Lua script.
  • Please always add CastSpecialImmobileTarget implementation to your Champion scripts.
    This is a very basic, yet extremely useful feature. It can use skillshots on target in special conditions, such as recalling in FoW, Master Yi Q landing, Zed R landing or Zhonya.
  • If DamageLib is missing damage map for your champion - please add it. You may read more on DamageLib map in sections below.
  • Please carefully follow all Menu guidelines.
  • Use unique key for your script menu. This is important to avoid script menu conflicts.
    If you are developing Champion script then make sure to add unique suffix to menu key, i.e.:
Game.localPlayer.charName .. "_YourName"
  • Make sure to use Champions.CreateBaseMenu to create Extra Settings menu. This menu is important and generalized. It has common shared keybind for Spell Farm feature and several other settings which are generally used by all champion scripts.
  • Avoid using common hotkeys such as keys used by other core scripts like Orbwalker or Evade - i.e. don't bind Z, X, C, V, Space, K and so on.
    Same applies to most common LoL keys, such as A, S, D, F, P (Shop), etc.
    However, when it comes to LoL keys - there are some exceptions which we do globally in our scripts. In some cases it is acceptable to override some of these:
    • You may override Q, W, E, R keys if it is passive spell and can add extra functionality to the champion.
    • It is fine to override T, Y or some of number keys like 2, 3, 4. T and Y can be useful for ultimate assistance (semi-auto R), fast combos or other special combos.
    • Feel free to be creative with these.

SDK

  • Do not ever use .displayName or other localized strings in your logic code, variables, keys, indexes and so on. Instead please use hashes or .charName.
    Localized strings should be used only for visuals, such as texts in Menu for example.
  • Avoid calling IssueOrder directly.
  • Do not throw all Renderer functions in OnImguiDraw callback. Use only ImGui Renderer functions in OnImguiDraw.
  • Please avoid using in your Release code stuff like DrawCircle3D, DrawVectorPoly, DrawCross and other similar Renderer functions which are marked for Dev/Debug only use.
    You may use them if you don't have any other option, but otherwise - please stick to Release Ready Renderer functions instead.
  • Avoid using usePacket true argument in several functions. In general it's better to use false by default, unless you know what you are doing and you want specifically to prevent other scripts from processing this call.
  • Do not throw all your logic inside OnFastTick handler. Do it only when it's necessary. Instead prefer using OnTick and let user decide how fast it runs with Ticks Delay setting.
    Read more about it in OnTick, OnFastTick and Ticks Delay setting caveat article

Caveats

Caveats describe various quirks in our SDK and will help you to avoid some important problems in your code.
Make sure to check all of them in each severity subcategory.

Prediction

  • Important: In spell data speed property use math.flt_max instead of math.huge.

Evade

  • Please do not neglect Evade API in your Champion scripts. Good Evade integration is what make a big difference between mediocre and high quality scripts.
  • Evade has built-in SpellBlock feature, which simply blocks many spells while evading except those which are in hardcoded whitelist (by default) or using advanced settings in menu (optional).
    Because of this feature your champion in Combo Mode can do silly stuff while evading. That's why it is extremely important to realize when you want to commit to combo or give up on it.
  • General rule is to avoid conflicts with Evade. You don't want to start executing important combo while dodging a spell, waste some cooldowns and then Evade will block you from doing the rest.
    Something like this will look ridiculous, nobody wants something like this to happen to them in-game. There are several things to keep in mind:
    • You must determine whether you are dodging some dangerous spell already and if yes - then postpone executing important combos.
    • If you are not dodging anything or dodging low danger level spells (without hard CC) - you may ignore those skillshots on purpose and execute your combo.
      It's up to you for how long you want to ignore skillshots while executing combo. Don't forget to stop ignoring them once you are done or when some dangerous skillshot is aiming you.
    • If you are dashing somewhere - please check if it's safe to do so using Evade API.
      If you intend to dash anyway, despite some skillshots in the way or at the end position of the dash - make sure to ignore these skillshots to avoid conflicts, otherwise Evade may dodge these skillshots upon your arrival, rendering all your intentions impossible.

DamageLib Map

  • DamageLib works not only for player's character, but also for enemies and allies.
    So please keep this in mind while working on it. This means that this code should work even if this hero is an enemy or ally.
  • When adding custom damage functions to damage map please use Game.spelldataHash hash method instead of getting spell name from player's spell book entries.
  • Inside damage function body never use hardcoded spell slots! Better use GetSpellSlot(hash) to retrieve it first, like in the example below.
  • You can learn how to extend DamageLib map from this example here.