User File #42092312074440655

Upload All User Files

#42092312074440655 - Shaman King 2 Lua

sk2.lua
684 downloads
Uploaded 9/30/2017 2:55 PM by xy2_ (see all 136)
version control never
-- GBA Shaman King - Master of Spirits 2, TASing script
-- Ram watch, Yoh and enemy information
-- Written by xy2_, 2017

-- Static data: tables
-- Color table
local color= {
	opaque= {
		[0]=0xFF00FF00, -- Green
		0xFFFFFF00, -- Yellow
		0xFFFF0000, -- Red
		0xFFBA8E7D, -- Brown
		0xFF0000FF, -- Blue
		0xFF665046, -- Dark brown
		0xFFFF007F, -- Purple
		0xFF00FFFF, -- Cyan
	};
	trans= {
		[0]=0x7700FF00, -- Green
		0x77FFFF00, -- Yellow
		0x77FF0000, -- Red
		0x77BA8E7D, -- Brown
		0x770000FF, -- Blue
		0x44665046, -- Dark brown
		0x77FF007F, -- Purple
		0x7700FFFF, -- Cyan
	}
}

-- Text of possible Yoh states; self-explainatory
local stateText= {
	[0]=  { "Standing","",""                   } ,
	      { "Walking","",""                    } ,
	      { "Ground","sliding",""              } ,
	      { "Crouching","",""                  } ,
	      { "Crouched","",""                   } ,
	      { "Standing","up",""                 } ,
	      { "Pre-","jumping",""                } ,
	      { "Jumping","",""                    } ,
	      { "Falling,","initial",""            } ,
	      { "Falling","",""                    } ,
	      { "Landing","",""                    } ,
	      { "Back","dashing",""                } ,
	      { "Entering","door",""               } ,
	      { "Exiting","door",""                } ,
	      { "Taking","damage",""               } ,
	      { "Taking","damage,","crouched"      } ,
	      { "Taking","damage,","air"           } ,
	      { "Knockback","damage",""            } ,
	      { "Knockback","upwards",""           } ,
	      { "Knockback","hitting","ground"     } ,
	      { "Knockback","fall",""              } ,
	      { "Knockback","ground",""            } ,
	      { "Knockback","getting up",""        } ,
	      { "Electro-","cuted",""              } ,
	      { "Electro-","cuted","2"             } ,
	      { "Taking","damage?",""              } ,
	      { "Taking","damage?",""              } ,
	      { "1st slash,","wooden,","ground"    } ,
	      { "1st slash,","light,","ground"     } ,
	      { "1st slash,","antiquity,","ground" } ,
	      { "2nd slash,","wooden,","ground"    } ,
	      { "2nd slash,","light,","ground"     } ,
	      { "2nd slash,","antiquity,","ground" } ,
		  { "3rd slash,","wooden,","ground"    } ,
	      { "3rd slash,","light,","ground"     } ,
	      { "3rd slash,","antiquity,","ground" } ,
	      { "1st slash,","wooden,","air"       } ,
	      { "1st slash,","light,","air"        } ,
	      { "1st slash,","antiquity,","air"    } ,
	      { "2nd slash,","wooden,","air"       } ,
	      { "2nd slash,","light,","air"        } ,
	      { "2nd slash,","antiquity,","air"    } ,
	      { "3rd slash,","wooden,","air"       } ,
	      { "3rd slash,","light,","air"        } ,
	      { "3rd slash,","antiquity,","air"    } ,
	      { "Crouch","slash,","wooden"         } ,
	      { "Crouch","slash,","light"          } ,
	      { "Crouch","slash,","antiquity"      } ,
	      { "Halo","Bump,","ground"            } ,
	      { "Halo","Bump,","air"               } ,
	      { "Nipopo","Punch", "ground"         } ,
	      { "Nipopo","Punch", "air"            } ,
	      { "Daodondo","",""                   } ,
	      { "Gussy", "Kenji", "ground"         } ,
	      { "Gussy", "Kenji", "air"            } ,
	      { "Jaguar","Swipe",""                } ,
	      { "Footballer","",""                 } ,
	      { "Footballer,","sparks",""          } ,
	      { "Big", "Thumb",""                  } ,
	      { "Big", "Thumb,","smoke"            } ,
	      { "Big", "Thumb,","Tokageroh"        } ,
	      { "Celestial","Slash,","ground"      } ,
	      { "Celestial","Slash,","air"         } ,
	      { "Celestial","Slash,","blade"       } ,
	[73]= { "Totem","Attack",""                } ,
	[292]={ "Leap,","wooden,","start"          } ,
	[295]={ "Leap,","wooden,","brandish"       } ,
	[298]={ "Leap,","wooden",""                } ,
	}

