Code Optimizing: need some help

Discussions Related to Game Hacking and Memory Hacking Software

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

Code Optimizing: need some help

Postby esco » Fri Mar 28, 2008 1:15 pm

Wussup Spiro, I need some quick help here. I'm as usual working on my hack for SOTN using the epsxe emulator.

I figured combining things would make the emulator run smoother (it slows down in certain rooms due to scripts), but it doesn't seem to have helped.

Here is the issue: there are 96 possible spots in ram that a monster can show up in, and 32 spots for stuff like enemy projectiles. The monsters in one room ALWAYS show up in the same spot in ram (if they are not infinitely respawning types), but I am trying to make scripts to account for all possible places since a map editor is being made by a friend of mine that should let me put more monsters into rooms.

Originally I had separate files for each monster, but in a few rooms if there were too many different TYPES of monsters it slowed things down due to all the scripts that would be running. I started combining them in hopes that it would run smoother, but it seems to have not helped.

Here is the ENTIRE code for one stage. If you have any tips on how I can get it to run these scripts without slowing down the emu as much, let me know.

Code: Select all
struct SPRITE {
    SHORT hmovement;
    SHORT hpos;
    SHORT vmovement;
    SHORT vpos;
    LONG hspeed;
    LONG vspeed;
    SHORT hoffset;
    SHORT voffset;
    SHORT dirfacing;
    SHORT color;
    SHORT transp;   //amount of transparency for some things
    SHORT hwidth;    //for dust
    SHORT vwidth;    //for dust
    SHORT anglesmall;   //angle of rotating items
    SHORT blank62a238;
    SHORT blank62a23a;
    SHORT blank62a23c;
    SHORT sprite1;  //what is created, enemy, item, weapon, etc.
    SHORT sprite2;  //what is created, enemy, item, weapon, etc.
    SHORT sprite3;
    SHORT action1;
    SHORT action2;
    SHORT itemnum;    //used for when richter is blinking
    SHORT blank62a24a;
    SHORT blank62a24c;
    SHORT showsdmg;
    SHORT blank62a250;
    SHORT doesdmg1;
    SHORT doesdmg2;    //does the move hit and do damage? 2 for sub weapons and attacks
    SHORT hp;
    SHORT dmg;
    SHORT dmgtype;   //type of element dmg attack does
    SHORT blank62a25c;
    BYTE hrange;
    BYTE vrange;
    SHORT delaymult;  //delay between hits when touch player.dmg is on
    SHORT blank62a262;
    SHORT actiondata;   //determines player.frame image used for each player.frame number
    SHORT blank62a266;
    SHORT frame;
    SHORT frametimer;
    SHORT blank62a26c;
    SHORT framepic;
    SHORT hitstun;
    SHORT blank62a272;
    SHORT blank62a274;
    SHORT blank62a276;
    SHORT blank62a278;
    SHORT blank62a27a;
    SHORT blank62a27c;
    SHORT blank62a27e;
    SHORT blank62a280;
    SHORT hitscandles;    //1=yes, 0 = no
    SHORT transp2;        //amount of transparency for dust
    SHORT blank62a286;
    SHORT blank62a288;
    SHORT blank62a28a;
    SHORT blank62a28c;
    SHORT blank62a28e;
    SHORT blank62a290;
    SHORT blank62a292;
    SHORT fadetimer;    //used BY daggers to fade out {N/A on player sprite)
    SHORT widthtimer;   //used by holy book to control how far spinning extends out
    SHORT attacktimer;       //WARG: timer till next attack
    SHORT spinangle;    //used BY holy book, determines what angle it spins at
    SHORT timer3;       //used by prism beam to determine how long till book opens up
    SHORT blank62a29e;
    SHORT blank62a2a0;
    SHORT blank62a2a2;
    SHORT dractimer;
    SHORT blank62a2a6;
    SHORT blinkintensity;    //used when richter is blinking to indicate how MUCH to show blinking
    SHORT blank62a2aa;
    SHORT usertag18;
    SHORT usertag17;
    SHORT usertag16;
    SHORT usertag15;
    SHORT usertag14;
    SHORT usertag13;
    SHORT usertag12;
    SHORT atknum;
    SHORT usertag10;
    SHORT usertag9;
    SHORT usertag8;
    SHORT usertag7;
    SHORT usertag6;
    SHORT usertag5;
    SHORT usertag4;
    SHORT usertag3;
    SHORT fivetag;
    SHORT novaballs;
    SHORT tag1;
    SHORT blank62a2d2;
};

