Heavily commentated NPC code

May 26, 2013 at 3:43 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him

Some useful Examples:



Debug Cat:


Code:
offset npc216 ;replaces Debug cat
 
push ebp                          ;This starts the code
mov ebp, esp                      ;You must always do this. Or die!
;And also note that ALL NUMBER ARE IN HEX (unless otherwise stated)
;[arg-1] = [EBP+8] for referance.

;============================
;=====<///FRAMERECTS\\\>=====
;============================
SUB ESP,10                        ;10 represents the total amount of framerects. (must match the highest EBP-___)
MOV DWORD PTR SS:[EBP-10],100     ;framerects are ordered Left...
MOV DWORD PTR SS:[EBP-C],0C0      ;UP
MOV DWORD PTR SS:[EBP-8],110      ;RIGHT
MOV DWORD PTR SS:[EBP-4],0D8      ;DOWN (notice that you MUST count by four's [in hex] for your framerects).
;this gives us a sprite (4 borders)

;================================
;=====<///BEHAVIOUR CODE\\\>=====
;================================

;----RECTS----

MOV EAX,DWORD PTR SS:[EBP+8]    ;"+8" puts object pointer in EDX. NEVER FORGET TO DO THIS!
ADD EAX,54                      ;holds 54 in the EAX

MOV ECX,[EBP-10]               ;takes EBP-10 (framerect 1) and stores the value of ECX into it.
MOV [EAX],ECX                  ;takes the 54 from the EAX and adds it to the argument and runs "+54" aka Frame_L to 
                               ;recognize that it is the left side on the NPC.

MOV EDX,[EBP-C]                ;takes EBP-C (framerect 2) and stores the value of EDX into it.
MOV [EAX+4],EDX                ;adds 4 to make "+58" aka Frame_U to recognize up side of NPC

MOV ECX,[EBP-8]                ;takes EBP-8 (framerect 3) and stores the value of EDX into it.
MOV [EAX+8],ECX                ;adds 4 to make "+5C" aka Frame_R to recognize right side of NPC

MOV EDX,[EBP-4]                ;takes EBP-4 (framerect 4) and stores the value of EDX into it.
MOV [EAX+0C],EDX               ;adds 4 to make "+60" aka Frame_D to recognize down side of NPC

;==============================
;======<///END OF CODE=========
;==============================
mov esp, ebp
pop ebp
retn




Shovel Bricade:


Code:
offset 451E90     ;replaces shovel bricade.


PUSH EBP          ;As always, start of the code.
MOV EBP,ESP       ;remember all number are in HEX

;==============================
;====<///FRAMARECTS\\\>========
;==============================


SUB ESP,44        ; The number of framarects, 

                ;===sprite 0 (stand still face left do nothing)===

MOV DWORD PTR SS:[EBP-20],0          ;Left border, sprite 0 
MOV DWORD PTR SS:[EBP-1C],40         ;Up border sprite 0
MOV DWORD PTR SS:[EBP-18],10         ;Rigth border sprite 0
MOV DWORD PTR SS:[EBP-14],50         ;Bottom border sprite 0

                ;===sprite 1 (stand still face left blink)===
MOV DWORD PTR SS:[EBP-10],10         ;Left border, sprite 1   (stand still blink)
MOV DWORD PTR SS:[EBP-0C],40         ;Up border, bla bla bla...
MOV DWORD PTR SS:[EBP-8],20          ;bla bla...
MOV DWORD PTR SS:[EBP-4],50

                ;===sprite 2 (stand still face left do nothing)===
MOV DWORD PTR SS:[EBP-40],0          ;Sprite 2
MOV DWORD PTR SS:[EBP-3C],50         
MOV DWORD PTR SS:[EBP-38],10
MOV DWORD PTR SS:[EBP-34],60

                ;===sprite 3 (stand still face left blink)===
MOV DWORD PTR SS:[EBP-30],10         ;Sprite 3
MOV DWORD PTR SS:[EBP-2C],50
MOV DWORD PTR SS:[EBP-28],20
MOV DWORD PTR SS:[EBP-24],60

;================================
;=======<///BEHAVIOUR\\\>========
;================================

;-Starting up-


MOV EAX,DWORD PTR SS:[EBP+8]         ;The oh-so important NPC pointer. nessisary before putting in any action (using EAX).
MOV ECX,DWORD PTR DS:[EAX+74]        ;refering to you wonderful table of NPC's "74+" means event script state (using ECX)
MOV DWORD PTR SS:[EBP-44],ECX        ;Let's store the value of [EBP-44] (a local variable) into the ECX for use later. (along with the script state)

;-Check for <ANP's and alternate direction flags-

CMP DWORD PTR SS:[EBP-44],0          ;Compares the state of [EBP-44] to see the current value
JE :jump_lower                       ;If it's zero, let's jump lower down...

CMP DWORD PTR SS:[EBP-44],1          ;Compares the state of [EBP-44] to see the current value
JE :even_lower                       ;If it's one, let's jump even lower down...

CMP DWORD PTR SS:[EBP-44],2          ;Compares the state of [EBP-44] to see the current value
JE  :lowest                          ;If it's one, let's jump even lower down...

JMP :if_not_any                      ;What? It's not any of these numbers?!?



:jump_lower
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV DWORD PTR DS:[EDX+74],1          ;changes NPC script state to to "1" (next time it loops through we will jump straight to :even_lower becasue this is not nessisary to do this again)
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV DWORD PTR DS:[EAX+68],0          ;===NPC frame number changed to no. 0===
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through ECX)
MOV DWORD PTR DS:[ECX+64],0          ;a timer to Wait is stores through ECX

:even_lower
PUSH 78                              ;Push 78    
PUSH 0                               ;Push 0 and then...
CALL 0040F350                        ;call random number between 0 and 78, stores it into the EAX
ADD ESP,8                            ;Something that has to be done after calling a random number.
CMP EAX,0A                           ;see's if the ramdon number is 0A (10 in decimal)
JNE :if_not_any                      ;If it isn't jump...

MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV DWORD PTR DS:[EDX+74],2          ;changes NPC Scriptstate to 2 
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV DWORD PTR DS:[EAX+78],0          ;NPC script timer stored through EAX using 0
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through ECX)
MOV DWORD PTR DS:[ECX+68],1          ;===NPC frame number changed to no. 1===
JMP :if_not_any

:lowest 
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV EAX,DWORD PTR DS:[EDX+78]        ;NPC script timer stored through EAX
ADD EAX,1                            ;Add 1 to the EAX
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to ECX
MOV DWORD PTR DS:[ECX+78],EAX        ;store the Script timer to the EAX
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to EDX
CMP DWORD PTR DS:[EDX+78],8          ;compare the EDX (including the script timer thingy stored to the EDX) to 8
JLE :if_not_any                      ;If it is equal or less then 8, jump...

MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to EAX
MOV DWORD PTR DS:[EAX+74],1          ;add 1 to Scriptstate
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to ECX
MOV DWORD PTR DS:[ECX+68],0          ;changes frame number to 0

:if_not_any
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
CMP DWORD PTR DS:[EDX+4C],0          ;Compares direction of NPC to 0 (left)
JNE :direction_not_zero

;-blink face left-
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV ECX,DWORD PTR DS:[EAX+68]        ;Changes frame number to ECX's current number.
SHL ECX,4                            ;SHL Shifts the value of the ECX 4 times.
LEA EDX,[ECX+EBP-20]                 ;put's ECX's number and [EPB-40] into EDX. (changes blink to previous sprite) done blink
MOV EAX,DWORD PTR SS:[EBP+8]         ;we went over this with the debug cat, makes the game realise the border of the sprites....
ADD EAX,54                           ;add 54 to EAX
MOV ECX,DWORD PTR DS:[EDX]           ;EDX is 54 "Frame left"
MOV DWORD PTR DS:[EAX],ECX
MOV ECX,DWORD PTR DS:[EDX+4]         ;EDX+4 is 58 "frame up"
MOV DWORD PTR DS:[EAX+4],ECX
MOV ECX,DWORD PTR DS:[EDX+8]         ;EDX+8 is 5C "frame right"
MOV DWORD PTR DS:[EAX+8],ECX
MOV EDX,DWORD PTR DS:[EDX+0C]        ;EDX+0C is 60 "frame bottom"
MOV DWORD PTR DS:[EAX+0C],EDX        ;then we end the code.
JMP :end_of_code

;-blink face right-
:direction_not_zero
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV ECX,DWORD PTR DS:[EAX+68]        ;Changes frame number to ECX's current number.
SHL ECX,4                            ;SHL Shifts the value of the ECX 4 times.
LEA EDX,[ECX+EBP-40]                 ;put's ECX's number and [EPB-40] into EDX.(changes blink to previous sprite)

MOV EAX,DWORD PTR SS:[EBP+8]         ;we went over this with the debug cat, makes the game realise the border of the sprites....
ADD EAX,54                           ;add 54 to EAX
MOV ECX,DWORD PTR DS:[EDX]           ;EDX is 54 "Frame left"
MOV DWORD PTR DS:[EAX],ECX           
MOV ECX,DWORD PTR DS:[EDX+4]         ;EDX+4 is 58 "frame up"
MOV DWORD PTR DS:[EAX+4],ECX         
MOV ECX,DWORD PTR DS:[EDX+8]         ;EDX+8 is 5C "frame right"
MOV DWORD PTR DS:[EAX+8],ECX
MOV EDX,DWORD PTR DS:[EDX+0C]        ;EDX+0C is 60 "frame bottom"
MOV DWORD PTR DS:[EAX+0C],EDX        

;=================================
;=======<///END OF CODE\\\>=======
;=================================

:end_of_code
MOV ESP,EBP                          ;That wasn't so bad.
POP EBP                  
RETN




Purple Critter:


Code:
offset 444930         

PUSH EBP                   ;Alright, the third and final test.
MOV EBP,ESP                ;Let's go.
 
SUB ESP,0D8                        ;Framarect/local variable counter 

              ;-Sprite 1 Idle face left-
MOV DWORD PTR SS:[EBP-68],0        ;Left border
MOV DWORD PTR SS:[EBP-64],60       ;Up border
MOV DWORD PTR SS:[EBP-60],10       ;Right border
MOV DWORD PTR SS:[EBP-5C],70       ;Down border

              ;-Sprite 2 alert face left-
MOV DWORD PTR SS:[EBP-58],10
MOV DWORD PTR SS:[EBP-54],60
MOV DWORD PTR SS:[EBP-50],20
MOV DWORD PTR SS:[EBP-4C],70

              ;-Sprite 3 jumping face left-
MOV DWORD PTR SS:[EBP-48],20
MOV DWORD PTR SS:[EBP-44],60
MOV DWORD PTR SS:[EBP-40],30
MOV DWORD PTR SS:[EBP-3C],70

              ;-Sprite 4 flying 1 face left-
MOV DWORD PTR SS:[EBP-38],30
MOV DWORD PTR SS:[EBP-34],60
MOV DWORD PTR SS:[EBP-30],40
MOV DWORD PTR SS:[EBP-2C],70

              ;-Sprite 5 flying 2 face left-
MOV DWORD PTR SS:[EBP-28],40
MOV DWORD PTR SS:[EBP-24],60
MOV DWORD PTR SS:[EBP-20],50
MOV DWORD PTR SS:[EBP-1C],70

              ;-Sprite 6 flying 3 face left-
MOV DWORD PTR SS:[EBP-18],50
MOV DWORD PTR SS:[EBP-14],60
MOV DWORD PTR SS:[EBP-10],60
MOV DWORD PTR SS:[EBP-0C],70

              ;-Sprite 7 Idle face right-
MOV DWORD PTR SS:[EBP-0D0],0
MOV DWORD PTR SS:[EBP-0CC],70
MOV DWORD PTR SS:[EBP-0C8],10
MOV DWORD PTR SS:[EBP-0C4],80

              ;-Sprite 8 alert face right-
MOV DWORD PTR SS:[EBP-0C0],10
MOV DWORD PTR SS:[EBP-0BC],70
MOV DWORD PTR SS:[EBP-0B8],20
MOV DWORD PTR SS:[EBP-0B4],80

              ;-Sprite 9 jumping face right-
MOV DWORD PTR SS:[EBP-0B0],20
MOV DWORD PTR SS:[EBP-0AC],70
MOV DWORD PTR SS:[EBP-0A8],30
MOV DWORD PTR SS:[EBP-0A4],80

              ;-Sprite 10 flying 1 face right-
MOV DWORD PTR SS:[EBP-0A0],30
MOV DWORD PTR SS:[EBP-9C],70
MOV DWORD PTR SS:[EBP-98],40
MOV DWORD PTR SS:[EBP-94],80

              ;-Sprite 11 flying 2 face right-
MOV DWORD PTR SS:[EBP-90],40
MOV DWORD PTR SS:[EBP-8C],70
MOV DWORD PTR SS:[EBP-88],50
MOV DWORD PTR SS:[EBP-84],80

              ;-Sprite 12 flying 3 face right-
MOV DWORD PTR SS:[EBP-80],50
MOV DWORD PTR SS:[EBP-7C],70
MOV DWORD PTR SS:[EBP-78],60
MOV DWORD PTR SS:[EBP-74],80

MOV EAX,DWORD PTR SS:[EBP+8]          ;NPC pointer
MOV ECX,DWORD PTR DS:[EAX+74]         ;Script State
MOV DWORD PTR SS:[EBP-0D8],ECX        ;add the scriptstate to the local variable. 
CMP DWORD PTR SS:[EBP-0D8],5          ;compare to 5.
JA :if_var_equal                      ;Jump on down.

MOV EDX,DWORD PTR SS:[EBP-0D8]        ;Move the variable to the EDX
JMP DWORD PTR DS:[EDX*4+445035]       ;jump to the critter state table, pending on the scriptstate stored in EDX, it will jump to the corosponding address. 


MOV EAX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+0C]         ;Load Y position of NPC to ECX
ADD ECX,600                           ;this changes the Y position by 3 pixels
MOV EDX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (edx)
MOV DWORD PTR DS:[EDX+0C],ECX         ;add ECX to Y position.
MOV EAX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (eax)
MOV DWORD PTR DS:[EAX+74],1           ;Make the script state 1
MOV ECX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (ecx)
CMP DWORD PTR DS:[ECX+78],8           ;Is our script timer 8?
JL SHORT :if_less_then_8              ;If less, JUMP
MOV EDX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+8]          ;check the X position of the critter
SUB EAX,0C000                         ;this
CMP EAX,DWORD PTR DS:[49E654]         ;compare the critters X position (stored in EAX) to Quotes Position (address 49E654) .       
JGE SHORT :if_less_then_8             ;If higer (Quote is to far away) JUMP
MOV ECX,DWORD PTR SS:[EBP+8]          ;otherwise, set pointer
MOV EDX,DWORD PTR DS:[ECX+8]          ;and load X position
ADD EDX,0C000                         ;this sees if critter is less then C000 [200 = 1 pixel] or 60 pixels to the right of Quote
CMP EDX,DWORD PTR DS:[49E654]         ;compare the critters X position (stored in EDX) to Quotes Position (address 49E654) . 
JLE SHORT :if_less_then_8             ;If less JUMP
MOV EAX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+0C]         ;move the Y position of critter to ECX
SUB ECX,0C000                         ;this sees if critter is less then C000 [200 = 1 pixel] or 60 pixels to the left of Quote
CMP ECX,DWORD PTR DS:[49E658]         ;CMP ECX to Player Y position (in Pixels)
JGE SHORT :if_less_then_8             ;If greater Jump
MOV EDX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+0C]         ;load the Y position of the critter to EAX 
ADD EAX,4000                          ;add 4000 to EAX
CMP EAX,DWORD PTR DS:[49E658]         ;again compare ECX to Player Y position (in Pixels)
JLE SHORT :if_less_then_8             ;if less or equal jump

         ;checks if it's to the left or right of Quote.
MOV ECX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (eCx)
MOV EDX,DWORD PTR DS:[ECX+8]          ;load the X position of the critter to EAX
CMP EDX,DWORD PTR DS:[49E654]         ;compare ECX to Player X position (in Pixels)
JLE SHORT :a_little_lower             ;If less or equal jump
MOV EAX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (eax)
MOV DWORD PTR DS:[EAX+4C],0           ;make direction 0 (becasue the above calculation tell us that Quote is to the left of the Critter)
JMP SHORT :direction_0                ;JUMP

:a_little_lower
MOV ECX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+4C],2           ;make direction "2"

:direction_0
MOV EDX,DWORD PTR SS:[EBP+8]          ;set up dat pointer! (edx)
MOV DWORD PTR DS:[EDX+68],1           ;Change frame number to no.1 (idle, face left)
JMP SHORT :end_frame_change


           ;-----Alert-------

:if_less_then_8
MOV EAX,DWORD PTR SS:[EBP+8]       ;Pointer set.
CMP DWORD PTR DS:[EAX+78],8        ;See if script timer is 8
JGE SHORT :down_there              ;This time if higher JUMP
MOV ECX,DWORD PTR SS:[EBP+8]       ;Number must be 8 (set pointer)
MOV EDX,DWORD PTR DS:[ECX+78]      ;Set script timer
ADD EDX,1                          ;add 1 to the EDX (why not INC EDX?)
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV DWORD PTR DS:[EAX+78],EDX      ;make whatever is in the EDX the script timer number (the <WAI period)

:down_there
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+68],0        ;this changes the frame number to no. 0

:end_frame_change
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOVZX EAX,BYTE PTR DS:[EDX+9C]     ;See if entity is hit, [0 = not] [1= hit] (only a bite is required to see if 1 or 0)
TEST EAX,EAX                       ;same as CMP EAX,0
JE SHORT :if_hit_not_true          ;if 1 Jump
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)    
MOV DWORD PTR DS:[ECX+74],2        ;change script state to 2
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)  
MOV DWORD PTR DS:[EDX+68],0        ;change frame number to 0
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax) 
MOV DWORD PTR DS:[EAX+78],0        ;change script timer to 0

:if_hit_not_true
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)  
CMP DWORD PTR DS:[ECX+78],8        ;compare script timer to 8
JL SHORT :jump_and_fly             ;if less, jump... to another jump...
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+8]       ;move value of EAX to critter X position
SUB EAX,6000                       ;this sees if critter is less then 6000 [200 = 1 pixel] or 48 pixels away from Quote's left side.
CMP EAX,DWORD PTR DS:[49E654]      ;compare X position to Quotes X position
JGE SHORT :jump_and_fly            ;if greater or equal jump
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx) 
MOV EDX,DWORD PTR DS:[ECX+8]       ;Move the EDX to critter X position
ADD EDX,6000                       ;this sees if critter is less then 6000 [200 = 1 pixel] or 48 pixels away from Quote's right side.
CMP EDX,DWORD PTR DS:[49E654]      ;Compare EDX to X position
JLE SHORT :jump_and_fly            ;if less or equal jump
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+0C]      ;move value of ECX to critter Y position
SUB ECX,0C000                      ;this sees if critter is less then C000 [200 = 1 pixel] or 60 pixels above Quote
CMP ECX,DWORD PTR DS:[49E658]      ;compare Y position to Quotes Y position
JGE SHORT :jump_and_fly            ;if higher or equal jump
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+0C]      ;move value of EAX to critter Y position
ADD EAX,4000                       ;this sees if critter is less then 4000 [200 = 1 pixel] or 20 pixels below Quote
CMP EAX,DWORD PTR DS:[49E658]      ;compare to Quote's Y position
JLE SHORT :jump_and_fly            ;If less or Equal, jump
MOV ECX,DWORD PTR SS:[EBP+8]       ;If we got past all thoese hurdals....
MOV DWORD PTR DS:[ECX+74],2        ;change script state to two
MOV EDX,DWORD PTR SS:[EBP+8]      
MOV DWORD PTR DS:[EDX+68],0        ;frame number to 0
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EAX+78],0        ;and script timer to 0
JMP :if_var_equal


            ;----FLY FLY FLY!------