-- Soul info
local soulInfo= {
	-- Format: string, active/passive (active=1), soul level (1= lv2, 2=lv3, 3=soul combo), splash number if splash
	-- Example: { "Tokageroh",1,0,4 } means the soul name is Tokageroh, it's a normal soul, and it has a splash & it's splash number is 4
	-- The splash number can be determined by looking in RAM: there are timers for each soul that has a splash
    [0]= { "Empty"       , 0 }   , 
         { "Halo Bump"   , 1 , 0 , 0 }  , 
         { "Cel.Slash"   , 1 , 1 }   , 
         { "Mosuke"      , 0 }   , 
         { "I.T.Antiq."  , 1 , 2 }   , 
         { "Tokageroh"   , 1 , 0 , 4 }  , 
         { "Corey"       , 1 }   , 
         { "Eliza"       , 0 }   , 
         { "S.Shield"    , 0 }   , 
         { "S.Tail"      , 0 }   , 
         { "S.Wing"      , 0 }   , 
         { "S.Horn"      , 0 }   , 
         { "S.Rod"       , 0 }   , 
         { "T.Attack"    , 1 }   , 
         { "Mic"         , 1 , 0 , 7 }  , 
         { "LeeP-Long"   , 1 }   , 
         { "Bason"       , 1 }   , 
         { "GT.Impale"   , 1 , 1 }   , 
         { "GrandTaoD."  , 1 }   , 
         { "Chloe"       , 1 }   , 
         { "Michael"     , 1 }   , 
         { "R.ofLight"   , 1 , 3 }   , 
         { "Kanta"       , 1 }   , 
         { "GussyKenji"  , 1 }   , 
         { "Tamegoroh"   , 0 }   , 
         { "Shikigami"   , 1 }   , 
         { "Fk.steiny"   , 0 }   , 
         { "Ponchi"      , 1 }   , 
         { "Konchi"      , 1 }   , 
         { "Ch.-Moryo"   , 1 }   , 
         { "Shaolin"     , 1 }   , 
         { "Blk.Raven"   , 0 }   , 
         { "TaotheGrt"   , 1 }   , 
         { "Ian"         , 0 }   , 
         { "Nizba"       , 0 }   , 
         { "Dreisa"      , 0 }   , 
         { "Yophia"      , 0 }   , 
         { "M.Memorial"  , 0 , 3 }   , 
         { "Badbh"       , 0 }   , 
         { "Vodianoi"    , 0 }   , 
         { "Deht"        , 0 }   , 
         { "Gororo"      , 1 }   , 
         { "Zenki"       , 1 }   , 
         { "Kohki"       , 1 }   , 
         { "Golem"       , 1 }   , 
         { "Orona"       , 0 }   , 
         { "PascalAvaf"  , 1 }   , 
         { "Jaguarman"   , 1 , 3 }   , 
         { "Yamagami"    , 1 }   , 
         { "Gundari"     , 0 }   , 
         { "Raphael"     , 0 }   , 
         { "Gabriel"     , 0 }   , 
         { "Uriel"       , 0 }   , 
         { "Metatoron"   , 0 }   , 
         { "Sariel"      , 0 }   , 
         { "Remiel"      , 0 }   , 
         { "Mash"        , 1 }   , 
         { "Blaumro"     , 1 }   , 
         { "F.baller"    , 1 }   , 
         { "Sh.-Shion"   , 1 }   , 
         { "Blocks"      , 1 }   , 
         { "Jen"         , 1 }   , 
         { "Ashcroft"    , 1 }   , 
         { "Jack"        , 1 }   , 
         { "Chuck"       , 1 }   , 
         { "C. & Joao"   , 1 }   , 
         { "Antonio"     , 1 }   , 
         { "Jose"        , 1 }   , 
         { "Pancho"      , 1 }   , 
         { "Zapata"      , 1 }   , 
         { "Miguel"      , 1 }   , 
         { "Grd.Phant."  , 1 }   , 
         { "M.scope"     , 1 }   , 
         { "Mama"        , 1 }   , 
         { "Cifer"       , 1 }   , 
         { "S.of Fire"   , 0 }   , 
         { "Matamune"    , 1 }   , 
         { "GdHaloBlade" , 1 , 1 }   , 
         { "U.C.Charge"  , 1 , 3 }   , 
         { "Tokageroh"   , 1 , 1 }   , 
         { "Corey"       , 1 , 1 }   , 
         { "Eliza"       , 1 , 1 }   , 
         { "T.Attack"    , 1 , 1 }   , 
         { "Mic"         , 1 , 1 }   , 
         { "LeeP-Long"   , 1 , 1 }   , 
         { "Chloe"       , 1 , 1 }   , 
         { "S. of All"   , 1 }   , 
         { "Skunk"       , 1 }   , 
         { "K.itachi"    , 1 }   , 
         { "Korogashi"   , 1 }   , 
         { "Enra-Enra"   , 1 }   , 
         { "O.F.Tama"    , 1 }   , 
         { "Jangalian"   , 1 }   , 
         { "GreatOgre"   , 1 }   , 
         { "Skelesaur"   , 1 }   , 
         { "Triglav"     , 1 }   , 
         { "F. Field"    , 1 , 3 }   , 
         { "Expl.Kick"   , 1 , 3 }   , 
         { "FinalBeam"   , 1 , 3 }   , 
         { "Blizzard"    , 1 , 3 }   , 
         { "Vik. Ship"   , 1 , 3 }   , 
         { "Jav. Tear"   , 1 , 3 }   , 
         { "Hom. Laser"  , 1 , 3 }   , 
         { "Gledhill"    , 1 }   , 
}