struct MONSTER {
   LONG text;
   SHORT hp;
   SHORT dmg;
   SHORT element;
   SHORT def;
   SHORT canblock;
   SHORT weakto;
   SHORT strongto;
   SHORT immuneto;
   SHORT absorbs;
   SHORT level;
   SHORT exp;
   SHORT commondrop;
   SHORT raredrop;
   SHORT commonrate;
   SHORT rarerate;
   BYTE hsize;
   BYTE vsize;
   BYTE unknown1;
   BYTE special;
};

int count;

/*Monsters: Warg, Zombie, Bat, Fishman, Meman (not needed due to being removed until later), Bone Scimitar*/

**HERE IS WHERE IT RUNS ALL THE SCRIPTS VIA THE LOOP**

void Lock ()
{
extern SHORT stagenum = { "", 0x0064e2e0 };

if (stagenum == 65)
{
   {count = 0;}
   for (count = 0; count < 96; count++)
   {
      if (count < 33) {zombie(); fishman();}
      {warg(); bonescimitar(); bat();}     
   }   
}
}

[b]**FROM HERE ON IS EACH DIFFERENT CREATURES SCRIPT**[/b]

extern SPRITE player = { "", 0x62a218 };
extern SPRITE enemy[1] = { "", 0x0062d118 };
extern SPRITE respawn[1] = { "", 0x00631798 };

void warg ()
{
extern MONSTER wargperm = { "", 0x00661298 };

if (wargperm.hp != 300) {wargperm.hp = 300; wargperm.dmg = 20; wargperm.weakto = 32896; wargperm.strongto = 8192; wargperm.special = 48; wargperm.level = 3; wargperm.exp = 25;}
if (enemy[count].sprite1 == 74 && enemy[count].sprite2 == -2240 && enemy[count].sprite3 == -32740)
{
   //bites and turns faster
   if (enemy[count].action1 == 6 && enemy[count].attacktimer > 10) {enemy[count].attacktimer = 10;}
   else if (enemy[count].action1 == 5 && enemy[count].frametimer > 3) {enemy[count].frametimer = 3;}   
}
}

void zombie ()
{
extern MONSTER zombieperm = { "", 0x00660870 };

//weak to fire/holy, strong to dark, immuneto psn/cur, absorbs none
if (zombieperm.hp < 14) {zombieperm.hp = 14; zombieperm.dmg = 6; zombieperm.weakto = 36864; zombieperm.strongto = 2048; zombieperm.immuneto = 384; zombieperm.level = 1; zombieperm.exp = 3;}
if (respawn[count].sprite1 == 76 && respawn[count].sprite2 == 25776 && respawn[count].sprite3 == -32739)
{
   //nothing slows them down
   if (respawn[count].showsdmg != -30704) {respawn[count].showsdmg = -30704;}
   //fixes hrange
   if (respawn[count].hrange == 8) {respawn[count].hrange = 13;}
   //rises out of ground faster
   if (respawn[count].action1 == 2 && respawn[count].frametimer > 3) {respawn[count].frametimer = 3;}
   //certain color zombies move faster than others
   if (respawn[count].tag1 == 0)
   {
      if (respawn[count].color == 723) {respawn[count].tag1 = 1;}     
      else if (respawn[count].color == 724) {respawn[count].tag1 = 2;}
   }   
   //tags needed so when zombies blink when hit they do NOT slow down
   else if (respawn[count].tag1 == 1)
   {
      if (respawn[count].dirfacing == 0) {respawn[count].hspeed = -100000;}   
      else {respawn[count].hspeed = 100000;} 
   }
   else if (respawn[count].tag1 == 2)
   {
      if (respawn[count].dirfacing == 0) {respawn[count].hspeed = -70000;}   
      else {respawn[count].hspeed = 70000;} 
   }
}   
}

