Bytecodes to fix random potential values in Elona Shooter
-migrated-
I'm having some trouble fixing some values which are random in the game Elona Shooter (SWF Link & Game Link).

I found the relevent code in sothink, in generatePlayer() (swf/Action/shootem_fla/MainTimeline)
Code: [Select]
 player.potentialAim[param1] = Math.random() / 1.25 + 0.1;
  player.potentialTeam[param1] = Math.random() / 1.25 + 0.1;
Which I'd like to change to
Code: [Select]
 player.potentialAim[param1] = 0.8;
  player.potentialTeam[param1] = 0.8;
I'm really not sure if I'm doing this right, but here's what I tried:
Replace the bytecode for 'player.potentialAim[param1] = Math.random() / 1.25 + 0.1;'
Code: [Select]
60 d2 26 66 9f 29 d1 60 95 27 46 a1 27 00 2f 21 a3 2f 20 a0 61 d5 26
Code: [Select]
//60 d2 26
_as3_getlex player
//66 9f 29
_as3_getproperty potentialAim
//d1
_as3_getlocal <1>
//60 95 27
_as3_getlex Math
//46 a1 27 00
_as3_callproperty random(param count:0)
//2f 21
_as3_pushdouble 1.25
//a3
_as3_divide
//2f 20
_as3_pushdouble 0.1
//a0
_as3_add
//61 d5 26
_as3_setproperty {}
with one to set it to 0.8 instead of performing the random calculation
Code: [Select]
60 d2 26 66 9f 29 d1 2f 24 61 d5 26 02 02 02 02 02 02 02 02 02 02 02
Code: [Select]
//60 d2 26
_as3_getlex player
//66 9f 29
_as3_getproperty potentialAim
//d1
_as3_getlocal <1>
//2f 24
_as3_pushdouble 0.8
//61 d5 26
_as3_setproperty {}
// 02 02... to make up the extra bytes
and also do the same with the potentialTeam one.
Code: [Select]
60 d2 26 66 a0 29 d1 60 95 27 46 a1 27 00 2f 21 a3 2f 20 a0 61 d5 26
->
60 d2 26 66 a0 29 d1 2f 24 61 d5 26 02 02 02 02 02 02 02 02 02 02 02
To test, start a new game, finish the first battle, fix the AP value to something big (it's 4 bytes, value*8+6), then refresh the recruit in the barracks & see if the wage varies like it did before the hack.

These potentialxxxx values aren't displayed anywhere that I know of, so I'm not sure, but I don't think this worked as I'd intended because the wages for new characters still vary a lot, and I expected that if the potential stats were fixed then the wage would be too since it's derived from the potentialxxxx values. (code in spoiler below)
Code: [Select]
       public function wage(param1:int)
        {
            var _loc_2:* = undefined;
            _loc_2 = player.lv[param1] * 6 + 50 - true_if(player.pic[param1] == 50) * 50;
            if (_loc_2 < 0)
            {
                _loc_2 = 0;
            }
            _loc_2 = _loc_2 * (75 + player.potentialAim[param1] * player.potentialTeam[param1] * 100) / 100;
            _loc_2 = _loc_2 * 100 / (100 + PARTY.ACCOUNTANT + IF(medal[_medalRagnarok]) * 3);
            if (param1 == _pc)
            {
                _loc_2 = 0;
            }
            return int(_loc_2);
        }// end function


This is my first attempt at bytecode hacking and I really don't know what I'm doing, so I was hoping someone who does could take a quick look at this and let me know if there's something obvious that I've done wrong, or why this doesn't seem to work.


PS I looked at the sticky tutorials and faqs on this site and also at the bytecode hacking tutorial vids which helped a lot. There is a problem with decompiling this swf with flasm though so that method isn't going to work I don't think. The output doesn't contain any source code, which is probably due to 'unknown tag' showing up I guess. Also, when I try to export to fla with sothink it crashes.
I also searched the the site for potentialAim etc and didn't find anything. There's another thread with some hacks for Elona Shooter, but it didn't include anything about changing the potentialxxx stats.

Windows XP
firefox 3.6.13
Flash plugin 10.1.102.64
sothink 5.2 build 521
Flasm 1.62
Never let a computer tell´╗┐ me shit.
i think your code does work. it should work anyways.

lets assume some vars here
Code: [Select]
param1 = 1;
player.lv[1]=1;//keeps math simple
player.potentialAim[1]=0.8
player.potentialTeam[1]=0.8

Code: [Select]
_loc_2 = player.lv[param1] * 6 + 50 - true_if(player.pic[param1] == 50) * 50;
if (_loc_2 < 0) _loc_2 = 0;

so if my order of operations are correct there are 2 possible values for _loc_2
_loc_2 = 56;//6+50-0*50
_loc_2 = 6;//6+50-1*50

then we do
Code: [Select]
_loc_2 = _loc_2 * (75 + player.potentialAim[param1] * player.potentialTeam[param1] * 100) / 100;_loc_2 = 77.84
_loc_2 = 8.34


so basically, you need to lock down the wage function too if you want to use it to test variables. ie remove
true_if(player.pic[param1] == 50)
and
_loc_2 = _loc_2 * 100 / (100 + PARTY.ACCOUNTANT + IF(medal[_medalRagnarok]) * 3);

ok so i was definitely wrong. your code doesnt work lol.
hell, you might want to just have the wage function return player.potentialAim[param1] * player.potentialTeam[param1] then you can know directly. wages will either be 0.64 or not.
wages =aim*team
60 d2 26 66 d3 26 d1 66 d5 26 24 06 a2 24 32 a0 5d 9d 29 60 d2 26 66 9e 29
60 d2 26 66 9f 29 d1 66 d5 26 60 d2 26 66 a0 29 d1 66 d5 26 a2 48 66 9e 29



I use this AoB tool to make all the AoBs I post. Try the online version if you dont feel like downloading it.
"Obviously, windows are central to Windows. They are so important that they named the operating system after them. But what is a window?"

lol, you got my hopes up there at the start.

Thanks taking a look at it kolonelkadat, and for the wage AoBs too.

I think the wage would be constant even without that though, if you are just refreshing the recruit (and the code I did worked that is) coz all the values except those potential ones should be fixed. It's good to be able to take them out of the equation though, coz I haven't checked where they're written to be 100% sure.
player.pic[param1]      - this is 50 for the unique "little girl' NPC character, who gets a wage discount I guess
player.lv[param1]        - won't change until you fight
PARTY.ACCOUNTANT   - is a party skill which won't change if you're just refreshing the recruit
medal[_medalRagnarok]  - whether or not you got this achievement
Some more info: This is the code which sets up the 'Little Girl' npc stats to hard coded values, which is where I copied the last part of the player.potentialTeam[param1] = 0.8 from.
Code: [Select]
       public function gameStart()
        {
            if (player.devType[_pc] == _devHunter || player.devType[_pc] == _devRogue)
            {
                generatePlayer(1, 1, _devGuard);
                player.name[1] = "Little Girl";
                player.potentialAim[1] = 0.7;
                player.potentialTeam[1] = 0.8;
                player.trait[1][TRAIT.BASE_AIMING] = 1;
                player.trait[1][TRAIT.BASE_TEAMWORK] = 1;
                player.pic[1] = 50;
                player.ai[1] = _aiFireAtWill;
                player.optBoss[1] = true;
                player.optWall[1] = true;
            }
Code: [Select]
       public function gameStart()
        {
//d0
_as3_getlocal <0>
//30
_as3_pushscope
//60 d2 26
_as3_getlex player
//66 96 28
_as3_getproperty devType
//60 d4 26
_as3_getlex _pc
//66 d5 26
_as3_getproperty {}
//60 84 28
_as3_getlex _devHunter
//ab
_as3_equals
//2a
_as3_dup
//11 11 00 00
_as3_iftrue offset: 17
//29
_as3_pop
//60 d2 26
_as3_getlex player
//66 96 28
_as3_getproperty devType
//60 d4 26
_as3_getlex _pc
//66 d5 26
_as3_getproperty {}
//60 85 28
_as3_getlex _devRogue
//ab
_as3_equals
//12 94 00 00
_as3_iffalse offset: 148
//5d a4 29
_as3_findpropstrict generatePlayer
//24 01
_as3_pushbyte 1
//2a
_as3_dup
//60 8c 28
_as3_getlex _devGuard
//4f a4 29 03
_as3_callpropvoid generatePlayer(param count:3)
//60 d2 26
_as3_getlex player
//66 cc 27
_as3_getproperty name
//24 01
_as3_pushbyte 1
//2c 9d 1e
_as3_pushstring "Little Girl"
//61 d5 26
_as3_setproperty {}


//                 player.potentialAim[1] = 0.7;

//60 d2 26
_as3_getlex player
//66 9f 29
_as3_getproperty potentialAim
//24 01
_as3_pushbyte 1
//2f 27
_as3_pushdouble 0.7
//61 d5 26
_as3_setproperty {}


//                player.potentialTeam[1] = 0.8;

//60 d2 26
_as3_getlex player
//66 a0 29
_as3_getproperty potentialTeam
//24 01
_as3_pushbyte 1
//2f 24
_as3_pushdouble 0.8
//61 d5 26
_as3_setproperty {}


//60 d2 26
_as3_getlex player
//66 91 28
_as3_getproperty trait
//24 01
_as3_pushbyte 1
//66 d5 26
_as3_getproperty {}
//60 e4 27
_as3_getlex TRAIT
//66 97 29
_as3_getproperty BASE_AIMING
//24 01
_as3_pushbyte 1
//61 d5 26
_as3_setproperty {}
//60 d2 26
_as3_getlex player
//66 91 28
_as3_getproperty trait
//24 01
_as3_pushbyte 1
//66 d5 26
_as3_getproperty {}
//60 e4 27
_as3_getlex TRAIT
//66 9a 29
_as3_getproperty BASE_TEAMWORK
//24 01
_as3_pushbyte 1
//61 d5 26
_as3_setproperty {}
//60 d2 26
_as3_getlex player
//66 9e 29
_as3_getproperty pic
//24 01
_as3_pushbyte 1
//24 32
_as3_pushbyte 50
//61 d5 26
_as3_setproperty {}
//60 d2 26
_as3_getlex player
//66 a5 29
_as3_getproperty ai
//24 01
_as3_pushbyte 1
//60 a6 29
_as3_getlex _aiFireAtWill
//61 d5 26
_as3_setproperty {}
//60 d2 26
_as3_getlex player
//66 ef 26
_as3_getproperty optBoss
//24 01
_as3_pushbyte 1
//26
_as3_pushtrue
//61 d5 26
_as3_setproperty {}
//60 d2 26
_as3_getlex player
//66 f0 26
_as3_getproperty optWall
//24 01
_as3_pushbyte 1
//26
_as3_pushtrue
//61 d5 26
_as3_setproperty {}
//5d f7 2a
_as3_findpropstrict geneMedalBonus
//4f f7 2a 00
_as3_callpropvoid geneMedalBonus(param count:0)
//60 f8 27
_as3_getlex medal
//60 ef 29
_as3_getlex _medalHardcore2
//66 d5 26
_as3_getproperty {}
//12 0f 00 00
_as3_iffalse offset: 15

I was kind of hoping I just did something daft which was easy to fix...
Quick tip: If you're not sure whether an AoB is doing its job, create another copy for the .swf file, pre-hack it and look at the action-script.