NPC Hacking 2
The NPC Object Pointer

NPC Object Pointer
Remember that DWORD [EBP+8] is used as the pointer to the NPC's object. In order to modify the variables of the object, we must MOV the address located inside DWORD [EBP+8] into some register. Variables held inside the object include the NPC's y-velocity, x-velocity, health, damage dealt, and so on.
MOV EAX,DWORD [EBP+8]    ;Use EAX to point to the NPC object.
Here we stored the contents of DWORD [EBP+8] into EAX, so now EAX points to the NPC object. We can now use EAX to change the values of the object variables.
We can also use different registers to hold the pointer to the object. ECX and EDX are just as valid as EAX:
MOV ECX,DWORD [EBP+8]    ;Use ECX to point to the NPC object.
MOV EDX,DWORD [EBP+8]    ;Use EDX to point to the NPC object.
NPC Members
Now, the last section didn't make much sense since we haven't even done anything with the object. We just stored a pointer to a register. How is that useful?

We'll now see why we need the pointer to the NPC object. Right now, we can still use the simple definition of an object: a bag of variables. Since the NPC object acts like a bag that can hold variables, we want to change those variables (health, x-velocity, y-velocity, and so on) in order to modify how a particular type of NPC works. Variables held inside an object are called members, so whenever you see the word "members" in ASM hacking, just realize that it means "object variables".

Here are a list of members for NPCs. This is taken from the Assembly Compendium.

NPC Object Variables            Comments
+0: Event.InUse (N)             ; Is the event active? Set this to 0 to remove the NPC from the map.
+4: Event.Collision             ; Flag to show what it's colliding with
+8: Event.X (N)                 ; X-position
+C: Event.Y (N)                 ; Y-position
+10: Event.MoveX                ; X-velocity, you must add this to X-position each step
+14: Event.MoveY                ; Y-velocity, you must add this to Y-position each step
+18: Event.AltVel               ; These two are also used for velocity in some NPCs.
+1C: Event.AltVel2              ;
+20: Event.Special1             ; This is how Curly targets her enemies.
+24: Event.Special2             ;
+28: Event.NPCID (N)            ; Sprite # or Entity #, as seen in CE or SW
+2C: Event.EntityID             ; Entity ID/FlagID, as seen in CE or SW
+30: Event.EventNum             ; Event #, as seen in CE or SW
+34: Event.Tileset (N)          ; The tileset # as seen in a NPC.tbl editor
+38: Event.HurtSound (N)        ;
+3C: Event.DeathSound (N)       ;
+40: Event.Health (?)           ; Health / Damage taken
+44: Event.EXP (?)              ; EXP dropped
+48: Event.DeathGraphic         ;
+4C: Event.Direction (N)        ; Which direction the NPC is facing.
+50: Event.Flags                ; Entity flags, such as 2000 is (press down to run event)
+54: Event.Display_L (N)        ; Left side of the display rect
+58: Event.Display_U (N)        ; Top side of the display rect
+5C: Event.Display_R (N)        ; Right side of the display rect 
+60: Event.Display_D (N)        ; Bottom side of the display rect 
+64: Event.FrameTimer           ;
+68: Event.FrameNum             ;
+6C: Event.ObjectTimer          ;
+70: Event.Directive            ; Usually something from the parent.
+74: Event.ScriptState          ;
+78: Event.ScriptTimer          ;
+7C: Event.HitRect_L            ; Left side of the hitrect
+80: Event.HitRect_U            ; Top side of the hitrect
+84: Event.HitRect_R            ; Right side of the hitrect
+88: Event.HitRect_D            ; Bottom side of the hitrect
+8C: ???                        ; nonzero 1000
+90: ???                        ; nonzero 1000
+94: ???                        ; nonzero 1000
+98: ???                        ; nonzero 3000
+9C: Event.HitTrue              ; Has the entity been Hit?
+A0: ???                        ; 
+A4: Event.Damage               ; Damage dealt to Player
+A8: Event.Parent               ; It's like the ebp+8 of the parent entity.

Changing the NPC Members
In order to change the NPC members, you must remember:
  1. Store DWORD [EBP+8] into some register. This register will hold the pointer to the NPC object.
  2. Use square brackets and indirect addressing on that same register. Use an ASM command to change the value of the member.
What?!?! Okay, maybe that was a horrible explanation. I swear, looking at an example is the easiest way to understand NPC hacking.