void fishman ()
{
extern MONSTER fishmanperm = { "", 0x0065fb78 };
extern MONSTER fireb = { "", 0x0065fba0 };

//weak to fire/lit, strong to ice
if (fishmanperm.hp != 16) {fishmanperm.hp = 16; fishmanperm.dmg = 6; fishmanperm.weakto = 49152; fishmanperm.strongto = 8192;
    fishmanperm.level = 3; fishmanperm.exp = 6; fishmanperm.commondrop = 0; fishmanperm.raredrop = 0;
    fireb.hp = 0; fireb.dmg = 8; fireb.canblock = 5; fireb.special = 0;}
//walks slightly faster
if (respawn[count].sprite1 == 65 && respawn[count].sprite2 == 19232 && respawn[count].sprite3 == -32739)
{
   if (respawn[count].hspeed > 0 && respawn[count].hspeed < 40000) {respawn[count].hspeed = 40000;}
   else if (respawn[count].hspeed < 0 && respawn[count].hspeed > -40000) {respawn[count].hspeed = -40000;}
}   
/*FIREBALL: moves faster*/
else if (respawn[count].sprite1 == 66 && respawn[count].sprite2 == 22232 && respawn[count].sprite3 == -32739)
{
   if (respawn[count].hspeed > 0 && respawn[count].hspeed < 150000) {respawn[count].hspeed = 150000;}
   else if (respawn[count].hspeed < 0 && respawn[count].hspeed > -150000) {respawn[count].hspeed = -150000;}
}
}

void bat ()
{
extern MONSTER batperm = { "", 0x00660140 };
extern SHORT timerticks = { "", 0x0064ea7c };

//weak to psn/stn
if (batperm.dmg < 10) {batperm.dmg = 10; batperm.weakto = 640; batperm.special = 16; batperm.level = 1; batperm.exp = 5;}
if (enemy[count].sprite1 == 72 && enemy[count].sprite2 == 25188 && enemy[count].sprite3 == -32739)
{
   //activates enemy sooner
   if (enemy[count].action1 == 1 && enemy[count].hpos >= player.hpos-128 && enemy[count].hpos <= player.hpos+128 && enemy[count].vpos >= player.vpos-96 && enemy[count].vpos <= player.vpos+96) {enemy[count].action1 = 2;}
   //sets bats to sometimes INSTANTLY attack
   if (timerticks %4 == 0 && enemy[count].tag1 == 0) {enemy[count].tag1 = 1;}
   else {enemy[count].tag1 = 2;}
   if (enemy[count].tag1 == 1 && enemy[count].action1 == 1) {enemy[count].action1 = 2; enemy[count].frame = 9;}
   //shakes for less time before it flies at you
   if (enemy[count].action1 == 2)
   {
      if (enemy[count].frame < 6) {enemy[count].frame = 6;}
      if (enemy[count].frametimer > 5) {enemy[count].frametimer = 5;} 
   }   
   //flies faster now
   else if (enemy[count].action1 == 3)
   {
       if (enemy[count].vspeed > 0) {enemy[count].vspeed = 108544;}
       if (enemy[count].hspeed < 0) {enemy[count].hspeed = -81920;}
       else if (enemy[count].hspeed > 0) {enemy[count].hspeed = 81920;}
   }   
   //speeds up once on same height plane as you
   else if (enemy[count].action1 == 4)
   {
      if (enemy[count].vspeed > 100000) {enemy[count].vspeed = 57344;}
      if (enemy[count].hspeed < 0) {enemy[count].hspeed = -131072;}
      else if (enemy[count].hspeed > 0) {enemy[count].hspeed = 131072;}
   }   
}   
}

void bonescimitar ()
{
extern MONSTER bonescimitarperm = { "", 0x006607a8 };

if (bonescimitarperm.dmg < 13) {bonescimitarperm.hp = 25; bonescimitarperm.def = 0; bonescimitarperm.dmg = 10;}
if (enemy[count].sprite1 == 70 && enemy[count].sprite2 == 23212 && enemy[count].sprite3 == -32739)
{   
   //attacks faster now
   if (enemy[count].action1 == 4 && enemy[count].frame == 1) {enemy[count].frame = 4; enemy[count].frametimer = 1;}
   //moves faster now ONLY when approaching
   if (enemy[count].hspeed > 0 && enemy[count].dirfacing == 1) {enemy[count].hmovement = -32768;}
   else if (enemy[count].hspeed < 0 && enemy[count].dirfacing == 0) {enemy[count].hmovement = 0;}
   if (enemy[count].frame == 9)
   {
      //holds sword out for less time
      if  (enemy[count].frametimer > 13) {enemy[count].frametimer = 13;}
      //increases sword range and moves hitbox
      {enemy[count].hrange= 25; enemy[count].hoffset= -15;}
   }   

   //moves sooner after atacking
   else if (enemy[count].frame > 9 && enemy[count].frametimer > 1) {enemy[count].frametimer = 1;}
}   
}