:jump_and_fly  
MOV ECX,DWORD PTR SS:[EBP+8]
MOV EDX,DWORD PTR DS:[ECX+78]      ;set script timer to EDX
ADD EDX,1                          ;INC EAX,1  pending on if it was facing left or right, increses frame number to the right sprite.
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV DWORD PTR DS:[EAX+78],EDX      ;move EDX to sprite number.
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
CMP DWORD PTR DS:[ECX+78],8        ;is sprite number 8?
JLE SHORT :Direction_zero          ;jump to another jump
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+74],3        ;change scriptstate to 3
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV DWORD PTR DS:[EAX+68],2        ;change frame number to two
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+14],-5FF     ;Change Y velocity to negative -5FF
PUSH 1                             ;Push 1
PUSH 1E                            ;Push 1E
CALL 00420640                      ;play sound 1E (mandatory to push 1 beforehand)
ADD ESP,8                          ;for every push we need to ADD 4 to the ESP
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+8]       ;move position X of crit to EAX
CMP EAX,DWORD PTR DS:[49E654]      ;Compare to Quotes X position
JLE SHORT :down_three_lines        ;if lessor equal, Jump
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+4C],0        ;change direction to 0
JMP SHORT :Direction_zero

:down_three_lines
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+4C],2        ;change direction to 2

:Direction_zero
JMP 00444EF4
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
CMP DWORD PTR DS:[EAX+14],100      ;compare Y velocity to 100 [falling]
JLE SHORT :if_var_equal            ;If less or equal, jump
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+0C]      ;move Y pos to EAX
MOV DWORD PTR DS:[ECX+24],EAX      ;Set Curly's targeting area for Y position [X pos in not required becasue the entity does not move left/right]
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+74],4        ;Change script state to 4
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+68],3        ;change frame number to 3
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV DWORD PTR DS:[EAX+78],0        ;change script timer to 0
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+78],0        ;change script timer to 0 again?
JMP :if_var_equal

MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+8]       ;Move X position to EAX
CMP EAX,DWORD PTR DS:[49E654]      ;compare with Quotes X position
JGE SHORT :is_zero                 ;If greater or equal
MOV ECX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+4C],2        ;Change direction of critter to two
JMP SHORT :is_two                  ;Jump

:is_zero
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+4C],0        ;Change direction of critter to zero

:is_two 
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+78]      ;move value of ECX to script timer
ADD ECX,1                          ;INC EAX
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+78],ECX      ;move script state to ECX
MOV EAX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+4]       ;see if it is colliding with cealing
AND ECX,00000007                   ;sets some asm flags that I can't comprehend
JNE SHORT :JNZ                     ;if flag zero is not set, jump
MOV EDX,DWORD PTR SS:[EBP+8]       ;set dat pointer! (edx)
CMP DWORD PTR DS:[EDX+78],3C       ;Is script timer less then 3C?
JLE SHORT :timer_less_then_3C      ;if yes, jump

:JNZ
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EAX+0A4],3
MOV ECX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[ECX+74],5
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+68],2
JMP :if_var_equal

:timer_less_then_3C 
MOV EAX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+78]    ;Store script state to ECX
AND ECX,80000003                 ;Sets sign flag if EAX is high/low enough
JNS SHORT 00444D86               ;Jump if sign flag is clear
DEC ECX                          ;REmove 1 from ECX
OR ECX,FFFFFFFC                  ;set's a asm flag, maybe
INC ECX                          ;add 1 to ECX
CMP ECX,1                        ;see if the number is one (remember that FFFFFFFE + 2 = 1
JNE SHORT :sound_done               
PUSH 1                           ;Push 1
PUSH 6D                          ;Push 6D
CALL 00420640                    ;play sound 6D (critter jumping)
ADD ESP,8                        ;we pushed twice and 4 + 4 = 8 so ADD ESP, 8

:sound_done
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+4]     ;store collision data to EAX
AND EAX,00000008                 ;set some flags if the EAX is at the right number
JE SHORT :Vel_Set_done           ;if it is the undesired number, jump
MOV ECX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+14],-200   ;set Y velocity to -200

:Vel_Set_done
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+78]    ;move value of EDX to script timer
CDQ                              ;makes EDX:EAX
MOV ECX,1E                       ;Move 1E into ECX
IDIV ECX                         ;divide ECX by EDX:EAX
CMP EDX,6                        ;EDX holds the remander, compare to 6
JNE :remiander_not_6             ;if it's not equal, jump
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+0C]    ;move Y position to EAX
SUB EAX,DWORD PTR DS:[49E658]    ;Subtract Quote's Y from EAX
PUSH EAX                         ;Push EAX onto stack
MOV ECX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (ecx)
MOV EDX,DWORD PTR DS:[ECX+8]     ;Move crit's X position to EDX
SUB EDX,DWORD PTR DS:[49E654]    ;Subtract Quote's X from Crit's X position
PUSH EDX                         ;Push EDX onto stack.
CALL 004258E0                    ;Detects player collision
ADD ESP,8                        ;we pushed twice and 4 + 4 = 8 so ADD ESP, 8
MOV BYTE PTR SS:[EBP-1],AL       ;move the value of AL to the local variable.
PUSH 6                           ;push 6
PUSH -6                          ;push -6 
CALL 0040F350                    ;Random number (stored in EAX) changes the angle that the critter proj will fire.
ADD ESP,8                        ;We pushed twice and 4 + 4 = 8 so ADD ESP, 8
MOVZX EAX,AL                     ;stores value of AL to EAX? (the start point and destination are the same?)
MOVZX ECX,BYTE PTR SS:[EBP-1]    ;move value of local variable to ECX
ADD ECX,EAX                      ;add EAX to ECX
MOV BYTE PTR SS:[EBP-1],CL       ;move the value of CL to the local variable 
MOV DL,BYTE PTR SS:[EBP-1]       ;and then move it to DL
PUSH EDX                         
CALL 004258B0                    ;call sin table (has to do with angle the crit projectile is fired at)
ADD ESP,4                        ;we already went over this part
IMUL EAX,EAX,3                   ;multiply EAX by 3, store answer into EAX
MOV DWORD PTR SS:[EBP-0D4],EAX   ;move the answer into this local variable
MOV AL,BYTE PTR SS:[EBP-1]       ;move the value of thie local variable to AL
PUSH EAX                         
CALL 004258C0                    ;call cos table( has to do with angle the crit projectile is fired at)
ADD ESP,4                        ;We already went over this.
IMUL EAX,EAX,3                   ;read above.
MOV DWORD PTR SS:[EBP-6C],EAX    ;store answer to this local variable
PUSH 100                                
PUSH 0                              
PUSH 0                             
MOV ECX,DWORD PTR SS:[EBP-0D4]   ;store the value of local variable to ECX
PUSH ECX                              
MOV EDX,DWORD PTR SS:[EBP-6C]    ;store the value of local var to EDX
PUSH EDX                              
MOV EAX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+0C]    ;store Y position of Crit to ECX
PUSH ECX                      
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+8]     ;store X position of Crit to EAX
PUSH EAX                             
PUSH 94                               
CALL 0046EFD0                    ;create NPC using above specs 
ADD ESP,20
PUSH 1                                 
PUSH 27                              
CALL 00420640                    ;play sound 27 [*bving*]
ADD ESP,8

:remiander_not_6
MOV ECX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (ecx)
MOV EDX,DWORD PTR DS:[ECX+64]    ;set frame timer into EDX
ADD EDX,1                        ;INC EDX
MOV EAX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (eax)
MOV DWORD PTR DS:[EAX+64],EDX    ;set frame timer to value of EDX
MOV ECX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (ecx)
CMP DWORD PTR DS:[ECX+64],0      ;is frame timer 0?
JLE SHORT :cat's_are_cool        ;if 0 or less, jump
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+64],0      ;change frame timer to 0
MOV EAX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (eax)
MOV ECX,DWORD PTR DS:[EAX+68]    ;move frame number to ECX
ADD ECX,1                        ;add 1
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV DWORD PTR DS:[EDX+68],ECX    ;store it back frame number

:cat's_are_cool 
MOV EAX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (eax)
CMP DWORD PTR DS:[EAX+68],5      ;is frame number 5?
JLE SHORT :is_less_then_5        ;if less or equal to 5 jump
MOV ECX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (ecx)
MOV DWORD PTR DS:[ECX+68],3      ;change frame number to 3
JMP SHORT :if_var_equal

:is_less_then_5 
MOV EDX,DWORD PTR SS:[EBP+8]     ;set dat pointer! (edx)
MOV EAX,DWORD PTR DS:[EDX+4]     ;check for collision.
AND EAX,00000008                 ;set asm flags
JE SHORT :if_var_equal           ;jump if right number
MOV ECX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[ECX+0A4],2     ;collision with entity has happened, quote takes 2 damamge
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+10],0      ;change critter vel to 0
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EAX+78],0      ;script timer to 0
MOV ECX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[ECX+68],0      ;frame number to 0
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+74],1      ;and script state to 1
PUSH 1                                   
PUSH 17                                  
CALL 00420640                    ;Play sound 17 [hex]
ADD ESP,8

:if_var_equal
MOV EAX,DWORD PTR SS:[EBP+8]               
CMP DWORD PTR DS:[EAX+74],4                ;compare the script state to 4
JE SHORT :if_four
MOV ECX,DWORD PTR SS:[EBP+8]               
MOV EDX,DWORD PTR DS:[ECX+14]              ;set EDX to NPC Y velocity
ADD EDX,20                                 ;add 20 to Y velocity
MOV EAX,DWORD PTR SS:[EBP+8]               
MOV DWORD PTR DS:[EAX+14],EDX              ;set Y velocity through EAX, Y vel is EDX
MOV ECX,DWORD PTR SS:[EBP+8]               
CMP DWORD PTR DS:[ECX+14],5FF              ;compare 5FF to the Y vel
JLE SHORT :less_then_5FF
MOV EDX,DWORD PTR SS:[EBP+8]               
MOV DWORD PTR DS:[EDX+14],5FF              ;make sure that it stays at 5FF
:less_then_5FF
JMP :near_bottom

:if_four
MOV EAX,DWORD PTR SS:[EBP+8]
MOV ECX,DWORD PTR SS:[EBP+8]
MOV EDX,DWORD PTR DS:[EAX+0C]    ;store Y pos ot EDX
CMP EDX,DWORD PTR DS:[ECX+24]    ;Compare to Curly targeting Y
JLE SHORT :Curly_target_off
MOV EAX,DWORD PTR SS:[EBP+8]
MOV ECX,DWORD PTR DS:[EAX+14]    ;move Y vel to ECX
SUB ECX,10                       ;subtract ten from it. [keeps it suspended in air]
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+14],ECX    ;store it back to the velocity
JMP SHORT :Velocity_set

:Curly_target_off
MOV EAX,DWORD PTR SS:[EBP+8]
MOV ECX,DWORD PTR DS:[EAX+14]    ;move Y vel to ECX
ADD ECX,10                       ;add 10
MOV EDX,DWORD PTR SS:[EBP+8]    
MOV DWORD PTR DS:[EDX+14],ECX    ;put it back in to Velocity

:Velocity_set
MOV EAX,DWORD PTR SS:[EBP+8]
CMP DWORD PTR DS:[EAX+14],200    ;compare the Y vel to 200
JLE SHORT :less_then_200         ;if less or equal jump
MOV ECX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[ECX+14],200    ;store 200 to Y velocity

:less_then_200
MOV EDX,DWORD PTR SS:[EBP+8]
CMP DWORD PTR DS:[EDX+14],-200   ;compare the vel to -200
JGE SHORT :more_then_200         ;if greater or equal jump
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EAX+14],-200   ;store -200 to Y vel

:more_then_200
MOV ECX,DWORD PTR SS:[EBP+8]
CMP DWORD PTR DS:[ECX+10],200    ;see if X vel is 200
JLE SHORT :catZ
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+10],200    ;store 200 to X vel

:catZ
MOV EAX,DWORD PTR SS:[EBP+8]
CMP DWORD PTR DS:[EAX+10],-200   ;see if X vel is -200
JGE SHORT :near_bottom
MOV ECX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[ECX+10],-200   ;store -200 to X vel

:near_bottom
MOV EDX,DWORD PTR SS:[EBP+8]
MOV EAX,DWORD PTR DS:[EDX+8]     ;make EAX to X pos
MOV ECX,DWORD PTR SS:[EBP+8]
ADD EAX,DWORD PTR DS:[ECX+10]    ;add EAX to X vel
MOV EDX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EDX+8],EAX     ;add EAX to X pos
MOV EAX,DWORD PTR SS:[EBP+8]
MOV ECX,DWORD PTR DS:[EAX+0C]    ;mov Y pos to eax
MOV EDX,DWORD PTR SS:[EBP+8]
ADD ECX,DWORD PTR DS:[EDX+14]    ;add Y vel tp EAX
MOV EAX,DWORD PTR SS:[EBP+8]
MOV DWORD PTR DS:[EAX+0C],ECX    ;move value of ECX to Y pos
MOV ECX,DWORD PTR SS:[EBP+8]
CMP DWORD PTR DS:[ECX+4C],0      ;is direction 0?
JNE SHORT :end_face_right

                     ;-Makes Game recognize sprite borders-

MOV EDX,DWORD PTR SS:[EBP+8]           ;We went over this with the debug cat.  
MOV EAX,DWORD PTR DS:[EDX+68]          ;And I'm to lazy to re-write this out.
SHL EAX,4                              ;Oh yeah, and this is if the NPc is facing left.
LEA ECX,[EAX+EBP-68]
MOV EDX,DWORD PTR SS:[EBP+8]
ADD EDX,54
MOV EAX,DWORD PTR DS:[ECX]
MOV DWORD PTR DS:[EDX],EAX
MOV EAX,DWORD PTR DS:[ECX+4]
MOV DWORD PTR DS:[EDX+4],EAX
MOV EAX,DWORD PTR DS:[ECX+8]
MOV DWORD PTR DS:[EDX+8],EAX
MOV ECX,DWORD PTR DS:[ECX+0C]
MOV DWORD PTR DS:[EDX+0C],ECX
JMP SHORT :end_of_code

:end_face_right
MOV EDX,DWORD PTR SS:[EBP+8]           ;We went over this with the debug cat.
MOV EAX,DWORD PTR DS:[EDX+68]          ;And I'm to lazy to re-write this out.
SHL EAX,4                              ;Oh yeah, and this is if the NPc is facing right.
LEA ECX,[EAX+EBP-0D0]
MOV EDX,DWORD PTR SS:[EBP+8]
ADD EDX,54
MOV EAX,DWORD PTR DS:[ECX]
MOV DWORD PTR DS:[EDX],EAX
MOV EAX,DWORD PTR DS:[ECX+4]
MOV DWORD PTR DS:[EDX+4],EAX
MOV EAX,DWORD PTR DS:[ECX+8]
MOV DWORD PTR DS:[EDX+8],EAX
MOV ECX,DWORD PTR DS:[ECX+0C]
MOV DWORD PTR DS:[EDX+0C],ECX

:end_of_code
MOV ESP,EBP                    ;End
POP EBP                        ;Of Code
RETN




old useless post:


I think this question is complicated enough to have it's own thread. How do I hack my own NPC into cave story? All I want (for now) is just a very simple npc that basically a carbon copy of Momorin. It stands around, blinks, and has one animation sprite (shocked). :momo:





here is what I've got


PUSH EBP

MOV EBP, ESP



ze' framarects.



actual coding



MOV ESP, EBP

POP EBP

RETN





here are my questions:



What address do I start at?



How do I make my own framarects?



Is it really as a simple as



MOV DWORD PTR SS: [LOCAL.--],--



and do I need to define what .bmp image the game draws the sprite from?





Do I just copy/ paste momo's coding? (I prefer to write it out to know exactly what the coding is applying)





Will CE or BL realize the newly added entity?





And please don't just shove this off as "oh, you can learn this latter" or "you need more skill" I want to learn it now, and learn it well.


 
May 26, 2013 at 4:28 PM
Professional Whatever
"Life begins and ends with Nu."
Join Date: Jan 13, 2011
Location: Lasagna
Posts: 4481
Pronouns: she/her
For the love of god we have a thread for this use it
 
May 26, 2013 at 4:33 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
MagicDoors said:
For the love of --- we have a thread for this use it
You mean this thread?

NPC Hacking

That doesn't answer my questions.
 