Example 1: Increasing Velocity
MOV EDX,DWORD [EBP+8]     ;Put the NPC object pointer into EDX. Do not forget to do this.
ADD DWORD [EDX+14],100    ;Add 100 to Y-velocity. The +14 part means that [EDX+14] = Y-Velocity of NPC.
The above code will increase the Y-velocity of an NPC by 100 (hex).
Look inside the blue table and you'll see that the value +14 represents the Y-velocity variable of the NPC.

The first thing we did was store the NPC object pointer to EDX. You could have stored the object pointer into ECX or EAX, but I chose EDX for now. This allows us to modify the object's variables.

Next we ADD the hex number 100 to the memory location DWORD [EDX+14].
[EDX+14] is the same thing as the NPC's Y-velocity variable, but only if you remembered to store the object pointer inside DWORD [EBP+8] to EDX.

Since we increased the Y-velocity, the NPC will now move faster in the vertical direction.

Example 2: Changing Damage Amount
MOV EAX,DWORD [EBP+8]     ;Put the NPC object pointer into EAX.
MOV DWORD [EAX+A4],40     ;Change the damage that the enemy deals to 40 (hex) = 64 (dec).
The above code will cause the NPC to deal 64 damage to the player upon contact.

We changed the amount of damage that the NPC deals, and we did this by using EAX as our NPC object pointer. In the blue table, +A4 represents the NPC's damage power. Therefore, putting EAX+A4 inside the square brackets allows us to modify the damage.

Example 3: Making the NPC Speed Up Depending on Direction
Address    Instruction
00426CC9   MOV EAX,DWORD [EBP+8]   ;Put NPC object pointer into EAX.
00426CCC   CMP DWORD [EAX+4C],0    ;Is the NPC facing left? (direction 0 = left, direction 2 = right)
00426CD0   JE 426CD8               ;If yes, jump to the SUB DWORD [EAX+10],60 instruction.
00426CD2   ADD DWORD [EAX+10],60   ;If not, make the NPC accelerate toward the right.
00426CD6   JMP 426CDC
00426CD8   SUB DWORD [EAX+10],60   ;Make the NPC accelerate toward the left.
00426CDC   NOP
This NPC code is a bit more complicated. I used EAX as the object pointer again. Here the game checks if the NPC's direction is left or right. If the direction is left (in other words, if DWORD [EAX+4C] holds 0), then decrease the X-velocity by 60 (hex). If the direction is not left, then increase the X-velocity by 60 (hex).

When the X-velocity is positive, that means the NPC is moving toward the right. If the X-velocity is negative, the NPC is moving toward the left. By checking which direction the NPC is facing, we can make the NPC's X-velocity more negative if the NPC is facing toward the left, or more positive if the NPC is facing toward the right.

The final result: the NPC "speeds up", or accelerates in the direction in which it is facing.

Now that sounds like something a monster in a game would actually do. The monster will speed up in a certain direction, either toward you (attacking) or away from you (running away).

Of course, none of this is possible without the blue table (or the Assembly Compendium). If we look at that table, we see that +4C represents the direction of the NPC, and +10 represents the X-velocity of the NPC.

A Final Note on the NPC Object Pointer
When working with the NPC object pointer, we do not have to store the pointer to a register repeatedly. As long as we don't modify the register we're using as the object pointer, we can keep using that same register to modify an object's variables.
MOV ECX,DWORD [EBP+8]         ;Store object pointer to ECX.
MOV DWORD [ECX+8],6000        ;Change X-position to 6000 (hex).
MOV DWORD [ECX+C],10000       ;Change Y-position to 10000.
MOV DWORD [ECX+10],-200       ;Change X-velocity to -200.
MOV DWORD [ECX+14],300        ;Change Y-velocity to 300.
MOV DWORD [ECX+4C],2          ;Change direction facing to right.
Notice that after storing the object pointer to ECX, I did not have to use MOV ECX,DWORD [EBP+8] repeatedly. As long as I don't change ECX during the course of the function, ECX will still point to the NPC object, and I can still use ECX to change the NPC object's members.

Cycling Code
If an NPC is put onto a map, that NPC's code will run constantly as long as you stay on that map.
(What actually happens is that the NPC's function is CALLed repeatedly by the game).

For example, if there's a power critter present on the map, the code for the power critter is continuously run over and over again for that particular NPC.

The NPC object variables are permanent variables. That means, they'll hold the same values during each cycle of an NPC's code. So, if you store 200 to the NPC's X-velocity, that NPC will still have 200 X-velocity for the duration of its existence on that map, unless you change the X-velocity to something else using ASM code.

Navigation
Previous Lesson: NPC Hacking 1
Next Lesson: NPC Hacking 3
Table of Contents