[/code]
Esco.... the name says it all. New Yorikan for life.
User avatar
esco
NULL
 
Posts: 148
Joined: Mon Sep 18, 2006 2:25 am
Location: Florida, a.k.a. the US's version of hell!

Postby L. Spiro » Fri Mar 28, 2008 1:46 pm

Code: Select all
extern SHORT stagenum = { "", 0x0064e2e0 };
extern MONSTER wargperm = { "", 0x00661298 };
extern MONSTER zombieperm = { "", 0x00660870 };
extern MONSTER fishmanperm = { "", 0x0065fb78 };
extern MONSTER fireb = { "", 0x0065fba0 };
extern MONSTER batperm = { "", 0x00660140 };
extern SHORT timerticks = { "", 0x0064ea7c };
extern MONSTER bonescimitarperm = { "", 0x006607a8 };

These should all be moved to global space outside of functions. Otherwise they are redeclared each time the functions are called.


Each time you use enemy[count] or respawn[count] the address of the item inside the array must be calculated. You can save time here with one of several methods:


warg()
Save time by not recalculating the index into the array each time.
Do this:
Code: Select all
void warg () {
    // Save an extern that points directly to the sprite we will modify.
    // There is some overhead in doing this, so if you do not have many
    //  enemy[count]’s to replace it will not be worth it.
    extern SPRITE eThisEnemy = { "", &enemy[count] };

    …


    if ( eThisEnemy.sprite1 == 74 && eThisEnemy.sprite2 == -2240 && eThisEnemy.sprite3 == -32740 ) {
        …
    }
}




zombie()
There is not much you can do to optimize this.


fishman()
respawn[count].hspeed and other values are used repeatedly. Each time they are used it will cost you one index calculation as well as a read of the target process.
For every value that is read multiple times without being changed by your script, save it to a local and use that.

Code: Select all
    INT iHSpeed = respawn[count].hspeed;
    if ( iHSpeed > 0 && iHSpeed < 40000) { respawn[count].hspeed = 40000; }
    else if ( iHSpeed < 0 && iHSpeed > -40000) { respawn[count].hspeed = -40000; }


This should be applied to all code everywhere.


bat()
The same thing as with warg() and fishman().


bonescimitar()
The same thing as with warg() and fishman().


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby esco » Fri Mar 28, 2008 2:20 pm

I understanding ALMOST everything you have just said, and the tip of using a local var for things that constantly change helps a little, and moving the vars to global helps a tiny bit.... but I don't understand the point of what you did above for warg.

Aren't you just basically moving what's in one extern to another, and putting in another step? How would this help? Or are you saying to have a loop look thru where the monsters are in a room, and save it so that the loop doesn't run over and over? Because the problem there is that more monsters spawn as I walk thru the room.

Or are you just saying to go thru rooms, record where the monsters show up, and set a script up for each room? Because this is my old way of doing it, and it's a pain.

Code: Select all
void warg () {
    // Save an extern that points directly to the sprite we will modify.
    // There is some overhead in doing this, so if you do not have many
    //  enemy[count]’s to replace it will not be worth it.
    extern SPRITE eThisEnemy = { "", &enemy[count] };

    …


    if ( eThisEnemy.sprite1 == 74 && eThisEnemy.sprite2 == -2240 && eThisEnemy.sprite3 == -32740 ) {
        …
    }
}
Esco.... the name says it all. New Yorikan for life.
User avatar
esco
NULL
 
Posts: 148
Joined: Mon Sep 18, 2006 2:25 am
Location: Florida, a.k.a. the US's version of hell!

Postby L. Spiro » Fri Mar 28, 2008 3:31 pm

esco wrote:Aren't you just basically moving what's in one extern to another

