Простая и лёгкая система, позволяющая поймать за руку игрока, использующего оригинальные чит-коды в одиночной игре. И также просто и легко обнаруживается в коде карты.
Принцип работы
Для работы системы используются три триггера. Первые два отслеживают события TEXT_CHANGED и ENTER для фрейма типа Edit Box, третий триггер — вспомогательный, он нужен для перерегистрации событий фрейма для основных триггеров при загрузке сохраненной игры (иначе фрейм ивенты будут потеряны). Весь текст, введённый игроком, сравнивается с содержимым таблицы чит-кодов, и найденное совпадение расценивается как ввод чит-кода.
Установка
- Переключить карту в режим Lua, если ещё не.
- Вставить код в карту.
- Вызвать метод AntiCheat:init(debugMode). Аргумент debugMode используется для включения/отключения дебаг сообщений (true/false).
Настройка и управление
- Реакция на ввод чита вынесена в функцию AntiCheat:punish(cheat), и может быть изменена по желанию пользователя. Функция принимает строку с обнаруженным чит-кодом.
- Список отслеживаемых чит-кодов хранится в таблице AnitCheat.list, и может быть измененён при необходимости.
- Функция AntiCheat:setEnable(true/false) позвоялет включать/отключать детект во время игры при необходимости.
- Удалить все триггеры системы в рантайме можно вызовом AntiCheat:destroy()
Код
Раскрыть
--[[
Simple and easy system that allows you to catch a player who using cheat codes in a single player game.
Configuration:
— You can change AntiCheat:_punish(cheat) function to your liking to create any reaction to entering a cheat code.
This function takes a cheat code string as an argument, which allows you to customize the reaction for each cheat code.
— The AntiCheat.list table stores a list of cheat codes, you can remove any from there or add something if necessary.
Control:
— To initialize the system, you need to call the AntiCheat:init(debugMode) method.
Use the debugMode argument to turn debug messages on or off (true/false).
I would not recommend calling this function too early, since the code must access some default frames that may not have time to initialize, which will lead to a game crash.
I took this problem into account and tried to make it more secure by adding a delay timer and checking for access to frames.
After that, I injected the function into main() without any problems in my tests, but I still think I should warn you about it.
— To destroy the system, you can call the AntiCheat:destroy() function.
— To temporarily disable the system, you can use the AntiCheat:setEnable(false) function.
Accordingly, to enable triggers later, you should call AntiCheat:setEnable(true).
--]]
AntiCheat = {}
AntiCheat.debug = true
function AntiCheat:_punish(cheat)
self:_displayMessage(cheat) -- Debug
-- You can add any reaction to entering a cheat code to this function
-- In this example, the player gets defeat
CustomDefeatBJ(GetLocalPlayer(), "Good luck next time!")
end
AntiCheat.list = { -- Table of known cheat codes in Warcraft 3
"allyourbasearebelongtous", -- Instantly win the current mission
"daylightsavings", -- Switches from day to night, halts or restarts the flow of the day/night cycle
"greedisgood", -- Instantly obtain set number of lumber and gold
"iocanepowder", -- Enables fast acting death/decay of bodies
"iseedeadpeople", -- Full map is revealed, fog of war disabled
"itvexesme", -- Disables victory conditions
"keysersoze", -- Instantly obtain set number of gold
"leafittome", -- Instantly obtain set number of lumber
"lightsout", -- Sets time of day to evening
"motherland", -- Selects a mission number for the chosen race to warp to
"pointbreak", -- Disables food limit for creating new units
"riseandshine", -- Sets time of day to morning
"sharpandshiny", -- Instantly grants all upgrades
"somebodysetupthebomb", -- Instantly lose the current mission
"strengthandhonor", -- Disables game over screen after losing objectives in campaign mode
"synergy", -- Unlocks the full tech tree
"tenthleveltaurenchieftan", -- Plays a special music track "Power of the Horde"
"thedudeabides", -- Enables faster spell cooldown times
"thereisnospoon", -- All units gain infinite mana
"warpten", -- Enables faster building times
"whoisjohngalt", -- Enables faster research time for upgrades
"whosyourdaddy", -- All units and buildings gain full invulnerability, units will be able to 1-hit kill any opponent or enemy structure (does not effect friendly fire)
-- Source: https://www.ign.com/wikis/warcraft-3/PC_Cheats_and_Secrets_-_List_of_Warcraft_3_Cheat_Codes
}
-- Debug Messages
AntiCheat.messages = {
success = "|c0000FF80Anti-Cheat system is enabled.|r",
cancel = "|c00EDED12Not a single-player mode. Initialization of the Anti-Cheat system was canceled.|r",
error = "|c00FF0000Error when trying to access Edit Box.\r\nThe Anti-Cheat system was not enabled.|r",
detect = "|c00FF0000\"CHEATCODE\" cheat code detected.|r",
disabled = "|c00EDED12Anti-Cheat system was disabled.|r",
destroyed = "|c00EDED12Anti-Cheat system was removed from game.|r"
}
-- “Impossible” index for nil-frame comparison
-- (do not use this index for real frames or change it if you need)
AntiCheat.nullFrameIndex = 93242
AntiCheat.states = {}
---@param debugMode boolean output debug messages
function AntiCheat:init(debugMode)
self.debug = debugMode
if not ReloadGameCachesFromDisk() then
self:_displayMessage("cancel")
return
end
local saveLoadedTrigger, textChangedTrigger, textEnteredTrigger = CreateTrigger(), CreateTrigger(), CreateTrigger()
local states, cheats = self.states, self.list
TriggerRegisterGameEvent(saveLoadedTrigger, EVENT_GAME_LOADED)
TriggerAddCondition(saveLoadedTrigger, Condition(function() self:_setBoxEvents() end))
TriggerAddCondition(textChangedTrigger, Condition(function()
states[2] = states[1]
states[1] = BlzGetTriggerFrameText()
end))
TriggerAddCondition(textEnteredTrigger, Condition(function()
local enteredText = states[2]:lower()
for i = 1, #cheats do
if enteredText:find(cheats[i]) then
self:_punish(cheats[i])
break
end
end
end))
self.triggers = {textChangedTrigger, textEnteredTrigger, saveLoadedTrigger}
self:_setBoxEvents()
end
function AntiCheat:_setBoxEvents()
-- Event registration has been moved to a separate function,
-- since when loading a saved game it will need to be done again.
local t = CreateTimer()
-- Accessing to the frame while the map is initializing can result in a fatal error, so delay is needed
TimerStart(t, .1, false, function()
local eBox = self:_getEditBox()
if eBox then
BlzTriggerRegisterFrameEvent(self.triggers[1], eBox, FRAMEEVENT_EDITBOX_TEXT_CHANGED)
BlzTriggerRegisterFrameEvent(self.triggers[2], eBox, FRAMEEVENT_EDITBOX_ENTER)
self:_displayMessage("success")
else
self:_displayMessage("error")
self:destroy()
end
DestroyTimer(t)
end)
end
function AntiCheat:_getEditBox()
-- Includes frame access check
local index = self.nullFrameIndex
local nullFrame = BlzGetOriginFrame(ConvertOriginFrameType(index), 0)
local gameUI = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
if gameUI == nullFrame then return nil end
nullFrame = BlzFrameGetChild(gameUI, index)
local msgFrame = BlzFrameGetChild(gameUI, 11)
if msgFrame == nullFrame then return nil end
local editBox = BlzFrameGetChild(msgFrame, 1)
if editBox == nullFrame then return nil end
return editBox
end
function AntiCheat:_displayMessage(mType)
if not self.debug then return end
if self.messages[mType] then
print(self.messages[mType])
return
end
for _, v in ipairs(self.list) do
if v == mType then
local message = self.messages.detect:gsub("CHEATCODE", mType)
print(message)
return
end
end
end
---@param enable boolean
function AntiCheat:setEnable(enable)
local triggers = self.triggers
if not triggers then return end
if enable then
EnableTrigger(triggers[2])
self:_displayMessage("success")
return
end
DisableTrigger(triggers[2])
self:_displayMessage("disabled")
end
function AntiCheat:destroy()
local triggers = self.triggers
if triggers then
for _, v in ipairs(triggers) do
DisableTrigger(v)
DestroyTrigger(v)
end
end
self.triggers = nil
self:_displayMessage("destroyed")
end
Ссылки и кредиты
- Список чит-кодов
- Инфа по фреймам
- По настоянию некоего Unryze были добавлены проверки на недоступные фреймы.
Ред. ScorpioT1000
Ред. ScorpioT1000
Ред. Vengeance
Используя подобную махинацию можно при этом ещё соединить триггер с убийством игрока молнией за применение команды чит-кода?)
СмЭЭЭрть(с акцентом деда)
Ред. ScorpioT1000
Хотелось создавать себе подобную кампанию в рпг-жанра как с Рексаром или с Сибирем РПГ(то есть Нортренд), где введение подобной команды сработает триггер где убивает ГГ и провалится миссия)
Просматривая подобные скриншоты, это пригодится другому челу...Который занимается машинимами...
Прокрутить к ресурсу
Прокрутить к ресурсу