local rngResults = {}
local pastRNG = {0, 0}

-- SK2 rng re-implementation in Lua
--#############################################################################
local function RngLua(value)
--#############################################################################
		
	local high = (value * 0x41C6) % 0x10000 -- Shoutouts to Scepheo
	local low  = (value * 0x4E6D) % 0x100000000
	return ((low + high * 0x10000) % 0x100000000) + 0x3039
end

-- Displays a table of the next X rng values, based on current RNG
--#############################################################################
local function RngPredict(x,y,number)
--#############################################################################

	local RNG = memory.read_u32_le(0x16C0, "IWRAM")

	-- Display the number of steps the RNG has advanced, if it advanced
	pastRNG[2]= pastRNG[1]
	pastRNG[1]= RNG
	if pastRNG[2] ~= pastRNG[1] then
		for i=1,number do
			if RNG == rngResults[i] then
				gui.pixelText(x+33,y, i, 0xFFFFFFFF, color.trans[6])
				gui.pixelText(x+33,y+i*7, "!", 0xFFFFFFFF, color.trans[2])
			end
		end
	end

	gui.pixelText(x,y, string.format("%08X", RNG))
	
	rngResults[1] = RngLua(RNG) 
	for i=1,number do
		rngResults[i+1] = RngLua(rngResults[i])
		gui.pixelText(x,y+i*7, string.format("%08X", rngResults[i]))
	end
	
end