We are moving an extern that also involves an array offset calculation into an extern that does not. You remove the array access which should be 2 instructions per access.


One more thing you can do which will be helpful for bat() and bonescimitar() (the others as well):

Reduce read operations to once per function by making a local copy of the whole structure.

Code: Select all
SPRITE sLocalEnemy;
ReadProcessMemory( GetCurProcessHandle(), (LPVOID)&enemy[count], &sLocalEnemy, sizeof( sLocalEnemy ), NULL );
// Use sLocalEnemy for all read statements in the function (all conditional checks primarily).


This will be faster even still if sLocalEnemy is a global, but you must be sure only to access it on one thread at a time (which is the default way scripts run anyway).


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby esco » Fri Mar 28, 2008 4:09 pm

L. Spiro wrote:
esco wrote:Aren't you just basically moving what's in one extern to another

We are moving an extern that also involves an array offset calculation into an extern that does not. You remove the array access which should be 2 instructions per access.


Ah, I see now. Makes sense. I also sped my code up a LOT by simply taking out the if (enemy[count].sprite1 == 1 && enemy[count].sprite2 == 2 && enemy[count].sprite3 == 3) part out of each function, and putting it under lock instead, with it's appropriate function next to it instead.

One more thing you can do which will be helpful for bat() and bonescimitar() (the others as well):

Reduce read operations to once per function by making a local copy of the whole structure.

Code: Select all
SPRITE sLocalEnemy;
ReadProcessMemory( GetCurProcessHandle(), (LPVOID)&enemy[count], &sLocalEnemy, sizeof( sLocalEnemy ), NULL );
// Use sLocalEnemy for all read statements in the function (all conditional checks primarily).


This will be faster even still if sLocalEnemy is a global, but you must be sure only to access it on one thread at a time (which is the default way scripts run anyway).


L. Spiro


So I put that under each enemy function, and declare sLocalEnemy as a global var then? Aight I'll try it tomorrow bro. Thanks.
Esco.... the name says it all. New Yorikan for life.
User avatar
esco
NULL
 
Posts: 148
Joined: Mon Sep 18, 2006 2:25 am
Location: Florida, a.k.a. the US's version of hell!

Postby esco » Sat Mar 29, 2008 2:12 am

Well bro I tried what you said on the bat type enemies.... when I get to a bat, the scripts do nothing in game. But before I made that small change they worked fine. Here is the bat function, with the lock part above it:

Code: Select all
struct SPRITE {
    SHORT hmovement;
    SHORT hpos;
    SHORT vmovement;
    SHORT vpos;
    LONG hspeed;
    LONG vspeed;
    SHORT hoffset;
    SHORT voffset;
    SHORT dirfacing;
    SHORT color;
    SHORT transp;   //amount of transparency for some things
    SHORT hwidth;    //for dust
    SHORT vwidth;    //for dust
    SHORT anglesmall;   //angle of rotating items
    SHORT blank62a238;
    SHORT blank62a23a;
    SHORT blank62a23c;
    SHORT sprite1;  //what is created, enemy, item, weapon, etc.
    SHORT sprite2;  //what is created, enemy, item, weapon, etc.
    SHORT sprite3;
    SHORT action1;
    SHORT action2;
    SHORT itemnum;    //used for when richter is blinking
    SHORT blank62a24a;
    SHORT blank62a24c;
    SHORT showsdmg;
    SHORT blank62a250;
    SHORT canbehit1;
    SHORT canbehit2;    //does the move hit and do damage? 2 for sub weapons and attacks
    SHORT hp;
    SHORT dmg;
    SHORT dmgtype;   //type of element dmg attack does
    SHORT blank62a25c;
    BYTE hrange;
    BYTE vrange;
    SHORT pain;
    SHORT blank62a262;
    SHORT actiondata;   //determines player.frame image used for each player.frame number
    SHORT blank62a266;
    SHORT frame;
    SHORT frametimer;
    SHORT blank62a26c;
    SHORT framepic;
    SHORT hitstun;
    SHORT blank62a272;
    SHORT blank62a274;
    SHORT blank62a276;
    SHORT blank62a278;
    SHORT blank62a27a;
    SHORT blank62a27c;
    SHORT blank62a27e;
    SHORT blank62a280;
    SHORT hitscandles;    //1=yes, 0 = no
    SHORT transp2;        //amount of transparency for dust
    SHORT blank62a286;
    SHORT blank62a288;
    SHORT blank62a28a;
    SHORT blank62a28c;
    SHORT blank62a28e;
    SHORT blank62a290;
    SHORT blank62a292;
    SHORT fadetimer;    //used BY daggers to fade out {N/A on player sprite)
    SHORT widthtimer;   //used by holy book to control how far spinning extends out
    SHORT attacktimer;       //WARG: timer till next attack
    SHORT mournetimer;  /*!used by owl knight!*/
    SHORT timer3;       //used by prism beam to determine how long till book opens up
    SHORT blank62a29e;
    SHORT blank62a2a0;
    SHORT blank62a2a2;
    SHORT weapontag;
    SHORT blank62a2a6;
    SHORT blinkintensity;    //used when richter is blinking to indicate how MUCH to show blinking
    SHORT blank62a2aa;
    SHORT usertag17;
    SHORT usertag16;
    SHORT usertag15;
    SHORT usertag14;
    LONG spintimer;
    SHORT usertag12;
    SHORT atknum;
    SHORT usertag10;
    SHORT usertag9;
    SHORT usertag8;
    SHORT usertag7;
    SHORT usertag6;
    SHORT frame2;
    SHORT usertag4;
    SHORT frametimer2;
    SHORT fivetag;
    SHORT tickstag;
    SHORT tag1;
    SHORT blank62a2d2;
};

