Understanding object/monster flags

Raftronaut

Member
Can Anyone tell me which script the bits are stored that determine the flag's values in Monsters>Object Details?

target type.PNG

I am looking specifically to find and study the monster flag, as well as set the unused "target type" flag to something else.

I have poked around in script settings to find the script where this would be determined but have not found it yet. I've looked in LoadMonsters, DrawSprites, PreDraw etc. I can't seem to find where these flags are pointing to in code.

Any insight out there?

-cheers
 

Mugi

Member
i belive those bits are stored in Object_flags

Code:
;; ObjectFlags:
;; 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0
;  |   |   |   |   |   |   |   + -- PERSISTENT (especially good for player!)
;  |   |   |   |   |   |   +------- player type
;  |   |   |   |   |   + ---------- player weapon/projectile type
;  |   |   |   |   +--------------- monster type
;  |   |   |   +------------------- monster weapon/projectile type
;  |   |   +----------------------- pickup / power up
;  |   + -------------------------- target type 
;  +------------------------------- NPC type
 

Raftronaut

Member
Mugi said:
i belive those bits are stored in Object_flags

Code:
;; ObjectFlags:
;; 7 - 6 - 5 - 4 - 3 - 2 - 1 - 0
;  |   |   |   |   |   |   |   + -- PERSISTENT (especially good for player!)
;  |   |   |   |   |   |   +------- player type
;  |   |   |   |   |   + ---------- player weapon/projectile type
;  |   |   |   |   +--------------- monster type
;  |   |   |   +------------------- monster weapon/projectile type
;  |   |   +----------------------- pickup / power up
;  |   + -------------------------- target type 
;  +------------------------------- NPC type

Ahh, and to clarify, is Object_flags an actual .asm file, or a macro contained elsewhere?
 

Mugi

Member
it's a variable.

you load this flag by loading your object in X, then Object_Flags,x in A

LDX Player1_object
LDA Object_flags,x
AND #%00000000 ; whatever flag you want to read

then do whatever with it

if you want to use a flag for something, you can edit their defines from project settings, they're called "MONSTER FLAGS" for some reason there.

of.png
 

dale_coop

Moderator
Staff member
Or if it's for a collision script or action script or hurt/death script...
You can check directly the flag (because the object is already loaded in the X registry):
Code:
 	LDA ObjectFlags,x	;; reading the flags of the object in X
	AND #%01001000  	;; checking the 3rd (monster?) bit and the 6th bit (target?)
	BEQ notABossMonster	;; it's not, branch to a specific label
	;; else, yes, it's a Boss Monster
	;; do something for it...
 

Raftronaut

Member
dale_coop said:
Or if it's for a collision script or action script or hurt/death script...
You can check directly the flag (because the object is already loaded in the X registry):
Code:
 	LDA ObjectFlags,x	;; reading the flags of the object in X
	AND #%01001000  	;; checking the 3rd (monster?) bit and the 6th bit (target?)
	BEQ notABossMonster	;; it's not, branch to a specific label
	;; else, yes, it's a Boss Monster
	;; do something for it...


ahhhhh, I think I understand now, so I can simply edit my monster death script to check for this flag?
 

Raftronaut

Member
Or I guess, since my intention is to create a special monster death object when whenever a monster with this flag is checked I could insert that right into my current hurt monster script?


Code:
;;; what should we do with the monster?
        ;;; monster is loaded in x
        LDA Object_vulnerability,x
        AND #%00000100 ;; is it weapon immune?
        BEQ notWeaponImmune
        ;PlaySound #SFX_MISS
        JMP skipHurtingMonsterAndSound
    notWeaponImmune:
        
        LDA Object_status,x
        AND #HURT_STATUS_MASK
        BEQ dontskipHurtingMonster
        JMP skipHurtingMonster
    dontskipHurtingMonster:
        LDA Object_status,x
        ORA #%00000001
        STA Object_status,x
        LDA #HURT_TIMER
        STA Object_timer_0,x
        ;;; assume idle is in step 0
        ChangeObjectState #$00,#$02
        ;;;; unfortunately this recoil is backwards
        LDA Object_status,x
        AND #%00000100
        BNE skipRecoilBecauseOnEdge
        LDA Object_vulnerability,x
        AND #%00001000 
        BNE skipRecoilBecauseOnEdge ;; skip recoil because bit is flipped to ignore recoil
        
        LDA selfCenterX
        STA recoil_otherX
        LDA selfCenterY
        STA recoil_otherY
        LDA otherCenterX
        STA recoil_selfX
        LDA otherCenterY
        STA recoil_selfY
        JSR DetermineRecoilDirection
    skipRecoilBecauseOnEdge:
        LDA Object_health,x
        SEC
        SBC #$01
        CMP #$01
        BCC +
		JMP notMonsterDeath
	+

        DeactivateCurrentObject
        PlaySound #SND_SPLAT
		

        
	LDX tempy	;;dale_coop

        JSR HandleDrops
        JSR HandleToggleScrolling
		
		CountObjects #%00001000, #$00
		LDA monsterCounter
		CLC	;;dale_coop
		BEQ +
		JMP ++
	+
		.include SCR_KILLED_LAST_MONSTER
	++
        JMP skipHurtingMonster
    notMonsterDeath
        STA Object_health,x
    skipHurtingMonster: 
        ;PlaySound #SFX_MONSTER_HURT
    
    skipHurtingMonsterAndSound:
        LDX tempx
        ;; what should we do with the projectile?
        DeactivateCurrentObject
 

