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
- Avoid using global scope variables (
_G
table). - Avoid using
ENV
unique variables such asMODULE_NAME
. If your script will ever be added to the core - it will have differentENV
. - Avoid storing refs to C++ objects in Lua variables.
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.
Menu
- 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 createExtra 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 asA
,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 like2
,3
,4
.T
andY
can be useful for ultimate assistance (semi-auto R), fast combos or other special combos. - Feel free to be creative with these.
- You may override
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 inOnImguiDraw
callback. Use only ImGui Renderer functions inOnImguiDraw
. - Please avoid using in your Release code stuff like
DrawCircle3D
,DrawVectorPoly
,DrawCross
and other similarRenderer
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 usefalse
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 usingOnTick
and let user decide how fast it runs withTicks 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 ofmath.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.