struct MONSTER {
   LONG text;
   SHORT hp;
   SHORT dmg;
   SHORT element;
   SHORT def;
   SHORT canblock;
   SHORT weakto;
   SHORT strongto;
   SHORT immuneto;
   SHORT absorbs;
   SHORT level;
   SHORT exp;
   SHORT commondrop;
   SHORT raredrop;
   SHORT commonrate;
   SHORT rarerate;
   BYTE hsize;
   BYTE vsize;
   BYTE unknown1;
   BYTE special;
};

int count;

/*Monsters: Owl Knight, Owl, Zombie, Bat, Fishman, Merman, Bloody Zombie, Blade, Gurkha, Slogra1, Gaibon1*/
void Lock ()
{
extern SHORT stagenum = { "", 0x0064e2e0 };

if (stagenum == 7)
{
   for (count = 0; count < 96; count++)
   {
      if (enemy[count].sprite1 == 64 && enemy[count].sprite2 == -26244 && enemy[count].sprite3 == -32740) {bat();}
      else if (enemy[count].sprite1 == 72 && enemy[count].sprite2 == -22956 && enemy[count].sprite3 == -32740) {bloodyzombie();}
      else if (enemy[count].sprite1 == 68 && enemy[count].sprite2 == -15648 && enemy[count].sprite3 == -32740) {owlknight();}
      else if (enemy[count].sprite1 == 69 && enemy[count].sprite2 == -20456 && enemy[count].sprite3 == -32740) {owl();}
      else if (enemy[count].sprite1 == 60 && enemy[count].sprite2 == -15520 && enemy[count].sprite3 == -32740) {blade();}
      else if (enemy[count].sprite1 == 88 && enemy[count].sprite2 == -1716 && enemy[count].sprite3 == -32740) {gurkha();}
      if (respawn[count].sprite1 == 57 && respawn[count].sprite2 == -32200 && respawn[count].sprite3 == -32740) {fishman();}
      else if (respawn[count].sprite1 == 50 && respawn[count].sprite2 == 25956 && respawn[count].sprite3 == -32740) {merman();}
      if (count > 63 && respawn[count].sprite1 == 58 && respawn[count].sprite2 == -29200 && respawn[count].sprite3 == -32740) {fishmanfireball();}
      else if (count > 63 && respawn[count].sprite1 == 66 && respawn[count].sprite2 == -25656 && respawn[count].sprite3 == -32740) {zombie();}     
      else if (count > 63 && respawn[count].sprite1 == 52 && respawn[count].sprite2 == 30848 && respawn[count].sprite3 == -32740) {mermanfireball();}                         
   }   
}
}

