Last active
May 14, 2022 04:23
-
-
Save MikuAuahDark/50a9c6f527f5383e00d13bf3adbe3b57 to your computer and use it in GitHub Desktop.
Change PvZ Plant Names Without Modding
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Cheat Engine Lua script to replace plant names in PvZ to names by Kobo Kanaeru. | |
-- Written by Miku AuahDark. | |
-- This file falls under Public Domain | |
-- To apply the plant names: | |
-- 1. Start PvZ and let it load until main menu | |
-- 2. Load 32-bit Cheat Engine and hook to PvZ process. | |
-- 3. Click Table -> Show Cheat Table Lua Script or press Ctrl+Alt+L | |
-- 4. Copy and paste this whole script then press "Execute Script" | |
-- 5. Cheat Engine may hang for a while, it's normal. | |
-- 6. After you regain control back to CE window, the script is done. | |
REPLACE_LIST = { | |
-- Note: Some items are ordered in specific way to prevent ambiguity when doing AOBScan. | |
{"Cherry Bomb", "Biji Meledak"}, | |
{"Peashooter", "Kipli"}, | |
-- Twin Sunflower first, then Sunflower | |
{"Twin Sunflower", "Dewa Dewi"}, | |
{"Sunflower", "Dewi"}, | |
-- "Giant Wall-nut" is NOT actually named by Kobo but added to prevent ambiguity! | |
{"Giant Wall-nut", "Beni Besar"}, | |
{"Wall-nut", "Beni"}, | |
{"Potato Mine", "Gilang"}, | |
{"Snow Pea", "Es Kipli"}, | |
{"Repeater", "Kiplipli"}, | |
{"Puff-shroom", "Ucup"}, | |
{"Grave Buster", "Ikhsan"}, | |
{"Hypno-shroom", "Ojan"}, | |
{"Scaredy-shroom", "Ujang"}, | |
{"Ice-shroom", "James"}, -- Is it? | |
{"Doom-shroom", "Ihshaap"}, | |
{"Lily Pad", "Dimas"}, | |
{"Squash", "Candra"}, | |
{"Threepeater", "Terkiplikipli"}, | |
{"Tangle Kelp", "Tatang"}, | |
{"Jalapeno", "Juna"}, | |
{"Torchwood", "Garok"}, | |
{"Spikeweed", "Syafiq Hidayat"}, | |
{"Tall-nut", "Fahrul Gunawan"}, | |
} | |
local function str2u16le(s) | |
local result = {} | |
for i = 1, #s do | |
result[#result + 1] = s:byte(i, i) | |
result[#result + 1] = 0 | |
end | |
return result | |
end | |
local function intTab2Hex(t) | |
local result = {} | |
for _, v in ipairs(t) do | |
result[#result + 1] = string.format("%02X", v) | |
end | |
return table.concat(result, " ") | |
end | |
local function checkWStringValidity(ptr, strlen) | |
-- We can't really sure. | |
local wlen = readInteger(ptr + 16) | |
local capacity | |
if strlen < 8 then | |
capacity = readInteger(ptr + 20) == 7 | |
else | |
-- Is it PO2? Not sure, assume 10x max | |
local capacityInt = readInteger(ptr + 20) | |
capacity = capacityInt >= wlen and capacityInt <= wlen * 10 | |
end | |
return capacity and wlen == strlen | |
end | |
local function findWString(str) | |
local hex = intTab2Hex(str2u16le(str.."\0")) | |
local scan = AOBScan(hex, "+W", 0, 0) | |
if scan then | |
-- Iterate result | |
for i = 1, scan.Count do | |
local address = tonumber(scan[i - 1], 16) | |
-- Here's a complicated explanation. If the str length we're looking for | |
-- is less than 8, that means it's in short string mode. | |
if #str < 8 then | |
-- This means we're attempt to scan directly, check directly this address. | |
if checkWStringValidity(address, #str) then | |
return address, address | |
end | |
else | |
-- This means this string is referenced somewhere. | |
local reference = AOBScan(string.format("%02X %02X %02X %02X", table.unpack(dwordToByteTable(address))), "+W", 0, 0) | |
if reference then | |
for j = 1, reference.Count do | |
local baseAddress = tonumber(reference[j - 1], 16) | |
if checkWStringValidity(baseAddress, #str) then | |
return baseAddress, address | |
end | |
end | |
end | |
end | |
end | |
end | |
return nil | |
end | |
local scratchBuffer = allocateMemory(4096) | |
local scratchStart = scratchBuffer | |
print(string.format("Allocating temporary buffer at 0x%08X", scratchBuffer)) | |
for _, v in ipairs(REPLACE_LIST) do | |
print("Replacing \""..v[1].."\" to \""..v[2].."\"") | |
-- Convert to UTF-16LE string hex with null terminator | |
local pointer, address = findWString(v[1]) | |
if pointer then | |
print(string.format("Found string 0x%08X referenced in 0x%08X", address, pointer)) | |
local byteTable = str2u16le(v[2].."\0") | |
if #v[2] >= readInteger(pointer + 20) then | |
print("Using temporary buffer") | |
-- Write to the scratch buffer first then write the pointer | |
writeBytes(scratchStart, byteTable) | |
writeInteger(pointer, scratchStart) | |
-- Write capacity | |
writeInteger(pointer + 20, #v[2]) | |
scratchStart = scratchStart + #byteTable | |
else | |
-- Fits in std::wstring::capacity | |
local byteTable = str2u16le(v[2].."\0") | |
if #v[2] < 8 then | |
print("Using short string mode") | |
-- Obey short string optimization | |
writeBytes(pointer, byteTable) | |
-- Write capacity | |
writeInteger(pointer + 20, 7) | |
else | |
-- Write directly | |
writeBytes(address, byteTable) | |
end | |
-- Write the length | |
writeInteger(pointer + 16, #v[2]) | |
end | |
else | |
print("Warning: Cannot replace \""..v[1].."\". Is it already patched?") | |
end | |
end |
Sedikit revisi, di bagian ini:
Load 32-bit Cheat Engine and hook to PvZ process
Untuk CE 64-bit, gua dah coba dan worked, kemungkinan di lapak lain gatau tapi di guanya sendiri work kok.
Saya cocokin dengan bitness gamenya. 32-bit karena PvZ itu 32-bit.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice project sir