dale_coop

Moderator
Staff member
In your project, the Monster Death object is created in your "Handle Monster Drops" script.
Edit that script... you should find it the very end, the create object for your monster death. There you could try adding the code.
 

Raftronaut

Member
Ok, I think i Understand.

I found the HandleDrop.asm.
Code:
	RTS ;; skip drops
;;; monster objects drop at random.
	LDA Object_x_hi,x
	STA temp
	LDA Object_y_hi,x
	STA temp1

	JSR GetRandomNumber
	AND #%00000111 ;; now, we have a number between 0 and 7
	BNE notPickup0 ;; 
	;; zero case here;
	;;; here, we'll create health
	CreateObject temp, temp1, #$04, #$00, currentNametable
	JMP donePickup
notPickup0:
	CMP #$01
	BNE notPickup1
	;; one case here;
;;; here, we'll create currency
	CreateObject temp, temp1, #$07, #$00, currentNametable
	JMP donePickup
notPickup1:
	CMP #$02
	BNE notPickup2
	;; two case here;
	;;; here, we'll create currency
	CreateObject temp, temp1, #$07, #$00, currentNametable
	JMP donePickup
notPickup2:
	;;;; do the same for each case.
	;;;; blank cases will simply return 'nothing'.
	
	
	
	
donePickup:	
	;;; ALL cases create a "pow"
	CreateObject temp, temp1, #$09, #$00, currentNametable
	
	 	LDA ObjectFlags,x	;; reading the flags of the object in X
	AND #%01001000  	;; checking the 3rd (monster?) bit and the 6th bit (target?)
	BEQ notABossMonster	;; it's not, branch to a specific label
	;; else, yes, it's a Boss Monster
	;; do something for it...


So, essentially I would simply need to insert this following code at the end of the HandleDrop.asm?
Code:
 	LDA ObjectFlags,x	;; reading the flags of the object in X
	AND #%01001000  	;; checking the 3rd (monster?) bit and the 6th bit (target?)
	BEQ notABossMonster	;; it's not, branch to a specific label
	;; else, yes, it's a Boss Monster
	;; do something for it...

Then Once I have the branch I can have the Create Boss Death which I counted as slot 09 (including 00 for player) object if monster is destroyed and has the flag checked?
boss death.PNG

line #38 already looks like it is creating object #$09:
Code:
CreateObject temp, temp1, #$09

Am I getting close at all? Still a bit confused.. It's been a long Nesmaker day :))))
 

dale_coop

Moderator
Staff member
Your Handle Drops script seems currently doing nothing (the code is skipped: there is an RTS at the begining), so I guess your game doesn't have (use) any monster death animation currently?
So, my first question would be, do you want that your monster drops items when they die? (like LP Life, charge pickup, key, ...)

If you want that, we can use the handle script for that and deal with the boss monsters / normal monsters' death animations.
If you don't want, we could add the boss monsters / normal monsters death animations directly in the HandleHurtMonster script.
 

dale_coop

Moderator
Staff member
If you don't need the handle drops...
Just modiify your Handle Hurt Monster script, around the line 53, you find:
Code:
	LDX tempy	;;dale_coop