extern SPRITE player = { "", 0x62a218 };
extern SHORT timerticks = { "", 0x0064ea7c };
extern SPRITE enemy[1] = { "", 0x0062d118 };
extern SPRITE respawn[1] = { "", 0x0062e898 };
extern MONSTER batperm = { "", 0x00660140 };
extern MONSTER bloodyzperm = { "", 0x0065f948 };
extern BYTE hrange1 = { "", 0x007396fe };
extern BYTE hrange2 = { "", 0x00739712 };
extern BYTE swordstabvrange = { "", 0x0073976f };
extern MONSTER owlknightperm = { "", 0x0065fa60 };
extern MONSTER knightsword = { "", 0x0065fa88 };
extern MONSTER owlperm = { "", 0x0065fab0 };
extern MONSTER zombieperm = { "", 0x00660870 };
extern MONSTER fishmanperm = { "", 0x0065fb78 };
extern MONSTER fishmanfireb = { "", 0x0065fba0 };
extern MONSTER gurkhaperm = { "", 0x006614a0 };
extern MONSTER gurkhaweapon = { "", 0x006614c8 };
extern MONSTER bladeperm = { "", 0x006614f0 };
extern MONSTER bladeweapon = { "", 0x00661518 };
extern MONSTER kick = { "", 0x00661540 };
extern MONSTER mermanperm = { "", 0x0065fbc8 };
extern MONSTER mermanfireb = { "", 0x0065fbf0 };

void bat ()
{
[b]
**I just changed these lines**[/b]
SPRITE currentenemy;

ReadProcessMemory( GetCurProcessHandle(), (LPVOID)&enemy[count], &currentenemy, sizeof( currentenemy ), NULL );
[b]**END OF CHANGES**[/b]

//weak to psn/stn
if (batperm.dmg < 10) {batperm.dmg = 10; batperm.weakto = 640; batperm.special = 16; batperm.level = 1; batperm.exp = 5;}

{
   //activates enemy sooner
   if (currentenemy.action1 == 1 && currentenemy.hpos >= player.hpos-128 && currentenemy.hpos <= player.hpos+128 && currentenemy.vpos >= player.vpos-96 && currentenemy.vpos <= player.vpos+96) {currentenemy.action1 = 2;}
   //sets bats to sometimes INSTANTLY attack
   if (timerticks %4 == 0 && currentenemy.tag1 == 0) {currentenemy.tag1 = 1;}
   else {currentenemy.tag1 = 2;}
   if (currentenemy.tag1 == 1 && currentenemy.action1 == 1) {currentenemy.action1 = 2; currentenemy.frame = 9;}
   //shakes for less time before it flies at you
   if (currentenemy.action1 == 2 && currentenemy.frame < 6) {currentenemy.frame = 6;}
   if (currentenemy.action1 == 2 && currentenemy.frametimer > 5) {currentenemy.frametimer = 5;} 
   //flies faster now
   if (currentenemy.action1 == 3)
   {
       int vspeed = currentenemy.vspeed;
       int hspeed = currentenemy.hspeed;
       if (vspeed > 0) {currentenemy.vspeed = 108544;}
       if (hspeed < 0) {currentenemy.hspeed = -81920;}
       else if (hspeed > 0) {currentenemy.hspeed = 81920;}
   }   
   //speeds up once on same height plane as you
   else if (currentenemy.action1 == 4)
   {
       int vspeed = currentenemy.vspeed;
       int hspeed = currentenemy.hspeed;
      if (vspeed > 100000) {currentenemy.vspeed = 57344;}
      if (hspeed < 0) {currentenemy.hspeed = -131072;}
      else if (hspeed > 0) {currentenemy.hspeed = 131072;}
   }   
}   
}


There are more functions below bat... but they are not relevant, since they are unchanged and still work.
Esco.... the name says it all. New Yorikan for life.
User avatar
esco
NULL
 
Posts: 148
Joined: Mon Sep 18, 2006 2:25 am
Location: Florida, a.k.a. the US's version of hell!

Postby L. Spiro » Sat Mar 29, 2008 9:47 am

if (currentenemy.action1 == 2 && currentenemy.frametimer > 5) {currentenemy.frametimer = 5;}

You were not supposed to change the write operations.


L. Spiro
Our songs remind you of songs you’ve never heard.
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan


Return to General Related Discussions

Who is online

Users browsing this forum: No registered users and 0 guests