May 26, 2013 at 5:24 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Pronouns: he/him
If you are really serious about this, then imo the best way to understand how to write your own NPC code is to examine and understand the ones that already exist. So I'm going to give you a few exercises.

Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
004517F0  /$  55            push ebp
004517F1  |.  8BEC          mov ebp,esp
004517F3  |.  83EC 10       sub esp,10
004517F6  |.  C745 F0 00010 mov dword ptr [local.4],100
004517FD  |.  C745 F4 C0000 mov dword ptr [local.3],0C0
00451804  |.  C745 F8 10010 mov dword ptr [local.2],110
0045180B  |.  C745 FC D8000 mov dword ptr [local.1],0D8
00451812  |.  8B45 08       mov eax,[arg.1]
00451815  |.  83C0 54       add eax,54
00451818  |.  8B4D F0       mov ecx,[local.4]
0045181B  |.  8908          mov [eax],ecx
0045181D  |.  8B55 F4       mov edx,[local.3]
00451820  |.  8950 04       mov [eax+4],edx
00451823  |.  8B4D F8       mov ecx,[local.2]
00451826  |.  8948 08       mov [eax+8],ecx
00451829  |.  8B55 FC       mov edx,[local.1]
0045182C  |.  8950 0C       mov [eax+0C],edx
0045182F  |.  8BE5          mov esp,ebp
00451831  |.  5D            pop ebp
00451832  \.  C3            retn
This is the code for the debug cat. It is possibly the simplest entity I can think of to give as an example. It has one frame and does absolutely nothing. Comment every line of code and tell me what it does.

Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00451E90  /$  55            push ebp
00451E91  |.  8BEC          mov ebp,esp
00451E93  |.  83EC 44       sub esp,44
00451E96  |.  C745 E0 00000 mov dword ptr [local.8],0
00451E9D  |.  C745 E4 40000 mov dword ptr [local.7],40
00451EA4  |.  C745 E8 10000 mov dword ptr [local.6],10
00451EAB  |.  C745 EC 50000 mov dword ptr [local.5],50
00451EB2  |.  C745 F0 10000 mov dword ptr [local.4],10
00451EB9  |.  C745 F4 40000 mov dword ptr [local.3],40
00451EC0  |.  C745 F8 20000 mov dword ptr [local.2],20
00451EC7  |.  C745 FC 50000 mov dword ptr [local.1],50
00451ECE  |.  C745 C0 00000 mov dword ptr [local.16],0
00451ED5  |.  C745 C4 50000 mov dword ptr [local.15],50
00451EDC  |.  C745 C8 10000 mov dword ptr [local.14],10
00451EE3  |.  C745 CC 60000 mov dword ptr [local.13],60
00451EEA  |.  C745 D0 10000 mov dword ptr [local.12],10
00451EF1  |.  C745 D4 50000 mov dword ptr [local.11],50
00451EF8  |.  C745 D8 20000 mov dword ptr [local.10],20
00451EFF  |.  C745 DC 60000 mov dword ptr [local.9],60
00451F06  |.  8B45 08       mov eax,[arg.1]
00451F09  |.  8B48 74       mov ecx,[eax+74]
00451F0C  |.  894D BC       mov [local.17],ecx
00451F0F  |.  837D BC 00    cmp dword ptr [local.17],0
00451F13  |.  74 0E         je short 00451F23
00451F15  |.  837D BC 01    cmp dword ptr [local.17],1
00451F19  |.  74 26         je short 00451F41
00451F1B  |.  837D BC 02    cmp dword ptr [local.17],2
00451F1F  |.  74 51         je short 00451F72
00451F21  |.  EB 7B         jmp short 00451F9E
00451F23  |>  8B55 08       mov edx,[arg.1]
00451F26  |.  C742 74 01000 mov dword ptr [edx+74],1
00451F2D  |.  8B45 08       mov eax,[arg.1]
00451F30  |.  C740 68 00000 mov dword ptr [eax+68],0
00451F37  |.  8B4D 08       mov ecx,[arg.1]
00451F3A  |.  C741 64 00000 mov dword ptr [ecx+64],0
00451F41  |>  6A 78         push 78                                  ; /Arg2 = 78
00451F43  |.  6A 00         push 0                                   ; |Arg1 = 0
00451F45  |.  E8 06D4FBFF   call 0040F350                            ; \Doukutsu_-_Copy.0040F350
00451F4A  |.  83C4 08       add esp,8
00451F4D  |.  83F8 0A       cmp eax,0A
00451F50  |.  75 1E         jne short 00451F70
00451F52  |.  8B55 08       mov edx,[arg.1]
00451F55  |.  C742 74 02000 mov dword ptr [edx+74],2
00451F5C  |.  8B45 08       mov eax,[arg.1]
00451F5F  |.  C740 78 00000 mov dword ptr [eax+78],0
00451F66  |.  8B4D 08       mov ecx,[arg.1]
00451F69  |.  C741 68 01000 mov dword ptr [ecx+68],1
00451F70  |>  EB 2C         jmp short 00451F9E
00451F72  |>  8B55 08       mov edx,[arg.1]
00451F75  |.  8B42 78       mov eax,[edx+78]
00451F78  |.  83C0 01       add eax,1
00451F7B  |.  8B4D 08       mov ecx,[arg.1]
00451F7E  |.  8941 78       mov [ecx+78],eax
00451F81  |.  8B55 08       mov edx,[arg.1]
00451F84  |.  837A 78 08    cmp dword ptr [edx+78],8
00451F88  |.  7E 14         jle short 00451F9E
00451F8A  |.  8B45 08       mov eax,[arg.1]
00451F8D  |.  C740 74 01000 mov dword ptr [eax+74],1
00451F94  |.  8B4D 08       mov ecx,[arg.1]
00451F97  |.  C741 68 00000 mov dword ptr [ecx+68],0
00451F9E  |>  8B55 08       mov edx,[arg.1]
00451FA1  |.  837A 4C 00    cmp dword ptr [edx+4C],0
00451FA5  |.  75 2B         jne short 00451FD2
00451FA7  |.  8B45 08       mov eax,[arg.1]
00451FAA  |.  8B48 68       mov ecx,[eax+68]
00451FAD  |.  C1E1 04       shl ecx,4
00451FB0  |.  8D540D E0     lea edx,[ecx+ebp-20]
00451FB4  |.  8B45 08       mov eax,[arg.1]
00451FB7  |.  83C0 54       add eax,54
00451FBA  |.  8B0A          mov ecx,[edx]
00451FBC  |.  8908          mov [eax],ecx
00451FBE  |.  8B4A 04       mov ecx,[edx+4]
00451FC1  |.  8948 04       mov [eax+4],ecx
00451FC4  |.  8B4A 08       mov ecx,[edx+8]
00451FC7  |.  8948 08       mov [eax+8],ecx
00451FCA  |.  8B52 0C       mov edx,[edx+0C]
00451FCD  |.  8950 0C       mov [eax+0C],edx
00451FD0  |.  EB 29         jmp short 00451FFB
00451FD2  |>  8B45 08       mov eax,[arg.1]
00451FD5  |.  8B48 68       mov ecx,[eax+68]
00451FD8  |.  C1E1 04       shl ecx,4
00451FDB  |.  8D540D C0     lea edx,[ecx+ebp-40]
00451FDF  |.  8B45 08       mov eax,[arg.1]
00451FE2  |.  83C0 54       add eax,54
00451FE5  |.  8B0A          mov ecx,[edx]
00451FE7  |.  8908          mov [eax],ecx
00451FE9  |.  8B4A 04       mov ecx,[edx+4]
00451FEC  |.  8948 04       mov [eax+4],ecx
00451FEF  |.  8B4A 08       mov ecx,[edx+8]
00451FF2  |.  8948 08       mov [eax+8],ecx
00451FF5  |.  8B52 0C       mov edx,[edx+0C]
00451FF8  |.  8950 0C       mov [eax+0C],edx
00451FFB  |>  8BE5          mov esp,ebp
00451FFD  |.  5D            pop ebp
00451FFE  \.  C3            retn
Here's the shovel brigade. Only slightly more complicated, I think they blink and turn to face you. But I could be wrong. Comment it and show me what the code does and how it works, you don't need to do *every* line but if it helps you then go to town. Understanding this one should be enough to make the NPC you want.
Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00444930  /$  55            push ebp
00444931  |.  8BEC          mov ebp,esp
00444933  |.  81EC D8000000 sub esp,0D8
00444939  |.  C745 98 00000 mov dword ptr [ebp-68],0
00444940  |.  C745 9C 60000 mov dword ptr [ebp-64],60
00444947  |.  C745 A0 10000 mov dword ptr [ebp-60],10
0044494E  |.  C745 A4 70000 mov dword ptr [ebp-5C],70
00444955  |.  C745 A8 10000 mov dword ptr [ebp-58],10
0044495C  |.  C745 AC 60000 mov dword ptr [ebp-54],60
00444963  |.  C745 B0 20000 mov dword ptr [ebp-50],20
0044496A  |.  C745 B4 70000 mov dword ptr [ebp-4C],70
00444971  |.  C745 B8 20000 mov dword ptr [ebp-48],20
00444978  |.  C745 BC 60000 mov dword ptr [ebp-44],60
0044497F  |.  C745 C0 30000 mov dword ptr [ebp-40],30
00444986  |.  C745 C4 70000 mov dword ptr [ebp-3C],70
0044498D  |.  C745 C8 30000 mov dword ptr [ebp-38],30
00444994  |.  C745 CC 60000 mov dword ptr [ebp-34],60
0044499B  |.  C745 D0 40000 mov dword ptr [ebp-30],40
004449A2  |.  C745 D4 70000 mov dword ptr [ebp-2C],70
004449A9  |.  C745 D8 40000 mov dword ptr [ebp-28],40
004449B0  |.  C745 DC 60000 mov dword ptr [ebp-24],60
004449B7  |.  C745 E0 50000 mov dword ptr [ebp-20],50
004449BE  |.  C745 E4 70000 mov dword ptr [ebp-1C],70
004449C5  |.  C745 E8 50000 mov dword ptr [ebp-18],50
004449CC  |.  C745 EC 60000 mov dword ptr [ebp-14],60
004449D3  |.  C745 F0 60000 mov dword ptr [ebp-10],60
004449DA  |.  C745 F4 70000 mov dword ptr [ebp-0C],70
004449E1  |.  C785 30FFFFFF mov dword ptr [ebp-0D0],0
004449EB  |.  C785 34FFFFFF mov dword ptr [ebp-0CC],70
004449F5  |.  C785 38FFFFFF mov dword ptr [ebp-0C8],10
004449FF  |.  C785 3CFFFFFF mov dword ptr [ebp-0C4],80
00444A09  |.  C785 40FFFFFF mov dword ptr [ebp-0C0],10
00444A13  |.  C785 44FFFFFF mov dword ptr [ebp-0BC],70
00444A1D  |.  C785 48FFFFFF mov dword ptr [ebp-0B8],20
00444A27  |.  C785 4CFFFFFF mov dword ptr [ebp-0B4],80
00444A31  |.  C785 50FFFFFF mov dword ptr [ebp-0B0],20
00444A3B  |.  C785 54FFFFFF mov dword ptr [ebp-0AC],70
00444A45  |.  C785 58FFFFFF mov dword ptr [ebp-0A8],30
00444A4F  |.  C785 5CFFFFFF mov dword ptr [ebp-0A4],80
00444A59  |.  C785 60FFFFFF mov dword ptr [ebp-0A0],30
00444A63  |.  C785 64FFFFFF mov dword ptr [ebp-9C],70
00444A6D  |.  C785 68FFFFFF mov dword ptr [ebp-98],40
00444A77  |.  C785 6CFFFFFF mov dword ptr [ebp-94],80
00444A81  |.  C785 70FFFFFF mov dword ptr [ebp-90],40
00444A8B  |.  C785 74FFFFFF mov dword ptr [ebp-8C],70
00444A95  |.  C785 78FFFFFF mov dword ptr [ebp-88],50
00444A9F  |.  C785 7CFFFFFF mov dword ptr [ebp-84],80
00444AA9  |.  C745 80 50000 mov dword ptr [ebp-80],50
00444AB0  |.  C745 84 70000 mov dword ptr [ebp-7C],70
00444AB7  |.  C745 88 60000 mov dword ptr [ebp-78],60
00444ABE  |.  C745 8C 80000 mov dword ptr [ebp-74],80
00444AC5  |.  8B45 08       mov eax,[ebp+8]
00444AC8  |.  8B48 74       mov ecx,[eax+74]
00444ACB  |.  898D 28FFFFFF mov [ebp-0D8],ecx
00444AD1  |.  83BD 28FFFFFF cmp dword ptr [ebp-0D8],5
00444AD8  |.  0F87 16040000 ja 00444EF4
00444ADE  |.  8B95 28FFFFFF mov edx,[ebp-0D8]
00444AE4  \.  FF2495 355044 jmp [edx*4+445035]
00444AEB  />  8B45 08       mov eax,[ebp+8]
00444AEE  |.  8B48 0C       mov ecx,[eax+0C]
00444AF1  |.  81C1 00060000 add ecx,600
00444AF7  |.  8B55 08       mov edx,[ebp+8]
00444AFA  |.  894A 0C       mov [edx+0C],ecx
00444AFD  |.  8B45 08       mov eax,[ebp+8]
00444B00  |.  C740 74 01000 mov dword ptr [eax+74],1
00444B07  |>  8B4D 08       mov ecx,[ebp+8]
00444B0A  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444B0E  |.  7C 7E         jl short 00444B8E
00444B10  |.  8B55 08       mov edx,[ebp+8]
00444B13  |.  8B42 08       mov eax,[edx+8]
00444B16  |.  2D 00C00000   sub eax,0C000
00444B1B  |.  3B05 54E64900 cmp eax,[49E654]
00444B21  |.  7D 6B         jge short 00444B8E
00444B23  |.  8B4D 08       mov ecx,[ebp+8]
00444B26  |.  8B51 08       mov edx,[ecx+8]
00444B29  |.  81C2 00C00000 add edx,0C000
00444B2F  |.  3B15 54E64900 cmp edx,[49E654]
00444B35  |.  7E 57         jle short 00444B8E
00444B37  |.  8B45 08       mov eax,[ebp+8]
00444B3A  |.  8B48 0C       mov ecx,[eax+0C]
00444B3D  |.  81E9 00C00000 sub ecx,0C000
00444B43  |.  3B0D 58E64900 cmp ecx,[49E658]
00444B49  |.  7D 43         jge short 00444B8E
00444B4B  |.  8B55 08       mov edx,[ebp+8]
00444B4E  |.  8B42 0C       mov eax,[edx+0C]
00444B51  |.  05 00400000   add eax,4000
00444B56  |.  3B05 58E64900 cmp eax,[49E658]
00444B5C  |.  7E 30         jle short 00444B8E
00444B5E  |.  8B4D 08       mov ecx,[ebp+8]
00444B61  |.  8B51 08       mov edx,[ecx+8]
00444B64  |.  3B15 54E64900 cmp edx,[49E654]
00444B6A  |.  7E 0C         jle short 00444B78
00444B6C  |.  8B45 08       mov eax,[ebp+8]
00444B6F  |.  C740 4C 00000 mov dword ptr [eax+4C],0
00444B76  |.  EB 0A         jmp short 00444B82
00444B78  |>  8B4D 08       mov ecx,[ebp+8]
00444B7B  |.  C741 4C 02000 mov dword ptr [ecx+4C],2
00444B82  |>  8B55 08       mov edx,[ebp+8]
00444B85  |.  C742 68 01000 mov dword ptr [edx+68],1
00444B8C  |.  EB 22         jmp short 00444BB0
00444B8E  |>  8B45 08       mov eax,[ebp+8]
00444B91  |.  8378 78 08    cmp dword ptr [eax+78],8
00444B95  |.  7D 0F         jge short 00444BA6
00444B97  |.  8B4D 08       mov ecx,[ebp+8]
00444B9A  |.  8B51 78       mov edx,[ecx+78]
00444B9D  |.  83C2 01       add edx,1
00444BA0  |.  8B45 08       mov eax,[ebp+8]
00444BA3  |.  8950 78       mov [eax+78],edx
00444BA6  |>  8B4D 08       mov ecx,[ebp+8]
00444BA9  |.  C741 68 00000 mov dword ptr [ecx+68],0
00444BB0  |>  8B55 08       mov edx,[ebp+8]
00444BB3  |.  0FB682 9C0000 movzx eax,byte ptr [edx+9C]
00444BBA  |.  85C0          test eax,eax
00444BBC  |.  74 1E         je short 00444BDC
00444BBE  |.  8B4D 08       mov ecx,[ebp+8]
00444BC1  |.  C741 74 02000 mov dword ptr [ecx+74],2
00444BC8  |.  8B55 08       mov edx,[ebp+8]
00444BCB  |.  C742 68 00000 mov dword ptr [edx+68],0
00444BD2  |.  8B45 08       mov eax,[ebp+8]
00444BD5  |.  C740 78 00000 mov dword ptr [eax+78],0
00444BDC  |>  8B4D 08       mov ecx,[ebp+8]
00444BDF  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444BE3  |.  7C 6C         jl short 00444C51
00444BE5  |.  8B55 08       mov edx,[ebp+8]
00444BE8  |.  8B42 08       mov eax,[edx+8]
00444BEB  |.  2D 00600000   sub eax,6000
00444BF0  |.  3B05 54E64900 cmp eax,[49E654]
00444BF6  |.  7D 59         jge short 00444C51
00444BF8  |.  8B4D 08       mov ecx,[ebp+8]
00444BFB  |.  8B51 08       mov edx,[ecx+8]
00444BFE  |.  81C2 00600000 add edx,6000
00444C04  |.  3B15 54E64900 cmp edx,[49E654]
00444C0A  |.  7E 45         jle short 00444C51
00444C0C  |.  8B45 08       mov eax,[ebp+8]
00444C0F  |.  8B48 0C       mov ecx,[eax+0C]
00444C12  |.  81E9 00C00000 sub ecx,0C000
00444C18  |.  3B0D 58E64900 cmp ecx,[49E658]
00444C1E  |.  7D 31         jge short 00444C51
00444C20  |.  8B55 08       mov edx,[ebp+8]
00444C23  |.  8B42 0C       mov eax,[edx+0C]
00444C26  |.  05 00400000   add eax,4000
00444C2B  |.  3B05 58E64900 cmp eax,[49E658]
00444C31  |.  7E 1E         jle short 00444C51
00444C33  |.  8B4D 08       mov ecx,[ebp+8]
00444C36  |.  C741 74 02000 mov dword ptr [ecx+74],2
00444C3D  |.  8B55 08       mov edx,[ebp+8]
00444C40  |.  C742 68 00000 mov dword ptr [edx+68],0
00444C47  |.  8B45 08       mov eax,[ebp+8]
00444C4A  |.  C740 78 00000 mov dword ptr [eax+78],0
00444C51  \>  E9 9E020000   jmp 00444EF4
00444C56  />  8B4D 08       mov ecx,[ebp+8]
00444C59  |.  8B51 78       mov edx,[ecx+78]
00444C5C  |.  83C2 01       add edx,1
00444C5F  |.  8B45 08       mov eax,[ebp+8]
00444C62  |.  8950 78       mov [eax+78],edx
00444C65  |.  8B4D 08       mov ecx,[ebp+8]
00444C68  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444C6C  |.  7E 4E         jle short 00444CBC
00444C6E  |.  8B55 08       mov edx,[ebp+8]
00444C71  |.  C742 74 03000 mov dword ptr [edx+74],3
00444C78  |.  8B45 08       mov eax,[ebp+8]
00444C7B  |.  C740 68 02000 mov dword ptr [eax+68],2
00444C82  |.  8B4D 08       mov ecx,[ebp+8]
00444C85  |.  C741 14 01FAF mov dword ptr [ecx+14],-5FF
00444C8C  |.  6A 01         push 1                                   ; /Arg2 = 1
00444C8E  |.  6A 1E         push 1E                                  ; |Arg1 = 1E
00444C90  |.  E8 ABB9FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444C95  |.  83C4 08       add esp,8
00444C98  |.  8B55 08       mov edx,[ebp+8]
00444C9B  |.  8B42 08       mov eax,[edx+8]
00444C9E  |.  3B05 54E64900 cmp eax,[49E654]
00444CA4  |.  7E 0C         jle short 00444CB2
00444CA6  |.  8B4D 08       mov ecx,[ebp+8]
00444CA9  |.  C741 4C 00000 mov dword ptr [ecx+4C],0
00444CB0  |.  EB 0A         jmp short 00444CBC
00444CB2  |>  8B55 08       mov edx,[ebp+8]
00444CB5  |.  C742 4C 02000 mov dword ptr [edx+4C],2
00444CBC  \>  E9 33020000   jmp 00444EF4
00444CC1  />  8B45 08       mov eax,[ebp+8]
00444CC4  |.  8178 14 00010 cmp dword ptr [eax+14],100
00444CCB  |.  7E 34         jle short 00444D01
00444CCD  |.  8B4D 08       mov ecx,[ebp+8]
00444CD0  |.  8B55 08       mov edx,[ebp+8]
00444CD3  |.  8B42 0C       mov eax,[edx+0C]
00444CD6  |.  8941 24       mov [ecx+24],eax
00444CD9  |.  8B4D 08       mov ecx,[ebp+8]
00444CDC  |.  C741 74 04000 mov dword ptr [ecx+74],4
00444CE3  |.  8B55 08       mov edx,[ebp+8]
00444CE6  |.  C742 68 03000 mov dword ptr [edx+68],3
00444CED  |.  8B45 08       mov eax,[ebp+8]
00444CF0  |.  C740 78 00000 mov dword ptr [eax+78],0
00444CF7  |.  8B4D 08       mov ecx,[ebp+8]
00444CFA  |.  C741 78 00000 mov dword ptr [ecx+78],0
00444D01  \>  E9 EE010000   jmp 00444EF4
00444D06  />  8B55 08       mov edx,[ebp+8]
00444D09  |.  8B42 08       mov eax,[edx+8]
00444D0C  |.  3B05 54E64900 cmp eax,[49E654]
00444D12  |.  7D 0C         jge short 00444D20
00444D14  |.  8B4D 08       mov ecx,[ebp+8]
00444D17  |.  C741 4C 02000 mov dword ptr [ecx+4C],2
00444D1E  |.  EB 0A         jmp short 00444D2A
00444D20  |>  8B55 08       mov edx,[ebp+8]
00444D23  |.  C742 4C 00000 mov dword ptr [edx+4C],0
00444D2A  |>  8B45 08       mov eax,[ebp+8]
00444D2D  |.  8B48 78       mov ecx,[eax+78]
00444D30  |.  83C1 01       add ecx,1
00444D33  |.  8B55 08       mov edx,[ebp+8]
00444D36  |.  894A 78       mov [edx+78],ecx
00444D39  |.  8B45 08       mov eax,[ebp+8]
00444D3C  |.  8B48 04       mov ecx,[eax+4]
00444D3F  |.  83E1 07       and ecx,00000007
00444D42  |.  75 09         jne short 00444D4D
00444D44  |.  8B55 08       mov edx,[ebp+8]
00444D47  |.  837A 78 3C    cmp dword ptr [edx+78],3C
00444D4B  |.  7E 26         jle short 00444D73
00444D4D  |>  8B45 08       mov eax,[ebp+8]
00444D50  |.  C780 A4000000 mov dword ptr [eax+0A4],3
00444D5A  |.  8B4D 08       mov ecx,[ebp+8]
00444D5D  |.  C741 74 05000 mov dword ptr [ecx+74],5
00444D64  |.  8B55 08       mov edx,[ebp+8]
00444D67  |.  C742 68 02000 mov dword ptr [edx+68],2
00444D6E  |.  E9 81010000   jmp 00444EF4
00444D73  |>  8B45 08       mov eax,[ebp+8]
00444D76  |.  8B48 78       mov ecx,[eax+78]
00444D79  |.  81E1 03000080 and ecx,80000003
00444D7F  |.  79 05         jns short 00444D86
00444D81  |.  49            dec ecx
00444D82  |.  83C9 FC       or ecx,FFFFFFFC
00444D85  |.  41            inc ecx
00444D86  |>  83F9 01       cmp ecx,1
00444D89  |.  75 0C         jne short 00444D97
00444D8B  |.  6A 01         push 1                                   ; /Arg2 = 1
00444D8D  |.  6A 6D         push 6D                                  ; |Arg1 = 6D
00444D8F  |.  E8 ACB8FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444D94  |.  83C4 08       add esp,8
00444D97  |>  8B55 08       mov edx,[ebp+8]
00444D9A  |.  8B42 04       mov eax,[edx+4]
00444D9D  |.  83E0 08       and eax,00000008
00444DA0  |.  74 0A         je short 00444DAC
00444DA2  |.  8B4D 08       mov ecx,[ebp+8]
00444DA5  |.  C741 14 00FEF mov dword ptr [ecx+14],-200
00444DAC  |>  8B55 08       mov edx,[ebp+8]
00444DAF  |.  8B42 78       mov eax,[edx+78]
00444DB2  |.  99            cdq
00444DB3  |.  B9 1E000000   mov ecx,1E
00444DB8  |.  F7F9          idiv ecx
00444DBA  |.  83FA 06       cmp edx,6
00444DBD  |.  0F85 9F000000 jne 00444E62
00444DC3  |.  8B55 08       mov edx,[ebp+8]
00444DC6  |.  8B42 0C       mov eax,[edx+0C]
00444DC9  |.  2B05 58E64900 sub eax,[49E658]
00444DCF  |.  50            push eax
00444DD0  |.  8B4D 08       mov ecx,[ebp+8]
00444DD3  |.  8B51 08       mov edx,[ecx+8]
00444DD6  |.  2B15 54E64900 sub edx,[49E654]
00444DDC  |.  52            push edx
00444DDD  |.  E8 FE0AFEFF   call 004258E0
00444DE2  |.  83C4 08       add esp,8
00444DE5  |.  8845 FF       mov [ebp-1],al
00444DE8  |.  6A 06         push 6                                   ; /Arg2 = 6
00444DEA  |.  6A FA         push -6                                  ; |Arg1 = -6
00444DEC  |.  E8 5FA5FCFF   call 0040F350                            ; \Doukutsu_-_Copy.0040F350
00444DF1  |.  83C4 08       add esp,8
00444DF4  |.  0FB6C0        movzx eax,al
00444DF7  |.  0FB64D FF     movzx ecx,byte ptr [ebp-1]
00444DFB  |.  03C8          add ecx,eax
00444DFD  |.  884D FF       mov [ebp-1],cl
00444E00  |.  8A55 FF       mov dl,[ebp-1]
00444E03  |.  52            push edx                                 ; /Arg1
00444E04  |.  E8 A70AFEFF   call 004258B0                            ; \Doukutsu_-_Copy.004258B0
00444E09  |.  83C4 04       add esp,4
00444E0C  |.  6BC0 03       imul eax,eax,3
00444E0F  |.  8985 2CFFFFFF mov [ebp-0D4],eax
00444E15  |.  8A45 FF       mov al,[ebp-1]
00444E18  |.  50            push eax                                 ; /Arg1
00444E19  |.  E8 A20AFEFF   call 004258C0                            ; \Doukutsu_-_Copy.004258C0
00444E1E  |.  83C4 04       add esp,4
00444E21  |.  6BC0 03       imul eax,eax,3
00444E24  |.  8945 94       mov [ebp-6C],eax
00444E27  |.  68 00010000   push 100                                 ; /Arg8 = 100
00444E2C  |.  6A 00         push 0                                   ; |Arg7 = 0
00444E2E  |.  6A 00         push 0                                   ; |Arg6 = 0
00444E30  |.  8B8D 2CFFFFFF mov ecx,[ebp-0D4]                        ; |
00444E36  |.  51            push ecx                                 ; |Arg5
00444E37  |.  8B55 94       mov edx,[ebp-6C]                         ; |
00444E3A  |.  52            push edx                                 ; |Arg4
00444E3B  |.  8B45 08       mov eax,[ebp+8]                          ; |
00444E3E  |.  8B48 0C       mov ecx,[eax+0C]                         ; |
00444E41  |.  51            push ecx                                 ; |Arg3
00444E42  |.  8B55 08       mov edx,[ebp+8]                          ; |
00444E45  |.  8B42 08       mov eax,[edx+8]                          ; |
00444E48  |.  50            push eax                                 ; |Arg2
00444E49  |.  68 94000000   push 94                                  ; |Arg1 = 94
00444E4E  |.  E8 7DA10200   call 0046EFD0                            ; \Doukutsu_-_Copy.0046EFD0
00444E53  |.  83C4 20       add esp,20
00444E56  |.  6A 01         push 1                                   ; /Arg2 = 1
00444E58  |.  6A 27         push 27                                  ; |Arg1 = 27
00444E5A  |.  E8 E1B7FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444E5F  |.  83C4 08       add esp,8
00444E62  |>  8B4D 08       mov ecx,[ebp+8]
00444E65  |.  8B51 64       mov edx,[ecx+64]
00444E68  |.  83C2 01       add edx,1
00444E6B  |.  8B45 08       mov eax,[ebp+8]
00444E6E  |.  8950 64       mov [eax+64],edx
00444E71  |.  8B4D 08       mov ecx,[ebp+8]
00444E74  |.  8379 64 00    cmp dword ptr [ecx+64],0
00444E78  |.  7E 19         jle short 00444E93
00444E7A  |.  8B55 08       mov edx,[ebp+8]
00444E7D  |.  C742 64 00000 mov dword ptr [edx+64],0
00444E84  |.  8B45 08       mov eax,[ebp+8]
00444E87  |.  8B48 68       mov ecx,[eax+68]
00444E8A  |.  83C1 01       add ecx,1
00444E8D  |.  8B55 08       mov edx,[ebp+8]
00444E90  |.  894A 68       mov [edx+68],ecx
00444E93  |>  8B45 08       mov eax,[ebp+8]
00444E96  |.  8378 68 05    cmp dword ptr [eax+68],5
00444E9A  |.  7E 0A         jle short 00444EA6
00444E9C  |.  8B4D 08       mov ecx,[ebp+8]
00444E9F  |.  C741 68 03000 mov dword ptr [ecx+68],3
00444EA6  \>  EB 4C         jmp short 00444EF4
00444EA8  />  8B55 08       mov edx,[ebp+8]
00444EAB  |.  8B42 04       mov eax,[edx+4]
00444EAE  |.  83E0 08       and eax,00000008
00444EB1  |.  74 41         je short 00444EF4
00444EB3  |.  8B4D 08       mov ecx,[ebp+8]
00444EB6  |.  C781 A4000000 mov dword ptr [ecx+0A4],2
00444EC0  |.  8B55 08       mov edx,[ebp+8]
00444EC3  |.  C742 10 00000 mov dword ptr [edx+10],0
00444ECA  |.  8B45 08       mov eax,[ebp+8]
00444ECD  |.  C740 78 00000 mov dword ptr [eax+78],0
00444ED4  |.  8B4D 08       mov ecx,[ebp+8]
00444ED7  |.  C741 68 00000 mov dword ptr [ecx+68],0
00444EDE  |.  8B55 08       mov edx,[ebp+8]
00444EE1  |.  C742 74 01000 mov dword ptr [edx+74],1
00444EE8  |.  6A 01         push 1                                   ; /Arg2 = 1
00444EEA  |.  6A 17         push 17                                  ; |Arg1 = 17
00444EEC  |.  E8 4FB7FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444EF1  |.  83C4 08       add esp,8
00444EF4  |>  8B45 08       mov eax,[ebp+8]
00444EF7  |.  8378 74 04    cmp dword ptr [eax+74],4
00444EFB  |.  74 2A         je short 00444F27
00444EFD  |.  8B4D 08       mov ecx,[ebp+8]
00444F00  |.  8B51 14       mov edx,[ecx+14]
00444F03  |.  83C2 20       add edx,20
00444F06  |.  8B45 08       mov eax,[ebp+8]
00444F09  |.  8950 14       mov [eax+14],edx
00444F0C  |.  8B4D 08       mov ecx,[ebp+8]
00444F0F  |.  8179 14 FF050 cmp dword ptr [ecx+14],5FF
00444F16  |.  7E 0A         jle short 00444F22
00444F18  |.  8B55 08       mov edx,[ebp+8]
00444F1B  |.  C742 14 FF050 mov dword ptr [edx+14],5FF
00444F22  |>  E9 86000000   jmp 00444FAD
00444F27  |>  8B45 08       mov eax,[ebp+8]
00444F2A  |.  8B4D 08       mov ecx,[ebp+8]
00444F2D  |.  8B50 0C       mov edx,[eax+0C]
00444F30  |.  3B51 24       cmp edx,[ecx+24]
00444F33  |.  7E 11         jle short 00444F46
00444F35  |.  8B45 08       mov eax,[ebp+8]
00444F38  |.  8B48 14       mov ecx,[eax+14]
00444F3B  |.  83E9 10       sub ecx,10
00444F3E  |.  8B55 08       mov edx,[ebp+8]
00444F41  |.  894A 14       mov [edx+14],ecx
00444F44  |.  EB 0F         jmp short 00444F55
00444F46  |>  8B45 08       mov eax,[ebp+8]
00444F49  |.  8B48 14       mov ecx,[eax+14]
00444F4C  |.  83C1 10       add ecx,10
00444F4F  |.  8B55 08       mov edx,[ebp+8]
00444F52  |.  894A 14       mov [edx+14],ecx
00444F55  |>  8B45 08       mov eax,[ebp+8]
00444F58  |.  8178 14 00020 cmp dword ptr [eax+14],200
00444F5F  |.  7E 0A         jle short 00444F6B
00444F61  |.  8B4D 08       mov ecx,[ebp+8]
00444F64  |.  C741 14 00020 mov dword ptr [ecx+14],200
00444F6B  |>  8B55 08       mov edx,[ebp+8]
00444F6E  |.  817A 14 00FEF cmp dword ptr [edx+14],-200
00444F75  |.  7D 0A         jge short 00444F81
00444F77  |.  8B45 08       mov eax,[ebp+8]
00444F7A  |.  C740 14 00FEF mov dword ptr [eax+14],-200
00444F81  |>  8B4D 08       mov ecx,[ebp+8]
00444F84  |.  8179 10 00020 cmp dword ptr [ecx+10],200
00444F8B  |.  7E 0A         jle short 00444F97
00444F8D  |.  8B55 08       mov edx,[ebp+8]
00444F90  |.  C742 10 00020 mov dword ptr [edx+10],200
00444F97  |>  8B45 08       mov eax,[ebp+8]
00444F9A  |.  8178 10 00FEF cmp dword ptr [eax+10],-200
00444FA1  |.  7D 0A         jge short 00444FAD
00444FA3  |.  8B4D 08       mov ecx,[ebp+8]
00444FA6  |.  C741 10 00FEF mov dword ptr [ecx+10],-200
00444FAD  |>  8B55 08       mov edx,[ebp+8]
00444FB0  |.  8B42 08       mov eax,[edx+8]
00444FB3  |.  8B4D 08       mov ecx,[ebp+8]
00444FB6  |.  0341 10       add eax,[ecx+10]
00444FB9  |.  8B55 08       mov edx,[ebp+8]
00444FBC  |.  8942 08       mov [edx+8],eax
00444FBF  |.  8B45 08       mov eax,[ebp+8]
00444FC2  |.  8B48 0C       mov ecx,[eax+0C]
00444FC5  |.  8B55 08       mov edx,[ebp+8]
00444FC8  |.  034A 14       add ecx,[edx+14]
00444FCB  |.  8B45 08       mov eax,[ebp+8]
00444FCE  |.  8948 0C       mov [eax+0C],ecx
00444FD1  |.  8B4D 08       mov ecx,[ebp+8]
00444FD4  |.  8379 4C 00    cmp dword ptr [ecx+4C],0
00444FD8  |.  75 2B         jne short 00445005
00444FDA  |.  8B55 08       mov edx,[ebp+8]
00444FDD  |.  8B42 68       mov eax,[edx+68]
00444FE0  |.  C1E0 04       shl eax,4
00444FE3  |.  8D4C05 98     lea ecx,[eax+ebp-68]
00444FE7  |.  8B55 08       mov edx,[ebp+8]
00444FEA  |.  83C2 54       add edx,54
00444FED  |.  8B01          mov eax,[ecx]
00444FEF  |.  8902          mov [edx],eax
00444FF1  |.  8B41 04       mov eax,[ecx+4]
00444FF4  |.  8942 04       mov [edx+4],eax
00444FF7  |.  8B41 08       mov eax,[ecx+8]
00444FFA  |.  8942 08       mov [edx+8],eax
00444FFD  |.  8B49 0C       mov ecx,[ecx+0C]
00445000  |.  894A 0C       mov [edx+0C],ecx
00445003  |.  EB 2C         jmp short 00445031
00445005  |>  8B55 08       mov edx,[ebp+8]
00445008  |.  8B42 68       mov eax,[edx+68]
0044500B  |.  C1E0 04       shl eax,4
0044500E  |.  8D8C05 30FFFF lea ecx,[eax+ebp-0D0]
00445015  |.  8B55 08       mov edx,[ebp+8]
00445018  |.  83C2 54       add edx,54
0044501B  |.  8B01          mov eax,[ecx]
0044501D  |.  8902          mov [edx],eax
0044501F  |.  8B41 04       mov eax,[ecx+4]
00445022  |.  8942 04       mov [edx+4],eax
00445025  |.  8B41 08       mov eax,[ecx+8]
00445028  |.  8942 08       mov [edx+8],eax
0044502B  |.  8B49 0C       mov ecx,[ecx+0C]
0044502E  |.  894A 0C       mov [edx+0C],ecx
00445031  |>  8BE5          mov esp,ebp
00445033  |.  5D            pop ebp
00445034  \.  C3            retn
00445035   .  EB4A4400      dd 00444AEB
00445039   .  074B4400      dd 00444B07
0044503D   .  564C4400      dd 00444C56
00445041   .  C14C4400      dd 00444CC1
00445045   .  064D4400      dd 00444D06
00445049   .  A84E4400      dd 00444EA8
This is the code for the purple critter that shoots stuff. If you can make sense of this, then you can probably figure out anything you need to put together basic NPCs from scratch apart from the few technical details of implemenetation.