Comment that line out... and replace with:
Code:
	;LDX tempy	;;dale_coop
	
	;;********************************************************
	;; dale_coop: DEATH ANIMATIONS:
	;;********************************************************
	LDA otherCenterX
	SBC #$08
	STA temp
	LDA otherCenterY
	SBC #$08
	STA temp1
	LDA Object_flags,x	;; reading the flags of the object in X
	CMP #%01001000		;; is it a BOSS MONSTER? (flagged "target" and "monster")				
	BEQ doBossMonsterDeathEffect
	;; if not a boss, we create NORMAL Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_MONSTER_DEATH, #$00, currentNametable
	JMP doneWithMonsterDeathEffect
	doBossMonsterDeathEffect:
	;; if a boss, we create BOSS Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_BOSS_DEATH, #$00, currentNametable
	doneWithMonsterDeathEffect:
	;;********************************************************

So you will need a new "OBJ_BOSS_DEATH" constant (in "Project Setttings > User Constants") set it to "9"... and don't forget to set your "OBJ_MONSTER_DEATH" constant to "10" (your effect for normal monster deaths).
 

Raftronaut

Member
dale_coop said:
If you don't need the handle drops...
Just modiify your Handle Hurt Monster script, around the line 53, you find:
Code:
	LDX tempy	;;dale_coop

Comment that line out... and replace with:
Code:
	;LDX tempy	;;dale_coop
	
	;;********************************************************
	;; dale_coop: DEATH ANIMATIONS:
	;;********************************************************
	LDA otherCenterX
	SBC #$08
	STA temp
	LDA otherCenterY
	SBC #$08
	STA temp1
	LDA Object_flags,x	;; reading the flags of the object in X
	CMP #%01001000		;; is it a BOSS MONSTER? (flagged "target" and "monster")				
	BEQ doBossMonsterDeathEffect
	;; if not a boss, we create NORMAL Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_MONSTER_DEATH, #$00, currentNametable
	JMP doneWithMonsterDeathEffect
	doBossMonsterDeathEffect:
	;; if a boss, we create BOSS Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_BOSS_DEATH, #$00, currentNametable
	doneWithMonsterDeathEffect:
	;;********************************************************

So you will need a new "OBJ_BOSS_DEATH" constant (in "Project Setttings > User Constants") set it to "9"... and don't forget to set your "OBJ_MONSTER_DEATH" constant to "10" (your effect for normal monster deaths).


Amazing!!!!! I hope to start messing with this tonight! I have not explored user constants much yet. I look forward to digging into this :)

My fingers are crossed this works as intended! I will report back with my findings..
 

Raftronaut

Member
dale_coop said:
If you don't need the handle drops...
Just modiify your Handle Hurt Monster script, around the line 53, you find:
Code:
	LDX tempy	;;dale_coop

Comment that line out... and replace with:
Code:
	;LDX tempy	;;dale_coop
	
	;;********************************************************
	;; dale_coop: DEATH ANIMATIONS:
	;;********************************************************
	LDA otherCenterX
	SBC #$08
	STA temp
	LDA otherCenterY
	SBC #$08
	STA temp1
	LDA Object_flags,x	;; reading the flags of the object in X
	CMP #%01001000		;; is it a BOSS MONSTER? (flagged "target" and "monster")				
	BEQ doBossMonsterDeathEffect
	;; if not a boss, we create NORMAL Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_MONSTER_DEATH, #$00, currentNametable
	JMP doneWithMonsterDeathEffect
	doBossMonsterDeathEffect:
	;; if a boss, we create BOSS Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_BOSS_DEATH, #$00, currentNametable
	doneWithMonsterDeathEffect:
	;;********************************************************

So you will need a new "OBJ_BOSS_DEATH" constant (in "Project Setttings > User Constants") set it to "9"... and don't forget to set your "OBJ_MONSTER_DEATH" constant to "10" (your effect for normal monster deaths).


Well OK!!!!!
BOSS DEATH WORKS! Boss flag checked on Object details>Details:
boss flag.PNG
Creates Boss Death Object #$09 when destroyed... (BOSS DEATH here)
game objects row.PNG
I set up project settings>User constant>Boss death value =9
obj boss death.PNG
I set Monster death value to 10.
mosnter death.PNG

Here is my first draft "boss chamber" in action:
https://youtu.be/azNe9ux6vL4

IT WORKS!!!!! I can DO SO MUCH with this, Add splash screens before every level, start to add new cutscenes, begin designing bosses etc.. This feature unlocks so much potential for my game!

Hahaha, however, I clearly did something wrong as there were more unintended consequences...Like I said before I did set Monster Death to value 10, so I thought it should be creating that object buuuuuut, instead regular monsters are creating projectiles...It's late here, so when i finally tested this I started laughing pretty hard..I just had to make a video...
https://youtu.be/JcDPqQx8ANw

If I set monster object to 10, is there something I editing wrong in the code?
I noticed like 21 in your code says :
Code:
ChangeObjectState #$00,#$02
I think #$02 is the slot my projectile is using, I changed that value to #$0A (hex 10?) but that did nothing..

