Golden Sun Hacking Community

Golden Sun Games => Golden Sun: The Lost Age => Topic started by: Plexa on 07, October, 2016, 08:50:05 AM

Title: GS2 Utility Script
Post by: Plexa on 07, October, 2016, 08:50:05 AM
Hello everyone! I'm back to work out some things for writing a utility script for GS2 akin to the one made for GS1 http://forum.goldensunhacking.net/index.php?topic=2656.0

The big difference between GS1 and GS2 is that the kinds of things I need out of the script are somewhat different. I've ported over everything from the GS1 script but there's one thing in particular that would be much more useful in GS2 than GS1 is the value of the agility roll in a fight.

So let's be precise. We know that a member of your party can have its agility boosted between 0-6% depending on RNG (specifically, the general random number "GRN" i.e. the random number in the 0x03xxxxxx series). What Zetonegi found a couple months ago is that the reason the GRN advances when finalising your party members action is that the game calculates the 0-6% boost at that step.

Just so there's no confusion; Say the party member is Felix, you command Felix to attack an enemy. You then get to issue a command for Jenna. Once the attack is issued and before you choose Jenna's action the random number is rolled to determine what Felix's agility will be for that action. If you cancel Felixs command (by pressing B) and issue a new one, a new agility boost is calculated by rolling the random number again.

I'm curious as to where this value is stored, so that I can get my script to read this value and know what agility my party members will have on that turn. 
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 07, October, 2016, 09:11:51 AM
Where it is stored? Already have that "magic trick" up my sleeve..

The turn table is at 0x02030338. (Shows only a single round of all character turns.)
0x10 bytes per character.
First byte = Starts with who's turn it is.
I think the Agility one would be at [+0x4] in a turn entry.