-- General RAM watch, and value display on screen
--#############################################################################
local function DisplayHud(x,y)
--#############################################################################

	-- Furyoku
	local furyoku     = memory.read_u16_le(0x64AA, "IWRAM")
	gui.pixelText (x+0,y+0, string.format("%4d", furyoku), 0xFFFFFFFF, color.trans[4])

	-- Furyoku refill
	local frefill     = memory.read_u16_le(0x22CA, "IWRAM")
	if refill == 0 then
	gui.pixelText(x+0,y+7, string.format("%4d", frefill), 0xFFFFFFFF, color.trans[0]) 
	else
	gui.pixelText(x+0,y+7, string.format("%4d", frefill), 0xFFFFFFFF, color.trans[2])
	end

	-- In-game time (current segment)
	local igtframeseg = memory.read_u32_le(0x36DD, "IWRAM")
	gui.pixelText(x+180,y+0, string.format("%8d", igtframeseg), color.opaque[6])
	-- In-game time (current area)
	local igtframearea= memory.read_u32_le(0x0498, "IWRAM")
	gui.pixelText(x+180,y+7, string.format("%8d", igtframearea), color.opaque[7])    
	-- In-game time (global)
	local igtframe    = memory.read_u32_le(0x62AC, "IWRAM")
	gui.pixelText(x+180,y+14, string.format("%8d", igtframe), color.opaque[1])
	-- Global timer
	local globalframe = memory.read_u32_le(0x62A8, "IWRAM")
	gui.pixelText(x+180,y+21, string.format("%8d", globalframe))

	-- Speed
	local xspeed = memory.read_s32_le(0x1A78, "IWRAM")
	local yspeed = memory.read_s32_le(0x1A7C, "IWRAM")
	gui.pixelText(x+215,y, string.format("%6d", xspeed))
	gui.pixelText(x+215,y+7, string.format("%6d", yspeed))


	-- Ground/air? Displays G on ground, A on air
	local groair = memory.read_u8(0x1A40, "IWRAM")
	if groair == 1 then
		gui.pixelText(x+215,y+14, "G", 0xFFFFFFFF, color.trans[4])
	else
		gui.pixelText(x+215,y+14, "A", 0xFFFFFFFF, color.trans[1])
	end

	-- Buffered down input timer to backdash
	local downbuffer = memory.read_u8(0x16E3, "IWRAM")
	if downbuffer >= 1 then
		gui.pixelText(x+219,y+14, "V" .. string.format("%4d", downbuffer))
	else
		gui.pixelText(x+219,y+14, string.format("%5d", downbuffer))
	end

	-- X and Y position
	local xposition   = memory.read_s32_le(0x1A70, "IWRAM")
	local yposition   = memory.read_s32_le(0x1A74, "IWRAM")
	gui.pixelText(x+203,y+35, string.format("%9d", xposition))
	gui.pixelText(x+203,y+42, string.format("%9d", yposition))
	
	-- Relative position to camera (>= 120 » Yoh invincible)
	local xrelative = math.abs(memory.read_s16_le(0x1A80, "IWRAM")-120)
	if xrelative >= 120 then
		gui.pixelText(x+223,y+49, "!" ..string.format("%3d", xrelative), 0xFFFFFFFF, color.trans[6])
	elseif xrelative >= 18 then
		gui.pixelText(x+223,y+49, "*" .. string.format("%3d", xrelative), color.opaque[6])
	elseif xrelative >= 1 then
		gui.pixelText(x+223,y+49, "+" .. string.format("%3d", xrelative), color.opaque[7])
	else
		gui.pixelText(x+223,y+49, string.format("%4d", xrelative))
	end
end

-- A visual separator for the sidebar
--#############################################################################
local function Separator(x,y, length)
--#############################################################################

	gui.drawLine(x+14,y, x+length,y)

	for i=0,6 do
		gui.drawPixel(x+i*2,y)
	end
end

-- General movie information
--#############################################################################
local function MovieInfo(x,y)
--#############################################################################

	local frame= emu.framecount()
	if emu.islagged() == true then
		gui.pixelText(x,y, frame, 0xFFFFFFFF, color.opaque[2])
	else
		gui.pixelText(x,y, frame)
	end

	local lagcount= emu.lagcount()
	gui.pixelText(x,y+7, lagcount, color.opaque[2])