As far as the other questions go, generally you can't add more NPCs than the number that are already in the game. You just hijack the function of an existing one that you aren't going to use (and don't give me that bs of "i wanna use all of them", you wont). It *is* possible but that's a bit more complex and requires an understanding of some of the systems around the NPCs that make them go and I don't want to explain it right now.
 
May 26, 2013 at 6:25 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
Noxid said:
If you are really serious about this, then imo the best way to understand how to write your own NPC code is to examine and understand the ones that already exist. So I'm going to give you a few exercises.


CPU Disasm
Address Hex dump Command Comments
004517F0 /$ 55 push ebp
004517F1 |. 8BEC mov ebp,esp
004517F3 |. 83EC 10 sub esp,10
004517F6 |. C745 F0 00010 mov dword ptr [local.4],100
004517FD |. C745 F4 C0000 mov dword ptr [local.3],0C0
00451804 |. C745 F8 10010 mov dword ptr [local.2],110
0045180B |. C745 FC D8000 mov dword ptr [local.1],0D8
00451812 |. 8B45 08 mov eax,[arg.1]
00451815 |. 83C0 54 add eax,54
00451818 |. 8B4D F0 mov ecx,[local.4]
0045181B |. 8908 mov [eax],ecx
0045181D |. 8B55 F4 mov edx,[local.3]
00451820 |. 8950 04 mov [eax+4],edx
00451823 |. 8B4D F8 mov ecx,[local.2]
00451826 |. 8948 08 mov [eax+8],ecx
00451829 |. 8B55 FC mov edx,[local.1]
0045182C |. 8950 0C mov [eax+0C],edx
0045182F |. 8BE5 mov esp,ebp
00451831 |. 5D pop ebp
00451832 \. C3 retn

This is the code for the debug cat. It is possibly the simplest entity I can think of to give as an example. It has one frame and does absolutely nothing. Comment every line of code and tell me what it does.

Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00451E90  /$  55            push ebp
00451E91  |.  8BEC          mov ebp,esp
00451E93  |.  83EC 44       sub esp,44
00451E96  |.  C745 E0 00000 mov dword ptr [local.8],0
00451E9D  |.  C745 E4 40000 mov dword ptr [local.7],40
00451EA4  |.  C745 E8 10000 mov dword ptr [local.6],10
00451EAB  |.  C745 EC 50000 mov dword ptr [local.5],50
00451EB2  |.  C745 F0 10000 mov dword ptr [local.4],10
00451EB9  |.  C745 F4 40000 mov dword ptr [local.3],40
00451EC0  |.  C745 F8 20000 mov dword ptr [local.2],20
00451EC7  |.  C745 FC 50000 mov dword ptr [local.1],50
00451ECE  |.  C745 C0 00000 mov dword ptr [local.16],0
00451ED5  |.  C745 C4 50000 mov dword ptr [local.15],50
00451EDC  |.  C745 C8 10000 mov dword ptr [local.14],10
00451EE3  |.  C745 CC 60000 mov dword ptr [local.13],60
00451EEA  |.  C745 D0 10000 mov dword ptr [local.12],10
00451EF1  |.  C745 D4 50000 mov dword ptr [local.11],50
00451EF8  |.  C745 D8 20000 mov dword ptr [local.10],20
00451EFF  |.  C745 DC 60000 mov dword ptr [local.9],60
00451F06  |.  8B45 08       mov eax,[arg.1]
00451F09  |.  8B48 74       mov ecx,[eax+74]
00451F0C  |.  894D BC       mov [local.17],ecx
00451F0F  |.  837D BC 00    cmp dword ptr [local.17],0
00451F13  |.  74 0E         je short 00451F23
00451F15  |.  837D BC 01    cmp dword ptr [local.17],1
00451F19  |.  74 26         je short 00451F41
00451F1B  |.  837D BC 02    cmp dword ptr [local.17],2
00451F1F  |.  74 51         je short 00451F72
00451F21  |.  EB 7B         jmp short 00451F9E
00451F23  |>  8B55 08       mov edx,[arg.1]
00451F26  |.  C742 74 01000 mov dword ptr [edx+74],1
00451F2D  |.  8B45 08       mov eax,[arg.1]
00451F30  |.  C740 68 00000 mov dword ptr [eax+68],0
00451F37  |.  8B4D 08       mov ecx,[arg.1]
00451F3A  |.  C741 64 00000 mov dword ptr [ecx+64],0
00451F41  |>  6A 78         push 78                                  ; /Arg2 = 78
00451F43  |.  6A 00         push 0                                   ; |Arg1 = 0
00451F45  |.  E8 06D4FBFF   call 0040F350                            ; \Doukutsu_-_Copy.0040F350
00451F4A  |.  83C4 08       add esp,8
00451F4D  |.  83F8 0A       cmp eax,0A
00451F50  |.  75 1E         jne short 00451F70
00451F52  |.  8B55 08       mov edx,[arg.1]
00451F55  |.  C742 74 02000 mov dword ptr [edx+74],2
00451F5C  |.  8B45 08       mov eax,[arg.1]
00451F5F  |.  C740 78 00000 mov dword ptr [eax+78],0
00451F66  |.  8B4D 08       mov ecx,[arg.1]
00451F69  |.  C741 68 01000 mov dword ptr [ecx+68],1
00451F70  |>  EB 2C         jmp short 00451F9E
00451F72  |>  8B55 08       mov edx,[arg.1]
00451F75  |.  8B42 78       mov eax,[edx+78]
00451F78  |.  83C0 01       add eax,1
00451F7B  |.  8B4D 08       mov ecx,[arg.1]
00451F7E  |.  8941 78       mov [ecx+78],eax
00451F81  |.  8B55 08       mov edx,[arg.1]
00451F84  |.  837A 78 08    cmp dword ptr [edx+78],8
00451F88  |.  7E 14         jle short 00451F9E
00451F8A  |.  8B45 08       mov eax,[arg.1]
00451F8D  |.  C740 74 01000 mov dword ptr [eax+74],1
00451F94  |.  8B4D 08       mov ecx,[arg.1]
00451F97  |.  C741 68 00000 mov dword ptr [ecx+68],0
00451F9E  |>  8B55 08       mov edx,[arg.1]
00451FA1  |.  837A 4C 00    cmp dword ptr [edx+4C],0
00451FA5  |.  75 2B         jne short 00451FD2
00451FA7  |.  8B45 08       mov eax,[arg.1]
00451FAA  |.  8B48 68       mov ecx,[eax+68]
00451FAD  |.  C1E1 04       shl ecx,4
00451FB0  |.  8D540D E0     lea edx,[ecx+ebp-20]
00451FB4  |.  8B45 08       mov eax,[arg.1]
00451FB7  |.  83C0 54       add eax,54
00451FBA  |.  8B0A          mov ecx,[edx]
00451FBC  |.  8908          mov [eax],ecx
00451FBE  |.  8B4A 04       mov ecx,[edx+4]
00451FC1  |.  8948 04       mov [eax+4],ecx
00451FC4  |.  8B4A 08       mov ecx,[edx+8]
00451FC7  |.  8948 08       mov [eax+8],ecx
00451FCA  |.  8B52 0C       mov edx,[edx+0C]
00451FCD  |.  8950 0C       mov [eax+0C],edx
00451FD0  |.  EB 29         jmp short 00451FFB
00451FD2  |>  8B45 08       mov eax,[arg.1]
00451FD5  |.  8B48 68       mov ecx,[eax+68]
00451FD8  |.  C1E1 04       shl ecx,4
00451FDB  |.  8D540D C0     lea edx,[ecx+ebp-40]
00451FDF  |.  8B45 08       mov eax,[arg.1]
00451FE2  |.  83C0 54       add eax,54
00451FE5  |.  8B0A          mov ecx,[edx]
00451FE7  |.  8908          mov [eax],ecx
00451FE9  |.  8B4A 04       mov ecx,[edx+4]
00451FEC  |.  8948 04       mov [eax+4],ecx
00451FEF  |.  8B4A 08       mov ecx,[edx+8]
00451FF2  |.  8948 08       mov [eax+8],ecx
00451FF5  |.  8B52 0C       mov edx,[edx+0C]
00451FF8  |.  8950 0C       mov [eax+0C],edx
00451FFB  |>  8BE5          mov esp,ebp
00451FFD  |.  5D            pop ebp
00451FFE  \.  C3            retn
Here's the shovel brigade. Only slightly more complicated, I think they blink and turn to face you. But I could be wrong. Comment it and show me what the code does and how it works, you don't need to do *every* line but if it helps you then go to town. Understanding this one should be enough to make the NPC you want.
Code:
CPU Disasm
Address   Hex dump          Command                                  Comments
00444930  /$  55            push ebp
00444931  |.  8BEC          mov ebp,esp
00444933  |.  81EC D8000000 sub esp,0D8
00444939  |.  C745 98 00000 mov dword ptr [ebp-68],0
00444940  |.  C745 9C 60000 mov dword ptr [ebp-64],60
00444947  |.  C745 A0 10000 mov dword ptr [ebp-60],10
0044494E  |.  C745 A4 70000 mov dword ptr [ebp-5C],70
00444955  |.  C745 A8 10000 mov dword ptr [ebp-58],10
0044495C  |.  C745 AC 60000 mov dword ptr [ebp-54],60
00444963  |.  C745 B0 20000 mov dword ptr [ebp-50],20
0044496A  |.  C745 B4 70000 mov dword ptr [ebp-4C],70
00444971  |.  C745 B8 20000 mov dword ptr [ebp-48],20
00444978  |.  C745 BC 60000 mov dword ptr [ebp-44],60
0044497F  |.  C745 C0 30000 mov dword ptr [ebp-40],30
00444986  |.  C745 C4 70000 mov dword ptr [ebp-3C],70
0044498D  |.  C745 C8 30000 mov dword ptr [ebp-38],30
00444994  |.  C745 CC 60000 mov dword ptr [ebp-34],60
0044499B  |.  C745 D0 40000 mov dword ptr [ebp-30],40
004449A2  |.  C745 D4 70000 mov dword ptr [ebp-2C],70
004449A9  |.  C745 D8 40000 mov dword ptr [ebp-28],40
004449B0  |.  C745 DC 60000 mov dword ptr [ebp-24],60
004449B7  |.  C745 E0 50000 mov dword ptr [ebp-20],50
004449BE  |.  C745 E4 70000 mov dword ptr [ebp-1C],70
004449C5  |.  C745 E8 50000 mov dword ptr [ebp-18],50
004449CC  |.  C745 EC 60000 mov dword ptr [ebp-14],60
004449D3  |.  C745 F0 60000 mov dword ptr [ebp-10],60
004449DA  |.  C745 F4 70000 mov dword ptr [ebp-0C],70
004449E1  |.  C785 30FFFFFF mov dword ptr [ebp-0D0],0
004449EB  |.  C785 34FFFFFF mov dword ptr [ebp-0CC],70
004449F5  |.  C785 38FFFFFF mov dword ptr [ebp-0C8],10
004449FF  |.  C785 3CFFFFFF mov dword ptr [ebp-0C4],80
00444A09  |.  C785 40FFFFFF mov dword ptr [ebp-0C0],10
00444A13  |.  C785 44FFFFFF mov dword ptr [ebp-0BC],70
00444A1D  |.  C785 48FFFFFF mov dword ptr [ebp-0B8],20
00444A27  |.  C785 4CFFFFFF mov dword ptr [ebp-0B4],80
00444A31  |.  C785 50FFFFFF mov dword ptr [ebp-0B0],20
00444A3B  |.  C785 54FFFFFF mov dword ptr [ebp-0AC],70
00444A45  |.  C785 58FFFFFF mov dword ptr [ebp-0A8],30
00444A4F  |.  C785 5CFFFFFF mov dword ptr [ebp-0A4],80
00444A59  |.  C785 60FFFFFF mov dword ptr [ebp-0A0],30
00444A63  |.  C785 64FFFFFF mov dword ptr [ebp-9C],70
00444A6D  |.  C785 68FFFFFF mov dword ptr [ebp-98],40
00444A77  |.  C785 6CFFFFFF mov dword ptr [ebp-94],80
00444A81  |.  C785 70FFFFFF mov dword ptr [ebp-90],40
00444A8B  |.  C785 74FFFFFF mov dword ptr [ebp-8C],70
00444A95  |.  C785 78FFFFFF mov dword ptr [ebp-88],50
00444A9F  |.  C785 7CFFFFFF mov dword ptr [ebp-84],80
00444AA9  |.  C745 80 50000 mov dword ptr [ebp-80],50
00444AB0  |.  C745 84 70000 mov dword ptr [ebp-7C],70
00444AB7  |.  C745 88 60000 mov dword ptr [ebp-78],60
00444ABE  |.  C745 8C 80000 mov dword ptr [ebp-74],80
00444AC5  |.  8B45 08       mov eax,[ebp+8]
00444AC8  |.  8B48 74       mov ecx,[eax+74]
00444ACB  |.  898D 28FFFFFF mov [ebp-0D8],ecx
00444AD1  |.  83BD 28FFFFFF cmp dword ptr [ebp-0D8],5
00444AD8  |.  0F87 16040000 ja 00444EF4
00444ADE  |.  8B95 28FFFFFF mov edx,[ebp-0D8]
00444AE4  \.  FF2495 355044 jmp [edx*4+445035]
00444AEB  />  8B45 08       mov eax,[ebp+8]
00444AEE  |.  8B48 0C       mov ecx,[eax+0C]
00444AF1  |.  81C1 00060000 add ecx,600
00444AF7  |.  8B55 08       mov edx,[ebp+8]
00444AFA  |.  894A 0C       mov [edx+0C],ecx
00444AFD  |.  8B45 08       mov eax,[ebp+8]
00444B00  |.  C740 74 01000 mov dword ptr [eax+74],1
00444B07  |>  8B4D 08       mov ecx,[ebp+8]
00444B0A  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444B0E  |.  7C 7E         jl short 00444B8E
00444B10  |.  8B55 08       mov edx,[ebp+8]
00444B13  |.  8B42 08       mov eax,[edx+8]
00444B16  |.  2D 00C00000   sub eax,0C000
00444B1B  |.  3B05 54E64900 cmp eax,[49E654]
00444B21  |.  7D 6B         jge short 00444B8E
00444B23  |.  8B4D 08       mov ecx,[ebp+8]
00444B26  |.  8B51 08       mov edx,[ecx+8]
00444B29  |.  81C2 00C00000 add edx,0C000
00444B2F  |.  3B15 54E64900 cmp edx,[49E654]
00444B35  |.  7E 57         jle short 00444B8E
00444B37  |.  8B45 08       mov eax,[ebp+8]
00444B3A  |.  8B48 0C       mov ecx,[eax+0C]
00444B3D  |.  81E9 00C00000 sub ecx,0C000
00444B43  |.  3B0D 58E64900 cmp ecx,[49E658]
00444B49  |.  7D 43         jge short 00444B8E
00444B4B  |.  8B55 08       mov edx,[ebp+8]
00444B4E  |.  8B42 0C       mov eax,[edx+0C]
00444B51  |.  05 00400000   add eax,4000
00444B56  |.  3B05 58E64900 cmp eax,[49E658]
00444B5C  |.  7E 30         jle short 00444B8E
00444B5E  |.  8B4D 08       mov ecx,[ebp+8]
00444B61  |.  8B51 08       mov edx,[ecx+8]
00444B64  |.  3B15 54E64900 cmp edx,[49E654]
00444B6A  |.  7E 0C         jle short 00444B78
00444B6C  |.  8B45 08       mov eax,[ebp+8]
00444B6F  |.  C740 4C 00000 mov dword ptr [eax+4C],0
00444B76  |.  EB 0A         jmp short 00444B82
00444B78  |>  8B4D 08       mov ecx,[ebp+8]
00444B7B  |.  C741 4C 02000 mov dword ptr [ecx+4C],2
00444B82  |>  8B55 08       mov edx,[ebp+8]
00444B85  |.  C742 68 01000 mov dword ptr [edx+68],1
00444B8C  |.  EB 22         jmp short 00444BB0
00444B8E  |>  8B45 08       mov eax,[ebp+8]
00444B91  |.  8378 78 08    cmp dword ptr [eax+78],8
00444B95  |.  7D 0F         jge short 00444BA6
00444B97  |.  8B4D 08       mov ecx,[ebp+8]
00444B9A  |.  8B51 78       mov edx,[ecx+78]
00444B9D  |.  83C2 01       add edx,1
00444BA0  |.  8B45 08       mov eax,[ebp+8]
00444BA3  |.  8950 78       mov [eax+78],edx
00444BA6  |>  8B4D 08       mov ecx,[ebp+8]
00444BA9  |.  C741 68 00000 mov dword ptr [ecx+68],0
00444BB0  |>  8B55 08       mov edx,[ebp+8]
00444BB3  |.  0FB682 9C0000 movzx eax,byte ptr [edx+9C]
00444BBA  |.  85C0          test eax,eax
00444BBC  |.  74 1E         je short 00444BDC
00444BBE  |.  8B4D 08       mov ecx,[ebp+8]
00444BC1  |.  C741 74 02000 mov dword ptr [ecx+74],2
00444BC8  |.  8B55 08       mov edx,[ebp+8]
00444BCB  |.  C742 68 00000 mov dword ptr [edx+68],0
00444BD2  |.  8B45 08       mov eax,[ebp+8]
00444BD5  |.  C740 78 00000 mov dword ptr [eax+78],0
00444BDC  |>  8B4D 08       mov ecx,[ebp+8]
00444BDF  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444BE3  |.  7C 6C         jl short 00444C51
00444BE5  |.  8B55 08       mov edx,[ebp+8]
00444BE8  |.  8B42 08       mov eax,[edx+8]
00444BEB  |.  2D 00600000   sub eax,6000
00444BF0  |.  3B05 54E64900 cmp eax,[49E654]
00444BF6  |.  7D 59         jge short 00444C51
00444BF8  |.  8B4D 08       mov ecx,[ebp+8]
00444BFB  |.  8B51 08       mov edx,[ecx+8]
00444BFE  |.  81C2 00600000 add edx,6000
00444C04  |.  3B15 54E64900 cmp edx,[49E654]
00444C0A  |.  7E 45         jle short 00444C51
00444C0C  |.  8B45 08       mov eax,[ebp+8]
00444C0F  |.  8B48 0C       mov ecx,[eax+0C]
00444C12  |.  81E9 00C00000 sub ecx,0C000
00444C18  |.  3B0D 58E64900 cmp ecx,[49E658]
00444C1E  |.  7D 31         jge short 00444C51
00444C20  |.  8B55 08       mov edx,[ebp+8]
00444C23  |.  8B42 0C       mov eax,[edx+0C]
00444C26  |.  05 00400000   add eax,4000
00444C2B  |.  3B05 58E64900 cmp eax,[49E658]
00444C31  |.  7E 1E         jle short 00444C51
00444C33  |.  8B4D 08       mov ecx,[ebp+8]
00444C36  |.  C741 74 02000 mov dword ptr [ecx+74],2
00444C3D  |.  8B55 08       mov edx,[ebp+8]
00444C40  |.  C742 68 00000 mov dword ptr [edx+68],0
00444C47  |.  8B45 08       mov eax,[ebp+8]
00444C4A  |.  C740 78 00000 mov dword ptr [eax+78],0
00444C51  \>  E9 9E020000   jmp 00444EF4
00444C56  />  8B4D 08       mov ecx,[ebp+8]
00444C59  |.  8B51 78       mov edx,[ecx+78]
00444C5C  |.  83C2 01       add edx,1
00444C5F  |.  8B45 08       mov eax,[ebp+8]
00444C62  |.  8950 78       mov [eax+78],edx
00444C65  |.  8B4D 08       mov ecx,[ebp+8]
00444C68  |.  8379 78 08    cmp dword ptr [ecx+78],8
00444C6C  |.  7E 4E         jle short 00444CBC
00444C6E  |.  8B55 08       mov edx,[ebp+8]
00444C71  |.  C742 74 03000 mov dword ptr [edx+74],3
00444C78  |.  8B45 08       mov eax,[ebp+8]
00444C7B  |.  C740 68 02000 mov dword ptr [eax+68],2
00444C82  |.  8B4D 08       mov ecx,[ebp+8]
00444C85  |.  C741 14 01FAF mov dword ptr [ecx+14],-5FF
00444C8C  |.  6A 01         push 1                                   ; /Arg2 = 1
00444C8E  |.  6A 1E         push 1E                                  ; |Arg1 = 1E
00444C90  |.  E8 ABB9FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444C95  |.  83C4 08       add esp,8
00444C98  |.  8B55 08       mov edx,[ebp+8]
00444C9B  |.  8B42 08       mov eax,[edx+8]
00444C9E  |.  3B05 54E64900 cmp eax,[49E654]
00444CA4  |.  7E 0C         jle short 00444CB2
00444CA6  |.  8B4D 08       mov ecx,[ebp+8]
00444CA9  |.  C741 4C 00000 mov dword ptr [ecx+4C],0
00444CB0  |.  EB 0A         jmp short 00444CBC
00444CB2  |>  8B55 08       mov edx,[ebp+8]
00444CB5  |.  C742 4C 02000 mov dword ptr [edx+4C],2
00444CBC  \>  E9 33020000   jmp 00444EF4
00444CC1  />  8B45 08       mov eax,[ebp+8]
00444CC4  |.  8178 14 00010 cmp dword ptr [eax+14],100
00444CCB  |.  7E 34         jle short 00444D01
00444CCD  |.  8B4D 08       mov ecx,[ebp+8]
00444CD0  |.  8B55 08       mov edx,[ebp+8]
00444CD3  |.  8B42 0C       mov eax,[edx+0C]
00444CD6  |.  8941 24       mov [ecx+24],eax
00444CD9  |.  8B4D 08       mov ecx,[ebp+8]
00444CDC  |.  C741 74 04000 mov dword ptr [ecx+74],4
00444CE3  |.  8B55 08       mov edx,[ebp+8]
00444CE6  |.  C742 68 03000 mov dword ptr [edx+68],3
00444CED  |.  8B45 08       mov eax,[ebp+8]
00444CF0  |.  C740 78 00000 mov dword ptr [eax+78],0
00444CF7  |.  8B4D 08       mov ecx,[ebp+8]
00444CFA  |.  C741 78 00000 mov dword ptr [ecx+78],0
00444D01  \>  E9 EE010000   jmp 00444EF4
00444D06  />  8B55 08       mov edx,[ebp+8]
00444D09  |.  8B42 08       mov eax,[edx+8]
00444D0C  |.  3B05 54E64900 cmp eax,[49E654]
00444D12  |.  7D 0C         jge short 00444D20
00444D14  |.  8B4D 08       mov ecx,[ebp+8]
00444D17  |.  C741 4C 02000 mov dword ptr [ecx+4C],2
00444D1E  |.  EB 0A         jmp short 00444D2A
00444D20  |>  8B55 08       mov edx,[ebp+8]
00444D23  |.  C742 4C 00000 mov dword ptr [edx+4C],0
00444D2A  |>  8B45 08       mov eax,[ebp+8]
00444D2D  |.  8B48 78       mov ecx,[eax+78]
00444D30  |.  83C1 01       add ecx,1
00444D33  |.  8B55 08       mov edx,[ebp+8]
00444D36  |.  894A 78       mov [edx+78],ecx
00444D39  |.  8B45 08       mov eax,[ebp+8]
00444D3C  |.  8B48 04       mov ecx,[eax+4]
00444D3F  |.  83E1 07       and ecx,00000007
00444D42  |.  75 09         jne short 00444D4D
00444D44  |.  8B55 08       mov edx,[ebp+8]
00444D47  |.  837A 78 3C    cmp dword ptr [edx+78],3C
00444D4B  |.  7E 26         jle short 00444D73
00444D4D  |>  8B45 08       mov eax,[ebp+8]
00444D50  |.  C780 A4000000 mov dword ptr [eax+0A4],3
00444D5A  |.  8B4D 08       mov ecx,[ebp+8]
00444D5D  |.  C741 74 05000 mov dword ptr [ecx+74],5
00444D64  |.  8B55 08       mov edx,[ebp+8]
00444D67  |.  C742 68 02000 mov dword ptr [edx+68],2
00444D6E  |.  E9 81010000   jmp 00444EF4
00444D73  |>  8B45 08       mov eax,[ebp+8]
00444D76  |.  8B48 78       mov ecx,[eax+78]
00444D79  |.  81E1 03000080 and ecx,80000003
00444D7F  |.  79 05         jns short 00444D86
00444D81  |.  49            dec ecx
00444D82  |.  83C9 FC       or ecx,FFFFFFFC
00444D85  |.  41            inc ecx
00444D86  |>  83F9 01       cmp ecx,1
00444D89  |.  75 0C         jne short 00444D97
00444D8B  |.  6A 01         push 1                                   ; /Arg2 = 1
00444D8D  |.  6A 6D         push 6D                                  ; |Arg1 = 6D
00444D8F  |.  E8 ACB8FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444D94  |.  83C4 08       add esp,8
00444D97  |>  8B55 08       mov edx,[ebp+8]
00444D9A  |.  8B42 04       mov eax,[edx+4]
00444D9D  |.  83E0 08       and eax,00000008
00444DA0  |.  74 0A         je short 00444DAC
00444DA2  |.  8B4D 08       mov ecx,[ebp+8]
00444DA5  |.  C741 14 00FEF mov dword ptr [ecx+14],-200
00444DAC  |>  8B55 08       mov edx,[ebp+8]
00444DAF  |.  8B42 78       mov eax,[edx+78]
00444DB2  |.  99            cdq
00444DB3  |.  B9 1E000000   mov ecx,1E
00444DB8  |.  F7F9          idiv ecx
00444DBA  |.  83FA 06       cmp edx,6
00444DBD  |.  0F85 9F000000 jne 00444E62
00444DC3  |.  8B55 08       mov edx,[ebp+8]
00444DC6  |.  8B42 0C       mov eax,[edx+0C]
00444DC9  |.  2B05 58E64900 sub eax,[49E658]
00444DCF  |.  50            push eax
00444DD0  |.  8B4D 08       mov ecx,[ebp+8]
00444DD3  |.  8B51 08       mov edx,[ecx+8]
00444DD6  |.  2B15 54E64900 sub edx,[49E654]
00444DDC  |.  52            push edx
00444DDD  |.  E8 FE0AFEFF   call 004258E0
00444DE2  |.  83C4 08       add esp,8
00444DE5  |.  8845 FF       mov [ebp-1],al
00444DE8  |.  6A 06         push 6                                   ; /Arg2 = 6
00444DEA  |.  6A FA         push -6                                  ; |Arg1 = -6
00444DEC  |.  E8 5FA5FCFF   call 0040F350                            ; \Doukutsu_-_Copy.0040F350
00444DF1  |.  83C4 08       add esp,8
00444DF4  |.  0FB6C0        movzx eax,al
00444DF7  |.  0FB64D FF     movzx ecx,byte ptr [ebp-1]
00444DFB  |.  03C8          add ecx,eax
00444DFD  |.  884D FF       mov [ebp-1],cl
00444E00  |.  8A55 FF       mov dl,[ebp-1]
00444E03  |.  52            push edx                                 ; /Arg1
00444E04  |.  E8 A70AFEFF   call 004258B0                            ; \Doukutsu_-_Copy.004258B0
00444E09  |.  83C4 04       add esp,4
00444E0C  |.  6BC0 03       imul eax,eax,3
00444E0F  |.  8985 2CFFFFFF mov [ebp-0D4],eax
00444E15  |.  8A45 FF       mov al,[ebp-1]
00444E18  |.  50            push eax                                 ; /Arg1
00444E19  |.  E8 A20AFEFF   call 004258C0                            ; \Doukutsu_-_Copy.004258C0
00444E1E  |.  83C4 04       add esp,4
00444E21  |.  6BC0 03       imul eax,eax,3
00444E24  |.  8945 94       mov [ebp-6C],eax
00444E27  |.  68 00010000   push 100                                 ; /Arg8 = 100
00444E2C  |.  6A 00         push 0                                   ; |Arg7 = 0
00444E2E  |.  6A 00         push 0                                   ; |Arg6 = 0
00444E30  |.  8B8D 2CFFFFFF mov ecx,[ebp-0D4]                        ; |
00444E36  |.  51            push ecx                                 ; |Arg5
00444E37  |.  8B55 94       mov edx,[ebp-6C]                         ; |
00444E3A  |.  52            push edx                                 ; |Arg4
00444E3B  |.  8B45 08       mov eax,[ebp+8]                          ; |
00444E3E  |.  8B48 0C       mov ecx,[eax+0C]                         ; |
00444E41  |.  51            push ecx                                 ; |Arg3
00444E42  |.  8B55 08       mov edx,[ebp+8]                          ; |
00444E45  |.  8B42 08       mov eax,[edx+8]                          ; |
00444E48  |.  50            push eax                                 ; |Arg2
00444E49  |.  68 94000000   push 94                                  ; |Arg1 = 94
00444E4E  |.  E8 7DA10200   call 0046EFD0                            ; \Doukutsu_-_Copy.0046EFD0
00444E53  |.  83C4 20       add esp,20
00444E56  |.  6A 01         push 1                                   ; /Arg2 = 1
00444E58  |.  6A 27         push 27                                  ; |Arg1 = 27
00444E5A  |.  E8 E1B7FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444E5F  |.  83C4 08       add esp,8
00444E62  |>  8B4D 08       mov ecx,[ebp+8]
00444E65  |.  8B51 64       mov edx,[ecx+64]
00444E68  |.  83C2 01       add edx,1
00444E6B  |.  8B45 08       mov eax,[ebp+8]
00444E6E  |.  8950 64       mov [eax+64],edx
00444E71  |.  8B4D 08       mov ecx,[ebp+8]
00444E74  |.  8379 64 00    cmp dword ptr [ecx+64],0
00444E78  |.  7E 19         jle short 00444E93
00444E7A  |.  8B55 08       mov edx,[ebp+8]
00444E7D  |.  C742 64 00000 mov dword ptr [edx+64],0
00444E84  |.  8B45 08       mov eax,[ebp+8]
00444E87  |.  8B48 68       mov ecx,[eax+68]
00444E8A  |.  83C1 01       add ecx,1
00444E8D  |.  8B55 08       mov edx,[ebp+8]
00444E90  |.  894A 68       mov [edx+68],ecx
00444E93  |>  8B45 08       mov eax,[ebp+8]
00444E96  |.  8378 68 05    cmp dword ptr [eax+68],5
00444E9A  |.  7E 0A         jle short 00444EA6
00444E9C  |.  8B4D 08       mov ecx,[ebp+8]
00444E9F  |.  C741 68 03000 mov dword ptr [ecx+68],3
00444EA6  \>  EB 4C         jmp short 00444EF4
00444EA8  />  8B55 08       mov edx,[ebp+8]
00444EAB  |.  8B42 04       mov eax,[edx+4]
00444EAE  |.  83E0 08       and eax,00000008
00444EB1  |.  74 41         je short 00444EF4
00444EB3  |.  8B4D 08       mov ecx,[ebp+8]
00444EB6  |.  C781 A4000000 mov dword ptr [ecx+0A4],2
00444EC0  |.  8B55 08       mov edx,[ebp+8]
00444EC3  |.  C742 10 00000 mov dword ptr [edx+10],0
00444ECA  |.  8B45 08       mov eax,[ebp+8]
00444ECD  |.  C740 78 00000 mov dword ptr [eax+78],0
00444ED4  |.  8B4D 08       mov ecx,[ebp+8]
00444ED7  |.  C741 68 00000 mov dword ptr [ecx+68],0
00444EDE  |.  8B55 08       mov edx,[ebp+8]
00444EE1  |.  C742 74 01000 mov dword ptr [edx+74],1
00444EE8  |.  6A 01         push 1                                   ; /Arg2 = 1
00444EEA  |.  6A 17         push 17                                  ; |Arg1 = 17
00444EEC  |.  E8 4FB7FDFF   call 00420640                            ; \Doukutsu_-_Copy.00420640
00444EF1  |.  83C4 08       add esp,8
00444EF4  |>  8B45 08       mov eax,[ebp+8]
00444EF7  |.  8378 74 04    cmp dword ptr [eax+74],4
00444EFB  |.  74 2A         je short 00444F27
00444EFD  |.  8B4D 08       mov ecx,[ebp+8]
00444F00  |.  8B51 14       mov edx,[ecx+14]
00444F03  |.  83C2 20       add edx,20
00444F06  |.  8B45 08       mov eax,[ebp+8]
00444F09  |.  8950 14       mov [eax+14],edx
00444F0C  |.  8B4D 08       mov ecx,[ebp+8]
00444F0F  |.  8179 14 FF050 cmp dword ptr [ecx+14],5FF
00444F16  |.  7E 0A         jle short 00444F22
00444F18  |.  8B55 08       mov edx,[ebp+8]
00444F1B  |.  C742 14 FF050 mov dword ptr [edx+14],5FF
00444F22  |>  E9 86000000   jmp 00444FAD
00444F27  |>  8B45 08       mov eax,[ebp+8]
00444F2A  |.  8B4D 08       mov ecx,[ebp+8]
00444F2D  |.  8B50 0C       mov edx,[eax+0C]
00444F30  |.  3B51 24       cmp edx,[ecx+24]
00444F33  |.  7E 11         jle short 00444F46
00444F35  |.  8B45 08       mov eax,[ebp+8]
00444F38  |.  8B48 14       mov ecx,[eax+14]
00444F3B  |.  83E9 10       sub ecx,10
00444F3E  |.  8B55 08       mov edx,[ebp+8]
00444F41  |.  894A 14       mov [edx+14],ecx
00444F44  |.  EB 0F         jmp short 00444F55
00444F46  |>  8B45 08       mov eax,[ebp+8]
00444F49  |.  8B48 14       mov ecx,[eax+14]
00444F4C  |.  83C1 10       add ecx,10
00444F4F  |.  8B55 08       mov edx,[ebp+8]
00444F52  |.  894A 14       mov [edx+14],ecx
00444F55  |>  8B45 08       mov eax,[ebp+8]
00444F58  |.  8178 14 00020 cmp dword ptr [eax+14],200
00444F5F  |.  7E 0A         jle short 00444F6B
00444F61  |.  8B4D 08       mov ecx,[ebp+8]
00444F64  |.  C741 14 00020 mov dword ptr [ecx+14],200
00444F6B  |>  8B55 08       mov edx,[ebp+8]
00444F6E  |.  817A 14 00FEF cmp dword ptr [edx+14],-200
00444F75  |.  7D 0A         jge short 00444F81
00444F77  |.  8B45 08       mov eax,[ebp+8]
00444F7A  |.  C740 14 00FEF mov dword ptr [eax+14],-200
00444F81  |>  8B4D 08       mov ecx,[ebp+8]
00444F84  |.  8179 10 00020 cmp dword ptr [ecx+10],200
00444F8B  |.  7E 0A         jle short 00444F97
00444F8D  |.  8B55 08       mov edx,[ebp+8]
00444F90  |.  C742 10 00020 mov dword ptr [edx+10],200
00444F97  |>  8B45 08       mov eax,[ebp+8]
00444F9A  |.  8178 10 00FEF cmp dword ptr [eax+10],-200
00444FA1  |.  7D 0A         jge short 00444FAD
00444FA3  |.  8B4D 08       mov ecx,[ebp+8]
00444FA6  |.  C741 10 00FEF mov dword ptr [ecx+10],-200
00444FAD  |>  8B55 08       mov edx,[ebp+8]
00444FB0  |.  8B42 08       mov eax,[edx+8]
00444FB3  |.  8B4D 08       mov ecx,[ebp+8]
00444FB6  |.  0341 10       add eax,[ecx+10]
00444FB9  |.  8B55 08       mov edx,[ebp+8]
00444FBC  |.  8942 08       mov [edx+8],eax
00444FBF  |.  8B45 08       mov eax,[ebp+8]
00444FC2  |.  8B48 0C       mov ecx,[eax+0C]
00444FC5  |.  8B55 08       mov edx,[ebp+8]
00444FC8  |.  034A 14       add ecx,[edx+14]
00444FCB  |.  8B45 08       mov eax,[ebp+8]
00444FCE  |.  8948 0C       mov [eax+0C],ecx
00444FD1  |.  8B4D 08       mov ecx,[ebp+8]
00444FD4  |.  8379 4C 00    cmp dword ptr [ecx+4C],0
00444FD8  |.  75 2B         jne short 00445005
00444FDA  |.  8B55 08       mov edx,[ebp+8]
00444FDD  |.  8B42 68       mov eax,[edx+68]
00444FE0  |.  C1E0 04       shl eax,4
00444FE3  |.  8D4C05 98     lea ecx,[eax+ebp-68]
00444FE7  |.  8B55 08       mov edx,[ebp+8]
00444FEA  |.  83C2 54       add edx,54
00444FED  |.  8B01          mov eax,[ecx]
00444FEF  |.  8902          mov [edx],eax
00444FF1  |.  8B41 04       mov eax,[ecx+4]
00444FF4  |.  8942 04       mov [edx+4],eax
00444FF7  |.  8B41 08       mov eax,[ecx+8]
00444FFA  |.  8942 08       mov [edx+8],eax
00444FFD  |.  8B49 0C       mov ecx,[ecx+0C]
00445000  |.  894A 0C       mov [edx+0C],ecx
00445003  |.  EB 2C         jmp short 00445031
00445005  |>  8B55 08       mov edx,[ebp+8]
00445008  |.  8B42 68       mov eax,[edx+68]
0044500B  |.  C1E0 04       shl eax,4
0044500E  |.  8D8C05 30FFFF lea ecx,[eax+ebp-0D0]
00445015  |.  8B55 08       mov edx,[ebp+8]
00445018  |.  83C2 54       add edx,54
0044501B  |.  8B01          mov eax,[ecx]
0044501D  |.  8902          mov [edx],eax
0044501F  |.  8B41 04       mov eax,[ecx+4]
00445022  |.  8942 04       mov [edx+4],eax
00445025  |.  8B41 08       mov eax,[ecx+8]
00445028  |.  8942 08       mov [edx+8],eax
0044502B  |.  8B49 0C       mov ecx,[ecx+0C]
0044502E  |.  894A 0C       mov [edx+0C],ecx
00445031  |>  8BE5          mov esp,ebp
00445033  |.  5D            pop ebp
00445034  \.  C3            retn
00445035   .  EB4A4400      dd 00444AEB
00445039   .  074B4400      dd 00444B07
0044503D   .  564C4400      dd 00444C56
00445041   .  C14C4400      dd 00444CC1
00445045   .  064D4400      dd 00444D06
00445049   .  A84E4400      dd 00444EA8
This is the code for the purple critter that shoots stuff. If you can make sense of this, then you can probably figure out anything you need to put together basic NPCs from scratch apart from the few technical details of implemenetation.

As far as the other questions go, generally you can't add more NPCs than the number that are already in the game. You just hijack the function of an existing one that you aren't going to use (and don't give me that bs of "i wanna use all of them", you wont). It *is* possible but that's a bit more complex and requires an understanding of some of the systems around the NPCs that make them go and I don't want to explain it right now.
ok, here it goes

~Debug Cat~
CPU Disasm
Address Hex dump Command Comments
004517F0 /$ 55 push ebp pushes onto the stack
004517F1 |. 8BEC mov ebp,esp start of the
004517F3 |. 83EC 10 sub esp,10 code
004517F6 |. C745 F0 00010 mov dword ptr [local.4],100 framarect, left border
004517FD |. C745 F4 C0000 mov dword ptr [local.3],0C0 framarect, upper border
00451804 |. C745 F8 10010 mov dword ptr [local.2],110 framarect, right border
0045180B |. C745 FC D8000 mov dword ptr [local.1],0D8 framarect, lower border
00451812 |. 8B45 08 mov eax,[arg.1] stores 8B45 in EAX for arg. 1 *
00451815 |. 83C0 54 add eax,54 adds 54 to EAX for arg. 1
00451818 |. 8B4D F0 mov ecx,[local.4] stores local variable into ECX
0045181B |. 8908 mov [eax],ecx store the value of EAX into ECX
0045181D |. 8B55 F4 mov edx,[local.3] stores local variable into ECX
00451820 |. 8950 04 mov [eax+4],edx obj. variable event collision stored at EDX
00451823 |. 8B4D F8 mov ecx,[local.2] stores local variable into ECX
00451826 |. 8948 08 mov [eax+8],ecx obj. variable event X position stored at EDX
00451829 |. 8B55 FC mov edx,[local.1] stores locav variable into ECX
0045182C |. 8950 0C mov [eax+0C],edx obj. variable event Y position stores at EDX
0045182F |. 8BE5 mov esp,ebp undo what was done up top
00451831 |. 5D pop ebp pop's what was pushed
00451832 \. C3 retn return to previous address (where
CALL command came from)



* argument one is facing to the left no other arguments are present so we have an only facing left NPC.

~Shovel brigade~
CPU Disasm
Address Hex dump Command Comments
00451E90 /$ 55 push ebp pushes onto the stack
00451E91 |. 8BEC mov ebp,esp start of the
00451E93 |. 83EC 44 sub esp,44 code
00451E96 |. C745 E0 00000 mov dword ptr [local.8],0 L border sprite 1
00451E9D |. C745 E4 40000 mov dword ptr [local.7],40 U border sprite 1
00451EA4 |. C745 E8 10000 mov dword ptr [local.6],10 R border sprite 1
00451EAB |. C745 EC 50000 mov dword ptr [local.5],50 D border sprite 1
00451EB2 |. C745 F0 10000 mov dword ptr [local.4],10 L border sprite 2
00451EB9 |. C745 F4 40000 mov dword ptr [local.3],40 ect.
00451EC0 |. C745 F8 20000 mov dword ptr [local.2],20 ect.
00451EC7 |. C745 FC 50000 mov dword ptr [local.1],50 ect.
00451ECE |. C745 C0 00000 mov dword ptr [local.16],0
00451ED5 |. C745 C4 50000 mov dword ptr [local.15],50
00451EDC |. C745 C8 10000 mov dword ptr [local.14],10
00451EE3 |. C745 CC 60000 mov dword ptr [local.13],60
00451EEA |. C745 D0 10000 mov dword ptr [local.12],10
00451EF1 |. C745 D4 50000 mov dword ptr [local.11],50
00451EF8 |. C745 D8 20000 mov dword ptr [local.10],20
00451EFF |. C745 DC 60000 mov dword ptr [local.9],60 end of framarects
00451F06 |. 8B45 08 mov eax,[arg.1] move argument 1 into EAX
00451F09 |. 8B48 74 mov ecx,[eax+74] obj. variable event script state stored at EDX
00451F0C |. 894D BC mov [local.17],ecx stores local variable into ECX
00451F0F |. 837D BC 00 cmp dword ptr [local.17],0 is the value zero?
00451F13 |. 74 0E je short 00451F23 if so, go to 00451F23.
00451F15 |. 837D BC 01 cmp dword ptr [local.17],1 is the value one?
00451F19 |. 74 26 je short 00451F41 if so, go to 00451F41.
00451F1B |. 837D BC 02 cmp dword ptr [local.17],2 is the value two?
00451F1F |. 74 51 je short 00451F72 if so, go to 00451F72,
00451F21 |. EB 7B jmp short 00451F9E then to 00451F9E
00451F23 |> 8B55 08 mov edx,[arg.1] if not, store value of arg. 1 to EDX
00451F26 |. C742 74 01000 mov dword ptr [edx+74],1 obj. variable script state stored at EDX
00451F2D |. 8B45 08 mov eax,[arg.1] stores variable for arg. 1 at EAX
00451F30 |. C740 68 00000 mov dword ptr [eax+68],0 obj. variable frame num stored at EDX
00451F37 |. 8B4D 08 mov ecx,[arg.1] stores variable for arg. 1 ar EAX
00451F3A |. C741 64 00000 mov dword ptr [ecx+64],0 obj. variable frame timer stored at EDX
00451F41 |> 6A 78 push 78 ; /Arg2 = 78
00451F43 |. 6A 00 push 0 ; |Arg1 = 0
00451F45 |. E8 06D4FBFF call 0040F350 apply coding at 0040F350 here.
00451F4A |. 83C4 08 add esp,8 add 8 to above coding through pointer ESP
00451F4D |. 83F8 0A cmp eax,0A is the value 0A?
00451F50 |. 75 1E jne short 00451F70 if so go to 00451F70
00451F52 |. 8B55 08 mov edx,[arg.1] if not, store value for arg. 1 to EDX
00451F55 |. C742 74 02000 mov dword ptr [edx+74],2 obj. variable script state stored at EDX
00451F5C |. 8B45 08 mov eax,[arg.1] stores variable for arg. 1 at EAX
00451F5F |. C740 78 00000 mov dword ptr [eax+78],0 obj. variable script timer stored at EAX
00451F66 |. 8B4D 08 mov ecx,[arg.1] stores variable for arg. 1 at EVX
00451F69 |. C741 68 01000 mov dword ptr [ecx+68],1 obj. variable frame number stored at ECX
00451F70 |> EB 2C jmp short 00451F9E
00451F72 |> 8B55 08 mov edx,[arg.1]
00451F75 |. 8B42 78 mov eax,[edx+78]
00451F78 |. 83C0 01 add eax,1
00451F7B |. 8B4D 08 mov ecx,[arg.1]
00451F7E |. 8941 78 mov [ecx+78],eax
00451F81 |. 8B55 08 mov edx,[arg.1]
00451F84 |. 837A 78 08 cmp dword ptr [edx+78],8
00451F88 |. 7E 14 jle short 00451F9E
00451F8A |. 8B45 08 mov eax,[arg.1]
00451F8D |. C740 74 01000 mov dword ptr [eax+74],1
00451F94 |. 8B4D 08 mov ecx,[arg.1]
00451F97 |. C741 68 00000 mov dword ptr [ecx+68],0
00451F9E |> 8B55 08 mov edx,[arg.1]
00451FA1 |. 837A 4C 00 cmp dword ptr [edx+4C],0
00451FA5 |. 75 2B jne short 00451FD2
00451FA7 |. 8B45 08 mov eax,[arg.1]
00451FAA |. 8B48 68 mov ecx,[eax+68]
00451FAD |. C1E1 04 shl ecx,4
00451FB0 |. 8D540D E0 lea edx,[ecx+ebp-20]
00451FB4 |. 8B45 08 mov eax,[arg.1]
00451FB7 |. 83C0 54 add eax,54
00451FBA |. 8B0A mov ecx,[edx]
00451FBC |. 8908 mov [eax],ecx
00451FBE |. 8B4A 04 mov ecx,[edx+4]
00451FC1 |. 8948 04 mov [eax+4],ecx
00451FC4 |. 8B4A 08 mov ecx,[edx+8]
00451FC7 |. 8948 08 mov [eax+8],ecx
00451FCA |. 8B52 0C mov edx,[edx+0C]
00451FCD |. 8950 0C mov [eax+0C],edx
00451FD0 |. EB 29 jmp short 00451FFB
00451FD2 |> 8B45 08 mov eax,[arg.1]
00451FD5 |. 8B48 68 mov ecx,[eax+68]
00451FD8 |. C1E1 04 shl ecx,4
00451FDB |. 8D540D C0 lea edx,[ecx+ebp-40]
00451FDF |. 8B45 08 mov eax,[arg.1]
00451FE2 |. 83C0 54 add eax,54
00451FE5 |. 8B0A mov ecx,[edx]
00451FE7 |. 8908 mov [eax],ecx
00451FE9 |. 8B4A 04 mov ecx,[edx+4]
00451FEC |. 8948 04 mov [eax+4],ecx
00451FEF |. 8B4A 08 mov ecx,[edx+8]
00451FF2 |. 8948 08 mov [eax+8],ecx
00451FF5 |. 8B52 0C mov edx,[edx+0C]
00451FF8 |. 8950 0C mov [eax+0C],edx
00451FFB |> 8BE5 mov esp,ebp undo what was done up top
00451FFD |. 5D pop ebp pop's what was pushed
00451FFE \. C3 retn return to previous CALL command




just posting my progress just so I don't lose it.
 
May 26, 2013 at 6:43 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Pronouns: he/him
You've got the "literal" meaning for the first one, but I kind of want you to comment on what it does in terms of the game. Code commenting basics, literal comments don't help anybody.
 
May 26, 2013 at 8:24 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
Noxid said:
You've got the "literal" meaning for the first one, but I kind of want you to comment on what it does in terms of the game. Code commenting basics, literal comments don't help anybody.
well that's kind of the thing. . . I don't understand exactly what that does. :/

I know what

push ebp
mov ebp,esp
sub esp,10

and

mov esp,ebp
pop ebp
retn


means, (along with why we mov esp before ebp at the end)

and the framarects. .

004517F6 |. C745 F0 00010 mov dword ptr [local.4],100
004517FD |. C745 F4 C0000 mov dword ptr [local.3],0C0
00451804 |. C745 F8 10010 mov dword ptr [local.2],110
0045180B |. C745 FC D8000 mov dword ptr [local.1],0D8



and the whole collision, and X/Y location. . .

00451812 |. 8B45 08 mov eax,[arg.1]
00451815 |. 83C0 54 add eax,54
00451818 |. 8B4D F0 mov ecx,[local.4]
0045181B |. 8908 mov [eax],ecx
0045181D |. 8B55 F4 mov edx,[local.3]
00451820 |. 8950 04 mov [eax+4],edx
00451823 |. 8B4D F8 mov ecx,[local.2]
00451826 |. 8948 08 mov [eax+8],ecx
00451829 |. 8B55 FC mov edx,[local.1]
0045182C |. 8950 0C mov [eax+0C],edx



In other words, I know WHAT is going on, but not WHY it is happening. :(
 
May 26, 2013 at 8:50 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Pronouns: he/him
Actually the last bit has nothing to do with collision, that is what sets the framerects.
I assume you have
Code:
# NPC Stuff [MISCNPC]

004A6220/4a5F98 0xAC, 0x0200
+0x00: Event.InUse 	(N)	; is the event active? 0 kills.
+0x04: Event.Collision	(N)	; flag to show what it's colliding w/
+0x08: Event.X 		(N)	; Position [x]
+0x0C: Event.Y		(N)	; Poxition [y]
+0x10: Event.MoveX		; xvel, add to event.x each step
+0x14: Event.MoveY		; yvel
+0x18: Event.AltVel		; 
+0x1C: Event.AltVel		; 
+0x20: Event.Unknown1		; For entities such as curly that use
+0x24: Event.Unknown2		; the targeting macro.
+0x28: Event.NPCID       (N)	; sprite #
+0x2C: Event.EntityID	 (N)	; Entity ID, as seen in CE
+0x30: Event.EventNum    (N)	; Event #, as seen in CE
+0x34: Event.Tileset     (N)	; The tileset # as seen in a NPC.tbl editor
+0x38: Event.HurtSound   (N)	;
+0x3C: Event.DeathSound  (N)	;
+0x40: Event.Health      (N)	; health/damagetaken
+0x44: Event.EXP	 (N)	; EXP dropped
+0x48: Event.Size(N)	;
+0x4C: Event.Direction   (N)	;
+0x50: Event.Flags       (N)	; Entity flags
+0x54: Event.Frame_L   (N)	; left side of the frame rect
+0x58: Event.Frame_U   (N)	; top side of the frame rect
+0x5C: Event.Frame_R   (N)	; right side of the frame rect 
+0x60: Event.Frame_D   (N)	; bottom side of the frame rect 
+0x64: Event.FrameTimer		;
+0x68: Event.FrameNum		;
+0x6C: Event.ObjectTimer	;
+0x70: Event.Directive		; Usually something from the parent.
+0x74: Event.ScriptState	;	
+0x78: Event.ScriptTimer	;
+0x7C: Event.HitRect_L	(N)	;
+0x80: Event.HitRect_U	(N)	;
+0x84: Event.HitRect_R	(N)	;	
+0x88: Event.HitRect_D	(N)	;
+0x8C: Event.Display_L  (N)	; Used to calc. how far left/right to offset the sprite when displaying
+0x90: Event.Display_U  (N)	; Used to calc. how far up/down to offset the sprite when displaying
+0x94: Event.Display_R  (N)	; Sometimes used as the radius of the entity for making smoke appear from it
+0x98: Event.Display_D  (N)	; no known use
+0x9c: Event.HitTrue	[N]	; Has the entity been Hit?
+0xA0: Event.DamageTaken(N)	; Damage displayed by damage numbers
+0xA4: Event.Damage	(N)	; Damage done to Player
+0xA8: Event.Parent	[N]	; It's like the ebp+8 of the parent entity.
So, when we get [arg.1] into eax, that's the pointer to the entity at +00.
00451815 |. 83C0 54 add eax,54
adds to the pointer, so our new base address is
+0x54: Event.Frame_L (N) ; left side of the frame rect
then it proceeds to set the value of each of the rects (left, up, right, down) with the values intialized in the local varaibles at the start of the function. If you really wanted to be efficient you could just skip putting them in locals, it's not necessary. So now describe it in terms of what each line means (i.e. "this stores the left side of the framerect into a local variable" "this sets the pointer to the address of the framerects"
 
Jun 9, 2013 at 2:53 AM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
Noxid said:
Actually the last bit has nothing to do with collision, that is what sets the framerects.
I assume you have
Code:
# NPC Stuff [MISCNPC]

004A6220/4a5F98 0xAC, 0x0200
+0x00: Event.InUse 	(N)	; is the event active? 0 kills.
+0x04: Event.Collision	(N)	; flag to show what it's colliding w/
+0x08: Event.X 		(N)	; Position [x]
+0x0C: Event.Y		(N)	; Poxition [y]
+0x10: Event.MoveX		; xvel, add to event.x each step
+0x14: Event.MoveY		; yvel
+0x18: Event.AltVel		; 
+0x1C: Event.AltVel		; 
+0x20: Event.Unknown1		; For entities such as curly that use
+0x24: Event.Unknown2		; the targeting macro.
+0x28: Event.NPCID       (N)	; sprite #
+0x2C: Event.EntityID	 (N)	; Entity ID, as seen in CE
+0x30: Event.EventNum    (N)	; Event #, as seen in CE
+0x34: Event.Tileset     (N)	; The tileset # as seen in a NPC.tbl editor
+0x38: Event.HurtSound   (N)	;
+0x3C: Event.DeathSound  (N)	;
+0x40: Event.Health      (N)	; health/damagetaken
+0x44: Event.EXP	 (N)	; EXP dropped
+0x48: Event.Size(N)	;
+0x4C: Event.Direction   (N)	;
+0x50: Event.Flags       (N)	; Entity flags
+0x54: Event.Frame_L   (N)	; left side of the frame rect
+0x58: Event.Frame_U   (N)	; top side of the frame rect
+0x5C: Event.Frame_R   (N)	; right side of the frame rect 
+0x60: Event.Frame_D   (N)	; bottom side of the frame rect 
+0x64: Event.FrameTimer		;
+0x68: Event.FrameNum		;
+0x6C: Event.ObjectTimer	;
+0x70: Event.Directive		; Usually something from the parent.
+0x74: Event.ScriptState	;	
+0x78: Event.ScriptTimer	;
+0x7C: Event.HitRect_L	(N)	;
+0x80: Event.HitRect_U	(N)	;
+0x84: Event.HitRect_R	(N)	;	
+0x88: Event.HitRect_D	(N)	;
+0x8C: Event.Display_L  (N)	; Used to calc. how far left/right to offset the sprite when displaying
+0x90: Event.Display_U  (N)	; Used to calc. how far up/down to offset the sprite when displaying
+0x94: Event.Display_R  (N)	; Sometimes used as the radius of the entity for making smoke appear from it
+0x98: Event.Display_D  (N)	; no known use
+0x9c: Event.HitTrue	[N]	; Has the entity been Hit?
+0xA0: Event.DamageTaken(N)	; Damage displayed by damage numbers
+0xA4: Event.Damage	(N)	; Damage done to Player
+0xA8: Event.Parent	[N]	; It's like the ebp+8 of the parent entity.
So, when we get [arg.1] into eax, that's the pointer to the entity at +00.
00451815 |. 83C0 54 add eax,54
adds to the pointer, so our new base address is
+0x54: Event.Frame_L (N) ; left side of the frame rect
then it proceeds to set the value of each of the rects (left, up, right, down) with the values intialized in the local varaibles at the start of the function. If you really wanted to be efficient you could just skip putting them in locals, it's not necessary. So now describe it in terms of what each line means (i.e. "this stores the left side of the framerect into a local variable" "this sets the pointer to the address of the framerects"




Yes, I do have that, and I was consulting to it.



~Debug Cat~


CPU Disasm
Address Hex dump Command Comments
004517F0 /$ 55 push ebp PUSHes on to the stack004517F1 |. 8BEC mov ebp,esp starts the
004517F3 |. 83EC 10 sub esp,10 code
004517F6 |. C745 F0 00010 mov dword ptr [local.4],100 framarects004517FD |. C745 F4 C0000 mov dword ptr [local.3],0C000451804 |. C745 F8 10010 mov dword ptr [local.2],1100045180B |. C745 FC D8000 mov dword ptr [local.1],0D8
00451812 |. 8B45 08 mov eax,[arg.1] this begins argument 1
00451815 |. 83C0 54 add eax,54 holds 54 in EAX 00451818 |. 8B4D F0 mov ecx,[local.4] stores the local variable into the ECX
0045181B |. 8908 mov [eax],ecx takes 54 from the EAX and adds it to the argument and runs event Frame_L (N) to recognize that it is the left side on the NPC
0045181D |. 8B55 F4 mov edx,[local.3] stores the local variable into the EDX00451820 |. 8950 04 mov [eax+4],edx Takes +4 (04)from the EAX and adds it to the argument and runs event Collision (N) to recognize what the NPC is colliding with 00451823 |. 8B4D F8 mov ecx,[local.2] stores the local variable into the ECX
00451826 |. 8948 08 mov [eax+8],ecx Takes 08 from the EXC and adds it to the argument and runs
event X (N) to realize the horizional position of the sprite *1 00451829 |. 8B55 FC mov edx,[local.1] stores the local variable into the EDX
0045182C |. 8950 0C mov [eax+0C],edx Takes 0C from the EDX and adds it to the argument and runs event Y (N) to realize the vertical position of the sprite *1
0045182F |. 8BE5 mov esp,ebp
00451831 |. 5D pop ebp
00451832 \. C3 retn



~Shovel brigade~


CPU Disasm
Address Hex dump Command Comments
00451E90 /$ 55 push ebp
00451E91 |. 8BEC mov ebp,esp
Beginning of ze' code
00451E93 |. 83EC 44 sub esp,44
00451E96 |. C745 E0 00000 mov dword ptr [local.8],0 framerects
00451E9D |. C745 E4 40000 mov dword ptr [local.7],40
00451EA4 |. C745 E8 10000 mov dword ptr [local.6],10
00451EAB |. C745 EC 50000 mov dword ptr [local.5],50
00451EB2 |. C745 F0 10000 mov dword ptr [local.4],10
00451EB9 |. C745 F4 40000 mov dword ptr [local.3],40
00451EC0 |. C745 F8 20000 mov dword ptr [local.2],20
00451EC7 |. C745 FC 50000 mov dword ptr [local.1],50
00451ECE |. C745 C0 00000 mov dword ptr [local.16],0
00451ED5 |. C745 C4 50000 mov dword ptr [local.15],50
00451EDC |. C745 C8 10000 mov dword ptr [local.14],10
00451EE3 |. C745 CC 60000 mov dword ptr [local.13],60
00451EEA |. C745 D0 10000 mov dword ptr [local.12],10
00451EF1 |. C745 D4 50000 mov dword ptr [local.11],50
00451EF8 |. C745 D8 20000 mov dword ptr [local.10],20
00451EFF |. C745 DC 60000 mov dword ptr [local.9],60

00451F06 |. 8B45 08 mov eax,[arg.1] This begins argument 1
00451F09 |. 8B48 74 mov ecx,[eax+74] stores 74 in ECX
00451F0C |. 894D BC mov [local.17],ecx stores local variable into ECX
00451F0F |. 837D BC 00 cmp dword ptr [local.17],0 is the value 0? (checks for no option)00451F13 |. 74 0E je short 00451F23 if so, jump to 00451F23
00451F15 |. 837D BC 01 cmp dword ptr [local.17],1 is the value 1? (checks for option 1)
00451F19 |. 74 26 je short 00451F41 if so, jump to 0045F41
00451F1B |. 837D BC 02 cmp dword ptr [local.17],2 is the value 2? (checks for option 2)
00451F1F |. 74 51 je short 00451F72 if so, jump to 0045F41
00451F21 |. EB 7B jmp short 00451F9E otherwise, jump to 00451F9E
00451F23 |> 8B55 08 mov edx,[arg.1] the value is 0, begin argument with EDX
00451F26 |. C742 74 01000 mov dword ptr [edx+74],1 put script state into the EDX. . . (no idea what this does)
00451F2D |. 8B45 08 mov eax,[arg.1] the value is 1, begin argument with EAX
00451F30 |. C740 68 00000 mov dword ptr [eax+68],0 put frame number into the EAX. has something to do with blinking
00451F37 |. 8B4D 08 mov ecx,[arg.1] the value is 2, begin argument with ECX
00451F3A |. C741 64 00000 mov dword ptr [ecx+64],0 put frame timer? into the ECX. also related to blinking
00451F41 |> 6A 78 push 78 puts number 78 and 0 onto the stack for the
00451F43 |. 6A 00 push 0 random number generator which is called
00451F45 |. E8 06D4FBFF call 0040F350 from address 040F350 2*
00451F4A |. 83C4 08 add esp,8 checks leftness/rightness
00451F4D |. 83F8 0A cmp eax,0A balances value from the randomly generated value and makes character blink accordingly.
00451F50 |. 75 1E jne short 00451F70 check to see if value (of EAX) is equal. . . (is character facing left?)
00451F52 |. 8B55 08 mov edx,[arg.1] if so, move the value of EDX into argument 1
00451F55 |. C742 74 02000 mov dword ptr [edx+74],2 then put script state in the EDX
00451F5C |. 8B45 08 mov eax,[arg.1] move the value of EDX into argument 1
00451F5F |. C740 78 00000 mov dword ptr [eax+78],0 then put script timer in the EAX
00451F66 |. 8B4D 08 mov ecx,[arg.1] move the value of ECX into agrument 1
00451F69 |. C741 68 01000 mov dword ptr [ecx+68],1 then put frame number in the ECX (tells what frame to put on the screen)
00451F70 |> EB 2C jmp short 00451F9E Jump to address 00451F9E JUMP
00451F72 |> 8B55 08 mov edx,[arg.1] move the value of EDX into argument 1
00451F75 |. 8B42 78 mov eax,[edx+78] then put the script state into EDX
00451F78 |. 83C0 01 add eax,1 add one to the EDX
00451F7B |. 8B4D 08 mov ecx,[arg.1] move the value of ECX into argument 1
00451F7E |. 8941 78 mov [ecx+78],eax then put script timer into the EAX
00451F81 |. 8B55 08 mov edx,[arg.1] move the contents of EDX to argument 1
00451F84 |. 837A 78 08 cmp dword ptr [edx+78],8 compare EDX to +78
00451F88 |. 7E 14 jle short 00451F9E if number is smaller then jump to address 00451F93
00451F8A |. 8B45 08 mov eax,[arg.1] otherwise, move the EAX to argument 1
00451F8D |. C740 74 01000 mov dword ptr [eax+74],1 add 1 to the EAX(?)
00451F94 |. 8B4D 08 mov ecx,[arg.1] move ECX to agument 1
00451F97 |. C741 68 00000 mov dword ptr [ecx+68],0 add 0 to ECX (?) /JUMP
00451F9E |> 8B55 08 mov edx,[arg.1] stores the argument into EDX00451FA1 |. 837A 4C 00 cmp dword ptr [edx+4C],0 compares +4C to EDX (checks relevance of direction) 00451FA5 |. 75 2B jne short 00451FD2 JUMP
00451FA7 |. 8B45 08 mov eax,[arg.1]
00451FAA |. 8B48 68 mov ecx,[eax+68]
00451FAD |. C1E1 04 shl ecx,4
00451FB0 |. 8D540D E0 lea edx,[ecx+ebp-20]
00451FB4 |. 8B45 08 mov eax,[arg.1]
00451FB7 |. 83C0 54 add eax,54
00451FBA |. 8B0A mov ecx,[edx]
00451FBC |. 8908 mov [eax],ecx
00451FBE |. 8B4A 04 mov ecx,[edx+4]
00451FC1 |. 8948 04 mov [eax+4],ecx
00451FC4 |. 8B4A 08 mov ecx,[edx+8]
00451FC7 |. 8948 08 mov [eax+8],ecx
00451FCA |. 8B52 0C mov edx,[edx+0C]
00451FCD |. 8950 0C mov [eax+0C],edx
00451FD0 |. EB 29 jmp short 00451FFB
00451FD2 |> 8B45 08 mov eax,[arg.1] /JUMP
00451FD5 |. 8B48 68 mov ecx,[eax+68]
00451FD8 |. C1E1 04 shl ecx,4
00451FDB |. 8D540D C0 lea edx,[ecx+ebp-40]
00451FDF |. 8B45 08 mov eax,[arg.1]
00451FE2 |. 83C0 54 add eax,54
00451FE5 |. 8B0A mov ecx,[edx]
00451FE7 |. 8908 mov [eax],ecx
00451FE9 |. 8B4A 04 mov ecx,[edx+4]
00451FEC |. 8948 04 mov [eax+4],ecx
00451FEF |. 8B4A 08 mov ecx,[edx+8]
00451FF2 |. 8948 08 mov [eax+8],ecx
00451FF5 |. 8B52 0C mov edx,[edx+0C]
00451FF8 |. 8950 0C mov [eax+0C],edx
00451FFB |> 8BE5 mov esp,ebp End
00451FFD |. 5D pop ebp of the
00451FFE \. C3 retn code
Footnotes:
*1 this usually isn't changed much, it is altered only for entities such and open chest which is why you need to place the actual entity higher then the area you want it to be shown. 2*
You have to use PUSH for the built in random number generator, which you could call like this:

PUSH xxxx
PUSH yyyy
CALL 0040F350

where xxxx is the maximum value you want to get, and yyyy is the minimum value.
The random number is stored back into the EAX. I assume that the number 78 is the max amount of ticks <WAI0078 that the NPC will wait at max before he blinks again.










Ok. . . I'm stuck, what does this mean?






00451F4A |. 83C4 08 add esp,8
00451F4D |. 83F8 0A cmp eax,0A
00451F50 |. 75 1E jne short 00451F70

umm, I know that your busy, but it's been over 2 weeks. . .

Could I please have a hand?
 
Jun 9, 2013 at 3:10 AM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Pronouns: he/him
Directly before it is CALL 40F350, which is the random number function. When a function returns a value, it always goes in EAX. The two parameters are 0x78 and 0
The ADD ESP, 08 is maintaining the stack frame, since when we PUSH those two variables to call our function it changes ESP, so we do this to keep it at the right value.
The CMP EAX is checking the value that was returned from the random number function to see if it's equal to 0xA. If I were to guess offhand, this is what makes it blink.
 
Jul 12, 2013 at 2:59 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
Noxid said:
Directly before it is CALL 40F350, which is the random number function. When a function returns a value, it always goes in EAX. The two parameters are 0x78 and 0
The ADD ESP, 08 is maintaining the stack frame, since when we PUSH those two variables to call our function it changes ESP, so we do this to keep it at the right value.
The CMP EAX is checking the value that was returned from the random number function to see if it's equal to 0xA. If I were to guess offhand, this is what makes it blink.
ok, another quick question. . .

00451F55 |. C742 74 02000 mov dword ptr [edx+74],2

00451F69 |. C741 68 01000 mov dword ptr [ecx+68],1

00451F5F |. C740 78 00000 mov dword ptr [eax+78],0

What does the 2, or 1, or 0 at the end of each row mean?

And what does +74 (event . ScriptState) do? There's no description.

*cough*

I (again) did the shovel bricade. . .

why is there so much MOVing?

and what does +74 @ +64
 
Jul 12, 2013 at 7:41 PM
Been here way too long...
"What're YOU lookin' at?"
Join Date: Oct 17, 2011
Location: probably somewhere else
Posts: 1104
Age: 27
Pronouns: none
These are values that are moved to the E_Xs. 2 is set on [ECX+74], etc.

The scriptstate is, umm, something. I don't use it, so I don't know.

And I believe the MOVs on the Shovel you are talking about are for setting framerects.
 
Sep 25, 2013 at 11:30 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him

Ok... after learning more about ASM I;m going to finish what I've started.





Debug Cat: (I made this from scratch, but It should work all the same.)


Code:
offset npc216 ;replaces Debug cat
 
push ebp                          ;This starts the code
mov ebp, esp                      ;You must always do this. Or die!
;And also note that ALL NUMBER ARE IN HEX (unless otherwise stated)
;[arg-1] = [EBP+8] for referance.

;============================
;=====<///FRAMERECTS\\\>=====
;============================
SUB ESP,10                        ;10 represents the total amount of framerects. (must match the highest EBP-___)
MOV DWORD PTR SS:[EBP-10],100     ;framerects are ordered Left...
MOV DWORD PTR SS:[EBP-C],0C0      ;UP
MOV DWORD PTR SS:[EBP-8],110      ;RIGHT
MOV DWORD PTR SS:[EBP-4],0D8      ;DOWN (notice that you MUST count by four's [in hex] for your framerects).
;this gives us a sprite (4 borders)

;================================
;=====<///BEHAVIOUR CODE\\\>=====
;================================

;----RECTS----

MOV EAX,DWORD PTR SS:[EBP+8]    ;"+8" puts object pointer in EDX. NEVER FORGET TO DO THIS!
ADD EAX,54                      ;holds 54 in the EAX

MOV ECX,[EBP-10]               ;takes EBP-10 (framerect 1) and stores the value of ECX into it.
MOV [EAX],ECX                  ;takes the 54 from the EAX and adds it to the argument and runs "+54" aka Frame_L to 
                               ;recognize that it is the left side on the NPC.

MOV EDX,[EBP-C]                ;takes EBP-C (framerect 2) and stores the value of EDX into it.
MOV [EAX+4],EDX                ;adds 4 to make "+58" aka Frame_U to recognize up side of NPC

MOV ECX,[EBP-8]                ;takes EBP-8 (framerect 3) and stores the value of EDX into it.
MOV [EAX+8],ECX                ;adds 4 to make "+5C" aka Frame_R to recognize right side of NPC

MOV EDX,[EBP-4]                ;takes EBP-4 (framerect 4) and stores the value of EDX into it.
MOV [EAX+0C],EDX               ;adds 4 to make "+60" aka Frame_D to recognize down side of NPC

;==============================
;======<///END OF CODE=========
;==============================
mov esp, ebp
pop ebp
retn




More to come.







Shovel Brigade:


Code:
offset 451E90     ;replaces shovel bricade.


PUSH EBP          ;As always, start of the code.
MOV EBP,ESP       ;remember all number are in HEX

;==============================
;====<///FRAMARECTS\\\>========
;==============================


SUB ESP,44        ; The number of framarects, 

                ;===sprite 0 (stand still face left do nothing)===

MOV DWORD PTR SS:[EBP-20],0          ;Left border, sprite 0 
MOV DWORD PTR SS:[EBP-1C],40         ;Up border sprite 0
MOV DWORD PTR SS:[EBP-18],10         ;Rigth border sprite 0
MOV DWORD PTR SS:[EBP-14],50         ;Bottom border sprite 0

                ;===sprite 1 (stand still face left blink)===
MOV DWORD PTR SS:[EBP-10],10         ;Left border, sprite 1   (stand still blink)
MOV DWORD PTR SS:[EBP-0C],40         ;Up border, bla bla bla...
MOV DWORD PTR SS:[EBP-8],20          ;bla bla...
MOV DWORD PTR SS:[EBP-4],50

                ;===sprite 2 (stand still face left do nothing)===
MOV DWORD PTR SS:[EBP-40],0          ;Sprite 2
MOV DWORD PTR SS:[EBP-3C],50         
MOV DWORD PTR SS:[EBP-38],10
MOV DWORD PTR SS:[EBP-34],60

                ;===sprite 3 (stand still face left blink)===
MOV DWORD PTR SS:[EBP-30],10         ;Sprite 3
MOV DWORD PTR SS:[EBP-2C],50
MOV DWORD PTR SS:[EBP-28],20
MOV DWORD PTR SS:[EBP-24],60

;================================
;=======<///BEHAVIOUR\\\>========
;================================

;-Starting up-


MOV EAX,DWORD PTR SS:[EBP+8]         ;The oh-so important NPC pointer. nessisary before putting in any action (using EAX).
MOV ECX,DWORD PTR DS:[EAX+74]        ;refering to you wonderful table of NPC's "74+" means event script state (using ECX)
MOV DWORD PTR SS:[EBP-44],ECX        ;Let's store the value of [EBP-44] (a local variable) into the ECX for use later. (along with the script state)

;-Check for <ANP's and alternate direction flags-

CMP DWORD PTR SS:[EBP-44],0          ;Compares the state of [EBP-44] to see the current value
JE :jump_lower                       ;If it's zero, let's jump lower down...

CMP DWORD PTR SS:[EBP-44],1          ;Compares the state of [EBP-44] to see the current value
JE :even_lower                       ;If it's one, let's jump even lower down...

CMP DWORD PTR SS:[EBP-44],2          ;Compares the state of [EBP-44] to see the current value
JE  :lowest                          ;If it's one, let's jump even lower down...

JMP :if_not_any                      ;What? It's not any of these numbers?!?



:jump_lower
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV DWORD PTR DS:[EDX+74],1          ;changes NPC script state to to "1" (next time it loops through we will jump straight to :even_lower becasue this is not nessisary to do this again)
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV DWORD PTR DS:[EAX+68],0          ;===NPC frame number changed to no. 0===
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through ECX)
MOV DWORD PTR DS:[ECX+64],0          ;a timer to Wait is stores through ECX

:even_lower
PUSH 78                              ;Push 78    
PUSH 0                               ;Push 0 and then...
CALL 0040F350                        ;call random number between 0 and 78, stores it into the EAX
ADD ESP,8                            ;Something that has to be done after calling a random number.
CMP EAX,0A                           ;see's if the ramdon number is 0A (10 in decimal)
JNE :if_not_any                      ;If it isn't jump...

MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV DWORD PTR DS:[EDX+74],2          ;changes NPC Scriptstate to 2 
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV DWORD PTR DS:[EAX+78],0          ;NPC script timer stored through EAX using 0
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through ECX)
MOV DWORD PTR DS:[ECX+68],1          ;===NPC frame number changed to no. 1===
JMP :if_not_any

:lowest 
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
MOV EAX,DWORD PTR DS:[EDX+78]        ;NPC script timer stored through EAX
ADD EAX,1                            ;Add 1 to the EAX
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to ECX
MOV DWORD PTR DS:[ECX+78],EAX        ;store the Script timer to the EAX
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to EDX
CMP DWORD PTR DS:[EDX+78],8          ;compare the EDX (including the script timer thingy stored to the EDX) to 8
JLE :if_not_any                      ;If it is equal or less then 8, jump...

MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to EAX
MOV DWORD PTR DS:[EAX+74],1          ;add 1 to Scriptstate
MOV ECX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored to ECX
MOV DWORD PTR DS:[ECX+68],0          ;changes frame number to 0

:if_not_any
MOV EDX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EDX)
CMP DWORD PTR DS:[EDX+4C],0          ;Compares direction of NPC to 0 (left)
JNE :direction_not_zero

;-blink face left-
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV ECX,DWORD PTR DS:[EAX+68]        ;Changes frame number to ECX's current number.
SHL ECX,4                            ;SHL Shifts the value of the ECX 4 times.
LEA EDX,[ECX+EBP-20]                 ;put's ECX's number and [EPB-40] into EDX. (changes blink to previous sprite) done blink
MOV EAX,DWORD PTR SS:[EBP+8]         ;we went over this with the debug cat, makes the game realise the border of the sprites....
ADD EAX,54                           ;add 54 to EAX
MOV ECX,DWORD PTR DS:[EDX]           ;EDX is 54 "Frame left"
MOV DWORD PTR DS:[EAX],ECX
MOV ECX,DWORD PTR DS:[EDX+4]         ;EDX+4 is 58 "frame up"
MOV DWORD PTR DS:[EAX+4],ECX
MOV ECX,DWORD PTR DS:[EDX+8]         ;EDX+8 is 5C "frame right"
MOV DWORD PTR DS:[EAX+8],ECX
MOV EDX,DWORD PTR DS:[EDX+0C]        ;EDX+0C is 60 "frame bottom"
MOV DWORD PTR DS:[EAX+0C],EDX        ;then we end the code.
JMP :end_of_code

;-blink face right-
:direction_not_zero
MOV EAX,DWORD PTR SS:[EBP+8]         ;NPC pointer stored (through EAX)
MOV ECX,DWORD PTR DS:[EAX+68]        ;Changes frame number to ECX's current number.
SHL ECX,4                            ;SHL Shifts the value of the ECX 4 times.
LEA EDX,[ECX+EBP-40]                 ;put's ECX's number and [EPB-40] into EDX.(changes blink to previous sprite)

MOV EAX,DWORD PTR SS:[EBP+8]         ;we went over this with the debug cat, makes the game realise the border of the sprites....
ADD EAX,54                           ;add 54 to EAX
MOV ECX,DWORD PTR DS:[EDX]           ;EDX is 54 "Frame left"
MOV DWORD PTR DS:[EAX],ECX           
MOV ECX,DWORD PTR DS:[EDX+4]         ;EDX+4 is 58 "frame up"
MOV DWORD PTR DS:[EAX+4],ECX         
MOV ECX,DWORD PTR DS:[EDX+8]         ;EDX+8 is 5C "frame right"
MOV DWORD PTR DS:[EAX+8],ECX
MOV EDX,DWORD PTR DS:[EDX+0C]        ;EDX+0C is 60 "frame bottom"
MOV DWORD PTR DS:[EAX+0C],EDX        

;=================================
;=======<///END OF CODE\\\>=======
;=================================

:end_of_code
MOV ESP,EBP                          ;That wasn't so bad.
POP EBP                  
RETN


EDIT: It looks a lot nicer in the assembler...


 
Sep 26, 2013 at 3:00 AM
Professional Whatever
"Life begins and ends with Nu."
Join Date: Jan 13, 2011
Location: Lasagna
Posts: 4481
Pronouns: she/her
you do know it's "framerects" not "framarects" right
You know
As in "frame"
 
Sep 26, 2013 at 4:35 AM
Been here way too long...
"What're YOU lookin' at?"
Join Date: Oct 17, 2011
Location: probably somewhere else
Posts: 1104
Age: 27
Pronouns: none
Debug cat is extremely easy. You just have to set framerects, and that's all. I believe he has no animation or anything. Shovel, on the other side, is quite harder. Good luck with all your hacks.

Also framarects, heh.
 
Sep 26, 2013 at 4:08 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him
Randolf said:
Debug cat is extremely easy. You just have to set framerects, and that's all. I believe he has no animation or anything. Shovel, on the other side, is quite harder. Good luck with all your hacks.

Also framarects, heh.


It was a little harder for me to do, but I winged it.



Also I did some guess work like what [EBP-44] was near the beginning, or what what "script timer" (possibly similar to <WAI) or "script number" (no idea) was...



And this...


SHL ECX,4
LEA EDX,[ECX+EBP-20] ;commands I'm not familiar with, likely swaps the framerect back to the original (not blinking) one.


...Just doesn't make sense to me.





But the thing I really don't get is why pixel would make one portion of the script run after the random number is equal to 0A but not any other time...
 
Sep 26, 2013 at 4:39 PM
Been here way too long...
"What're YOU lookin' at?"
Join Date: Oct 17, 2011
Location: probably somewhere else
Posts: 1104
Age: 27
Pronouns: none
Maybe to have a very little chance of that script to happen?
 
Sep 26, 2013 at 5:06 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Pronouns: he/him
LEA is load effective address
it puts ecx + ebp -20 into edx
 
Sep 26, 2013 at 7:56 PM
The TideWalker
Modding Community Discord Founder
"That dog!"
Join Date: Apr 5, 2013
Location: In my mind and of my body.
Posts: 1640
Age: 27
Pronouns: he/him

After lurking through ASM threads some more, I found this.


Here's a little bit of physics: to have smooth, realistic movement, you need to use velocities. A velocity is something you add to a position every frame to get a new position. For instance...
x position = x position + x velocity
y position = y position + y velocity

This isn't enough though. Imagine you have a tennis ball. Without friction to slow it down, the moment you'd hit the ball it would keep going in the same direction without slowing down at all. So you also need to make the velocity drop each frame.

x velocity = x velocity * 0.975
y velocity = y velocity * 0.975
x position = x position + x velocity
y position = y position + y velocity

Here we have a friction of 0.975. The higher the number, the longer it takes to reach 0, the slower the object loses its velocity. Now when we hit our tennis ball, it'll go in a straight line and slow down, stopping suspended in the air. This is enough for most things, but if we have objects that jump or otherwise lose contact with the floor, they'll need gravity.
x velocity = x velocity * 0.975
y velocity = y velocity * 0.975 + 0.1
x position = x position + x velocity
y position = y position + y velocity

We have a gravity of 0.1 now. Since we add a small value every frame, the y velocity will gradually go from -1 to 0 then up into positive numbers, making the object arc upwards then back down realistically.


This is what MoveX and MoveY are for. :) None of this happens automatically, though: you have to implant that in your code yourself. And this introduces a lot of timing issues; when does your enemy start moving? When does it stop moving? To set this up, you can and should use the ScriptState member. If ScriptState is equal to 0, set the initial velocity and set Script State to 1. If ScriptState is equal to 1, keep updating the position until the velocity drops to 0, then set ScriptState to 2. Etc, etc..


So Is Scriptstate is like <FL+ or <FLJ or <FL- or what? Is it made to loop code until desired results are met?
 
Back
Top