Limited weapon and charge weapon pickup

dale_coop

Moderator
Staff member
For my game I wanted to have a weapon (like a laser gun) that need to be charged, and of course, each time you use it, it loses ammo (or energy).
For that I will use the variable "GLOBAL_Player1_Ammo". I share with you how I did it...

First I modified the "InitLoad.asm" script to initialize the variable
Code:
;;; SET UP INITIAL VARIABLE VALUE HERE:
	LDA #$00
	STA GLOBAL_Player1_Ammo

Following the tutorial videos about HUD, I showed the player weapon ammo (with "Var tiles" for the variable "GLOBAL_Player1_Ammo")



Added the code in the "InitLoads.asm" to set up the HUD hooks :
Code:
	LDA #HUD_ELEMENT_4
	STA HUD_updateAmmo

Then, I will add some routines in the "Usersubroutines.asm" script, to decrease the Ammo and to update the HUD:
Code:
decreasePlayerAmmo:	
	LDX GLOBAL_Player1_Ammo
	DEX
	TXA
	STA GLOBAL_Player1_Ammo
	JSR updateHUDPlayerAmmo:	
	RTS
updateHUDPlayerAmmo:	
	STA hudElementTilesToLoad
	LDA #$00
	STA hudElementTilesMax	
	LDA DrawHudBytes
	ORA HUD_updateAmmo
	STA DrawHudBytes
	RTS

And I will modify the "CreateSimpleProjectileWithMotion.asm" script to use and test the variable GLOBAL_Player1_Ammo. If it's different than 0, the script can continue creating the projectile:
Code:
CreateSimpleProjectileWithMotion:
    LDY player1_object
    CPY #$FF ;; if the player object is set to ff, he's dead.
    BNE playerCanCreateProjectile
    RTS
 playerCanCreateProjectile:
	LDA GLOBAL_Player1_Ammo
	BNE continueCreateProjectile
	RTS
continueCreateProjectile:
    ;; get offset
    ;; in a later version, we will use user defined offsets.
    ;; for now, we'll place projectile creation at center of object
    LDA Object_movement,y
    AND #%00000111
    TAX
    LDA weaponOffsetTableX,x
    ;;; now we have the offset
     CLC
     ADC Object_x_hi,y
    STA temp1
    LDA weaponOffsetTableY,x
    CLC
    ADC Object_y_hi,y
    STA temp2
    CreateObject temp1, temp2, #$01, #$00  ;;testVar
    LDA Object_movement,y
    AND #%00000111
    STA temp
    TAY
    LDA DirectionMovementTable,y
    ORA temp
    
    STA Object_movement,x
    
    ;; add object size offset.
    LDA Object_x_hi,x
    SEC
    SBC #$08 ;; half of the width of the intended projectile
    STA Object_x_hi,x
    LDA Object_y_hi,x
    SEC
    SBC #$08 ;; half of the height of the intended projectile
    STA Object_y_hi,x
    
    PlaySound #$00, #$00
    JMP decreasePlayerAmmo
    RTS


Now I create a pickup object to be my "ammo" collectable item. And to be more useful, I will use its "Health" value as my "Ammo recharge" value. Something like this:



So, what I want is when my player takes the ammo pickup, his weapon is fully charged (6 ammo).

Like I wrote in another post, I found a way to have collectable object that doesn't trigger the screen, I will use that technique for my "Ammo collectable" object.
I modified the "HandleObjectCollisions.asm" script, when the player collect the collectable pickup, if its "health" is different than 0, so I charge the Ammo variable and update the HUD, else the script continue as usual:

Code:
otherIsNotAMonsterTypeCollision:
	LDA ObjectFlags,y
	AND #%00100000 ;; is it a 'collectable'?
	BEQ otherIsNotAcollectable
	;;;; IS A pickup / power up
	DeactivateCurrentObject ;; makes the other object go away
							;; since other object is loaded in X
;;=========== WHAT DO YOU WANT TO HAVE HAPPEN WHEN YOU COLLECT THIS ITEM?
;;CHARGE WEAPON:
	LDA Object_health,x  ;; read the "health" of the collectable/pickup
	BEQ continueOtherIsNotAMonsterTypeCollision  ;; if it's NOT a Ammo pickup (=if health is 0)
	STA GLOBAL_Player1_Ammo  ;; it IS ammo, put in the var
	;;PlaySound #$00, #$00
	JMP updateHUDPlayerAmmo 
;;;;;;;;;;;;;;;;;;;;;;;

continueOtherIsNotAMonsterTypeCollision: 
    ;;PlaySound #$01, #$00
    JSR countAllTargets
otherIsNotAcollectable:


Voilà, the "charge weapon" pickup should work, as expected.


ChargedWeapon.gif
 

TurtleRescueNES

Active member
Hi Dale! This is a fantastic function, and I was hoping you could help me implement this.

In my game, I'm making this approach easier by using the established myMoney as the ammunition. This is similar to Zelda where rupees are used for arrows.
I already have the code in place to decrease myMoney by one in the A_Create_Projectile.asm script. I am also updating the HUD as well. The only thing I cannot safely do is validate that myMoney is not equal to 0 before the projectile is created. I'm looking at your code above, and can almost see how you're doing it, but I am also overwhelmed by all the new checks Joe is doing before the projectile is created in his default script. I assume I should be inserting "LDA myMoney" somewhere at the start of the script, but I am unsure the best way to do so and if there should be any other lines to support it.

I would greatly appreciate your thoughts on this!
 

dale_coop

Moderator
Staff member
Of course ;)
In his "A_Create_Projectile.asm" script, Joe starts with:
Code:
 LDA gameHandler
 AND #%00100000
 BEQ notNPCstate_proj
 JMP doneShooting
 notNPCstate_proj
 LDA weaponsUnlocked
 AND #%00000010
 BNE canShoot
 JMP doneShooting
canShoot:


You could just add your test on myMoney:
Code:
 LDA gameHandler
 AND #%00100000
 BEQ notNPCstate_proj
 JMP doneShooting
 notNPCstate_proj:
 LDA weaponsUnlocked
 AND #%00000010
 BNE canShootIfEnoughMoney
 JMP doneShooting
canShootIfEnoughMoney:
	LDA myMoney
	BNE canShoot
	JMP doneShooting
canShoot:
 

TurtleRescueNES

Active member
Wonderful, thank you! It now works as intended!

That helped me identify a little bug where I placed the subtract myMoney function in the doneShooting subroutine, so I moved it up.
 

TurtleRescueNES

Active member
Okay, so further testing has revealed an interesting limitation. When my money/ammunition count goes higher than 10, then 10 becomes the same as zero. Same with 20. Zero means no ammunition is detected, so no projectiles are created. Which kind of makes sense in that I now recall that there are tricks to allow counters to go into the tens, hundreds and thousands.

My guess is that the code of "LDA myMoney" is unable to recognize a value in the tens, only the first decimal place. Any thoughts around this?

Dale, I see your Press Start game never ran into this because you maxed out at 6 shots.
 

chronosv2

New member
From what I remember, myMoney and other HUD numbers are actually a series of bytes. So I think you could achieve this by checking

If myMoney+1 = 0
If so, check myMoney for non-zero
If not, we have more than 9 shots, so subtract as normal.
 

dale_coop

Moderator
Staff member
jsherman, you right I found today the exact same limitation... when trying to pay an item in my shop with “10”as myMoney.

Thanks chronosv2, will check that.
 
Top Bottom