end

-- Displays information about Yoh's animations on the sidebar
--#############################################################################
local function GetYohState(x,y)
--#############################################################################

	local state      = memory.read_u16_le(0x1A08, "IWRAM")
    local duration   = memory.read_u8(    0x1A05, "IWRAM")
    local statetimer = memory.read_u8(    0x1A10, "IWRAM")
    local delay      = memory.read_u16_le(0x1A59, "IWRAM")

    local t          = stateText[state]
	if t then
                gui.pixelText(x,y, state .. ":" .. statetimer)
                gui.pixelText(x,y+ 7,t[1],color.opaque[1])
                gui.pixelText(x,y+14,t[2],color.opaque[1])
                gui.pixelText(x,y+21,t[3],color.opaque[1])
                gui.pixelText(x,y+28, duration .. ":" .. delay, 0xFFFFFFFF, color.trans[2])
	else
                gui.pixelText(x,y, state .. ":" .. statetimer)
                gui.pixelText(x,y+ 7,"NULL!!!",0xFFC0C0C0)
                gui.pixelText(x,y+28, duration .. ":" .. delay, 0xFFFFFFFF, color.trans[2])
	end

end

-- Information about our inventory - mediums
--#############################################################################
local function MediumInfo(x,y)
--#############################################################################

-- 	local leafcount = memory.read_u8(0x2358, "IWRAM")
-- 	local rockcount = memory.read_u8(0x2359, "IWRAM")
-- 	local dollcount = memory.read_u8(0x235A, "IWRAM")
-- 	TODO: find proper values
-- 	gui.pixelText(x,y, leafcount, color.opaque[0])
-- 	gui.pixelText(x+11,y, rockcount, color.opaque[3])
-- 	gui.pixelText(x+22,y, dollcount, color.opaque[5])

end

-- Information about our inventory - souls
--#############################################################################
local function SoulInfo(x,y)
--#############################################################################

	-- Current deck
	local deck= memory.read_u8(0x658B, "IWRAM") 
	
	for i=0,4 do -- For each of the slots in the deck
		local soul= memory.read_u8(0x6557 + 0x1*i + 0x5*deck, "IWRAM")
        local t= soulInfo[soul]
        if t then -- Just in case
			if soul == 0 then -- Is there a soul equipped?
				gui.pixelText(x,y+i*7, t[1], color.opaque[5])
			elseif t[3] == 3 then -- Is it a soul combo?
				gui.pixelText(x,y+i*7, t[1], color.opaque[1])
			elseif t[3] == 1 then -- Is it a lv2 soul?
				gui.pixelText(x,y+i*7, t[1], color.opaque[7])
			elseif t[3] == 2 then -- Is it a lv3 soul?
				gui.pixelText(x,y+i*7, t[1], color.opaque[2])
			elseif t[2] == 1 then -- Is it an active soul?
				gui.pixelText(x,y+i*7, t[1], color.opaque[0])
			else -- It's a passive soul
				gui.pixelText(x,y+i*7, t[1])
			end
			if t[4] then -- Does this soul have a splash?
				-- Base splash adress
				local splasht = memory.read_u16_le(0x64E0 + 0x2*t[4], "IWRAM")
				if splasht >= 1 then
					gui.pixelText(x-18,y, string.format("%4d", splasht), color.opaque[6])
				else
					gui.pixelText(x-6,y, splasht, 0xFFFFFFFF, color.trans[6])
				end
			end
        end
	end

end