Any Ideas?

Here is the full script for HandleHurtMonster.asm for sake of convenience:
Code:
;;; what should we do with the monster?
        ;;; monster is loaded in x
        LDA Object_vulnerability,x
        AND #%00000100 ;; is it weapon immune?
        BEQ notWeaponImmune
        ;PlaySound #SFX_MISS
        JMP skipHurtingMonsterAndSound
    notWeaponImmune:
        
        LDA Object_status,x
        AND #HURT_STATUS_MASK
        BEQ dontskipHurtingMonster
        JMP skipHurtingMonster
    dontskipHurtingMonster:
        LDA Object_status,x
        ORA #%00000001
        STA Object_status,x
        LDA #HURT_TIMER
        STA Object_timer_0,x
        ;;; assume idle is in step 0
        ChangeObjectState #$00,#$02
        ;;;; unfortunately this recoil is backwards
        LDA Object_status,x
        AND #%00000100
        BNE skipRecoilBecauseOnEdge
        LDA Object_vulnerability,x
        AND #%00001000 
        BNE skipRecoilBecauseOnEdge ;; skip recoil because bit is flipped to ignore recoil
        
        LDA selfCenterX
        STA recoil_otherX
        LDA selfCenterY
        STA recoil_otherY
        LDA otherCenterX
        STA recoil_selfX
        LDA otherCenterY
        STA recoil_selfY
        JSR DetermineRecoilDirection
    skipRecoilBecauseOnEdge:
        LDA Object_health,x
        SEC
        SBC #$01
        CMP #$01
        BCC +
		JMP notMonsterDeath
	+

        DeactivateCurrentObject
        PlaySound #SND_SPLAT
		

        
		;LDX tempy	;;dale_coop
	
	;;********************************************************
	;; dale_coop: DEATH ANIMATIONS:
	;;********************************************************
	LDA otherCenterX
	SBC #$08
	STA temp
	LDA otherCenterY
	SBC #$08
	STA temp1
	LDA Object_flags,x	;; reading the flags of the object in X
	CMP #%01001000		;; is it a BOSS MONSTER? (flagged "target" and "monster")				
	BEQ doBossMonsterDeathEffect
	;; if not a boss, we create NORMAL Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_MONSTER_DEATH, #$00, currentNametable
	JMP doneWithMonsterDeathEffect
	doBossMonsterDeathEffect:
	;; if a boss, we create BOSS Monster Death Animation object:
	CreateObject temp, temp1, #OBJ_BOSS_DEATH, #$00, currentNametable
	doneWithMonsterDeathEffect:
	;;********************************************************	


        JSR HandleDrops
        JSR HandleToggleScrolling
		
		CountObjects #%00001000, #$00
		LDA monsterCounter
		CLC	;;dale_coop
		BEQ +
		JMP ++
	+
		.include SCR_KILLED_LAST_MONSTER
	++
        JMP skipHurtingMonster
    notMonsterDeath
        STA Object_health,x
    skipHurtingMonster: 
        ;PlaySound #SFX_MONSTER_HURT
    
    skipHurtingMonsterAndSound:
        LDX tempx
        ;; what should we do with the projectile?
        DeactivateCurrentObject
 

dale_coop

Moderator
Staff member
The code is correct... don't think you need to change anything.
Maybe your "Monster Death" game object has an action step "shoot at player" set? Could you share a screenshot its action steps settings?

Btw, the code:
Code:
	ChangeObjectState #$00,#$02
change to "0" the action step of the current object (loaded in teh X registry). And "02" is the animation speed, to use with the action step 0.
 

Dirk

Member
After you find out why your enemies are behaving like that you could re-add it as difficult mode or activate it when you replay the game after finishing it, like some older games did.
 

Raftronaut

Member
Wow, Dale I didn't think to look there, I was too busy wondering why it was creating game object 02 before I went to bed that I did not check actions states for Monster Death.

Sure enough, the 1st action step I had set as Monster death was "shoot at player"...
I changed that and monster death seems to work just fine. Monster deaths were not working previous, not sure if they were ommitted from shooter module, but they are working now and look lovely with my monster death animation :)
I tested it again as soon as I woke up, and was very happy to see my simple oversight could be easily corrected, I appreciate your insight

Thank you Again! :)

Dirk, unforunately leaving this on woudl make the game impossible, as there are areas where have to destroy enemies contained within a gap, and that would create projectile in a very small area..
 
Top Bottom