-- Cast on positionplayer :castSpell("pos", 0, enemy.pos)-- Cast on targetplayer :castSpell("obj", 1, enemy)-- Cast on selfplayer :castSpell("self", 2)if enemy:hasBuff("zedpassivecd") then -- Passive on cooldownendfor enemy in objManager.ienemies do if enemy:isValidTarget(600) then if enemy.healthPercent < 0.5 then player:attack(enemy) end endendfor enemy in objManager.ienemies do if enemy:isValidTarget(1200) then -- Check if enemy has our mark if enemy:hasBuff("zedpassivecd") then local buffTime = enemy:getBuffTime("zedpassivecd") if buffTime > 2 then -- Safe to engage player:attack(enemy) end end endendlocal target = TargetSelector.getLowHP(600)if target then -- Predict where they'll be in 0.5s local predictedPos = target:predictPosition(0.5) -- Attack them player:attack(target) -- Move away from their position local awayPos = player.pos + (player.pos - predictedPos):normalize() * 100 player :move(awayPos.x, awayPos.y, awayPos.z)endfor minion in objManager.ienemyminions do if minion:isValidTarget(600) then local aaDamage = damage.autoattack(player, minion) -- Last hit if we can kill it if minion.health < aaDamage then player:attack(minion) break end endendlocal bestPosition = nillocal maxHits = 0for enemy in objManager.ienemies do if enemy:isValidTarget(1000) then -- Count enemies in AOE range local nearbyEnemies = objManager.getEnemiesInRange(300, enemy) if #nearbyEnemies > maxHits then maxHits = #nearbyEnemies bestPosition = enemy.pos end endendif maxHits >= 2 then player :castSpell("pos", 3, bestPosition)endlocal enemies = objManager.getEnemiesInRange(1000, player)if #enemies >= 3 then -- Too many enemies, retreat player:move(safePosition)endlocal input = { delay = 0.25, radius = 70, range = 1000, speed = 1400, type = SkillshotType.Line, collisionFlags = Collision_Minions}local prediction = pred.get_prediction(target, input)if prediction.hitChance >= HitChance_High then player :castSpell("pos", 0, prediction.castPosition)endfor enemy in objManager.ienemies do if enemy:isValidTarget(900) then -- Check if they're stunned/rooted/snared if pred.is_immobile(enemy) then local timeImmobile = pred.time_until_mobile(enemy) -- If they're immobile for at least 1s, guaranteed hit if timeImmobile >= 1.0 then player :castSpell("pos", 3, enemy.pos) end end endendlocal target = TargetSelector.getLowHP(1000)if target then local qDmg = damage.spell(player, target, 0) local wDmg = damage.spell(player, target, 1) local eDmg = damage.spell(player, target, 2) local rDmg = damage.spell(player, target, 3) local aaDmg = damage.autoattack(player, target) * 2 local totalDamage = qDmg + wDmg + eDmg + rDmg + aaDmg if totalDamage > target.health * 1.2 then -- We can kill with 20% safety margin print("All-in: " .. totalDamage .. " > " .. target.health) endend-- Check if we can kill with Q+W+E combolocal spellMask = (1<<0) | (1<<1) | (1<<2) -- Q | W | Efor enemy in objManager.ienemies do if enemy:isValidTarget(800) then if damage.isKillable(enemy, spellMask, true) then -- Execute combo player:castSpell("obj", 0, enemy) player:castSpell("obj", 1, enemy) player:castSpell("obj", 2, enemy) end endendlocal selector = TargetSelector() :setMode(TargetMode.LowHP) :range(1000) :onlyKillable() :excludeClones() :notUnderTower()local target = selector:execute()if target then player:attack(target)end-- Prioritize low HP enemies that are closerlocal target = TargetSelector() :setMode(TargetMode.Custom) :range(1000) :customScore(function(enemy) local hpScore = (1 - enemy:healthPercent()) * 100 local distScore = (1000 - enemy:dist(player)) / 10 return hpScore + distScore end) :execute()if target then player:attack(target)endif player:spellState(0) == SpellState.Ready then local target = TargetSelector.getClosest(1000) if target then player :castSpell("pos", 0, target.pos) endendlocal qReady = player:spellState(0) == SpellState.Readylocal wReady = player:spellState(1) == SpellState.Readylocal eReady = player:spellState(2) == SpellState.Readyif qReady and wReady and eReady then local target = TargetSelector.getLowHP(800) if target then player:castSpell("obj", 0, target) player:castSpell("obj", 1, target) player:castSpell("obj", 2, target) endend-- Find direction away from enemieslocal enemyDir = Vector3(0, 0, 0)local enemyCount = 0for enemy in objManager.ienemies do if enemy:dist(player) < 1000 then enemyDir = enemyDir + (enemy.pos - player.pos) enemyCount = enemyCount + 1 endendif enemyCount > 0 then -- Normalize and go opposite direction local escapeDir = geometry.normalize(-enemyDir) local escapePos = player.pos + escapeDir * 400 player :move(escapePos.x, escapePos.y, escapePos.z)endlocal target = TargetSelector.getClosest(1000)if target then local castPos = target.pos local skillshotWidth = 80 -- Check if other enemies are in the line local hitCount = 0 for enemy in objManager.ienemies do if geometry.intersectLine(player.pos, castPos, enemy.pos, skillshotWidth) then hitCount = hitCount + 1 end end print("Can hit " .. hitCount .. " enemies")endevents::on<OnSpellCastEvent>(function(event) if event.caster.isEnemy then print("Enemy cast: " .. event.spellName) -- Dodge if it's a dangerous spell if event.spellName == "LuxLightBinding" then local dodgePos = player.pos + player.dir * 200 player :move(dodgePos.x, dodgePos.y, dodgePos.z) end endend)events::on<OnTickEvent>(function() -- Main script logic runs every tick local target = TargetSelector.getClosest(1000) if target and target:isValidTarget(900) then -- Combo logic if player:spellState(0) == SpellState.Ready then local pred = pred.get_prediction(target, qInput) if pred.hitChance >= HitChance_High then player :castSpell("pos", 0, pred.castPosition) end end endend)events::on<OnBuffAddEvent>(function(event) if event.target.isMe and event.buffName == "zhonyasringshield" then print("Zhonya's active! Invulnerable for 2.5s") end -- Track enemy buffs if event.target.isEnemy and event.buffName == "summonerexhaust" then print(event.target.charName .. " exhausted!") endend)High-performance caching with automatic expiration and O(1) lookups.
Thread-safe key-value storage for frequently accessed game data.
-- Cache enemy positions with 2 second TTLcb.add(cb.CB_TICK, function() for enemy in objManager.ienemies do if enemy:isValidTarget() then local key = "pos_" .. enemy.networkID cache.set(key, enemy.pos, 2.0) end endend)-- Later, retrieve cached positionlocal cachedPos = cache.get("pos_" .. enemy.networkID)if cachedPos then -- Use cached position for calculations local distance = player.pos:dist(cachedPos)end-- Calculate and cache combo damagefunction getComboDamage(target) local cacheKey = "combo_" .. target.networkID if cache.has(cacheKey) then return cache.get(cacheKey) end -- Expensive calculation local qDmg = damage.spell(player, target, 0) local wDmg = damage.spell(player, target, 1) local eDmg = damage.spell(player, target, 2) local total = qDmg + wDmg + eDmg -- Cache for 0.5 seconds cache.set(cacheKey, total, 0.5) return totalend-- Use cached damagelocal dmg = getComboDamage(enemy)if dmg > enemy.health then -- Execute comboend-- Cache spell data to avoid repeated lookupsfunction getSpellData(spellName) local cacheKey = "spell_" .. spellName if cache.has(cacheKey) then return cache.get(cacheKey) end local spellData = SpellDB.get(spellName) cache.set(cacheKey, spellData, 60) -- Cache for 1 minute return spellDataend-- Monitor cache performancelocal stats = cache.stats()print("Cache hit rate: " .. (stats.hits / (stats.hits + stats.misses) * 100) .. "%")Best used for: expensive calculations, database queries, position predictions, and frequently accessed data.
Buff/debuff detection with duration tracking and comprehensive database.
Detect, analyze, and query buffs/debuffs on any game unit.
cb.add(cb.CB_TICK, function() local me = player -- Check if we're stunned or rooted if me:hasBuff("stun") or me:hasBuff("root") then -- Cancel combo, we can't move return end -- Check for silence (can't cast spells) if me:hasBuff("silence") then -- Skip spell casting logic return end -- Proceed with normal logicend)-- Track Vayne Silver Bolts stacksfor enemy in objManager.ienemies do if enemy:isValidTarget(550) then local stacks = enemy:getBuffCount("VayneSilverDebuff") if stacks == 2 then -- Enemy has 2 stacks, next AA will proc print(enemy.charName .. " has 2 silver bolt stacks!") end endend-- Track Darius passive stackslocal target = TargetSelector.get(player, 400)if target then local hemorrhageStacks = target:getBuffCount("dariushemo") if hemorrhageStacks >= 5 then -- Full passive stacks - DON'T fight! print("DANGER: Full Darius passive!") endend-- Wait for enemy buff to expire before engaginglocal target = TargetSelector.get(player, 1000)if target then -- Check if enemy has defensive buff if target:hasBuff("summonerbarrier") then local remaining = target:getBuffRemaining("summonerbarrier") print("Barrier expires in " .. remaining .. "s") if remaining < 0.5 then -- Barrier about to expire, prepare combo prepareCombo(target) end end -- Check steroid buff duration if player:hasBuff("LuluW") then local duration = player:getBuffDuration("LuluW") local remaining = player:getBuffRemaining("LuluW") print("Whimsy: " .. remaining .. "/" .. duration .. "s") if remaining > 2 then -- Plenty of time, play aggressive executeCombo(target) end endend-- Debug: Print all buffs on playerlocal allBuffs = player:getAllBuffs()print("Active buffs on player:")for i, buff in ipairs(allBuffs) do local remaining = player:getBuffRemaining(buff.name) local stacks = player:getBuffCount(buff.name) print(string.format( "[%d] %s (x%d) - %.1fs remaining", i, buff.name, stacks, remaining )) if buffs.isCC(buff.name) then print(" ^^ THIS IS CC!") endendThe module includes a comprehensive JSON database containing metadata for hundreds of League of Legends buffs:
The Buffs module integrates seamlessly with:
Item database access, inventory management, and active item usage.
Query item data, manage inventory, and use active items.
-- Item IDslocal YOUMUUS = 3142local ECLIPSE = 6692local BOTRK = 3153cb.add(cb.CB_TICK, function() local target = TargetSelector.get(player, 1000) if not target then return end -- Use Youmuu's for speed boost if player:hasItem(YOUMUUS) then local slot = player:getItemSlot(YOUMUUS) if items.getCooldown(slot) == 0 then player:useItem(slot) end end -- Use Eclipse when in range if player:hasItem(ECLIPSE) and target.dist < 550 then local slot = player:getItemSlot(ECLIPSE) if items.getCooldown(slot) == 0 then player:useItem(slot) player:attack(target) end end -- Use BotRK on low HP target if player:hasItem(BOTRK) and target:healthPercent() < 50 then local slot = player:getItemSlot(BOTRK) if items.getCooldown(slot) == 0 then player:castSpell("obj", slot, target) end endend)-- Track mythic item completionlocal MYTHIC_ITEMS = { 3152, -- Hextech Rocketbelt 6653, -- Liandry's Anguish 3068, -- Sunfire Aegis 6632, -- Divine Sunderer}local hasMythic = falsefor _, itemId in ipairs(MYTHIC_ITEMS) do if player:hasItem(itemId) then hasMythic = true local info = items.getInfo(itemId) print("Mythic completed: " .. info.name) break endendif not hasMythic then print("No mythic item yet - " .. player.gold .. "g available")end-- Auto-use defensive itemslocal ZHONYAS = 3157local STOPWATCH = 2420local QSS = 3140cb.add(cb.CB_TICK, function() local me = player -- Use Zhonya's when low HP and in danger if me:hasItem(ZHONYAS) and me:healthPercent() < 20 then local enemiesNearby = 0 for enemy in objManager.ienemies do if enemy:isValidTarget(600) then enemiesNearby = enemiesNearby + 1 end end if enemiesNearby >= 2 then local slot = me:getItemSlot(ZHONYAS) if items.getCooldown(slot) == 0 then me:useItem(slot) print("ZHONYAS ACTIVATED!") end end end -- Use QSS to cleanse CC if me:hasItem(QSS) then if me:hasBuff("stun") or me:hasBuff("root") or me:hasBuff("charm") then local slot = me:getItemSlot(QSS) if items.getCooldown(slot) == 0 then me:useItem(slot) print("QSS CLEANSED CC!") end end endend)-- Query item informationlocal itemId = 3089 -- Rabadon's Deathcaplocal info = items.getInfo(itemId)if info then print("Item: " .. info.name) print("Cost: " .. info.gold.total) print("AP: " .. info.stats.abilityPower) if items.isActive(itemId) then print("Has active component") else print("Passive item only") endend-- Check inventory valuelocal totalGold = 0for slot = 0, 6 do local item = player:getItemInSlot(slot) if item then local info = items.getInfo(item.id) totalGold = totalGold + info.gold.total endendprint("Inventory value: " .. totalGold .. "g")Item slot numbering:
Note: Trinkets use SpellSlot.Trinket for casting
The Items module integrates with:
Chainable query operations for filtering, sorting, and aggregating game objects.
LINQ-style fluent API for powerful object collection queries.
-- Get 3 lowest HP enemies within 1000 rangelocal lowHpEnemies = objManager.getObjects() :enemies() :inRange(player.pos, 1000) :sortByHealth() :take(3) :toVector()for _, enemy in ipairs(lowHpEnemies) do print(enemy.charName .. " has " .. enemy.health .. " HP")end-- Count enemies in AOE spell arealocal spellPos = Vector3(1000, 0, 2000)local spellRadius = 400local enemiesInAOE = objManager.getObjects() :enemies() :alive() :inRange(spellPos, spellRadius) :count()if enemiesInAOE >= 3 then -- Cast AOE spell player:castSpell("pos", SpellSlot.R, spellPos)end-- Find closest minion below 100 HP for last hittinglocal lastHitTarget = objManager.getObjects() :minions() :enemies() :where(function(m) return m.health < 100 end) :sortByDistance(player.pos) :firstOrNull()if lastHitTarget then player:attack(lastHitTarget)end-- Sum total AD of all enemies nearbylocal totalEnemyAD = objManager.getObjects() :enemies() :heroes() :inRange(player.pos, 1500) :sum(function(e) return e.totalAttackDamage end)if totalEnemyAD > 500 then print("DANGER: High enemy damage nearby!")end-- Check if all allies have sufficient HPlocal allAlliesSafe = objManager.getObjects() :allies() :heroes() :all(function(a) return a:healthPercent() > 30 end)if not allAlliesSafe then -- Play defensively print("Team low on HP - defensive mode")end-- Complex query: Find best gank target-- (Enemy, isolated, low HP, high priority)local gankTarget = objManager.getObjects() :enemies() :heroes() :alive() :validTargets(2000) :where(function(e) -- Check if isolated (no allies nearby) local alliesNearby = objManager.getObjects() :allies() :heroes() :inRange(e.pos, 800) :count() return alliesNearby == 0 end) :sortBy(function(e) -- Lower score = better target return e:healthPercent() + (e.armor / 100) end) :firstOrNull()if gankTarget then print("Best gank target: " .. gankTarget.charName)endNote: For performance-critical paths with large collections, consider caching results or batching operations.
Humanized skillshot dodging with realistic reaction times and learning systems.
Intelligent detection and evasion with advanced humanization.
Configure evade behavior with extensive options:
| Level | Reaction Time | Fail Rate |
|---|---|---|
| Bronze | 300-500ms | 25% |
| Silver | 250-400ms | 18% |
| Gold | 200-350ms | 12% |
| Platinum | 150-280ms | 8% |
| Diamond | 100-220ms | 5% |
| Master | 80-180ms | 3% |
| Challenger | 50-120ms | 1.5% |
| Inhuman ⚠️ | 0-50ms | 0% |
⚠️ Inhuman level NOT recommended - instant reactions are detectable
-- Initialize evade with safe settingslocal config = { enabled = true, mode = EvadeMode.DodgeAll, skillLevel = SkillLevel.Diamond, addReactionDelay = true, addMouseMovementTime = true, addRandomization = true, allowFlashToEvade = false -- NEVER flash to evade}evade.initialize(config)-- Main game loopcb.add(cb.CB_TICK, function() evade.update() if evade.shouldEvade() then local safePos = evade.getSafePosition() evade.executeEvade() endend)-- Only evade high-priority spellslocal config = { mode = EvadeMode.Custom, skillLevel = SkillLevel.Platinum, minDangerLevel = DangerLevel.Medium, dodgeCC = true, -- Always dodge CC dodgeDangerous = true, -- Always dodge ults -- Callback when skillshot detected onSkillshotDetected = function(skillshot) if skillshot.dangerLevel == DangerLevel.Extreme then print("EXTREME DANGER: " .. skillshot.spellName) return true -- Process this end -- Ignore low danger skillshots return skillshot.dangerLevel >= DangerLevel.Medium end}evade.initialize(config)-- Validate positions before movementcb.add(cb.CB_ISSUE_ORDER, function(order) if order.type == OrderType.MoveTo then local targetPos = order.targetPos -- Check if position is safe if not evade.isSafe(targetPos) then local danger = evade.getDangerAt(targetPos) print("UNSAFE POSITION: Danger level " .. danger) -- Get alternative safe position local safePos = evade.getSafePosition() if safePos then order.targetPos = safePos else -- Cancel movement if no safe path return false end end end return trueend)-- Display active skillshots and dangerlocal skillshots = evade.getActiveSkillshots()for _, ss in ipairs(skillshots) do print(string.format( "Skillshot: %s from %s (Danger: %s)", ss.spellName, ss.caster.charName, ss.dangerLevel )) -- Draw skillshot hitbox draw.circle(ss.position, ss.radius, 1, 0, 0)end-- Show statslocal stats = evade.getStats()print(string.format( "Evade Stats: %d dodged / %d total (%.1f%%)", stats.successfulDodges, stats.totalSkillshots, stats.successfulDodges / stats.totalSkillshots * 100))Advanced systems make evade behavior realistic and undetectable:
Rendering API for shapes, text, and overlays in world and screen space.
Visual debugging and custom overlay creation.
cb.add(cb.CB_DRAW_WORLD, function() local me = player -- Draw Q range (blue) draw.circle(me.pos, 1000, 0.2, 0.5, 1.0, 0.3) -- Draw W range (green) draw.circle(me.pos, 800, 0.2, 1.0, 0.5, 0.3) -- Draw R range (red) draw.circle(me.pos, 1500, 1.0, 0.2, 0.2, 0.3) -- Draw auto-attack range (white) draw.circle(me.pos, me.attackRange, 1.0, 1.0, 1.0, 0.5)end)cb.add(cb.CB_DRAW_WORLD, function() local target = TargetSelector.get(player, 1200) if target then -- Draw line to target draw.line(player.pos, target.pos, 2, 1.0, 0.0, 0.0) -- Draw target circle draw.circle(target.pos, 100, 1.0, 1.0, 0.0, 0.8) -- Draw predicted position local predPos = target:predictPosition(0.5) draw.circle(predPos, 80, 0.0, 1.0, 1.0, 0.5) -- Draw line to prediction draw.line(target.pos, predPos, 1, 0.5, 1.0, 0.5, 0.5) -- Draw health bar local screenPos = draw.worldToScreen(target.pos) if screenPos then local hpPercent = target:healthPercent() draw.rect( screenPos.x - 25, screenPos.y - 40, 50 * (hpPercent / 100), 5, 0.0, 1.0, 0.0 ) end endend)cb.add(cb.CB_DRAW_HUD, function() local width, height = draw.getScreenSize() -- Draw script status draw.text(10, 10, "rito.sh - ACTIVE", 14, 0.0, 1.0, 0.0) -- Draw FPS draw.text(10, 30, "FPS: " .. gameTime, 12, 1.0, 1.0, 1.0) -- Draw combo status (top-center) local comboKey = "Space" local color = input.isKeyDown(comboKey) and {1, 0, 0} or {0.5, 0.5, 0.5} draw.text( width / 2 - 50, 10, "COMBO: " .. (input.isKeyDown(comboKey) and "ON" or "OFF"), 16, color[1], color[2], color[3] ) -- Draw target info local target = TargetSelector.get(player, 1000) if target then draw.text(10, 60, "Target: " .. target.charName, 12, 1, 1, 0) draw.text(10, 75, "HP: " .. math.floor(target.health), 12, 1, 1, 0) draw.text(10, 90, "Distance: " .. math.floor(target.dist), 12, 1, 1, 0) endend)-- Visualize Ezreal Qcb.add(cb.CB_DRAW_WORLD, function() if player.charName == "Ezreal" then local qReady = player:spellState(SpellSlot.Q) == SpellState.Ready if qReady then local target = TargetSelector.get(player, 1150) if target then local pred = pred.get_prediction(target, 0.25, 60, 1150, 2000) if pred.canHit then -- Draw Q line local endPos = player.pos:extended(pred.castPosition, 1150) draw.line(player.pos, endPos, 60, 0.0, 0.8, 1.0, 0.3) -- Draw hit indicator draw.circle(pred.castPosition, 80, 0.0, 1.0, 0.0, 0.7) -- Draw hitchance text draw.text3D( pred.castPosition, "HIT: " .. pred.hitChance, 14, 1.0, 1.0, 1.0 ) end end end endend)-- Visualize evade danger zonescb.add(cb.CB_DRAW_WORLD, function() local skillshots = evade.getActiveSkillshots() for _, ss in ipairs(skillshots) do local color = {1, 0, 0} if ss.dangerLevel == DangerLevel.Low then color = {1, 1, 0} elseif ss.dangerLevel == DangerLevel.Extreme then color = {1, 0, 1} end -- Draw skillshot area if ss.type == "line" then draw.line(ss.start, ss.end, ss.radius * 2, color[1], color[2], color[3], 0.4) elseif ss.type == "circle" then draw.circle(ss.position, ss.radius, color[1], color[2], color[3], 0.4) end end -- Draw safe position if evade.shouldEvade() then local safePos = evade.getSafePosition() if safePos then draw.circle(safePos, 100, 0.0, 1.0, 0.0, 0.7) draw.line(player.pos, safePos, 3, 0.0, 1.0, 0.0, 0.9) end endend)Use these callbacks for drawing:
Note: Drawing operations are batched and rendered efficiently. Heavy draw calls may impact performance.
Global game state, timing, terrain queries, and match information.
Access game state and utility functions.
-- Track game time for objective timerslocal dragonSpawnTime = 5 * 60 -- 5 minuteslocal baronSpawnTime = 20 * 60 -- 20 minutescb.add(cb.CB_TICK, function() local currentTime = game.getTime() if currentTime > dragonSpawnTime then -- Dragon is spawned if currentTime % 60 < 1 then -- Print once per minute print("Dragon available!") end end if currentTime > baronSpawnTime then print("Baron available!") endend)-- Delay action with game timelocal lastCastTime = 0local cooldown = 1.0 -- 1 second cooldowncb.add(cb.CB_TICK, function() if game.getTime() - lastCastTime > cooldown then -- Can cast again lastCastTime = game.getTime() player:castSpell("self", SpellSlot.Q) endend)-- Validate position before movementfunction isSafePosition(pos) -- Check if it's a wall if game.isWallAt(pos) then return false end -- Check if too close to enemies for enemy in objManager.ienemies do if enemy:isValidTarget() and enemy.pos:dist(pos) < 400 then return false end end return trueend-- Move to cursor if safecb.add(cb.CB_TICK, function() if input.isKeyDown("Space") then local cursorPos = game.getCursorPos() if isSafePosition(cursorPos) then player:move(cursorPos) else print("Unsafe position!") end endend)-- Hide in brush when low HPcb.add(cb.CB_TICK, function() local me = player if me:healthPercent() < 30 then -- Find nearest brush local nearestBrush = nil local minDist = 999999 for x = -200, 200, 100 do for y = -200, 200, 100 do local checkPos = me.pos + Vector3(x, 0, y) if game.isGrass(checkPos) then local dist = me.pos:dist(checkPos) if dist < minDist then minDist = dist nearestBrush = checkPos end end end end if nearestBrush and minDist < 500 then -- Move to brush me:move(nearestBrush) print("Hiding in brush!") end endend)-- Different logic for different mapslocal MAP_SR = 11 -- Summoner's Riftlocal MAP_ARAM = 12 -- Howling Abysslocal MAP_TFT = 22 -- TFTcb.add(cb.CB_LOAD, function() local mapId = game.getMapId() if mapId == MAP_SR then print("Summoner's Rift - Full feature set") -- Enable jungle clear, objective tracking, etc. elseif mapId == MAP_ARAM then print("ARAM - Teamfight mode") -- Disable jungle features, focus on teamfights elseif mapId == MAP_TFT then print("TFT detected - disabling script") return endend)-- Adjust prediction based on pingfunction getPredictionDelay() local ping = game.getPing() -- Add ping compensation to spell delay local baseDelay = 0.25 local pingDelay = ping / 1000 -- Convert ms to seconds return baseDelay + pingDelayend-- Use in predictionlocal target = TargetSelector.get(player, 1000)if target then local delay = getPredictionDelay() local pred = pred.get_prediction(target, delay, 70, 1000, 1400) if pred.canHit then player:castSpell("pos", SpellSlot.Q, pred.castPosition) endendCommon map IDs:
Logging and debugging with multiple levels and file output.
Debug and monitor scripts with structured logging.
-- Simple logginglog.info("Script loaded successfully")log.info("Player: " .. player.charName)-- Formatted logginglog.info(string.format( "Position: (%.0f, %.0f, %.0f)", player.x, player.y, player.z))-- Warnings and errorsif not target then log.warn("No target found")endif player:healthPercent() < 10 then log.error("CRITICAL HP: " .. player.health)end-- Set log level (only show INFO and above)log.setLevel("INFO")-- These will be shownlog.info("Script initialized")log.warn("Low mana: " .. player.mana)log.error("Spell cast failed")-- This will be hidden (below INFO level)log.debug("Target health: " .. target.health)-- Enable debug modelog.setLevel("DEBUG")-- Now debug messages are shownlog.debug("Checking target validity...")log.debug("Prediction hit chance: " .. pred.hitChance)-- Enable file logginglog.setFile("logs/script.log")log.info("=== Script Started ===")log.info("Time: " .. os.date("%Y-%m-%d %H:%M:%S"))-- Log important events to filecb.add(cb.CB_DEATH, function(unit) if unit.isMe then log.error("DEATH: Died at " .. game.getTime() .. "s") elseif unit.isEnemy and unit.isHero then log.info("KILL: " .. unit.charName .. " eliminated") endend)cb.add(cb.CB_LEVEL_UP, function() log.info("LEVEL UP: Now level " .. player.level)end)-- Trace function callsfunction performCombo(target) log.trace("performCombo called") log.debug("Target: " .. target.charName) if player:spellState(SpellSlot.Q) ~= SpellState.Ready then log.warn("Q not ready, aborting combo") return false end log.debug("Casting Q...") local result = player:castSpell("obj", SpellSlot.Q, target) if result then log.info("Combo executed successfully") else log.error("Combo failed - spell cast returned false") end return resultend-- Comprehensive error loggingfunction safeCast(slot, target) log.debug("Attempting to cast " .. slot) if not target or not target.valid then log.error("Invalid target for spell cast") return false end if not target:isValidTarget() then log.warn("Target not valid: " .. target.charName) return false end local state = player:spellState(slot) if state ~= SpellState.Ready then log.debug("Spell not ready: " .. state) return false end return player:castSpell("obj", slot, target)end-- Log with conditionslocal LOG_SPELLS = truelocal LOG_MOVEMENT = falselocal LOG_TARGETING = truecb.add(cb.CB_CAST_SPELL, function(spell) if LOG_SPELLS then log.info(string.format( "[SPELL] %s cast %s at %.0fs", player.charName, spell.name, game.getTime() )) endend)-- Periodic stats logginglocal lastLogTime = 0local LOG_INTERVAL = 60 -- Log every 60 secondscb.add(cb.CB_TICK, function() if game.getTime() - lastLogTime > LOG_INTERVAL then lastLogTime = game.getTime() log.info("=== Status Update ===") log.info(string.format( "Level: %d | Gold: %d | KDA: %d/%d/%d", player.level, player.gold, player.kills or 0, player.deaths or 0, player.assists or 0 )) endend)-- Performance logginglocal frameCount = 0local startTime = game.getTime()cb.add(cb.CB_TICK, function() frameCount = frameCount + 1 if frameCount % 1000 == 0 then local elapsed = game.getTime() - startTime local fps = frameCount / elapsed log.info(string.format( "Performance: %.1f FPS (avg over %d frames)", fps, frameCount )) endend)When you set a log level, only messages at that level or higher are displayed. For example, setting level to INFO will show INFO, WARN, and ERROR, but hide DEBUG.
ImGui-based overlay system for creating in-game menus and ESP rendering.
Complete DirectX 11 overlay system with widgets and ESP rendering.
-- Create main menu windowgui.window("Script Menu", function() gui.text("Rito.sh - Script Controls") gui.separator() -- Combat section if gui.collapsingHeader("Combat") then local changed, newValue = gui.checkbox("Enable Combo", comboEnabled) if changed then comboEnabled = newValue end comboRange = gui.sliderInt("Combo Range", comboRange, 400, 1200) if gui.button("Reset Settings") then comboEnabled = false comboRange = 800 end end -- Drawing section if gui.collapsingHeader("Drawing") then drawRanges = gui.checkbox("Draw Ranges", drawRanges) drawPrediction = gui.checkbox("Draw Prediction", drawPrediction) gui.text("Circle Alpha:") gui.sameLine() circleAlpha = gui.sliderFloat("##alpha", circleAlpha, 0.0, 1.0) endend)gui.window("Feature Menu", function() if gui.beginTabBar("MainTabs") then if gui.beginTabItem("Combo") then gui.checkbox("Q in Combo", useQ) gui.checkbox("W in Combo", useW) gui.checkbox("E in Combo", useE) gui.checkbox("R in Combo", useR) gui.endTabItem() end if gui.beginTabItem("Harass") then gui.checkbox("Q Harass", harassQ) gui.checkbox("W Harass", harassW) manaThreshold = gui.sliderInt("Min Mana %", manaThreshold, 0, 100) gui.endTabItem() end if gui.beginTabItem("Drawing") then drawColor = gui.combo("Draw Color", drawColor, { "Red", "Green", "Blue", "White" }) gui.endTabItem() end gui.endTabBar() endend)-- Draw ESP on all enemiescb.add(cb.CB_DRAW_WORLD, function() for enemy in objManager.ienemies do if enemy:isValidTarget() then -- Convert world position to screen local visible, screenX, screenY = esp.worldToScreen( enemy.x, enemy.y, enemy.z ) if visible then -- Draw box around enemy esp.drawBox(screenX - 25, screenY - 40, 50, 80, 1.0, 0.0, 0.0, 0.5) -- Red box -- Draw name above head esp.drawText(screenX, screenY - 50, enemy.charName, 1.0, 1.0, 1.0) -- White text -- Draw health bar esp.drawHealthBar(screenX - 25, screenY + 45, 50, 5, enemy.health, enemy.maxHealth) -- Draw line from player to enemy local _, myX, myY = esp.worldToScreen( player.x, player.y, player.z ) if myX then esp.drawLine(myX, myY, screenX, screenY, 0.0, 1.0, 0.0, 2) -- Green line end end end endend)-- ESP with distance-based renderinglocal MAX_DISTANCE = 3000local NEAR_DISTANCE = 1000cb.add(cb.CB_DRAW_WORLD, function() for enemy in objManager.ienemies do if enemy:isValidTarget() then local distance = enemy.dist -- Skip if too far if distance > MAX_DISTANCE then goto continue end local visible, sx, sy = esp.worldToScreen( enemy.x, enemy.y, enemy.z ) if visible then -- Color based on distance local r, g, b = 1.0, 0.0, 0.0 if distance < NEAR_DISTANCE then -- Close = red r, g, b = 1.0, 0.0, 0.0 else -- Far = yellow r, g, b = 1.0, 1.0, 0.0 end -- Draw box with distance color esp.drawBox(sx - 25, sy - 40, 50, 80, r, g, b, 0.7) -- Draw champion name and distance local text = string.format("%s [%dm]", enemy.charName, math.floor(distance) ) esp.drawText(sx, sy - 50, text, 1.0, 1.0, 1.0) -- Draw health bar esp.drawHealthBar(sx - 25, sy + 45, 50, 5, enemy.health, enemy.maxHealth) -- Draw circle at feet for close enemies if distance < NEAR_DISTANCE then esp.drawCircle(sx, sy + 40, 30, r, g, b, 32) end end ::continue:: end endend)-- Menu with custom colors and stylinggui.window("Styled Menu", function() -- Push red color for critical button gui.pushStyleColor(0, 1.0, 0.0, 0.0, 1.0) -- Button color if gui.button("DANGER: Reset All") then resetAllSettings() end gui.popStyleColor(1) gui.spacing() -- Success button in green gui.pushStyleColor(0, 0.0, 1.0, 0.0, 1.0) if gui.button("Save Configuration") then saveConfig() end gui.popStyleColor(1) gui.separator() -- Colored status text if scriptActive then gui.textColored(0.0, 1.0, 0.0, 1.0, "Status: ACTIVE") else gui.textColored(1.0, 0.0, 0.0, 1.0, "Status: INACTIVE") endend)The GUI system automatically handles input capture:
gui.wantCaptureMouse() and gui.wantCaptureKeyboard() to check capture stateAll color parameters use RGBA format with values from 0.0 to 1.0:
Alpha channel (4th value) controls transparency: 1.0 = opaque, 0.0 = transparent