-- Draws hitboxes
-- Object size: C8 (200)
--#############################################################################
local function DrawHitbox(x,y, offset, id)
--#############################################################################

	local cameraX = memory.read_s24_le(0x6359, "IWRAM")
	local cameraY = memory.read_s24_le(0x635D, "IWRAM")

	-- Figure out appropriate pixel values
	local X1 = memory.read_s24_le(0x1A89 + offset, "IWRAM")
	local X2 = memory.read_s24_le(0x1A8D + offset, "IWRAM")
	local Y1 = memory.read_s24_le(0x1A91 + offset, "IWRAM")
	local Y2 = memory.read_s24_le(0x1A95 + offset, "IWRAM")
	
	-- Hitbox
	local pixelX1, pixelX2 = X1-cameraX+120, X2-cameraX+120
	local pixelY1, pixelY2 = cameraY-Y1+70, cameraY-Y2+70

	-- Invicibility
	local invicibility = memory.read_u8(0x1A5D + offset, "IWRAM")
	-- Add invicibility counter if invicible
	if invicibility >= 1 then
		gui.drawBox (x+pixelX1, y+pixelY1, x+pixelX2, y+pixelY2, color.opaque[1], color.trans[5])
		gui.pixelText (x+pixelX1, y+pixelY1, invicibility, 0xFFFFFFFF, color.trans[1])
	else
		gui.drawBox (x+pixelX1, y+pixelY1, x+pixelX2, y+pixelY2, color.opaque[5], color.trans[5])
	end
    
	-- Poison
	if id == 1 then
		local poison = memory.read_u16_le(0x1A5E + offset, "IWRAM")
		if poison >= 1 then
-- 			local poisontimer = memory.read_u16_le(0x1A59, "IWRAM")
			gui.pixelText (x+pixelX1, y+pixelY1+7, poison, 0xFFFFFFFF, color.trans[0])
-- 			gui.pixelText (x+pixelX1, y+pixelY1+14, poisontimer, color.opaque[0])
		end
	end

	local relposX, relposY = memory.read_s16_le(0x1A80, "IWRAM"), memory.read_s16_le(0x1A82, "IWRAM")
	
	-- Slot number
	gui.pixelText(x+pixelX1 - 9, y+pixelY2 - 7, string.format("%02d", id), 0xFFFFFFFF, color.trans[7])
	
	-- Facing direction
	local fdirection = memory.read_u8(0x1A65 + offset, "IWRAM")
	if fdirection == 1 then
                gui.pixelText (x+pixelX1, y+pixelY2 - 7, "<")
	elseif fdirection == 0 then
                gui.pixelText (x+pixelX1, y+pixelY2 - 7, ">")
	else
                gui.pixelText (x+pixelX1, y+pixelY2 - 7, "?")
	end

	-- Raw damage output
	local rawdmg = memory.read_u8(0x1A62 + offset, "IWRAM")
	gui.pixelText (x+pixelX1 + 8, y+pixelY2 - 7, rawdmg, 0xFFFFFFFF, color.trans[2])

	-- Health
	local health= memory.read_u16_le(0x1A60 + offset, "IWRAM")
	gui.pixelText(x+pixelX1 + 10, y+pixelY1, health, color.opaque[1])
		
	-- State, animation and timer information
	if id ~= 1 then
		local state      = memory.read_u16_le(0x1A08 + offset, "IWRAM")
		local duration   = memory.read_u8(    0x1A05 + offset, "IWRAM")
		local statetimer = memory.read_u8(    0x1A10 + offset, "IWRAM")
		local delay      = memory.read_u16_le(0x1A59 + offset, "IWRAM")
		gui.pixelText (x+pixelX1 + 24, y+pixelY2, state .. ":" .. statetimer)
		gui.pixelText (x+pixelX1 + 24, y+pixelY2 - 7, duration .. ":" .. delay, 0xFFFFFFFF, color.trans[2])
	end
end

client.SetGameExtraPadding(0,0,40,0)

--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
while true do
--@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	
	MovieInfo(241,0)
	RngPredict(0,20,15)
	Separator(241,15,38)
	GetYohState(241,17)
	Separator(241,54,38)
-- 	InventoryInfo(241,56)
	SoulInfo(241,56)
	DisplayHud(0,0)
	
	for i=1,2 do
		--		if memory.read_u16_le(0x1A60 + i*200, "IWRAM") ~= 0 then
			DrawHitbox(0,8, (i-1)*200, i)
		--		end
	end
	
	emu.frameadvance()
end