(You could read 0x02030338 directly (Since I don't expect the position to actually change), or follow the pointer @03000024 the way the game does. - Everything in 03000000-030000FF is pretty much pointers to RAM data tables... with the first two being free space pointers.)
Title: Re: GS2 Utility Script
Post by: Salanewt on 07, October, 2016, 09:24:49 AM
And that's total Agility post-RNG.

Need any other questions answered?
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 10:01:33 AM
Quote from: Fox on 07, October, 2016, 09:11:51 AM
Where it is stored? Already have that "magic trick" up my sleeve..

The turn table is at 0x02030338. (Shows only a single round of all character turns.)
0x10 bytes per character.
First byte = Starts with who's turn it is.
I think the Agility one would be at [+0x4] in a turn entry.

(You could read 0x02030338 directly (Since I don't expect the position to actually change), or follow the pointer @03000024 the way the game does. - Everything in 03000000-030000FF is pretty much pointers to RAM data tables... with the first two being free space pointers.)
Perfect! I'll poke around and extract what I need from there :)

@Lord Squirtle, I think that's the only missing thing that I can't brute force conveniently. I did want to look into the other random number (BRN) and predict when you get attacks first and whatnot but I don't know how to use that information in a useful way in the context of GS2 (i know that encounters add 1 BRN per enemy provided you don't have attacks first, but if I can't predict the size of the mob without a script then I can utilise manip'ing for attacks first).

I eventually want to learn how collision works in this game (because its really really weird), but that extends beyond the scope of this question :)
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 01:17:57 PM
Actually, now I do have another question!

So I know the agility of, say, Felix is stored at 0x02000A90 but this is the agility after modifiers have been added (class, equipment, etc). Where might I find the raw agility stat of each character? This is important because its useful to know how many "imperfect" level ups we get for each character since we don't control the stat boost for each level up. (the HP stat would also be useful!)

EDIT: Nevermind! Found it :)
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 08, October, 2016, 01:47:05 PM
You mean the part in the base stats? (Should be in the same order as the current stats.) - Base stats might include Stat Bonuses from Use items. (Apple, Hard Nut, etc.)
(http://forum.goldensunhacking.net/index.php?action=dlattach;topic=2758.0;attach=1724;image)
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 01:51:36 PM
I literally just found it myself, with that said, your image is very useful. Thank you :)
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 03:13:34 PM
Sorry to make yet another reply, but how do sleep bombs work? When using the pirate sword dream tide may make enemies sleep based off of your mercury power. However, sleep bombs don't have an elemental affinity? So I was wondering how this works?
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 08, October, 2016, 08:23:00 PM
QuoteSorry to make yet another reply, but how do sleep bombs work?
The Ailment Success function? (Which is listed on http://forum.goldensunhacking.net/index.php?topic=2460.0)

QuoteWhen using the pirate sword dream tide may make enemies sleep based off of your mercury power. However, sleep bombs don't have an elemental affinity? So I was wondering how this works?
It's Unleash is the Dreamtide ability (Water attribute), and not Sleep Bomb (As an ability, Wind attribute.).  Both can inflict Sleep.
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 08:43:47 PM
Quote from: Fox on 08, October, 2016, 08:23:00 PM
QuoteSorry to make yet another reply, but how do sleep bombs work?
The Ailment Success function? (Which is listed on http://forum.goldensunhacking.net/index.php?topic=2460.0)

QuoteWhen using the pirate sword dream tide may make enemies sleep based off of your mercury power. However, sleep bombs don't have an elemental affinity? So I was wondering how this works?
It's Unleash is the Dreamtide ability (Water attribute), and not Sleep Bomb (As an ability, Wind attribute.).  Both can inflict Sleep.
So I get that it successes the Ailment success function, just didn't know what element it was associated to (I guessed jupiter).

I'm currently debugging my script because I think a lot of the memory addresses I'm trying to read are the wrong ones lol

Does 0x080C6684 point to the enemy index?
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 08, October, 2016, 08:49:26 PM
QuoteDoes 0x080C6684 point to the enemy index?
Nope.... That's Elemental data... Enemies index to them. - The info can be seen at the bottom in Atrius's enemy editor... The first four top values are actually just one value. (32-bit), and should represent elemental type. (Forgot what for? Attack?)
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 09:46:35 PM
EDIT: actually it's worse than that lol I have 0x080C6684 all over the place in places it shouldn't be.

S=memory.readbyte(0x02030A12)
function enemy (S,Elm) -- Enemy Elemental Data Table
       elemInd = memory.readbyte(0x080C6684  + ((S - 8) * 0x54) + 0x34)
       enemyelmlevel = memory.readbyte(0x080C6684  + (elemInd * 0x18) + 4+Elm)
       return enemyelmlevel
end

That first instance of 6684 looks okay, the second one doesn't look okay.  
if memory.readbyte(0x080C6684  + (PC * 0xB4) + 0x92 + Elm) == 54 then
elmaff = 5
else
elmaff = 0
end

Again, this one is probably wrong since that should be pointing to the PC elemental data. From the gs2 data google doc shouldn't this be 080C6644?  But then +0xB4 would take it back into the enemy elemntal index.

EDIT2:
Made these edits
function enemy (S,Elm) -- Enemy Elemental Data Table
        elemInd = memory.readbyte(0x080C6684  + ((S - 8) * 0x4C) + 0x2A)
        enemyelmlevel = memory.readbyte(0x080B9E7C  + (elemInd * 0x18) + 4+Elm)
        return enemyelmlevel
end

if memory.readbyte(0x080C0F4C  + (U * 0xB4) + 0x92 + Elm) == 54 then
elmaff = 5
else
elmaff = 0
end

But this still doesn't work... tried to follow your advice here: http://forum.goldensunhacking.net/index.php?topic=2656.msg44420#msg44420
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 08, October, 2016, 10:59:56 PM
@1: Other way around? Haha...

080B9E7C = Enemy Stats (76 bytes per entry)
GS2 is 0x4C bytes/entry here... (GS1's could probably be 0x54/entry, but would have to check.)
+2A = Elem. Index?

Which means I'm getting this for GS2 version:

        elemInd = memory.readbyte(0x080B9E7C  + ((S - 8) * 0x4C) + 0x2A)
        enemyelmlevel = memory.readbyte(0x080C6684  + (elemInd * 0x18) + 4+Elm)

@2: Looks like it should be the Party data (Stuff you start with.)

080C0F4C


EDIT: I forgot to refresh the page.
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 11:04:41 PM
Yeah I still had the first two addresses round the wrong way, fixed that now...

Still getting the wrong results =/ 0x02030A12 is enemy index correct? (for the first enemy)

EDIT: Here's the full script atm http://pastebin.com/qMpEmPnT it's just the unleash/effect proc stuff thats messing up atm.

EDIT2: Now I think there's a problem here
function vuln (S)
e1Ind = S
vuln1 = memory.readbyte(0x080B9E7C  + ((e1Ind - 8) * 0x4C) + 0x48)
vuln2 = memory.readbyte(0x080B9E7C  + ((e1Ind - 8) * 0x4C) + 0x49)
vuln3 = memory.readbyte(0x080B9E7C  + ((e1Ind - 8) * 0x4C) + 0x4A)
return vul1, vul2, vul3
end
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 08, October, 2016, 11:25:23 PM
@    eind = memory.readbyte(0x02030A12) -- Enemy Index

It may be a byte in GS1, but it is a 16-bit in GS2.

@Edit 2: Yeah, Probably should be +0x3E, +0x3F, and +0x40.... (For enemy vulns....)
Title: Re: GS2 Utility Script
Post by: Plexa on 08, October, 2016, 11:43:34 PM
Right I've updated things. Still getting the wrong results.

When I run
proc = (((uelm + elmaff - eelm)-(math.floor(eluc/2)))*3+bchance(E)+v)

During the King Scorpion fight with Sheba (with 2 jupiter djinn) using the sleep bomb I get the following data
uelm = 7 -- user elemental level
elmaff = 5 -- user elemental affinity
eelm = 0 -- enemy elemental level
math.floor(eluc/2) = 20 -- enemy luck/2
bchance(E) = 40 -- base chance
v=0

So I get the value of -20 at the end of this. This isn't right because it's very easy to get the King Scorpion to sleep. I don't see that KS is vulnerable to sleep in Atrius's editor either. Do any of these numbers look wrong?

Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 09, October, 2016, 12:40:40 AM
King Scorpion vuln - Effect 24 is the Sleep effect... King Scorpion has 12, 13, and 24... So I see it.

Sleep is supposed to be 45 base chance... The Master Function List topic say 35%, but I think it is wrong.  The other effect base chances are correct if the Master Function List is correct on those.

Quotemath.floor(eluc/2) = 20 -- enemy luck/2
This is actually just eluck >> 1, in-game...  bit.rshift(eluck,1) , but I put that other stuff there (in my original announcement of the formula) for newbies who don't know bit-shifts.  (Simpler to explain. :P)

Quoteeluc = memory.readbyte(0x020308E6) -- Enemy Luck
Base luck?
Title: Re: GS2 Utility Script
Post by: Plexa on 09, October, 2016, 01:12:15 AM
Right then its the vuln function thats messing up in my script! Thanks for the help (as always lol). I'll continue debugging this later tonight and keep you posted with any updates.

EDIT: ugh there was a type in the vuln function which lead to me trying to call vul1 instead of vuln1 etc hahhahhaha

Everything appears to be working now!
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 09, October, 2016, 04:27:16 AM
Okay. Sounds good!

I do have a small question myself, though?

Is there even a way to call GBA thumb functions from LUA? (There probably is if you can write values to RAM... (Think: Writing in function pointers)  But not so sure if that's efficient/user-friendly enough.)
And if not, then would it be wise to code this stuff you are doing into something that could get converted to Thumb for insertion? (Similar to that devkitadv/devkitpro stuff I was looking into...)

@devkit: In that case, calling a function could be as simple as setting a list of them up. (So you can use them anywhere in your code.) For example:
Quoteregister int *r4 asm ("r4"); //Should be at the top, and allows variable "r4" to use register "r4"...
int Calculate_Ailment_Success(int attacker, int defender, int element, int effect, int percentMod) {
   r4=(int*)0x080B075D; goto *r4; //Thumb pointers are odd numbers.
}

(I haven't figured out the best most user-friendly way of inserting the new code back into the ROM, but I assume it is easy enough for any partially experienced user. - Basically cut & paste + attach a hook (I mean get the code execution to call your main function.))

(Assuming one can still get graphics on the screen? - But even then you could still do a combo - LUA for graphics only, Thumb for everything else/store stuff in memory... In the area where there's plenty of free space.)
(I would still need to think out any kinks and think about how much shorter the code could be. - On the plus side, shorter code could mean fewer bugs slip through.)

For example, effectproc, would mainly be a function call to:
Well,  basically...

int temp = [currentRNG];
(Loop to count how many RNG cycles needed) ; 080B075C = Calculate_Ailment_Success(attacker,defender,element,effect,percentMod)
[currentRNG] = temp;

Pretty much.... (Defender would be 0x80 for the first enemy... And percentMod would be set at 100% assuming you are only calculating for the target...)


I'm also assuming Unleash could be this one?:
080B04BC = unleash_check(pc) Returns ability to cast. (Unleash if chance succeeds, or attack.)

(Relies on having checked item equipped...)

Hmm..
while Calculate_Ailment_Success(5,0x80,1,24,100%) == false or unleash_check(5) != Dreamtide do
....




EDIT:::

Quoteif memory.readbyte(0x02030900+0x14C*4)>0 then
        gui.text(60,80, "E5 Agi: " .. memory.readbyte(0x020308E4+0x14C*4))
        gui.text(110,80, "HP: " .. memory.readbyte(0x02030900+0x14C*5))
    else
TYPO!! :P (That "5", and I also thought these were 16-bits as well??) - But yeah, that's my point about bugs possibly appearing when you have an excess of dirty code. Looks like something that could have its own function/loop. (Of course, even I understand that cleaning it can be a nuisance. :P)

I think item drops are more like... if rnd(0,0xFFFF) < 0x20000 >> chance { get item } (But shift two extra depending on djinn or not?  Looking at the damage function, it seems more like there's a random chance for the quadruple rate to be applied... One of the variables for that may include Elemental Resistance... still looking, though. - It is assume that the element of djinn in which the enemy has the highest resistance in (of all their elements),... may have a 0% chance to quadruple rate?
And the one with the least resistance... should then execute this check.... still need to read the rest, though.
Title: Re: GS2 Utility Script
Post by: Plexa on 11, October, 2016, 02:43:56 AM
Good catch on the *5 error! Probably would have never found that myself since its so rare that you even get 5 enemies (to the point where I never bothered including them in the flee calculation).

I don't know enough LUA to be able to answer your question about calling thumb functions. I imagine there is since it is possible to write to RAM (we use that to suppress encounters when hunting for oob doors).

Interesting that there's a random increased drop chance, keep me posted on what you find.

EDIT: Are you sure that you're not just talking about rainbow killing enemies xD
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 11, October, 2016, 07:57:02 AM
QuoteGood catch on the *5 error! Probably would have never found that myself since its so rare that you even get 5 enemies (to the point where I never bothered including them in the flee calculation).
If I'm not mistaking, the maximum number of enemies that can be in a battle should be six. But I'm not too worried about that since it's obvious your script is for speedrunning, and that you won't come across that.

QuoteI don't know enough LUA to be able to answer your question about calling thumb functions. I imagine there is since it is possible to write to RAM (we use that to suppress encounters when hunting for oob doors).
There is a pointer list that point to functions to be called every frame at 02003610... But actually inserting functions may be the harder part if you only want just a LUA script to be messed with. (You can probably still insert hex to WRAM/IRAM that represents code and point it there.) - In the case it is used, I would recommend a simple code that just calls functions with arguments and puts return values in a specific place in RAM for use. While also resetting back the RNGs as if they were never used by these specific calls. (Assuming that's all that would be necessary from a *simple* LUA script that doesn't want to duplicate potentially(?) unnecessary things... etc.)

QuoteInteresting that there's a random increased drop chance, keep me posted on what you find.

Looking at your script is what got me looking into that in the first place... The basic details is that it only works with using djinn that are of the same element as the weakest elemental resistance of the enemy, and from there, the chance to quadruple the item chance is (Attacker ePower - Defender eResist + 30) * 655 > BRN(,0xFFFF) ... So basically you only need like 71 difference to ensure 100% chance of quadrupling, it seems. I'll give a bit more info, though....

QuoteEDIT: Are you sure that you're not just talking about rainbow killing enemies xD
Pardon?


Anyway, there are two places in the code that are notable. (+ 1~2 other places that are not-so-important, that I may skip having a specific explanation on.)  I'll start with the Damage Formula.

---
08120454 = Damage Formula
[sp, 0x18] Initially set to 0.

081205E8 = Elemental check (I think.) and,  [sp,0x18] = -1 when the element of use is one which the enemy is strongest in.
08120620 = [sp,0x18] = 1 when the element of use is one which the enemy is weakest in.
08120646 = Basically an element check for Neutral(4+), and a check for if using item - Both do [sp,0x10]=0x64 , which represents ePower. (Not really that useful though, since we branch out anyway? Except in the case where these variables could be used for other things?)
08120668 = Check for if it is djinn being used.
08120672 = Element check... 4 is neutral so it doesn't have a chance to quadruple rate, anything above 4 should be never used.
08120676 = Checks [sp,0x18] , if it is <= 0 ,  branches out... So anything other than the weakest enemy elemental resistance of the enemy doesn't have a chance to quadruple the item chance.
0812067C = The (Attacker ePower - Defender eResist + 30) * 655 > BRN(,0xFFFF) calculation.
081206A4 = Function call that puts in vars 0xD, 0x5... (0x5 is probably unused..?) ... when those (at least the 0xD) are evaluated later, it sets 0203089C to 1, which is responsible for the quadrupled chance.

---
0812824C = What happens when an enemy dies... (Coin/Exp/Item reward.... etc.) Not the same as the next function (End-of-battle), but sets up data that that function uses....

r8 = Enemy data (ROM) address.
r11 = The argument of the function is pute here, but that number should be the number at 0203089C. (Representing the quadrupler.)
r12 = address of the chance value.

0812844C = Get item chance.  If the quadrupler is not 0, then subtract 2 from it. Minimum cap is 0.  (That is the quadruple effect.)
0812845A = (0x20000 >> chance value) > BRN(0,0xFFFF)

---

Small Work-In-Progress C++ script that I made for future use... (I think it is more of an alternative version meant to be compiled/inserted into ROM rather than a replacement, though? Unless you don't mind switching your method. :P)
I know for sure that I prefer C++ more than LUA, so it shouldn't be too much of a bother for people who think the same. XD

Trivial notes about GBA/C++ code:
#defines = Basically code substitution... in my opinion. You can still use local variables from functions into them as well... (Can make it easier to read. And doesn't really change how something is compiled. (Unless the optimizer makes note of it, dunno.))
32-bit number = (int)Number
Pointer to 32-bit data = (int*)Pointer
32-bit value at pointer = *(int*)Pointer
^ Here, "Pointer" (for the GBA) should be 32-bit regardless of data-type?

For the GBA, anytime a local variable is used, it should always be 32-bit (esp. iterators/loop index variables.), or else you may get extra shifts. (May not matter if your optimizer can detect/remove them, though... but we can do it just to be safe.) - Global/RAM variables, you can do whatever you want. :)
[spoiler]//GS2 Utility Script
//Original version was by Plexa, this version is by Teawater.
//Direct function calls to: reduce bugs, cleanliness, and increased compatibility for anyone interested in ASM hacks.
register int *r4 asm ("r4"); //Allows variable "r4" to use register "r4"...

int getItemSlot(pc, item) {
r4 = (int*)0x080AEE98; goto *r4;
}
int psyCheck(pc, ability) {
   r4=(int*)0x080AF4B9; goto *r4;
}
int unleashCheck(int pc) { //Returns ability used.
   r4=(int*)0x080B04BD; goto *r4;
}
int effectSuccess(int attacker, int defender, int element, int effect, int percentMod) {
   r4=(int*)0x080B075D; goto *r4;
}
int fleeSuccess() {
   r4=(int*)0x0811CE95; goto *r4;
}

#define AD3 *(int*)0x0200049A
#define BRN *(int*)0x020054C8
#define GRN *(int*)0x030011BC
int main() {
int brn = BRN, grn = GRN;
//gui.text(160,00,"BRN: ".. (memory.readdword(AD4)))
//gui.text(160,10,"GRN: ".. (memory.readdword(AD5)))
//In battle:
//gui.text(0,20,"Encounter: ".. (memory.readword(AD3)))
//Missing Agility Stats...
//GRN/BRN counts.
int count = 0;
while ((fleeSuccess() == 0) && (++count <= 100)) { }
BRN = brn; GRN = grn; count = 0;
int pc = 0;
while (pc < 8) {
if (getItemSlot(pc, 0xE3) != -1) { //Sleep bomb - Sleep effect
while ((effectSuccess(pc, 0x80, 3, 24, 64) == 0) && (++count <= 100)) { };
BRN = brn; GRN = grn; count = 0;
}
if ((psyCheck(pc, 0x112) == 0)) { //Weaken - Resistance effect
while ((effectSuccess(pc, 0x80, 3, 16, 64) == 0) && (++count <= 100)) { };
BRN = brn; GRN = grn; count = 0;
}
pc++;
}
//Drop Stuff to come.

return 0;
}
[/spoiler]
Title: Re: GS2 Utility Script
Post by: Plexa on 11, October, 2016, 06:37:51 PM
"Rainbow Kills" are when you kill an enemy with a djinn of an element that the enemy is weak to, this gives bonus exp and item drop chance (tons of stuff on gamefaqs about this). Sounds like that is what this code is referring to.
Title: Re: GS2 Utility Script
Post by: leaf on 11, October, 2016, 09:47:04 PM
Yeah, it's definitely referring to rainbow kills. I already knew that rainbow kills could fail as a result of insufficient epow, but didn't know the exact threshold.
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 11, October, 2016, 10:07:00 PM
@Rainbow kills: Oh... You have a point, hahah... Well, at least we know where the code for it is now, right? :)
One guide seems to think Luck is a factor? (Not directly stated.) I didn't see anything on that, but can we say whether it is or isn't?
Title: Re: GS2 Utility Script
Post by: leaf on 11, October, 2016, 10:31:24 PM
Does that function reference luck? I think you have your answer.
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 11, October, 2016, 10:50:42 PM
Well, I did say I didn't see it in this area? So I guess not...

@Article: It did seem mostly implied, however, don't really know what else they'd refer to.
Was just asking in case I missed something somewhere else...
Title: Re: GS2 Utility Script
Post by: Plexa on 12, October, 2016, 05:42:32 PM
Quote from: leaf on 11, October, 2016, 09:47:04 PM
Yeah, it's definitely referring to rainbow kills. I already knew that rainbow kills could fail as a result of insufficient epow, but didn't know the exact threshold.
Thats interesting, I thought it was something that just depended on BRN I had no idea that it was a check against elemental power !
Title: Re: GS2 Utility Script
Post by: Rolina on 12, October, 2016, 08:40:26 PM
Nope!  That's why RNG exploits for item drops recommend base classes.
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 15, October, 2016, 10:25:12 PM
In your Speed Run, do you get any Sleep Bombs via using Scoop on the ground? (It's a random reward.)
Would it be worth considering adding a display for that to your script? (Or is Scoop retrieved a little too late (Yampi Desert) for it to be useful? - Although, I should probably check the first enemies with that reward and maybe I'll have my answer.)

@Scoop: Should be a random number for if something is rewarded? (Probably 1/16?) There are a few GRNS, so....

Hmm... (GRN < 0xC000  = Item rewarded))
Coins (1/4?) - Amount to reward would be ((2nd GRN * level) << 1 >> 0x10) + 1.
Item Rewarded (3/4) ==>
080F0FC0 = Item list (Chosen by random number from 0x0-0xF.) ((2nd GRN << 4) >> 0x10)
Herb (1/4)
Antidote (3/16)
Smoke Bomb (1/8)
Sleep Bomb (1/8)
Game Ticket (3/16)
Nut (1/8)

Sleep Bomb dropping enemies:
Enemy - Weakest Resistance (Initial chance of item reward.)

Death Cap - 7 Mars (1/32)
Aqua Jelly - 7 Mars (1/32)
Mini-Goblin - 48 Jupiter (1/16)
Bone Fighters - 25 Venus (1/32)
Kobolds - 48 Jupiter (1/16)
Slayers - 72 Jupiter (1/32)

Obviously, Slayers are worst choice... but the others could be reasonable.


@Staff of Anubis: Should be 0x144, and not 0x44.
Red Demon - 72 Jupiter (1/64)
Title: Re: GS2 Utility Script
Post by: Plexa on 15, November, 2016, 03:34:43 PM
We use exactly two sleep bombs; one on King Scorpion and the other on Avimander. Both are easily obtainable from Inns. But I'll keep this in mind and pass it on to Zetonegi who might have a use for it (he does japanese which has precise RNG control).

Speaking of Japanese... looks like the ROM is very different from the English one. First, the items are out of order compared to english (0x44 is supposed to be the Staff of Anubis but in Jap it is 0x144). Second, enemy data in the ROM (looked up via enemy index) is all over the place and the old calculations don't work. By chance do you have any insights there?
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 15, November, 2016, 10:25:12 PM
QuoteFirst, the items are out of order compared to english (0x44 is supposed to be the Staff of Anubis but in Jap it is 0x144).
Nah. It's 0x144 on both (U) and (J)... Unless I'm missing something. (I checked just now by giving the item to a PC.... from the PC RAM data.)

So yeah... that post still goes:
Quote@Staff of Anubis: Should be 0x144, and not 0x44.
Red Demon - 72 Jupiter (1/64)

@Enemy data: Probably just a simple base address change for each ROM table. You probably should be doing this anyway, but create a variable for each base address of a table... And the Localization will determine what the address is for each.

080B9E7C = (U) version Enemy data

080B4E4C = (J) version Enemy data


So yeah... Everything is basically there, but  the (J) version is of a slightly earlier address... (You can find it by searching for matching data between (U) and (J) versions if you want.)
Title: Re: GS2 Utility Script
Post by: Plexa on 21, November, 2016, 06:04:08 PM
Thanks for that! I never anticipated doing any work with JP but making it a variable sounds like a good idea.
Title: Re: GS2 Utility Script
Post by: Plexa on 10, January, 2017, 11:10:57 AM
Hey just checking.... but when fleeing after the reunion does it consider the party level to be the average of all 8 members (assuming they're alive) or just the front four?
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 10, January, 2017, 03:42:45 PM
Should be just the living PCs in front.
Title: Re: GS2 Utility Script
Post by: Plexa on 11, January, 2017, 08:19:07 AM
My script is returning a lower rate of flee success than what the game is - afaik it's only happening after the reunion. Any idea what is wrong?

if memory.readword(0x02000420) == 0x1FE then                 -- if in battle then do the following

if el4 ~= 0 then                                 --Hacky way of getting the enemy level; doesn't work for 5+
ela = (el1+el2+el3+el4)/4
elseif el3 ~=0 then
ela = (el1+el2+el3)/3
elseif el2 ~=0 then
ela = (el1+el2)/2
else
ela = el1
end

pc1 = memory.readbyte(0x02000458)
pc2 = memory.readbyte(0x02000459)
pc3 = memory.readbyte(0x0200045A)
pc4 = memory.readbyte(0x0200045B)
if party == 0x70 then
ml = (memory.readbyte(0x02000520+0x14C*pc1+0xF)+memory.readbyte(0x02000520+0x14C*pc2+0xF)+memory.readbyte(0x02000520+0x14C*pc3+0xF))/3
else
ml = (memory.readbyte(0x02000520+0x14C*pc1+0xF)+memory.readbyte(0x02000520+0x14C*pc2+0xF)+memory.readbyte(0x02000520+0x14C*pc3+0xF)+memory.readbyte(0x02000520+0x14C*pc4+0xF))/4
end

LevelAve = ml-ela

fleeFail = memory.readbyte(0x02030092)

function flee(S) -- Flee Success Calculation
g = S
g = RNB(g)*10000
fl = 5000 + (2000*fleeFail) + (LevelAve * 500)
g = bit.rshift(g, 16)
if fl >= g then
return true
else
return false
end
end
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 11, January, 2017, 05:20:42 PM
Huh... That's strange.
Is it corrected when you remove the last four PCs (after reunion and before entering battle)?
(I assume you're only Fleeing at the beginning of a battle - so we skipped checking for whether they were living or not.)

I might have to run your script in a bit... and maybe compare with SDL-H.... so not sure what's going on yet.

Quoteif fl >= g then
      return true
   else
      return false
   end
This can be reduced to "return fl >= g" ...


Or rather, since I like short code, more like:

function flee(S) -- Flee Success Calculation
   return ((5000 + (2000*fleeFail) + (LevelAve * 500)) >= (bit.rshift(RNB(S)*10000, 16)))
end

But if you like things split up... this works too: (Probably the easiest to read of all of these?)

function flee(S) -- Flee Success Calculation
   fl = 5000 + (2000*fleeFail) + (LevelAve * 500)
   g = bit.rshift(RNB(S)*10000, 16)
   return fl >= g
end



[spoiler=------- Fun thought -------]If LUA has any dictionary types... I bet this could be shortened way down: (Best case scenario is... possibly a one liner inside the function...?)
Quotefunction bchance (E) -- base chance for status
    if E == 16 or E == 17 then
        c = 75
    elseif E == 23 then
    c = 40
    elseif E == 24 then
    c = 45
    elseif E == 27 then
    c = 20
    end
    return c
end
I'm thinking something like: (Not tested of course.... But you can do this type of thing in Python... however, here... I try to write in LUA..., so I should look into it.)
return {[16]=75, [17]=75, [23]=40, [24]=45, [27]=20}[E]

After testing, LUA seems to not allow for the [E] part... unless I missed something. (There might be a way, but??) ...so you may have to assign the dictionary to a variable first...

c = {[16]=75, [17]=75, [23]=40, [24]=45, [27]=20}
return c[E]

Should do it.

I wouldn't recommend a one liner unless it is a small dictionary, though... and I think this is small enough. (If it was long, you could put each element on a separate line - simple, I think.)[/spoiler]

So are you planning to make a big edit to your GS2 Script? Or is it just bug fixes?
Title: Re: GS2 Utility Script
Post by: Plexa on 12, January, 2017, 07:24:34 PM
I just went through and checked everything by having my script print intermediate variables and whatnot; I can't see any issue with what's going on. Maybe I just misread errors earlier on... can't seem to replicate the behavior anymore =/
Title: Re: GS2 Utility Script
Post by: Daddy Poi's Oily Gorillas on 12, January, 2017, 08:34:10 PM
Interesting... So there are no errors?

Only possibilities I can think of at the moment are these:
-You misread something.
-Killed off an enemy ... maybe/maybe not used a savestate/forgot it won't the start of the battle.
-Started a battle with 5+ enemies/forgot that there wasn't support for that.

Etc.


---
So I googled golden sun hacking in my emails.... Found out you mailed me on youtube in 2013, but I can't access the whole message... I think b/c youtube doesn't do Inbox anymore?.... Do you remember what it was about?
It linked to this topic (http://forum.goldensunhacking.net/index.php?topic=1632.0 ) ... but the message cuts off (with "more" as a link to a Not Found page.)

Title: Re: GS2 Utility Script
Post by: Plexa on 16, January, 2017, 07:20:02 PM
Would have been about RNG stuff, we knew nothing back then! xD